Index: trunk/extensions/InlineEditor/InlineEditor.class.php |
— | — | @@ -0,0 +1,401 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * InlineEditor base class, contains all the basic logic of the editor. |
| 5 | + * It handles hooks through static functions, and they can spawn an InlineEditor object using |
| 6 | + * an article object, and then render like a normal page, or as JSON. Reason for this is to be |
| 7 | + * able to pass this object to different hook functions. |
| 8 | + */ |
| 9 | +class InlineEditor { |
| 10 | + private static $fallbackReason; ///< reason for not using the editor, used for showing a message |
| 11 | + const REASON_BROWSER = 1; ///< reason is an incompatible browser |
| 12 | + const REASON_ADVANCED = 2; ///< reason is editing an 'advanced' page, whatever that may be |
| 13 | + |
| 14 | + private $article; ///< Article object to edit |
| 15 | + private $editModes; ///< array of different edit modes, see addEditMode() |
| 16 | + private $extendedEditPage; ///< ExtendedEditPage object we're using to handle editor logic |
| 17 | + |
| 18 | + /** |
| 19 | + * Main entry point, hooks into MediaWikiPerformAction. |
| 20 | + * Checks whether or not to spawn the editor, and does so if nessicary. |
| 21 | + */ |
| 22 | + public static function mediaWikiPerformAction( $output, $article, $title, $user, $request, $wiki ) { |
| 23 | + global $wgHooks; |
| 24 | + |
| 25 | + // the action of the page, i.e. 'view' or 'edit' |
| 26 | + $action = $wiki->getVal( 'Action' ); |
| 27 | + |
| 28 | + // check if the editor could be used on this page, and if so, hide the [edit] links |
| 29 | + if ( self::isValidBrowser() && !self::isAdvancedPage( $article, $title ) ) { |
| 30 | + self::hideEditSection( $output ); |
| 31 | + } |
| 32 | + |
| 33 | + // return if the action is not 'edit' or if it's disabled |
| 34 | + if( $action != 'edit' || in_array( $action, $wiki->getVal( 'DisabledActions', array() ) ) ) |
| 35 | + { |
| 36 | + return true; |
| 37 | + } |
| 38 | + |
| 39 | + // check if the 'fulleditor' parameter is set either in GET or POST |
| 40 | + if ( $request->getCheck( 'fulleditor' ) ) { |
| 41 | + // hook into the edit page to inject the hidden 'fulleditor' input field again |
| 42 | + $wgHooks['EditPage::showEditForm:fields'][] = 'InlineEditor::showEditFormFields'; |
| 43 | + return true; |
| 44 | + } |
| 45 | + |
| 46 | + // terminate if the browser is not supported |
| 47 | + if( !self::isValidBrowser() ) { |
| 48 | + self::$fallbackReason = self::REASON_BROWSER; |
| 49 | + return true; |
| 50 | + } |
| 51 | + |
| 52 | + // terminate if we consider this page 'advanced' |
| 53 | + if( self::isAdvancedPage( $article, $title ) ) { |
| 54 | + self::$fallbackReason = self::REASON_ADVANCED; |
| 55 | + return true; |
| 56 | + } |
| 57 | + |
| 58 | + // start the session if needed |
| 59 | + if( session_id() == '' ) { |
| 60 | + wfSetupSession(); |
| 61 | + } |
| 62 | + |
| 63 | + // try to spawn the editor and render the page |
| 64 | + $editor = new InlineEditor( $article ); |
| 65 | + if( $editor->render( $output ) ) { |
| 66 | + return false; |
| 67 | + } |
| 68 | + else { |
| 69 | + // if rendering fails for some reason, terminate and show the advanced page notice |
| 70 | + self::$fallbackReason = self::REASON_ADVANCED; |
| 71 | + return true; |
| 72 | + } |
| 73 | + } |
| 74 | + |
| 75 | + /** |
| 76 | + * Hooks into EditPage::showEditForm:initial. Shows a message if there is a fallback reason set. |
| 77 | + * @param $editPage EditPage |
| 78 | + */ |
| 79 | + public static function showEditForm( &$editPage ) { |
| 80 | + global $wgExtensionAssetsPath, $wgOut, $wgRequest; |
| 81 | + |
| 82 | + // check for a fallback reason |
| 83 | + if( isset( self::$fallbackReason ) ) { |
| 84 | + // add the style for fallback message |
| 85 | + $wgOut->addExtensionStyle( $wgExtensionAssetsPath . "/InlineEditor/EditForm.css?0" ); |
| 86 | + |
| 87 | + // show the appropriate message at the top of the page |
| 88 | + switch( self::$fallbackReason ) { |
| 89 | + case self::REASON_BROWSER: |
| 90 | + self::prependFallbackMessage( wfMsgExt( 'inline-editor-redirect-browser', 'parseinline' ) ); |
| 91 | + break; |
| 92 | + case self::REASON_ADVANCED: |
| 93 | + self::prependFallbackMessage( wfMsgExt( 'inline-editor-redirect-advanced', 'parseinline' ) ); |
| 94 | + break; |
| 95 | + } |
| 96 | + } |
| 97 | + |
| 98 | + return true; |
| 99 | + } |
| 100 | + |
| 101 | + /** |
| 102 | + * Prepends a fallback message at the top of the page. |
| 103 | + * @param $html String with correct HTML |
| 104 | + */ |
| 105 | + private static function prependFallbackMessage( $html ) { |
| 106 | + global $wgOut; |
| 107 | + $wgOut->prependHTML( '<div class="inlineEditorMessage">' . $html . '</div>'); |
| 108 | + } |
| 109 | + |
| 110 | + /** |
| 111 | + * Checks if the browser is supported. |
| 112 | + * This function is borrowed from EditPage::checkUnicodeCompliantBrowser(). |
| 113 | + */ |
| 114 | + private static function isValidBrowser() { |
| 115 | + global $wgInlineEditorBrowserBlacklist; |
| 116 | + if ( empty( $_SERVER["HTTP_USER_AGENT"] ) ) { |
| 117 | + // No User-Agent header sent? Trust it by default... |
| 118 | + return true; |
| 119 | + } |
| 120 | + $currentbrowser = $_SERVER["HTTP_USER_AGENT"]; |
| 121 | + foreach ( $wgInlineEditorBrowserBlacklist as $browser ) { |
| 122 | + if ( preg_match($browser, $currentbrowser) ) { |
| 123 | + return false; |
| 124 | + } |
| 125 | + } |
| 126 | + return true; |
| 127 | + } |
| 128 | + |
| 129 | + /** |
| 130 | + * Check if the page is 'advanced'. For now, that means it has to be in an allowed namespace. |
| 131 | + * @param $article Article |
| 132 | + * @param $title Title |
| 133 | + * @return boolean |
| 134 | + */ |
| 135 | + private static function isAdvancedPage( &$article, &$title ) { |
| 136 | + global $wgInlineEditorAllowedNamespaces; |
| 137 | + if( !empty( $wgInlineEditorAllowedNamespaces ) |
| 138 | + && !in_array( $title->getNamespace(), $wgInlineEditorAllowedNamespaces ) ) { |
| 139 | + return true; |
| 140 | + } |
| 141 | + return false; |
| 142 | + } |
| 143 | + |
| 144 | + /** |
| 145 | + * Entry point for the 'Preview' function through Ajax. |
| 146 | + * No real point in securing this, as nothing is actually saved. |
| 147 | + * @param $json String JSON object from the client |
| 148 | + * @param $pageName String The page we're editing |
| 149 | + * @return String HTML |
| 150 | + */ |
| 151 | + public static function ajaxPreview( $json, $pageName ) { |
| 152 | + $title = Title::newFromText( $pageName ); |
| 153 | + $article = Article::newFromId( $title->getArticleId() ); |
| 154 | + |
| 155 | + $editor = new InlineEditor( $article ); |
| 156 | + return $editor->preview( $json ); |
| 157 | + } |
| 158 | + |
| 159 | + /** |
| 160 | + * Hide the [edit] links on the page by enabling a piece of CSS (instead of screwing with the parser cache). |
| 161 | + * @param $output OutputPage |
| 162 | + */ |
| 163 | + public static function hideEditSection( &$output ) { |
| 164 | + global $wgExtensionAssetsPath; |
| 165 | + $output->addExtensionStyle( $wgExtensionAssetsPath . "/InlineEditor/HideEditSection.css?0" ); |
| 166 | + } |
| 167 | + |
| 168 | + /** |
| 169 | + * Add a 'fulleditor' hidden input field to the normal edit page |
| 170 | + * @param $editpage EditPage |
| 171 | + * @param $output OutputPage |
| 172 | + */ |
| 173 | + public static function showEditFormFields( &$editpage, &$output ) { |
| 174 | + $output->addHTML( |
| 175 | + HTML::rawElement( 'input', array( 'name' => 'fulleditor', 'type' => 'hidden', 'value' => '1' )) |
| 176 | + ); |
| 177 | + return true; |
| 178 | + } |
| 179 | + |
| 180 | + /** |
| 181 | + * Constructor which takes only an Article object |
| 182 | + * @param $article Article |
| 183 | + */ |
| 184 | + public function __construct( $article ) { |
| 185 | + $this->article = $article; |
| 186 | + $editmodes = array(); |
| 187 | + } |
| 188 | + |
| 189 | + /** |
| 190 | + * Render the editor. |
| 191 | + * Spawns an ExtendedEditPage which is an EditPage with some specific logic for this editor. |
| 192 | + * This is supplied with wikitext generated using InlineEditorText, from the posted JSON. |
| 193 | + * If the page is being saved, the ExtendedEditPage will terminate the script itself, else |
| 194 | + * the editing interface will show as usual. |
| 195 | + * @param $output OutputPage |
| 196 | + */ |
| 197 | + public function render( &$output ) { |
| 198 | + global $wgParser, $wgHooks, $wgRequest, $wgExtensionAssetsPath; |
| 199 | + |
| 200 | + // create an InlineEditorText object which generates the HTML and JSON for the editor |
| 201 | + $text = new InlineEditorText( $this->article ); |
| 202 | + |
| 203 | + // if the page is being saved, retrieve the wikitext from the JSON |
| 204 | + if( $wgRequest->wasPosted() ) { |
| 205 | + $text->loadFromJson( $wgRequest->getVal( 'json' ) ); |
| 206 | + $wgRequest->setVal( 'wpTextbox1', $text->getWikiOriginal() ); |
| 207 | + } |
| 208 | + |
| 209 | + // try to init, or else return false, which will spawn an 'advanced page' notice |
| 210 | + $this->extendedEditPage = new ExtendedEditPage( $this->article ); |
| 211 | + if( $this->extendedEditPage->initInlineEditor() ) { |
| 212 | + // IMPORTANT: if the page was being saved, the script has been terminated by now!! |
| 213 | + |
| 214 | + // include the required JS and CSS files |
| 215 | + $output->includeJQuery(); |
| 216 | + $output->addScriptFile( $wgExtensionAssetsPath . "/InlineEditor/jquery.inlineEditor.js?0" ); |
| 217 | + $output->addScriptFile( $wgExtensionAssetsPath . "/InlineEditor/jquery.inlineEditor.basicEditor.js?0" ); |
| 218 | + $output->addScriptFile( $wgExtensionAssetsPath . "/InlineEditor/jquery-ui-effects-1.8.4.min.js?0" ); |
| 219 | + $output->addExtensionStyle( $wgExtensionAssetsPath . "/InlineEditor/InlineEditor.css?0" ); |
| 220 | + |
| 221 | + // have the different kind of editors register themselves |
| 222 | + wfRunHooks( 'InlineEditorDefineEditors', array( &$this, &$output ) ); |
| 223 | + |
| 224 | + // load the wikitext into the InlineEditorText object |
| 225 | + $text->loadFromWikiText( $this->extendedEditPage->getWikiText() ); |
| 226 | + |
| 227 | + // add a large <div> around the marked wikitext to denote the editing position |
| 228 | + $parserOutput = $text->getParserOutputMarked(); |
| 229 | + $parserOutput->setText( '<div id="editContent">' . $parserOutput->getText() . '</div>' ); |
| 230 | + |
| 231 | + // put the marked output into the page |
| 232 | + $output->addParserOutput( $parserOutput ); |
| 233 | + |
| 234 | + // add the different edit modes and initial JSON state in Javascript, and finally init the editor |
| 235 | + $output->addInlineScript( |
| 236 | + 'jQuery( document ).ready( function() { |
| 237 | + jQuery.inlineEditor.editModes = ["' . implode( '","', array_keys( $this->editModes ) ) . '"]; |
| 238 | + jQuery.inlineEditor.currentMode = "' . reset( $this->editModes ) . '"; |
| 239 | + jQuery.inlineEditor.addInitialState( ' . $text->getWikiJson() . ' ); |
| 240 | + jQuery.inlineEditor.init(); |
| 241 | + } );' |
| 242 | + ); |
| 243 | + |
| 244 | + // hook into SiteNoticeBefore to display the two boxes above the title |
| 245 | + // @todo: fix this in core, make sure that anything can be inserted above the title, outside #siteNotice |
| 246 | + $wgHooks['SiteNoticeBefore'][] = array( $this, 'siteNoticeBefore' ); |
| 247 | + return true; |
| 248 | + } |
| 249 | + else { |
| 250 | + return false; |
| 251 | + } |
| 252 | + } |
| 253 | + |
| 254 | + /** |
| 255 | + * Get the Article being edited |
| 256 | + * @return Article |
| 257 | + */ |
| 258 | + public function getArticle() { |
| 259 | + return $this->article; |
| 260 | + } |
| 261 | + |
| 262 | + /** |
| 263 | + * Pass JSON into an InlineEditorText object and return combined JSON (HTML + sentence representation) |
| 264 | + * @param $json String |
| 265 | + * @return String |
| 266 | + */ |
| 267 | + public function preview ( $json ) { |
| 268 | + $text = new InlineEditorText( $this->article ); |
| 269 | + $text->loadFromJson( $json ); |
| 270 | + return $text->getCombinedJson(); |
| 271 | + } |
| 272 | + |
| 273 | + /** |
| 274 | + * Hooks into SiteNoticeBefore. Renders the edit interface above the title of the page. |
| 275 | + * @param $siteNotice String |
| 276 | + */ |
| 277 | + public function siteNoticeBefore( &$siteNotice ) { |
| 278 | + $siteNotice = $this->renderEditBox() . $this->renderEditModes(); |
| 279 | + return false; |
| 280 | + } |
| 281 | + |
| 282 | + /** |
| 283 | + * Add an edit mode to the list. |
| 284 | + * @param $name String Name to be used in id-fields |
| 285 | + * @param $caption String Name to be displayed |
| 286 | + * @param $description String Description to be displayed when the mode is selected (*escaped* HTML only!) |
| 287 | + */ |
| 288 | + public function addEditMode($name, $caption, $description) { |
| 289 | + $this->editModes[$name] = array( |
| 290 | + 'radioid' => 'radio-' . $name, |
| 291 | + 'descriptionid' => 'description-' . $name, |
| 292 | + 'caption' => $caption, |
| 293 | + 'description' => $description |
| 294 | + ); |
| 295 | + } |
| 296 | + |
| 297 | + /** |
| 298 | + * Generates "Edit box" (the first one) |
| 299 | + * This looks like this: |
| 300 | + * <div class="editbox"> |
| 301 | + * inline-editor-editbox-top |
| 302 | + * <hr/> |
| 303 | + * |
| 304 | + * inline-editor-editbox-changes-question |
| 305 | + * <input class="summary" name="summary" /> |
| 306 | + * <div class="example">inline-editor-editbox-changes-example</div> |
| 307 | + * <hr/> |
| 308 | + * |
| 309 | + * <div class="side"> |
| 310 | + * inline-editor-editbox-publish-notice |
| 311 | + * <div class="terms">inline-editor-editbox-publish-terms</div> |
| 312 | + * </div> |
| 313 | + * <a id="publish">inline-editor-editbox-publish-caption</a></div> |
| 314 | + * @return string HTML |
| 315 | + */ |
| 316 | + private function renderEditBox() { |
| 317 | + $top = wfMsgExt( 'inline-editor-editbox-top', 'parseinline' ); |
| 318 | + $top .= '<hr/>'; |
| 319 | + |
| 320 | + $summary = wfMsgExt( 'inline-editor-editbox-changes-question', 'parseinline' ); |
| 321 | + $summary .= Html::input( 'wpSummary', $this->extendedEditPage->getSummary(), |
| 322 | + 'text', array( 'class' => 'summary', 'maxlength' => 250 ) ); |
| 323 | + $summary .= Html::rawElement( 'div', array( 'class' => 'example' ), |
| 324 | + wfMsgExt( 'inline-editor-editbox-changes-example', 'parseinline' ) ); |
| 325 | + $summary .= '<hr/>'; |
| 326 | + |
| 327 | + $terms = Html::rawElement( 'div', array( 'class' => 'terms' ), |
| 328 | + wfMsgExt( 'inline-editor-editbox-publish-terms', 'parseinline', '[[' . wfMsgForContent( 'copyrightpage' ) . ']]' ) ); |
| 329 | + $publish = Html::rawElement( 'div', array( 'class' => 'side' ), |
| 330 | + wfMsgExt( 'inline-editor-editbox-publish-notice', 'parseinline' ) . $terms ); |
| 331 | + $publish .= Html::rawElement( 'a', array( 'id' => 'publish', 'href' => '#' ), |
| 332 | + wfMsgExt( 'inline-editor-editbox-publish-caption', 'parseinline' ) ); |
| 333 | + $publish .= HTML::rawElement( 'input', array( 'id' => 'json', 'name' => 'json', 'type' => 'hidden' )); |
| 334 | + |
| 335 | + $form = Html::rawElement( 'form', array( |
| 336 | + 'id' => 'editForm', |
| 337 | + 'method' => 'POST', |
| 338 | + 'action' => $this->extendedEditPage->getSubmitUrl() ), $top . $summary . $publish ); |
| 339 | + |
| 340 | + |
| 341 | + return Html::rawElement( 'div', array( 'class' => 'editbox' ), $form ); |
| 342 | + } |
| 343 | + |
| 344 | + /** |
| 345 | + * Generates "Edit mode" box (the second one) |
| 346 | + * This looks like this: |
| 347 | + * <div class="editmode"> |
| 348 | + * <div class="header"> |
| 349 | + * <div class="radio title">Edit mode: <!-- inline-editor-editmodes-caption --></div> |
| 350 | + * <div class="radio"><!-- radio button + label --></div> |
| 351 | + * <div class="radio"><!-- radio button + label --></div> |
| 352 | + * <!-- for every edit mode one button --> |
| 353 | + * <!-- and finally undo and redo buttons (with class 'button') --> |
| 354 | + * </div> |
| 355 | + * <div class="descriptionOuter"> |
| 356 | + * <div class="descriptionInner" id="description-text"> |
| 357 | + * <!-- for every edit mode a description --> |
| 358 | + * </div> |
| 359 | + * </div> |
| 360 | + * @return string HTML |
| 361 | + */ |
| 362 | + private function renderEditModes() { |
| 363 | + if (!isset($this->editModes)) return ''; |
| 364 | + |
| 365 | + $header = Html::rawElement( 'div', array( 'class' => 'radio title' ), |
| 366 | + wfMsgExt( 'inline-editor-editmodes-caption', 'parseinline' ) ); |
| 367 | + |
| 368 | + $descriptions = ''; |
| 369 | + $first = true; |
| 370 | + foreach( $this->editModes as $editmode ) { |
| 371 | + $inputOptions = array( 'id' => $editmode['radioid'], 'class' => 'optionMode' ); |
| 372 | + if ($first) { |
| 373 | + $inputOptions['checked'] = 'checked'; |
| 374 | + $first = false; |
| 375 | + } |
| 376 | + $input = Html::input( 'optionMode', '', 'radio', $inputOptions ); |
| 377 | + $label = Html::rawElement('label', array( 'for' => $editmode['radioid'] ), $editmode['caption'] ); |
| 378 | + |
| 379 | + $header .= Html::rawElement( 'div', array( 'class' => 'radio' ), $input . $label ); |
| 380 | + |
| 381 | + $descriptions .= Html::rawElement('div', array( 'class' => 'descriptionInner', 'id' => $editmode['descriptionid']), |
| 382 | + $editmode['description'] ); |
| 383 | + } |
| 384 | + |
| 385 | + $header .= Html::rawElement( 'div', array( 'class' => 'button' ), |
| 386 | + Html::rawElement( 'a', array( 'id' => 'redo', 'href' => '#' ), |
| 387 | + wfMsgExt( 'inline-editor-editmodes-redo', 'parseinline' ) ) |
| 388 | + ); |
| 389 | + $header .= Html::rawElement( 'div', array( 'class' => 'button' ), |
| 390 | + Html::rawElement( 'a', array( 'id' => 'undo', 'href' => '#' ), |
| 391 | + wfMsgExt( 'inline-editor-editmodes-undo', 'parseinline' ) ) |
| 392 | + ); |
| 393 | + $header .= Html::rawElement( 'div', array( 'class' => 'button' ), |
| 394 | + Html::rawElement( 'div', array( 'id' => 'editCounter', 'href' => '#' ), '#0' ) |
| 395 | + ); |
| 396 | + |
| 397 | + return Html::rawElement( 'div', array( 'class' => 'editmode' ), |
| 398 | + Html::rawElement( 'div', array( 'class' => 'header' ), $header ) |
| 399 | + . Html::rawElement( 'div', array( 'class' => 'descriptionOuter' ), $descriptions ) |
| 400 | + ); |
| 401 | + } |
| 402 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/InlineEditor.class.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 403 | + native |
Index: trunk/extensions/InlineEditor/ListEditor/ListEditor.i18n.php |
— | — | @@ -0,0 +1,43 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Internationalisation file for extension ListEditor. |
| 5 | + * |
| 6 | + * @file |
| 7 | + * @ingroup Extensions |
| 8 | + */ |
| 9 | + |
| 10 | +$messages = array(); |
| 11 | + |
| 12 | +/** English |
| 13 | + * @author Jan Paul Posma |
| 14 | + */ |
| 15 | +$messages['en'] = array( |
| 16 | + 'list-editor-desc' => 'Adds the "Lists" edit mode for the InlineEditor', |
| 17 | + |
| 18 | + 'list-editor-editmode-caption' => "Lists", |
| 19 | + 'list-editor-editmode-description' => " |
| 20 | +Lists work like shown below. |
| 21 | +You can also make a new list by going in any other mode, like the '''Text''' mode, |
| 22 | +and add a list like the one below. |
| 23 | + |
| 24 | +{| width=\"100%\" style=\"background-color: inherit\" |
| 25 | +! Code |
| 26 | +! Output |
| 27 | +|- |
| 28 | +| |
| 29 | +<code><nowiki>* Lists are easy to do:</nowiki></code><br/> |
| 30 | +<code><nowiki>** start every line</nowiki></code><br/> |
| 31 | +<code><nowiki>* with a star</nowiki></code><br/> |
| 32 | +<code><nowiki>** more stars mean</nowiki></code><br/> |
| 33 | +<code><nowiki>*** deeper levels</nowiki></code><br/> |
| 34 | +| |
| 35 | +* Lists are easy to do: |
| 36 | +** start every line |
| 37 | +* with a star |
| 38 | +** more stars mean |
| 39 | +*** deeper levels |
| 40 | +|} |
| 41 | + |
| 42 | +[http://meta.wikimedia.org/wiki/Help:List More information] |
| 43 | + ", |
| 44 | +); |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/ListEditor/ListEditor.i18n.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 45 | + native |
Index: trunk/extensions/InlineEditor/ListEditor/jquery.inlineEditor.editors.listEditor.js |
— | — | @@ -0,0 +1,40 @@ |
| 2 | +/** |
| 3 | + * Client side part of the ListEditor. |
| 4 | + */ |
| 5 | +( function( $ ) { $.inlineEditor.editors.listEditor = { |
| 6 | + |
| 7 | +click: function(event) { |
| 8 | + // prevent clicks from reaching other elements |
| 9 | + event.stopPropagation(); |
| 10 | + event.preventDefault(); |
| 11 | + |
| 12 | + // find the element and retrieve the corresponding wikitext |
| 13 | + var $field = $(this); |
| 14 | + var wiki = $.inlineEditor.getTextById( $field.attr( 'id' ) ); |
| 15 | + |
| 16 | + $newField = $.inlineEditor.basicEditor.newField( $field, $.inlineEditor.editors.listEditor.click ); |
| 17 | + $.inlineEditor.basicEditor.addEditBar( $newField, 500, wiki ); |
| 18 | +}, |
| 19 | + |
| 20 | +enable: function() { |
| 21 | + // do what we also do when reloading the page |
| 22 | + $.inlineEditor.editors.listEditor.reload(); |
| 23 | + |
| 24 | + // add the identifying class to #editContent |
| 25 | + $( '#editContent' ).addClass( 'listEditor' ); |
| 26 | +}, |
| 27 | + |
| 28 | +reload: function() { |
| 29 | + // make lists clickable |
| 30 | + $( '.listEditorElement' ).click( $.inlineEditor.editors.listEditor.click ); |
| 31 | +}, |
| 32 | + |
| 33 | +disable: function() { |
| 34 | + // remove the click event from the lists |
| 35 | + $( '.listEditorElement' ).unbind( 'click' ); |
| 36 | + |
| 37 | + // remove the identifying class from #editContent |
| 38 | + $( '#editContent' ).removeClass( 'listEditor' ); |
| 39 | +} |
| 40 | + |
| 41 | +}; } ) ( jQuery ); |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/ListEditor/jquery.inlineEditor.editors.listEditor.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 42 | + native |
Index: trunk/extensions/InlineEditor/ListEditor/ListEditor.php |
— | — | @@ -0,0 +1,41 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * ListEditor extension for the InlineEditor. |
| 5 | + * |
| 6 | + * @file |
| 7 | + * @ingroup Extensions |
| 8 | + * |
| 9 | + * This is the include file for the ListEditor. |
| 10 | + * |
| 11 | + * Usage: Include the following line in your LocalSettings.php |
| 12 | + * require_once( "$IP/extensions/InlineEditor/ListEditor/ListEditor.php" ); |
| 13 | + * |
| 14 | + * @author Jan Paul Posma <jp.posma@gmail.com> |
| 15 | + * @license GPL v2 or later |
| 16 | + * @version 0.0.0 |
| 17 | + */ |
| 18 | + |
| 19 | +if ( !defined( 'MEDIAWIKI' ) ) die(); |
| 20 | + |
| 21 | +// credits |
| 22 | +$wgExtensionCredits['other'][] = array( |
| 23 | + 'path' => __FILE__, |
| 24 | + 'name' => 'ListEditor', |
| 25 | + 'author' => array( 'Jan Paul Posma' ), |
| 26 | + 'version' => '0.1.0', |
| 27 | + 'url' => 'http://www.mediawiki.org/wiki/Extension:InlineEditor#ListEditor', |
| 28 | + 'descriptionmsg' => 'list-editor-desc', |
| 29 | +); |
| 30 | + |
| 31 | +// current directory including trailing slash |
| 32 | +$dir = dirname( __FILE__ ) . '/'; |
| 33 | + |
| 34 | +// add autoload classes |
| 35 | +$wgAutoloadClasses['ListEditor'] = $dir . 'ListEditor.class.php'; |
| 36 | + |
| 37 | +// register hooks |
| 38 | +$wgHooks['InlineEditorMark'][] = 'ListEditor::mark'; |
| 39 | +$wgHooks['InlineEditorDefineEditors'][] = 'ListEditor::defineEditors'; |
| 40 | + |
| 41 | +// i18n messages |
| 42 | +$wgExtensionMessagesFiles['ListEditor'] = $dir . 'ListEditor.i18n.php'; |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/ListEditor/ListEditor.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 43 | + native |
Index: trunk/extensions/InlineEditor/ListEditor/ListEditor.css |
— | — | @@ -0,0 +1,32 @@ |
| 2 | +.listEditor .listEditorElement { |
| 3 | + /* soft-blue background color to highlight editable lists */ |
| 4 | + background-color: #E4F0F9; |
| 5 | + |
| 6 | + /* create a hand cursor, cross-browser hack: http://www.quirksmode.org/css/cursor.html */ |
| 7 | + cursor: pointer; |
| 8 | + cursor: hand; |
| 9 | +} |
| 10 | + |
| 11 | +.listEditor .listEditorElement:hover { |
| 12 | + /* indicate the list to be edited with a darker color */ |
| 13 | + background-color: #a7d7f9; |
| 14 | +} |
| 15 | + |
| 16 | +.listEditor .editing { |
| 17 | + /* keeping the custom padding and margin breaks in Webkit browsers */ |
| 18 | + padding: 0px; |
| 19 | + margin: 0px; |
| 20 | + |
| 21 | + /* reset the cursor when editing */ |
| 22 | + cursor: auto; |
| 23 | +} |
| 24 | + |
| 25 | +.listEditor .edited { |
| 26 | + /* have a yellow color to highlight edited elements, basically the orange color with the hue shifted */ |
| 27 | + background-color: #F9F2A7; |
| 28 | +} |
| 29 | + |
| 30 | +.listEditor .lastEdit { |
| 31 | + /* have an orange color, the exact complement of the hover color, for highlighting on preview/cancel */ |
| 32 | + background-color: #f9c9a7; |
| 33 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/ListEditor/ListEditor.css |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 34 | + native |
Index: trunk/extensions/InlineEditor/ListEditor/ListEditor.class.php |
— | — | @@ -0,0 +1,50 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Simple editor for lists. |
| 5 | + */ |
| 6 | +class ListEditor { |
| 7 | + |
| 8 | + /** |
| 9 | + * This function hooks into InlineEditorMark and marks the media. |
| 10 | + * @param $inlineEditorText InlineEditorText |
| 11 | + */ |
| 12 | + public static function mark( &$inlineEditorText ) { |
| 13 | + // get the original wikitext |
| 14 | + $text = $inlineEditorText->getWikiOriginal(); |
| 15 | + |
| 16 | + $matches = array(); |
| 17 | + preg_match_all( '/(\n|^)(([*#;:].*(\n|$))+)/', $text, $matches, PREG_OFFSET_CAPTURE ); |
| 18 | + |
| 19 | + foreach( $matches[2] as $match ) { |
| 20 | + $start = $match[1]; |
| 21 | + $end = $start + strlen( $match[0] ); |
| 22 | + |
| 23 | + // do not include the trailing newline |
| 24 | + if( substr( $match[0], -1) == "\n" ) $end--; |
| 25 | + |
| 26 | + $inlineEditorText->addPiece( new InlineEditorPiece( $start, $end, 'listEditorElement', false ) ); |
| 27 | + } |
| 28 | + |
| 29 | + return true; |
| 30 | + } |
| 31 | + |
| 32 | + /** |
| 33 | + * Hooks into InlineEditorDefineEditors. Adds the option to to the list and adds CSS and JS files |
| 34 | + * @param $editor InlineEditor |
| 35 | + * @param $output OutputPage |
| 36 | + */ |
| 37 | + public static function defineEditors( &$editor, &$output ) { |
| 38 | + global $wgExtensionAssetsPath; |
| 39 | + |
| 40 | + $editor->addEditMode( |
| 41 | + 'listEditor', |
| 42 | + wfMsgExt( 'list-editor-editmode-caption', 'parseinline' ), |
| 43 | + wfMsgExt( 'list-editor-editmode-description','parseinline' ) |
| 44 | + ); |
| 45 | + |
| 46 | + $output->addExtensionStyle( "$wgExtensionAssetsPath/InlineEditor/ListEditor/ListEditor.css?0"); |
| 47 | + $output->addScriptFile( "$wgExtensionAssetsPath/InlineEditor/ListEditor/jquery.inlineEditor.editors.listEditor.js?0" ); |
| 48 | + |
| 49 | + return true; |
| 50 | + } |
| 51 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/ListEditor/ListEditor.class.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 52 | + native |
Index: trunk/extensions/InlineEditor/TemplateEditor/TemplateEditor.i18n.php |
— | — | @@ -0,0 +1,25 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Internationalisation file for extension TemplateEditor. |
| 5 | + * |
| 6 | + * @file |
| 7 | + * @ingroup Extensions |
| 8 | + */ |
| 9 | + |
| 10 | +$messages = array(); |
| 11 | + |
| 12 | +/** English |
| 13 | + * @author Jan Paul Posma |
| 14 | + */ |
| 15 | +$messages['en'] = array( |
| 16 | + 'template-editor-desc' => 'Adds the "Template" edit mode for the InlineEditor', |
| 17 | + |
| 18 | + 'template-editor-editmode-caption' => "Templates", |
| 19 | + 'template-editor-editmode-description' => " |
| 20 | +Templates are used to show the same thing on multiple pages. |
| 21 | +To fully understand templates, you should read documentation |
| 22 | +found online. |
| 23 | + |
| 24 | +[http://www.mediawiki.org/wiki/Help:Templates More information] |
| 25 | +", |
| 26 | +); |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/TemplateEditor/TemplateEditor.i18n.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 27 | + native |
Index: trunk/extensions/InlineEditor/TemplateEditor/jquery.inlineEditor.editors.templateEditor.js |
— | — | @@ -0,0 +1,41 @@ |
| 2 | +/** |
| 3 | + * Client side part of the TemplateEditor. |
| 4 | + */ |
| 5 | +( function( $ ) { $.inlineEditor.editors.templateEditor = { |
| 6 | + |
| 7 | +click: function(event) { |
| 8 | + // prevent clicks from reaching other elements |
| 9 | + event.stopPropagation(); |
| 10 | + event.preventDefault(); |
| 11 | + |
| 12 | + // find the element and retrieve the corresponding wikitext |
| 13 | + var $field = $(this); |
| 14 | + var wiki = $.inlineEditor.getTextById( $field.attr( 'id' ) ); |
| 15 | + |
| 16 | + $newField = $.inlineEditor.basicEditor.newField( $field, $.inlineEditor.editors.templateEditor.click ); |
| 17 | + $newField.removeClass( 'templateEditorElementNotEditing' ); |
| 18 | + $.inlineEditor.basicEditor.addEditBar( $newField, 700, wiki ); |
| 19 | +}, |
| 20 | + |
| 21 | +enable: function() { |
| 22 | + // do what we also do when reloading the page |
| 23 | + $.inlineEditor.editors.templateEditor.reload(); |
| 24 | + |
| 25 | + // add the identifying class to #editContent |
| 26 | + $( '#editContent' ).addClass( 'templateEditor' ); |
| 27 | +}, |
| 28 | + |
| 29 | +reload: function() { |
| 30 | + // make templates clickable |
| 31 | + $( '.templateEditorElement' ).click( $.inlineEditor.editors.templateEditor.click ); |
| 32 | +}, |
| 33 | + |
| 34 | +disable: function() { |
| 35 | + // remove the click event from the templates |
| 36 | + $( '.templateEditorElement' ).unbind( 'click' ); |
| 37 | + |
| 38 | + // remove the identifying class from #editContent |
| 39 | + $( '#editContent' ).removeClass( 'templateEditor' ); |
| 40 | +} |
| 41 | + |
| 42 | +}; } ) ( jQuery ); |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/TemplateEditor/jquery.inlineEditor.editors.templateEditor.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 43 | + native |
Index: trunk/extensions/InlineEditor/TemplateEditor/TemplateEditor.php |
— | — | @@ -0,0 +1,41 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * TemplateEditor extension for the InlineEditor. |
| 5 | + * |
| 6 | + * @file |
| 7 | + * @ingroup Extensions |
| 8 | + * |
| 9 | + * This is the include file for the TemplateEditor. |
| 10 | + * |
| 11 | + * Usage: Include the following line in your LocalSettings.php |
| 12 | + * require_once( "$IP/extensions/InlineEditor/TemplateEditor/TemplateEditor.php" ); |
| 13 | + * |
| 14 | + * @author Jan Paul Posma <jp.posma@gmail.com> |
| 15 | + * @license GPL v2 or later |
| 16 | + * @version 0.0.0 |
| 17 | + */ |
| 18 | + |
| 19 | +if ( !defined( 'MEDIAWIKI' ) ) die(); |
| 20 | + |
| 21 | +// credits |
| 22 | +$wgExtensionCredits['other'][] = array( |
| 23 | + 'path' => __FILE__, |
| 24 | + 'name' => 'TemplateEditor', |
| 25 | + 'author' => array( 'Jan Paul Posma' ), |
| 26 | + 'version' => '0.1.0', |
| 27 | + 'url' => 'http://www.mediawiki.org/wiki/Extension:InlineEditor#TemplateEditor', |
| 28 | + 'descriptionmsg' => 'template-editor-desc', |
| 29 | +); |
| 30 | + |
| 31 | +// current directory including trailing slash |
| 32 | +$dir = dirname( __FILE__ ) . '/'; |
| 33 | + |
| 34 | +// add autoload classes |
| 35 | +$wgAutoloadClasses['TemplateEditor'] = $dir . 'TemplateEditor.class.php'; |
| 36 | + |
| 37 | +// register hooks |
| 38 | +$wgHooks['InlineEditorMark'][] = 'TemplateEditor::mark'; |
| 39 | +$wgHooks['InlineEditorDefineEditors'][] = 'TemplateEditor::defineEditors'; |
| 40 | + |
| 41 | +// i18n messages |
| 42 | +$wgExtensionMessagesFiles['TemplateEditor'] = $dir . 'TemplateEditor.i18n.php'; |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/TemplateEditor/TemplateEditor.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 43 | + native |
Index: trunk/extensions/InlineEditor/TemplateEditor/TemplateEditor.css |
— | — | @@ -0,0 +1,37 @@ |
| 2 | +.templateEditor .templateEditorElement { |
| 3 | + /* soft-blue background color to highlight editable templates */ |
| 4 | + background-color: #E4F0F9; |
| 5 | + |
| 6 | + /* create a hand cursor, cross-browser hack: http://www.quirksmode.org/css/cursor.html */ |
| 7 | + cursor: pointer; |
| 8 | + cursor: hand; |
| 9 | +} |
| 10 | + |
| 11 | +.templateEditor .templateEditorElement:hover { |
| 12 | + /* indicate the template to be edited with a darker color */ |
| 13 | + background-color: #a7d7f9; |
| 14 | +} |
| 15 | + |
| 16 | +.templateEditor .templateEditorElementNotEditing * { |
| 17 | + /* make sure all the child elements inherit the background color */ |
| 18 | + background-color: inherit !important; |
| 19 | +} |
| 20 | + |
| 21 | +.templateEditor .editing { |
| 22 | + /* keeping the custom padding and margin breaks in Webkit browsers */ |
| 23 | + padding: 0px; |
| 24 | + margin: 0px; |
| 25 | + |
| 26 | + /* reset the cursor when editing */ |
| 27 | + cursor: auto; |
| 28 | +} |
| 29 | + |
| 30 | +.templateEditor .edited { |
| 31 | + /* have a yellow color to highlight edited elements, basically the orange color with the hue shifted */ |
| 32 | + background-color: #F9F2A7; |
| 33 | +} |
| 34 | + |
| 35 | +.templateEditor .lastEdit { |
| 36 | + /* have an orange color, the exact complement of the hover color, for highlighting on preview/cancel */ |
| 37 | + background-color: #f9c9a7; |
| 38 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/TemplateEditor/TemplateEditor.css |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 39 | + native |
Index: trunk/extensions/InlineEditor/TemplateEditor/TemplateEditor.class.php |
— | — | @@ -0,0 +1,46 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Simple editor for templates. |
| 5 | + */ |
| 6 | +class TemplateEditor { |
| 7 | + |
| 8 | + /** |
| 9 | + * This function hooks into InlineEditorMark and marks the media. |
| 10 | + * @param $inlineEditorText InlineEditorText |
| 11 | + */ |
| 12 | + public static function mark( &$inlineEditorText ) { |
| 13 | + // get the original wikitext |
| 14 | + $text = $inlineEditorText->getWikiOriginal(); |
| 15 | + |
| 16 | + $matches = array(); |
| 17 | + preg_match_all('/^(\{\{.*?\}\})/ms', $text, $matches, PREG_OFFSET_CAPTURE); |
| 18 | + |
| 19 | + foreach( $matches[0] as $match ) { |
| 20 | + $start = $match[1]; |
| 21 | + $end = $start + strlen( $match[0] ); |
| 22 | + $inlineEditorText->addPiece( new InlineEditorPiece( $start, $end, 'templateEditorElement templateEditorElementNotEditing', false ) ); |
| 23 | + } |
| 24 | + |
| 25 | + return true; |
| 26 | + } |
| 27 | + |
| 28 | + /** |
| 29 | + * Hooks into InlineEditorDefineEditors. Adds the option to to the list and adds CSS and JS files |
| 30 | + * @param $editor InlineEditor |
| 31 | + * @param $output OutputPage |
| 32 | + */ |
| 33 | + public static function defineEditors( &$editor, &$output ) { |
| 34 | + global $wgExtensionAssetsPath; |
| 35 | + |
| 36 | + $editor->addEditMode( |
| 37 | + 'templateEditor', |
| 38 | + wfMsgExt( 'template-editor-editmode-caption', 'parseinline' ), |
| 39 | + wfMsgExt( 'template-editor-editmode-description','parseinline' ) |
| 40 | + ); |
| 41 | + |
| 42 | + $output->addExtensionStyle( "$wgExtensionAssetsPath/InlineEditor/TemplateEditor/TemplateEditor.css?0"); |
| 43 | + $output->addScriptFile( "$wgExtensionAssetsPath/InlineEditor/TemplateEditor/jquery.inlineEditor.editors.templateEditor.js?0" ); |
| 44 | + |
| 45 | + return true; |
| 46 | + } |
| 47 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/TemplateEditor/TemplateEditor.class.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 48 | + native |
Index: trunk/extensions/InlineEditor/InlineEditorText.class.php |
— | — | @@ -0,0 +1,343 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Stores wikitext, pieces and previous markings, and generates HTML and JSON from them. |
| 6 | + * Can import wikitext and previous markings from JSON and from an original article. |
| 7 | + * |
| 8 | + * Computation path is as follows: |
| 9 | + * |
| 10 | + * First time editing the page: |
| 11 | + * wikitext from article => adding of new pieces => generating HTML (using parser) and JSON array |
| 12 | + * |
| 13 | + * Previewing the page: |
| 14 | + * JSON array with pieces + last edit diff => adding of new pieces |
| 15 | + * => computing overlap of pieces with previous markings => generating HTML (using parser) and JSON array |
| 16 | + * => generating combined JSON array |
| 17 | + * |
| 18 | + * Saving the page: |
| 19 | + * JSON array with pieces => new wikitext |
| 20 | + * |
| 21 | + */ |
| 22 | +class InlineEditorText { |
| 23 | + private $wikiOriginal; |
| 24 | + private $parserOutputMarked; |
| 25 | + private $wikiJsonArray; |
| 26 | + private $wikiJsonText; |
| 27 | + private $combinedJson; |
| 28 | + private $article; |
| 29 | + private $pieces; |
| 30 | + private $previousMarkings; |
| 31 | + |
| 32 | + /** |
| 33 | + * @param $article Article The article to work with. |
| 34 | + */ |
| 35 | + function __construct( $article ) { |
| 36 | + $this->article = $article; |
| 37 | + $this->pieces = array(); |
| 38 | + $this->previousMarkings = array(); |
| 39 | + } |
| 40 | + |
| 41 | + /** |
| 42 | + * Load the original wikitext from $wikiText. |
| 43 | + * @param $wikiText String |
| 44 | + */ |
| 45 | + public function loadFromWikiText( $wikiText ) { |
| 46 | + $this->reset(); |
| 47 | + $this->wikiOriginal = $wikiText; |
| 48 | + } |
| 49 | + |
| 50 | + /** |
| 51 | + * Get the original wikitext. |
| 52 | + * @return String Original wikitext |
| 53 | + */ |
| 54 | + public function getWikiOriginal() { |
| 55 | + return $this->wikiOriginal; |
| 56 | + } |
| 57 | + |
| 58 | + /** |
| 59 | + * Get the HTML with <span> and <div> markings. |
| 60 | + * @return String HTML |
| 61 | + */ |
| 62 | + public function getParserOutputMarked() { |
| 63 | + if( !isset( $this->parserOutputMarked ) ) $this->process(); |
| 64 | + return $this->parserOutputMarked; |
| 65 | + } |
| 66 | + |
| 67 | + /** |
| 68 | + * Get JSON representation of the wikitext and markings. |
| 69 | + * @return String JSON |
| 70 | + */ |
| 71 | + public function getWikiJson() { |
| 72 | + if( !isset( $this->wikiJsonText ) ) $this->toJsonText(); |
| 73 | + return $this->wikiJsonText; |
| 74 | + } |
| 75 | + |
| 76 | + /** |
| 77 | + * Get a combined JSON representation of the wikitext with markings, and marked HTML. |
| 78 | + * @return String JSON with HTML in it |
| 79 | + */ |
| 80 | + public function getCombinedJson() { |
| 81 | + if( !isset( $this->combinedJson ) ) $this->toCombinedJson(); |
| 82 | + return $this->combinedJson; |
| 83 | + } |
| 84 | + |
| 85 | + /** |
| 86 | + * Add a marking piece to the list of pieces. To be called by the different edit modes. |
| 87 | + * @param $piece InlineEditorPiece |
| 88 | + */ |
| 89 | + public function addPiece( InlineEditorPiece $piece ) { |
| 90 | + if( isset( $this->pieces[$piece->getStart()] ) ) return; |
| 91 | + if( !$piece->isValid() ) return; |
| 92 | + |
| 93 | + $this->pieces[$piece->getStart()] = $piece; |
| 94 | + } |
| 95 | + |
| 96 | + /** |
| 97 | + * Reset the object. |
| 98 | + */ |
| 99 | + public function reset() { |
| 100 | + unset( $this->wikiOriginal ); |
| 101 | + unset( $this->parserOutputMarked ); |
| 102 | + unset( $this->wikiJsonArray ); |
| 103 | + unset( $this->wikiJsonText ); |
| 104 | + unset( $this->combinedJson ); |
| 105 | + $this->pieces = array(); |
| 106 | + $this->previousMarkings = array(); |
| 107 | + } |
| 108 | + |
| 109 | + /** |
| 110 | + * Load original wikitext and previous markings from JSON |
| 111 | + * @param $json String JSON string from the client side editor |
| 112 | + */ |
| 113 | + public function loadFromJson( $json ) { |
| 114 | + // first of all, reset the object |
| 115 | + $this->reset(); |
| 116 | + |
| 117 | + // decode the JSON to an associative array |
| 118 | + $input = FormatJson::decode( $json, true ); |
| 119 | + |
| 120 | + // if the 'lastEdit' attribute is set, this contains the edit the user made |
| 121 | + // the original text is kept intact, but we don't need it, so just overwrite it with the new text |
| 122 | + if( isset($input['lastEdit']) ) { |
| 123 | + $input['originalWiki']['locations'][$input['lastEdit']['id']]['text'] = $input['lastEdit']['text']; |
| 124 | + } |
| 125 | + |
| 126 | + // convert the 'locations' array (by id) to the $pieces array (by position) |
| 127 | + $pieces = array(); |
| 128 | + foreach( $input['originalWiki']['locations'] as $id => $piece ) { |
| 129 | + $piece['id'] = $id; |
| 130 | + $pieces[$piece['pos']] = $piece; |
| 131 | + } |
| 132 | + |
| 133 | + // sort the $pieces array by position |
| 134 | + ksort($pieces); |
| 135 | + |
| 136 | + // init loop variables |
| 137 | + $text = ''; // reconstructed wikitext |
| 138 | + $lastPos = 0; // position in the text of the previous piece |
| 139 | + $offset = 0; // total amount of wikitext *inside* pieces so far |
| 140 | + |
| 141 | + // iterate on all pieces |
| 142 | + foreach( $pieces as $pos => $piece) { |
| 143 | + // calculate the length of the piece |
| 144 | + $length = strlen( $piece['text'] ); |
| 145 | + |
| 146 | + // add the wikitext between the previous piece and this piece |
| 147 | + $text .= substr( $input['originalWiki']['text'], $lastPos, $pos - $lastPos ); |
| 148 | + |
| 149 | + // add the wikitext of the piece itself |
| 150 | + $text .= $piece['text']; |
| 151 | + |
| 152 | + // if this piece was last edited or marked before, add it to previousMarkings |
| 153 | + if( ( isset( $input['lastEdit'] ) && $input['lastEdit']['id'] == $piece['id'] ) |
| 154 | + || $piece['edited'] ) |
| 155 | + { |
| 156 | + // because these positions are within the text *with* the pieces included, |
| 157 | + // the position has to be offsetted by exactly the total length of pieces so far |
| 158 | + $previousStart = $pos + $offset; |
| 159 | + $previousMarking = new InlineEditorPreviousMarking( $previousStart, $previousStart + $length ); |
| 160 | + $previousMarking->setEdited( true ); |
| 161 | + |
| 162 | + if( isset( $input['lastEdit'] ) && $input['lastEdit']['id'] == $piece['id'] ) { |
| 163 | + $previousMarking->setLastEdit( true ); |
| 164 | + } |
| 165 | + |
| 166 | + // last sanity check before adding the marking |
| 167 | + if( $previousMarking->isValid() ) { |
| 168 | + $this->previousMarkings[$previousStart] = $previousMarking; |
| 169 | + } |
| 170 | + } |
| 171 | + |
| 172 | + // set variables for next round |
| 173 | + $lastPos = $pos; |
| 174 | + $offset += $length; |
| 175 | + } |
| 176 | + |
| 177 | + // add the text after the last piece |
| 178 | + $text .= substr( $input['originalWiki']['text'], $lastPos ); |
| 179 | + |
| 180 | + // store it as the original wikitext |
| 181 | + $this->wikiOriginal = $text; |
| 182 | + } |
| 183 | + |
| 184 | + /** |
| 185 | + * Encodes the wikiJsonArray to a JSON string and stores it. |
| 186 | + */ |
| 187 | + private function toJsonText() { |
| 188 | + if ( !isset( $this->wikiJsonArray ) ) $this->process(); |
| 189 | + $this->wikiJsonText = FormatJson::encode( $this->wikiJsonArray ); |
| 190 | + } |
| 191 | + |
| 192 | + /** |
| 193 | + * Encodes both the wikiJsonArray and the parserOutputMarked to a JSON string and stores it. |
| 194 | + */ |
| 195 | + private function toCombinedJson() { |
| 196 | + if ( !isset( $this->wikiJsonArray ) || !isset( $this->parserOutputMarked ) ) $this->process(); |
| 197 | + |
| 198 | + $combined = array('html' => $this->parserOutputMarked->getText(), 'wiki' => $this->wikiJsonArray); |
| 199 | + $this->combinedJson = FormatJson::encode( $combined ); |
| 200 | + } |
| 201 | + |
| 202 | + /** |
| 203 | + * Calls the InlineEditorMark hook to have pieces added, and calculates the JSON and marked HTML. |
| 204 | + */ |
| 205 | + private function process() { |
| 206 | + global $wgParser; |
| 207 | + |
| 208 | + // make sure the pieces are added by the edit modes |
| 209 | + wfRunHooks( 'InlineEditorMark', array( &$this ) ); |
| 210 | + |
| 211 | + // init the basic variables |
| 212 | + $last = 0; // end position of the last piece in the original wikitext |
| 213 | + $offset = 0; // total amount of wikitext *inside* pieces so far |
| 214 | + $wikiMarked = ''; // marked wikitext to run through the parser |
| 215 | + $jsonText = ''; // wikitext in JSON, which has the pieces *removed* |
| 216 | + $jsonLocations = array(); // pieces with positions where to insert them in $jsonText |
| 217 | + |
| 218 | + // sort the pieces by start position |
| 219 | + ksort( $this->pieces ); |
| 220 | + |
| 221 | + // make sure the 'edited' and 'lastEdit' properties on pieces are correctly set |
| 222 | + $this->applyPreviousMarkings(); |
| 223 | + |
| 224 | + // iterate on all pieces |
| 225 | + foreach( $this->pieces as $start => $piece ) { |
| 226 | + // do not allow overlap of pieces, so only take those with the lowest |
| 227 | + // starting position |
| 228 | + if ( $start < $last ) { |
| 229 | + unset( $this->pieces[$start] ); |
| 230 | + } |
| 231 | + else { |
| 232 | + // get the end and calculate the length of the current piece |
| 233 | + $end = $piece->getEnd(); |
| 234 | + $length = $end-$start; |
| 235 | + |
| 236 | + // get the text between last piece and this piece |
| 237 | + $prePieceText = substr($this->wikiOriginal, $last, $start-$last); |
| 238 | + |
| 239 | + // get the text of the piece itself |
| 240 | + $pieceText = substr($this->wikiOriginal, $start, $length); |
| 241 | + |
| 242 | + // add the text between last piece and this piece, followed by |
| 243 | + // the text of the piece surrounded by markings |
| 244 | + $wikiMarked .= $prePieceText |
| 245 | + . $piece->renderStartMarking() |
| 246 | + . $pieceText |
| 247 | + . $piece->renderEndMarking(); |
| 248 | + |
| 249 | + // only add the text between pieces to the JSON text |
| 250 | + $jsonText .= $prePieceText; |
| 251 | + |
| 252 | + // add the piece and position in $jsonText to the list of locations |
| 253 | + // note that because we're taking out exactly the length of text within pieces, |
| 254 | + // we can subtract this number from the start position of the piece, to obtain |
| 255 | + // the position within $jsonText |
| 256 | + $jsonLocations[$piece->getId()] = array( |
| 257 | + 'text' => $pieceText, |
| 258 | + 'pos' => $start - $offset, |
| 259 | + 'edited' => ($piece->getEdited() ? '1' : '0') |
| 260 | + ); |
| 261 | + |
| 262 | + // set variables for the next round |
| 263 | + $offset += $length; |
| 264 | + $last = $end; |
| 265 | + } |
| 266 | + } |
| 267 | + |
| 268 | + // get the text after the last piece and add it to both variables |
| 269 | + $postPieceText = substr($this->wikiOriginal, $last); |
| 270 | + $wikiMarked .= $postPieceText; |
| 271 | + $jsonText .= $postPieceText; |
| 272 | + |
| 273 | + // store the JSON text and locations |
| 274 | + $this->wikiJsonArray = array( 'text' => $jsonText, 'locations' => $jsonLocations ); |
| 275 | + |
| 276 | + // get the same parser options as usual, but remove [edit] links |
| 277 | + $parserOptions = clone $this->article->getParserOptions(); |
| 278 | + $parserOptions->setEditSection( false ); |
| 279 | + |
| 280 | + // run $wikiMarked through the parser and store the result |
| 281 | + $this->parserOutputMarked = $wgParser->parse( $wikiMarked, $this->article->getTitle(), |
| 282 | + $parserOptions, true, true, $this->article->getRevIdFetched() ); |
| 283 | + } |
| 284 | + |
| 285 | + /** |
| 286 | + * Checks if pieces have overlap with previous markings and marks them again with |
| 287 | + * 'edited' or 'lastEdit'. |
| 288 | + * |
| 289 | + * A piece can have overlap with multiple previous markings, but not with many. To |
| 290 | + * avoid checking all pieces against all markings, a smarter algorithm is employed. |
| 291 | + * |
| 292 | + * When both the pieces are sorted (*precondition*) and the previous markings are |
| 293 | + * sorted (which is done in the function), both arrays can be walked. For the array of |
| 294 | + * previous markings we define a $firstId and $lastId. The end of the first previous marking |
| 295 | + * has to be at least on or past the start of the current piece. The start of the last |
| 296 | + * previous marking has to be at least past the end of the current piece. This way we can |
| 297 | + * increment $firstId and $lastId until this is true, and we have a smaller window to |
| 298 | + * check. |
| 299 | + * |
| 300 | + * @return unknown_type |
| 301 | + */ |
| 302 | + private function applyPreviousMarkings() { |
| 303 | + // if there are no previous markings there is no point in checking |
| 304 | + if( empty( $this->previousMarkings ) ) return; |
| 305 | + |
| 306 | + // start both at the beginning |
| 307 | + $firstId = 0; |
| 308 | + $lastId = 0; |
| 309 | + |
| 310 | + // sort based on start position |
| 311 | + ksort( $this->previousMarkings ); |
| 312 | + |
| 313 | + // use an array with as keys 0, 1, 2, etc. |
| 314 | + $previous = array_values( $this->previousMarkings ); |
| 315 | + |
| 316 | + // interate over all pieces |
| 317 | + foreach( $this->pieces as $start => $piece ) { |
| 318 | + $end = $piece->getEnd(); |
| 319 | + |
| 320 | + // move the pointer of the first previous marking so it overlaps with the piece |
| 321 | + while( isset( $previous[$firstId] ) && $previous[$firstId]->getEnd() < $start ) { |
| 322 | + $firstId++; |
| 323 | + } |
| 324 | + |
| 325 | + // if the pointer to the first previous marking has gone too far, there is nothing |
| 326 | + // to check for anymore: we're done |
| 327 | + if( !isset( $previous[$firstId] ) ) return; |
| 328 | + |
| 329 | + // move the pointer of the last previous marking so it just doesn't overlap |
| 330 | + while( isset( $previous[$lastId] ) && $previous[$lastId]->getStart() <= $end ) { |
| 331 | + $lastId++; |
| 332 | + } |
| 333 | + |
| 334 | + // check the (small) window of previous markings for overlap |
| 335 | + for( $i = $firstId; $i < $lastId; $i++ ) { |
| 336 | + // this should always be true, but check anyway! |
| 337 | + if( $previous[$i]->inMarking( $piece ) ) { |
| 338 | + if( $previous[$i]->getEdited() ) $piece->setEdited( true ); |
| 339 | + if( $previous[$i]->getLastEdit() ) $piece->setLastEdit( true ); |
| 340 | + } |
| 341 | + } |
| 342 | + } |
| 343 | + } |
| 344 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/InlineEditorText.class.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 345 | + native |
Index: trunk/extensions/InlineEditor/InlineEditorPiece.class.php |
— | — | @@ -0,0 +1,102 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Denotes the start and end of an editiable piece in the wikitext, along with some properties. |
| 6 | + */ |
| 7 | +class InlineEditorPiece { |
| 8 | + private static $lastId = 0; ///< counter which is used to generate unique ids |
| 9 | + |
| 10 | + private $start; ///< start position of the piece in the wikitext |
| 11 | + private $end; ///< end position of the piece in the wikitext |
| 12 | + private $class; ///< class(es) attached to the piece, usually identifies the edit mode |
| 13 | + private $inline; ///< whether or not the piece is inline (span) or not (div) |
| 14 | + private $id; ///< unique id of this piece |
| 15 | + private $edited; ///< boolean whether or not (part of) the piece has been edited before |
| 16 | + private $lastEdit; ///< boolean whether or not (part of) the piece was in the last edit |
| 17 | + |
| 18 | + // getter functions for most private variables |
| 19 | + public function getStart() { return $this->start; } |
| 20 | + public function getEnd() { return $this->end; } |
| 21 | + public function getClass() { return $this->class; } |
| 22 | + public function getId() { return $this->id; } |
| 23 | + public function getEdited() { return $this->edited; } |
| 24 | + public function getLastEdit() { return $this->lastEdit; } |
| 25 | + |
| 26 | + // setter functions for edited and lastEdit, as these are not set by the different editors, |
| 27 | + // but by InlineEditorText |
| 28 | + public function setEdited( $val ) { $this->edited = $val; } |
| 29 | + public function setLastEdit( $val ) { $this->lastEdit = $val; } |
| 30 | + |
| 31 | + /** |
| 32 | + * @param $start Integer Start of the piece, offset in number of characters from the begin of the wikitext |
| 33 | + * @param $end Integer End of the piece, offset in number of characters from the begin of the wikitext |
| 34 | + * @param $class String Class(es) the piece should be labeled with |
| 35 | + * @param $inline Boolean Whether the piece is inline (span) or not (div), a div also adds newlines |
| 36 | + */ |
| 37 | + function __construct($start, $end, $class, $inline) { |
| 38 | + $this->start = $start; |
| 39 | + $this->end = $end; |
| 40 | + $this->class = $class; |
| 41 | + $this->inline = $inline; |
| 42 | + $this->id = self::uniqueId(); |
| 43 | + $this->edited = false; |
| 44 | + $this->lastEdit = false; |
| 45 | + } |
| 46 | + |
| 47 | + /** |
| 48 | + * Render the open tag, depending on $this->inline this is a <span> or a <div>. |
| 49 | + * @return String HTML |
| 50 | + */ |
| 51 | + public function renderStartMarking() { |
| 52 | + $attribs = array( 'class' => $this->getFullClass(), 'id' => $this->id ); |
| 53 | + return HTML::openElement( $this->getElement(), $attribs ) . $this->getNewline(); |
| 54 | + } |
| 55 | + |
| 56 | + /** |
| 57 | + * Render the close tag. |
| 58 | + * @return String HTML |
| 59 | + */ |
| 60 | + public function renderEndMarking() { |
| 61 | + return $this->getNewline() . '</' . $this->getElement() . '>'; |
| 62 | + } |
| 63 | + |
| 64 | + /** |
| 65 | + * Simple check to prevent invalid values. |
| 66 | + * @return boolean |
| 67 | + */ |
| 68 | + public function isValid() { |
| 69 | + return $this->end > $this->start; |
| 70 | + } |
| 71 | + |
| 72 | + /** |
| 73 | + * Get the class that should be rendered, this may include 'edited' and 'lastEdit' for highlighting. |
| 74 | + * @return String All the classes |
| 75 | + */ |
| 76 | + private function getFullClass() { |
| 77 | + return $this->class . ($this->edited ? ' edited' : '') . ($this->lastEdit ? ' lastEdit' : ''); |
| 78 | + } |
| 79 | + |
| 80 | + /** |
| 81 | + * Get the element name based on $this->inline. |
| 82 | + * @return String Element name |
| 83 | + */ |
| 84 | + private function getElement() { |
| 85 | + return $this->inline ? 'span' : 'div'; |
| 86 | + } |
| 87 | + |
| 88 | + /** |
| 89 | + * Get a newline or not based on $this->inline. |
| 90 | + * @return String Empty string or single newline character |
| 91 | + */ |
| 92 | + private function getNewline() { |
| 93 | + return $this->inline ? '' : "\n"; |
| 94 | + } |
| 95 | + |
| 96 | + /** |
| 97 | + * Get a unique id by using self::$lastId and incrementing it. |
| 98 | + * @return String |
| 99 | + */ |
| 100 | + private static function uniqueId() { |
| 101 | + return 'inline-editor-' . self::$lastId++; |
| 102 | + } |
| 103 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/InlineEditorPiece.class.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 104 | + native |
Index: trunk/extensions/InlineEditor/InlineEditorPreviousMarking.class.php |
— | — | @@ -0,0 +1,47 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * Denotes the start and end of previously edited pieces in the wikitext. |
| 6 | + */ |
| 7 | +class InlineEditorPreviousMarking { |
| 8 | + private $start; ///< start position of the piece in the wikitext |
| 9 | + private $end; ///< end position of the piece in the wikitext |
| 10 | + private $edited; ///< boolean whether or not (part of) the piece has been edited before |
| 11 | + private $lastEdit; ///< boolean whether or not (part of) the piece was in the last edit |
| 12 | + |
| 13 | + // getters and setters for the private variables |
| 14 | + public function getStart() { return $this->start; } |
| 15 | + public function getEnd() { return $this->end; } |
| 16 | + public function getEdited() { return $this->edited; } |
| 17 | + public function getLastEdit() { return $this->lastEdit; } |
| 18 | + public function setEdited( $val ) { $this->edited = $val; } |
| 19 | + public function setLastEdit( $val ) { $this->lastEdit = $val; } |
| 20 | + |
| 21 | + /** |
| 22 | + * @param $start Integer Start of the piece, offset in number of characters from the begin of the wikitext |
| 23 | + * @param $end Integer End of the piece, offset in number of characters from the begin of the wikitext |
| 24 | + */ |
| 25 | + function __construct($start, $end) { |
| 26 | + $this->start = $start; |
| 27 | + $this->end = $end; |
| 28 | + } |
| 29 | + |
| 30 | + /** |
| 31 | + * Checks if an InlineEditorPiece overlaps *or touches* with this marking. |
| 32 | + * @param $piece InlineEditorPiece |
| 33 | + * @return Boolean |
| 34 | + */ |
| 35 | + public function inMarking( InlineEditorPiece $piece ) { |
| 36 | + $start = $piece->getStart(); |
| 37 | + $end = $piece->getEnd(); |
| 38 | + return ($start >= $this->start && $start <= $this->end) || ($end >= $this->start && $end <= $this->end); |
| 39 | + } |
| 40 | + |
| 41 | + /** |
| 42 | + * Simple check to prevent invalid values. |
| 43 | + * @return boolean |
| 44 | + */ |
| 45 | + public function isValid() { |
| 46 | + return $this->end > $this->start; |
| 47 | + } |
| 48 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/InlineEditorPreviousMarking.class.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 49 | + native |
Index: trunk/extensions/InlineEditor/MediaEditor/MediaEditor.class.php |
— | — | @@ -0,0 +1,60 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Simple editor for media (images, video, sound). |
| 5 | + */ |
| 6 | +class MediaEditor { |
| 7 | + |
| 8 | + /** |
| 9 | + * This function hooks into InlineEditorMark and marks the media. |
| 10 | + * @param $inlineEditorText InlineEditorText |
| 11 | + */ |
| 12 | + public static function mark( &$inlineEditorText ) { |
| 13 | + // get the original wikitext |
| 14 | + $text = $inlineEditorText->getWikiOriginal(); |
| 15 | + |
| 16 | + $matches = array(); |
| 17 | + preg_match_all( '/^\s*(\[\[(.*:.*)\]\])\s*$/m', $text, $matches, PREG_OFFSET_CAPTURE ); |
| 18 | + |
| 19 | + foreach( $matches[1] as $id => $match ) { |
| 20 | + $link = $matches[2][$id][0]; |
| 21 | + $firstPipe = strpos($link, '|'); |
| 22 | + if( $firstPipe !== false ) { |
| 23 | + $url = substr( $link, 0, $firstPipe ); |
| 24 | + } |
| 25 | + else { |
| 26 | + $url = $link; |
| 27 | + } |
| 28 | + |
| 29 | + $title = Title::newFromText( $url ); |
| 30 | + $namespace = $title->getNamespace(); |
| 31 | + |
| 32 | + if( $namespace == NS_FILE ) { |
| 33 | + $start = $match[1]; |
| 34 | + $end = $start + strlen( $match[0] ); |
| 35 | + $inlineEditorText->addPiece( new InlineEditorPiece( $start, $end, 'mediaEditorElement', false ) ); |
| 36 | + } |
| 37 | + } |
| 38 | + |
| 39 | + return true; |
| 40 | + } |
| 41 | + |
| 42 | + /** |
| 43 | + * Hooks into InlineEditorDefineEditors. Adds the option to to the list and adds CSS and JS files |
| 44 | + * @param $editor InlineEditor |
| 45 | + * @param $output OutputPage |
| 46 | + */ |
| 47 | + public static function defineEditors( &$editor, &$output ) { |
| 48 | + global $wgExtensionAssetsPath; |
| 49 | + |
| 50 | + $editor->addEditMode( |
| 51 | + 'mediaEditor', |
| 52 | + wfMsgExt( 'media-editor-editmode-caption', 'parseinline' ), |
| 53 | + wfMsgExt( 'media-editor-editmode-description','parseinline' ) |
| 54 | + ); |
| 55 | + |
| 56 | + $output->addExtensionStyle( "$wgExtensionAssetsPath/InlineEditor/MediaEditor/MediaEditor.css?0"); |
| 57 | + $output->addScriptFile( "$wgExtensionAssetsPath/InlineEditor/MediaEditor/jquery.inlineEditor.editors.mediaEditor.js?0" ); |
| 58 | + |
| 59 | + return true; |
| 60 | + } |
| 61 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/MediaEditor/MediaEditor.class.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 62 | + native |
Index: trunk/extensions/InlineEditor/MediaEditor/MediaEditor.i18n.php |
— | — | @@ -0,0 +1,26 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Internationalisation file for extension MediaEditor. |
| 5 | + * |
| 6 | + * @file |
| 7 | + * @ingroup Extensions |
| 8 | + */ |
| 9 | + |
| 10 | +$messages = array(); |
| 11 | + |
| 12 | +/** English |
| 13 | + * @author Jan Paul Posma |
| 14 | + */ |
| 15 | +$messages['en'] = array( |
| 16 | + 'media-editor-desc' => 'Adds the "Media" edit mode for the InlineEditor', |
| 17 | + |
| 18 | + 'media-editor-editmode-caption' => "Media", |
| 19 | + 'media-editor-editmode-description' => " |
| 20 | +You can edit media like images, video and sound using this mode. |
| 21 | +Sometimes templates are used to display images, in which case you have to use the '''Template''' mode. |
| 22 | + |
| 23 | +:<code><nowiki>[[File:Example.jpg|thumb|An example file]]</nowiki></code> |
| 24 | + |
| 25 | +[http://en.wikipedia.org/wiki/Help:Files More information] |
| 26 | +", |
| 27 | +); |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/MediaEditor/MediaEditor.i18n.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 28 | + native |
Index: trunk/extensions/InlineEditor/MediaEditor/jquery.inlineEditor.editors.mediaEditor.js |
— | — | @@ -0,0 +1,40 @@ |
| 2 | +/** |
| 3 | + * Client side part of the MediaEditor. |
| 4 | + */ |
| 5 | +( function( $ ) { $.inlineEditor.editors.mediaEditor = { |
| 6 | + |
| 7 | +click: function(event) { |
| 8 | + // prevent clicks from reaching other elements |
| 9 | + event.stopPropagation(); |
| 10 | + event.preventDefault(); |
| 11 | + |
| 12 | + // find the element and retrieve the corresponding wikitext |
| 13 | + var $field = $(this); |
| 14 | + var wiki = $.inlineEditor.getTextById( $field.attr( 'id' ) ); |
| 15 | + |
| 16 | + $newField = $.inlineEditor.basicEditor.newField( $field, $.inlineEditor.editors.mediaEditor.click ); |
| 17 | + $.inlineEditor.basicEditor.addEditBar( $newField, 700, wiki ); |
| 18 | +}, |
| 19 | + |
| 20 | +enable: function() { |
| 21 | + // do what we also do when reloading the page |
| 22 | + $.inlineEditor.editors.mediaEditor.reload(); |
| 23 | + |
| 24 | + // add the identifying class to #editContent |
| 25 | + $( '#editContent' ).addClass( 'mediaEditor' ); |
| 26 | +}, |
| 27 | + |
| 28 | +reload: function() { |
| 29 | + // make media clickable |
| 30 | + $( '.mediaEditorElement' ).click( $.inlineEditor.editors.mediaEditor.click ); |
| 31 | +}, |
| 32 | + |
| 33 | +disable: function() { |
| 34 | + // remove the click event from the media |
| 35 | + $( '.mediaEditorElement' ).unbind( 'click' ); |
| 36 | + |
| 37 | + // remove the identifying class from #editContent |
| 38 | + $( '#editContent' ).removeClass( 'mediaEditor' ); |
| 39 | +} |
| 40 | + |
| 41 | +}; } ) ( jQuery ); |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/MediaEditor/jquery.inlineEditor.editors.mediaEditor.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 42 | + native |
Index: trunk/extensions/InlineEditor/MediaEditor/MediaEditor.php |
— | — | @@ -0,0 +1,41 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * MediaEditor extension for the InlineEditor. |
| 5 | + * |
| 6 | + * @file |
| 7 | + * @ingroup Extensions |
| 8 | + * |
| 9 | + * This is the include file for the MediaEditor. |
| 10 | + * |
| 11 | + * Usage: Include the following line in your LocalSettings.php |
| 12 | + * require_once( "$IP/extensions/InlineEditor/MediaEditor/MediaEditor.php" ); |
| 13 | + * |
| 14 | + * @author Jan Paul Posma <jp.posma@gmail.com> |
| 15 | + * @license GPL v2 or later |
| 16 | + * @version 0.0.0 |
| 17 | + */ |
| 18 | + |
| 19 | +if ( !defined( 'MEDIAWIKI' ) ) die(); |
| 20 | + |
| 21 | +// credits |
| 22 | +$wgExtensionCredits['other'][] = array( |
| 23 | + 'path' => __FILE__, |
| 24 | + 'name' => 'MediaEditor', |
| 25 | + 'author' => array( 'Jan Paul Posma' ), |
| 26 | + 'version' => '0.1.0', |
| 27 | + 'url' => 'http://www.mediawiki.org/wiki/Extension:InlineEditor#MediaEditor', |
| 28 | + 'descriptionmsg' => 'media-editor-desc', |
| 29 | +); |
| 30 | + |
| 31 | +// current directory including trailing slash |
| 32 | +$dir = dirname( __FILE__ ) . '/'; |
| 33 | + |
| 34 | +// add autoload classes |
| 35 | +$wgAutoloadClasses['MediaEditor'] = $dir . 'MediaEditor.class.php'; |
| 36 | + |
| 37 | +// register hooks |
| 38 | +$wgHooks['InlineEditorMark'][] = 'MediaEditor::mark'; |
| 39 | +$wgHooks['InlineEditorDefineEditors'][] = 'MediaEditor::defineEditors'; |
| 40 | + |
| 41 | +// i18n messages |
| 42 | +$wgExtensionMessagesFiles['MediaEditor'] = $dir . 'MediaEditor.i18n.php'; |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/MediaEditor/MediaEditor.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 43 | + native |
Index: trunk/extensions/InlineEditor/MediaEditor/MediaEditor.css |
— | — | @@ -0,0 +1,37 @@ |
| 2 | +.mediaEditor .mediaEditorElement { |
| 3 | + /* soft-blue background color to highlight editable media */ |
| 4 | + background-color: #E4F0F9; |
| 5 | + |
| 6 | + /* create a hand cursor, cross-browser hack: http://www.quirksmode.org/css/cursor.html */ |
| 7 | + cursor: pointer; |
| 8 | + cursor: hand; |
| 9 | +} |
| 10 | + |
| 11 | +.mediaEditor .mediaEditorElement:hover { |
| 12 | + /* indicate the media to be edited with a darker color */ |
| 13 | + background-color: #a7d7f9; |
| 14 | +} |
| 15 | + |
| 16 | +.mediaEditor .editing { |
| 17 | + /* keeping the custom padding and margin breaks in Webkit browsers */ |
| 18 | + padding: 0px; |
| 19 | + margin: 0px; |
| 20 | + |
| 21 | + /* reset the cursor when editing */ |
| 22 | + cursor: auto; |
| 23 | +} |
| 24 | + |
| 25 | +.mediaEditor .edited { |
| 26 | + /* have a yellow color to highlight edited elements, basically the orange color with the hue shifted */ |
| 27 | + background-color: #F9F2A7; |
| 28 | +} |
| 29 | + |
| 30 | +.mediaEditor .lastEdit { |
| 31 | + /* have an orange color, the exact complement of the hover color, for highlighting on preview/cancel */ |
| 32 | + background-color: #f9c9a7; |
| 33 | +} |
| 34 | + |
| 35 | +.mediaEditor .thumb, |
| 36 | +.mediaEditor .thumbinner { |
| 37 | + background-color: inherit !important; |
| 38 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/MediaEditor/MediaEditor.css |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 39 | + native |
Index: trunk/extensions/InlineEditor/InlineEditor.i18n.php |
— | — | @@ -0,0 +1,29 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Internationalisation file for extension InlineScripts. |
| 5 | + * |
| 6 | + * @file |
| 7 | + * @ingroup Extensions |
| 8 | + */ |
| 9 | + |
| 10 | +$messages = array(); |
| 11 | + |
| 12 | +/** English |
| 13 | + * @author Jan Paul Posma |
| 14 | + */ |
| 15 | +$messages['en'] = array( |
| 16 | + 'inline-editor-desc' => 'Provides an alternative editor which is easier to use', |
| 17 | + |
| 18 | + 'inline-editor-editbox-top' => "'''Awesome, you're editing {{SITENAME}}!'''<br/>You can edit the article below, by clicking on <span class=\"highlightExample\">blue elements</span> in the article.", |
| 19 | + 'inline-editor-editbox-changes-question' => "Can you briefly describe the changes you're making?", |
| 20 | + 'inline-editor-editbox-changes-example' => 'For example: "Fixed spelling mistake", "Corrected facts", "Wrote a new paragraph", etc.', |
| 21 | + 'inline-editor-editbox-publish-notice' => "When you're done, don't forget to publish the page!", |
| 22 | + //'inline-editor-editbox-publish-terms' => 'When you click "Publish", you agree to the [http://wikimediafoundation.org/wiki/Terms_of_Use Terms of Use]. This means that you agree to share your contributions under a free license.', |
| 23 | + 'inline-editor-editbox-publish-terms' => 'When you click "Publish", you agree with our copyright policy. See $1 for more information.', |
| 24 | + 'inline-editor-editbox-publish-caption' => 'Publish', |
| 25 | + 'inline-editor-editmodes-caption' => 'Edit mode:', |
| 26 | + 'inline-editor-redirect-browser' => 'The new editing interface is not supported by your browser.', |
| 27 | + 'inline-editor-redirect-advanced' => "Editing this page is considered '''advanced''' use of Wikipedia. You can only use the '''full editor''' for this page.", |
| 28 | + 'inline-editor-editmodes-undo' => 'Undo', |
| 29 | + 'inline-editor-editmodes-redo' => 'Redo', |
| 30 | +); |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/InlineEditor.i18n.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 31 | + native |
Index: trunk/extensions/InlineEditor/ajax-loader.gif |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
Property changes on: trunk/extensions/InlineEditor/ajax-loader.gif |
___________________________________________________________________ |
Added: svn:mime-type |
2 | 32 | + application/octet-stream |
Index: trunk/extensions/InlineEditor/HideEditSection.css |
— | — | @@ -0,0 +1,4 @@ |
| 2 | +.editsection { |
| 3 | + /* hide the edit section from the page using CSS as opposed to hacking the parser options (and thus, cache) */ |
| 4 | + display: none !important; |
| 5 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/HideEditSection.css |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 6 | + native |
Index: trunk/extensions/InlineEditor/ExtendedEditPage.class.php |
— | — | @@ -0,0 +1,132 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * This is basically an EditPage with some specific functions for the InlineEditor. This |
| 5 | + * allows retrieval of wikitext, summary and a submit URL, and handles when to fall back |
| 6 | + * to the full/traditional editor. |
| 7 | + */ |
| 8 | +class ExtendedEditPage extends EditPage { |
| 9 | + |
| 10 | + /** |
| 11 | + * Inits the edit page for the InlineEditor. |
| 12 | + * This is largely a copy-paste from EditPage::edit(), with some specific changes. |
| 13 | + */ |
| 14 | + public function initInlineEditor() { |
| 15 | + global $wgRequest, $wgOut; |
| 16 | + $this->importFormData( $wgRequest ); |
| 17 | + |
| 18 | + if( !empty( $this->section ) ) return false; |
| 19 | + |
| 20 | + // @todo: refactor this piece in EditPage.php to (a) different function(s) |
| 21 | + // so that this is not an ugly copy-paste |
| 22 | + |
| 23 | + if ( wfReadOnly() && $this->save ) { |
| 24 | + // Force preview |
| 25 | + $this->save = false; |
| 26 | + $this->preview = true; |
| 27 | + } |
| 28 | + |
| 29 | + $permErrors = $this->getEditPermissionErrors(); |
| 30 | + if ( $permErrors ) { |
| 31 | + wfDebug( __METHOD__ . ": User can't edit\n" ); |
| 32 | + $this->readOnlyPage( $this->getContent( false ), true, $permErrors, 'edit' ); |
| 33 | + wfProfileOut( __METHOD__ ); |
| 34 | + return false; |
| 35 | + } else { |
| 36 | + if ( $this->save ) { |
| 37 | + $this->formtype = 'save'; |
| 38 | + } else if ( $this->preview ) { |
| 39 | + $this->formtype = 'preview'; |
| 40 | + } else if ( $this->diff ) { |
| 41 | + $this->formtype = 'diff'; |
| 42 | + } else { # First time through |
| 43 | + $this->firsttime = true; |
| 44 | + if ( $this->previewOnOpen() ) { |
| 45 | + $this->formtype = 'preview'; |
| 46 | + } else { |
| 47 | + $this->formtype = 'initial'; |
| 48 | + } |
| 49 | + } |
| 50 | + } |
| 51 | + |
| 52 | + // If they used redlink=1 and the page exists, redirect to the main article |
| 53 | + if ( $wgRequest->getBool( 'redlink' ) && $this->mTitle->exists() ) { |
| 54 | + $wgOut->redirect( $this->mTitle->getFullURL() ); |
| 55 | + } |
| 56 | + |
| 57 | + $this->isConflict = false; |
| 58 | + // css / js subpages of user pages get a special treatment |
| 59 | + $this->isCssJsSubpage = $this->mTitle->isCssJsSubpage(); |
| 60 | + $this->isCssSubpage = $this->mTitle->isCssSubpage(); |
| 61 | + $this->isJsSubpage = $this->mTitle->isJsSubpage(); |
| 62 | + $this->isValidCssJsSubpage = $this->mTitle->isValidCssJsSubpage(); |
| 63 | + |
| 64 | + // catch the HTML that the intro throws |
| 65 | + // if anything is thrown, fall back to the normal editor |
| 66 | + $wgOut->clearHTML(); |
| 67 | + if ( $this->formtype == 'initial' || $this->firsttime ) { |
| 68 | + $this->showIntro(); |
| 69 | + if( $wgOut->getHTML() != '' ) { |
| 70 | + $wgOut->clearHTML(); |
| 71 | + return false; |
| 72 | + } |
| 73 | + } |
| 74 | + |
| 75 | + if ( 'initial' == $this->formtype || 'preview' == $this->formtype || $this->firsttime ) { |
| 76 | + if ( $this->initialiseForm() !== false ) { |
| 77 | + return true; |
| 78 | + } |
| 79 | + else { |
| 80 | + return false; |
| 81 | + } |
| 82 | + } |
| 83 | + elseif ( 'save' == $this->formtype ) { |
| 84 | + // attemptSave does a redirect *itself* when it's succesful! |
| 85 | + $this->attemptSave(); |
| 86 | + if( $this->isConflict ) { |
| 87 | + return false; |
| 88 | + } |
| 89 | + else { |
| 90 | + return true; |
| 91 | + } |
| 92 | + } |
| 93 | + else { |
| 94 | + return false; |
| 95 | + } |
| 96 | + } |
| 97 | + |
| 98 | + /** |
| 99 | + * Get the wikitext to render the page from |
| 100 | + * @return String |
| 101 | + */ |
| 102 | + public function getWikiText() { |
| 103 | + return $this->textbox1; |
| 104 | + } |
| 105 | + |
| 106 | + /** |
| 107 | + * Get the summary to show in the input field |
| 108 | + * @return String |
| 109 | + */ |
| 110 | + public function getSummary() { |
| 111 | + return $this->summary; |
| 112 | + } |
| 113 | + |
| 114 | + /** |
| 115 | + * Get the URL to submit to, with some options in the URL that are usually hidden fields |
| 116 | + * @return String |
| 117 | + */ |
| 118 | + public function getSubmitUrl() { |
| 119 | + global $wgUser; |
| 120 | + $options = array( |
| 121 | + 'action' => 'edit', |
| 122 | + 'wpEditToken' => $wgUser->editToken(), |
| 123 | + 'wpEdittime' => $this->edittime, |
| 124 | + 'wpStarttime' => $this->starttime |
| 125 | + ); |
| 126 | + |
| 127 | + if( $this->scrolltop ) $options['wpScrolltop'] = 1; |
| 128 | + if( $this->minoredit ) $options['wpMinorEdit'] = 1; |
| 129 | + if( $this->watchthis ) $options['wpWatchthis'] = 1; |
| 130 | + |
| 131 | + return $this->mTitle->getLocalURL( $options ); |
| 132 | + } |
| 133 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/ExtendedEditPage.class.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 134 | + native |
Index: trunk/extensions/InlineEditor/EditForm.css |
— | — | @@ -0,0 +1,13 @@ |
| 2 | +/* style for message on top of the full/original editor, put there by the InlineEditor */ |
| 3 | + |
| 4 | +.inlineEditorMessage { |
| 5 | + /* box on top of the page, colors are the same as the surrounding colors */ |
| 6 | + /* it scales with the display size */ |
| 7 | + font-size: 1.0em; |
| 8 | + background-color: #eaf3f8; |
| 9 | + border: 1px solid #A7D7F9; |
| 10 | + margin-bottom: 10px; |
| 11 | + padding: 10px 10px 5px; |
| 12 | + max-width: 700px; |
| 13 | + position: relative; |
| 14 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/EditForm.css |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 15 | + native |
Index: trunk/extensions/InlineEditor/jquery.inlineEditor.basicEditor.js |
— | — | @@ -0,0 +1,122 @@ |
| 2 | +/** |
| 3 | + * Provides a basic editor with preview and cancel functionality. |
| 4 | + */ |
| 5 | +( function( $ ) { $.inlineEditor.basicEditor = { |
| 6 | + |
| 7 | +/** |
| 8 | + * Creates a new field which stores the original field inside. |
| 9 | + * The original click event is required to bind with the original field. |
| 10 | + */ |
| 11 | +newField: function( $field, originalClickEvent ) { |
| 12 | + // store the original field in a hidden field |
| 13 | + var $orig = $( '<' + $field.get(0).nodeName + '/>' ); |
| 14 | + $orig.html( $field.html() ); |
| 15 | + $orig.attr( 'id', $field.attr( 'id' ) ); |
| 16 | + $orig.addClass( $field.attr( 'class' ) ); |
| 17 | + $orig.addClass( 'orig' ); |
| 18 | + $orig.click( originalClickEvent ); |
| 19 | + |
| 20 | + // create a new field and add the original text |
| 21 | + var $newField = $( '<' + $field.get(0).nodeName + '/>' ); |
| 22 | + $newField.addClass( $field.attr('class' ) ); |
| 23 | + $newField.addClass( 'editing' ); |
| 24 | + $newField.append( $orig ); |
| 25 | + |
| 26 | + // add the new field after the current one, and remove the current one |
| 27 | + // editing the current field is buggy in Webkit browsers |
| 28 | + $field.after( $newField ); |
| 29 | + $field.remove(); |
| 30 | + |
| 31 | + return $newField; |
| 32 | +}, |
| 33 | + |
| 34 | +/** |
| 35 | + * Adds an edit bar to the field with preview and cancel functionality. |
| 36 | + */ |
| 37 | +addEditBar: function( $newSpan, width, wiki ) { |
| 38 | + // build the input field |
| 39 | + var $input = $( '<textarea style="width: ' + (width-60-60-10) + 'px;"></textarea>' ); |
| 40 | + $input.text( wiki ); |
| 41 | + |
| 42 | + // build preview and cancel buttons and add click events |
| 43 | + var $preview = $( '<input type="button" value="Preview" style="width: 60px; margin-left: ' + (3) + 'px;" class="preview"/>' ); |
| 44 | + var $cancel = $( '<input type="button" value="Cancel" style="width: 60px; margin-left: ' + (60+3+3) + 'px;" class="cancel"/>' ); |
| 45 | + $preview.click( $.inlineEditor.basicEditor.preview ); |
| 46 | + $cancel.click( $.inlineEditor.basicEditor.cancel ); |
| 47 | + |
| 48 | + // build the edit bar from the input field and buttons |
| 49 | + var $editBar = $( '<span class="editbar" style="width: ' + width + 'px"></span>' ); |
| 50 | + $editBar.append( $input ); |
| 51 | + $editBar.append( $preview ); |
| 52 | + $editBar.append( $cancel ); |
| 53 | + |
| 54 | + // append the edit bar to the new span |
| 55 | + $newSpan.append( $editBar ); |
| 56 | + |
| 57 | + // automatically resize the textarea using the Elastic plugin |
| 58 | + $input.elastic(); |
| 59 | + |
| 60 | + // focus on the input so you can start typing immediately |
| 61 | + $input.focus(); |
| 62 | + |
| 63 | + return $editBar; |
| 64 | +}, |
| 65 | + |
| 66 | +/** |
| 67 | + * Cancels the current edit operation. |
| 68 | + */ |
| 69 | +cancel: function( event ) { |
| 70 | + // prevent clicks from reaching other elements |
| 71 | + event.stopPropagation(); |
| 72 | + event.preventDefault(); |
| 73 | + |
| 74 | + // find the outer span, two parents above the buttons |
| 75 | + var $span = $(this).parent().parent(); |
| 76 | + |
| 77 | + // find the span with the original value |
| 78 | + var $orig = $span.children('.orig'); |
| 79 | + |
| 80 | + // convert the span to it's original state |
| 81 | + $orig.removeClass( 'orig' ); |
| 82 | + |
| 83 | + // place the original span after the current span and remove the current span |
| 84 | + // editing the current span is buggy in Webkit browsers |
| 85 | + $span.after( $orig ); |
| 86 | + $span.remove(); |
| 87 | + |
| 88 | + // highlight the text orange and have it fade to blue again |
| 89 | + // this is a visual indicator to where the element is now |
| 90 | + $orig.addClass( 'lastEdit' ); |
| 91 | + $orig.removeClass( 'lastEdit', 'slow' ); |
| 92 | +}, |
| 93 | + |
| 94 | +/** |
| 95 | + * Previews the current edit operation. |
| 96 | + */ |
| 97 | +preview: function( event ) { |
| 98 | + // prevent clicks from reaching other elements |
| 99 | + event.stopPropagation(); |
| 100 | + event.preventDefault(); |
| 101 | + |
| 102 | + // find the span with class 'editbar', one parent above the buttons |
| 103 | + var $editbar = $(this).parent(); |
| 104 | + |
| 105 | + // the element is one level above the editbar |
| 106 | + var $element = $editbar.parent(); |
| 107 | + |
| 108 | + // add a visual indicator to show the preview is loading |
| 109 | + $element.addClass( 'saving' ); |
| 110 | + var $overlay = $( '<div class="overlay"><div class="alpha"></div><img class="spinner" src="' + wgScriptPath + '/extensions/InlineEditor/ajax-loader.gif"/></div>' ); |
| 111 | + $editbar.append( $overlay ); |
| 112 | + |
| 113 | + // get the edited text and the id to save it to |
| 114 | + text = $editbar.children( 'textarea' ).val(); |
| 115 | + id = $element.children( '.orig' ).attr( 'id' ); |
| 116 | + |
| 117 | + // let the inlineEditor framework handle the preview |
| 118 | + $.inlineEditor.previewTextById( text, id ); |
| 119 | +} |
| 120 | + |
| 121 | +}; } ) ( jQuery ); |
| 122 | + |
| 123 | + |
Property changes on: trunk/extensions/InlineEditor/jquery.inlineEditor.basicEditor.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 124 | + native |
Index: trunk/extensions/InlineEditor/ReferenceEditor/ReferenceEditor.class.php |
— | — | @@ -0,0 +1,46 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Simple editor for references. |
| 5 | + */ |
| 6 | +class ReferenceEditor { |
| 7 | + |
| 8 | + /** |
| 9 | + * This function hooks into InlineEditorMark and marks the references. |
| 10 | + * @param $inlineEditorText InlineEditorText |
| 11 | + */ |
| 12 | + public static function mark( &$inlineEditorText ) { |
| 13 | + // get the original wikitext |
| 14 | + $text = $inlineEditorText->getWikiOriginal(); |
| 15 | + |
| 16 | + $matches = array(); |
| 17 | + preg_match_all( '/<ref[^\/]*?>.*?<\/ref>|<ref.*?\/>/is', $text, $matches, PREG_OFFSET_CAPTURE ); |
| 18 | + |
| 19 | + foreach( $matches[0] as $match ) { |
| 20 | + $start = $match[1]; |
| 21 | + $end = $start + strlen( $match[0] ); |
| 22 | + $inlineEditorText->addPiece( new InlineEditorPiece( $start, $end, 'referenceEditorElement', true ) ); |
| 23 | + } |
| 24 | + |
| 25 | + return true; |
| 26 | + } |
| 27 | + |
| 28 | + /** |
| 29 | + * Hooks into InlineEditorDefineEditors. Adds the option to to the list and adds CSS and JS files |
| 30 | + * @param $editor InlineEditor |
| 31 | + * @param $output OutputPage |
| 32 | + */ |
| 33 | + public static function defineEditors( &$editor, &$output ) { |
| 34 | + global $wgExtensionAssetsPath; |
| 35 | + |
| 36 | + $editor->addEditMode( |
| 37 | + 'referenceEditor', |
| 38 | + wfMsgExt( 'reference-editor-editmode-caption', 'parseinline' ), |
| 39 | + wfMsgExt( 'reference-editor-editmode-description','parseinline' ) |
| 40 | + ); |
| 41 | + |
| 42 | + $output->addExtensionStyle( "$wgExtensionAssetsPath/InlineEditor/ReferenceEditor/ReferenceEditor.css?0"); |
| 43 | + $output->addScriptFile( "$wgExtensionAssetsPath/InlineEditor/ReferenceEditor/jquery.inlineEditor.editors.referenceEditor.js?0" ); |
| 44 | + |
| 45 | + return true; |
| 46 | + } |
| 47 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/ReferenceEditor/ReferenceEditor.class.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 48 | + native |
Index: trunk/extensions/InlineEditor/ReferenceEditor/ReferenceEditor.i18n.php |
— | — | @@ -0,0 +1,26 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Internationalisation file for extension ReferenceEditor. |
| 5 | + * |
| 6 | + * @file |
| 7 | + * @ingroup Extensions |
| 8 | + */ |
| 9 | + |
| 10 | +$messages = array(); |
| 11 | + |
| 12 | +/** English |
| 13 | + * @author Jan Paul Posma |
| 14 | + */ |
| 15 | +$messages['en'] = array( |
| 16 | + 'reference-editor-desc' => 'Adds the "References" edit mode for the InlineEditor', |
| 17 | + |
| 18 | + 'reference-editor-editmode-caption' => "References", |
| 19 | + 'reference-editor-editmode-description' => " |
| 20 | +References are placed after a piece of text. |
| 21 | +You can edit them in this mode, and add new references in the '''Text''' mode. |
| 22 | + |
| 23 | +:<code><nowiki>According to scientists, the Sun is pretty big. <ref>E. Miller, The Sun, (New York: Academic Press, 2005), 23-5.</ref></nowiki></code> |
| 24 | + |
| 25 | +[http://www.mediawiki.org/wiki/Extension:Cite/Cite.php More information] |
| 26 | +", |
| 27 | +); |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/ReferenceEditor/ReferenceEditor.i18n.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 28 | + native |
Index: trunk/extensions/InlineEditor/ReferenceEditor/jquery.inlineEditor.editors.referenceEditor.js |
— | — | @@ -0,0 +1,40 @@ |
| 2 | +/** |
| 3 | + * Client side part of the ReferenceEditor. Defines $.inlineEditor.editors.referenceEditor. |
| 4 | + */ |
| 5 | +( function( $ ) { $.inlineEditor.editors.referenceEditor = { |
| 6 | + |
| 7 | +click: function(event) { |
| 8 | + // prevent clicks from reaching other elements |
| 9 | + event.stopPropagation(); |
| 10 | + event.preventDefault(); |
| 11 | + |
| 12 | + // find the element and retrieve the corresponding wikitext |
| 13 | + var $field = $(this); |
| 14 | + var wiki = $.inlineEditor.getTextById( $field.attr( 'id' ) ); |
| 15 | + |
| 16 | + $newField = $.inlineEditor.basicEditor.newField( $field, $.inlineEditor.editors.referenceEditor.click ); |
| 17 | + $.inlineEditor.basicEditor.addEditBar( $newField, 500, wiki ); |
| 18 | +}, |
| 19 | + |
| 20 | +enable: function() { |
| 21 | + // do what we also do when reloading the page |
| 22 | + $.inlineEditor.editors.referenceEditor.reload(); |
| 23 | + |
| 24 | + // add the identifying class to #editContent |
| 25 | + $( '#editContent' ).addClass( 'referenceEditor' ); |
| 26 | +}, |
| 27 | + |
| 28 | +reload: function() { |
| 29 | + // make references clickable |
| 30 | + $( '.referenceEditorElement' ).click( $.inlineEditor.editors.referenceEditor.click ); |
| 31 | +}, |
| 32 | + |
| 33 | +disable: function() { |
| 34 | + // remove the click event from the references |
| 35 | + $( '.referenceEditorElement' ).unbind( 'click' ); |
| 36 | + |
| 37 | + // remove the identifying class from #editContent |
| 38 | + $( '#editContent' ).removeClass( 'referenceEditor' ); |
| 39 | +} |
| 40 | + |
| 41 | +}; } ) ( jQuery ); |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/ReferenceEditor/jquery.inlineEditor.editors.referenceEditor.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 42 | + native |
Index: trunk/extensions/InlineEditor/ReferenceEditor/ReferenceEditor.php |
— | — | @@ -0,0 +1,41 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * ReferenceEditor extension for the InlineEditor. |
| 5 | + * |
| 6 | + * @file |
| 7 | + * @ingroup Extensions |
| 8 | + * |
| 9 | + * This is the include file for the ReferenceEditor. |
| 10 | + * |
| 11 | + * Usage: Include the following line in your LocalSettings.php |
| 12 | + * require_once( "$IP/extensions/InlineEditor/ReferenceEditor/ReferenceEditor.php" ); |
| 13 | + * |
| 14 | + * @author Jan Paul Posma <jp.posma@gmail.com> |
| 15 | + * @license GPL v2 or later |
| 16 | + * @version 0.0.0 |
| 17 | + */ |
| 18 | + |
| 19 | +if ( !defined( 'MEDIAWIKI' ) ) die(); |
| 20 | + |
| 21 | +// credits |
| 22 | +$wgExtensionCredits['other'][] = array( |
| 23 | + 'path' => __FILE__, |
| 24 | + 'name' => 'ReferenceEditor', |
| 25 | + 'author' => array( 'Jan Paul Posma' ), |
| 26 | + 'version' => '0.1.0', |
| 27 | + 'url' => 'http://www.mediawiki.org/wiki/Extension:InlineEditor#ReferenceEditor', |
| 28 | + 'descriptionmsg' => 'reference-editor-desc', |
| 29 | +); |
| 30 | + |
| 31 | +// current directory including trailing slash |
| 32 | +$dir = dirname( __FILE__ ) . '/'; |
| 33 | + |
| 34 | +// add autoload classes |
| 35 | +$wgAutoloadClasses['ReferenceEditor'] = $dir . 'ReferenceEditor.class.php'; |
| 36 | + |
| 37 | +// register hooks |
| 38 | +$wgHooks['InlineEditorMark'][] = 'ReferenceEditor::mark'; |
| 39 | +$wgHooks['InlineEditorDefineEditors'][] = 'ReferenceEditor::defineEditors'; |
| 40 | + |
| 41 | +// i18n messages |
| 42 | +$wgExtensionMessagesFiles['ReferenceEditor'] = $dir . 'ReferenceEditor.i18n.php'; |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/ReferenceEditor/ReferenceEditor.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 43 | + native |
Index: trunk/extensions/InlineEditor/ReferenceEditor/ReferenceEditor.css |
— | — | @@ -0,0 +1,35 @@ |
| 2 | +.referenceEditor .referenceEditorElement { |
| 3 | + /* soft-blue background color to highlight editable references */ |
| 4 | + background-color: #E4F0F9; |
| 5 | + |
| 6 | + /* create a hand cursor, cross-browser hack: http://www.quirksmode.org/css/cursor.html */ |
| 7 | + cursor: pointer; |
| 8 | + cursor: hand; |
| 9 | + |
| 10 | + /* add a lot of padding to make them stand out */ |
| 11 | + padding: 0.5em; |
| 12 | +} |
| 13 | + |
| 14 | +.referenceEditor .referenceEditorElement:hover { |
| 15 | + /* indicate the reference to be edited with a darker color */ |
| 16 | + background-color: #a7d7f9; |
| 17 | +} |
| 18 | + |
| 19 | +.referenceEditor .editing { |
| 20 | + /* keeping the custom padding and margin breaks in Webkit browsers */ |
| 21 | + padding: 0px; |
| 22 | + margin: 0px; |
| 23 | + |
| 24 | + /* reset the cursor when editing */ |
| 25 | + cursor: auto; |
| 26 | +} |
| 27 | + |
| 28 | +.referenceEditor .edited { |
| 29 | + /* have a yellow color to highlight edited elements, basically the orange color with the hue shifted */ |
| 30 | + background-color: #F9F2A7; |
| 31 | +} |
| 32 | + |
| 33 | +.referenceEditor .lastEdit { |
| 34 | + /* have an orange color, the exact complement of the hover color, for highlighting on preview/cancel */ |
| 35 | + background-color: #f9c9a7; |
| 36 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/ReferenceEditor/ReferenceEditor.css |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 37 | + native |
Index: trunk/extensions/InlineEditor/FullEditor/FullEditor.php |
— | — | @@ -0,0 +1,40 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * FullEditor extension for the InlineEditor. |
| 5 | + * |
| 6 | + * @file |
| 7 | + * @ingroup Extensions |
| 8 | + * |
| 9 | + * This is the include file for the FullEditor. |
| 10 | + * |
| 11 | + * Usage: Include the following line in your LocalSettings.php |
| 12 | + * require_once( "$IP/extensions/InlineEditor/FullEditor/FullEditor.php" ); |
| 13 | + * |
| 14 | + * @author Jan Paul Posma <jp.posma@gmail.com> |
| 15 | + * @license GPL v2 or later |
| 16 | + * @version 0.0.0 |
| 17 | + */ |
| 18 | + |
| 19 | +if ( !defined( 'MEDIAWIKI' ) ) die(); |
| 20 | + |
| 21 | +// credits |
| 22 | +$wgExtensionCredits['other'][] = array( |
| 23 | + 'path' => __FILE__, |
| 24 | + 'name' => 'FullEditor', |
| 25 | + 'author' => array( 'Jan Paul Posma' ), |
| 26 | + 'version' => '0.1.0', |
| 27 | + 'url' => 'http://www.mediawiki.org/wiki/Extension:InlineEditor#FullEditor', |
| 28 | + 'descriptionmsg' => 'fulleditor-desc', |
| 29 | +); |
| 30 | + |
| 31 | +// current directory including trailing slash |
| 32 | +$dir = dirname( __FILE__ ) . '/'; |
| 33 | + |
| 34 | +// add autoload classes |
| 35 | +$wgAutoloadClasses['FullEditor'] = $dir . 'FullEditor.class.php'; |
| 36 | + |
| 37 | +// register hooks |
| 38 | +$wgHooks['InlineEditorDefineEditors'][] = 'FullEditor::defineEditors'; |
| 39 | + |
| 40 | +// i18n messages |
| 41 | +$wgExtensionMessagesFiles['FullEditor'] = $dir . 'FullEditor.i18n.php'; |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/FullEditor/FullEditor.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 42 | + native |
Index: trunk/extensions/InlineEditor/FullEditor/FullEditor.class.php |
— | — | @@ -0,0 +1,17 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * This 'editor' just shows some description with a link to the full/traditional editor. |
| 5 | + */ |
| 6 | +class FullEditor { |
| 7 | + public static function defineEditors( &$editor, &$output ) { |
| 8 | + $editor->addEditMode( |
| 9 | + 'FullEditor', |
| 10 | + wfMsgExt( 'fulleditor-editmode-caption', 'parseinline' ), |
| 11 | + wfMsgExt( 'fulleditor-editmode-description', 'parseinline' ) |
| 12 | + . '<br/><a class="fulleditor" href="' . $editor->getArticle()->getTitle()->getLocalURL( 'action=edit&fulleditor=1' ) . '">' |
| 13 | + . wfMsgExt( 'fulleditor-editmode-description-link', 'parseinline' ) |
| 14 | + . '</a>' |
| 15 | + ); |
| 16 | + return true; |
| 17 | + } |
| 18 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/FullEditor/FullEditor.class.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 19 | + native |
Index: trunk/extensions/InlineEditor/FullEditor/FullEditor.i18n.php |
— | — | @@ -0,0 +1,23 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Internationalisation file for extension FullEditor. |
| 5 | + * |
| 6 | + * @file |
| 7 | + * @ingroup Extensions |
| 8 | + */ |
| 9 | + |
| 10 | +$messages = array(); |
| 11 | + |
| 12 | +/** English |
| 13 | + * @author Jan Paul Posma |
| 14 | + */ |
| 15 | +$messages['en'] = array( |
| 16 | + 'fulleditor-desc' => 'Provides a link to the full editor for the InlineEditor', |
| 17 | + |
| 18 | + 'fulleditor-editmode-caption' => 'Full editor', |
| 19 | + 'fulleditor-editmode-description' => " |
| 20 | +If you want full control over the page, you can use the full editor. |
| 21 | +With this editor you can edit the [http://en.wikipedia.org/wiki/Help:Wiki_markup Wiki markup] directly. |
| 22 | +The editor is also more complex to use, but to have full control of editing Wikipedia, that's worth it!", |
| 23 | + 'fulleditor-editmode-description-link' => 'Use the full editor »', |
| 24 | +); |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/FullEditor/FullEditor.i18n.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 25 | + native |
Index: trunk/extensions/InlineEditor/jquery-ui-effects-1.8.4.min.js |
— | — | @@ -0,0 +1,31 @@ |
| 2 | +/* |
| 3 | + * jQuery UI Effects 1.8.4 |
| 4 | + * |
| 5 | + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) |
| 6 | + * Dual licensed under the MIT or GPL Version 2 licenses. |
| 7 | + * http://jquery.org/license |
| 8 | + * |
| 9 | + * http://docs.jquery.com/UI/Effects/ |
| 10 | + */ |
| 11 | +jQuery.effects||function(f,j){function l(c){var a;if(c&&c.constructor==Array&&c.length==3)return c;if(a=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(c))return[parseInt(a[1],10),parseInt(a[2],10),parseInt(a[3],10)];if(a=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(c))return[parseFloat(a[1])*2.55,parseFloat(a[2])*2.55,parseFloat(a[3])*2.55];if(a=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(c))return[parseInt(a[1], |
| 12 | +16),parseInt(a[2],16),parseInt(a[3],16)];if(a=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(c))return[parseInt(a[1]+a[1],16),parseInt(a[2]+a[2],16),parseInt(a[3]+a[3],16)];if(/rgba\(0, 0, 0, 0\)/.exec(c))return m.transparent;return m[f.trim(c).toLowerCase()]}function r(c,a){var b;do{b=f.curCSS(c,a);if(b!=""&&b!="transparent"||f.nodeName(c,"body"))break;a="backgroundColor"}while(c=c.parentNode);return l(b)}function n(){var c=document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle, |
| 13 | +a={},b,d;if(c&&c.length&&c[0]&&c[c[0]])for(var e=c.length;e--;){b=c[e];if(typeof c[b]=="string"){d=b.replace(/\-(\w)/g,function(g,h){return h.toUpperCase()});a[d]=c[b]}}else for(b in c)if(typeof c[b]==="string")a[b]=c[b];return a}function o(c){var a,b;for(a in c){b=c[a];if(b==null||f.isFunction(b)||a in s||/scrollbar/.test(a)||!/color/i.test(a)&&isNaN(parseFloat(b)))delete c[a]}return c}function t(c,a){var b={_:0},d;for(d in a)if(c[d]!=a[d])b[d]=a[d];return b}function k(c,a,b,d){if(typeof c=="object"){d= |
| 14 | +a;b=null;a=c;c=a.effect}if(f.isFunction(a)){d=a;b=null;a={}}if(typeof a=="number"||f.fx.speeds[a]){d=b;b=a;a={}}if(f.isFunction(b)){d=b;b=null}a=a||{};b=b||a.duration;b=f.fx.off?0:typeof b=="number"?b:f.fx.speeds[b]||f.fx.speeds._default;d=d||a.complete;return[c,a,b,d]}f.effects={};f.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor","borderTopColor","color","outlineColor"],function(c,a){f.fx.step[a]=function(b){if(!b.colorInit){b.start=r(b.elem,a);b.end=l(b.end);b.colorInit= |
| 15 | +true}b.elem.style[a]="rgb("+Math.max(Math.min(parseInt(b.pos*(b.end[0]-b.start[0])+b.start[0],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[1]-b.start[1])+b.start[1],10),255),0)+","+Math.max(Math.min(parseInt(b.pos*(b.end[2]-b.start[2])+b.start[2],10),255),0)+")"}});var m={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189, |
| 16 | +183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255, |
| 17 | +165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]},p=["add","remove","toggle"],s={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};f.effects.animateClass=function(c,a,b,d){if(f.isFunction(b)){d=b;b=null}return this.each(function(){var e=f(this),g=e.attr("style")||" ",h=o(n.call(this)),q,u=e.attr("className");f.each(p,function(v, |
| 18 | +i){c[i]&&e[i+"Class"](c[i])});q=o(n.call(this));e.attr("className",u);e.animate(t(h,q),a,b,function(){f.each(p,function(v,i){c[i]&&e[i+"Class"](c[i])});if(typeof e.attr("style")=="object"){e.attr("style").cssText="";e.attr("style").cssText=g}else e.attr("style",g);d&&d.apply(this,arguments)})})};f.fn.extend({_addClass:f.fn.addClass,addClass:function(c,a,b,d){return a?f.effects.animateClass.apply(this,[{add:c},a,b,d]):this._addClass(c)},_removeClass:f.fn.removeClass,removeClass:function(c,a,b,d){return a? |
| 19 | +f.effects.animateClass.apply(this,[{remove:c},a,b,d]):this._removeClass(c)},_toggleClass:f.fn.toggleClass,toggleClass:function(c,a,b,d,e){return typeof a=="boolean"||a===j?b?f.effects.animateClass.apply(this,[a?{add:c}:{remove:c},b,d,e]):this._toggleClass(c,a):f.effects.animateClass.apply(this,[{toggle:c},a,b,d])},switchClass:function(c,a,b,d,e){return f.effects.animateClass.apply(this,[{add:a,remove:c},b,d,e])}});f.extend(f.effects,{version:"1.8.4",save:function(c,a){for(var b=0;b<a.length;b++)a[b]!== |
| 20 | +null&&c.data("ec.storage."+a[b],c[0].style[a[b]])},restore:function(c,a){for(var b=0;b<a.length;b++)a[b]!==null&&c.css(a[b],c.data("ec.storage."+a[b]))},setMode:function(c,a){if(a=="toggle")a=c.is(":hidden")?"show":"hide";return a},getBaseline:function(c,a){var b;switch(c[0]){case "top":b=0;break;case "middle":b=0.5;break;case "bottom":b=1;break;default:b=c[0]/a.height}switch(c[1]){case "left":c=0;break;case "center":c=0.5;break;case "right":c=1;break;default:c=c[1]/a.width}return{x:c,y:b}},createWrapper:function(c){if(c.parent().is(".ui-effects-wrapper"))return c.parent(); |
| 21 | +var a={width:c.outerWidth(true),height:c.outerHeight(true),"float":c.css("float")},b=f("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0});c.wrap(b);b=c.parent();if(c.css("position")=="static"){b.css({position:"relative"});c.css({position:"relative"})}else{f.extend(a,{position:c.css("position"),zIndex:c.css("z-index")});f.each(["top","left","bottom","right"],function(d,e){a[e]=c.css(e);if(isNaN(parseInt(a[e],10)))a[e]="auto"}); |
| 22 | +c.css({position:"relative",top:0,left:0})}return b.css(a).show()},removeWrapper:function(c){if(c.parent().is(".ui-effects-wrapper"))return c.parent().replaceWith(c);return c},setTransition:function(c,a,b,d){d=d||{};f.each(a,function(e,g){unit=c.cssUnit(g);if(unit[0]>0)d[g]=unit[0]*b+unit[1]});return d}});f.fn.extend({effect:function(c){var a=k.apply(this,arguments);a={options:a[1],duration:a[2],callback:a[3]};var b=f.effects[c];return b&&!f.fx.off?b.call(this,a):this},_show:f.fn.show,show:function(c){if(!c|| |
| 23 | +typeof c=="number"||f.fx.speeds[c])return this._show.apply(this,arguments);else{var a=k.apply(this,arguments);a[1].mode="show";return this.effect.apply(this,a)}},_hide:f.fn.hide,hide:function(c){if(!c||typeof c=="number"||f.fx.speeds[c])return this._hide.apply(this,arguments);else{var a=k.apply(this,arguments);a[1].mode="hide";return this.effect.apply(this,a)}},__toggle:f.fn.toggle,toggle:function(c){if(!c||typeof c=="number"||f.fx.speeds[c]||typeof c=="boolean"||f.isFunction(c))return this.__toggle.apply(this, |
| 24 | +arguments);else{var a=k.apply(this,arguments);a[1].mode="toggle";return this.effect.apply(this,a)}},cssUnit:function(c){var a=this.css(c),b=[];f.each(["em","px","%","pt"],function(d,e){if(a.indexOf(e)>0)b=[parseFloat(a),e]});return b}});f.easing.jswing=f.easing.swing;f.extend(f.easing,{def:"easeOutQuad",swing:function(c,a,b,d,e){return f.easing[f.easing.def](c,a,b,d,e)},easeInQuad:function(c,a,b,d,e){return d*(a/=e)*a+b},easeOutQuad:function(c,a,b,d,e){return-d*(a/=e)*(a-2)+b},easeInOutQuad:function(c, |
| 25 | +a,b,d,e){if((a/=e/2)<1)return d/2*a*a+b;return-d/2*(--a*(a-2)-1)+b},easeInCubic:function(c,a,b,d,e){return d*(a/=e)*a*a+b},easeOutCubic:function(c,a,b,d,e){return d*((a=a/e-1)*a*a+1)+b},easeInOutCubic:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a+b;return d/2*((a-=2)*a*a+2)+b},easeInQuart:function(c,a,b,d,e){return d*(a/=e)*a*a*a+b},easeOutQuart:function(c,a,b,d,e){return-d*((a=a/e-1)*a*a*a-1)+b},easeInOutQuart:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a+b;return-d/2*((a-=2)*a*a*a-2)+ |
| 26 | +b},easeInQuint:function(c,a,b,d,e){return d*(a/=e)*a*a*a*a+b},easeOutQuint:function(c,a,b,d,e){return d*((a=a/e-1)*a*a*a*a+1)+b},easeInOutQuint:function(c,a,b,d,e){if((a/=e/2)<1)return d/2*a*a*a*a*a+b;return d/2*((a-=2)*a*a*a*a+2)+b},easeInSine:function(c,a,b,d,e){return-d*Math.cos(a/e*(Math.PI/2))+d+b},easeOutSine:function(c,a,b,d,e){return d*Math.sin(a/e*(Math.PI/2))+b},easeInOutSine:function(c,a,b,d,e){return-d/2*(Math.cos(Math.PI*a/e)-1)+b},easeInExpo:function(c,a,b,d,e){return a==0?b:d*Math.pow(2, |
| 27 | +10*(a/e-1))+b},easeOutExpo:function(c,a,b,d,e){return a==e?b+d:d*(-Math.pow(2,-10*a/e)+1)+b},easeInOutExpo:function(c,a,b,d,e){if(a==0)return b;if(a==e)return b+d;if((a/=e/2)<1)return d/2*Math.pow(2,10*(a-1))+b;return d/2*(-Math.pow(2,-10*--a)+2)+b},easeInCirc:function(c,a,b,d,e){return-d*(Math.sqrt(1-(a/=e)*a)-1)+b},easeOutCirc:function(c,a,b,d,e){return d*Math.sqrt(1-(a=a/e-1)*a)+b},easeInOutCirc:function(c,a,b,d,e){if((a/=e/2)<1)return-d/2*(Math.sqrt(1-a*a)-1)+b;return d/2*(Math.sqrt(1-(a-=2)* |
| 28 | +a)+1)+b},easeInElastic:function(c,a,b,d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e)==1)return b+d;g||(g=e*0.3);if(h<Math.abs(d)){h=d;c=g/4}else c=g/(2*Math.PI)*Math.asin(d/h);return-(h*Math.pow(2,10*(a-=1))*Math.sin((a*e-c)*2*Math.PI/g))+b},easeOutElastic:function(c,a,b,d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e)==1)return b+d;g||(g=e*0.3);if(h<Math.abs(d)){h=d;c=g/4}else c=g/(2*Math.PI)*Math.asin(d/h);return h*Math.pow(2,-10*a)*Math.sin((a*e-c)*2*Math.PI/g)+d+b},easeInOutElastic:function(c, |
| 29 | +a,b,d,e){c=1.70158;var g=0,h=d;if(a==0)return b;if((a/=e/2)==2)return b+d;g||(g=e*0.3*1.5);if(h<Math.abs(d)){h=d;c=g/4}else c=g/(2*Math.PI)*Math.asin(d/h);if(a<1)return-0.5*h*Math.pow(2,10*(a-=1))*Math.sin((a*e-c)*2*Math.PI/g)+b;return h*Math.pow(2,-10*(a-=1))*Math.sin((a*e-c)*2*Math.PI/g)*0.5+d+b},easeInBack:function(c,a,b,d,e,g){if(g==j)g=1.70158;return d*(a/=e)*a*((g+1)*a-g)+b},easeOutBack:function(c,a,b,d,e,g){if(g==j)g=1.70158;return d*((a=a/e-1)*a*((g+1)*a+g)+1)+b},easeInOutBack:function(c, |
| 30 | +a,b,d,e,g){if(g==j)g=1.70158;if((a/=e/2)<1)return d/2*a*a*(((g*=1.525)+1)*a-g)+b;return d/2*((a-=2)*a*(((g*=1.525)+1)*a+g)+2)+b},easeInBounce:function(c,a,b,d,e){return d-f.easing.easeOutBounce(c,e-a,0,d,e)+b},easeOutBounce:function(c,a,b,d,e){return(a/=e)<1/2.75?d*7.5625*a*a+b:a<2/2.75?d*(7.5625*(a-=1.5/2.75)*a+0.75)+b:a<2.5/2.75?d*(7.5625*(a-=2.25/2.75)*a+0.9375)+b:d*(7.5625*(a-=2.625/2.75)*a+0.984375)+b},easeInOutBounce:function(c,a,b,d,e){if(a<e/2)return f.easing.easeInBounce(c,a*2,0,d,e)*0.5+ |
| 31 | +b;return f.easing.easeOutBounce(c,a*2-e,0,d,e)*0.5+d*0.5+b}})}(jQuery); |
| 32 | +; |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/jquery-ui-effects-1.8.4.min.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 33 | + native |
Added: svn:executable |
2 | 34 | + * |
Index: trunk/extensions/InlineEditor/SentenceEditor/SentenceEditor.i18n.php |
— | — | @@ -0,0 +1,42 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Internationalisation file for extension SentenceEditor. |
| 5 | + * |
| 6 | + * @file |
| 7 | + * @ingroup Extensions |
| 8 | + */ |
| 9 | + |
| 10 | +$messages = array(); |
| 11 | + |
| 12 | +/** English |
| 13 | + * @author Jan Paul Posma |
| 14 | + */ |
| 15 | +$messages['en'] = array( |
| 16 | + 'sentence-editor-desc' => 'Adds the "Text" edit mode for the InlineEditor', |
| 17 | + |
| 18 | + 'sentence-editor-editmode-caption' => "Text", |
| 19 | +/* |
| 20 | + 'sentence-editor-editmode-description' => " |
| 21 | +There are a few [http://en.wikipedia.org/wiki/Wikipedia:Simplified_ruleset guidelines] for editing an article:<br/> |
| 22 | +* Write what you think is best for the article, or as we say here: [http://en.wikipedia.org/wiki/Wikipedia:Be_bold be bold when updating pages]! If you feel that a rule prevents you from improving Wikipedia, [http://en.wikipedia.org/wiki/Wikipedia:Ignore_all_rules ignore it]. |
| 23 | +* [http://en.wikipedia.org/wiki/Wikipedia:What_Wikipedia_is_not Wikipedia is an encyclopedia.] Someone else should be able to [http://en.wikipedia.org/wiki/Wikipedia:Verifiability verify] what you've written, for example in books or online. |
| 24 | +* Write from a [http://en.wikipedia.org/wiki/Wikipedia:Neutral_point_of_view neutral point of view], and use your [http://en.wikipedia.org/wiki/Wikipedia:Copyrights own words]. |
| 25 | + ", |
| 26 | +*/ |
| 27 | + 'sentence-editor-editmode-description' => " |
| 28 | +Edit sentences by clicking on them. You can use wiki syntax to format the text. Some examples: |
| 29 | +{| width=\"100%\" style=\"background-color: inherit\" |
| 30 | +! Code |
| 31 | +! Output |
| 32 | +|- |
| 33 | +| <code><nowiki>Here's a link to the [[Main Page]].</nowiki></code> |
| 34 | +| Here's a link to the [[Main Page]]. |
| 35 | +|- |
| 36 | +| <code><nowiki>This is ''italic text'' and this is '''bold text'''.</nowiki></code> |
| 37 | +| This is ''italic text'' and this is '''bold text'''. |
| 38 | +|- |
| 39 | +| <code><nowiki>[http://meta.wikimedia.org/wiki/Help:Editing More information]</nowiki></code> |
| 40 | +| [http://meta.wikimedia.org/wiki/Help:Editing More information] |
| 41 | +|} |
| 42 | + ", |
| 43 | +); |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/SentenceEditor/SentenceEditor.i18n.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 44 | + native |
Index: trunk/extensions/InlineEditor/SentenceEditor/jquery.inlineEditor.editors.sentenceEditor.js |
— | — | @@ -0,0 +1,46 @@ |
| 2 | +/** |
| 3 | + * Client side part of the SentenceEditor. Defines $.inlineEditor.editors.sentenceEditor, |
| 4 | + * and uses $.elastic and $.textWidth. |
| 5 | + */ |
| 6 | +( function( $ ) { $.inlineEditor.editors.sentenceEditor = { |
| 7 | + |
| 8 | +click: function(event) { |
| 9 | + // prevent clicks from reaching other elements |
| 10 | + event.stopPropagation(); |
| 11 | + event.preventDefault(); |
| 12 | + |
| 13 | + // find the <span> element and retrieve the corresponding wikitext |
| 14 | + var $span = $(this); |
| 15 | + var wiki = $.inlineEditor.getTextById( $span.attr( 'id' ) ); |
| 16 | + |
| 17 | + // calculate width based on the text width witin the page flow |
| 18 | + // this means that this width will never exeed the original width when it's a multiline sentence |
| 19 | + var width = $span.textWidth() - 5; |
| 20 | + if( width < 300 ) width = 300; |
| 21 | + |
| 22 | + $newField = $.inlineEditor.basicEditor.newField( $span, $.inlineEditor.editors.sentenceEditor.click ); |
| 23 | + $.inlineEditor.basicEditor.addEditBar( $newField, width, wiki ); |
| 24 | +}, |
| 25 | + |
| 26 | +enable: function() { |
| 27 | + // do what we also do when reloading the page |
| 28 | + $.inlineEditor.editors.sentenceEditor.reload(); |
| 29 | + |
| 30 | + // add the identifying class to #editContent |
| 31 | + $( '#editContent' ).addClass( 'sentenceEditor' ); |
| 32 | +}, |
| 33 | + |
| 34 | +reload: function() { |
| 35 | + // make sentences clickable |
| 36 | + $( '.sentenceEditorElement' ).click( $.inlineEditor.editors.sentenceEditor.click ); |
| 37 | +}, |
| 38 | + |
| 39 | +disable: function() { |
| 40 | + // remove the click event from the sentences |
| 41 | + $( '.sentenceEditorElement' ).unbind( 'click' ); |
| 42 | + |
| 43 | + // remove the identifying class from #editContent |
| 44 | + $( '#editContent' ).removeClass( 'sentenceEditor' ); |
| 45 | +} |
| 46 | + |
| 47 | +}; } ) ( jQuery ); |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/SentenceEditor/jquery.inlineEditor.editors.sentenceEditor.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 48 | + native |
Index: trunk/extensions/InlineEditor/SentenceEditor/SentenceEditor.php |
— | — | @@ -0,0 +1,46 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * SentenceEditor extension for the InlineEditor. |
| 5 | + * |
| 6 | + * @file |
| 7 | + * @ingroup Extensions |
| 8 | + * |
| 9 | + * This is the include file for the SentenceEditor. |
| 10 | + * |
| 11 | + * Usage: Include the following line in your LocalSettings.php |
| 12 | + * require_once( "$IP/extensions/InlineEditor/SentenceEditor/SentenceEditor.php" ); |
| 13 | + * |
| 14 | + * @author Jan Paul Posma <jp.posma@gmail.com> |
| 15 | + * @license GPL v2 or later |
| 16 | + * @version 0.0.0 |
| 17 | + */ |
| 18 | + |
| 19 | +if ( !defined( 'MEDIAWIKI' ) ) die(); |
| 20 | + |
| 21 | +// credits |
| 22 | +$wgExtensionCredits['other'][] = array( |
| 23 | + 'path' => __FILE__, |
| 24 | + 'name' => 'SentenceEditor', |
| 25 | + 'author' => array( 'Jan Paul Posma' ), |
| 26 | + 'version' => '0.1.0', |
| 27 | + 'url' => 'http://www.mediawiki.org/wiki/Extension:InlineEditor#SentenceEditor', |
| 28 | + 'descriptionmsg' => 'sentence-editor-desc', |
| 29 | +); |
| 30 | + |
| 31 | +// current directory including trailing slash |
| 32 | +$dir = dirname( __FILE__ ) . '/'; |
| 33 | + |
| 34 | +// add autoload classes |
| 35 | +$wgAutoloadClasses['SentenceEditor'] = $dir . 'SentenceEditor.class.php'; |
| 36 | +$wgAutoloadClasses['ISentenceDetection'] = $dir . 'SentenceDetection/ISentenceDetection.class.php'; |
| 37 | +$wgAutoloadClasses['SentenceDetectionBasic'] = $dir . 'SentenceDetection/SentenceDetectionBasic.class.php'; |
| 38 | + |
| 39 | +// register hooks |
| 40 | +$wgHooks['InlineEditorMark'][] = 'SentenceEditor::mark'; |
| 41 | +$wgHooks['InlineEditorDefineEditors'][] = 'SentenceEditor::defineEditors'; |
| 42 | + |
| 43 | +// i18n messages |
| 44 | +$wgExtensionMessagesFiles['SentenceEditor'] = $dir . 'SentenceEditor.i18n.php'; |
| 45 | + |
| 46 | +// default settings |
| 47 | +$wgSentenceEditorDetectionDefault = 'SentenceDetectionBasic'; |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/SentenceEditor/SentenceEditor.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 48 | + native |
Index: trunk/extensions/InlineEditor/SentenceEditor/SentenceEditor.css |
— | — | @@ -0,0 +1,36 @@ |
| 2 | +.sentenceEditor .sentenceEditorElement { |
| 3 | + /* soft-blue background color to highlight editable sentences */ |
| 4 | + background-color: #E4F0F9; |
| 5 | + |
| 6 | + /* create a hand cursor, cross-browser hack: http://www.quirksmode.org/css/cursor.html */ |
| 7 | + cursor: pointer; |
| 8 | + cursor: hand; |
| 9 | + |
| 10 | + /* have the background color extend just a bit around the text border, looks better */ |
| 11 | + margin: -1px; |
| 12 | + padding: 1px; |
| 13 | +} |
| 14 | + |
| 15 | +.sentenceEditor .sentenceEditorElement:hover { |
| 16 | + /* indicate the sentence to be edited with a darker color */ |
| 17 | + background-color: #a7d7f9; |
| 18 | +} |
| 19 | + |
| 20 | +.sentenceEditor .editing { |
| 21 | + /* keeping the custom padding and margin breaks in Webkit browsers */ |
| 22 | + padding: 0px; |
| 23 | + margin: 0px; |
| 24 | + |
| 25 | + /* reset the cursor when editing */ |
| 26 | + cursor: auto; |
| 27 | +} |
| 28 | + |
| 29 | +.sentenceEditor .edited { |
| 30 | + /* have a yellow color to highlight edited elements, basically the orange color with the hue shifted */ |
| 31 | + background-color: #F9F2A7; |
| 32 | +} |
| 33 | + |
| 34 | +.sentenceEditor .lastEdit { |
| 35 | + /* have an orange color, the exact complement of the hover color, for highlighting on preview/cancel */ |
| 36 | + background-color: #f9c9a7; |
| 37 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/SentenceEditor/SentenceEditor.css |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 38 | + native |
Index: trunk/extensions/InlineEditor/SentenceEditor/SentenceDetection/SentenceDetectionBasic.class.php |
— | — | @@ -0,0 +1,36 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Basic implementation of sentence splitting. Not recommended for actual use, but does the job |
| 5 | + * for a simple demo. |
| 6 | + */ |
| 7 | +class SentenceDetectionBasic implements ISentenceDetection { |
| 8 | + private $wikiTexts; |
| 9 | + |
| 10 | + function __construct() { |
| 11 | + $this->wikiTexts = array(); |
| 12 | + } |
| 13 | + |
| 14 | + public function addWikiText( $text, $offset ) { |
| 15 | + $this->wikiTexts[] = array( 'text' => $text, 'offset' => $offset ); |
| 16 | + } |
| 17 | + |
| 18 | + public function addPiecesToText( InlineEditorText &$inlineEditorText, $class, $inline ) { |
| 19 | + $pieces = array(); |
| 20 | + foreach( $this->wikiTexts as $wikiText ) { |
| 21 | + $sentences = preg_split( "/(?<!\..|\...|\....)([\?\!\.]+)\s(?!.\.|..\.|...\.)/u", $wikiText['text'], -1, |
| 22 | + PREG_SPLIT_OFFSET_CAPTURE | PREG_SPLIT_DELIM_CAPTURE ); |
| 23 | + |
| 24 | + foreach( $sentences as $index => $sentence ) { |
| 25 | + if( $index % 2 == 0 ) { |
| 26 | + if( isset( $sentences[$index+1] ) ) { |
| 27 | + $sentence[0] .= $sentences[$index+1][0]; |
| 28 | + } |
| 29 | + $start = $wikiText['offset'] + $sentence[1]; |
| 30 | + $end = $start + strlen( $sentence[0] ); |
| 31 | + $inlineEditorText->addPiece( new InlineEditorPiece( $start, $end, $class, $inline ) ); |
| 32 | + } |
| 33 | + } |
| 34 | + } |
| 35 | + return $pieces; |
| 36 | + } |
| 37 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/SentenceEditor/SentenceDetection/SentenceDetectionBasic.class.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 38 | + native |
Index: trunk/extensions/InlineEditor/SentenceEditor/SentenceDetection/ISentenceDetection.class.php |
— | — | @@ -0,0 +1,23 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * This interface defines what a sentence detector should be able to do, which is |
| 5 | + * adding portions of wikitext and adding the detected sentences as pieces to an |
| 6 | + * InlineEditorText object. |
| 7 | + */ |
| 8 | +interface ISentenceDetection { |
| 9 | + /** |
| 10 | + * Add a bit of wikitext to the object. The wikitext has to be split in sentences while |
| 11 | + * remembering the position of each sentence. |
| 12 | + * @param $text String |
| 13 | + * @param $position Integer |
| 14 | + */ |
| 15 | + public function addWikiText( $text, $position ); |
| 16 | + |
| 17 | + /** |
| 18 | + * All the sentences and their offsets have to be added as pieces to $inlineEditorText. |
| 19 | + * @param $inlineEditorText InlineEditorText Object the pieces should be added to |
| 20 | + * @param $class String Class name of the piece |
| 21 | + * @param $inline Boolean whether the pieces are inline or not |
| 22 | + */ |
| 23 | + public function addPiecesToText( InlineEditorText &$inlineEditorText, $class, $inline ); |
| 24 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/SentenceEditor/SentenceDetection/ISentenceDetection.class.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 25 | + native |
Index: trunk/extensions/InlineEditor/SentenceEditor/SentenceEditor.class.php |
— | — | @@ -0,0 +1,127 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * This editor allows for editing individual sentences. It strips the wikitext from |
| 5 | + * things that are too hard to edit, and leaves the splitting of sentences to a |
| 6 | + * class that implements the interface ISentenceDetection. |
| 7 | + * |
| 8 | + * It's very much possible to create an extension that inherits from this class to |
| 9 | + * do the detection another way, i.e. without the preprocessing and splitting. |
| 10 | + */ |
| 11 | +class SentenceEditor { |
| 12 | + |
| 13 | + /** |
| 14 | + * This function hooks into InlineEditorMark and marks the sentences. |
| 15 | + * @param $inlineEditorText InlineEditorText |
| 16 | + */ |
| 17 | + public static function mark( &$inlineEditorText ) { |
| 18 | + global $wgSentenceEditorDetectionDefault; |
| 19 | + |
| 20 | + // get the original wikitext |
| 21 | + $text = $inlineEditorText->getWikiOriginal(); |
| 22 | + |
| 23 | + // preprocess the text by replacing everything difficult by spaces |
| 24 | + $text = self::preprocess( $text ); |
| 25 | + |
| 26 | + // split what's left into sensible blocks of text |
| 27 | + $split = self::split( $text ); |
| 28 | + |
| 29 | + // get the default detection class and make it able for extensions to alter it |
| 30 | + $detectionClass = $wgSentenceEditorDetectionDefault; |
| 31 | + wfRunHooks( 'SentenceEditorDetectionClass', array( &$detectionClass ) ); |
| 32 | + |
| 33 | + // spawn the detection class and add the texts and position |
| 34 | + $detection = new $detectionClass(); |
| 35 | + foreach( $split as $wikiText ) { |
| 36 | + // $wikiText[0] is the text, $wikiText[1] is the position of that text |
| 37 | + $detection->addWikiText( $wikiText[0], $wikiText[1] ); |
| 38 | + } |
| 39 | + |
| 40 | + // have the detection class add the pieces to the InlineEditorText object, |
| 41 | + // class 'sentenceEditorElement', inline elements |
| 42 | + $detection->addPiecesToText( $inlineEditorText, 'sentenceEditorElement', true ); |
| 43 | + |
| 44 | + return true; |
| 45 | + } |
| 46 | + |
| 47 | + /** |
| 48 | + * Hooks into InlineEditorDefineEditors. Adds the option to to the list and adds CSS and JS files |
| 49 | + * @param $editor InlineEditor |
| 50 | + * @param $output OutputPage |
| 51 | + */ |
| 52 | + public static function defineEditors( &$editor, &$output ) { |
| 53 | + global $wgExtensionAssetsPath; |
| 54 | + |
| 55 | + $editor->addEditMode( |
| 56 | + 'sentenceEditor', |
| 57 | + wfMsgExt( 'sentence-editor-editmode-caption', 'parseinline' ), |
| 58 | + wfMsgExt( 'sentence-editor-editmode-description','parseinline' ) |
| 59 | + ); |
| 60 | + |
| 61 | + $output->addExtensionStyle( "$wgExtensionAssetsPath/InlineEditor/SentenceEditor/SentenceEditor.css?0"); |
| 62 | + $output->addScriptFile( "$wgExtensionAssetsPath/InlineEditor/SentenceEditor/jquery.inlineEditor.editors.sentenceEditor.js?0" ); |
| 63 | + $output->addScriptFile( "$wgExtensionAssetsPath/InlineEditor/SentenceEditor/jquery.textWidth.js?0" ); |
| 64 | + $output->addScriptFile( "$wgExtensionAssetsPath/InlineEditor/SentenceEditor/jquery.elastic.js?0" ); |
| 65 | + |
| 66 | + return true; |
| 67 | + } |
| 68 | + |
| 69 | + /** |
| 70 | + * Replaces all occurences of unsupported wikitext by spaces. This is to make sure the |
| 71 | + * positions of what's left are still the same as those in the original wikitext |
| 72 | + * @param $wikitext String |
| 73 | + * @return String |
| 74 | + */ |
| 75 | + protected static function preprocess( $wikitext ) { |
| 76 | + $patterns = array(); |
| 77 | + |
| 78 | + // remove references |
| 79 | + $patterns[] = '/(<ref[^>\/]*>.*?<\/ref>)/is'; |
| 80 | + |
| 81 | + // remove references like <ref/> |
| 82 | + $patterns[] = '/(<ref.*?\/>)/i'; |
| 83 | + |
| 84 | + // remove templates starting at the beginning of a line (or with whitespace) |
| 85 | + $patterns[] = '/^\s*(\{\{.*?\}\})/ms'; |
| 86 | + |
| 87 | + // remove tables |
| 88 | + $patterns[] = '/(\{\|.*?\|\})/'; |
| 89 | + |
| 90 | + // remove links with : in it |
| 91 | + $patterns[] = '/(\[\[[^:\[\]]*:[^:\[\]]*\]\])/'; |
| 92 | + |
| 93 | + // remove headings |
| 94 | + $patterns[] = '/^(=+[^=]*=+)\s*$/m'; |
| 95 | + |
| 96 | + // remove lists, indents, things like that |
| 97 | + $patterns[] = '/^[\*#:;](.*)$/m'; |
| 98 | + |
| 99 | + return preg_replace_callback( $patterns, 'SentenceEditor::makeSpaces', $wikitext ); |
| 100 | + } |
| 101 | + |
| 102 | + /** |
| 103 | + * Function used by preprocess() to replace matches with spaces |
| 104 | + * @param $matches array |
| 105 | + * @return String |
| 106 | + */ |
| 107 | + protected static function makeSpaces ( $matches ) { |
| 108 | + return str_repeat( ' ', strlen($matches[0]) ); |
| 109 | + } |
| 110 | + |
| 111 | + /** |
| 112 | + * Splits the wikitext into pieces of actual text. A split is forced where there are |
| 113 | + * two spaces or a newline. This way, it's possible to have the users define the sentences. |
| 114 | + * @param $wikitext String |
| 115 | + * @return array |
| 116 | + */ |
| 117 | + protected static function split( $wikitext ) { |
| 118 | + // split where there are at least two spaces, or a newline, or the beginning of the text |
| 119 | + $splits = preg_split( '/\s\s+|\n\s*|^/', $wikitext, -1, PREG_SPLIT_OFFSET_CAPTURE ); |
| 120 | + |
| 121 | + // remove small occurences |
| 122 | + foreach( $splits as $index => $split ) { |
| 123 | + if( strlen( $split[0] ) < 2 ) unset( $splits[$index] ); |
| 124 | + } |
| 125 | + |
| 126 | + return $splits; |
| 127 | + } |
| 128 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/SentenceEditor/SentenceEditor.class.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 129 | + native |
Index: trunk/extensions/InlineEditor/SentenceEditor/jquery.elastic.js |
— | — | @@ -0,0 +1,6 @@ |
| 2 | +(function(jQuery){jQuery.fn.extend({elastic:function(){var mimics=['paddingTop','paddingRight','paddingBottom','paddingLeft','fontSize','lineHeight','fontFamily','width','fontWeight'];return this.each(function(){if(this.type!='textarea'){return false;} |
| 3 | +var $textarea=jQuery(this),$twin=jQuery('<div />').css({'position':'absolute','display':'none','word-wrap':'break-word'}),lineHeight=parseInt($textarea.css('line-height'),10)||parseInt($textarea.css('font-size'),'10'),minheight=parseInt($textarea.css('height'),10)||lineHeight*3,maxheight=parseInt($textarea.css('max-height'),10)||Number.MAX_VALUE,goalheight=0,i=0;if(maxheight<0){maxheight=Number.MAX_VALUE;} |
| 4 | +$twin.appendTo($textarea.parent());var i=mimics.length;while(i--){$twin.css(mimics[i].toString(),$textarea.css(mimics[i].toString()));} |
| 5 | +function setHeightAndOverflow(height,overflow){curratedHeight=Math.floor(parseInt(height,10));if($textarea.height()!=curratedHeight){$textarea.css({'height':curratedHeight+'px','overflow':overflow});}} |
| 6 | +function update(){var textareaContent=$textarea.val().replace(/&/g,'&').replace(/ /g,' ').replace(/<|>/g,'>').replace(/\n/g,'<br />');var twinContent=$twin.html();if(textareaContent+' '!=twinContent){$twin.html(textareaContent+' ');if(Math.abs($twin.height()+lineHeight-$textarea.height())>3){var goalheight=$twin.height()+lineHeight;if(goalheight>=maxheight){setHeightAndOverflow(maxheight,'auto');}else if(goalheight<=minheight){setHeightAndOverflow(minheight,'hidden');}else{setHeightAndOverflow(goalheight,'hidden');}}}} |
| 7 | +$textarea.css({'overflow':'hidden'});$textarea.keyup(function(){update();});$textarea.live('input paste',function(e){setTimeout(update,250);});update();});}});})(jQuery); |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/SentenceEditor/jquery.elastic.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 8 | + native |
Index: trunk/extensions/InlineEditor/SentenceEditor/jquery.textWidth.js |
— | — | @@ -0,0 +1,33 @@ |
| 2 | +/** |
| 3 | + * Function to determine the actual usable width of a span. |
| 4 | + * This means that the span has to start at the left of the containing element, |
| 5 | + * and the text inside the span may wrap if it gets too long. |
| 6 | + */ |
| 7 | +( function( $ ) { |
| 8 | + $.fn.textWidth = function(){ |
| 9 | + var element = $j(this); |
| 10 | + |
| 11 | + // build an outer element that stretches to the maximum width, so the span will |
| 12 | + // be located to the leftmost position |
| 13 | + var outer = $('<div style="width: 100%"></div>'); |
| 14 | + |
| 15 | + // build a span inside the outer div |
| 16 | + var inner = $('<span></span>'); |
| 17 | + inner.html(element.html()); |
| 18 | + outer.append(inner); |
| 19 | + |
| 20 | + // place the outer div after the original element and hide the original element so it'll |
| 21 | + // be in exactly the same place |
| 22 | + element.after(outer); |
| 23 | + element.hide(); |
| 24 | + |
| 25 | + // calculate the div of the span (which will wrap when it meets the maximum width) |
| 26 | + var width = inner.width(); |
| 27 | + |
| 28 | + // remove the test elements and show the original element again |
| 29 | + outer.remove(); |
| 30 | + element.show(); |
| 31 | + |
| 32 | + return width; |
| 33 | + }; |
| 34 | +} ) ( jQuery ); |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/SentenceEditor/jquery.textWidth.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 35 | + native |
Index: trunk/extensions/InlineEditor/InlineEditor.php |
— | — | @@ -0,0 +1,61 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * InlineEditor extension. |
| 5 | + * |
| 6 | + * @file |
| 7 | + * @ingroup Extensions |
| 8 | + * |
| 9 | + * This is the include file for the InlineEditor. |
| 10 | + * |
| 11 | + * Usage: Include the following line in your LocalSettings.php |
| 12 | + * require_once( "$IP/extensions/InlineEditor.php" ); |
| 13 | + * |
| 14 | + * To enable all provided editors, add this in your LocalSettings.php: |
| 15 | + * require_once( "$IP/extensions/InlineEditor/InlineEditor.php" ); |
| 16 | + * require_once( "$IP/extensions/InlineEditor/SentenceEditor/SentenceEditor.php" ); |
| 17 | + * require_once( "$IP/extensions/InlineEditor/ListEditor/ListEditor.php" ); |
| 18 | + * require_once( "$IP/extensions/InlineEditor/ReferenceEditor/ReferenceEditor.php" ); |
| 19 | + * require_once( "$IP/extensions/InlineEditor/MediaEditor/MediaEditor.php" ); |
| 20 | + * require_once( "$IP/extensions/InlineEditor/TemplateEditor/TemplateEditor.php" ); |
| 21 | + * require_once( "$IP/extensions/InlineEditor/FullEditor/FullEditor.php" ); |
| 22 | + * |
| 23 | + * @author Jan Paul Posma <jp.posma@gmail.com> |
| 24 | + * @license GPL v2 or later |
| 25 | + * @version 0.0.0 |
| 26 | + */ |
| 27 | + |
| 28 | +if ( !defined( 'MEDIAWIKI' ) ) die(); |
| 29 | + |
| 30 | +// credits |
| 31 | +$wgExtensionCredits['other'][] = array( |
| 32 | + 'path' => __FILE__, |
| 33 | + 'name' => 'InlineEditor', |
| 34 | + 'author' => array( 'Jan Paul Posma' ), |
| 35 | + 'version' => '0.1.0', |
| 36 | + 'url' => 'http://www.mediawiki.org/wiki/Extension:InlineEditor', |
| 37 | + 'descriptionmsg' => 'inline-editor-desc', |
| 38 | +); |
| 39 | + |
| 40 | +// current directory including trailing slash |
| 41 | +$dir = dirname(__FILE__) . '/'; |
| 42 | + |
| 43 | +// add autoload classes |
| 44 | +$wgAutoloadClasses['InlineEditor'] = $dir . 'InlineEditor.class.php'; |
| 45 | +$wgAutoloadClasses['InlineEditorText'] = $dir . 'InlineEditorText.class.php'; |
| 46 | +$wgAutoloadClasses['InlineEditorPiece'] = $dir . 'InlineEditorPiece.class.php'; |
| 47 | +$wgAutoloadClasses['InlineEditorPreviousMarking'] = $dir . 'InlineEditorPreviousMarking.class.php'; |
| 48 | +$wgAutoloadClasses['ExtendedEditPage'] = $dir . 'ExtendedEditPage.class.php'; |
| 49 | + |
| 50 | +// register hooks |
| 51 | +$wgHooks['MediaWikiPerformAction'][] = 'InlineEditor::mediaWikiPerformAction'; |
| 52 | +$wgHooks['EditPage::showEditForm:initial'][] = 'InlineEditor::showEditForm'; |
| 53 | + |
| 54 | +// i18n messages |
| 55 | +$wgExtensionMessagesFiles['InlineEditor'] = $dir . 'InlineEditor.i18n.php'; |
| 56 | + |
| 57 | +// ajax functions |
| 58 | +$wgAjaxExportList[] = 'InlineEditor::ajaxPreview'; |
| 59 | + |
| 60 | +// default options |
| 61 | +$wgInlineEditorBrowserBlacklist = $wgBrowserBlackList; |
| 62 | +$wgInlineEditorAllowedNamespaces = array( NS_MAIN, NS_TALK, NS_USER, NS_USER_TALK ); |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/InlineEditor.php |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 63 | + native |
Index: trunk/extensions/InlineEditor/InlineEditor.css |
— | — | @@ -0,0 +1,258 @@ |
| 2 | +/* |
| 3 | + * Right now everything has #siteNotice in front as there's no better way, really, to include the |
| 4 | + * top boxes to the page. |
| 5 | + */ |
| 6 | + |
| 7 | +#siteNotice { |
| 8 | + text-align: inherit; |
| 9 | + font-size: inherit; |
| 10 | +} |
| 11 | + |
| 12 | +#siteNotice div, |
| 13 | +#siteNotice p { |
| 14 | + /* make these elements behave normal again */ |
| 15 | + margin: 0px; |
| 16 | + padding: 0px; |
| 17 | +} |
| 18 | + |
| 19 | +#siteNotice div.editbox { |
| 20 | + /* box on top of the page, colors are the same as the surrounding colors */ |
| 21 | + /* it scales with the display size */ |
| 22 | + font-size: 1.0em; |
| 23 | + background-color: #eaf3f8; |
| 24 | + border: 1px solid #A7D7F9; |
| 25 | + margin-bottom: 10px; |
| 26 | + padding: 10px 10px 5px; |
| 27 | + max-width: 700px; |
| 28 | + position: relative; |
| 29 | +} |
| 30 | + |
| 31 | +#siteNotice div.editbox .highlightExample { |
| 32 | + /* example in the text to show how the highlights look like */ |
| 33 | + background-color: #a7d7f9; |
| 34 | + padding: 1px 3px; |
| 35 | +} |
| 36 | + |
| 37 | +#siteNotice div.editbox input.summary { |
| 38 | + /* summary box, scales with the editbox to a certain point */ |
| 39 | + display: block; |
| 40 | + width: 500px; |
| 41 | + max-width: 98%; |
| 42 | + padding: 2px; |
| 43 | + margin: 2px 0px; |
| 44 | + font-size: 0.8em; |
| 45 | +} |
| 46 | + |
| 47 | +#siteNotice div.editbox .example, .editbox .terms { |
| 48 | + /* smaller font and lighter color for less important items */ |
| 49 | + font-size: 0.8em; |
| 50 | + color: #555; |
| 51 | +} |
| 52 | + |
| 53 | +#siteNotice div.editbox .side { |
| 54 | + /* text besides the publish button */ |
| 55 | + margin-right: 150px; |
| 56 | +} |
| 57 | + |
| 58 | +/*#siteNotice div.editbox*/ #publish { |
| 59 | + /* style the publish button to be eye-catching using a bright green color */ |
| 60 | + background-color: #008C00; |
| 61 | + color: #fff; |
| 62 | + font-size: 1.5em; |
| 63 | + padding: 8px 16px 6px; |
| 64 | + line-height: 1em; |
| 65 | + position: absolute; |
| 66 | + bottom: 10px; |
| 67 | + right: 10px; |
| 68 | + border: 1px solid green; |
| 69 | + |
| 70 | + /* cross (modern) browser rounded corners */ |
| 71 | + border-radius: 10px; |
| 72 | + -moz-border-radius: 10px; |
| 73 | + -webkit-border-radius: 10px; |
| 74 | +} |
| 75 | + |
| 76 | +#siteNotice div.editmode { |
| 77 | + /* style the mode selection box essentially in the same way as the box above */ |
| 78 | + border: 1px solid #A7D7F9; |
| 79 | + padding: 0px; |
| 80 | + max-width: 720px; |
| 81 | + margin-bottom: 10px; |
| 82 | +} |
| 83 | + |
| 84 | +#siteNotice div.editmode .header { |
| 85 | + /* only the header has a blue background color */ |
| 86 | + background-color: #eaf3f8; |
| 87 | + margin: 0px; |
| 88 | + padding: 0px; |
| 89 | + |
| 90 | + /* make sure the header resizes due to the floated elements */ |
| 91 | + overflow: auto; |
| 92 | + |
| 93 | + /* make the bottom borders of the buttons collapse */ |
| 94 | + margin-bottom: -1px; |
| 95 | +} |
| 96 | + |
| 97 | +#siteNotice div.editmode .header .radio, #siteNotice div.editmode .header .button { |
| 98 | + /* margin fix for old IE versions, see http://www.positioniseverything.net/explorer/doubled-margin.html */ |
| 99 | + display: inline; |
| 100 | + float: left; |
| 101 | + |
| 102 | + /* have the borders here, not in the header div, to make sure it looks good on smaller displays! */ |
| 103 | + border-top: 1px solid #A7D7F9; |
| 104 | + border-right: 1px solid #A7D7F9; |
| 105 | + border-bottom: 1px solid #A7D7F9; |
| 106 | + padding: 2px 6px; |
| 107 | + height: 22px; |
| 108 | + |
| 109 | + /* collapse the top border */ |
| 110 | + margin-top: -1px; |
| 111 | +} |
| 112 | + |
| 113 | +#siteNotice div.editmode .header .button { |
| 114 | + /* undo and redo buttons on the right, as well as the counter */ |
| 115 | + float: right; |
| 116 | + border-left: 1px solid #A7D7F9; |
| 117 | + border-right: none; |
| 118 | +} |
| 119 | + |
| 120 | +#siteNotice div.editmode .header .button a { |
| 121 | + font-size: 0.9em; |
| 122 | +} |
| 123 | + |
| 124 | +/*#siteNotice div.editmode .header .button */ #editCounter { |
| 125 | + font-size: 0.9em; |
| 126 | + color: #555; |
| 127 | +} |
| 128 | + |
| 129 | +/*#siteNotice div.editmode .header .button */ #editCounter.changeHighlight { |
| 130 | + color: #eaf3f8; |
| 131 | +} |
| 132 | + |
| 133 | +#siteNotice div.editmode .header .radio input { |
| 134 | + /* use only the padding of .radio div, and the label margin */ |
| 135 | + margin: 0px; |
| 136 | +} |
| 137 | + |
| 138 | +#siteNotice div.editmode .header .title { |
| 139 | + /* bold title on the left side of the header */ |
| 140 | + font-size: 0.9em; |
| 141 | + font-weight: bold; |
| 142 | +} |
| 143 | + |
| 144 | +#siteNotice div.editmode .header .radio label { |
| 145 | + /* only have a small margin on the left side */ |
| 146 | + font-size: 0.9em; |
| 147 | + margin: 0px 0px 0px 5px; |
| 148 | + |
| 149 | + /* create a hand cursor, cross-browser hack: http://www.quirksmode.org/css/cursor.html */ |
| 150 | + cursor: pointer; |
| 151 | + cursor: hand; |
| 152 | +} |
| 153 | + |
| 154 | +#siteNotice div.editmode .header .radio label:hover { |
| 155 | + /* make the labels recognizable as clickable */ |
| 156 | + text-decoration: underline; |
| 157 | +} |
| 158 | + |
| 159 | +#siteNotice div.editmode .descriptionOuter { |
| 160 | + /* have a top border which collapses with the label borders */ |
| 161 | + border-top: 1px solid #A7D7F9; |
| 162 | + |
| 163 | + /* use padding and margin only in the inner div */ |
| 164 | + padding: 0px; |
| 165 | + margin: 0px; |
| 166 | + |
| 167 | + |
| 168 | + /* make sure the box works correctly for the nice animation */ |
| 169 | + background-color: #f8f8f8; |
| 170 | + position: relative; |
| 171 | + overflow: hidden; |
| 172 | +} |
| 173 | + |
| 174 | +#siteNotice div.editmode .descriptionInner { |
| 175 | + /* have the same padding as the box above */ |
| 176 | + padding: 10px 10px 5px; |
| 177 | + margin: 0px; |
| 178 | + |
| 179 | + /* position all the inner descriptions at the same place for the nice animation */ |
| 180 | + position: absolute; |
| 181 | + top: 0px; |
| 182 | + left: 0px; |
| 183 | +} |
| 184 | + |
| 185 | +#editContent a, #editContent a:hover, #editContent a:visited, #editContent a:active { |
| 186 | + /* remove the link underline because that way it looks they're clickable */ |
| 187 | + text-decoration: none; |
| 188 | +} |
| 189 | + |
| 190 | +#editContent .orig { |
| 191 | + /* hide the original element */ |
| 192 | + display: none; |
| 193 | +} |
| 194 | + |
| 195 | +#editContent .editbar { |
| 196 | + /* use an inline-block to support no-wrap and width; this makes sure everything is on one line |
| 197 | + the inline-block is cross-browser supported because a span is inline by default, |
| 198 | + see http://www.quirksmode.org/css/display.html */ |
| 199 | + display: inline-block; |
| 200 | + white-space: no-wrap; |
| 201 | + |
| 202 | + /* this is used for vertical alignment */ |
| 203 | + position: relative; |
| 204 | + vertical-align: middle; |
| 205 | + |
| 206 | + margin: 2px; |
| 207 | +} |
| 208 | + |
| 209 | +#editContent .editbar input { |
| 210 | + /* vertically align the inputs */ |
| 211 | + position: absolute; |
| 212 | + top: 50%; |
| 213 | + height: 22px; |
| 214 | + margin-top: -11px; |
| 215 | +} |
| 216 | + |
| 217 | +#editContent .editbar textarea { |
| 218 | + /* style the textarea font, as this differs heavily from browser to browser */ |
| 219 | + font-family: sans-serif; |
| 220 | + font-size: 1.0em; |
| 221 | + line-height: 1.3em; |
| 222 | + margin: 0px; |
| 223 | + padding: 0px; |
| 224 | + height: 50px; |
| 225 | + |
| 226 | + /* disable resizing for browsers like Chrome, as we do this ourselves */ |
| 227 | + resize: none; |
| 228 | +} |
| 229 | + |
| 230 | +#editContent .editbar .overlay { |
| 231 | + /* position the overly to cover the entire editbar */ |
| 232 | + height: 100%; |
| 233 | + left: 0; |
| 234 | + position: absolute; |
| 235 | + text-align: center; |
| 236 | + top: 0; |
| 237 | + width: 100%; |
| 238 | +} |
| 239 | + |
| 240 | +#editContent .editbar .overlay img.spinner { |
| 241 | + /* position the spinner exactly in the middle */ |
| 242 | + left: 50%; |
| 243 | + margin-left: -8px; |
| 244 | + margin-top: -8px; |
| 245 | + position: absolute; |
| 246 | + top: 50%; |
| 247 | + width: 16px; |
| 248 | + height: 16px; |
| 249 | +} |
| 250 | + |
| 251 | +#editContent .editbar .overlay .alpha { |
| 252 | + /* have a cross-browser alpha overlay, see http://www.quirksmode.org/css/opacity.html */ |
| 253 | + width: 100%; |
| 254 | + height: 100%; |
| 255 | + background-color: #333; |
| 256 | + opacity: 0.7; |
| 257 | + -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=70)"; |
| 258 | + filter: alpha(opacity=70); |
| 259 | +} |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/InlineEditor.css |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 260 | + native |
Index: trunk/extensions/InlineEditor/jquery.inlineEditor.js |
— | — | @@ -0,0 +1,229 @@ |
| 2 | +/** |
| 3 | + * Client side framework of the InlineEditor. Facilitates publishing, previewing, |
| 4 | + * switching edit modes and undo/redo operations. |
| 5 | + */ |
| 6 | +( function( $ ) { $.inlineEditor = { |
| 7 | +editors: {}, |
| 8 | + |
| 9 | +editModes: [], |
| 10 | +currentMode: '', |
| 11 | + |
| 12 | +states: [], |
| 13 | +currentState: 0, |
| 14 | +lastState: 0, |
| 15 | + |
| 16 | +/** |
| 17 | + * Adds the initial state from the current HTML and a wiki string. |
| 18 | + */ |
| 19 | +addInitialState: function( stateWiki ) { |
| 20 | + $.inlineEditor.states[0] = { |
| 21 | + wiki: stateWiki, |
| 22 | + html: $('#editContent').html() |
| 23 | + }; |
| 24 | + $.inlineEditor.currentState = 0; |
| 25 | +}, |
| 26 | + |
| 27 | +/** |
| 28 | + * Returns wikitext in the current state given an ID. |
| 29 | + */ |
| 30 | +getTextById: function( id ) { |
| 31 | + return $.inlineEditor.states[$.inlineEditor.currentState].wiki.locations[id].text; |
| 32 | +}, |
| 33 | + |
| 34 | +/** |
| 35 | + * Previews given a new text for a given field by ID. |
| 36 | + */ |
| 37 | +previewTextById: function( text, id ) { |
| 38 | + // send out an AJAX request which will be handled by addNewState() |
| 39 | + var data = { |
| 40 | + 'originalWiki': $.inlineEditor.states[$.inlineEditor.currentState].wiki, |
| 41 | + 'lastEdit': { 'id': id, 'text': text } |
| 42 | + }; |
| 43 | + |
| 44 | + var args = [ JSON.stringify( data ), wgPageName ]; |
| 45 | + sajax_request_type = 'POST'; |
| 46 | + sajax_do_call( 'InlineEditor::ajaxPreview', args, $.inlineEditor.addNewState ); |
| 47 | +}, |
| 48 | + |
| 49 | +/** |
| 50 | + * Adds a new state from an AJAX request. |
| 51 | + */ |
| 52 | +addNewState: function( request ) { |
| 53 | + // save the state and show it on the screen |
| 54 | + state = JSON.parse( request.responseText ); |
| 55 | + $('#editContent').html( state.html ); |
| 56 | + $.inlineEditor.currentState += 1; |
| 57 | + $.inlineEditor.states[$.inlineEditor.currentState] = state; |
| 58 | + |
| 59 | + // clear out all states after the current state, because undo/redo would be broken |
| 60 | + var i = $.inlineEditor.currentState + 1; |
| 61 | + while( i <= $.inlineEditor.lastState ) { |
| 62 | + delete $.inlineEditor.states[i]; |
| 63 | + i += 1; |
| 64 | + } |
| 65 | + $.inlineEditor.lastState = $.inlineEditor.currentState; |
| 66 | + |
| 67 | + // reload the current editor and update the edit counter |
| 68 | + $.inlineEditor.reload(); |
| 69 | + $.inlineEditor.updateEditCounter(); |
| 70 | +}, |
| 71 | + |
| 72 | +/** |
| 73 | + * Reloads the current editor and finish some things in the HTML. |
| 74 | + */ |
| 75 | +reload: function() { |
| 76 | + // reload the current editor |
| 77 | + $.inlineEditor.editors[$.inlineEditor.currentMode].reload(); |
| 78 | + |
| 79 | + // fade out all lastEdit elements |
| 80 | + $('.lastEdit').removeClass('lastEdit', 200); |
| 81 | + |
| 82 | + // make the links in the article unusable |
| 83 | + $('#editContent a').click(function(event) { event.preventDefault(); }); |
| 84 | +}, |
| 85 | + |
| 86 | +/** |
| 87 | + * Moves back one state. |
| 88 | + */ |
| 89 | +undo: function( event ) { |
| 90 | + event.stopPropagation(); |
| 91 | + event.preventDefault(); |
| 92 | + |
| 93 | + // check if we can move backward one state and do it |
| 94 | + if( $.inlineEditor.currentState > 0 ) { |
| 95 | + $.inlineEditor.currentState -= 1; |
| 96 | + $('#editContent').html( $.inlineEditor.states[$.inlineEditor.currentState].html ); |
| 97 | + $.inlineEditor.reload(); |
| 98 | + } |
| 99 | + |
| 100 | + // refresh the edit counter regardless of actually switching, this confirms |
| 101 | + // that the button works, even if there is nothing to switch to |
| 102 | + $.inlineEditor.updateEditCounter(); |
| 103 | +}, |
| 104 | + |
| 105 | +/** |
| 106 | + * Moves forward one state. |
| 107 | + */ |
| 108 | +redo: function( event ) { |
| 109 | + event.stopPropagation(); |
| 110 | + event.preventDefault(); |
| 111 | + |
| 112 | + // check if we can move forward one state and do it |
| 113 | + if( $.inlineEditor.currentState < $.inlineEditor.lastState ) { |
| 114 | + $.inlineEditor.currentState += 1; |
| 115 | + $('#editContent').html( $.inlineEditor.states[$.inlineEditor.currentState].html ); |
| 116 | + $.inlineEditor.reload(); |
| 117 | + } |
| 118 | + |
| 119 | + // refresh the edit counter regardless of actually switching, this confirms |
| 120 | + // that the button works, even if there is nothing to switch to |
| 121 | + $.inlineEditor.updateEditCounter(); |
| 122 | +}, |
| 123 | + |
| 124 | +/** |
| 125 | + * Updates the edit counter and makes it flash. |
| 126 | + */ |
| 127 | +updateEditCounter: function() { |
| 128 | + // update the value of the edit counter |
| 129 | + var $editCounter = $( '#editCounter' ); |
| 130 | + $editCounter.text( '#' + $.inlineEditor.currentState ); |
| 131 | + |
| 132 | + // remove everything from the editcounter, and have it fade again |
| 133 | + $editCounter.removeClass( 'changeHighlight' ); |
| 134 | + $editCounter.attr( 'style', '' ); |
| 135 | + $editCounter.addClass( 'changeHighlight' ); |
| 136 | + $editCounter.removeClass( 'changeHighlight', 200 ); |
| 137 | +}, |
| 138 | + |
| 139 | +/** |
| 140 | + * Checks if the mode radio button has changed and selects the new editor and description. |
| 141 | + */ |
| 142 | +changeMode: function( event ) { |
| 143 | + // set the currently visible descriptions in the foreground to have them |
| 144 | + // fade away nicely |
| 145 | + $( '.editmode .descriptionInner' ).css( 'z-index', 2 ); |
| 146 | + $( '.editmode .descriptionInner' ).fadeOut(300); |
| 147 | + |
| 148 | + // check for all options if they are selected |
| 149 | + for( var optionNr in $.inlineEditor.editModes ) { |
| 150 | + if( $.inlineEditor.editModes[optionNr] ) { |
| 151 | + var option = $.inlineEditor.editModes[optionNr]; |
| 152 | + |
| 153 | + // if a certain option is selected, show the description |
| 154 | + // and set the edit mode in #content, then exit this function as only |
| 155 | + // one mode can be selected |
| 156 | + if( $( '#radio-' + option ).attr( 'checked' ) ) { |
| 157 | + // get the description, put it behind the currently visible description, |
| 158 | + // and show it instantly |
| 159 | + $description = $( '#description-' + option ); |
| 160 | + $description.show(); |
| 161 | + $description.css( 'z-index', 1 ); |
| 162 | + |
| 163 | + // resize the outer box to match the description height, also take in |
| 164 | + // account the padding of the description box |
| 165 | + $( '.editmode .descriptionOuter' ).animate( { |
| 166 | + height: $description.height() + 15 |
| 167 | + }, 600); |
| 168 | + |
| 169 | + // if we've actually switched, disable the previous editor and enable |
| 170 | + // the new one |
| 171 | + if( $.inlineEditor.currentMode != option ) { |
| 172 | + if( $.inlineEditor.editors[$.inlineEditor.currentMode] ) { |
| 173 | + $.inlineEditor.editors[$.inlineEditor.currentMode].disable(); |
| 174 | + } |
| 175 | + |
| 176 | + $.inlineEditor.currentMode = option; |
| 177 | + |
| 178 | + if( $.inlineEditor.editors[$.inlineEditor.currentMode] ) { |
| 179 | + $.inlineEditor.editors[$.inlineEditor.currentMode].enable(); |
| 180 | + } |
| 181 | + } |
| 182 | + |
| 183 | + // we've found the option to switch to, nothing to be done anymore |
| 184 | + return; |
| 185 | + } |
| 186 | + } |
| 187 | + } |
| 188 | +}, |
| 189 | + |
| 190 | +/** |
| 191 | + * Publishes the document in its current state. |
| 192 | + */ |
| 193 | +publish: function( event ) { |
| 194 | + event.stopPropagation(); |
| 195 | + event.preventDefault(); |
| 196 | + |
| 197 | + // get the wikitext from the state as it's currently on the screen |
| 198 | + var data = { 'originalWiki': $.inlineEditor.states[$.inlineEditor.currentState].wiki }; |
| 199 | + var json = JSON.stringify( data ); |
| 200 | + |
| 201 | + // set and send the form |
| 202 | + $( '#json' ).val( json ); |
| 203 | + $( '#editForm' ).submit(); |
| 204 | +}, |
| 205 | + |
| 206 | +/** |
| 207 | + * Initializes the editor. |
| 208 | + */ |
| 209 | +init : function() { |
| 210 | + // make the edit mode radiobuttons clickable |
| 211 | + $( '.optionMode' ).change( $.inlineEditor.changeMode ); |
| 212 | + |
| 213 | + $( '#publish' ).click( $.inlineEditor.publish ); |
| 214 | + $( '#undo' ).click( $.inlineEditor.undo ); |
| 215 | + $( '#redo' ).click( $.inlineEditor.redo ); |
| 216 | + |
| 217 | + // initially hide the descriptions, else things look messy because of the animation |
| 218 | + $( '.editmode .descriptionInner' ).hide(); |
| 219 | + |
| 220 | + // open all our links in a new window except for switching to the full editor |
| 221 | + $( '#siteNotice a[class!=fulleditor]' ).attr( 'target', '_blank' ); |
| 222 | + |
| 223 | + // check the current selected edit mode |
| 224 | + $.inlineEditor.changeMode(); |
| 225 | + |
| 226 | + // reload the current editor |
| 227 | + $.inlineEditor.reload(); |
| 228 | +} |
| 229 | + |
| 230 | +}; } ) ( jQuery ); |
\ No newline at end of file |
Property changes on: trunk/extensions/InlineEditor/jquery.inlineEditor.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 231 | + native |