Simple Page Ordering - Version 2.2

Version Description

  • Updated look and feel to better match WordPress 3.8 admin redesign
  • Improved awareness of and compatibility with Quick Edit (inline editor)
  • Prevent collisions with themes and plugins bundling Simple Page Ordering
Download this release

Release Info

Developer jakemgold
Plugin Icon 128x128 Simple Page Ordering
Version 2.2
Comparing to
See all releases

Code changes from version 2.1.2 to 2.2

readme.txt CHANGED
@@ -2,9 +2,9 @@
2
  Contributors: jakemgold, 10up, thinkoomph
3
  Donate link: http://10up.com/plugins/simple-page-ordering-wordpress/
4
  Tags: order, re-order, ordering, pages, page, manage, menu_order, hierarchical, ajax, drag-and-drop, admin
5
- Requires at least: 3.4
6
- Tested up to: 3.6
7
- Stable tag: 2.1.2
8
 
9
  Order your pages and other hierarchical post types with simple drag and drop right from the standard page list.
10
 
@@ -77,6 +77,11 @@ This feature is already built into WordPress natively, but a bit tucked away. If
77
 
78
  == Changelog ==
79
 
 
 
 
 
 
80
  = 2.1.2 =
81
  * Bug fix: hierarchical custom post types without page-attributes was still broken - doh!
82
  * Bug fix: extreme edge case where post columns did not include the post title now supported
2
  Contributors: jakemgold, 10up, thinkoomph
3
  Donate link: http://10up.com/plugins/simple-page-ordering-wordpress/
4
  Tags: order, re-order, ordering, pages, page, manage, menu_order, hierarchical, ajax, drag-and-drop, admin
5
+ Requires at least: 3.8
6
+ Tested up to: 3.9
7
+ Stable tag: 2.2
8
 
9
  Order your pages and other hierarchical post types with simple drag and drop right from the standard page list.
10
 
77
 
78
  == Changelog ==
79
 
80
+ = 2.2 =
81
+ * Updated look and feel to better match WordPress 3.8 admin redesign
82
+ * Improved awareness of and compatibility with Quick Edit (inline editor)
83
+ * Prevent collisions with themes and plugins bundling Simple Page Ordering
84
+
85
  = 2.1.2 =
86
  * Bug fix: hierarchical custom post types without page-attributes was still broken - doh!
87
  * Bug fix: extreme edge case where post columns did not include the post title now supported
screenshot-1.png DELETED
Binary file
screenshot-2.png DELETED
Binary file
simple-page-ordering.css CHANGED
@@ -1,40 +1,31 @@
1
  .wp-list-table .ui-sortable tr {
2
  cursor: move;
3
  }
4
- .wp-list-table .spo-updating tr {
 
 
5
  cursor: default;
6
  }
 
