¿Cómo guardar el estado de un editor de diseño de front-end jQuery UI Sortables?

20

Estoy construyendo un editor de diseño de publicaciones front-end usando jQuery UI Sortable .

Las publicaciones se presentan en cuadros de 300 px por 250 px sobre una imagen de fondo. Las publicaciones se crean y editan utilizando el administrador de WordPress, pero quiero permitir que el administrador del sitio ajuste el orden de los cuadros mediante una interfaz de arrastrar y soltar en la parte frontal.

Tengo la parte ordenable de arrastrar y soltar funcionando, pero necesito encontrar una manera de guardar el estado (orden) de las cajas. Idealmente, me gustaría poder guardar el estado como una opción e incorporarlo a la consulta.

La consulta de las publicaciones es una simple WP_Query que también obtiene datos de meta cuadros personalizados para determinar el diseño individual de los cuadros:

$args= array(
      'meta_key' => 'c3m_shown_on',
       'meta_value'=> 'home' );
    $box_query = new WP_Query($args);  ?>
        <ul id="sortable">
            <?php
    while ($box_query->have_posts()) : $box_query->the_post(); global $post; global $prefix;           
    $box_size = c3m_get_field($prefix.'box_size', FALSE);
    $box_image = c3m_get_field($prefix.'post_box_image', FALSE);
    $overlay_class = c3m_get_field($prefix.'overlay_class', FALSE);

    if ( c3m_get_field($prefix.'external_link', FALSE) ) {
    $post_link = c3m_get_field($prefix.'external_link', FALSE);
    } else
            { $post_link = post_permalink(); 
    } ?>     
     <li class="<?php echo $box_size;?>  ui-state-default">
        <article <?php post_class() ?> id="post-<?php the_ID(); ?>">
            <?php echo  '<a href="'.$post_link.'" ><img src="'.esc_url($box_image).'" alt="Image via xxxxx.com" /></a>'; ?>
                <div class="post-box <?php echo $overlay_class;?>">
                <?php if ( c3m_get_field( $prefix.'text_display', FALSE) ) { ?>     
                <h2><a href="<?php echo $post_link?>"><?php the_title();?></a></h2> 
                <p><?php echo substr($post->post_excerpt, 0, 90) . '...'; ?></p>            
                <?php } ?>               
                </div>
         </article>
     </li>              
    <?php endwhile; ?>
       </ul>
</section>

El javascript es solo las instrucciones ordenables predeterminadas básicas

jQuery(document).ready(function() {
    jQuery("#sortable").sortable();
  });

Hay métodos disponibles que usan cookies para guardar el estado, pero también necesito deshabilitar la función de arrastrar y soltar ordenable para usuarios que no son administradores, por lo que realmente necesito guardar en la base de datos.

Estoy buscando el método más creativo y útil y otorgaré una recompensa de 100 puntos a la mejor respuesta.

Actualizar:

Tengo de somáticas responden a trabajar con un cambio menor.

