Como salvar o estado de um editor de layout de front end do arrastar e soltar jQuery UI Sortables?

20

Estou criando um editor de layout de postagem de front-end usando o jQuery UI Sortable .

As postagens são dispostas em caixas de 300 x 250 pixels sobre uma imagem de plano de fundo. As postagens são criadas e editadas usando o administrador do WordPress, mas quero permitir que o administrador dos sites ajuste a ordem das caixas usando uma interface de arrastar e soltar no front-end.

Eu tenho a parte classificável de arrastar e soltar funcionando, mas preciso criar uma maneira de salvar o estado (ordem) das caixas. Idealmente, eu gostaria de poder salvar o estado como uma opção e construí-lo na consulta.

A consulta para as postagens é um WP_Query simples que também obtém dados de meta boxes personalizadas para determinar o layout da caixa individual .:

$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>

O javascript é apenas as instruções classificáveis ​​padrão básicas

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

Existem métodos disponíveis usando cookies para salvar o estado, mas também preciso desativar o recurso de arrastar e soltar classificável para usuários que não são administradores, por isso realmente preciso salvar no banco de dados.

Estou procurando o método mais criativo e utilizável e concedo uma recompensa de 100 pontos à melhor resposta.

Atualizar:

Eu recebi a resposta da sommatic trabalhando com uma pequena alteração.

o ajaxurl não retorna o valor nas páginas que não são de administração, então eu costumava wp_localize_script( 'functions', 'MyAjax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );definir o valor e alterei a linha javascript em opções para:
url: MyAjax.ajaxurl,

Para limitar o acesso à organização do pedido apenas para administradores, adicionei um condicional à minha função 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' ) ) );
    }
}

Vou fazer um pouco mais de teste e marcar esta questão como resolvida e premiar a recompensa.

Chris_O
fonte
11
É possível usar o menu_order nas postagens? Sei que você pode usá-los em anexos. Por que não postar? se a sua possível este é o lugar onde você pode armazenar a ordem das mensagens ...
Brady
11
Parece que você pode - 'menu_order' - Ordenar por ordem de página. Usado com mais freqüência para Páginas (campo Pedido na caixa Editar atributos da página) e anexos (os campos inteiros na caixa de diálogo Inserir / Carregar galeria de mídia), mas pode ser usado para qualquer tipo de postagem com valores distintos 'menu_order' (todos padrão para 0).
Brady
@Brady Ótima idéia sobre o uso de menu_order. A @somatic expandiu e funcionou. Obrigado!
8892 Chris_O

Respostas:

21

A Brady está certa de que a melhor maneira de lidar com o salvamento e a exibição de pedidos de tipo de postagem personalizados é usando a menu_orderpropriedade

Aqui está o jquery para tornar a lista classificável e passar os dados via ajax para o 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);
        }
    }); 
});

Aqui está a função wordpress que escuta o retorno de chamada do ajax e executa as alterações no banco de dados:

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');

A chave para exibir as postagens na ordem que você salvou é adicionar a menu_orderpropriedade aos argumentos da consulta:

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

$box_query = new WP_Query($args);

Em seguida, execute seu loop e produza cada item ... (a primeira linha é a animação principal de carregamento do wp - você deseja ocultá-la inicialmente via css e a função jquery será exibida durante o processamento)

<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 no excelente tutorial de soulsizzle .

somático
fonte
Excelente resposta. Vou tentar.
67711 Chris_O
Muito obrigado por isso - totalmente ajudou em algo que eu estava trabalhando também. Um problema com o qual me deparei foi que cada item da lista classificável precisa ter um ID que corresponda ao ID da postagem. Isso estava no tutorial de soulsizzle, mas não no post do OP.
Dalton
Absolutamente certo, Dalton, fui breve demais no meu exemplo. Código atualizado.
sommatic
4

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

Longe de terminar, mas a idéia é enviar uma solicitação de ajax ao arrastar e soltar. Você também pode acionar a solicitação ajax somente depois de clicar em um botão "salvar" ou algo assim. Uma matriz contendo IDs de postagem e novo pedido seria enviada.

Então você teria que atualizar as postagens no banco de dados no final do servidor. Por fim, adicione um orderparâmetro ao seu WP_Queryloop.

Espero que isso ajude você. Qualquer um fica à vontade para continuar brincando.

Geert
fonte
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 );

Arquivo 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
fonte
Por favor, não despeje apenas o código. Você é solicitado a adicionar algumas explicações, por que o código acima responderá à pergunta.
Mayeenul Islam
A descrição @MayeenulIslam já foi adicionada dentro dos trechos de código como linha de comentário.
SkyRar