Foxtrott has submitted this change and it was merged.

Change subject: Several improvements to the navbar
......................................................................


Several improvements to the navbar

* split off navmenu into its own class
* page tools: allow hiding link to current namespace
* page tools: don't display if there are no tools (e.g. Special Pages)
* improve navhead.xml (flatten nav menu, hide link to current namespace)
* fix z-index of navbars

Change-Id: Iba41064af7fe36946143841d55bde2860ac91cb4
---
M chameleon.php
A includes/components/NavMenu.php
M includes/components/NavbarHorizontal.php
M includes/components/PageTools.php
M layouts/navhead.xml
M styles/screen.less
6 files changed, 286 insertions(+), 117 deletions(-)

Approvals:
  Foxtrott: Verified; Looks good to me, approved



diff --git a/chameleon.php b/chameleon.php
index dbaab4f..56a2299 100644
--- a/chameleon.php
+++ b/chameleon.php
@@ -73,7 +73,7 @@
        'Cell',
        'Grid',
        'NavbarHorizontal',
-       'NavHead',
+       'NavMenu',
        'PageTools',
        'NewtalkNotifier',
        'PersonalTools',
diff --git a/includes/components/NavMenu.php b/includes/components/NavMenu.php
new file mode 100644
index 0000000..2a10995
--- /dev/null
+++ b/includes/components/NavMenu.php
@@ -0,0 +1,154 @@
+<?php
+/**
+ * File holding the NavMenu class
+ *
+ * @copyright (C) 2014, Stephan Gambke
+ * @license       http://www.gnu.org/licenses/gpl-3.0.html GNU General Public 
License, version 3 (or later)
+ *
+ * This file is part of the MediaWiki extension Chameleon.
+ * The Chameleon extension 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 extension 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 Linker;
+use skins\chameleon\IdRegistry;
+
+/**
+ * The NavMenu class.
+ *
+ *
+ * @ingroup Skins
+ */
+class NavMenu extends Component {
+
+       /**
+        * Builds the HTML code for this component
+        *
+        * @return String the HTML code
+        */
+       public function getHtml() {
+
+               $ret = '';
+
+               $sidebar = $this->getSkinTemplate()->getSidebar( array(
+                               'search' => false, 'toolbox' => false, 
'languages' => false
+                       )
+               );
+
+               $msg = \Message::newFromKey( 'skin-chameleon-navmenu-flatten' );
+
+               if ( $msg->exists() ) {
+                       $flatten = array_map( trim, explode( ';', $msg->plain() 
) );
+               } elseif ( $this->getDomElement() !== null ) {
+                       $flatten = array_map( trim, explode( ';', 
$this->getDomElement()->getAttribute( 'flatten' ) ) );
+               } else {
+                       $flatten = array();
+               }
+
+               // create a dropdown for each sidebar box
+               foreach ( $sidebar as $boxName => $box ) {
+
+                       $ret .= $this->getDropdownForNavMenu( $boxName, $box, 
array_search( $boxName, $flatten ) !== false );
+               }
+
+               return $ret;
+       }
+
+       /**
+        * Create a single dropdown
+        *
+        * @param string $boxName
+        * @param array  $box
+        * @param bool   $flatten
+        *
+        * @return string
+        */
+       protected function getDropdownForNavMenu( $boxName, $box, $flatten = 
false ) {
+
+               // open list item containing the dropdown
+               $ret = $this->indent() . '<!-- ' . $boxName . ' -->';
+
+               $menuitems = '';
+
+               // build the list of submenu items
+               if ( is_array( $box[ 'content' ] ) && count( $box[ 'content' ] 
) > 0 ) {
+
+                       $this->indent( $flatten ? 0 : 2 );
+
+                       foreach ( $box[ 'content' ] as $key => $item ) {
+                               $menuitems .= $this->indent() . 
$this->getSkinTemplate()->makeListItem( $key, $item );
+                       }
+
+                       $this->indent( $flatten ? 0 : -2 );
+
+               } else {
+                       $menuitems .= $this->indent() . '<!-- empty -->';
+               }
+
+               if ( $flatten ) {
+                       // if the menu is to be flattened, just return the 
introducing comment and the list of menu items as is
+
+                       $ret .= $menuitems;
+
+               } elseif ( !is_array( $box[ 'content' ] ) || count( $box[ 
'content' ] ) === 0 ) {
+                       //if the menu is not to be flattened, but is empty, 
return an inert link
+
+                       $ret .= $this->indent() . \Html::rawElement( 'li',
+                                       array(
+                                               'class' => '',
+                                               'title' => Linker::titleAttrib( 
$box[ 'id' ] )
+                                       ),
+                                       '<a href="#">' . htmlspecialchars( 
$box[ 'header' ] ) . '</a>'
+                               );
+
+               } else {
+
+                       // open list item containing the dropdown
+                       $ret .= $this->indent() . \Html::openElement( 'li',
+                                       array(
+                                               'class' => 'dropdown',
+                                               'title' => Linker::titleAttrib( 
$box[ 'id' ] )
+                                       )
+                               );
+
+                       // add the dropdown toggle
+                       $ret .= $this->indent( 1 ) . '<a href="#" 
class="dropdown-toggle" data-toggle="dropdown">' .
+                               htmlspecialchars( $box[ 'header' ] ) . ' <b 
class="caret"></b></a>';
+
+                       // open list of dropdown menu items
+                       $ret .= $this->indent() .
+                               $this->indent() . \Html::openElement( 'ul',
+                                       array(
+                                               'class' => 'dropdown-menu ' . 
$box[ 'id' ],
+                                               'id'    => 
IdRegistry::getRegistry()->getId( $box[ 'id' ] ),
+                                       )
+                               );
+
+                       // add list of menu items
+                       $ret .= $menuitems;
+
+                       // close list of dropdown menu items and the list item 
containing the dropdown
+                       $ret .=
+                               $this->indent() . '</ul>' .
+                               $this->indent( -1 ) . '</li>';
+               }
+
+               return $ret;
+       }
+
+}
diff --git a/includes/components/NavbarHorizontal.php 
b/includes/components/NavbarHorizontal.php
index 2714f63..93b2b4b 100644
--- a/includes/components/NavbarHorizontal.php
+++ b/includes/components/NavbarHorizontal.php
@@ -26,7 +26,6 @@
 namespace skins\chameleon\components;
 
 use Linker;