7
  .wp-list-table .ui-sortable-placeholder {
8
- border: 0;
9
- height: 51px;
10
- background: #808080;
11
- background-image: -webkit-gradient(linear, left bottom, left top, from(#6d6d6d), to(#808080));
12
- background-image: -webkit-linear-gradient(bottom, #6d6d6d, #808080);
13
- background-image: -moz-linear-gradient(bottom, #6d6d6d, #808080);
14
- background-image: -o-linear-gradient(bottom, #6d6d6d, #808080);
15
- background-image: linear-gradient(to top, #6d6d6d, #808080);
16
  visibility: visible !important;
17
  }
18
  .wp-list-table .ui-sortable-helper {
19
  background-color: #fff;
20
- margin-left: -1px;
21
- border: 1px solid #dfdfdf;
22
  }
23
- .wp-list-table .ui-sortable-helper th,
24
- .wp-list-table .ui-sortable-helper td {
25
- border-bottom-width: 0 !important;
26
- }
27
-
28
  .spo-updating-row .check-column {
29
- background: url('../../../wp-admin/images/wpspin_light.gif') center no-repeat;
30
  }
31
  @media print,
32
  (-o-min-device-pixel-ratio: 5/4),
33
  (-webkit-min-device-pixel-ratio: 1.25),
34
  (min-resolution: 120dpi) {
35
  .spo-updating-row .check-column {
36
- background-image: url('../../../wp-admin/images/wpspin_light-2x.gif');
37
- background-size: 16px 16px;
38
  }
39
  }
40
  .spo-updating-row .check-column input {
1
  .wp-list-table .ui-sortable tr {
2
  cursor: move;
3
  }
4
+
5
+ .wp-list-table .spo-updating tr,
6
+ .wp-list-table .ui-sortable tr.inline-editor {
7
  cursor: default;
8
  }
9
+
10
  .wp-list-table .ui-sortable-placeholder {
11
+ outline: 1px dashed #bbb;
12
+ background: #F1F1F1;
 
 
 
 
 
 
13
  visibility: visible !important;
14
  }
15
  .wp-list-table .ui-sortable-helper {
16
  background-color: #fff;
17
+ outline: 1px solid #e1e1e1;
 
18
  }
 
 
 
 
 
19
  .spo-updating-row .check-column {
20
+ background: url('../../../wp-admin/images/spinner.gif') 11px 11px no-repeat;
21
  }
22
  @media print,
23
  (-o-min-device-pixel-ratio: 5/4),
24
  (-webkit-min-device-pixel-ratio: 1.25),
25
  (min-resolution: 120dpi) {
26
  .spo-updating-row .check-column {
27
+ background-image: url('../../../wp-admin/images/spinner-2x.gif');
28
+ background-size: 20px 20px;
29
  }
30
  }
31
  .spo-updating-row .check-column input {
simple-page-ordering.dev.js CHANGED
@@ -63,11 +63,16 @@ sortable_post_table.sortable({
63
  cursor: 'move',
64
  axis: 'y',
65
  containment: 'table.widefat',
66
- scrollSensitivity: 40,
67
  cancel: '.inline-edit-row',
68
- distance: 5,
69
- opacity: .85,
70
- forceHelperSize: true,
 
 
 
 
 
 
71
  update: function(event, ui) {
72
  sortable_post_table.sortable('disable').addClass('spo-updating');
73
  ui.item.addClass('spo-updating-row');
@@ -99,5 +104,6 @@ sortable_post_table.sortable({
99
  jQuery( table_rows[table_row_count]).removeClass('alternate');
100
  }
101
  }
 
102
  }
103
  });
63
  cursor: 'move',
64
  axis: 'y',
65
  containment: 'table.widefat',
 
66
  cancel: '.inline-edit-row',
67
+ distance: 2,
68
+ opacity: .8,
69
+ tolerance: 'pointer',
70
+ start: function(e, ui){
71
+ if ( typeof(inlineEditPost) !== 'undefined' ) {
72
+ inlineEditPost.revert();
73
+ }
74
+ ui.placeholder.height(ui.item.height());
75
+ },
76
  update: function(event, ui) {
77
  sortable_post_table.sortable('disable').addClass('spo-updating');
78
  ui.item.addClass('spo-updating-row');
104
  jQuery( table_rows[table_row_count]).removeClass('alternate');
105
  }
106
  }
107
+ // fix quick edit
108
  }
109
  });
simple-page-ordering.js CHANGED
@@ -1 +1 @@
1
- function update_simple_ordering_callback(e){if("children"===e){window.location.reload();return}var t=jQuery.parseJSON(e);var n=t.new_pos;for(var r in n){if("next"===r)continue;var i=document.getElementById("inline_"+r);if(null!==i&&n.hasOwnProperty(r)){var s=i.querySelector(".menu_order");if(undefined!==n[r]["menu_order"]){if(null!==s)s.innerHTML=n[r]["menu_order"];var o=i.querySelector(".post_parent");if(null!==o)o.innerHTML=n[r]["post_parent"];var u=null;var a=i.querySelector(".post_title");if(null!==a)u=a.innerHTML;var f=0;while(f<n[r]["depth"]){u=" "+u;f++}var l=i.parentNode.querySelector(".row-title");if(null!==l&&null!==u)l.innerHTML=u}else if(null!==s){s.innerHTML=n[r]}}}if(t.next){jQuery.post(ajaxurl,{action:"simple_page_ordering",id:t.next["id"],previd:t.next["previd"],nextid:t.next["nextid"],start:t.next["start"],excluded:t.next["excluded"]},update_simple_ordering_callback)}else{jQuery(document.querySelector(".spo-updating-row")).removeClass("spo-updating-row");sortable_post_table.removeClass("spo-updating").sortable("enable")}}var sortable_post_table=jQuery(document.querySelector(".wp-list-table tbody"));sortable_post_table.sortable({items:"> tr",cursor:"move",axis:"y",containment:"table.widefat",scrollSensitivity:40,cancel:".inline-edit-row",distance:5,opacity:.85,forceHelperSize:true,update:function(e,t){sortable_post_table.sortable("disable").addClass("spo-updating");t.item.addClass("spo-updating-row");var n=t.item[0].id.substr(5);var r=false;var i=t.item.prev();if(i.length>0){r=i.attr("id").substr(5)}var s=false;var o=t.item.next();if(o.length>0){s=o.attr("id").substr(5)}jQuery.post(ajaxurl,{action:"simple_page_ordering",id:n,previd:r,nextid:s},update_simple_ordering_callback);var u=document.querySelectorAll("tr.iedit"),a=u.length;while(a--){if(a%2==0){jQuery(u[a]).addClass("alternate")}else{jQuery(u[a]).removeClass("alternate")}}}})
1
+ function update_simple_ordering_callback(e){if("children"===e){window.location.reload();return}var t=jQuery.parseJSON(e);var n=t.new_pos;for(var r in n){if("next"===r)continue;var i=document.getElementById("inline_"+r);if(null!==i&&n.hasOwnProperty(r)){var s=i.querySelector(".menu_order");if(undefined!==n[r]["menu_order"]){if(null!==s)s.innerHTML=n[r]["menu_order"];var o=i.querySelector(".post_parent");if(null!==o)o.innerHTML=n[r]["post_parent"];var u=null;var a=i.querySelector(".post_title");if(null!==a)u=a.innerHTML;var f=0;while(f<n[r]["depth"]){u="&mdash; "+u;f++}var l=i.parentNode.querySelector(".row-title");if(null!==l&&null!==u)l.innerHTML=u}else if(null!==s){s.innerHTML=n[r]}}}if(t.next){jQuery.post(ajaxurl,{action:"simple_page_ordering",id:t.next["id"],previd:t.next["previd"],nextid:t.next["nextid"],start:t.next["start"],excluded:t.next["excluded"]},update_simple_ordering_callback)}else{jQuery(document.querySelector(".spo-updating-row")).removeClass("spo-updating-row");sortable_post_table.removeClass("spo-updating").sortable("enable")}}var sortable_post_table=jQuery(document.querySelector(".wp-list-table tbody"));sortable_post_table.sortable({items:"> tr",cursor:"move",axis:"y",containment:"table.widefat",cancel:".inline-edit-row",distance:2,opacity:.8,tolerance:"pointer",start:function(e,t){if(typeof inlineEditPost!=="undefined"){inlineEditPost.revert()}t.placeholder.height(t.item.height())},update:function(e,t){sortable_post_table.sortable("disable").addClass("spo-updating");t.item.addClass("spo-updating-row");var n=t.item[0].id.substr(5);var r=false;var i=t.item.prev();if(i.length>0){r=i.attr("id").substr(5)}var s=false;var o=t.item.next();if(o.length>0){s=o.attr("id").substr(5)}jQuery.post(ajaxurl,{action:"simple_page_ordering",id:n,previd:r,nextid:s},update_simple_ordering_callback);var u=document.querySelectorAll("tr.iedit"),a=u.length;while(a--){if(a%2==0){jQuery(u[a]).addClass("alternate")}else{jQuery(u[a]).removeClass("alternate")}}}})
simple-page-ordering.php CHANGED
@@ -3,46 +3,84 @@
3
  Plugin Name: Simple Page Ordering
4
  Plugin URI: http://10up.com/plugins/simple-page-ordering-wordpress/
5
  Description: Order your pages and hierarchical post types using drag and drop on the built in page list. For further instructions, open the "Help" tab on the Pages screen.
6
- Version: 2.1.2
7
  Author: Jake Goldman, 10up
8
  Author URI: http://10up.com
9
  License: GPLv2 or later
10
  */
11
 
 
 
12
  class Simple_Page_Ordering {
13
 
14
- public function __construct() {
15
- add_action( 'load-edit.php', array( $this, 'load_edit_screen' ) );
16
- add_action( 'wp_ajax_simple_page_ordering', array( $this, 'ajax_simple_page_ordering' ) );
 
 
 
 
 
 
 
 
 
 
 
 
17
  }
18
 
19
- public function load_edit_screen() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  $screen = get_current_screen();
21
  $post_type = $screen->post_type;
22
 
23
  // is post type sortable?
24
  $sortable = ( post_type_supports( $post_type, 'page-attributes' ) || is_post_type_hierarchical( $post_type ) ); // check permission
25
- if ( ! $sortable = apply_filters( 'simple_page_ordering_is_sortable', $sortable, $post_type ) )
26
  return;
 
27
 
28
  // does user have the right to manage these post objects?
29
- if ( ! $this->check_edit_others_caps( $post_type ) )
30
  return;
 
31
 
32
- add_filter( 'views_' . $screen->id, array( $this, 'sort_by_order_link' ) ); // add view by menu order to views
33
- add_action( 'wp', array( $this, 'wp' ) );
34
- add_action( 'admin_head', array( $this, 'admin_head' ) );
35
  }
36
 
37
- public function wp() {
38
- if ( 0 === strpos( get_query_var('orderby'), 'menu_order' ) ) { // we can only sort if we're organized by menu order
 
 
 
39
  $script_name = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? 'simple-page-ordering.dev.js' : 'simple-page-ordering.js';
40
  wp_enqueue_script( 'simple-page-ordering', plugins_url( $script_name, __FILE__ ), array('jquery-ui-sortable'), '2.1', true );
41
  wp_enqueue_style( 'simple-page-ordering', plugins_url( 'simple-page-ordering.css', __FILE__ ) );
42
  }
43
  }
44
 
45
- public function admin_head() {
 
 
 
46
  $screen = get_current_screen();
47
  $screen->add_help_tab(array(
48
  'id' => 'simple_page_ordering_help_tab',
@@ -51,22 +89,26 @@ class Simple_Page_Ordering {
51
  ));
52
  }
53
 
54
- public function ajax_simple_page_ordering() {
55
  // check and make sure we have what we need
56
- if ( empty( $_POST['id'] ) || ( !isset( $_POST['previd'] ) && !isset( $_POST['nextid'] ) ) )
57
  die(-1);
 
58
 
59
  // real post?
60
- if ( ! $post = get_post( $_POST['id'] ) )
61
  die(-1);
 
62
 
63
  // does user have the right to manage these post objects?
64
- if ( ! $this->check_edit_others_caps( $post->post_type ) )
65
  die(-1);
 
66
 
67
  // badly written plug-in hooks for save post can break things
68
- if ( !defined( 'WP_DEBUG' ) || !WP_DEBUG )
69
  error_reporting( 0 );
 
70
 
71
  $previd = empty( $_POST['previd'] ) ? false : (int) $_POST['previd'];
72
  $nextid = empty( $_POST['nextid'] ) ? false : (int) $_POST['nextid'];
@@ -90,12 +132,14 @@ class Simple_Page_Ordering {
90
  }
91
  }
92
  // if the next post's parent isn't our parent, it might as well be false (irrelevant to our query)
93
- if ( $next_post_parent !== $parent_id )
94
  $nextid = false;
 
95
 
96
  $max_sortable_posts = (int) apply_filters( 'simple_page_ordering_limit', 50 ); // should reliably be able to do about 50 at a time
97
- if ( $max_sortable_posts < 5 ) // don't be ridiculous!
98
  $max_sortable_posts = 50;
 
99
 
100
  // we need to handle all post stati, except trash (in case of custom stati)
101
  $post_stati = get_post_stati(array(
@@ -123,8 +167,9 @@ class Simple_Page_Ordering {
123
  foreach( $siblings->posts as $sibling ) :
124
 
125
  // don't handle the actual post
126
- if ( $sibling->ID === $post->ID )
127
  continue;
 
128
 
129
  // if this is the post that comes after our repositioned post, set our repositioned post position and increment menu order
130
  if ( $nextid === $sibling->ID ) {
@@ -210,7 +255,13 @@ class Simple_Page_Ordering {
210
  die( json_encode( $return_data ) );
211
  }
212
 
213
- public function sort_by_order_link( $views ) {
 
 
 
 
 
 
214
  $class = ( get_query_var('orderby') == 'menu_order title' ) ? 'current' : '';
215
  $query_string = remove_query_arg(array( 'orderby', 'order' ));
216
  $query_string = add_query_arg( 'orderby', urlencode('menu_order title'), $query_string );
@@ -221,14 +272,16 @@ class Simple_Page_Ordering {
221
  /**
222
  * Checks to see if the current user has the capability to "edit others" for a post type
223
  *
224
- * @param (string) $post_type Post type name
225
- * @return (bool) True or false
226
  */
227
- public function check_edit_others_caps( $post_type ) {
228
  $post_type_object = get_post_type_object( $post_type );
229
  $edit_others_cap = empty( $post_type_object ) ? 'edit_others_' . $post_type . 's' : $post_type_object->cap->edit_others_posts;
230
  return apply_filters( 'simple_page_ordering_edit_rights', current_user_can( $edit_others_cap ), $post_type );
231
  }
232
  }
233
 
234
- $simple_page_ordering = new Simple_Page_Ordering;
 
 
3
  Plugin Name: Simple Page Ordering
4
  Plugin URI: http://10up.com/plugins/simple-page-ordering-wordpress/
5
  Description: Order your pages and hierarchical post types using drag and drop on the built in page list. For further instructions, open the "Help" tab on the Pages screen.
6
+ Version: 2.2
7
  Author: Jake Goldman, 10up
8
  Author URI: http://10up.com
9
  License: GPLv2 or later
10
  */
11
 
12
+ if ( ! class_exists( 'Simple_Page_Ordering' ) ) :
13
+
14
  class Simple_Page_Ordering {
15
 
16
+ /**
17
+ * Handles initializing this class and returning the singleton instance after it's been cached.
18
+ *
19
+ * @return null|Simple_page_Ordering
20
+ */
21
+ public static function get_instance() {
22
+ // Store the instance locally to avoid private static replication
23
+ static $instance = null;
24
+
25
+ if ( null === $instance ) {
26
+ $instance = new self();
27
+ self::_add_actions();
28
+ }
29
+
30
+ return $instance;
31
  }
32
 
33
+ /**
34
+ * An empty constructor
35
+ */
36
+ public function __construct() { /* Purposely do nothing here */ }
37
+
38
+ /**
39
+ * Handles registering hooks that initialize this plugin.
40
+ */
41
+ public static function _add_actions() {
42
+ add_action( 'load-edit.php', array( __CLASS__, 'load_edit_screen' ) );
43
+ add_action( 'wp_ajax_simple_page_ordering', array( __CLASS__, 'ajax_simple_page_ordering' ) );
44
+ }
45
+
46
+ /**
47
+ * Load up page ordering scripts for the edit screen
48
+ */
49
+ public static function load_edit_screen() {
50
  $screen = get_current_screen();
51
  $post_type = $screen->post_type;
52
 
53
  // is post type sortable?
54
  $sortable = ( post_type_supports( $post_type, 'page-attributes' ) || is_post_type_hierarchical( $post_type ) ); // check permission
55
+ if ( ! $sortable = apply_filters( 'simple_page_ordering_is_sortable', $sortable, $post_type ) ) {
56
  return;
57
+ }
58
 
59
  // does user have the right to manage these post objects?
60
+ if ( ! self::check_edit_others_caps( $post_type ) ) {
61
  return;
62
+ }
63
 
64
+ add_filter( 'views_' . $screen->id, array( __CLASS__, 'sort_by_order_link' ) ); // add view by menu order to views
65
+ add_action( 'wp', array( __CLASS__, 'wp' ) );
66
+ add_action( 'admin_head', array( __CLASS__, 'admin_head' ) );
67
  }
68
 
69
+ /**
70
+ * when we load up our posts query, if we're actually sorting by menu order, initialize sorting scripts
71
+ */
72
+ public static function wp() {
73
+ if ( 0 === strpos( get_query_var('orderby'), 'menu_order' ) ) {
74
  $script_name = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? 'simple-page-ordering.dev.js' : 'simple-page-ordering.js';
75
  wp_enqueue_script( 'simple-page-ordering', plugins_url( $script_name, __FILE__ ), array('jquery-ui-sortable'), '2.1', true );
76
  wp_enqueue_style( 'simple-page-ordering', plugins_url( 'simple-page-ordering.css', __FILE__ ) );
77
  }
78
  }
79
 
80
+ /**
81
+ * Add page ordering help to the help tab
82
+ */
83
+ public static function admin_head() {
84
  $screen = get_current_screen();
85
  $screen->add_help_tab(array(
86
  'id' => 'simple_page_ordering_help_tab',
89
  ));
90
  }
91
 
92
+ public static function ajax_simple_page_ordering() {
93
  // check and make sure we have what we need
94
+ if ( empty( $_POST['id'] ) || ( !isset( $_POST['previd'] ) && !isset( $_POST['nextid'] ) ) ) {
95
  die(-1);
96
+ }
97
 
98
  // real post?
99
+ if ( ! $post = get_post( $_POST['id'] ) ) {
100
  die(-1);
101
+ }
102
 
103
  // does user have the right to manage these post objects?
104
+ if ( ! self::check_edit_others_caps( $post->post_type ) ) {
105
  die(-1);
106
+ }
107
 
108
  // badly written plug-in hooks for save post can break things
109
+ if ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) {
110
  error_reporting( 0 );
111
+ }
112
 
113
  $previd = empty( $_POST['previd'] ) ? false : (int) $_POST['previd'];
114
  $nextid = empty( $_POST['nextid'] ) ? false : (int) $_POST['nextid'];
132
  }
133
  }
134
  // if the next post's parent isn't our parent, it might as well be false (irrelevant to our query)
135
+ if ( $next_post_parent !== $parent_id ) {
136
  $nextid = false;
137
+ }
138
 
139
  $max_sortable_posts = (int) apply_filters( 'simple_page_ordering_limit', 50 ); // should reliably be able to do about 50 at a time
140
+ if ( $max_sortable_posts < 5 ) { // don't be ridiculous!
141
  $max_sortable_posts = 50;
142
+ }
143
 
144
  // we need to handle all post stati, except trash (in case of custom stati)
145
  $post_stati = get_post_stati(array(
167
  foreach( $siblings->posts as $sibling ) :
168
 
169
  // don't handle the actual post
170
+ if ( $sibling->ID === $post->ID ) {
171
  continue;
172
+ }
173
 
174
  // if this is the post that comes after our repositioned post, set our repositioned post position and increment menu order
175
  if ( $nextid === $sibling->ID ) {
255
  die( json_encode( $return_data ) );
256
  }
257
 
258
+ /**
259
+ * Append a sort by order link to the post actions
260
+ *
261
+ * @param string $views
262
+ * @return string
263
+ */
264
+ public static function sort_by_order_link( $views ) {
265
  $class = ( get_query_var('orderby') == 'menu_order title' ) ? 'current' : '';
266
  $query_string = remove_query_arg(array( 'orderby', 'order' ));
267
  $query_string = add_query_arg( 'orderby', urlencode('menu_order title'), $query_string );
272
  /**
273
  * Checks to see if the current user has the capability to "edit others" for a post type
274
  *
275
+ * @param string $post_type Post type name
276
+ * @return bool True or false
277
  */
278
+ private static function check_edit_others_caps( $post_type ) {
279
  $post_type_object = get_post_type_object( $post_type );
280
  $edit_others_cap = empty( $post_type_object ) ? 'edit_others_' . $post_type . 's' : $post_type_object->cap->edit_others_posts;
281
  return apply_filters( 'simple_page_ordering_edit_rights', current_user_can( $edit_others_cap ), $post_type );
282
  }
283
  }
284
 
285
+ Simple_Page_Ordering::get_instance();
286
+
287
+ endif;