Files
edx-platform/cms/static/js/views/modals/edit_xblock.js
2016-08-08 15:04:06 -04:00

230 lines
9.4 KiB
JavaScript

/**
* The EditXBlockModal is a Backbone view that shows an xblock editor in a modal window.
* It is invoked using the edit method which is passed an existing rendered xblock,
* and upon save an optional refresh function can be invoked to update the display.
*/
define(['jquery', 'underscore', 'gettext', 'js/views/modals/base_modal', 'common/js/components/utils/view_utils',
'js/models/xblock_info', 'js/views/xblock_editor'],
function($, _, gettext, BaseModal, ViewUtils, XBlockInfo, XBlockEditorView) {
'strict mode';
var EditXBlockModal = BaseModal.extend({
events: _.extend({}, BaseModal.prototype.events, {
'click .action-save': 'save',
'click .action-modes a': 'changeMode'
}),
options: $.extend({}, BaseModal.prototype.options, {
modalName: 'edit-xblock',
addSaveButton: true,
view: 'studio_view',
viewSpecificClasses: 'modal-editor confirm',
// Translators: "title" is the name of the current component being edited.
titleFormat: gettext('Editing: %(title)s')
}),
initialize: function() {
BaseModal.prototype.initialize.call(this);
this.template = this.loadTemplate('edit-xblock-modal');
this.editorModeButtonTemplate = this.loadTemplate('editor-mode-button');
},
/**
* Show an edit modal for the specified xblock
* @param xblockElement The element that contains the xblock to be edited.
* @param rootXBlockInfo An XBlockInfo model that describes the root xblock on the page.
* @param options A standard options object.
*/
edit: function(xblockElement, rootXBlockInfo, options) {
this.xblockElement = xblockElement;
this.xblockInfo = this.findXBlockInfo(xblockElement, rootXBlockInfo);
this.options.modalType = this.xblockInfo.get('category');
this.editOptions = options;
this.render();
this.show();
// Hide the action bar until we know which buttons we want
this.getActionBar().hide();
// Display the xblock after the modal is shown as there are some xblocks
// that depend upon being visible when they initialize, e.g. the problem xmodule.
this.displayXBlock();
},
getContentHtml: function() {
return this.template({
xblockInfo: this.xblockInfo
});
},
displayXBlock: function() {
this.editorView = new XBlockEditorView({
el: this.$('.xblock-editor'),
model: this.xblockInfo,
view: this.options.view
});
this.editorView.render({
success: _.bind(this.onDisplayXBlock, this)
});
},
onDisplayXBlock: function() {
var editorView = this.editorView,
title = this.getTitle(),
readOnlyView = (this.editOptions && this.editOptions.readOnlyView) || !this.canSave();
// Notify the runtime that the modal has been shown
editorView.notifyRuntime('modal-shown', this);
// Update the modal's header
if (editorView.hasCustomTabs()) {
// Hide the modal's header as the custom editor provides its own
this.$('.modal-header').hide();
// Update the custom editor's title
editorView.$('.component-name').text(title);
} else {
this.$('.modal-window-title').text(title);
if (editorView.getDataEditor() && editorView.getMetadataEditor()) {
this.addDefaultModes();
this.selectMode(editorView.mode);
}
}
// If the xblock is not using custom buttons then choose which buttons to show
if (!editorView.hasCustomButtons()) {
// If the xblock does not support save then disable the save button
if (readOnlyView) {
this.disableSave();
}
this.getActionBar().show();
}
// Resize the modal to fit the window
this.resize();
},
canSave: function() {
return this.editorView.xblock.save || this.editorView.xblock.collectFieldData;
},
disableSave: function() {
var saveButton = this.getActionButton('save'),
cancelButton = this.getActionButton('cancel');
saveButton.parent().hide();
cancelButton.text(gettext('Close'));
cancelButton.addClass('action-primary');
},
getTitle: function() {
var displayName = this.xblockInfo.get('display_name');
if (!displayName) {
displayName = gettext('Component');
}
return interpolate(this.options.titleFormat, {title: displayName}, true);
},
addDefaultModes: function() {
var defaultModes, i, mode;
defaultModes = this.editorView.getDefaultModes();
for (i = 0; i < defaultModes.length; i++) {
mode = defaultModes[i];
this.addModeButton(mode.id, mode.name);
}
},
changeMode: function(event) {
this.removeCheatsheetVisibility();
var parent = $(event.target.parentElement),
mode = parent.data('mode');
event.preventDefault();
this.selectMode(mode);
},
selectMode: function(mode) {
var editorView = this.editorView,
buttonSelector;
editorView.selectMode(mode);
this.$('.editor-modes a').removeClass('is-set');
if (mode) {
buttonSelector = '.' + mode + '-button';
this.$(buttonSelector).addClass('is-set');
}
},
save: function(event) {
var self = this,
editorView = this.editorView,
xblockInfo = this.xblockInfo,
data = editorView.getXBlockFieldData();
event.preventDefault();
if (data) {
ViewUtils.runOperationShowingMessage(gettext('Saving'),
function() {
return xblockInfo.save(data);
}).done(function() {
self.onSave();
});
}
},
onSave: function() {
var refresh = this.editOptions.refresh;
this.hide();
if (refresh) {
refresh(this.xblockInfo);
}
},
hide: function() {
BaseModal.prototype.hide.call(this);
// Notify the runtime that the modal has been hidden
this.editorView.notifyRuntime('modal-hidden');
},
findXBlockInfo: function(xblockWrapperElement, defaultXBlockInfo) {
var xblockInfo = defaultXBlockInfo,
xblockElement,
displayName;
if (xblockWrapperElement.length > 0) {
xblockElement = xblockWrapperElement.find('.xblock');
displayName = xblockWrapperElement.find('.xblock-header .header-details .xblock-display-name').text().trim();
// If not found, try looking for the old unit page style rendering.
// Only used now by static pages.
if (!displayName) {
displayName = this.xblockElement.find('.component-header').text().trim();
}
xblockInfo = new XBlockInfo({
id: xblockWrapperElement.data('locator'),
courseKey: xblockWrapperElement.data('course-key'),
category: xblockElement.data('block-type'),
display_name: displayName
});
}
return xblockInfo;
},
addModeButton: function(mode, displayName) {
var buttonPanel = this.$('.editor-modes');
buttonPanel.append(this.editorModeButtonTemplate({
mode: mode,
displayName: displayName
}));
},
removeCheatsheetVisibility: function() {
var cheatsheet = $('article.simple-editor-open-ended-cheatsheet');
if (cheatsheet.length === 0) {
cheatsheet = $('article.simple-editor-cheatsheet');
}
if (cheatsheet.hasClass('shown')) {
cheatsheet.removeClass('shown');
$('.modal-content').removeClass('cheatsheet-is-shown');
}
}
});
return EditXBlockModal;
});