mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-11-24 14:33:59 +00:00
Merge branch 'dmrewrite' of ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor into dmrewrite
This commit is contained in:
commit
1fa1908402
|
@ -126,12 +126,12 @@ $wgResourceModules += array(
|
|||
// ve
|
||||
'jquery/jquery.json.js',
|
||||
've2/ve.js',
|
||||
've2/ve.EventEmitter.js',
|
||||
)
|
||||
),
|
||||
'ext.visualEditor.core' => $wgVisualEditorResourceTemplate + array(
|
||||
'scripts' => array(
|
||||
// ve
|
||||
've2/ve.EventEmitter.js',
|
||||
've2/ve.Factory.js',
|
||||
've2/ve.Position.js',
|
||||
've2/ve.Range.js',
|
||||
|
|
|
@ -25,3 +25,8 @@
|
|||
.ve-ce-branchNode p:empty:before {
|
||||
content: url('data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==');
|
||||
}
|
||||
|
||||
li.ve-ce-branchNode p.ve-ce-branchNode:first-child {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
.ve-surface {
|
||||
margin-top: 0.8em;
|
||||
}
|
||||
|
||||
.es-toolbar-wrapper {
|
||||
margin: -1em -1em 1em -1em;
|
||||
transition: margin 250ms, height 250ms;
|
||||
-moz-transition: margin 250ms, height 250ms;
|
||||
-webkit-transition: margin 250ms, height 250ms;
|
||||
-o-transition: margin 250ms, height 250ms;
|
||||
}
|
||||
|
||||
.es-toolbar {
|
||||
|
@ -31,7 +31,7 @@
|
|||
float: right;
|
||||
}
|
||||
|
||||
.ve-init-viewPageTarget-button {
|
||||
.ve-init-viewPageTarget-toolbar-saveButton {
|
||||
display: inline-block;
|
||||
border: solid 1px
|
||||
transparent;
|
||||
|
@ -47,40 +47,31 @@
|
|||
border: solid 1px transparent;
|
||||
}
|
||||
|
||||
.ve-init-viewPageTarget-button:before {
|
||||
.ve-init-viewPageTarget-toolbar-saveButton:before {
|
||||
content: " ";
|
||||
position: absolute;
|
||||
display: block;
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
.ve-init-viewPageTarget-button:hover {
|
||||
.ve-init-viewPageTarget-toolbar-saveButton:hover {
|
||||
border-color: #eeeeee;
|
||||
}
|
||||
|
||||
.ve-init-viewPageTarget-button:active,
|
||||
.ve-init-viewPageTarget-button-down {
|
||||
.ve-init-viewPageTarget-toolbar-saveButton:active,
|
||||
.ve-init-viewPageTarget-toolbar-saveButton-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);
|
||||
}
|
||||
|
||||
.ve-init-viewPageTarget-button-disabled {
|
||||
.ve-init-viewPageTarget-toolbar-saveButton-disabled {
|
||||
opacity: 0.5;
|
||||
-moz-opacity: 0.5;
|
||||
}
|
||||
|
||||
/* inspector styles */
|
||||
.ve-init-viewPageTarget-saveButton {
|
||||
border: 1px solid transparent;
|
||||
border-radius: 0.125em;
|
||||
-webkit-border-radius: 0.125em;
|
||||
-moz-border-radius: 0.125em;
|
||||
-o-border-radius: 0.125em;
|
||||
}
|
||||
|
||||
.ve-init-viewPageTarget-saveButton-icon {
|
||||
.ve-init-viewPageTarget-toolbar-saveButton-icon {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 32px;
|
||||
|
@ -91,7 +82,7 @@
|
|||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.ve-init-viewPageTarget-saveButton-label {
|
||||
.ve-init-viewPageTarget-toolbar-saveButton-label {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
height: 32px;
|
||||
|
@ -110,36 +101,39 @@
|
|||
|
||||
.ve-init-viewPageTarget-saveDialog-saveButton {
|
||||
position: absolute;
|
||||
border: 1px solid rgb(196,229,154);
|
||||
cursor: pointer;
|
||||
border: 1px solid #c3e59a;
|
||||
margin-top: 10px;
|
||||
right: 10px;
|
||||
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 */
|
||||
background-image: linear-gradient(bottom, rgb(195,229,154) 0%, rgb(240,251,225) 100%);
|
||||
background-image: -o-linear-gradient(bottom, rgb(195,229,154) 0%, rgb(240,251,225) 100%);
|
||||
background-image: -moz-linear-gradient(bottom, rgb(195,229,154) 0%, rgb(240,251,225) 100%);
|
||||
background-image: -webkit-linear-gradient(bottom, rgb(195,229,154) 0%, rgb(240,251,225) 100%);
|
||||
background-image: -ms-linear-gradient(bottom, rgb(195,229,154) 0%, rgb(240,251,225) 100%);
|
||||
background-image: linear-gradient(bottom, #c3e59a 0%, #f0fbe1 100%);
|
||||
background-image: -o-linear-gradient(bottom, #c3e59a 0%, #f0fbe1 100%);
|
||||
background-image: -moz-linear-gradient(bottom, #c3e59a 0%, #f0fbe1 100%);
|
||||
background-image: -webkit-linear-gradient(bottom, #c3e59a 0%, #f0fbe1 100%);
|
||||
background-image: -ms-linear-gradient(bottom, #c3e59a 0%, #f0fbe1 100%);
|
||||
background-image: -webkit-gradient(
|
||||
linear,
|
||||
left bottom,
|
||||
left top,
|
||||
color-stop(0, rgb(195,229,154)),
|
||||
color-stop(1, rgb(240,251,225))
|
||||
color-stop(0, #c3e59a),
|
||||
color-stop(1, #f0fbe1)
|
||||
);
|
||||
}
|
||||
|
||||
.ve-init-viewPageTarget-saveDialog-saveButton:hover {
|
||||
border-color: #a7cd76;
|
||||
}
|
||||
|
||||
.ve-init-viewPageTarget-saveDialog-saveButton-icon {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
height: 2em;
|
||||
width: 28px;
|
||||
margin-right: -4px;
|
||||
background: transparent;
|
||||
background-image: url(../../ui/styles/images/accept-clear.png);
|
||||
background-position: right top;
|
||||
|
@ -171,7 +165,7 @@
|
|||
}
|
||||
|
||||
.ve-init-viewPageTarget-saveDialog input[type='text'] {
|
||||
width: 96%;
|
||||
width: 98%;
|
||||
font-size: 12px;
|
||||
padding: 4px;
|
||||
margin: 10px 0;
|
||||
|
|
|
@ -11,34 +11,35 @@ ve.init.ViewPageTarget = function() {
|
|||
ve.init.Target.call( this, mw.config.get( 'wgPageName' ) );
|
||||
|
||||
// Properties
|
||||
this.$content = $( '#content' );
|
||||
this.$page = $( '#mw-content-text' );
|
||||
this.$view = $( '#bodyContent' );
|
||||
this.$toc = $( '#toc' );
|
||||
this.$heading = $( '#firstHeading' );
|
||||
this.$surface = $( '<div class="ve-surface"></div>' );
|
||||
this.$toolbar = null;
|
||||
this.$spinner = $( '<div class="ve-init-viewPageTarget-loadingSpinner"></div>' );
|
||||
this.$toolbarSaveButton = $( '<div class="ve-init-viewPageTarget-toolbar-saveButton"></div>' );
|
||||
this.$saveDialog = $( '<div class="es-inspector ve-init-viewPageTarget-saveDialog"></div>' );
|
||||
this.surface = null;
|
||||
this.active = false;
|
||||
this.edited = false;
|
||||
this.activating = false;
|
||||
this.deactivating = false;
|
||||
this.scrollTop = null;
|
||||
this.section = null;
|
||||
this.proxiedOnSurfaceModelTransact = ve.proxy( this.onSurfaceModelTransact, this );
|
||||
this.surfaceOptions = {
|
||||
'toolbars': {
|
||||
'top': {
|
||||
// If mobile device, float false
|
||||
'float': !this.isMobileDevice,
|
||||
// Toolbar modes
|
||||
'modes': ['wikitext']
|
||||
}
|
||||
}
|
||||
};
|
||||
this.surfaceOptions = { 'toolbars': { 'top': { 'float': !this.isMobileDevice } } };
|
||||
|
||||
// Events
|
||||
this.addListenerMethods( this, {
|
||||
'load': 'onLoad',
|
||||
'save': 'onSave',
|
||||
'loadError': 'onLoadError',
|
||||
'saveError': 'onSaveError'
|
||||
} );
|
||||
|
||||
// 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();
|
||||
this.setupSkinTabs();
|
||||
this.setupSectionEditLinks();
|
||||
this.setupToolbarSaveButton();
|
||||
this.setupSaveDialog();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -46,7 +47,6 @@ ve.init.ViewPageTarget = function() {
|
|||
|
||||
/*jshint multistr: true*/
|
||||
ve.init.ViewPageTarget.saveDialogTemplate = '\
|
||||
<div class="es-inspector ve-init-viewPageTarget-saveDialog">\
|
||||
<div class="es-inspector-title ve-init-viewPageTarget-saveDialog-title"></div>\
|
||||
<div class="es-inspector-button ve-init-viewPageTarget-saveDialog-closeButton"></div>\
|
||||
<div class="ve-init-viewPageTarget-saveDialog-body">\
|
||||
|
@ -72,103 +72,181 @@ ve.init.ViewPageTarget.saveDialogTemplate = '\
|
|||
</div>\
|
||||
<div class="ve-init-viewPageTarget-saveDialog-foot">\
|
||||
<p class="ve-init-viewPageTarget-saveDialog-license"></p>\
|
||||
</div>\
|
||||
</div>';
|
||||
</div>';
|
||||
|
||||
/* Methods */
|
||||
|
||||
/**
|
||||
* ...
|
||||
* Switches to edit mode.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.onEditTabClick = function( e, section ) {
|
||||
// Ignore multiple clicks while editor is active
|
||||
ve.init.ViewPageTarget.prototype.activate = function() {
|
||||
if ( !this.active && !this.activating ) {
|
||||
this.activating = true;
|
||||
// UI updates
|
||||
this.setSelectedTab( 'ca-edit' );
|
||||
// User interface changes
|
||||
this.transformSkinTabs();
|
||||
this.showSpinner();
|
||||
this.$toc.addClass( 've-init-viewPageTarget-pageToc' ).slideUp( 'fast' );
|
||||
// Remember scroll position
|
||||
var scrollTop = $( window ).scrollTop();
|
||||
// Asynchronous initialization - load ve modules at the same time as the content
|
||||
this.load( ve.proxy( function( error, dom ) {
|
||||
this.onLoad( error, dom );
|
||||
if ( section !== undefined ) {
|
||||
// HACK: All of this code is fragile, be careful and suspicious
|
||||
var $heading = this.$surface
|
||||
.find( '.ve-ce-documentNode' )
|
||||
.find( 'h1, h2, h3, h4, h5, h6' )
|
||||
.eq( section );
|
||||
surfaceView = this.surface.getView(),
|
||||
surfaceModel = surfaceView.getModel(),
|
||||
doc = surfaceModel.getDocument();
|
||||
if ( $heading.length ) {
|
||||
var offset = doc.getNearestContentOffset(
|
||||
$heading.data( 'node' ).getModel().getOffset()
|
||||
);
|
||||
surfaceModel.setSelection( new ve.Range( offset, offset ) );
|
||||
surfaceView.showSelection( surfaceModel.getSelection() );
|
||||
// Restore scroll position
|
||||
$( window ).scrollTop( scrollTop );
|
||||
}
|
||||
}
|
||||
}, this ) );
|
||||
this.hideTableOfContents();
|
||||
this.mutePageContent();
|
||||
this.mutePageTitle();
|
||||
this.saveScrollPosition();
|
||||
this.load();
|
||||
}
|
||||
// Prevent the edit tab's normal behavior
|
||||
e.preventDefault();
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* ...
|
||||
* Switches to view mode.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.onEditSectionLinkClick = function( e ) {
|
||||
var heading = $( e.target ).closest( 'h1, h2, h3, h4, h5, h6' )[0],
|
||||
tocHeading = this.$page.find( '#toc h2' )[0];
|
||||
section = 0;
|
||||
this.$page.find( 'h1, h2, h3, h4, h5, h6' ).each( function() {
|
||||
if ( this === heading ) {
|
||||
return false;
|
||||
}
|
||||
if ( this !== tocHeading ) {
|
||||
section++;
|
||||
}
|
||||
} );
|
||||
return this.onEditTabClick( e, section );
|
||||
};
|
||||
|
||||
/**
|
||||
* ...
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.onViewTabClick = function( e ) {
|
||||
// Don't do anything special unless we are in editing mode
|
||||
ve.init.ViewPageTarget.prototype.deactivate = function() {
|
||||
if ( this.active && !this.deactivating ) {
|
||||
this.deactivating = true;
|
||||
if (
|
||||
!this.surface.getModel().getHistory().length ||
|
||||
confirm( 'Are you sure you want to go back to view mode without saving first?' )
|
||||
) {
|
||||
this.deactivating = true;
|
||||
// User interface changes
|
||||
this.restoreSkinTabs();
|
||||
this.hideSpinner();
|
||||
this.detachToolbarSaveButton();
|
||||
this.detachSaveDialog();
|
||||
this.tearDownSurface();
|
||||
this.showTableOfContents();
|
||||
this.deactivating = false;
|
||||
}
|
||||
// Prevent the edit tab's normal behavior
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* ...
|
||||
* Handles successful DOM load event.
|
||||
*
|
||||
* @method
|
||||
* @param {HTMLElement} dom Parsed DOM from server
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.onSaveDialogSaveButtonClick = function( e ) {
|
||||
ve.init.ViewPageTarget.prototype.onLoad = function( dom ) {
|
||||
this.edited = false;
|
||||
this.setUpSurface( dom );
|
||||
this.attachToolbarSaveButton();
|
||||
this.attachSaveDialog();
|
||||
this.restoreScrollPosition();
|
||||
this.restoreEditSection();
|
||||
this.$surface.find( '.ve-ce-documentNode' ).focus();
|
||||
this.activating = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles failed DOM load event.
|
||||
*
|
||||
* @method
|
||||
* @param {Object} data HTTP Response object
|
||||
* @param {String} status Text status message
|
||||
* @param {Mixed} error Thrown exception or HTTP error string
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.onLoadError = function( response, status, error ) {
|
||||
// TODO: Something...
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles successful DOM save event.
|
||||
*
|
||||
* @method
|
||||
* @param {HTMLElement} html Rendered HTML from server
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.onSave = function( html ) {
|
||||
this.hideSaveDialog();
|
||||
this.replacePageContent( html );
|
||||
this.deactivate();
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles failed DOM save event.
|
||||
*
|
||||
* @method
|
||||
* @param {Object} data HTTP Response object
|
||||
* @param {String} status Text status message
|
||||
* @param {Mixed} error Thrown exception or HTTP error string
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.onSaveError = function( response, status, error ) {
|
||||
// TODO: Something...
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles clicks on the edit tab.
|
||||
*
|
||||
* @method
|
||||
* @param {Event} e DOM event
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.onEditTabClick = function( event ) {
|
||||
console.log( this );
|
||||
this.activate();
|
||||
// Prevent the edit tab's normal behavior
|
||||
event.preventDefault();
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles clicks on a section edit link.
|
||||
*
|
||||
* @method
|
||||
* @param {Event} event DOM event
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.onEditSectionLinkClick = function( event ) {
|
||||
this.saveEditingSection( $( event.target ).closest( 'h1, h2, h3, h4, h5, h6' )[0] );
|
||||
this.activate();
|
||||
// Prevent the edit tab's normal behavior
|
||||
event.preventDefault();
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles clicks on the view tab.
|
||||
*
|
||||
* @method
|
||||
* @param {Event} event DOM event
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.onViewTabClick = function( event ) {
|
||||
console.log( this );
|
||||
this.deactivate();
|
||||
// Prevent the edit tab's normal behavior
|
||||
event.preventDefault();
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles clicks on the save button in the toolbar.
|
||||
*
|
||||
* @method
|
||||
* @param {Event} event DOM event
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.onToolbarSaveButtonClick = function( event ) {
|
||||
if ( this.edited ) {
|
||||
this.showSaveDialog();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles the first transaction in the surface model.
|
||||
*
|
||||
* This handler is removed the first time it's used, but added each time the surface is setup.
|
||||
*
|
||||
* @method
|
||||
* @param {ve.Transaction} tx Processed transaction
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.onSurfaceModelTransact = function( tx ) {
|
||||
this.edited = true;
|
||||
this.enableToolbarSaveButton();
|
||||
this.surface.getModel().removeListener( 'transact', this.proxiedOnSurfaceModelTransact );
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles clicks on the save button in the save dialog.
|
||||
*
|
||||
* @method
|
||||
* @param {Event} event DOM event
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.onSaveDialogSaveButtonClick = function( event ) {
|
||||
this.showSpinner();
|
||||
// Save
|
||||
this.save(
|
||||
|
@ -183,183 +261,65 @@ ve.init.ViewPageTarget.prototype.onSaveDialogSaveButtonClick = function( e ) {
|
|||
};
|
||||
|
||||
/**
|
||||
* ...
|
||||
* Handles clicks on the close button in the save dialog.
|
||||
*
|
||||
* @method
|
||||
* @param {Event} event DOM event
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.onSurfaceModelTransact = function() {
|
||||
if ( !this.edited ) {
|
||||
this.edited = true;
|
||||
this.$toolbar.find( '.ve-init-viewPageTarget-saveButton ' )
|
||||
.removeClass( 've-init-viewPageTarget-button-disabled' );
|
||||
this.surface.getModel().removeListener( 'transact', this.proxiedOnSurfaceModelTransact );
|
||||
}
|
||||
ve.init.ViewPageTarget.prototype.onSaveDialogCloseButtonClick = function( event ) {
|
||||
this.hideSaveDialog();
|
||||
};
|
||||
|
||||
/**
|
||||
* ...
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.onSaveButtonClick = function( e ) {
|
||||
if ( this.edited ) {
|
||||
this.$dialog.fadeIn( 'fast' );
|
||||
this.$dialog.find( 'input:first' ).focus();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* ...
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.onSaveDialogCloseButtonClick = function( e ) {
|
||||
this.$dialog.fadeOut( 'fast' );
|
||||
this.$surface.find( '.ve-ce-documentNode' ).focus();
|
||||
};
|
||||
|
||||
/**
|
||||
* ...
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.onLoad = function( error, dom ) {
|
||||
this.activating = false;
|
||||
if ( error ) {
|
||||
// TODO: Error handling in the UI
|
||||
} else {
|
||||
this.edited = false;
|
||||
this.setUpSurface( dom );
|
||||
this.$surface.find( '.ve-ce-documentNode' ).focus();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* ...
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.onSave = function( error, content ) {
|
||||
if ( error ) {
|
||||
// TODO: Handle error in UI
|
||||
} else {
|
||||
// Hide the save dialog
|
||||
this.$dialog.fadeOut();
|
||||
// Refresh page with changed content
|
||||
this.$content.find( '#mw-content-text' ).html( content );
|
||||
// Restore the page to how it used to be
|
||||
this.tearDownSurface();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* ...
|
||||
* Switches to editing mode.
|
||||
*
|
||||
* @method
|
||||
* @param {HTMLElement} dom HTML DOM to edit
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.setUpSurface = function( dom ) {
|
||||
// Initialize surface
|
||||
this.$surface.appendTo( this.$content );
|
||||
this.attachSurface();
|
||||
this.surface = new ve.Surface( this.$surface, dom, this.surfaceOptions );
|
||||
this.surface.getModel().on( 'transact', this.proxiedOnSurfaceModelTransact );
|
||||
// Transplant the toolbar
|
||||
this.$toolbar = this.$surface.find( '.es-toolbar-wrapper' );
|
||||
this.$toolbar.find( '.es-toolbar' ).slideDown( 'fast' );
|
||||
this.$heading
|
||||
.before( this.$toolbar )
|
||||
.addClass( 've-init-viewPageTarget-pageTitle' )
|
||||
.fadeTo( 'fast', 0.5 );
|
||||
this.attachToolbar();
|
||||
this.transformPageTitle();
|
||||
// Update UI
|
||||
this.$view.hide();
|
||||
this.$spinner.remove();
|
||||
this.$dialog = $( ve.init.ViewPageTarget.saveDialogTemplate );
|
||||
// Add save and close buttons
|
||||
this.$toolbar
|
||||
.find( '.es-modes' )
|
||||
.append(
|
||||
$( '<div></div>' )
|
||||
.addClass(
|
||||
've-init-viewPageTarget-button ' +
|
||||
've-init-viewPageTarget-button-disabled ' +
|
||||
've-init-viewPageTarget-saveButton'
|
||||
)
|
||||
.append(
|
||||
$( '<span class="ve-init-viewPageTarget-saveButton-label"></span>' )
|
||||
.text( mw.msg( 'savearticle' ) )
|
||||
)
|
||||
.append( $( '<span class="ve-init-viewPageTarget-saveButton-icon"></span>' ) )
|
||||
.mousedown( function( e ) {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
} )
|
||||
.click( ve.proxy( this.onSaveButtonClick, this ) )
|
||||
);
|
||||
// Set up save dialog
|
||||
this.$dialog
|
||||
.find( '.ve-init-viewPageTarget-saveDialog-title' )
|
||||
.text( mw.msg( 'tooltip-save' ) )
|
||||
.end()
|
||||
.find( '.ve-init-viewPageTarget-saveDialog-closeButton' )
|
||||
.click( ve.proxy( this.onSaveDialogCloseButtonClick, this ) )
|
||||
.end()
|
||||
.find( '.ve-init-viewPageTarget-saveDialog-editSummary-label' )
|
||||
.text( mw.msg( 'summary' ) )
|
||||
.end()
|
||||
.find( '.ve-init-viewPageTarget-saveDialog-minorEdit-label' )
|
||||
.text( mw.msg( 'minoredit' ) )
|
||||
.end()
|
||||
.find( '.ve-init-viewPageTarget-saveDialog-watchList' )
|
||||
.prop( 'checked', ve.config.isPageWatched )
|
||||
.end()
|
||||
.find( '.ve-init-viewPageTarget-saveDialog-watchList-label' )
|
||||
.text( mw.msg( 'watchthis' ) )
|
||||
.end()
|
||||
.find( '.ve-init-viewPageTarget-saveDialog-saveButton' )
|
||||
.click( ve.proxy( this.onSaveDialogSaveButtonClick, this ) )
|
||||
.end()
|
||||
.find( '.ve-init-viewPageTarget-saveDialog-saveButton-label' )
|
||||
.text( mw.msg( 'savearticle' ) )
|
||||
.end()
|
||||
.find( '.ve-init-viewPageTarget-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-viewPageTarget-saveButton' ) );
|
||||
this.hidePageContent();
|
||||
this.hideSpinner();
|
||||
this.disableToolbarSaveButton();
|
||||
this.active = true;
|
||||
};
|
||||
|
||||
ve.init.ViewPageTarget.prototype.tearDownSurface = function( content ) {
|
||||
/**
|
||||
* Switches to viewing mode.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.tearDownSurface = function() {
|
||||
// Reset tabs
|
||||
this.setSelectedTab( 'ca-view' );
|
||||
this.restoreSkinTabs();
|
||||
// Update UI
|
||||
this.$surface.find( '.ve-ce-documentNode' ).blur();
|
||||
this.$surface.empty().detach();
|
||||
this.$toolbar.find( '.es-toolbar' ).slideUp( 'fast', function() {
|
||||
$(this).parent().remove();
|
||||
} );
|
||||
this.$spinner.remove();
|
||||
$( '.es-contextView' ).remove();
|
||||
this.$view.show().fadeTo( 'fast', 1 );
|
||||
this.$heading.fadeTo( 'fast', 1 );
|
||||
setTimeout( ve.proxy( function() {
|
||||
$(this).removeClass( 've-init-viewPageTarget-pageTitle' );
|
||||
}, this.$heading ), 1000 );
|
||||
this.$toc.slideDown( 'fast', function() {
|
||||
$(this).removeClass( 've-init-viewPageTarget-pageToc' );
|
||||
} );
|
||||
this.detachToolbar();
|
||||
this.hideSpinner();
|
||||
this.showPageContent();
|
||||
this.restorePageTitle();
|
||||
this.showTableOfContents();
|
||||
// Remove handler if it's still active
|
||||
this.surface.getModel().removeListener( 'transact', this.proxiedOnSurfaceModelTransact );
|
||||
// Destroy editor
|
||||
this.surface = null;
|
||||
this.active = false;
|
||||
};
|
||||
|
||||
ve.init.ViewPageTarget.prototype.setupTabs = function(){
|
||||
/**
|
||||
* Modifies tabs in the skin to support in-place editing.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.setupSkinTabs = 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
|
||||
|
@ -395,32 +355,401 @@ ve.init.ViewPageTarget.prototype.setupTabs = function(){
|
|||
);
|
||||
}
|
||||
$( '#ca-edit a' ).click( ve.proxy( this.onEditTabClick, this ) );
|
||||
$( '#mw-content-text .editsection a' ).click( ve.proxy( this.onEditSectionLinkClick, this ) );
|
||||
$( '#ca-view a' ).click( ve.proxy( this.onViewTabClick, this ) );
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows a loading spinner.
|
||||
* Modifies page content to make section edit links activate the editor.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.setupSectionEditLinks = function() {
|
||||
$( '#mw-content-text .editsection a' ).click( ve.proxy( this.onEditSectionLinkClick, this ) );
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds content and event bindings to the save button.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.setupToolbarSaveButton = function() {
|
||||
this.$toolbarSaveButton
|
||||
.append(
|
||||
$( '<span class="ve-init-viewPageTarget-toolbar-saveButton-label"></span>' )
|
||||
.text( mw.msg( 'savearticle' ) )
|
||||
)
|
||||
.append( $( '<span class="ve-init-viewPageTarget-toolbar-saveButton-icon"></span>' ) )
|
||||
.mousedown( function( e ) {
|
||||
$(this).addClass( 've-init-viewPageTarget-toolbar-saveButton-down' );
|
||||
e.preventDefault();
|
||||
return false;
|
||||
} )
|
||||
.mouseup( function( e ) {
|
||||
$(this).removeClass( 've-init-viewPageTarget-toolbar-saveButton-down' );
|
||||
e.preventDefault();
|
||||
return false;
|
||||
} )
|
||||
.click( ve.proxy( this.onToolbarSaveButtonClick, this ) );
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds the save button to the user interface.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.attachToolbarSaveButton = function() {
|
||||
$( '.es-toolbar .es-modes' ).append( this.$toolbarSaveButton );
|
||||
this.disableToolbarSaveButton();
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the save button from the user interface.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.detachToolbarSaveButton = function() {
|
||||
this.$toolbarSaveButton.detach();
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds content and event bindings to the save dialog.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.setupSaveDialog = function() {
|
||||
this.$saveDialog
|
||||
.html( ve.init.ViewPageTarget.saveDialogTemplate )
|
||||
.find( '.ve-init-viewPageTarget-saveDialog-title' )
|
||||
.text( mw.msg( 'tooltip-save' ) )
|
||||
.end()
|
||||
.find( '.ve-init-viewPageTarget-saveDialog-closeButton' )
|
||||
.click( ve.proxy( this.onSaveDialogCloseButtonClick, this ) )
|
||||
.end()
|
||||
.find( '.ve-init-viewPageTarget-saveDialog-editSummary-label' )
|
||||
.text( mw.msg( 'summary' ) )
|
||||
.end()
|
||||
.find( '.ve-init-viewPageTarget-saveDialog-minorEdit-label' )
|
||||
.text( mw.msg( 'minoredit' ) )
|
||||
.end()
|
||||
.find( '.ve-init-viewPageTarget-saveDialog-watchList' )
|
||||
.prop( 'checked', mw.config.get( 'wgVisualEditor' ).isPageWatched )
|
||||
.end()
|
||||
.find( '.ve-init-viewPageTarget-saveDialog-watchList-label' )
|
||||
.text( mw.msg( 'watchthis' ) )
|
||||
.end()
|
||||
.find( '.ve-init-viewPageTarget-saveDialog-saveButton' )
|
||||
.click( ve.proxy( this.onSaveDialogSaveButtonClick, this ) )
|
||||
.end()
|
||||
.find( '.ve-init-viewPageTarget-saveDialog-saveButton-label' )
|
||||
.text( mw.msg( 'savearticle' ) )
|
||||
.end()
|
||||
.find( '.ve-init-viewPageTarget-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>"
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds the save dialog to the user interface.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.attachSaveDialog = function() {
|
||||
this.$saveDialog.insertAfter( this.$toolbarSaveButton );
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes the save dialog from the user interface.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.detachSaveDialog = function() {
|
||||
this.$saveDialog.detach();
|
||||
};
|
||||
|
||||
/**
|
||||
* Remembers the window's scroll position.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.saveScrollPosition = function() {
|
||||
this.scrollTop = $( window ).scrollTop();
|
||||
};
|
||||
|
||||
/**
|
||||
* Restores the window's scroll position.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.restoreScrollPosition = function() {
|
||||
if ( this.scrollTop ) {
|
||||
$( window ).scrollTop( this.scrollTop );
|
||||
this.scrollTop = null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows the loading spinner.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.showSpinner = function() {
|
||||
this.$spinner = $( '<div></div>' )
|
||||
.addClass( 've-init-viewPageTarget-loadingSpinner' )
|
||||
.prependTo( this.$heading );
|
||||
this.$spinner.prependTo( $( '#firstHeading' ) );
|
||||
};
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* Hides the loading spinner.
|
||||
*
|
||||
* @method
|
||||
* @param {String} id HTML ID of tab to select
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.setSelectedTab = function( id ) {
|
||||
ve.init.ViewPageTarget.prototype.hideSpinner = function() {
|
||||
this.$spinner.detach();
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows the page content.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.showPageContent = function() {
|
||||
$( '#bodyContent' ).children().not( '#siteSub' ).show().fadeTo( 0, 1 );
|
||||
};
|
||||
|
||||
/**
|
||||
* Mutes the page content.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.mutePageContent = function() {
|
||||
$( '#bodyContent' ).children().not( '#siteSub' ).fadeTo( 'fast', 0.25 );
|
||||
};
|
||||
|
||||
/**
|
||||
* Hides the page content.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.hidePageContent = function() {
|
||||
$( '#bodyContent' ).children().not( '#siteSub' ).hide();
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows the table of contents in the view mode.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.showTableOfContents = function() {
|
||||
$( '#toc' ).slideDown( 'fast', function() {
|
||||
$(this).removeClass( 've-init-viewPageTarget-pageToc' );
|
||||
} );
|
||||
};
|
||||
|
||||
/**
|
||||
* Hides the table of contents in the view mode.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.hideTableOfContents = function() {
|
||||
$( '#toc' ).addClass( 've-init-viewPageTarget-pageToc' ).slideUp( 'fast' );
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows the save dialog.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.showSaveDialog = function() {
|
||||
this.$saveDialog.fadeIn( 'fast' ).find( 'input:first' ).focus();
|
||||
};
|
||||
|
||||
/**
|
||||
* Hides the save dialog
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.hideSaveDialog = function() {
|
||||
this.$saveDialog.fadeOut( 'fast' );
|
||||
this.$surface.find( '.ve-ce-documentNode' ).focus();
|
||||
};
|
||||
|
||||
/**
|
||||
* Enables the toolbar save button.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.enableToolbarSaveButton = function() {
|
||||
this.$toolbarSaveButton.removeClass( 've-init-viewPageTarget-toolbar-saveButton-disabled' );
|
||||
};
|
||||
|
||||
/**
|
||||
* Disables the toolbar save button.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.disableToolbarSaveButton = function() {
|
||||
this.$toolbarSaveButton.addClass( 've-init-viewPageTarget-toolbar-saveButton-disabled' );
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows the toolbar.
|
||||
*
|
||||
* This also transplants the toolbar to a new location.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.attachToolbar = function() {
|
||||
$( '.es-toolbar-wrapper' )
|
||||
.insertBefore( $( '#firstHeading' ) )
|
||||
.find( '.es-toolbar' )
|
||||
.slideDown( 'fast' );
|
||||
};
|
||||
|
||||
/**
|
||||
* Hides the toolbar.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.detachToolbar = function() {
|
||||
$( '.es-toolbar' ).slideUp( 'fast', function() {
|
||||
$(this).parent().remove();
|
||||
} );
|
||||
};
|
||||
|
||||
/**
|
||||
* Enables the toolbar save button.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.transformPageTitle = function() {
|
||||
$( '#firstHeading' ).addClass( 've-init-viewPageTarget-pageTitle' );
|
||||
};
|
||||
|
||||
/**
|
||||
* Enables the toolbar save button.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.mutePageTitle = function() {
|
||||
$( '#firstHeading' ).fadeTo( 'fast', 0.25 );
|
||||
$( '#siteSub' ).fadeTo( 'fast', 0.25 );
|
||||
};
|
||||
|
||||
/**
|
||||
* Disables the toolbar save button.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.restorePageTitle = function() {
|
||||
$( '#firstHeading' ).fadeTo( 'fast', 1 );
|
||||
$( '#siteSub' ).fadeTo( 'fast', 1 );
|
||||
setTimeout( function() {
|
||||
$( '#firstHeading' ).removeClass( 've-init-viewPageTarget-pageTitle' );
|
||||
}, 1000 );
|
||||
};
|
||||
|
||||
/**
|
||||
* Modifies page tabs to show that editing is taking place.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.transformSkinTabs = function() {
|
||||
$( '#p-views' ).find( 'li.selected' ).removeClass( 'selected' );
|
||||
$( '#' + id ).addClass( 'selected' );
|
||||
$( '#ca-edit' ).addClass( 'selected' );
|
||||
};
|
||||
|
||||
/**
|
||||
* Modifies page tabs to show that viewing is taking place.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.restoreSkinTabs = function() {
|
||||
$( '#p-views' ).find( 'li.selected' ).removeClass( 'selected' );
|
||||
$( '#ca-view' ).addClass( 'selected' );
|
||||
};
|
||||
|
||||
/**
|
||||
* Replaces the page content with new HTML.
|
||||
*
|
||||
* @method
|
||||
* @param {HTMLElement} html Rendered HTML from server
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.replacePageContent = function( html ) {
|
||||
$( '#mw-content-text' ).html( html );
|
||||
};
|
||||
|
||||
/**
|
||||
* Attaches the surface to the page.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.attachSurface = function() {
|
||||
$( '#content' ).append( this.$surface );
|
||||
};
|
||||
|
||||
/**
|
||||
* Attaches the surface to the page.
|
||||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.detachSurface = function() {
|
||||
this.$surface.detach();
|
||||
$( '.es-contextView' ).remove();
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the numeric index of a section in the page.
|
||||
*
|
||||
* @method
|
||||
* @param {HTMLElement} heading Heading element of section
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.saveEditSection = function( heading ) {
|
||||
var $page = $( '#mw-content-text' );
|
||||
tocHeading = $page.find( '#toc h2' )[0];
|
||||
section = 0;
|
||||
$page.find( 'h1, h2, h3, h4, h5, h6' ).each( function() {
|
||||
if ( this === heading ) {
|
||||
return false;
|
||||
}
|
||||
if ( this !== tocHeading ) {
|
||||
section++;
|
||||
}
|
||||
} );
|
||||
this.section = section;
|
||||
};
|
||||
|
||||
/**
|
||||
* Moves the cursor in the editor to a given section.
|
||||
*
|
||||
* @method
|
||||
* @param {Number} section Section to move cursor to
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.restoreEditSection = function() {
|
||||
if ( this.section ) {
|
||||
var surfaceView = this.surface.getView(),
|
||||
surfaceModel = surfaceView.getModel();
|
||||
this.$surface
|
||||
.find( '.ve-ce-documentNode' )
|
||||
.find( 'h1, h2, h3, h4, h5, h6' )
|
||||
.eq( this.section )
|
||||
.each( function() {
|
||||
var headingNode = $(this).data( 'node' );
|
||||
if ( headingNode ) {
|
||||
var offset = surfaceModel.getDocument().getNearestContentOffset(
|
||||
headingNode.getModel().getOffset()
|
||||
);
|
||||
surfaceModel.setSelection( new ve.Range( offset, offset ) );
|
||||
surfaceView.showSelection( surfaceModel.getSelection() );
|
||||
}
|
||||
} );
|
||||
this.section = null;
|
||||
}
|
||||
};
|
||||
|
||||
/* Inheritance */
|
||||
|
@ -429,7 +758,4 @@ ve.extendClass( ve.init.ViewPageTarget, ve.init.Target );
|
|||
|
||||
/* Initialization */
|
||||
|
||||
// TODO: Clean this stuff up
|
||||
|
||||
ve.config = mw.config.get( 'wgVisualEditor' );
|
||||
ve.init.current = new ve.init.ViewPageTarget();
|
||||
ve.init.viewPageTarget = new ve.init.ViewPageTarget();
|
||||
|
|
|
@ -6,19 +6,129 @@
|
|||
* @param {String} title Page title of target
|
||||
*/
|
||||
ve.init.Target = function( title ) {
|
||||
// Inheritance
|
||||
ve.EventEmitter.call( this );
|
||||
|
||||
// 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.loading = false;
|
||||
this.saving = false;
|
||||
this.dom = null;
|
||||
this.isMobileDevice = (
|
||||
'ontouchstart' in window ||
|
||||
( window.DocumentTouch && document instanceof DocumentTouch )
|
||||
);
|
||||
};
|
||||
|
||||
/* Static Methods */
|
||||
|
||||
/**
|
||||
* Handle response to a successful load request.
|
||||
*
|
||||
* This method is called within the context of a target instance. If successful the DOM from the
|
||||
* server will be parsed, stored in {this.dom} and then {ve.init.Target.onReady} will be called once
|
||||
* the modules are ready.
|
||||
*
|
||||
* @static
|
||||
* @method
|
||||
* @param {Object} response XHR Response object
|
||||
* @param {String} status Text status message
|
||||
* @emits loadError (message)
|
||||
*/
|
||||
ve.init.Target.onLoad = function( response, status ) {
|
||||
var data = response['ve-parsoid'];
|
||||
if ( !data ) {
|
||||
this.loading = false;
|
||||
this.emit( 'loadError', 'Invalid response from server' );
|
||||
} else if ( typeof data.parsed !== 'string' ) {
|
||||
this.loading = false;
|
||||
this.emit( 'loadError', 'Invalid HTML content in response from server' );
|
||||
} else {
|
||||
this.dom = $( '<div></div>' ).html( data.parsed )[0];
|
||||
// Everything worked, the page was loaded, continue as soon as the module is ready
|
||||
mw.loader.using( this.modules, ve.proxy( ve.init.Target.onReady, this ) );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle both DOM and modules being loaded and ready.
|
||||
*
|
||||
* This method is called within the context of a target instance. After the load event is emitted
|
||||
* this.dom is cleared, allowing it to be garbage collected.
|
||||
*
|
||||
* @static
|
||||
* @method
|
||||
* @emits load (dom)
|
||||
*/
|
||||
ve.init.Target.onReady = function() {
|
||||
this.loading = false;
|
||||
this.emit( 'load', this.dom );
|
||||
// Release DOM data
|
||||
this.dom = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle response to a successful load request.
|
||||
*
|
||||
* This method is called within the context of a target instance.
|
||||
*
|
||||
* @static
|
||||
* @method
|
||||
* @param {Object} response XHR Response object
|
||||
* @param {String} status Text status message
|
||||
* @param {Mixed} error Thrown exception or HTTP error string
|
||||
* @emits load (dom)
|
||||
*/
|
||||
ve.init.Target.onLoadError = function( response, text, exception ) {
|
||||
this.loading = false;
|
||||
this.emit( 'loadError', response, text, exception );
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle response to a successful save request.
|
||||
*
|
||||
* This method is called within the context of a target instance.
|
||||
*
|
||||
* @static
|
||||
* @method
|
||||
* @param {Object} response XHR Response object
|
||||
* @param {String} status Text status message
|
||||
* @emits save (html)
|
||||
*/
|
||||
ve.init.Target.onSave = function( response, status ) {
|
||||
this.saving = false;
|
||||
var data = response['ve-parsoid'];
|
||||
if ( !response ) {
|
||||
this.emit( 'saveError', 'Invalid response from server' );
|
||||
} else if ( data.result !== 'success' ) {
|
||||
this.emit( 'saveError', 'Unsuccessful request: ' + data.result );
|
||||
} else if ( typeof data.content !== 'string' ) {
|
||||
this.emit( 'saveError', 'Invalid HTML content in response from server' );
|
||||
} else {
|
||||
this.emit( 'save', data.content );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle response to a successful save request.
|
||||
*
|
||||
* This method is called within the context of a target instance.
|
||||
*
|
||||
* @static
|
||||
* @method
|
||||
* @param {Object} data HTTP Response object
|
||||
* @param {String} status Text status message
|
||||
* @param {Mixed} error Thrown exception or HTTP error string
|
||||
* @emits save (html)
|
||||
*/
|
||||
ve.init.Target.onSaveError = function( response, status, error ) {
|
||||
this.saving = false;
|
||||
this.emit( 'saveError', response, status, error );
|
||||
};
|
||||
|
||||
/* Methods */
|
||||
|
||||
/**
|
||||
|
@ -39,13 +149,13 @@ ve.init.Target = function( title ) {
|
|||
*/
|
||||
ve.init.Target.prototype.load = function( callback ) {
|
||||
// Prevent duplicate requests
|
||||
if ( this.isDomLoading ) {
|
||||
if ( this.loading ) {
|
||||
return false;
|
||||
}
|
||||
// Start loading the module immediately
|
||||
mw.loader.load( this.modules );
|
||||
// Load DOM
|
||||
this.isDomLoading = true;
|
||||
this.loading = true;
|
||||
$.ajax( {
|
||||
'url': this.apiUrl,
|
||||
'data': {
|
||||
|
@ -59,21 +169,8 @@ ve.init.Target.prototype.load = function( callback ) {
|
|||
'cache': 'false',
|
||||
// Wait up to 9 seconds
|
||||
'timeout': 9000,
|
||||
'error': callback,
|
||||
'success': ve.proxy( 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( this.modules, function() {
|
||||
callback( null, $( '<div></div>' ).html( data['ve-parsoid'].parsed )[0] );
|
||||
} );
|
||||
}
|
||||
}, this )
|
||||
'error': ve.proxy( ve.init.Target.onLoadError, this ),
|
||||
'success': ve.proxy( ve.init.Target.onLoad, this )
|
||||
} );
|
||||
return true;
|
||||
};
|
||||
|
@ -103,11 +200,11 @@ ve.init.Target.prototype.load = function( callback ) {
|
|||
*/
|
||||
ve.init.Target.prototype.save = function( dom, options, callback ) {
|
||||
// Prevent duplicate requests
|
||||
if ( this.isDomSaving ) {
|
||||
if ( this.saving ) {
|
||||
return false;
|
||||
}
|
||||
// Save DOM
|
||||
this.isDomSaving = true;
|
||||
this.saving = true;
|
||||
$.ajax( {
|
||||
'url': this.apiUrl,
|
||||
'data': {
|
||||
|
@ -123,21 +220,12 @@ ve.init.Target.prototype.save = function( dom, options, callback ) {
|
|||
},
|
||||
'dataType': 'json',
|
||||
'type': 'POST',
|
||||
'error': callback,
|
||||
'success': ve.proxy( 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 );
|
||||
}
|
||||
}, this )
|
||||
'error': ve.proxy( ve.init.Target.onSaveError, this ),
|
||||
'success': ve.proxy( ve.init.Target.onSave, this )
|
||||
} );
|
||||
return true;
|
||||
};
|
||||
|
||||
/* Inheritance */
|
||||
|
||||
ve.extendClass( ve.init.Target, ve.EventEmitter );
|
||||
|
|
Loading…
Reference in a new issue