Index: trunk/extensions/MobileSkin/MobileFrontend2.php |
— | — | @@ -1,84 +0,0 @@ |
2 | | -<?php |
3 | | -/** |
4 | | -* Extension MobileFrontend2 — Mobile Frontend 2 |
5 | | -* |
6 | | -* @file |
7 | | -* @ingroup Extensions |
8 | | -*/ |
9 | | - |
10 | | -// Needs to be called within MediaWiki; not standalone |
11 | | -if ( !defined( 'MEDIAWIKI' ) ) { |
12 | | - echo( "This is an extension to the MediaWiki package and cannot be run standalone.\n" ); |
13 | | - die( -1 ); |
14 | | -} |
15 | | - |
16 | | -// Extension credits that will show up on Special:Version |
17 | | -$wgExtensionCredits['other'][] = array( |
18 | | - 'path' => __FILE__, |
19 | | - 'name' => 'MobileFrontend2', |
20 | | - 'version' => 1, |
21 | | - 'author' => 'John Du Hart', |
22 | | - 'descriptionmsg' => 'mobile-frontend2-desc', |
23 | | - 'url' => 'https://www.mediawiki.org/wiki/Extension:MobileFrontend2', |
24 | | -); |
25 | | - |
26 | | -$dir = dirname( __FILE__ ) . '/'; |
27 | | -$wgExtensionMessagesFiles['MobileFrontend2'] = $dir . 'MobileFrontend2.i18n.php'; |
28 | | - |
29 | | -$wgAutoloadClasses['MobileFrontend2_Detection'] = $dir . 'MobileFrontend2_Detection.php'; |
30 | | -$wgAutoloadClasses['MobileFrontend2_Hooks'] = $dir . 'MobileFrontend2_Hooks.php'; |
31 | | -$wgAutoloadClasses['MobileFrontend2_Options'] = $dir . 'MobileFrontend2_Options.php'; |
32 | | -$wgAutoloadClasses['MobileFrontend2_PostParse'] = $dir . 'MobileFrontend2_PostParse.php'; |
33 | | - |
34 | | -// Skins |
35 | | -$wgAutoloadClasses['SkinMobile'] = $dir . 'skins/Mobile.php'; |
36 | | - |
37 | | -// Hooks |
38 | | -$wgHooks['RequestContextCreateSkin'][] = 'MobileFrontend2_Hooks::createSkin'; |
39 | | -$wgHooks['ParserSectionCreate'][] = 'MobileFrontend2_Hooks::parserSectionCreate'; |
40 | | -$wgHooks['ArticleViewHeader'][] = 'MobileFrontend2_Hooks::articleView'; |
41 | | -$wgHooks['ResourceLoaderGetStartupModules'][] = 'MobileFrontend2_Hooks::startupModule'; |
42 | | -$wgHooks['ResourceLoaderRegisterModules'][] = 'MobileFrontend2_Hooks::registerModules'; |
43 | | -$wgHooks['BeforeInitialize'][] = 'MobileFrontend2_Hooks::beforeInitialize'; |
44 | | -$wgExtensionFunctions[] = 'MobileFrontend2_Hooks::setup'; |
45 | | - |
46 | | -// Modules |
47 | | -$commonModuleInfo = array( |
48 | | - 'localBasePath' => dirname( __FILE__ ) . '/modules', |
49 | | - 'remoteExtPath' => 'MobileFrontend2/modules', |
50 | | -); |
51 | | - |
52 | | -// Main style |
53 | | -$wgResourceModules['ext.mobileFrontend2'] = array( |
54 | | - 'scripts' => 'ext.mobileFrontend2/ext.mobileFrontend2.js', |
55 | | - 'messages' => array( |
56 | | - 'mobile-frontend2-show-button', |
57 | | - 'mobile-frontend2-hide-button', |
58 | | - ), |
59 | | - 'dependencies' => array( |
60 | | - 'mediawiki.util.lite', |
61 | | - 'mediawiki.api.lite', |
62 | | - ), |
63 | | -) + $commonModuleInfo; |
64 | | - |
65 | | -$wgResourceModules['ext.mobileFrontend2.common'] = array( |
66 | | - 'styles' => array( |
67 | | - 'ext.mobileFrontend2/ext.mobileFrontend2.css', |
68 | | - 'ext.mobileFrontend2/ext.mobileFrontend2.search.css', |
69 | | - ), |
70 | | -) + $commonModuleInfo; |
71 | | - |
72 | | -$wgResourceModules['zepto'] = array( |
73 | | - 'scripts' => array( |
74 | | - 'zepto/zepto.js', |
75 | | - 'zepto/zepto.mw.js', |
76 | | - ), |
77 | | -) + $commonModuleInfo; |
78 | | - |
79 | | -// Config |
80 | | -/** |
81 | | - * Logo used on MobileFrontend2 |
82 | | - * |
83 | | - * @var $wgMobileFrontend2Logo string |
84 | | - */ |
85 | | -$wgMobileFrontend2Logo = null; |
\ No newline at end of file |
Index: trunk/extensions/MobileSkin/MobileFrontend2_PostParse.php |
— | — | @@ -1,92 +0,0 @@ |
2 | | -<?php |
3 | | - |
4 | | -/** |
5 | | - * Take the bodycontent and manipulate it for mobile |
6 | | - */ |
7 | | -class MobileFrontend2_PostParse { |
8 | | - |
9 | | - /** |
10 | | - * HTML to parse |
11 | | - * |
12 | | - * @var string |
13 | | - */ |
14 | | - protected $html; |
15 | | - |
16 | | - /** |
17 | | - * DOM of the bodycontent |
18 | | - * |
19 | | - * @var DOMDocument |
20 | | - */ |
21 | | - protected $dom; |
22 | | - |
23 | | - /** |
24 | | - * Private constructor, use the mange function |
25 | | - * |
26 | | - * @param $html |
27 | | - */ |
28 | | - protected function __construct( $html ) { |
29 | | - $this->html = $html; |
30 | | - |
31 | | - $this->initDom(); |
32 | | - } |
33 | | - |
34 | | - /** |
35 | | - * Entry point for the class |
36 | | - * |
37 | | - * @param $text string |
38 | | - * @return string |
39 | | - */ |
40 | | - public static function mangle( $text ) { |
41 | | - $postParse = new self( $text ); |
42 | | - $postParse->parse(); |
43 | | - |
44 | | - return $postParse->html; |
45 | | - } |
46 | | - |
47 | | - /** |
48 | | - * Sets up the DOM document |
49 | | - */ |
50 | | - protected function initDom() { |
51 | | - // LibXML is noisy apparently |
52 | | - libxml_use_internal_errors( true ); |
53 | | - $dom = new DOMDocument(); |
54 | | - $dom->loadHTML( '<?xml encoding="UTF-8">' . $this->html ); |
55 | | - libxml_use_internal_errors( false ); |
56 | | - |
57 | | - $dom->strictErrorChecking = false; |
58 | | - $dom->encoding = 'UTF-8'; |
59 | | - |
60 | | - $this->dom = $dom; |
61 | | - } |
62 | | - |
63 | | - /** |
64 | | - * Actually parse the DOM |
65 | | - */ |
66 | | - public function parse() { |
67 | | - // Remove the TOC |
68 | | - $this->removeToc(); |
69 | | - |
70 | | - // Render the now manipulated HTML |
71 | | - $this->render(); |
72 | | - } |
73 | | - |
74 | | - /** |
75 | | - * Removes the TOC (#toc) from the body |
76 | | - */ |
77 | | - protected function removeToc() { |
78 | | - $element = $this->dom->getElementById( 'toc' ); |
79 | | - |
80 | | - if ( $element !== null ) { |
81 | | - $element->parentNode->removeChild( $element ); |
82 | | - } |
83 | | - } |
84 | | - |
85 | | - /** |
86 | | - * Saves the HTML to $html |
87 | | - */ |
88 | | - protected function render() { |
89 | | - $this->html = $this->dom->saveXML( |
90 | | - $this->dom->getElementsByTagName( 'body' ) |
91 | | - ->item( 0 )->childNodes->item( 0 ) ); |
92 | | - } |
93 | | -} |
\ No newline at end of file |
Index: trunk/extensions/MobileSkin/MobileFrontend2_Hooks.php |
— | — | @@ -1,171 +0,0 @@ |
2 | | -<?php |
3 | | - |
4 | | -/** |
5 | | - * Hooks for the new mobile frontend |
6 | | - */ |
7 | | -class MobileFrontend2_Hooks { |
8 | | - /** |
9 | | - * Loads the mobile skin if we need to |
10 | | - * |
11 | | - * @param $context ResourceContext |
12 | | - * @param $skin Skin |
13 | | - * @return bool |
14 | | - */ |
15 | | - public static function createSkin( $context, &$skin ) { |
16 | | - // Abort if we're not using the mobile frontend |
17 | | - if ( !MobileFrontend2_Detection::isEnabled() ) { |
18 | | - return true; |
19 | | - } |
20 | | - |
21 | | - // TODO: WML support |
22 | | - $skin = new SkinMobile; |
23 | | - |
24 | | - // Be a dick and halt the hook |
25 | | - return false; |
26 | | - } |
27 | | - |
28 | | - /** |
29 | | - * Adds jump back a section links to content blocks |
30 | | - * |
31 | | - * @todo broken, see mobile main page |
32 | | - * |
33 | | - * @param $parser MobileFrontend2_Parser |
34 | | - * @param $i int |
35 | | - * @param $section string |
36 | | - * @param $showEditLink bool |
37 | | - * @return bool |
38 | | - */ |
39 | | - public static function parserSectionCreate( $parser, $i, &$section, $showEditLink ) { |
40 | | - if ( !MobileFrontend2_Detection::isEnabled() ) { |
41 | | - return true; |
42 | | - } |
43 | | - |
44 | | - // We don't enclose the opening section |
45 | | - if ( $i == 0 ) { |
46 | | - return true; |
47 | | - } |
48 | | - |
49 | | - // Separate the header from the section |
50 | | - preg_match( '/<H[1-6].*?' . '>.*?<\/H[1-6]>/i', $section, $match ); |
51 | | - $headerLength = strlen( $match[0] ); |
52 | | - |
53 | | - $section = "<div section_id=\"$i\" id=\"section-$i\" class=\"mf2-section-container\">" |
54 | | - . substr( $section, 0, $headerLength ) |
55 | | - . '<div class="mf2-content-block">' |
56 | | - . substr( $section, $headerLength ) . "\n\n" |
57 | | - . '<div class="mf2-section-anchor">' |
58 | | - . '<a href="#section-' . $i . '">' |
59 | | - . wfMessage( 'mobile-frontend2-back-to-top-of-section' )->escaped() |
60 | | - . '</a></div></div></div>'; |
61 | | - |
62 | | - return true; |
63 | | - } |
64 | | - |
65 | | - public static function articleView( &$article, &$outputDone, &$useParserCache ) { |
66 | | - // This is where we want to fetch the article from squids |
67 | | - return true; |
68 | | - } |
69 | | - |
70 | | - /** |
71 | | - * Replaces jQuery with zepto.js for mobile |
72 | | - * |
73 | | - * @param $modules |
74 | | - * @return bool |
75 | | - */ |
76 | | - public static function startupModule( &$modules ) { |
77 | | - // comment about this |
78 | | - if ( self::isMobileSkin() ) { |
79 | | - $modules = array( |
80 | | - 'zepto', |
81 | | - 'mediawiki', |
82 | | - ); |
83 | | - return false; |
84 | | - } |
85 | | - |
86 | | - return true; |
87 | | - } |
88 | | - |
89 | | - /** |
90 | | - * Registers lite versions of core modules for mobile |
91 | | - * |
92 | | - * @param ResourceLoader $resourceLoader |
93 | | - * @return bool |
94 | | - */ |
95 | | - public static function registerModules( ResourceLoader &$resourceLoader ) { |
96 | | - if ( self::isMobileSkin() ) { |
97 | | - global $wgResourceModules; |
98 | | - |
99 | | - // We need to remove dependencies from mw.util that will don't use and |
100 | | - // aren't compatible with zepto.js |
101 | | - // Krinkle will hate me |
102 | | - // TODO: This only saves about 4KB, reevaluate later |
103 | | - $wgResourceModules['mediawiki.util.lite'] = array( |
104 | | - 'scripts' => 'resources/mediawiki/mediawiki.util.js', |
105 | | - /*'dependencies' => array( |
106 | | - 'jquery.client', |
107 | | - 'jquery.cookie', |
108 | | - 'jquery.messageBox', |
109 | | - 'jquery.mwExtension', |
110 | | - ),*/ |
111 | | - //'messages' => array( 'showtoc', 'hidetoc' ), |
112 | | - 'position' => 'top', // For $wgPreloadJavaScriptMwUtil |
113 | | - ); |
114 | | - $wgResourceModules['mediawiki.api.lite'] = array( |
115 | | - 'scripts' => 'resources/mediawiki/mediawiki.api.js', |
116 | | - 'dependencies' => 'mediawiki.util.lite', |
117 | | - ); |
118 | | - } |
119 | | - |
120 | | - return true; |
121 | | - } |
122 | | - |
123 | | - /** |
124 | | - * Overrides the main page with the mobile version of the main page |
125 | | - * |
126 | | - * @param Title $title |
127 | | - * @param $unused |
128 | | - * @param $output |
129 | | - * @param $user |
130 | | - * @param $request |
131 | | - * @param $wiki |
132 | | - * @return bool |
133 | | - */ |
134 | | - public static function beforeInitialize( Title &$title, &$unused, &$output, &$user, $request, $wiki ) { |
135 | | - if ( MobileFrontend2_Detection::isEnabled() && $title->isMainPage() ) { |
136 | | - $title = Title::newFromText( wfMsgForContent( 'mainpage-mobile' ) ); |
137 | | - RequestContext::getMain()->setTitle( $title ); |
138 | | - MobileFrontend2_Options::setMainPage( true ); |
139 | | - } |
140 | | - |
141 | | - return true; |
142 | | - } |
143 | | - |
144 | | - /** |
145 | | - * Checks if the skin parameter is for a mobile skin |
146 | | - * |
147 | | - * This only works for load.php |
148 | | - * |
149 | | - * @return bool |
150 | | - */ |
151 | | - protected static function isMobileSkin() { |
152 | | - return RequestContext::getMain()->getRequest()->getVal( 'skin' ) == 'mobile'; |
153 | | - } |
154 | | - |
155 | | - /** |
156 | | - * Perform very early setup |
157 | | - * |
158 | | - * @return bool |
159 | | - */ |
160 | | - public static function setup() { |
161 | | - if ( !MobileFrontend2_Detection::isEnabled() ) { |
162 | | - return true; |
163 | | - } |
164 | | - global $wgMobileFrontend2Logo, $wgExtensionAssetsPath; |
165 | | - |
166 | | - // We need a sane default and $wgExtensionAssetsPath isn't ready until |
167 | | - // after LocalSettings |
168 | | - if ( $wgMobileFrontend2Logo === null ) { |
169 | | - $wgMobileFrontend2Logo = $wgExtensionAssetsPath . '/MobileFrontend2/modules/ext.mobileFrontend2/images/mw.png'; |
170 | | - } |
171 | | - } |
172 | | -} |
\ No newline at end of file |
Index: trunk/extensions/MobileSkin/MobileFrontend2_Options.php |
— | — | @@ -1,82 +0,0 @@ |
2 | | -<?php |
3 | | - |
4 | | -class MobileFrontend2_Options { |
5 | | - |
6 | | - /** |
7 | | - * Hide the search bar |
8 | | - * |
9 | | - * @var bool |
10 | | - */ |
11 | | - protected static $hideSearch = false; |
12 | | - |
13 | | - /** |
14 | | - * Hides the logo |
15 | | - * |
16 | | - * @var bool |
17 | | - */ |
18 | | - protected static $hideLogo = false; |
19 | | - |
20 | | - /** |
21 | | - * Hides the footer |
22 | | - * |
23 | | - * @var bool |
24 | | - */ |
25 | | - protected static $hideFooter = false; |
26 | | - |
27 | | - /** |
28 | | - * Not a user-option, used to do thing such as hide the title for the main |
29 | | - * page |
30 | | - * |
31 | | - * @var bool |
32 | | - */ |
33 | | - protected static $mainPage = false; |
34 | | - |
35 | | - /** |
36 | | - * Detects options based on user preferences |
37 | | - */ |
38 | | - public static function detect() { |
39 | | - $request = RequestContext::getMain()->getRequest(); |
40 | | - |
41 | | - self::$hideSearch = $request->getBool( 'hidesearch' ); |
42 | | - self::$hideLogo = $request->getBool( 'hidelogo' ); |
43 | | - // TODO: Previously this was lumped into hidelogo. Notify mobile team |
44 | | - self::$hideFooter = $request->getBool( 'hidefooter' ); |
45 | | - |
46 | | - // TODO: Hook for Wikimedia |
47 | | - } |
48 | | - |
49 | | - /** |
50 | | - * @return boolean |
51 | | - */ |
52 | | - public static function getHideLogo() { |
53 | | - return self::$hideLogo; |
54 | | - } |
55 | | - |
56 | | - /** |
57 | | - * @return boolean |
58 | | - */ |
59 | | - public static function getHideSearch() { |
60 | | - return self::$hideSearch; |
61 | | - } |
62 | | - |
63 | | - /** |
64 | | - * @return boolean |
65 | | - */ |
66 | | - public static function getHideFooter() { |
67 | | - return self::$hideFooter; |
68 | | - } |
69 | | - |
70 | | - /** |
71 | | - * @param boolean $mainPage |
72 | | - */ |
73 | | - public static function setMainPage( $mainPage ) { |
74 | | - self::$mainPage = $mainPage; |
75 | | - } |
76 | | - |
77 | | - /** |
78 | | - * @return boolean |
79 | | - */ |
80 | | - public static function getMainPage() { |
81 | | - return self::$mainPage; |
82 | | - } |
83 | | -} |
Index: trunk/extensions/MobileSkin/MobileFrontend2.i18n.php |
— | — | @@ -1,27 +0,0 @@ |
2 | | -<?php |
3 | | -/** |
4 | | - * Internationalisation file for the extension MobileFrontend2 |
5 | | - * |
6 | | - * @file |
7 | | - * @ingroup Extensions |
8 | | - */ |
9 | | - |
10 | | -$messages = array(); |
11 | | - |
12 | | -$messages['en'] = array( |
13 | | - 'mobile-frontend2-desc' => 'Mobile Frontend', |
14 | | - 'mobile-frontend2-back-to-top-of-section' => '↑ Jump back a section', |
15 | | - 'mobile-frontend2-show-button' => 'Show', |
16 | | - 'mobile-frontend2-hide-button' => 'Hide', |
17 | | - 'mobile-frontend2-regular-site' => 'View this page on regular {{SITENAME}}', |
18 | | - 'mobile-frontend2-perm-stop-redirect' => 'Permanently disable mobile site', |
19 | | - 'mobile-frontend2-disable-images' => 'Disable images on mobile site', |
20 | | - |
21 | | - 'mainpage-mobile' => '{{int:mainpage}}', |
22 | | -); |
23 | | - |
24 | | -$messages['qqq'] = array( |
25 | | - 'mobile-frontend2-desc' => '{{desc}}', |
26 | | - |
27 | | - 'mainpage-mobile' => 'Page name for the Main Page used in the mobile view. Defaults to {{mw-msg|mainpage}}', |
28 | | -); |
\ No newline at end of file |
Index: trunk/extensions/MobileSkin/MobileFrontend2_Detection.php |
— | — | @@ -1,70 +0,0 @@ |
2 | | -<?php |
3 | | - |
4 | | -/** |
5 | | - * Class containing all detection logic for mobile frontend |
6 | | - */ |
7 | | -class MobileFrontend2_Detection { |
8 | | - |
9 | | - /** |
10 | | - * Cached detection result |
11 | | - * |
12 | | - * @var null|bool |
13 | | - */ |
14 | | - protected static $enabled = null; |
15 | | - |
16 | | - /** |
17 | | - * Main function deciding if the MobileFrontend should be enabled |
18 | | - * |
19 | | - * @return bool |
20 | | - */ |
21 | | - public static function isEnabled() { |
22 | | - if ( self::$enabled !== null ) { |
23 | | - return self::$enabled; |
24 | | - } |
25 | | - |
26 | | - self::detect(); |
27 | | - |
28 | | - return self::$enabled; |
29 | | - } |
30 | | - |
31 | | - private static function detect() { |
32 | | - $request = RequestContext::getMain()->getRequest(); |
33 | | - $useFormat = $request->getText( 'useformat' ); |
34 | | - |
35 | | - // Start with the basics, did they force the frontend? |
36 | | - if ( $useFormat == 'mobile' ) { |
37 | | - return self::enable(); |
38 | | - } |
39 | | - |
40 | | - // TODO: Other detection magic |
41 | | - |
42 | | - // Nope. No mobile frontend for you. |
43 | | - return self::disable(); |
44 | | - } |
45 | | - |
46 | | - /** |
47 | | - * Enable mobile frontend |
48 | | - * |
49 | | - * @return bool |
50 | | - */ |
51 | | - private static function enable() { |
52 | | - global $wgResourceModules; |
53 | | - |
54 | | - self::$enabled = true; |
55 | | - |
56 | | - // Do some initialization |
57 | | - MobileFrontend2_Options::detect(); |
58 | | - |
59 | | - return true; |
60 | | - } |
61 | | - |
62 | | - /** |
63 | | - * Disable mobile frontend |
64 | | - * |
65 | | - * @return bool |
66 | | - */ |
67 | | - private static function disable() { |
68 | | - self::$enabled = false; |
69 | | - return false; |
70 | | - } |
71 | | -} |
Index: trunk/extensions/MobileSkin/MobileSkin.i18n.php |
— | — | @@ -0,0 +1,27 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Internationalisation file for the extension MobileSkin |
| 5 | + * |
| 6 | + * @file |
| 7 | + * @ingroup Extensions |
| 8 | + */ |
| 9 | + |
| 10 | +$messages = array(); |
| 11 | + |
| 12 | +$messages['en'] = array( |
| 13 | + 'mobile-skin-desc' => 'Mobile Skin', |
| 14 | + 'mobile-skin-back-to-top-of-section' => '↑ Jump back a section', |
| 15 | + 'mobile-skin-show-button' => 'Show', |
| 16 | + 'mobile-skin-hide-button' => 'Hide', |
| 17 | + 'mobile-skin-regular-site' => 'View this page on regular {{SITENAME}}', |
| 18 | + 'mobile-skin-perm-stop-redirect' => 'Permanently disable mobile site', |
| 19 | + 'mobile-skin-disable-images' => 'Disable images on mobile site', |
| 20 | + |
| 21 | + 'mainpage-mobile' => '{{int:mainpage}}', |
| 22 | +); |
| 23 | + |
| 24 | +$messages['qqq'] = array( |
| 25 | + 'mobile-skin-desc' => '{{desc}}', |
| 26 | + |
| 27 | + 'mainpage-mobile' => 'Page name for the Main Page used in the mobile view. Defaults to {{mw-msg|mainpage}}', |
| 28 | +); |
\ No newline at end of file |
Property changes on: trunk/extensions/MobileSkin/MobileSkin.i18n.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 29 | + native |
Index: trunk/extensions/MobileSkin/MobileSkin_Detection.php |
— | — | @@ -0,0 +1,70 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Class containing all detection logic for mobile skin |
| 6 | + */ |
| 7 | +class MobileSkin_Detection { |
| 8 | + |
| 9 | + /** |
| 10 | + * Cached detection result |
| 11 | + * |
| 12 | + * @var null|bool |
| 13 | + */ |
| 14 | + protected static $enabled = null; |
| 15 | + |
| 16 | + /** |
| 17 | + * Main function deciding if the MobileSkin should be enabled |
| 18 | + * |
| 19 | + * @return bool |
| 20 | + */ |
| 21 | + public static function isEnabled() { |
| 22 | + if ( self::$enabled !== null ) { |
| 23 | + return self::$enabled; |
| 24 | + } |
| 25 | + |
| 26 | + self::detect(); |
| 27 | + |
| 28 | + return self::$enabled; |
| 29 | + } |
| 30 | + |
| 31 | + private static function detect() { |
| 32 | + $request = RequestContext::getMain()->getRequest(); |
| 33 | + $useFormat = $request->getText( 'useformat' ); |
| 34 | + |
| 35 | + // Start with the basics, did they force the skin? |
| 36 | + if ( $useFormat == 'mobile' ) { |
| 37 | + return self::enable(); |
| 38 | + } |
| 39 | + |
| 40 | + // TODO: Other detection magic |
| 41 | + |
| 42 | + // Nope. No mobile skin for you. |
| 43 | + return self::disable(); |
| 44 | + } |
| 45 | + |
| 46 | + /** |
| 47 | + * Enable mobile skin |
| 48 | + * |
| 49 | + * @return bool |
| 50 | + */ |
| 51 | + private static function enable() { |
| 52 | + global $wgResourceModules; |
| 53 | + |
| 54 | + self::$enabled = true; |
| 55 | + |
| 56 | + // Do some initialization |
| 57 | + MobileSkin_Options::detect(); |
| 58 | + |
| 59 | + return true; |
| 60 | + } |
| 61 | + |
| 62 | + /** |
| 63 | + * Disable mobile skin |
| 64 | + * |
| 65 | + * @return bool |
| 66 | + */ |
| 67 | + private static function disable() { |
| 68 | + self::$enabled = false; |
| 69 | + return false; |
| 70 | + } |
| 71 | +} |
Property changes on: trunk/extensions/MobileSkin/MobileSkin_Detection.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 72 | + native |
Index: trunk/extensions/MobileSkin/MobileSkin.php |
— | — | @@ -0,0 +1,84 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | +* Extension MobileSkin — Mobile Skin |
| 5 | +* |
| 6 | +* @file |
| 7 | +* @ingroup Extensions |
| 8 | +*/ |
| 9 | + |
| 10 | +// Needs to be called within MediaWiki; not standalone |
| 11 | +if ( !defined( 'MEDIAWIKI' ) ) { |
| 12 | + echo( "This is an extension to the MediaWiki package and cannot be run standalone.\n" ); |
| 13 | + die( -1 ); |
| 14 | +} |
| 15 | + |
| 16 | +// Extension credits that will show up on Special:Version |
| 17 | +$wgExtensionCredits['other'][] = array( |
| 18 | + 'path' => __FILE__, |
| 19 | + 'name' => 'MobileSkin', |
| 20 | + 'version' => 1, |
| 21 | + 'author' => 'John Du Hart', |
| 22 | + 'descriptionmsg' => 'mobile-skin-desc', |
| 23 | + 'url' => 'https://www.mediawiki.org/wiki/Extension:MobileSkin', |
| 24 | +); |
| 25 | + |
| 26 | +$dir = dirname( __FILE__ ) . '/'; |
| 27 | +$wgExtensionMessagesFiles['MobileSkin'] = $dir . 'MobileSkin.i18n.php'; |
| 28 | + |
| 29 | +$wgAutoloadClasses['MobileSkin_Detection'] = $dir . 'MobileSkin_Detection.php'; |
| 30 | +$wgAutoloadClasses['MobileSkin_Hooks'] = $dir . 'MobileSkin_Hooks.php'; |
| 31 | +$wgAutoloadClasses['MobileSkin_Options'] = $dir . 'MobileSkin_Options.php'; |
| 32 | +$wgAutoloadClasses['MobileSkin_PostParse'] = $dir . 'MobileSkin_PostParse.php'; |
| 33 | + |
| 34 | +// Skins |
| 35 | +$wgAutoloadClasses['SkinMobile'] = $dir . 'skins/Mobile.php'; |
| 36 | + |
| 37 | +// Hooks |
| 38 | +$wgHooks['RequestContextCreateSkin'][] = 'MobileSkin_Hooks::createSkin'; |
| 39 | +$wgHooks['ParserSectionCreate'][] = 'MobileSkin_Hooks::parserSectionCreate'; |
| 40 | +$wgHooks['ArticleViewHeader'][] = 'MobileSkin_Hooks::articleView'; |
| 41 | +$wgHooks['ResourceLoaderGetStartupModules'][] = 'MobileSkin_Hooks::startupModule'; |
| 42 | +$wgHooks['ResourceLoaderRegisterModules'][] = 'MobileSkin_Hooks::registerModules'; |
| 43 | +$wgHooks['BeforeInitialize'][] = 'MobileSkin_Hooks::beforeInitialize'; |
| 44 | +$wgExtensionFunctions[] = 'MobileSkin_Hooks::setup'; |
| 45 | + |
| 46 | +// Modules |
| 47 | +$commonModuleInfo = array( |
| 48 | + 'localBasePath' => dirname( __FILE__ ) . '/modules', |
| 49 | + 'remoteExtPath' => 'MobileSkin/modules', |
| 50 | +); |
| 51 | + |
| 52 | +// Main style |
| 53 | +$wgResourceModules['ext.mobileSkin'] = array( |
| 54 | + 'scripts' => 'ext.mobileSkin/ext.mobileSkin.js', |
| 55 | + 'messages' => array( |
| 56 | + 'mobile-skin-show-button', |
| 57 | + 'mobile-skin-hide-button', |
| 58 | + ), |
| 59 | + 'dependencies' => array( |
| 60 | + 'mediawiki.util.lite', |
| 61 | + 'mediawiki.api.lite', |
| 62 | + ), |
| 63 | +) + $commonModuleInfo; |
| 64 | + |
| 65 | +$wgResourceModules['ext.mobileSkin.common'] = array( |
| 66 | + 'styles' => array( |
| 67 | + 'ext.mobileSkin/ext.mobileSkin.css', |
| 68 | + 'ext.mobileSkin/ext.mobileSkin.search.css', |
| 69 | + ), |
| 70 | +) + $commonModuleInfo; |
| 71 | + |
| 72 | +$wgResourceModules['zepto'] = array( |
| 73 | + 'scripts' => array( |
| 74 | + 'zepto/zepto.js', |
| 75 | + 'zepto/zepto.mw.js', |
| 76 | + ), |
| 77 | +) + $commonModuleInfo; |
| 78 | + |
| 79 | +// Config |
| 80 | +/** |
| 81 | + * Logo used on MobileSkin |
| 82 | + * |
| 83 | + * @var $wgMobileSkinLogo string |
| 84 | + */ |
| 85 | +$wgMobileSkinLogo = null; |
\ No newline at end of file |
Property changes on: trunk/extensions/MobileSkin/MobileSkin.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 86 | + native |
Index: trunk/extensions/MobileSkin/MobileSkin_PostParse.php |
— | — | @@ -0,0 +1,92 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Take the bodycontent and manipulate it for mobile |
| 6 | + */ |
| 7 | +class MobileSkin_PostParse { |
| 8 | + |
| 9 | + /** |
| 10 | + * HTML to parse |
| 11 | + * |
| 12 | + * @var string |
| 13 | + */ |
| 14 | + protected $html; |
| 15 | + |
| 16 | + /** |
| 17 | + * DOM of the bodycontent |
| 18 | + * |
| 19 | + * @var DOMDocument |
| 20 | + */ |
| 21 | + protected $dom; |
| 22 | + |
| 23 | + /** |
| 24 | + * Private constructor, use the mange function |
| 25 | + * |
| 26 | + * @param $html |
| 27 | + */ |
| 28 | + protected function __construct( $html ) { |
| 29 | + $this->html = $html; |
| 30 | + |
| 31 | + $this->initDom(); |
| 32 | + } |
| 33 | + |
| 34 | + /** |
| 35 | + * Entry point for the class |
| 36 | + * |
| 37 | + * @param $text string |
| 38 | + * @return string |
| 39 | + */ |
| 40 | + public static function mangle( $text ) { |
| 41 | + $postParse = new self( $text ); |
| 42 | + $postParse->parse(); |
| 43 | + |
| 44 | + return $postParse->html; |
| 45 | + } |
| 46 | + |
| 47 | + /** |
| 48 | + * Sets up the DOM document |
| 49 | + */ |
| 50 | + protected function initDom() { |
| 51 | + // LibXML is noisy apparently |
| 52 | + libxml_use_internal_errors( true ); |
| 53 | + $dom = new DOMDocument(); |
| 54 | + $dom->loadHTML( '<?xml encoding="UTF-8">' . $this->html ); |
| 55 | + libxml_use_internal_errors( false ); |
| 56 | + |
| 57 | + $dom->strictErrorChecking = false; |
| 58 | + $dom->encoding = 'UTF-8'; |
| 59 | + |
| 60 | + $this->dom = $dom; |
| 61 | + } |
| 62 | + |
| 63 | + /** |
| 64 | + * Actually parse the DOM |
| 65 | + */ |
| 66 | + public function parse() { |
| 67 | + // Remove the TOC |
| 68 | + $this->removeToc(); |
| 69 | + |
| 70 | + // Render the now manipulated HTML |
| 71 | + $this->render(); |
| 72 | + } |
| 73 | + |
| 74 | + /** |
| 75 | + * Removes the TOC (#toc) from the body |
| 76 | + */ |
| 77 | + protected function removeToc() { |
| 78 | + $element = $this->dom->getElementById( 'toc' ); |
| 79 | + |
| 80 | + if ( $element !== null ) { |
| 81 | + $element->parentNode->removeChild( $element ); |
| 82 | + } |
| 83 | + } |
| 84 | + |
| 85 | + /** |
| 86 | + * Saves the HTML to $html |
| 87 | + */ |
| 88 | + protected function render() { |
| 89 | + $this->html = $this->dom->saveXML( |
| 90 | + $this->dom->getElementsByTagName( 'body' ) |
| 91 | + ->item( 0 )->childNodes->item( 0 ) ); |
| 92 | + } |
| 93 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/MobileSkin/MobileSkin_PostParse.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 94 | + native |
Index: trunk/extensions/MobileSkin/MobileSkin_Hooks.php |
— | — | @@ -0,0 +1,171 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Hooks for the new mobile skin |
| 6 | + */ |
| 7 | +class MobileSkin_Hooks { |
| 8 | + /** |
| 9 | + * Loads the mobile skin if we need to |
| 10 | + * |
| 11 | + * @param $context ResourceContext |
| 12 | + * @param $skin Skin |
| 13 | + * @return bool |
| 14 | + */ |
| 15 | + public static function createSkin( $context, &$skin ) { |
| 16 | + // Abort if we're not using the mobile skin |
| 17 | + if ( !MobileSkin_Detection::isEnabled() ) { |
| 18 | + return true; |
| 19 | + } |
| 20 | + |
| 21 | + // TODO: WML support |
| 22 | + $skin = new SkinMobile; |
| 23 | + |
| 24 | + // Be a dick and halt the hook |
| 25 | + return false; |
| 26 | + } |
| 27 | + |
| 28 | + /** |
| 29 | + * Adds jump back a section links to content blocks |
| 30 | + * |
| 31 | + * @todo broken, see mobile main page |
| 32 | + * |
| 33 | + * @param $parser MobileSkin_Parser |
| 34 | + * @param $i int |
| 35 | + * @param $section string |
| 36 | + * @param $showEditLink bool |
| 37 | + * @return bool |
| 38 | + */ |
| 39 | + public static function parserSectionCreate( $parser, $i, &$section, $showEditLink ) { |
| 40 | + if ( !MobileSkin_Detection::isEnabled() ) { |
| 41 | + return true; |
| 42 | + } |
| 43 | + |
| 44 | + // We don't enclose the opening section |
| 45 | + if ( $i == 0 ) { |
| 46 | + return true; |
| 47 | + } |
| 48 | + |
| 49 | + // Separate the header from the section |
| 50 | + preg_match( '/<H[1-6].*?' . '>.*?<\/H[1-6]>/i', $section, $match ); |
| 51 | + $headerLength = strlen( $match[0] ); |
| 52 | + |
| 53 | + $section = "<div section_id=\"$i\" id=\"section-$i\" class=\"mf2-section-container\">" |
| 54 | + . substr( $section, 0, $headerLength ) |
| 55 | + . '<div class="mf2-content-block">' |
| 56 | + . substr( $section, $headerLength ) . "\n\n" |
| 57 | + . '<div class="mf2-section-anchor">' |
| 58 | + . '<a href="#section-' . $i . '">' |
| 59 | + . wfMessage( 'mobile-skin-back-to-top-of-section' )->escaped() |
| 60 | + . '</a></div></div></div>'; |
| 61 | + |
| 62 | + return true; |
| 63 | + } |
| 64 | + |
| 65 | + public static function articleView( &$article, &$outputDone, &$useParserCache ) { |
| 66 | + // This is where we want to fetch the article from squids |
| 67 | + return true; |
| 68 | + } |
| 69 | + |
| 70 | + /** |
| 71 | + * Replaces jQuery with zepto.js for mobile |
| 72 | + * |
| 73 | + * @param $modules |
| 74 | + * @return bool |
| 75 | + */ |
| 76 | + public static function startupModule( &$modules ) { |
| 77 | + // comment about this |
| 78 | + if ( self::isMobileSkin() ) { |
| 79 | + $modules = array( |
| 80 | + 'zepto', |
| 81 | + 'mediawiki', |
| 82 | + ); |
| 83 | + return false; |
| 84 | + } |
| 85 | + |
| 86 | + return true; |
| 87 | + } |
| 88 | + |
| 89 | + /** |
| 90 | + * Registers lite versions of core modules for mobile |
| 91 | + * |
| 92 | + * @param ResourceLoader $resourceLoader |
| 93 | + * @return bool |
| 94 | + */ |
| 95 | + public static function registerModules( ResourceLoader &$resourceLoader ) { |
| 96 | + if ( self::isMobileSkin() ) { |
| 97 | + global $wgResourceModules; |
| 98 | + |
| 99 | + // We need to remove dependencies from mw.util that will don't use and |
| 100 | + // aren't compatible with zepto.js |
| 101 | + // Krinkle will hate me |
| 102 | + // TODO: This only saves about 4KB, reevaluate later |
| 103 | + $wgResourceModules['mediawiki.util.lite'] = array( |
| 104 | + 'scripts' => 'resources/mediawiki/mediawiki.util.js', |
| 105 | + /*'dependencies' => array( |
| 106 | + 'jquery.client', |
| 107 | + 'jquery.cookie', |
| 108 | + 'jquery.messageBox', |
| 109 | + 'jquery.mwExtension', |
| 110 | + ),*/ |
| 111 | + //'messages' => array( 'showtoc', 'hidetoc' ), |
| 112 | + 'position' => 'top', // For $wgPreloadJavaScriptMwUtil |
| 113 | + ); |
| 114 | + $wgResourceModules['mediawiki.api.lite'] = array( |
| 115 | + 'scripts' => 'resources/mediawiki/mediawiki.api.js', |
| 116 | + 'dependencies' => 'mediawiki.util.lite', |
| 117 | + ); |
| 118 | + } |
| 119 | + |
| 120 | + return true; |
| 121 | + } |
| 122 | + |
| 123 | + /** |
| 124 | + * Overrides the main page with the mobile version of the main page |
| 125 | + * |
| 126 | + * @param Title $title |
| 127 | + * @param $unused |
| 128 | + * @param $output |
| 129 | + * @param $user |
| 130 | + * @param $request |
| 131 | + * @param $wiki |
| 132 | + * @return bool |
| 133 | + */ |
| 134 | + public static function beforeInitialize( Title &$title, &$unused, &$output, &$user, $request, $wiki ) { |
| 135 | + if ( MobileSkin_Detection::isEnabled() && $title->isMainPage() ) { |
| 136 | + $title = Title::newFromText( wfMsgForContent( 'mainpage-mobile' ) ); |
| 137 | + RequestContext::getMain()->setTitle( $title ); |
| 138 | + MobileSkin_Options::setMainPage( true ); |
| 139 | + } |
| 140 | + |
| 141 | + return true; |
| 142 | + } |
| 143 | + |
| 144 | + /** |
| 145 | + * Checks if the skin parameter is for a mobile skin |
| 146 | + * |
| 147 | + * This only works for load.php |
| 148 | + * |
| 149 | + * @return bool |
| 150 | + */ |
| 151 | + protected static function isMobileSkin() { |
| 152 | + return RequestContext::getMain()->getRequest()->getVal( 'skin' ) == 'mobile'; |
| 153 | + } |
| 154 | + |
| 155 | + /** |
| 156 | + * Perform very early setup |
| 157 | + * |
| 158 | + * @return bool |
| 159 | + */ |
| 160 | + public static function setup() { |
| 161 | + if ( !MobileSkin_Detection::isEnabled() ) { |
| 162 | + return true; |
| 163 | + } |
| 164 | + global $wgMobileSkinLogo, $wgExtensionAssetsPath; |
| 165 | + |
| 166 | + // We need a sane default and $wgExtensionAssetsPath isn't ready until |
| 167 | + // after LocalSettings |
| 168 | + if ( $wgMobileSkinLogo === null ) { |
| 169 | + $wgMobileSkinLogo = $wgExtensionAssetsPath . '/MobileSkin/modules/ext.mobileSkin/images/mw.png'; |
| 170 | + } |
| 171 | + } |
| 172 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/MobileSkin/MobileSkin_Hooks.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 173 | + native |
Index: trunk/extensions/MobileSkin/skins/Mobile.php |
— | — | @@ -12,7 +12,7 @@ |
13 | 13 | * @param null|OutputPage $out |
14 | 14 | */ |
15 | 15 | function outputPage( OutputPage $out = null ) { |
16 | | - global $wgScript, $wgMobileFrontend2Logo; |
| 16 | + global $wgScript, $wgMobileSkinLogo; |
17 | 17 | |
18 | 18 | $out = $this->getOutput(); |
19 | 19 | $request = $this->getRequest(); |
— | — | @@ -23,13 +23,13 @@ |
24 | 24 | $out->clearAllModules(); |
25 | 25 | |
26 | 26 | // Add the mobile js |
27 | | - $out->addModules( 'ext.mobileFrontend2' ); |
| 27 | + $out->addModules( 'ext.mobileSkin' ); |
28 | 28 | |
29 | 29 | // TODO: Hook for adding modules |
30 | 30 | |
31 | 31 | $bodyClass = 'mobile'; |
32 | 32 | |
33 | | - if ( MobileFrontend2_Options::getMainPage() ) { |
| 33 | + if ( MobileSkin_Options::getMainPage() ) { |
34 | 34 | // fixup the HTML title |
35 | 35 | $msg = wfMessage( 'pagetitle-view-mainpage' )->inContentLanguage(); |
36 | 36 | if ( !$msg->isDisabled() ) { |
— | — | @@ -63,7 +63,7 @@ |
64 | 64 | $tpl->setRef( 'wgScript', $wgScript ); |
65 | 65 | |
66 | 66 | // Mobile stuff |
67 | | - $tpl->setRef( 'mobilelogopath', $wgMobileFrontend2Logo ); |
| 67 | + $tpl->setRef( 'mobilelogopath', $wgMobileSkinLogo ); |
68 | 68 | |
69 | 69 | # Add a <div class="mw-content-ltr/rtl"> around the body text |
70 | 70 | # not for special pages or file pages AND only when viewing AND if the page exists |
— | — | @@ -77,7 +77,7 @@ |
78 | 78 | $out->mBodytext = Html::rawElement( 'div', $realBodyAttribs, $out->mBodytext ); |
79 | 79 | } |
80 | 80 | |
81 | | - $tpl->setRef( 'bodycontent', MobileFrontend2_PostParse::mangle( $out->mBodytext ) ); |
| 81 | + $tpl->setRef( 'bodycontent', MobileSkin_PostParse::mangle( $out->mBodytext ) ); |
82 | 82 | |
83 | 83 | // Pass the bodyClass for CSS magic |
84 | 84 | $tpl->set( 'bodyclass', $bodyClass ); |
— | — | @@ -104,7 +104,7 @@ |
105 | 105 | * @param OutputPage $out |
106 | 106 | */ |
107 | 107 | function setupSkinUserCss( OutputPage $out ) { |
108 | | - $out->addModuleStyles( 'ext.mobileFrontend2.common' ); |
| 108 | + $out->addModuleStyles( 'ext.mobileSkin.common' ); |
109 | 109 | } |
110 | 110 | |
111 | 111 | /** |
— | — | @@ -118,7 +118,7 @@ |
119 | 119 | * @return string |
120 | 120 | */ |
121 | 121 | public function doEditSectionLink( Title $nt, $section, $tooltip = null, $lang = false ) { |
122 | | - return '<button class="mf2-section-toggle">' . wfMessage( 'mobile-frontend2-show-button' )->escaped() . '</button>'; |
| 122 | + return '<button class="mf2-section-toggle">' . wfMessage( 'mobile-skin-show-button' )->escaped() . '</button>'; |
123 | 123 | } |
124 | 124 | |
125 | 125 | /** |
— | — | @@ -163,12 +163,12 @@ |
164 | 164 | </head> |
165 | 165 | <body class="<?php $this->text( 'bodyclass' ) ?>"> |
166 | 166 | |
167 | | - <?php if ( !MobileFrontend2_Options::getHideSearch() ): ?> |
| 167 | + <?php if ( !MobileSkin_Options::getHideSearch() ): ?> |
168 | 168 | <!-- search/header --> |
169 | 169 | <div id="results"></div> |
170 | 170 | <div id="header"> |
171 | 171 | <div id="searchbox"> |
172 | | - <?php if ( !MobileFrontend2_Options::getHideLogo() ): ?> |
| 172 | + <?php if ( !MobileSkin_Options::getHideLogo() ): ?> |
173 | 173 | <img src="<?php $this->text( 'mobilelogopath' ) ?>" alt="Logo" id="mf2-logo" width="35" height="22" /> |
174 | 174 | <?php endif ?> |
175 | 175 | <form action="<?php $this->text( 'wgScript' ) ?>" class="mf2-search-bar" method="get"> |
— | — | @@ -186,7 +186,7 @@ |
187 | 187 | |
188 | 188 | <!-- content --> |
189 | 189 | <div class="show" id="content_wrapper"> |
190 | | - <?php if ( !MobileFrontend2_Options::getMainPage() ): ?> |
| 190 | + <?php if ( !MobileSkin_Options::getMainPage() ): ?> |
191 | 191 | <!-- firstHeading --> |
192 | 192 | <h1 id="firstHeading" class="firstHeading"> |
193 | 193 | <span dir="auto"><?php $this->html( 'title' ) ?></span> |
— | — | @@ -203,18 +203,18 @@ |
204 | 204 | <!-- /bodyContent --> |
205 | 205 | </div> |
206 | 206 | |
207 | | - <?php if ( !MobileFrontend2_Options::getHideFooter() ): ?> |
| 207 | + <?php if ( !MobileSkin_Options::getHideFooter() ): ?> |
208 | 208 | <!-- footer --> |
209 | 209 | <div id="footer"> |
210 | 210 | <div id="innerFooter"> |
211 | | - <a href="#"><?php $this->msg( 'mobile-frontend2-regular-site' ) ?></a> | <a href="#"><?php $this->msg( 'mobile-frontend2-disable-images' ) ?></a> |
| 211 | + <a href="#"><?php $this->msg( 'mobile-skin-regular-site' ) ?></a> | <a href="#"><?php $this->msg( 'mobile-skin-disable-images' ) ?></a> |
212 | 212 | |
213 | 213 | <div id="perm"> |
214 | | - <a href="#"><?php $this->msg( 'mobile-frontend2-perm-stop-redirect' ) ?></a> |
| 214 | + <a href="#"><?php $this->msg( 'mobile-skin-perm-stop-redirect' ) ?></a> |
215 | 215 | </div> |
216 | 216 | </div> |
217 | 217 | <div id="copyright"> |
218 | | - <?php $this->msg( 'mobile-frontend2-copyright' ) ?> |
| 218 | + <?php $this->msg( 'mobile-skin-copyright' ) ?> |
219 | 219 | </div> |
220 | 220 | </div> |
221 | 221 | <?php endif ?> |
Index: trunk/extensions/MobileSkin/modules/ext.mobileSkin/ext.mobileSkin.css |
— | — | @@ -0,0 +1,113 @@ |
| 2 | +/* CSS For MobileSkin */ |
| 3 | + |
| 4 | +/* Basic styling */ |
| 5 | +html { |
| 6 | + font-size: 0.8em; |
| 7 | +} |
| 8 | + |
| 9 | +body { |
| 10 | + line-height: 1; |
| 11 | + color: black; |
| 12 | + background: white; |
| 13 | + font-family: sans-serif; |
| 14 | + -webkit-text-size-adjust: none; |
| 15 | + margin: 0; |
| 16 | +} |
| 17 | + |
| 18 | +p, li, dl { |
| 19 | + line-height: 1.65; |
| 20 | +} |
| 21 | + |
| 22 | +pre { |
| 23 | + white-space: pre-wrap; |
| 24 | +} |
| 25 | + |
| 26 | +h2 { |
| 27 | + border-bottom: 1px solid #aaaaaa; |
| 28 | + padding-top: 0.3em; |
| 29 | + font-size: 1.3em; |
| 30 | +} |
| 31 | + |
| 32 | +/* Links */ |
| 33 | +a { |
| 34 | + text-decoration: none; |
| 35 | + color: #002bb8; |
| 36 | +} |
| 37 | + |
| 38 | +a:visited { |
| 39 | + color: #5a3696; |
| 40 | +} |
| 41 | + |
| 42 | +a:active { |
| 43 | + color: #faa700; |
| 44 | +} |
| 45 | + |
| 46 | +a:hover { |
| 47 | + text-decoration: underline; |
| 48 | +} |
| 49 | + |
| 50 | +a.new, a.new:visited, a.new:hover { |
| 51 | + color: red; |
| 52 | +} |
| 53 | + |
| 54 | +/* Page Title */ |
| 55 | +#firstHeading { |
| 56 | + font-size: 1.7em; |
| 57 | +} |
| 58 | + |
| 59 | +/* Jump back a section links */ |
| 60 | +.mf2-section-anchor a, |
| 61 | +.mf2-section-anchor a:visited { |
| 62 | + margin-top: 7px; |
| 63 | + color:blue; |
| 64 | +} |
| 65 | + |
| 66 | +/* All the main content divs should be 8px from the side */ |
| 67 | +#header { |
| 68 | + margin: 8px 8px 0 8px; |
| 69 | +} |
| 70 | + |
| 71 | +#content_wrapper { |
| 72 | + clear: both; |
| 73 | + margin: 0 8px; |
| 74 | +} |
| 75 | + |
| 76 | +#footer { |
| 77 | + margin: 0 8px; |
| 78 | + padding: 1em 0 5px; |
| 79 | +} |
| 80 | + |
| 81 | +#footer #innerFooter { |
| 82 | + padding: 5px; |
| 83 | + background: #dddddd; |
| 84 | + -webkit-border-radius: 5px; |
| 85 | + margin-top: 5px; |
| 86 | + text-align: center; |
| 87 | + border: 1px solid grey; |
| 88 | + font-size: 1.1em; |
| 89 | +} |
| 90 | + |
| 91 | +#footer #innerFooter #perm { |
| 92 | + padding-top: 2em; |
| 93 | + font-size: 90%; |
| 94 | +} |
| 95 | + |
| 96 | +#footer #copyright { |
| 97 | + padding: 1em 0; |
| 98 | + font-size: 80%; |
| 99 | +} |
| 100 | + |
| 101 | +/* Hide the content block */ |
| 102 | +.mf2-content-block { |
| 103 | + display: none; |
| 104 | +} |
| 105 | + |
| 106 | +/* Disable content folding on the main page */ |
| 107 | +body.mainPage .mf2-section-anchor, |
| 108 | +body.mainPage button.mf2-section-toggle { |
| 109 | + display: none; |
| 110 | +} |
| 111 | + |
| 112 | +body.mainPage .mf2-content-block { |
| 113 | + display: block; |
| 114 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/MobileSkin/modules/ext.mobileSkin/ext.mobileSkin.css |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 115 | + native |
Index: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/100px-globe.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/100px-globe.png |
___________________________________________________________________ |
Added: svn:mime-type |
2 | 116 | + image/png |
Index: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/clearicon.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/clearicon.png |
___________________________________________________________________ |
Added: svn:mime-type |
3 | 117 | + image/png |
Index: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/logo-en.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/logo-en.png |
___________________________________________________________________ |
Added: svn:mime-type |
4 | 118 | + image/png |
Index: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/search-big.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/search-big.png |
___________________________________________________________________ |
Added: svn:mime-type |
5 | 119 | + image/png |
Index: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/buttonbg.gif |
Cannot display: file marked as a binary type. |
svn:mime-type = image/gif |
Property changes on: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/buttonbg.gif |
___________________________________________________________________ |
Added: svn:mime-type |
6 | 120 | + image/gif |
Index: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/search.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/search.png |
___________________________________________________________________ |
Added: svn:mime-type |
7 | 121 | + image/png |
Index: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/system-search.gif |
Cannot display: file marked as a binary type. |
svn:mime-type = image/gif |
Property changes on: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/system-search.gif |
___________________________________________________________________ |
Added: svn:mime-type |
8 | 122 | + image/gif |
Index: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/s-xhdpi.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/s-xhdpi.png |
___________________________________________________________________ |
Added: svn:mime-type |
9 | 123 | + image/png |
Index: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/s.svg |
Cannot display: file marked as a binary type. |
svn:mime-type = image/svg+xml |
Property changes on: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/s.svg |
___________________________________________________________________ |
Added: svn:mime-type |
10 | 124 | + image/svg+xml |
Index: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/close-button.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/close-button.png |
___________________________________________________________________ |
Added: svn:mime-type |
11 | 125 | + image/png |
Index: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/arrow-left.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/arrow-left.png |
___________________________________________________________________ |
Added: svn:mime-type |
12 | 126 | + image/png |
Index: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/mw.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/mw.png |
___________________________________________________________________ |
Added: svn:mime-type |
13 | 127 | + image/png |
Index: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/s.gif |
Cannot display: file marked as a binary type. |
svn:mime-type = image/gif |
Property changes on: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/s.gif |
___________________________________________________________________ |
Added: svn:mime-type |
14 | 128 | + image/gif |
Index: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/s-hdpi.png |
Cannot display: file marked as a binary type. |
svn:mime-type = image/png |
Property changes on: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/s-hdpi.png |
___________________________________________________________________ |
Added: svn:mime-type |
15 | 129 | + image/png |
Index: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/search.gif |
Cannot display: file marked as a binary type. |
svn:mime-type = image/gif |
Property changes on: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/search.gif |
___________________________________________________________________ |
Added: svn:mime-type |
16 | 130 | + image/gif |
Index: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/w.gif |
Cannot display: file marked as a binary type. |
svn:mime-type = image/gif |
Property changes on: trunk/extensions/MobileSkin/modules/ext.mobileSkin/images/w.gif |
___________________________________________________________________ |
Added: svn:mime-type |
17 | 131 | + image/gif |
Index: trunk/extensions/MobileSkin/modules/ext.mobileSkin/ext.mobileSkin.js |
— | — | @@ -0,0 +1,155 @@ |
| 2 | +(function( $, mw, undefined ) { |
| 3 | + |
| 4 | +var MobileSkin = mf2 = { |
| 5 | + /** |
| 6 | + * Timer for updating search suggestions |
| 7 | + */ |
| 8 | + searchTimer: undefined, |
| 9 | + |
| 10 | + /** |
| 11 | + * mw.Api object for accessing the API |
| 12 | + * |
| 13 | + * @var api {mw.Api} |
| 14 | + */ |
| 15 | + api: undefined, |
| 16 | + |
| 17 | + /** |
| 18 | + * Run to set up the page |
| 19 | + */ |
| 20 | + init: function() { |
| 21 | + // Create our API object |
| 22 | + mf2.api = new mw.Api(); |
| 23 | + |
| 24 | + // Hook the section toggle |
| 25 | + $( '.mf2-section-container h2' ).click( mf2.toggleSection ); |
| 26 | + |
| 27 | + // Listen for searches |
| 28 | + $( '#search' ).keyup( mf2.searchKeyUp ); |
| 29 | + |
| 30 | + // Setup the width for search |
| 31 | + // TODO: Only worry about this if we have the search element |
| 32 | + mf2.updateSearchWidth(); |
| 33 | + }, |
| 34 | + |
| 35 | + /** |
| 36 | + * Toggles page section visibility |
| 37 | + */ |
| 38 | + toggleSection: function() { |
| 39 | + var $header = $( this ), |
| 40 | + $contentDiv = $header.next(), |
| 41 | + buttonMsg; |
| 42 | + |
| 43 | + // Toggle the div |
| 44 | + $contentDiv.toggle(); |
| 45 | + |
| 46 | + // Change the button text |
| 47 | + buttonMsg = $contentDiv.css( 'display' ) === 'block' ? 'mobile-skin-hide-button' : 'mobile-skin-show-button'; |
| 48 | + $header.find( 'button' ).html( mw.msg( buttonMsg ) ); |
| 49 | + }, |
| 50 | + |
| 51 | + /** |
| 52 | + * Schedules an update of search suggestions |
| 53 | + * |
| 54 | + * Fired when data is entered into the search box |
| 55 | + */ |
| 56 | + searchKeyUp: function() { |
| 57 | + clearTimeout( mf2.searchTimer ); |
| 58 | + |
| 59 | + if ( this.value.length < 1 ) { |
| 60 | + $( '#results' ).html( '' ); |
| 61 | + } else { |
| 62 | + // TODO: Config |
| 63 | + mf2.searchTimer = setTimeout( mf2.search, 500 ); |
| 64 | + } |
| 65 | + }, |
| 66 | + |
| 67 | + /** |
| 68 | + * Fires off the request to the API to get search results |
| 69 | + */ |
| 70 | + search: function() { |
| 71 | + mf2.api.get( { |
| 72 | + action: 'opensearch', |
| 73 | + limit: 5, |
| 74 | + namespace: 0, |
| 75 | + search: $( '#search' ).val() |
| 76 | + }, mf2.searchResults ); |
| 77 | + }, |
| 78 | + |
| 79 | + /** |
| 80 | + * Update the search suggestions with API results |
| 81 | + * |
| 82 | + * @param data |
| 83 | + */ |
| 84 | + searchResults: function( data ) { |
| 85 | + var results = data[1], // Second element has the results, fuck standards |
| 86 | + $results = $( '#results' ); |
| 87 | + |
| 88 | + $results.show(); |
| 89 | + if ( results.length < 1 ) { |
| 90 | + $results.text( 'No results' ); // TRANSLATE |
| 91 | + return; |
| 92 | + } |
| 93 | + |
| 94 | + $r = $( '<div class="suggestions">' ); |
| 95 | + |
| 96 | + $.each( results, function( i, title ) { |
| 97 | + $( '<div class="suggestions-result">' ) |
| 98 | + .attr( 'title', title ) |
| 99 | + .attr( 'rel', i + 1 ) // ? |
| 100 | + .append( |
| 101 | + $( '<a class="suggestions-result-update">' ) |
| 102 | + .text( '+' ) // Translate? |
| 103 | + .click( mf2.updateSearchValue ) |
| 104 | + ) |
| 105 | + .append( |
| 106 | + $( '<a class="search-result-item">' ) |
| 107 | + .attr( 'href', mw.util.wikiGetlink( title ) ) |
| 108 | + .text( title ) |
| 109 | + ) |
| 110 | + .appendTo( $r ); |
| 111 | + } ); |
| 112 | + |
| 113 | + $results.html( $r ); |
| 114 | + }, |
| 115 | + |
| 116 | + /** |
| 117 | + * Update the value of the search box with the selected suggestion |
| 118 | + * |
| 119 | + * Fire when the plus symbol is clicked |
| 120 | + */ |
| 121 | + updateSearchValue: function () { |
| 122 | + var title = $( this ).parent().attr( 'title' ); |
| 123 | + |
| 124 | + $( '#search' ) |
| 125 | + .val( title + ' ' ) |
| 126 | + .focus(); |
| 127 | + |
| 128 | + // Reload suggestions |
| 129 | + mf2.search(); |
| 130 | + }, |
| 131 | + |
| 132 | + /** |
| 133 | + * Updates the width of the header and search box |
| 134 | + * |
| 135 | + * Fired when the screen orientation changes |
| 136 | + */ |
| 137 | + updateSearchWidth: function () { |
| 138 | + var clientWidth = $( window ).width(), |
| 139 | + $sq = $( '#sq' ), |
| 140 | + sqOffset = $sq.offset(); |
| 141 | + |
| 142 | + // TODO: ew. This should be CSS |
| 143 | + $( '#searchbox' ).width( clientWidth - 30 ); |
| 144 | + $sq.width( clientWidth - 110 ); |
| 145 | + $( '#search' ).width( clientWidth - 130 ); |
| 146 | + $( '#results' ).css({ |
| 147 | + width: $sq.width() - 2, |
| 148 | + left: sqOffset.left, |
| 149 | + top: sqOffset.top + $sq.height() |
| 150 | + }); |
| 151 | + } |
| 152 | +}; |
| 153 | + |
| 154 | +$( mf2.init ); |
| 155 | + |
| 156 | +})( Zepto, mediaWiki ); |
\ No newline at end of file |
Property changes on: trunk/extensions/MobileSkin/modules/ext.mobileSkin/ext.mobileSkin.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 157 | + native |
Index: trunk/extensions/MobileSkin/modules/ext.mobileSkin/ext.mobileSkin.search.css |
— | — | @@ -0,0 +1,138 @@ |
| 2 | +/* SEARCH */ |
| 3 | +#search { |
| 4 | + -webkit-appearance: none; |
| 5 | + border-top-width: 0px; |
| 6 | + border-right-width: 0px; |
| 7 | + border-bottom-width: 0px; |
| 8 | + border-left-width: 0px; |
| 9 | + outline-style: none; |
| 10 | + outline-width: initial; |
| 11 | + outline-color: initial; |
| 12 | + height: 1.4em; |
| 13 | +} |
| 14 | + |
| 15 | +#search:focus { |
| 16 | + outline: none; |
| 17 | +} |
| 18 | + |
| 19 | +#searchbox img, |
| 20 | +#searchbox form, |
| 21 | +#searchbox input, |
| 22 | +#searchbox button { |
| 23 | + vertical-align: middle; |
| 24 | + display: inline-block; |
| 25 | +} |
| 26 | + |
| 27 | +#searchbox { |
| 28 | + width: auto; |
| 29 | + padding: 5px; |
| 30 | + border: 1px solid #cccccc; |
| 31 | + -webkit-border-radius: 2px; |
| 32 | + -moz-border-radius: 2px; |
| 33 | +} |
| 34 | + |
| 35 | +#searchbox a, #searchbox img { |
| 36 | + border: 0px; |
| 37 | + vertical-align: middle; |
| 38 | +} |
| 39 | + |
| 40 | +#searchbox #goButton { |
| 41 | + border: 0; |
| 42 | + /* @embed */ |
| 43 | + background: url(images/s.gif) no-repeat top left; |
| 44 | + background-size: 27px 25px; |
| 45 | + height: 25px; |
| 46 | + width: 27px; |
| 47 | +} |
| 48 | + |
| 49 | +#searchbox #searchField { |
| 50 | + width: auto; |
| 51 | +} |
| 52 | + |
| 53 | +/*TODO: This might need to go in the main one*/ |
| 54 | +.clearlink { |
| 55 | + /* @embed */ |
| 56 | + background: url(images/close-button.png) no-repeat scroll 0 0 transparent; |
| 57 | + background-position: center center; |
| 58 | + cursor: pointer; |
| 59 | + zoom: 1; |
| 60 | + position: absolute; |
| 61 | + right: 0.25em; |
| 62 | + top: 50%; |
| 63 | + margin: 1px; |
| 64 | + height: 12px; |
| 65 | + width: 12px; |
| 66 | + margin-top: -6px; |
| 67 | + z-index: 2; |
| 68 | + border: 0px solid; |
| 69 | + display: none; |
| 70 | +} |
| 71 | + |
| 72 | +.divclearable { |
| 73 | + border: 1px solid #888; |
| 74 | + display: -moz-inline-stack; |
| 75 | + display: inline-block; |
| 76 | + zoom: 1; |
| 77 | + *display: inline; |
| 78 | + vertical-align: middle; |
| 79 | + height: 1.5em; |
| 80 | + position: relative; |
| 81 | +} |
| 82 | + |
| 83 | +/* Search Suggestions */ |
| 84 | +#results { |
| 85 | + display: none; |
| 86 | + background-color: #ffffff; |
| 87 | + border-top: none; |
| 88 | + border-left: 1px solid #888; |
| 89 | + border-right: 1px solid #888; |
| 90 | + border-bottom: 1px solid #888; |
| 91 | + z-index: 2; |
| 92 | + position: absolute; |
| 93 | +} |
| 94 | + |
| 95 | +.suggestions { |
| 96 | + font-size: 1.2em; |
| 97 | + cursor: pointer; |
| 98 | +} |
| 99 | + |
| 100 | +.suggestions-result { |
| 101 | + color: black; |
| 102 | + color: WindowText; |
| 103 | + margin: 0; |
| 104 | + line-height: 1.8em; |
| 105 | + padding: 0.01em 0.25em; |
| 106 | + text-align: left; |
| 107 | + postion: relative; |
| 108 | + border-bottom: solid 1px #999999; |
| 109 | +} |
| 110 | + |
| 111 | +.suggestions-result:hover { |
| 112 | + background-color: #ACD1E9; |
| 113 | +} |
| 114 | + |
| 115 | +.suggestions-result a, |
| 116 | +.suggestions-result a:link, |
| 117 | +.suggestions-result a:visited, |
| 118 | +.suggestions-result a:hover, |
| 119 | +.suggestions-result a:active { |
| 120 | + text-decoration: none; |
| 121 | + color: #000000; |
| 122 | +} |
| 123 | + |
| 124 | +a.suggestions-result-update { |
| 125 | + font-size: 1.3em; |
| 126 | + display: block; |
| 127 | + font-weight: normal; |
| 128 | + text-decoration: none; |
| 129 | + color: #000000; |
| 130 | + position: absolute; |
| 131 | + right: 0; |
| 132 | + width: 1.5em; |
| 133 | + text-align: center; |
| 134 | +} |
| 135 | + |
| 136 | +a.search-result-item { |
| 137 | + display: block; |
| 138 | + margin-right: 2em; |
| 139 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/MobileSkin/modules/ext.mobileSkin/ext.mobileSkin.search.css |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 140 | + native |
Index: trunk/extensions/MobileSkin/MobileSkin_Options.php |
— | — | @@ -0,0 +1,82 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +class MobileSkin_Options { |
| 5 | + |
| 6 | + /** |
| 7 | + * Hide the search bar |
| 8 | + * |
| 9 | + * @var bool |
| 10 | + */ |
| 11 | + protected static $hideSearch = false; |
| 12 | + |
| 13 | + /** |
| 14 | + * Hides the logo |
| 15 | + * |
| 16 | + * @var bool |
| 17 | + */ |
| 18 | + protected static $hideLogo = false; |
| 19 | + |
| 20 | + /** |
| 21 | + * Hides the footer |
| 22 | + * |
| 23 | + * @var bool |
| 24 | + */ |
| 25 | + protected static $hideFooter = false; |
| 26 | + |
| 27 | + /** |
| 28 | + * Not a user-option, used to do thing such as hide the title for the main |
| 29 | + * page |
| 30 | + * |
| 31 | + * @var bool |
| 32 | + */ |
| 33 | + protected static $mainPage = false; |
| 34 | + |
| 35 | + /** |
| 36 | + * Detects options based on user preferences |
| 37 | + */ |
| 38 | + public static function detect() { |
| 39 | + $request = RequestContext::getMain()->getRequest(); |
| 40 | + |
| 41 | + self::$hideSearch = $request->getBool( 'hidesearch' ); |
| 42 | + self::$hideLogo = $request->getBool( 'hidelogo' ); |
| 43 | + // TODO: Previously this was lumped into hidelogo. Notify mobile team |
| 44 | + self::$hideFooter = $request->getBool( 'hidefooter' ); |
| 45 | + |
| 46 | + // TODO: Hook for Wikimedia |
| 47 | + } |
| 48 | + |
| 49 | + /** |
| 50 | + * @return boolean |
| 51 | + */ |
| 52 | + public static function getHideLogo() { |
| 53 | + return self::$hideLogo; |
| 54 | + } |
| 55 | + |
| 56 | + /** |
| 57 | + * @return boolean |
| 58 | + */ |
| 59 | + public static function getHideSearch() { |
| 60 | + return self::$hideSearch; |
| 61 | + } |
| 62 | + |
| 63 | + /** |
| 64 | + * @return boolean |
| 65 | + */ |
| 66 | + public static function getHideFooter() { |
| 67 | + return self::$hideFooter; |
| 68 | + } |
| 69 | + |
| 70 | + /** |
| 71 | + * @param boolean $mainPage |
| 72 | + */ |
| 73 | + public static function setMainPage( $mainPage ) { |
| 74 | + self::$mainPage = $mainPage; |
| 75 | + } |
| 76 | + |
| 77 | + /** |
| 78 | + * @return boolean |
| 79 | + */ |
| 80 | + public static function getMainPage() { |
| 81 | + return self::$mainPage; |
| 82 | + } |
| 83 | +} |
Property changes on: trunk/extensions/MobileSkin/MobileSkin_Options.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 84 | + native |