­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ ­ (function( $ ) { 'use strict'; $(document).ready( function() { var itemList = $('#item-list'), // Container of item list maxLevel = 6, dragAxis = false, dragTabSize = 20, hierarchicalValue = ( typeof contentOrderSort.hierarchical !== 'undefined' ) ? contentOrderSort.hierarchical : contentOrderSort.hirarchical, isHierarchical = ( String( hierarchicalValue ) === 'true' ), disableParentChange = ! isHierarchical, isSavingOrder = false, sort_started = {}, // For data related to the dragged element when dragging started sort_finished = {}; // For data related to the dragged element when dragging has finished // console.log(contentOrderSort); // Data passed from PHP via wp_localize_script if ( ! isHierarchical ) { // Non-hierarchical lists should only support top-level reordering. maxLevel = 1; // Locking drag to vertical axis prevents right-drift from triggering invalid nest attempts. dragAxis = 'y'; // Keep placeholder-based drop valid even when pointer drifts right. dragTabSize = 9999; } // Make item list into nested sortable // Ref: https://api.jqueryui.com/sortable/ // Ref: https://github.com/ilikenwf/nestedSortable // See options at https://github.com/ilikenwf/nestedSortable/blob/master/jquery.mjs.nestedSortable.js#L37 // Ref: https://ilikenwf.github.io/example.html (demo) itemList.nestedSortable({ // Disable nesting if set to true protectRoot: false, // Disable moving sub-item to a different parent or up the nested structure disableParentChange: disableParentChange, isTree: true, // Forces the placeholder to have a size. forcePlaceholderSize: true, // Restricts sort start click to the specified element. // Allows for a helper element to be used for dragging display. // If set to "clone", then the element will be cloned and the clone will be dragged. helper: 'clone', // Use vertical-only dragging for non-hierarchical post types. axis: dragAxis, listType: 'ul', items: 'li', toleranceElement: '> div', // Direct children of the li element handle: 'div', // The same
for toleranceElement is set as the drag handle // Specifies which mode to use for testing whether the item being moved is hovering over another item. // If set to 'pointr', is when the mouse pointer overlaps the other item. tolerance: 'pointer', // The maximum depth of nested items the list can accept. maxLevels: maxLevel, // Defines the opacity of the helper while sorting. opacity: 0.6, placeholder: 'ui-sortable-placeholder', // Whether the sortable items should revert to their new positions using a smooth animation. // If set as a number, it's in miliseconds revert: 250, // How far right or left (in pixels) the item has to travel // in order to be nested or to be sent outside its current list. Default: 20 tabSize: dragTabSize, // This event is triggered when sorting starts. start: function (event, ui) { if ( isSavingOrder ) { return false; } // console.log('ui.item -- start'); // console.log(ui.item); sort_started.item = ui.item; // The jQuery object representing the current dragged element. sort_started.prev = ui.item.prev(':not(".ui-sortable-placeholder")'); sort_started.next = ui.item.next(':not(".ui-sortable-placeholder")'); }, // This event is triggered when the user stopped sorting and the DOM position has changed. update: function (event, ui) { // console.log('ui.item -- update'); // console.log(ui.item); // Elements of the "Updating order..." notice var updateNotice = $('#updating-order-notice'), // Wrapper spinner = $('#spinner-img'), // Spinner updateSuccess = $('.updating-order-notice .dashicons.dashicons-saved'); // Check mark ui.item.find('div.row-content:first').append(updateNotice); // Reset the state of the "Updating order..." indicator $(spinner).show(); $(updateSuccess).hide(); $(updateNotice).css('background-color','#eee').fadeIn(); // Get the end items where the item was placed // console.log('sort_finished'); // console.log(sort_finished); sort_finished.item = ui.item; // The jQuery object representing the current dragged element. // sort_finished.prev = ui.item.prev(':not(".ui-sortable-placeholder")'); // sort_finished.next = ui.item.next(':not(".ui-sortable-placeholder")'); // If an item is moved as a child of another item // it will be inserted inside the ul.child-list with a data-parent if ( ui.item.parent('.child-list').length ) { // if ( ui.item.siblings('.list-item').length ) { // Do something // } else { // Let's set the item's parent ID here, taking from ul.child-list's data-parent info sort_finished.item.attr('data-parent', ui.item.parent('.child-list').attr('data-parent')); // } } else { sort_finished.item.attr('data-parent', '0'); } // console.log('sort_finished.prev'); // console.log(sort_finished.prev); var list_offset = parseInt(sort_finished.item.index()); sort_finished.item.attr('data-menu-order', list_offset); // Get attributes var attributes = {}; $.each(sort_finished.item[0].attributes, function () { attributes[this.name] = this.value; }); // console.log('attributes: ' + cleanStringify(attributes)); // Data for ajax call var dataArgs = { action: contentOrderSort.action, // from wp_localize_script item_parent: 0, // We only deal with top-level items, not child items start: 0, // Start processing menu_order update in DB from item with menu_order defined here nonce: contentOrderSort.nonce, post_id: sort_finished.item.attr('data-id'), menu_order: sort_finished.item.attr('data-menu-order'), excluded_items: {}, post_type: sort_started.item.attr('data-post-type'), attributes: attributes, }; // console.log('dataArgs: ' + cleanStringify(dataArgs)); isSavingOrder = true; // AJAX call to update menu_order for items in the list $.ajax({ type: "POST", url: ajaxurl, data: dataArgs, success: function(response) { // console.log(response); // Update the state of the "Updating order..." indicator $(spinner).hide(); $(updateSuccess).show(); $(updateNotice).css('background-color','#cce5cc').delay(1000).fadeOut(); }, error: function(errorThrown) { console.log(errorThrown); }, complete: function() { isSavingOrder = false; } }); } }); }); // Convert object to simpler string for console.log. Ref: https://stackoverflow.com/a/48845206 // function cleanStringify(object) { // if (object && typeof object === 'object') { // object = copyWithoutCircularReferences([object], object); // } // return JSON.stringify(object); // function copyWithoutCircularReferences(references, object) { // var cleanObject = {}; // Object.keys(object).forEach(function(key) { // var value = object[key]; // if (value && typeof value === 'object') { // if (references.indexOf(value) < 0) { // references.push(value); // cleanObject[key] = copyWithoutCircularReferences(references, value); // references.pop(); // } else { // cleanObject[key] = '###_Circular_###'; // } // } else if (typeof value !== 'function') { // cleanObject[key] = value; // } // }); // return cleanObject; // } // } })( jQuery );