r70123 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r70122‎ | r70123 | r70124 >
Date:23:56, 28 July 2010
Author:tparscal
Status:deferred
Tags:
Comment:
Ported edit.js to mw.legacy.edit.js
Modified paths:
  • /branches/resourceloader/phase3/resources/mw/mw.legacy.edit.js (modified) (history)

Diff [purge]

Index: branches/resourceloader/phase3/resources/mw/mw.legacy.edit.js
@@ -0,0 +1,258 @@
 2+/*
 3+ * Legacy emulation for the now depricated changepassword.js
 4+ *
 5+ * Ported by: Trevor Parscal
 6+ */
 7+
 8+( function( $ ) {
 9+
 10+$.extend( mw.legacy, {
 11+ 'currentFocused': null,
 12+ /**
 13+ * Generates the actual toolbar buttons with localized text we use it to avoid creating the toolbar
 14+ * where javascript is not enabled
 15+ */
 16+ 'addButton': function( imageFile, speedTip, tagOpen, tagClose, sampleText, imageId ) {
 17+ // Don't generate buttons for browsers which don't fully support it.
 18+ mw.legacy.mwEditButtons.push( {
 19+ 'imageId': imageId,
 20+ 'imageFile': imageFile,
 21+ 'speedTip': speedTip,
 22+ 'tagOpen': tagOpen,
 23+ 'tagClose': tagClose,
 24+ 'sampleText': sampleText
 25+ } );
 26+ },
 27+ /**
 28+ * Generates the actual toolbar buttons with localized text we use it to avoid creating the toolbar where JavaScript
 29+ * is not enabled
 30+ */
 31+ 'mwInsertEditButton': function( parent, item ) {
 32+ var $image = $( '<img />' )
 33+ .attr( {
 34+ 'width': 23,
 35+ 'height': 22,
 36+ 'class': 'mw-toolbar-editbutton',
 37+ 'id': item.imageId ? item.imageId : null,
 38+ 'src': = item.imageFile,
 39+ 'border': 0,
 40+ 'alt': item.speedTip,
 41+ 'title': item.speedTip
 42+ } )
 43+ .css( 'cursor', 'pointer' )
 44+ .click( function() {
 45+ mw.legacy.insertTags( item.tagOpen, item.tagClose, item.sampleText );
 46+ // Click tracking
 47+ if ( typeof $.trackAction != 'undefined' ) {
 48+ $.trackAction( 'oldedit.' + item.speedTip.replace( / /g, "-" ) );
 49+ }
 50+ return false;
 51+ } )
 52+ .appendTo( $( parent ) );
 53+ return true;
 54+ },
 55+ /**
 56+ * Sets up the toolbar
 57+ */
 58+ 'mwSetupToolbar': function() {
 59+ var $toolbar = $( '#toolbar' );
 60+ var $textbox = $( 'textarea' ).get( 0 );
 61+ if ( !$toolbar.length || !$textbox.length ) {
 62+ return false;
 63+ }
 64+ // Only check for selection capability if the textarea is visible - errors will occur otherwise - just because
 65+ // the textarea is not visible, doesn't mean we shouldn't build out the toolbar though - it might have been
 66+ // replaced with some other kind of control
 67+ if (
 68+ $textbox.is( ':visible' ) &&
 69+ !( document.selection && document.selection.createRange ) &&
 70+ textboxes[0].selectionStart === null
 71+ ) {
 72+ return false;
 73+ }
 74+ for ( var i = 0; i < mw.legacy.mwEditButtons.length; i++ ) {
 75+ mw.legacy.mwInsertEditButton( $toolbar, mw.legacy.mwEditButtons[i] );
 76+ }
 77+ for ( var i = 0; i < mw.legacy.mwCustomEditButtons.length; i++ ) {
 78+ mw.legacy.mwInsertEditButton( $toolbar, mw.legacy.mwCustomEditButtons[i] );
 79+ }
 80+ return true;
 81+ },
 82+ /**
 83+ * Apply tagOpen/tagClose to selection in textarea, use sampleText instead of selection if there is none
 84+ */
 85+ 'insertTags': function( tagOpen, tagClose, sampleText ) {
 86+ function checkSelectedText() {
 87+ if ( !selText ) {
 88+ selText = sampleText;
 89+ isSample = true;
 90+ } else if ( selText.charAt( selText.length - 1 ) == ' ' ) { // exclude ending space char
 91+ selText = selText.substring( 0, selText.length - 1 );
 92+ tagClose += ' ';
 93+ }
 94+ }
 95+ var currentFocused = $( mw.legacy.currentFocused );
 96+ if (
 97+ typeof $.fn.textSelection != 'undefined' &&
 98+ ( $currentFocused.name().toLowerCase() == 'iframe' || $currentFocused.attr( 'id' ) == 'wpTextbox1' )
 99+ ) {
 100+ $j( '#wpTextbox1' ).textSelection(
 101+ 'encapsulateSelection', { 'pre': tagOpen, 'peri': sampleText, 'post': tagClose }
 102+ );
 103+ return;
 104+ }
 105+ var $textarea;
 106+ if ( $( 'form[name=editform]' ) {
 107+ $textarea = $currentFocused;
 108+ } else {
 109+ // Some alternate form? take the first one we can find
 110+ $textarea = $( 'textarea' ).get( 0 );
 111+ }
 112+ var selText, isSample = false;
 113+ // Text selection implementation for IE and Opera
 114+ if ( document.selection && document.selection.createRange ) {
 115+ // Save window scroll position
 116+ if ( document.documentElement && document.documentElement.scrollTop ) {
 117+ var winScroll = document.documentElement.scrollTop
 118+ } else if ( document.body ) {
 119+ var winScroll = document.body.scrollTop;
 120+ }
 121+ // Get current selection
 122+ $textarea.focus();
 123+ var range = document.selection.createRange();
 124+ selText = range.text;
 125+ // Insert tags
 126+ checkSelectedText();
 127+ range.text = tagOpen + selText + tagClose;
 128+ // Mark sample text as selected
 129+ if ( isSample && range.moveStart ) {
 130+ if ( window.opera ) {
 131+ tagClose = tagClose.replace( /\n/g,'' );
 132+ }
 133+ range.moveStart( 'character', - tagClose.length - selText.length );
 134+ range.moveEnd( 'character', - tagClose.length );
 135+ }
 136+ range.select();
 137+ // Restore window scroll position
 138+ if ( document.documentElement && document.documentElement.scrollTop ) {
 139+ document.documentElement.scrollTop = winScroll;
 140+ } else if ( document.body ) {
 141+ document.body.scrollTop = winScroll;
 142+ }
 143+ }
 144+ // Text selection implementation for Mozilla, Chrome and Safari
 145+ else if ( $textarea[0].selectionStart || $textarea[0].selectionStart == '0' ) {
 146+ // Save textarea scroll position
 147+ var textScroll = $textarea.scrollTop;
 148+ // Get current selection
 149+ $textarea.focus();
 150+ var startPos = $textarea[0].selectionStart;
 151+ var endPos = $textarea[0].selectionEnd;
 152+ selText = $textarea.value.substring( startPos, endPos );
 153+ // Insert tags
 154+ checkSelectedText();
 155+ $textarea.val(
 156+ $textarea.val().substring( 0, startPos ) +
 157+ tagOpen + selText + tagClose +
 158+ $textarea.val().substring( endPos, $textarea.val().length )
 159+ );
 160+ // Set new selection
 161+ if ( isSample ) {
 162+ $textarea[0].selectionStart = startPos + tagOpen.length;
 163+ $textarea[0].selectionEnd = startPos + tagOpen.length + selText.length;
 164+ } else {
 165+ $textarea[0].selectionStart = startPos + tagOpen.length + selText.length + tagClose.length;
 166+ $textarea[0].selectionEnd = $textarea[0].selectionStart;
 167+ }
 168+ // Restore textarea scroll position
 169+ $textarea[0].scrollTop = textScroll;
 170+ }
 171+ },
 172+ /**
 173+ * Restore the edit box scroll state following a preview operation,
 174+ * and set up a form submission handler to remember this state
 175+ */
 176+ 'scrollEditBox': function() {
 177+ var $textbox = $( '#wpTextbox1' );
 178+ var $scrollTop = $( '#wpScrolltop' );
 179+ var $editForm = $( '#editform' );
 180+ if ( $editForm.length && $textbox.length && $scrollTop.length ) {
 181+ if ( scrollTop.val() ) {
 182+ $textbox.scrollTop = $scrollTop.val();
 183+ }
 184+ $editForm.submit( function() {
 185+ $scrollTop.val( $textbox.scrollTop );
 186+ } );
 187+ }
 188+ }
 189+} );
 190+
 191+/* Initialization */
 192+
 193+$( document ).ready( function() {
 194+ mw.legacy.scrollEditBox();
 195+ mw.legacy.mwSetupToolbar();
 196+ mw.legacy.currentFocused = $( '#wpTextbox1' ).get( 0 );
 197+ // http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html focus does not bubble normally, but using a
 198+ // trick we can do event delegation on the focus event on all text inputs to make the toolbox usable on all of them
 199+ $( '#editform' ).focus( function() {
 200+ $(this).each( function( e ) {
 201+ var elm = e.target || e.srcElement;
 202+ if ( !elm ) {
 203+ return;
 204+ }
 205+ var tagName = elm.tagName.toLowerCase();
 206+ var type = elm.type || '';
 207+ if ( tagName !== 'textarea' && tagName !== 'input' ) {
 208+ return;
 209+ }
 210+ if ( tagName === 'input' && type.toLowerCase() !== 'text' ) {
 211+ return;
 212+ }
 213+ mw.legacy.currentFocused = elm;
 214+ } );
 215+ } );
 216+ // HACK: make currentFocused work with the usability iframe - with proper focus detection support (HTML 5!) this'll
 217+ // be much cleaner
 218+ var $iframe = $j( '.wikiEditor-ui-text iframe' );
 219+ if ( $iframe.length > 0 ) {
 220+ $j( $iframe.get( 0 ).contentWindow.document )
 221+ // For IE
 222+ .add( $iframe.get( 0 ).contentWindow.document.body )
 223+ .focus( function() { mw.legacy.currentFocused = $iframe.get( 0 ); } );
 224+ }
 225+ // Make sure edit summary does not exceed byte limit
 226+ var $summary = $( '#wpSummary' );
 227+ if ( !$summary.length ) {
 228+ return;
 229+ }
 230+ // L must be capitalized in length
 231+ $summary.get( 0 ).maxLength = 250;
 232+ $summary.keypress( function( e ) {
 233+ // First check to see if this is actually a character key being pressed. Based on key-event info from
 234+ // http://unixpapa.com/js/key.html note === sign, if undefined, still could be a real key
 235+ if ( e.which === 0 || e.charCode === 0 || e.ctrlKey || e.altKey || e.metaKey ) {
 236+ // A special key (backspace, etc) so don't interefere.
 237+ return true;
 238+ }
 239+ // This basically figures out how many bytes a utf-16 string (which is what js sees) will take in utf-8 by
 240+ // replacing a 2 byte character with 2 *'s, etc, and counting that. Note, surogate (\uD800-\uDFFF) characters
 241+ // are counted as 2 bytes, since theres two of them and the actual character takes 4 bytes in utf-8 (2*2=4).
 242+ // Might not work perfectly in edge cases such as such as illegal sequences, but that should never happen.
 243+ len = summary.value
 244+ .replace(/[\u0080-\u07FF\uD800-\uDFFF]/g, '**')
 245+ .replace(/[\u0800-\uD7FF\uE000-\uFFFF]/g, '***')
 246+ .length;
 247+ // 247 as this doesn't count character about to be inserted.
 248+ if ( len > 247 ) {
 249+ if ( e.preventDefault ) {
 250+ e.preventDefault();
 251+ }
 252+ // IE
 253+ e.returnValue = false;
 254+ return false;
 255+ }
 256+ } );
 257+} );
 258+
 259+} )( jQuery );
\ No newline at end of file

Status & tagging log