mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/WikiEditor
synced 2024-11-23 15:57:15 +00:00
build: Test JS code with jshint and jscs via npm
Change-Id: I039bc4c17fbba3c74a5050066b20af05434ca482
This commit is contained in:
parent
f3f4dbe888
commit
bdb67f719c
7
.jscsrc
Normal file
7
.jscsrc
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"preset": "wikimedia",
|
||||
"validateQuoteMarks": null,
|
||||
"requireVarDeclFirst": null,
|
||||
"requireMultipleVarDecl": null,
|
||||
"requireCamelCaseOrUpperCaseIdentifiers": null
|
||||
}
|
2
.jshintignore
Normal file
2
.jshintignore
Normal file
|
@ -0,0 +1,2 @@
|
|||
node_modules
|
||||
vendor
|
22
Gruntfile.js
22
Gruntfile.js
|
@ -1,10 +1,24 @@
|
|||
/*jshint node:true */
|
||||
module.exports = function ( grunt ) {
|
||||
grunt.loadNpmTasks( 'grunt-banana-checker' );
|
||||
grunt.loadNpmTasks( 'grunt-jsonlint' );
|
||||
|
||||
var conf = grunt.file.readJSON( 'extension.json' );
|
||||
grunt.loadNpmTasks( 'grunt-contrib-jshint' );
|
||||
grunt.loadNpmTasks( 'grunt-jsonlint' );
|
||||
grunt.loadNpmTasks( 'grunt-banana-checker' );
|
||||
grunt.loadNpmTasks( 'grunt-jscs' );
|
||||
|
||||
grunt.initConfig( {
|
||||
jshint: {
|
||||
options: {
|
||||
jshintrc: true
|
||||
},
|
||||
all: [
|
||||
'**/*.js',
|
||||
'!node_modules/**'
|
||||
]
|
||||
},
|
||||
jscs: {
|
||||
src: '<%= jshint.all %>'
|
||||
},
|
||||
banana: conf.MessagesDirs,
|
||||
jsonlint: {
|
||||
all: [
|
||||
|
@ -14,6 +28,6 @@ module.exports = function ( grunt ) {
|
|||
}
|
||||
} );
|
||||
|
||||
grunt.registerTask( 'test', [ 'jsonlint', 'banana' ] );
|
||||
grunt.registerTask( 'test', [ 'jshint', 'jscs', 'jsonlint', 'banana' ] );
|
||||
grunt.registerTask( 'default', 'test' );
|
||||
};
|
||||
|
|
|
@ -34,12 +34,12 @@
|
|||
}, data );
|
||||
|
||||
if ( mw.user.isAnon() ) {
|
||||
data['user.class'] = 'IP';
|
||||
data[ 'user.class' ] = 'IP';
|
||||
}
|
||||
|
||||
data['action.' + action + '.type'] = data.type;
|
||||
data['action.' + action + '.mechanism'] = data.mechanism;
|
||||
data['action.' + action + '.timing'] = data.timing === undefined ?
|
||||
data[ 'action.' + action + '.type' ] = data.type;
|
||||
data[ 'action.' + action + '.mechanism' ] = data.mechanism;
|
||||
data[ 'action.' + action + '.timing' ] = data.timing === undefined ?
|
||||
0 : Math.floor( data.timing );
|
||||
// Remove renamed properties
|
||||
delete data.type;
|
||||
|
@ -70,7 +70,7 @@
|
|||
onUnloadFallback = window.onunload;
|
||||
window.onunload = function () {
|
||||
var fallbackResult, abortType,
|
||||
caVeEdit = $( '#ca-ve-edit' )[0],
|
||||
caVeEdit = $( '#ca-ve-edit' )[ 0 ],
|
||||
switchingToVE = caVeEdit && (
|
||||
document.activeElement === caVeEdit ||
|
||||
$.contains( caVeEdit, document.activeElement )
|
||||
|
|
|
@ -20,32 +20,32 @@ $.wikiEditor.modules.dialogs.config = {
|
|||
section: 'main',
|
||||
group: 'insert',
|
||||
tools: {
|
||||
'link': {
|
||||
link: {
|
||||
labelMsg: 'wikieditor-toolbar-tool-link',
|
||||
type: 'button',
|
||||
icon: 'insert-link.png',
|
||||
offset: [2, -1654],
|
||||
offset: [ 2, -1654 ],
|
||||
action: {
|
||||
type: 'dialog',
|
||||
module: 'insert-link'
|
||||
}
|
||||
},
|
||||
'file': {
|
||||
file: {
|
||||
labelMsg: 'wikieditor-toolbar-tool-file',
|
||||
type: 'button',
|
||||
icon: 'insert-file.png',
|
||||
offset: [2, -1438],
|
||||
offset: [ 2, -1438 ],
|
||||
action: {
|
||||
type: 'dialog',
|
||||
module: 'insert-file'
|
||||
}
|
||||
},
|
||||
'reference': {
|
||||
reference: {
|
||||
labelMsg: 'wikieditor-toolbar-tool-reference',
|
||||
filters: [ 'body.ns-subject' ],
|
||||
type: 'button',
|
||||
icon: 'insert-reference.png',
|
||||
offset: [2, -1798],
|
||||
offset: [ 2, -1798 ],
|
||||
action: {
|
||||
type: 'dialog',
|
||||
module: 'insert-reference'
|
||||
|
@ -57,11 +57,11 @@ $.wikiEditor.modules.dialogs.config = {
|
|||
section: 'advanced',
|
||||
group: 'insert',
|
||||
tools: {
|
||||
'table': {
|
||||
table: {
|
||||
labelMsg: 'wikieditor-toolbar-tool-table',
|
||||
type: 'button',
|
||||
icon: 'insert-table.png',
|
||||
offset: [2, -1942],
|
||||
offset: [ 2, -1942 ],
|
||||
action: {
|
||||
type: 'dialog',
|
||||
module: 'insert-table'
|
||||
|
@ -72,13 +72,13 @@ $.wikiEditor.modules.dialogs.config = {
|
|||
.wikiEditor( 'addToToolbar', {
|
||||
section: 'advanced',
|
||||
groups: {
|
||||
'search': {
|
||||
search: {
|
||||
tools: {
|
||||
'replace': {
|
||||
replace: {
|
||||
labelMsg: 'wikieditor-toolbar-tool-replace',
|
||||
type: 'button',
|
||||
icon: 'search-replace.png',
|
||||
offset: [-70, -214],
|
||||
offset: [ -70, -214 ],
|
||||
action: {
|
||||
type: 'dialog',
|
||||
module: 'search-and-replace'
|
||||
|
@ -91,7 +91,7 @@ $.wikiEditor.modules.dialogs.config = {
|
|||
},
|
||||
|
||||
getDefaultConfig: function () {
|
||||
return { 'dialogs': {
|
||||
return { dialogs: {
|
||||
'insert-link': {
|
||||
titleMsg: 'wikieditor-toolbar-tool-link-title',
|
||||
id: 'wikieditor-toolbar-link-dialog',
|
||||
|
@ -144,17 +144,17 @@ $.wikiEditor.modules.dialogs.config = {
|
|||
internal = false;
|
||||
}
|
||||
// Abort previous request
|
||||
var request = $( '#wikieditor-toolbar-link-int-target-status' ).data( 'request' );
|
||||
var request = $( '#wikieditor-toolbar-link-int-target-status' ).data( 'request' ),
|
||||
target = $( '#wikieditor-toolbar-link-int-target' ).val(),
|
||||
cache = $( '#wikieditor-toolbar-link-int-target-status' ).data( 'existencecache' );
|
||||
if ( request ) {
|
||||
request.abort();
|
||||
}
|
||||
var target = $( '#wikieditor-toolbar-link-int-target' ).val();
|
||||
var cache = $( '#wikieditor-toolbar-link-int-target-status' ).data( 'existencecache' );
|
||||
if ( hasOwn.call( cache, target ) ) {
|
||||
updateWidget( cache[target] );
|
||||
updateWidget( cache[ target ] );
|
||||
return;
|
||||
}
|
||||
if ( target.replace( /^\s+$/,'' ) === '' ) {
|
||||
if ( target.replace( /^\s+$/, '' ) === '' ) {
|
||||
// Hide the widget when the textbox is empty
|
||||
updateWidget( false );
|
||||
return;
|
||||
|
@ -191,7 +191,7 @@ $.wikiEditor.modules.dialogs.config = {
|
|||
// This happens in some weird cases like interwiki links
|
||||
status = false;
|
||||
} else {
|
||||
var page = data.query.pages[data.query.pageids[0]];
|
||||
var page = data.query.pages[ data.query.pageids[ 0 ] ];
|
||||
status = 'exists';
|
||||
if ( page.missing !== undefined ) {
|
||||
status = 'notexists';
|
||||
|
@ -204,7 +204,7 @@ $.wikiEditor.modules.dialogs.config = {
|
|||
// Cache the status of the link target if the force internal
|
||||
// parameter was not passed
|
||||
if ( !internal ) {
|
||||
cache[target] = status;
|
||||
cache[ target ] = status;
|
||||
}
|
||||
updateWidget( status );
|
||||
} )
|
||||
|
@ -299,8 +299,8 @@ $.wikiEditor.modules.dialogs.config = {
|
|||
}, 0 );
|
||||
} );
|
||||
$( '#wikieditor-toolbar-link-int-text' ).bind( 'change keydown paste cut', function () {
|
||||
var oldVal = $( this ).val();
|
||||
var that = this;
|
||||
var oldVal = $( this ).val(),
|
||||
that = this;
|
||||
setTimeout( function () {
|
||||
if ( $( that ).val() !== oldVal ) {
|
||||
$( that ).data( 'untouched', false );
|
||||
|
@ -330,9 +330,9 @@ $.wikiEditor.modules.dialogs.config = {
|
|||
.append( $( '<div>' )
|
||||
.attr( 'id', 'wikieditor-toolbar-link-int-target-status-loading' )
|
||||
.append( $( '<img>' ).attr( {
|
||||
'src': $.wikiEditor.imgPath + 'dialogs/' + 'loading-small.gif',
|
||||
'alt': loadingMsg,
|
||||
'title': loadingMsg
|
||||
src: $.wikiEditor.imgPath + 'dialogs/' + 'loading-small.gif',
|
||||
alt: loadingMsg,
|
||||
title: loadingMsg
|
||||
} ) )
|
||||
)
|
||||
.append( $( '<div>' )
|
||||
|
@ -365,8 +365,8 @@ $.wikiEditor.modules.dialogs.config = {
|
|||
// Title suggestions
|
||||
$( '#wikieditor-toolbar-link-int-target' ).data( 'suggcache', {} ).suggestions( {
|
||||
fetch: function () {
|
||||
var that = this;
|
||||
var title = $( this ).val();
|
||||
var that = this,
|
||||
title = $( this ).val();
|
||||
|
||||
if ( isExternalLink( title ) || title.indexOf( '|' ) !== -1 || title === '' ) {
|
||||
$( this ).suggestions( 'suggestions', [] );
|
||||
|
@ -375,7 +375,7 @@ $.wikiEditor.modules.dialogs.config = {
|
|||
|
||||
var cache = $( this ).data( 'suggcache' );
|
||||
if ( hasOwn.call( cache, title ) ) {
|
||||
$( this ).suggestions( 'suggestions', cache[title] );
|
||||
$( this ).suggestions( 'suggestions', cache[ title ] );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -386,15 +386,16 @@ $.wikiEditor.modules.dialogs.config = {
|
|||
suggest: ''
|
||||
} )
|
||||
.done( function ( data ) {
|
||||
cache[title] = data[1];
|
||||
$( that ).suggestions( 'suggestions', data[1] );
|
||||
cache[ title ] = data[ 1 ];
|
||||
$( that ).suggestions( 'suggestions', data[ 1 ] );
|
||||
} );
|
||||
$( this ).data( 'request', request );
|
||||
},
|
||||
cancel: function () {
|
||||
var request = $( this ).data( 'request' );
|
||||
if ( request )
|
||||
if ( request ) {
|
||||
request.abort();
|
||||
}
|
||||
}
|
||||
} );
|
||||
},
|
||||
|
@ -414,15 +415,17 @@ $.wikiEditor.modules.dialogs.config = {
|
|||
function escapeExternalText( s ) {
|
||||
return s.replace( /(\]+)/g, '<nowiki>$1</nowiki>' );
|
||||
}
|
||||
var insertText = '';
|
||||
var whitespace = $( '#wikieditor-toolbar-link-dialog' ).data( 'whitespace' );
|
||||
var target = $( '#wikieditor-toolbar-link-int-target' ).val();
|
||||
var text = $( '#wikieditor-toolbar-link-int-text' ).val();
|
||||
var insertText = '',
|
||||
whitespace = $( '#wikieditor-toolbar-link-dialog' ).data( 'whitespace' ),
|
||||
target = $( '#wikieditor-toolbar-link-int-target' ).val(),
|
||||
text = $( '#wikieditor-toolbar-link-int-text' ).val();
|
||||
// check if the tooltips were passed as target or text
|
||||
if ( $( '#wikieditor-toolbar-link-int-target' ).data( 'tooltip-mode' ) )
|
||||
if ( $( '#wikieditor-toolbar-link-int-target' ).data( 'tooltip-mode' ) ) {
|
||||
target = "";
|
||||
if ( $( '#wikieditor-toolbar-link-int-text' ).data( 'tooltip-mode' ) )
|
||||
}
|
||||
if ( $( '#wikieditor-toolbar-link-int-text' ).data( 'tooltip-mode' ) ) {
|
||||
text = "";
|
||||
}
|
||||
if ( target === '' ) {
|
||||
alert( mw.msg( 'wikieditor-toolbar-tool-link-empty' ) );
|
||||
return;
|
||||
|
@ -440,24 +443,26 @@ $.wikiEditor.modules.dialogs.config = {
|
|||
return;
|
||||
}
|
||||
|
||||
if ( target === text || !text.length )
|
||||
if ( target === text || !text.length ) {
|
||||
insertText = '[[' + target + ']]';
|
||||
else
|
||||
} else {
|
||||
insertText = '[[' + target + '|' + escapeInternalText( text ) + ']]';
|
||||
}
|
||||
} else {
|
||||
target = $.trim( target );
|
||||
// Prepend http:// if there is no protocol
|
||||
if ( !target.match( /^[a-z]+:\/\/./ ) )
|
||||
if ( !target.match( /^[a-z]+:\/\/./ ) ) {
|
||||
target = 'http://' + target;
|
||||
}
|
||||
|
||||
// Detect if this is really an internal link in disguise
|
||||
var match = target.match( $( this ).data( 'articlePathRegex' ) );
|
||||
if ( match && !$( this ).data( 'ignoreLooksInternal' ) ) {
|
||||
var buttons = { };
|
||||
var that = this;
|
||||
var buttons = { },
|
||||
that = this;
|
||||
buttons[ mw.msg( 'wikieditor-toolbar-tool-link-lookslikeinternal-int' ) ] =
|
||||
function () {
|
||||
$( '#wikieditor-toolbar-link-int-target' ).val( match[1] ).change();
|
||||
$( '#wikieditor-toolbar-link-int-target' ).val( match[ 1 ] ).change();
|
||||
$( this ).dialog( 'close' );
|
||||
};
|
||||
buttons[ mw.msg( 'wikieditor-toolbar-tool-link-lookslikeinternal-ext' ) ] =
|
||||
|
@ -468,25 +473,26 @@ $.wikiEditor.modules.dialogs.config = {
|
|||
$( this ).dialog( 'close' );
|
||||
};
|
||||
$.wikiEditor.modules.dialogs.quickDialog(
|
||||
mw.msg( 'wikieditor-toolbar-tool-link-lookslikeinternal', match[1] ),
|
||||
mw.msg( 'wikieditor-toolbar-tool-link-lookslikeinternal', match[ 1 ] ),
|
||||
{ buttons: buttons }
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
var escTarget = escapeExternalTarget( target );
|
||||
var escText = escapeExternalText( text );
|
||||
var escTarget = escapeExternalTarget( target ),
|
||||
escText = escapeExternalText( text );
|
||||
|
||||
if ( escTarget === escText )
|
||||
if ( escTarget === escText ) {
|
||||
insertText = escTarget;
|
||||
else if ( text === '' )
|
||||
} else if ( text === '' ) {
|
||||
insertText = '[' + escTarget + ']';
|
||||
else
|
||||
} else {
|
||||
insertText = '[' + escTarget + ' ' + escText + ']';
|
||||
}
|
||||
}
|
||||
// Preserve whitespace in selection when replacing
|
||||
if ( whitespace ) {
|
||||
insertText = whitespace[0] + insertText + whitespace[1];
|
||||
insertText = whitespace[ 0 ] + insertText + whitespace[ 1 ];
|
||||
}
|
||||
$( this ).dialog( 'close' );
|
||||
$.wikiEditor.modules.toolbar.fn.doAction( $( this ).data( 'context' ), {
|
||||
|
@ -531,18 +537,18 @@ $.wikiEditor.modules.dialogs.config = {
|
|||
if ( selection !== '' ) {
|
||||
if ( ( matches = selection.match( /^(\s*)\[\[([^\]\|]+)(\|([^\]\|]*))?\]\](\s*)$/ ) ) ) {
|
||||
// [[foo|bar]] or [[foo]]
|
||||
target = matches[2];
|
||||
text = ( matches[4] ? matches[4] : matches[2] );
|
||||
target = matches[ 2 ];
|
||||
text = ( matches[ 4 ] ? matches[ 4 ] : matches[ 2 ] );
|
||||
type = 'int';
|
||||
// Preserve whitespace when replacing
|
||||
$( '#wikieditor-toolbar-link-dialog' ).data( 'whitespace', [ matches[1], matches[5] ] );
|
||||
$( '#wikieditor-toolbar-link-dialog' ).data( 'whitespace', [ matches[ 1 ], matches[ 5 ] ] );
|
||||
} else if ( ( matches = selection.match( /^(\s*)\[([^\] ]+)( ([^\]]+))?\](\s*)$/ ) ) ) {
|
||||
// [http://www.example.com foo] or [http://www.example.com]
|
||||
target = matches[2];
|
||||
text = ( matches[4] || '' );
|
||||
target = matches[ 2 ];
|
||||
text = ( matches[ 4 ] || '' );
|
||||
type = 'ext';
|
||||
// Preserve whitespace when replacing
|
||||
$( '#wikieditor-toolbar-link-dialog' ).data( 'whitespace', [ matches[1], matches[5] ] );
|
||||
$( '#wikieditor-toolbar-link-dialog' ).data( 'whitespace', [ matches[ 1 ], matches[ 5 ] ] );
|
||||
} else {
|
||||
// Trim any leading and trailing whitespace from the selection,
|
||||
// but preserve it when replacing
|
||||
|
@ -559,12 +565,15 @@ $.wikiEditor.modules.dialogs.config = {
|
|||
|
||||
// Change the value by calling val() doesn't trigger the change event, so let's do that
|
||||
// ourselves
|
||||
if ( typeof text !== 'undefined' )
|
||||
if ( typeof text !== 'undefined' ) {
|
||||
$( '#wikieditor-toolbar-link-int-text' ).val( text ).change();
|
||||
if ( typeof target !== 'undefined' )
|
||||
}
|
||||
if ( typeof target !== 'undefined' ) {
|
||||
$( '#wikieditor-toolbar-link-int-target' ).val( target ).change();
|
||||
if ( typeof type !== 'undefined' )
|
||||
}
|
||||
if ( typeof type !== 'undefined' ) {
|
||||
$( '#wikieditor-toolbar-link-' + type ).prop( 'checked', true );
|
||||
}
|
||||
}
|
||||
$( '#wikieditor-toolbar-link-int-text' ).data( 'untouched',
|
||||
$( '#wikieditor-toolbar-link-int-text' ).val() ===
|
||||
|
@ -580,8 +589,9 @@ $.wikiEditor.modules.dialogs.config = {
|
|||
|
||||
$( '#wikieditor-toolbar-link-int-text, #wikiedit-toolbar-link-int-target' )
|
||||
.each( function () {
|
||||
if ( $( this ).val() === '' )
|
||||
if ( $( this ).val() === '' ) {
|
||||
$( this ).parent().find( 'label' ).show();
|
||||
}
|
||||
} );
|
||||
|
||||
if ( !$( this ).data( 'dialogkeypressset' ) ) {
|
||||
|
@ -631,9 +641,9 @@ $.wikiEditor.modules.dialogs.config = {
|
|||
{
|
||||
type: 'replace',
|
||||
options: {
|
||||
pre: whitespace[0] + '<ref' + attributes + '>',
|
||||
pre: whitespace[ 0 ] + '<ref' + attributes + '>',
|
||||
peri: insertText,
|
||||
post: '</ref>' + whitespace[1]
|
||||
post: '</ref>' + whitespace[ 1 ]
|
||||
}
|
||||
},
|
||||
$( this )
|
||||
|
@ -663,11 +673,11 @@ $.wikiEditor.modules.dialogs.config = {
|
|||
if ( selection !== '' ) {
|
||||
var matches, text;
|
||||
if ( ( matches = selection.match( /^(\s*)<ref([^\>]*)>([^<]*)<\/ref\>(\s*)$/ ) ) ) {
|
||||
text = matches[3];
|
||||
text = matches[ 3 ];
|
||||
// Preserve whitespace when replacing
|
||||
$( '#wikieditor-toolbar-reference-dialog' )
|
||||
.data( 'whitespace', [ matches[1], matches[4] ] );
|
||||
$( '#wikieditor-toolbar-reference-dialog' ).data( 'attributes', matches[2] );
|
||||
.data( 'whitespace', [ matches[ 1 ], matches[ 4 ] ] );
|
||||
$( '#wikieditor-toolbar-reference-dialog' ).data( 'attributes', matches[ 2 ] );
|
||||
} else {
|
||||
text = selection;
|
||||
}
|
||||
|
@ -771,9 +781,9 @@ $.wikiEditor.modules.dialogs.config = {
|
|||
);
|
||||
|
||||
// Restore form state
|
||||
$( ['#wikieditor-toolbar-file-target',
|
||||
$( [ '#wikieditor-toolbar-file-target',
|
||||
'#wikieditor-toolbar-file-caption',
|
||||
'#wikieditor-toolbar-file-size'].join( ',' )
|
||||
'#wikieditor-toolbar-file-size' ].join( ',' )
|
||||
).val( '' );
|
||||
$( '#wikieditor-toolbar-file-float' ).val( 'default' );
|
||||
/*jshint camelcase: false */
|
||||
|
@ -924,10 +934,12 @@ $.wikiEditor.modules.dialogs.config = {
|
|||
table = table.substr( 0, table.length - 1 ) + "\n";
|
||||
}
|
||||
var classes = [];
|
||||
if ( $( '#wikieditor-toolbar-table-wikitable' ).is( ':checked' ) )
|
||||
if ( $( '#wikieditor-toolbar-table-wikitable' ).is( ':checked' ) ) {
|
||||
classes.push( 'wikitable' );
|
||||
if ( $( '#wikieditor-toolbar-table-sortable' ).is( ':checked' ) )
|
||||
}
|
||||
if ( $( '#wikieditor-toolbar-table-sortable' ).is( ':checked' ) ) {
|
||||
classes.push( 'sortable' );
|
||||
}
|
||||
var classStr = classes.length > 0 ? ' class="' + classes.join( ' ' ) + '"' : '';
|
||||
$( this ).dialog( 'close' );
|
||||
$.wikiEditor.modules.toolbar.fn.doAction(
|
||||
|
@ -945,16 +957,19 @@ $.wikiEditor.modules.dialogs.config = {
|
|||
);
|
||||
|
||||
// Restore form state
|
||||
$( '#wikieditor-toolbar-table-dimensions-rows' ).val( 3 );
|
||||
$( '#wikieditor-toolbar-table-dimensions-columns' ).val( 3 );
|
||||
$( '#wikieditor-toolbar-table-dimensions-rows' ).val( 3 );
|
||||
$( '#wikieditor-toolbar-table-dimensions-columns' ).val( 3 );
|
||||
// Simulate clicks instead of setting values, so the according
|
||||
// actions are performed
|
||||
if ( !$( '#wikieditor-toolbar-table-dimensions-header' ).is( ':checked' ) )
|
||||
$( '#wikieditor-toolbar-table-dimensions-header' ).click();
|
||||
if ( !$( '#wikieditor-toolbar-table-wikitable' ).is( ':checked' ) )
|
||||
$( '#wikieditor-toolbar-table-wikitable' ).click();
|
||||
if ( $( '#wikieditor-toolbar-table-sortable' ).is( ':checked' ) )
|
||||
$( '#wikieditor-toolbar-table-sortable' ).click();
|
||||
if ( !$( '#wikieditor-toolbar-table-dimensions-header' ).is( ':checked' ) ) {
|
||||
$( '#wikieditor-toolbar-table-dimensions-header' ).click();
|
||||
}
|
||||
if ( !$( '#wikieditor-toolbar-table-wikitable' ).is( ':checked' ) ) {
|
||||
$( '#wikieditor-toolbar-table-wikitable' ).click();
|
||||
}
|
||||
if ( $( '#wikieditor-toolbar-table-sortable' ).is( ':checked' ) ) {
|
||||
$( '#wikieditor-toolbar-table-sortable' ).click();
|
||||
}
|
||||
},
|
||||
'wikieditor-toolbar-tool-table-cancel': function () {
|
||||
$( this ).dialog( 'close' );
|
||||
|
@ -984,22 +999,22 @@ $.wikiEditor.modules.dialogs.config = {
|
|||
}
|
||||
},
|
||||
'search-and-replace': {
|
||||
'browsers': {
|
||||
browsers: {
|
||||
// Left-to-right languages
|
||||
'ltr': {
|
||||
'msie': [['>=', 11]], // Known to work on 11.
|
||||
'firefox': [['>=', 2]],
|
||||
'opera': false,
|
||||
'safari': [['>=', 3]],
|
||||
'chrome': [['>=', 3]]
|
||||
ltr: {
|
||||
msie: [ [ '>=', 11 ] ], // Known to work on 11.
|
||||
firefox: [ [ '>=', 2 ] ],
|
||||
opera: false,
|
||||
safari: [ [ '>=', 3 ] ],
|
||||
chrome: [ [ '>=', 3 ] ]
|
||||
},
|
||||
// Right-to-left languages
|
||||
'rtl': {
|
||||
'msie': [['>=', 11]], // Works on 11 but dialog positioning is cruddy.
|
||||
'firefox': [['>=', 2]],
|
||||
'opera': false,
|
||||
'safari': [['>=', 3]],
|
||||
'chrome': [['>=', 3]]
|
||||
rtl: {
|
||||
msie: [ [ '>=', 11 ] ], // Works on 11 but dialog positioning is cruddy.
|
||||
firefox: [ [ '>=', 2 ] ],
|
||||
opera: false,
|
||||
safari: [ [ '>=', 3 ] ],
|
||||
chrome: [ [ '>=', 3 ] ]
|
||||
}
|
||||
},
|
||||
titleMsg: 'wikieditor-toolbar-tool-replace-title',
|
||||
|
@ -1083,25 +1098,25 @@ $.wikiEditor.modules.dialogs.config = {
|
|||
// FIXME: Repetitively calling encapsulateSelection() is probably the best strategy
|
||||
// in Firefox/Webkit, but in IE replacing the entire content once is better.
|
||||
for ( i = 0; i < match.length; i++ ) {
|
||||
index = textRemainder.indexOf( match[i] );
|
||||
index = textRemainder.indexOf( match[ i ] );
|
||||
if ( index === -1 ) {
|
||||
// This shouldn't happen
|
||||
break;
|
||||
}
|
||||
var matchedText = textRemainder.substr( index, match[i].length );
|
||||
textRemainder = textRemainder.substr( index + match[i].length );
|
||||
var matchedText = textRemainder.substr( index, match[ i ].length );
|
||||
textRemainder = textRemainder.substr( index + match[ i ].length );
|
||||
|
||||
start = index + offset;
|
||||
end = start + match[i].length;
|
||||
end = start + match[ i ].length;
|
||||
// Make regex placeholder substitution ($1) work
|
||||
var replace = isRegex ? matchedText.replace( regex, replaceStr ) : replaceStr;
|
||||
var newEnd = start + replace.length;
|
||||
$textarea
|
||||
.textSelection( 'setSelection', { 'start': start, 'end': end } )
|
||||
.textSelection( 'setSelection', { start: start, end: end } )
|
||||
.textSelection( 'encapsulateSelection', {
|
||||
'peri': replace,
|
||||
'replace': true } )
|
||||
.textSelection( 'setSelection', { 'start': start, 'end': newEnd } );
|
||||
peri: replace,
|
||||
replace: true } )
|
||||
.textSelection( 'setSelection', { start: start, end: newEnd } );
|
||||
offset = newEnd;
|
||||
}
|
||||
$( '#wikieditor-toolbar-replace-success' )
|
||||
|
@ -1115,7 +1130,7 @@ $.wikiEditor.modules.dialogs.config = {
|
|||
|
||||
if ( isRegex ) {
|
||||
// If backreferences (like $1) are used, the actual actual replacement string will be different
|
||||
actualReplacement = match[0].replace( regex, replaceStr );
|
||||
actualReplacement = match[ 0 ].replace( regex, replaceStr );
|
||||
} else {
|
||||
actualReplacement = replaceStr;
|
||||
}
|
||||
|
@ -1123,20 +1138,20 @@ $.wikiEditor.modules.dialogs.config = {
|
|||
if ( match ) {
|
||||
// Do the replacement
|
||||
$textarea.textSelection( 'encapsulateSelection', {
|
||||
'peri': actualReplacement,
|
||||
'replace': true } );
|
||||
peri: actualReplacement,
|
||||
replace: true } );
|
||||
// Reload the text after replacement
|
||||
text = $textarea.textSelection( 'getContents' );
|
||||
}
|
||||
|
||||
// Find the next instance
|
||||
offset = offset + match[0].length + actualReplacement.length;
|
||||
offset = offset + match[ 0 ].length + actualReplacement.length;
|
||||
textRemainder = text.substr( offset );
|
||||
match = textRemainder.match( regex );
|
||||
|
||||
if ( match ) {
|
||||
start = offset + match.index;
|
||||
end = start + match[0].length;
|
||||
end = start + match[ 0 ].length;
|
||||
} else {
|
||||
// If no new string was found, try searching from the beginning.
|
||||
// TODO: Add a "Wrap around" option.
|
||||
|
@ -1144,7 +1159,7 @@ $.wikiEditor.modules.dialogs.config = {
|
|||
match = textRemainder.match( regex );
|
||||
if ( match ) {
|
||||
start = match.index;
|
||||
end = start + match[0].length;
|
||||
end = start + match[ 0 ].length;
|
||||
} else {
|
||||
// Give up
|
||||
start = 0;
|
||||
|
@ -1153,18 +1168,17 @@ $.wikiEditor.modules.dialogs.config = {
|
|||
}
|
||||
} else {
|
||||
start = offset + match.index;
|
||||
end = start + match[0].length;
|
||||
end = start + match[ 0 ].length;
|
||||
}
|
||||
|
||||
$( this ).data( 'matchIndex', start );
|
||||
|
||||
$textarea.textSelection( 'setSelection', {
|
||||
'start': start,
|
||||
'end': end
|
||||
} );
|
||||
start: start,
|
||||
end: end } );
|
||||
$textarea.textSelection( 'scrollToCaretPosition' );
|
||||
$( this ).data( 'offset', end );
|
||||
$textarea[0].focus();
|
||||
$textarea[ 0 ].focus();
|
||||
}
|
||||
} );
|
||||
},
|
||||
|
|
|
@ -11,25 +11,35 @@ $.wikiEditor.modules.dialogs = {
|
|||
browsers: {
|
||||
// Left-to-right languages
|
||||
ltr: {
|
||||
msie: [['>=', 7]],
|
||||
msie: [ [ '>=', 7 ] ],
|
||||
// jQuery UI appears to be broken in FF 2.0 - 2.0.0.4
|
||||
firefox: [
|
||||
['>=', 2], ['!=', '2.0'], ['!=', '2.0.0.1'], ['!=', '2.0.0.2'], ['!=', '2.0.0.3'], ['!=', '2.0.0.4']
|
||||
[ '>=', 2 ],
|
||||
[ '!=', '2.0' ],
|
||||
[ '!=', '2.0.0.1' ],
|
||||
[ '!=', '2.0.0.2' ],
|
||||
[ '!=', '2.0.0.3' ],
|
||||
[ '!=', '2.0.0.4' ]
|
||||
],
|
||||
opera: [['>=', 9.6]],
|
||||
safari: [['>=', 3]],
|
||||
chrome: [['>=', 3]]
|
||||
opera: [ [ '>=', 9.6 ] ],
|
||||
safari: [ [ '>=', 3 ] ],
|
||||
chrome: [ [ '>=', 3 ] ]
|
||||
},
|
||||
// Right-to-left languages
|
||||
rtl: {
|
||||
msie: [['>=', 7]],
|
||||
msie: [ [ '>=', 7 ] ],
|
||||
// jQuery UI appears to be broken in FF 2.0 - 2.0.0.4
|
||||
firefox: [
|
||||
['>=', 2], ['!=', '2.0'], ['!=', '2.0.0.1'], ['!=', '2.0.0.2'], ['!=', '2.0.0.3'], ['!=', '2.0.0.4']
|
||||
[ '>=', 2 ],
|
||||
[ '!=', '2.0' ],
|
||||
[ '!=', '2.0.0.1' ],
|
||||
[ '!=', '2.0.0.2' ],
|
||||
[ '!=', '2.0.0.3' ],
|
||||
[ '!=', '2.0.0.4' ]
|
||||
],
|
||||
opera: [['>=', 9.6]],
|
||||
safari: [['>=', 3]],
|
||||
chrome: [['>=', 3]]
|
||||
opera: [ [ '>=', 9.6 ] ],
|
||||
safari: [ [ '>=', 3 ] ],
|
||||
chrome: [ [ '>=', 3 ] ]
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -42,7 +52,7 @@ $.wikiEditor.modules.dialogs = {
|
|||
},
|
||||
openDialog: function ( context, module ) {
|
||||
if ( module in $.wikiEditor.modules.dialogs.modules ) {
|
||||
var mod = $.wikiEditor.modules.dialogs.modules[module],
|
||||
var mod = $.wikiEditor.modules.dialogs.modules[ module ],
|
||||
$dialog = $( '#' + mod.id );
|
||||
if ( $dialog.length === 0 ) {
|
||||
$.wikiEditor.modules.dialogs.fn.reallyCreate( context, mod, module );
|
||||
|
@ -59,7 +69,7 @@ $.wikiEditor.modules.dialogs = {
|
|||
},
|
||||
closeDialog: function ( context, module ) {
|
||||
if ( module in $.wikiEditor.modules.dialogs.modules ) {
|
||||
$( '#' + $.wikiEditor.modules.dialogs.modules[module].id ).dialog( 'close' );
|
||||
$( '#' + $.wikiEditor.modules.dialogs.modules[ module ].id ).dialog( 'close' );
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -79,12 +89,12 @@ $.wikiEditor.modules.dialogs = {
|
|||
|
||||
// Defer building of modules, unless they require immediate creation
|
||||
for ( mod in config ) {
|
||||
module = config[mod];
|
||||
module = config[ mod ];
|
||||
// Only create the dialog if it's supported, isn't filtered and doesn't exist yet
|
||||
filtered = false;
|
||||
if ( typeof module.filters !== 'undefined' ) {
|
||||
for ( i = 0; i < module.filters.length; i++ ) {
|
||||
if ( $( module.filters[i] ).length === 0 ) {
|
||||
if ( $( module.filters[ i ] ).length === 0 ) {
|
||||
filtered = true;
|
||||
break;
|
||||
}
|
||||
|
@ -98,7 +108,7 @@ $.wikiEditor.modules.dialogs = {
|
|||
// Re-select from the DOM, we might have removed the dialog just now
|
||||
$existingDialog = $( '#' + module.id );
|
||||
if ( !filtered && $.wikiEditor.isSupported( module ) && $existingDialog.length === 0 ) {
|
||||
$.wikiEditor.modules.dialogs.modules[mod] = module;
|
||||
$.wikiEditor.modules.dialogs.modules[ mod ] = module;
|
||||
context.$textarea.trigger( 'wikiEditor-dialogs-setup-' + mod );
|
||||
// If this dialog requires immediate creation, create it now
|
||||
if ( typeof module.immediateCreate !== 'undefined' && module.immediateCreate ) {
|
||||
|
@ -110,9 +120,10 @@ $.wikiEditor.modules.dialogs = {
|
|||
|
||||
/**
|
||||
* Build the actual dialog. This done on-demand rather than in create()
|
||||
*
|
||||
* @param {Object} context Context object of editor dialog belongs to
|
||||
* @param {Object} module Dialog module object
|
||||
* @param {String} name Dialog name (key in $.wikiEditor.modules.dialogs.modules)
|
||||
* @param {string} name Dialog name (key in $.wikiEditor.modules.dialogs.modules)
|
||||
*/
|
||||
reallyCreate: function ( context, module, name ) {
|
||||
var msg, dialogDiv, $content,
|
||||
|
@ -130,7 +141,7 @@ $.wikiEditor.modules.dialogs = {
|
|||
// foo = { mw.msg( 'bar' ): baz }
|
||||
configuration.newButtons = {};
|
||||
for ( msg in configuration.buttons ) {
|
||||
configuration.newButtons[mw.msg( msg )] = configuration.buttons[msg];
|
||||
configuration.newButtons[ mw.msg( msg ) ] = configuration.buttons[ msg ];
|
||||
}
|
||||
configuration.buttons = configuration.newButtons;
|
||||
if ( module.htmlTemplate ) {
|
||||
|
@ -199,7 +210,7 @@ $.wikiEditor.modules.dialogs = {
|
|||
wrapperWidth = Math.max( wrapper.get( 0 ).scrollWidth, wrapperWidth );
|
||||
wrapper.width( wrapperWidth );
|
||||
$( this ).data( 'wrapperWidth', wrapperWidth );
|
||||
$( this ).dialog( { 'width': wrapper.width() } );
|
||||
$( this ).dialog( { width: wrapper.width() } );
|
||||
wrapper.css( 'left', parseInt( wrapper.css( 'left' ), 10 ) - ( wrapper.width() - oldWidth ) / 2 );
|
||||
}
|
||||
$( this ).css( 'white-space', oldWS );
|
||||
|
@ -207,9 +218,11 @@ $.wikiEditor.modules.dialogs = {
|
|||
$( this ).attr( 'style', $( this ).data( 'oldstyle' ) );
|
||||
} );
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the right tabindexes on elements in a dialog
|
||||
* @param $elements Elements to set tabindexes on. If they already have tabindexes, this function can behave a bit weird
|
||||
*
|
||||
* @param {Object} $elements Elements to set tabindexes on. If they already have tabindexes, this function can behave a bit weird
|
||||
*/
|
||||
setTabindexes: function ( $elements ) {
|
||||
// Get the highest tab index
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
*
|
||||
*/
|
||||
/*jshint onevar:false, boss:true */
|
||||
// jscs:disable requireParamTypes
|
||||
( function ( $, mw ) {
|
||||
|
||||
var hasOwn = Object.prototype.hasOwnProperty,
|
||||
|
@ -21,7 +22,7 @@ fallbackChain = ( function () {
|
|||
chain = mw.language.getFallbackLanguageChain();
|
||||
|
||||
// Do not fallback to 'en'
|
||||
if ( chain.length >= 2 && !/^en-/.test( chain[chain.length - 2] ) ) {
|
||||
if ( chain.length >= 2 && !/^en-/.test( chain[ chain.length - 2 ] ) ) {
|
||||
chain.pop();
|
||||
}
|
||||
if ( isRTL ) {
|
||||
|
@ -65,34 +66,34 @@ $.wikiEditor = {
|
|||
// Left-to-right languages
|
||||
ltr: {
|
||||
// The toolbar layout is broken in IE6
|
||||
msie: [['>=', 7]],
|
||||
msie: [ [ '>=', 7 ] ],
|
||||
// Layout issues in FF < 2
|
||||
firefox: [['>=', 2]],
|
||||
firefox: [ [ '>=', 2 ] ],
|
||||
// Text selection bugs galore
|
||||
opera: [['>=', 9.6]],
|
||||
opera: [ [ '>=', 9.6 ] ],
|
||||
// jQuery minimums
|
||||
safari: [['>=', 3]],
|
||||
chrome: [['>=', 3]],
|
||||
netscape: [['>=', 9]],
|
||||
safari: [ [ '>=', 3 ] ],
|
||||
chrome: [ [ '>=', 3 ] ],
|
||||
netscape: [ [ '>=', 9 ] ],
|
||||
blackberry: false,
|
||||
ipod: [['>=', 6]],
|
||||
iphone: [['>=', 6]]
|
||||
ipod: [ [ '>=', 6 ] ],
|
||||
iphone: [ [ '>=', 6 ] ]
|
||||
},
|
||||
// Right-to-left languages
|
||||
rtl: {
|
||||
// The toolbar layout is broken in IE 7 in RTL mode, and IE6 in any mode
|
||||
msie: [['>=', 8]],
|
||||
msie: [ [ '>=', 8 ] ],
|
||||
// Layout issues in FF < 2
|
||||
firefox: [['>=', 2]],
|
||||
firefox: [ [ '>=', 2 ] ],
|
||||
// Text selection bugs galore
|
||||
opera: [['>=', 9.6]],
|
||||
opera: [ [ '>=', 9.6 ] ],
|
||||
// jQuery minimums
|
||||
safari: [['>=', 3]],
|
||||
chrome: [['>=', 3]],
|
||||
netscape: [['>=', 9]],
|
||||
safari: [ [ '>=', 3 ] ],
|
||||
chrome: [ [ '>=', 3 ] ],
|
||||
netscape: [ [ '>=', 9 ] ],
|
||||
blackberry: false,
|
||||
ipod: [['>=', 6]],
|
||||
iphone: [['>=', 6]]
|
||||
ipod: [ [ '>=', 6 ] ],
|
||||
iphone: [ [ '>=', 6 ] ]
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -112,7 +113,8 @@ $.wikiEditor = {
|
|||
* similar to another existing browser that things actually do work as expected. The merrits of this argument, which
|
||||
* is essentially to blacklist rather than whitelist are debateable, but at this point we've decided it's the more
|
||||
* "open-web" way to go.
|
||||
* @param module Module object, defaults to $.wikiEditor
|
||||
*
|
||||
* @param {Object} module Module object, defaults to $.wikiEditor
|
||||
*/
|
||||
isSupported: function ( module ) {
|
||||
// Fallback to the wikiEditor browser map if no special map is provided in the module
|
||||
|
@ -128,13 +130,14 @@ $.wikiEditor = {
|
|||
|
||||
/**
|
||||
* Checks if a module has a specific requirement
|
||||
* @param module Module object
|
||||
* @param requirement String identifying requirement
|
||||
*
|
||||
* @param {Object} module Module object
|
||||
* @param {string} requirement String identifying requirement
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -145,8 +148,8 @@ $.wikiEditor = {
|
|||
/**
|
||||
* Provides a way to extract messages from objects. Wraps a mediaWiki.message( ... ).plain() call.
|
||||
*
|
||||
* @param object Object to extract messages from
|
||||
* @param property String of name of property which contains the message. This should be the base name of the
|
||||
* @param {Object} object Object to extract messages from
|
||||
* @param {string} property String of name of property which contains the message. This should be the base name of the
|
||||
* property, which means that in the case of the object { this: 'that', fooMsg: 'bar' }, passing property as 'this'
|
||||
* would return the raw text 'that', while passing property as 'foo' would return the internationalized message
|
||||
* with the key 'bar'.
|
||||
|
@ -156,16 +159,16 @@ $.wikiEditor = {
|
|||
// Accept array of possible properties, of which the first one found will be used
|
||||
if ( typeof property === 'object' ) {
|
||||
for ( i in property ) {
|
||||
if ( property[i] in object || property[i] + 'Msg' in object ) {
|
||||
property = property[i];
|
||||
if ( property[ i ] in object || property[ i ] + 'Msg' in object ) {
|
||||
property = property[ i ];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( property in object ) {
|
||||
return object[property];
|
||||
return object[ property ];
|
||||
} else if ( property + 'Msg' in object ) {
|
||||
p = object[property + 'Msg'];
|
||||
p = object[ property + 'Msg' ];
|
||||
if ( $.isArray( p ) && p.length >= 2 ) {
|
||||
return mw.message.apply( mw.message, p ).plain();
|
||||
} else {
|
||||
|
@ -182,15 +185,15 @@ $.wikiEditor = {
|
|||
* should ideally be the case so that you may use a string or object of any number of strings keyed by language
|
||||
* with a default.
|
||||
*
|
||||
* @param object Object to extract property from
|
||||
* @param {Object} object Object to extract property from
|
||||
*/
|
||||
autoLang: function ( object ) {
|
||||
var i, key;
|
||||
|
||||
for ( i = 0; i < fallbackChain.length; i++ ) {
|
||||
key = fallbackChain[i];
|
||||
key = fallbackChain[ i ];
|
||||
if ( hasOwn.call( object, key ) ) {
|
||||
return object[key];
|
||||
return object[ key ];
|
||||
}
|
||||
}
|
||||
return object;
|
||||
|
@ -200,14 +203,14 @@ $.wikiEditor = {
|
|||
* Provides a way to extract the path of an icon in a certain language, automatically appending a version number for
|
||||
* caching purposes and prepending an image path when icon paths are relative.
|
||||
*
|
||||
* @param icon Icon object from e.g. toolbar config
|
||||
* @param path Default icon path, defaults to $.wikiEditor.imgPath
|
||||
* @param {Object} icon Icon object from e.g. toolbar config
|
||||
* @param {string} path Default icon path, defaults to $.wikiEditor.imgPath
|
||||
*/
|
||||
autoIcon: function ( icon, path ) {
|
||||
var src = $.wikiEditor.autoLang( icon );
|
||||
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.getVersion( 'jquery.wikiEditor' );
|
||||
|
@ -216,9 +219,10 @@ $.wikiEditor = {
|
|||
/**
|
||||
* Get the sprite offset for a language if available, icon for a language if available, or the default offset or icon,
|
||||
* in that order of preference.
|
||||
* @param icon Icon object, see autoIcon()
|
||||
* @param offset Offset object
|
||||
* @param path Icon path, see autoIcon()
|
||||
*
|
||||
* @param {Object} icon Icon object, see autoIcon()
|
||||
* @param {Object} offset Offset object
|
||||
* @param {string} path Icon path, see autoIcon()
|
||||
*/
|
||||
autoIconOrOffset: function ( icon, offset, path ) {
|
||||
var i, key, src;
|
||||
|
@ -226,14 +230,14 @@ $.wikiEditor = {
|
|||
path = path || $.wikiEditor.imgPath;
|
||||
|
||||
for ( i = 0; i < fallbackChain.length; i++ ) {
|
||||
key = fallbackChain[i];
|
||||
key = fallbackChain[ i ];
|
||||
if ( offset && hasOwn.call( offset, key ) ) {
|
||||
return offset[key];
|
||||
return offset[ key ];
|
||||
}
|
||||
if ( icon && hasOwn.call( icon, key ) ) {
|
||||
src = icon[key];
|
||||
src = icon[ key ];
|
||||
// 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.getVersion( 'jquery.wikiEditor' );
|
||||
|
@ -248,382 +252,382 @@ $.wikiEditor = {
|
|||
*/
|
||||
$.fn.wikiEditor = function () {
|
||||
|
||||
// Skip any further work when running in browsers that are unsupported
|
||||
if ( !$.wikiEditor.isSupported() ) {
|
||||
return $( this );
|
||||
}
|
||||
// Skip any further work when running in browsers that are unsupported
|
||||
if ( !$.wikiEditor.isSupported() ) {
|
||||
return $( this );
|
||||
}
|
||||
|
||||
// Save browser profile for detailed tests.
|
||||
var profile = $.client.profile();
|
||||
// Save browser profile for detailed tests.
|
||||
var profile = $.client.profile();
|
||||
|
||||
/* Initialization */
|
||||
/* 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' );
|
||||
// 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' ) {
|
||||
// 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' );
|
||||
// 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' ) {
|
||||
|
||||
// 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 ),
|
||||
// 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
|
||||
'modules': {},
|
||||
// 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,
|
||||
// Saved selection state for old IE (<=10)
|
||||
'savedSelection': null,
|
||||
// List of extensions active on this context
|
||||
'extensions': []
|
||||
};
|
||||
// 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 ),
|
||||
// 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
|
||||
modules: {},
|
||||
// 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,
|
||||
// Saved selection state for old IE (<=10)
|
||||
savedSelection: null,
|
||||
// List of extensions active on this context
|
||||
extensions: []
|
||||
};
|
||||
|
||||
/**
|
||||
* Externally Accessible API
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
context.api = {
|
||||
/**
|
||||
* Activates a module on a specific context with optional configuration data.
|
||||
* Externally Accessible API
|
||||
*
|
||||
* @param data Either a string of the name of a module to add without any additional configuration parameters,
|
||||
* or an object with members keyed with module names and valued with configuration objects.
|
||||
* 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.
|
||||
*/
|
||||
'addModule': function ( context, data ) {
|
||||
var module, call,
|
||||
modules = {};
|
||||
if ( typeof data === 'string' ) {
|
||||
modules[data] = {};
|
||||
} else if ( typeof data === 'object' ) {
|
||||
modules = data;
|
||||
|
||||
context.api = {
|
||||
/*!
|
||||
* Activates a module on a specific context with optional configuration data.
|
||||
*
|
||||
* @param data Either a string of the name of a module to add without any additional configuration parameters,
|
||||
* or an object with members keyed with module names and valued with configuration objects.
|
||||
*/
|
||||
addModule: function ( context, data ) {
|
||||
var module, call,
|
||||
modules = {};
|
||||
if ( typeof data === 'string' ) {
|
||||
modules[ data ] = {};
|
||||
} 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' &&
|
||||
$.wikiEditor.isSupported( $.wikiEditor.modules[ module ] )
|
||||
) {
|
||||
// Extend the context's core API with this module's own API calls
|
||||
if ( 'api' in $.wikiEditor.modules[ module ] ) {
|
||||
for ( call in $.wikiEditor.modules[ module ].api ) {
|
||||
// Modules may not overwrite existing API functions - first come, first serve
|
||||
if ( !( call in context.api ) ) {
|
||||
context.api[ call ] = $.wikiEditor.modules[ module ].api[ call ];
|
||||
}
|
||||
}
|
||||
}
|
||||
// Activate the module on this context
|
||||
if ( 'fn' in $.wikiEditor.modules[ module ] && 'create' in $.wikiEditor.modules[ module ].fn ) {
|
||||
// Add a place for the module to put it's own stuff
|
||||
context.modules[ module ] = {};
|
||||
// Tell the module to create itself on the context
|
||||
$.wikiEditor.modules[ module ].fn.create( context, modules[ module ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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' &&
|
||||
$.wikiEditor.isSupported( $.wikiEditor.modules[module] ) )
|
||||
{
|
||||
// Extend the context's core API with this module's own API calls
|
||||
if ( 'api' in $.wikiEditor.modules[module] ) {
|
||||
for ( call in $.wikiEditor.modules[module].api ) {
|
||||
// Modules may not overwrite existing API functions - first come, first serve
|
||||
if ( !( call in context.api ) ) {
|
||||
context.api[call] = $.wikiEditor.modules[module].api[call];
|
||||
};
|
||||
|
||||
/**
|
||||
* Event Handlers
|
||||
*
|
||||
* These act as filters returning false if the event should be ignored or returning true if it should be passed
|
||||
* on to all modules. This is also where we can attach some extra information to the events.
|
||||
*/
|
||||
|
||||
context.evt = {
|
||||
/* Empty until extensions add some; see jquery.wikiEditor.iframe.js for examples. */
|
||||
};
|
||||
|
||||
/* Internal Functions */
|
||||
|
||||
context.fn = {
|
||||
/**
|
||||
* Executes core event filters as well as event handlers provided by modules.
|
||||
*/
|
||||
trigger: function ( name, event ) {
|
||||
// Workaround for a scrolling bug in IE8 (bug 61908)
|
||||
if ( profile.name === 'msie' && profile.versionNumber === 8 ) {
|
||||
context.$textarea.css( 'width', context.$textarea.parent().width() );
|
||||
}
|
||||
|
||||
// Event is an optional argument, but from here on out, at least the type field should be dependable
|
||||
if ( typeof event === 'undefined' ) {
|
||||
event = { type: 'custom' };
|
||||
}
|
||||
// Ensure there's a place for extra information to live
|
||||
if ( typeof event.data === 'undefined' ) {
|
||||
event.data = {};
|
||||
}
|
||||
|
||||
// Allow filtering to occur
|
||||
if ( name in context.evt ) {
|
||||
if ( !context.evt[ name ]( event ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
var returnFromModules = null; // they return null by default
|
||||
// Pass the event around to all modules activated on this context
|
||||
|
||||
for ( var module in context.modules ) {
|
||||
if (
|
||||
module in $.wikiEditor.modules &&
|
||||
'evt' in $.wikiEditor.modules[ module ] &&
|
||||
name in $.wikiEditor.modules[ module ].evt
|
||||
) {
|
||||
var ret = $.wikiEditor.modules[ module ].evt[ name ]( context, event );
|
||||
if ( ret !== null ) {
|
||||
// if 1 returns false, the end result is false
|
||||
if ( returnFromModules === null ) {
|
||||
returnFromModules = ret;
|
||||
} else {
|
||||
returnFromModules = returnFromModules && ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Activate the module on this context
|
||||
if ( 'fn' in $.wikiEditor.modules[module] && 'create' in $.wikiEditor.modules[module].fn ) {
|
||||
// Add a place for the module to put it's own stuff
|
||||
context.modules[module] = {};
|
||||
// Tell the module to create itself on the context
|
||||
$.wikiEditor.modules[module].fn.create( context, modules[module] );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Event Handlers
|
||||
*
|
||||
* These act as filters returning false if the event should be ignored or returning true if it should be passed
|
||||
* on to all modules. This is also where we can attach some extra information to the events.
|
||||
*/
|
||||
|
||||
context.evt = {
|
||||
/* Empty until extensions add some; see jquery.wikiEditor.iframe.js for examples. */
|
||||
};
|
||||
|
||||
/* Internal Functions */
|
||||
|
||||
context.fn = {
|
||||
/**
|
||||
* Executes core event filters as well as event handlers provided by modules.
|
||||
*/
|
||||
trigger: function ( name, event ) {
|
||||
// Workaround for a scrolling bug in IE8 (bug 61908)
|
||||
if ( profile.name === 'msie' && profile.versionNumber === 8 ) {
|
||||
context.$textarea.css( 'width', context.$textarea.parent().width() );
|
||||
}
|
||||
|
||||
// Event is an optional argument, but from here on out, at least the type field should be dependable
|
||||
if ( typeof event === 'undefined' ) {
|
||||
event = { 'type': 'custom' };
|
||||
}
|
||||
// Ensure there's a place for extra information to live
|
||||
if ( typeof event.data === 'undefined' ) {
|
||||
event.data = {};
|
||||
}
|
||||
|
||||
// Allow filtering to occur
|
||||
if ( name in context.evt ) {
|
||||
if ( !context.evt[name]( event ) ) {
|
||||
return false;
|
||||
if ( returnFromModules !== null ) {
|
||||
return returnFromModules;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
var returnFromModules = null; // they return null by default
|
||||
// Pass the event around to all modules activated on this context
|
||||
},
|
||||
|
||||
for ( var module in context.modules ) {
|
||||
if (
|
||||
module in $.wikiEditor.modules &&
|
||||
'evt' in $.wikiEditor.modules[module] &&
|
||||
name in $.wikiEditor.modules[module].evt
|
||||
) {
|
||||
var ret = $.wikiEditor.modules[module].evt[name]( context, event );
|
||||
if ( ret !== null ) {
|
||||
// if 1 returns false, the end result is false
|
||||
if ( returnFromModules === null ) {
|
||||
returnFromModules = ret;
|
||||
} else {
|
||||
returnFromModules = returnFromModules && ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( returnFromModules !== null ) {
|
||||
return returnFromModules;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a button to the UI
|
||||
*/
|
||||
addButton: function ( options ) {
|
||||
// Ensure that buttons and tabs are visible
|
||||
context.$controls.show();
|
||||
context.$buttons.show();
|
||||
return $( '<button>' )
|
||||
.text( $.wikiEditor.autoMsg( options, 'caption' ) )
|
||||
.click( options.action )
|
||||
.appendTo( context.$buttons );
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a view to the UI, which is accessed using a set of tabs. Views are mutually exclusive and by default a
|
||||
* wikitext view will be present. Only when more than one view exists will the tabs will be visible.
|
||||
*/
|
||||
addView: function ( options ) {
|
||||
// Adds a tab
|
||||
function addTab( options ) {
|
||||
/**
|
||||
* Adds a button to the UI
|
||||
*/
|
||||
addButton: function ( options ) {
|
||||
// Ensure that buttons and tabs are visible
|
||||
context.$controls.show();
|
||||
context.$tabs.show();
|
||||
// Return the newly appended tab
|
||||
context.$buttons.show();
|
||||
return $( '<button>' )
|
||||
.text( $.wikiEditor.autoMsg( options, 'caption' ) )
|
||||
.click( options.action )
|
||||
.appendTo( context.$buttons );
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a view to the UI, which is accessed using a set of tabs. Views are mutually exclusive and by default a
|
||||
* wikitext view will be present. Only when more than one view exists will the tabs will be visible.
|
||||
*/
|
||||
addView: function ( options ) {
|
||||
// Adds a tab
|
||||
function addTab( options ) {
|
||||
// Ensure that buttons and tabs are visible
|
||||
context.$controls.show();
|
||||
context.$tabs.show();
|
||||
// Return the newly appended tab
|
||||
return $( '<div>' )
|
||||
.attr( 'rel', 'wikiEditor-ui-view-' + options.name )
|
||||
.addClass( context.view === options.name ? 'current' : null )
|
||||
.append( $( '<a>' )
|
||||
.attr( 'href', '#' )
|
||||
.mousedown( function () {
|
||||
// No dragging!
|
||||
return false;
|
||||
} )
|
||||
.click( function ( event ) {
|
||||
context.$ui.find( '.wikiEditor-ui-view' ).hide();
|
||||
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' ) {
|
||||
options.init( context );
|
||||
}
|
||||
event.preventDefault();
|
||||
return false;
|
||||
} )
|
||||
.text( $.wikiEditor.autoMsg( options, 'title' ) )
|
||||
)
|
||||
.appendTo( context.$tabs );
|
||||
}
|
||||
// Automatically add the previously not-needed wikitext tab
|
||||
if ( !context.$tabs.children().length ) {
|
||||
addTab( { name: 'wikitext', titleMsg: 'wikieditor-wikitext-tab' } );
|
||||
}
|
||||
// Add the tab for the view we were actually asked to add
|
||||
addTab( options );
|
||||
// Return newly appended view
|
||||
return $( '<div>' )
|
||||
.attr( 'rel', 'wikiEditor-ui-view-' + options.name )
|
||||
.addClass( context.view === options.name ? 'current' : null )
|
||||
.append( $( '<a>' )
|
||||
.attr( 'href', '#' )
|
||||
.mousedown( function () {
|
||||
// No dragging!
|
||||
return false;
|
||||
} )
|
||||
.click( function ( event ) {
|
||||
context.$ui.find( '.wikiEditor-ui-view' ).hide();
|
||||
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' ) {
|
||||
options.init( context );
|
||||
}
|
||||
event.preventDefault();
|
||||
return false;
|
||||
} )
|
||||
.text( $.wikiEditor.autoMsg( options, 'title' ) )
|
||||
)
|
||||
.appendTo( context.$tabs );
|
||||
}
|
||||
// Automatically add the previously not-needed wikitext tab
|
||||
if ( !context.$tabs.children().length ) {
|
||||
addTab( { 'name': 'wikitext', 'titleMsg': 'wikieditor-wikitext-tab' } );
|
||||
}
|
||||
// Add the tab for the view we were actually asked to add
|
||||
addTab( options );
|
||||
// Return newly appended view
|
||||
return $( '<div>' )
|
||||
.addClass( 'wikiEditor-ui-view wikiEditor-ui-view-' + options.name )
|
||||
.hide()
|
||||
.appendTo( context.$ui );
|
||||
},
|
||||
.addClass( 'wikiEditor-ui-view wikiEditor-ui-view-' + options.name )
|
||||
.hide()
|
||||
.appendTo( context.$ui );
|
||||
},
|
||||
|
||||
/**
|
||||
* Save scrollTop and cursor position for old IE (<=10)
|
||||
* Related to old IE 8 issues that are no longer reproducible
|
||||
*/
|
||||
saveCursorAndScrollTop: function () {
|
||||
if ( profile.name === 'msie' && document.selection && document.selection.createRange ) {
|
||||
var IHateIE8 = {
|
||||
'scrollTop': context.$textarea.scrollTop(),
|
||||
'pos': context.$textarea.textSelection( 'getCaretPosition', { startAndEnd: true } )
|
||||
};
|
||||
context.$textarea.data( 'IHateIE8', IHateIE8 );
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Save scrollTop and cursor position for old IE (<=10)
|
||||
* Related to old IE 8 issues that are no longer reproducible
|
||||
*/
|
||||
saveCursorAndScrollTop: function () {
|
||||
if ( profile.name === 'msie' && document.selection && document.selection.createRange ) {
|
||||
var IHateIE8 = {
|
||||
scrollTop: context.$textarea.scrollTop(),
|
||||
pos: context.$textarea.textSelection( 'getCaretPosition', { startAndEnd: true } )
|
||||
};
|
||||
context.$textarea.data( 'IHateIE8', IHateIE8 );
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Restore scrollTo and cursor position for IE (<=10)
|
||||
* Related to old IE 8 issues that are no longer reproducible
|
||||
*/
|
||||
restoreCursorAndScrollTop: function () {
|
||||
if ( profile.name === 'msie' && document.selection && document.selection.createRange ) {
|
||||
var IHateIE8 = context.$textarea.data( 'IHateIE' );
|
||||
if ( IHateIE8 ) {
|
||||
context.$textarea.scrollTop( IHateIE8.scrollTop );
|
||||
context.$textarea.textSelection( 'setSelection', { start: IHateIE8.pos[0], end: IHateIE8.pos[1] } );
|
||||
context.$textarea.data( 'IHateIE8', null );
|
||||
/**
|
||||
* Restore scrollTo and cursor position for IE (<=10)
|
||||
* Related to old IE 8 issues that are no longer reproducible
|
||||
*/
|
||||
restoreCursorAndScrollTop: function () {
|
||||
if ( profile.name === 'msie' && document.selection && document.selection.createRange ) {
|
||||
var IHateIE8 = context.$textarea.data( 'IHateIE' );
|
||||
if ( IHateIE8 ) {
|
||||
context.$textarea.scrollTop( IHateIE8.scrollTop );
|
||||
context.$textarea.textSelection( 'setSelection', { start: IHateIE8.pos[ 0 ], end: IHateIE8.pos[ 1 ] } );
|
||||
context.$textarea.data( 'IHateIE8', null );
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Save text selection for old IE (<=10)
|
||||
*/
|
||||
saveSelection: function () {
|
||||
if ( profile.name === 'msie' && document.selection && document.selection.createRange ) {
|
||||
context.$textarea.focus();
|
||||
context.savedSelection = document.selection.createRange();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Restore text selection for old IE (<=10)
|
||||
*/
|
||||
restoreSelection: function () {
|
||||
if ( profile.name === 'msie' && context.savedSelection !== null ) {
|
||||
context.$textarea.focus();
|
||||
context.savedSelection.select();
|
||||
context.savedSelection = null;
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Save text selection for old IE (<=10)
|
||||
* Workaround for a scrolling bug in IE8 (bug 61908)
|
||||
*/
|
||||
saveSelection: function () {
|
||||
if ( profile.name === 'msie' && document.selection && document.selection.createRange ) {
|
||||
context.$textarea.focus();
|
||||
context.savedSelection = document.selection.createRange();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Restore text selection for old IE (<=10)
|
||||
*/
|
||||
restoreSelection: function () {
|
||||
if ( profile.name === 'msie' && context.savedSelection !== null ) {
|
||||
context.$textarea.focus();
|
||||
context.savedSelection.select();
|
||||
context.savedSelection = null;
|
||||
}
|
||||
if ( profile.name === 'msie' && profile.versionNumber === 8 ) {
|
||||
context.$textarea.css( 'height', context.$textarea.height() );
|
||||
context.$textarea.css( 'width', context.$textarea.parent().width() );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Workaround for a scrolling bug in IE8 (bug 61908)
|
||||
*/
|
||||
if ( profile.name === 'msie' && profile.versionNumber === 8 ) {
|
||||
context.$textarea.css( 'height', context.$textarea.height() );
|
||||
context.$textarea.css( 'width', context.$textarea.parent().width() );
|
||||
/**
|
||||
* Base UI Construction
|
||||
*
|
||||
* The UI is built from several containers, the outer-most being a div classed as "wikiEditor-ui". These containers
|
||||
* provide a certain amount of "free" layout, but in some situations procedural layout is needed, which is performed
|
||||
* as a response to the "resize" event.
|
||||
*/
|
||||
|
||||
// Assemble a temporary div to place over the wikiEditor while it's being constructed
|
||||
/* Disabling our loading div for now
|
||||
var $loader = $( '<div>' )
|
||||
.addClass( 'wikiEditor-ui-loading' )
|
||||
.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
|
||||
.after( $loader )
|
||||
.add( $loader )
|
||||
*/
|
||||
.wrapAll( $( '<div>' ).addClass( 'wikiEditor-ui' ) )
|
||||
.wrapAll( $( '<div>' ).addClass( 'wikiEditor-ui-view wikiEditor-ui-view-wikitext' ) )
|
||||
.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();
|
||||
// Add in tab and button containers
|
||||
context.$wikitext
|
||||
.before(
|
||||
$( '<div>' ).addClass( 'wikiEditor-ui-controls' )
|
||||
.append( $( '<div>' ).addClass( 'wikiEditor-ui-tabs' ).hide() )
|
||||
.append( $( '<div>' ).addClass( 'wikiEditor-ui-buttons' ) )
|
||||
)
|
||||
.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>' ).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
|
||||
context.view = 'wikitext';
|
||||
// Trigger the "resize" event anytime the window is resized
|
||||
$( window ).resize( function ( event ) {
|
||||
context.fn.trigger( 'resize', event );
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
* Base UI Construction
|
||||
*
|
||||
* The UI is built from several containers, the outer-most being a div classed as "wikiEditor-ui". These containers
|
||||
* provide a certain amount of "free" layout, but in some situations procedural layout is needed, which is performed
|
||||
* as a response to the "resize" event.
|
||||
*/
|
||||
/* API Execution */
|
||||
|
||||
// Assemble a temporary div to place over the wikiEditor while it's being constructed
|
||||
/* Disabling our loading div for now
|
||||
var $loader = $( '<div>' )
|
||||
.addClass( 'wikiEditor-ui-loading' )
|
||||
.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
|
||||
.after( $loader )
|
||||
.add( $loader )
|
||||
*/
|
||||
.wrapAll( $( '<div>' ).addClass( 'wikiEditor-ui' ) )
|
||||
.wrapAll( $( '<div>' ).addClass( 'wikiEditor-ui-view wikiEditor-ui-view-wikitext' ) )
|
||||
.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] } );
|
||||
}
|
||||
// Since javascript gives arguments as an object, we need to convert them so they can be used more easily
|
||||
var args = $.makeArray( arguments );
|
||||
|
||||
// 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();
|
||||
// Add in tab and button containers
|
||||
context.$wikitext
|
||||
.before(
|
||||
$( '<div>' ).addClass( 'wikiEditor-ui-controls' )
|
||||
.append( $( '<div>' ).addClass( 'wikiEditor-ui-tabs' ).hide() )
|
||||
.append( $( '<div>' ).addClass( 'wikiEditor-ui-buttons' ) )
|
||||
)
|
||||
.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>' ).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
|
||||
context.view = 'wikitext';
|
||||
// Trigger the "resize" event anytime the window is resized
|
||||
$( window ).resize( function ( event ) {
|
||||
context.fn.trigger( 'resize', event );
|
||||
} );
|
||||
}
|
||||
|
||||
/* API Execution */
|
||||
|
||||
// Since javascript gives arguments as an object, we need to convert them so they can be used more easily
|
||||
var args = $.makeArray( arguments );
|
||||
|
||||
// Dynamically setup core extensions for modules that are required
|
||||
if ( args[0] === 'addModule' && typeof args[1] !== 'undefined' ) {
|
||||
var modules = args[1];
|
||||
if ( typeof modules !== 'object' ) {
|
||||
modules = {};
|
||||
modules[args[1]] = '';
|
||||
}
|
||||
for ( var module in modules ) {
|
||||
// Only allow modules which are supported (and thus actually being turned on) affect the decision to extend
|
||||
if ( module in $.wikiEditor.modules && $.wikiEditor.isSupported( $.wikiEditor.modules[module] ) ) {
|
||||
// Activate all required core extensions on context
|
||||
for ( var e in $.wikiEditor.extensions ) {
|
||||
if (
|
||||
$.wikiEditor.isRequired( $.wikiEditor.modules[module], e ) &&
|
||||
$.inArray( e, context.extensions ) === -1
|
||||
) {
|
||||
context.extensions[context.extensions.length] = e;
|
||||
$.wikiEditor.extensions[e]( context );
|
||||
// Dynamically setup core extensions for modules that are required
|
||||
if ( args[ 0 ] === 'addModule' && typeof args[ 1 ] !== 'undefined' ) {
|
||||
var modules = args[ 1 ];
|
||||
if ( typeof modules !== 'object' ) {
|
||||
modules = {};
|
||||
modules[ args[ 1 ] ] = '';
|
||||
}
|
||||
for ( var module in modules ) {
|
||||
// Only allow modules which are supported (and thus actually being turned on) affect the decision to extend
|
||||
if ( module in $.wikiEditor.modules && $.wikiEditor.isSupported( $.wikiEditor.modules[ module ] ) ) {
|
||||
// Activate all required core extensions on context
|
||||
for ( var e in $.wikiEditor.extensions ) {
|
||||
if (
|
||||
$.wikiEditor.isRequired( $.wikiEditor.modules[ module ], e ) &&
|
||||
$.inArray( e, context.extensions ) === -1
|
||||
) {
|
||||
context.extensions[ context.extensions.length ] = e;
|
||||
$.wikiEditor.extensions[ e ]( context );
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// There would need to be some arguments if the API is being called
|
||||
if ( args.length > 0 ) {
|
||||
// Handle API calls
|
||||
var call = args.shift();
|
||||
if ( call in context.api ) {
|
||||
context.api[call]( context, typeof args[0] === 'undefined' ? {} : args[0] );
|
||||
// There would need to be some arguments if the API is being called
|
||||
if ( args.length > 0 ) {
|
||||
// Handle API calls
|
||||
var call = args.shift();
|
||||
if ( call in context.api ) {
|
||||
context.api[ call ]( context, typeof args[ 0 ] === 'undefined' ? {} : args[ 0 ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Store the context for next time, and support chaining
|
||||
return $( this ).data( 'wikiEditor-context', context );
|
||||
// Store the context for next time, and support chaining
|
||||
return $( this ).data( 'wikiEditor-context', context );
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -3,170 +3,170 @@
|
|||
/*jshint onevar:false */
|
||||
$.wikiEditor.modules.preview = {
|
||||
|
||||
/**
|
||||
* Compatability map
|
||||
*/
|
||||
browsers: {
|
||||
// Left-to-right languages
|
||||
ltr: {
|
||||
msie: [['>=', 7]],
|
||||
firefox: [['>=', 3]],
|
||||
opera: [['>=', 9.6]],
|
||||
safari: [['>=', 4]]
|
||||
},
|
||||
// Right-to-left languages
|
||||
rtl: {
|
||||
msie: [['>=', 8]],
|
||||
firefox: [['>=', 3]],
|
||||
opera: [['>=', 9.6]],
|
||||
safari: [['>=', 4]]
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Internally used functions
|
||||
*/
|
||||
fn: {
|
||||
/**
|
||||
* Creates a preview module within a wikiEditor
|
||||
* @param context Context object of editor to create module in
|
||||
* @param config Configuration object to create module from
|
||||
* Compatability map
|
||||
*/
|
||||
create: function ( context ) {
|
||||
var api = new mw.Api();
|
||||
|
||||
if ( 'initialized' in context.modules.preview ) {
|
||||
return;
|
||||
browsers: {
|
||||
// Left-to-right languages
|
||||
ltr: {
|
||||
msie: [ [ '>=', 7 ] ],
|
||||
firefox: [ [ '>=', 3 ] ],
|
||||
opera: [ [ '>=', 9.6 ] ],
|
||||
safari: [ [ '>=', 4 ] ]
|
||||
},
|
||||
// Right-to-left languages
|
||||
rtl: {
|
||||
msie: [ [ '>=', 8 ] ],
|
||||
firefox: [ [ '>=', 3 ] ],
|
||||
opera: [ [ '>=', 9.6 ] ],
|
||||
safari: [ [ '>=', 4 ] ]
|
||||
}
|
||||
context.modules.preview = {
|
||||
'initialized': true,
|
||||
'previewText': null,
|
||||
'changesText': null
|
||||
};
|
||||
context.modules.preview.$preview = context.fn.addView( {
|
||||
'name': 'preview',
|
||||
'titleMsg': 'wikieditor-preview-tab',
|
||||
'init': function ( context ) {
|
||||
// Gets the latest copy of the wikitext
|
||||
var wikitext = context.$textarea.textSelection( 'getContents' );
|
||||
// Aborts when nothing has changed since the last preview
|
||||
if ( context.modules.preview.previewText === wikitext ) {
|
||||
return;
|
||||
}
|
||||
context.modules.preview.$preview.find( '.wikiEditor-preview-contents' ).empty();
|
||||
context.modules.preview.$preview.find( '.wikiEditor-preview-loading' ).show();
|
||||
api.post( {
|
||||
action: 'parse',
|
||||
title: mw.config.get( 'wgPageName' ),
|
||||
text: wikitext,
|
||||
prop: 'text|modules',
|
||||
pst: ''
|
||||
} ).done( function ( data ) {
|
||||
if ( !data.parse || !data.parse.text || data.parse.text['*'] === undefined ) {
|
||||
},
|
||||
|
||||
/**
|
||||
* Internally used functions
|
||||
*/
|
||||
fn: {
|
||||
/**
|
||||
* Creates a preview module within a wikiEditor
|
||||
*
|
||||
* @param {Object} context Context object of editor to create module in
|
||||
*/
|
||||
create: function ( context ) {
|
||||
var api = new mw.Api();
|
||||
|
||||
if ( 'initialized' in context.modules.preview ) {
|
||||
return;
|
||||
}
|
||||
context.modules.preview = {
|
||||
initialized: true,
|
||||
previewText: null,
|
||||
changesText: null
|
||||
};
|
||||
context.modules.preview.$preview = context.fn.addView( {
|
||||
name: 'preview',
|
||||
titleMsg: 'wikieditor-preview-tab',
|
||||
init: function ( context ) {
|
||||
// Gets the latest copy of the wikitext
|
||||
var wikitext = context.$textarea.textSelection( 'getContents' );
|
||||
// Aborts when nothing has changed since the last preview
|
||||
if ( context.modules.preview.previewText === wikitext ) {
|
||||
return;
|
||||
}
|
||||
|
||||
context.modules.preview.previewText = wikitext;
|
||||
context.modules.preview.$preview.find( '.wikiEditor-preview-loading' ).hide();
|
||||
context.modules.preview.$preview.find( '.wikiEditor-preview-contents' )
|
||||
.html( data.parse.text['*'] )
|
||||
.append( '<div class="visualClear"></div>' )
|
||||
.find( 'a:not([href^=#])' )
|
||||
.click( false );
|
||||
|
||||
var loadmodules = data.parse.modules.concat(
|
||||
data.parse.modulescripts,
|
||||
data.parse.modulestyles
|
||||
);
|
||||
mw.loader.load( loadmodules );
|
||||
} );
|
||||
}
|
||||
} );
|
||||
|
||||
context.$changesTab = context.fn.addView( {
|
||||
'name': 'changes',
|
||||
'titleMsg': 'wikieditor-preview-changes-tab',
|
||||
'init': function ( context ) {
|
||||
// Gets the latest copy of the wikitext
|
||||
var wikitext = context.$textarea.textSelection( 'getContents' );
|
||||
// Aborts when nothing has changed since the last time
|
||||
if ( context.modules.preview.changesText === wikitext ) {
|
||||
return;
|
||||
}
|
||||
context.$changesTab.find( 'table.diff tbody' ).empty();
|
||||
context.$changesTab.find( '.wikiEditor-preview-loading' ).show();
|
||||
|
||||
// Call the API. First PST the input, then diff it
|
||||
api.post( {
|
||||
action: 'parse',
|
||||
title: mw.config.get( 'wgPageName' ),
|
||||
onlypst: '',
|
||||
text: wikitext
|
||||
} ).done( function ( data ) {
|
||||
try {
|
||||
var postdata2 = {
|
||||
action: 'query',
|
||||
indexpageids: '',
|
||||
prop: 'revisions',
|
||||
titles: mw.config.get( 'wgPageName' ),
|
||||
rvdifftotext: data.parse.text['*'],
|
||||
rvprop: ''
|
||||
};
|
||||
var section = $( '[name="wpSection"]' ).val();
|
||||
if ( section !== '' ) {
|
||||
postdata2.rvsection = section;
|
||||
context.modules.preview.$preview.find( '.wikiEditor-preview-contents' ).empty();
|
||||
context.modules.preview.$preview.find( '.wikiEditor-preview-loading' ).show();
|
||||
api.post( {
|
||||
action: 'parse',
|
||||
title: mw.config.get( 'wgPageName' ),
|
||||
text: wikitext,
|
||||
prop: 'text|modules',
|
||||
pst: ''
|
||||
} ).done( function ( data ) {
|
||||
if ( !data.parse || !data.parse.text || data.parse.text[ '*' ] === undefined ) {
|
||||
return;
|
||||
}
|
||||
|
||||
api.post( postdata2 )
|
||||
.done( function ( data ) {
|
||||
// Add diff CSS
|
||||
mw.loader.load( 'mediawiki.action.history.diff' );
|
||||
try {
|
||||
var diff = data.query.pages[data.query.pageids[0]]
|
||||
.revisions[0].diff['*'];
|
||||
context.modules.preview.previewText = wikitext;
|
||||
context.modules.preview.$preview.find( '.wikiEditor-preview-loading' ).hide();
|
||||
context.modules.preview.$preview.find( '.wikiEditor-preview-contents' )
|
||||
.html( data.parse.text[ '*' ] )
|
||||
.append( '<div class="visualClear"></div>' )
|
||||
.find( 'a:not([href^=#])' )
|
||||
.click( false );
|
||||
|
||||
context.$changesTab.find( 'table.diff tbody' )
|
||||
.html( diff )
|
||||
.append( '<div class="visualClear"></div>' );
|
||||
context.modules.preview.changesText = wikitext;
|
||||
} catch ( e ) {
|
||||
// "data.blah is undefined" error, ignore
|
||||
}
|
||||
context.$changesTab.find( '.wikiEditor-preview-loading' ).hide();
|
||||
} );
|
||||
} catch ( e ) {
|
||||
// "data.blah is undefined" error, ignore
|
||||
var loadmodules = data.parse.modules.concat(
|
||||
data.parse.modulescripts,
|
||||
data.parse.modulestyles
|
||||
);
|
||||
mw.loader.load( loadmodules );
|
||||
} );
|
||||
}
|
||||
} );
|
||||
|
||||
context.$changesTab = context.fn.addView( {
|
||||
name: 'changes',
|
||||
titleMsg: 'wikieditor-preview-changes-tab',
|
||||
init: function ( context ) {
|
||||
// Gets the latest copy of the wikitext
|
||||
var wikitext = context.$textarea.textSelection( 'getContents' );
|
||||
// Aborts when nothing has changed since the last time
|
||||
if ( context.modules.preview.changesText === wikitext ) {
|
||||
return;
|
||||
}
|
||||
} );
|
||||
}
|
||||
} );
|
||||
context.$changesTab.find( 'table.diff tbody' ).empty();
|
||||
context.$changesTab.find( '.wikiEditor-preview-loading' ).show();
|
||||
|
||||
var loadingMsg = mw.msg( 'wikieditor-preview-loading' );
|
||||
context.modules.preview.$preview
|
||||
.add( context.$changesTab )
|
||||
.append( $( '<div>' )
|
||||
.addClass( 'wikiEditor-preview-loading' )
|
||||
.append( $( '<img>' )
|
||||
.addClass( 'wikiEditor-preview-spinner' )
|
||||
.attr( {
|
||||
'src': $.wikiEditor.imgPath + 'dialogs/loading.gif',
|
||||
'valign': 'absmiddle',
|
||||
'alt': loadingMsg,
|
||||
'title': loadingMsg
|
||||
} )
|
||||
// Call the API. First PST the input, then diff it
|
||||
api.post( {
|
||||
action: 'parse',
|
||||
title: mw.config.get( 'wgPageName' ),
|
||||
onlypst: '',
|
||||
text: wikitext
|
||||
} ).done( function ( data ) {
|
||||
try {
|
||||
var postdata2 = {
|
||||
action: 'query',
|
||||
indexpageids: '',
|
||||
prop: 'revisions',
|
||||
titles: mw.config.get( 'wgPageName' ),
|
||||
rvdifftotext: data.parse.text[ '*' ],
|
||||
rvprop: ''
|
||||
};
|
||||
var section = $( '[name="wpSection"]' ).val();
|
||||
if ( section !== '' ) {
|
||||
postdata2.rvsection = section;
|
||||
}
|
||||
|
||||
api.post( postdata2 )
|
||||
.done( function ( data ) {
|
||||
// Add diff CSS
|
||||
mw.loader.load( 'mediawiki.action.history.diff' );
|
||||
try {
|
||||
var diff = data.query.pages[ data.query.pageids[ 0 ] ]
|
||||
.revisions[ 0 ].diff[ '*' ];
|
||||
|
||||
context.$changesTab.find( 'table.diff tbody' )
|
||||
.html( diff )
|
||||
.append( '<div class="visualClear"></div>' );
|
||||
context.modules.preview.changesText = wikitext;
|
||||
} catch ( e ) {
|
||||
// "data.blah is undefined" error, ignore
|
||||
}
|
||||
context.$changesTab.find( '.wikiEditor-preview-loading' ).hide();
|
||||
} );
|
||||
} catch ( e ) {
|
||||
// "data.blah is undefined" error, ignore
|
||||
}
|
||||
} );
|
||||
}
|
||||
} );
|
||||
|
||||
var loadingMsg = mw.msg( 'wikieditor-preview-loading' );
|
||||
context.modules.preview.$preview
|
||||
.add( context.$changesTab )
|
||||
.append( $( '<div>' )
|
||||
.addClass( 'wikiEditor-preview-loading' )
|
||||
.append( $( '<img>' )
|
||||
.addClass( 'wikiEditor-preview-spinner' )
|
||||
.attr( {
|
||||
src: $.wikiEditor.imgPath + 'dialogs/loading.gif',
|
||||
valign: 'absmiddle',
|
||||
alt: loadingMsg,
|
||||
title: loadingMsg
|
||||
} )
|
||||
)
|
||||
.append(
|
||||
$( '<span>' ).text( loadingMsg )
|
||||
)
|
||||
)
|
||||
.append(
|
||||
$( '<span>' ).text( loadingMsg )
|
||||
)
|
||||
)
|
||||
.append( $( '<div>' )
|
||||
.addClass( 'wikiEditor-preview-contents' )
|
||||
);
|
||||
context.$changesTab.find( '.wikiEditor-preview-contents' )
|
||||
.html( '<table class="diff"><col class="diff-marker"/><col class="diff-content"/>' +
|
||||
'<col class="diff-marker"/><col class="diff-content"/><tbody/></table>' );
|
||||
.append( $( '<div>' )
|
||||
.addClass( 'wikiEditor-preview-contents' )
|
||||
);
|
||||
context.$changesTab.find( '.wikiEditor-preview-contents' )
|
||||
.html( '<table class="diff"><col class="diff-marker"/><col class="diff-content"/>' +
|
||||
'<col class="diff-marker"/><col class="diff-content"/><tbody/></table>' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -4,159 +4,160 @@
|
|||
|
||||
$.wikiEditor.modules.publish = {
|
||||
|
||||
/**
|
||||
* Compatability map
|
||||
*/
|
||||
browsers: {
|
||||
// Left-to-right languages
|
||||
ltr: {
|
||||
msie: [['>=', 7]],
|
||||
firefox: [['>=', 3]],
|
||||
opera: [['>=', 9.6]],
|
||||
safari: [['>=', 4]]
|
||||
},
|
||||
// Right-to-left languages
|
||||
rtl: {
|
||||
msie: [['>=', 8]],
|
||||
firefox: [['>=', 3]],
|
||||
opera: [['>=', 9.6]],
|
||||
safari: [['>=', 4]]
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Internally used functions
|
||||
*/
|
||||
fn: {
|
||||
/**
|
||||
* Creates a publish module within a wikiEditor
|
||||
* @param context Context object of editor to create module in
|
||||
* @param config Configuration object to create module from
|
||||
* Compatability map
|
||||
*/
|
||||
create: function ( context ) {
|
||||
// Build the dialog behind the Publish button
|
||||
var dialogID = 'wikiEditor-' + context.instance + '-dialog';
|
||||
$.wikiEditor.modules.dialogs.fn.create(
|
||||
context,
|
||||
{
|
||||
previewsave: {
|
||||
id: dialogID,
|
||||
titleMsg: 'wikieditor-publish-dialog-title',
|
||||
html: '\
|
||||
<div class="wikiEditor-publish-dialog-copywarn"></div>\
|
||||
<div class="wikiEditor-publish-dialog-editoptions">\
|
||||
<form id="wikieditor-' + context.instance + '-publish-dialog-form">\
|
||||
<div class="wikiEditor-publish-dialog-summary">\
|
||||
<label for="wikiEditor-' + context.instance + '-dialog-summary"\
|
||||
rel="wikieditor-publish-dialog-summary"></label>\
|
||||
<br />\
|
||||
<input type="text" id="wikiEditor-' + context.instance + '-dialog-summary"\
|
||||
style="width: 100%;" />\
|
||||
</div>\
|
||||
<div class="wikiEditor-publish-dialog-options">\
|
||||
<input type="checkbox"\
|
||||
id="wikiEditor-' + context.instance + '-dialog-minor" />\
|
||||
<label for="wikiEditor-' + context.instance + '-dialog-minor"\
|
||||
rel="wikieditor-publish-dialog-minor"></label>\
|
||||
<input type="checkbox"\
|
||||
id="wikiEditor-' + context.instance + '-dialog-watch" />\
|
||||
<label for="wikiEditor-' + context.instance + '-dialog-watch"\
|
||||
rel="wikieditor-publish-dialog-watch"></label>\
|
||||
</div>\
|
||||
</form>\
|
||||
</div>',
|
||||
init: function () {
|
||||
var i;
|
||||
browsers: {
|
||||
// Left-to-right languages
|
||||
ltr: {
|
||||
msie: [ [ '>=', 7 ] ],
|
||||
firefox: [ [ '>=', 3 ] ],
|
||||
opera: [ [ '>=', 9.6 ] ],
|
||||
safari: [ [ '>=', 4 ] ]
|
||||
},
|
||||
// Right-to-left languages
|
||||
rtl: {
|
||||
msie: [ [ '>=', 8 ] ],
|
||||
firefox: [ [ '>=', 3 ] ],
|
||||
opera: [ [ '>=', 9.6 ] ],
|
||||
safari: [ [ '>=', 4 ] ]
|
||||
}
|
||||
},
|
||||
|
||||
$( this ).find( '[rel]' ).each( function () {
|
||||
$( this ).text( mediaWiki.msg( $( this ).attr( 'rel' ) ) );
|
||||
} );
|
||||
/**
|
||||
* Internally used functions
|
||||
*/
|
||||
fn: {
|
||||
/**
|
||||
* Creates a publish module within a wikiEditor
|
||||
*
|
||||
* @param {Object} context Context object of editor to create module in
|
||||
*/
|
||||
create: function ( context ) {
|
||||
// Build the dialog behind the Publish button
|
||||
var dialogID = 'wikiEditor-' + context.instance + '-dialog';
|
||||
$.wikiEditor.modules.dialogs.fn.create(
|
||||
context,
|
||||
{
|
||||
previewsave: {
|
||||
id: dialogID,
|
||||
titleMsg: 'wikieditor-publish-dialog-title',
|
||||
html: '\
|
||||
<div class="wikiEditor-publish-dialog-copywarn"></div>\
|
||||
<div class="wikiEditor-publish-dialog-editoptions">\
|
||||
<form id="wikieditor-' + context.instance + '-publish-dialog-form">\
|
||||
<div class="wikiEditor-publish-dialog-summary">\
|
||||
<label for="wikiEditor-' + context.instance + '-dialog-summary"\
|
||||
rel="wikieditor-publish-dialog-summary"></label>\
|
||||
<br />\
|
||||
<input type="text" id="wikiEditor-' + context.instance + '-dialog-summary"\
|
||||
style="width: 100%;" />\
|
||||
</div>\
|
||||
<div class="wikiEditor-publish-dialog-options">\
|
||||
<input type="checkbox"\
|
||||
id="wikiEditor-' + context.instance + '-dialog-minor" />\
|
||||
<label for="wikiEditor-' + context.instance + '-dialog-minor"\
|
||||
rel="wikieditor-publish-dialog-minor"></label>\
|
||||
<input type="checkbox"\
|
||||
id="wikiEditor-' + context.instance + '-dialog-watch" />\
|
||||
<label for="wikiEditor-' + context.instance + '-dialog-watch"\
|
||||
rel="wikieditor-publish-dialog-watch"></label>\
|
||||
</div>\
|
||||
</form>\
|
||||
</div>',
|
||||
init: function () {
|
||||
var i;
|
||||
|
||||
/* REALLY DIRTY HACK! */
|
||||
// Reformat the copyright warning stuff, if available
|
||||
if ( $( '#editpage-copywarn p' ).length ) {
|
||||
var copyWarnHTML = $( '#editpage-copywarn p' ).html();
|
||||
// TODO: internationalize by splitting on other characters that end statements
|
||||
var copyWarnStatements = copyWarnHTML.split( '. ' );
|
||||
var newCopyWarnHTML = '<ul>';
|
||||
for ( i = 0; i < copyWarnStatements.length; i++ ) {
|
||||
if ( copyWarnStatements[i] !== '' ) {
|
||||
var copyWarnStatement = $.trim( copyWarnStatements[i] ).replace( /\.*$/, '' );
|
||||
newCopyWarnHTML += '<li>' + copyWarnStatement + '.</li>';
|
||||
$( this ).find( '[rel]' ).each( function () {
|
||||
$( this ).text( mediaWiki.msg( $( this ).attr( 'rel' ) ) );
|
||||
} );
|
||||
|
||||
/* REALLY DIRTY HACK! */
|
||||
// Reformat the copyright warning stuff, if available
|
||||
if ( $( '#editpage-copywarn p' ).length ) {
|
||||
var copyWarnHTML = $( '#editpage-copywarn p' ).html();
|
||||
// TODO: internationalize by splitting on other characters that end statements
|
||||
var copyWarnStatements = copyWarnHTML.split( '. ' );
|
||||
var newCopyWarnHTML = '<ul>';
|
||||
for ( i = 0; i < copyWarnStatements.length; i++ ) {
|
||||
if ( copyWarnStatements[ i ] !== '' ) {
|
||||
var copyWarnStatement = $.trim( copyWarnStatements[ i ] ).replace( /\.*$/, '' );
|
||||
newCopyWarnHTML += '<li>' + copyWarnStatement + '.</li>';
|
||||
}
|
||||
}
|
||||
newCopyWarnHTML += '</ul>';
|
||||
// No list if there's only one element
|
||||
$( this ).find( '.wikiEditor-publish-dialog-copywarn' ).html(
|
||||
copyWarnStatements.length > 1 ? newCopyWarnHTML : copyWarnHTML
|
||||
);
|
||||
}
|
||||
newCopyWarnHTML += '</ul>';
|
||||
// No list if there's only one element
|
||||
$( this ).find( '.wikiEditor-publish-dialog-copywarn' ).html(
|
||||
copyWarnStatements.length > 1 ? newCopyWarnHTML : copyWarnHTML
|
||||
);
|
||||
}
|
||||
/* END OF REALLY DIRTY HACK */
|
||||
/* END OF REALLY DIRTY HACK */
|
||||
|
||||
if ( $( '#wpMinoredit' ).length === 0 ) {
|
||||
$( '#wikiEditor-' + context.instance + '-dialog-minor' ).hide();
|
||||
} else if ( $( '#wpMinoredit' ).prop( 'checked' ) ) {
|
||||
$( '#wikiEditor-' + context.instance + '-dialog-minor' )
|
||||
.prop( 'checked', true );
|
||||
}
|
||||
if ( $( '#wpWatchthis' ).length === 0 ) {
|
||||
$( '#wikiEditor-' + context.instance + '-dialog-watch' ).hide();
|
||||
} else if ( $( '#wpWatchthis' ).prop( 'checked' ) ) {
|
||||
$( '#wikiEditor-' + context.instance + '-dialog-watch' )
|
||||
.prop( 'checked', true );
|
||||
if ( $( '#wpMinoredit' ).length === 0 ) {
|
||||
$( '#wikiEditor-' + context.instance + '-dialog-minor' ).hide();
|
||||
} else if ( $( '#wpMinoredit' ).prop( 'checked' ) ) {
|
||||
$( '#wikiEditor-' + context.instance + '-dialog-minor' )
|
||||
.prop( 'checked', true );
|
||||
}
|
||||
if ( $( '#wpWatchthis' ).length === 0 ) {
|
||||
$( '#wikiEditor-' + context.instance + '-dialog-watch' ).hide();
|
||||
} else if ( $( '#wpWatchthis' ).prop( 'checked' ) ) {
|
||||
$( '#wikiEditor-' + context.instance + '-dialog-watch' )
|
||||
.prop( 'checked', true );
|
||||
}
|
||||
|
||||
$( this ).find( 'form' ).submit( function ( e ) {
|
||||
$( this ).closest( '.ui-dialog' ).find( 'button:first' ).click();
|
||||
e.preventDefault();
|
||||
} );
|
||||
},
|
||||
immediateCreate: true,
|
||||
dialog: {
|
||||
buttons: {
|
||||
'wikieditor-publish-dialog-publish': function () {
|
||||
var minorChecked = $( '#wikiEditor-' + context.instance +
|
||||
'-dialog-minor' ).is( ':checked' ) ?
|
||||
'checked' : '';
|
||||
var watchChecked = $( '#wikiEditor-' + context.instance +
|
||||
'-dialog-watch' ).is( ':checked' ) ?
|
||||
'checked' : '';
|
||||
$( '#wpMinoredit' ).prop( 'checked', minorChecked );
|
||||
$( '#wpWatchthis' ).prop( 'checked', watchChecked );
|
||||
$( '#wpSummary' ).val( $( '#wikiEditor-' + context.instance +
|
||||
'-dialog-summary' ).val() );
|
||||
$( '#editform' ).submit();
|
||||
$( this ).find( 'form' ).submit( function ( e ) {
|
||||
$( this ).closest( '.ui-dialog' ).find( 'button:first' ).click();
|
||||
e.preventDefault();
|
||||
} );
|
||||
},
|
||||
immediateCreate: true,
|
||||
dialog: {
|
||||
buttons: {
|
||||
'wikieditor-publish-dialog-publish': function () {
|
||||
var minorChecked = $( '#wikiEditor-' + context.instance +
|
||||
'-dialog-minor' ).is( ':checked' ) ?
|
||||
'checked' : '';
|
||||
var watchChecked = $( '#wikiEditor-' + context.instance +
|
||||
'-dialog-watch' ).is( ':checked' ) ?
|
||||
'checked' : '';
|
||||
$( '#wpMinoredit' ).prop( 'checked', minorChecked );
|
||||
$( '#wpWatchthis' ).prop( 'checked', watchChecked );
|
||||
$( '#wpSummary' ).val( $( '#wikiEditor-' + context.instance +
|
||||
'-dialog-summary' ).val() );
|
||||
$( '#editform' ).submit();
|
||||
},
|
||||
'wikieditor-publish-dialog-goback': function () {
|
||||
$( this ).dialog( 'close' );
|
||||
}
|
||||
},
|
||||
'wikieditor-publish-dialog-goback': function () {
|
||||
$( this ).dialog( 'close' );
|
||||
}
|
||||
open: function () {
|
||||
$( '#wikiEditor-' + context.instance + '-dialog-summary' ).focus();
|
||||
},
|
||||
width: 500
|
||||
},
|
||||
open: function () {
|
||||
$( '#wikiEditor-' + context.instance + '-dialog-summary' ).focus();
|
||||
},
|
||||
width: 500
|
||||
},
|
||||
resizeme: false
|
||||
resizeme: false
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
context.fn.addButton( {
|
||||
'captionMsg': 'wikieditor-publish-button-publish',
|
||||
'action': function () {
|
||||
$( '#' + dialogID ).dialog( 'open' );
|
||||
return false;
|
||||
}
|
||||
} );
|
||||
context.fn.addButton( {
|
||||
captionMsg: 'wikieditor-publish-button-publish',
|
||||
action: function () {
|
||||
$( '#' + dialogID ).dialog( 'open' );
|
||||
return false;
|
||||
}
|
||||
} );
|
||||
|
||||
context.fn.addButton( {
|
||||
'captionMsg': 'wikieditor-publish-button-cancel',
|
||||
'action': function () {
|
||||
window.location.href = $( '#mw-editform-cancel' ).attr( 'href' );
|
||||
return false;
|
||||
}
|
||||
} );
|
||||
context.fn.addButton( {
|
||||
captionMsg: 'wikieditor-publish-button-cancel',
|
||||
action: function () {
|
||||
window.location.href = $( '#mw-editform-cancel' ).attr( 'href' );
|
||||
return false;
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -7,6 +7,8 @@
|
|||
"grunt": "0.4.5",
|
||||
"grunt-cli": "0.1.13",
|
||||
"grunt-banana-checker": "0.2.2",
|
||||
"grunt-jsonlint": "1.0.4"
|
||||
"grunt-jsonlint": "1.0.4",
|
||||
"grunt-contrib-jshint": "0.11.3",
|
||||
"grunt-jscs": "2.3.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@
|
|||
label: 'Icons',
|
||||
type: 'select',
|
||||
list: {
|
||||
wink : {
|
||||
wink: {
|
||||
label: 'Wink',
|
||||
action: {
|
||||
type: 'encapsulate',
|
||||
|
@ -87,7 +87,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
frown : {
|
||||
frown: {
|
||||
label: 'Frown',
|
||||
action: {
|
||||
type: 'encapsulate',
|
||||
|
@ -96,7 +96,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
bigSmile : {
|
||||
bigSmile: {
|
||||
label: 'Big smile',
|
||||
action: {
|
||||
type: 'encapsulate',
|
||||
|
@ -178,23 +178,23 @@
|
|||
data = {
|
||||
section: 'info',
|
||||
page: 'colors',
|
||||
rows: [
|
||||
{
|
||||
name: { text: 'Red' },
|
||||
temp: { text: 'Warm' },
|
||||
swatch: { html: '<div style="width: 10px; height: 10px; background-color: red;">' }
|
||||
},
|
||||
{
|
||||
name: { text: 'Blue' },
|
||||
temp: { text: 'Cold' },
|
||||
swatch: { html: '<div style="width: 10px; height: 10px; background-color: blue;">' }
|
||||
},
|
||||
{
|
||||
name: { text: 'Silver' },
|
||||
temp: { text: 'Neutral' },
|
||||
swatch: { html: '<div style="width: 10px; height: 10px; background-color: silver;">' }
|
||||
}
|
||||
]
|
||||
rows: [
|
||||
{
|
||||
name: { text: 'Red' },
|
||||
temp: { text: 'Warm' },
|
||||
swatch: { html: '<div style="width: 10px; height: 10px; background-color: red;">' }
|
||||
},
|
||||
{
|
||||
name: { text: 'Blue' },
|
||||
temp: { text: 'Cold' },
|
||||
swatch: { html: '<div style="width: 10px; height: 10px; background-color: blue;">' }
|
||||
},
|
||||
{
|
||||
name: { text: 'Silver' },
|
||||
temp: { text: 'Neutral' },
|
||||
swatch: { html: '<div style="width: 10px; height: 10px; background-color: silver;">' }
|
||||
}
|
||||
]
|
||||
};
|
||||
assert.equal( this.$ui.find( '*[rel="info"].section *[rel="colors"].page tr td' ).length, 0, 'Before adding table rows' );
|
||||
this.$target.wikiEditor( 'addToToolbar', data );
|
||||
|
|
Loading…
Reference in a new issue