Jump to content

Wishlist: Add a "Siblings" tab to edit mode


creativejay
 Share

Recommended Posts

Just one of those things I often find myself wishing for:

Could a future update add a "Siblings" list tab (or make a "Children & Siblings" combined tab) to /page/edit/?

Save + Next is a godsend, but in many cases I need to jump around instead of cycling through. Sometimes I just want to reference how I titled other pages under one parent to keep the naming consistent. Other times I'm deep enough in my page tree that it's a half-dozen or so more clicks than I'd like to get back to where I was.

So far my workaround is to right-click on the parent's name in the Breadcrumb nav, and open the page tree in a new tab. But when editing a site often has me opening ten or more browser tabs at a time, each one I can cut out is a blessing. 

Thanks for your consideration!

  • Like 1
Link to comment
Share on other sites

2 minutes ago, Klenkes said:

Since it remembers which tree is open it's exactly two clicks. Open tree and click on siblingpage.

Or do you mean a siblingsview on the same tab as your fields?

Yes once I use it once it remembers, but I just was hoping for a cleaner approach to it since there's already a tab for that page's "Family" ifyaknowaddimean.

Link to comment
Share on other sites

<?php

/**
 * Add "Siblings" tab to page editor.
 *
 */

class PageEditSiblings extends WireData implements Module {
	public static function getModuleInfo() {
		return array(
			"title"		=>	"Page Edit Siblings",
			"summary"	=>	_("Add siblings tab to page edtior"),
			"version"	=>	"0.0.1",
			"autoload"	=>	true
		);
	}
	
	public function init() {
		$this->addHookAfter("ProcessPageEdit::buildForm", $this, "addSiblingsTab");
	}
	
	public function addSiblingsTab(HookEvent $event) {
		$edit = $event->object;
		$form = $event->return;
		
		$master = $edit->getMasterPage();
		$page = $master ?  $master : $edit->getPage();
		
		$wrap = $this->buildFormSiblings($edit, $form, $master, $page);
		
		$form->insertAfter($wrap, $form->get("ProcessPageEditChildren"));
	}
	
	public function ___buildFormSiblings($edit, $form, $master, $page) {
		$wrapper = $this->wire(new InputfieldWrapper());
		$id = $this->className();
		$wrapper->attr('id+name', $id);
		if(!empty($settings['ajaxChildren'])) $wrapper->collapsed = Inputfield::collapsedYesAjax;

		$defaultTitle = $this->_('Siblings'); // Tab Label: Siblings
		$title = $this->page->template->getTabLabel('siblings'); 
		if(!$title) $title = $defaultTitle;
		
		if($page->parent->numChildren > 1) $wrapper->attr('title', "<em>$title</em>"); 
			else $wrapper->attr('title', $title); 

		$this->addTab($edit, $id, $title);

		if(!$edit->isPost) { 
			$pageListParent = $page->parent;

			/** @var InputfieldMarkup $field */
			$field = $this->modules->get("InputfieldMarkup"); 
			$field->label = $title == $defaultTitle ? $this->_("Sibling Pages") : $title; // Siblings field label
			if($pageListParent->numChildren > 1) {
				$field->value = $this->renderPages($pageListParent->children(), $page);
			} else {
				$field->description = $this->_("There are currently no siblings of this page.");
			}

			if($page->addable()) { 
				/** @var InputfieldButton $button */
				$button = $this->modules->get("InputfieldButton"); 
				$button->attr('id+name', 'AddPageBtn'); 
				$button->attr('value', $this->_('Add New Page Under Parent')); // Button: add new child page
				$button->icon = 'plus-circle';
				$button->attr('href', "../add/?parent_id={$page->parent->id}" . ($this->input->get('modal') ? "&modal=1" : ''));
				$field->append($button);
			}
			$wrapper->append($field); 
		}

		return $wrapper;
	}
	
	public function ___renderPages($list, $cur) {
		$out = '<div class="PageList" style="display: block;">' . "\n";
		foreach($list as $p) {
			$out .= ($p == $cur)
					? "<div class='PageListItem'>{$p->title}</div>\n"
					: "<div class='PageListItem'><a href='{$this->page->url}?id={$p->id}' title='{$p->name}' class='PageListPage label'>{$p->title}</a></div>\n"
			;
		}
		$out .= "</div>";
		
		return $out;
	}
	
	protected function addTab($edit, $siblingid, $siblingtitle) {
		$tabs = $edit->getTabs();
		$removed = array();
		foreach(array_reverse($tabs) as $id => $title) {
			if($id == "ProcessPageEditChildren") {
				break;
			}
			$removed[$id] = $title;
			$edit->removeTab($id);
		}
		
		$edit->addTab($siblingid, $siblingtitle);
		
		foreach(array_reverse($removed) as $id => $title) {
			$edit->addTab($id, $title);
		}
	}
}

Only tested on PW 3.0.34 but should (I hope) work on any 2.7.x / 2.8.x / 3.0.x install. Large parts stolen from ProcessPageEdit::___buildFormChildren.

  • Like 9
Link to comment
Share on other sites

That's great BitPoet, thank you! Works as advertised in my 3.0.42 installation. I'll flag it to keep an eye on after future updates, though.

 

Thanks again! 

 

ETA: It does seem to cause a conflict with the user page edit, FYI anyone who comes along later. I'll just turn it on and off when I need it and then remove it before the site goes live. Or see if I have some time to try and debug it.

Edited by creativejay
error reporting
  • Like 1
Link to comment
Share on other sites

  • 7 months later...

As said above it throws some error while on the user page or when trying to add a new repeater.

Spoiler

Error: Uncaught TypeError: Argument 2 passed to ProcessWire\InputfieldWrapper::insertAfter() must be an instance of ProcessWire\Inputfield, null given, called in ...\site\assets\cache\FileCompiler\site\modules\PageEditSiblings.module on line 34 and defined in ...\wire\core\InputfieldWrapper.php:296
Stack trace:
#0 ...\site\assets\cache\FileCompiler\site\modules\PageEditSiblings.module(34): ProcessWire\InputfieldWrapper->insertAfter(Object(ProcessWire\InputfieldWrapper), NULL)
#1 ...\wire\core\WireHooks.php(782): PageEditSiblings->addSiblingsTab(Object(ProcessWire\HookEvent))
#2 ...\wire\core\Wire.php(442): ProcessWire\WireHooks->runHooks(Object(ProcessWire\ProcessPageEdit), 'buildForm', Array)
#3 ...\wire\modules\Process\ProcessPageEdit\ProcessPageEdit.module(406): ProcessWire\Wire->__call('buildForm', Array)
#4 ...\wire\co (line 296 of ...\wire\core\InputfieldWrapper.php)

 

My fix:

//replace
public function init() {
  $this->addHookAfter("ProcessPageEdit::buildForm", $this, "addSiblingsTab");
}

//with
public function ready() {
  if($this->wire("page")->name === "edit" && !$this->wire("config")->ajax)
  $this->addHookAfter("ProcessPageEdit::buildForm", $this, "addSiblingsTab");
}

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...