Paladox has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/227212

Change subject: Clean up Apex skin
......................................................................

Clean up Apex skin

* Cleans up code in apex skin to match some of vector which this skin is
* based on.

Includes two new configs to enable or disable watch icon and the search
bar with an icon instead of button.

Adds two missing files.

Add search icon in svg format too.

Convert css to less

Add some svg images

Fixes login and create account was hidden with this patch it is un hidden.

Updated the personal menu so when your logged out it shows The name as
guest which should fix login in and creating account issue.

Change-Id: I9aca5319ee9bee1e069fa7f0ce83c70e1a381c7a
---
M ApexTemplate.php
M SkinApex.php
A csshover.htc
A csshover.min.htc
A hooks.txt
A i18n/de.json
M i18n/en.json
A i18n/es.json
A i18n/ksh.json
A i18n/lb.json
A i18n/mk.json
A i18n/my.json
A i18n/pl.json
M i18n/qqq.json
A i18n/ro.json
A i18n/ru.json
A i18n/shn.json
A i18n/vi.json
A i18n/zh-hans.json
A images/bullet-icon.png
A images/bullet-icon.svg
R images/menu-hover.png
R images/menu.png
R images/nav-hover.png
R images/nav.png
R images/search-ltr.png
A images/search-ltr.svg
A images/search-rtl.png
A images/search-rtl.svg
R images/talk.png
R images/toc-hover.png
R images/toc.png
A images/unwatch-icon-hl.png
A images/unwatch-icon-hl.svg
A images/unwatch-icon.png
A images/unwatch-icon.svg
A images/user-icon.png
A images/user-icon.svg
R images/user.png
A images/watch-icon-hl.png
A images/watch-icon-hl.svg
A images/watch-icon-loading.png
A images/watch-icon-loading.svg
A images/watch-icon.png
A images/watch-icon.svg
D resources/images/icons/watch-loading.gif
D resources/images/icons/watch.png
R resources/screen-narrow.less
R resources/screen-wide.less
R resources/screen.less
M skin.json
51 files changed, 1,128 insertions(+), 290 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/skins/apex 
refs/changes/12/227212/1

diff --git a/ApexTemplate.php b/ApexTemplate.php
index 23b673c..48faf0e 100644
--- a/ApexTemplate.php
+++ b/ApexTemplate.php
@@ -14,12 +14,18 @@
        public function execute() {
                global $wgSitename, $wgApexLogo, $wgStylePath;
 
+               $skin = $this->getSkin();
+
                // Build additional attributes for navigation urls
                $nav = $this->data['content_navigation'];
-               $mode = $this->getSkin()->getUser()->isWatched( 
$this->getSkin()->getRelevantTitle() ) ?
-                       'unwatch' : 'watch';
+
+               $mode = $this->getSkin()->getUser()->isWatched( 
$this->getSkin()->getRelevantTitle() )
+                       ? 'unwatch'
+                       : 'watch';
+
                if ( isset( $nav['actions'][$mode] ) ) {
                        $nav['views'][$mode] = $nav['actions'][$mode];
+                       $nav['views'][$mode]['class'] = rtrim( 'icon ' . 
$nav['views'][$mode]['class'], ' ' );
                        $nav['views'][$mode]['primary'] = true;
                        unset( $nav['actions'][$mode] );
                }
@@ -69,55 +75,136 @@
                        $this->data['personal_urls'] =
                                array_reverse( $this->data['personal_urls'] );
                }
+
+               $this->data['pageLanguage'] =
+                       
$this->getSkin()->getTitle()->getPageViewLanguage()->getHtmlCode();
+
+
+               // User name (or "Guest") to be displayed at the top right (on 
LTR
+               // interfaces) portion of the skin
+               $user = $skin->getUser();
+               if ( !$user->isLoggedIn() ) {
+                       $userNameTop = $skin->msg( 'apex-guest' )->text();
+               } else {
+                       $userNameTop = htmlspecialchars( $user->getName(), 
ENT_QUOTES );
+               }
+
                // Output HTML Page
                $this->html( 'headelement' );
-?>
+               ?>
                <div class="apex-content-wrapper">
-                       <div id="content" class="mw-body">
+                       <div id="content" class="mw-body" role="main">
                                <a id="top"></a>
-                               <div id="mw-js-message" 
style="display:none;"<?php $this->html( 'userlangattributes' ) ?>></div>
-                               <?php if ( $this->data['sitenotice'] ): ?>
-                               <div id="siteNotice"><?php $this->html( 
'sitenotice' ) ?></div>
-                               <?php endif; ?>
-                               <h1 id="firstHeading" 
class="firstHeading"><?php $this->html( 'title' ) ?></h1>
-                               <div id="bodyContent">
-                                       <?php if ( $this->data['isarticle'] ): 
?>
-                                       <div id="siteSub"><?php $this->msg( 
'tagline' ) ?></div>
-                                       <?php endif; ?>
-                                       <div id="contentSub"<?php $this->html( 
'userlangattributes' ) ?>><?php $this->html( 'subtitle' ) ?></div>
-                                       <?php if ( $this->data['undelete'] ): ?>
-                                       <div id="contentSub2"><?php 
$this->html( 'undelete' ) ?></div>
-                                       <?php endif; ?>
-                                       <?php if( $this->data['newtalk'] ): ?>
-                                       <div class="usermessage"><?php 
$this->html( 'newtalk' )  ?></div>
-                                       <?php endif; ?>
-                                       <?php if ( $this->data['showjumplinks'] 
): ?>
+
+                               <?php
+                               if ( $this->data['sitenotice'] ) {
+                                       ?>
+                                       <div id="siteNotice"><?php $this->html( 
'sitenotice' ) ?></div>
+                               <?php
+                               }
+                               ?>
+                               <?php
+                               // Loose comparison with '!=' is intentional, 
to catch null and false too, but not '0'
+                               if ( $this->data['title'] != '' ) {
+                               ?>
+                               <h1 id="firstHeading" class="firstHeading" 
lang="<?php $this->text( 'pageLanguage' ); ?>"><?php
+                                        $this->html( 'title' )
+                               ?></h1>
+                               <?php
+                               } ?>
+                               <?php $this->html( 'prebodyhtml' ) ?>
+                               <div id="bodyContent" class="mw-body-content">
+                                       <?php
+                                       if ( $this->data['isarticle'] ) {
+                                               ?>
+                                               <div id="siteSub"><?php 
$this->msg( 'tagline' ) ?></div>
+                                       <?php
+                                       }
+                                       ?>
+                                       <div id="contentSub"<?php $this->html( 
'userlangattributes' ) ?>><?php
+                                               $this->html( 'subtitle' )
+                                       ?></div>
+                                       <?php
+                                       if ( $this->data['undelete'] ) {
+                                               ?>
+                                               <div id="contentSub2"><?php 
$this->html( 'undelete' ) ?></div>
+                                       <?php
+                                       }
+                                       ?>
+                                       <?php
+                                       if ( $this->data['newtalk'] ) {
+                                               ?>
+                                               <div class="usermessage"><?php 
$this->html( 'newtalk' ) ?></div>
+                                       <?php
+                                       }
+                                       ?>
                                        <div id="jump-to-nav" class="mw-jump">
                                                <?php $this->msg( 'jumpto' ) ?>
-                                               <a href="#mw-head"><?php 
$this->msg( 'jumptonavigation' ) ?></a><?php $this->msg( 'comma-separator' ) ?>
+                                               <a href="#mw-head"><?php
+                                                       $this->msg( 
'jumptonavigation' )
+                                               ?></a><?php $this->msg( 
'comma-separator' ) ?>
                                                <a href="#p-search"><?php 
$this->msg( 'jumptosearch' ) ?></a>
                                        </div>
-                                       <?php endif; ?>
-                                       <?php $this->html( 'bodycontent' ) ?>
-                                       <?php if ( $this->data['printfooter'] 
): ?>
-                                       <div class="printfooter">
-                                       <?php $this->html( 'printfooter' ); ?>
-                                       </div>
-                                       <?php endif; ?>
-                                       <?php if ( $this->data['catlinks'] ): ?>
-                                       <?php $this->html( 'catlinks' ); ?>
-                                       <?php endif; ?>
-                                       <?php if ( 
$this->data['dataAfterContent'] ): ?>
-                                       <?php $this->html( 'dataAfterContent' 
); ?>
-                                       <?php endif; ?>
+                                       <?php
+                                       $this->html( 'bodycontent' );
+                                       if ( $this->data['printfooter'] ) {
+                                               ?>
+                                               <div class="printfooter">
+                                                       <?php $this->html( 
'printfooter' ); ?>
+                                               </div>
+                                       <?php
+                                       }
+                                       if ( $this->data['catlinks'] ) {
+                                               $this->html( 'catlinks' );
+                                       }
+
+                                       if ( $this->data['dataAfterContent'] ) {
+                                               $this->html( 'dataAfterContent' 
);
+                                       }
+                                       ?>
                                        <div class="visualClear"></div>
                                        <?php $this->html( 'debughtml' ); ?>
                                </div>
                        </div>
                </div>
                <div id="mw-head" class="noprint">
-                       <div id="p-logo"><a style="background-image: url(<?php 
$this->text( 'logopath-1x' ) ?>);" href="<?php echo htmlspecialchars( 
$this->data['nav_urls']['mainpage']['href'] ) ?>" <?php echo 
Xml::expandAttributes( Linker::tooltipAndAccesskeyAttribs( 'p-logo' ) ) 
?>><span><?php echo $wgSitename ?></span></a></div>
-                       <?php $this->renderNavigation( array( 'SEARCH', 
'PERSONAL' ) ); ?>
+                       <?php
+                       if ( $this->config->get( 'ApexUseLogo' ) ) {
+                               ?>
+                               <div id="p-logo" role="banner"><a 
class="mw-wiki-logo" href="<?php
+                                       echo htmlspecialchars( 
$this->data['nav_urls']['mainpage']['href'] )
+                                       ?>" <?php
+                                       echo Xml::expandAttributes( 
Linker::tooltipAndAccesskeyAttribs( 'p-logo' ) )
+                                       ?>></a>
+                               </div>
+                       <?php
+                       } else {
+                               ?>
+                               <div id="p-logo"><a style="background-image: 
url(<?php
+                                       $this->text( 'logopath-1x' ) ?>);" 
href="<?php
+                                       echo htmlspecialchars( 
$this->data['nav_urls']['mainpage']['href'] )
+                                       ?>"<?php
+                                       echo Xml::expandAttributes( 
Linker::tooltipAndAccesskeyAttribs( 'p-logo' ) )
+                                       ?>>
+                                       <span><?php echo $GLOBALS['wgSitename'] 
?></span></a>
+                               </div>
+                       <?php
+                       }
+                       ?>
+                       <?php $this->renderNavigation( array( 'SEARCH' ) ); ?>
+                       <div class="apex-menu" id="usermenu">
+                                       <a href="#" class="user-icon-container">
+                                               <span id="username-top">
+                                                       <span 
id="username-text"><?php echo $userNameTop ?></span>
+                                                       <span 
class="username-space spacer"> </span>
+                                                       <span id="userIcon20">
+                                                               <div 
class="userIcon20"></div>
+                                               </span>
+                                       </a>
+                                       <div class="apex-menu-popup 
personal-menu">
+                                               <?php $this->renderNavigation( 
'PERSONAL' ); ?>
+                                       </div>
+                       </div>
                        <div class="apex-nav">
                                <div class="apex-nav-primary">
                                        <?php $this->renderNavigation( array( 
'NAMESPACES', 'VARIANTS' ) ); ?>
@@ -131,31 +218,47 @@
                        <div class="apex-flyout-pull"></div>
                        <?php $this->renderPortals( $this->data['sidebar'] ); ?>
                </div>
