1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-23 14:56:51 +02:00

Add new Page::numDescendants() method and property, plus descendants() and descendant() alias methods. Add Page::findOne() method. Update ProcessPageList with the ability to customize what is shown in the numChildren/count shown for each Page, along with the ability to display the the newly added Page descendants numbers instead of or in addition to the Page numChildren.

This commit is contained in:
Ryan Cramer
2018-10-05 08:11:16 -04:00
parent faa0d4f4df
commit 5fddd95b43
7 changed files with 277 additions and 43 deletions

View File

@@ -131,6 +131,10 @@ $(document).ready(function() {
// session field name that holds page label format, when used
labelName: '',
// what to show in the PageListNumChildren quantity: 'children', 'total', 'children/total', 'total/children', or 'id'
// default is blank, which implies 'children'
qtyType: '',
};
// array of "123.0" (page_id.start) that are currently open (used in non-select mode only)
@@ -511,7 +515,9 @@ $(document).ready(function() {
var nextStart = data.start + data.limit;
//var openPageKey = id + '-' + start;
if($target.hasClass('PageListItem')) setNumChildren($target, data.page.numChildren);
if($target.hasClass('PageListItem')) {
setNumChildren($target, data.page.numChildren, data.page.numTotal);
}
if(data.page.numChildren > nextStart) {
var $a = $("<a></a>").attr('href', nextStart).data('pageId', id).text(options.moreLabel).click(clickMore);
@@ -717,8 +723,7 @@ $(document).ready(function() {
});
$li.append($a);
var $numChildren = $("<span>" + (child.numChildren ? child.numChildren : '') + "</span>").addClass('PageListNumChildren detail');
$li.append($numChildren);
setNumChildren($li, child.numChildren, child.numTotal, true);
if(child.note && child.note.length) $li.append($("<span>" + child.note + "</span>").addClass('PageListNote detail'));
@@ -794,30 +799,101 @@ $(document).ready(function() {
* Get number of children for given .PageListItem
*
*/
function getNumChildren($item) {
var $numChildren = $item.children('.PageListNumChildren');
if(!$numChildren.length) return 0;
var numChildren = $numChildren.text();
return numChildren.length ? parseInt(numChildren) : 0;
function getNumChildren($item, getTotal) {
if(typeof getTotal == "undefined") var getTotal = false;
if(getTotal) {
var n = $item.attr('data-numTotal');
} else {
var n = $item.attr('data-numChild');
}
return n && n.length > 0 ? parseInt(n) : 0;
}
function getNumTotal($item) {
return getNumChildren($item, true);
}
/**
* Set number of children for given PageListItem
*
*/
function setNumChildren($item, numChildren) {
var $numChildren = $item.children('.PageListNumChildren');
if(!$numChildren.length) {
$numChildren = $('<span>0</span>').addClass('PageListNumChildren detail');
$item.append($numChildren);
function setNumChildren($item, numChildren, numTotal, addNew) {
if(typeof numTotal == "undefined") var numTotal = numChildren;
if(typeof addNew == "undefined") var addNew = false;
var $numChildren = addNew ? '' : $item.children('.PageListNumChildren');
var n = numChildren === false ? numTotal : numChildren;
if(addNew || !$numChildren.length) {
$numChildren = $('<span></span>').addClass('PageListNumChildren detail');
addNew = true;
}
if(numChildren < 1) {
if(n < 1) {
$item.removeClass('PageListHasChildren').addClass('PageListNoChildren');
numChildren = '';
if(numTotal !== false) numTotal = 0;
} else {
$item.removeClass('PageListNoChildren').addClass('PageListHasChildren');
}
$numChildren.text(numChildren);
if(numTotal === false) {
numTotal = getNumTotal($item);
} else {
$item.attr('data-numTotal', numTotal);
}
if(numChildren === false) {
numChildren = getNumChildren($item);
} else {
if(numChildren < 0) numChildren = 0;
$item.attr('data-numChild', numChildren);
}
var numLabel = '';
switch(options.qtyType) {
case 'total':
numLabel = numTotal;
break;
case 'total/children':
var slash = "<span class='ui-priority-secondary'>/</span>";
numLabel = numTotal > 0 && numTotal != numChildren ? numTotal + slash + numChildren : numTotal;
break;
case 'children/total':
var slash = "<span class='ui-priority-secondary'>/</span>";
numLabel = numTotal > 0 && numTotal != numChildren ? numChildren + slash + numTotal : numTotal;
break;
case 'id':
numLabel = $item.data('pageId');
break;
default:
numLabel = numChildren;
}
if(!numLabel) numLabel = '';
$numChildren.html(numLabel);
if(addNew) $item.append($numChildren);
}
/**
* Set total/descendants
*
*/
function setNumTotal($item, numTotal) {
setNumChildren($item, false, numTotal);
}
/**
* Recursively adjust total/descendants number up the tree by given amount (n)
*
*/
function adjustNumTotal($item, n) {
var numTotal = getNumTotal($item);
numTotal += n;
if(numTotal < 0) numTotal = 0;
setNumTotal($item, numTotal);
var $parentItem = $item.closest('.PageList').prev('.PageListItem');
if($parentItem.length) adjustNumTotal($parentItem, n);
}
/**
@@ -935,12 +1011,15 @@ $(document).ready(function() {
$msg.fadeOut('normal', function () {
var $parentItem = $liNew.closest('.PageList').prev('.PageListItem');
var numChildren = getNumChildren($parentItem);
var numTotal = getNumTotal($parentItem);
if(removeItem) {
numChildren--;
adjustNumTotal($parentItem, -1);
} else if(addNew) {
numChildren++;
adjustNumTotal($parentItem, 1);
}
setNumChildren($parentItem, numChildren);
setNumChildren($parentItem, numChildren, false);
setForceReload($parentItem);
if(removeItem) {
$liNew.next('.PageList').fadeOut('fast');
@@ -1031,7 +1110,7 @@ $(document).ready(function() {
}
} else {
$li.addClass('PageListItemOpen');
var numChildren = parseInt($li.children('.PageListNumChildren').text());
var numChildren = getNumChildren($li);
if(numChildren > 0 || $li.hasClass('PageListForceReload')) {
ignoreClicks = true;
var start = getOpenPageStart(id);
@@ -1169,7 +1248,7 @@ $(document).ready(function() {
// make an invisible PageList placeholder that allows 'move' action to create a child below this
$root.find('.PageListItemOpen').each(function() {
var numChildren = $(this).children('.PageListNumChildren').text();
var numChildren = getNumChildren($(this));
// if there are children and the next sibling doesn't contain a visible .PageList, then don't add a placeholder
if(parseInt(numChildren) > 1 && $(this).next().find(".PageList:visible").length == 0) {
return;
@@ -1333,20 +1412,22 @@ $(document).ready(function() {
if(!$ul.is("#PageListMoveFrom")) {
// update count where item came from
var $fromItem = $from.prev(".PageListItem");
var $numChildren = $fromItem.children(".PageListNumChildren");
var n = $numChildren.text().length > 0 ? parseInt($numChildren.text()) - 1 : 0;
if(n == 0) {
n = '';
var numChildren = getNumChildren($fromItem);
var numTotal = getNumTotal($fromItem);
if(numChildren > 0) {
numChildren--;
adjustNumTotal($fromItem, -1);
} else {
$from.remove(); // empty list, no longer needed
}
$numChildren.text(n);
setNumChildren($fromItem, numChildren, false);
setForceReload($fromItem);
// update count where item went to
var $toItem = $ul.prev(".PageListItem");
$numChildren = $toItem.children(".PageListNumChildren");
n = $numChildren.text().length > 0 ? parseInt($numChildren.text()) + 1 : 1;
$numChildren.text(n);
numChildren = getNumChildren($toItem) + 1;
adjustNumTotal($toItem, 1);
setNumChildren($toItem, numChildren, false);
setForceReload($toItem);
}
$from.attr('id', ''); // remove tempoary #PageListMoveFrom

File diff suppressed because one or more lines are too long

View File

@@ -20,6 +20,7 @@
* @property int $hoverActionFade Milliseconds to spend fading in or out actions.
* @property bool|int $useBookmarks Allow use of PageList bookmarks?
* @property bool|int $useTrash Allow non-superusers to use Trash?
* @property string $qtyType What to show in children quantity label? 'children', 'total', 'children/total', 'total/children', or 'id'
*
* @method string ajaxAction($action)
* @method PageArray find($selectorString, Page $page)
@@ -116,6 +117,7 @@ class ProcessPageList extends Process implements ConfigurableModule {
$this->set('useBookmarks', false);
$this->set('useTrash', false);
$this->set('bookmarks', array());
$this->set('qtyType', '');
parent::__construct();
}
@@ -302,6 +304,7 @@ class ProcessPageList extends Process implements ConfigurableModule {
'limit' => $this->limit,
'start' => $this->start,
'speed' => ($this->speed !== null ? (int) $this->speed : self::defaultSpeed),
'qtyType' => $this->qtyType,
'useHoverActions' => $this->useHoverActions ? true : false,
'hoverActionDelay' => (int) $this->hoverActionDelay,
'hoverActionFade' => (int) $this->hoverActionFade,
@@ -347,12 +350,14 @@ class ProcessPageList extends Process implements ConfigurableModule {
$children = $this->wire('pages')->newPageArray();
}
/** @var ProcessPageListRender $renderer */
$renderer = $this->wire(new $className($page, $children));
$renderer->setStart($start);
$renderer->setLimit($limit);
$renderer->setPageLabelField($this->getPageLabelField());
$renderer->setLabel('trash', $this->trashLabel);
$renderer->setUseTrash($this->useTrash || $this->wire('user')->isSuperuser());
$renderer->setQtyType($this->qtyType);
return $renderer;
}
@@ -700,6 +705,20 @@ class ProcessPageList extends Process implements ConfigurableModule {
$field->description = $this->_('This is the speed at which each branch in the page tree animates up or down. Lower numbers are faster but less visible. For no animation specify 0.'); // Animation speed description
$field->notes = sprintf($defaultNote1, self::defaultSpeed) . ' ' . $defaultNote2;
$fields->append($field);
/** @var InputfieldRadios $field */
$field = $modules->get('InputfieldRadios');
$field->attr('name', 'qtyType');
$field->label = $this->_('Children quantity type');
$field->description = $this->_('In the page list, a quantity of children is shown next to each page when applicable. What type of quantity should it show?');
$field->notes = $this->_('When showing descendants, the quantity includes all descendants, whether listable to the user or not.');
$field->addOption('', $this->_('Immediate children (default)'));
$field->addOption('total', $this->_('Descendants: children, grandchildren, great-grandchildren, and on…'));
$field->addOption('children/total', $this->_('Both: children/descendants'));
$field->addOption('total/children', $this->_('Both: descendants/children'));
$field->addOption('id', $this->_('Show Page ID number instead'));
$field->attr('value', empty($data['qtyType']) ? '' : $data['qtyType']);
$fields->append($field);
return $fields;
}

View File

@@ -20,6 +20,7 @@ abstract class ProcessPageListRender extends Wire {
protected $actions = null;
protected $options = array();
protected $useTrash = false;
protected $qtyType = '';
public function __construct(Page $page, PageArray $children) {
$this->page = $page;
@@ -77,6 +78,10 @@ abstract class ProcessPageListRender extends Wire {
$this->pageLabelField = $pageLabelField;
}
public function setQtyType($qtyType) {
$this->qtyType = $qtyType;
}
public function actions() {
return $this->actions;
}

View File

@@ -72,13 +72,18 @@ class ProcessPageListRenderJSON extends ProcessPageListRender {
if($child->listable()) $numChildren++;
}
}
if(strpos($this->qtyType, 'total') !== false) {
$numTotal = $this->wire('pages')->trasher()->getTrashTotal();
} else {
$numTotal = $numChildren;
}
} else {
if($page->hasStatus(Page::statusTemp)) $icons[] = 'bolt';
if($page->hasStatus(Page::statusLocked)) $icons[] = 'lock';
if($page->hasStatus(Page::statusDraft)) $icons[] = 'paperclip';
$numChildren = $page->numChildren(1);
$numTotal = strpos($this->qtyType, 'total') !== false ? $page->numDescendants : $numChildren;
}
if(!$label) $label = $this->getPageLabel($page);
if(count($icons)) foreach($icons as $n => $icon) {
@@ -90,6 +95,7 @@ class ProcessPageListRenderJSON extends ProcessPageListRender {
'label' => $label,
'status' => $page->status,
'numChildren' => $numChildren,
'numTotal' => $numTotal,
'path' => $page->template->slashUrls || $page->id == 1 ? $page->path() : rtrim($page->path(), '/'),
'template' => $page->template->name,
//'rm' => $this->superuser && $page->trashable(),