Cum să salvezi starea unui editor de layout drag and drop jQuery UI Sortables în interfața site-ului?

4 mai 2011, 17:12:19
Vizualizări: 29.8K
Voturi: 21

Construiesc un editor de layout pentru articole în interfața site-ului folosind jQuery UI Sortable.

Articolele sunt aranjate în cutii de 300px pe 250px peste o imagine de fundal. Articolele sunt create și editate din interfața de administrare WordPress dar vreau să permit administratorului site-ului să ajusteze ordinea cutiilor folosind o interfață drag and drop în frontend.

Am reușit să implementez partea de drag and drop sortable dar am nevoie de o metodă pentru a salva starea (ordinea) cutiilor. Ideal aș vrea să pot salva starea ca o opțiune și să o integrez în query.

Query-ul pentru articole este un simplu WP_Query care preia și date din custom meta boxes pentru a determina layout-ul individual al cutiilor:

$args= array(
      'meta_key' => 'c3m_shown_on', // cheia meta
       'meta_value'=> 'home' ); // valoarea meta
    $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="Imagine 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>

JavaScript-ul este doar instrucțiunea de bază pentru sortable

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

Există metode disponibile folosind cookie-uri pentru a salva starea dar trebuie să dezactivez și funcția de drag and drop pentru utilizatorii non-admin așa că am nevoie să salvez în baza de date.

Caut cea mai creativă și utilă metodă și voi acorda o recompensă de 100 de puncte pentru cel mai bun răspuns.

Update:

Am reușit să implementez răspunsul lui somatic cu o mică modificare.

ajaxurl nu returnează valoarea pe paginile non-admin așa că am folosit wp_localize_script( 'functions', 'MyAjax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) ); pentru a defini valoarea și am schimbat linia JavaScript de sub options în:
url: MyAjax.ajaxurl,

Pentru a limita accesul la aranjarea ordinii doar pentru administratori am adăugat o condiție la funcția mea 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' ) ) );
    }
}

O să mai fac câteva teste și voi marca această întrebare ca rezolvată și voi acorda recompensa.

3
Comentarii

Este posibil să folosești menu_order pe postări? Știu că poți să le folosești pe atașamente, deci de ce nu și pe postări? Dacă este posibil, aici ai putea stoca ordinea postărilor...

Scott Scott
6 mai 2011 19:05:37

Se pare că se poate - 'menu_order' - Ordonează după Ordinea Paginilor. Folosit cel mai des pentru Pagini (câmpul Ordine în caseta Editează Atributele Paginii) și pentru atașamente (câmpurile numerice în dialogul Inserează/Încarcă Galerie Media), dar ar putea fi folosit pentru orice tip de postare cu valori distincte 'menu_order' (toate au implicit valoarea 0).

Scott Scott
6 mai 2011 19:07:57

@Brady Idee excelentă cu utilizarea menu_order. @somatic a dezvoltat-o și a funcționat. Mulțumesc!

Chris_O Chris_O
8 mai 2011 06:12:15
Toate răspunsurile la întrebare 3
3
23

Brady are dreptate că cea mai bună metodă de a gestiona salvarea și afișarea ordinii postărilor personalizate este prin utilizarea proprietății menu_order.

Iată codul jQuery pentru a face lista sortabilă și pentru a transmite datele via AJAX către WordPress:

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

    itemList.sortable({
        update: function(event, ui) {
            $('#loading-animation').show(); // Afișează animația de încărcare în timp ce așteptăm

            opts = {
                url: ajaxurl, // ajaxurl este definit de WordPress și indică spre /wp-admin/admin-ajax.php
                type: 'POST',
                async: true,
                cache: false,
                dataType: 'json',
                data:{
                    action: 'item_sort', // Spune WordPress cum să gestioneze această cerere AJAX
                    order: itemList.sortable('toArray').toString() // Transmite ID-urile elementelor listei în format 1,3,2
                },
                success: function(response) {
                    $('#loading-animation').hide(); // Ascunde animația de încărcare
                    return; 
                },
                error: function(xhr,textStatus,e) {  // Poate fi extins pentru a furniza mai multe informații
                    alert(e);
                    // alert('A apărut o eroare la salvarea actualizărilor');
                    $('#loading-animation').hide(); // Ascunde animația de încărcare
                    return; 
                }
            };
            $.ajax(opts);
        }
    }); 
});

Iată funcția WordPress care ascultă pentru callback-ul AJAX și efectuează modificările în baza de date:

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

Cheia pentru afișarea postărilor în ordinea pe care ai salvat-o este adăugarea proprietății menu_order la argumentele query-ului:

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

$box_query = new WP_Query($args);

Apoi rulează loop-ul și afișează fiecare element... (prima linie este animația de încărcare WordPress - vei dori să o ascunzi inițial prin CSS, iar funcția jQuery o va afișa în timpul procesării)

<img src="<?php bloginfo('url'); ?>/wp-admin/images/loading.gif" id="loading-animation" alt="Animație încărcare" title="Se încarcă..." />
<ul id="sortable">
    <li id="{echo post ID here}">{echo title or other name here}</li>
</ul>

Cod inspirat din excelentul tutorial al lui soulsizzle.

7 mai 2011 00:26:16
Comentarii

Răspuns excelent. O să încerc.

Chris_O Chris_O
7 mai 2011 00:30:42

Mulțumesc mult pentru asta - m-a ajutat enorm la ce lucram și eu. O problemă pe care am întâmpinat-o a fost că fiecare element din lista sortabilă trebuie să aibă un ID care să corespundă cu ID-ul postării. Acest lucru era prezent în tutorialul lui soulsizzle, dar nu în postarea inițială.

Dalton Rooney Dalton Rooney
17 aug. 2011 23:51:31

Absolut corect, Dalton, am fost prea succint în exemplul meu. Cod actualizat.

somatic somatic
29 aug. 2011 04:11:06
0

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

Departe de a fi finalizat, dar ideea este de a trimite o cerere AJAX la efectuarea acțiunii de drag and drop. De asemenea, poți dori să declanșezi cererea AJAX doar după ce apeși pe un buton "salvează" sau similar. Un array care conține ID-urile postărilor și noua ordine ar fi trimis.

Apoi, ar trebui să actualizezi postările în baza de date pe partea de server. În final, adaugă un parametru order în bucla ta de WP_Query.

Sper că acest lucru te ajută să începi. Oricine poate continua să lucreze la acest exemplu.

4 mai 2011 18:04:34
2
/**
 *  Încarcă fișierele javascript și css
 */
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');


/**
 *  Actualizează ordinea postărilor prin ajax la declanșarea evenimentului de drag and drop
 */
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');


/**
 *  Afișează postările sortate
 */
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 );

Fișier 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', // Spune WordPress-ului cum să gestioneze această cerere ajax
                    order: '4567,4569,4565 ' // Transmite ID-urile elementelor listei în format 1,3,2. Scrie-ți propria metodă js pentru a accesa lista de id-uri din frontend.
                },
                success: function(data, response) {
                    console.log(response);
                },
                error: function(xhr,textStatus,e) {
                    alert(e);
                }

                });

        }
    });
28 mai 2019 03:05:41
Comentarii

Vă rugăm să nu doar să copiați codul. Vi se cere să adăugați o explicație, de ce credeți că codul de mai sus răspunde la întrebare.

Mayeenul Islam Mayeenul Islam
28 mai 2019 08:50:20

@MayeenulIslam Descrierea a fost deja adăugată în fragmentele de cod ca linii de comentariu.

SkyRar SkyRar
28 mai 2019 23:13:12