-               <div id="footer"<?php $this->html( 'userlangattributes' ) ?>>
-                       <?php foreach( $this->getFooterLinks() as $category => 
$links ): ?>
+               <div id="footer" role="contentinfo"<?php $this->html( 
'userlangattributes' ) ?>>
+                       <?php
+                       foreach ( $this->getFooterLinks() as $category => 
$links ) {
+                               ?>
                                <ul id="footer-<?php echo $category ?>">
-                                       <?php foreach( $links as $link ): ?>
-                                               <li id="footer-<?php echo 
$category ?>-<?php echo $link ?>">
-                                                       <?php $this->html( 
$link ) ?>
-                                               </li>
-                                       <?php endforeach; ?>
+                                       <?php
+                                       foreach ( $links as $link ) {
+                                               ?>
+                                               <li id="footer-<?php echo 
$category ?>-<?php echo $link ?>"><?php $this->html( $link ) ?></li>
+                                       <?php
+                                       }
+                                       ?>
                                </ul>
-                       <?php endforeach; ?>
-                       <?php $footericons = $this->getFooterIcons("icononly");
-                       if ( count( $footericons ) > 0 ): ?>
+                       <?php
+                       }
+                       ?>
+                       <?php $footericons = $this->getFooterIcons( "icononly" 
);
+                       if ( count( $footericons ) > 0 ) {
+                               ?>
                                <ul id="footer-icons" class="noprint">
-                                       <?php foreach ( $footericons as 
$blockName => $footerIcons ): ?>
-                                       <li id="footer-<?php echo 
htmlspecialchars( $blockName ); ?>ico">
-                                               <?php foreach ( $footerIcons as 
$icon ): ?>
-                                               <?php echo 
$this->getSkin()->makeFooterIcon( $icon ); ?>
-                                               <?php endforeach; ?>
-                                       </li>
-                                       <?php endforeach; ?>
+                                       <?php
+                                       foreach ( $footericons as $blockName => 
$footerIcons ) {
+                                               ?>
+                                               <li id="footer-<?php echo 
htmlspecialchars( $blockName ); ?>ico">
+                                                       <?php
+                                                       foreach ( $footerIcons 
as $icon ) {
+                                                               echo 
$this->getSkin()->makeFooterIcon( $icon );
+                                                       }
+                                                       ?>
+                                               </li>
+                                       <?php
+                                       }
+                                       ?>
                                </ul>
-                       <?php endif; ?>
+                       <?php
+                       }
+                       ?>
                        <div style="clear:both"></div>
                </div>
                <?php $this->printTrail(); ?>
+
        </body>
 </html>
 <?php
@@ -164,7 +267,7 @@
        /**
         * Render a series of portals
         *
-        * @param $portals array
+        * @param array $portals
         */
        protected function renderPortals( $portals ) {
                // Force the rendering of the following portals
@@ -182,179 +285,292 @@
                        if ( $content === false ) {
                                continue;
                        }
-                       switch( $name ) {
+
+                       // Numeric strings gets an integer when set as key, 
cast back - T73639
+                       $name = (string)$name;
+
+                       switch ( $name ) {
                                case 'SEARCH':
                                        break;
                                case 'TOOLBOX':
                                        $this->renderPortal( 'tb', 
$this->getToolbox(), 'toolbox', 'SkinTemplateToolboxEnd' );
                                        break;
                                case 'LANGUAGES':
-                                       if ( $this->data['language_urls'] ) {
+                                       if ( $this->data['language_urls'] !== 
false ) {
                                                $this->renderPortal( 'lang', 
$this->data['language_urls'], 'otherlanguages' );
                                        }
                                        break;
                                default:
                                        $this->renderPortal( $name, $content );
-                               break;
+                                       break;
                        }
                }
        }
 
        /**
-        * @param $name string
-        * @param $content array
-        * @param $msg null|string
-        * @param $hook null|string|array
+        * @param string $name
+        * @param array $content
+        * @param null|string $msg
+        * @param null|string|array $hook
         */
        protected function renderPortal( $name, $content, $msg = null, $hook = 
null ) {
                if ( $msg === null ) {
                        $msg = $name;
                }
+               $msgObj = wfMessage( $msg );
+               $labelId = Sanitizer::escapeId( "p-$name-label" );
                ?>
-<div class="portal" id='<?php echo Sanitizer::escapeId( "p-$name" ) ?>'<?php 
echo Linker::tooltip( 'p-' . $name ) ?>>
-       <h5<?php $this->html( 'userlangattributes' ) ?>><?php $msgObj = 
wfMessage( $msg ); echo htmlspecialchars( $msgObj->exists() ? $msgObj->text() : 
$msg ); ?></h5>
-       <div class="body">
-<?php
-               if ( is_array( $content ) ): ?>
-               <ul>
-<?php
-                       foreach( $content as $key => $val ): ?>
-                       <?php echo $this->makeListItem( $key, $val ); ?>
+               <div class="portal" role="navigation" id='<?php
+               echo Sanitizer::escapeId( "p-$name" )
+               ?>'<?php
+               echo Linker::tooltip( 'p-' . $name )
+               ?> aria-labelledby='<?php echo $labelId ?>'>
+                       <h5<?php $this->html( 'userlangattributes' ) ?> 
id='<?php echo $labelId ?>'><?php
+                               echo htmlspecialchars( $msgObj->exists() ? 
$msgObj->text() : $msg );
+                               ?></h5>
 
-<?php
-                       endforeach;
-                       if ( $hook !== null ) {
-                               wfRunHooks( $hook, array( &$this, true ) );
-                       }
-                       ?>
-               </ul>
-<?php
-               else: ?>
-               <?php echo $content; /* Allow raw HTML block to be defined by 
extensions */ ?>
-<?php
-               endif; ?>
-       </div>
-</div>
-<?php
+                       <div class="body">
+                               <?php
+                               if ( is_array( $content ) ) {
+                                       ?>
+                                       <ul>
+                                               <?php
+                                               foreach ( $content as $key => 
$val ) {
+                                                       echo 
$this->makeListItem( $key, $val );
+                                               }
+                                               if ( $hook !== null ) {
+                                                       Hooks::run( $hook, 
array( &$this, true ) );
+                                               }
+                                               ?>
+                                       </ul>
+                               <?php
+                               } else {
+                                       echo $content; /* Allow raw HTML block 
to be defined by extensions */
+                               }
+
+                               $this->renderAfterPortlet( $name );
+                               ?>
+                       </div>
+               </div>
+       <?php
        }
 
        /**
         * Render one or more navigations elements by name, automatically 
reveresed
         * when UI is in RTL mode
         *
-        * @param $elements array
+        * @param array $elements
         */
        protected function renderNavigation( $elements ) {
                // If only one element was given, wrap it in an array, allowing 
more
                // flexible arguments
                if ( !is_array( $elements ) ) {
                        $elements = array( $elements );
-               // If there's a series of elements, reverse them when in RTL 
mode
+                       // If there's a series of elements, reverse them when 
in RTL mode
                } elseif ( $this->data['rtl'] ) {
                        $elements = array_reverse( $elements );
                }
                // Render elements
-               foreach ( $elements as $element ) {
+               foreach ( $elements as $name => $element ) {
                        switch ( $element ) {
                                case 'NAMESPACES':
-?>
-<div id="p-namespaces" class="apex-tabs<?php if ( count( 
$this->data['namespace_urls'] ) == 0 ) echo ' emptyPortlet'; ?>">
-       <h5><?php $this->msg( 'namespaces' ) ?></h5>
-       <ul<?php $this->html( 'userlangattributes' ) ?>>
-               <?php foreach ( $this->data['namespace_urls'] as $link ): ?>
-                       <li <?php echo $link['attributes'] ?>><span><a 
href="<?php echo htmlspecialchars( $link['href'] ) ?>" <?php echo $link['key'] 
?>><?php echo htmlspecialchars( $link['text'] ) ?></a></span></li>
-               <?php endforeach; ?>
-       </ul>
-</div>
-<?php
-                               break;
+                                       ?>
+                                       <div id="p-namespaces" 
role="navigation" class="apex-tabs<?php
+                                       if ( count( 
$this->data['namespace_urls'] ) == 0 ) {
+                                               echo ' emptyPortlet';
+                                       }
+                                       ?>" 
aria-labelledby="p-namespaces-label">
+                                               <h5 
id="p-namespaces-label"><?php $this->msg( 'namespaces' ) ?></h5>
+                                               <ul<?php $this->html( 
'userlangattributes' ) ?>>
+                                                       <?php
+                                                       foreach ( 
$this->data['namespace_urls'] as $link ) {
+                                                               ?>
+                                                               <li <?php echo 
$link['attributes'] ?>><span><a href="<?php
+                                                                               
echo htmlspecialchars( $link['href'] )
+                                                                               
?>" <?php
+                                                                               
echo $link['key'];
+                                                                               
if ( isset ( $link['rel'] ) ) {
+                                                                               
        echo ' rel="' . htmlspecialchars( $link['rel'] ) . '"';
+                                                                               
}
+                                                                               
?>><?php
+                                                                               
        echo htmlspecialchars( $link['text'] )
+                                                                               
        ?></a></span></li>
+                                                       <?php
+                                                       }
+                                                       ?>
+                                               </ul>
+                                       </div>
+                                       <?php
+                                       break;
                                case 'VARIANTS':
-?>
-<div id="p-variants" class="apex-menu<?php if ( count( 
$this->data['variant_urls'] ) == 0 ) echo ' emptyPortlet'; ?>">
-       <h4>
-       <?php foreach ( $this->data['variant_urls'] as $link ): ?>
-               <?php if ( stripos( $link['attributes'], 'selected' ) !== false 
): ?>
-                       <?php echo htmlspecialchars( $link['text'] ) ?>
-               <?php endif; ?>
-       <?php endforeach; ?>
-       </h4>
-       <h5><span><?php $this->msg( 'variants' ) ?></span><a href="#"></a></h5>
-       <div class="menu">
-               <ul>
-                       <?php foreach ( $this->data['variant_urls'] as $link ): 
?>
-                               <li<?php echo $link['attributes'] ?>><a 
href="<?php echo htmlspecialchars( $link['href'] ) ?>" lang="<?php echo 
htmlspecialchars( $link['lang'] ) ?>" hreflang="<?php echo htmlspecialchars( 
$link['hreflang'] ) ?>" <?php echo $link['key'] ?>><?php echo htmlspecialchars( 
$link['text'] ) ?></a></li>
-                       <?php endforeach; ?>
-               </ul>
-       </div>
-</div>
-<?php
-                               break;
+                                       ?>
+                                       <div id="p-variants" role="navigation" 
class="apex-menu<?php
+                                       if ( count( $this->data['variant_urls'] 
) == 0 ) {
+                                               echo ' emptyPortlet';
+                                       }
+                                       ?>" aria-labelledby="p-variants-label">
+                                               <?php
+                                               // Replace the label with the 
name of currently chosen variant, if any
+                                               $variantLabel = $this->getMsg( 
'variants' )->text();
+                                               foreach ( 
$this->data['variant_urls'] as $link ) {
+                                                       if ( stripos( 
$link['attributes'], 'selected' ) !== false ) {
+                                                               $variantLabel = 
$link['text'];
+                                                               break;
+                                                       }
+                                               }
+                                               ?>
+                                               <h5 id="p-variants-label">
+                                                       <span><?php echo 
htmlspecialchars( $variantLabel ) ?></span><a href="#"></a>
+                                               </h5>
+
+                                               <div class="menu">
+                                                       <ul>
+                                                               <?php
+                                                               foreach ( 
$this->data['variant_urls'] as $link ) {
+                                                                       ?>
+                                                                       
<li<?php echo $link['attributes'] ?>><a href="<?php
+                                                                               
echo htmlspecialchars( $link['href'] )
+                                                                               
?>" lang="<?php
+                                                                               
echo htmlspecialchars( $link['lang'] )
+                                                                               
?>" hreflang="<?php
+                                                                               
echo htmlspecialchars( $link['hreflang'] )
+                                                                               
?>" <?php
+                                                                               
echo $link['key']
+                                                                               
?>><?php
+                                                                               
        echo htmlspecialchars( $link['text'] )
+                                                                               
        ?></a></li>
+                                                               <?php
+                                                               }
+                                                               ?>
+                                                       </ul>
+                                               </div>
+                                       </div>
+                                       <?php
+                                       break;
                                case 'VIEWS':