-use Sanitizer;
 use skins\chameleon\IdRegistry;
 
 /**
@@ -55,10 +54,13 @@
                        $this->indent() .
                        \HTML::openElement( 'nav', array(
                                        'class' => 'navbar navbar-default 
p-navbar ' . $this->getClassString(),
-                                       'role' => 'navigation',
-                                       'id' => 
IdRegistry::getRegistry()->getId('p-navbar')
-                               )) .
+                                       'role'  => 'navigation',
+                                       'id'    => 
IdRegistry::getRegistry()->getId( 'p-navbar' )
+                               )
+                       ) .
                        $this->indent( 1 ) . '<ul class="nav navbar-nav">';
+
+               $this->indent( 1 );
 
                // add components
                $this->eachChild( function ( \DOMElement $node ) {
@@ -69,19 +71,19 @@
 
                                switch ( $node->getAttribute( 'type' ) ) {
                                        case 'Logo':
-                                               $this->mHtml .= 
$this->getLogo();
+                                               $this->mHtml .= $this->getLogo( 
$node );
                                                break;
                                        case 'NavMenu':
-                                               $this->mHtml .= 
$this->getNavMenu();
+                                               $this->mHtml .= 
$this->getNavMenu( $node );
                                                break;
                                        case 'PageTools':
-                                               $this->mHtml .= 
$this->getPageTools();
+                                               $this->mHtml .= 
$this->getPageTools( $node );
                                                break;
                                        case 'SearchBar':
-                                               $this->mHtml .= 
$this->getSearchBar();
+                                               $this->mHtml .= 
$this->getSearchBar( $node );
                                                break;
                                        case 'PersonalTools':
-                                               $this->mHtml .= 
$this->getPersonalTools();
+                                               $this->mHtml .= 
$this->getPersonalTools( $node );
                                                break;
                                }
                        }
@@ -96,11 +98,13 @@
        /**
         * Creates HTML code for the wiki logo in a navbar
         *
+        * @param \DOMElement $domElement
+        *
         * @return String
         */
