TNL-6920 Component Editor Efficiency Improvements
* Enlarges component modal for easier editing * Allows display name to be edited in place * Improves markdown button labeling * Moves markdown cheatsheet to the edit modal, for quick reference
This commit is contained in:
@@ -48,7 +48,8 @@ CONTAINER_TEMPLATES = [
|
||||
"add-xblock-component", "add-xblock-component-button", "add-xblock-component-menu",
|
||||
"add-xblock-component-support-legend", "add-xblock-component-support-level", "add-xblock-component-menu-problem",
|
||||
"xblock-string-field-editor", "xblock-access-editor", "publish-xblock", "publish-history",
|
||||
"unit-outline", "container-message", "container-access", "license-selector",
|
||||
"unit-outline", "container-message", "container-access", "license-selector", "copy-clipboard-button",
|
||||
"edit-title-button",
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ describe('EditXBlockModal', function() {
|
||||
it('shows the correct title', function() {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
modal = showModal(requests, mockXBlockEditorHtml);
|
||||
expect(modal.$('.modal-window-title').text()).toBe('Editing: Component');
|
||||
expect(modal.$('.modal-window-title span.modal-button-title').text()).toBe('Editing: Component');
|
||||
});
|
||||
|
||||
it('does not show any editor mode buttons', function() {
|
||||
@@ -134,7 +134,7 @@ describe('EditXBlockModal', function() {
|
||||
it('shows the correct title', function() {
|
||||
var requests = AjaxHelpers.requests(this);
|
||||
modal = showModal(requests, mockXModuleEditorHtml);
|
||||
expect(modal.$('.modal-window-title').text()).toBe('Editing: Component');
|
||||
expect(modal.$('.modal-window-title span.modal-button-title').text()).toBe('Editing: Component');
|
||||
});
|
||||
|
||||
it('shows the correct default buttons', function() {
|
||||
|
||||
@@ -90,6 +90,7 @@ installEditTemplates = function(append) {
|
||||
// Add templates needed by the edit XBlock modal
|
||||
TemplateHelpers.installTemplate('edit-xblock-modal');
|
||||
TemplateHelpers.installTemplate('editor-mode-button');
|
||||
TemplateHelpers.installTemplate('edit-title-button');
|
||||
|
||||
// Add templates needed by the settings editor
|
||||
TemplateHelpers.installTemplate('metadata-editor');
|
||||
|
||||
@@ -29,7 +29,7 @@ define(['jquery', 'common/js/spec_helpers/template_helpers', 'common/js/spec_hel
|
||||
|
||||
getModalTitle = function(modal) {
|
||||
var modalElement = getModalElement(modal);
|
||||
return modalElement.find('.modal-window-title').text();
|
||||
return modalElement.find('.modal-window-title span.modal-button-title').text();
|
||||
};
|
||||
|
||||
isShowingModal = function(modal) {
|
||||
|
||||
@@ -63,6 +63,7 @@ define(['jquery', 'underscore', 'gettext', 'js/views/baseview'],
|
||||
},
|
||||
|
||||
render: function() {
|
||||
// xss-lint: disable=javascript-jquery-html
|
||||
this.$el.html(this.modalTemplate({
|
||||
name: this.options.modalName,
|
||||
type: this.options.modalType,
|
||||
@@ -83,6 +84,7 @@ define(['jquery', 'underscore', 'gettext', 'js/views/baseview'],
|
||||
|
||||
renderContents: function() {
|
||||
var contentHtml = this.getContentHtml();
|
||||
// xss-lint: disable=javascript-jquery-html
|
||||
this.$('.modal-content').html(contentHtml);
|
||||
},
|
||||
|
||||
@@ -146,6 +148,7 @@ define(['jquery', 'underscore', 'gettext', 'js/views/baseview'],
|
||||
name: name,
|
||||
isPrimary: isPrimary
|
||||
});
|
||||
// xss-lint: disable=javascript-jquery-append
|
||||
this.getActionBar().find('ul').append(html);
|
||||
},
|
||||
|
||||
@@ -178,8 +181,8 @@ define(['jquery', 'underscore', 'gettext', 'js/views/baseview'],
|
||||
modalWindow = this.$el.find(this.options.modalWindowClass);
|
||||
availableWidth = $(window).width();
|
||||
availableHeight = $(window).height();
|
||||
maxWidth = availableWidth * 0.80;
|
||||
maxHeight = availableHeight * 0.80;
|
||||
maxWidth = availableWidth * 0.98;
|
||||
maxHeight = availableHeight * 0.98;
|
||||
modalWidth = Math.min(modalWindow.outerWidth(), maxWidth);
|
||||
modalHeight = Math.min(modalWindow.outerHeight(), maxHeight);
|
||||
|
||||
|
||||
@@ -11,7 +11,8 @@ define(['jquery', 'underscore', 'backbone', 'gettext', 'js/views/modals/base_mod
|
||||
var EditXBlockModal = BaseModal.extend({
|
||||
events: _.extend({}, BaseModal.prototype.events, {
|
||||
'click .action-save': 'save',
|
||||
'click .action-modes a': 'changeMode'
|
||||
'click .action-modes a': 'changeMode',
|
||||
'click .title-edit-button': 'clickTitleButton'
|
||||
}),
|
||||
|
||||
options: $.extend({}, BaseModal.prototype.options, {
|
||||
@@ -40,6 +41,7 @@ define(['jquery', 'underscore', 'backbone', 'gettext', 'js/views/modals/base_mod
|
||||
this.xblockInfo = XBlockViewUtils.findXBlockInfo(xblockElement, rootXBlockInfo);
|
||||
this.options.modalType = this.xblockInfo.get('category');
|
||||
this.editOptions = options;
|
||||
|
||||
this.render();
|
||||
this.show();
|
||||
|
||||
@@ -68,6 +70,11 @@ define(['jquery', 'underscore', 'backbone', 'gettext', 'js/views/modals/base_mod
|
||||
});
|
||||
},
|
||||
|
||||
createTitleEditor: function(title) {
|
||||
// xss-lint: disable=javascript-jquery-html
|
||||
this.$('.modal-window-title').html(this.loadTemplate('edit-title-button')({title: title}));
|
||||
},
|
||||
|
||||
onDisplayXBlock: function() {
|
||||
var editorView = this.editorView,
|
||||
title = this.getTitle(),
|
||||
@@ -84,7 +91,7 @@ define(['jquery', 'underscore', 'backbone', 'gettext', 'js/views/modals/base_mod
|
||||
// Update the custom editor's title
|
||||
editorView.$('.component-name').text(title);
|
||||
} else {
|
||||
this.$('.modal-window-title').text(title);
|
||||
this.createTitleEditor(title);
|
||||
if (editorView.getDataEditor() && editorView.getMetadataEditor()) {
|
||||
this.addDefaultModes();
|
||||
// If the plugins content element exists, add a button to reveal it.
|
||||
@@ -103,8 +110,6 @@ define(['jquery', 'underscore', 'backbone', 'gettext', 'js/views/modals/base_mod
|
||||
}
|
||||
this.getActionBar().show();
|
||||
}
|
||||
|
||||
// Resize the modal to fit the window
|
||||
this.resize();
|
||||
},
|
||||
|
||||
@@ -146,7 +151,6 @@ define(['jquery', 'underscore', 'backbone', 'gettext', 'js/views/modals/base_mod
|
||||
},
|
||||
|
||||
changeMode: function(event) {
|
||||
this.removeCheatsheetVisibility();
|
||||
var $parent = $(event.target.parentElement),
|
||||
mode = $parent.data('mode');
|
||||
event.preventDefault();
|
||||
@@ -207,16 +211,30 @@ define(['jquery', 'underscore', 'backbone', 'gettext', 'js/views/modals/base_mod
|
||||
}));
|
||||
},
|
||||
|
||||
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');
|
||||
}
|
||||
clickTitleButton: function(event) {
|
||||
var self = this,
|
||||
oldTitle = this.xblockInfo.get('display_name'),
|
||||
titleElt = this.$('.modal-window-title'),
|
||||
$input = $('<input type="text" size="40" />'),
|
||||
changeFunc = function(evt) {
|
||||
var newTitle = $(evt.target).val();
|
||||
if (oldTitle !== newTitle) {
|
||||
self.xblockInfo.set('display_name', newTitle);
|
||||
self.xblockInfo.save({metadata: {display_name: newTitle}});
|
||||
}
|
||||
self.createTitleEditor(self.getTitle());
|
||||
return true;
|
||||
};
|
||||
event.preventDefault();
|
||||
|
||||
$input.val(oldTitle);
|
||||
$input.change(changeFunc).blur(changeFunc);
|
||||
titleElt.html($input); // xss-lint: disable=javascript-jquery-html
|
||||
$input.focus().select();
|
||||
$(event.target).remove();
|
||||
return true;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return EditXBlockModal;
|
||||
|
||||
@@ -30,6 +30,7 @@ define(['jquery', 'underscore', 'backbone', 'gettext', 'js/views/pages/base_page
|
||||
|
||||
view: 'container_preview',
|
||||
|
||||
|
||||
defaultViewClass: ContainerView,
|
||||
|
||||
// Overridable by subclasses-- determines whether the XBlock component
|
||||
|
||||
@@ -219,6 +219,11 @@
|
||||
color: $blue-d4;
|
||||
}
|
||||
}
|
||||
.clipboard-button {
|
||||
position: absolute;
|
||||
right: 30px;
|
||||
bottom: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +253,7 @@
|
||||
// large modals - component editors and interactives
|
||||
// ------------------------
|
||||
.modal-lg {
|
||||
width: 70%;
|
||||
width: 95%;
|
||||
min-width: ($baseline*27.5);
|
||||
height: auto;
|
||||
|
||||
@@ -266,7 +271,7 @@
|
||||
}
|
||||
|
||||
.editor-modes {
|
||||
width: 48%;
|
||||
width: 49%;
|
||||
display: inline-block;
|
||||
|
||||
@include text-align(right);
|
||||
@@ -378,7 +383,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MODAL TYPE: component - video modal (includes special overrides for xblock-related editing view)
|
||||
.modal-lg.modal-type-video {
|
||||
.modal-content {
|
||||
|
||||
5
cms/templates/js/copy-clipboard-button.underscore
Normal file
5
cms/templates/js/copy-clipboard-button.underscore
Normal file
@@ -0,0 +1,5 @@
|
||||
<a href="#" class="button action-button clipboard-button" data-tooltip="<%- gettext('Copy Component Location') %>">
|
||||
<i class="fa fa-link"></i>
|
||||
<%- gettext('Copy Component Location') %>
|
||||
<input class="sr" value="<%- location %>"/>
|
||||
</a>
|
||||
1
cms/templates/js/edit-title-button.underscore
Normal file
1
cms/templates/js/edit-title-button.underscore
Normal file
@@ -0,0 +1 @@
|
||||
<span class="modal-button-title"><%- title %></span> <button data-tooltip="<%- gettext('Edit Title') %>" class="btn-default action-edit title-edit-button"><span class="icon fa fa-pencil" aria-hidden="true"></span><span class="sr"> <%- gettext('Edit Title') %></span></button>
|
||||
@@ -3,10 +3,4 @@
|
||||
<li class="field comp-setting-entry metadata_entry">
|
||||
</li>
|
||||
<% }) %>
|
||||
<li class="field comp-setting-entry metadata_entry">
|
||||
<div class="wrapper-comp-setting-text">
|
||||
<label class="label setting-label"><%- gettext("Component Location ID") %></label>
|
||||
<span class="setting-text"><%- locator %></span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<%! from django.utils.translation import ugettext as _ %>
|
||||
<%page expression_filter="h"/>
|
||||
<%namespace name='static' file='../static_content.html'/>
|
||||
|
||||
<% isLaTexProblem='source_code' in editable_metadata_fields and editable_metadata_fields['source_code']['explicitly_set'] and enable_latex_compiler %>
|
||||
@@ -18,6 +19,7 @@
|
||||
<span class="problem-editor-icon heading3">
|
||||
<img class="icon" src="${static.url('images/cms-editor_heading.png')}" alt="${_("Insert a heading")}">
|
||||
</span>
|
||||
${_("Heading")}
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
@@ -25,6 +27,7 @@
|
||||
<span class="problem-editor-icon multiple-choice">
|
||||
<img class="icon" src="${static.url('images/cms-editor_radio.png')}" alt="${_("Add a multiple choice question")}">
|
||||
</span>
|
||||
${_("Multiple Choice")}
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
@@ -32,6 +35,7 @@
|
||||
<span class="problem-editor-icon checks">
|
||||
<img class="icon" src="${static.url('images/cms-editor_checkbox.png')}" alt="${_("Add a question with checkboxes")}">
|
||||
</span>
|
||||
${_("Checkboxes")}
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
@@ -39,6 +43,7 @@
|
||||
<span class="problem-editor-icon string">
|
||||
<img class="icon" src="${static.url('images/cms-editor_text.png')}" alt="${_("Insert a text response")}">
|
||||
</span>
|
||||
${_("Text Input")}
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
@@ -46,6 +51,7 @@
|
||||
<span class="problem-editor-icon number">
|
||||
<img class="icon" src="${static.url('images/cms-editor_number.png')}" alt="${_("Insert a numerical response")}">
|
||||
</span>
|
||||
${_("Numerical Input")}
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
@@ -53,6 +59,7 @@
|
||||
<span class="problem-editor-icon dropdown">
|
||||
<img class="icon" src="${static.url('images/cms-editor_dropdown.png')}" alt="${_("Insert a dropdown response")}">
|
||||
</span>
|
||||
${_("Dropdown")}
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
@@ -60,103 +67,108 @@
|
||||
<span class="problem-editor-icon explanation">
|
||||
<img class="icon" src="${static.url('images/cms-editor_explanation.png')}" alt="${_("Add an explanation for this question")}">
|
||||
</span>
|
||||
${_("Explanation")}
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="editor-tabs">
|
||||
<li><button type="button" class="xml-tab advanced-toggle" data-tab="xml">${_("Advanced Editor")}</button></li>
|
||||
<li><button type="button" class="cheatsheet-toggle" data-tooltip="${_("Toggle Cheatsheet")}">?</button></li>
|
||||
</ul>
|
||||
</div>
|
||||
<textarea class="markdown-box">${markdown | h}</textarea>
|
||||
%endif
|
||||
<textarea class="xml-box" rows="8" cols="40">${data | h}</textarea>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script type="text/template" id="simple-editor-cheatsheet">
|
||||
<article class="simple-editor-cheatsheet">
|
||||
<div class="cheatsheet-wrapper">
|
||||
<div class="row">
|
||||
<h6>${_("Heading")}</h6>
|
||||
<div class="col sample heading-1">
|
||||
<img class="icon" src="${static.url('images/cms-editor_heading.png')}" alt="${_("Insert a heading")}">
|
||||
</div>
|
||||
<div class="col">
|
||||
<textarea class="markdown-box">${markdown}</textarea>
|
||||
<article class="simple-editor-cheatsheet shown">
|
||||
<div class="cheatsheet-wrapper">
|
||||
<div class="row">
|
||||
<h5>${_("Markdown Help")}</h5>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col sample heading-1">
|
||||
<img class="icon" src="${static.url('images/cms-editor_heading.png')}" alt="${_("Insert a heading")}">
|
||||
<h6>${_("Heading")}</h6>
|
||||
</div>
|
||||
<div class="col">
|
||||
<pre><code>H3
|
||||
=====
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<h6>${_("Multiple Choice")}</h6>
|
||||
<div class="col sample multiple-choice">
|
||||
<img class="icon" src="${static.url('images/cms-editor_radio.png')}" alt="${_("Add a multiple choice question")}">
|
||||
</div>
|
||||
<div class="col">
|
||||
</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col sample multiple-choice">
|
||||
<img class="icon" src="${static.url('images/cms-editor_radio.png')}" alt="${_("Add a multiple choice question")}">
|
||||
<h6>${_("Multiple Choice")}</h6>
|
||||
</div>
|
||||
<div class="col">
|
||||
<pre><code>( ) red
|
||||
( ) green
|
||||
(x) blue</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<h6>${_("Checkboxes")}</h6>
|
||||
<div class="col sample check-multiple">
|
||||
<img class="icon" src="${static.url('images/cms-editor_checkbox.png')}" alt="${_("Add a question with checkboxes")}">
|
||||
</div>
|
||||
<div class="col">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col sample check-multiple">
|
||||
<img class="icon" src="${static.url('images/cms-editor_checkbox.png')}" alt="${_("Add a question with checkboxes")}">
|
||||
<h6>${_("Checkboxes")}</h6>
|
||||
</div>
|
||||
<div class="col">
|
||||
<pre><code>[x] earth
|
||||
[ ] wind
|
||||
[x] water</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<h6>${_("Text Input")}</h6>
|
||||
<div class="col sample string-response">
|
||||
<img class="icon" src="${static.url('images/cms-editor_text.png')}" alt="${_("Insert a text response")}">
|
||||
</div>
|
||||
<div class="col">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col sample string-response">
|
||||
<img class="icon" src="${static.url('images/cms-editor_text.png')}" alt="${_("Insert a text response")}">
|
||||
<h6>${_("Text Input")}</h6>
|
||||
</div>
|
||||
<div class="col">
|
||||
<pre><code>= dog
|
||||
or= cat
|
||||
or= mouse</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col sample numerical-response">
|
||||
<img class="icon" src="${static.url('images/cms-editor_number.png')}" alt="${_("Insert a numerical response")}">
|
||||
<h6>${_("Numerical Input")}</h6>
|
||||
</div>
|
||||
<div class="col">
|
||||
<pre><code>= 3.14 +- 2%</code></pre>
|
||||
<pre><code>= [3.14, 3.15)</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col sample option-reponse">
|
||||
<img class="icon" src="${static.url('images/cms-editor_dropdown.png')}" alt="${_("Insert a dropdown response")}">
|
||||
<h6>${_("Dropdown")}</h6>
|
||||
</div>
|
||||
<div class="col">
|
||||
<pre><code>[[wrong, (right)]]</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<h6>${_("Label")}</h6>
|
||||
<div class="col">
|
||||
<pre><code>>>What is the capital of Argentina?<<</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col sample explanation">
|
||||
<img class="icon" src="${static.url('images/cms-editor_explanation.png')}" alt="${_("Add an explanation for this question")}">
|
||||
<h6>${_("Explanation")}</h6>
|
||||
</div>
|
||||
<div class="col">
|
||||
<pre><code>[explanation] A short explanation of the answer. [explanation]</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<h6>${_("Numerical Input")}</h6>
|
||||
<div class="col sample numerical-response">
|
||||
<img class="icon" src="${static.url('images/cms-editor_number.png')}" alt="${_("Insert a numerical response")}">
|
||||
</div>
|
||||
<div class="col">
|
||||
<pre><code>= 3.14 +- 2%</code></pre>
|
||||
<pre><code>= [3.14, 3.15)</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<h6>${_("Dropdown")}</h6>
|
||||
<div class="col sample option-reponse">
|
||||
<img class="icon" src="${static.url('images/cms-editor_dropdown.png')}" alt="${_("Insert a dropdown response")}">
|
||||
</div>
|
||||
<div class="col">
|
||||
<pre><code>[[wrong, (right)]]</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<h6>${_("Label")}</h6>
|
||||
<div class="col">
|
||||
<pre><code>>>What is the capital of Argentina?<<</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<h6>${_("Explanation")}</h6>
|
||||
<div class="col sample explanation">
|
||||
<img class="icon" src="${static.url('images/cms-editor_explanation.png')}" alt="${_("Add an explanation for this question")}">
|
||||
</div>
|
||||
<div class="col">
|
||||
<pre><code>[explanation] A short explanation of the answer. [explanation]</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</article>
|
||||
</div>
|
||||
%endif
|
||||
</div>
|
||||
<textarea class="xml-box" rows="8" cols="40">${data}</textarea>
|
||||
</section>
|
||||
|
||||
<script type="text/template" id="simple-editor-cheatsheet">
|
||||
|
||||
</script>
|
||||
</div>
|
||||
<%include file="metadata-edit.html" />
|
||||
|
||||
@@ -23,50 +23,37 @@
|
||||
}
|
||||
}
|
||||
|
||||
.cheatsheet-toggle {
|
||||
width: 21px;
|
||||
height: 21px;
|
||||
padding: 0;
|
||||
margin: -1px 5px 0 15px;
|
||||
border-radius: 22px;
|
||||
border: 1px solid #a5aaaf;
|
||||
background: #e5ecf3;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
color: #565d64;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.simple-editor-cheatsheet {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 100%;
|
||||
top: 41px;
|
||||
left: 70%;
|
||||
width: 0;
|
||||
border-radius: 0 3px 3px 0;
|
||||
border-left: 1px solid $gray-l2;
|
||||
|
||||
@include linear-gradient(left, $shadow-l1, $transparent 4px);
|
||||
|
||||
background-color: $white;
|
||||
background-color: $lightGrey;
|
||||
overflow: hidden;
|
||||
|
||||
@include transition(width 0.3s linear 0s);
|
||||
|
||||
&.shown {
|
||||
width: 20%;
|
||||
height: 100%;
|
||||
width: 30%;
|
||||
height: 92%;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.cheatsheet-wrapper {
|
||||
padding: 10%;
|
||||
padding: 5%;
|
||||
}
|
||||
|
||||
h6 {
|
||||
margin-top: 4px;
|
||||
margin-bottom: 7px;
|
||||
margin-left: 4px;
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.row {
|
||||
@@ -86,7 +73,6 @@
|
||||
display: block;
|
||||
|
||||
&.sample {
|
||||
width: 60px;
|
||||
margin-right: 30px;
|
||||
|
||||
.icon {
|
||||
@@ -110,6 +96,7 @@
|
||||
// adding padding to simple editor only - adjacent selector is needed since there are no toggles for CodeMirror
|
||||
.markdown-box + .CodeMirror {
|
||||
padding: 10px;
|
||||
width: 69%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,12 +53,6 @@
|
||||
|
||||
function MarkdownEditingDescriptor(element) {
|
||||
var that = this;
|
||||
this.toggleCheatsheetVisibility = function() {
|
||||
return MarkdownEditingDescriptor.prototype.toggleCheatsheetVisibility.apply(that, arguments);
|
||||
};
|
||||
this.toggleCheatsheet = function() {
|
||||
return MarkdownEditingDescriptor.prototype.toggleCheatsheet.apply(that, arguments);
|
||||
};
|
||||
this.onToolbarButton = function() {
|
||||
return MarkdownEditingDescriptor.prototype.onToolbarButton.apply(that, arguments);
|
||||
};
|
||||
@@ -75,7 +69,6 @@
|
||||
// Add listeners for toolbar buttons (only present for markdown editor)
|
||||
this.element.on('click', '.xml-tab', this.onShowXMLButton);
|
||||
this.element.on('click', '.format-buttons button', this.onToolbarButton);
|
||||
this.element.on('click', '.cheatsheet-toggle', this.toggleCheatsheet);
|
||||
// Hide the XML text area
|
||||
$(this.element.find('.xml-box')).hide();
|
||||
} else {
|
||||
@@ -110,10 +103,6 @@
|
||||
*/
|
||||
MarkdownEditingDescriptor.prototype.onShowXMLButton = function(e) {
|
||||
e.preventDefault();
|
||||
if (this.cheatsheet && this.cheatsheet.hasClass('shown')) {
|
||||
this.cheatsheet.toggleClass('shown');
|
||||
this.toggleCheatsheetVisibility();
|
||||
}
|
||||
if (this.confirmConversionToXml()) {
|
||||
this.createXMLEditor(MarkdownEditingDescriptor.markdownToXml(this.markdown_editor.getValue()));
|
||||
this.xml_editor.setCursor(0);
|
||||
@@ -169,29 +158,6 @@
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
Event listener for toggling cheatsheet (only possible when markdown editor is visible).
|
||||
*/
|
||||
MarkdownEditingDescriptor.prototype.toggleCheatsheet = function(e) {
|
||||
var that = this;
|
||||
e.preventDefault();
|
||||
if (!$(this.markdown_editor.getWrapperElement()).find('.simple-editor-cheatsheet')[0]) {
|
||||
this.cheatsheet = $($('#simple-editor-cheatsheet').html());
|
||||
$(this.markdown_editor.getWrapperElement()).append(this.cheatsheet);
|
||||
}
|
||||
this.toggleCheatsheetVisibility();
|
||||
return setTimeout((function() {
|
||||
return that.cheatsheet.toggleClass('shown');
|
||||
}), 10);
|
||||
};
|
||||
|
||||
/*
|
||||
Function to toggle cheatsheet visibility.
|
||||
*/
|
||||
MarkdownEditingDescriptor.prototype.toggleCheatsheetVisibility = function() {
|
||||
return $('.modal-content').toggleClass('cheatsheet-is-shown');
|
||||
};
|
||||
|
||||
/*
|
||||
Stores the current editor and hides the one that is not displayed.
|
||||
*/
|
||||
@@ -212,7 +178,6 @@
|
||||
MarkdownEditingDescriptor.prototype.save = function() {
|
||||
this.element.off('click', '.xml-tab', this.changeEditor);
|
||||
this.element.off('click', '.format-buttons button', this.onToolbarButton);
|
||||
this.element.off('click', '.cheatsheet-toggle', this.toggleCheatsheet);
|
||||
if (this.current_editor === this.markdown_editor) {
|
||||
return {
|
||||
data: MarkdownEditingDescriptor.markdownToXml(this.markdown_editor.getValue()),
|
||||
@@ -327,12 +292,13 @@
|
||||
// <label>question</label> <description>description</description>
|
||||
xml = xml.replace(/>>([^]+?)<</gm, function(match, questionText) {
|
||||
var result = questionText.split('||'),
|
||||
label = '<label>' + result[0] + '</label>\n';
|
||||
label = '<label>' + result[0] + '</label>\n'; // xss-lint: disable=javascript-concat-html
|
||||
|
||||
// don't add empty <description> tag
|
||||
if (result.length === 1 || !result[1]) {
|
||||
return label;
|
||||
}
|
||||
// xss-lint: disable=javascript-concat-html
|
||||
return label + '<description>' + result[1] + '</description>\n';
|
||||
});
|
||||
|
||||
@@ -425,6 +391,7 @@
|
||||
optiontag += correct[1];
|
||||
}
|
||||
optiontag += '">';
|
||||
// xss-lint: disable=javascript-concat-html
|
||||
return '\n<optionresponse>\n' + optiontag + '</optioninput>\n</optionresponse>\n\n';
|
||||
}
|
||||
|
||||
@@ -442,12 +409,15 @@
|
||||
if (label) {
|
||||
label = ' label="' + label + '"';
|
||||
}
|
||||
// xss-lint: disable=javascript-concat-html
|
||||
hintstr = ' <optionhint' + label + '>' + textHint.hint + '</optionhint>';
|
||||
}
|
||||
// xss-lint: disable=javascript-concat-html
|
||||
optionlines += ' <option' + correctstr + '>' + textHint.nothint + hintstr +
|
||||
'</option>\n';
|
||||
}
|
||||
}
|
||||
// xss-lint: disable=javascript-concat-html
|
||||
return '\n<optionresponse>\n <optioninput>\n' + optionlines +
|
||||
' </optioninput>\n</optionresponse>\n\n';
|
||||
});
|
||||
@@ -477,8 +447,10 @@
|
||||
hint = extractHint(value);
|
||||
if (hint.hint) {
|
||||
value = hint.nothint;
|
||||
// xss-lint: disable=javascript-concat-html
|
||||
value = value + ' <choicehint' + hint.labelassign + '>' + hint.hint + '</choicehint>';
|
||||
}
|
||||
// xss-lint: disable=javascript-concat-html
|
||||
choices += ' <choice correct="' + correct + '"' + fixed + '>' + value + '</choice>\n';
|
||||
}
|
||||
}
|
||||
@@ -515,6 +487,7 @@
|
||||
// lone case of hint text processing outside of extractHint, since syntax here is unique
|
||||
hintbody = abhint[2];
|
||||
hintbody = hintbody.replace('&lf;', '\n').trim();
|
||||
// xss-lint: disable=javascript-concat-html
|
||||
endHints += ' <compoundhint value="' + abhint[1].trim() + '">' + hintbody +
|
||||
'</compoundhint>\n';
|
||||
continue; // bail
|
||||
@@ -534,11 +507,13 @@
|
||||
// checkbox choicehints get their own line, since there can be two of them
|
||||
// <choicehint selected="true">You’re right that apple is a fruit.</choicehint>
|
||||
if (select) {
|
||||
// xss-lint: disable=javascript-concat-html
|
||||
hints += '\n <choicehint selected="true">' + select[2].trim() +
|
||||
'</choicehint>';
|
||||
}
|
||||
select = /{\s*(u|unselected):((.|\n)*?)}/i.exec(inner);
|
||||
if (select) {
|
||||
// xss-lint: disable=javascript-concat-html
|
||||
hints += '\n <choicehint selected="false">' + select[2].trim() +
|
||||
'</choicehint>';
|
||||
}
|
||||
@@ -549,6 +524,7 @@
|
||||
value = hint.nothint;
|
||||
}
|
||||
}
|
||||
// xss-lint: disable=javascript-concat-html
|
||||
groupString += ' <choice correct="' + correct + '">' + value + hints + '</choice>\n';
|
||||
}
|
||||
}
|
||||
@@ -694,10 +670,12 @@
|
||||
typ = ' type="ci regexp"';
|
||||
firstAnswer = firstAnswer.slice(1).trim();
|
||||
}
|
||||
// xss-lint: disable=javascript-concat-html
|
||||
string = '<stringresponse answer="' + firstAnswer + '"' + typ + ' >\n';
|
||||
if (textHint.hint) {
|
||||
// xss-lint: disable=javascript-concat-html
|
||||
string += ' <correcthint' + textHint.labelassign + '>' +
|
||||
textHint.hint + '</correcthint>\n';
|
||||
textHint.hint + '</correcthint>\n'; // xss-lint: disable=javascript-concat-html
|
||||
}
|
||||
|
||||
// Subsequent cases are not= or or=
|
||||
@@ -705,16 +683,22 @@
|
||||
textHint = extractHint(values[i]);
|
||||
notMatch = /^not\=\s*(.*)/.exec(textHint.nothint);
|
||||
if (notMatch) {
|
||||
// xss-lint: disable=javascript-concat-html
|
||||
string += ' <stringequalhint answer="' + notMatch[1] + '"' +
|
||||
// xss-lint: disable=javascript-concat-html
|
||||
textHint.labelassign + '>' + textHint.hint + '</stringequalhint>\n';
|
||||
|
||||
continue;
|
||||
}
|
||||
orMatch = /^or\=\s*(.*)/.exec(textHint.nothint);
|
||||
if (orMatch) {
|
||||
// additional_answer with answer= attribute
|
||||
// xss-lint: disable=javascript-concat-html
|
||||
string += ' <additional_answer answer="' + orMatch[1] + '">';
|
||||
if (textHint.hint) {
|
||||
// xss-lint: disable=javascript-concat-html
|
||||
string += '<correcthint' + textHint.labelassign + '>' +
|
||||
// xss-lint: disable=javascript-concat-html
|
||||
textHint.hint + '</correcthint>';
|
||||
}
|
||||
string += '</additional_answer>\n';
|
||||
@@ -732,12 +716,15 @@
|
||||
|
||||
// replace explanations
|
||||
xml = xml.replace(/\[explanation\]\n?([^\]]*)\[\/?explanation\]/gmi, function(match, p1) {
|
||||
// xss-lint: disable=javascript-concat-html
|
||||
return '<solution>\n<div class="detailed-solution">\n' +
|
||||
// xss-lint: disable=javascript-concat-html
|
||||
gettext('Explanation') + '\n\n' + p1 + '\n</div>\n</solution>';
|
||||
});
|
||||
|
||||
// replace code blocks
|
||||
xml = xml.replace(/\[code\]\n?([^\]]*)\[\/?code\]/gmi, function(match, p1) {
|
||||
// xss-lint: disable=javascript-concat-html
|
||||
return '<pre><code>' + p1 + '</code></pre>';
|
||||
});
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ class ProblemXBlockEditorView(XBlockEditorView):
|
||||
"""
|
||||
If editing, set the value of a field.
|
||||
"""
|
||||
selector = u'.xblock-studio_view li.field label:contains("{}") + input'.format(field_display_name)
|
||||
selector = u'.metadata_edit li.field label:contains("{}") + input'.format(field_display_name)
|
||||
script = "$(arguments[0]).val(arguments[1]).change();"
|
||||
self.browser.execute_script(script, selector, field_value)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user