diff options
Diffstat (limited to 'www/wiki/skins/chameleon/src/Components/NavbarHorizontal.php')
-rw-r--r-- | www/wiki/skins/chameleon/src/Components/NavbarHorizontal.php | 256 |
1 files changed, 256 insertions, 0 deletions
diff --git a/www/wiki/skins/chameleon/src/Components/NavbarHorizontal.php b/www/wiki/skins/chameleon/src/Components/NavbarHorizontal.php new file mode 100644 index 00000000..3694382a --- /dev/null +++ b/www/wiki/skins/chameleon/src/Components/NavbarHorizontal.php @@ -0,0 +1,256 @@ +<?php +/** + * File holding the NavbarHorizontal class + * + * This file is part of the MediaWiki skin Chameleon. + * + * @copyright 2013 - 2017, Stephan Gambke + * @license GNU General Public License, version 3 (or any later version) + * + * The Chameleon skin is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the Free + * Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * The Chameleon skin is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + * + * @file + * @ingroup Skins + */ + +namespace Skins\Chameleon\Components; + +use DOMElement; +use Skins\Chameleon\IdRegistry; + +/** + * The NavbarHorizontal class. + * + * A horizontal navbar containing the sidebar items. + * Does not include standard items (toolbox, search, language links). They need + * to be added to the page elsewhere + * + * The navbar is a list of lists wrapped in a nav element: <nav + * role="navigation" id="p-navbar" > + * + * @author Stephan Gambke + * @since 1.0 + * @ingroup Skins + */ +class NavbarHorizontal extends Component { + + private $mHtml = null; + private $htmlId = null; + + /** + * Builds the HTML code for this component + * + * @return String the HTML code + */ + public function getHtml() { + + if ( $this->mHtml === null ) { + $this->buildHtml(); + } + + return $this->mHtml; + } + + /** + * + */ + protected function buildHtml() { + + if ( $this->getDomElement() === null ) { + $this->mHtml = ''; + return; + } + + $this->mHtml = + $this->buildFixedNavBarIfRequested() . + $this->buildNavBarOpeningTags() . + $this->buildNavBarComponents() . + $this->buildNavBarClosingTags(); + } + + /** + * + */ + protected function buildFixedNavBarIfRequested() { + // if a fixed navbar is requested + if ( filter_var( $this->getDomElement()->getAttribute( 'fixed' ), FILTER_VALIDATE_BOOLEAN ) === true || + $this->getDomElement()->getAttribute( 'position' ) === 'fixed' + ) { + + // first build the actual navbar and set a class so it will be fixed + $this->getDomElement()->setAttribute( 'fixed', '0' ); + $this->getDomElement()->setAttribute( 'position', '' ); + + $realNav = new self( $this->getSkinTemplate(), $this->getDomElement(), $this->getIndent() ); + $realNav->setClasses( $this->getClassString() . ' navbar-fixed-top' ); + + // then add an invisible copy of the nav bar that will act as a spacer + $this->addClasses( 'navbar-static-top invisible' ); + + return $realNav->getHtml(); + } else { + return ''; + } + } + + /** + * @return string + */ + protected function buildNavBarOpeningTags() { + $openingTags = + $this->indent() . '<!-- navigation bar -->' . + $this->indent() . \Html::openElement( 'nav', array( + 'class' => 'navbar navbar-default p-navbar ' . $this->getClassString(), + 'role' => 'navigation', + 'id' => $this->getHtmlId() + ) + ) . + $this->indent( 1 ) . '<div class="container">'; + + $this->indent( 1 ); + + return $openingTags; + } + + /** + * @return string + */ + private function getHtmlId() { + if ( $this->htmlId === null ) { + $this->htmlId = IdRegistry::getRegistry()->getId( 'mw-navigation' ); + } + return $this->htmlId; + } + + /** + * + */ + protected function buildNavBarComponents() { + + $elements = $this->buildNavBarElementsFromDomTree(); + + if ( !empty( $elements[ 'right' ] ) ) { + + $elements[ 'left' ][ ] = + $this->indent( 1 ) . '<div class="navbar-right-aligned">' . + implode( $elements[ 'right' ] ) . + $this->indent() . '</div> <!-- navbar-right-aligned -->'; + + $this->indent( -1 ); + } + + return + $this->buildHead( $elements[ 'head' ] ) . + $this->buildTail( $elements[ 'left' ] ); + } + + /** + * @return string[][] + */ + protected function buildNavBarElementsFromDomTree() { + + $elements = array( + 'head' => array(), + 'left' => array(), + 'right' => array(), + ); + + /** @var \DOMElement[] $children */ + $children = $this->getDomElement()->hasChildNodes() ? $this->getDomElement()->childNodes : array(); + + // add components + foreach ( $children as $node ) { + $this->buildAndCollectNavBarElementFromDomElement( $node, $elements ); + } + return $elements; + } + + /** + * @param DOMElement $node + * @param $elements + */ + protected function buildAndCollectNavBarElementFromDomElement( $node, &$elements ) { + + if ( $node instanceof DOMElement && $node->tagName === 'component' && $node->hasAttribute( 'type' ) ) { + + $position = $node->getAttribute( 'position' ); + + if ( !array_key_exists( $position, $elements ) ) { + $position = 'left'; + } + + $indentation = ( $position === 'right' ) ? 2 : 1; + + $this->indent( $indentation ); + $html = $this->buildNavBarElementFromDomElement( $node ); + $this->indent( -$indentation ); + + $elements[ $position ][ ] = $html; + + // } else { + // TODO: Warning? Error? + } + } + + /** + * @param \DomElement $node + * + * @return string + */ + protected function buildNavBarElementFromDomElement( $node ) { + return $this->getSkin()->getComponentFactory()->getComponent( $node, $this->getIndent() )->getHtml(); + } + + /** + * @param string[] $headElements + * + * @return string + */ + protected function buildHead( $headElements ) { + + $head = + $this->indent() . "<div class=\"navbar-header\">\n" . + $this->indent( 1 ) . "<button type=\"button\" class=\"navbar-toggle collapsed\" data-toggle=\"collapse\" data-target=\"#" . $this->getHtmlId() . "-collapse\">" . + $this->indent( 1 ) . "<span class=\"sr-only\">Toggle navigation</span>" . + $this->indent() . str_repeat( "<span class=\"icon-bar\"></span>", 3 ) . + $this->indent( -1 ) . "</button>\n" . + implode( '', $headElements ) . "\n" . + $this->indent( -1 ) . "</div>\n"; + + return $head; + } + + /** + * @param string[] $tailElements + * + * @return string + */ + protected function buildTail( $tailElements ) { + + return + $this->indent() . '<div class="collapse navbar-collapse" id="' . $this->getHtmlId() . '-collapse">' . + implode( '', $tailElements ) . + $this->indent() . '</div><!-- /.navbar-collapse -->'; + } + + /** + * @return string + */ + protected function buildNavBarClosingTags() { + return + $this->indent( -1 ) . '</div>' . + $this->indent( -1 ) . '</nav>' . "\n"; + } + +} |