Я использую следующий код, который преобразует любую иерархическую страницу или пользовательский тип записи с возможностью изменения порядка страниц с помощью простого перетаскивания. (также этот код также добавляет новый фильтр отображения на иерархические страницы, чтобы упростить задачу).
Проблема, с которой мне нужна помощь, которая в настоящее время не работает, заключается в возможности перетаскивания одного дерева страниц в другое дерево страниц или из существующего дерева страниц.
Может ли кто-нибудь предоставить модификации кода, необходимые для расширения этой возможности?
Если вы знаете лучший способ достичь тех же целей с помощью другого кода вместо расширения кода, представленного ниже, также опубликуйте его.
ОБНОВЛЕНО: я также разместил код здесь: https://gist.github.com/812204
ПРИМЕЧАНИЕ: для всех тех, кто хотел бы проверить это, просто сделайте следующее.
1. Скопируйте/вставьте приведенный ниже код в файл functions.php вашей темы.
///////////////////////////////////////////////////////////////////////////////////////////
// CODE TO ADD POST PER PAGE FILTER
///////////////////////////////////////////////////////////////////////////////////////////
add_filter( 'edit_posts_per_page', 'reorder_edit_posts_per_page', 10, 2 );
function reorder_edit_posts_per_page( $per_page, $post_type ) {
// CHECK USER PERMISSIONS
if ( !current_user_can('edit_others_pages') )
return;
$post_type_object = get_post_type_object( $post_type );
// ONLY APPLY TO HIERARCHICAL POST TYPE
if ( !$post_type_object->hierarchical )
return;
// ADD POST PER PAGE DROP DOWN UI
add_action( 'restrict_manage_posts', 'reorder_posts_per_page_filter' );
// ADD SPECIAL STYLES (MOVE CURSOR & SPINNING LOADER AFTER REORDER)
wp_enqueue_script( 'page-ordering', get_bloginfo('stylesheet_directory') . '/custom/js/page-resorting.js', array('jquery-ui-sortable'), '0.8.4', true );
add_action( 'admin_print_styles', 'reorder_admin_styles' );
if ( isset( $_GET['spo'] ) && is_numeric( $_GET['spo'] ) && ( $_GET['spo'] == -1 || ($_GET['spo']%10) == 0 ) ) :
global $edit_per_page, $user_ID;
$per_page = $_GET['spo'];
if ( $per_page == -1 )
$per_page = 99999;
update_user_option( $user_ID, $edit_per_page, $per_page );
endif;
return $per_page;
}
// STYLING CSS FOR THE AJAX
function reorder_admin_styles() {
echo '<style type="text/css">table.widefat tbody th, table.widefat tbody td { cursor: move; }</style>';
}
// FUNCTION TO CREATE THE NUMBER OF POSTS PER PAGE DROPDOWN UI
function reorder_posts_per_page_filter() {
global $per_page;
$spo = isset($_GET['spo']) ? (int)$_GET['spo'] : $per_page;
?>
Display:<select name="spo" style="width: 100px;">
<option<?php selected( $spo, -1 ); ?> value="-1"><?php _e('All Results'); ?></option>
<?php for( $i=10;$i<=100;$i+=10 ) : ?>
<option<?php selected( $spo, $i ); ?> value="<?php echo $i ?>"><?php echo $i; ?> <?php _e('Results'); ?></option>
<?php endfor; ?>
</select>
<?php
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ACTUAL AJAX REQUEST FOR SORTING PAGES
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
add_action( 'wp_ajax_simple_page_ordering', 'reorder_do_page_ordering' );
function reorder_do_page_ordering() {
// RECHECK PERMISSIONS
if ( !current_user_can('edit_others_pages') || !isset($_POST['id']) || empty($_POST['id']) || ( !isset($_POST['previd']) && !isset($_POST['nextid']) ) )
die(-1);
// IS IT A REAL POST?
if ( !$post = get_post( $_POST['id'] ) )
die(-1);
$previd = isset($_POST['previd']) ? $_POST['previd'] : false;
$nextid = isset($_POST['nextid']) ? $_POST['nextid'] : false;
if ( $previd ) {
// FETCH ALL THE SIBLINGS (RELATIVE ORDERING)
$siblings = get_posts(array( 'depth' => 1, 'numberposts' => -1, 'post_type' => $post->post_type, 'post_status' => 'publish,pending,draft,future,private', 'post_parent' => $post->post_parent, 'orderby' => 'menu_order', 'order' => 'ASC', 'exclude' => $post->ID ));
foreach( $siblings as $sibling ) :
// BEGIN UPDATING MENU ORDERS
if ( $sibling->ID == $previd ) {
$menu_order = $sibling->menu_order + 1;
// UPDATE THE ACTUAL MOVED POST TO 1 AFTER PREV
wp_update_post(array( 'ID' => $post->ID, 'menu_order' => $menu_order ));
continue;
}
// NOTHING LEFT TO DO - NUMBERS CORRECTLY PADDED
if ( isset($menu_order) && $menu_order < $sibling->menu_order )
break;
// NEED TO UPDATE THE SIBLINGS MENU ORDER AS WELL
if ( isset($menu_order) ) {
$menu_order++;
// UPDATE THE ACTUAL MOVED POST TO 1 AFTER PREV
wp_update_post(array( 'ID' => $sibling->ID, 'menu_order' => $menu_order ));
}
endforeach;
}
if ( !isset($menu_order) && $nextid ) {
// FETCH ALL THE SIBLINGS (RELATIVE ORDERING)
$siblings = get_posts(array( 'depth' => 1, 'numberposts' => -1, 'post_type' => $post->post_type, 'post_status' => 'publish,pending,draft,future,private', 'post_parent' => $post->post_parent, 'orderby' => 'menu_order', 'order' => 'DESC', 'exclude' => $post->ID ));
foreach( $siblings as $sibling ) :
// START UPDATING MENU ORDERS
if ( $sibling->ID == $nextid ) {
$menu_order = $sibling->menu_order - 1;
// UPDATE THE ACTUAL MOVED POST TO 1 AFTER PREV
wp_update_post(array( 'ID' => $post->ID, 'menu_order' => $menu_order ));
continue;
}
// NOTHING LEFT TO DO - NUMBER ALREADY PADDED
if ( isset($menu_order) && $menu_order > $sibling->menu_order )
break;
// NEED TO UPDATE THE SIBLING MENU ORDER
if ( isset($menu_order) ) {
$menu_order--;
// UPDATE THE ACTUAL MOVED POST TO 1 AFTER PREV
wp_update_post(array( 'ID' => $sibling->ID, 'menu_order' => $menu_order ));
}
endforeach;
}
// FETCH ALL THE SIBLINGS WITH RELATIVE ORDERING AND IF THE MOVED POST HAS CHILDREN REFRESH THE PAGE
$children = get_posts(array( 'depth' => 1, 'numberposts' => 1, 'post_type' => $post->post_type, 'post_status' => 'publish,pending,draft,future,private', 'post_parent' => $post->ID ));
if ( !empty($children) )
die('children');
die();
}
2- й шаг Поскольку приведенный ниже сценарий вызывает пользовательский js-файл, нам также необходимо создать и включить этот файл. Если вы не хотите изменять приведенный выше скрипт, создайте папку в корневом каталоге папки вашей темы и назовите ее «custom». Затем в этой папке создайте еще одну папку с именем «js». Затем создайте в этой папке новый файл с именем «page-resorting.js» и вставьте в этот файл следующий код. После того, как это будет сделано, вы сможете изменить порядок путем перетаскивания всех страниц в административной области.
/////////////////////////////////////////////////////////////////////////////////////////////////////
// THIS SCRIPT APPLIES TO THE CUSTOM SCRIPT MODIFICATION ALLOWING HIERARCHICAL PAGES TO BE REORDERED
/////////////////////////////////////////////////////////////////////////////////////////////////////
jQuery("table.widefat tbody").sortable({
cursor: 'move',
axis: 'y',
containment: 'table.widefat',
scrollSensitivity: 40,
helper: function(e, ui) {
ui.children().each(function() { jQuery(this).width(jQuery(this).width()); });
return ui;
},
start: function(event, ui) {
if ( ! ui.item.hasClass('alternate') ) ui.item.css( 'background-color', '#ffffff' );
ui.item.children('td, th').css('border','none');
ui.item.css( 'outline', '1px solid #dfdfdf' );
},
stop: function(event, ui) {
ui.item.removeAttr('style');
ui.item.children('td, th').removeAttr('style');
},
update: function(event, ui) {
if ( ui.item.hasClass('inline-editor') ) {
jQuery("table.widefat tbody").sortable('cancel');
alert( 'Please close the quick editor before reordering this item.' );
return;
}
var postid = ui.item.find('.check-column input').val(); // THIS POST ID
var postparent = ui.item.find('.post_parent').html(); // POST PARENT
var prevpostid = ui.item.prev().find('.check-column input').val();
var nextpostid = ui.item.next().find('.check-column input').val();
// can only sort in same tree
var prevpostparent = undefined;
if ( prevpostid != undefined ) {
var prevpostparent = ui.item.prev().find('.post_parent').html()
if ( prevpostparent != postparent) prevpostid = undefined;
}
var nextpostparent = undefined;
if ( nextpostid != undefined ) {
nextpostparent = ui.item.next().find('.post_parent').html();
if ( nextpostparent != postparent) nextpostid = undefined;
}
// DISPLAY AN ALERT MESSAGE IF ANY OF THE FOLLOWING TAKES PLACE
// IF PREVIOUS AND NEXT ARE NOT AT THE SAME TREE LEVEL OR NOT AT THE SAME TREE LEVEL AND THE PREVIOUS PAGE IS THE PARENT OF THE NEXT OR JUST MOVED BENEATH ITS OWN CHILDREN
if ( ( prevpostid == undefined && nextpostid == undefined ) || ( nextpostid == undefined && nextpostparent == prevpostid ) || ( nextpostid != undefined && prevpostparent == postid ) ) {
jQuery("table.widefat tbody").sortable('cancel');
alert( "SORRY, THIS ACTION IS NOT POSSIBLE!\n\n>>> WHY THIS DOES NOT WORK:\nDrag-and-Drop capabilities only work for items within their current tree.\n\n>>> HERE IS HOW YOU CAN MOVE IT:\nIn order to move this item to the location you specified you simply need to use the "Quick Edit" link and modify the associated "Parent" page.\n\n>>> LOCATING THE QUICK EDIT LINK:\nOn the post you want to move, just hover over the post title and click on the "Quick Edit" link which appears below the title." );
return;
}
// SHOW AJAX SPINNING SAVE ELEMENT
ui.item.find('.check-column input').hide().after('<img alt="processing" src="images/wpspin_light.gif" class="waiting" style="margin-left: 6px;" />');
// EXECUTE THE SORTING VIA AJAX
jQuery.post( ajaxurl, { action: 'simple_page_ordering', id: postid, previd: prevpostid, nextid: nextpostid }, function(response){
if ( response == 'children' ) window.location.reload();
else ui.item.find('.check-column input').show().siblings('img').remove();
});
// FIX CELL COLORS
jQuery( 'table.widefat tbody tr' ).each(function(){
var i = jQuery('table.widefat tbody tr').index(this);
if ( i%2 == 0 ) jQuery(this).addClass('alternate');
else jQuery(this).removeClass('alternate');
});
}
}).disableSelection();
Только что попробовала и это потрясающе! Я спрашивал об этом несколько месяцев назад… wordpress.stackexchange.com/questions/2/…
обновление: выпадающие списки в режиме быстрого редактирования не работают.
еще одно небольшое исправление, вы должны вернуть $per_page; при проверке разрешений пользователя и при применении к иерархическому типу записи.
Это много кода, который трудно отследить в таком виде. Не могли бы вы загрузить его в какой-нибудь репозиторий или github, чтобы с ним было проще иметь дело? Например, его можно легко загрузить в виде плагина.
@hakre — я посмотрю, что я могу сделать, чтобы это произошло сегодня
@aredwilli спасибо, что нашли время опубликовать распакованную версию, но имейте в виду, что почти любой (за редкими исключениями) распакованный файл js доступен с каждым пакетом wordpress как файл с префиксом (-dev) рядом с упакованным файлом. Поэтому обычно нет необходимости создавать списки для тех, файлы thpse уже находятся в сети, например: /wp-admin/js/nav-menu.dev.js
У меня не было версии для разработчиков в моем wp-admin, или я не видел ее. Я просто подумал, что не было ни одного для этого.
Не совсем ответ, но, возможно, ответ находится где-то внутри этого. Я распаковал js-скрипт navmenu и удалил код, который делает возможным перетаскивание сортируемых вложенных элементов навигации. Это некрасиво.
Я не думаю, что перетаскиваемые/сортируемые модули пользовательского интерфейса jQuery поддерживают вложенные элементы, и это, скорее всего, то, что сделает или сломает, заставите ли вы его работать таким образом. Сценарий navmenu имеет довольно глубокий и сложный для расшифровки набор объектов и функций, которые используются для вычисления внутренней и внешней ширины или глубины. Я бы попытался понять это, но у меня есть собственная проблема с моими почтовыми вложениями ajax, которые загружают плагин динамического метабокса и заставляют его работать правильно.
Возможно, просмотр этого даст вам некоторое представление о том, что вам нужно делать в вашем коде, если вы даже можете использовать jqUI.
Вот весь распакованный файл nav-menu.js, https://gist.github.com/820633. Возможно, вам понадобятся фрагменты, которые связывают все это вместе, чтобы понять смысл, которые я не включил.
Это метод инициализации sortables, который делает некоторые сумасшедшие алгебраические вещи, выглядящие как E=Mc2, лол.
Было бы неплохо, если бы у них была версия этого файла для разработчиков, как они делают с другими скриптами в WP. Минимизированные однобуквенные вары слишком сложны для меня прямо сейчас. Это просто Алфавитный суп.