Come salvare lo stato di un trascinamento della selezione dell'editor di layout front-end dell'interfaccia utente jQuery Sortables?


20

Sto costruendo un editor di layout di post front-end usando l' interfaccia utente jQuery ordinabile .

I post sono disposti in scatole da 300 x 250 scatole su un'immagine di sfondo. I post vengono creati e modificati utilizzando l'amministratore di WordPress ma voglio consentire all'amministratore dei siti di regolare l'ordine delle caselle utilizzando un'interfaccia di trascinamento della selezione sul front-end.

Ho la parte trascinabile ordinabile funzionante, ma ho bisogno di trovare un modo per salvare lo stato (ordine) delle scatole. Idealmente, vorrei essere in grado di salvare lo stato come opzione e incorporarlo nella query.

La query per i post è una semplice WP_Query che ottiene anche dati da meta box personalizzate per determinare il layout delle singole caselle .:

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

Il javascript è solo le istruzioni ordinabili predefinite di base

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

Esistono metodi disponibili che utilizzano i cookie per salvare lo stato, ma devo anche disabilitare il trascinamento della selezione ordinabile per gli utenti non amministratori, quindi ho davvero bisogno di salvare nel database.

Sto cercando il metodo più creativo e utilizzabile e assegnerò un premio di 100 punti alla migliore risposta.

Aggiornare:

Ho avuto la risposta di Somatic lavorando con un piccolo cambiamento.

ajaxurl non restituisce il valore su pagine non amministrative quindi ho usato wp_localize_script( 'functions', 'MyAjax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );per definire il valore e ho cambiato la riga javascript sotto le opzioni in:
url: MyAjax.ajaxurl,

Per limitare l'accesso alla disposizione dell'ordine ai soli amministratori, ho aggiunto un condizionale alla mia funzione 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' ) ) );
    }
}

Proverò un po 'di più e segnerò questa domanda come risolta e assegnerò il premio.


1
È possibile che tu possa utilizzare menu_order sui post? So che puoi usarli sugli allegati, quindi perché non pubblicare post? se è possibile questo è dove è possibile memorizzare l'ordine dei messaggi ...
Brady,

1
Sembra che tu possa - 'menu_order' - Ordina per Ordine pagine. Utilizzato più spesso per Pages (campo Ordine nella casella Modifica attributi pagina) e per gli allegati (i campi interi nella finestra di dialogo Inserisci / Carica galleria multimediale), ma potrebbe essere utilizzato per qualsiasi tipo di post con valori 'menu_order' distinti (tutti predefiniti a 0).
Brady,

@Brady Ottima idea sull'uso di menu_order. @somatic si è espanso e ha funzionato. Grazie!
Chris_O

Risposte:


21

Brady ha ragione sul fatto che il modo migliore per gestire il salvataggio e la visualizzazione di ordini di tipo di posta personalizzati è utilizzando la menu_orderproprietà

Ecco il jquery per rendere ordinabile l'elenco e passare i dati tramite 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);
        }
    }); 
});

Ecco la funzione wordpress che ascolta il callback ajax ed esegue le modifiche sul DB:

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 chiave per visualizzare i post nell'ordine salvato è aggiungere la menu_orderproprietà alla query args:

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

$box_query = new WP_Query($args);

Quindi esegui il tuo ciclo e visualizza ogni elemento ... (la prima riga è l'animazione di caricamento core di wp - ti consigliamo di nasconderla inizialmente tramite CSS, quindi la funzione jquery verrà visualizzata durante l'elaborazione)

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

Codice ispirato all'eccellente tutorial di Soulsizzle .


Risposta eccellente. Ci proverò.
Chris_O,

Grazie mille per questo - mi ha aiutato totalmente anche su qualcosa a cui stavo lavorando. Un problema che ho riscontrato è che ogni elemento nell'elenco ordinabile deve avere un ID che corrisponda all'ID del post. Questo era nel tutorial di Soulsizzle ma non nel post del PO.
Dalton,

Assolutamente vero, Dalton, ero troppo breve nel mio esempio. Codice aggiornato
somatico

4

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

Lungi dall'essere finito, ma l'idea è di inviare una richiesta Ajax su trascinamento della selezione. Puoi anche attivare la richiesta Ajax solo dopo aver fatto clic su un pulsante "Salva" o qualcosa del genere. Verrà inviato un array contenente ID post e nuovo ordine.

Quindi dovresti aggiornare i post nel database sul lato server. Infine, aggiungi un orderparametro al tuo WP_Queryloop.

Spero che questo ti inizi. Chiunque si senta libero di continuare a giocherellare.


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

File 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);
                }

                });

        }
    });

Per favore, non solo scaricare il codice. Ti viene chiesto di aggiungere alcune spiegazioni, perché pensi che il codice sopra risponderà alla domanda.
Mayeenul Islam

@MayeenulIslam La descrizione è già stata aggiunta negli snippet di codice come riga di commento.
SkyRar,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.