diff --git a/css/off-canvas-sidebars-admin.css b/css/off-canvas-sidebars-admin.css index 7f0c3cd..9a9f9ca 100644 --- a/css/off-canvas-sidebars-admin.css +++ b/css/off-canvas-sidebars-admin.css @@ -44,6 +44,8 @@ .off-canvas-sidebars-settings .icon { font-size: 1.3em; vertical-align: middle; text-decoration: none; } .off-canvas-sidebars-settings .icon:first-child {margin-right: 5px;} +.off_canvas_sidebars_options_sidebars_content_id_wrapper { margin-top: .5em; margin-left: 1.5em; } + @media only screen and (min-width: 850px) { .off-canvas-sidebars-settings { margin-right: 300px; diff --git a/css/off-canvas-sidebars-admin.min.css b/css/off-canvas-sidebars-admin.min.css index 643c28c..ba9f628 100644 --- a/css/off-canvas-sidebars-admin.min.css +++ b/css/off-canvas-sidebars-admin.min.css @@ -7,4 +7,4 @@ * @version 0.5.4 * @preserve */ -.ocs-credits{overflow:hidden;background:#fff;position:relative;margin:0;box-shadow:0 0 0 1px rgba(0,0,0,0.05)}.ocs-credits .inside{padding:0;margin:0}.ocs-credits .inner{padding-left:10px;padding-right:10px}.ocs-credits h3{font-size:14px;line-height:1.4;margin:0;padding:8px 12px;border-bottom:1px solid #eee}.off-canvas-sidebars-settings .postbox-container{float:none}.postbox.section-sidebar{-webkit-transition:all .1s;-moz-transition:all .1s;-o-transition:all .1s;transition:all .1s}.postbox.section-sidebar:hover{opacity:1 !important}.off-canvas-sidebars-settings .form-table tbody>tr:not(:last-child){border-bottom:1px solid #eee}.off-canvas-sidebars-settings .form-table:not(:last-child){margin-bottom:1em;border-bottom:1px solid #eee}.off-canvas-sidebars-settings fieldset.radio label,.off-canvas-sidebars-settings fieldset.checkbox label{display:block}.off-canvas-sidebars-settings fieldset.radio label+br{display:none}.off-canvas-sidebars-settings fieldset.radio label+.description{margin-bottom:.5em;display:inline-block}.off-canvas-sidebars-settings input+select{vertical-align:top}.off-canvas-sidebars-settings .form-table code{display:inline-block}.off-canvas-sidebars-settings .icon{font-size:1.3em;vertical-align:middle;text-decoration:none}.off-canvas-sidebars-settings .icon:first-child{margin-right:5px}@media only screen and (min-width:850px){.off-canvas-sidebars-settings{margin-right:300px}.off-canvas-sidebars-settings form{float:left;min-width:100%;width:auto}.ocs-credits{float:right;margin:10px -300px 10px 20px;width:280px}.off-canvas-sidebars-settings .postbox-container .postbox-third{float:left;width:33%;margin-left:.5%;box-sizing:border-box}.off-canvas-sidebars-settings .postbox-container .postbox-third.first{margin-left:0}}@media only screen and (min-width:959px){.ocs-credits{position:fixed;right:0;margin:10px 20px}} \ No newline at end of file +.ocs-credits{overflow:hidden;background:#fff;position:relative;margin:0;box-shadow:0 0 0 1px rgba(0,0,0,0.05)}.ocs-credits .inside{padding:0;margin:0}.ocs-credits .inner{padding-left:10px;padding-right:10px}.ocs-credits h3{font-size:14px;line-height:1.4;margin:0;padding:8px 12px;border-bottom:1px solid #eee}.off-canvas-sidebars-settings .postbox-container{float:none}.postbox.section-sidebar{-webkit-transition:all .1s;-moz-transition:all .1s;-o-transition:all .1s;transition:all .1s}.postbox.section-sidebar:hover{opacity:1 !important}.off-canvas-sidebars-settings .form-table tbody>tr:not(:last-child){border-bottom:1px solid #eee}.off-canvas-sidebars-settings .form-table:not(:last-child){margin-bottom:1em;border-bottom:1px solid #eee}.off-canvas-sidebars-settings fieldset.radio label,.off-canvas-sidebars-settings fieldset.checkbox label{display:block}.off-canvas-sidebars-settings fieldset.radio label+br{display:none}.off-canvas-sidebars-settings fieldset.radio label+.description{margin-bottom:.5em;display:inline-block}.off-canvas-sidebars-settings input+select{vertical-align:top}.off-canvas-sidebars-settings .form-table code{display:inline-block}.off-canvas-sidebars-settings .icon{font-size:1.3em;vertical-align:middle;text-decoration:none}.off-canvas-sidebars-settings .icon:first-child{margin-right:5px}.off_canvas_sidebars_options_sidebars_content_id_wrapper{margin-top:.5em;margin-left:1.5em}@media only screen and (min-width:850px){.off-canvas-sidebars-settings{margin-right:300px}.off-canvas-sidebars-settings form{float:left;min-width:100%;width:auto}.ocs-credits{float:right;margin:10px -300px 10px 20px;width:280px}.off-canvas-sidebars-settings .postbox-container .postbox-third{float:left;width:33%;margin-left:.5%;box-sizing:border-box}.off-canvas-sidebars-settings .postbox-container .postbox-third.first{margin-left:0}}@media only screen and (min-width:959px){.ocs-credits{position:fixed;right:0;margin:10px 20px}} \ No newline at end of file diff --git a/includes/class-frontend.php b/includes/class-frontend.php index b4056c5..0e9d678 100644 --- a/includes/class-frontend.php +++ b/includes/class-frontend.php @@ -274,6 +274,27 @@ public function do_sidebar( $sidebar_id ) { break; + case 'post': + $post_id = ( isset( $sidebar_data['content_id'] ) ) ? $sidebar_data['content_id'] : 0; + // @todo translate + + /** + * Overwrite sidebar content post ID. + * + * @since 0.6.0 + * + * @param int $post_id The post ID. + * @param string $sidebar_id The ID of this sidebar as configured in: Appearance > Off-Canvas Sidebars > Sidebars. + * @param array $sidebar_data The sidebar settings. + */ + $post_id = apply_filters( 'ocs_sidebar_content_post_id', $post_id, $sidebar_id, $sidebar_data ); + + if ( $post_id ) { + echo apply_filters( 'the_content', get_post_field( 'post_content', $post_id ) ); + } + + break; + case 'action': default: /** diff --git a/includes/class-page.php b/includes/class-page.php index 97d8f86..09bc4a3 100644 --- a/includes/class-page.php +++ b/includes/class-page.php @@ -111,7 +111,9 @@ public function enqueue_styles_scripts( $hook ) { 'general_key' => $this->general_key, 'plugin_key' => $this->plugin_key, 'css_prefix' => $this->get_settings( 'css_prefix' ), - '__required_fields_not_set' => __( 'Some required fields are not set!', OCS_DOMAIN ), + '_nonce' => wp_create_nonce( OCS_DOMAIN ), + '__required_fields_not_set' => esc_html__( 'Some required fields are not set!', OCS_DOMAIN ), + '__search' => esc_html__( 'Search', OCS_DOMAIN ) ) ); diff --git a/includes/class-settings.php b/includes/class-settings.php index 7fd220a..479afc4 100644 --- a/includes/class-settings.php +++ b/includes/class-settings.php @@ -73,6 +73,7 @@ final class OCS_Off_Canvas_Sidebars_Settings extends OCS_Off_Canvas_Sidebars_Bas 'enable' => 0, 'label' => '', 'content' => 'sidebar', + 'content_id' => 0, 'location' => 'left', 'style' => 'push', 'size' => 'default', diff --git a/includes/class-tab-sidebars.php b/includes/class-tab-sidebars.php index 54deefd..6a30bba 100644 --- a/includes/class-tab-sidebars.php +++ b/includes/class-tab-sidebars.php @@ -43,6 +43,8 @@ protected function __construct() { add_filter( 'ocs_settings_parse_input', array( $this, 'parse_input' ), 11, 2 ); add_filter( 'ocs_settings_validate_input', array( $this, 'validate_input' ), 11, 2 ); + + add_action( 'wp_ajax_ocs_get_posts', array( $this, 'ajax_get_posts' ) ); } /** @@ -170,6 +172,50 @@ public function register_sidebar_fields( $args ) { } } + /** + * Handle AJAX get posts requests. + * + * @since 0.6.0 + */ + public function ajax_get_posts() { + + if ( ! wp_verify_nonce( $_POST['ocs_nonce'], OCS_DOMAIN ) ) { + wp_send_json_error(); + die; + } + + $current = ''; + if ( ! empty( $_POST['ocs_sidebar_id'] ) ) { + $current = off_canvas_sidebars_settings()->get_sidebar_settings( $_POST['ocs_sidebar_id'], 'content_id' ); + if ( $current ) { + $current = get_post( $current ); + } + } + + $posts = array(); + if ( ! empty( $_POST['ocs_search'] ) ) { + $args = array( + 'orderby' => 'title', + 'order' => 'ASC', + 'post_type' => 'any', + 's' => $_POST['ocs_search'], + ); + $posts = get_posts( $args ); + } + + $data = array( 'current' => '' ); + if ( $current ) { + $data['current'] = $current->ID; + $data[ $current->ID ] = $current->post_title . ' [' . $current->post_type . ']'; + } + foreach ( $posts as $post ) { + $data[ $post->ID ] = $post->post_title . ' [' . $post->post_type . ']'; + } + + wp_send_json_success( $data ); + die; + } + /** * Parses sidebar post values, checks all values with the current existing data. * @@ -370,12 +416,13 @@ protected function get_tab_fields() { 'type' => 'text', ), 'content' => array( - 'name' => 'content', - 'title' => esc_attr__( 'Content', OCS_DOMAIN ), - 'callback' => 'radio_option', - 'type' => 'radio', - 'default' => 'sidebar', - 'options' => array( + 'name' => 'content', + 'title' => esc_attr__( 'Content', OCS_DOMAIN ), + 'callback' => 'radio_option', + 'type' => 'radio', + 'default' => 'sidebar', + 'description' => __( 'Keep in mind that WordPress has menu and text widgets by default, the "sidebar" object is your best option in most cases.', OCS_DOMAIN ), + 'options' => array( 'sidebar' => array( 'name' => 'sidebar', 'label' => __( 'Sidebar', OCS_DOMAIN ) . '   (' . __( 'Default', OCS_DOMAIN ) . ')', @@ -386,13 +433,23 @@ protected function get_tab_fields() { 'label' => __( 'Menu', OCS_DOMAIN ), 'value' => 'menu', ), + 'post' => array( + 'name' => 'post', + 'label' => __( 'Post content', OCS_DOMAIN ), + 'value' => 'post', + ), 'action' => array( 'name' => 'action', 'label' => __( 'Custom', OCS_DOMAIN ) . '   (' . __( 'Action hook', OCS_DOMAIN ) . ': ocs_custom_content_sidebar_ )', 'value' => 'action', ), ), - 'description' => __( 'Keep in mind that WordPress has menu and text widgets by default, the "sidebar" object is your best option in most cases.', OCS_DOMAIN ), + ), + 'content_id' => array( + 'name' => 'content_id', + 'hidden' => true, + 'default' => '', + 'type' => 'number', ), 'location' => array( 'name' => 'location', diff --git a/js/off-canvas-sidebars-settings.js b/js/off-canvas-sidebars-settings.js index 4d47ad7..436857a 100644 --- a/js/off-canvas-sidebars-settings.js +++ b/js/off-canvas-sidebars-settings.js @@ -16,7 +16,9 @@ if ( 'undefined' === typeof ocsOffCanvasSidebarsSettings ) { general_key: 'off_canvas_sidebars_options', plugin_key: 'off-canvas-sidebars-settings', css_prefix: 'ocs', - __required_fields_not_set: 'Some required fields are not set!' + _nonce: '', + __required_fields_not_set: 'Some required fields are not set!', + __search: 'Search', }; } @@ -59,6 +61,11 @@ if ( 'undefined' === typeof ocsOffCanvasSidebarsSettings ) { ocs_show_hide_options( global_settings_trigger, '.' + sidebar_prefix + '_disable_over', 'tr' ); ocs_show_hide_options( global_settings_trigger, '.' + sidebar_prefix + '_hide_control_classes', 'tr' ); ocs_show_hide_options( global_settings_trigger, '.' + sidebar_prefix + '_scroll_lock', 'tr' ); + + $this.find( 'input.off_canvas_sidebars_options_sidebars_content' ).on( 'click ocs_init', function() { + var $this = $( this ); + ocs_post_selector( sidebar_id, this, ( $this.is( ':checked' ) && 'post' === $this.val() ) ); + } ).filter( ':checked' ).trigger( 'ocs_init' ); } ); } else { ocs_show_hide_options_radio( @@ -118,6 +125,121 @@ if ( 'undefined' === typeof ocsOffCanvasSidebarsSettings ) { } ).trigger( 'change' ); } + /** + * Create a post selector with AJAX search. + * + * @since 0.6.0 + * @param {string} sidebar_id + * @param {string|object} elem + * @param {boolean} show + */ + function ocs_post_selector( sidebar_id, elem, show ) { + var $elem = $( elem ), + $label = $elem.parent(), + wrapper = 'off_canvas_sidebars_options_sidebars_content_id_wrapper', + input = 'off_canvas_sidebars_options_sidebars_content_id', + results = 'off_canvas_sidebars_options_sidebars_content_id_results', + $wrapper = $label.parent().find( '.' + wrapper ), + init = false; + + if ( ! show ) { + $wrapper.slideUp(); + return; + } + + if ( ! $wrapper.length ) { + init = true; + $label.append( '
' ); + $wrapper = $label.parent().find( '.' + wrapper ); + } else { + $wrapper.slideDown(); + } + + var $input = $wrapper.find( '.' + input ), + $results = $input.parent().find( '.' + results ), + $loading = $wrapper.find( '.ocs-loading' ), + ajax_delay_timer = null, + loading_interval = null; + + $input.on( 'keyup ocs_init', function() { + clearInterval( loading_interval ); + clearTimeout( ajax_delay_timer ); + if ( $loading.length ) { + $loading.hide(); + } + + var search = $input.val(); + + if ( ! search && ! init ) { + return; + } + + ajax_delay_timer = setTimeout( function() { + var loading = '. . . '; + + if ( ! $results.length ) { + $wrapper.append( '
' ); + $results = $input.parent().find( '.' + results ); + } else { + $results.find( '.ocs-result' ).remove(); + } + + if ( ! $loading.length ) { + $results.after( '
' ); + $loading = $wrapper.find( '.ocs-loading' ); + } + + $loading.text( loading ).show(); + + loading_interval = setInterval( function() { + if ( 20 < loading.length ) { + loading = '. . . '; + } + loading += '. '; + $loading.text( loading ); + }, 500 ); + + $.post( + ajaxurl, + { + action: 'ocs_get_posts', + ocs_nonce: ocsOffCanvasSidebarsSettings._nonce, + ocs_search: $input.val(), + ocs_sidebar_id: sidebar_id + }, + function( response ) { + clearInterval( loading_interval ); + clearTimeout( ajax_delay_timer ); + if ( $loading.length ) { + $loading.hide(); + } + if ( response.hasOwnProperty( 'success' ) && response.success ) { + var html = '', + name = $elem.attr( 'name' ).replace( '[content]', '[content_id]' ), + current = parseInt( response.data.current, 10 ); + + delete response.data.current; + for ( var id in response.data ) { + if ( ! response.data.hasOwnProperty( id ) ) { + continue; + } + + if ( parseInt( id, 10 ) === current ) { + html = '' + html; + } else { + html += ''; + } + } + $results.html( html ); + } + } + ); + + }, 500 ); + + } ).trigger( 'ocs_init' ); + } + // Enable the WP Color Picker. $( 'input.color-picker' ).wpColorPicker(); diff --git a/tests/test-settings.php b/tests/test-settings.php index 724aca3..b3ec137 100644 --- a/tests/test-settings.php +++ b/tests/test-settings.php @@ -211,6 +211,7 @@ function test_save() { 'enable' => 1, 'label' => 'Test', 'content' => 'menu', + 'content_id' => 0, 'location' => 'right', 'style' => 'overlay', 'size' => 'large', @@ -246,6 +247,7 @@ function test_save() { 'enable' => 'yes', // Parse as true (1) 'label' => 'Test strip_tags test', 'content' => array( 'action' ),// Invalid radio option, will return to default + 'content_id' => 'whoooo', 'location' => 'nope', // Invalid radio option, will return to default 'style' => false, // Invalid radio option, will return to default 'size' => 'nope', // Invalid radio option, will return to default @@ -271,6 +273,7 @@ function test_save() { 'enable' => 1, 'label' => 'Test strip_tags test', 'content' => 'sidebar', + 'content_id' => 0, 'location' => 'left', 'style' => 'push', 'size' => 'default', @@ -308,6 +311,7 @@ function test_save() { 'enable' => 1, 'label' => 'Test', 'content' => 'menu', + 'content_id' => 0, 'location' => 'right', 'style' => 'overlay', 'size' => 'large', @@ -337,6 +341,7 @@ function test_save() { 'enable' => 0, 'label' => 'Test rename', 'content' => 'menu', + 'content_id' => 0, 'location' => 'left', // update 'style' => 'push', // update 'size' => 'large', @@ -359,6 +364,7 @@ function test_save() { 'enable' => 1, 'label' => 'Test 2', 'content' => 'menu', + 'content_id' => 8, 'location' => 'right', 'style' => 'overlay', 'size' => 'large',