-?>
-<div id="p-views" class="apex-tabs<?php if ( count( $this->data['view_urls'] ) 
== 0 ) { echo ' emptyPortlet'; } ?>">
-       <h5><?php $this->msg('views') ?></h5>
-       <ul<?php $this->html('userlangattributes') ?>>
-               <?php foreach ( $this->data['view_urls'] as $link ): ?>
-                       <li<?php echo $link['attributes'] ?>><span><a 
href="<?php echo htmlspecialchars( $link['href'] ) ?>" <?php echo $link['key'] 
?>><?php
-                               // $link['text'] can be undefined - bug 27764
-                               if ( array_key_exists( 'text', $link ) ) {
-                                       echo array_key_exists( 'img', $link ) ? 
 '<img src="' . $link['img'] . '" alt="' . $link['text'] . '" />' : 
htmlspecialchars( $link['text'] );
-                               }
-                               ?></a></span></li>
-               <?php endforeach; ?>
-       </ul>
-</div>
-<?php
-                               break;
+                                       ?>
+                                       <div id="p-views" role="navigation" 
class="apex-tabs<?php
+                                       if ( count( $this->data['view_urls'] ) 
== 0 ) {
+                                               echo ' emptyPortlet';
+                                       }
+                                       ?>" aria-labelledby="p-views-label">
+                                               <h5 id="p-views-label"><?php 
$this->msg( 'views' ) ?></h5>
+                                               <ul<?php $this->html( 
'userlangattributes' ) ?>>
+                                                       <?php
+                                                       foreach ( 
$this->data['view_urls'] as $link ) {
+                                                               ?>
+                                                               <li<?php echo 
$link['attributes'] ?>><span><a href="<?php
+                                                                               
echo htmlspecialchars( $link['href'] )
+                                                                               
?>" <?php
+                                                                               
echo $link['key'];
+                                                                               
if ( isset ( $link['rel'] ) ) {
+                                                                               
        echo ' rel="' . htmlspecialchars( $link['rel'] ) . '"';
+                                                                               
}
+                                                                               
?>><?php
+                                                                               
        // $link['text'] can be undefined - bug 27764
+                                                                               
        if ( array_key_exists( 'text', $link ) ) {
+                                                                               
                echo array_key_exists( 'img', $link )
+                                                                               
                        ? '<img src="' . $link['img'] . '" alt="' . 
$link['text'] . '" />'
+                                                                               
                        : htmlspecialchars( $link['text'] );
+                                                                               
        }
+                                                                               
        ?></a></span></li>
+                                                       <?php
+                                                       }
+                                                       ?>
+                                               </ul>
+                                       </div>
+                                       <?php
+                                       break;
                                case 'ACTIONS':
-?>
-<div id="p-cactions" class="apex-menu<?php if ( count( 
$this->data['action_urls'] ) == 0 ) echo ' emptyPortlet'; ?>">
-       <h5><span><?php $this->msg( 'actions' ) ?></span><a href="#"></a></h5>
-       <div class="apex-menu-popup">
-               <ul<?php $this->html( 'userlangattributes' ) ?>>
-                       <?php foreach ( $this->data['action_urls'] as $link ): 
?>
-                               <li<?php echo $link['attributes'] ?>><span><a 
href="<?php echo htmlspecialchars( $link['href'] ) ?>" <?php echo $link['key'] 
?>><?php echo htmlspecialchars( $link['text'] ) ?></span></a></li>
-                       <?php endforeach; ?>
-               </ul>
-       </div>
-</div>
-<?php
+                                       ?>
+                                       <div id="p-cactions" role="navigation"  
class="apex-menu<?php
+                                       if ( count( $this->data['action_urls'] 
) == 0 ) {
+                                               echo ' emptyPortlet';
+                                       }
+                                       ?>" aria-labelledby="p-cactions-label">
+                                               <h5 
id="p-cactions-label"><span><?php
+                                                       $this->msg( 
'vector-more-actions' )
+                                               ?></span><a href="#"></a></h5>
+
+                                               <div class="apex-menu-popup">
+                                                       <ul<?php $this->html( 
'userlangattributes' ) ?>>
+                                                               <?php
+                                                               foreach ( 
$this->data['action_urls'] as $link ) {
+                                                                       ?>
+                                                                       
<li<?php echo $link['attributes'] ?>>
+                                                                               
<a href="<?php
+                                                                               
echo htmlspecialchars( $link['href'] )
+                                                                               
?>" <?php
+                                                                               
echo $link['key'] ?>><?php echo htmlspecialchars( $link['text'] )
+                                                                               
        ?></a>
+                                                                       </li>
+                                                               <?php
+                                                               }
+                                                               ?>
+                                                       </ul>
+                                               </div>
+                                       </div>
+                                       <?php
+                                       break;
                                break;
                                case 'PERSONAL':
-?>
-<div id="p-personal" class="<?php if ( count( $this->data['personal_urls'] ) 
== 0 ) echo ' emptyPortlet'; ?>">
-       <h5><?php $this->msg( 'personaltools' ) ?></h5>
-       <ul<?php $this->html( 'userlangattributes' ) ?>>
-               <?php foreach( $this->getPersonalTools() as $key => $item ): ?>
-                       <?php if ( $key === 'userpage' ): ?>
-                       <?php echo $this->makeListItem( $key, $item ); ?>
-                       <?php endif; ?>
-               <?php endforeach; ?>
-       </ul>
-       <ul<?php $this->html( 'userlangattributes' ) ?> class="apex-menu-popup">
-               <?php foreach( $this->getPersonalTools() as $key => $item ): ?>
-                       <?php if ( $key !== 'userpage' ): ?>
-                       <?php echo $this->makeListItem( $key, $item ); ?>
-                       <?php endif; ?>
-               <?php endforeach; ?>
-       </ul>
-</div>
-<?php
-                               break;
+                                       ?>
+                                       <div id="p-personal" role="navigation" 
class="<?php
+                                       if ( count( 
$this->data['personal_urls'] ) == 0 ) {
+                                               echo ' emptyPortlet';
+                                       }
+                                       ?>" aria-labelledby="p-personal-label">
+                                               <h5 id="p-personal-label"><?php 
$this->msg( 'personaltools' ) ?></h5>
+                                               <ul<?php $this->html( 
'userlangattributes' ) ?>>
+                                                       <?php
+                                                       $personalTools = 
$this->getPersonalTools();
+                                                       foreach ( 
$personalTools as $key => $item ) {
+                                                                       echo 
$this->makeListItem( $key, $item );
+                                                       }
+                                                       ?>
+                                               </ul>
+
+                                       </div>
+                                       <?php
+                                       break;
                                case 'SEARCH':
-?>
-<div id="p-search">
-       <h5<?php $this->html( 'userlangattributes' ) ?>><label 
for="searchInput"><?php $this->msg( 'search' ) ?></label></h5>
-       <form action="<?php $this->text( 'wgScript' ) ?>" id="searchform">
-               <div id="simpleSearch">
-                       <?php echo $this->makeSearchInput( array( 'id' => 
'searchInput', 'type' => 'text' ) ); ?>
-                       <?php echo $this->makeSearchButton( 'image', array( 
'id' => 'searchButton', 'src' => $this->getSkin()->getSkinStylePath( 
'images/icons/search.png' ), 'width' => '12', 'height' => '13' ) ); ?>
-                       <input type='hidden' name="title" value="<?php 
$this->text( 'searchtitle' ) ?>"/>
-               </div>
-       </form>
-</div>
-<?php
-                               break;
+                                       ?>
+                                       <div id="p-search" role="search">
+                                               <h5<?php $this->html( 
'userlangattributes' ) ?>>
+                                                       <label 
for="searchInput"><?php $this->msg( 'search' ) ?></label>
+                                               </h5>
+
+                                               <form action="<?php 
$this->text( 'wgScript' ) ?>" id="searchform">
+                                                       <div id="simpleSearch">
+                                                       <?php
+                                                       echo 
$this->makeSearchInput( array( 'id' => 'searchInput' ) );
+                                                       echo Html::hidden( 
'title', $this->get( 'searchtitle' ) );
+                                                       // We construct two 
buttons (for 'go' and 'fulltext' search modes),
+                                                       // but only one will be 
visible and actionable at a time (they are
+                                                       // overlaid on top of 
each other in CSS).
+                                                       // * Browsers will use 
the 'fulltext' one by default (as it's the
+                                                       //   first in 
tree-order), which is desirable when they are unable
+                                                       //   to show search 
suggestions (either due to being broken or
+                                                       //   having JavaScript 
turned off).
+                                                       // * The 
mediawiki.searchSuggest module, after doing tests for the
+                                                       //   broken browsers, 
removes the 'fulltext' button and handles
+                                                       //   'fulltext' search 
itself; this will reveal the 'go' button and
+                                                       //   cause it to be 
used.
+                                                       echo 
$this->makeSearchButton(
+                                                               'fulltext',
+                                                               array( 'id' => 
'mw-searchButton', 'class' => 'searchButton mw-fallbackSearchButton' )
+                                                       );
+                                                       echo 
$this->makeSearchButton(
+                                                               'go',
+                                                               array( 'id' => 
'searchButton', 'class' => 'searchButton' )
+                                                       );
+                                                       ?>
+                                                       </div>
+                                               </form>
+                                       </div>
+                                       <?php
+
+                                       break;
                        }
                }
        }
