Index: trunk/phase3/RELEASE-NOTES |
— | — | @@ -100,6 +100,8 @@ |
101 | 101 | file repository |
102 | 102 | * $wgWikiId added to override default output of wfWikiId() |
103 | 103 | * $wgDBAhandler added to choose a DBA handler when using CACHE_DBA |
| 104 | +* $wgPreviewOnOpenNamespaces for extensions that create namespaces that behave |
| 105 | + similarly to the category namespace. |
104 | 106 | |
105 | 107 | === New features in 1.16 === |
106 | 108 | |
Index: trunk/phase3/includes/EditPage.php |
— | — | @@ -72,9 +72,9 @@ |
73 | 73 | # Form values |
74 | 74 | var $save = false, $preview = false, $diff = false; |
75 | 75 | var $minoredit = false, $watchthis = false, $recreate = false; |
76 | | - var $textbox1 = '', $textbox2 = '', $summary = ''; |
| 76 | + var $textbox1 = '', $textbox2 = '', $summary = '', $nosummary = false; |
77 | 77 | var $edittime = '', $section = '', $starttime = ''; |
78 | | - var $oldid = 0, $editintro = '', $scrolltop = null; |
| 78 | + var $oldid = 0, $editintro = '', $scrolltop = null, $bot = true; |
79 | 79 | |
80 | 80 | # Placeholders for text injection by hooks (must be HTML) |
81 | 81 | # extensions should take care to _append_ to the present value |
— | — | @@ -534,7 +534,7 @@ |
535 | 535 | * @return bool |
536 | 536 | */ |
537 | 537 | protected function previewOnOpen() { |
538 | | - global $wgRequest, $wgUser; |
| 538 | + global $wgRequest, $wgUser, $wgPreviewOnOpenNamespaces; |
539 | 539 | if ( $wgRequest->getVal( 'preview' ) == 'yes' ) { |
540 | 540 | // Explicit override from request |
541 | 541 | return true; |
— | — | @@ -547,7 +547,10 @@ |
548 | 548 | } elseif ( ( $wgRequest->getVal( 'preload' ) !== null || $this->mTitle->exists() ) && $wgUser->getOption( 'previewonfirst' ) ) { |
549 | 549 | // Standard preference behaviour |
550 | 550 | return true; |
551 | | - } elseif ( !$this->mTitle->exists() && $this->mTitle->getNamespace() == NS_CATEGORY ) { |
| 551 | + } elseif ( !$this->mTitle->exists() && |
| 552 | + isset($wgPreviewOnOpenNamespaces[$this->mTitle->getNamespace()]) && |
| 553 | + $wgPreviewOnOpenNamespaces[$this->mTitle->getNamespace()] ) |
| 554 | + { |
552 | 555 | // Categories are special |
553 | 556 | return true; |
554 | 557 | } else { |
— | — | @@ -684,7 +687,7 @@ |
685 | 688 | $this->save = false; |
686 | 689 | $this->diff = false; |
687 | 690 | $this->minoredit = false; |
688 | | - $this->watchthis = false; |
| 691 | + $this->watchthis = $request->getBool( 'watchthis', false ); // Watch may be overriden by request parameters |
689 | 692 | $this->recreate = false; |
690 | 693 | |
691 | 694 | if ( $this->section == 'new' && $request->getVal( 'preloadtitle' ) ) { |
— | — | @@ -699,6 +702,9 @@ |
700 | 703 | } |
701 | 704 | } |
702 | 705 | |
| 706 | + $this->bot = $request->getBool( 'bot', true ); |
| 707 | + $this->nosummary = $request->getBool( 'nosummary' ); |
| 708 | + |
703 | 709 | // FIXME: unused variable? |
704 | 710 | $this->oldid = $request->getInt( 'oldid' ); |
705 | 711 | |
— | — | @@ -1174,8 +1180,22 @@ |
1175 | 1181 | * Called on the first invocation, e.g. when a user clicks an edit link |
1176 | 1182 | */ |
1177 | 1183 | function initialiseForm() { |
| 1184 | + global $wgUser; |
1178 | 1185 | $this->edittime = $this->mArticle->getTimestamp(); |
1179 | 1186 | $this->textbox1 = $this->getContent( false ); |
| 1187 | + // activate checkboxes if user wants them to be always active |
| 1188 | + # Sort out the "watch" checkbox |
| 1189 | + if ( $wgUser->getOption( 'watchdefault' ) ) { |
| 1190 | + # Watch all edits |
| 1191 | + $this->watchthis = true; |
| 1192 | + } elseif ( $wgUser->getOption( 'watchcreations' ) && !$this->mTitle->exists() ) { |
| 1193 | + # Watch creations |
| 1194 | + $this->watchthis = true; |
| 1195 | + } elseif ( $this->mTitle->userIsWatching() ) { |
| 1196 | + # Already watched |
| 1197 | + $this->watchthis = true; |
| 1198 | + } |
| 1199 | + if ( $wgUser->getOption( 'minordefault' ) ) $this->minoredit = true; |
1180 | 1200 | if ( $this->textbox1 === false ) return false; |
1181 | 1201 | wfProxyCheck(); |
1182 | 1202 | return true; |
— | — | @@ -1211,7 +1231,7 @@ |
1212 | 1232 | * near the top, for captchas and the like. |
1213 | 1233 | */ |
1214 | 1234 | function showEditForm( $formCallback=null ) { |
1215 | | - global $wgOut, $wgUser, $wgTitle, $wgRequest; |
| 1235 | + global $wgOut, $wgUser, $wgTitle; |
1216 | 1236 | |
1217 | 1237 | # If $wgTitle is null, that means we're in API mode. |
1218 | 1238 | # Some hook probably called this function without checking |
— | — | @@ -1240,7 +1260,7 @@ |
1241 | 1261 | # Enabled article-related sidebar, toplinks, etc. |
1242 | 1262 | $wgOut->setArticleRelated( true ); |
1243 | 1263 | |
1244 | | - if ( $this->editFormHeadInit() === false ) |
| 1264 | + if ( $this->showHeader() === false ) |
1245 | 1265 | return; |
1246 | 1266 | |
1247 | 1267 | $action = htmlspecialchars($this->getActionURL($wgTitle)); |
— | — | @@ -1253,28 +1273,6 @@ |
1254 | 1274 | } |
1255 | 1275 | |
1256 | 1276 | |
1257 | | - // activate checkboxes if user wants them to be always active |
1258 | | - if ( !$this->preview && !$this->diff ) { |
1259 | | - # Sort out the "watch" checkbox |
1260 | | - if ( $wgUser->getOption( 'watchdefault' ) ) { |
1261 | | - # Watch all edits |
1262 | | - $this->watchthis = true; |
1263 | | - } elseif ( $wgUser->getOption( 'watchcreations' ) && !$this->mTitle->exists() ) { |
1264 | | - # Watch creations |
1265 | | - $this->watchthis = true; |
1266 | | - } elseif ( $this->mTitle->userIsWatching() ) { |
1267 | | - # Already watched |
1268 | | - $this->watchthis = true; |
1269 | | - } |
1270 | | - |
1271 | | - # May be overriden by request parameters |
1272 | | - if( $wgRequest->getBool( 'watchthis' ) ) { |
1273 | | - $this->watchthis = true; |
1274 | | - } |
1275 | | - |
1276 | | - if ( $wgUser->getOption( 'minordefault' ) ) $this->minoredit = true; |
1277 | | - } |
1278 | | - |
1279 | 1277 | $wgOut->addHTML( $this->editFormPageTop ); |
1280 | 1278 | |
1281 | 1279 | if ( $wgUser->getOption( 'previewontop' ) ) { |
— | — | @@ -1333,7 +1331,7 @@ |
1334 | 1332 | # For a bit more sophisticated detection of blank summaries, hash the |
1335 | 1333 | # automatic one and pass that in the hidden field wpAutoSummary. |
1336 | 1334 | if ( $this->missingSummary || |
1337 | | - ( $this->section == 'new' && $wgRequest->getBool( 'nosummary' ) ) ) |
| 1335 | + ( $this->section == 'new' && $this->nosummary ) ) |
1338 | 1336 | $wgOut->addHTML( Xml::hidden( 'wpIgnoreBlankSummary', true ) ); |
1339 | 1337 | $autosumm = $this->autoSumm ? $this->autoSumm : md5( $this->summary ); |
1340 | 1338 | $wgOut->addHTML( Xml::hidden( 'wpAutoSummary', $autosumm ) ); |
— | — | @@ -1395,7 +1393,7 @@ |
1396 | 1394 | wfProfileOut( __METHOD__ ); |
1397 | 1395 | } |
1398 | 1396 | |
1399 | | - protected function editFormHeadInit() { |
| 1397 | + protected function showHeader() { |
1400 | 1398 | global $wgOut, $wgParser, $wgUser, $wgMaxArticleSize, $wgLang; |
1401 | 1399 | if ( $this->isConflict ) { |
1402 | 1400 | $wgOut->wrapWikiMsg( "<div class='mw-explainconflict'>\n$1</div>", 'explainconflict' ); |
— | — | @@ -1422,20 +1420,25 @@ |
1423 | 1421 | } |
1424 | 1422 | } |
1425 | 1423 | |
1426 | | - if ( $this->missingComment ) |
| 1424 | + if ( $this->missingComment ) { |
1427 | 1425 | $wgOut->wrapWikiMsg( '<div id="mw-missingcommenttext">$1</div>', 'missingcommenttext' ); |
| 1426 | + } |
1428 | 1427 | |
1429 | | - if ( $this->missingSummary && $this->section != 'new' ) |
| 1428 | + if ( $this->missingSummary && $this->section != 'new' ) { |
1430 | 1429 | $wgOut->wrapWikiMsg( '<div id="mw-missingsummary">$1</div>', 'missingsummary' ); |
| 1430 | + } |
1431 | 1431 | |
1432 | | - if ( $this->missingSummary && $this->section == 'new' ) |
| 1432 | + if ( $this->missingSummary && $this->section == 'new' ) { |
1433 | 1433 | $wgOut->wrapWikiMsg( '<div id="mw-missingcommentheader">$1</div>', 'missingcommentheader' ); |
| 1434 | + } |
1434 | 1435 | |
1435 | | - if ( $this->hookError !== '' ) |
| 1436 | + if ( $this->hookError !== '' ) { |
1436 | 1437 | $wgOut->addWikiText( $this->hookError ); |
| 1438 | + } |
1437 | 1439 | |
1438 | | - if ( !$this->checkUnicodeCompliantBrowser() ) |
| 1440 | + if ( !$this->checkUnicodeCompliantBrowser() ) { |
1439 | 1441 | $wgOut->addWikiMsg( 'nonunicodebrowser' ); |
| 1442 | + } |
1440 | 1443 | |
1441 | 1444 | if ( isset( $this->mArticle ) && isset( $this->mArticle->mRevision ) ) { |
1442 | 1445 | // Let sysop know that this will make private content public if saved |
— | — | @@ -1501,8 +1504,9 @@ |
1502 | 1505 | $wgOut->wrapWikiMsg( '<div class="mw-titleprotectedwarning">$1</div>', 'titleprotectedwarning' ); |
1503 | 1506 | } |
1504 | 1507 | |
1505 | | - if ( $this->kblength === false ) |
| 1508 | + if ( $this->kblength === false ) { |
1506 | 1509 | $this->kblength = (int)( strlen( $this->textbox1 ) / 1024 ); |
| 1510 | + } |
1507 | 1511 | |
1508 | 1512 | if ( $this->tooBig || $this->kblength > $wgMaxArticleSize ) { |
1509 | 1513 | $wgOut->addHTML( "<div class='error' id='mw-edit-longpageerror'>\n" ); |
— | — | @@ -1529,23 +1533,19 @@ |
1530 | 1534 | * |
1531 | 1535 | * @return array An array in the format array( $label, $input ) |
1532 | 1536 | */ |
1533 | | - function getSummaryInput($summary = "", $labelText = null, $userInputAttrs = null, $userSpanLabelAttrs = null) { |
1534 | | - $inputAttrs = array( |
| 1537 | + function getSummaryInput($summary = "", $labelText = null, $inputAttrs = null, $spanLabelAttrs = null) { |
| 1538 | + $inputAttrs = ( is_array($inputAttrs) ? $inputAttrs : array() ) + array( |
1535 | 1539 | 'id' => 'wpSummary', |
1536 | 1540 | 'maxlength' => '200', |
1537 | 1541 | 'tabindex' => '1', |
1538 | 1542 | 'size' => 60, |
1539 | 1543 | 'spellcheck' => 'true', |
1540 | | - 'onfocus' => "currentFocused = this;", // Make wpSummary insertable for editbuttons |
1541 | 1544 | ); |
1542 | | - if ( $userInputAttrs ) |
1543 | | - $inputAttrs += $userInputAttrs; |
1544 | | - $spanLabelAttrs = array( |
| 1545 | + |
| 1546 | + $spanLabelAttrs = ( is_array($spanLabelAttrs) ? $spanLabelAttrs : array() ) + array( |
1545 | 1547 | 'class' => $this->missingSummary ? 'mw-summarymissed' : 'mw-summary', |
1546 | 1548 | 'id' => "wpSummaryLabel" |
1547 | 1549 | ); |
1548 | | - if ( is_array($userSpanLabelAttrs) ) |
1549 | | - $spanLabelAttrs += $userSpanLabelAttrs; |
1550 | 1550 | |
1551 | 1551 | $label = null; |
1552 | 1552 | if ( $labelText ) { |
— | — | @@ -1566,11 +1566,11 @@ |
1567 | 1567 | * @return string |
1568 | 1568 | */ |
1569 | 1569 | protected function showSummaryInput( $isSubjectPreview, $summary = "" ) { |
1570 | | - global $wgOut, $wgContLang, $wgRequest; |
| 1570 | + global $wgOut, $wgContLang; |
1571 | 1571 | # Add a class if 'missingsummary' is triggered to allow styling of the summary line |
1572 | 1572 | $summaryClass = $this->missingSummary ? 'mw-summarymissed' : 'mw-summary'; |
1573 | 1573 | if ( $isSubjectPreview ) { |
1574 | | - if ( $wgRequest->getBool( 'nosummary' ) ) |
| 1574 | + if ( $this->nosummary ) |
1575 | 1575 | return; |
1576 | 1576 | } else { |
1577 | 1577 | if ( !$this->mShowSummaryField ) |
— | — | @@ -1710,7 +1710,6 @@ |
1711 | 1711 | 'id' => $name, |
1712 | 1712 | 'cols' => $wgUser->getIntOption( 'cols' ), |
1713 | 1713 | 'rows' => $wgUser->getIntOption( 'rows' ), |
1714 | | - 'onfocus' => "currentFocused = this;", // Make textareas insertable for editbuttons |
1715 | 1714 | 'style' => '' // avoid php notices when appending for editwidth preference (appending allows customAttribs['style'] to still work |
1716 | 1715 | ); |
1717 | 1716 | |
— | — | @@ -1999,7 +1998,7 @@ |
2000 | 1999 | * Call the stock "user is blocked" page |
2001 | 2000 | */ |
2002 | 2001 | function blockedPage() { |
2003 | | - global $wgOut, $wgUser; |
| 2002 | + global $wgOut; |
2004 | 2003 | $wgOut->blockedPage( false ); # Standard block notice on the top, don't 'return' |
2005 | 2004 | |
2006 | 2005 | # If the user made changes, preserve them when showing the markup |
— | — | @@ -2013,14 +2012,9 @@ |
2014 | 2013 | |
2015 | 2014 | # Spit out the source or the user's modified version |
2016 | 2015 | if ( $source !== false ) { |
2017 | | - $rows = $wgUser->getIntOption( 'rows' ); |
2018 | | - $cols = $wgUser->getIntOption( 'cols' ); |
2019 | | - $attribs = array( 'id' => 'wpTextbox1', 'name' => 'wpTextbox1', 'cols' => $cols, 'rows' => $rows, 'readonly' => 'readonly' ); |
2020 | 2016 | $wgOut->addHTML( '<hr />' ); |
2021 | 2017 | $wgOut->addWikiMsg( $first ? 'blockedoriginalsource' : 'blockededitsource', $this->mTitle->getPrefixedText() ); |
2022 | | - # Why we don't use Xml::element here? |
2023 | | - # Is it because if $source is '', it returns <textarea />? |
2024 | | - $wgOut->addHTML( Xml::openElement( 'textarea', $attribs ) . htmlspecialchars( $source ) . Xml::closeElement( 'textarea' ) ); |
| 2018 | + $this->showTextbox1( array( 'readonly' ), $source ); |
2025 | 2019 | } |
2026 | 2020 | } |
2027 | 2021 | |
— | — | @@ -2616,11 +2610,11 @@ |
2617 | 2611 | * @return bool false if output is done, true if the rest of the form should be displayed |
2618 | 2612 | */ |
2619 | 2613 | function attemptSave() { |
2620 | | - global $wgUser, $wgOut, $wgTitle, $wgRequest; |
| 2614 | + global $wgUser, $wgOut, $wgTitle; |
2621 | 2615 | |
2622 | 2616 | $resultDetails = false; |
2623 | 2617 | # Allow bots to exempt some edits from bot flagging |
2624 | | - $bot = $wgUser->isAllowed( 'bot' ) && $wgRequest->getBool( 'bot', true ); |
| 2618 | + $bot = $wgUser->isAllowed( 'bot' ) && $this->bot; |
2625 | 2619 | $value = $this->internalAttemptSave( $resultDetails, $bot ); |
2626 | 2620 | |
2627 | 2621 | if ( $value == self::AS_SUCCESS_UPDATE || $value == self::AS_SUCCESS_NEW_ARTICLE ) { |
Index: trunk/phase3/includes/DefaultSettings.php |
— | — | @@ -2162,6 +2162,15 @@ |
2163 | 2163 | NS_CATEGORY_TALK => true |
2164 | 2164 | ); |
2165 | 2165 | |
| 2166 | +/** |
| 2167 | + * Which namespaces have special treatment where they should be preview-on-open |
| 2168 | + * Internaly only Category: pages apply, but using this extensions (e.g. Semantic MediaWiki) |
| 2169 | + * can specify namespaces of pages they have special treatment for |
| 2170 | + */ |
| 2171 | +$wgPreviewOnOpenNamespaces = array( |
| 2172 | + NS_CATEGORY => true |
| 2173 | +); |
| 2174 | + |
2166 | 2175 | $wgNamespacesToBeSearchedDefault = array( |
2167 | 2176 | NS_MAIN => true, |
2168 | 2177 | ); |
Index: trunk/phase3/skins/common/edit.js |
— | — | @@ -46,9 +46,14 @@ |
47 | 47 | |
48 | 48 | // Don't generate buttons for browsers which don't fully |
49 | 49 | // support it. |
50 | | - var textbox = document.createElement('textarea'); // abstract, don't assume wpTextbox1 is always there |
| 50 | + // but don't assume wpTextbox1 is always here |
| 51 | + var textboxes = document.getElementsByTagName('textarea'); |
| 52 | + if ( !textboxes.length ) { |
| 53 | + // No toolbar if we can't find any textarea |
| 54 | + return false; |
| 55 | + } |
51 | 56 | if (!(document.selection && document.selection.createRange) |
52 | | - && textbox.selectionStart === null) { |
| 57 | + && textboxes[0].selectionStart === null) { |
53 | 58 | return false; |
54 | 59 | } |
55 | 60 | |
— | — | @@ -160,5 +165,35 @@ |
161 | 166 | hookEvent( 'load', mwSetupToolbar ); |
162 | 167 | hookEvent( 'load', function() { |
163 | 168 | currentFocused = document.getElementById( 'wpTextbox1' ); |
| 169 | + // http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html |
| 170 | + // focus does not bubble normally, but using a trick we can do event delegation |
| 171 | + // on the focus event on all text inputs to make the toolbox usable on all of them |
| 172 | + var editForm = document.getElementById( 'editform' ); |
| 173 | + if ( !editForm ) |
| 174 | + return; |
| 175 | + |
| 176 | + function onfocus(e) { |
| 177 | + var elm = e.target; |
| 178 | + if ( !elm ) |
| 179 | + return; |
| 180 | + var tagName = elm.tagName.toLowerCase(); |
| 181 | + var type = elm.type.toLowerCase(); |
| 182 | + if ( tagName !== "textarea" && tagName !== "input" ) |
| 183 | + return; |
| 184 | + if ( tagName === "input" && type && type !== "text" ) |
| 185 | + return; |
| 186 | + |
| 187 | + currentFocused = elm; |
| 188 | + } |
| 189 | + |
| 190 | + if ( editForm.addEventListener ) { |
| 191 | + // Gecko, WebKit, Opera, etc... (all standards compliant browsers) |
| 192 | + editForm.addEventListener('focus', onfocus, true); // This MUST be true to work |
| 193 | + } else if ( editForm.attachEvent ) { |
| 194 | + // IE needs a specific trick here since it doesn't support the standard |
| 195 | + editForm.attachEvent( 'onfocusin', function() { onfocus(event); }, handler ); |
| 196 | + } |
| 197 | + |
| 198 | + editForm |
164 | 199 | } ); |
165 | 200 | |