summaryrefslogtreecommitdiff
path: root/extensions/WikiEditor/modules/jquery.wikiEditor.js
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/WikiEditor/modules/jquery.wikiEditor.js')
-rw-r--r--extensions/WikiEditor/modules/jquery.wikiEditor.js127
1 files changed, 66 insertions, 61 deletions
diff --git a/extensions/WikiEditor/modules/jquery.wikiEditor.js b/extensions/WikiEditor/modules/jquery.wikiEditor.js
index def8b69e..e5d34aa9 100644
--- a/extensions/WikiEditor/modules/jquery.wikiEditor.js
+++ b/extensions/WikiEditor/modules/jquery.wikiEditor.js
@@ -8,7 +8,8 @@
* $( 'textarea#wpTextbox1' ).wikiEditor( 'addModule', 'toolbar', { ... config ... } );
*
*/
-( function ( $ ) {
+/*jshint onevar:false, boss:true */
+( function ( $, mw ) {
/**
* Global static object for wikiEditor that provides generally useful functionality to all modules and contexts.
@@ -47,15 +48,15 @@ $.wikiEditor = {
msie: [['>=', 7]],
// Layout issues in FF < 2
firefox: [['>=', 2]],
- // Text selection bugs galore - this may be a different situation with the new iframe-based solution
+ // Text selection bugs galore
opera: [['>=', 9.6]],
// jQuery minimums
safari: [['>=', 3]],
chrome: [['>=', 3]],
netscape: [['>=', 9]],
blackberry: false,
- ipod: false,
- iphone: false
+ ipod: [['>=', 6]],
+ iphone: [['>=', 6]]
},
// Right-to-left languages
rtl: {
@@ -63,15 +64,15 @@ $.wikiEditor = {
msie: [['>=', 8]],
// Layout issues in FF < 2
firefox: [['>=', 2]],
- // Text selection bugs galore - this may be a different situation with the new iframe-based solution
+ // Text selection bugs galore
opera: [['>=', 9.6]],
// jQuery minimums
safari: [['>=', 3]],
chrome: [['>=', 3]],
netscape: [['>=', 9]],
blackberry: false,
- ipod: false,
- iphone: false
+ ipod: [['>=', 6]],
+ iphone: [['>=', 6]]
}
},
@@ -113,7 +114,7 @@ $.wikiEditor = {
isRequired: function ( module, requirement ) {
if ( typeof module.req !== 'undefined' ) {
for ( var req in module.req ) {
- if ( module.req[req] == requirement ) {
+ if ( module.req[req] === requirement ) {
return true;
}
}
@@ -132,9 +133,10 @@ $.wikiEditor = {
* with the key 'bar'.
*/
autoMsg: function ( object, property ) {
+ var i, p;
// Accept array of possible properties, of which the first one found will be used
- if ( typeof property == 'object' ) {
- for ( var i in property ) {
+ if ( typeof property === 'object' ) {
+ for ( i in property ) {
if ( property[i] in object || property[i] + 'Msg' in object ) {
property = property[i];
break;
@@ -144,11 +146,11 @@ $.wikiEditor = {
if ( property in object ) {
return object[property];
} else if ( property + 'Msg' in object ) {
- var p = object[property + 'Msg'];
+ p = object[property + 'Msg'];
if ( $.isArray( p ) && p.length >= 2 ) {
- return mediaWiki.message.apply( mediaWiki.message, p ).plain();
+ return mw.message.apply( mw.message, p ).plain();
} else {
- return mediaWiki.message( p ).plain();
+ return mw.message( p ).plain();
}
} else {
return '';
@@ -181,10 +183,10 @@ $.wikiEditor = {
var src = $.wikiEditor.autoLang( icon, lang );
path = path || $.wikiEditor.imgPath;
// Prepend path if src is not absolute
- if ( src.substr( 0, 7 ) != 'http://' && src.substr( 0, 8 ) != 'https://' && src[0] != '/' ) {
+ if ( src.substr( 0, 7 ) !== 'http://' && src.substr( 0, 8 ) !== 'https://' && src[0] !== '/' ) {
src = path + src;
}
- return src + '?' + mw.loader.version( 'jquery.wikiEditor' );
+ return src + '?' + mw.loader.getVersion( 'jquery.wikiEditor' );
},
/**
@@ -197,9 +199,9 @@ $.wikiEditor = {
*/
autoIconOrOffset: function ( icon, offset, path, lang ) {
lang = lang || mw.config.get( 'wgUserLanguage' );
- if ( typeof offset == 'object' && lang in offset ) {
+ if ( typeof offset === 'object' && lang in offset ) {
return offset[lang];
- } else if ( typeof icon == 'object' && lang in icon ) {
+ } else if ( typeof icon === 'object' && lang in icon ) {
return $.wikiEditor.autoIcon( icon, undefined, lang );
} else {
return $.wikiEditor.autoLang( offset, lang );
@@ -214,21 +216,21 @@ $.fn.wikiEditor = function () {
// Skip any further work when running in browsers that are unsupported
if ( !$.wikiEditor.isSupported() ) {
- return $(this);
+ return $( this );
}
/* Initialization */
// The wikiEditor context is stored in the element's data, so when this function gets called again we can pick up right
// where we left off
-var context = $(this).data( 'wikiEditor-context' );
+var context = $( this ).data( 'wikiEditor-context' );
// On first call, we need to set things up, but on all following calls we can skip right to the API handling
-if ( !context || typeof context == 'undefined' ) {
+if ( !context || typeof context === 'undefined' ) {
// Star filling the context with useful data - any jQuery selections, as usual should be named with a preceding $
context = {
// Reference to the textarea element which the wikiEditor is being built around
- '$textarea': $(this),
+ '$textarea': $( this ),
// Container for any number of mutually exclusive views that are accessible by tabs
'views': {},
// Container for any number of module-specific data - only including data for modules in use on this context
@@ -236,25 +238,9 @@ if ( !context || typeof context == 'undefined' ) {
// General place to shouve bits of data into
'data': {},
// Unique numeric ID of this instance used both for looking up and differentiating instances of wikiEditor
- 'instance': $.wikiEditor.instances.push( $(this) ) - 1,
- // Array mapping elements in the textarea to character offsets
- 'offsets': null,
- // Cache for context.fn.htmlToText()
- 'htmlToTextMap': {},
- // The previous HTML of the iframe, stored to detect whether something really changed.
- 'oldHTML': null,
- // Same for delayedChange()
- 'oldDelayedHTML': null,
- // The previous selection of the iframe, stored to detect whether the selection has changed
- 'oldDelayedSel': null,
- // Saved selection state for IE
+ 'instance': $.wikiEditor.instances.push( $( this ) ) - 1,
+ // Saved selection state for old IE (<=10)
'savedSelection': null,
- // Stack of states in { html: [string] } form
- 'history': [],
- // Current history state position - this is number of steps backwards, so it's always -1 or less
- 'historyPosition': -1,
- /// The previous historyPosition, stored to detect if change events were due to an undo or redo action
- 'oldDelayedHistoryPosition': -1,
// List of extensions active on this context
'extensions': []
};
@@ -262,7 +248,7 @@ if ( !context || typeof context == 'undefined' ) {
/**
* Externally Accessible API
*
- * These are available using calls to $(selection).wikiEditor( call, data ) where selection is a jQuery selection
+ * These are available using calls to $( selection ).wikiEditor( call, data ) where selection is a jQuery selection
* of the textarea that the wikiEditor instance was built around.
*/
@@ -276,14 +262,14 @@ if ( !context || typeof context == 'undefined' ) {
'addModule': function ( context, data ) {
var module, call,
modules = {};
- if ( typeof data == 'string' ) {
+ if ( typeof data === 'string' ) {
modules[data] = {};
- } else if ( typeof data == 'object' ) {
+ } else if ( typeof data === 'object' ) {
modules = data;
}
for ( module in modules ) {
// Check for the existance of an available / supported module with a matching name and a create function
- if ( typeof module == 'string' && typeof $.wikiEditor.modules[module] !== 'undefined' &&
+ if ( typeof module === 'string' && typeof $.wikiEditor.modules[module] !== 'undefined' &&
$.wikiEditor.isSupported( $.wikiEditor.modules[module] ) )
{
// Extend the context's core API with this module's own API calls
@@ -326,11 +312,11 @@ if ( !context || typeof context == 'undefined' ) {
*/
trigger: function ( name, event ) {
// Event is an optional argument, but from here on out, at least the type field should be dependable
- if ( typeof event == 'undefined' ) {
+ if ( typeof event === 'undefined' ) {
event = { 'type': 'custom' };
}
// Ensure there's a place for extra information to live
- if ( typeof event.data == 'undefined' ) {
+ if ( typeof event.data === 'undefined' ) {
event.data = {};
}
@@ -350,9 +336,9 @@ if ( !context || typeof context == 'undefined' ) {
name in $.wikiEditor.modules[module].evt
) {
var ret = $.wikiEditor.modules[module].evt[name]( context, event );
- if (ret !== null) {
+ if ( ret !== null ) {
//if 1 returns false, the end result is false
- if( returnFromModules === null ) {
+ if ( returnFromModules === null ) {
returnFromModules = ret;
} else {
returnFromModules = returnFromModules && ret;
@@ -393,7 +379,7 @@ if ( !context || typeof context == 'undefined' ) {
// Return the newly appended tab
return $( '<div>' )
.attr( 'rel', 'wikiEditor-ui-view-' + options.name )
- .addClass( context.view == options.name ? 'current' : null )
+ .addClass( context.view === options.name ? 'current' : null )
.append( $( '<a>' )
.attr( 'href', '#' )
.mousedown( function () {
@@ -402,11 +388,11 @@ if ( !context || typeof context == 'undefined' ) {
} )
.click( function ( event ) {
context.$ui.find( '.wikiEditor-ui-view' ).hide();
- context.$ui.find( '.' + $(this).parent().attr( 'rel' ) ).show();
+ context.$ui.find( '.' + $( this ).parent().attr( 'rel' ) ).show();
context.$tabs.find( 'div' ).removeClass( 'current' );
- $(this).parent().addClass( 'current' );
- $(this).blur();
- if ( 'init' in options && typeof options.init == 'function' ) {
+ $( this ).parent().addClass( 'current' );
+ $( this ).blur();
+ if ( 'init' in options && typeof options.init === 'function' ) {
options.init( context );
}
event.preventDefault();
@@ -457,17 +443,17 @@ if ( !context || typeof context == 'undefined' ) {
},
/**
- * Save text selection for IE
+ * Save text selection for old IE (<=10)
*/
saveSelection: function () {
- if ( $.client.profile().name === 'msie' ) {
+ if ( $.client.profile().name === 'msie' && document.selection && document.selection.createRange ) {
context.$textarea.focus();
context.savedSelection = document.selection.createRange();
}
},
/**
- * Restore text selection for IE
+ * Restore text selection for old IE (<=10)
*/
restoreSelection: function () {
if ( $.client.profile().name === 'msie' && context.savedSelection !== null ) {
@@ -479,6 +465,13 @@ if ( !context || typeof context == 'undefined' ) {
};
/**
+ * Workaround for a scrolling bug in IE8 (bug 61908)
+ */
+ if ( $.client.profile().name === 'msie' ) {
+ context.$textarea.css( 'height', context.$textarea.height() );
+ }
+
+ /**
* Base UI Construction
*
* The UI is built from several containers, the outer-most being a div classed as "wikiEditor-ui". These containers
@@ -493,6 +486,9 @@ if ( !context || typeof context == 'undefined' ) {
.append( $( '<span>' + mediaWiki.msg( 'wikieditor-loading' ) + '</span>' )
.css( 'marginTop', context.$textarea.height() / 2 ) );
*/
+ /* Preserving cursor and focus state, which will get lost due to wrapAll */
+ var hasFocus = context.$textarea.is( ':focus' ),
+ cursorPos = context.$textarea.textSelection( 'getCaretPosition', { startAndEnd: true } );
// Encapsulate the textarea with some containers for layout
context.$textarea
/* Disabling our loading div for now
@@ -504,6 +500,14 @@ if ( !context || typeof context == 'undefined' ) {
.wrapAll( $( '<div>' ).addClass( 'wikiEditor-ui-left' ) )
.wrapAll( $( '<div>' ).addClass( 'wikiEditor-ui-bottom' ) )
.wrapAll( $( '<div>' ).addClass( 'wikiEditor-ui-text' ) );
+ // Restore scroll position after this wrapAll (tracked by mediawiki.action.edit)
+ context.$textarea.prop( 'scrollTop', $( '#wpScrolltop' ).val() );
+ // Restore focus and cursor if needed
+ if ( hasFocus ) {
+ context.$textarea.focus();
+ context.$textarea.textSelection( 'setSelection', { start: cursorPos[0], end: cursorPos[1] } );
+ }
+
// Get references to some of the newly created containers
context.$ui = context.$textarea.parent().parent().parent().parent().parent();
context.$wikitext = context.$textarea.parent().parent().parent().parent();
@@ -514,15 +518,16 @@ if ( !context || typeof context == 'undefined' ) {
.append( $( '<div>' ).addClass( 'wikiEditor-ui-tabs' ).hide() )
.append( $( '<div>' ).addClass( 'wikiEditor-ui-buttons' ) )
)
- .before( $( '<div style="clear: both;"></div>' ) );
+ .before( $( '<div>' ).addClass( 'wikiEditor-ui-clear' ) );
// Get references to some of the newly created containers
context.$controls = context.$ui.find( '.wikiEditor-ui-buttons' ).hide();
context.$buttons = context.$ui.find( '.wikiEditor-ui-buttons' );
context.$tabs = context.$ui.find( '.wikiEditor-ui-tabs' );
// Clear all floating after the UI
- context.$ui.after( $( '<div style="clear: both;"></div>' ) );
+ context.$ui.after( $( '<div>' ).addClass( 'wikiEditor-ui-clear' ) );
// Attach a right container
context.$wikitext.append( $( '<div>' ).addClass( 'wikiEditor-ui-right' ) );
+ context.$wikitext.append( $( '<div>' ).addClass( 'wikiEditor-ui-clear' ) );
// Attach a top container to the left pane
context.$wikitext.find( '.wikiEditor-ui-left' ).prepend( $( '<div>' ).addClass( 'wikiEditor-ui-top' ) );
// Setup the intial view
@@ -539,9 +544,9 @@ if ( !context || typeof context == 'undefined' ) {
var args = $.makeArray( arguments );
// Dynamically setup core extensions for modules that are required
-if ( args[0] == 'addModule' && typeof args[1] !== 'undefined' ) {
+if ( args[0] === 'addModule' && typeof args[1] !== 'undefined' ) {
var modules = args[1];
- if ( typeof modules !== "object" ) {
+ if ( typeof modules !== 'object' ) {
modules = {};
modules[args[1]] = '';
}
@@ -573,8 +578,8 @@ if ( args.length > 0 ) {
}
// Store the context for next time, and support chaining
-return $(this).data( 'wikiEditor-context', context );
+return $( this ).data( 'wikiEditor-context', context );
};
-}( jQuery ) );
+}( jQuery, mediaWiki ) );