182 lines
6.8 KiB
JavaScript
182 lines
6.8 KiB
JavaScript
/**
|
|
* XBlockEditorView displays the authoring view of an xblock, and allows the user to switch between
|
|
* the available modes.
|
|
*/
|
|
define(['jquery', 'underscore', 'gettext', 'js/views/baseview', 'js/views/xblock', 'js/views/metadata', 'js/collections/metadata',
|
|
'jquery.inputnumber'],
|
|
function($, _, gettext, BaseView, XBlockView, MetadataView, MetadataCollection) {
|
|
var XBlockEditorView = XBlockView.extend({
|
|
// takes XBlockInfo as a model
|
|
|
|
options: $.extend({}, XBlockView.prototype.options, {
|
|
view: 'studio_view'
|
|
}),
|
|
|
|
initialize: function() {
|
|
XBlockView.prototype.initialize.call(this);
|
|
this.view = this.options.view;
|
|
},
|
|
|
|
xblockReady: function(xblock) {
|
|
XBlockView.prototype.xblockReady.call(this, xblock);
|
|
this.initializeEditors();
|
|
},
|
|
|
|
initializeEditors: function() {
|
|
var metadataEditor,
|
|
pluginEl,
|
|
defaultMode = 'editor';
|
|
metadataEditor = this.createMetadataEditor();
|
|
this.metadataEditor = metadataEditor;
|
|
if (!this.hasCustomTabs()) {
|
|
if (this.getDataEditor()) {
|
|
defaultMode = 'editor';
|
|
} else if (metadataEditor) {
|
|
defaultMode = 'settings';
|
|
}
|
|
this.selectMode(defaultMode);
|
|
}
|
|
pluginEl = this.$('.wrapper-comp-plugins');
|
|
if (pluginEl.length > 0) {
|
|
this.pluginEditor = new BaseView({
|
|
el: pluginEl
|
|
});
|
|
}
|
|
},
|
|
|
|
getDefaultModes: function() {
|
|
return [
|
|
{id: 'editor', name: gettext('Editor')},
|
|
{id: 'settings', name: gettext('Settings')}
|
|
];
|
|
},
|
|
|
|
hasCustomTabs: function() {
|
|
return this.$('.editor-with-tabs').length > 0;
|
|
},
|
|
|
|
hasCustomButtons: function() {
|
|
return this.$('.editor-with-buttons').length > 0;
|
|
},
|
|
|
|
createMetadataEditor: function() {
|
|
var metadataEditor,
|
|
metadataData,
|
|
models = [],
|
|
key,
|
|
xblock = this.xblock,
|
|
metadataView = null;
|
|
metadataEditor = this.$('.metadata_edit');
|
|
if (metadataEditor.length === 1) {
|
|
metadataData = metadataEditor.data('metadata');
|
|
for (key in metadataData) {
|
|
if (metadataData.hasOwnProperty(key)) {
|
|
models.push(metadataData[key]);
|
|
}
|
|
}
|
|
metadataView = new MetadataView.Editor({
|
|
el: metadataEditor,
|
|
collection: new MetadataCollection(models)
|
|
});
|
|
if (xblock && xblock.setMetadataEditor) {
|
|
xblock.setMetadataEditor(metadataView);
|
|
}
|
|
}
|
|
return metadataView;
|
|
},
|
|
|
|
getDataEditor: function() {
|
|
var editor = this.$('.wrapper-comp-editor');
|
|
return editor.length === 1 ? editor : null;
|
|
},
|
|
|
|
getMetadataEditor: function() {
|
|
return this.metadataEditor;
|
|
},
|
|
|
|
getPluginEditor: function() {
|
|
return this.pluginEditor;
|
|
},
|
|
|
|
/**
|
|
* Returns the updated field data for the xblock. Note that this works for all
|
|
* XModules as well as for XBlocks that provide a 'collectFieldData' API.
|
|
*/
|
|
getXBlockFieldData: function() {
|
|
var xblock = this.xblock,
|
|
metadataEditor = this.getMetadataEditor(),
|
|
data = null;
|
|
// If the xblock supports returning its field data then collect it
|
|
if (xblock.collectFieldData) {
|
|
data = xblock.collectFieldData();
|
|
// ... else if this is an XModule then call its save method
|
|
} else if (xblock.save) {
|
|
data = xblock.save();
|
|
if (metadataEditor) {
|
|
data.metadata = _.extend(data.metadata || {}, this.getChangedMetadata());
|
|
}
|
|
// ... else log an error
|
|
} else {
|
|
console.error('Cannot save xblock as it has no save method');
|
|
}
|
|
return data;
|
|
},
|
|
|
|
/**
|
|
* Returns the metadata that has changed in the editor. This is a combination of the metadata
|
|
* modified in the "Settings" editor, as well as any custom metadata provided by the component.
|
|
* Set `replaceNullWithDefault` to true to replace null values with the default values.
|
|
*/
|
|
getChangedMetadata: function(replaceNullWithDefault = false) {
|
|
var metadataEditor = this.getMetadataEditor();
|
|
return _.extend(metadataEditor.getModifiedMetadataValues(replaceNullWithDefault), this.getCustomMetadata());
|
|
},
|
|
|
|
/**
|
|
* Returns custom metadata defined by a particular xmodule that aren't part of the metadata editor.
|
|
* In particular, this is used for LaTeX high level source.
|
|
*/
|
|
getCustomMetadata: function() {
|
|
// Walk through the set of elements which have the 'data-metadata_name' attribute and
|
|
// build up an object to pass back to the server on the subsequent POST.
|
|
// Note that these values will always be sent back on POST, even if they did not actually change.
|
|
var metadata, metadataNameElements, i, element, metadataName;
|
|
metadata = {};
|
|
metadataNameElements = this.$('[data-metadata-name]');
|
|
for (i = 0; i < metadataNameElements.length; i++) {
|
|
element = metadataNameElements[i];
|
|
metadataName = $(element).data('metadata-name');
|
|
metadata[metadataName] = element.value;
|
|
}
|
|
return metadata;
|
|
},
|
|
|
|
getMode: function() {
|
|
return this.mode;
|
|
},
|
|
|
|
selectMode: function(mode) {
|
|
var dataEditor = this.getDataEditor(),
|
|
metadataEditor = this.getMetadataEditor(),
|
|
pluginEditor = this.getPluginEditor();
|
|
if (dataEditor) {
|
|
this.setEditorActivation(dataEditor, mode === 'editor');
|
|
}
|
|
if (metadataEditor) {
|
|
this.setEditorActivation(metadataEditor.$el, mode === 'settings');
|
|
}
|
|
if (pluginEditor) {
|
|
this.setEditorActivation(pluginEditor.$el, mode === 'plugins');
|
|
}
|
|
this.mode = mode;
|
|
},
|
|
|
|
setEditorActivation: function(editor, isActive) {
|
|
editor.removeClass('is-active').removeClass('is-inactive');
|
|
editor.addClass(isActive ? 'is-active' : 'is-inactive');
|
|
}
|
|
});
|
|
|
|
return XBlockEditorView;
|
|
}); // end define();
|