From 0ca69ef41069bccfc0d03c7616b1a6bf33d40b04 Mon Sep 17 00:00:00 2001 From: Elliot Condon Date: Fri, 14 Oct 2016 11:50:53 +0200 Subject: [PATCH] 5.4.7 --- acf.php | 4 +- admin/field-group.php | 24 +- admin/field-groups.php | 180 +++---- api/api-field.php | 143 +++--- api/api-helpers.php | 76 ++- api/api-template.php | 468 ++++++++++-------- .../timepicker/jquery-ui-timepicker-addon.js | 4 + .../jquery-ui-timepicker-addon.min.js | 7 +- assets/js/acf-field-group.js | 9 +- assets/js/acf-field-group.min.js | 2 +- assets/js/acf-input.js | 192 ++++--- assets/js/acf-input.min.js | 6 +- core/field.php | 82 ++- fields/date_picker.php | 71 +-- fields/date_time_picker.php | 4 +- fields/google-map.php | 1 - fields/taxonomy.php | 15 +- pro/assets/js/acf-pro-input.js | 23 +- pro/assets/js/acf-pro-input.min.js | 2 +- pro/fields/flexible-content.php | 74 ++- pro/fields/repeater.php | 44 ++ readme.txt | 11 + 22 files changed, 801 insertions(+), 641 deletions(-) diff --git a/acf.php b/acf.php index fcac0a5..57bb02d 100644 --- a/acf.php +++ b/acf.php @@ -3,7 +3,7 @@ Plugin Name: Advanced Custom Fields PRO Plugin URI: https://www.advancedcustomfields.com/ Description: Customise WordPress with powerful, professional and intuitive fields -Version: 5.4.6 +Version: 5.4.7 Author: Elliot Condon Author URI: http://www.elliotcondon.com/ Copyright: Elliot Condon @@ -58,7 +58,7 @@ class acf { // basic 'name' => __('Advanced Custom Fields', 'acf'), - 'version' => '5.4.6', + 'version' => '5.4.7', // urls 'basename' => plugin_basename( __FILE__ ), diff --git a/admin/field-group.php b/admin/field-group.php index 25579d5..b4368f8 100644 --- a/admin/field-group.php +++ b/admin/field-group.php @@ -1133,17 +1133,14 @@ class acf_admin_field_group { $args = acf_parse_args($_POST, array( 'nonce' => '', + 'post_id' => 0, 'field_id' => 0, 'field_group_id' => 0 )); // verify nonce - if( ! wp_verify_nonce($args['nonce'], 'acf_nonce') ) { - - die(); - - } + if( !wp_verify_nonce($args['nonce'], 'acf_nonce') ) die(); // confirm? @@ -1183,15 +1180,22 @@ class acf_admin_field_group { $choices = array(); + // check if( !empty($field_groups) ) { + // loop foreach( $field_groups as $field_group ) { - if( $field_group['ID'] ) { - - $choices[ $field_group['ID'] ] = $field_group['title']; - - } + // bail early if no ID + if( !$field_group['ID'] ) continue; + + + // bail ealry if is current + if( $field_group['ID'] == $args['post_id'] ) continue; + + + // append + $choices[ $field_group['ID'] ] = $field_group['title']; } diff --git a/admin/field-groups.php b/admin/field-groups.php index 096ac1d..4813fc6 100644 --- a/admin/field-groups.php +++ b/admin/field-groups.php @@ -150,52 +150,51 @@ class acf_admin_field_groups { } - // import field group + // vars + $ids = array(); + + + // check single if( $id = acf_maybe_get($_GET, 'acfduplicate') ) { + $ids[] = $id; + + // check multiple + } elseif( acf_maybe_get($_GET, 'action2') === 'acfduplicate' ) { + + $ids = acf_maybe_get($_GET, 'post'); + + } + + + // sync + if( !empty($ids) ) { + // validate check_admin_referer('bulk-posts'); - // duplicate - $field_group = acf_duplicate_field_group( $id ); + // vars + $new_ids = array(); + + + // loop + foreach( $ids as $id ) { + + // duplicate + $field_group = acf_duplicate_field_group( $id ); + + + // increase counter + $new_ids[] = $field_group['ID']; + + } // redirect - wp_redirect( admin_url( $this->url . '&acfduplicatecomplete=' . $field_group['ID'] ) ); + wp_redirect( admin_url( $this->url . '&acfduplicatecomplete=' . implode(',', $new_ids)) ); exit; - - } elseif( acf_maybe_get($_GET, 'action2') === 'acfduplicate' ) { - - // validate - check_admin_referer('bulk-posts'); - - // get ids - $ids = acf_maybe_get($_GET, 'post'); - - if( !empty($ids) ) { - - // vars - $new_ids = array(); - - foreach( $ids as $id ) { - - // duplicate - $field_group = acf_duplicate_field_group( $id ); - - - // increase counter - $new_ids[] = $field_group['ID']; - - } - - - // redirect - wp_redirect( admin_url( $this->url . '&acfduplicatecomplete=' . implode(',', $new_ids)) ); - exit; - } - } } @@ -241,11 +240,7 @@ class acf_admin_field_groups { // bail early if no field groups - if( empty($groups) ) { - - return; - - } + if( empty($groups) ) return; // find JSON field groups which have not yet been imported @@ -276,85 +271,72 @@ class acf_admin_field_groups { // bail if no sync needed - if( empty($this->sync) ) { + if( empty($this->sync) ) return; + + + // maybe sync + $sync_keys = array(); + + + // check single + if( $key = acf_maybe_get($_GET, 'acfsync') ) { - return; + $sync_keys[] = $key; + + // check multiple + } elseif( acf_maybe_get($_GET, 'action2') === 'acfsync' ) { + + $sync_keys = acf_maybe_get($_GET, 'post'); } - - // import field group - if( $key = acf_maybe_get($_GET, 'acfsync') ) { + + // sync + if( !empty($sync_keys) ) { + + // validate + check_admin_referer('bulk-posts'); + + + // disable filters to ensure ACF loads raw data from DB + acf_disable_filters(); + acf_enable_filter('local'); + // disable JSON // - this prevents a new JSON file being created and causing a 'change' to theme files - solves git anoyance acf_update_setting('json', false); - // validate - check_admin_referer('bulk-posts'); - - - // append fields - if( acf_have_local_fields( $key ) ) { - - $this->sync[ $key ]['fields'] = acf_get_local_fields( $key ); - - } - - - // import - $field_group = acf_import_field_group( $this->sync[ $key ] ); - - - // redirect - wp_redirect( admin_url( $this->url . '&acfsynccomplete=' . $field_group['ID'] ) ); - exit; - - } elseif( acf_maybe_get($_GET, 'action2') === 'acfsync' ) { - - // validate - check_admin_referer('bulk-posts'); + // vars + $new_ids = array(); - // get ids - $keys = acf_maybe_get($_GET, 'post'); - - if( !empty($keys) ) { + // loop + foreach( $sync_keys as $key ) { - // disable JSON - // - this prevents a new JSON file being created and causing a 'change' to theme files - solves git anoyance - acf_update_setting('json', false); - - // vars - $new_ids = array(); - - foreach( $keys as $key ) { + // append fields + if( acf_have_local_fields($key) ) { - // append fields - if( acf_have_local_fields( $key ) ) { - - $this->sync[ $key ]['fields'] = acf_get_local_fields( $key ); - - } - - - // import - $field_group = acf_import_field_group( $this->sync[ $key ] ); - - - // append - $new_ids[] = $field_group['ID']; + $this->sync[ $key ]['fields'] = acf_get_local_fields( $key ); } - // redirect - wp_redirect( admin_url( $this->url . '&acfsynccomplete=' . implode(',', $new_ids)) ); - exit; + // import + $field_group = acf_import_field_group( $this->sync[ $key ] ); + + + // append + $new_ids[] = $field_group['ID']; } - + + + // redirect + wp_redirect( admin_url( $this->url . '&acfsynccomplete=' . implode(',', $new_ids)) ); + exit; + } diff --git a/api/api-field.php b/api/api-field.php index 6372165..15c55cc 100644 --- a/api/api-field.php +++ b/api/api-field.php @@ -1856,82 +1856,17 @@ function acf_prepare_field_for_import( $field ) { function acf_get_sub_field( $selector, $field ) { - // sub fields - if( $field['type'] == 'repeater' ) { - - // extract sub fields - $sub_fields = acf_extract_var( $field, 'sub_fields'); - - if( !empty($sub_fields) ) { - - foreach( $sub_fields as $sub_field ) { - - if( $sub_field['name'] == $selector || $sub_field['key'] == $selector ) { - - // return - return $sub_field; - - } - // if - - } - // foreach - - } - // if - - } elseif( $field['type'] == 'flexible_content' ) { - - // vars - $layouts = acf_extract_var( $field, 'layouts'); - $current = get_row_layout(); - - - if( !empty($layouts) ) { - - foreach( $layouts as $layout ) { - - // skip layout if the current layout key does not match - if( $current && $current !== $layout['name'] ) { - - continue; - - } - - - // extract sub fields - $sub_fields = acf_extract_var( $layout, 'sub_fields'); - - if( !empty($sub_fields) ) { - - foreach( $sub_fields as $sub_field ) { - - if( $sub_field['name'] == $selector || $sub_field['key'] == $selector ) { - - // return - return $sub_field; - - } - // if - - } - // foreach - - } - // if - - } - // foreach - - } - // if - - } - // if + // vars + $sub_field = false; + + + // filter for 3rd party customization + $sub_field = apply_filters( "acf/get_sub_field", $sub_field, $selector, $field ); + $sub_field = apply_filters( "acf/get_sub_field/type={$field['type']}", $sub_field, $selector, $field ); // return - return false; + return $sub_field; } @@ -1970,4 +1905,66 @@ function acf_get_field_ancestors( $field ) { } +/* +* acf_maybe_get_sub_field +* +* This function will attempt to find a sub field +* +* @type function +* @date 3/10/2016 +* @since 5.4.0 +* +* @param $post_id (int) +* @return $post_id (int) +*/ + +function acf_maybe_get_sub_field( $selectors, $post_id = false, $strict = true ) { + + // bail ealry if not enough selectors + if( !is_array($selectors) || count($selectors) < 3 ) return false; + + + // vars + $selector = acf_extract_var( $selectors, 0 ); + $selectors = array_values( $selectors ); // reset keys + + + // attempt get field + $field = acf_maybe_get_field( $selector, $post_id, $strict ); + + + // bail early if no field + if( !$field ) return false; + + + // loop + for( $j = 0; $j < count($selectors); $j+=2 ) { + + // vars + $sub_i = $selectors[ $j ]; + $sub_s = $selectors[ $j+1 ]; + $field_name = $field['name']; + + + // find sub field + $field = acf_get_sub_field( $sub_s, $field ); + + + // bail early if no sub field + if( !$field ) return false; + + + // add to name + $field['name'] = $field_name . '_' . ($sub_i-1) . '_' . $field['name']; + + } + + + // return + return $field; + + +} + + ?> diff --git a/api/api-helpers.php b/api/api-helpers.php index dd16cec..22a1f29 100644 --- a/api/api-helpers.php +++ b/api/api-helpers.php @@ -1033,6 +1033,48 @@ function acf_get_image_size( $s = '' ) { } +/* +* acf_get_terms +* +* This function is a wrapper for the get_terms() function +* +* @type function +* @date 28/09/2016 +* @since 5.4.0 +* +* @param $args (array) +* @return (array) +*/ + +function acf_get_terms( $args ) { + + // global + global $wp_version; + + + // vars + $terms = array(); + + + // WP 4.5+ + if( version_compare($wp_version, '4.5', '>=' ) ) { + + $terms = get_terms( $args ); + + // WP < 4.5 + } else { + + $terms = get_terms( $args['taxonomy'], $args ); + + } + + + // return + return $terms; + +} + + /* * acf_get_taxonomies * @@ -1164,8 +1206,11 @@ function acf_get_taxonomy_terms( $taxonomies = array() ) { // vars $label = $taxonomies[ $taxonomy ]; - $terms = get_terms( $taxonomy, array( 'hide_empty' => false ) ); $is_hierarchical = is_taxonomy_hierarchical( $taxonomy ); + $terms = acf_get_terms(array( + 'taxonomy' => $taxonomy, + 'hide_empty' => false + )); // bail early i no terms @@ -3200,7 +3245,7 @@ function acf_upload_files( $ancestors = array() ) { function acf_upload_file( $uploaded_file ) { // required - require_once( ABSPATH . "/wp-load.php" ); + //require_once( ABSPATH . "/wp-load.php" ); // WP should already be loaded require_once( ABSPATH . "/wp-admin/includes/media.php" ); // video functions require_once( ABSPATH . "/wp-admin/includes/file.php" ); require_once( ABSPATH . "/wp-admin/includes/image.php" ); @@ -4368,29 +4413,18 @@ function acf_format_date( $value, $format ) { if( !$value ) return $value; - // attempt strtotime for standard date value - $unixtimestamp = strtotime($value); + // vars + $unixtimestamp = 0; - // check strtotime - if( !$unixtimestamp ) { + // numeric (either unix or YYYYMMDD) + if( is_numeric($value) && strlen($value) !== 8 ) { - // $value may already be a timestamp - if( is_numeric($value) ) { - - $unixtimestamp = $value; + $unixtimestamp = $value; - // $value may be Unix epoch (1970-01-01) - } elseif( $value === '1970-01-01' ) { - - $unixtimestamp = 0; - - // error - } else { - - return $value; - - } + } else { + + $unixtimestamp = strtotime($value); } diff --git a/api/api-template.php b/api/api-template.php index 9959e8e..1124f9a 100644 --- a/api/api-template.php +++ b/api/api-template.php @@ -796,47 +796,18 @@ function has_sub_fields( $field_name, $post_id = false ) { * @return (mixed) */ -function get_sub_field( $selector, $format_value = true ) { +function get_sub_field( $selector = '', $format_value = true ) { - // vars - $row = acf_get_loop('active'); + // get sub field + $sub_field = get_sub_field_object( $selector, $format_value ); - // bail early if no row - if( !$row ) return null; - - - // attempt to find sub field - $sub_field = get_row_sub_field( $selector ); - - - // update selector - if( $sub_field ) { - - $selector = $sub_field['key']; - - } else { - - $format_value = false; - - } - - - // load value - $value = get_row_sub_value( $selector ); - - - // format value - if( $format_value ) { - - // get value for field - $value = acf_format_value( $value, $row['post_id'], $sub_field ); - - } + // bail early if no sub field + if( !$sub_field ) return false; // return - return $value; + return $sub_field['value']; } @@ -900,7 +871,11 @@ function get_sub_field_object( $selector, $format_value = true, $load_value = tr // load value - $sub_field['value'] = get_row_sub_value( $sub_field['key'] ); + if( $load_value ) { + + $sub_field['value'] = get_row_sub_value( $sub_field['key'] ); + + } // format value @@ -1634,118 +1609,32 @@ function update_field( $selector, $value, $post_id = false ) { function update_sub_field( $selector, $value, $post_id = false ) { + // vars + $sub_field = false; + + // filter post_id $post_id = acf_get_valid_post_id( $post_id ); - // vars - $field = false; + // get sub field + if( is_array($selector) ) { + + $sub_field = acf_maybe_get_sub_field( $selector, $post_id, false ); - - // within a have_rows loop - if( is_string($selector) ) { + } else { - // get current row - $row = acf_get_loop('active'); - - - // override $post_id - $post_id = $row['post_id']; - - - // attempt to find sub field - $field = get_row_sub_field($selector); - - - // create dummy field - if( !$field ) { - - $field = acf_get_valid_field(array( - 'name' => "{$row['name']}_{$row['i']}_{$selector}", - 'key' => '', - 'type' => '', - )); - - } - - } elseif( is_array($selector) ) { - - // validate - if( count($selector) < 3 ) { - - return false; - - } - - - // vars - $parent_name = acf_extract_var( $selector, 0 ); - - - // load parent - $field = acf_maybe_get_field( $parent_name, $post_id ); - - - // add to name - $name = $field['name']; - - - // sub fields - foreach( $selector as $s ) { - - if( is_numeric($s) ) { - - // get row index - $row_i = intval($s) - 1; - - // add to name - $name .= "_{$row_i}"; - - } else { - - // update parent - $field = acf_get_sub_field( $s, $field ); - - - // create dummy field - if( !$field ) { - - $field = acf_get_valid_field(array( - 'name' => $s, - 'key' => '', - 'type' => '', - )); - - } - - - // add to name - $name .= "_{$field['name']}"; - - } - // if - - } - // foreach - - - // update name - $field['name'] = $name; - - - } - - - // delete - if( $value === null ) { - - return acf_delete_value( $post_id, $field ); + $sub_field = get_row_sub_field( $selector ); } + // bail early if no sub field + if( !$sub_field ) return false; + + // update - return acf_update_value( $value, $post_id, $field ); + return acf_update_value( $value, $post_id, $sub_field ); } @@ -1805,17 +1694,19 @@ function delete_sub_field( $selector, $post_id = false ) { /* * add_row * -* description +* This function will add a row of data to a field * * @type function * @date 16/10/2015 * @since 5.2.3 * -* @param $post_id (int) -* @return $post_id (int) +* @param $selector (string) +* @param $row (array) +* @param $post_id (mixed) +* @return (boolean) */ -function add_row( $selector, $value, $post_id = false ) { +function add_row( $selector, $row = false, $post_id = false ) { // filter post_id $post_id = acf_get_valid_post_id( $post_id ); @@ -1826,73 +1717,106 @@ function add_row( $selector, $value, $post_id = false ) { // bail early if no field - if( !$field ) { + if( !$field ) return false; + + + // get raw value + $value = acf_get_value( $post_id, $field ); + + + // ensure array + $value = acf_get_array($value); + + + // append + $value[] = $row; + + + // update value + return acf_update_value( $value, $post_id, $field ); - return false; +} + + +/* +* add_sub_row +* +* This function will add a row of data to a field +* +* @type function +* @date 16/10/2015 +* @since 5.2.3 +* +* @param $selector (string) +* @param $row (array) +* @param $post_id (mixed) +* @return (boolean) +*/ + +function add_sub_row( $selector, $row = false, $post_id = false ) { + + // vars + $sub_field = false; + + + // filter post_id + $post_id = acf_get_valid_post_id( $post_id ); + + + // get sub field + if( is_array($selector) ) { + + $sub_field = acf_maybe_get_sub_field( $selector, $post_id, false ); + + } else { + + $sub_field = get_row_sub_field( $selector ); } - // get row count - $i = (int) acf_get_metadata( $post_id, $field['name'] ); + // bail early if no sub field + if( !$sub_field ) return false; - - // if no rows, save this field via update_field() so that the reference field is created - if( !$i ) { - // acf_update_value will return boolean, simply convert this to int for 1 | 0 (the number of rows!) - return (int) acf_update_value( array( $value ), $post_id, $field ); + // get raw value + $value = acf_get_value( $post_id, $sub_field ); + + + // ensure array + $value = acf_get_array( $value ); + + + // append + $value[] = $row; + + + // update + return acf_update_value( $value, $post_id, $sub_field ); - } - - - // increase $i - $i++; - - - // update meta - $result = acf_update_metadata( $post_id, $field['name'], $i ); - - - // update sub fields - if( $value ) { - - foreach( $value as $k => $v ) { - - update_sub_field( array( $field['key'], $i, $k ), $v, $post_id ); - - } - - } - - - // return - return $i; - } /* * update_row * -* description +* This function will update a row of data to a field * * @type function * @date 19/10/2015 * @since 5.2.3 * -* @param $post_id (int) -* @return $post_id (int) +* @param $selector (string) +* @param $i (int) +* @param $row (array) +* @param $post_id (mixed) +* @return (boolean) */ -function update_row( $selector, $row = 1, $value = false, $post_id = false ) { +function update_row( $selector, $i = 1, $row = false, $post_id = false ) { - // bail early if no value - if( empty($value) ) { - - return false; - - } + // vars + $i--; // filter post_id @@ -1907,34 +1831,104 @@ function update_row( $selector, $row = 1, $value = false, $post_id = false ) { if( !$field ) return false; - // update sub fields - foreach( $value as $k => $v ) { + // get raw value + $value = acf_get_value( $post_id, $field ); + + + // ensure array + $value = acf_get_array($value); + + + // update + $value[ $i ] = $row; + + + // update value + return acf_update_value( $value, $post_id, $field ); + +} + + +/* +* update_sub_row +* +* This function will add a row of data to a field +* +* @type function +* @date 16/10/2015 +* @since 5.2.3 +* +* @param $selector (string) +* @param $row (array) +* @param $post_id (mixed) +* @return (boolean) +*/ + +function update_sub_row( $selector, $i = 1, $row = false, $post_id = false ) { + + // vars + $sub_field = false; + $i--; + + + // filter post_id + $post_id = acf_get_valid_post_id( $post_id ); + + + // get sub field + if( is_array($selector) ) { - update_sub_field( array( $field['key'], $row, $k ), $v, $post_id ); + $sub_field = acf_maybe_get_sub_field( $selector, $post_id, false ); + + } else { + + $sub_field = get_row_sub_field( $selector ); } - // return - return true; + // bail early if no sub field + if( !$sub_field ) return false; + + // get raw value + $value = acf_get_value( $post_id, $sub_field ); + + + // ensure array + $value = acf_get_array( $value ); + + + // append + $value[ $i ] = $row; + + + // update + return acf_update_value( $value, $post_id, $sub_field ); + } /* * delete_row * -* description +* This function will delete a row of data from a field * * @type function * @date 19/10/2015 * @since 5.2.3 * -* @param $post_id (int) -* @return $post_id (int) +* @param $selector (string) +* @param $i (int) +* @param $post_id (mixed) +* @return (boolean) */ -function delete_row( $selector, $row = 1, $post_id = false ) { +function delete_row( $selector, $i = 1, $post_id = false ) { + + // vars + $i--; + // filter post_id $post_id = acf_get_valid_post_id( $post_id ); @@ -1949,36 +1943,80 @@ function delete_row( $selector, $row = 1, $post_id = false ) { // get value - $rows = acf_get_value( $post_id, $field ); + $value = acf_get_value( $post_id, $field ); - // bail early if no value - if( empty($rows) ) return false; - - - // vars - $i = $row-1; - - - // bail early if row doesn't exist - if( empty($rows[ $i ]) ) return false; - + // ensure array + $value = acf_get_array($value); + // unset - unset( $rows[ $i ] ); - - - // reindex - $rows = array_values($rows); + unset( $value[ $i ] ); // update - acf_update_value( $rows, $post_id, $field ); + return acf_update_value( $value, $post_id, $field ); + +} + + +/* +* delete_sub_row +* +* This function will add a row of data to a field +* +* @type function +* @date 16/10/2015 +* @since 5.2.3 +* +* @param $selector (string) +* @param $row (array) +* @param $post_id (mixed) +* @return (boolean) +*/ + +function delete_sub_row( $selector, $i = 1, $post_id = false ) { + + // vars + $sub_field = false; + $i--; - // return - return true; + // filter post_id + $post_id = acf_get_valid_post_id( $post_id ); + + // get sub field + if( is_array($selector) ) { + + $sub_field = acf_maybe_get_sub_field( $selector, $post_id, false ); + + } else { + + $sub_field = get_row_sub_field( $selector ); + + } + + + // bail early if no sub field + if( !$sub_field ) return false; + + + // get raw value + $value = acf_get_value( $post_id, $sub_field ); + + + // ensure array + $value = acf_get_array( $value ); + + + // append + unset( $value[ $i ] ); + + + // update + return acf_update_value( $value, $post_id, $sub_field ); + } diff --git a/assets/inc/timepicker/jquery-ui-timepicker-addon.js b/assets/inc/timepicker/jquery-ui-timepicker-addon.js index d37bc02..3da2a08 100644 --- a/assets/inc/timepicker/jquery-ui-timepicker-addon.js +++ b/assets/inc/timepicker/jquery-ui-timepicker-addon.js @@ -882,11 +882,15 @@ else { this.$timeObj.val($.datepicker.formatTime(pickerTimeFormat, this, o) + pickerTimeSuffix); } + /* + // Input loses focus when typing with picker open + // https://github.com/trentrichardson/jQuery-Timepicker-Addon/issues/848 if (this.$timeObj[0].setSelectionRange) { var sPos = this.$timeObj[0].selectionStart; var ePos = this.$timeObj[0].selectionEnd; this.$timeObj[0].setSelectionRange(sPos, ePos); } + */ } this.timeDefined = true; diff --git a/assets/inc/timepicker/jquery-ui-timepicker-addon.min.js b/assets/inc/timepicker/jquery-ui-timepicker-addon.min.js index f3777f7..d8d0aaa 100644 --- a/assets/inc/timepicker/jquery-ui-timepicker-addon.min.js +++ b/assets/inc/timepicker/jquery-ui-timepicker-addon.min.js @@ -1,5 +1,2 @@ -/*! jQuery Timepicker Addon - v1.6.3 - 2016-04-20 -* http://trentrichardson.com/examples/timepicker -* Copyright (c) 2016 Trent Richardson; Licensed MIT */ -!function(a){"function"==typeof define&&define.amd?define(["jquery","jquery-ui"],a):a(jQuery)}(function($){if($.ui.timepicker=$.ui.timepicker||{},!$.ui.timepicker.version){$.extend($.ui,{timepicker:{version:"1.6.3"}});var Timepicker=function(){this.regional=[],this.regional[""]={currentText:"Now",closeText:"Done",amNames:["AM","A"],pmNames:["PM","P"],timeFormat:"HH:mm",timeSuffix:"",timeOnlyTitle:"Choose Time",timeText:"Time",hourText:"Hour",minuteText:"Minute",secondText:"Second",millisecText:"Millisecond",microsecText:"Microsecond",timezoneText:"Time Zone",isRTL:!1},this._defaults={showButtonPanel:!0,timeOnly:!1,timeOnlyShowDate:!1,showHour:null,showMinute:null,showSecond:null,showMillisec:null,showMicrosec:null,showTimezone:null,showTime:!0,stepHour:1,stepMinute:1,stepSecond:1,stepMillisec:1,stepMicrosec:1,hour:0,minute:0,second:0,millisec:0,microsec:0,timezone:null,hourMin:0,minuteMin:0,secondMin:0,millisecMin:0,microsecMin:0,hourMax:23,minuteMax:59,secondMax:59,millisecMax:999,microsecMax:999,minDateTime:null,maxDateTime:null,maxTime:null,minTime:null,onSelect:null,hourGrid:0,minuteGrid:0,secondGrid:0,millisecGrid:0,microsecGrid:0,alwaysSetTime:!0,separator:" ",altFieldTimeOnly:!0,altTimeFormat:null,altSeparator:null,altTimeSuffix:null,altRedirectFocus:!0,pickerTimeFormat:null,pickerTimeSuffix:null,showTimepicker:!0,timezoneList:null,addSliderAccess:!1,sliderAccessArgs:null,controlType:"slider",oneLine:!1,defaultValue:null,parse:"strict",afterInject:null},$.extend(this._defaults,this.regional[""])};$.extend(Timepicker.prototype,{$input:null,$altInput:null,$timeObj:null,inst:null,hour_slider:null,minute_slider:null,second_slider:null,millisec_slider:null,microsec_slider:null,timezone_select:null,maxTime:null,minTime:null,hour:0,minute:0,second:0,millisec:0,microsec:0,timezone:null,hourMinOriginal:null,minuteMinOriginal:null,secondMinOriginal:null,millisecMinOriginal:null,microsecMinOriginal:null,hourMaxOriginal:null,minuteMaxOriginal:null,secondMaxOriginal:null,millisecMaxOriginal:null,microsecMaxOriginal:null,ampm:"",formattedDate:"",formattedTime:"",formattedDateTime:"",timezoneList:null,units:["hour","minute","second","millisec","microsec"],support:{},control:null,setDefaults:function(a){return extendRemove(this._defaults,a||{}),this},_newInst:function($input,opts){var tp_inst=new Timepicker,inlineSettings={},fns={},overrides,i;for(var attrName in this._defaults)if(this._defaults.hasOwnProperty(attrName)){var attrValue=$input.attr("time:"+attrName);if(attrValue)try{inlineSettings[attrName]=eval(attrValue)}catch(err){inlineSettings[attrName]=attrValue}}overrides={beforeShow:function(a,b){return $.isFunction(tp_inst._defaults.evnts.beforeShow)?tp_inst._defaults.evnts.beforeShow.call($input[0],a,b,tp_inst):void 0},onChangeMonthYear:function(a,b,c){$.isFunction(tp_inst._defaults.evnts.onChangeMonthYear)&&tp_inst._defaults.evnts.onChangeMonthYear.call($input[0],a,b,c,tp_inst)},onClose:function(a,b){tp_inst.timeDefined===!0&&""!==$input.val()&&tp_inst._updateDateTime(b),$.isFunction(tp_inst._defaults.evnts.onClose)&&tp_inst._defaults.evnts.onClose.call($input[0],a,b,tp_inst)}};for(i in overrides)overrides.hasOwnProperty(i)&&(fns[i]=opts[i]||this._defaults[i]||null);tp_inst._defaults=$.extend({},this._defaults,inlineSettings,opts,overrides,{evnts:fns,timepicker:tp_inst}),tp_inst.amNames=$.map(tp_inst._defaults.amNames,function(a){return a.toUpperCase()}),tp_inst.pmNames=$.map(tp_inst._defaults.pmNames,function(a){return a.toUpperCase()}),tp_inst.support=detectSupport(tp_inst._defaults.timeFormat+(tp_inst._defaults.pickerTimeFormat?tp_inst._defaults.pickerTimeFormat:"")+(tp_inst._defaults.altTimeFormat?tp_inst._defaults.altTimeFormat:"")),"string"==typeof tp_inst._defaults.controlType?("slider"===tp_inst._defaults.controlType&&"undefined"==typeof $.ui.slider&&(tp_inst._defaults.controlType="select"),tp_inst.control=tp_inst._controls[tp_inst._defaults.controlType]):tp_inst.control=tp_inst._defaults.controlType;var timezoneList=[-720,-660,-600,-570,-540,-480,-420,-360,-300,-270,-240,-210,-180,-120,-60,0,60,120,180,210,240,270,300,330,345,360,390,420,480,525,540,570,600,630,660,690,720,765,780,840];null!==tp_inst._defaults.timezoneList&&(timezoneList=tp_inst._defaults.timezoneList);var tzl=timezoneList.length,tzi=0,tzv=null;if(tzl>0&&"object"!=typeof timezoneList[0])for(;tzl>tzi;tzi++)tzv=timezoneList[tzi],timezoneList[tzi]={value:tzv,label:$.timepicker.timezoneOffsetString(tzv,tp_inst.support.iso8601)};return tp_inst._defaults.timezoneList=timezoneList,tp_inst.timezone=null!==tp_inst._defaults.timezone?$.timepicker.timezoneOffsetNumber(tp_inst._defaults.timezone):-1*(new Date).getTimezoneOffset(),tp_inst.hour=tp_inst._defaults.hourtp_inst._defaults.hourMax?tp_inst._defaults.hourMax:tp_inst._defaults.hour,tp_inst.minute=tp_inst._defaults.minutetp_inst._defaults.minuteMax?tp_inst._defaults.minuteMax:tp_inst._defaults.minute,tp_inst.second=tp_inst._defaults.secondtp_inst._defaults.secondMax?tp_inst._defaults.secondMax:tp_inst._defaults.second,tp_inst.millisec=tp_inst._defaults.millisectp_inst._defaults.millisecMax?tp_inst._defaults.millisecMax:tp_inst._defaults.millisec,tp_inst.microsec=tp_inst._defaults.microsectp_inst._defaults.microsecMax?tp_inst._defaults.microsecMax:tp_inst._defaults.microsec,tp_inst.ampm="",tp_inst.$input=$input,tp_inst._defaults.altField&&(tp_inst.$altInput=$(tp_inst._defaults.altField),tp_inst._defaults.altRedirectFocus===!0&&tp_inst.$altInput.css({cursor:"pointer"}).focus(function(){$input.trigger("focus")})),(0===tp_inst._defaults.minDate||0===tp_inst._defaults.minDateTime)&&(tp_inst._defaults.minDate=new Date),(0===tp_inst._defaults.maxDate||0===tp_inst._defaults.maxDateTime)&&(tp_inst._defaults.maxDate=new Date),void 0!==tp_inst._defaults.minDate&&tp_inst._defaults.minDate instanceof Date&&(tp_inst._defaults.minDateTime=new Date(tp_inst._defaults.minDate.getTime())),void 0!==tp_inst._defaults.minDateTime&&tp_inst._defaults.minDateTime instanceof Date&&(tp_inst._defaults.minDate=new Date(tp_inst._defaults.minDateTime.getTime())),void 0!==tp_inst._defaults.maxDate&&tp_inst._defaults.maxDate instanceof Date&&(tp_inst._defaults.maxDateTime=new Date(tp_inst._defaults.maxDate.getTime())),void 0!==tp_inst._defaults.maxDateTime&&tp_inst._defaults.maxDateTime instanceof Date&&(tp_inst._defaults.maxDate=new Date(tp_inst._defaults.maxDateTime.getTime())),tp_inst.$input.bind("focus",function(){tp_inst._onFocus()}),tp_inst},_addTimePicker:function(a){var b=$.trim(this.$altInput&&this._defaults.altFieldTimeOnly?this.$input.val()+" "+this.$altInput.val():this.$input.val());this.timeDefined=this._parseTime(b),this._limitMinMaxDateTime(a,!1),this._injectTimePicker(),this._afterInject()},_parseTime:function(a,b){if(this.inst||(this.inst=$.datepicker._getInst(this.$input[0])),b||!this._defaults.timeOnly){var c=$.datepicker._get(this.inst,"dateFormat");try{var d=parseDateTimeInternal(c,this._defaults.timeFormat,a,$.datepicker._getFormatConfig(this.inst),this._defaults);if(!d.timeObj)return!1;$.extend(this,d.timeObj)}catch(e){return $.timepicker.log("Error parsing the date/time string: "+e+"\ndate/time string = "+a+"\ntimeFormat = "+this._defaults.timeFormat+"\ndateFormat = "+c),!1}return!0}var f=$.datepicker.parseTime(this._defaults.timeFormat,a,this._defaults);return f?($.extend(this,f),!0):!1},_afterInject:function(){var a=this.inst.settings;$.isFunction(a.afterInject)&&a.afterInject.call(this)},_injectTimePicker:function(){var a=this.inst.dpDiv,b=this.inst.settings,c=this,d="",e="",f=null,g={},h={},i=null,j=0,k=0;if(0===a.find("div.ui-timepicker-div").length&&b.showTimepicker){var l=" ui_tpicker_unit_hide",m='
'+b.timeText+'
";for(j=0,k=this.units.length;k>j;j++){if(d=this.units[j],e=d.substr(0,1).toUpperCase()+d.substr(1),f=null!==b["show"+e]?b["show"+e]:this.support[d],g[d]=parseInt(b[d+"Max"]-(b[d+"Max"]-b[d+"Min"])%b["step"+e],10),h[d]=0,m+='
'+b[d+"Text"]+'
',f&&b[d+"Grid"]>0){if(m+='
',"hour"===d)for(var n=b[d+"Min"];n<=g[d];n+=parseInt(b[d+"Grid"],10)){h[d]++;var o=$.datepicker.formatTime(this.support.ampm?"hht":"HH",{hour:n},b);m+='"}else for(var p=b[d+"Min"];p<=g[d];p+=parseInt(b[d+"Grid"],10))h[d]++,m+='";m+="
'+o+"'+(10>p?"0":"")+p+"
"}m+="
"}var q=null!==b.showTimezone?b.showTimezone:this.support.timezone;m+='
'+b.timezoneText+"
",m+='
',m+="
";var r=$(m);for(b.timeOnly===!0&&(r.prepend('
'+b.timeOnlyTitle+"
"),a.find(".ui-datepicker-header, .ui-datepicker-calendar").hide()),j=0,k=c.units.length;k>j;j++)d=c.units[j],e=d.substr(0,1).toUpperCase()+d.substr(1),f=null!==b["show"+e]?b["show"+e]:this.support[d],c[d+"_slider"]=c.control.create(c,r.find(".ui_tpicker_"+d+"_slider"),d,c[d],b[d+"Min"],g[d],b["step"+e]),f&&b[d+"Grid"]>0&&(i=100*h[d]*b[d+"Grid"]/(g[d]-b[d+"Min"]),r.find(".ui_tpicker_"+d+" table").css({width:i+"%",marginLeft:b.isRTL?"0":i/(-2*h[d])+"%",marginRight:b.isRTL?i/(-2*h[d])+"%":"0",borderCollapse:"collapse"}).find("td").click(function(a){var b=$(this),e=b.html(),f=parseInt(e.replace(/[^0-9]/g),10),g=e.replace(/[^apm]/gi),h=b.data("for");"hour"===h&&(-1!==g.indexOf("p")&&12>f?f+=12:-1!==g.indexOf("a")&&12===f&&(f=0)),c.control.value(c,c[h+"_slider"],d,f),c._onTimeChange(),c._onSelectHandler()}).css({cursor:"pointer",width:100/h[d]+"%",textAlign:"center",overflow:"hidden"}));if(this.timezone_select=r.find(".ui_tpicker_timezone").append("").find("select"),$.fn.append.apply(this.timezone_select,$.map(b.timezoneList,function(a,b){return $("