diff --git a/cms/static/coffee/src/views/unit.coffee b/cms/static/coffee/src/views/unit.coffee index a250925bf9..6c06c85400 100644 --- a/cms/static/coffee/src/views/unit.coffee +++ b/cms/static/coffee/src/views/unit.coffee @@ -1,6 +1,7 @@ class CMS.Views.UnitEdit extends Backbone.View events: - 'click .new-component .new-component-type a': 'showComponentTemplates' + # 'click .new-component .new-component-type a': 'showComponentTemplates' + 'click .new-component .new-component-type a': 'addNewComponent' 'click .new-component .cancel-button': 'closeNewComponent' 'click .new-component-templates .new-component-template a': 'saveNewComponent' 'click .new-component-templates .cancel-button': 'closeNewComponent' @@ -79,6 +80,42 @@ class CMS.Views.UnitEdit extends Backbone.View @$newComponentItem.find('.rendered-component').remove() @$newComponentItem.css('height', @$newComponentButton.outerHeight()) + addNewComponent: (event) => + event.preventDefault() + + @$componentItem = $('
  • ').addClass('editing') + $modalCover.show() + $modalCover.bind('click', @closeEditor) + type = $(event.currentTarget).data('type') + + switch type + when 'video' + @$editor = $($('#video-editor').html()) + $preview = $($('#video-preview').html()) + when 'problem' + @$editor = $($('#problem-editor').html()) + $preview = $($('#problem-preview').html()) + initProblemEditors(@$editor, $preview) + + @$editor.find('.save-button').bind('click', => + @$componentItem.removeClass('editing') + @closeEditor() + ) + + $componentActions = $($('#component-actions').html()); + + @$componentItem.append(@$editor) + @$componentItem.append($preview) + @$componentItem.append($componentActions); + @$newComponentItem.before(@$componentItem) + + closeEditor: (event) => + console.log('close') + $modalCover.hide() + $modalCover.unbind('click', @closeEditor) + @$editor.remove() + @$componentItem.removeClass('editing') + saveNewComponent: (event) => event.preventDefault() diff --git a/cms/static/img/problem-editor-icons.png b/cms/static/img/problem-editor-icons.png new file mode 100644 index 0000000000..62f078560f Binary files /dev/null and b/cms/static/img/problem-editor-icons.png differ diff --git a/cms/static/js/speed-editor.js b/cms/static/js/speed-editor.js new file mode 100644 index 0000000000..7d6a37a6b2 --- /dev/null +++ b/cms/static/js/speed-editor.js @@ -0,0 +1,421 @@ +var $body; +var $preview; +var $tooltip; +var simpleEditor; +var xmlEditor; +var currentEditor; +var controlDown; +var commandDown; + + +function initProblemEditors($editor, $prev) { + simpleEditor = CodeMirror.fromTextArea($editor.find('.edit-box')[0], { + lineWrapping: true, + extraKeys: { + 'Ctrl-N': newUnit, + 'Ctrl-H': makeHeader, + 'Ctrl-V': makeVideo, + 'Ctrl-M': makeMultipleChoice, + 'Ctrl-C': makeCheckboxes, + 'Ctrl-S': makeStringInput, + 'Shift-Ctrl-3': makeNumberInput, + 'Shift-Ctrl-S': makeSelect + }, + mode: null, + onChange: onSimpleEditorUpdate + }); + + xmlEditor = CodeMirror.fromTextArea($editor.find('.xml-box')[0], { + lineWrapping: true, + mode: 'xml', + lineNumbers: true + }); + + currentEditor = simpleEditor; + + $(simpleEditor.getWrapperElement()).css('background', '#fff'); + $(xmlEditor.getWrapperElement()).css({ + 'background': '#fff' + }).hide(); + + $(simpleEditor.getWrapperElement()).bind('click', setFocus); + $preview = $prev.find('.problem'); + + $body.on('click', '.editor-bar a', onEditorButton); + $body.on('click', '.editor-tabs a', setEditorTab); + $(document).bind('keyup', onKeyboard); +} + +function setEditorTab(e) { + e.preventDefault(); + $('.editor-tabs .current').removeClass('current'); + $(this).addClass('current'); + if($(this).hasClass('simple-tab')) { + currentEditor = simpleEditor; + $(simpleEditor.getWrapperElement()).show(); + $(xmlEditor.getWrapperElement()).hide(); + $(simpleEditor).focus(); + } else { + currentEditor = xmlEditor; + $(simpleEditor.getWrapperElement()).hide(); + $(xmlEditor.getWrapperElement()).show(); + $(xmlEditor).focus(); + } + onSimpleEditorUpdate(); +} + +function setFocus(e) { + $(simpleEditor).focus(); +} + +function onSimpleEditorUpdate() { + updatePreview(); + updateXML(); +} + +function updateXML() { + var val = simpleEditor.getValue(); + var xml = val; + + // replace headers + xml = xml.replace(/(^.*)\n(?=\=\=+)/g, '

    $1

    '); + xml = xml.replace(/\=\=+/g, ''); + + // group multiple choice answers + xml = xml.replace(/(\(.?\).*\n*)+/g, function(match, p) { + var groupString = '\n'; + groupString += ' \n'; + var options = match.split('\n'); + for(var i = 0; i < options.length; i++) { + if(options[i].length > 0) { + var value = options[i].split(/\)\s*/)[1]; + var correct = /\(x\)/i.test(options[i]); + groupString += ' ' + value + '\n'; + } + } + groupString += ' \n'; + groupString += '\n\n'; + return groupString; + }); + + // group check answers + xml = xml.replace(/(\[.?\].*\n*)+/g, function(match, p) { + var groupString = '\n'; + groupString += ' \n'; + var options = match.split('\n'); + for(var i = 0; i < options.length; i++) { + if(options[i].length > 0) { + var value = options[i].split(/\]\s*/)[1]; + var correct = /\[x\]/i.test(options[i]); + groupString += ' ' + value + '\n'; + } + } + groupString += ' \n'; + groupString += '\n\n'; + return groupString; + }); + + // replace videos + xml = xml.replace(/\{\{video\s(.*)\}\}/g, '
  • % endfor -
  • - - New Component - +
  • -
    Select Component Type
    +
    Add New Component
    - Cancel -
    - % for type, templates in sorted(component_templates.items()): -
    - - Cancel -
    - % endfor +