diff --git a/SkinApex.php b/SkinApex.php
index bcbd767..27c6861 100644
--- a/SkinApex.php
+++ b/SkinApex.php
@@ -8,25 +8,32 @@
 
        protected static $bodyClasses = array( 'apex-animateLayout' );
 
-       var $skinname = 'apex', $stylename = 'apex',
-               $template = 'ApexTemplate', $useHeadElement = true;
+       public $skinname = 'apex';
+       public $stylename = 'apex';
+       public $template = 'ApexTemplate';
+       /**
+        * @var Config
+        */
+       private $apexConfig;
+
+       public function __construct() {
+               $this->apexConfig = 
ConfigFactory::getDefaultInstance()->makeConfig( 'apex' );
+       }
 
        /**
         * Initializes output page and sets up skin-specific parameters
-        * @param $out OutputPage object to initialize
+        * @param OutputPage $out Object to initialize
         */
        public function initPage( OutputPage $out ) {
-               global $wgLocalStylePath;
-
                parent::initPage( $out );
 
                // Append CSS which includes IE only behavior fixes for hover 
support -
-               // this is better than including this in a CSS fille since it 
doesn't
+               // this is better than including this in a CSS file since it 
doesn't
                // wait for the CSS file to load before fetching the HTC file.
                $min = $this->getRequest()->getFuzzyBool( 'debug' ) ? '' : 
'.min';
                $out->addHeadItem( 'csshover',
                        '<!--[if lt IE 7]><style 
type="text/css">body{behavior:url("' .
-                               htmlspecialchars( $wgLocalStylePath ) .
+                               htmlspecialchars( $this->getConfig()->get( 
'LocalStylePath' ) ) .
                                
"/{$this->stylename}/csshover{$min}.htc\")}</style><![endif]-->"
                );
                $out->addHeadItem( 'ie9-gradient',
@@ -34,20 +41,25 @@
                                '.gradient { filter: none; 
}</style><![endif]-->'
                );
 
-               $out->addModuleScripts( 'skins.apex' );
+               $out->addModuleScripts( 'skins.apex.js' );
        }
 
        /**
-        * Load skin and user CSS files in the correct order
-        * fixes bug 22916
-        * @param $out OutputPage object
+        * Loads skin and user CSS files.
+        * @param OutputPage $out
         */
-       function setupSkinUserCss( OutputPage $out ){
+       function setupSkinUserCss( OutputPage $out ) {
                parent::setupSkinUserCss( $out );
-               $out->addModuleStyles( array(
-                       'mediawiki.skinning.interface',
-                       'skins.apex'
-               ) );
+
+               $styles = array( 'mediawiki.skinning.interface', 'skins.apex' );
+               $out->addModuleStyles( $styles );
+       }
+
+       /**
+        * Override to pass our Config instance to it
+        */
+       public function setupTemplate( $classname, $repository = false, 
$cache_dir = false ) {
+               return new $classname( $this->apexConfig );
        }
 
        /**
diff --git a/csshover.htc b/csshover.htc
new file mode 100644
index 0000000..a13ea68
--- /dev/null
+++ b/csshover.htc
@@ -0,0 +1,284 @@
+<public:attach event="ondocumentready" onevent="CSSHover()" />
+<script>
+/**
+ *     Whatever:hover - V3.11
+ *     ------------------------------------------------------------
+ *     Author  - Peter Nederlof, http://www.xs4all.nl/~peterned
+ *     License - http://creativecommons.org/licenses/LGPL/2.1
+ *
+ *     Special thanks to Sergiu Dumitriu, http://purl.org/net/sergiu,
+ *     for fixing the expression loop.
+ *
+ *     Whatever:hover is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU Lesser General Public
+ *     License as published by the Free Software Foundation; either
+ *     version 2.1 of the License, or (at your option) any later version.
+ *
+ *     Whatever:hover 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
+ *     Lesser General Public License for more details.
+ *
+ *     howto: body { behavior:url("csshover3.htc"); }
+ *     ------------------------------------------------------------
+ */
+
+window.CSSHover = (function(){
+
+       // regular expressions, used and explained later on.
+       var REG_INTERACTIVE = /(^|\s)((([^a]([^ ]+)?)|(a([^#.][^ 
]+)+)):(hover|active|focus))/i;
+       var REG_AFFECTED = /(.*?)\:(hover|active|focus)/i;
+       var REG_PSEUDO = /[^:]+:([a-z\-]+).*/i;
+       var REG_SELECT = /(\.([a-z0-9_\-]+):[a-z]+)|(:[a-z]+)/gi;
+       var REG_CLASS = /\.([a-z0-9_\-]*on(hover|active|focus))/i;
+       var REG_MSIE = /msie (5|6|7)/i;
+       var REG_COMPAT = /backcompat/i;
+
+       // property mapping, real css properties must be used in order to clear 
expressions later on...
+       // Uses obscure css properties that no-one is likely to use. The 
properties are borrowed to
+       // set an expression, and are then restored to the most likely correct 
value.
+       var Properties = {
+               index: 0,
+               list: ['text-kashida', 'text-kashida-space', 'text-justify'],
+               get: function() {
+                       return this.list[(this.index++)%this.list.length];
+               }
+       };
+
+       // camelize is used to convert css properties from (eg) text-kashida to 
textKashida
+       var camelize = function(str) {
+               return str.replace(/-(.)/mg, function(result, match){
+                       return match.toUpperCase();
+               });
+       };
+       
+       /**
+        *      Local CSSHover object
+        *      --------------------------
+        */
+       
+       var CSSHover = {
+               
+               // array of CSSHoverElements, used to unload created events
+               elements: [], 
+               
+               // buffer used for checking on duplicate expressions
+               callbacks: {}, 
+               
+               // init, called once ondomcontentready via the exposed 
window.CSSHover function
+               init:function() {
+                       // don't run in IE8 standards; expressions don't work 
in standards mode anyway, 
+                       // and the stuff we're trying to fix should already 
work properly
+                       if(!REG_MSIE.test(navigator.userAgent) && 
!REG_COMPAT.test(window.document.compatMode)) {
+                               return;
+                       }
+
+                       // start parsing the existing stylesheets
+                       var sheets = window.document.styleSheets, l = 
sheets.length;
+                       for(var i=0; i<l; i++) {
+                               this.parseStylesheet(sheets[i]);
+                       }
+               },
+
+               // called from init, parses individual stylesheets
+               parseStylesheet:function(sheet) {
+                       // check sheet imports and parse those recursively
+                       if(sheet.imports) {
+                               try {
+                                       var imports = sheet.imports;
+                                       var l = imports.length;
+                                       for(var i=0; i<l; i++) {
+                                               
this.parseStylesheet(sheet.imports[i]);
+                                       }
+                               } catch(securityException){
+                                       // trycatch for various possible errors
+                               }
+                       }
+                       
+                       // interate the sheet's rules and send them to the 
parser
+                       try {
+                               var rules = sheet.rules;
+                               var r = rules.length;
+                               for(var j=0; j<r; j++) {
+                                       this.parseCSSRule(rules[j], sheet);
+                               }
+                       } catch(someException){
+                               // trycatch for various errors, most likely 
accessing the sheet's rules.
+                       }
+               },
+
+               // magic starts here ...
+               parseCSSRule:function(rule, sheet) {
+                       
+                       // The sheet is used to insert new rules into, this 
must be the same sheet the rule 
+                       // came from, to ensure that relative paths keep 
pointing to the right location.
+
+                       // only parse a rule if it contains an interactive 
pseudo.
+                       var select = rule.selectorText;
+                       if(REG_INTERACTIVE.test(select)) {
+                               var style = rule.style.cssText;
+                                       
+                               // affected elements are found by truncating 
the selector after the interactive pseudo,
+                               // eg: "div li:hover" >>  "div li"
+                               var affected = REG_AFFECTED.exec(select)[1];
+                                       
+                               // that pseudo is needed for a classname, and 
defines the type of interaction (focus, hover, active)
+                               // eg: "li:hover" >> "onhover"
+                               var pseudo = select.replace(REG_PSEUDO, 'on$1');
+                                       
+                               // the new selector is going to use that 
classname in a new css rule,
+                               // since IE6 doesn't support multiple 
classnames, this is merged into one classname
+                               // eg: "li:hover" >> "li.onhover",  
"li.folder:hover" >> "li.folderonhover"
+                               var newSelect = select.replace(REG_SELECT, 
'.$2' + pseudo);
+                                       
+                               // the classname is needed for the events that 
are going to be set on affected nodes
+                               // eg: "li.folder:hover" >> "folderonhover"
+                               var className = REG_CLASS.exec(newSelect)[1];
+
+                               // no need to set the same callback more than 
once when the same selector uses the same classname
+                               var hash = affected + className;
+                               if(!this.callbacks[hash]) {
+                                       
+                                       // affected elements are given an 
expression under a borrowed css property, because fake properties
+                                       // can't have their expressions 
cleared. Different properties are used per pseudo, to avoid
+                                       // expressions from overwriting 
eachother. The expression does a callback to CSSHover.patch, 
+                                       // rerouted via the exposed 
window.CSSHover function.
+                                       var property = Properties.get();
+                                       var atRuntime = camelize(property);
+
+                                       // because the expression is added to 
the stylesheet, and styles are always applied to html that is
+                                       // dynamically added to the dom, the 
expression will also trigger for those new elements (provided
+                                       // they are selected by the affected 
selector). 
+                                       sheet.addRule(affected, property + 
':expression(CSSHover(this, "'+pseudo+'", "'+className+'", "'+atRuntime+'"))');
+                                       
+                                       // hash it, so an identical 
selector/class combo does not duplicate the expression
+                                       this.callbacks[hash] = true;
+                               }
+                               
+                               // duplicate expressions need not be set, but 
the style could differ
+                               sheet.addRule(newSelect, style);
+                       }
+               },
+
+               // called via the expression, patches individual nodes
+               patch:function(node, type, className, property) {
+
+                       // restores the borrowed css property to the value of 
its immediate parent, clearing
+                       // the expression so that it's not repeatedly called. 
+                       try {
+                               var value = 
node.parentNode.currentStyle[property];
+                               node.style[property] = value;   
+                       } catch(e) {
+                               // the above reset should never fail, but just 
in case, clear the runtimeStyle if it does.
+                               // this will also stop the expression.
+                               node.runtimeStyle[property] = '';
+                       }                       
+               
+                       // just to make sure, also keep track of patched 
classnames locally on the node
+                       if(!node.csshover) {
+                               node.csshover = [];
+                       }
+
+                       // and check for it to prevent duplicate events with 
the same classname from being set
+                       if(!node.csshover[className]) {
+                               node.csshover[className] = true;
+
+                               // create an instance for the given type and 
class
+                               var element = new CSSHoverElement(node, type, 
className);
+                               
+                               // and store that instance for unloading later 
on
+                               this.elements.push(element);
+                       }
+
+                       // returns a dummy value to the expression
+                       return type;
+               },
+
+               // unload stuff onbeforeunload
+               unload:function() {
+                       try {
+                               
+                               // remove events
+                               var l = this.elements.length;
+                               for(var i=0; i<l; i++) {
+                                       this.elements[i].unload();
+                               }
+
+                               // and set properties to null 
+                               this.elements = [];
+                               this.callbacks = {};
+
+                       } catch (e) {
+                       }
+               }
+       };
+
+       /**
+        *      CSSHoverElement
+        *      --------------------------
+        */
+
+       // the event types associated with the interactive pseudos
+       var CSSEvents = {
+               onhover:  { activator: 'onmouseenter', deactivator: 
'onmouseleave' },
+               onactive: { activator: 'onmousedown',  deactivator: 'onmouseup' 
},
+               onfocus:  { activator: 'onfocus',      deactivator: 'onblur' }
+       };
+       
+       // CSSHoverElement constructor, called via CSSHover.patch
+       function CSSHoverElement(node, type, className) {
+
+               // the CSSHoverElement patches individual nodes by manually 
applying the events that should 
+               // have fired by the css pseudoclasses, eg mouseenter and 
mouseleave for :hover. 
+
+               this.node = node;
+               this.type = type;
+               var replacer = new RegExp('(^|\\s)'+className+'(\\s|$)', 'g');
+
+               // store event handlers for removal onunload
+               this.activator =   function(){ node.className += ' ' + 
className; };
+               this.deactivator = function(){ node.className = 
node.className.replace(replacer, ' '); };
+               
+               // add the events
+               node.attachEvent(CSSEvents[type].activator, this.activator);
+               node.attachEvent(CSSEvents[type].deactivator, this.deactivator);
+       }
+       
+       CSSHoverElement.prototype = {
+               // onbeforeunload, called via CSSHover.unload
+               unload:function() {
+
+                       // remove events 
+                       this.node.detachEvent(CSSEvents[this.type].activator, 
this.activator);
+                       this.node.detachEvent(CSSEvents[this.type].deactivator, 
this.deactivator);
+
+                       // and set properties to null 
+                       this.activator = null;
+                       this.deactivator = null;
+                       this.node = null;
+                       this.type = null;
+               }
+       };
+
+       // add the unload to the onbeforeunload event
+       window.attachEvent('onbeforeunload', function(){
+               CSSHover.unload();
+       });
+
+       /**
+        *      Public hook
+        *      --------------------------
+        */
+       
+       return function(node, type, className, property) {
+               if(node) {
+                       // called via the css expression; patches individual 
nodes
+                       return CSSHover.patch(node, type, className, property);
+               } else {
+                       // called ondomcontentready via the public:attach node
+                       CSSHover.init();
+               }
+       };
+
+})();
+</script>
\ No newline at end of file
diff --git a/csshover.min.htc b/csshover.min.htc
new file mode 100644
index 0000000..7e5c57b
--- /dev/null
+++ b/csshover.min.htc
@@ -0,0 +1,12 @@
+<public:attach event="ondocumentready" onevent="CSSHover()" />
+<script>
+/**
+ * Whatever:hover - V3.11
+ * http://www.xs4all.nl/~peterned/
+ *     
+ * Copyright (c) 2009 Peter Nederlof
+ * Licensed under the LGPL license
+ * http://creativecommons.org/licenses/LGPL/2.1
+ */
+window.CSSHover=(function(){var m=/(^|\s)((([^a]([^ ]+)?)|(a([^#.][^ 
]+)+)):(hover|active|focus))/i;var n=/(.*?)\:(hover|active|focus)/i;var 
o=/[^:]+:([a-z\-]+).*/i;var p=/(\.([a-z0-9_\-]+):[a-z]+)|(:[a-z]+)/gi;var 
q=/\.([a-z0-9_\-]*on(hover|active|focus))/i;var s=/msie (5|6|7)/i;var 
t=/backcompat/i;var 
u={index:0,list:['text-kashida','text-kashida-space','text-justify'],get:function(){return
 this.list[(this.index++)%this.list.length]}};var v=function(c){return 
c.replace(/-(.)/mg,function(a,b){return b.toUpperCase()})};var 
w={elements:[],callbacks:{},init:function(){if(!s.test(navigator.userAgent)&&!t.test(window.document.compatMode)){return}var
 a=window.document.styleSheets,l=a.length;for(var 
i=0;i<l;i++){this.parseStylesheet(a[i])}},parseStylesheet:function(a){if(a.imports){try{var
 b=a.imports;var l=b.length;for(var 
i=0;i<l;i++){this.parseStylesheet(a.imports[i])}}catch(securityException){}}try{var
 c=a.rules;var r=c.length;for(var 
j=0;j<r;j++){this.parseCSSRule(c[j],a)}}catch(someException){}},parseCSSRule:function(a,b){var
 c=a.selectorText;if(m.test(c)){var d=a.style.cssText;var e=n.exec(c)[1];var 
f=c.replace(o,'on$1');var g=c.replace(p,'.$2'+f);var h=q.exec(g)[1];var 
i=e+h;if(!this.callbacks[i]){var j=u.get();var 
k=v(j);b.addRule(e,j+':expression(CSSHover(this, "'+f+'", "'+h+'", 
"'+k+'"))');this.callbacks[i]=true}b.addRule(g,d)}},patch:function(a,b,c,d){try{var
 
f=a.parentNode.currentStyle[d];a.style[d]=f}catch(e){a.runtimeStyle[d]=''}if(!a.csshover){a.csshover=[]}if(!a.csshover[c]){a.csshover[c]=true;var
 g=new CSSHoverElement(a,b,c);this.elements.push(g)}return 
b},unload:function(){try{var l=this.elements.length;for(var 
i=0;i<l;i++){this.elements[i].unload()}this.elements=[];this.callbacks={}}catch(e){}}};var
 
x={onhover:{activator:'onmouseenter',deactivator:'onmouseleave'},onactive:{activator:'onmousedown',deactivator:'onmouseup'},onfocus:{activator:'onfocus',deactivator:'onblur'}};function
 CSSHoverElement(a,b,c){this.node=a;this.type=b;var d=new 
RegExp('(^|\\s)'+c+'(\\s|$)','g');this.activator=function(){a.className+=' 
'+c};this.deactivator=function(){a.className=a.className.replace(d,' 
')};a.attachEvent(x[b].activator,this.activator);a.attachEvent(x[b].deactivator,this.deactivator)}CSSHoverElement.prototype={unload:function(){this.node.detachEvent(x[this.type].activator,this.activator);this.node.detachEvent(x[this.type].deactivator,this.deactivator);this.activator=null;this.deactivator=null;this.node=null;this.type=null}};window.attachEvent('onbeforeunload',function(){w.unload()});return
 function(a,b,c,d){if(a){return w.patch(a,b,c,d)}else{w.init()}}})();
+</script>
diff --git a/hooks.txt b/hooks.txt
new file mode 100644
index 0000000..9cdb10e
--- /dev/null
+++ b/hooks.txt
@@ -0,0 +1,6 @@
+Hooks provided by the Apex skin.
+
+'SkinApexStyleModules': Called when defining the list of module styles to be
+loaded by the Apex skin.
+$skin: SkinApex object
+&$styles: Array of module names whose style will be loaded for the skin
diff --git a/i18n/de.json b/i18n/de.json
new file mode 100644
index 0000000..8ac4cd8
--- /dev/null
+++ b/i18n/de.json
@@ -0,0 +1,19 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Metalhead64"
+               ]
+       },
+       "apex-desc": "Eine moderne Version von Vector mit einem frischen 
Aussehen und vielen Benutzerfreundlichkeitsverbesserungen",
+       "apex-action-addsection": "Thema hinzufügen",
+       "apex-action-delete": "Löschen",
+       "apex-action-move": "Verschieben",
+       "apex-action-protect": "Schützen",
+       "apex-action-undelete": "Wiederherstellen",
+       "apex-action-unprotect": "Schutz ändern",
+       "apex-view-create": "Erstellen",
+       "apex-view-edit": "Bearbeiten",
+       "apex-view-history": "Versionsgeschichte",
+       "apex-view-view": "Lesen",
+       "apex-view-viewsource": "Quelltext betrachten"
+}
diff --git a/i18n/en.json b/i18n/en.json
index 6303654..daf4f25 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -16,5 +16,6 @@
        "apex-view-edit": "Edit",
        "apex-view-history": "View history",
        "apex-view-view": "Read",
-       "apex-view-viewsource": "View source"
+       "apex-view-viewsource": "View source",
+       "apex-guest": "Guest"
 }