-       protected function getLogo() {
+       protected function getLogo( \DOMElement $domElement = null ) {
 
-               $logo = new Logo( $this->getSkinTemplate(), null, 
$this->getIndent() );
+               $logo = new Logo( $this->getSkinTemplate(), $domElement, 
$this->getIndent() );
                $logo->addClasses( 'navbar-brand' );
 
                return $logo->getHtml();
@@ -109,112 +113,56 @@
        /**
         * Create a dropdown containing the page tools (page, talk, edit, 
history, ...)
         *
+        * @param \DOMElement $domElement
+        *
         * @return string
         */
-       protected function getPageTools() {
+       protected function getPageTools( \DOMElement $domElement = null ) {
 
-               $pageTools = new PageTools( $this->getSkinTemplate(), null, 
$this->indent( 1 ) );
+               $pageTools = new PageTools( $this->getSkinTemplate(), 
$domElement, $this->getIndent() );
 
                $pageTools->setFlat( true );
                $pageTools->removeClasses( 'text-center list-inline' );
                $pageTools->addClasses( 'dropdown-menu' );
 
-               $ret = $this->indent() . '<!-- page tools -->' .
-                       $this->indent() . \Html::openElement( 'li', array( 
'class' => 'dropdown' ) );
+               $ret = $pageTools->getHtml();
 
-               $ret .= '<a data-toggle="dropdown" class="dropdown-toggle" 
href="#">Page Tools <b class="caret"></b></a>' . $pageTools->getHtml() . 
'</li>';
-
+               if ( $ret !== '' ) {
+                       $ret =
+                               $this->indent() . '<!-- page tools -->' .
+                               $this->indent() . \Html::openElement( 'li', 
array( 'class' => 'dropdown' ) ) .
+                               $this->indent( 1 ) . '<a data-toggle="dropdown" 
class="dropdown-toggle" href="#">Page Tools <b class="caret"></b></a>' .
+                               $ret .
+                               $this->indent( -1 ) . '</li>' . "\n";
+               }
                return $ret;
        }
 
        /**
         * Creates a list of navigational links usually found in the sidebar
         *
-        * @return string
-        */
-       protected function getNavMenu() {
-
-               $ret = '';
-
-               $this->indent( 1 );
-               $sidebar = $this->getSkinTemplate()->getSidebar( array(
-                               'search' => false, 'toolbox' => false, 
'languages' => false
-                       )
-               );
-
-               // create a dropdown for each sidebar box
-               foreach ( $sidebar as $boxName => $box ) {
-
-                       $ret .= $this->getDropdownForNavMenu( $boxName, $box );
-               }
-
-               return $ret;
-       }
-
-       /**
-        * Create a single dropdown
-        *
-        * @param $boxName
-        * @param $box
+        * @param \DOMElement $domElement
         *
         * @return string
         */
-       protected function getDropdownForNavMenu( $boxName, $box ) {
+       protected function getNavMenu( \DOMElement $domElement = null ) {
 
-               // open list item containing the dropdown
-               $ret = $this->indent() . '<!-- ' . $boxName . ' -->' .
-                       $this->indent() . \Html::openElement( 'li',
-                               array(
-                                       'class' => 'dropdown',
-                                       'title' => Linker::titleAttrib( $box[ 
'id' ] )
-                               )
-                       );
+               $navMenu = new NavMenu( $this->getSkinTemplate(), $domElement, 
$this->getIndent() );
 
-               $this->indent( 1 );
-               if ( is_array( $box[ 'content' ] ) && count( $box[ 'content' ] 
) > 0 ) {
+               return $navMenu->getHtml() . "\n";
 
-                       // the dropdown toggle
-                       $ret .= $this->indent() . '<a href="#" 
class="dropdown-toggle" data-toggle="dropdown">' .
-                               htmlspecialchars( $box[ 'header' ] ) . ' <b 
class="caret"></b></a>';
-
-                       // open list of dropdown menu items
-                       $ret .= $this->indent() .
-                       $this->indent() . \Html::openElement( 'ul',
-                               array(
-                                       'class' => 'dropdown-menu ' . 
Sanitizer::escapeId( $box[ 'id' ] ),
-                                       'id'    => 
IdRegistry::getRegistry()->getId( Sanitizer::escapeId( $box[ 'id' ] ) ),
-                               )
-                       );
-
-                       // output dropdown menu items
-                       $this->indent( 1 );
-                       foreach ( $box[ 'content' ] as $key => $item ) {
-                               $ret .= $this->indent() . 
$this->getSkinTemplate()->makeListItem( $key, $item );
-                       }
-
-                       // close list of dropdown menu items
-                       $ret .= $this->indent( -1 ) . '</ul>';
-
-               } else {
-                       $ret .= $this->indent() . '<a href="#">' . 
htmlspecialchars( $box[ 'header' ] ) . '</a>';
-               }
-               $this->indent( -1 );
-
-               // close list item
-               $ret .= $this->indent() . '</li>';
-
-               return $ret;
        }
 
        /**
         * Creates a user's personal tools and the newtalk notifier
         *
+        * @param \DOMElement $domElement
+        *
         * @return string
         */
-       protected function getPersonalTools() {
+       protected function getPersonalTools( \DOMElement $domElement = null ) {
 
                $user = $this->getSkinTemplate()->getSkin()->getUser();
-
 
                if ( $user->isLoggedIn() ) {
                        $toolsClass    = 'navbar-userloggedin';
@@ -226,7 +174,9 @@
 
                // start personal tools element
 
-               $ret = $this->indent() . '<ul class="navbar-right navbar-nav 
navbar-personaltools" >' .
+               $ret =
+                       $this->indent() . '<!-- personal tools -->' .
+                       $this->indent() . '<ul class="navbar-right navbar-nav 
navbar-personaltools" >' .
                        $this->indent( 1 ) . '<li class="dropdown 
navbar-personaltools-tools">' .
                        $this->indent( 1 ) . '<a class="dropdown-toggle 
glyphicon glyphicon-user ' . $toolsClass . '" href="#" data-toggle="dropdown" 
title="' . $toolsLinkText . '" ></a>' .
                        $this->indent() . '<ul class="p-personal-tools 
dropdown-menu" >';
@@ -274,9 +224,9 @@
                return $ret;
        }
 
-       protected function getSearchBar() {
+       protected function getSearchBar( \DOMElement $domElement = null ) {
 
-               $search = new SearchBar( $this->getSkinTemplate(), null, 
$this->getIndent() );
+               $search = new SearchBar( $this->getSkinTemplate(), $domElement, 
$this->getIndent() );
                $search->addClasses( 'navbar-form' );
 
                return $search->getHtml();
diff --git a/includes/components/PageTools.php 
b/includes/components/PageTools.php
index 8272b96..cf7b6aa 100644
--- a/includes/components/PageTools.php
+++ b/includes/components/PageTools.php
@@ -25,7 +25,9 @@
 
 namespace skins\chameleon\components;
 
+use MWNamespace;
 use skins\chameleon\ChameleonTemplate;
+use skins\chameleon\IdRegistry;
 
 /**
  * The PageTools class.
@@ -40,7 +42,7 @@
 
        private $mFlat = false;
 
-       public function __construct( ChameleonTemplate $template, $domElement, 
$indent = 0 ) {
+       public function __construct( ChameleonTemplate $template, \DOMElement 
$domElement = null, $indent = 0 ) {
 
                parent::__construct( $template, $domElement, $indent );
 
@@ -56,12 +58,18 @@
         */
        public function getHtml() {
 
-               $ret = $this->indent() . '<!-- Content navigation -->' .
-                          $this->indent() . '<ul class="p-contentnavigation ' 
. $this->getClassString() . '" id="p-contentnavigation">';
-
                $navigation = $this->getSkinTemplate()->data[ 
'content_navigation' ];
 
-               $this->indent( 1 );
+               $hideSelectedNameSpace = filter_var( 
$this->getDomElement()->getAttribute( 'hideSelectedNameSpace' ), 
FILTER_VALIDATE_BOOLEAN );
+
+               if ( $hideSelectedNameSpace ) {
+                       $namespacekey = $this->getNamespaceKey();
+                       unset( $navigation['namespaces'][ $namespacekey ] );
+               }
+
+               $ret = '';
+
+               $this->indent( 2 );
                foreach ( $navigation as $category => $tabs ) {
 
                        // TODO: visually group all links of one category (e.g. 
some space between categories)
@@ -74,11 +82,13 @@
 
                        if ( !$this->mFlat ) {
                                // output the name of the current category 
(e.g. 'namespaces', 'views', ...)
-                               $ret .= $this->indent() . '<li id="p-' . 
$category . '" >' .
-                                               $this->indent( 1 ) . '<ul 
class="list-inline" >';
+                               $ret .= $this->indent() .
+                                       \Html::openElement( 'li', array( 'id' 
=> IdRegistry::getRegistry()->getId( 'p-' . $category ) ) ) .
+                                       $this->indent( 1 ) . '<ul 
class="list-inline" >';
+
+                               $this->indent( 1 );
                        }
 
-                       $this->indent( 1 );
                        foreach ( $tabs as $key => $tab ) {
 
                                // skip redundant links (i.e. the 'view' link)
@@ -102,8 +112,19 @@
                                                $this->indent( -1 ) . '</li>';
                        }
                }
+               $this->indent( -2 );
 
-               $ret .= $this->indent( -1 ) . '</ul>' . "\n";
+               if ( $ret !== '' ){
+               $ret = $this->indent( 1 ) . '<!-- Content navigation -->' .
+                       $this->indent() .
+                       \Html::openElement( 'ul',
+                               array(
+                                       'class' => 'p-contentnavigation ' . 
$this->getClassString(),
+                                       'id' => 
IdRegistry::getRegistry()->getId( 'p-contentnavigation' ),
+                               ) ) .
+                       $ret .
+                       $this->indent() . '</ul>';
+               }
 
                return $ret;
        }
@@ -117,4 +138,43 @@
                $this->mFlat = $flat;
        }
 
+       /**
+        * Generate strings used for xml 'id' names in tabs
+        *
+        * Stolen from MW's Title::getNamespaceKey()
+        *
+        * Difference: This function here reports the actual namespace while 
the one in Title reports the subject namespace,
+        * i.e. no talk namespaces
+        *
+        * @return mixed|string
+        */
+       public function getNamespaceKey() {
+               global $wgContLang;
+
+               // Gets the subject namespace if this title
+               $namespace = 
$this->getSkinTemplate()->getSkin()->getTitle()->getNamespace();
+
+               // Checks if canonical namespace name exists for namespace
+               if ( MWNamespace::exists( 
$this->getSkinTemplate()->getSkin()->getTitle()->getNamespace() ) ) {
+                       // Uses canonical namespace name
+                       $namespaceKey = MWNamespace::getCanonicalName( 
$namespace );
+               } else {
+                       // Uses text of namespace
+                       $namespaceKey = 
$this->getSkinTemplate()->getSkin()->getTitle()->getNsText();
+               }
+
+               // Makes namespace key lowercase
+               $namespaceKey = $wgContLang->lc( $namespaceKey );
+               // Uses main
+               if ( $namespaceKey == '' ) {
+                       $namespaceKey = 'main';
+               }
+               // Changes file to image for backwards compatibility
+               if ( $namespaceKey == 'file' ) {
+                       $namespaceKey = 'image';
+               }
+               return $namespaceKey;
+       }
+
+
 }
diff --git a/layouts/navhead.xml b/layouts/navhead.xml
index 7ea8a38..fbe694c 100644
--- a/layouts/navhead.xml
+++ b/layouts/navhead.xml
@@ -5,8 +5,8 @@
                        <cell span="12">
                                <component type="NavbarHorizontal">
                     <component type="Logo"></component>
-                    <component type="NavMenu"></component>
-                    <component type="PageTools"></component>
+                    <component type="NavMenu" flatten="navigation"></component>
+                    <component type="PageTools" 
hideSelectedNameSpace="1"></component>
                     <component type="PersonalTools"></component>
                     <component type="SearchBar"></component>
                                </component>
diff --git a/styles/screen.less b/styles/screen.less
index d33cad1..1871e64 100644
--- a/styles/screen.less
+++ b/styles/screen.less
@@ -31,14 +31,18 @@
 @navbar-newtalk-available: @brand-primary;
 @navbar-newtalk-available-hover: darken(@navbar-newtalk-available, 20%);
 
-// if the navbar is in the first row (i.e. at the top of the page) add some 
margin
+// if the navbar is in the first row (i.e. at the top of the page) add some 
margin at the top
 .container > *:first-child .navbar {
        margin-top: (@grid-gutter-width / 2);
 }
 
+.navbar {
 
-.navbar .nav {
-  width: 100%;
+       z-index: auto;
+
+       .nav {
+               width: 100%;
+       }
 }
 
 // override some navbar-brand styles to accommodate an image and include a 
separator to the rest of the navbar
@@ -55,7 +59,7 @@
        }
 }
 
-// styles for personal tools in the navhead component
+// styles for personal tools in the navbar component
 .navbar-personaltools {
 
        .nav();
@@ -115,7 +119,7 @@
 
                }
 
-               &:last-child > a, &.open:last-child > a  {
+               &:last-child > a, &.open:last-child > a {
                        border: none;
                }
 
@@ -125,7 +129,7 @@
 
 .mw-body {
        padding: 0 2em;
-       margin:  1em 0;
+       margin: 1em 0;
 }
 
 .catlinks {
@@ -133,14 +137,14 @@
 }
 
 .firstHeading {
-       border-bottom:  1px solid #eeeeee;
+       border-bottom: 1px solid #eeeeee;
        padding-bottom: .2em;
-       margin-bottom:  .2em;
+       margin-bottom: .2em;
 }
 
 .contentHeader {
-       margin:         1em 0 1.5em;
-       border-bottom:  0;
+       margin: 1em 0 1.5em;
+       border-bottom: 0;
        padding-bottom: 0;
 }
 
@@ -162,7 +166,7 @@
        margin-bottom: 10px;
 }
 
-.p-contentnavigation{
+.p-contentnavigation {
 
        a.selected {
                font-style: italic;
@@ -205,11 +209,11 @@
                &,
                &:hover,
                &:focus {
-                       color:               @nav-tabs-active-link-hover-color;
-                       background-color:    @nav-tabs-active-link-hover-bg;
-                       border:              1px solid 
@nav-tabs-active-link-hover-border-color;
+                       color: @nav-tabs-active-link-hover-color;
+                       background-color: @nav-tabs-active-link-hover-bg;
+                       border: 1px solid 
@nav-tabs-active-link-hover-border-color;
                        border-bottom-color: transparent;
-                       cursor:              default;
+                       cursor: default;
                }
        }
 }
@@ -217,3 +221,4 @@
 .navbar .p-contentnavigation li {
        display: block;
 }
+

-- 
To view, visit https://gerrit.wikimedia.org/r/122266
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Iba41064af7fe36946143841d55bde2860ac91cb4
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/skins/chameleon
Gerrit-Branch: master
Gerrit-Owner: Foxtrott <s7ep...@gmail.com>
Gerrit-Reviewer: Foxtrott <s7ep...@gmail.com>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to