ajaxurl no devuelve el valor en páginas que no son de administrador, así que solía wp_localize_script( 'functions', 'MyAjax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );definir el valor y cambié la línea de JavaScript en las opciones a:
url: MyAjax.ajaxurl,

Para limitar el acceso a la organización del pedido solo a los administradores, agregué un condicional a mi función wp_enqueue_script:

    function c3m_load_scripts() { 
    if ( current_user_can( 'edit_posts' ) ) {
        wp_enqueue_script( 'jquery-ui' );
        wp_enqueue_script( 'functions', get_bloginfo( 'stylesheet_directory' ) . '/_/js/functions.js', array( 'jquery', 'jquery-ui' ), false);
        wp_localize_script( 'functions', 'MyAjax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );
    }
}

Voy a hacer un poco más de pruebas y marcaré esta pregunta como resuelta y otorgaré la recompensa.

Chris_O
fuente
1
¿Es posible que puedas usar menu_order en las publicaciones? Sé que puedes usarlos en archivos adjuntos, ¿por qué no publicar? si su posible aquí es donde se puede almacenar el orden de los mensajes ...
Brady
1
Parece que puedes - 'menu_order' - Ordenar por orden de página. Se usa con mayor frecuencia para páginas (campo Orden en el cuadro Editar atributos de página) y para archivos adjuntos (los campos enteros en el cuadro de diálogo Insertar / cargar galería de medios), pero podría usarse para cualquier tipo de publicación con valores distintos de 'menú_orden' (todos predeterminados a 0).
Brady
@Brady Gran idea sobre el uso de menu_order. @somatic se expandió y funcionó. ¡Gracias!
Chris_O

Respuestas:

21

Brady tiene razón en que la mejor manera de manejar el almacenamiento y la visualización de órdenes de tipo de publicación personalizada es mediante el uso de la menu_orderpropiedad

Aquí está el jquery para hacer que la lista se pueda ordenar y pasar los datos a través de ajax a wordpress:

jQuery(document).ready(function($) {        
    var itemList = $('#sortable');

    itemList.sortable({
        update: function(event, ui) {
            $('#loading-animation').show(); // Show the animate loading gif while waiting

            opts = {
                url: ajaxurl, // ajaxurl is defined by WordPress and points to /wp-admin/admin-ajax.php
                type: 'POST',
                async: true,
                cache: false,
                dataType: 'json',
                data:{
                    action: 'item_sort', // Tell WordPress how to handle this ajax request
                    order: itemList.sortable('toArray').toString() // Passes ID's of list items in  1,3,2 format
                },
                success: function(response) {
                    $('#loading-animation').hide(); // Hide the loading animation
                    return; 
                },
                error: function(xhr,textStatus,e) {  // This can be expanded to provide more information
                    alert(e);
                    // alert('There was an error saving the updates');
                    $('#loading-animation').hide(); // Hide the loading animation
                    return; 
                }
            };
            $.ajax(opts);
        }
    }); 
});

Aquí está la función de wordpress que escucha la devolución de llamada ajax y realiza los cambios en la base de datos:

function my_save_item_order() {
    global $wpdb;

    $order = explode(',', $_POST['order']);
    $counter = 0;
    foreach ($order as $item_id) {
        $wpdb->update($wpdb->posts, array( 'menu_order' => $counter ), array( 'ID' => $item_id) );
        $counter++;
    }
    die(1);
}
add_action('wp_ajax_item_sort', 'my_save_item_order');
add_action('wp_ajax_nopriv_item_sort', 'my_save_item_order');

La clave para mostrar las publicaciones en el orden que ha guardado es agregar la menu_orderpropiedad a los argumentos de la consulta:

$args= array(
    'meta_key' => 'c3m_shown_on',
    'meta_value'=> 'home'
    'orderby' => 'menu_order',
    'order' => 'ASC'
);

$box_query = new WP_Query($args);

Luego ejecute su bucle y muestre cada elemento ... (la primera línea es la animación de carga de wp central; querrá ocultarlo inicialmente a través de css, y luego la función jquery se mostrará al procesar)

<img src="<?php bloginfo('url'); ?>/wp-admin/images/loading.gif" id="loading-animation" />
<ul id="sortable">
    <li id="{echo post ID here}">{echo title or other name here}</li>
</ul>

Código inspirado en el excelente tutorial de soulsizzle .

somático
fuente
Excelente respuesta Lo intentaré.
Chris_O
Muchas gracias por esto, también me ayudó totalmente en algo en lo que estaba trabajando. Un problema con el que me topé fue que cada elemento de la lista ordenable debe tener una ID que coincida con la ID de la publicación. Esto estaba en el tutorial de soulsizzle pero no en la publicación del OP.
Dalton
Absolutamente correcto, Dalton, fui demasiado breve en mi ejemplo. Código actualizado
somático
4

http://jsfiddle.net/TbR69/1/

Lejos de terminar, pero la idea es enviar una solicitud ajax en arrastrar y soltar. También es posible que desee activar la solicitud ajax solo después de hacer clic en el botón "Guardar" o algo así. Se enviará una matriz que contiene ID de publicaciones y un nuevo pedido.

Luego, tendría que actualizar las publicaciones en la base de datos en el extremo del servidor. Finalmente, agregue un orderparámetro a su WP_Queryciclo.

Espero que esto te ayude a comenzar. Cualquiera se sienta libre de seguir jugando.

Geert
fuente
0
/**
 *  Enqueue javascript and css files
 */
function uc_enqueue_my_assets() {
    wp_enqueue_script( 'jquery-ui-sortable');
    wp_register_script( 'order', plugins_url( '/js/order.js', __FILE__ ), array( 'jquery' ) );
    wp_enqueue_script( 'order' );
}

function uc_is_user_logged_in()
{
    if ( is_user_logged_in()) {
        add_action( 'wp_enqueue_scripts', 'uc_enqueue_my_assets' );
        add_action( 'admin_enqueue_scripts', 'uc_enqueue_my_assets' );
    }
}
add_action('init', 'uc_is_user_logged_in');


/**
 *  Update order of posts by ajax on trigger of drag and drop event
 */
function uc_sort_post_items() {

    $order = wp_parse_id_list(explode(',', $_POST['order']));
    write_log($order);

    global $wpdb;
    $list = join(', ', $order);
    $wpdb->query('SELECT @i:=0');
    $wpdb->query(
        "UPDATE wp_posts SET menu_order = ( @i:= @i+1 )
        WHERE ID IN ( $list ) ORDER BY FIELD( ID, $list );"
    );

    wp_die();
}
add_action('wp_ajax_uc_sort_post_items', 'uc_sort_post_items');
add_action('wp_ajax_nopriv_uc_sort_post_items', 'uc_sort_post_items');



/**
 *  Display sorted posts
 */
function uc_pre_get_posts( $wp_query ) {
    write_log(basename($_SERVER['PHP_SELF']));
    $wp_query->set('orderby', 'menu_order');
    $wp_query->set('order', 'ASC');
}
add_action( 'pre_get_posts', 'uc_pre_get_posts', 1 );

Archivo Javascript order.js

$('#the-list').sortable({
        update: function(event, ui) {

            $.ajax({

                url: '/wp-admin/admin-ajax.php',
                type: 'post',
                dataType: 'json',
                data:{
                    action: 'uc_sort_post_items', // Tell WordPress how to handle this ajax request
                    order: '4567,4569,4565 ' // Passes ID's of list items in  1,3,2 format. Write your own js method to access the list of id from frontend.
                },
                success: function(data, response) {
                    console.log(response);
                },
                error: function(xhr,textStatus,e) {
                    alert(e);
                }

                });

        }
    });
SkyRar
fuente
Por favor, no solo volcar el código. Se le solicita que agregue alguna explicación, por qué cree que el código anterior responderá la pregunta.
Mayeenul Islam
@MayeenulIslam La descripción ya se ha agregado dentro de los fragmentos de código como línea de comentarios.
SkyRar