diff --git a/i18n/es.json b/i18n/es.json
new file mode 100644
index 0000000..d46e884
--- /dev/null
+++ b/i18n/es.json
@@ -0,0 +1,19 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Macofe"
+               ]
+       },
+       "apex-desc": "Versión moderna de Vector, con un aspecto actualizado y 
muchas mejoras de usabilidad",
+       "apex-action-addsection": "Añadir tema",
+       "apex-action-delete": "Borrar",
+       "apex-action-move": "Trasladar",
+       "apex-action-protect": "Proteger",
+       "apex-action-undelete": "Restaurar",
+       "apex-action-unprotect": "Cambiar protección",
+       "apex-view-create": "Crear",
+       "apex-view-edit": "Editar",
+       "apex-view-history": "Ver historial",
+       "apex-view-view": "Leer",
+       "apex-view-viewsource": "Ver código"
+}
diff --git a/i18n/ksh.json b/i18n/ksh.json
new file mode 100644
index 0000000..6df1f02
--- /dev/null
+++ b/i18n/ksh.json
@@ -0,0 +1,19 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Purodha"
+               ]
+       },
+       "apex-desc": "En modärne Väsjohn vun dä älldere Bedehnbovverfläsch „<i 
lang=\"en\" xml:lang=\"en\" dir=\"ltr\">Vector</i>“ met enem neue Ußsinn un 
Verbäßeronge bem Bedehne.",
+       "apex-action-addsection": "Tehma derbeidonn",
+       "apex-action-delete": "Fottschmiiße",
+       "apex-action-move": "Ömbenänne",
+       "apex-action-protect": "Schöze",
+       "apex-action-undelete": "Zerökholle",
+       "apex-action-unprotect": "Schoz ändere",
+       "apex-view-create": "Aanlähje",
+       "apex-view-edit": "Ändere",
+       "apex-view-history": "De Väsohne belohre",
+       "apex-view-view": "Lässe",
+       "apex-view-viewsource": "Wikkitäx aanlohre"
+}
diff --git a/i18n/lb.json b/i18n/lb.json
new file mode 100644
index 0000000..d482e22
--- /dev/null
+++ b/i18n/lb.json
@@ -0,0 +1,19 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Robby"
+               ]
+       },
+       "apex-desc": "Modern Versioun vu Vecor tmat frëschem Look a ville 
Verbesserunge vun der Benotzerfrëndlechkeet",
+       "apex-action-addsection": "Sujet derbäisetzen",
+       "apex-action-delete": "Läschen",
+       "apex-action-move": "Réckelen",
+       "apex-action-protect": "Spären",
+       "apex-action-undelete": "Restauréieren",
+       "apex-action-unprotect": "Spär änneren",
+       "apex-view-create": "Uleeën",
+       "apex-view-edit": "Änneren",
+       "apex-view-history": "Versioune weisen",
+       "apex-view-view": "Liesen",
+       "apex-view-viewsource": "Quellcode weisen"
+}
diff --git a/i18n/mk.json b/i18n/mk.json
new file mode 100644
index 0000000..39b84f0
--- /dev/null
+++ b/i18n/mk.json
@@ -0,0 +1,19 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Bjankuloski06"
+               ]
+       },
+       "apex-desc": "Современа верзија на рувото „Векторско“ со свеж изглед и 
многу подобрувања на употребливоста",
+       "apex-action-addsection": "Додај тема",
+       "apex-action-delete": "Избриши",
+       "apex-action-move": "Премести",
+       "apex-action-protect": "Заштити",
+       "apex-action-undelete": "Поврати",
+       "apex-action-unprotect": "Измени заштита",
+       "apex-view-create": "Создај",
+       "apex-view-edit": "Уреди",
+       "apex-view-history": "Историја",
+       "apex-view-view": "Читај",
+       "apex-view-viewsource": "Извор"
+}
diff --git a/i18n/my.json b/i18n/my.json
new file mode 100644
index 0000000..d2c3301
--- /dev/null
+++ b/i18n/my.json
@@ -0,0 +1,12 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Zawthet"
+               ]
+       },
+       "apex-action-delete": "ဖျက်​ပါ​",
+       "apex-action-move": "ရွှေ့ရန်",
+       "apex-action-protect": "ထိန်း​သိမ်း​ပါ​",
+       "apex-action-undelete": "မဖျက်တော့ရန်",
+       "apex-view-edit": "ပြင်​ဆင်​ရန်​"
+}
diff --git a/i18n/pl.json b/i18n/pl.json
new file mode 100644
index 0000000..1bd0ac7
--- /dev/null
+++ b/i18n/pl.json
@@ -0,0 +1,18 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Chrumps"
+               ]
+       },
+       "apex-desc": "Odświeżona wersja skórki Wektor, z nowym wyglądem i 
usprawnieniami",
+       "apex-action-delete": "Usuń",
+       "apex-action-move": "Przenieś",
+       "apex-action-protect": "Zabezpiecz",
+       "apex-action-undelete": "Odtwórz",
+       "apex-action-unprotect": "Zmień zabezpieczenie",
+       "apex-view-create": "Utwórz",
+       "apex-view-edit": "Edytuj",
+       "apex-view-history": "Wyświetl historię",
+       "apex-view-view": "Czytaj",
+       "apex-view-viewsource": "Pokaż źródło"
+}
diff --git a/i18n/qqq.json b/i18n/qqq.json
index 8806002..fe58869 100644
--- a/i18n/qqq.json
+++ b/i18n/qqq.json
@@ -14,5 +14,6 @@
        "apex-view-edit": "Tab label in the Apex skin. See for example 
{{canonicalurl:Main_Page|useskin=apex}}\n{{Identical|Edit}}",
        "apex-view-history": "Tab label in the Apex skin. See for example 
{{canonicalurl:Main_Page|useskin=apex}}\n{{Identical|View history}}",
        "apex-view-view": "Tab label in the Apex skin (verb). See for example 
{{canonicalurl:Main_Page|useskin=apex}}.\n{{Identical|Read}}",
-       "apex-view-viewsource": "Tab label in the Apex skin.\n{{Identical|View 
source}}"
+       "apex-view-viewsource": "Tab label in the Apex skin.\n{{Identical|View 
source}}",
+       "apex-guest": "Used for descbribing you as a guest editing the 
wiki.\n{{Identical|Guest}}"
 }
