Plugin Directory

Changeset 969547


Ignore:
Timestamp:
08/21/2014 09:16:59 AM (12 years ago)
Author:
kinstahosting
Message:

updated custom metaboxes class

Location:
infinite-slider/trunk/public/includes/cmb
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • infinite-slider/trunk/public/includes/cmb/helpers/cmb_Meta_Box_Sanitize.php

    r884566 r969547  
    88
    99    /**
    10      * A single instance of this class.
    11      * @var   cmb_Meta_Box_types object
    12      * @since 1.0.0
    13      */
    14     public static $instance = null;
    15 
    16     /**
    17      * Creates or returns an instance of this class.
    18      * @since  1.0.0
    19      * @return cmb_Meta_Box_Sanitize A single instance of this class.
    20      */
    21     public static function get() {
    22         if ( self::$instance === null )
    23             self::$instance = new self();
    24 
    25         return self::$instance;
    26     }
    27 
    28     /**
    29      * Sample field validation
    30      * @since  0.0.4
    31      */
    32     public static function check_text( $text ) {
    33         return $text === 'hello' ? true : false;
    34     }
    35 
    36     /**
    37      * Simple checkbox validation
    38      * @since  1.0.1
    39      * @param  mixed  $text 'on' or false
    40      * @return mixex        'on' or false
    41      */
    42     public static function checkbox( $text ) {
    43         return $text === 'on' ? 'on' : false;
    44     }
    45 
    46     /**
    47      * Validate url in a meta value
    48      * @since  1.0.1
    49      * @param  string $meta  Meta value
    50      * @param  array  $field Field config array
    51      * @return string        Empty string or escaped url
    52      */
    53     public static function text_url( $meta, $field ) {
    54 
    55         $protocols = isset( $field['protocols'] ) ? (array) $field['protocols'] : null;
    56         if ( is_array( $meta ) ) {
    57             foreach ( $meta as $key => $value ) {
    58                 $meta[ $key ] = $value ? esc_url_raw( $value, $protocols ) : $field['default'];
    59             }
    60         } else {
    61             $meta = $meta ? esc_url_raw( $meta, $protocols ) : $field['default'];
    62         }
    63 
    64         return $meta;
    65     }
    66 
    67     /**
    68      * Because we don't want oembed data passed through the cmb_validate_ filter
    69      * @since  1.0.1
    70      * @param  string  $meta oembed cached data
    71      * @return string        oembed cached data
    72      */
    73     public static function oembed( $meta ) {
    74         return $meta;
    75     }
    76 
    77     /**
    78      * Validate email in a meta value
    79      * @since  1.0.1
    80      * @param  string $meta Meta value
    81      * @return string       Empty string or validated email
    82      */
    83     public static function text_email( $meta ) {
    84 
    85         if ( is_array( $meta ) ) {
    86             foreach ( $meta as $key => $value ) {
    87                 $value = trim( $value );
    88                 $meta[ $key ] = is_email( $value ) ? $value : '';
    89             }
    90         } else {
    91             $meta = trim( $meta );
    92             $meta = is_email( $meta ) ? $meta : '';
    93         }
    94 
    95         return $meta;
    96     }
    97 
    98     /**
    99      * Validate money in a meta value
    100      * @since  1.0.1
    101      * @param  string $meta Meta value
    102      * @return string       Empty string or validated money value
    103      */
    104     public static function text_money( $meta ) {
    105         if ( is_array( $meta ) ) {
    106             foreach ( $meta as $key => $value ) {
    107                 $meta[ $key ] = number_format( (float) str_ireplace( ',', '', $value ), 2, '.', ',');
    108             }
    109         } else {
    110             $meta = number_format( (float) str_ireplace( ',', '', $meta ), 2, '.', ',');
    111         }
    112 
    113         return $meta;
    114     }
    115 
    116     /**
    117      * Converts text date to timestamp
    118      * @since  1.0.2
    119      * @param  string $meta Meta value
    120      * @return string       Timestring
    121      */
    122     public static function text_date_timestamp( $meta ) {
    123         return strtotime( $meta );;
    124     }
    125 
    126     /**
    127      * Datetime to timestamp
    128      * @since  1.0.1
    129      * @param  string $meta Meta value
    130      * @return string       Timestring
    131      */
    132     public static function text_datetime_timestamp( $meta ) {
    133 
    134         $test = is_array( $meta ) ? array_filter( $meta ) : '';
    135         if ( empty( $test ) )
    136             return '';
    137 
    138         $meta = strtotime( $meta['date'] .' '. $meta['time'] );
    139 
    140         if ( $tz_offset = cmb_Meta_Box::field_timezone_offset() )
    141             $meta += $tz_offset;
    142 
    143         return $meta;
    144     }
    145 
    146     /**
    147      * Datetime to imestamp with timezone
    148      * @since  1.0.1
    149      * @param  string $meta Meta value
    150      * @return string       Timestring
    151      */
    152     public static function text_datetime_timestamp_timezone( $meta ) {
    153 
    154         $test = is_array( $meta ) ? array_filter( $meta ) : '';
    155         if ( empty( $test ) )
    156             return '';
    157 
    158         $tzstring = null;
    159 
    160         if ( is_array( $meta ) && array_key_exists( 'timezone', $meta ) )
    161             $tzstring = $meta['timezone'];
    162 
    163         if ( empty( $tzstring ) )
    164             $tzstring = cmb_Meta_Box::timezone_string();
    165 
    166         $offset = cmb_Meta_Box::timezone_offset( $tzstring, true );
    167 
    168         if ( substr( $tzstring, 0, 3 ) === 'UTC' )
    169             $tzstring = timezone_name_from_abbr( '', $offset, 0 );
    170 
    171         $meta = new DateTime( $meta['date'] .' '. $meta['time'], new DateTimeZone( $tzstring ) );
    172         $meta = serialize( $meta );
    173 
    174         return $meta;
    175     }
    176 
    177     /**
    178      * Sanitize textareas and wysiwyg fields
    179      * @since  1.0.1
    180      * @param  string $meta Meta value
    181      * @return string       Sanitized data
    182      */
    183     public static function textarea( $meta ) {
    184         return wp_kses_post( $meta );
    185     }
    186 
    187     /**
    188      * Sanitize code textareas
    189      * @since  1.0.2
    190      * @param  string $meta Meta value
    191      * @return string       Sanitized data
    192      */
    193     public static function textarea_code( $meta ) {
    194         return htmlspecialchars_decode( stripslashes( $meta ) );
    195     }
    196 
    197     /**
    198      * Sanitize code textareas
    199      * @since  1.0.2
    200      * @param  string $meta  Meta value
    201      * @param  array  $field Field config array
    202      * @return string        Sanitized data
    203      */
    204     public static function file( $meta, $field ) {
    205         $_id_name = $field['id'] .'_id';
    206         // get _id old value
    207         $_id_old = cmb_Meta_Box::get_data( $_id_name );
    208 
    209         // If specified NOT to save the file ID
    210         if ( isset( $field['save_id'] ) && ! $field['save_id'] ) {
    211             $_new_id = '';
    212         } else {
    213             // otherwise get the file ID
    214             $_new_id = isset( $_POST[ $_id_name ] ) ? $_POST[ $_id_name ] : null;
    215 
    216             // If there is no ID saved yet, try to get it from the url
    217             if ( isset( $_POST[ $field['id'] ] ) && $_POST[ $field['id'] ] && ! $_new_id ) {
    218                 $_new_id = cmb_Meta_Box::image_id_from_url( esc_url_raw( $_POST[ $field['id'] ] ) );
    219             }
    220 
    221         }
    222 
    223         if ( $_new_id && $_new_id != $_id_old ) {
    224             $updated[] = $_id_name;
    225             cmb_Meta_Box::update_data( $_new_id, $_id_name );
    226         } elseif ( '' == $_new_id && $_id_old ) {
    227             $updated[] = $_id_name;
    228             cmb_Meta_Box::remove_data( $_id_name, $old );
    229         }
    230 
    231         return self::default_sanitization( $meta, $field );
    232 
     10     * A CMB field object
     11     * @var cmb_Meta_Box_field object
     12     */
     13    public $field;
     14
     15    /**
     16     * Field's $_POST value
     17     * @var mixed
     18     */
     19    public $value;
     20
     21    /**
     22     * Setup our class vars
     23     * @since 1.1.0
     24     * @param object $field A CMB field object
     25     * @param mixed  $value Field value
     26     */
     27    public function __construct( $field, $value ) {
     28        $this->field       = $field;
     29        $this->value       = $value;
     30        $this->object_id   = cmb_Meta_Box::get_object_id();
     31        $this->object_type = cmb_Meta_Box::get_object_type();
    23332    }
    23433
     
    24039     */
    24140    public function __call( $name, $arguments ) {
    242         list( $meta_value, $field ) = $arguments;
    243         return self::default_sanitization( $meta_value, $field );
     41        list( $value ) = $arguments;
     42        return $this->default_sanitization( $value );
    24443    }
    24544
     
    24746     * Default fallback sanitization method. Applies filters.
    24847     * @since  1.0.2
    249      * @param  mixed $meta_value Meta value
    250      * @param  array $field      Field config array
    251      */
    252     public static function default_sanitization( $meta_value, $field ) {
    253 
    254         $object_type = cmb_Meta_Box::get_object_type();
    255         $object_id   = cmb_Meta_Box::get_object_id();
     48     * @param  mixed $value Meta value
     49     */
     50    public function default_sanitization( $value ) {
    25651
    25752        // Allow field type validation via filter
    258         $updated     = apply_filters( 'cmb_validate_'. $field['type'], null, $meta_value, $object_id, $field, $object_type );
    259 
    260         if ( null != $updated ) {
     53        $updated = apply_filters( 'cmb_validate_'. $this->field->type(), null, $value, $this->object_id, $this->field->args(), $this );
     54
     55        if ( null !== $updated )
    26156            return $updated;
    262         }
    263 
    264         // we'll fallback to 'sanitize_text_field', or 'wp_kses_post`
    265         switch ( $field['type'] ) {
     57
     58        switch ( $this->field->type() ) {
    26659            case 'wysiwyg':
    267                 // $cb = 'wp_kses';
     60                // $value = wp_kses( $value );
    26861                // break;
    26962            case 'textarea_small':
    270                 $cb = array( 'cmb_Meta_Box_Sanitize', 'textarea' );
    271                 break;
     63                return $this->textarea( $value );
     64            case 'taxonomy_select':
     65            case 'taxonomy_radio':
     66            case 'taxonomy_multicheck':
     67                if ( $this->field->args( 'taxonomy' ) ) {
     68                    return wp_set_object_terms( $this->object_id, $value, $this->field->args( 'taxonomy' ) );
     69                }
     70            case 'multicheck':
     71            case 'file_list':
     72            case 'oembed':
     73                // no filtering
     74                return $value;
    27275            default:
    273                 $cb = 'sanitize_text_field';
    274                 break;
    275         }
    276 
    277         // Handle repeatable fields array
    278         if ( is_array( $meta_value ) ) {
    279             foreach ( $meta_value as $key => $value ) {
    280                 $meta_value[ $key ] = call_user_func( $cb, $value );
     76                // Handle repeatable fields array
     77                // We'll fallback to 'sanitize_text_field'
     78                return is_array( $value ) ? array_map( 'sanitize_text_field', $value ) : call_user_func( 'sanitize_text_field', $value );
     79        }
     80    }
     81
     82    /**
     83     * Simple checkbox validation
     84     * @since  1.0.1
     85     * @param  mixed  $val 'on' or false
     86     * @return mixed         'on' or false
     87     */
     88    public function checkbox( $value ) {
     89        return $value === 'on' ? 'on' : false;
     90    }
     91
     92    /**
     93     * Validate url in a meta value
     94     * @since  1.0.1
     95     * @param  string $value  Meta value
     96     * @return string        Empty string or escaped url
     97     */
     98    public function text_url( $value ) {
     99        $protocols = $this->field->args( 'protocols' );
     100        // for repeatable
     101        if ( is_array( $value ) ) {
     102            foreach ( $value as $key => $val ) {
     103                $value[ $key ] = $val ? esc_url_raw( $val, $protocols ) : $this->field->args( 'default' );
    281104            }
    282105        } else {
    283             $meta_value = call_user_func( $cb, $meta_value );
    284         }
    285 
    286         return $meta_value;
     106            $value = $value ? esc_url_raw( $value, $protocols ) : $this->field->args( 'default' );
     107        }
     108
     109        return $value;
     110    }
     111
     112    public function colorpicker( $value ) {
     113        // for repeatable
     114        if ( is_array( $value ) ) {
     115            $check = $value;
     116            $value = array();
     117            foreach ( $check as $key => $val ) {
     118                if ( $val && '#' != $val ) {
     119                    $value[ $key ] = esc_attr( $val );
     120                }
     121            }
     122        } else {
     123            $value = ! $value || '#' == $value ? '' : esc_attr( $value );
     124        }
     125        return $value;
     126    }
     127
     128    /**
     129     * Validate email in a meta value
     130     * @since  1.0.1
     131     * @param  string $value Meta value
     132     * @return string       Empty string or validated email
     133     */
     134    public function text_email( $value ) {
     135        // for repeatable
     136        if ( is_array( $value ) ) {
     137            foreach ( $value as $key => $val ) {
     138                $val = trim( $val );
     139                $value[ $key ] = is_email( $val ) ? $val : '';
     140            }
     141        } else {
     142            $value = trim( $value );
     143            $value = is_email( $value ) ? $value : '';
     144        }
     145
     146        return $value;
     147    }
     148
     149    /**
     150     * Validate money in a meta value
     151     * @since  1.0.1
     152     * @param  string $value Meta value
     153     * @return string       Empty string or validated money value
     154     */
     155    public function text_money( $value ) {
     156
     157        global $wp_locale;
     158
     159        $search = array( $wp_locale->number_format['thousands_sep'], $wp_locale->number_format['decimal_point'] );
     160        $replace = array( '', '.' );
     161
     162        // for repeatable
     163        if ( is_array( $value ) ) {
     164            foreach ( $value as $key => $val ) {
     165                $value[ $key ] = number_format_i18n( (float) str_ireplace( $search, $replace, $val ), 2 );
     166            }
     167        } else {
     168            $value = number_format_i18n( (float) str_ireplace( $search, $replace, $value ), 2 );
     169        }
     170
     171        return $value;
     172    }
     173
     174    /**
     175     * Converts text date to timestamp
     176     * @since  1.0.2
     177     * @param  string $value Meta value
     178     * @return string       Timestring
     179     */
     180    public function text_date_timestamp( $value ) {
     181        return is_array( $value ) ? array_map( 'strtotime', $value ) : strtotime( $value );
     182    }
     183
     184    /**
     185     * Datetime to timestamp
     186     * @since  1.0.1
     187     * @param  string $value Meta value
     188     * @return string       Timestring
     189     */
     190    public function text_datetime_timestamp( $value, $repeat = false ) {
     191
     192        $test = is_array( $value ) ? array_filter( $value ) : '';
     193        if ( empty( $test ) )
     194            return '';
     195
     196        if ( $repeat_value = $this->_check_repeat( $value, __FUNCTION__, $repeat ) )
     197            return $repeat_value;
     198
     199        $value = strtotime( $value['date'] .' '. $value['time'] );
     200
     201        if ( $tz_offset = $this->field->field_timezone_offset() )
     202            $value += $tz_offset;
     203
     204        return $value;
     205    }
     206
     207    /**
     208     * Datetime to imestamp with timezone
     209     * @since  1.0.1
     210     * @param  string $value Meta value
     211     * @return string       Timestring
     212     */
     213    public function text_datetime_timestamp_timezone( $value, $repeat = false ) {
     214
     215        $test = is_array( $value ) ? array_filter( $value ) : '';
     216        if ( empty( $test ) )
     217            return '';
     218
     219        if ( $repeat_value = $this->_check_repeat( $value, __FUNCTION__, $repeat ) )
     220            return $repeat_value;
     221
     222        $tzstring = null;
     223
     224        if ( is_array( $value ) && array_key_exists( 'timezone', $value ) )
     225            $tzstring = $value['timezone'];
     226
     227        if ( empty( $tzstring ) )
     228            $tzstring = cmb_Meta_Box::timezone_string();
     229
     230        $offset = cmb_Meta_Box::timezone_offset( $tzstring, true );
     231
     232        if ( substr( $tzstring, 0, 3 ) === 'UTC' )
     233            $tzstring = timezone_name_from_abbr( '', $offset, 0 );
     234
     235        $value = new DateTime( $value['date'] .' '. $value['time'], new DateTimeZone( $tzstring ) );
     236        $value = serialize( $value );
     237
     238        return $value;
     239    }
     240
     241    /**
     242     * Sanitize textareas and wysiwyg fields
     243     * @since  1.0.1
     244     * @param  string $value Meta value
     245     * @return string       Sanitized data
     246     */
     247    public function textarea( $value ) {
     248        return is_array( $value ) ? array_map( 'wp_kses_post', $value ) : wp_kses_post( $value );
     249    }
     250
     251    /**
     252     * Sanitize code textareas
     253     * @since  1.0.2
     254     * @param  string $value Meta value
     255     * @return string       Sanitized data
     256     */
     257    public function textarea_code( $value, $repeat = false ) {
     258        if ( $repeat_value = $this->_check_repeat( $value, __FUNCTION__, $repeat ) )
     259            return $repeat_value;
     260
     261        return htmlspecialchars_decode( stripslashes( $value ) );
     262    }
     263
     264    /**
     265     * Peforms saving of `file` attachement's ID
     266     * @since  1.1.0
     267     * @param  string $value File url
     268     */
     269    public function _save_file_id( $value ) {
     270        $group      = $this->field->group;
     271        $args       = $this->field->args();
     272        $args['id'] = $args['_id'] . '_id';
     273
     274        unset( $args['_id'], $args['_name'] );
     275        // And get new field object
     276        $field      = new cmb_Meta_Box_field( $args, $group );
     277        $id_key     = $field->_id();
     278        $id_val_old = $field->escaped_value( 'absint' );
     279
     280        if ( $group ) {
     281            // Check group $_POST data
     282            $i       = $group->index;
     283            $base_id = $group->_id();
     284            $id_val  = isset( $_POST[ $base_id ][ $i ][ $id_key ] ) ? absint( $_POST[ $base_id ][ $i ][ $id_key ] ) : 0;
     285
     286        } else {
     287            // Check standard $_POST data
     288            $id_val = isset( $_POST[ $field->id() ] ) ? $_POST[ $field->id() ] : null;
     289
     290        }
     291
     292        // If there is no ID saved yet, try to get it from the url
     293        if ( $value && ! $id_val ) {
     294            $id_val = cmb_Meta_Box::image_id_from_url( $value );
     295        }
     296
     297        if ( $group ) {
     298            return array(
     299                'attach_id' => $id_val,
     300                'field_id'  => $id_key
     301            );
     302        }
     303
     304        if ( $id_val && $id_val != $id_val_old ) {
     305            return $field->update_data( $id_val );
     306        } elseif ( empty( $id_val ) && $id_val_old ) {
     307            return $field->remove_data( $old );
     308        }
     309    }
     310
     311    /**
     312     * Handles saving of attachment post ID and sanitizing file url
     313     * @since  1.1.0
     314     * @param  string $value File url
     315     * @return string        Sanitized url
     316     */
     317    public function file( $value ) {
     318        // If NOT specified to NOT save the file ID
     319        if ( $this->field->args( 'save_id' ) ) {
     320            $id_value = $this->_save_file_id( $value );
     321        }
     322        $clean = $this->text_url( $value );
     323
     324        // Return an array with url/id if saving a group field
     325        return $this->field->group ? array_merge( array( 'url' => $clean), $id_value ) : $clean;
     326    }
     327
     328    /**
     329     * If repeating, loop through and re-apply sanitization method
     330     * @since  1.1.0
     331     * @param  mixed  $value  Meta value
     332     * @param  string $method Class method
     333     * @param  bool   $repeat Whether repeating or not
     334     * @return mixed          Sanitized value
     335     */
     336    public function _check_repeat( $value, $method, $repeat ) {
     337        if ( $repeat || ! $this->field->args( 'repeatable' ) )
     338            return;
     339        $new_value = array();
     340        foreach ( $value as $iterator => $val ) {
     341            $new_value[] = $this->$method( $val, true );
     342        }
     343        return $new_value;
    287344    }
    288345
  • infinite-slider/trunk/public/includes/cmb/helpers/cmb_Meta_Box_ajax.php

    r884566 r969547  
    2020     * Creates or returns an instance of this class.
    2121     * @since  0.1.0
    22      * @return cmb_Meta_Box_types A single instance of this class.
     22     * @return cmb_Meta_Box_ajax A single instance of this class.
    2323     */
    2424    public static function get() {
     
    129129        // Send back our embed
    130130        if ( $check_embed && $check_embed != $fallback )
    131             return '<div class="embed_status">'. $check_embed .'<p><a href="#" class="cmb_remove_file_button" rel="'. $args['field_id'] .'">'. __( 'Remove Embed', 'cmb' ) .'</a></p></div>';
     131            return '<div class="embed_status">'. $check_embed .'<p class="cmb_remove_wrapper"><a href="#" class="cmb_remove_file_button" rel="'. $args['field_id'] .'">'. __( 'Remove Embed', 'cmb' ) .'</a></p></div>';
    132132
    133133        // Otherwise, send back error info that no oEmbeds were found
  • infinite-slider/trunk/public/includes/cmb/helpers/cmb_Meta_Box_types.php

    r884566 r969547  
    33/**
    44 * CMB field types
     5 *
     6 * @todo test taxonomy methods with non-post objects
     7 * @todo test all methods with non-post objects
     8 * @todo Date/Time fields should store date format as data attribute for JS
     9 *
    510 * @since  1.0.0
    611 */
     
    813
    914    /**
    10      * @todo test taxonomy methods with non-post objects
    11      * @todo test all methods with non-post objects
    12      */
    13 
    14     /**
    15      * A single instance of this class.
    16      * @var   cmb_Meta_Box_types object
    17      * @since 1.0.0
    18      */
    19     public static $instance = null;
    20 
    21     /**
    2215     * An iterator value for repeatable fields
    2316     * @var   integer
    2417     * @since 1.0.0
    2518     */
    26     public static $iterator = 0;
    27 
    28     /**
    29      * Holds cmb_valid_img_types
    30      * @var   array
    31      * @since 1.0.0
    32      */
    33     public static $valid = array();
    34 
    35     /**
    36      * Current field type
    37      * @var   string
    38      * @since 1.0.0
    39      */
    40     public static $type = 'text';
     19    public $iterator = 0;
    4120
    4221    /**
     
    4524     * @since 1.0.0
    4625     */
    47     public static $field;
    48 
    49     /**
    50      * Current field meta value
    51      * @var   mixed
    52      * @since 1.0.0
    53      */
    54     public static $meta;
    55 
    56     /**
    57      * Creates or returns an instance of this class.
     26    public $field;
     27
     28    public function __construct( $field ) {
     29        $this->field = $field;
     30    }
     31
     32    /**
     33     * Default fallback. Allows rendering fields via "cmb_render_$name" hook
    5834     * @since  1.0.0
    59      * @return cmb_Meta_Box_types A single instance of this class.
    60      */
    61     public static function get() {
    62         if ( self::$instance === null )
    63             self::$instance = new self();
    64 
    65         return self::$instance;
    66     }
    67 
    68     /**
    69      * Generates a field's description markup
    70      * @since  1.0.0
    71      * @param  string  $desc      Field's description
    72      * @param  boolean $paragraph Paragraph tag or span
    73      * @return strgin             Field's description markup
    74      */
    75     private static function desc( $paragraph = false ) {
    76         $tag = $paragraph ? 'p' : 'span';
    77         $desc = cmb_Meta_Box::$field['desc'];
    78         return "\n<$tag class=\"cmb_metabox_description\">$desc</$tag>\n";
    79     }
    80 
    81     /**
    82      * Generates repeatable text fields
    83      * @since  1.0.0
    84      * @param  string  $field Metabox field
    85      * @param  mixed   $meta  Field's meta value
    86      * @param  string  $class Field's class attribute
    87      * @param  string  $type  Field Type
    88      */
    89     private static function repeat_text_field( $meta, $class = '', $type = 'text' ) {
    90 
    91         $field = cmb_Meta_Box::$field; self::$meta = $meta; self::$type = $type;
    92 
    93         // check for default content
    94         $default = isset( $field['default'] ) ? array( $field['default'] ) : false;
    95         // check for saved data
    96         if ( !empty( $meta ) ) {
    97             $meta = is_array( $meta ) ? array_filter( $meta ) : $meta;
    98             $meta = ! empty( $meta ) ? $meta : $default;
     35     * @param  string $name      Non-existent method name
     36     * @param  array  $arguments All arguments passed to the method
     37     */
     38    public function __call( $name, $arguments ) {
     39        // When a non-registered field is called, send it through an action.
     40        do_action( "cmb_render_$name", $this->field->args(), $this->field->escaped_value(), $this->field->object_id, $this->field->object_type, $this );
     41    }
     42
     43    /**
     44     * Render a field (and handle repeatable)
     45     * @since  1.1.0
     46     */
     47    public function render() {
     48        if ( $this->field->args( 'repeatable' ) ) {
     49            $this->render_repeatable_field();
    9950        } else {
    100             $meta = $default;
    101         }
    102 
    103         self::repeat_table_open( $class );
    104 
    105         $class = $class ? $class .' widefat' : 'widefat';
    106 
    107         if ( !empty( $meta ) ) {
    108             foreach ( (array) $meta as $val ) {
    109                 self::repeat_row( self::text_input( $class, $val ) );
    110             }
    111         } else {
    112             self::repeat_row( self::text_input( $class ) );
    113         }
    114 
    115         self::empty_row( self::text_input( $class ) );
    116         self::repeat_table_close();
    117         // reset iterator
    118         self::$iterator = 0;
    119     }
    120 
    121     /**
    122      * Text input field used by repeatable fields
    123      * @since  1.0.0
    124      * @param  string  $class Field's class attribute
    125      * @param  mixed   $val   Field's meta value
    126      * @return string         HTML text input
    127      */
    128     private static function text_input( $class = '', $val = '' ) {
    129         self::$iterator = self::$iterator ? self::$iterator + 1 : 1;
    130         $before = '';
    131         if ( cmb_Meta_Box::$field['type'] == 'text_money' )
    132             $before = ! empty( cmb_Meta_Box::$field['before'] ) ? ' ' : '$ ';
    133         return $before . '<input type="'. self::$type .'" class="'. $class .'" name="'. cmb_Meta_Box::$field['id'] .'[]" id="'. cmb_Meta_Box::$field['id'] .'_'. self::$iterator .'" value="'. self::esc( $val ) .'" data-id="'. cmb_Meta_Box::$field['id'] .'" data-count="'. self::$iterator .'"/>';
    134     }
    135 
    136     /**
    137      * Generates repeatable field opening table markup for repeatable fields
    138      * @since  1.0.0
    139      * @param  string $class Field's class attribute
    140      */
    141     private static function repeat_table_open( $class = '' ) {
    142         echo self::desc(), '<table id="', cmb_Meta_Box::$field['id'], '_repeat" class="cmb-repeat-table ', $class ,'"><tbody>';
    143     }
    144 
    145     /**
    146      * Generates repeatable feild closing table markup for repeatable fields
    147      * @since 1.0.0
    148      */
    149     private static function repeat_table_close() {
    150         echo '</tbody></table><p class="add-row"><a data-selector="', cmb_Meta_Box::$field['id'] ,'_repeat" class="add-row-button button" href="#">'. __( 'Add Row', 'cmb' ) .'</a></p>';
    151     }
    152 
    153     /**
    154      * Generates table row markup for repeatable fields
    155      * @since 1.0.0
    156      * @param string $input Table cell markup
    157      */
    158     private static function repeat_row( $input ) {
    159         echo '<tr class="repeat-row">', self::repeat_cell( $input ) ,'</tr>';
    160     }
    161 
    162     /**
    163      * Generates the empty table row markup (for duplication) for repeatable fields
    164      * @since 1.0.0
    165      * @param string $input Table cell markup
    166      */
    167     private static function empty_row( $input ) {
    168         echo '<tr class="empty-row">', self::repeat_cell( $input ) ,'</tr>';
    169     }
    170 
    171     /**
    172      * Generates table cell markup for repeatable fields
    173      * @since  1.0.0
    174      * @param  string $input Text input field
    175      * @return string        HTML table cell markup
    176      */
    177     private static function repeat_cell( $input ) {
    178         return '<td>'. $input .'</td><td class="remove-row"><a class="button remove-row-button" href="#">'. __( 'Remove', 'cmb' ) .'</a></td>';
     51            $this->_render();
     52        }
     53    }
     54
     55    /**
     56     * Render a field type
     57     * @since  1.1.0
     58     */
     59    protected function _render() {
     60        echo $this->{$this->field->type()}();
     61    }
     62
     63    /**
     64     * Checks if we can get a post object, and if so, uses `get_the_terms` which utilizes caching
     65     * @since  1.0.2
     66     * @return mixed Array of terms on success
     67     */
     68    public function get_object_terms() {
     69        $object_id = $this->field->object_id;
     70        $taxonomy = $this->field->args( 'taxonomy' );
     71
     72        if ( ! $post = get_post( $object_id ) ) {
     73
     74            $cache_key = 'cmb-cache-'. $taxonomy .'-'. $object_id;
     75
     76            // Check cache
     77            $cached = $test = get_transient( $cache_key );
     78            if ( $cached )
     79                return $cached;
     80
     81            $cached = wp_get_object_terms( $object_id, $taxonomy );
     82            // Do our own (minimal) caching. Long enough for a page-load.
     83            $set = set_transient( $cache_key, $cached, 60 );
     84            return $cached;
     85        }
     86
     87        // WP caches internally so it's better to use
     88        return get_the_terms( $post, $taxonomy );
     89
    17990    }
    18091
     
    18596     * @return string|false       File extension or false
    18697     */
    187     public static function get_file_ext( $file ) {
     98    public function get_file_ext( $file ) {
    18899        $parsed = @parse_url( $file, PHP_URL_PATH );
    189100        return $parsed ? strtolower( pathinfo( $parsed, PATHINFO_EXTENSION ) ) : false;
     
    196107     * @return bool         Whether file has a valid image extension
    197108     */
    198     public static function is_valid_img_ext( $file ) {
    199         $file_ext = self::get_file_ext( $file );
    200 
    201         self::$valid = empty( self::$valid ) ? (array) apply_filters( 'cmb_valid_img_types', array( 'jpg', 'jpeg', 'png', 'gif', 'ico', 'icon' ) ) : self::$valid;
    202 
    203         return ( $file_ext && in_array( $file_ext, self::$valid ) );
    204     }
    205 
    206     /**
    207      * Checks if we can get a post object, and if so, uses `get_the_terms` which utilizes caching
    208      * @since  1.0.2
    209      * @param  integer $object_id Object ID
    210      * @param  string  $taxonomy  Taxonomy terms to return
    211      * @return mixed              Array of terms on success
    212      */
    213     public static function get_object_terms( $object_id, $taxonomy ) {
    214 
    215         if ( ! $post = get_post( $object_id ) ) {
    216 
    217             $cache_key = 'cmb-cache-'. $taxonomy .'-'. $object_id;
    218 
    219             // Check cache
    220             $cached = $test = get_transient( $cache_key );
    221             if ( $cached )
    222                 return $cached;
    223 
    224             $cached = wp_get_object_terms( $object_id, $taxonomy );
    225             // Do our own (minimal) caching. Long enough for a page-load.
    226             $set = set_transient( $cache_key, $cached, 60 );
    227             return $cached;
    228         }
    229 
    230         // WP caches internally so it's better to use
    231         return get_the_terms( $post, $taxonomy );
    232 
    233     }
    234 
    235     /**
    236      * Escape the value before output. Defaults to 'esc_attr()'
    237      * @since  1.0.1
    238      * @param  mixed  $meta_value Meta value
    239      * @param  mixed  $func       Escaping function (if not esc_attr())
    240      * @return mixed              Final value
    241      */
    242     public static function esc( $meta_value, $func = '' ) {
    243         $field = cmb_Meta_Box::$field;
    244 
    245         // Check if the field has a registered escaping callback
    246         $cb = cmb_Meta_Box::maybe_callback( $field, 'escape_cb' );
    247         if ( false === $cb ) {
    248             // If requesting NO escaping, return meta value
    249             return $meta_value;
    250         } elseif ( $cb ) {
    251             // Ok, callback is good, let's run it.
    252             return call_user_func( $cb, $meta_value, $field );
    253         }
    254 
    255         // Or custom escaping filter can be used
    256         $esc = apply_filters( 'cmb_types_esc_'. $field['type'], null, $meta_value, $field );
    257         if ( null !== $esc ) {
    258             return $esc;
    259         }
    260 
    261         // escaping function passed in?
    262         $func       = is_string( $func ) && ! empty( $func ) ? $func : 'esc_attr';
    263         $meta_value = ! empty( $meta_value ) ? $meta_value : $field['default'];
    264 
    265         return call_user_func( $func, $meta_value );
    266     }
    267 
     109    public function is_valid_img_ext( $file ) {
     110        $file_ext = $this->get_file_ext( $file );
     111
     112        $this->valid = empty( $this->valid )
     113            ? (array) apply_filters( 'cmb_valid_img_types', array( 'jpg', 'jpeg', 'png', 'gif', 'ico', 'icon' ) )
     114            : $this->valid;
     115
     116        return ( $file_ext && in_array( $file_ext, $this->valid ) );
     117    }
     118
     119    /**
     120     * Handles parsing and filtering attributes while preserving any passed in via field config.
     121     * @since  1.1.0
     122     * @param  array  $args     Override arguments
     123     * @param  string $element  Element for filter
     124     * @param  array  $defaults Default arguments
     125     * @return array            Parsed and filtered arguments
     126     */
     127    public function parse_args( $args, $element, $defaults ) {
     128        return wp_parse_args( apply_filters( "cmb_{$element}_attributes", $this->field->maybe_set_attributes( $args ), $this->field, $this ), $defaults );
     129    }
     130
     131    /**
     132     * Combines attributes into a string for a form element
     133     * @since  1.1.0
     134     * @param  array  $attrs        Attributes to concatenate
     135     * @param  array  $attr_exclude Attributes that should NOT be concatenated
     136     * @return string               String of attributes for form element
     137     */
     138    public function concat_attrs( $attrs, $attr_exclude = array() ) {
     139        $attributes = '';
     140        foreach ( $attrs as $attr => $val ) {
     141            if ( ! in_array( $attr, (array) $attr_exclude, true ) )
     142                $attributes .= sprintf( ' %s="%s"', $attr, $val );
     143        }
     144        return $attributes;
     145    }
     146
     147    /**
     148     * Generates html for an option element
     149     * @since  1.1.0
     150     * @param  string  $opt_label Option label
     151     * @param  string  $opt_value Option value
     152     * @param  mixed   $selected  Selected attribute if option is selected
     153     * @return string             Generated option element html
     154     */
     155    public function option( $opt_label, $opt_value, $selected ) {
     156        return sprintf( "\t".'<option value="%s" %s>%s</option>', $opt_value, selected( $selected, true, false ), $opt_label )."\n";
     157    }
     158
     159    /**
     160     * Generates options html
     161     * @since  1.1.0
     162     * @param  array   $args   Optional arguments
     163     * @param  string  $method Method to generate individual option item
     164     * @return string          Concatenated html options
     165     */
     166    public function concat_options( $args = array(), $method = 'list_input' ) {
     167
     168        $options     = (array) $this->field->args( 'options' );
     169        $saved_value = $this->field->escaped_value();
     170        $value       = $saved_value ? $saved_value : $this->field->args( 'default' );
     171
     172        $_options = ''; $i = 1;
     173        foreach ( $options as $option_key => $option ) {
     174
     175            // Check for the "old" way
     176            $opt_label  = is_array( $option ) && array_key_exists( 'name', $option ) ? $option['name'] : $option;
     177            $opt_value  = is_array( $option ) && array_key_exists( 'value', $option ) ? $option['value'] : $option_key;
     178            // Check if this option is the value of the input
     179            $is_current = $value == $opt_value;
     180
     181            if ( ! empty( $args ) ) {
     182                // Clone args & modify for just this item
     183                $this_args = $args;
     184                $this_args['value'] = $opt_value;
     185                $this_args['label'] = $opt_label;
     186                if ( $is_current )
     187                    $this_args['checked'] = 'checked';
     188
     189                $_options .= $this->$method( $this_args, $i );
     190            } else {
     191                $_options .= $this->option( $opt_label, $opt_value, $is_current );
     192            }
     193            $i++;
     194        }
     195        return $_options;
     196    }
     197
     198    /**
     199     * Generates html for list item with input
     200     * @since  1.1.0
     201     * @param  array  $args Override arguments
     202     * @param  int    $i    Iterator value
     203     * @return string       Gnerated list item html
     204     */
     205    public function list_input( $args = array(), $i ) {
     206        $args = $this->parse_args( $args, 'list_input', array(
     207            'type'  => 'radio',
     208            'class' => 'cmb_option',
     209            'name'  => $this->_name(),
     210            'id'    => $this->_id( $i ),
     211            'value' => $this->field->escaped_value(),
     212            'label' => '',
     213        ) );
     214
     215        return sprintf( "\t".'<li><input%s/> <label for="%s">%s</label></li>'."\n", $this->concat_attrs( $args, 'label' ), $args['id'], $args['label'] );
     216    }
     217
     218    /**
     219     * Generates html for list item with checkbox input
     220     * @since  1.1.0
     221     * @param  array  $args Override arguments
     222     * @param  int    $i    Iterator value
     223     * @return string       Gnerated list item html
     224     */
     225    public function list_input_checkbox( $args, $i ) {
     226        unset( $args['selected'] );
     227        $saved_value = $this->field->escaped_value();
     228        if ( is_array( $saved_value ) && in_array( $args['value'], $saved_value ) ) {
     229            $args['checked'] = 'checked';
     230        }
     231        return $this->list_input( $args, $i );
     232    }
     233
     234    /**
     235     * Generates repeatable field table markup
     236     * @since  1.0.0
     237     */
     238    public function render_repeatable_field() {
     239        $table_id = $this->field->id() .'_repeat';
     240
     241        $this->_desc( true, true );
     242        ?>
     243
     244        <table id="<?php echo $table_id; ?>" class="cmb-repeat-table">
     245            <tbody>
     246                <?php $this->repeatable_rows(); ?>
     247            </tbody>
     248        </table>
     249        <p class="add-row">
     250            <a data-selector="<?php echo $table_id; ?>" class="add-row-button button" href="#"><?php _e( 'Add Row', 'cmb' ); ?></a>
     251        </p>
     252
     253        <?php
     254        // reset iterator
     255        $this->iterator = 0;
     256    }
     257
     258    /**
     259     * Generates repeatable field rows
     260     * @since  1.1.0
     261     */
     262    public function repeatable_rows() {
     263        $meta_value = $this->field->escaped_value();
     264        // check for default content
     265        $default    = $this->field->args( 'default' );
     266
     267        // check for saved data
     268        if ( ! empty( $meta_value ) ) {
     269            $meta_value = is_array( $meta_value ) ? array_filter( $meta_value ) : $meta_value;
     270            $meta_value = ! empty( $meta_value ) ? $meta_value : $default;
     271        } else {
     272            $meta_value = $default;
     273        }
     274
     275        // Loop value array and add a row
     276        if ( ! empty( $meta_value ) ) {
     277            foreach ( (array) $meta_value as $val ) {
     278                $this->field->escaped_value = $val;
     279                $this->repeat_row();
     280                $this->iterator++;
     281            }
     282        } else {
     283            // Otherwise add one row
     284            $this->repeat_row();
     285        }
     286
     287        // Then add an empty row
     288        $this->field->escaped_value = '';
     289        $this->iterator = $this->iterator ? $this->iterator : 1;
     290        $this->repeat_row( 'empty-row' );
     291    }
     292
     293    /**
     294     * Generates a repeatable row's markup
     295     * @since  1.1.0
     296     * @param  string  $class Repeatable table row's class
     297     */
     298    protected function repeat_row( $class = 'repeat-row' ) {
     299        ?>
     300
     301        <tr class="<?php echo $class; ?>">
     302            <td>
     303                <?php $this->_render(); ?>
     304            </td>
     305            <td class="remove-row">
     306                <a class="button remove-row-button" href="#"><?php _e( 'Remove', 'cmb' ); ?></a>
     307            </td>
     308        </tr>
     309
     310        <?php
     311    }
     312
     313    /**
     314     * Generates description markup
     315     * @since  1.0.0
     316     * @param  boolean $paragraph Paragraph tag or span
     317     * @param  boolean $echo      Whether to echo description or only return it
     318     * @return string             Field's description markup
     319     */
     320    public function _desc( $paragraph = false, $echo = false ) {
     321        // Prevent description from printing multiple times for repeatable fields
     322        if ( $this->field->args( 'repeatable' ) || $this->iterator > 0 ) {
     323            return '';
     324        }
     325        $tag = $paragraph ? 'p' : 'span';
     326        $desc = "\n<$tag class=\"cmb_metabox_description\">{$this->field->args( 'description' )}</$tag>\n";
     327        if ( $echo )
     328            echo $desc;
     329        return $desc;
     330    }
     331
     332    /**
     333     * Generate field name attribute
     334     * @since  1.1.0
     335     * @param  string  $suffix For multi-part fields
     336     * @return string          Name attribute
     337     */
     338    public function _name( $suffix = '' ) {
     339        return $this->field->args( '_name' ) . ( $this->field->args( 'repeatable' ) ? '['. $this->iterator .']' : '' ) . $suffix;
     340    }
     341
     342    /**
     343     * Generate field id attribute
     344     * @since  1.1.0
     345     * @param  string  $suffix For multi-part fields
     346     * @return string          Id attribute
     347     */
     348    public function _id( $suffix = '' ) {
     349        return $this->field->id() . $suffix . ( $this->field->args( 'repeatable' ) ? '_'. $this->iterator .'" data-iterator="'. $this->iterator : '' );
     350    }
     351
     352    /**
     353     * Handles outputting an 'input' element
     354     * @since  1.1.0
     355     * @param  array  $args Override arguments
     356     * @return string       Form input element
     357     */
     358    public function input( $args = array() ) {
     359        $args = $this->parse_args( $args, 'input', array(
     360            'type'  => 'text',
     361            'class' => 'regular-text',
     362            'name'  => $this->_name(),
     363            'id'    => $this->_id(),
     364            'value' => $this->field->escaped_value(),
     365            'desc'  => $this->_desc( true ),
     366        ) );
     367
     368        return sprintf( '<input%s/>%s', $this->concat_attrs( $args, 'desc' ), $args['desc'] );
     369    }
     370
     371    /**
     372     * Handles outputting an 'textarea' element
     373     * @since  1.1.0
     374     * @param  array  $args Override arguments
     375     * @return string       Form textarea element
     376     */
     377    public function textarea( $args = array() ) {
     378        $args = $this->parse_args( $args, 'textarea', array(
     379            'class' => 'cmb_textarea',
     380            'name'  => $this->_name(),
     381            'id'    => $this->_id(),
     382            'cols'  => 60,
     383            'rows'  => 10,
     384            'value' => $this->field->escaped_value( 'esc_textarea' ),
     385            'desc'  => $this->_desc( true ),
     386        ) );
     387        return sprintf( '<textarea%s>%s</textarea>%s', $this->concat_attrs( $args, array( 'desc', 'value' ) ), $args['value'], $args['desc'] );
     388    }
    268389
    269390    /**
     
    271392     */
    272393
    273     public static function text( $field, $meta ) {
    274         if ( $field['repeatable'] ) {
    275             return self::repeat_text_field( $meta );
    276         }
    277 
    278         echo '<input type="text" class="regular-text" name="', $field['id'], '" id="', $field['id'], '" value="', self::esc( $meta ), '" />', self::desc( true );
    279     }
    280 
    281     public static function text_small( $field, $meta ) {
    282         if ( $field['repeatable'] ) {
    283             return self::repeat_text_field( $meta, 'cmb_text_small' );
    284         }
    285 
    286         echo '<input class="cmb_text_small" type="text" name="', $field['id'], '" id="', $field['id'], '" value="', self::esc( $meta ), '" />', self::desc();
    287     }
    288 
    289     public static function text_medium( $field, $meta ) {
    290         if ( $field['repeatable'] ) {
    291             return self::repeat_text_field( $meta, 'cmb_text_medium' );
    292         }
    293         echo '<input class="cmb_text_medium" type="text" name="', $field['id'], '" id="', $field['id'], '" value="', self::esc( $meta ), '" />', self::desc();
    294     }
    295 
    296     public static function text_email( $field, $meta ) {
    297         if ( $field['repeatable'] ) {
    298             return self::repeat_text_field( $meta, 'cmb_text_email cmb_text_medium', 'email' );
    299         }
    300 
    301         echo '<input class="cmb_text_email cmb_text_medium" type="email" name="', $field['id'], '" id="', $field['id'], '" value="', self::esc( $meta ), '" />', self::desc( true );
    302     }
    303 
    304     public static function text_url( $field, $meta ) {
    305         if ( $field['repeatable'] ) {
    306             return self::repeat_text_field( $meta, 'cmb_text_url cmb_text_medium' );
    307         }
    308 
    309         echo '<input class="cmb_text_url cmb_text_medium regular-text" type="text" name="', $field['id'], '" id="', $field['id'], '" value="', self::esc( $meta, 'esc_url' ), '" />', self::desc( true );
    310     }
    311 
    312     public static function text_date( $field, $meta ) {
    313         echo '<input class="cmb_text_small cmb_datepicker" type="text" name="', $field['id'], '" id="', $field['id'], '" value="', self::esc( $meta ), '" />', self::desc();
    314     }
    315 
    316     public static function text_date_timestamp( $field, $meta ) {
    317         echo '<input class="cmb_text_small cmb_datepicker" type="text" name="', $field['id'], '" id="', $field['id'], '" value="', ! empty( $meta ) ? date( 'm\/d\/Y', $meta ) : $field['default'], '" />', self::desc();
    318     }
    319 
    320     public static function text_datetime_timestamp( $field, $meta, $object_id ) {
    321 
    322         // This will be used if there is a select_timezone set for this field
    323         $tz_offset = cmb_Meta_Box::field_timezone_offset( $object_id );
    324         if ( ! empty( $tz_offset ) ) {
    325             $meta -= $tz_offset;
    326         }
    327 
    328         echo '<input class="cmb_text_small cmb_datepicker" type="text" name="', $field['id'], '[date]" id="', $field['id'], '_date" value="', ! empty( $meta ) ? date( 'm\/d\/Y', $meta ) : $field['default'], '" />';
    329         echo '<input class="cmb_timepicker text_time" type="text" name="', $field['id'], '[time]" id="', $field['id'], '_time" value="', ! empty( $meta ) ? date( 'h:i A', $meta ) : $field['default'], '" />', self::desc();
    330     }
    331 
    332     public static function text_datetime_timestamp_timezone( $field, $meta ) {
    333 
    334         $datetime = unserialize( $meta );
    335         $meta = $tzstring = false;
     394    public function text() {
     395        return $this->input();
     396    }
     397
     398    public function text_small() {
     399        return $this->input( array( 'class' => 'cmb_text_small', 'desc' => $this->_desc() ) );
     400    }
     401
     402    public function text_medium() {
     403        return $this->input( array( 'class' => 'cmb_text_medium', 'desc' => $this->_desc() ) );
     404    }
     405
     406    public function text_email() {
     407        return $this->input( array( 'class' => 'cmb_text_email cmb_text_medium', 'type' => 'email' ) );
     408    }
     409
     410    public function text_url() {
     411        return $this->input( array( 'class' => 'cmb_text_url cmb_text_medium regular-text', 'value' => $this->field->escaped_value( 'esc_url' ) ) );
     412    }
     413
     414    public function text_date() {
     415        return $this->input( array( 'class' => 'cmb_text_small cmb_datepicker', 'desc' => $this->_desc() ) );
     416    }
     417
     418    public function text_time() {
     419        return $this->input( array( 'class' => 'cmb_timepicker text_time', 'desc' => $this->_desc() ) );
     420    }
     421
     422    public function text_money() {
     423        return ( ! $this->field->args( 'before' ) ? '$ ' : ' ' ) . $this->input( array( 'class' => 'cmb_text_money', 'desc' => $this->_desc() ) );
     424    }
     425
     426    public function textarea_small() {
     427        return $this->textarea( array( 'class' => 'cmb_textarea_small', 'rows' => 4 ) );
     428    }
     429
     430    public function textarea_code() {
     431        return sprintf( '<pre>%s</pre>', $this->textarea( array( 'class' => 'cmb_textarea_code' )  ) );
     432    }
     433
     434    public function wysiwyg( $args = array() ) {
     435        extract( $this->parse_args( $args, 'input', array(
     436            'id'      => $this->_id(),
     437            'value'   => $this->field->escaped_value( 'stripslashes' ),
     438            'desc'    => $this->_desc( true ),
     439            'options' => $this->field->args( 'options' ),
     440        ) ) );
     441
     442        wp_editor( $value, $id, $options );
     443        echo $desc;
     444    }
     445
     446    public function text_date_timestamp() {
     447        $meta_value = $this->field->escaped_value();
     448        $value = ! empty( $meta_value ) ? date( $this->field->args( 'date_format' ), $meta_value ) : '';
     449        return $this->input( array( 'class' => 'cmb_text_small cmb_datepicker', 'value' => $value ) );
     450    }
     451
     452    public function text_datetime_timestamp( $meta_value = '' ) {
     453        $desc = '';
     454        if ( ! $meta_value ) {
     455            $meta_value = $this->field->escaped_value();
     456            // This will be used if there is a select_timezone set for this field
     457            $tz_offset = $this->field->field_timezone_offset();
     458            if ( ! empty( $tz_offset ) ) {
     459                $meta_value -= $tz_offset;
     460            }
     461            $desc = $this->_desc();
     462        }
     463
     464        $inputs = array(
     465            $this->input( array(
     466                'class' => 'cmb_text_small cmb_datepicker',
     467                'name'  => $this->_name( '[date]' ),
     468                'id'    => $this->_id( '_date' ),
     469                'value' => ! empty( $meta_value ) ? date( $this->field->args( 'date_format' ), $meta_value ) : '',
     470                'desc'  => '',
     471            ) ),
     472            $this->input( array(
     473                'class' => 'cmb_timepicker text_time',
     474                'name'  => $this->_name( '[time]' ),
     475                'id'    => $this->_id( '_time' ),
     476                'value' => ! empty( $meta_value ) ? date( $this->field->args( 'time_format' ), $meta_value ) : '',
     477                'desc'  => $desc,
     478            ) )
     479        );
     480
     481        return implode( "\n", $inputs );
     482    }
     483
     484    public function text_datetime_timestamp_timezone() {
     485        $meta_value = $this->field->escaped_value();
     486        $datetime   = unserialize( $meta_value );
     487        $meta_value = $tzstring = false;
    336488
    337489        if ( $datetime && $datetime instanceof DateTime ) {
    338             $tz = $datetime->getTimezone();
    339             $tzstring = $tz->getName();
    340 
    341             $meta = $datetime->getTimestamp() + $tz->getOffset( new DateTime('NOW') );
    342         }
    343 
    344         echo '<input class="cmb_text_small cmb_datepicker" type="text" name="', $field['id'], '[date]" id="', $field['id'], '_date" value="', ! empty( $meta ) ? date( 'm\/d\/Y', $meta ) : $field['default'], '" />';
    345         echo '<input class="cmb_timepicker text_time" type="text" name="', $field['id'], '[time]" id="', $field['id'], '_time" value="', ! empty( $meta ) ? date( 'h:i A', $meta ) : $field['default'], '" />';
    346 
    347         echo '<select name="', $field['id'], '[timezone]" id="', $field['id'], '_timezone">';
    348         echo wp_timezone_choice( $tzstring );
    349         echo '</select>', self::desc();
    350     }
    351 
    352     public static function text_time( $field, $meta ) {
    353         echo '<input class="cmb_timepicker text_time" type="text" name="', $field['id'], '" id="', $field['id'], '" value="', self::esc( $meta ), '" />', self::desc();
    354     }
    355 
    356     public static function select_timezone( $field, $meta ) {
    357         $meta = self::esc( $meta );
    358         if ( '' === $meta )
    359             $meta = cmb_Meta_Box::timezone_string();
    360 
    361         echo '<select name="', $field['id'], '" id="', $field['id'], '">';
    362         echo wp_timezone_choice( $meta );
    363         echo '</select>';
    364     }
    365 
    366     public static function text_money( $field, $meta ) {
    367         if ( $field['repeatable'] ) {
    368             return self::repeat_text_field( $meta, 'cmb_text_money' );
    369         }
    370 
    371         echo ! empty( $field['before'] ) ? '' : '$', ' <input class="cmb_text_money" type="text" name="', $field['id'], '" id="', $field['id'], '" value="', self::esc( $meta ), '" />', self::desc();
    372     }
    373 
    374     public static function colorpicker( $field, $meta ) {
    375         $meta = self::esc( $meta );
     490            $tz         = $datetime->getTimezone();
     491            $tzstring   = $tz->getName();
     492            $meta_value = $datetime->getTimestamp() + $tz->getOffset( new DateTime( 'NOW' ) );
     493        }
     494
     495        $inputs = $this->text_datetime_timestamp( $meta_value );
     496        $inputs .= '<select name="'. $this->_name( '[timezone]' ) .'" id="'. $this->_id( '_timezone' ) .'">';
     497        $inputs .= wp_timezone_choice( $tzstring );
     498        $inputs .= '</select>'. $this->_desc();
     499
     500        return $inputs;
     501    }
     502
     503    public function select_timezone() {
     504        $this->field->args['default'] = $this->field->args( 'default' )
     505            ? $this->field->args( 'default' )
     506            : cmb_Meta_Box::timezone_string();
     507
     508        $meta_value = $this->field->escaped_value();
     509
     510        return '<select name="'. $this->_name() .'" id="'. $this->_id() .'">'. wp_timezone_choice( $meta_value ) .'</select>';
     511    }
     512
     513    public function colorpicker() {
     514        $meta_value = $this->field->escaped_value();
    376515        $hex_color = '(([a-fA-F0-9]){3}){1,2}$';
    377         if ( preg_match( '/^' . $hex_color . '/i', $meta ) ) // Value is just 123abc, so prepend #.
    378             $meta = '#' . $meta;
    379         elseif ( ! preg_match( '/^#' . $hex_color . '/i', $meta ) ) // Value doesn't match #123abc, so sanitize to just #.
    380             $meta = "#";
    381         echo '<input class="cmb_colorpicker cmb_text_small" type="text" name="', $field['id'], '" id="', $field['id'], '" value="', $meta, '" />', self::desc();
    382     }
    383 
    384     public static function textarea( $field, $meta ) {
    385         echo '<textarea name="', $field['id'], '" id="', $field['id'], '" cols="60" rows="10">', self::esc( $meta, 'esc_textarea' ), '</textarea>', self::desc( true );
    386     }
    387 
    388     public static function textarea_small( $field, $meta ) {
    389         echo '<textarea name="', $field['id'], '" id="', $field['id'], '" cols="60" rows="4">', self::esc( $meta, 'esc_textarea' ), '</textarea>', self::desc( true );
    390     }
    391 
    392     public static function textarea_code( $field, $meta ) {
    393         echo '<pre><textarea name="', $field['id'], '" id="', $field['id'], '" cols="60" rows="10" class="cmb_textarea_code">', ! empty( $meta ) ? $meta : $field['default'], '</textarea></pre>', self::desc( true );
    394     }
    395 
    396     public static function select( $field, $meta ) {
    397         $meta = self::esc( $meta );
    398         echo '<select name="', $field['id'], '" id="', $field['id'], '">';
    399         foreach ( $field['options'] as $option_key => $option ) {
    400 
    401             // Check for the "old" way
    402             $label = isset( $option['name'] ) ? $option['name'] : $option;
    403             $value = isset( $option['value'] ) ? $option['value'] : $option_key;
    404 
    405             echo '<option value="', $value, '" ', selected( $meta == $value ) ,'>', $label, '</option>';
    406 
    407         }
    408         echo '</select>', self::desc( true );
    409     }
    410 
    411     public static function radio( $field, $meta ) {
    412         $meta = self::esc( $meta );
    413         echo '<ul>';
    414         $i = 1;
    415         foreach ( $field['options'] as $option_key => $option ) {
    416 
    417             // Check for the "old" way
    418             $label = isset( $option['name'] ) ? $option['name'] : $option;
    419             $value = isset( $option['value'] ) ? $option['value'] : $option_key;
    420 
    421             echo '<li class="cmb_option"><input type="radio" name="', $field['id'], '" id="', $field['id'], $i,'" value="', $value, '" ', checked( $meta == $value ), ' /> <label for="', $field['id'], $i, '">', $label ,'</label></li>';
    422             $i++;
    423         }
    424         echo '</ul>', self::desc( true );
    425     }
    426 
    427     public static function radio_inline( $field, $meta ) {
    428         self::radio( $field, $meta );
    429     }
    430 
    431     public static function checkbox( $field, $meta ) {
    432         echo '<input class="cmb_option" type="checkbox" name="', $field['id'], '" id="', $field['id'], '" ', checked( ! empty( $meta ) ), ' value="on"/> <label for="', $field['id'], '">', self::desc() ,'</label>';
    433     }
    434 
    435     public static function multicheck( $field, $meta ) {
    436         echo '<ul>';
    437         $i = 1;
    438         foreach ( $field['options'] as $value => $name ) {
    439             echo '<li><input class="cmb_option" type="checkbox" name="', $field['id'], '[]" id="', $field['id'], $i, '" value="', $value, '" ', checked( is_array( $meta ) && in_array( $value, $meta ) ), '  /> <label for="', $field['id'], $i, '">', $name, '</label></li>';
    440             $i++;
    441         }
    442         echo '</ul>', self::desc();
    443     }
    444 
    445     public static function multicheck_inline( $field, $meta ) {
    446         self::multicheck( $field, $meta );
    447     }
    448 
    449     public static function title( $field, $meta, $object_id, $object_type ) {
    450         $tag = $object_type == 'post' ? 'h5' : 'h3';
    451         echo '<'. $tag .' class="cmb_metabox_title">', $field['name'], '</'. $tag .'>', self::desc( true );
    452     }
    453 
    454     public static function wysiwyg( $field, $meta ) {
    455         wp_editor( stripslashes( html_entity_decode( self::esc( $meta, 'esc_html' ) ) ), $field['id'], isset( $field['options'] ) ? $field['options'] : array() );
    456         echo self::desc( true );
    457     }
    458 
    459     public static function taxonomy_select( $field, $meta, $object_id ) {
    460 
    461         echo '<select name="', $field['id'], '" id="', $field['id'], '">';
    462         $names    = self::get_object_terms( $object_id, $field['taxonomy'] );
    463         $terms    = get_terms( $field['taxonomy'], 'hide_empty=0' );
    464         $has_term = false;
     516        if ( preg_match( '/^' . $hex_color . '/i', $meta_value ) ) // Value is just 123abc, so prepend #.
     517            $meta_value = '#' . $meta_value;
     518        elseif ( ! preg_match( '/^#' . $hex_color . '/i', $meta_value ) ) // Value doesn't match #123abc, so sanitize to just #.
     519            $meta_value = "#";
     520
     521        return $this->input( array( 'class' => 'cmb_colorpicker cmb_text_small', 'value' => $meta_value ) );
     522    }
     523
     524    public function title() {
     525        extract( $this->parse_args( array(), 'title', array(
     526            'tag'   => $this->field->object_type == 'post' ? 'h5' : 'h3',
     527            'class' => 'cmb_metabox_title',
     528            'name'  => $this->field->args( 'name' ),
     529            'desc'  => $this->_desc( true ),
     530        ) ) );
     531
     532        return sprintf( '<%1$s class="%2$s">%3$s</%1$s>%4$s', $tag, $class, $name, $desc );
     533    }
     534
     535    public function select( $args = array() ) {
     536        $args = $this->parse_args( $args, 'select', array(
     537            'class'   => 'cmb_select',
     538            'name'    => $this->_name(),
     539            'id'      => $this->_id(),
     540            'desc'    => $this->_desc( true ),
     541            'options' => $this->concat_options(),
     542        ) );
     543
     544        $attrs = $this->concat_attrs( $args, array( 'desc', 'options' ) );
     545        return sprintf( '<select%s>%s</select>%s', $attrs, $args['options'], $args['desc'] );
     546    }
     547
     548    public function taxonomy_select() {
     549
     550        $names      = $this->get_object_terms();
     551        $saved_term = is_wp_error( $names ) || empty( $names ) ? $this->field->args( 'default' ) : $names[0]->slug;
     552        $terms      = get_terms( $this->field->args( 'taxonomy' ), 'hide_empty=0' );
     553        $options    = '';
    465554
    466555        foreach ( $terms as $term ) {
    467             if ( !is_wp_error( $names ) && !empty( $names ) && ! strcmp( $term->slug, $names[0]->slug ) ) {
    468                 echo '<option value="' . $term->slug . '" selected>' . $term->name . '</option>';
    469                 $has_term = true;
     556            $selected = $saved_term == $term->slug;
     557            $options .= $this->option( $term->name, $term->slug, $selected );
     558        }
     559
     560        return $this->select( array( 'options' => $options ) );
     561    }
     562
     563    public function radio( $args = array(), $type = 'radio' ) {
     564        extract( $this->parse_args( $args, $type, array(
     565            'class'   => 'cmb_radio_list cmb_list',
     566            'options' => $this->concat_options( array( 'label' => 'test' ) ),
     567            'desc'    => $this->_desc( true ),
     568        ) ) );
     569
     570        return sprintf( '<ul class="%s">%s</ul>%s', $class, $options, $desc );
     571    }
     572
     573    public function radio_inline() {
     574        return $this->radio( array(), 'radio_inline' );
     575    }
     576
     577    public function multicheck( $type = 'checkbox' ) {
     578        return $this->radio( array( 'class' => 'cmb_checkbox_list cmb_list', 'options' => $this->concat_options( array( 'type' => 'checkbox', 'name' => $this->_name() .'[]' ), 'list_input_checkbox' ) ), $type );
     579    }
     580
     581    public function multicheck_inline() {
     582        $this->multicheck( 'multicheck_inline' );
     583    }
     584
     585    public function checkbox() {
     586        $meta_value = $this->field->escaped_value();
     587        $args = array( 'type' => 'checkbox', 'class' => 'cmb_option cmb_list', 'value' => 'on', 'desc' => '' );
     588        if ( ! empty( $meta_value ) ) {
     589            $args['checked'] = 'checked';
     590        }
     591        return sprintf( '%s <label for="%s">%s</label>', $this->input( $args ), $this->_id(), $this->_desc() );
     592    }
     593
     594    public function taxonomy_radio() {
     595        $names      = $this->get_object_terms();
     596        $saved_term = is_wp_error( $names ) || empty( $names ) ? $this->field->args( 'default' ) : $names[0]->slug;
     597        $terms      = get_terms( $this->field->args( 'taxonomy' ), 'hide_empty=0' );
     598        $options    = ''; $i = 1;
     599
     600        if ( ! $terms ) {
     601            $options .= '<li><label>'. __( 'No terms', 'cmb' ) .'</label></li>';
     602        } else {
     603            foreach ( $terms as $term ) {
     604                $args = array(
     605                    'value' => $term->slug,
     606                    'label' => $term->name,
     607                );
     608
     609                if ( $saved_term == $term->slug ) {
     610                    $args['checked'] = 'checked';
     611                }
     612                $options .= $this->list_input( $args, $i );
     613                $i++;
    470614            }
    471             else if ( ! $has_term == false && $term->slug == $field['default'] ) {
    472                 echo '<option value="' . $term->slug . '" selected>' . $term->name . '</option>';
    473             } else {
    474                 echo '<option value="' . $term->slug . '  ' , $meta == $term->slug ? $meta : ' ' ,'  ">' . $term->name . '</option>';
     615        }
     616
     617        return $this->radio( array( 'options' => $options ), 'taxonomy_radio' );
     618    }
     619
     620    public function taxonomy_radio_inline() {
     621        $this->taxonomy_radio();
     622    }
     623
     624    public function taxonomy_multicheck() {
     625
     626        $names   = $this->get_object_terms();
     627        $saved_terms   = is_wp_error( $names ) || empty( $names )
     628            ? $this->field->args( 'default' )
     629            : wp_list_pluck( $names, 'slug' );
     630        $terms   = get_terms( $this->field->args( 'taxonomy' ), 'hide_empty=0' );
     631        $name    = $this->_name() .'[]';
     632        $options = ''; $i = 1;
     633
     634        if ( ! $terms ) {
     635            $options .= '<li><label>'. __( 'No terms', 'cmb' ) .'</label></li>';
     636        } else {
     637
     638            foreach ( $terms as $term ) {
     639                $args = array(
     640                    'value' => $term->slug,
     641                    'label' => $term->name,
     642                    'type' => 'checkbox',
     643                    'name' => $name,
     644                );
     645
     646                if ( is_array( $saved_terms ) && in_array( $term->slug, $saved_terms ) ) {
     647                    $args['checked'] = 'checked';
     648                }
     649                $options .= $this->list_input( $args, $i );
     650                $i++;
    475651            }
    476652        }
    477         echo '</select>', self::desc( true );
    478     }
    479 
    480     public static function taxonomy_radio( $field, $meta, $object_id ) {
    481 
    482         $names = self::get_object_terms( $object_id, $field['taxonomy'] );
    483         $terms = get_terms( $field['taxonomy'], 'hide_empty=0' );
    484         echo '<ul>';
    485         $i = 1;
    486         foreach ( $terms as $term ) {
    487             $checked = ( !is_wp_error( $names ) && !empty( $names ) && !strcmp( $term->slug, $names[0]->slug ) );
    488 
    489             echo '<li class="cmb_option"><input type="radio" name="', $field['id'], '" id="', $field['id'], $i,'" value="'. $term->slug . '" ', checked( $checked ), ' /> <label for="', $field['id'], $i, '">' . $term->name . '</label></li>';
    490             $i++;
    491         }
    492         echo '</ul>', self::desc( true );
    493     }
    494 
    495     public static function taxonomy_radio_inline( $field, $meta ) {
    496         self::taxonomy_radio( $field, $meta );
    497     }
    498 
    499     public static function taxonomy_multicheck( $field, $meta, $object_id ) {
    500         echo '<ul>';
    501         $names = self::get_object_terms( $object_id, $field['taxonomy'] );
    502         $terms = get_terms( $field['taxonomy'], 'hide_empty=0' );
    503         $i = 1;
    504         foreach ( $terms as $term ) {
    505             echo '<li><input class="cmb_option" type="checkbox" name="', $field['id'], '[]" id="', $field['id'], $i,'" value="'. $term->slug . '" ';
    506             foreach ($names as $name) {
    507                 checked( $term->slug == $name->slug );
    508             }
    509 
    510             echo ' /> <label for="', $field['id'], $i, '">' . $term->name . '</label></li>';
    511             $i++;
    512         }
    513         echo '</ul>', self::desc();
    514     }
    515 
    516     public static function taxonomy_multicheck_inline( $field, $meta ) {
    517         self::taxonomy_multicheck( $field, $meta );
    518     }
    519 
    520     public static function file_list( $field, $meta, $object_id ) {
    521 
    522         echo '<input class="cmb_upload_file cmb_upload_list" type="hidden" size="45" id="', $field['id'], '" name="', $field['id'], '" value="" />';
    523         echo '<input class="cmb_upload_button button cmb_upload_list" type="button" value="'. __( 'Add or Upload File', 'cmb' ) .'" />', self::desc( true );
    524 
    525         echo '<ul id="', $field['id'], '_status" class="cmb_media_status attach_list">';
    526 
    527         if ( $meta && is_array( $meta ) ) {
    528 
    529             $preview_size = empty( $field['preview_size'] ) ? array( 50, 50 ) : $field['preview_size'];
    530 
    531             foreach ( $meta as $id => $fullurl ) {
    532                 if ( self::is_valid_img_ext( $fullurl ) ) {
     653
     654        return $this->radio( array( 'class' => 'cmb_checkbox_list cmb_list', 'options' => $options ), 'taxonomy_multicheck' );
     655    }
     656
     657    public function taxonomy_multicheck_inline() {
     658        $this->taxonomy_multicheck();
     659    }
     660
     661    public function file_list() {
     662        $meta_value = $this->field->escaped_value();
     663
     664        $name = $this->_name();
     665
     666        echo $this->input( array(
     667            'type'  => 'hidden',
     668            'class' => 'cmb_upload_file cmb_upload_list',
     669            'size'  => 45, 'desc'  => '', 'value'  => '',
     670        ) ),
     671        $this->input( array(
     672            'type'  => 'button',
     673            'class' => 'cmb_upload_button button cmb_upload_list',
     674            'value'  => __( 'Add or Upload File', 'cmb' ),
     675            'name'  => '', 'id'  => '',
     676        ) );
     677
     678        echo '<ul id="', $this->_id( '_status' ) ,'" class="cmb_media_status attach_list">';
     679
     680        if ( $meta_value && is_array( $meta_value ) ) {
     681
     682            foreach ( $meta_value as $id => $fullurl ) {
     683                $id_input = $this->input( array(
     684                    'type'  => 'hidden',
     685                    'value' => $fullurl,
     686                    'name'  => $name .'['. $id .']',
     687                    'id'    => 'filelist-'. $id,
     688                    'desc'  => '', 'class' => '',
     689                ) );
     690
     691                if ( $this->is_valid_img_ext( $fullurl ) ) {
    533692                    echo
    534693                    '<li class="img_status">',
    535                         wp_get_attachment_image( $id, $preview_size ),
    536                         '<p><a href="#" class="cmb_remove_file_button">'. __( 'Remove Image', 'cmb' ) .'</a></p>
    537                         <input type="hidden" id="filelist-', $id ,'" name="', $field['id'] ,'[', $id ,']" value="', $fullurl ,'" />
     694                        wp_get_attachment_image( $id, $this->field->args( 'preview_size' ) ),
     695                        '<p class="cmb_remove_wrapper"><a href="#" class="cmb_remove_file_button">'. __( 'Remove Image', 'cmb' ) .'</a></p>
     696                        '. $id_input .'
    538697                    </li>';
    539698
     
    546705                    '<li>',
    547706                        __( 'File:', 'cmb' ), ' <strong>', $title, '</strong>&nbsp;&nbsp;&nbsp; (<a href="', $fullurl, '" target="_blank" rel="external">'. __( 'Download', 'cmb' ) .'</a> / <a href="#" class="cmb_remove_file_button">'. __( 'Remove', 'cmb' ) .'</a>)
    548                         <input type="hidden" id="filelist-', $id ,'" name="', $field['id'] ,'[', $id ,']" value="', $fullurl ,'" />
     707                        '. $id_input .'
    549708                    </li>';
    550709                }
     
    555714    }
    556715
    557     public static function file( $field, $meta, $object_id, $object_type ) {
    558 
    559         $input_type_url = 'hidden';
    560         if ( 'url' == $field['allow'] || ( is_array( $field['allow'] ) && in_array( 'url', $field['allow'] ) ) )
    561             $input_type_url = 'text';
    562         echo '<input class="cmb_upload_file" type="' . $input_type_url . '" size="45" id="', $field['id'], '" name="', $field['id'], '" value="', $meta, '" />';
    563         echo '<input class="cmb_upload_button button" type="button" value="'. __( 'Add or Upload File', 'cmb' ) .'" />';
    564 
    565         $_id_name = $field['id'] .'_id';
    566 
    567         $_id_meta = cmb_Meta_Box::get_data( $_id_name );
     716    public function file() {
     717        $meta_value = $this->field->escaped_value();
     718        $allow      = $this->field->args( 'allow' );
     719        $input_type = ( 'url' == $allow || ( is_array( $allow ) && in_array( 'url', $allow ) ) )
     720            ? 'text' : 'hidden';
     721
     722        echo $this->input( array(
     723            'type'  => $input_type,
     724            'class' => 'cmb_upload_file',
     725            'size'  => 45,
     726            'desc'  => '',
     727        ) ),
     728        '<input class="cmb_upload_button button" type="button" value="'. __( 'Add or Upload File', 'cmb' ) .'" />',
     729        $this->_desc( true );
     730
     731        $cached_id = $this->_id();
     732        // Reset field args for attachment ID
     733        $args = $this->field->args();
     734        $args['id'] = $args['_id'] . '_id';
     735        unset( $args['_id'], $args['_name'] );
     736
     737        // And get new field object
     738        $this->field = new cmb_Meta_Box_field( $args, $this->field->group );
     739
     740        // Get ID value
     741        $_id_value = $this->field->escaped_value( 'absint' );
    568742
    569743        // If there is no ID saved yet, try to get it from the url
    570         if ( $meta && ! $_id_meta ) {
    571             $_id_meta = cmb_Meta_Box::image_id_from_url( esc_url_raw( $meta ) );
    572         }
    573 
    574         echo '<input class="cmb_upload_file_id" type="hidden" id="', $_id_name, '" name="', $_id_name, '" value="', $_id_meta, '" />',
    575         self::desc( true ),
    576         '<div id="', $field['id'], '_status" class="cmb_media_status">';
    577             if ( ! empty( $meta ) ) {
    578 
    579                 if ( self::is_valid_img_ext( $meta ) ) {
     744        if ( $meta_value && ! $_id_value ) {
     745            $_id_value = cmb_Meta_Box::image_id_from_url( esc_url_raw( $meta_value ) );
     746        }
     747
     748        echo $this->input( array(
     749            'type'  => 'hidden',
     750            'class' => 'cmb_upload_file_id',
     751            'value' => $_id_value,
     752            'desc'  => '',
     753        ) ),
     754        '<div id="', $this->_id( '_status' ) ,'" class="cmb_media_status">';
     755            if ( ! empty( $meta_value ) ) {
     756
     757                if ( $this->is_valid_img_ext( $meta_value ) ) {
    580758                    echo '<div class="img_status">';
    581                     echo '<img style="max-width: 350px; width: 100%; height: auto;" src="', $meta, '" alt="" />';
    582                     echo '<p><a href="#" class="cmb_remove_file_button" rel="', $field['id'], '">'. __( 'Remove Image', 'cmb' ) .'</a></p>';
     759                    echo '<img style="max-width: 350px; width: 100%; height: auto;" src="', $meta_value, '" alt="" />';
     760                    echo '<p class="cmb_remove_wrapper"><a href="#" class="cmb_remove_file_button" rel="', $cached_id, '">'. __( 'Remove Image', 'cmb' ) .'</a></p>';
    583761                    echo '</div>';
    584762                } else {
    585                     // $file_ext = self::get_file_ext( $meta );
    586                     $parts = explode( '/', $meta );
     763                    // $file_ext = $this->get_file_ext( $meta_value );
     764                    $parts = explode( '/', $meta_value );
    587765                    for ( $i = 0; $i < count( $parts ); ++$i ) {
    588766                        $title = $parts[$i];
    589767                    }
    590                     echo __( 'File:', 'cmb' ), ' <strong>', $title, '</strong>&nbsp;&nbsp;&nbsp; (<a href="', $meta, '" target="_blank" rel="external">'. __( 'Download', 'cmb' ) .'</a> / <a href="#" class="cmb_remove_file_button" rel="', $field['id'], '">'. __( 'Remove', 'cmb' ) .'</a>)';
     768                    echo __( 'File:', 'cmb' ), ' <strong>', $title, '</strong>&nbsp;&nbsp;&nbsp; (<a href="', $meta_value, '" target="_blank" rel="external">'. __( 'Download', 'cmb' ) .'</a> / <a href="#" class="cmb_remove_file_button" rel="', $cached_id, '">'. __( 'Remove', 'cmb' ) .'</a>)';
    591769                }
    592770            }
     
    594772    }
    595773
    596     public static function oembed( $field, $meta, $object_id, $object_type ) {
    597         echo '<input class="cmb_oembed regular-text" type="text" name="', $field['id'], '" id="', $field['id'], '" value="', self::esc( $meta ), '" data-objectid="', $object_id ,'" data-objecttype="', $object_type ,'" />', self::desc( true );
    598         echo '<p class="cmb-spinner spinner" style="display:none;"><img src="'. admin_url( '/images/wpspin_light.gif' ) .'" alt="spinner"/></p>';
    599         echo '<div id="', $field['id'], '_status" class="cmb_media_status ui-helper-clearfix embed_wrap">';
    600 
    601             if ( $meta != '' )
    602                 echo cmb_Meta_Box_ajax::get_oembed( $meta, $object_id, array(
    603                     'object_type' => $object_type,
     774    public function oembed() {
     775        echo $this->input( array(
     776            'class'           => 'cmb_oembed regular-text',
     777            'data-objectid'   => $this->field->object_id,
     778            'data-objecttype' => $this->field->object_type
     779        ) ),
     780        '<p class="cmb-spinner spinner" style="display:none;"><img src="'. admin_url( '/images/wpspin_light.gif' ) .'" alt="spinner"/></p>',
     781        '<div id="',$this->_id( '_status' ) ,'" class="cmb_media_status ui-helper-clearfix embed_wrap">';
     782
     783            if ( $meta_value = $this->field->escaped_value() ) {
     784                echo cmb_Meta_Box_ajax::get_oembed( $meta_value, $this->field->object_id, array(
     785                    'object_type' => $this->field->object_type,
    604786                    'oembed_args' => array( 'width' => '640' ),
    605                     'field_id'    => $field['id'],
     787                    'field_id'    => $this->_id(),
    606788                ) );
     789            }
    607790
    608791        echo '</div>';
    609792    }
    610793
    611     /**
    612      * Deprecated methods. use cmb_Meta_Box_types::repeat( true/false ) to toggle repeatable
    613      */
    614 
    615     public static function text_repeat( $field, $meta ) {
    616         self::repeat_text_field( $meta );
    617     }
    618     public static function text_small_repeat( $field, $meta ) {
    619         self::repeat_text_field( $meta, 'cmb_text_small' );
    620     }
    621     public static function text_medium_repeat( $field, $meta ) {
    622         self::repeat_text_field( $meta, 'cmb_text_medium' );
    623     }
    624     public static function text_email_repeat( $field, $meta ) {
    625         self::repeat_text_field( $meta, 'cmb_text_email cmb_text_medium', 'email' );
    626     }
    627     public static function text_url_repeat( $field, $meta ) {
    628         $val = self::esc( $meta );
    629         $protocols = isset( $field['protocols'] ) ? (array) $field['protocols'] : null;
    630         $val = $val ? esc_url( $val, $protocols ) : '';
    631         self::repeat_text_field( $val, 'cmb_text_url cmb_text_medium' );
    632     }
    633     public static function text_money_repeat( $field, $meta ) {
    634         self::repeat_text_field( $meta, 'cmb_text_money' );
    635     }
    636 
    637 
    638     /**
    639      * Default fallback. Allows rendering fields via "cmb_render_$name" hook
    640      * @since  1.0.0
    641      * @param  string $name      Non-existent method name
    642      * @param  array  $arguments All arguments passed to the method
    643      */
    644     public function __call( $name, $arguments ) {
    645         list( $field, $meta, $object_id, $object_type ) = $arguments;
    646         // When a non-registered field is called, send it through an action.
    647         do_action( "cmb_render_$name", $field, $meta, $object_id, $object_type );
    648     }
    649 
    650794}
  • infinite-slider/trunk/public/includes/cmb/init.php

    r884566 r969547  
    11<?php
    22/*
    3 Script Name:    Custom Metaboxes and Fields
    4 Contributors:   Andrew Norcross (@norcross / andrewnorcross.com)
    5                 Jared Atchison (@jaredatch / jaredatchison.com)
    6                 Bill Erickson (@billerickson / billerickson.net)
    7                 Justin Sternberg (@jtsternberg / dsgnwrks.pro)
    8 Description:    This will create metaboxes with custom fields that will blow your mind.
    9 Version:        1.0.2
     3Script Name:  Custom Metaboxes and Fields
     4Contributors: WebDevStudios (@webdevstudios / webdevstudios.com)
     5              Justin Sternberg (@jtsternberg / dsgnwrks.pro)
     6              Jared Atchison (@jaredatch / jaredatchison.com)
     7              Bill Erickson (@billerickson / billerickson.net)
     8              Andrew Norcross (@norcross / andrewnorcross.com)
     9Description:  This will create metaboxes with custom fields that will blow your mind.
     10Version:      1.2.0
    1011*/
    1112
     
    5556     * @since 1.0.0
    5657     */
    57     const CMB_VERSION = '1.0.2';
     58    const CMB_VERSION = '1.2.0';
    5859
    5960    /**
     
    7273        'id'         => '',
    7374        'title'      => '',
     75        'type'       => '',
    7476        'pages'      => array(), // Post type
    7577        'context'    => 'normal',
     
    117119
    118120    /**
     121     * Whether CMB nonce has been added to the page. (oly add once)
     122     * @var   bool
     123     * @since 1.2.0
     124     */
     125    protected static $nonce_added = false;
     126
     127    /**
    119128     * Type of object specified by the metabox Config
    120129     * @var   string
     
    130139    protected static $options = array();
    131140
     141    /**
     142     * List of fields that are changed/updated on save
     143     * @var   array
     144     * @since 1.1.0
     145     */
     146    protected static $updated = array();
    132147
    133148    /**
     
    228243
    229244        // scripts required for cmb
    230         $scripts = array( 'jquery', 'jquery-ui-core', 'jquery-ui-datepicker', /*'media-upload', */'cmb-timepicker' );
     245        $scripts = array( 'jquery', 'jquery-ui-core', 'cmb-datepicker', /*'media-upload', */'cmb-timepicker' );
    231246        // styles required for cmb
    232247        $styles = array();
     
    241256            wp_register_script( 'wp-color-picker', admin_url( 'js/color-picker.min.js' ), array( 'iris' ), self::CMB_VERSION );
    242257                wp_localize_script( 'wp-color-picker', 'wpColorPickerL10n', array(
    243                     'clear' => __( 'Clear' ),
     258                    'clear'         => __( 'Clear' ),
    244259                    'defaultString' => __( 'Default' ),
    245                     'pick' => __( 'Select Color' ),
    246                     'current' => __( 'Current Color' ),
     260                    'pick'          => __( 'Select Color' ),
     261                    'current'       => __( 'Current Color' ),
    247262                ) );
    248263            }
     
    252267            $styles[] = 'farbtastic';
    253268        }
     269        wp_register_script( 'cmb-datepicker', CMB_META_BOX_URL . 'js/jquery.datePicker.min.js' );
    254270        wp_register_script( 'cmb-timepicker', CMB_META_BOX_URL . 'js/jquery.timePicker.min.js' );
    255271        wp_register_script( 'cmb-scripts', CMB_META_BOX_URL .'js/cmb'. $min .'.js', $scripts, self::CMB_VERSION );
     
    257273        wp_enqueue_media();
    258274
    259         wp_localize_script( 'cmb-scripts', 'cmb_l10', array(
     275        wp_localize_script( 'cmb-scripts', 'cmb_l10', apply_filters( 'cmb_localized_data', array(
    260276            'ajax_nonce'      => wp_create_nonce( 'ajax_nonce' ),
    261277            'script_debug'    => defined('SCRIPT_DEBUG') && SCRIPT_DEBUG,
     
    268284            'download'        => 'Download',
    269285            'ajaxurl'         => admin_url( '/admin-ajax.php' ),
    270         ) );
     286            'up_arrow'        => '[ ↑ ]&nbsp;',
     287            'down_arrow'      => '&nbsp;[ ↓ ]',
     288            'check_toggle'    => __( 'Select / Deselect All', 'cmb' ),
     289        ) ) );
    271290
    272291        wp_register_style( 'cmb-styles', CMB_META_BOX_URL . 'style'. $min .'.css', $styles );
     
    286305
    287306            // default is to show cmb styles on post pages
    288             if ( $this->_meta_box['cmb_styles'] != false )
     307            if ( $this->_meta_box['cmb_styles'] )
    289308                wp_enqueue_style( 'cmb-styles' );
    290309        }
     
    365384        $object_id = self::set_object_id( $object_id ? $object_id : self::get_object_id() );
    366385
    367         // get box types
    368         $types = cmb_Meta_Box_types::get();
     386        // Add nonce only once per page.
     387        if ( ! self::$nonce_added ) {
     388            wp_nonce_field( self::nonce(), 'wp_meta_box_nonce', false, true );
     389            self::$nonce_added = true;
     390        }
    369391
    370392        // Use nonce for verification
    371393        echo "\n<!-- Begin CMB Fields -->\n";
    372         wp_nonce_field( self::nonce(), 'wp_meta_box_nonce', false, true );
    373394        do_action( 'cmb_before_table', $meta_box, $object_id, $object_type );
    374395        echo '<table class="form-table cmb_metabox">';
    375396
    376         foreach ( $meta_box['fields'] as $field ) {
    377 
    378             if ( isset( $field['on_front'] ) && $field['on_front'] == false )
    379                 continue;
    380 
    381             self::$field =& $field;
    382 
    383             // Set up blank or default values for empty ones
    384             if ( ! isset( $field['name'] ) ) $field['name'] = '';
    385             if ( ! isset( $field['desc'] ) ) $field['desc'] = '';
    386             if ( ! isset( $field['default'] ) ) {
    387                 // Phase out 'std', and use 'default' instead
    388                 $field['default'] = isset( $field['std'] ) ? $field['std'] : '';
     397        foreach ( $meta_box['fields'] as $field_args ) {
     398
     399            $field_args['context'] = $meta_box['context'];
     400
     401            if ( 'group' == $field_args['type'] ) {
     402
     403                if ( ! isset( $field_args['show_names'] ) ) {
     404                    $field_args['show_names'] = $meta_box['show_names'];
     405                }
     406                self::render_group( $field_args );
     407            } else {
     408
     409                $field_args['show_names'] = $meta_box['show_names'];
     410                // Render default fields
     411                $field = new cmb_Meta_Box_field( $field_args );
     412                $field->render_field();
    389413            }
    390             // Allow a filter override of the default value
    391             $field['default'] = apply_filters( 'cmb_default_filter', $field['default'], $field, $object_id, $object_type );
    392             // 'cmb_std_filter' deprectated, use 'cmb_default_filter' instead
    393             $field['default'] = apply_filters( 'cmb_std_filter', $field['default'], $field, $object_id, $object_type );
    394             $field['allow'] = 'file' == $field['type'] && ! isset( $field['allow'] ) ? array( 'url', 'attachment' ) : array();
    395             $field['save_id'] = 'file' == $field['type'] && ! isset( $field['save_id'] );
    396             $field['multiple'] = 'multicheck' == $field['type'];
    397 
    398             // Allow an override for the field's value
    399             // (assuming no one would want to save 'cmb_no_override_val' as a value)
    400             $meta = apply_filters( 'cmb_override_meta_value', 'cmb_no_override_val', $object_id, $field, $object_type );
    401 
    402             // If no override, get our meta
    403             if ( $meta === 'cmb_no_override_val' )
    404                 $meta = self::get_data();
    405 
    406             $classes = '';
    407             $field['repeatable'] = isset( $field['repeatable'] ) && $field['repeatable'];
    408             $classes .= $field['repeatable'] ? ' cmb-repeat' : '';
    409             // 'inline' flag, or _inline in the field type, set to true
    410             $inline = ( isset( $field['inline'] ) && $field['inline'] || false !== stripos( $field['type'], '_inline' ) );
    411             $classes .= $inline ? ' cmb-inline' : '';
    412 
    413             echo '<tr class="cmb-type-'. sanitize_html_class( $field['type'] ) .' cmb_id_'. sanitize_html_class( $field['id'] ) . $classes .'">';
    414 
    415             if ( $field['type'] == "title" ) {
    416                 echo '<td colspan="2">';
    417             } else {
    418                 if ( isset( $meta_box['show_names'] ) && $meta_box['show_names'] == true ) {
    419                     $style = $object_type == 'post' ? ' style="width:18%"' : '';
    420                     echo '<th'. $style .'><label for="', $field['id'], '">', $field['name'], '</label></th>';
    421                 } else {
    422                     echo '<label style="display:none;" for="', $field['id'], '">', $field['name'], '</label></th>';
    423                 }
    424                 echo '<td>';
    425             }
    426 
    427             echo empty( $field['before'] ) ? '' : $field['before'];
    428 
    429             call_user_func( array( $types, $field['type'] ), $field, $meta, $object_id, $object_type );
    430 
    431             echo empty( $field['after'] ) ? '' : $field['after'];
    432 
    433             echo '</td>','</tr>';
    434414        }
    435415        echo '</table>';
     
    440420
    441421    /**
     422     * Render a repeatable group
     423     */
     424    public static function render_group( $args ) {
     425        if ( ! isset( $args['id'], $args['fields'] ) || ! is_array( $args['fields'] ) )
     426            return;
     427
     428        $args['count']   = 0;
     429        $field_group     = new cmb_Meta_Box_field( $args );
     430        $desc            = $field_group->args( 'description' );
     431        $label           = $field_group->args( 'name' );
     432        $sortable        = $field_group->options( 'sortable' ) ? ' sortable' : '';
     433        $group_val       = (array) $field_group->value();
     434        $nrows           = count( $group_val );
     435        $remove_disabled = $nrows <= 1 ? 'disabled="disabled" ' : '';
     436
     437        echo '<tr><td colspan="2"><table id="', $field_group->id(), '_repeat" class="repeatable-group'. $sortable .'" style="width:100%;">';
     438        if ( $desc || $label ) {
     439            echo '<tr><th>';
     440                if ( $label )
     441                    echo '<h2 class="cmb-group-name">'. $label .'</h2>';
     442                if ( $desc )
     443                    echo '<p class="cmb_metabox_description">'. $desc .'</p>';
     444            echo '</th></tr>';
     445        }
     446
     447        if ( ! empty( $group_val ) ) {
     448
     449            foreach ( $group_val as $iterator => $field_id ) {
     450                self::render_group_row( $field_group, $remove_disabled );
     451            }
     452        } else {
     453            self::render_group_row( $field_group, $remove_disabled );
     454        }
     455
     456        echo '<tr><td><p class="add-row"><button data-selector="', $field_group->id() ,'_repeat" data-grouptitle="', $field_group->options( 'group_title' ) ,'" class="add-group-row button">'. $field_group->options( 'add_button' ) .'</button></p></td></tr>';
     457
     458        echo '</table></td></tr>';
     459
     460    }
     461
     462    public static function render_group_row( $field_group, $remove_disabled ) {
     463
     464        echo '
     465        <tr class="repeatable-grouping" data-iterator="'. $field_group->count() .'">
     466            <td>
     467                <table class="cmb-nested-table" style="width: 100%;">';
     468                if ( $field_group->options( 'group_title' ) ) {
     469                    echo '
     470                    <tr class="cmb-group-title">
     471                        <th colspan="2">
     472                            ', sprintf( '<h4>%1$s</h4>', $field_group->replace_hash( $field_group->options( 'group_title' ) ) ), '
     473                        <th>
     474                    </tr>
     475                    ';
     476                }
     477                // Render repeatable group fields
     478                foreach ( array_values( $field_group->args( 'fields' ) ) as $field_args ) {
     479                    $field_args['show_names'] = $field_group->args( 'show_names' );
     480                    $field_args['context'] = $field_group->args( 'context' );
     481                    $field = new cmb_Meta_Box_field( $field_args, $field_group );
     482                    $field->render_field();
     483                }
     484                echo '
     485                    <tr>
     486                        <td class="remove-row" colspan="2">
     487                            <button '. $remove_disabled .'data-selector="'. $field_group->id() .'_repeat" class="button remove-group-row alignright">'. $field_group->options( 'remove_button' ) .'</button>
     488                        </td>
     489                    </tr>
     490                </table>
     491            </td>
     492        </tr>
     493        ';
     494
     495        $field_group->args['count']++;
     496    }
     497
     498    /**
    442499     * Save data from metabox
    443500     */
    444     public function save_post( $post_id, $post = false )  {
     501    public function save_post( $post_id, $post = false ) {
    445502
    446503        $post_type = $post ? $post->post_type : get_post_type( $post_id );
     
    501558
    502559        // save field ids of those that are updated
    503         $updated = array();
    504 
    505         foreach ( $meta_box['fields'] as $field ) {
    506 
    507             self::$field =& $field;
    508             $name = $field['id'];
    509 
    510             if ( ! isset( $field['multiple'] ) )
    511                 $field['multiple'] = ( 'multicheck' == $field['type'] ) ? true : false;
    512 
    513             $old = self::get_data();
    514             $new = isset( $_POST[ $field['id'] ] ) ? $_POST[ $field['id'] ] : null;
    515 
    516 
    517             if ( $object_type == 'post' ) {
    518 
    519                 if (
    520                     isset( $field['taxonomy'] )
    521                     && in_array( $field['type'], array( 'taxonomy_select', 'taxonomy_radio', 'taxonomy_multicheck' ) )
    522                 )
    523                     $new = wp_set_object_terms( $object_id, $new, $field['taxonomy'] );
    524 
    525             }
    526 
    527             if ( isset( $field['repeatable'] ) && $field['repeatable'] && is_array( $new ) ) {
    528                 $new = array_filter( $new );
    529             }
    530 
    531             // Check if this metabox field has a registered validation callback, or perform default sanitization
    532             $new = self::sanitization_cb( $new );
    533 
    534             if ( $field['multiple'] ) {
    535 
    536                 self::remove_data( $name );
    537                 if ( ! empty( $new ) ) {
    538                     foreach ( $new as $add_new ) {
    539                         $updated[] = $name;
    540                         self::update_data( $add_new, $name, true );
    541                     }
    542                 }
    543             } elseif ( ! empty( $new ) && $new != $old  ) {
    544                 $updated[] = $name;
    545                 self::update_data( $new );
    546             } elseif ( empty( $new ) ) {
    547                 if ( ! empty( $old ) )
    548                     $updated[] = $name;
    549                 self::remove_data( $name );
     560        self::$updated = array();
     561
     562        foreach ( $meta_box['fields'] as $field_args ) {
     563
     564            if ( 'group' == $field_args['type'] ) {
     565                self::save_group( $field_args );
     566            } else {
     567                // Save default fields
     568                $field = new cmb_Meta_Box_field( $field_args );
     569                self::save_field( self::sanitize_field( $field ), $field );
    550570            }
    551571
     
    556576            self::save_option( $object_id );
    557577
    558         do_action( "cmb_save_{$object_type}_fields", $object_id, $meta_box['id'], $updated, $meta_box );
    559 
    560     }
    561 
    562     /**
    563      * Returns a timezone string representing the default timezone for the site.
    564      *
    565      * Roughly copied from WordPress, as get_option('timezone_string') will return
    566      * and empty string if no value has beens set on the options page.
    567      * A timezone string is required by the wp_timezone_choice() used by the
    568      * select_timezone field.
    569      *
    570      * @since  1.0.0
    571      * @return string Timezone string
    572      */
    573     public static function timezone_string() {
    574         $current_offset = get_option( 'gmt_offset' );
    575         $tzstring       = get_option( 'timezone_string' );
    576 
    577         if ( empty( $tzstring ) ) { // Create a UTC+- zone if no timezone string exists
    578             if ( 0 == $current_offset )
    579                 $tzstring = 'UTC+0';
    580             elseif ( $current_offset < 0 )
    581                 $tzstring = 'UTC' . $current_offset;
    582             else
    583                 $tzstring = 'UTC+' . $current_offset;
    584         }
    585 
    586         return $tzstring;
    587     }
    588 
    589     /**
    590      * Returns time string offset by timezone
    591      * @since  1.0.0
    592      * @param  string $tzstring Time string
    593      * @return string           Offset time string
    594      */
    595     public static function timezone_offset( $tzstring ) {
    596         if ( !empty( $tzstring ) ) {
    597 
    598             if ( substr( $tzstring, 0, 3 ) === 'UTC' ) {
    599                 $tzstring = str_replace( array( ':15',':30',':45' ), array( '.25','.5','.75' ), $tzstring );
    600                 return intval( floatval( substr( $tzstring, 3 ) ) * HOUR_IN_SECONDS );
     578        do_action( "cmb_save_{$object_type}_fields", $object_id, $meta_box['id'], self::$updated, $meta_box );
     579
     580    }
     581
     582    /**
     583     * Save a repeatable group
     584     */
     585    public static function save_group( $args ) {
     586        if ( ! isset( $args['id'], $args['fields'], $_POST[ $args['id'] ] ) || ! is_array( $args['fields'] ) )
     587            return;
     588
     589        $field_group        = new cmb_Meta_Box_field( $args );
     590        $base_id            = $field_group->id();
     591        $old                = $field_group->get_data();
     592        $group_vals         = $_POST[ $base_id ];
     593        $saved              = array();
     594        $is_updated         = false;
     595        $field_group->index = 0;
     596
     597        // $group_vals[0]['color'] = '333';
     598        foreach ( array_values( $field_group->fields() ) as $field_args ) {
     599            $field = new cmb_Meta_Box_field( $field_args, $field_group );
     600            $sub_id = $field->id( true );
     601
     602            foreach ( (array) $group_vals as $field_group->index => $post_vals ) {
     603
     604                // Get value
     605                $new_val = isset( $group_vals[ $field_group->index ][ $sub_id ] )
     606                    ? $group_vals[ $field_group->index ][ $sub_id ]
     607                    : false;
     608
     609                // Sanitize
     610                $new_val = self::sanitize_field( $field, $new_val, $field_group->index );
     611
     612                if ( 'file' == $field->type() && is_array( $new_val ) ) {
     613                    // Add image ID to the array stack
     614                    $saved[ $field_group->index ][ $new_val['field_id'] ] = $new_val['attach_id'];
     615                    // Reset var to url string
     616                    $new_val = $new_val['url'];
     617                }
     618
     619                // Get old value
     620                $old_val = is_array( $old ) && isset( $old[ $field_group->index ][ $sub_id ] )
     621                    ? $old[ $field_group->index ][ $sub_id ]
     622                    : false;
     623
     624                $is_updated = ( ! empty( $new_val ) && $new_val != $old_val );
     625                $is_removed = ( empty( $new_val ) && ! empty( $old_val ) );
     626                // Compare values and add to `$updated` array
     627                if ( $is_updated || $is_removed )
     628                    self::$updated[] = $base_id .'::'. $field_group->index .'::'. $sub_id;
     629
     630                // Add to `$saved` array
     631                $saved[ $field_group->index ][ $sub_id ] = $new_val;
     632
    601633            }
    602 
    603             $date_time_zone_selected = new DateTimeZone( $tzstring );
    604             $tz_offset = timezone_offset_get( $date_time_zone_selected, date_create() );
    605 
    606             return $tz_offset;
    607         }
    608 
    609         return 0;
    610     }
    611 
    612     /**
    613      * Offset a time value based on timezone
    614      * @since  1.0.0
    615      * @param  integer $object_id Object ID
    616      * @return string             Offset time string
    617      */
    618     public static function field_timezone_offset( $object_id = 0 ) {
    619 
    620         $tzstring = self::field_timezone( $object_id );
    621 
    622         return self::timezone_offset( $tzstring );
    623     }
    624 
    625     /**
    626      * Return timezone string
    627      * @since  1.0.0
    628      * @param  integer $object_id Object ID
    629      * @return string             Timezone string
    630      */
    631     public static function field_timezone( $object_id = 0 ) {
    632         $tzstring = null;
    633         if ( ! ( $object_id = self::get_object_id( $object_id ) ) )
    634             return $tzstring;
    635 
    636         if ( array_key_exists( 'timezone', self::$field ) && self::$field['timezone'] ) {
    637             $tzstring = self::$field['timezone'];
    638         } else if ( array_key_exists( 'timezone_meta_key', self::$field ) && self::$field['timezone_meta_key'] ) {
    639             $tzstring = self::get_data( self::$field['timezone_meta_key'] );
    640 
    641             return $tzstring;
    642         }
    643 
    644         return false;
     634            $saved[ $field_group->index ] = array_filter( $saved[ $field_group->index ] );
     635        }
     636        $saved = array_filter( $saved );
     637
     638        $field_group->update_data( $saved, true );
     639    }
     640
     641    public static function sanitize_field( $field, $new_value = null ) {
     642
     643        $new_value = null !== $new_value
     644            ? $new_value
     645            : ( isset( $_POST[ $field->id( true ) ] ) ? $_POST[ $field->id( true ) ] : null );
     646
     647        if ( $field->args( 'repeatable' ) && is_array( $new_value ) ) {
     648            // Remove empties
     649            $new_value = array_filter( $new_value );
     650        }
     651
     652        // Check if this metabox field has a registered validation callback, or perform default sanitization
     653        return $field->sanitization_cb( $new_value );
     654    }
     655
     656    public static function save_field( $new_value, $field ) {
     657        $name = $field->id();
     658        $old  = $field->get_data();
     659
     660        // if ( $field->args( 'multiple' ) && ! $field->args( 'repeatable' ) && ! $field->group ) {
     661        //  $field->remove_data();
     662        //  if ( ! empty( $new_value ) ) {
     663        //      foreach ( $new_value as $add_new ) {
     664        //          self::$updated[] = $name;
     665        //          $field->update_data( $add_new, $name, false );
     666        //      }
     667        //  }
     668        // } else
     669        if ( ! empty( $new_value ) && $new_value != $old  ) {
     670            self::$updated[] = $name;
     671            return $field->update_data( $new_value );
     672        } elseif ( empty( $new_value ) ) {
     673            if ( ! empty( $old ) )
     674                self::$updated[] = $name;
     675            return $field->remove_data();
     676        }
    645677    }
    646678
     
    797829
    798830    /**
    799      * Utility method that attempts to get an attachment's ID by it's url
    800      * @since  1.0.0
    801      * @param  string  $img_url Attachment url
    802      * @return mixed            Attachment ID or false
    803      */
    804     public static function image_id_from_url( $img_url ) {
    805         global $wpdb;
    806 
    807         // Get just the file name
    808         if ( false !== strpos( $img_url, '/' ) ) {
    809             $explode = explode( '/', $img_url );
    810             $img_url = end( $explode );
    811         }
    812 
    813         // And search for a fuzzy match of the file name
    814         $attachment = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE guid LIKE '%%%s%%' LIMIT 1;", $img_url ) );
    815 
    816         // If we found an attachement ID, return it
    817         if ( !empty( $attachment ) && is_array( $attachment ) )
    818             return $attachment[0];
    819 
    820         // No luck
    821         return false;
    822     }
    823 
    824     /**
    825      * Checks if field has a registered validation callback
    826      * @since  1.0.1
    827      * @param  mixed $meta_value Meta value
    828      * @param  array $field      Field config array
    829      * @return mixed             Possibly validated meta value
    830      */
    831     public static function sanitization_cb( $meta_value, $field = array() ) {
    832         if ( empty( $meta_value ) )
    833             return $meta_value;
    834 
    835         $field = $field !== array() ? $field : self::$field;
    836 
    837         // Check if the field has a registered validation callback
    838         $cb = self::maybe_callback( $field, 'sanitization_cb' );
    839         if ( false === $cb ) {
    840             // If requestion NO validation, return meta value
    841             return $meta_value;
    842         } elseif ( $cb ) {
    843             // Ok, callback is good, let's run it.
    844             return call_user_func( $cb, $meta_value, $field );
    845         }
    846 
    847         // Validation via 'cmb_Meta_Box_Sanitize' (with fallback filter)
    848         return call_user_func( array( cmb_Meta_Box_Sanitize::get(), $field['type'] ), $meta_value, $field );
    849     }
    850 
    851     /**
    852      * Checks if field has a callback value
    853      * @since  1.0.1
    854      * @param  array   $field Field config array
    855      * @param  string  $cb    Callback string
    856      * @return mixed          NULL, false for NO validation, or $cb string if it exists.
    857      */
    858     public static function maybe_callback( $field, $cb ) {
    859         if ( ! isset( $field[ $cb ] ) )
    860             return;
    861 
    862         // Check if metabox is requesting NO validation
    863         $cb = false !== $field[ $cb ] && 'false' !== $field[ $cb ] ? $field[ $cb ] : false;
    864 
    865         // If requestion NO validation, return false
    866         if ( ! $cb )
    867             return false;
    868 
    869         if (
    870             // Standard function
    871             ( is_string( $cb ) && function_exists( $cb ) )
    872             // Or Class method
    873             || ( is_array( $cb ) && is_callable( $cb ) )
    874         ) {
    875             return $cb;
    876         }
    877 
    878     }
    879 
    880     /**
    881831     * Defines the url which is used to load local resources.
    882832     * This may need to be filtered for local Window installations.
     
    915865
    916866    /**
    917      * Retrieves metadata/option data
    918      * @since  1.0.1
    919      * @param  string  $field_id Meta key/Option array key
    920      * @return mixed             Meta/Option value
    921      */
    922     public static function get_data( $field_id = '' ) {
    923 
    924         $type     = self::get_object_type();
    925         $id       = self::get_object_id();
    926         $field_id = $field_id ? $field_id : self::$field['id'];
    927 
    928         $data = 'options-page' === $type
    929             ? self::get_option( $id, $field_id )
    930             : get_metadata( $type, $id, $field_id, !self::$field['multiple'] /* If multicheck this can be multiple values */ );
    931 
    932         return $data;
    933     }
    934 
    935 
    936     /**
    937      * Updates metadata/option data
    938      * @since  1.0.1
    939      * @param  mixed   $value    Value to update data with
    940      * @param  string  $field_id Meta key/Option array key
    941      * @param  bool    $multiple Whether data is an array (add_metadata)
    942      */
    943     public static function update_data( $value, $field_id = '', $multiple = false ) {
    944 
    945         $type     = self::get_object_type();
    946         $id       = self::get_object_id();
    947         $field_id = $field_id ? $field_id : self::$field['id'];
    948 
    949         if ( 'options-page' === $type ) {
    950             self::update_option( $id, $field_id, $value );
    951         } else {
    952             if ( $multiple ) {
    953                 add_metadata( $type, $id, $field_id, $value, false );
    954             } else {
    955                 update_metadata( $type, $id, $field_id, $value );
    956             }
    957         }
    958     }
    959 
    960     /**
    961      * Removes/updates metadata/option data
    962      * @since  1.0.1
    963      * @param  string  $field_id Meta key/Option array key
    964      * @param  string  $old      Old value
    965      */
    966     public static function remove_data( $field_id = '', $old = '' ) {
    967 
    968         $type     = self::get_object_type();
    969         $id       = self::get_object_id();
    970         $field_id = $field_id ? $field_id : self::$field['id'];
    971 
    972         $data = 'options-page' === $type
    973             ? self::remove_option( $id, $field_id )
    974             : delete_metadata( $type, $id, $field_id, $old );
    975 
    976     }
    977 
    978     /**
    979867     * Removes an option from an option array
    980868     * @since  1.0.1
     
    1017905     * @param  string  $field_id   Option array field key
    1018906     * @param  mixed   $value      Value to update data with
    1019      * @param  array   $field      Optionally specify a field array
     907     * @param  bool    $single     Whether data should be an array
    1020908     * @return array               Modified options
    1021909     */
    1022     public static function update_option( $option_key, $field_id, $value, $field = array() ) {
    1023 
    1024         $field = $field !== array() ? $field : self::$field;
    1025 
    1026         if ( isset( $field['multiple'] ) && $field['multiple'] ) {
     910    public static function update_option( $option_key, $field_id, $value, $single = true ) {
     911
     912        if ( ! $single ) {
    1027913            // If multiple, add to array
    1028914            self::$options[ $option_key ][ $field_id ][] = $value;
     
    1076962        // If no override, update the option
    1077963        return update_option( $option_key, $to_save );
     964    }
     965
     966    /**
     967     * Utility method that returns a timezone string representing the default timezone for the site.
     968     *
     969     * Roughly copied from WordPress, as get_option('timezone_string') will return
     970     * and empty string if no value has beens set on the options page.
     971     * A timezone string is required by the wp_timezone_choice() used by the
     972     * select_timezone field.
     973     *
     974     * @since  1.0.0
     975     * @return string Timezone string
     976     */
     977    public static function timezone_string() {
     978        $current_offset = get_option( 'gmt_offset' );
     979        $tzstring       = get_option( 'timezone_string' );
     980
     981        if ( empty( $tzstring ) ) { // Create a UTC+- zone if no timezone string exists
     982            if ( 0 == $current_offset )
     983                $tzstring = 'UTC+0';
     984            elseif ( $current_offset < 0 )
     985                $tzstring = 'UTC' . $current_offset;
     986            else
     987                $tzstring = 'UTC+' . $current_offset;
     988        }
     989
     990        return $tzstring;
     991    }
     992
     993    /**
     994     * Utility method that returns time string offset by timezone
     995     * @since  1.0.0
     996     * @param  string $tzstring Time string
     997     * @return string           Offset time string
     998     */
     999    public static function timezone_offset( $tzstring ) {
     1000        if ( ! empty( $tzstring ) && is_string( $tzstring ) ) {
     1001            if ( substr( $tzstring, 0, 3 ) === 'UTC' ) {
     1002                $tzstring = str_replace( array( ':15',':30',':45' ), array( '.25','.5','.75' ), $tzstring );
     1003                return intval( floatval( substr( $tzstring, 3 ) ) * HOUR_IN_SECONDS );
     1004            }
     1005
     1006            $date_time_zone_selected = new DateTimeZone( $tzstring );
     1007            $tz_offset = timezone_offset_get( $date_time_zone_selected, date_create() );
     1008
     1009            return $tz_offset;
     1010        }
     1011
     1012        return 0;
     1013    }
     1014
     1015    /**
     1016     * Utility method that attempts to get an attachment's ID by it's url
     1017     * @since  1.0.0
     1018     * @param  string  $img_url Attachment url
     1019     * @return mixed            Attachment ID or false
     1020     */
     1021    public static function image_id_from_url( $img_url ) {
     1022        global $wpdb;
     1023
     1024        $img_url = esc_url_raw( $img_url );
     1025        // Get just the file name
     1026        if ( false !== strpos( $img_url, '/' ) ) {
     1027            $explode = explode( '/', $img_url );
     1028            $img_url = end( $explode );
     1029        }
     1030
     1031        // And search for a fuzzy match of the file name
     1032        $attachment = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE guid LIKE '%%%s%%' LIMIT 1;", $img_url ) );
     1033
     1034        // If we found an attachement ID, return it
     1035        if ( !empty( $attachment ) && is_array( $attachment ) )
     1036            return $attachment[0];
     1037
     1038        // No luck
     1039        return false;
    10781040    }
    10791041
     
    10961058
    10971059/**
     1060 * Get a CMB field object.
     1061 * @since  1.1.0
     1062 * @param  array  $field_args  Field arguments
     1063 * @param  int    $object_id   Object ID
     1064 * @param  string $object_type Type of object being saved. (e.g., post, user, or comment)
     1065 * @return object              cmb_Meta_Box_field object
     1066 */
     1067function cmb_get_field( $field_args, $object_id = 0, $object_type = 'post' ) {
     1068    // Default to the loop post ID
     1069    $object_id = $object_id ? $object_id : get_the_ID();
     1070    cmb_Meta_Box::set_object_id( $object_id );
     1071    cmb_Meta_Box::set_object_type( $object_type );
     1072    // Send back field object
     1073    return new cmb_Meta_Box_field( $field_args );
     1074}
     1075
     1076/**
     1077 * Get a field's value.
     1078 * @since  1.1.0
     1079 * @param  array  $field_args  Field arguments
     1080 * @param  int    $object_id   Object ID
     1081 * @param  string $object_type Type of object being saved. (e.g., post, user, comment, or options-page)
     1082 * @return mixed               Maybe escaped value
     1083 */
     1084function cmb_get_field_value( $field_args, $object_id = 0, $object_type = 'post' ) {
     1085    $field = cmb_get_field( $field_args, $object_id, $object_type );
     1086    return $field->escaped_value();
     1087}
     1088
     1089/**
    10981090 * Loop and output multiple metaboxes
    10991091 * @since 1.0.0
     
    11831175    $form_format = apply_filters( 'cmb_frontend_form_format', '<form class="cmb-form" method="post" id="%s" enctype="multipart/form-data" encoding="multipart/form-data"><input type="hidden" name="object_id" value="%s">%s<input type="submit" name="submit-cmb" value="%s" class="button-primary"></form>', $object_id, $meta_box, $form );
    11841176
    1185     $form = sprintf( $form_format, $meta_box['id'], $object_id, $form, __( 'Save', 'cmb' ) );
     1177    $form = sprintf( $form_format, $meta_box['id'], $object_id, $form, __( 'Save' ) );
    11861178
    11871179    if ( $echo )
  • infinite-slider/trunk/public/includes/cmb/js/cmb.js

    r884566 r969547  
    99 */
    1010
    11 /*jslint browser: true, devel: true, indent: 4, maxerr: 50, sub: true */
    12 /*global jQuery, tb_show, tb_remove */
    13 
    1411/**
    1512 * Custom jQuery for Custom Metaboxes and Fields
    1613 */
    17 (function(window, document, $, undefined){
     14window.CMB = (function(window, document, $, undefined){
    1815    'use strict';
    1916
    20     // Move CMB functionality to an object
    21     window.CMB = {
    22         formfield : '',
    23         iterator: 0,
    24         file_frames: {},
    25 
    26         init: function() {
    27             CMB.log( window.cmb_l10 );
    28 
    29             // hide our spinner gif if we're on a MP6 dashboard
    30             if ( window.cmb_l10.new_admin_style ) {
    31                 $('.cmb-spinner img').hide();
    32             }
    33 
    34             /**
    35              * Initialize timepicker (this will be moved inline in a future release)
    36              */
    37             $('.cmb_timepicker').each( function() {
    38                 $('#' + jQuery(this).attr('id')).timePicker({
    39                     startTime: "07:00",
    40                     endTime: "22:00",
    41                     show24Hours: false,
    42                     separator: ':',
    43                     step: 30
     17    // localization strings
     18    var l10n = window.cmb_l10;
     19    var setTimeout = window.setTimeout;
     20
     21    // CMB functionality object
     22    var cmb = {
     23        formfield   : '',
     24        idNumber    : false,
     25        file_frames : {},
     26        repeatEls   : 'input:not([type="button"]),select,textarea,.cmb_media_status'
     27    };
     28
     29    cmb.metabox = function() {
     30        if ( cmb.$metabox ) {
     31            return cmb.$metabox;
     32        }
     33        cmb.$metabox = $('table.cmb_metabox');
     34        return cmb.$metabox;
     35    };
     36
     37    cmb.init = function() {
     38
     39        var $metabox = cmb.metabox();
     40        var $repeatGroup = $metabox.find('.repeatable-group');
     41
     42        // hide our spinner gif if we're on a MP6 dashboard
     43        if ( l10n.new_admin_style ) {
     44            $metabox.find('.cmb-spinner img').hide();
     45        }
     46
     47        /**
     48         * Initialize time/date/color pickers
     49         */
     50        cmb.initPickers( $metabox.find('input:text.cmb_timepicker'), $metabox.find('input:text.cmb_datepicker'), $metabox.find('input:text.cmb_colorpicker') );
     51
     52        // Wrap date picker in class to narrow the scope of jQuery UI CSS and prevent conflicts
     53        $("#ui-datepicker-div").wrap('<div class="cmb_element" />');
     54
     55        // Insert toggle button into DOM wherever there is multicheck. credit: Genesis Framework
     56        $( '<p><span class="button cmb-multicheck-toggle">' + l10n.check_toggle + '</span></p>' ).insertBefore( 'ul.cmb_checkbox_list' );
     57
     58        $metabox
     59            .on( 'change', '.cmb_upload_file', function() {
     60                cmb.formfield = $(this).attr('id');
     61                $('#' + cmb.formfield + '_id').val('');
     62            })
     63            // Media/file management
     64            .on( 'click', '.cmb-multicheck-toggle', cmb.toggleCheckBoxes )
     65            .on( 'click', '.cmb_upload_button', cmb.handleMedia )
     66            .on( 'click', '.cmb_remove_file_button', cmb.handleRemoveMedia )
     67            // Repeatable content
     68            .on( 'click', '.add-group-row', cmb.addGroupRow )
     69            .on( 'click', '.add-row-button', cmb.addAjaxRow )
     70            .on( 'click', '.remove-group-row', cmb.removeGroupRow )
     71            .on( 'click', '.remove-row-button', cmb.removeAjaxRow )
     72            // Ajax oEmbed display
     73            .on( 'keyup paste focusout', '.cmb_oembed', cmb.maybeOembed )
     74            // Reset titles when removing a row
     75            .on( 'cmb_remove_row', '.repeatable-group', cmb.resetTitlesAndIterator );
     76
     77        if ( $repeatGroup.length ) {
     78            $repeatGroup
     79                .filter('.sortable').each( function() {
     80                    // Add sorting arrows
     81                    $(this).find( '.remove-group-row' ).before( '<a class="shift-rows move-up alignleft" href="#">'+ l10n.up_arrow +'</a> <a class="shift-rows move-down alignleft" href="#">'+ l10n.down_arrow +'</a>' );
     82                })
     83                .on( 'click', '.shift-rows', cmb.shiftRows )
     84                .on( 'cmb_add_row', cmb.emptyValue );
     85        }
     86
     87        // on pageload
     88        setTimeout( cmb.resizeoEmbeds, 500);
     89        // and on window resize
     90        $(window).on( 'resize', cmb.resizeoEmbeds );
     91
     92    };
     93
     94    cmb.resetTitlesAndIterator = function() {
     95        // Loop repeatable group tables
     96        $( '.repeatable-group' ).each( function() {
     97            var $table = $(this);
     98            // Loop repeatable group table rows
     99            $table.find( '.repeatable-grouping' ).each( function( rowindex ) {
     100                var $row = $(this);
     101                // Reset rows iterator
     102                $row.data( 'iterator', rowindex );
     103                // Reset rows title
     104                $row.find( '.cmb-group-title h4' ).text( $table.find( '.add-group-row' ).data( 'grouptitle' ).replace( '{#}', ( rowindex + 1 ) ) );
     105            });
     106        });
     107    };
     108
     109    cmb.toggleCheckBoxes = function( event ) {
     110        event.preventDefault();
     111        var $self = $(this);
     112        var $multicheck = $self.parents( 'td' ).find( 'input[type=checkbox]' );
     113
     114        // If the button has already been clicked once...
     115        if ( $self.data( 'checked' ) ) {
     116            // clear the checkboxes and remove the flag
     117            $multicheck.prop( 'checked', false );
     118            $self.data( 'checked', false );
     119        }
     120        // Otherwise mark the checkboxes and add a flag
     121        else {
     122            $multicheck.prop( 'checked', true );
     123            $self.data( 'checked', true );
     124        }
     125    };
     126
     127    cmb.handleMedia = function(event) {
     128
     129        if ( ! wp ) {
     130            return;
     131        }
     132
     133        event.preventDefault();
     134
     135        var $metabox     = cmb.metabox();
     136        var $self        = $(this);
     137        cmb.formfield    = $self.prev('input').attr('id');
     138        var $formfield   = $('#'+cmb.formfield);
     139        var formName     = $formfield.attr('name');
     140        var uploadStatus = true;
     141        var attachment   = true;
     142        var isList       = $self.hasClass( 'cmb_upload_list' );
     143
     144        // If this field's media frame already exists, reopen it.
     145        if ( cmb.formfield in cmb.file_frames ) {
     146            cmb.file_frames[cmb.formfield].open();
     147            return;
     148        }
     149
     150        // Create the media frame.
     151        cmb.file_frames[cmb.formfield] = wp.media.frames.file_frame = wp.media({
     152            title: $metabox.find('label[for=' + cmb.formfield + ']').text(),
     153            button: {
     154                text: l10n.upload_file
     155            },
     156            multiple: isList ? true : false
     157        });
     158
     159        var handlers = {
     160            list : function( selection ) {
     161                // Get all of our selected files
     162                attachment = selection.toJSON();
     163
     164                $formfield.val(attachment.url);
     165                $('#'+ cmb.formfield +'_id').val(attachment.id);
     166
     167                // Setup our fileGroup array
     168                var fileGroup = [];
     169
     170                // Loop through each attachment
     171                $( attachment ).each( function() {
     172                    if ( this.type && this.type === 'image' ) {
     173                        // image preview
     174                        uploadStatus = '<li class="img_status">'+
     175                            '<img width="50" height="50" src="' + this.url + '" class="attachment-50x50" alt="'+ this.filename +'">'+
     176                            '<p><a href="#" class="cmb_remove_file_button" rel="'+ cmb.formfield +'['+ this.id +']">'+ l10n.remove_image +'</a></p>'+
     177                            '<input type="hidden" id="filelist-'+ this.id +'" name="'+ formName +'['+ this.id +']" value="' + this.url + '">'+
     178                        '</li>';
     179
     180                    } else {
     181                        // Standard generic output if it's not an image.
     182                        uploadStatus = '<li>'+ l10n.file +' <strong>'+ this.filename +'</strong>&nbsp;&nbsp;&nbsp; (<a href="' + this.url + '" target="_blank" rel="external">'+ l10n.download +'</a> / <a href="#" class="cmb_remove_file_button" rel="'+ cmb.formfield +'['+ this.id +']">'+ l10n.remove_file +'</a>)'+
     183                            '<input type="hidden" id="filelist-'+ this.id +'" name="'+ formName +'['+ this.id +']" value="' + this.url + '">'+
     184                        '</li>';
     185
     186                    }
     187
     188                    // Add our file to our fileGroup array
     189                    fileGroup.push( uploadStatus );
    44190                });
     191
     192                // Append each item from our fileGroup array to .cmb_media_status
     193                $( fileGroup ).each( function() {
     194                    $formfield.siblings('.cmb_media_status').slideDown().append(this);
     195                });
     196            },
     197            single : function( selection ) {
     198                // Only get one file from the uploader
     199                attachment = selection.first().toJSON();
     200
     201                $formfield.val(attachment.url);
     202                $('#'+ cmb.formfield +'_id').val(attachment.id);
     203
     204                if ( attachment.type && attachment.type === 'image' ) {
     205                    // image preview
     206                    uploadStatus = '<div class="img_status"><img style="max-width: 350px; width: 100%; height: auto;" src="' + attachment.url + '" alt="'+ attachment.filename +'" title="'+ attachment.filename +'" /><p><a href="#" class="cmb_remove_file_button" rel="' + cmb.formfield + '">'+ l10n.remove_image +'</a></p></div>';
     207                } else {
     208                    // Standard generic output if it's not an image.
     209                    uploadStatus = l10n.file +' <strong>'+ attachment.filename +'</strong>&nbsp;&nbsp;&nbsp; (<a href="'+ attachment.url +'" target="_blank" rel="external">'+ l10n.download +'</a> / <a href="#" class="cmb_remove_file_button" rel="'+ cmb.formfield +'">'+ l10n.remove_file +'</a>)';
     210                }
     211
     212                // add/display our output
     213                $formfield.siblings('.cmb_media_status').slideDown().html(uploadStatus);
     214            }
     215        };
     216
     217        // When an file is selected, run a callback.
     218        cmb.file_frames[cmb.formfield].on( 'select', function() {
     219            var selection = cmb.file_frames[cmb.formfield].state().get('selection');
     220            var type = isList ? 'list' : 'single';
     221            handlers[type]( selection );
     222        });
     223
     224        // Finally, open the modal
     225        cmb.file_frames[cmb.formfield].open();
     226    };
     227
     228    cmb.handleRemoveMedia = function( event ) {
     229        event.preventDefault();
     230        var $self = $(this);
     231        if ( $self.is( '.attach_list .cmb_remove_file_button' ) ){
     232            $self.parents('li').remove();
     233            return false;
     234        }
     235        cmb.formfield    = $self.attr('rel');
     236        var $container   = $self.parents('.img_status');
     237
     238        cmb.metabox().find('input#' + cmb.formfield).val('');
     239        cmb.metabox().find('input#' + cmb.formfield + '_id').val('');
     240        if ( ! $container.length ) {
     241            $self.parents('.cmb_media_status').html('');
     242        } else {
     243            $container.html('');
     244        }
     245        return false;
     246    };
     247
     248    // src: http://www.benalman.com/projects/jquery-replacetext-plugin/
     249    $.fn.replaceText = function(b, a, c) {
     250        return this.each(function() {
     251            var f = this.firstChild, g, e, d = [];
     252            if (f) {
     253                do {
     254                    if (f.nodeType === 3) {
     255                        g = f.nodeValue;
     256                        e = g.replace(b, a);
     257                        if (e !== g) {
     258                            if (!c && /</.test(e)) {
     259                                $(f).before(e);
     260                                d.push(f);
     261                            } else {
     262                                f.nodeValue = e;
     263                            }
     264                        }
     265                    }
     266                } while (f = f.nextSibling);
     267            }
     268            if ( d.length ) { $(d).remove(); }
     269        });
     270    };
     271
     272    $.fn.cleanRow = function( prevNum, group ) {
     273        var $self = $(this);
     274        var $inputs = $self.find('input:not([type="button"]), select, textarea, label');
     275        if ( group ) {
     276            // Remove extra ajaxed rows
     277            $self.find('.cmb-repeat-table .repeat-row:not(:first-child)').remove();
     278        }
     279        cmb.$focus = false;
     280        cmb.neweditor_id = [];
     281
     282        $inputs.filter(':checked').removeAttr( 'checked' );
     283        $inputs.filter(':selected').removeAttr( 'selected' );
     284
     285        if ( $self.find('.cmb-group-title') ) {
     286            $self.find( '.cmb-group-title h4' ).text( $self.data( 'title' ).replace( '{#}', ( cmb.idNumber + 1 ) ) );
     287        }
     288
     289        $inputs.each( function(){
     290            var $newInput = $(this);
     291            var isEditor  = $newInput.hasClass( 'wp-editor-area' );
     292            var oldFor    = $newInput.attr( 'for' );
     293            // var $next     = $newInput.next();
     294            var attrs     = {};
     295            var newID, oldID;
     296            if ( oldFor ) {
     297                attrs = { 'for' : oldFor.replace( '_'+ prevNum, '_'+ cmb.idNumber ) };
     298            } else {
     299                var oldName = $newInput.attr( 'name' );
     300                // Replace 'name' attribute key
     301                var newName = oldName ? oldName.replace( '['+ prevNum +']', '['+ cmb.idNumber +']' ) : '';
     302                oldID       = $newInput.attr( 'id' );
     303                newID       = oldID ? oldID.replace( '_'+ prevNum, '_'+ cmb.idNumber ) : '';
     304                attrs       = {
     305                    id: newID,
     306                    name: newName,
     307                    // value: '',
     308                    'data-iterator': cmb.idNumber,
     309                };
     310            }
     311
     312            $newInput
     313                .removeClass( 'hasDatepicker' )
     314                .attr( attrs ).val('');
     315
     316            // wysiwyg field
     317            if ( isEditor ) {
     318                // Get new wysiwyg ID
     319                newID = newID ? oldID.replace( 'zx'+ prevNum, 'zx'+ cmb.idNumber ) : '';
     320                // Empty the contents
     321                $newInput.html('');
     322                // Get wysiwyg field
     323                var $wysiwyg = $newInput.parents( '.cmb-type-wysiwyg' );
     324                // Remove extra mce divs
     325                $wysiwyg.find('.mce-tinymce:not(:first-child)').remove();
     326                // Replace id instances
     327                var html = $wysiwyg.html().replace( new RegExp( oldID, 'g' ), newID );
     328                // Update field html
     329                $wysiwyg.html( html );
     330                // Save ids for later to re-init tinymce
     331                cmb.neweditor_id.push( { 'id': newID, 'old': oldID } );
     332            }
     333
     334            cmb.$focus = cmb.$focus ? cmb.$focus : $newInput;
     335        });
     336
     337        return this;
     338    };
     339
     340    $.fn.newRowHousekeeping = function() {
     341        var $row         = $(this);
     342        var $colorPicker = $row.find( '.wp-picker-container' );
     343        var $list        = $row.find( '.cmb_media_status' );
     344
     345        if ( $colorPicker.length ) {
     346            // Need to clean-up colorpicker before appending
     347            $colorPicker.each( function() {
     348                var $td = $(this).parent();
     349                $td.html( $td.find( 'input:text.cmb_colorpicker' ).attr('style', '') );
    45350            });
    46 
    47             /**
    48              * Initialize jQuery UI datepicker (this will be moved inline in a future release)
    49              */
    50             $('.cmb_datepicker').each( function() {
    51                 $('#' + jQuery(this).attr('id')).datepicker();
    52                 // $('#' + jQuery(this).attr('id')).datepicker({ dateFormat: 'yy-mm-dd' });
    53                 // For more options see http://jqueryui.com/demos/datepicker/#option-dateFormat
     351        }
     352
     353        // Need to clean-up colorpicker before appending
     354        if ( $list.length ) {
     355            $list.empty();
     356        }
     357
     358        return this;
     359    };
     360
     361    cmb.afterRowInsert = function( $row ) {
     362        if ( cmb.$focus ) {
     363            cmb.$focus.focus();
     364        }
     365
     366        var _prop;
     367
     368        // Need to re-init wp_editor instances
     369        if ( cmb.neweditor_id.length ) {
     370            var i;
     371            for ( i = cmb.neweditor_id.length - 1; i >= 0; i-- ) {
     372                var id = cmb.neweditor_id[i].id;
     373                var old = cmb.neweditor_id[i].old;
     374
     375                if ( typeof( tinyMCEPreInit.mceInit[ id ] ) === 'undefined' ) {
     376                    var newSettings = jQuery.extend( {}, tinyMCEPreInit.mceInit[ old ] );
     377
     378                    for ( _prop in newSettings ) {
     379                        if ( 'string' === typeof( newSettings[_prop] ) ) {
     380                            newSettings[_prop] = newSettings[_prop].replace( new RegExp( old, 'g' ), id );
     381                        }
     382                    }
     383                    tinyMCEPreInit.mceInit[ id ] = newSettings;
     384                }
     385                if ( typeof( tinyMCEPreInit.qtInit[ id ] ) === 'undefined' ) {
     386                    var newQTS = jQuery.extend( {}, tinyMCEPreInit.qtInit[ old ] );
     387                    for ( _prop in newQTS ) {
     388                        if ( 'string' === typeof( newQTS[_prop] ) ) {
     389                            newQTS[_prop] = newQTS[_prop].replace( new RegExp( old, 'g' ), id );
     390                        }
     391                    }
     392                    tinyMCEPreInit.qtInit[ id ] = newQTS;
     393                }
     394                tinyMCE.init({
     395                    id : tinyMCEPreInit.mceInit[ id ],
     396                });
     397
     398            }
     399        }
     400
     401        // Init pickers from new row
     402        cmb.initPickers( $row.find('input:text.cmb_timepicker'), $row.find('input:text.cmb_datepicker'), $row.find('input:text.cmb_colorpicker') );
     403    };
     404
     405    cmb.updateNameAttr = function () {
     406
     407        var $this = $(this);
     408        var name  = $this.attr( 'name' ); // get current name
     409
     410        // No name? bail
     411        if ( typeof name === 'undefined' ) {
     412            return false;
     413        }
     414
     415        var prevNum = parseInt( $this.parents( '.repeatable-grouping' ).data( 'iterator' ) );
     416        var newNum  = prevNum - 1; // Subtract 1 to get new iterator number
     417
     418        // Update field name attributes so data is not orphaned when a row is removed and post is saved
     419        var $newName = name.replace( '[' + prevNum + ']', '[' + newNum + ']' );
     420
     421        // New name with replaced iterator
     422        $this.attr( 'name', $newName );
     423
     424    };
     425
     426    cmb.emptyValue = function( event, row ) {
     427        $('input:not([type="button"]), textarea', row).val('');
     428    };
     429
     430    cmb.addGroupRow = function( event ) {
     431
     432        event.preventDefault();
     433
     434        var $self    = $(this);
     435        var $table   = $('#'+ $self.data('selector'));
     436        var $oldRow  = $table.find('.repeatable-grouping').last();
     437        var prevNum  = parseInt( $oldRow.data('iterator') );
     438        cmb.idNumber = prevNum + 1;
     439        var $row     = $oldRow.clone();
     440
     441        $row.data( 'title', $self.data( 'grouptitle' ) ).newRowHousekeeping().cleanRow( prevNum, true );
     442
     443        // console.log( '$row.html()', $row.html() );
     444        var $newRow = $( '<tr class="repeatable-grouping" data-iterator="'+ cmb.idNumber +'">'+ $row.html() +'</tr>' );
     445        $oldRow.after( $newRow );
     446        // console.log( '$newRow.html()', $row.html() );
     447
     448        cmb.afterRowInsert( $newRow );
     449
     450        if ( $table.find('.repeatable-grouping').length <= 1 ) {
     451            $table.find('.remove-group-row').prop('disabled', true);
     452        } else {
     453            $table.find('.remove-group-row').removeAttr( 'disabled' );
     454        }
     455
     456        $table.trigger( 'cmb_add_row', $newRow );
     457    };
     458
     459    cmb.addAjaxRow = function( event ) {
     460
     461        event.preventDefault();
     462
     463        var $self         = $(this);
     464        var tableselector = '#'+ $self.data('selector');
     465        var $table        = $(tableselector);
     466        var $emptyrow     = $table.find('.empty-row');
     467        var prevNum       = parseInt( $emptyrow.find('[data-iterator]').data('iterator') );
     468        cmb.idNumber      = prevNum + 1;
     469        var $row          = $emptyrow.clone();
     470
     471        $row.newRowHousekeeping().cleanRow( prevNum );
     472
     473        $emptyrow.removeClass('empty-row').addClass('repeat-row');
     474        $emptyrow.after( $row );
     475
     476        cmb.afterRowInsert( $row );
     477        $table.trigger( 'cmb_add_row', $row );
     478    };
     479
     480    cmb.removeGroupRow = function( event ) {
     481        event.preventDefault();
     482        var $self   = $(this);
     483        var $table  = $('#'+ $self.data('selector'));
     484        var $parent = $self.parents('.repeatable-grouping');
     485        var noRows  = $table.find('.repeatable-grouping').length;
     486
     487        // when a group is removed loop through all next groups and update fields names
     488        $parent.nextAll( '.repeatable-grouping' ).find( cmb.repeatEls ).each( cmb.updateNameAttr );
     489
     490        if ( noRows > 1 ) {
     491            $parent.remove();
     492            if ( noRows < 3 ) {
     493                $table.find('.remove-group-row').prop('disabled', true);
     494            } else {
     495                $table.find('.remove-group-row').prop('disabled', false);
     496            }
     497            $table.trigger( 'cmb_remove_row' );
     498        }
     499    };
     500
     501    cmb.removeAjaxRow = function( event ) {
     502        event.preventDefault();
     503        var $self   = $(this);
     504        var $parent = $self.parents('tr');
     505        var $table  = $self.parents('.cmb-repeat-table');
     506
     507        // cmb.log( 'number of tbodys', $table.length );
     508        // cmb.log( 'number of trs', $('tr', $table).length );
     509        if ( $table.find('tr').length > 1 ) {
     510            if ( $parent.hasClass('empty-row') ) {
     511                $parent.prev().addClass( 'empty-row' ).removeClass('repeat-row');
     512            }
     513            $self.parents('.cmb-repeat-table tr').remove();
     514            $table.trigger( 'cmb_remove_row' );
     515        }
     516    };
     517
     518    cmb.shiftRows = function( event ) {
     519
     520        event.preventDefault();
     521
     522        var $self     = $(this);
     523        var $parent   = $self.parents( '.repeatable-grouping' );
     524        var $goto     = $self.hasClass( 'move-up' ) ? $parent.prev( '.repeatable-grouping' ) : $parent.next( '.repeatable-grouping' );
     525
     526        if ( ! $goto.length ) {
     527            return;
     528        }
     529
     530        var inputVals = [];
     531        // Loop this items fields
     532        $parent.find( cmb.repeatEls ).each( function() {
     533            var $element = $(this);
     534            var val;
     535            if ( $element.hasClass('cmb_media_status') ) {
     536                // special case for image previews
     537                val = $element.html();
     538            } else if ( 'checkbox' === $element.attr('type') ) {
     539                val = $element.is(':checked');
     540                cmb.log( 'checked', val );
     541            } else if ( 'select' === $element.prop('tagName') ) {
     542                val = $element.is(':selected');
     543                cmb.log( 'checked', val );
     544            } else {
     545                val = $element.val();
     546            }
     547            // Get all the current values per element
     548            inputVals.push( { val: val, $: $element } );
     549        });
     550        // And swap them all
     551        $goto.find( cmb.repeatEls ).each( function( index ) {
     552            var $element = $(this);
     553            var val;
     554
     555            if ( $element.hasClass('cmb_media_status') ) {
     556                // special case for image previews
     557                val = $element.html();
     558                $element.html( inputVals[ index ]['val'] );
     559                inputVals[ index ]['$'].html( val );
     560
     561            }
     562            // handle checkbox swapping
     563            else if ( 'checkbox' === $element.attr('type') ) {
     564                inputVals[ index ]['$'].prop( 'checked', $element.is(':checked') );
     565                $element.prop( 'checked', inputVals[ index ]['val'] );
     566            }
     567            // handle select swapping
     568            else if ( 'select' === $element.prop('tagName') ) {
     569                inputVals[ index ]['$'].prop( 'selected', $element.is(':selected') );
     570                $element.prop( 'selected', inputVals[ index ]['val'] );
     571            }
     572            // handle normal input swapping
     573            else {
     574                inputVals[ index ]['$'].val( $element.val() );
     575                $element.val( inputVals[ index ]['val'] );
     576            }
     577        });
     578    };
     579
     580    /**
     581     * @todo make work, always
     582     */
     583    cmb.initPickers = function( $timePickers, $datePickers, $colorPickers ) {
     584        // Initialize timepicker
     585        cmb.initTimePickers( $timePickers );
     586
     587        // Initialize jQuery UI datepicker
     588        cmb.initDatePickers( $datePickers );
     589
     590        // Initialize color picker
     591        cmb.initColorPickers( $colorPickers );
     592    };
     593
     594    cmb.initTimePickers = function( $selector ) {
     595        if ( ! $selector.length ) {
     596            return;
     597        }
     598
     599        $selector.timePicker({
     600            startTime: "00:00",
     601            endTime: "23:59",
     602            show24Hours: false,
     603            separator: ':',
     604            step: 30
     605        });
     606    };
     607
     608    cmb.initDatePickers = function( $selector ) {
     609        if ( ! $selector.length ) {
     610            return;
     611        }
     612
     613        $selector.datepicker( "destroy" );
     614        $selector.datepicker();
     615    };
     616
     617    cmb.initColorPickers = function( $selector ) {
     618        if ( ! $selector.length ) {
     619            return;
     620        }
     621        if (typeof jQuery.wp === 'object' && typeof jQuery.wp.wpColorPicker === 'function') {
     622
     623            $selector.wpColorPicker();
     624
     625        } else {
     626            $selector.each( function(i) {
     627                $(this).after('<div id="picker-' + i + '" style="z-index: 1000; background: #EEE; border: 1px solid #CCC; position: absolute; display: block;"></div>');
     628                $('#picker-' + i).hide().farbtastic($(this));
     629            })
     630            .focus( function() {
     631                $(this).next().show();
     632            })
     633            .blur( function() {
     634                $(this).next().hide();
    54635            });
    55             // Wrap date picker in class to narrow the scope of jQuery UI CSS and prevent conflicts
    56             $("#ui-datepicker-div").wrap('<div class="cmb_element" />');
    57 
    58             /**
    59              * Initialize color picker
    60              */
    61             if (typeof jQuery.wp === 'object' && typeof jQuery.wp.wpColorPicker === 'function') {
    62                 $('input:text.cmb_colorpicker').wpColorPicker();
    63             } else {
    64                 $('input:text.cmb_colorpicker').each( function(i) {
    65                     $(this).after('<div id="picker-' + i + '" style="z-index: 1000; background: #EEE; border: 1px solid #CCC; position: absolute; display: block;"></div>');
    66                     $('#picker-' + i).hide().farbtastic($(this));
    67                 })
    68                 .focus( function() {
    69                     $(this).next().show();
    70                 })
    71                 .blur( function() {
    72                     $(this).next().hide();
    73                 });
    74             }
    75 
    76 
    77             /**
    78              * File and image upload handling
    79              */
    80 
    81 
    82             $('.cmb_metabox')
    83             .on( 'change', '.cmb_upload_file', function() {
    84                 CMB.formfield = $(this).attr('name');
    85                 $('#' + CMB.formfield + '_id').val("");
    86             })
    87             .on( 'click', '.cmb_upload_button', function(event) {
    88 
    89                 event.preventDefault();
    90 
    91                 var $self = $(this);
    92                 CMB.formfield = $self.prev('input').attr('name');
    93                 var $formfield = $('#'+CMB.formfield);
    94                 var uploadStatus = true;
    95                 var attachment = true;
    96                 var isList = $self.hasClass( 'cmb_upload_list' );
    97 
    98 
    99                 // If this field's media frame already exists, reopen it.
    100                 if ( CMB.formfield in CMB.file_frames ) {
    101                     CMB.file_frames[CMB.formfield].open();
     636        }
     637    };
     638
     639    cmb.maybeOembed = function( evt ) {
     640        var $self = $(this);
     641        var type = evt.type;
     642
     643        var m = {
     644            focusout : function() {
     645                setTimeout( function() {
     646                    // if it's been 2 seconds, hide our spinner
     647                    cmb.spinner( '.postbox table.cmb_metabox', true );
     648                }, 2000);
     649            },
     650            keyup : function() {
     651                var betw = function( min, max ) {
     652                    return ( evt.which <= max && evt.which >= min );
     653                };
     654                // Only Ajax on normal keystrokes
     655                if ( betw( 48, 90 ) || betw( 96, 111 ) || betw( 8, 9 ) || evt.which === 187 || evt.which === 190 ) {
     656                    // fire our ajax function
     657                    cmb.doAjax( $self, evt);
     658                }
     659            },
     660            paste : function() {
     661                // paste event is fired before the value is filled, so wait a bit
     662                setTimeout( function() { cmb.doAjax( $self ); }, 100);
     663            }
     664        };
     665        m[type]();
     666
     667    };
     668
     669    /**
     670     * Resize oEmbed videos to fit in their respective metaboxes
     671     */
     672    cmb.resizeoEmbeds = function() {
     673        cmb.metabox().each( function() {
     674            var $self      = $(this);
     675            var $tableWrap = $self.parents('.inside');
     676            if ( ! $tableWrap.length )  {
     677                return true; // continue
     678            }
     679
     680            // Calculate new width
     681            var newWidth = Math.round(($tableWrap.width() * 0.82)*0.97) - 30;
     682            if ( newWidth > 639 ) {
     683                return true; // continue
     684            }
     685
     686            var $embeds   = $self.find('.cmb-type-oembed .embed_status');
     687            var $children = $embeds.children().not('.cmb_remove_wrapper');
     688            if ( ! $children.length ) {
     689                return true; // continue
     690            }
     691
     692            $children.each( function() {
     693                var $self     = $(this);
     694                var iwidth    = $self.width();
     695                var iheight   = $self.height();
     696                var _newWidth = newWidth;
     697                if ( $self.parents( '.repeat-row' ).length ) {
     698                    // Make room for our repeatable "remove" button column
     699                    _newWidth = newWidth - 91;
     700                }
     701                // Calc new height
     702                var newHeight = Math.round((_newWidth * iheight)/iwidth);
     703                $self.width(_newWidth).height(newHeight);
     704            });
     705
     706        });
     707    };
     708
     709    /**
     710     * Safely log things if query var is set
     711     * @since  1.0.0
     712     */
     713    cmb.log = function() {
     714        if ( l10n.script_debug && console && typeof console.log === 'function' ) {
     715            console.log.apply(console, arguments);
     716        }
     717    };
     718
     719    cmb.spinner = function( $context, hide ) {
     720        if ( hide ) {
     721            $('.cmb-spinner', $context ).hide();
     722        }
     723        else {
     724            $('.cmb-spinner', $context ).show();
     725        }
     726    };
     727
     728    // function for running our ajax
     729    cmb.doAjax = function($obj) {
     730        // get typed value
     731        var oembed_url = $obj.val();
     732        // only proceed if the field contains more than 6 characters
     733        if ( oembed_url.length < 6 ) {
     734            return;
     735        }
     736
     737        // only proceed if the user has pasted, pressed a number, letter, or whitelisted characters
     738
     739            // get field id
     740            var field_id = $obj.attr('id');
     741            // get our inputs $context for pinpointing
     742            var $context = $obj.parents('.cmb-repeat-table  tr td');
     743            $context = $context.length ? $context : $obj.parents('.cmb_metabox tr td');
     744
     745            var embed_container = $('.embed_status', $context);
     746            var oembed_width = $obj.width();
     747            var child_el = $(':first-child', embed_container);
     748
     749            // http://www.youtube.com/watch?v=dGG7aru2S6U
     750            cmb.log( 'oembed_url', oembed_url, field_id );
     751            oembed_width = ( embed_container.length && child_el.length ) ? child_el.width() : $obj.width();
     752
     753            // show our spinner
     754            cmb.spinner( $context );
     755            // clear out previous results
     756            $('.embed_wrap', $context).html('');
     757            // and run our ajax function
     758            setTimeout( function() {
     759                // if they haven't typed in 500 ms
     760                if ( $('.cmb_oembed:focus').val() !== oembed_url ) {
    102761                    return;
    103762                }
    104 
    105                 // Create the media frame.
    106                 CMB.file_frames[CMB.formfield] = wp.media.frames.file_frame = wp.media({
    107                     title: $('label[for=' + CMB.formfield + ']').text(),
    108                     button: {
    109                         text: window.cmb_l10.upload_file
     763                $.ajax({
     764                    type : 'post',
     765                    dataType : 'json',
     766                    url : l10n.ajaxurl,
     767                    data : {
     768                        'action': 'cmb_oembed_handler',
     769                        'oembed_url': oembed_url,
     770                        'oembed_width': oembed_width > 300 ? oembed_width : 300,
     771                        'field_id': field_id,
     772                        'object_id': $obj.data('objectid'),
     773                        'object_type': $obj.data('objecttype'),
     774                        'cmb_ajax_nonce': l10n.ajax_nonce
    110775                    },
    111                     multiple: isList ? true : false
    112                 });
    113 
    114                 // When an file is selected, run a callback.
    115                 CMB.file_frames[CMB.formfield].on( 'select', function() {
    116 
    117 
    118                     if ( isList ) {
    119 
    120                         // Get all of our selected files
    121                         attachment = CMB.file_frames[CMB.formfield].state().get('selection').toJSON();
    122 
    123                         $formfield.val(attachment.url);
    124                         $('#'+ CMB.formfield +'_id').val(attachment.id);
    125 
    126                         // Setup our fileGroup array
    127                         var fileGroup = [];
    128 
    129                         // Loop through each attachment
    130                         $( attachment ).each( function() {
    131                             if ( this.type && this.type === 'image' ) {
    132                                 // image preview
    133                                 uploadStatus = '<li class="img_status">'+
    134                                     '<img width="50" height="50" src="' + this.url + '" class="attachment-50x50" alt="'+ this.filename +'">'+
    135                                     '<p><a href="#" class="cmb_remove_file_button" rel="'+ CMB.formfield +'['+ this.id +']">'+ cmb_l10.remove_image +'</a></p>'+
    136                                     '<input type="hidden" id="filelist-'+ this.id +'" name="'+ CMB.formfield +'['+ this.id +']" value="' + this.url + '">'+
    137                                 '</li>';
    138 
    139                             } else {
    140                                 // Standard generic output if it's not an image.
    141                                 uploadStatus = '<li>'+ cmb_l10.file +' <strong>'+ this.filename +'</strong>&nbsp;&nbsp;&nbsp; (<a href="' + this.url + '" target="_blank" rel="external">'+ cmb_l10.download +'</a> / <a href="#" class="cmb_remove_file_button" rel="'+ CMB.formfield +'['+ this.id +']">'+ cmb_l10.remove_file +'</a>)'+
    142                                     '<input type="hidden" id="filelist-'+ this.id +'" name="'+ CMB.formfield +'['+ this.id +']" value="' + this.url + '">'+
    143                                 '</li>';
    144 
    145                             }
    146 
    147                             // Add our file to our fileGroup array
    148                             fileGroup.push( uploadStatus );
    149                         });
    150 
    151                         // Append each item from our fileGroup array to .cmb_media_status
    152                         $( fileGroup ).each( function() {
    153                             $formfield.siblings('.cmb_media_status').slideDown().append(this);
    154                         });
    155 
    156                     } else {
    157 
    158                         // Only get one file from the uploader
    159                         attachment = CMB.file_frames[CMB.formfield].state().get('selection').first().toJSON();
    160 
    161                         $formfield.val(attachment.url);
    162                         $('#'+ CMB.formfield +'_id').val(attachment.id);
    163 
    164                         if ( attachment.type && attachment.type === 'image' ) {
    165                             // image preview
    166                             uploadStatus = '<div class="img_status"><img style="max-width: 350px; width: 100%; height: auto;" src="' + attachment.url + '" alt="'+ attachment.filename +'" title="'+ attachment.filename +'" /><p><a href="#" class="cmb_remove_file_button" rel="' + CMB.formfield + '">'+ cmb_l10.remove_image +'</a></p></div>';
    167                         } else {
    168                             // Standard generic output if it's not an image.
    169                             uploadStatus = cmb_l10.file +' <strong>'+ attachment.filename +'</strong>&nbsp;&nbsp;&nbsp; (<a href="'+ attachment.url +'" target="_blank" rel="external">'+ cmb_l10.download +'</a> / <a href="#" class="cmb_remove_file_button" rel="'+ CMB.formfield +'">'+ cmb_l10.remove_file +'</a>)';
     776                    success: function(response) {
     777                        cmb.log( response );
     778                        // Make sure we have a response id
     779                        if ( typeof response.id === 'undefined' ) {
     780                            return;
    170781                        }
    171782
    172                         // add/display our output
    173                         $formfield.siblings('.cmb_media_status').slideDown().html(uploadStatus);
     783                        // hide our spinner
     784                        cmb.spinner( $context, true );
     785                        // and populate our results from ajax response
     786                        $('.embed_wrap', $context).html(response.result);
    174787                    }
    175788                });
    176789
    177                 // Finally, open the modal
    178                 CMB.file_frames[CMB.formfield].open();
    179             })
    180             .on( 'click', '.cmb_remove_file_button', function(event) {
    181                 var $self        = $(this);
    182                 if ( $self.is( '.attach_list .cmb_remove_file_button' ) ){
    183                     $self.parents('li').remove();
    184                     return false;
    185                 }
    186                 CMB.formfield    = $self.attr('rel');
    187                 var $container   = $self.parents('.img_status');
    188 
    189                 $('input#' + CMB.formfield).val('');
    190                 $('input#' + CMB.formfield + '_id').val('');
    191                 if ( ! $container.length ) {
    192                     $self.parents('.cmb_media_status').html('');
    193                 } else {
    194                     $container.html('');
    195                 }
    196                 return false;
    197             })
    198             .on( 'click', '.add-row-button', function(e) {
    199 
    200                 e.preventDefault();
    201                 var $self = $(this);
    202 
    203                 var tableselector = '#'+ $self.data('selector');
    204                 var $table = $(tableselector);
    205                 var row = $('.empty-row', $table).clone(true);
    206                 row.removeClass('empty-row').addClass('repeat-row');
    207                 row.insertBefore( tableselector +' tbody>tr:last' );
    208                 var input = $('input.cmb_datepicker',row);
    209                 var id = input.attr('id');
    210                 input.attr('id', id + CMB.iterator );
    211                 CMB.iterator++;
    212 
    213                 // @todo Make a colorpicker field repeatable
    214                 // row.find('.wp-color-result').remove();
    215                 // row.find('input:text.cmb_colorpicker').wpColorPicker();
    216 
    217             })
    218             .on( 'click', '.remove-row-button', function(e) {
    219                 e.preventDefault();
    220                 var $self = $(this);
    221                 var $parent = $self.parents('.cmb-repeat-table');
    222                 CMB.log( 'number of tbodys', $parent.length );
    223                 CMB.log( 'number of trs', $('tr', $parent).length );
    224                 if ( $('tr', $parent).length > 2 )
    225                     $self.parents('.cmb-repeat-table tr').remove();
    226             })
    227 
    228             /**
    229              * Ajax oEmbed display
    230              */
    231 
    232             // ajax when typing
    233             .on( 'keyup', '.cmb_oembed', function(event) {
    234                 // fire our ajax function
    235                 CMB.doAjax($(this), event);
    236             });
    237 
    238             // ajax on paste
    239             $('.cmb_oembed').bind( 'paste', function(e) {
    240                 var pasteitem = $(this);
    241                 // paste event is fired before the value is filled, so wait a bit
    242                 setTimeout( function() {
    243                     // fire our ajax function
    244                     CMB.doAjax(pasteitem, 'paste');
    245                 }, 100);
    246             }).blur( function() {
    247                 // when leaving the input
    248                 setTimeout( function() {
    249                     // if it's been 2 seconds, hide our spinner
    250                     CMB.spinner( '.postbox table.cmb_metabox', true );
    251                 }, 2000);
    252             });
    253 
    254             // on pageload
    255             setTimeout( CMB.resizeoEmbeds, 500);
    256             // and on window resize
    257             $(window).on( 'resize', CMB.resizeoEmbeds );
    258 
    259         },
    260 
    261         /**
    262          * Safely log things if query var is set
    263          * @since  1.0.0
    264          */
    265         log: function() {
    266             if ( window.cmb_l10.script_debug && console && typeof console.log === 'function' ) {
    267                 console.log.apply(console, arguments);
    268             }
    269         },
    270 
    271         spinner: function( context, hide ) {
    272             if ( hide )
    273                 $('.cmb-spinner', context).hide();
    274             else
    275                 $('.cmb-spinner', context).show();
    276         },
    277 
    278         // function for running our ajax
    279         doAjax: function(obj, e) {
    280             // get typed value
    281             var oembed_url = obj.val();
    282             // only proceed if the field contains more than 6 characters
    283             if (oembed_url.length < 6)
    284                 return;
    285 
    286             // only proceed if the user has pasted, pressed a number, letter, or whitelisted characters
    287             if (e === 'paste' || e.which <= 90 && e.which >= 48 || e.which >= 96 && e.which <= 111 || e.which == 8 || e.which == 9 || e.which == 187 || e.which == 190) {
    288 
    289                 // get field id
    290                 var field_id = obj.attr('id');
    291                 // get our inputs context for pinpointing
    292                 var context = obj.parents('.cmb_metabox tr td');
    293 
    294                 var embed_container = $('.embed_status', context);
    295                 var oembed_width = obj.width();
    296                 var child_el = $(':first-child', embed_container);
    297 
    298                 oembed_width = ( embed_container.length && child_el.length ) ? child_el.width() : obj.width();
    299 
    300                 // show our spinner
    301                 CMB.spinner( context );
    302                 // clear out previous results
    303                 $('.embed_wrap', context).html('');
    304                 // and run our ajax function
    305                 setTimeout( function() {
    306                     // if they haven't typed in 500 ms
    307                     if ($('.cmb_oembed:focus').val() != oembed_url)
    308                         return;
    309                     $.ajax({
    310                         type : 'post',
    311                         dataType : 'json',
    312                         url : window.cmb_l10.ajaxurl,
    313                         data : {
    314                             'action': 'cmb_oembed_handler',
    315                             'oembed_url': oembed_url,
    316                             'oembed_width': oembed_width > 300 ? oembed_width : 300,
    317                             'field_id': field_id,
    318                             'object_id': obj.data('objectid'),
    319                             'object_type': obj.data('objecttype'),
    320                             'cmb_ajax_nonce': window.cmb_l10.ajax_nonce
    321                         },
    322                         success: function(response) {
    323                             CMB.log( response );
    324                             // Make sure we have a response id
    325                             if (typeof response.id === 'undefined')
    326                                 return;
    327 
    328                             // hide our spinner
    329                             CMB.spinner( context, true );
    330                             // and populate our results from ajax response
    331                             $('.embed_wrap', context).html(response.result);
    332                         }
    333                     });
    334 
    335                 }, 500);
    336             }
    337         },
    338 
    339         /**
    340          * Resize oEmbed videos to fit in their respective metaboxes
    341          */
    342         resizeoEmbeds: function() {
    343             $('table.cmb_metabox').each( function( index ) {
    344                 var self = $(this);
    345                 var parents = self.parents('.inside');
    346                 if ( ! parents.length )
    347                     return true; // continue
    348 
    349                 var tWidth = parents.width();
    350                 var newWidth = Math.round((tWidth * 0.82)*0.97) - 30;
    351                 if ( newWidth > 639 )
    352                     return true; // continue
    353 
    354                 var child_el = $('.cmb-type-oembed .embed_status', self).children().first();
    355                 var iwidth = child_el.width();
    356                 var iheight = child_el.height();
    357                 var newHeight = Math.round((newWidth * iheight)/iwidth);
    358                 child_el.width(newWidth).height(newHeight);
    359 
    360             });
    361         }
    362 
    363     };
    364 
    365     $(document).ready(CMB.init);
     790            }, 500);
     791    };
     792
     793    $(document).ready(cmb.init);
     794
     795    return cmb;
    366796
    367797})(window, document, jQuery);
  • infinite-slider/trunk/public/includes/cmb/js/cmb.min.js

    r884566 r969547  
    1 (function(b,a,c,d){b.CMB={formfield:"",iterator:0,file_frames:{},init:function(){CMB.log(b.cmb_l10);if(b.cmb_l10.new_admin_style){c(".cmb-spinner img").hide();
    2 }c(".cmb_timepicker").each(function(){c("#"+jQuery(this).attr("id")).timePicker({startTime:"07:00",endTime:"22:00",show24Hours:false,separator:":",step:30});
    3 });c(".cmb_datepicker").each(function(){c("#"+jQuery(this).attr("id")).datepicker();});c("#ui-datepicker-div").wrap('<div class="cmb_element" />');if(typeof jQuery.wp==="object"&&typeof jQuery.wp.wpColorPicker==="function"){c("input:text.cmb_colorpicker").wpColorPicker();
    4 }else{c("input:text.cmb_colorpicker").each(function(e){c(this).after('<div id="picker-'+e+'" style="z-index: 1000; background: #EEE; border: 1px solid #CCC; position: absolute; display: block;"></div>');
    5 c("#picker-"+e).hide().farbtastic(c(this));}).focus(function(){c(this).next().show();}).blur(function(){c(this).next().hide();});}c(".cmb_metabox").on("change",".cmb_upload_file",function(){CMB.formfield=c(this).attr("name");
    6 c("#"+CMB.formfield+"_id").val("");}).on("click",".cmb_upload_button",function(f){f.preventDefault();var j=c(this);CMB.formfield=j.prev("input").attr("name");
    7 var i=c("#"+CMB.formfield);var e=true;var h=true;var g=j.hasClass("cmb_upload_list");if(CMB.formfield in CMB.file_frames){CMB.file_frames[CMB.formfield].open();
    8 return;}CMB.file_frames[CMB.formfield]=wp.media.frames.file_frame=wp.media({title:c("label[for="+CMB.formfield+"]").text(),button:{text:b.cmb_l10.upload_file},multiple:g?true:false});
    9 CMB.file_frames[CMB.formfield].on("select",function(){if(g){h=CMB.file_frames[CMB.formfield].state().get("selection").toJSON();i.val(h.url);c("#"+CMB.formfield+"_id").val(h.id);
    10 var k=[];c(h).each(function(){if(this.type&&this.type==="image"){e='<li class="img_status"><img width="50" height="50" src="'+this.url+'" class="attachment-50x50" alt="'+this.filename+'"><p><a href="#" class="cmb_remove_file_button" rel="'+CMB.formfield+"["+this.id+']">'+cmb_l10.remove_image+'</a></p><input type="hidden" id="filelist-'+this.id+'" name="'+CMB.formfield+"["+this.id+']" value="'+this.url+'"></li>';
    11 }else{e="<li>"+cmb_l10.file+" <strong>"+this.filename+'</strong>&nbsp;&nbsp;&nbsp; (<a href="'+this.url+'" target="_blank" rel="external">'+cmb_l10.download+'</a> / <a href="#" class="cmb_remove_file_button" rel="'+CMB.formfield+"["+this.id+']">'+cmb_l10.remove_file+'</a>)<input type="hidden" id="filelist-'+this.id+'" name="'+CMB.formfield+"["+this.id+']" value="'+this.url+'"></li>';
    12 }k.push(e);});c(k).each(function(){i.siblings(".cmb_media_status").slideDown().append(this);});}else{h=CMB.file_frames[CMB.formfield].state().get("selection").first().toJSON();
    13 i.val(h.url);c("#"+CMB.formfield+"_id").val(h.id);if(h.type&&h.type==="image"){e='<div class="img_status"><img style="max-width: 350px; width: 100%; height: auto;" src="'+h.url+'" alt="'+h.filename+'" title="'+h.filename+'" /><p><a href="#" class="cmb_remove_file_button" rel="'+CMB.formfield+'">'+cmb_l10.remove_image+"</a></p></div>";
    14 }else{e=cmb_l10.file+" <strong>"+h.filename+'</strong>&nbsp;&nbsp;&nbsp; (<a href="'+h.url+'" target="_blank" rel="external">'+cmb_l10.download+'</a> / <a href="#" class="cmb_remove_file_button" rel="'+CMB.formfield+'">'+cmb_l10.remove_file+"</a>)";
    15 }i.siblings(".cmb_media_status").slideDown().html(e);}});CMB.file_frames[CMB.formfield].open();}).on("click",".cmb_remove_file_button",function(e){var g=c(this);
    16 if(g.is(".attach_list .cmb_remove_file_button")){g.parents("li").remove();return false;}CMB.formfield=g.attr("rel");var f=g.parents(".img_status");c("input#"+CMB.formfield).val("");
    17 c("input#"+CMB.formfield+"_id").val("");if(!f.length){g.parents(".cmb_media_status").html("");}else{f.html("");}return false;}).on("click",".add-row-button",function(i){i.preventDefault();
    18 var k=c(this);var h="#"+k.data("selector");var g=c(h);var j=c(".empty-row",g).clone(true);j.removeClass("empty-row").addClass("repeat-row");j.insertBefore(h+" tbody>tr:last");
    19 var f=c("input.cmb_datepicker",j);var l=f.attr("id");f.attr("id",l+CMB.iterator);CMB.iterator++;}).on("click",".remove-row-button",function(g){g.preventDefault();
    20 var h=c(this);var f=h.parents(".cmb-repeat-table");CMB.log("number of tbodys",f.length);CMB.log("number of trs",c("tr",f).length);if(c("tr",f).length>2){h.parents(".cmb-repeat-table tr").remove();
    21 }}).on("keyup",".cmb_oembed",function(e){CMB.doAjax(c(this),e);});c(".cmb_oembed").bind("paste",function(g){var f=c(this);setTimeout(function(){CMB.doAjax(f,"paste");
    22 },100);}).blur(function(){setTimeout(function(){CMB.spinner(".postbox table.cmb_metabox",true);},2000);});setTimeout(CMB.resizeoEmbeds,500);c(b).on("resize",CMB.resizeoEmbeds);
    23 },log:function(){if(b.cmb_l10.script_debug&&console&&typeof console.log==="function"){console.log.apply(console,arguments);}},spinner:function(f,e){if(e){c(".cmb-spinner",f).hide();
    24 }else{c(".cmb-spinner",f).show();}},doAjax:function(m,l){var h=m.val();if(h.length<6){return;}if(l==="paste"||l.which<=90&&l.which>=48||l.which>=96&&l.which<=111||l.which==8||l.which==9||l.which==187||l.which==190){var j=m.attr("id");
    25 var g=m.parents(".cmb_metabox tr td");var k=c(".embed_status",g);var f=m.width();var i=c(":first-child",k);f=(k.length&&i.length)?i.width():m.width();CMB.spinner(g);
    26 c(".embed_wrap",g).html("");setTimeout(function(){if(c(".cmb_oembed:focus").val()!=h){return;}c.ajax({type:"post",dataType:"json",url:b.cmb_l10.ajaxurl,data:{action:"cmb_oembed_handler",oembed_url:h,oembed_width:f>300?f:300,field_id:j,object_id:m.data("objectid"),object_type:m.data("objecttype"),cmb_ajax_nonce:b.cmb_l10.ajax_nonce},success:function(e){CMB.log(e);
    27 if(typeof e.id==="undefined"){return;}CMB.spinner(g,true);c(".embed_wrap",g).html(e.result);}});},500);}},resizeoEmbeds:function(){c("table.cmb_metabox").each(function(j){var m=c(this);
    28 var l=m.parents(".inside");if(!l.length){return true;}var i=l.width();var h=Math.round((i*0.82)*0.97)-30;if(h>639){return true;}var f=c(".cmb-type-oembed .embed_status",m).children().first();
    29 var g=f.width();var k=f.height();var e=Math.round((h*k)/g);f.width(h).height(e);});}};c(a).ready(CMB.init);})(window,document,jQuery);
     1window.CMB=function(window,document,$){"use strict";var l10n=window.cmb_l10,setTimeout=window.setTimeout,cmb={formfield:"",idNumber:!1,file_frames:{},repeatEls:'input:not([type="button"]),select,textarea,.cmb_media_status'};return cmb.metabox=function(){return cmb.$metabox?cmb.$metabox:(cmb.$metabox=$("table.cmb_metabox"),cmb.$metabox)},cmb.init=function(){var $metabox=cmb.metabox(),$repeatGroup=$metabox.find(".repeatable-group");l10n.new_admin_style&&$metabox.find(".cmb-spinner img").hide(),cmb.initPickers($metabox.find("input:text.cmb_timepicker"),$metabox.find("input:text.cmb_datepicker"),$metabox.find("input:text.cmb_colorpicker")),$("#ui-datepicker-div").wrap('<div class="cmb_element" />'),$('<p><span class="button cmb-multicheck-toggle">'+l10n.check_toggle+"</span></p>").insertBefore("ul.cmb_checkbox_list"),$metabox.on("change",".cmb_upload_file",function(){cmb.formfield=$(this).attr("id"),$("#"+cmb.formfield+"_id").val("")}).on("click",".cmb-multicheck-toggle",cmb.toggleCheckBoxes).on("click",".cmb_upload_button",cmb.handleMedia).on("click",".cmb_remove_file_button",cmb.handleRemoveMedia).on("click",".add-group-row",cmb.addGroupRow).on("click",".add-row-button",cmb.addAjaxRow).on("click",".remove-group-row",cmb.removeGroupRow).on("click",".remove-row-button",cmb.removeAjaxRow).on("keyup paste focusout",".cmb_oembed",cmb.maybeOembed).on("cmb_remove_row",".repeatable-group",cmb.resetTitlesAndIterator),$repeatGroup.length&&$repeatGroup.filter(".sortable").each(function(){$(this).find(".remove-group-row").before('<a class="shift-rows move-up alignleft" href="#">'+l10n.up_arrow+'</a> <a class="shift-rows move-down alignleft" href="#">'+l10n.down_arrow+"</a>")}).on("click",".shift-rows",cmb.shiftRows).on("cmb_add_row",cmb.emptyValue),setTimeout(cmb.resizeoEmbeds,500),$(window).on("resize",cmb.resizeoEmbeds)},cmb.resetTitlesAndIterator=function(){$(".repeatable-group").each(function(){var $table=$(this);$table.find(".repeatable-grouping").each(function(rowindex){var $row=$(this);$row.data("iterator",rowindex),$row.find(".cmb-group-title h4").text($table.find(".add-group-row").data("grouptitle").replace("{#}",rowindex+1))})})},cmb.toggleCheckBoxes=function(event){event.preventDefault();var $self=$(this),$multicheck=$self.parents("td").find("input[type=checkbox]");$self.data("checked")?($multicheck.prop("checked",!1),$self.data("checked",!1)):($multicheck.prop("checked",!0),$self.data("checked",!0))},cmb.handleMedia=function(event){if(wp){event.preventDefault();var $metabox=cmb.metabox(),$self=$(this);cmb.formfield=$self.prev("input").attr("id");var $formfield=$("#"+cmb.formfield),formName=$formfield.attr("name"),uploadStatus=!0,attachment=!0,isList=$self.hasClass("cmb_upload_list");if(cmb.formfield in cmb.file_frames)return void cmb.file_frames[cmb.formfield].open();cmb.file_frames[cmb.formfield]=wp.media.frames.file_frame=wp.media({title:$metabox.find("label[for="+cmb.formfield+"]").text(),button:{text:l10n.upload_file},multiple:isList?!0:!1});var handlers={list:function(selection){attachment=selection.toJSON(),$formfield.val(attachment.url),$("#"+cmb.formfield+"_id").val(attachment.id);var fileGroup=[];$(attachment).each(function(){uploadStatus=this.type&&"image"===this.type?'<li class="img_status"><img width="50" height="50" src="'+this.url+'" class="attachment-50x50" alt="'+this.filename+'"><p><a href="#" class="cmb_remove_file_button" rel="'+cmb.formfield+"["+this.id+']">'+l10n.remove_image+'</a></p><input type="hidden" id="filelist-'+this.id+'" name="'+formName+"["+this.id+']" value="'+this.url+'"></li>':"<li>"+l10n.file+" <strong>"+this.filename+'</strong>&nbsp;&nbsp;&nbsp; (<a href="'+this.url+'" target="_blank" rel="external">'+l10n.download+'</a> / <a href="#" class="cmb_remove_file_button" rel="'+cmb.formfield+"["+this.id+']">'+l10n.remove_file+'</a>)<input type="hidden" id="filelist-'+this.id+'" name="'+formName+"["+this.id+']" value="'+this.url+'"></li>',fileGroup.push(uploadStatus)}),$(fileGroup).each(function(){$formfield.siblings(".cmb_media_status").slideDown().append(this)})},single:function(selection){attachment=selection.first().toJSON(),$formfield.val(attachment.url),$("#"+cmb.formfield+"_id").val(attachment.id),uploadStatus=attachment.type&&"image"===attachment.type?'<div class="img_status"><img style="max-width: 350px; width: 100%; height: auto;" src="'+attachment.url+'" alt="'+attachment.filename+'" title="'+attachment.filename+'" /><p><a href="#" class="cmb_remove_file_button" rel="'+cmb.formfield+'">'+l10n.remove_image+"</a></p></div>":l10n.file+" <strong>"+attachment.filename+'</strong>&nbsp;&nbsp;&nbsp; (<a href="'+attachment.url+'" target="_blank" rel="external">'+l10n.download+'</a> / <a href="#" class="cmb_remove_file_button" rel="'+cmb.formfield+'">'+l10n.remove_file+"</a>)",$formfield.siblings(".cmb_media_status").slideDown().html(uploadStatus)}};cmb.file_frames[cmb.formfield].on("select",function(){var selection=cmb.file_frames[cmb.formfield].state().get("selection"),type=isList?"list":"single";handlers[type](selection)}),cmb.file_frames[cmb.formfield].open()}},cmb.handleRemoveMedia=function(event){event.preventDefault();var $self=$(this);if($self.is(".attach_list .cmb_remove_file_button"))return $self.parents("li").remove(),!1;cmb.formfield=$self.attr("rel");var $container=$self.parents(".img_status");return cmb.metabox().find("input#"+cmb.formfield).val(""),cmb.metabox().find("input#"+cmb.formfield+"_id").val(""),$container.length?$container.html(""):$self.parents(".cmb_media_status").html(""),!1},$.fn.replaceText=function(b,a,c){return this.each(function(){var g,e,f=this.firstChild,d=[];if(f)do 3===f.nodeType&&(g=f.nodeValue,e=g.replace(b,a),e!==g&&(!c&&/</.test(e)?($(f).before(e),d.push(f)):f.nodeValue=e));while(f=f.nextSibling);d.length&&$(d).remove()})},$.fn.cleanRow=function(prevNum,group){var $self=$(this),$inputs=$self.find('input:not([type="button"]), select, textarea, label');return group&&$self.find(".cmb-repeat-table .repeat-row:not(:first-child)").remove(),cmb.$focus=!1,cmb.neweditor_id=[],$inputs.filter(":checked").removeAttr("checked"),$inputs.filter(":selected").removeAttr("selected"),$self.find(".cmb-group-title")&&$self.find(".cmb-group-title h4").text($self.data("title").replace("{#}",cmb.idNumber+1)),$inputs.each(function(){var newID,oldID,$newInput=$(this),isEditor=$newInput.hasClass("wp-editor-area"),oldFor=$newInput.attr("for"),attrs={};if(oldFor)attrs={"for":oldFor.replace("_"+prevNum,"_"+cmb.idNumber)};else{var oldName=$newInput.attr("name"),newName=oldName?oldName.replace("["+prevNum+"]","["+cmb.idNumber+"]"):"";oldID=$newInput.attr("id"),newID=oldID?oldID.replace("_"+prevNum,"_"+cmb.idNumber):"",attrs={id:newID,name:newName,"data-iterator":cmb.idNumber}}if($newInput.removeClass("hasDatepicker").attr(attrs).val(""),isEditor){newID=newID?oldID.replace("zx"+prevNum,"zx"+cmb.idNumber):"",$newInput.html("");var $wysiwyg=$newInput.parents(".cmb-type-wysiwyg");$wysiwyg.find(".mce-tinymce:not(:first-child)").remove();var html=$wysiwyg.html().replace(new RegExp(oldID,"g"),newID);$wysiwyg.html(html),cmb.neweditor_id.push({id:newID,old:oldID})}cmb.$focus=cmb.$focus?cmb.$focus:$newInput}),this},$.fn.newRowHousekeeping=function(){var $row=$(this),$colorPicker=$row.find(".wp-picker-container"),$list=$row.find(".cmb_media_status");return $colorPicker.length&&$colorPicker.each(function(){var $td=$(this).parent();$td.html($td.find("input:text.cmb_colorpicker").attr("style",""))}),$list.length&&$list.empty(),this},cmb.afterRowInsert=function($row){cmb.$focus&&cmb.$focus.focus();var _prop;if(cmb.neweditor_id.length){var i;for(i=cmb.neweditor_id.length-1;i>=0;i--){var id=cmb.neweditor_id[i].id,old=cmb.neweditor_id[i].old;if("undefined"==typeof tinyMCEPreInit.mceInit[id]){var newSettings=jQuery.extend({},tinyMCEPreInit.mceInit[old]);for(_prop in newSettings)"string"==typeof newSettings[_prop]&&(newSettings[_prop]=newSettings[_prop].replace(new RegExp(old,"g"),id));tinyMCEPreInit.mceInit[id]=newSettings}if("undefined"==typeof tinyMCEPreInit.qtInit[id]){var newQTS=jQuery.extend({},tinyMCEPreInit.qtInit[old]);for(_prop in newQTS)"string"==typeof newQTS[_prop]&&(newQTS[_prop]=newQTS[_prop].replace(new RegExp(old,"g"),id));tinyMCEPreInit.qtInit[id]=newQTS}tinyMCE.init({id:tinyMCEPreInit.mceInit[id]})}}cmb.initPickers($row.find("input:text.cmb_timepicker"),$row.find("input:text.cmb_datepicker"),$row.find("input:text.cmb_colorpicker"))},cmb.updateNameAttr=function(){var $this=$(this),name=$this.attr("name");if("undefined"==typeof name)return!1;var prevNum=parseInt($this.parents(".repeatable-grouping").data("iterator")),newNum=prevNum-1,$newName=name.replace("["+prevNum+"]","["+newNum+"]");$this.attr("name",$newName)},cmb.emptyValue=function(event,row){$('input:not([type="button"]), textarea',row).val("")},cmb.addGroupRow=function(event){event.preventDefault();var $self=$(this),$table=$("#"+$self.data("selector")),$oldRow=$table.find(".repeatable-grouping").last(),prevNum=parseInt($oldRow.data("iterator"));cmb.idNumber=prevNum+1;var $row=$oldRow.clone();$row.data("title",$self.data("grouptitle")).newRowHousekeeping().cleanRow(prevNum,!0);var $newRow=$('<tr class="repeatable-grouping" data-iterator="'+cmb.idNumber+'">'+$row.html()+"</tr>");$oldRow.after($newRow),cmb.afterRowInsert($newRow),$table.find(".repeatable-grouping").length<=1?$table.find(".remove-group-row").prop("disabled",!0):$table.find(".remove-group-row").removeAttr("disabled"),$table.trigger("cmb_add_row",$newRow)},cmb.addAjaxRow=function(event){event.preventDefault();var $self=$(this),tableselector="#"+$self.data("selector"),$table=$(tableselector),$emptyrow=$table.find(".empty-row"),prevNum=parseInt($emptyrow.find("[data-iterator]").data("iterator"));cmb.idNumber=prevNum+1;var $row=$emptyrow.clone();$row.newRowHousekeeping().cleanRow(prevNum),$emptyrow.removeClass("empty-row").addClass("repeat-row"),$emptyrow.after($row),cmb.afterRowInsert($row),$table.trigger("cmb_add_row",$row)},cmb.removeGroupRow=function(event){event.preventDefault();var $self=$(this),$table=$("#"+$self.data("selector")),$parent=$self.parents(".repeatable-grouping"),noRows=$table.find(".repeatable-grouping").length;$parent.nextAll(".repeatable-grouping").find(cmb.repeatEls).each(cmb.updateNameAttr),noRows>1&&($parent.remove(),3>noRows?$table.find(".remove-group-row").prop("disabled",!0):$table.find(".remove-group-row").prop("disabled",!1),$table.trigger("cmb_remove_row"))},cmb.removeAjaxRow=function(event){event.preventDefault();var $self=$(this),$parent=$self.parents("tr"),$table=$self.parents(".cmb-repeat-table");$table.find("tr").length>1&&($parent.hasClass("empty-row")&&$parent.prev().addClass("empty-row").removeClass("repeat-row"),$self.parents(".cmb-repeat-table tr").remove(),$table.trigger("cmb_remove_row"))},cmb.shiftRows=function(event){event.preventDefault();var $self=$(this),$parent=$self.parents(".repeatable-grouping"),$goto=$self.hasClass("move-up")?$parent.prev(".repeatable-grouping"):$parent.next(".repeatable-grouping");if($goto.length){var inputVals=[];$parent.find(cmb.repeatEls).each(function(){var val,$element=$(this);$element.hasClass("cmb_media_status")?val=$element.html():"checkbox"===$element.attr("type")?(val=$element.is(":checked"),cmb.log("checked",val)):"select"===$element.prop("tagName")?(val=$element.is(":selected"),cmb.log("checked",val)):val=$element.val(),inputVals.push({val:val,$:$element})}),$goto.find(cmb.repeatEls).each(function(index){var val,$element=$(this);$element.hasClass("cmb_media_status")?(val=$element.html(),$element.html(inputVals[index].val),inputVals[index].$.html(val)):"checkbox"===$element.attr("type")?(inputVals[index].$.prop("checked",$element.is(":checked")),$element.prop("checked",inputVals[index].val)):"select"===$element.prop("tagName")?(inputVals[index].$.prop("selected",$element.is(":selected")),$element.prop("selected",inputVals[index].val)):(inputVals[index].$.val($element.val()),$element.val(inputVals[index].val))})}},cmb.initPickers=function($timePickers,$datePickers,$colorPickers){cmb.initTimePickers($timePickers),cmb.initDatePickers($datePickers),cmb.initColorPickers($colorPickers)},cmb.initTimePickers=function($selector){$selector.length&&$selector.timePicker({startTime:"00:00",endTime:"23:59",show24Hours:!1,separator:":",step:30})},cmb.initDatePickers=function($selector){$selector.length&&($selector.datepicker("destroy"),$selector.datepicker())},cmb.initColorPickers=function($selector){$selector.length&&("object"==typeof jQuery.wp&&"function"==typeof jQuery.wp.wpColorPicker?$selector.wpColorPicker():$selector.each(function(i){$(this).after('<div id="picker-'+i+'" style="z-index: 1000; background: #EEE; border: 1px solid #CCC; position: absolute; display: block;"></div>'),$("#picker-"+i).hide().farbtastic($(this))}).focus(function(){$(this).next().show()}).blur(function(){$(this).next().hide()}))},cmb.maybeOembed=function(evt){var $self=$(this),type=evt.type,m={focusout:function(){setTimeout(function(){cmb.spinner(".postbox table.cmb_metabox",!0)},2e3)},keyup:function(){var betw=function(min,max){return evt.which<=max&&evt.which>=min};(betw(48,90)||betw(96,111)||betw(8,9)||187===evt.which||190===evt.which)&&cmb.doAjax($self,evt)},paste:function(){setTimeout(function(){cmb.doAjax($self)},100)}};m[type]()},cmb.resizeoEmbeds=function(){cmb.metabox().each(function(){var $self=$(this),$tableWrap=$self.parents(".inside");if(!$tableWrap.length)return!0;var newWidth=Math.round(.82*$tableWrap.width()*.97)-30;if(newWidth>639)return!0;var $embeds=$self.find(".cmb-type-oembed .embed_status"),$children=$embeds.children().not(".cmb_remove_wrapper");return $children.length?void $children.each(function(){var $self=$(this),iwidth=$self.width(),iheight=$self.height(),_newWidth=newWidth;$self.parents(".repeat-row").length&&(_newWidth=newWidth-91);var newHeight=Math.round(_newWidth*iheight/iwidth);$self.width(_newWidth).height(newHeight)}):!0})},cmb.log=function(){l10n.script_debug&&console&&"function"==typeof console.log&&console.log.apply(console,arguments)},cmb.spinner=function($context,hide){hide?$(".cmb-spinner",$context).hide():$(".cmb-spinner",$context).show()},cmb.doAjax=function($obj){var oembed_url=$obj.val();if(!(oembed_url.length<6)){var field_id=$obj.attr("id"),$context=$obj.parents(".cmb-repeat-table  tr td");$context=$context.length?$context:$obj.parents(".cmb_metabox tr td");var embed_container=$(".embed_status",$context),oembed_width=$obj.width(),child_el=$(":first-child",embed_container);cmb.log("oembed_url",oembed_url,field_id),oembed_width=embed_container.length&&child_el.length?child_el.width():$obj.width(),cmb.spinner($context),$(".embed_wrap",$context).html(""),setTimeout(function(){$(".cmb_oembed:focus").val()===oembed_url&&$.ajax({type:"post",dataType:"json",url:l10n.ajaxurl,data:{action:"cmb_oembed_handler",oembed_url:oembed_url,oembed_width:oembed_width>300?oembed_width:300,field_id:field_id,object_id:$obj.data("objectid"),object_type:$obj.data("objecttype"),cmb_ajax_nonce:l10n.ajax_nonce},success:function(response){cmb.log(response),"undefined"!=typeof response.id&&(cmb.spinner($context,!0),$(".embed_wrap",$context).html(response.result))}})},500)}},$(document).ready(cmb.init),cmb}(window,document,jQuery);
  • infinite-slider/trunk/public/includes/cmb/style.css

    r884566 r969547  
    22 * CMB Styling
    33 */
     4
    45table.cmb_metabox {
    56    clear: both;
    67}
    78
    8 table.cmb_metabox tr:first-of-type td, table.cmb_metabox tr:first-of-type th {
    9     border:0;
    10 }
    11 
    12 .post-php table.cmb_metabox td, .post-new-php table.cmb_metabox td, .post-php table.cmb_metabox th, .post-new-php table.cmb_metabox th {
     9table.cmb_metabox > tr:first-of-type > td,
     10table.cmb_metabox > tr:first-of-type > th,
     11table.cmb_metabox tbody > tr:first-of-type > td,
     12table.cmb_metabox tbody > tr:first-of-type > th,
     13.post-php table.cmb_metabox .cmb-nested-table td,
     14.post-new-php table.cmb_metabox .cmb-nested-table td,
     15.post-php table.cmb_metabox .repeatable-group th,
     16.post-new-php table.cmb_metabox .repeatable-group th,
     17.post-php table.cmb_metabox .repeatable-group:first-of-type,
     18.post-new-php table.cmb_metabox .repeatable-group:first-of-type {
     19    border: 0;
     20}
     21
     22.post-php table.cmb_metabox td,
     23.post-new-php table.cmb_metabox td,
     24.post-php table.cmb_metabox th,
     25.post-new-php table.cmb_metabox th,
     26.post-php table.cmb_metabox .repeatable-group,
     27.post-new-php table.cmb_metabox .repeatable-group,
     28.post-php table.cmb_metabox .repeatable-group,
     29.post-new-php table.cmb_metabox .repeatable-group {
    1330    border-top: 1px solid #E9E9E9;
     31}
     32
     33.repeatable-group th {
     34    padding: 5px;
     35}
     36
     37.repeatable-group .shift-rows {
     38    text-decoration: none;
     39    margin-right: 5px;
     40    font-size: 1.2em;
     41}
     42
     43.repeatable-group .cmb_upload_button {
     44    float: right;
     45}
     46
     47#poststuff .repeatable-group h2 {
     48    margin: 0;
     49}
     50
     51.cmb-group-title h4 {
     52    font-size: 1.2em;
     53    font-weight: 500;
     54    border-bottom: 1px solid #ddd;
    1455}
    1556
    1657.post-php table.cmb_metabox th, .post-new-php table.cmb_metabox th {
    1758    text-align: right;
    18     font-weight:bold
     59    font-weight:bold;
     60}
     61
     62.post-php table.cmb_metabox table th, .post-new-php table.cmb_metabox table th {
     63    text-align: left;
    1964}
    2065
     
    202247 * Sidebar placement adjustments
    203248 */
    204 .inner-sidebar table.cmb_metabox input[type=text], #side-sortables table.cmb_metabox input[type=text], table.cmb_metabox textarea {
     249.inner-sidebar table.cmb_metabox input[type=text],
     250#side-sortables table.cmb_metabox input[type=text],
     251table.cmb_metabox textarea {
    205252    width: 95%;
    206253}
    207254
    208 .inner-sidebar table.cmb_metabox .cmb_media_status .img_status img, #side-sortables table.cmb_metabox .cmb_media_status .img_status img, .inner-sidebar table.cmb_metabox .cmb_media_status .embed_status img, #side-sortables table.cmb_metabox .cmb_media_status .embed_status img {
     255.inner-sidebar table.cmb_metabox .cmb_media_status .img_status img,
     256#side-sortables table.cmb_metabox .cmb_media_status .img_status img,
     257.inner-sidebar table.cmb_metabox .cmb_media_status .embed_status img,
     258#side-sortables table.cmb_metabox .cmb_media_status .embed_status img {
    209259    width: 90%;
     260}
     261
     262.inner-sidebar table.cmb_metabox label,
     263#side-sortables table.cmb_metabox label {
     264    display: block;
     265    font-weight: bold;
     266    padding: 0 0 5px;
     267}
     268
     269.inner-sidebar table.cmb_metabox .cmb_list label,
     270#side-sortables table.cmb_metabox .cmb_list label {
     271    display: inline;
     272    font-weight: normal;
     273}
     274
     275.inner-sidebar table.cmb_metabox .cmb_metabox_description,
     276#side-sortables table.cmb_metabox .cmb_metabox_description {
     277    display: block;
     278    padding: 7px 0 0;
     279}
     280
     281.inner-sidebar table.cmb_metabox .cmb_metabox_title,
     282#side-sortables table.cmb_metabox .cmb_metabox_title {
     283    font-size: 1.2em;
     284    font-style: italic;
    210285}
    211286
  • infinite-slider/trunk/public/includes/cmb/style.min.css

    r884566 r969547  
    1 table.cmb_metabox{clear:both}table.cmb_metabox tr:first-of-type td,table.cmb_metabox tr:first-of-type th{border:0}.post-php table.cmb_metabox td,.post-new-php table.cmb_metabox td,.post-php table.cmb_metabox th,.post-new-php table.cmb_metabox th{border-top:1px solid #e9e9e9}
    2 .post-php table.cmb_metabox th,.post-new-php table.cmb_metabox th{text-align:right;font-weight:bold}table.cmb_metabox th label{margin-top:5px;display:block}
    3 p.cmb_metabox_description{color:#AAA;font-style:italic;margin:2px 0!important}span.cmb_metabox_description{color:#AAA;font-style:italic}table.cmb_metabox input,table.cmb_metabox textarea{font-size:14px;padding:5px}
    4 table.cmb_metabox input[type=text],table.cmb_metabox textarea{width:97%}table.cmb_metabox textarea.cmb_textarea_code{font-family:Consolas,Monaco,monospace;line-height:16px}
    5 table.cmb_metabox input.cmb_text_small{width:100px;margin-right:15px}table.cmb_metabox input.cmb_timepicker{width:100px;margin-right:15px}table.cmb_metabox input.cmb_text_money{width:90px;margin-right:15px}
    6 table.cmb_metabox input.cmb_text_medium{width:230px;margin-right:15px}table.cmb_metabox input.cmb_upload_file{width:65%}table.cmb_metabox input.ed_button{padding:2px 4px}
    7 table.cmb_metabox li{font-size:14px;margin:1px 0 5px 0;line-height:16px}table.cmb_metabox ul{padding-top:5px;margin:0}table.cmb_metabox select{font-size:14px;margin-top:3px}
    8 table.cmb_metabox input:focus,table.cmb_metabox textarea:focus{background:#fffff8}.cmb_metabox_title{margin:0 0 5px 0;padding:5px 0 0 0}.edit-tags-php .cmb_metabox_title,.profile-php .cmb_metabox_title,.user-edit-php .cmb_metabox_title{margin-left:-10px}
    9 .cmb-inline ul{padding:4px 0 0 0}.cmb-inline li{display:inline-block;padding-right:18px}table.cmb_metabox input[type="radio"]{margin:0 5px 0 0;padding:0}
    10 table.cmb_metabox input[type="checkbox"]{margin:0 5px 0 0;padding:0}table.cmb_metabox .mceLayout{border:1px solid #dfdfdf!important}
    11 table.cmb_metabox .mceIframeContainer{background:#FFF}table.cmb_metabox .meta_mce{width:97%}table.cmb_metabox .meta_mce textarea{width:100%}table.cmb_metabox .cmb_media_status{margin:10px 0 0 0}
    12 table.cmb_metabox .cmb_media_status .img_status{display:inline-block}table.cmb_metabox .cmb-type-file_list .cmb_media_status .img_status{clear:none;float:left;margin-right:10px;width:auto}
    13 table.cmb_metabox .cmb_media_status .img_status,table.cmb_metabox .cmb_media_status .embed_status{position:relative}table.cmb_metabox .cmb_media_status .img_status img,table.cmb_metabox .cmb_media_status .embed_status{border:1px solid #dfdfdf;background:#fafafa;max-width:350px;padding:5px;-moz-border-radius:2px;border-radius:2px}
    14 table.cmb_metabox .cmb_media_status .embed_status{float:left;max-width:800px}table.cmb_metabox .cmb_media_status .img_status .cmb_remove_file_button,table.cmb_metabox .cmb_media_status .embed_status .cmb_remove_file_button{text-indent:-9999px;background:url(images/ico-delete.png);width:16px;height:16px;position:absolute;top:-5px;left:-5px}
    15 table.cmb_metabox .attach_list li{clear:both;display:inline-block;margin-bottom:25px;width:100%}table.cmb_metabox .attach_list li img{float:left;margin-right:10px}
    16 .inner-sidebar table.cmb_metabox input[type=text],#side-sortables table.cmb_metabox input[type=text],table.cmb_metabox textarea{width:95%}.inner-sidebar table.cmb_metabox .cmb_media_status .img_status img,#side-sortables table.cmb_metabox .cmb_media_status .img_status img,.inner-sidebar table.cmb_metabox .cmb_media_status .embed_status img,#side-sortables table.cmb_metabox .cmb_media_status .embed_status img{width:90%}
    17 .postbox table.cmb_metabox .cmb-spinner{float:left}table.cmb_metabox .wp-color-result,table.cmb_metabox .wp-picker-input-wrap{vertical-align:middle}table.cmb_metabox .wp-color-result,table.cmb_metabox .wp-picker-container{margin:0 10px 0 0}
    18 div.time-picker{position:absolute;height:191px;width:6em;overflow:auto;background:#fff;border:1px solid #aaa;z-index:99;margin:0}div.time-picker-12hours{width:8em}
    19 div.time-picker ul{list-style-type:none;margin:0;padding:0}div.time-picker li{cursor:pointer;height:10px;font:14px/1 Helvetica,Arial,sans-serif;padding:4px 3px}
    20 div.time-picker li.selected{background:#0063ce;color:#fff}.cmb_element .ui-helper-hidden{display:none}.cmb_element .ui-helper-hidden-accessible{position:absolute!important;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}
    21 .cmb_element .ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.cmb_element .ui-helper-clearfix:after{content:".";display:block;height:0;clear:both;visibility:hidden}
    22 .cmb_element .ui-helper-clearfix{display:inline-block}* html .ui-helper-clearfix{height:1%}.cmb_element .ui-helper-clearfix{display:block}.cmb_element .ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}
    23 .cmb_element .ui-state-disabled{cursor:default!important}.cmb_element .ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}
    24 .cmb_element .ui-widget-overlay{position:absolute;top:0;left:0;width:100%;height:100%}.cmb_element .ui-widget{font-family:Verdana,Arial,sans-serif;font-size:1.1em}
    25 .cmb_element .ui-widget .ui-widget{font-size:1em}.cmb_element .ui-widget input,.cmb_element .ui-widget select,.cmb_element .ui-widget textarea,.cmb_element .ui-widget button{font-family:Verdana,Arial,sans-serif;font-size:1em}
    26 .cmb_element .ui-widget-content{border:1px solid #aaa;background:#fff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x;color:#222}.cmb_element .ui-widget-content a{color:#222}
    27 .cmb_element .ui-widget-header{border:1px solid #aaa;background:#ccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x;color:#222;font-weight:bold}
    28 .cmb_element .ui-widget-header a{color:#222}.cmb_element .ui-state-default,.cmb_element .ui-widget-content .ui-state-default,.cmb_element .ui-widget-header .ui-state-default{border:1px solid #d3d3d3;background:#e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x;font-weight:normal;color:#555}
    29 .cmb_element .ui-state-default a,.cmb_element .ui-state-default a:link,.cmb_element .ui-state-default a:visited{color:#555;text-decoration:none}.cmb_element .ui-state-hover,.cmb_element .ui-widget-content .ui-state-hover,.cmb_element .ui-widget-header .ui-state-hover,.cmb_element .ui-state-focus,.cmb_element .ui-widget-content .ui-state-focus,.cmb_element .ui-widget-header .ui-state-focus{border:1px solid #999;background:#dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x;font-weight:normal;color:#212121}
    30 .cmb_element .ui-state-hover a,.cmb_element .ui-state-hover a:hover{color:#212121;text-decoration:none}.cmb_element .ui-state-active,.cmb_element .ui-widget-content .ui-state-active,.cmb_element .ui-widget-header .ui-state-active{border:1px solid #aaa;background:#fff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x;font-weight:normal;color:#212121}
    31 .cmb_element .ui-state-active a,.cmb_element .ui-state-active a:link,.cmb_element .ui-state-active a:visited{color:#212121;text-decoration:none}.cmb_element .ui-widget :active{outline:0}
    32 .cmb_element .ui-state-highlight,.cmb_element .ui-widget-content .ui-state-highlight,.cmb_element .ui-widget-header .ui-state-highlight{border:1px solid #fcefa1;background:#fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x;color:#363636}
    33 .cmb_element .ui-state-highlight a,.cmb_element .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.cmb_element .ui-state-error,.cmb_element .ui-widget-content .ui-state-error,.cmb_element .ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x;color:#cd0a0a}
    34 .cmb_element .ui-state-error a,.cmb_element .ui-widget-content .ui-state-error a,.cmb_element .ui-widget-header .ui-state-error a{color:#cd0a0a}.cmb_element .ui-state-error-text,.cmb_element .ui-widget-content .ui-state-error-text,.cmb_element .ui-widget-header .ui-state-error-text{color:#cd0a0a}
    35 .cmb_element .ui-priority-primary,.cmb_element .ui-widget-content .ui-priority-primary,.cmb_element .ui-widget-header .ui-priority-primary{font-weight:bold}
    36 .cmb_element .ui-priority-secondary,.cmb_element .ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}
    37 .cmb_element .ui-state-disabled,.cmb_element .ui-widget-content .ui-state-disabled,.cmb_element .ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}
    38 .cmb_element .ui-icon{width:16px;height:16px;background-image:url(images/ui-icons_222222_256x240.png)}.cmb_element .ui-widget-content .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}
    39 .cmb_element .ui-widget-header .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.cmb_element .ui-state-default .ui-icon{background-image:url(images/ui-icons_888888_256x240.png)}
    40 .cmb_element .ui-state-hover .ui-icon,.cmb_element .ui-state-focus .ui-icon{background-image:url(images/ui-icons_454545_256x240.png)}.cmb_element .ui-state-active .ui-icon{background-image:url(images/ui-icons_454545_256x240.png)}
    41 .cmb_element .ui-state-highlight .ui-icon{background-image:url(images/ui-icons_2e83ff_256x240.png)}.cmb_element .ui-state-error .ui-icon,.cmb_element .ui-state-error-text .ui-icon{background-image:url(images/ui-icons_cd0a0a_256x240.png)}
    42 .cmb_element .ui-icon-carat-1-n{background-position:0 0}.cmb_element .ui-icon-carat-1-ne{background-position:-16px 0}.cmb_element .ui-icon-carat-1-e{background-position:-32px 0}
    43 .cmb_element .ui-icon-carat-1-se{background-position:-48px 0}.cmb_element .ui-icon-carat-1-s{background-position:-64px 0}.cmb_element .ui-icon-carat-1-sw{background-position:-80px 0}
    44 .cmb_element .ui-icon-carat-1-w{background-position:-96px 0}.cmb_element .ui-icon-carat-1-nw{background-position:-112px 0}.cmb_element .ui-icon-carat-2-n-s{background-position:-128px 0}
    45 .cmb_element .ui-icon-carat-2-e-w{background-position:-144px 0}.cmb_element .ui-icon-triangle-1-n{background-position:0 -16px}.cmb_element .ui-icon-triangle-1-ne{background-position:-16px -16px}
    46 .cmb_element .ui-icon-triangle-1-e{background-position:-32px -16px}.cmb_element .ui-icon-triangle-1-se{background-position:-48px -16px}.cmb_element .ui-icon-triangle-1-s{background-position:-64px -16px}
    47 .cmb_element .ui-icon-triangle-1-sw{background-position:-80px -16px}.cmb_element .ui-icon-triangle-1-w{background-position:-96px -16px}.cmb_element .ui-icon-triangle-1-nw{background-position:-112px -16px}
    48 .cmb_element .ui-icon-triangle-2-n-s{background-position:-128px -16px}.cmb_element .ui-icon-triangle-2-e-w{background-position:-144px -16px}.cmb_element .ui-icon-arrow-1-n{background-position:0 -32px}
    49 .cmb_element .ui-icon-arrow-1-ne{background-position:-16px -32px}.cmb_element .ui-icon-arrow-1-e{background-position:-32px -32px}.cmb_element .ui-icon-arrow-1-se{background-position:-48px -32px}
    50 .cmb_element .ui-icon-arrow-1-s{background-position:-64px -32px}.cmb_element .ui-icon-arrow-1-sw{background-position:-80px -32px}.cmb_element .ui-icon-arrow-1-w{background-position:-96px -32px}
    51 .cmb_element .ui-icon-arrow-1-nw{background-position:-112px -32px}.cmb_element .ui-icon-arrow-2-n-s{background-position:-128px -32px}.cmb_element .ui-icon-arrow-2-ne-sw{background-position:-144px -32px}
    52 .cmb_element .ui-icon-arrow-2-e-w{background-position:-160px -32px}.cmb_element .ui-icon-arrow-2-se-nw{background-position:-176px -32px}.cmb_element .ui-icon-arrowstop-1-n{background-position:-192px -32px}
    53 .cmb_element .ui-icon-arrowstop-1-e{background-position:-208px -32px}.cmb_element .ui-icon-arrowstop-1-s{background-position:-224px -32px}.cmb_element .ui-icon-arrowstop-1-w{background-position:-240px -32px}
    54 .cmb_element .ui-icon-arrowthick-1-n{background-position:0 -48px}.cmb_element .ui-icon-arrowthick-1-ne{background-position:-16px -48px}.cmb_element .ui-icon-arrowthick-1-e{background-position:-32px -48px}
    55 .cmb_element .ui-icon-arrowthick-1-se{background-position:-48px -48px}.cmb_element .ui-icon-arrowthick-1-s{background-position:-64px -48px}.cmb_element .ui-icon-arrowthick-1-sw{background-position:-80px -48px}
    56 .cmb_element .ui-icon-arrowthick-1-w{background-position:-96px -48px}.cmb_element .ui-icon-arrowthick-1-nw{background-position:-112px -48px}.cmb_element .ui-icon-arrowthick-2-n-s{background-position:-128px -48px}
    57 .cmb_element .ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.cmb_element .ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.cmb_element .ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}
    58 .cmb_element .ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.cmb_element .ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.cmb_element .ui-icon-arrowthickstop-1-s{background-position:-224px -48px}
    59 .cmb_element .ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.cmb_element .ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.cmb_element .ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}
    60 .cmb_element .ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.cmb_element .ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}
    61 .cmb_element .ui-icon-arrowreturn-1-w{background-position:-64px -64px}.cmb_element .ui-icon-arrowreturn-1-n{background-position:-80px -64px}.cmb_element .ui-icon-arrowreturn-1-e{background-position:-96px -64px}
    62 .cmb_element .ui-icon-arrowreturn-1-s{background-position:-112px -64px}.cmb_element .ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.cmb_element .ui-icon-arrowrefresh-1-n{background-position:-144px -64px}
    63 .cmb_element .ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.cmb_element .ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.cmb_element .ui-icon-arrow-4{background-position:0 -80px}
    64 .cmb_element .ui-icon-arrow-4-diag{background-position:-16px -80px}.cmb_element .ui-icon-extlink{background-position:-32px -80px}.cmb_element .ui-icon-newwin{background-position:-48px -80px}
    65 .cmb_element .ui-icon-refresh{background-position:-64px -80px}.cmb_element .ui-icon-shuffle{background-position:-80px -80px}.cmb_element .ui-icon-transfer-e-w{background-position:-96px -80px}
    66 .cmb_element .ui-icon-transferthick-e-w{background-position:-112px -80px}.cmb_element .ui-icon-folder-collapsed{background-position:0 -96px}.cmb_element .ui-icon-folder-open{background-position:-16px -96px}
    67 .cmb_element .ui-icon-document{background-position:-32px -96px}.cmb_element .ui-icon-document-b{background-position:-48px -96px}.cmb_element .ui-icon-note{background-position:-64px -96px}
    68 .cmb_element .ui-icon-mail-closed{background-position:-80px -96px}.cmb_element .ui-icon-mail-open{background-position:-96px -96px}.cmb_element .ui-icon-suitcase{background-position:-112px -96px}
    69 .cmb_element .ui-icon-comment{background-position:-128px -96px}.cmb_element .ui-icon-person{background-position:-144px -96px}.cmb_element .ui-icon-print{background-position:-160px -96px}
    70 .cmb_element .ui-icon-trash{background-position:-176px -96px}.cmb_element .ui-icon-locked{background-position:-192px -96px}.cmb_element .ui-icon-unlocked{background-position:-208px -96px}
    71 .cmb_element .ui-icon-bookmark{background-position:-224px -96px}.cmb_element .ui-icon-tag{background-position:-240px -96px}.cmb_element .ui-icon-home{background-position:0 -112px}
    72 .cmb_element .ui-icon-flag{background-position:-16px -112px}.cmb_element .ui-icon-calendar{background-position:-32px -112px}.cmb_element .ui-icon-cart{background-position:-48px -112px}
    73 .cmb_element .ui-icon-pencil{background-position:-64px -112px}.cmb_element .ui-icon-clock{background-position:-80px -112px}.cmb_element .ui-icon-disk{background-position:-96px -112px}
    74 .cmb_element .ui-icon-calculator{background-position:-112px -112px}.cmb_element .ui-icon-zoomin{background-position:-128px -112px}.cmb_element .ui-icon-zoomout{background-position:-144px -112px}
    75 .cmb_element .ui-icon-search{background-position:-160px -112px}.cmb_element .ui-icon-wrench{background-position:-176px -112px}.cmb_element .ui-icon-gear{background-position:-192px -112px}
    76 .cmb_element .ui-icon-heart{background-position:-208px -112px}.cmb_element .ui-icon-star{background-position:-224px -112px}.cmb_element .ui-icon-link{background-position:-240px -112px}
    77 .cmb_element .ui-icon-cancel{background-position:0 -128px}.cmb_element .ui-icon-plus{background-position:-16px -128px}.cmb_element .ui-icon-plusthick{background-position:-32px -128px}
    78 .cmb_element .ui-icon-minus{background-position:-48px -128px}.cmb_element .ui-icon-minusthick{background-position:-64px -128px}.cmb_element .ui-icon-close{background-position:-80px -128px}
    79 .cmb_element .ui-icon-closethick{background-position:-96px -128px}.cmb_element .ui-icon-key{background-position:-112px -128px}.cmb_element .ui-icon-lightbulb{background-position:-128px -128px}
    80 .cmb_element .ui-icon-scissors{background-position:-144px -128px}.cmb_element .ui-icon-clipboard{background-position:-160px -128px}.cmb_element .ui-icon-copy{background-position:-176px -128px}
    81 .cmb_element .ui-icon-contact{background-position:-192px -128px}.cmb_element .ui-icon-image{background-position:-208px -128px}.cmb_element .ui-icon-video{background-position:-224px -128px}
    82 .cmb_element .ui-icon-script{background-position:-240px -128px}.cmb_element .ui-icon-alert{background-position:0 -144px}.cmb_element .ui-icon-info{background-position:-16px -144px}
    83 .cmb_element .ui-icon-notice{background-position:-32px -144px}.cmb_element .ui-icon-help{background-position:-48px -144px}.cmb_element .ui-icon-check{background-position:-64px -144px}
    84 .cmb_element .ui-icon-bullet{background-position:-80px -144px}.cmb_element .ui-icon-radio-off{background-position:-96px -144px}.cmb_element .ui-icon-radio-on{background-position:-112px -144px}
    85 .cmb_element .ui-icon-pin-w{background-position:-128px -144px}.cmb_element .ui-icon-pin-s{background-position:-144px -144px}.cmb_element .ui-icon-play{background-position:0 -160px}
    86 .cmb_element .ui-icon-pause{background-position:-16px -160px}.cmb_element .ui-icon-seek-next{background-position:-32px -160px}.cmb_element .ui-icon-seek-prev{background-position:-48px -160px}
    87 .cmb_element .ui-icon-seek-end{background-position:-64px -160px}.cmb_element .ui-icon-seek-start{background-position:-80px -160px}.cmb_element .ui-icon-seek-first{background-position:-80px -160px}
    88 .cmb_element .ui-icon-stop{background-position:-96px -160px}.cmb_element .ui-icon-eject{background-position:-112px -160px}.cmb_element .ui-icon-volume-off{background-position:-128px -160px}
    89 .cmb_element .ui-icon-volume-on{background-position:-144px -160px}.cmb_element .ui-icon-power{background-position:0 -176px}.cmb_element .ui-icon-signal-diag{background-position:-16px -176px}
    90 .cmb_element .ui-icon-signal{background-position:-32px -176px}.cmb_element .ui-icon-battery-0{background-position:-48px -176px}.cmb_element .ui-icon-battery-1{background-position:-64px -176px}
    91 .cmb_element .ui-icon-battery-2{background-position:-80px -176px}.cmb_element .ui-icon-battery-3{background-position:-96px -176px}.cmb_element .ui-icon-circle-plus{background-position:0 -192px}
    92 .cmb_element .ui-icon-circle-minus{background-position:-16px -192px}.cmb_element .ui-icon-circle-close{background-position:-32px -192px}.cmb_element .ui-icon-circle-triangle-e{background-position:-48px -192px}
    93 .cmb_element .ui-icon-circle-triangle-s{background-position:-64px -192px}.cmb_element .ui-icon-circle-triangle-w{background-position:-80px -192px}.cmb_element .ui-icon-circle-triangle-n{background-position:-96px -192px}
    94 .cmb_element .ui-icon-circle-arrow-e{background-position:-112px -192px}.cmb_element .ui-icon-circle-arrow-s{background-position:-128px -192px}.cmb_element .ui-icon-circle-arrow-w{background-position:-144px -192px}
    95 .cmb_element .ui-icon-circle-arrow-n{background-position:-160px -192px}.cmb_element .ui-icon-circle-zoomin{background-position:-176px -192px}.cmb_element .ui-icon-circle-zoomout{background-position:-192px -192px}
    96 .cmb_element .ui-icon-circle-check{background-position:-208px -192px}.cmb_element .ui-icon-circlesmall-plus{background-position:0 -208px}.cmb_element .ui-icon-circlesmall-minus{background-position:-16px -208px}
    97 .cmb_element .ui-icon-circlesmall-close{background-position:-32px -208px}.cmb_element .ui-icon-squaresmall-plus{background-position:-48px -208px}.cmb_element .ui-icon-squaresmall-minus{background-position:-64px -208px}
    98 .cmb_element .ui-icon-squaresmall-close{background-position:-80px -208px}.cmb_element .ui-icon-grip-dotted-vertical{background-position:0 -224px}.cmb_element .ui-icon-grip-dotted-horizontal{background-position:-16px -224px}
    99 .cmb_element .ui-icon-grip-solid-vertical{background-position:-32px -224px}.cmb_element .ui-icon-grip-solid-horizontal{background-position:-48px -224px}
    100 .cmb_element .ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.cmb_element .ui-icon-grip-diagonal-se{background-position:-80px -224px}.cmb_element .ui-corner-all,.cmb_element .ui-corner-top,.cmb_element .ui-corner-left,.cmb_element .ui-corner-tl{-moz-border-radius-topleft:4px;-webkit-border-top-left-radius:4px;-khtml-border-top-left-radius:4px;border-top-left-radius:4px}
    101 .cmb_element .ui-corner-all,.cmb_element .ui-corner-top,.cmb_element .ui-corner-right,.cmb_element .ui-corner-tr{-moz-border-radius-topright:4px;-webkit-border-top-right-radius:4px;-khtml-border-top-right-radius:4px;border-top-right-radius:4px}
    102 .cmb_element .ui-corner-all,.cmb_element .ui-corner-bottom,.cmb_element .ui-corner-left,.cmb_element .ui-corner-bl{-moz-border-radius-bottomleft:4px;-webkit-border-bottom-left-radius:4px;-khtml-border-bottom-left-radius:4px;border-bottom-left-radius:4px}
    103 .cmb_element .ui-corner-all,.cmb_element .ui-corner-bottom,.cmb_element .ui-corner-right,.cmb_element .ui-corner-br{-moz-border-radius-bottomright:4px;-webkit-border-bottom-right-radius:4px;-khtml-border-bottom-right-radius:4px;border-bottom-right-radius:4px}
    104 .cmb_element .ui-widget-overlay{background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.30;filter:Alpha(Opacity=30)}.cmb_element .ui-widget-shadow{margin:-8px 0 0 -8px;padding:8px;background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.30;filter:Alpha(Opacity=30);-moz-border-radius:8px;-khtml-border-radius:8px;-webkit-border-radius:8px;border-radius:8px}
    105 .cmb_element .ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.cmb_element .ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}
    106 .cmb_element .ui-datepicker .ui-datepicker-prev,.cmb_element .ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.cmb_element .ui-datepicker .ui-datepicker-prev-hover,.cmb_element .ui-datepicker .ui-datepicker-next-hover{top:1px}
    107 .cmb_element .ui-datepicker .ui-datepicker-prev{left:2px}.cmb_element .ui-datepicker .ui-datepicker-next{right:2px}.cmb_element .ui-datepicker .ui-datepicker-prev-hover{left:1px}
    108 .cmb_element .ui-datepicker .ui-datepicker-next-hover{right:1px}.cmb_element .ui-datepicker .ui-datepicker-prev span,.cmb_element .ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}
    109 .cmb_element .ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.cmb_element .ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}
    110 .cmb_element .ui-datepicker select.ui-datepicker-month-year{width:100%}.cmb_element .ui-datepicker select.ui-datepicker-month,.cmb_element .ui-datepicker select.ui-datepicker-year{width:49%}
    111 .cmb_element .ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.cmb_element .ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}
    112 .cmb_element .ui-datepicker td{border:0;padding:1px}.cmb_element .ui-datepicker td span,.cmb_element .ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}
    113 .cmb_element .ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}
    114 .cmb_element .ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}
    115 .cmb_element .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.cmb_element .ui-datepicker.ui-datepicker-multi{width:auto}
    116 .cmb_element .ui-datepicker-multi .ui-datepicker-group{float:left}.cmb_element .ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}
    117 .cmb_element .ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.cmb_element .ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.cmb_element .ui-datepicker-multi-4 .ui-datepicker-group{width:25%}
    118 .cmb_element .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header{border-left-width:0}.cmb_element .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}
    119 .cmb_element .ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.cmb_element .ui-datepicker-row-break{clear:both;width:100%;font-size:0}.cmb_element .ui-datepicker-rtl{direction:rtl}
    120 .cmb_element .ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.cmb_element .ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.cmb_element .ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}
    121 .cmb_element .ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.cmb_element .ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.cmb_element .ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}
    122 .cmb_element .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current{float:right}.cmb_element .ui-datepicker-rtl .ui-datepicker-group{float:right}
    123 .cmb_element .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header{border-right-width:0;border-left-width:1px}.cmb_element .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}
    124 .cmb_element .ui-datepicker-cover{display:none;display:block;position:absolute;z-index:-1;filter:mask();top:-4px;left:-4px;width:200px;height:200px}
     1table.cmb_metabox{clear:both}.post-new-php table.cmb_metabox .cmb-nested-table td,.post-new-php table.cmb_metabox .repeatable-group th,.post-new-php table.cmb_metabox .repeatable-group:first-of-type,.post-php table.cmb_metabox .cmb-nested-table td,.post-php table.cmb_metabox .repeatable-group th,.post-php table.cmb_metabox .repeatable-group:first-of-type,table.cmb_metabox tbody>tr:first-of-type>td,table.cmb_metabox tbody>tr:first-of-type>th,table.cmb_metabox>tr:first-of-type>td,table.cmb_metabox>tr:first-of-type>th{border:0}.post-new-php table.cmb_metabox .repeatable-group,.post-new-php table.cmb_metabox td,.post-new-php table.cmb_metabox th,.post-php table.cmb_metabox .repeatable-group,.post-php table.cmb_metabox td,.post-php table.cmb_metabox th{border-top:1px solid #E9E9E9}.repeatable-group th{padding:5px}.repeatable-group .shift-rows{text-decoration:none;margin-right:5px;font-size:1.2em}.repeatable-group .cmb_upload_button{float:right}#poststuff .repeatable-group h2{margin:0}.cmb-group-title h4{font-size:1.2em;font-weight:500;border-bottom:1px solid #ddd}.post-new-php table.cmb_metabox th,.post-php table.cmb_metabox th{text-align:right;font-weight:700}.post-new-php table.cmb_metabox table th,.post-php table.cmb_metabox table th{text-align:left}table.cmb_metabox th label{margin-top:5px;display:block}p.cmb_metabox_description{color:#AAA;font-style:italic;margin:2px 0!important}span.cmb_metabox_description{color:#AAA;font-style:italic}table.cmb_metabox input,table.cmb_metabox textarea{font-size:14px;padding:5px}table.cmb_metabox input[type=text],table.cmb_metabox textarea{width:97%}table.cmb_metabox textarea.cmb_textarea_code{font-family:Consolas,Monaco,monospace;line-height:16px}table.cmb_metabox input.cmb_text_small,table.cmb_metabox input.cmb_timepicker{width:100px;margin-right:15px}table.cmb_metabox input.cmb_text_money{width:90px;margin-right:15px}table.cmb_metabox input.cmb_text_medium{width:230px;margin-right:15px}table.cmb_metabox input.cmb_upload_file{width:65%}table.cmb_metabox input.ed_button{padding:2px 4px}table.cmb_metabox li{font-size:14px;margin:1px 0 5px;line-height:16px}table.cmb_metabox ul{padding-top:5px;margin:0}table.cmb_metabox select{font-size:14px;margin-top:3px}table.cmb_metabox input:focus,table.cmb_metabox textarea:focus{background:#fffff8}.cmb_metabox_title{margin:0 0 5px;padding:5px 0 0}.edit-tags-php .cmb_metabox_title,.profile-php .cmb_metabox_title,.user-edit-php .cmb_metabox_title{margin-left:-10px}.cmb-inline ul{padding:4px 0 0}.cmb-inline li{display:inline-block;padding-right:18px}table.cmb_metabox input[type=checkbox],table.cmb_metabox input[type=radio]{margin:0 5px 0 0;padding:0}table.cmb_metabox .mceLayout{border:1px solid #DFDFDF!important}table.cmb_metabox .mceIframeContainer{background:#FFF}table.cmb_metabox .meta_mce{width:97%}table.cmb_metabox .meta_mce textarea{width:100%}table.cmb_metabox .cmb_media_status{margin:10px 0 0}table.cmb_metabox .cmb_media_status .img_status{clear:none;float:left;display:inline-block;margin-right:10px;width:auto}table.cmb_metabox .cmb-type-file_list .cmb_media_status .img_status{clear:none;float:left;margin-right:10px;width:auto}table.cmb_metabox .cmb_media_status .embed_status,table.cmb_metabox .cmb_media_status .img_status{position:relative}table.cmb_metabox .cmb_media_status .embed_status,table.cmb_metabox .cmb_media_status .img_status img{border:1px solid #DFDFDF;background:#FAFAFA;max-width:350px;padding:5px;-moz-border-radius:2px;border-radius:2px}table.cmb_metabox .cmb_media_status .embed_status{float:left;max-width:800px}table.cmb_metabox .cmb_media_status .embed_status .cmb_remove_file_button,table.cmb_metabox .cmb_media_status .img_status .cmb_remove_file_button{text-indent:-9999px;background:url(images/ico-delete.png);width:16px;height:16px;position:absolute;top:-5px;left:-5px}table.cmb_metabox .attach_list li{clear:both;display:inline-block;margin-bottom:25px;width:100%}table.cmb_metabox .attach_list li img{float:left;margin-right:10px}#side-sortables table.cmb_metabox input[type=text],.inner-sidebar table.cmb_metabox input[type=text],table.cmb_metabox textarea{width:95%}#side-sortables table.cmb_metabox .cmb_media_status .embed_status img,#side-sortables table.cmb_metabox .cmb_media_status .img_status img,.inner-sidebar table.cmb_metabox .cmb_media_status .embed_status img,.inner-sidebar table.cmb_metabox .cmb_media_status .img_status img{width:90%}#side-sortables table.cmb_metabox label,.inner-sidebar table.cmb_metabox label{display:block;font-weight:700;padding:0 0 5px}#side-sortables table.cmb_metabox .cmb_list label,.inner-sidebar table.cmb_metabox .cmb_list label{display:inline;font-weight:400}#side-sortables table.cmb_metabox .cmb_metabox_description,.inner-sidebar table.cmb_metabox .cmb_metabox_description{display:block;padding:7px 0 0}#side-sortables table.cmb_metabox .cmb_metabox_title,.inner-sidebar table.cmb_metabox .cmb_metabox_title{font-size:1.2em;font-style:italic}.postbox table.cmb_metabox .cmb-spinner{float:left}table.cmb_metabox .wp-color-result,table.cmb_metabox .wp-picker-input-wrap{vertical-align:middle}table.cmb_metabox .wp-color-result,table.cmb_metabox .wp-picker-container{margin:0 10px 0 0}div.time-picker{position:absolute;height:191px;width:6em;overflow:auto;background:#fff;border:1px solid #aaa;z-index:99;margin:0}div.time-picker-12hours{width:8em}div.time-picker ul{list-style-type:none;margin:0;padding:0}div.time-picker li{cursor:pointer;height:10px;font:14px/1 Helvetica,Arial,sans-serif;padding:4px 3px}div.time-picker li.selected{background:#0063CE;color:#fff}.cmb_element .ui-helper-hidden{display:none}.cmb_element .ui-helper-hidden-accessible{position:absolute!important;clip:rect(1px 1px 1px 1px);clip:rect(1px,1px,1px,1px)}.cmb_element .ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.cmb_element .ui-helper-clearfix:after{content:".";display:block;height:0;clear:both;visibility:hidden}* html .ui-helper-clearfix{height:1%}.cmb_element .ui-helper-clearfix{display:block}.cmb_element .ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.cmb_element .ui-state-disabled{cursor:default!important}.cmb_element .ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.cmb_element .ui-widget-overlay{position:absolute;top:0;left:0;width:100%;height:100%}.cmb_element .ui-widget{font-family:Verdana,Arial,sans-serif;font-size:1.1em}.cmb_element .ui-widget .ui-widget{font-size:1em}.cmb_element .ui-widget button,.cmb_element .ui-widget input,.cmb_element .ui-widget select,.cmb_element .ui-widget textarea{font-family:Verdana,Arial,sans-serif;font-size:1em}.cmb_element .ui-widget-content{border:1px solid #aaa;background:#fff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x;color:#222}.cmb_element .ui-widget-content a{color:#222}.cmb_element .ui-widget-header{border:1px solid #aaa;background:#ccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x;color:#222;font-weight:700}.cmb_element .ui-widget-header a{color:#222}.cmb_element .ui-state-default,.cmb_element .ui-widget-content .ui-state-default,.cmb_element .ui-widget-header .ui-state-default{border:1px solid #d3d3d3;background:#e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x;font-weight:400;color:#555}.cmb_element .ui-state-default a,.cmb_element .ui-state-default a:link,.cmb_element .ui-state-default a:visited{color:#555;text-decoration:none}.cmb_element .ui-state-focus,.cmb_element .ui-state-hover,.cmb_element .ui-widget-content .ui-state-focus,.cmb_element .ui-widget-content .ui-state-hover,.cmb_element .ui-widget-header .ui-state-focus,.cmb_element .ui-widget-header .ui-state-hover{border:1px solid #999;background:#dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x;font-weight:400;color:#212121}.cmb_element .ui-state-hover a,.cmb_element .ui-state-hover a:hover{color:#212121;text-decoration:none}.cmb_element .ui-state-active,.cmb_element .ui-widget-content .ui-state-active,.cmb_element .ui-widget-header .ui-state-active{border:1px solid #aaa;background:#fff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x;font-weight:400;color:#212121}.cmb_element .ui-state-active a,.cmb_element .ui-state-active a:link,.cmb_element .ui-state-active a:visited{color:#212121;text-decoration:none}.cmb_element .ui-widget :active{outline:0}.cmb_element .ui-state-highlight,.cmb_element .ui-widget-content .ui-state-highlight,.cmb_element .ui-widget-header .ui-state-highlight{border:1px solid #fcefa1;background:#fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x;color:#363636}.cmb_element .ui-state-highlight a,.cmb_element .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.cmb_element .ui-state-error,.cmb_element .ui-widget-content .ui-state-error,.cmb_element .ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x;color:#cd0a0a}.cmb_element .ui-state-error a,.cmb_element .ui-state-error-text,.cmb_element .ui-widget-content .ui-state-error a,.cmb_element .ui-widget-content .ui-state-error-text,.cmb_element .ui-widget-header .ui-state-error a,.cmb_element .ui-widget-header .ui-state-error-text{color:#cd0a0a}.cmb_element .ui-priority-primary,.cmb_element .ui-widget-content .ui-priority-primary,.cmb_element .ui-widget-header .ui-priority-primary{font-weight:700}.cmb_element .ui-priority-secondary,.cmb_element .ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:400}.cmb_element .ui-state-disabled,.cmb_element .ui-widget-content .ui-state-disabled,.cmb_element .ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.cmb_element .ui-icon{width:16px;height:16px;background-image:url(images/ui-icons_222222_256x240.png)}.cmb_element .ui-widget-content .ui-icon,.cmb_element .ui-widget-header .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.cmb_element .ui-state-default .ui-icon{background-image:url(images/ui-icons_888888_256x240.png)}.cmb_element .ui-state-active .ui-icon,.cmb_element .ui-state-focus .ui-icon,.cmb_element .ui-state-hover .ui-icon{background-image:url(images/ui-icons_454545_256x240.png)}.cmb_element .ui-state-highlight .ui-icon{background-image:url(images/ui-icons_2e83ff_256x240.png)}.cmb_element .ui-state-error .ui-icon,.cmb_element .ui-state-error-text .ui-icon{background-image:url(images/ui-icons_cd0a0a_256x240.png)}.cmb_element .ui-icon-carat-1-n{background-position:0 0}.cmb_element .ui-icon-carat-1-ne{background-position:-16px 0}.cmb_element .ui-icon-carat-1-e{background-position:-32px 0}.cmb_element .ui-icon-carat-1-se{background-position:-48px 0}.cmb_element .ui-icon-carat-1-s{background-position:-64px 0}.cmb_element .ui-icon-carat-1-sw{background-position:-80px 0}.cmb_element .ui-icon-carat-1-w{background-position:-96px 0}.cmb_element .ui-icon-carat-1-nw{background-position:-112px 0}.cmb_element .ui-icon-carat-2-n-s{background-position:-128px 0}.cmb_element .ui-icon-carat-2-e-w{background-position:-144px 0}.cmb_element .ui-icon-triangle-1-n{background-position:0 -16px}.cmb_element .ui-icon-triangle-1-ne{background-position:-16px -16px}.cmb_element .ui-icon-triangle-1-e{background-position:-32px -16px}.cmb_element .ui-icon-triangle-1-se{background-position:-48px -16px}.cmb_element .ui-icon-triangle-1-s{background-position:-64px -16px}.cmb_element .ui-icon-triangle-1-sw{background-position:-80px -16px}.cmb_element .ui-icon-triangle-1-w{background-position:-96px -16px}.cmb_element .ui-icon-triangle-1-nw{background-position:-112px -16px}.cmb_element .ui-icon-triangle-2-n-s{background-position:-128px -16px}.cmb_element .ui-icon-triangle-2-e-w{background-position:-144px -16px}.cmb_element .ui-icon-arrow-1-n{background-position:0 -32px}.cmb_element .ui-icon-arrow-1-ne{background-position:-16px -32px}.cmb_element .ui-icon-arrow-1-e{background-position:-32px -32px}.cmb_element .ui-icon-arrow-1-se{background-position:-48px -32px}.cmb_element .ui-icon-arrow-1-s{background-position:-64px -32px}.cmb_element .ui-icon-arrow-1-sw{background-position:-80px -32px}.cmb_element .ui-icon-arrow-1-w{background-position:-96px -32px}.cmb_element .ui-icon-arrow-1-nw{background-position:-112px -32px}.cmb_element .ui-icon-arrow-2-n-s{background-position:-128px -32px}.cmb_element .ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.cmb_element .ui-icon-arrow-2-e-w{background-position:-160px -32px}.cmb_element .ui-icon-arrow-2-se-nw{background-position:-176px -32px}.cmb_element .ui-icon-arrowstop-1-n{background-position:-192px -32px}.cmb_element .ui-icon-arrowstop-1-e{background-position:-208px -32px}.cmb_element .ui-icon-arrowstop-1-s{background-position:-224px -32px}.cmb_element .ui-icon-arrowstop-1-w{background-position:-240px -32px}.cmb_element .ui-icon-arrowthick-1-n{background-position:0 -48px}.cmb_element .ui-icon-arrowthick-1-ne{background-position:-16px -48px}.cmb_element .ui-icon-arrowthick-1-e{background-position:-32px -48px}.cmb_element .ui-icon-arrowthick-1-se{background-position:-48px -48px}.cmb_element .ui-icon-arrowthick-1-s{background-position:-64px -48px}.cmb_element .ui-icon-arrowthick-1-sw{background-position:-80px -48px}.cmb_element .ui-icon-arrowthick-1-w{background-position:-96px -48px}.cmb_element .ui-icon-arrowthick-1-nw{background-position:-112px -48px}.cmb_element .ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.cmb_element .ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.cmb_element .ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.cmb_element .ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.cmb_element .ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.cmb_element .ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.cmb_element .ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.cmb_element .ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.cmb_element .ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.cmb_element .ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.cmb_element .ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.cmb_element .ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.cmb_element .ui-icon-arrowreturn-1-w{background-position:-64px -64px}.cmb_element .ui-icon-arrowreturn-1-n{background-position:-80px -64px}.cmb_element .ui-icon-arrowreturn-1-e{background-position:-96px -64px}.cmb_element .ui-icon-arrowreturn-1-s{background-position:-112px -64px}.cmb_element .ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.cmb_element .ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.cmb_element .ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.cmb_element .ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.cmb_element .ui-icon-arrow-4{background-position:0 -80px}.cmb_element .ui-icon-arrow-4-diag{background-position:-16px -80px}.cmb_element .ui-icon-extlink{background-position:-32px -80px}.cmb_element .ui-icon-newwin{background-position:-48px -80px}.cmb_element .ui-icon-refresh{background-position:-64px -80px}.cmb_element .ui-icon-shuffle{background-position:-80px -80px}.cmb_element .ui-icon-transfer-e-w{background-position:-96px -80px}.cmb_element .ui-icon-transferthick-e-w{background-position:-112px -80px}.cmb_element .ui-icon-folder-collapsed{background-position:0 -96px}.cmb_element .ui-icon-folder-open{background-position:-16px -96px}.cmb_element .ui-icon-document{background-position:-32px -96px}.cmb_element .ui-icon-document-b{background-position:-48px -96px}.cmb_element .ui-icon-note{background-position:-64px -96px}.cmb_element .ui-icon-mail-closed{background-position:-80px -96px}.cmb_element .ui-icon-mail-open{background-position:-96px -96px}.cmb_element .ui-icon-suitcase{background-position:-112px -96px}.cmb_element .ui-icon-comment{background-position:-128px -96px}.cmb_element .ui-icon-person{background-position:-144px -96px}.cmb_element .ui-icon-print{background-position:-160px -96px}.cmb_element .ui-icon-trash{background-position:-176px -96px}.cmb_element .ui-icon-locked{background-position:-192px -96px}.cmb_element .ui-icon-unlocked{background-position:-208px -96px}.cmb_element .ui-icon-bookmark{background-position:-224px -96px}.cmb_element .ui-icon-tag{background-position:-240px -96px}.cmb_element .ui-icon-home{background-position:0 -112px}.cmb_element .ui-icon-flag{background-position:-16px -112px}.cmb_element .ui-icon-calendar{background-position:-32px -112px}.cmb_element .ui-icon-cart{background-position:-48px -112px}.cmb_element .ui-icon-pencil{background-position:-64px -112px}.cmb_element .ui-icon-clock{background-position:-80px -112px}.cmb_element .ui-icon-disk{background-position:-96px -112px}.cmb_element .ui-icon-calculator{background-position:-112px -112px}.cmb_element .ui-icon-zoomin{background-position:-128px -112px}.cmb_element .ui-icon-zoomout{background-position:-144px -112px}.cmb_element .ui-icon-search{background-position:-160px -112px}.cmb_element .ui-icon-wrench{background-position:-176px -112px}.cmb_element .ui-icon-gear{background-position:-192px -112px}.cmb_element .ui-icon-heart{background-position:-208px -112px}.cmb_element .ui-icon-star{background-position:-224px -112px}.cmb_element .ui-icon-link{background-position:-240px -112px}.cmb_element .ui-icon-cancel{background-position:0 -128px}.cmb_element .ui-icon-plus{background-position:-16px -128px}.cmb_element .ui-icon-plusthick{background-position:-32px -128px}.cmb_element .ui-icon-minus{background-position:-48px -128px}.cmb_element .ui-icon-minusthick{background-position:-64px -128px}.cmb_element .ui-icon-close{background-position:-80px -128px}.cmb_element .ui-icon-closethick{background-position:-96px -128px}.cmb_element .ui-icon-key{background-position:-112px -128px}.cmb_element .ui-icon-lightbulb{background-position:-128px -128px}.cmb_element .ui-icon-scissors{background-position:-144px -128px}.cmb_element .ui-icon-clipboard{background-position:-160px -128px}.cmb_element .ui-icon-copy{background-position:-176px -128px}.cmb_element .ui-icon-contact{background-position:-192px -128px}.cmb_element .ui-icon-image{background-position:-208px -128px}.cmb_element .ui-icon-video{background-position:-224px -128px}.cmb_element .ui-icon-script{background-position:-240px -128px}.cmb_element .ui-icon-alert{background-position:0 -144px}.cmb_element .ui-icon-info{background-position:-16px -144px}.cmb_element .ui-icon-notice{background-position:-32px -144px}.cmb_element .ui-icon-help{background-position:-48px -144px}.cmb_element .ui-icon-check{background-position:-64px -144px}.cmb_element .ui-icon-bullet{background-position:-80px -144px}.cmb_element .ui-icon-radio-off{background-position:-96px -144px}.cmb_element .ui-icon-radio-on{background-position:-112px -144px}.cmb_element .ui-icon-pin-w{background-position:-128px -144px}.cmb_element .ui-icon-pin-s{background-position:-144px -144px}.cmb_element .ui-icon-play{background-position:0 -160px}.cmb_element .ui-icon-pause{background-position:-16px -160px}.cmb_element .ui-icon-seek-next{background-position:-32px -160px}.cmb_element .ui-icon-seek-prev{background-position:-48px -160px}.cmb_element .ui-icon-seek-end{background-position:-64px -160px}.cmb_element .ui-icon-seek-first,.cmb_element .ui-icon-seek-start{background-position:-80px -160px}.cmb_element .ui-icon-stop{background-position:-96px -160px}.cmb_element .ui-icon-eject{background-position:-112px -160px}.cmb_element .ui-icon-volume-off{background-position:-128px -160px}.cmb_element .ui-icon-volume-on{background-position:-144px -160px}.cmb_element .ui-icon-power{background-position:0 -176px}.cmb_element .ui-icon-signal-diag{background-position:-16px -176px}.cmb_element .ui-icon-signal{background-position:-32px -176px}.cmb_element .ui-icon-battery-0{background-position:-48px -176px}.cmb_element .ui-icon-battery-1{background-position:-64px -176px}.cmb_element .ui-icon-battery-2{background-position:-80px -176px}.cmb_element .ui-icon-battery-3{background-position:-96px -176px}.cmb_element .ui-icon-circle-plus{background-position:0 -192px}.cmb_element .ui-icon-circle-minus{background-position:-16px -192px}.cmb_element .ui-icon-circle-close{background-position:-32px -192px}.cmb_element .ui-icon-circle-triangle-e{background-position:-48px -192px}.cmb_element .ui-icon-circle-triangle-s{background-position:-64px -192px}.cmb_element .ui-icon-circle-triangle-w{background-position:-80px -192px}.cmb_element .ui-icon-circle-triangle-n{background-position:-96px -192px}.cmb_element .ui-icon-circle-arrow-e{background-position:-112px -192px}.cmb_element .ui-icon-circle-arrow-s{background-position:-128px -192px}.cmb_element .ui-icon-circle-arrow-w{background-position:-144px -192px}.cmb_element .ui-icon-circle-arrow-n{background-position:-160px -192px}.cmb_element .ui-icon-circle-zoomin{background-position:-176px -192px}.cmb_element .ui-icon-circle-zoomout{background-position:-192px -192px}.cmb_element .ui-icon-circle-check{background-position:-208px -192px}.cmb_element .ui-icon-circlesmall-plus{background-position:0 -208px}.cmb_element .ui-icon-circlesmall-minus{background-position:-16px -208px}.cmb_element .ui-icon-circlesmall-close{background-position:-32px -208px}.cmb_element .ui-icon-squaresmall-plus{background-position:-48px -208px}.cmb_element .ui-icon-squaresmall-minus{background-position:-64px -208px}.cmb_element .ui-icon-squaresmall-close{background-position:-80px -208px}.cmb_element .ui-icon-grip-dotted-vertical{background-position:0 -224px}.cmb_element .ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.cmb_element .ui-icon-grip-solid-vertical{background-position:-32px -224px}.cmb_element .ui-icon-grip-solid-horizontal{background-position:-48px -224px}.cmb_element .ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.cmb_element .ui-icon-grip-diagonal-se{background-position:-80px -224px}.cmb_element .ui-corner-all,.cmb_element .ui-corner-left,.cmb_element .ui-corner-tl,.cmb_element .ui-corner-top{-moz-border-radius-topleft:4px;-webkit-border-top-left-radius:4px;-khtml-border-top-left-radius:4px;border-top-left-radius:4px}.cmb_element .ui-corner-all,.cmb_element .ui-corner-right,.cmb_element .ui-corner-top,.cmb_element .ui-corner-tr{-moz-border-radius-topright:4px;-webkit-border-top-right-radius:4px;-khtml-border-top-right-radius:4px;border-top-right-radius:4px}.cmb_element .ui-corner-all,.cmb_element .ui-corner-bl,.cmb_element .ui-corner-bottom,.cmb_element .ui-corner-left{-moz-border-radius-bottomleft:4px;-webkit-border-bottom-left-radius:4px;-khtml-border-bottom-left-radius:4px;border-bottom-left-radius:4px}.cmb_element .ui-corner-all,.cmb_element .ui-corner-bottom,.cmb_element .ui-corner-br,.cmb_element .ui-corner-right{-moz-border-radius-bottomright:4px;-webkit-border-bottom-right-radius:4px;-khtml-border-bottom-right-radius:4px;border-bottom-right-radius:4px}.cmb_element .ui-widget-overlay{background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30)}.cmb_element .ui-widget-shadow{margin:-8px 0 0 -8px;padding:8px;background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30);-moz-border-radius:8px;-khtml-border-radius:8px;-webkit-border-radius:8px;border-radius:8px}.cmb_element .ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.cmb_element .ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.cmb_element .ui-datepicker .ui-datepicker-next,.cmb_element .ui-datepicker .ui-datepicker-prev{position:absolute;top:2px;width:1.8em;height:1.8em}.cmb_element .ui-datepicker .ui-datepicker-next-hover,.cmb_element .ui-datepicker .ui-datepicker-prev-hover{top:1px}.cmb_element .ui-datepicker .ui-datepicker-prev{left:2px}.cmb_element .ui-datepicker .ui-datepicker-next{right:2px}.cmb_element .ui-datepicker .ui-datepicker-prev-hover{left:1px}.cmb_element .ui-datepicker .ui-datepicker-next-hover{right:1px}.cmb_element .ui-datepicker .ui-datepicker-next span,.cmb_element .ui-datepicker .ui-datepicker-prev span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.cmb_element .ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.cmb_element .ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.cmb_element .ui-datepicker select.ui-datepicker-month-year{width:100%}.cmb_element .ui-datepicker select.ui-datepicker-month,.cmb_element .ui-datepicker select.ui-datepicker-year{width:49%}.cmb_element .ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.cmb_element .ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:700;border:0}.cmb_element .ui-datepicker td{border:0;padding:1px}.cmb_element .ui-datepicker td a,.cmb_element .ui-datepicker td span{display:block;padding:.2em;text-align:right;text-decoration:none}.cmb_element .ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.cmb_element .ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em;width:auto;overflow:visible}.cmb_element .ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.cmb_element .ui-datepicker.ui-datepicker-multi{width:auto}.cmb_element .ui-datepicker-multi .ui-datepicker-group{float:left}.cmb_element .ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.cmb_element .ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.cmb_element .ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.cmb_element .ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.cmb_element .ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.cmb_element .ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.cmb_element .ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.cmb_element .ui-datepicker-row-break{clear:both;width:100%;font-size:0}.cmb_element .ui-datepicker-rtl{direction:rtl}.cmb_element .ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.cmb_element .ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.cmb_element .ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.cmb_element .ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.cmb_element .ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.cmb_element .ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.cmb_element .ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.cmb_element .ui-datepicker-rtl .ui-datepicker-group{float:right}.cmb_element .ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.cmb_element .ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.cmb_element .ui-datepicker-cover{display:none;display:block;position:absolute;z-index:-1;filter:mask();top:-4px;left:-4px;width:200px;height:200px}
Note: See TracChangeset for help on using the changeset viewer.