mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-09-24 02:38:40 +00:00
Refactored veCore class into ve.init and ve.init.EditPageTarget
Change-Id: I52ef09aee38471ca49f3f4a845daf02e6dcc024c
This commit is contained in:
parent
38e64418b5
commit
ce8efd6b15
|
@ -2,57 +2,58 @@
|
|||
|
||||
class VisualEditorHooks {
|
||||
/**
|
||||
* Adds VisualEditor JS to the output if in the correct namespace
|
||||
* Adds VisualEditor JS to the output if in the correct namespace.
|
||||
*
|
||||
* This is attached to the MediaWiki 'BeforePageDisplay' hook.
|
||||
*
|
||||
* @param $output OutputPage
|
||||
* @param $skin Skin
|
||||
*/
|
||||
public static function onPageDisplay( &$output, &$skin ) {
|
||||
if ( self::loadVisualEditor( $output, $skin ) ) {
|
||||
$output->addModules( array( 'ext.visualEditor.core' ) );
|
||||
public static function onBeforePageDisplay( &$output, &$skin ) {
|
||||
global $wgTitle;
|
||||
if (
|
||||
// Vector skin supported for now.
|
||||
$skin->getSkinName() === 'vector' &&
|
||||
// Be sure current page is VisualEditor:Something
|
||||
$wgTitle->getNamespace() === NS_VISUALEDITOR
|
||||
) {
|
||||
$output->addModules( array( 'ext.visualEditor.editPageInit' ) );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether or not we should construct the loader.
|
||||
* Adds extra variables to the page config.
|
||||
*
|
||||
* @param $output OutputPage
|
||||
* @param $skin Skin
|
||||
* This is attached to the MediaWiki 'MakeGlobalVariablesScript' hook.
|
||||
*/
|
||||
public static function loadVisualEditor( &$output, &$skin ) {
|
||||
global $wgTitle;
|
||||
// Vector skin supported for now.
|
||||
if ( $skin->getSkinName() !== 'vector' ) {
|
||||
return false;
|
||||
}
|
||||
// Be sure current page is VisualEditor:Something
|
||||
if ( $wgTitle->getNamespace() !== NS_VISUALEDITOR ) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
public static function makeGlobalVariablesScript( &$vars ) {
|
||||
public static function onMakeGlobalVariablesScript( &$vars ) {
|
||||
global $wgUser, $wgTitle;
|
||||
$vars['vePageWatched'] = $wgUser->isWatched( $wgTitle ) ? true : false;
|
||||
$vars['wgVisualEditor'] = array(
|
||||
'isPageWatched' => $wgUser->isWatched( $wgTitle )
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public static function namespaceProtection( &$title, &$user, $action, &$result ){
|
||||
* Prevents editing in the VisualEditor namespace by non-sysop users.
|
||||
*
|
||||
* This is attached to the MediaWiki 'userCan' hook.
|
||||
*/
|
||||
public static function onUserCan( &$title, &$user, $action, &$result ) {
|
||||
global $wgUser, $wgNamespaceProtection;
|
||||
|
||||
if ( array_key_exists( $title->mNamespace, $wgNamespaceProtection ) ) {
|
||||
$nsProt = $wgNamespaceProtection[ $title->mNamespace ];
|
||||
|
||||
if ( !is_array($nsProt) ) $nsProt = array($nsProt);
|
||||
foreach( $nsProt as $right ) {
|
||||
if( '' != $right && !$user->isAllowed( $right ) ) {
|
||||
$result = false;
|
||||
}
|
||||
$nsProt = $wgNamespaceProtection[$title->mNamespace];
|
||||
if ( !is_array( $nsProt ) ) {
|
||||
$nsProt = array( $nsProt );
|
||||
}
|
||||
foreach( $nsProt as $right ) {
|
||||
if ( $right != '' && !$user->isAllowed( $right ) ) {
|
||||
$result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
// URL to the parsoid instance
|
||||
$wgVisualEditorParsoidURL = 'http://parsoid.wmflabs.org/';
|
||||
|
||||
|
||||
/* Setup */
|
||||
|
||||
$wgExtensionCredits['other'][] = array(
|
||||
|
@ -82,12 +81,19 @@ $wgResourceModules += array(
|
|||
),
|
||||
'styles' => 'sandbox/sandbox.css',
|
||||
'dependencies' => array(
|
||||
'ext.visualEditor.ve',
|
||||
'ext.visualEditor.core',
|
||||
),
|
||||
),
|
||||
'ext.visualEditor.core' => $wgVisualEditorResourceTemplate + array(
|
||||
'ext.visualEditor.editPageInit' => $wgVisualEditorResourceTemplate + array(
|
||||
'scripts' => array(
|
||||
'core/ve.Core.js',
|
||||
've2/init/targets/ve.init.EditPageTarget.js',
|
||||
),
|
||||
'styles' => array(
|
||||
've2/init/styles/ve.init.EditPageTarget.css',
|
||||
),
|
||||
'dependencies' => array(
|
||||
'ext.visualEditor.init',
|
||||
'mediawiki.util'
|
||||
),
|
||||
'messages' => array(
|
||||
'minoredit',
|
||||
|
@ -101,19 +107,27 @@ $wgResourceModules += array(
|
|||
'accesskey-ca-edit',
|
||||
'tooltip-ca-edit',
|
||||
'viewsource'
|
||||
|
||||
),
|
||||
'styles' => 'core/ve.Core.css',
|
||||
'dependencies' => array(
|
||||
'jquery',
|
||||
'mediawiki.util'
|
||||
),
|
||||
),
|
||||
'ext.visualEditor.ve' => $wgVisualEditorResourceTemplate + array(
|
||||
'ext.visualEditor.init' => $wgVisualEditorResourceTemplate + array(
|
||||
'scripts' => array(
|
||||
've2/init/ve.init.js',
|
||||
've2/init/ve.init.Target.js',
|
||||
),
|
||||
'dependencies' => array(
|
||||
'ext.visualEditor.base'
|
||||
),
|
||||
),
|
||||
'ext.visualEditor.base' => $wgVisualEditorResourceTemplate + array(
|
||||
'scripts' => array(
|
||||
// ve
|
||||
'jquery/jquery.json.js',
|
||||
've2/ve.js',
|
||||
)
|
||||
),
|
||||
'ext.visualEditor.core' => $wgVisualEditorResourceTemplate + array(
|
||||
'scripts' => array(
|
||||
// ve
|
||||
've2/ve.EventEmitter.js',
|
||||
've2/ve.Factory.js',
|
||||
've2/ve.Position.js',
|
||||
|
@ -224,6 +238,7 @@ $wgResourceModules += array(
|
|||
'dependencies' => array(
|
||||
'jquery',
|
||||
'rangy',
|
||||
'ext.visualEditor.base'
|
||||
),
|
||||
'messages' => array(
|
||||
'visualeditor-tooltip-wikitext',
|
||||
|
@ -237,20 +252,21 @@ $wgResourceModules += array(
|
|||
)
|
||||
);
|
||||
|
||||
/*
|
||||
VisualEditor Namespace
|
||||
Using 2500 range as it appears available in
|
||||
MW Extension_namespace_registration
|
||||
/*
|
||||
* VisualEditor Namespace
|
||||
* Using 2500 and 2501 as per registration on mediawiki.org
|
||||
*
|
||||
* @see http://www.mediawiki.org/wiki/Extension_default_namespaces
|
||||
*/
|
||||
define("NS_VISUALEDITOR", 2500);
|
||||
define("NS_VISUALEDITOR_TALK", 2501);
|
||||
$wgExtraNamespaces[NS_VISUALEDITOR] = "VisualEditor";
|
||||
$wgExtraNamespaces[NS_VISUALEDITOR_TALK] = "VisualEditor_talk";
|
||||
define( 'NS_VISUALEDITOR', 2500 );
|
||||
define( 'NS_VISUALEDITOR_TALK', 2501 );
|
||||
$wgExtraNamespaces[NS_VISUALEDITOR] = 'VisualEditor';
|
||||
$wgExtraNamespaces[NS_VISUALEDITOR_TALK] = 'VisualEditor_talk';
|
||||
$wgContentNamespaces[] = NS_VISUALEDITOR;
|
||||
$wgContentNamespaces[] = NS_VISUALEDITOR_TALK;
|
||||
|
||||
// VE Namespace protection
|
||||
$wgNamespaceProtection[NS_VISUALEDITOR] = array('ve-edit');
|
||||
$wgNamespaceProtection[NS_VISUALEDITOR] = array( 've-edit' );
|
||||
$wgGroupPermissions['sysop']['ve-edit'] = true;
|
||||
|
||||
// Parsoid Wrapper API
|
||||
|
@ -259,6 +275,6 @@ $wgAPIModules['ve-parsoid'] = 'ApiVisualEditor';
|
|||
|
||||
// Integration Hooks
|
||||
$wgAutoloadClasses['VisualEditorHooks'] = $dir . 'VisualEditor.hooks.php';
|
||||
$wgHooks['BeforePageDisplay'][] = 'VisualEditorHooks::onPageDisplay';
|
||||
$wgHooks['userCan'][] = 'VisualEditorHooks::namespaceProtection';
|
||||
$wgHooks['MakeGlobalVariablesScript'][] = 'VisualEditorHooks::makeGlobalVariablesScript';
|
||||
$wgHooks['BeforePageDisplay'][] = 'VisualEditorHooks::onBeforePageDisplay';
|
||||
$wgHooks['userCan'][] = 'VisualEditorHooks::onUserCan';
|
||||
$wgHooks['MakeGlobalVariablesScript'][] = 'VisualEditorHooks::onMakeGlobalVariablesScript';
|
||||
|
|
|
@ -1,442 +0,0 @@
|
|||
/*
|
||||
VisualEditor Core Module for MediaWiki.org integration
|
||||
*/
|
||||
(function( mw, $ ){
|
||||
|
||||
veCore = function(){
|
||||
var _this = this,
|
||||
pageName = mw.config.get( 'wgPageName' ),
|
||||
validNamespace = mw.config.get('wgCanonicalNamespace') === 'VisualEditor' ? true: false;
|
||||
|
||||
this.mainEditor = null;
|
||||
// On VisualEditor namespace ?
|
||||
if ( validNamespace ) {
|
||||
this.$content = $('#content');
|
||||
this.setupTabs();
|
||||
// modify / stash content styles
|
||||
this.prepareContentStyles();
|
||||
$('#ca-edit > span > a').click( function( e ){
|
||||
// hijack the edit link
|
||||
e.preventDefault();
|
||||
// Load Editor if not already loaded
|
||||
if( _this.mainEditor === null ) {
|
||||
_this.selectTab( 'ca-edit' );
|
||||
_this.showSpinner();
|
||||
// async init
|
||||
mw.loader.using( 'ext.visualEditor.ve', function(){
|
||||
_this.init();
|
||||
});
|
||||
_this.getParsoidHTML( pageName, function( content ){
|
||||
_this.init( content );
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
} //valid namespace
|
||||
};
|
||||
|
||||
// called once for each asnyc callback.
|
||||
// once ve is loaded and page has been parsed into html, continue init
|
||||
veCore.prototype.init = function( html ) {
|
||||
var _this = this,
|
||||
isMobileDevice =
|
||||
('ontouchstart' in window) ||
|
||||
window.DocumentTouch && document instanceof DocumentTouch ||
|
||||
false;
|
||||
|
||||
// store the html
|
||||
if (typeof html !== 'undefined') {
|
||||
this.html = html;
|
||||
}
|
||||
// if html and ve are loaded
|
||||
if(
|
||||
typeof ve !== 'undefined' &&
|
||||
typeof this.html !== 'undefined'
|
||||
){
|
||||
$html = $("<div />")
|
||||
.html( this.html );
|
||||
|
||||
// release this.html
|
||||
delete this.html;
|
||||
|
||||
var options = {
|
||||
toolbars: {
|
||||
top: {
|
||||
// If mobile device, float false
|
||||
'float': !isMobileDevice,
|
||||
// Toolbar modes
|
||||
'modes': ['wikitext']
|
||||
}
|
||||
}
|
||||
};
|
||||
this.$editor = $('<div id="ve-editor"></div>');
|
||||
this.$spinner.hide();
|
||||
|
||||
this.$content.css({
|
||||
'padding':'0px 0px 0px 1px'
|
||||
}).append( this.$editor );
|
||||
|
||||
|
||||
this.mainEditor = new ve.Surface( '#ve-editor', $html[0], options );
|
||||
|
||||
this.$editor.find('.es-panes')
|
||||
.css('padding', this.contentStyles.padding );
|
||||
|
||||
// Save BTN
|
||||
this.$editor.find('.es-modes')
|
||||
.append(
|
||||
$('<div />')
|
||||
.attr('class', 've-action-button es-inspector-savebutton')
|
||||
.text('Save')
|
||||
.click(function(){
|
||||
// show/hide dialog
|
||||
_this.$dialog.toggle();
|
||||
})
|
||||
).append(
|
||||
$('<div />')
|
||||
.attr('class', 've-action-button ve-closeBtn')
|
||||
.click(function(){
|
||||
// back to read mode
|
||||
_this.mainEditor = null;
|
||||
_this.cleanup();
|
||||
})
|
||||
);
|
||||
this.initSaveDialog();
|
||||
}
|
||||
};
|
||||
|
||||
veCore.prototype.setupTabs = function(){
|
||||
//Non admins shouldn't have an edit button, only ca-viewsource
|
||||
var $viewsource;
|
||||
|
||||
// If no edit button, user not sysop
|
||||
if ( $('#ca-edit').length === 0 ) {
|
||||
// Add Edit button
|
||||
mw.util.addPortletLink(
|
||||
'p-views',
|
||||
'#',
|
||||
mw.msg('edit'),
|
||||
'ca-edit',
|
||||
mw.msg('tooltip-ca-edit'),
|
||||
mw.msg('accesskey-ca-edit'),
|
||||
'#ca-history'
|
||||
);
|
||||
// Create 'View Source' link in sub menu from original.
|
||||
// Remove original
|
||||
$viewsource = $('#ca-viewsource');
|
||||
if ($viewsource.length > 0) {
|
||||
// if admin, move this to the p-cactions link
|
||||
mw.util.addPortletLink(
|
||||
'p-cactions',
|
||||
$viewsource.find('span > a').attr('href'),
|
||||
$viewsource.find('span > a').text(),
|
||||
$viewsource.attr('id')
|
||||
);
|
||||
$viewsource.remove();
|
||||
}
|
||||
} else {
|
||||
// admin user, create an edit source link
|
||||
mw.util.addPortletLink(
|
||||
'p-cactions',
|
||||
mw.util.wikiGetlink() + '?action=edit',
|
||||
'Edit Source', // TODO: i18n
|
||||
'ca-editsource'
|
||||
);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
// Reset tabs, select tab with tabID
|
||||
// #ca-view, #ca-edit, #ca-history
|
||||
veCore.prototype.selectTab = function( tabID ){
|
||||
// unselects all tabs, selects sel
|
||||
$('#p-views')
|
||||
.find('ul')
|
||||
.children()
|
||||
.each(function(){
|
||||
if( $(this).attr('id') === tabID ) {
|
||||
$(this).addClass('selected');
|
||||
} else {
|
||||
$(this).removeClass('selected');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
veCore.prototype.save = function(){
|
||||
var _this = this;
|
||||
_this.showSpinner();
|
||||
// Save
|
||||
_this.getParsoidWikitextAndSave( function( content ){
|
||||
// cleanup
|
||||
_this.$dialog.slideUp();
|
||||
// load saved page
|
||||
_this.$content
|
||||
.find('#mw-content-text').html( content );
|
||||
_this.cleanup();
|
||||
});
|
||||
};
|
||||
|
||||
veCore.prototype.initSaveDialog = function(){
|
||||
var _this = this;
|
||||
this.$dialog =
|
||||
$('<div />')
|
||||
.attr({
|
||||
'id': 've-saveDialog',
|
||||
'class': 'es-inspector'
|
||||
}).append(
|
||||
$('<div />')
|
||||
.attr('class', 'es-inspector-title')
|
||||
.text( mw.msg('tooltip-save') )
|
||||
).append(
|
||||
$('<div />')
|
||||
.attr('class', 'es-inspector-button ve-saveBtn')
|
||||
.click(function(){
|
||||
_this.$dialog.toggle();
|
||||
})
|
||||
).append(
|
||||
$('<div />')
|
||||
.attr('class', 've-dialog-divider')
|
||||
.append(
|
||||
$('<div />')
|
||||
.text("Describe what you changed")
|
||||
//.text( mw.msg('summary') )
|
||||
).append(
|
||||
$('<input />')
|
||||
.attr({
|
||||
'id': 'txtEditSummary',
|
||||
'type':'text'
|
||||
})
|
||||
).append(
|
||||
$('<br />')
|
||||
).append(
|
||||
$('<div />')
|
||||
.attr('class', 've-dialog-left')
|
||||
.append(
|
||||
$('<input />')
|
||||
.attr({
|
||||
'type': 'checkbox',
|
||||
'name': 'chkMinorEdit',
|
||||
'id': 'chkMinorEdit'
|
||||
})
|
||||
).append(
|
||||
$('<label />')
|
||||
.attr('for', 'chkMinorEdit')
|
||||
.text( mw.msg('minoredit') )
|
||||
).append(
|
||||
$('<br />')
|
||||
).append(
|
||||
$('<input />')
|
||||
.attr({
|
||||
'type': 'checkbox',
|
||||
'name': 'chkWatchlist',
|
||||
'id': 'chkWatchlist'
|
||||
}).prop(
|
||||
'checked',
|
||||
mw.config.get('vePageWatched')
|
||||
)
|
||||
).append(
|
||||
$('<label />')
|
||||
.attr('for', 'chkWatchlist')
|
||||
.text( mw.msg('watchthis') )
|
||||
)
|
||||
).append(
|
||||
$('<div />')
|
||||
.attr('class', 've-action-button es-inspector-savebutton doSaveBtn')
|
||||
.text( mw.msg('savearticle') )
|
||||
.click(function(){
|
||||
_this.save();
|
||||
})
|
||||
.append(
|
||||
$('<div />')
|
||||
.attr('class', 'doSaveBtnIcon')
|
||||
)
|
||||
).append(
|
||||
$('<br />')
|
||||
)
|
||||
).append(
|
||||
$('<div />')
|
||||
.attr('class', 've-dialog-divider')
|
||||
.append(
|
||||
$("<p />")
|
||||
// TODO: i18n
|
||||
.html(
|
||||
"By editing this page, you agree to irrevocably release your \
|
||||
contributions under the CC-By-SA 3.0 License. If you don't \
|
||||
want your writing to be editied mercilessly and redistrubuted \
|
||||
at will, then don't submit it here. <br /><br />You are also \
|
||||
confirming that you wrote this yourself, or copied it from a \
|
||||
public domain or similar free resource. See Project:Copyright \
|
||||
for full details of the licenses used on this site. \
|
||||
<b>DO NOT SUBMIT COPYRIGHTED WORK WITHOUT PERMISSION!</b>"
|
||||
)
|
||||
)
|
||||
);
|
||||
this.$editor
|
||||
.find('.es-inspector-savebutton')
|
||||
.after ( this.$dialog );
|
||||
|
||||
};
|
||||
|
||||
veCore.prototype.showSpinner = function(){
|
||||
var _this = this;
|
||||
|
||||
this.$spinner = $('<div />')
|
||||
.attr({
|
||||
'id': 've-loader-spinner',
|
||||
'class': 'mw-ajax-loader'
|
||||
}).css({
|
||||
'height': this.$content.height() + 'px',
|
||||
'width': (this.$content.width() -20 ) + 'px'
|
||||
});
|
||||
|
||||
_this.$spinner.remove();
|
||||
//hide all of the #content element children
|
||||
_this.$content
|
||||
.children()
|
||||
.each(function(){
|
||||
$(this).hide();
|
||||
});
|
||||
_this.$content.append(
|
||||
_this.$spinner.show()
|
||||
);
|
||||
};
|
||||
|
||||
/* Make a backup of the #content div styles
|
||||
In order to tuck the toolbar close under the tabs,
|
||||
We need to change the padding before inserting the toolbar
|
||||
Additionally, the transitions must be removed so that
|
||||
when adjusting the padding, there is no animated transition.
|
||||
*/
|
||||
veCore.prototype.prepareContentStyles = function(){
|
||||
// Store Padding and transitions
|
||||
this.contentStyles = {
|
||||
'padding': this.$content.css('padding'),
|
||||
'transition': this.$content.css('transition'),
|
||||
'transition-property': this.$content.css('transition-property'),
|
||||
'-moz-transition': this.$content.css('-moz-transition'),
|
||||
'-webkit-transition': this.$content.css('-webkit-transition'),
|
||||
'-o-transition': this.$content.css('-o-transition')
|
||||
};
|
||||
// Squash transitions
|
||||
this.$content.css({
|
||||
'transition': 'none',
|
||||
'transition-property': 'none',
|
||||
'-moz-transition': 'none',
|
||||
'-webkit-transition': 'none',
|
||||
'-o-transition': 'color 0 ease-in'
|
||||
});
|
||||
};
|
||||
|
||||
//back to view
|
||||
veCore.prototype.cleanup = function(){
|
||||
this.mainEditor = null;
|
||||
this.selectTab( 'ca-view' );
|
||||
this.$content
|
||||
.find('#mw-content-text, #bodyContent, #firstHeading').show()
|
||||
.end()
|
||||
.find('#ve-editor, #ve-loader-spinner').remove()
|
||||
.end()
|
||||
//.css( this.contentStyles );
|
||||
// only put back padding for now, ideally restore transition css though
|
||||
.css('padding', this.contentStyles.padding);
|
||||
};
|
||||
|
||||
veCore.prototype.getParsoidHTML = function (title, callback) {
|
||||
$.ajax({
|
||||
url: mw.util.wikiScript( 'api' ),
|
||||
data: {
|
||||
'action': 've-parsoid',
|
||||
'paction': 'parse',
|
||||
'page': mw.config.get( 'wgPageName' ),
|
||||
'format': 'json'
|
||||
},
|
||||
dataType: 'json',
|
||||
type: 'GET',
|
||||
cache: 'false',
|
||||
timeout: 9000, //wait up to 9 seconds
|
||||
success: function( data ) {
|
||||
if (data && data['ve-parsoid'] && data['ve-parsoid'].parsed ) {
|
||||
if( typeof callback === 'function') {
|
||||
callback( data['ve-parsoid'].parsed );
|
||||
}
|
||||
}
|
||||
},
|
||||
error: function( error ) {}
|
||||
});
|
||||
};
|
||||
/*
|
||||
Posts HTML to Parsoid Wrapper API
|
||||
API Posts HTML to Parsoid Service, receives Wikitext,
|
||||
API Saves Wikitext to page.
|
||||
Returns new page content
|
||||
*/
|
||||
veCore.prototype.getParsoidWikitextAndSave = function( callback ) {
|
||||
var data = this.mainEditor.documentModel.getData(),
|
||||
html = ve.dm.converter.getDomFromData( data ),
|
||||
summary = $('#txtEditSummary').val(),
|
||||
minor = $('#chkMinorEdit').prop('checked'),
|
||||
watch = $('#chkWatchlist').prop('checked');
|
||||
|
||||
$.ajax({
|
||||
url: mw.util.wikiScript( 'api' ),
|
||||
data: {
|
||||
'action': 've-parsoid',
|
||||
'paction': 'save',
|
||||
'page': mw.config.get( 'wgPageName' ),
|
||||
'html': $(html).html(),
|
||||
'token': mw.user.tokens.get('editToken'),
|
||||
'summary': summary,
|
||||
'minor': minor,
|
||||
'watch': watch,
|
||||
'format': 'json'
|
||||
},
|
||||
dataType: 'json',
|
||||
type: 'POST',
|
||||
success: function( data ) {
|
||||
if (
|
||||
data &&
|
||||
data['ve-parsoid'] &&
|
||||
data['ve-parsoid'].result &&
|
||||
data['ve-parsoid'].result === 'success' &&
|
||||
data['ve-parsoid'].content
|
||||
) {
|
||||
//saved
|
||||
callback( data['ve-parsoid'].content );
|
||||
}
|
||||
},
|
||||
error: function( error ) {}
|
||||
});
|
||||
};
|
||||
|
||||
/* Gets HTML for a page from MW API action parse */
|
||||
veCore.prototype.getParsedPage = function( title, callback ) {
|
||||
//currently using mw api to get
|
||||
$.ajax({
|
||||
url: mw.util.wikiScript( 'api' ),
|
||||
data: {
|
||||
'action': 'parse',
|
||||
'format': 'json',
|
||||
'page': title
|
||||
},
|
||||
dataType: 'json',
|
||||
type: 'GET',
|
||||
cache: 'false',
|
||||
success: function( data ) {
|
||||
if ( data && data.parse && data.parse.text ) {
|
||||
// return pages to callback
|
||||
if( typeof callback === 'function') {
|
||||
callback( data.parse.text['*'] );
|
||||
}
|
||||
}
|
||||
},
|
||||
error: function() {
|
||||
if( typeof callback === 'function') {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var core = new veCore();
|
||||
|
||||
})( window.mw, jQuery );
|
|
@ -1,8 +1,21 @@
|
|||
#ve-loader-spinner {
|
||||
background-color: #FFF;
|
||||
opacity:.5;
|
||||
.es-toolbar-wrapper {
|
||||
margin: -1.25em -1.5em -1.5em -1.5em;
|
||||
}
|
||||
.ve-action-button {
|
||||
|
||||
.es-toolbar {
|
||||
margin-left: 1px;
|
||||
}
|
||||
|
||||
.ve-init-editPageTarget-loadingSpinner {
|
||||
background-color: #ffffff;
|
||||
opacity: 0.75;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-position: center 2em !important;
|
||||
}
|
||||
|
||||
.ve-init-editPageTarget-button {
|
||||
display: inline-block;
|
||||
border: solid 1px
|
||||
transparent;
|
||||
|
@ -17,72 +30,33 @@
|
|||
margin-right: 0.25em;
|
||||
border: solid 1px transparent;
|
||||
}
|
||||
.ve-action-button:before {
|
||||
.ve-init-editPageTarget-button:before {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
display: block;
|
||||
height: 22px;
|
||||
}
|
||||
.ve-action-button:hover {
|
||||
.ve-init-editPageTarget-button:hover {
|
||||
border-color: #eeeeee;
|
||||
}
|
||||
.ve-action-button:active,
|
||||
.ve-action-button-down {
|
||||
.ve-init-editPageTarget-button:active,
|
||||
.ve-init-editPageTarget-button-down {
|
||||
border-color: #dddddd;
|
||||
-webkit-box-shadow: inset 0px 1px 4px 0px rgba(0, 0, 0, 0.07);
|
||||
-moz-box-shadow: inset 0px 1px 4px 0px rgba(0, 0, 0, 0.07);
|
||||
box-shadow: inset 0px 1px 4px 0px rgba(0, 0, 0, 0.07);
|
||||
}
|
||||
|
||||
/* Save dialog styles */
|
||||
#ve-saveDialog {
|
||||
top: -1px;
|
||||
right: 2.5em;
|
||||
width: 29em;
|
||||
}
|
||||
|
||||
#ve-saveDialog > .ve-dialog-divider {
|
||||
border-top:1px solid #dddddd;
|
||||
padding: 10px 0;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
#ve-saveDialog br {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.ve-dialog-left {
|
||||
float: left;
|
||||
}
|
||||
|
||||
#ve-saveDialog input[type='text'] {
|
||||
width: 96%;
|
||||
font-size: 12px;
|
||||
padding: 4px;
|
||||
margin: 10px 0px;
|
||||
}
|
||||
|
||||
#ve-saveDialog input[type='checkbox'] {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.ve-closeBtn {
|
||||
.ve-init-editPageTarget-closeButton {
|
||||
width: 22px;
|
||||
background-image: url(../ve2/ui/styles/images/close.png);
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
/* mini save button */
|
||||
.ve-saveBtn {
|
||||
right: .025em;
|
||||
width: 22px;
|
||||
background-image: url(../ve2/ui/styles/images/close.png);
|
||||
background-image: url(../../ui/styles/images/close.png);
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
/* inspector styles */
|
||||
.es-inspector-savebutton {
|
||||
padding-right: 26px;
|
||||
.ve-init-editPageTarget-saveButton {
|
||||
padding-right: 32px;
|
||||
border:1px solid transparent;
|
||||
border-radius: 0.125em;
|
||||
-webkit-border-radius: 0.125em;
|
||||
|
@ -90,18 +64,34 @@
|
|||
-o-border-radius: 0.125em;
|
||||
/* need new button */
|
||||
/* @embed */
|
||||
background-image: url(../ve2/ui/styles/images/close.png);
|
||||
background-position: center right;
|
||||
background-image: url(../../ui/styles/images/accept.png);
|
||||
background-position: right center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.doSaveBtn {
|
||||
|
||||
.ve-init-editPageTarget-saveButton span {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
/* mini save button */
|
||||
.ve-init-editPageTarget-saveDialog-closeButton {
|
||||
right: .025em;
|
||||
width: 22px;
|
||||
background-image: url(../../ui/styles/images/close.png);
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.ve-init-editPageTarget-saveDialog-saveButton {
|
||||
position: absolute;
|
||||
border: 1px solid rgb(196,229,154);
|
||||
margin-top: 10px;
|
||||
right: 10px;
|
||||
font-size: 12px;
|
||||
padding: 5px 10px;
|
||||
background-image: url(../ve2/ui/styles/images/close.png);
|
||||
font-size: 1em;
|
||||
padding: 0.5em 1em;
|
||||
border-radius: 0.25em;
|
||||
-moz-border-radius: 0.25em;
|
||||
background-image: url(../../ui/styles/images/close.png);
|
||||
background-position: center right;
|
||||
background-repeat: no-repeat;
|
||||
/* Fancy CSS background */
|
||||
|
@ -118,12 +108,48 @@
|
|||
color-stop(1, rgb(240,251,225))
|
||||
);
|
||||
}
|
||||
.doSaveBtn > div.doSaveBtnIcon {
|
||||
height:2em;
|
||||
width:2em;
|
||||
float:right;
|
||||
.ve-init-editPageTarget-saveDialog-saveButton-icon {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
height: 2em;
|
||||
width: 28px;
|
||||
background: transparent;
|
||||
background-image: url(../ve2/ui/styles/images/accept.png);
|
||||
background-position: center right;
|
||||
background-image: url(../../ui/styles/images/accept-clear.png);
|
||||
background-position: top right;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
}
|
||||
|
||||
/* Save dialog styles */
|
||||
|
||||
.ve-init-editPageTarget-saveDialog {
|
||||
display: block;
|
||||
top: -1px;
|
||||
right: 2.5em;
|
||||
width: 29em;
|
||||
}
|
||||
|
||||
.ve-init-editPageTarget-saveDialog-body {
|
||||
border-top:1px solid #dddddd;
|
||||
padding: 10px 0;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.ve-init-editPageTarget-saveDialog-license {
|
||||
font-size: 0.7em;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.ve-init-editPageTarget-saveDialog-options {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.ve-init-editPageTarget-saveDialog input[type='text'] {
|
||||
width: 96%;
|
||||
font-size: 12px;
|
||||
padding: 4px;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.ve-init-editPageTarget-saveDialog input[type='checkbox'] {
|
||||
margin-right: 5px;
|
||||
}
|
308
modules/ve2/init/targets/ve.init.EditPageTarget.js
Normal file
308
modules/ve2/init/targets/ve.init.EditPageTarget.js
Normal file
|
@ -0,0 +1,308 @@
|
|||
/**
|
||||
* Edit page target.
|
||||
*
|
||||
* @class
|
||||
* @constructor
|
||||
* @extends {ve.init.Target}
|
||||
* @param {String} title Page title of target
|
||||
*/
|
||||
ve.init.EditPageTarget = function() {
|
||||
// Inheritance
|
||||
ve.init.Target.call( this, mw.config.get( 'wgPageName' ) );
|
||||
|
||||
// Properties
|
||||
this.$content = $( '#content' );
|
||||
this.$view = this.$content.find( '#mw-content-text, #bodyContent' );
|
||||
this.$heading = $( '#firstHeading' );
|
||||
this.$surface = $( '<div class="ve-surface"></div>' );
|
||||
this.$toolbar = null;
|
||||
this.surface = null;
|
||||
this.active = false;
|
||||
this.surfaceOptions = {
|
||||
'toolbars': {
|
||||
'top': {
|
||||
// If mobile device, float false
|
||||
'float': !this.isMobileDevice,
|
||||
// Toolbar modes
|
||||
'modes': ['wikitext']
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Initialization
|
||||
if ( mw.config.get('wgCanonicalNamespace') === 'VisualEditor' ) {
|
||||
// Clicking the edit tab is the only way any other code gets run, and this sets that up
|
||||
this.setupTabs();
|
||||
}
|
||||
};
|
||||
|
||||
/* Static Members */
|
||||
|
||||
/*jshint multistr: true*/
|
||||
ve.init.EditPageTarget.saveDialogTemplate = '\
|
||||
<div class="es-inspector ve-init-editPageTarget-saveDialog">\
|
||||
<div class="es-inspector-title ve-init-editPageTarget-saveDialog-title"></div>\
|
||||
<div class="es-inspector-button ve-init-editPageTarget-saveDialog-closeButton"></div>\
|
||||
<div class="ve-init-editPageTarget-saveDialog-body">\
|
||||
<div class="ve-init-editPageTarget-saveDialog-editSummary-label"></div>\
|
||||
<input name="editSummary" id="ve-init-editPageTarget-saveDialog-editSummary" type="text">\
|
||||
<div class="clear:both"></div>\
|
||||
<div class="ve-init-editPageTarget-saveDialog-options">\
|
||||
<input type="checkbox" name="minorEdit" \
|
||||
id="ve-init-editPageTarget-saveDialog-minorEdit">\
|
||||
<label class="ve-init-editPageTarget-saveDialog-minorEdit-label" \
|
||||
for="ve-init-editPageTarget-saveDialog-minorEdit">This is a minor edit</label>\
|
||||
<div style="clear:both"></div>\
|
||||
<input type="checkbox" name="watchList" \
|
||||
id="ve-init-editPageTarget-saveDialog-watchList">\
|
||||
<label class="ve-init-editPageTarget-saveDialog-watchList-label" \
|
||||
for="ve-init-editPageTarget-saveDialog-watchList">Watch this page</label>\
|
||||
</div>\
|
||||
<div class="ve-init-editPageTarget-button ve-init-editPageTarget-saveDialog-saveButton">\
|
||||
<span class="ve-init-editPageTarget-saveDialog-saveButton-label"></span>\
|
||||
<div class="ve-init-editPageTarget-saveDialog-saveButton-icon"></div>\
|
||||
</div>\
|
||||
<div style="clear:both"></div>\
|
||||
</div>\
|
||||
<div class="ve-init-editPageTarget-saveDialog-foot">\
|
||||
<p class="ve-init-editPageTarget-saveDialog-license"></p>\
|
||||
</div>\
|
||||
</div>';
|
||||
|
||||
/* Methods */
|
||||
|
||||
/**
|
||||
* ...
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.EditPageTarget.prototype.onEditTabClick = function( e ) {
|
||||
// Ignore multiple clicks while editor is active
|
||||
if ( !this.active ) {
|
||||
// UI updates
|
||||
this.setSelectedTab( 'ca-edit' );
|
||||
this.showSpinner();
|
||||
// Asynchronous initialization - load ve modules at the same time as the content
|
||||
this.load( ve.proxy( this.onLoad, this ) );
|
||||
}
|
||||
// Prevent the edit tab's normal behavior
|
||||
e.preventDefault();
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* ...
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.EditPageTarget.prototype.onSaveDialogSaveButtonClick = function( e ) {
|
||||
var _this = this;
|
||||
this.showSpinner();
|
||||
// Save
|
||||
this.save(
|
||||
ve.dm.converter.getDomFromData( this.surface.getDocumentModel().getData() ),
|
||||
{
|
||||
'summary': $( '#ve-init-editPageTarget-saveDialog-editSummary' ).val(),
|
||||
'minor': $( '#ve-init-editPageTarget-saveDialog-minorEdit' ).prop( 'checked' ),
|
||||
'watch': $( '#ve-init-editPageTarget-saveDialog-watchList' ).prop( 'checked' )
|
||||
},
|
||||
ve.proxy( this.onSave, this )
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* ...
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.EditPageTarget.prototype.onLoad = function( error, dom ) {
|
||||
if ( error ) {
|
||||
// TODO: Error handling in the UI
|
||||
} else {
|
||||
this.setUpSurface( dom );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* ...
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.EditPageTarget.prototype.onSave = function( error, content ) {
|
||||
if ( error ) {
|
||||
// TODO: Handle error in UI
|
||||
} else {
|
||||
// Hide the save dialog
|
||||
this.$dialog.slideUp();
|
||||
// Refresh page with changed content
|
||||
this.$content.find( '#mw-content-text' ).html( content );
|
||||
// Restore the page to how it used to be
|
||||
this.tearDownSurface();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* ...
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.EditPageTarget.prototype.setUpSurface = function( dom ) {
|
||||
// Initialize surface
|
||||
this.$surface.appendTo( this.$content );
|
||||
this.surface = new ve.Surface( this.$surface, dom, this.surfaceOptions );
|
||||
// Transplant the toolbar
|
||||
this.$toolbar = this.$surface.find( '.es-toolbar-wrapper' ).insertBefore( this.$heading );
|
||||
this.$heading.css( 'margin-top', this.$toolbar.outerHeight() );
|
||||
// Update UI
|
||||
this.$spinner.remove();
|
||||
this.$view.hide();
|
||||
this.$spinner.hide();
|
||||
this.$dialog = $( ve.init.EditPageTarget.saveDialogTemplate );
|
||||
// Add save and close buttons
|
||||
this.$toolbar
|
||||
.find( '.es-modes' )
|
||||
.append(
|
||||
$( '<div></div>' )
|
||||
.addClass( 've-init-editPageTarget-button ve-init-editPageTarget-saveButton' )
|
||||
.append(
|
||||
$( '<span></span>' )
|
||||
.text( mw.msg( 'savearticle' ) )
|
||||
)
|
||||
.click( ve.proxy( this.$dialog.show, this.$dialog ) )
|
||||
)
|
||||
.append(
|
||||
$( '<div></div>' )
|
||||
.addClass( 've-init-editPageTarget-button ve-init-editPageTarget-closeButton' )
|
||||
.click( ve.proxy( this.tearDownSurface, this ) )
|
||||
);
|
||||
// Set up save dialog
|
||||
this.$dialog
|
||||
.find( '.ve-init-editPageTarget-saveDialog-title' )
|
||||
.text( mw.msg( 'tooltip-save' ) )
|
||||
.end()
|
||||
.find( '.ve-init-editPageTarget-saveDialog-closeButton' )
|
||||
.click( ve.proxy( this.$dialog.hide, this.$dialog ) )
|
||||
.end()
|
||||
.find( '.ve-init-editPageTarget-saveDialog-editSummary-label' )
|
||||
.text( mw.msg( 'summary' ) )
|
||||
.end()
|
||||
.find( '.ve-init-editPageTarget-saveDialog-minorEdit-label' )
|
||||
.text( mw.msg( 'minoredit' ) )
|
||||
.end()
|
||||
.find( '.ve-init-editPageTarget-saveDialog-watchList' )
|
||||
.prop( 'checked', ve.config.isPageWatched )
|
||||
.end()
|
||||
.find( '.ve-init-editPageTarget-saveDialog-watchList-label' )
|
||||
.text( mw.msg( 'watchthis' ) )
|
||||
.end()
|
||||
.find( '.ve-init-editPageTarget-saveDialog-saveButton' )
|
||||
.click( ve.proxy( this.onSaveDialogSaveButtonClick, this ) )
|
||||
.end()
|
||||
.find( '.ve-init-editPageTarget-saveDialog-saveButton-label' )
|
||||
.text( mw.msg( 'savearticle' ) )
|
||||
.end()
|
||||
.find( '.ve-init-editPageTarget-saveDialog-license' )
|
||||
.html(
|
||||
"By editing this page, you agree to irrevocably release your \
|
||||
contributions under the CC-By-SA 3.0 License. If you don't want your \
|
||||
writing to be editied mercilessly and redistrubuted at will, then \
|
||||
don't submit it here.<br /><br />You are also confirming that you \
|
||||
wrote this yourself, or copied it from a public domain or similar free \
|
||||
resource. See Project:Copyright for full details of the licenses \
|
||||
used on this site.\
|
||||
<b>DO NOT SUBMIT COPYRIGHTED WORK WITHOUT PERMISSION!</b>"
|
||||
)
|
||||
.end()
|
||||
.insertAfter( this.$toolbar.find( '.ve-init-editPageTarget-saveButton' ) );
|
||||
};
|
||||
|
||||
ve.init.EditPageTarget.prototype.tearDownSurface = function( content ) {
|
||||
// Reset tabs
|
||||
this.setSelectedTab( 'ca-view' );
|
||||
// Update UI
|
||||
this.$view.show().fadeTo( 1 );
|
||||
this.$surface.remove();
|
||||
this.$toolbar.remove();
|
||||
this.$spinner.remove();
|
||||
this.$heading.css( 'margin-top', 0 );
|
||||
// Destroy editor
|
||||
this.surface = null;
|
||||
};
|
||||
|
||||
ve.init.EditPageTarget.prototype.setupTabs = function(){
|
||||
// Only sysop users will have an edit tab in this namespace, so we might need to add one
|
||||
if ( $( '#ca-edit' ).length === 0 ) {
|
||||
// Add edit tab
|
||||
mw.util.addPortletLink(
|
||||
'p-views',
|
||||
'#',
|
||||
mw.msg( 'edit' ),
|
||||
'ca-edit',
|
||||
mw.msg( 'tooltip-ca-edit' ),
|
||||
mw.msg( 'accesskey-ca-edit' ),
|
||||
'#ca-history'
|
||||
);
|
||||
// If there isn't an edit tab, there's a view source tab we need to replace with edit source
|
||||
var $viewSource = $( '#ca-viewsource' );
|
||||
if ( $viewSource.length > 0 ) {
|
||||
// "Move" the view source link to p-actions
|
||||
mw.util.addPortletLink(
|
||||
'p-cactions',
|
||||
$viewSource.find( 'a' ).attr( 'href' ),
|
||||
$viewSource.find( 'a' ).text(),
|
||||
$viewSource.attr( 'id' )
|
||||
);
|
||||
// Remove the view original source link
|
||||
$viewSource.remove();
|
||||
}
|
||||
} else {
|
||||
// Sysop users will need a new edit source tab since we are highjacking the edit tab
|
||||
mw.util.addPortletLink(
|
||||
'p-cactions',
|
||||
mw.util.wikiGetlink() + '?action=edit',
|
||||
'Edit Source', // TODO: i18n
|
||||
'ca-editsource'
|
||||
);
|
||||
}
|
||||
$( '#ca-edit > span > a' ).click( ve.proxy( this.onEditTabClick, this ) );
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows a loading spinner.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.EditPageTarget.prototype.showSpinner = function() {
|
||||
var $bodyContent = $( '#bodyContent' );
|
||||
this.$spinner = $( '<div></div>' )
|
||||
.addClass( 've-init-editPageTarget-loadingSpinner mw-ajax-loader' )
|
||||
.css( {
|
||||
'height': $bodyContent.height() + 'px',
|
||||
'width': ( $bodyContent.width() -20 ) + 'px'
|
||||
} )
|
||||
.appendTo( $bodyContent );
|
||||
};
|
||||
|
||||
/**
|
||||
* Resets all tabs in the UI and selects a specific one.
|
||||
*
|
||||
* If no ID is given, or no ID matches the given ID, all tabs will be unselected.
|
||||
*
|
||||
* @method
|
||||
* @param {String} id HTML ID of tab to select
|
||||
*/
|
||||
ve.init.EditPageTarget.prototype.setSelectedTab = function( id ) {
|
||||
$( '#p-views' ).find( 'li.selected' ).removeClass( 'selected' );
|
||||
$( '#' + id ).addClass( 'selected' );
|
||||
};
|
||||
|
||||
/* Inheritance */
|
||||
|
||||
ve.extendClass( ve.init.EditPageTarget, ve.init.Target );
|
||||
|
||||
/* Initialization */
|
||||
|
||||
// TODO: Clean this stuff up
|
||||
|
||||
ve.config = mw.config.get( 'wgVisualEditor' );
|
||||
ve.init.current = new ve.init.EditPageTarget();
|
144
modules/ve2/init/ve.init.Target.js
Normal file
144
modules/ve2/init/ve.init.Target.js
Normal file
|
@ -0,0 +1,144 @@
|
|||
/**
|
||||
* Generic target.
|
||||
*
|
||||
* @class
|
||||
* @constructor
|
||||
* @param {String} title Page title of target
|
||||
*/
|
||||
ve.init.Target = function( title ) {
|
||||
// Properties
|
||||
this.title = title;
|
||||
this.editToken = mw.user.tokens.get( 'editToken' );
|
||||
this.apiUrl = mw.util.wikiScript( 'api' );
|
||||
this.modules = ['ext.visualEditor.core'];
|
||||
this.isDomLoading = false;
|
||||
this.isDomSaving = false;
|
||||
this.isMobileDevice = (
|
||||
'ontouchstart' in window ||
|
||||
( window.DocumentTouch && document instanceof DocumentTouch )
|
||||
);
|
||||
};
|
||||
|
||||
/* Methods */
|
||||
|
||||
/**
|
||||
* Gets DOM from Parsoid API.
|
||||
*
|
||||
* This method performs an asynchronous action and uses a callback function to handle the result.
|
||||
*
|
||||
* @example
|
||||
* target.loadDom(
|
||||
* function( error, dom ) {
|
||||
* // Handle errors and do something with the loaded DOM
|
||||
* }
|
||||
* );
|
||||
*
|
||||
* @method
|
||||
* @param {Function} callback Function to call when complete, accepts error and dom arguments
|
||||
* @returns {Boolean} Loading is now in progress
|
||||
*/
|
||||
ve.init.Target.prototype.load = function( callback ) {
|
||||
// Prevent duplicate requests
|
||||
if ( this.isDomLoading ) {
|
||||
return false;
|
||||
}
|
||||
// Start loading the module immediately
|
||||
var modules = this.modules;
|
||||
mw.loader.load( modules );
|
||||
// Load DOM
|
||||
this.isDomLoading = true;
|
||||
$.ajax( {
|
||||
'url': this.apiUrl,
|
||||
'data': {
|
||||
'action': 've-parsoid',
|
||||
'paction': 'parse',
|
||||
'page': this.title,
|
||||
'format': 'json'
|
||||
},
|
||||
'dataType': 'json',
|
||||
'type': 'GET',
|
||||
'cache': 'false',
|
||||
// Wait up to 9 seconds
|
||||
'timeout': 9000,
|
||||
'error': callback,
|
||||
'success': function( data ) {
|
||||
this.isDomLoading = false;
|
||||
var response = data['ve-parsoid'];
|
||||
if ( !response ) {
|
||||
callback( 'Invalid response from server' );
|
||||
} else if ( typeof response.parsed !== 'string' ) {
|
||||
callback( 'Invalid HTML content in response from server' );
|
||||
} else {
|
||||
// Everything worked, the page was loaded, continue as soon as the module is ready
|
||||
mw.loader.using( modules, function() {
|
||||
callback( null, $( '<div></div>' ).html( data['ve-parsoid'].parsed )[0] );
|
||||
} );
|
||||
}
|
||||
}
|
||||
} );
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Posts DOM to Parsoid API.
|
||||
*
|
||||
* This method performs an asynchronous action and uses a callback function to handle the result.
|
||||
*
|
||||
* @example
|
||||
* target.saveDom(
|
||||
* dom,
|
||||
* { 'summary': 'test', 'minor': true, 'watch': false },
|
||||
* function( error, html ) {
|
||||
* // Handle errors and do something with the rendered HTML
|
||||
* }
|
||||
* );
|
||||
*
|
||||
* @method
|
||||
* @param {HTMLElement} dom DOM to save
|
||||
* @param {Object} options Saving options
|
||||
* @param {String} options.summary Edit summary
|
||||
* @param {Boolean} options.minor Edit is a minor edit
|
||||
* @param {Boolean} options.watch Watch this page
|
||||
* @param {Function} callback Function to call when complete, accepts error and html arguments
|
||||
* @returns {Boolean} Saving is now in progress
|
||||
*/
|
||||
ve.init.Target.prototype.save = function( dom, options, callback ) {
|
||||
// Prevent duplicate requests
|
||||
if ( this.isDomSaving ) {
|
||||
return false;
|
||||
}
|
||||
// Save DOM
|
||||
this.isDomSaving = true;
|
||||
$.ajax( {
|
||||
'url': this.apiUrl,
|
||||
'data': {
|
||||
'format': 'json',
|
||||
'action': 've-parsoid',
|
||||
'paction': 'save',
|
||||
'page': this.title,
|
||||
'html': $( dom ).html(),
|
||||
'token': this.editToken,
|
||||
'summary': options.summary,
|
||||
'minor': options.minor,
|
||||
'watch': options.watch
|
||||
},
|
||||
'dataType': 'json',
|
||||
'type': 'POST',
|
||||
'error': callback,
|
||||
'success': function( data ) {
|
||||
this.isDomSaving = false;
|
||||
var response = data['ve-parsoid'];
|
||||
if ( !response ) {
|
||||
callback( 'Invalid response from server' );
|
||||
} else if ( response.result !== 'success' ) {
|
||||
callback( 'Unsuccessful request: ' + response.result );
|
||||
} else if ( typeof response.content !== 'string' ) {
|
||||
callback( 'Invalid HTML content in response from server' );
|
||||
} else {
|
||||
// Everything worked, the page was saved, continue immediately
|
||||
callback( null, response.content );
|
||||
}
|
||||
}
|
||||
} );
|
||||
return true;
|
||||
};
|
8
modules/ve2/init/ve.init.js
Normal file
8
modules/ve2/init/ve.init.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
/**
|
||||
* Initialization namespace.
|
||||
*
|
||||
* All classes and functions will be attached to this object to keep the global namespace clean.
|
||||
*/
|
||||
ve.init = {
|
||||
//
|
||||
};
|
BIN
modules/ve2/ui/styles/images/accept-clear.png
Normal file
BIN
modules/ve2/ui/styles/images/accept-clear.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
|
@ -1,4 +1,5 @@
|
|||
.es-inspector {
|
||||
font-family: sans-serif;
|
||||
display: none;
|
||||
position: absolute;
|
||||
border: solid 1px #cccccc;
|
||||
|
|
|
@ -203,27 +203,20 @@ ve.ui.Context.prototype.addInspector = function( name, inspector ) {
|
|||
inspectorDoc.write( inspectorContent );
|
||||
inspectorDoc.close();
|
||||
|
||||
$('head', inspectorDoc).append( $styleLink );
|
||||
$('#ve-inspector-wrapper', inspectorDoc ).append( inspector.$ );
|
||||
$( 'head', inspectorDoc).append( $styleLink );
|
||||
$( '#ve-inspector-wrapper', inspectorDoc ).append( inspector.$ );
|
||||
|
||||
$( 'body', inspectorDoc ).css({
|
||||
$( 'body', inspectorDoc ).css( {
|
||||
'padding': '0px 5px 10px 5px',
|
||||
'margin': 0
|
||||
});
|
||||
|
||||
var asdf = {
|
||||
'width': inspector.$.outerWidth( true ) + 10,
|
||||
'height': inspector.$.outerHeight( true ) + 10
|
||||
};
|
||||
console.log (asdf);
|
||||
console.log (inspector.$);
|
||||
} );
|
||||
|
||||
// apply the dimensions of the inspector to the iframe, may need to be moved to open inspector
|
||||
function tweakIframeDimensions() {
|
||||
_this.$inspectors.css({
|
||||
_this.$inspectors.css( {
|
||||
'width': inspector.$.outerWidth( true ) + 10,
|
||||
'height': inspector.$.outerHeight( true ) + 10
|
||||
});
|
||||
} );
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
* VisualEditor User Interface namespace.
|
||||
*
|
||||
*
|
||||
* All classes and functions will be attached to this object to keep the global namespace clean.
|
||||
*/
|
||||
ve.ui = {
|
||||
|
@ -14,5 +14,5 @@ ve.ui = {
|
|||
ve.ui.getStylesheetPath = function() {
|
||||
// gets the path to a UI
|
||||
// TODO: look for mw.util and rewrite
|
||||
return "/extensions/VisualEditor/modules/ve2/ui/styles/";
|
||||
};
|
||||
return mw.config.get( 'wgExtensionAssetsPath' ) + '/VisualEditor/modules/ve2/ui/styles/';
|
||||
};
|
||||
|
|
|
@ -4,9 +4,7 @@
|
|||
* All classes and functions will be attached to this object to keep the global namespace clean.
|
||||
*/
|
||||
window.ve = {
|
||||
/**
|
||||
* List of instances of visual editors
|
||||
*/
|
||||
// List of instances of visual editors
|
||||
'instances': []
|
||||
};
|
||||
|
||||
|
@ -53,6 +51,8 @@ ve.isEmptyObject = $.isEmptyObject;
|
|||
|
||||
ve.isArray = $.isArray;
|
||||
|
||||
ve.proxy = $.proxy;
|
||||
|
||||
/**
|
||||
* Wrapper for Array.prototype.indexOf
|
||||
*
|
||||
|
|
Loading…
Reference in a new issue