diff --git a/i18n/ro.json b/i18n/ro.json
new file mode 100644
index 0000000..b6c7fd7
--- /dev/null
+++ b/i18n/ro.json
@@ -0,0 +1,17 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Wintereu"
+               ]
+       },
+       "apex-action-addsection": "Adaugă un subiect",
+       "apex-action-delete": "Șterge",
+       "apex-action-move": "Mută",
+       "apex-action-protect": "Protejare",
+       "apex-action-undelete": "Recuperare",
+       "apex-action-unprotect": "Schimbă protecția",
+       "apex-view-create": "Creează",
+       "apex-view-edit": "Modifică",
+       "apex-view-history": "Vizualizare istoric",
+       "apex-view-view": "Citește"
+}
diff --git a/i18n/ru.json b/i18n/ru.json
new file mode 100644
index 0000000..55ad92c
--- /dev/null
+++ b/i18n/ru.json
@@ -0,0 +1,17 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Okras"
+               ]
+       },
+       "apex-action-addsection": "Добавить тему",
+       "apex-action-delete": "Удалить",
+       "apex-action-move": "Переименовать",
+       "apex-action-protect": "Защитить",
+       "apex-action-undelete": "Отменить удаление",
+       "apex-action-unprotect": "Изменить защиту",
+       "apex-view-create": "Создать",
+       "apex-view-edit": "Править",
+       "apex-view-history": "Посмотреть историю",
+       "apex-view-view": "Читать"
+}
diff --git a/i18n/shn.json b/i18n/shn.json
new file mode 100644
index 0000000..1e6cdaf
--- /dev/null
+++ b/i18n/shn.json
@@ -0,0 +1,18 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Saosukham"
+               ]
+       },
+       "apex-action-addsection": "ထႅမ်သႂ်ႇ ႁူဝ်ၶေႃႈ",
+       "apex-action-delete": "ယႃႉ",
+       "apex-action-move": "ၶၢႆႉ",
+       "apex-action-protect": "ႁေႉၵင်ႈ",
+       "apex-action-undelete": "ဢမ်ႇယႃႉ",
+       "apex-action-unprotect": "လႅၵ်ႈလၢႆႈ ၵၢၼ်ႁေႉၵင်ႈ",
+       "apex-view-create": "သၢင်ႈ",
+       "apex-view-edit": "မႄးထတ်း",
+       "apex-view-history": "ၼႄပိုၼ်း",
+       "apex-view-view": "လူတူၺ်း",
+       "apex-view-viewsource": "ၼႄ ငဝ်ႈငႃႇ"
+}
diff --git a/i18n/vi.json b/i18n/vi.json
new file mode 100644
index 0000000..acf970f
--- /dev/null
+++ b/i18n/vi.json
@@ -0,0 +1,22 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Minh Nguyen"
+               ]
+       },
+       "skinname-apex": "Đỉnh",
+       "apex-desc": "Giao diện làm lại từ Vectơ có màu tươi và khả dụng hơn",
+       "apex.css": "/* Mã CSS tại đây sẽ ảnh hưởng đến những người dùng sử 
dụng giao diện Đỉnh */",
+       "apex.js": "/* Mã JavaScript tại đây sẽ được tải khi người dùng sử dụng 
giao diện Đỉnh */",
+       "apex-action-addsection": "Thêm chủ đề",
+       "apex-action-delete": "Xóa",
+       "apex-action-move": "Di chuyển",
+       "apex-action-protect": "Khóa",
+       "apex-action-undelete": "Phục hồi",
+       "apex-action-unprotect": "Đổi mức khóa",
+       "apex-view-create": "Tạo mới",
+       "apex-view-edit": "Sửa đổi",
+       "apex-view-history": "Xem lịch sử",
+       "apex-view-view": "Đọc",
+       "apex-view-viewsource": "Xem mã nguồn"
+}
diff --git a/i18n/zh-hans.json b/i18n/zh-hans.json
new file mode 100644
index 0000000..572934e
--- /dev/null
+++ b/i18n/zh-hans.json
@@ -0,0 +1,19 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Liuxinyu970226"
+               ]
+       },
+       "apex-desc": "提供清新的外观和很多可用性改进的现代版Vector",
+       "apex-action-addsection": "添加话题",
+       "apex-action-delete": "删除",
+       "apex-action-move": "移动",
+       "apex-action-protect": "保护",
+       "apex-action-undelete": "还原",
+       "apex-action-unprotect": "更改保护",
+       "apex-view-create": "创建",
+       "apex-view-edit": "编辑",
+       "apex-view-history": "查看历史",
+       "apex-view-view": "阅读",
+       "apex-view-viewsource": "查看源代码"
+}
diff --git a/images/bullet-icon.png b/images/bullet-icon.png
new file mode 100644
index 0000000..7bae98f
--- /dev/null
+++ b/images/bullet-icon.png
Binary files differ
diff --git a/images/bullet-icon.svg b/images/bullet-icon.svg
new file mode 100644
index 0000000..dede350
--- /dev/null
+++ b/images/bullet-icon.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg"; version="1.1" width="5" height="13">
+<circle cx="2.5" cy="9.5" r="2.5" fill="#00528c"/>
+</svg>
diff --git a/resources/images/icons/menu-hover.png b/images/menu-hover.png
similarity index 100%
rename from resources/images/icons/menu-hover.png
rename to images/menu-hover.png
Binary files differ
diff --git a/resources/images/icons/menu.png b/images/menu.png
similarity index 100%
rename from resources/images/icons/menu.png
rename to images/menu.png
Binary files differ
diff --git a/resources/images/icons/nav-hover.png b/images/nav-hover.png
similarity index 100%
rename from resources/images/icons/nav-hover.png
rename to images/nav-hover.png
Binary files differ
diff --git a/resources/images/icons/nav.png b/images/nav.png
similarity index 100%
rename from resources/images/icons/nav.png
rename to images/nav.png
Binary files differ
diff --git a/images/icons/search.png b/images/search-ltr.png
similarity index 100%
rename from images/icons/search.png
rename to images/search-ltr.png
Binary files differ
diff --git a/images/search-ltr.svg b/images/search-ltr.svg
new file mode 100644
index 0000000..0720f20
--- /dev/null
+++ b/images/search-ltr.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg"; 
width="12" height="13"><g stroke-width="2" stroke="#6c6c6c" fill="none"><path 
d="M11.29 11.71l-4-4"/><circle cx="5" cy="5" r="4"/></g></svg>
\ No newline at end of file
diff --git a/images/search-rtl.png b/images/search-rtl.png
new file mode 100644
index 0000000..c26c8d0
--- /dev/null
+++ b/images/search-rtl.png
Binary files differ
diff --git a/images/search-rtl.svg b/images/search-rtl.svg
new file mode 100644
index 0000000..622d5f9
--- /dev/null
+++ b/images/search-rtl.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg"; 
width="12" height="13"><g stroke-width="2" stroke="#6c6c6c" fill="none"><path 
d="M.71 11.71l4-4"/><circle cx="7" cy="5" r="4"/></g></svg>
\ No newline at end of file
diff --git a/resources/images/icons/talk.png b/images/talk.png
similarity index 100%
rename from resources/images/icons/talk.png
rename to images/talk.png
Binary files differ
diff --git a/resources/images/icons/toc-hover.png b/images/toc-hover.png
similarity index 100%
rename from resources/images/icons/toc-hover.png
rename to images/toc-hover.png
Binary files differ
diff --git a/resources/images/icons/toc.png b/images/toc.png
similarity index 100%
rename from resources/images/icons/toc.png
rename to images/toc.png
Binary files differ
diff --git a/images/unwatch-icon-hl.png b/images/unwatch-icon-hl.png
new file mode 100644
index 0000000..6b2b502
--- /dev/null
+++ b/images/unwatch-icon-hl.png
Binary files differ
diff --git a/images/unwatch-icon-hl.svg b/images/unwatch-icon-hl.svg
new file mode 100644
index 0000000..d52d547
--- /dev/null
+++ b/images/unwatch-icon-hl.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg"; 
xmlns:xlink="http://www.w3.org/1999/xlink"; width="16" 
height="16"><defs><linearGradient id="a"><stop offset="0" 
stop-color="#c2edff"/><stop offset=".5" stop-color="#68bdff"/><stop offset="1" 
stop-color="#fff"/></linearGradient><linearGradient x1="13.47" y1="14.363" 
x2="4.596" y2="3.397" id="b" xlink:href="#a" 
gradientUnits="userSpaceOnUse"/></defs><path d="M8.103 1.146l2.175 4.408 
4.864.707-3.52 3.431.831 4.845-4.351-2.287-4.351 2.287.831-4.845-3.52-3.431 
4.864-.707z" fill="url(#b)" stroke="#c8b250" 
stroke-width="0.9999199999999999"/></svg>
\ No newline at end of file
diff --git a/images/unwatch-icon.png b/images/unwatch-icon.png
new file mode 100644
index 0000000..9fd9436
--- /dev/null
+++ b/images/unwatch-icon.png
Binary files differ
diff --git a/images/unwatch-icon.svg b/images/unwatch-icon.svg
new file mode 100644
index 0000000..cde7bc5
--- /dev/null
+++ b/images/unwatch-icon.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg"; 
xmlns:xlink="http://www.w3.org/1999/xlink"; width="16" 
height="16"><defs><linearGradient id="a"><stop offset="0" 
stop-color="#c2edff"/><stop offset=".5" stop-color="#68bdff"/><stop offset="1" 
stop-color="#fff"/></linearGradient><linearGradient x1="13.47" y1="14.363" 
x2="4.596" y2="3.397" id="b" xlink:href="#a" 
gradientUnits="userSpaceOnUse"/></defs><path d="M8.103 1.146l2.175 4.408 
4.864.707-3.52 3.431.831 4.845-4.351-2.287-4.351 2.287.831-4.845-3.52-3.431 
4.864-.707z" fill="url(#b)" stroke="#7cb5d1" 
stroke-width="0.9999199999999999"/></svg>
\ No newline at end of file
diff --git a/images/user-icon.png b/images/user-icon.png
new file mode 100644
index 0000000..909bcce
--- /dev/null
+++ b/images/user-icon.png
Binary files differ
diff --git a/images/user-icon.svg b/images/user-icon.svg
new file mode 100644
index 0000000..c37d464
--- /dev/null
+++ b/images/user-icon.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" 
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd";>
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg"; 
xmlns:xlink="http://www.w3.org/1999/xlink"; x="0px" y="0px"
+        width="12px" height="13.836px" viewBox="0 0 12 13.836" 
enable-background="new 0 0 12 13.836" xml:space="preserve">
+<path fill="#777777" 
d="M1.938,6.656c-1.32,1.485-1.47,3.15-0.97,4.25c0.323,0.707,0.78,1.127,1.313,1.375
+       
c0.496,0.229,1.074,0.273,1.658,0.282c0.023,0,0.04,0.03,0.062,0.03h4.187c0.61,0,1.225-0.125,1.75-0.405
+       
c0.527-0.28,0.961-0.718,1.188-1.376c0.335-0.964,0.175-2.529-1.094-4.03C9.094,7.954,7.68,8.719,6.065,8.719
+       c-1.677,0-3.182-0.812-4.125-2.063H1.938z"/>
+<path fill="#777777" 
d="M6.063,0c-1.89,0-3.595,1.674-3.594,3.563C2.467,5.45,4.173,7.155,6.06,7.155
+       c1.89,0,3.564-1.705,3.563-3.593C9.625,1.673,7.95,0,6.063,0L6.063,0z"/>
+</svg>
diff --git a/resources/images/icons/user.png b/images/user.png
similarity index 100%
rename from resources/images/icons/user.png
rename to images/user.png
Binary files differ
diff --git a/images/watch-icon-hl.png b/images/watch-icon-hl.png
new file mode 100644
index 0000000..4cb87cd
--- /dev/null
+++ b/images/watch-icon-hl.png
Binary files differ
diff --git a/images/watch-icon-hl.svg b/images/watch-icon-hl.svg
new file mode 100644
index 0000000..664c671
--- /dev/null
+++ b/images/watch-icon-hl.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg"; 
width="16" height="16"><path d="M8.103 1.146l2.175 4.408 4.864.707-3.52 
3.431.831 4.845-4.351-2.287-4.351 2.287.831-4.845-3.52-3.431 4.864-.707z" 
fill="#fff" stroke="#c8b250" stroke-width="0.9999199999999999"/></svg>
\ No newline at end of file
diff --git a/images/watch-icon-loading.png b/images/watch-icon-loading.png
new file mode 100644
index 0000000..5f0c490
--- /dev/null
+++ b/images/watch-icon-loading.png
Binary files differ
diff --git a/images/watch-icon-loading.svg b/images/watch-icon-loading.svg
new file mode 100644
index 0000000..751eb14
--- /dev/null
+++ b/images/watch-icon-loading.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg"; 
width="16" height="16"><path d="M8.103 1.146l2.175 4.408 4.864.707-3.52 
3.431.831 4.845-4.351-2.287-4.351 2.287.831-4.845-3.52-3.431 4.864-.707z" 
fill="#fff" stroke="#d1d1d1" stroke-width="0.9999199999999999"/></svg>
\ No newline at end of file
diff --git a/images/watch-icon.png b/images/watch-icon.png
new file mode 100644
index 0000000..39daff2
--- /dev/null
+++ b/images/watch-icon.png
Binary files differ
diff --git a/images/watch-icon.svg b/images/watch-icon.svg
new file mode 100644
index 0000000..907b05b
--- /dev/null
+++ b/images/watch-icon.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg"; 
width="16" height="16"><path d="M8.103 1.146l2.175 4.408 4.864.707-3.52 
3.431.831 4.845-4.351-2.287-4.351 2.287.831-4.845-3.52-3.431 4.864-.707z" 
fill="#fff" stroke="#7cb5d1" stroke-width="0.9999199999999999"/></svg>
\ No newline at end of file
diff --git a/resources/images/icons/watch-loading.gif 
b/resources/images/icons/watch-loading.gif
deleted file mode 100644
index 618c308..0000000
--- a/resources/images/icons/watch-loading.gif
+++ /dev/null
Binary files differ
diff --git a/resources/images/icons/watch.png b/resources/images/icons/watch.png
deleted file mode 100644
index 3673054..0000000
--- a/resources/images/icons/watch.png
+++ /dev/null
Binary files differ
diff --git a/resources/screen-narrow.css b/resources/screen-narrow.less
similarity index 94%
rename from resources/screen-narrow.css
rename to resources/screen-narrow.less
index 310550f..85ae647 100644
--- a/resources/screen-narrow.css
+++ b/resources/screen-narrow.less
@@ -47,7 +47,3 @@
 #searchInput:focus {
        width: 6em;
 }
-
-div#mw-js-message {
-       right: 1.5em;
-}
\ No newline at end of file
diff --git a/resources/screen-wide.css b/resources/screen-wide.less
similarity index 100%
rename from resources/screen-wide.css
rename to resources/screen-wide.less
diff --git a/resources/screen.css b/resources/screen.less
similarity index 72%
rename from resources/screen.css
rename to resources/screen.less
index 8ce4d50..c804f72 100644
--- a/resources/screen.css
+++ b/resources/screen.less
@@ -1,3 +1,6 @@
+@import "mediawiki.mixins";
+@import "mediawiki.mixins.rotation";
+
 html,
 body {
        height: 100%;
@@ -216,17 +219,16 @@
        left: 0;
        right: 0;
        height: 5em;
-background: #ffffff; /* Old browsers */
-/* IE9 SVG, needs conditional override of 'filter' to 'none' */
-background: 
url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2ZmZmZmZiIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjgzJSIgc3RvcC1jb2xvcj0iI2Y5ZjlmOSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNmMmY5ZjkiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+);
-background: -moz-linear-gradient(top,  #ffffff 0%, #f9f9f9 83%, #f2f9f9 100%); 
/* FF3.6+ */
-background: -webkit-gradient(linear, left top, left bottom, 
color-stop(0%,#ffffff), color-stop(83%,#f9f9f9), color-stop(100%,#f2f9f9)); /* 
Chrome,Safari4+ */
-background: -webkit-linear-gradient(top,  #ffffff 0%,#f9f9f9 83%,#f2f9f9 
100%); /* Chrome10+,Safari5.1+ */
-background: -o-linear-gradient(top,  #ffffff 0%,#f9f9f9 83%,#f2f9f9 100%); /* 
Opera 11.10+ */
-background: -ms-linear-gradient(top,  #ffffff 0%,#f9f9f9 83%,#f2f9f9 100%); /* 
IE10+ */
-background: linear-gradient(to bottom,  #ffffff 0%,#f9f9f9 83%,#f2f9f9 100%); 
/* W3C */
-filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', 
endColorstr='#f2f9f9',GradientType=0 ); /* IE6-8 */
-
+       background: #ffffff; /* Old browsers */
+       /* IE9 SVG, needs conditional override of 'filter' to 'none' */
+       background: 
url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/Pgo8c3ZnIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgdmlld0JveD0iMCAwIDEgMSIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+CiAgPGxpbmVhckdyYWRpZW50IGlkPSJncmFkLXVjZ2ctZ2VuZXJhdGVkIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSIgeDE9IjAlIiB5MT0iMCUiIHgyPSIwJSIgeTI9IjEwMCUiPgogICAgPHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2ZmZmZmZiIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjgzJSIgc3RvcC1jb2xvcj0iI2Y5ZjlmOSIgc3RvcC1vcGFjaXR5PSIxIi8+CiAgICA8c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNmMmY5ZjkiIHN0b3Atb3BhY2l0eT0iMSIvPgogIDwvbGluZWFyR3JhZGllbnQ+CiAgPHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkLXVjZ2ctZ2VuZXJhdGVkKSIgLz4KPC9zdmc+);
+       background: -moz-linear-gradient(top,  #ffffff 0%, #f9f9f9 83%, #f2f9f9 
100%); /* FF3.6+ */
+       background: -webkit-gradient(linear, left top, left bottom, 
color-stop(0%,#ffffff), color-stop(83%,#f9f9f9), color-stop(100%,#f2f9f9)); /* 
Chrome,Safari4+ */
+       background: -webkit-linear-gradient(top,  #ffffff 0%,#f9f9f9 
83%,#f2f9f9 100%); /* Chrome10+,Safari5.1+ */
+       background: -o-linear-gradient(top,  #ffffff 0%,#f9f9f9 83%,#f2f9f9 
100%); /* Opera 11.10+ */
+       background: -ms-linear-gradient(top,  #ffffff 0%,#f9f9f9 83%,#f2f9f9 
100%); /* IE10+ */
+       background: linear-gradient(to bottom,  #ffffff 0%,#f9f9f9 83%,#f2f9f9 
100%); /* W3C */
+       filter: progid:DXImageTransform.Microsoft.gradient( 
startColorstr='#ffffff', endColorstr='#f2f9f9',GradientType=0 ); /* IE6-8 */
 }
 
 #mw-panel,
@@ -287,7 +289,7 @@
        left: 0;
        width: 3em;
        height: 2em;
-       background-image: url(images/icons/nav.png);
+       background-image: url('../images/nav.png');
        background-position: center center;
        background-repeat: no-repeat;
        cursor: pointer;
@@ -298,18 +300,18 @@
        right: 0;
        width: 3em;
        height: 2em;
-       background-image: url(images/icons/toc.png);
+       background-image: url('../images/toc.png');
        background-position: center center;
        background-repeat: no-repeat;
        cursor: pointer;
 }
 
 #mw-panel:hover .apex-flyout-pull {
-       background-image: url(images/icons/nav-hover.png);
+       background-image: url('../images/nav-hover.png');
 }
 
 #toc:hover #toctitle {
-       background-image: url(images/icons/toc-hover.png);
+       background-image: url('../images/toc-hover.png');
 }
 
 #content #toc {
@@ -443,20 +445,68 @@
 #p-personal:hover .apex-menu-popup {
        display: block;
 }
+
+#username-top {
+       height: 40px;
+       display: table-cell;
+       vertical-align: middle;
+       font-size: 9.5pt;
+       padding-top: 1px;
+       font-family: sans-serif;
+}
+
+#usermenu {
+       float: right;
+       background-image: none;
+       vertical-align: middle;
+       height: 40px;
+       padding-left: 10px;
+       padding-right: 10px;
+       position: relative;
+       top: 0.7em;
+       right: 10px;
+       width: auto;
+
+       div > a.user-icon-container {
+               text-decoration: none;
+       }
+}
+
+#userIcon20 {
+       position: relative;
+       .background-image-svg('../images/user-icon.svg', 
'../images/user-icon.png');
+       width: 35px;
+       height: 38px;
+       background-repeat: no-repeat;
+       right: -1.5em;
+       float: left;
+}
+
+.username-space {
+       margin-right: 0.4em;
+}
+
+div.personal-menu {
+       margin: 0;
+       position: absolute;
+       top: 33px;
+       right: 0px;
+       z-index: 1;
+}
+
 #pt-userpage {
        padding-right: 18px;
        background-position: right center;
        background-repeat: no-repeat;
 }
 
