Je construis un éditeur de mise en page avant avec jQuery UI Sortable .
Les messages sont disposés dans des boîtes 300px par 250px sur une image de fond. Les publications sont créées et éditées à l’aide de l’administrateur de WordPress, mais je veux permettre à l’administrateur du site d’ajuster l’ordre des boîtes à l’aide d’une interface glisser-déposer au front-end.
La partie triable par glisser-déposer fonctionne, mais je dois trouver un moyen de sauvegarder l'état des boîtes. Idéalement, j'aimerais pouvoir enregistrer l'état en tant qu'option et l'intégrer à la requête.
La requête pour les publications est un simple WP_Query qui récupère également des données à partir de boîtes de méta personnalisées pour déterminer la présentation de chaque boîte.
$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>
Le javascript n'est que la base des instructions triables par défaut
jQuery(document).ready(function() {
jQuery("#sortable").sortable();
});
Il existe des méthodes disponibles en utilisant cookies pour sauvegarder l’état, mais je dois aussi désactiver le glisser-déposer triable pour les utilisateurs non-administrateurs, donc j’ai vraiment besoin de sauvegarder dans la base de données.
Je recherche la méthode la plus créative et la plus utilisable et attribuerai une prime de 100 points à la meilleure réponse.
J'ai eu la réponse somatique en travaillant avec un changement mineur.
ajaxurl ne renvoyant pas la valeur sur les pages non admin, j'ai donc utilisé wp_localize_script( 'functions', 'MyAjax', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );
pour définir la valeur et modifié la ligne javascript sous options en:url: MyAjax.ajaxurl,
Pour limiter l'accès à la commande aux seuls administrateurs, j'ai ajouté une condition à ma fonction 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' ) ) );
}
}
Je vais faire un peu plus de tests et marquer cette question comme résolue et attribuer la prime.
Brady a raison de dire que le meilleur moyen de gérer la sauvegarde et l'affichage des commandes de type publication personnalisées est d'utiliser la propriété menu_order
.
Voici la requête pour rendre la liste triable et pour transmettre les données via ajax à 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);
}
});
});
Voici la fonction wordpress qui écoute le rappel ajax et effectue les modifications sur la base de données:
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 clé pour afficher les publications dans l'ordre que vous avez enregistré consiste à ajouter la propriété menu_order
aux arguments de la requête:
$args= array(
'meta_key' => 'c3m_shown_on',
'meta_value'=> 'home'
'orderby' => 'menu_order',
'order' => 'ASC'
);
$box_query = new WP_Query($args);
Ensuite, lancez votre boucle et sortez chaque élément ... (la première ligne est l’animation de chargement wp principale - vous voudrez le cacher initialement via css, puis la fonction jquery s’affichera lors du traitement)
<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>
Code inspiré par soulsizzle's excellent tutoriel .
Loin d’être terminé, l’idée est d’envoyer une requête ajax par glisser-déposer. Vous pouvez également vouloir déclencher la demande ajax uniquement après avoir cliqué sur un bouton "Enregistrer" ou quelque chose du genre. Un tableau contenant les identifiants de poste et le nouvel ordre serait envoyé.
Ensuite, vous devrez mettre à jour les publications de la base de données côté serveur. Enfin, ajoutez un paramètre order
à votre boucle WP_Query
.
J'espère que cela vous permet de commencer. N'importe qui peut continuer à jouer du violon.
/**
* 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 );
Fichier 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);
}
});
}
});