-#pt-userpage a {
-       padding-left: 18px;
-       background-image: url(images/icons/user.png);
-       background-position: left 40%;
-       background-repeat: no-repeat;
-}
+
 #pt-userpage a:hover {
        text-decoration: none;
+}
+
+.suggestions {
+       top: -3.5em !important;
 }
 
 #p-search {
@@ -464,9 +514,7 @@
        margin-right: 3em;
        margin-top: 1.25em;
 }
-#simpleSearch {
-       text-align: right;
-}
+
 #p-search h5 {
        display: none;
 }
@@ -494,40 +542,79 @@
        opacity: 1;
 }
 
-#ca-watch a,
-#ca-unwatch a {
-       display: inline-block;
-       padding-right: 0;
-       padding-left: 26px;
-       padding-right: 0;
-       width: 0;
+div#simpleSearch #searchButton, #mw-searchButton {
+       top: 0;
+       width: 1.65em;
+       height: 100%;
+       cursor: pointer;
+       /* Hide button text and replace it with the image. */
+       text-indent: -99999px;
+       /* Opera 12 on RTL flips the text in a funny way without this. */
+       /* @noflip */
+       direction: ltr;
+       white-space: nowrap;
        overflow: hidden;
-       background-image: url(images/icons/watch.png);
-       background-position: left center;
+       .background-image-svg('../images/search-ltr.svg', 
'../images/search-ltr.png');
+       background-position: center center;
        background-repeat: no-repeat;
 }
-#ca-unwatch a {
-       background-position: -43px 50%;
-}
-#ca-watch a {
-       background-position: 5px 50%;
-}
-#ca-unwatch a:hover,
-#ca-unwatch a:focus {
+
+div#simpleSearch,
+#mw-searchButton {
+       z-index: 1;
+       background-image: none;
        background-color: transparent;
-       background-position: -67px 50%;
+       border: 0;
 }
-#ca-watch a:hover,
-#ca-watch a:focus {
-       background-color: transparent;
-       background-position: -19px 50%;
+
+/* Watch/Unwatch Icon Styling */
+#ca-unwatch.icon a,
+#ca-watch.icon a {
+       margin: 0;
+       padding: 0;
+       display: block;
+       width: 26px;
+       /* This hides the text but shows the background image */
+       padding-top: 3.1em;
+       margin-top: 0;
+       /* Only applied in IE6 */
+       margin-top: -0.8em !ie;
+       height: 0;
+       overflow: hidden;
+       background-position: 5px 25% !important;
+       background-repeat: no-repeat;
 }
-#ca-unwatch .loading,
-#ca-watch .loading {
-       /* @embed */
-       background-image: url(images/icons/watch-loading.gif);
-       background-position: 5px 50%;
+#ca-unwatch.icon a {
+       .background-image-svg('../images/unwatch-icon.svg', 
'../images/unwatch-icon.png');
 }
+#ca-watch.icon a {
+       .background-image-svg('../images/watch-icon.svg', 
'../images/watch-icon.png');
+}
+#ca-unwatch.icon a:hover,
+#ca-unwatch.icon a:focus {
+       .background-image-svg('../images/unwatch-icon-hl.svg', 
'../images/unwatch-icon-hl.png');
+}
+#ca-watch.icon a:hover,
+#ca-watch.icon a:focus {
+       .background-image-svg('../images/watch-icon-hl.svg', 
'../images/watch-icon-hl.png');
+}
+#ca-unwatch.icon a.loading,
+#ca-watch.icon a.loading {
+       .background-image-svg('../images/watch-icon-loading.svg', 
'../images/watch-icon-loading.png');
+       .rotation(700ms);
+       /* Suppress the hilarious rotating focus outline on Firefox */
+       outline: none;
+       cursor: default;
+       pointer-events: none;
+       background-position: 50% 60%;
+       -webkit-transform-origin: 50% 57%;
+       transform-origin: 50% 57%;
+}
+#ca-unwatch.icon a span,
+#ca-watch.icon a span {
+       display: none;
+}
+
 
 #p-cactions {
        position: relative;
@@ -569,43 +656,19 @@
        padding: 0.25em;
 }
 
-div#mw-js-message {
-       background-color: #fff;
-       font-size: 0.8em;
-       position: absolute;
-       margin: 0;
-       padding: 1em 2em;
-       right: 3em;
-       top: 1.5em;
-       width: 20em;
-       z-index: 10000;
-       border: solid 1px #d5eaed;
-       -webkit-border-radius: 0.25em;
-       -moz-border-radius: 0.25em;
-       border-radius: 0.25em;
-       -webkit-box-shadow: 0 0.125em 0.5em 0 rgba(0, 0, 0, 0.25);
-       -moz-box-shadow: 0 0.125em 0.5em 0 rgba(0, 0, 0, 0.25);
-       box-shadow: 0 0.125em 0.5em 0 rgba(0, 0, 0, 0.25);
+ul {
+       list-style-type: disc;
+       .list-style-image-svg('../images/bullet-icon.svg', 
'../images/bullet-icon.png');
 }
 
 /* Background images */
 
-#pt-userpage,
 #p-cactions h5 {
-       background-image: url(images/icons/menu.png);
+       background-image: url('../images/menu.png');
 }
 
-#p-personal:hover #pt-userpage,
 #p-cactions:hover h5 {
-       background-image: url(images/icons/menu-hover.png);
-}
-
-/* Animation for media-query changes */
-div#mw-js-message {
-       transition: right 250ms;
-       -moz-transition: right 250ms;
-       -webkit-transition: right 250ms;
-       -o-transition: right 250ms;
+       background-image: url('../images/menu-hover.png');
 }
 
 #searchInput {
diff --git a/skin.json b/skin.json
index 4bc6316..d6248a1 100644
--- a/skin.json
+++ b/skin.json
@@ -1,13 +1,16 @@
 {
        "name": "Apex",
+       "namemsg": "skinname-apex",
        "author": [
                "Trevor Parscal"
        ],
        "url": "https://www.mediawiki.org/wiki/Skin:Apex";,
        "descriptionmsg": "apex-desc",
-       "namemsg": "skinname-apex",
        "license-name": "GPL-2.0+",
        "type": "skin",
+       "ConfigRegistry": {
+               "apex": "GlobalVarConfig::newInstance"
+       },
        "ValidSkinNames": {
                "apex": "Apex"
        },
@@ -25,18 +28,21 @@
        },
        "ResourceModules": {
                "skins.apex": {
-                       "position": "bottom",
+                       "position": "top",
                        "styles": {
-                               "resources/screen.css": {
+                               "resources/screen.less": {
                                        "media": "screen"
                                },
-                               "resources/screen-narrow.css": {
+                               "resources/screen-narrow.less": {
                                        "media": "screen and (max-width: 700px)"
                                },
-                               "resources/screen-wide.css": {
+                               "resources/screen-wide.less": {
                                        "media": "screen and (min-width: 982px)"
                                }
-                       },
+                       }
+               },
+               "skins.apex.js": {
+                       "position": "bottom",
                        "scripts": "resources/apex.js"
                }
        },
@@ -45,6 +51,7 @@
                "remoteSkinPath": "apex"
        },
        "config": {
+               "ApexUseLogo": false,
                "ApexLogo": {
                        "1x": false,
                        "2x": false

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I9aca5319ee9bee1e069fa7f0ce83c70e1a381c7a
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/skins/apex
Gerrit-Branch: master
Gerrit-Owner: Paladox <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to