Pull modal cover and date utils into their own files.
Move overview-specific functions into overview.js.
This commit is contained in:
@@ -54,17 +54,14 @@ define ["js/views/course_info_handout", "js/views/course_info_update", "js/model
|
||||
@courseInfoEdit.$el.find('.save-button').click()
|
||||
|
||||
@cancelNewCourseInfo = (useCancelButton) ->
|
||||
spyOn(@courseInfoEdit.$modalCover, 'show').andCallThrough()
|
||||
spyOn(@courseInfoEdit.$modalCover, 'hide').andCallThrough()
|
||||
|
||||
@courseInfoEdit.onNew(@event)
|
||||
expect(@courseInfoEdit.$modalCover.show).toHaveBeenCalled()
|
||||
spyOn(@courseInfoEdit.$modalCover, 'hide').andCallThrough()
|
||||
|
||||
spyOn(@courseInfoEdit.$codeMirror, 'getValue').andReturn('unsaved changes')
|
||||
model = @collection.at(0)
|
||||
spyOn(model, "save").andCallThrough()
|
||||
|
||||
cancelEditingUpdate(useCancelButton)
|
||||
cancelEditingUpdate(@courseInfoEdit, @courseInfoEdit.$modalCover, useCancelButton)
|
||||
|
||||
expect(@courseInfoEdit.$modalCover.hide).toHaveBeenCalled()
|
||||
expect(model.save).not.toHaveBeenCalled()
|
||||
@@ -73,28 +70,25 @@ define ["js/views/course_info_handout", "js/views/course_info_update", "js/model
|
||||
|
||||
@cancelExistingCourseInfo = (useCancelButton) ->
|
||||
@createNewUpdate('existing update')
|
||||
|
||||
spyOn(@courseInfoEdit.$modalCover, 'show').andCallThrough()
|
||||
spyOn(@courseInfoEdit.$modalCover, 'hide').andCallThrough()
|
||||
@courseInfoEdit.$el.find('.edit-button').click()
|
||||
expect(@courseInfoEdit.$modalCover.show).toHaveBeenCalled()
|
||||
spyOn(@courseInfoEdit.$modalCover, 'hide').andCallThrough()
|
||||
|
||||
spyOn(@courseInfoEdit.$codeMirror, 'getValue').andReturn('modification')
|
||||
model = @collection.at(0)
|
||||
spyOn(model, "save").andCallThrough()
|
||||
|
||||
cancelEditingUpdate(useCancelButton)
|
||||
model.id = "saved_to_server"
|
||||
cancelEditingUpdate(@courseInfoEdit, @courseInfoEdit.$modalCover, useCancelButton)
|
||||
|
||||
expect(@courseInfoEdit.$modalCover.hide).toHaveBeenCalled()
|
||||
expect(model.save).not.toHaveBeenCalled()
|
||||
previewContents = @courseInfoEdit.$el.find('.update-contents').html()
|
||||
expect(previewContents).toEqual('existing update')
|
||||
|
||||
cancelEditingUpdate = (update, useCancelButton) ->
|
||||
cancelEditingUpdate = (update, modalCover, useCancelButton) ->
|
||||
if useCancelButton
|
||||
update.$el.find('.cancel-button').click()
|
||||
else
|
||||
$('.modal-cover').click()
|
||||
modalCover.click()
|
||||
|
||||
afterEach ->
|
||||
@xhrRestore()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
define ["js/views/overview", "js/views/feedback_notification", "sinon", "js/base", "date", "jquery.timepicker"],
|
||||
(OverviewDragger, Notification, sinon) ->
|
||||
(Overview, Notification, sinon) ->
|
||||
|
||||
describe "Course Overview", ->
|
||||
beforeEach ->
|
||||
@@ -62,9 +62,9 @@ define ["js/views/overview", "js/views/feedback_notification", "sinon", "js/base
|
||||
</ol>
|
||||
"""
|
||||
|
||||
spyOn(window, 'saveSetSectionScheduleDate').andCallThrough()
|
||||
spyOn(Overview, 'saveSetSectionScheduleDate').andCallThrough()
|
||||
# Have to do this here, as it normally gets bound in document.ready()
|
||||
$('a.save-button').click(saveSetSectionScheduleDate)
|
||||
$('a.save-button').click(Overview.saveSetSectionScheduleDate)
|
||||
$('a.delete-section-button').click(deleteSection)
|
||||
$(".edit-subsection-publish-settings .start-date").datepicker()
|
||||
|
||||
@@ -75,7 +75,7 @@ define ["js/views/overview", "js/views/feedback_notification", "sinon", "js/base
|
||||
requests = @requests = []
|
||||
@xhr.onCreate = (req) -> requests.push(req)
|
||||
|
||||
OverviewDragger.makeDraggable(
|
||||
Overview.overviewDragger.makeDraggable(
|
||||
'.unit',
|
||||
'.unit-drag-handle',
|
||||
'ol.sortable-unit-list',
|
||||
@@ -90,7 +90,7 @@ define ["js/views/overview", "js/views/feedback_notification", "sinon", "js/base
|
||||
it "should save model when save is clicked", ->
|
||||
$('a.edit-button').click()
|
||||
$('a.save-button').click()
|
||||
expect(saveSetSectionScheduleDate).toHaveBeenCalled()
|
||||
expect(Overview.saveSetSectionScheduleDate).toHaveBeenCalled()
|
||||
|
||||
it "should show a confirmation on save", ->
|
||||
$('a.edit-button').click()
|
||||
@@ -120,7 +120,7 @@ define ["js/views/overview", "js/views/feedback_notification", "sinon", "js/base
|
||||
$ele.offset(
|
||||
top: $ele.offset().top + 10, left: $ele.offset().left
|
||||
)
|
||||
destination = OverviewDragger.findDestination($ele, 1)
|
||||
destination = Overview.overviewDragger.findDestination($ele, 1)
|
||||
expect(destination.ele).toBe($('#unit-2'))
|
||||
expect(destination.attachMethod).toBe('before')
|
||||
|
||||
@@ -130,7 +130,7 @@ define ["js/views/overview", "js/views/feedback_notification", "sinon", "js/base
|
||||
top: $('#unit-4').offset().top + 8
|
||||
left: $ele.offset().left
|
||||
)
|
||||
destination = OverviewDragger.findDestination($ele, 1)
|
||||
destination = Overview.overviewDragger.findDestination($ele, 1)
|
||||
expect(destination.ele).toBe($('#unit-4'))
|
||||
# Dragging down into first element, we have a fudge factor makes it easier to drag at beginning.
|
||||
expect(destination.attachMethod).toBe('before')
|
||||
@@ -139,7 +139,7 @@ define ["js/views/overview", "js/views/feedback_notification", "sinon", "js/base
|
||||
top: $('#unit-4').offset().top + 12
|
||||
left: $ele.offset().left
|
||||
)
|
||||
destination = OverviewDragger.findDestination($ele, 1)
|
||||
destination = Overview.overviewDragger.findDestination($ele, 1)
|
||||
expect(destination.ele).toBe($('#unit-4'))
|
||||
expect(destination.attachMethod).toBe('after')
|
||||
|
||||
@@ -149,7 +149,7 @@ define ["js/views/overview", "js/views/feedback_notification", "sinon", "js/base
|
||||
top: $('#unit-3').offset().bottom + 4
|
||||
left: $ele.offset().left
|
||||
)
|
||||
destination = OverviewDragger.findDestination($ele, -1)
|
||||
destination = Overview.overviewDragger.findDestination($ele, -1)
|
||||
expect(destination.ele).toBe($('#unit-3'))
|
||||
# Dragging down up into last element, we have a fudge factor makes it easier to drag at beginning.
|
||||
expect(destination.attachMethod).toBe('after')
|
||||
@@ -158,7 +158,7 @@ define ["js/views/overview", "js/views/feedback_notification", "sinon", "js/base
|
||||
top: $('#unit-3').offset().top + 4
|
||||
left: $ele.offset().left
|
||||
)
|
||||
destination = OverviewDragger.findDestination($ele, -1)
|
||||
destination = Overview.overviewDragger.findDestination($ele, -1)
|
||||
expect(destination.ele).toBe($('#unit-3'))
|
||||
expect(destination.attachMethod).toBe('before')
|
||||
|
||||
@@ -168,7 +168,7 @@ define ["js/views/overview", "js/views/feedback_notification", "sinon", "js/base
|
||||
top: $('#subsection-3').offset().top + 10
|
||||
left: $ele.offset().left
|
||||
)
|
||||
destination = OverviewDragger.findDestination($ele, 1)
|
||||
destination = Overview.overviewDragger.findDestination($ele, 1)
|
||||
expect(destination.ele).toBe($('#subsection-list-3'))
|
||||
expect(destination.attachMethod).toBe('prepend')
|
||||
|
||||
@@ -177,7 +177,7 @@ define ["js/views/overview", "js/views/feedback_notification", "sinon", "js/base
|
||||
$ele.offset(
|
||||
top: $ele.offset().top + 200, left: $ele.offset().left
|
||||
)
|
||||
destination = OverviewDragger.findDestination($ele, 1)
|
||||
destination = Overview.overviewDragger.findDestination($ele, 1)
|
||||
expect(destination).toEqual(
|
||||
ele: null
|
||||
attachMethod: ""
|
||||
@@ -190,21 +190,21 @@ define ["js/views/overview", "js/views/feedback_notification", "sinon", "js/base
|
||||
top: $('#subsection-2').offset().top + 3
|
||||
left: $ele.offset().left
|
||||
)
|
||||
destination = OverviewDragger.findDestination($ele, 1)
|
||||
destination = Overview.overviewDragger.findDestination($ele, 1)
|
||||
expect(destination.ele).toBe($('#subsection-list-2'))
|
||||
expect(destination.parentList).toBe($('#subsection-2'))
|
||||
expect(destination.attachMethod).toBe('prepend')
|
||||
|
||||
describe "onDragStart", ->
|
||||
it "sets the dragState to its default values", ->
|
||||
expect(OverviewDragger.dragState).toEqual({})
|
||||
expect(Overview.overviewDragger.dragState).toEqual({})
|
||||
# Call with some dummy data
|
||||
OverviewDragger.onDragStart(
|
||||
Overview.overviewDragger.onDragStart(
|
||||
{element: $('#unit-1')},
|
||||
null,
|
||||
null
|
||||
)
|
||||
expect(OverviewDragger.dragState).toEqual(
|
||||
expect(Overview.overviewDragger.dragState).toEqual(
|
||||
dropDestination: null,
|
||||
attachMethod: '',
|
||||
parentList: null,
|
||||
@@ -214,7 +214,7 @@ define ["js/views/overview", "js/views/feedback_notification", "sinon", "js/base
|
||||
|
||||
it "collapses expanded elements", ->
|
||||
expect($('#subsection-1')).not.toHaveClass('collapsed')
|
||||
OverviewDragger.onDragStart(
|
||||
Overview.overviewDragger.onDragStart(
|
||||
{element: $('#subsection-1')},
|
||||
null,
|
||||
null
|
||||
@@ -233,7 +233,7 @@ define ["js/views/overview", "js/views/feedback_notification", "sinon", "js/base
|
||||
$ele.offset(
|
||||
top: dragY, left: dragX
|
||||
)
|
||||
OverviewDragger.onDragMove(
|
||||
Overview.overviewDragger.onDragMove(
|
||||
{element: $ele, dragPoint:
|
||||
{y: dragY}}, '', {clientX: dragX}
|
||||
)
|
||||
@@ -246,7 +246,7 @@ define ["js/views/overview", "js/views/feedback_notification", "sinon", "js/base
|
||||
$ele.offset(
|
||||
top: dragY, left: $ele.offset().left
|
||||
)
|
||||
OverviewDragger.onDragMove(
|
||||
Overview.overviewDragger.onDragMove(
|
||||
{element: $ele, dragPoint:
|
||||
{y: dragY}}, '', {clientX: $ele.offset().left - 3}
|
||||
)
|
||||
@@ -254,33 +254,33 @@ define ["js/views/overview", "js/views/feedback_notification", "sinon", "js/base
|
||||
expect($ele).not.toHaveClass('valid-drop')
|
||||
|
||||
it "scrolls up if necessary", ->
|
||||
OverviewDragger.onDragMove(
|
||||
Overview.overviewDragger.onDragMove(
|
||||
{element: $('#unit-1')}, '', {clientY: 2}
|
||||
)
|
||||
expect(@scrollSpy).toHaveBeenCalledWith(0, -10)
|
||||
|
||||
it "scrolls down if necessary", ->
|
||||
OverviewDragger.onDragMove(
|
||||
Overview.overviewDragger.onDragMove(
|
||||
{element: $('#unit-1')}, '', {clientY: (window.innerHeight - 5)}
|
||||
)
|
||||
expect(@scrollSpy).toHaveBeenCalledWith(0, 10)
|
||||
|
||||
describe "onDragEnd", ->
|
||||
beforeEach ->
|
||||
@reorderSpy = spyOn(OverviewDragger, 'handleReorder')
|
||||
@reorderSpy = spyOn(Overview.overviewDragger, 'handleReorder')
|
||||
|
||||
afterEach ->
|
||||
@reorderSpy.reset()
|
||||
|
||||
it "calls handleReorder on a successful drag", ->
|
||||
OverviewDragger.dragState.dropDestination = $('#unit-2')
|
||||
OverviewDragger.dragState.attachMethod = "before"
|
||||
OverviewDragger.dragState.parentList = $('#subsection-1')
|
||||
Overview.overviewDragger.dragState.dropDestination = $('#unit-2')
|
||||
Overview.overviewDragger.dragState.attachMethod = "before"
|
||||
Overview.overviewDragger.dragState.parentList = $('#subsection-1')
|
||||
$('#unit-1').offset(
|
||||
top: $('#unit-1').offset().top + 10
|
||||
left: $('#unit-1').offset().left
|
||||
)
|
||||
OverviewDragger.onDragEnd(
|
||||
Overview.overviewDragger.onDragEnd(
|
||||
{element: $('#unit-1')},
|
||||
null,
|
||||
{clientX: $('#unit-1').offset().left}
|
||||
@@ -288,15 +288,15 @@ define ["js/views/overview", "js/views/feedback_notification", "sinon", "js/base
|
||||
expect(@reorderSpy).toHaveBeenCalled()
|
||||
|
||||
it "clears out the drag state", ->
|
||||
OverviewDragger.onDragEnd(
|
||||
Overview.overviewDragger.onDragEnd(
|
||||
{element: $('#unit-1')},
|
||||
null,
|
||||
null
|
||||
)
|
||||
expect(OverviewDragger.dragState).toEqual({})
|
||||
expect(Overview.overviewDragger.dragState).toEqual({})
|
||||
|
||||
it "sets the element to the correct position", ->
|
||||
OverviewDragger.onDragEnd(
|
||||
Overview.overviewDragger.onDragEnd(
|
||||
{element: $('#unit-1')},
|
||||
null,
|
||||
null
|
||||
@@ -308,7 +308,7 @@ define ["js/views/overview", "js/views/feedback_notification", "sinon", "js/base
|
||||
it "expands an element if it was collapsed on drag start", ->
|
||||
$('#subsection-1').addClass('collapsed')
|
||||
$('#subsection-1').addClass('expand-on-drop')
|
||||
OverviewDragger.onDragEnd(
|
||||
Overview.overviewDragger.onDragEnd(
|
||||
{element: $('#subsection-1')},
|
||||
null,
|
||||
null
|
||||
@@ -318,10 +318,10 @@ define ["js/views/overview", "js/views/feedback_notification", "sinon", "js/base
|
||||
|
||||
it "expands a collapsed element when something is dropped in it", ->
|
||||
$('#subsection-2').addClass('collapsed')
|
||||
OverviewDragger.dragState.dropDestination = $('#list-2')
|
||||
OverviewDragger.dragState.attachMethod = "prepend"
|
||||
OverviewDragger.dragState.parentList = $('#subsection-2')
|
||||
OverviewDragger.onDragEnd(
|
||||
Overview.overviewDragger.dragState.dropDestination = $('#list-2')
|
||||
Overview.overviewDragger.dragState.attachMethod = "prepend"
|
||||
Overview.overviewDragger.dragState.parentList = $('#subsection-2')
|
||||
Overview.overviewDragger.onDragEnd(
|
||||
{element: $('#unit-1')},
|
||||
null,
|
||||
{clientX: $('#unit-1').offset().left}
|
||||
@@ -344,15 +344,15 @@ define ["js/views/overview", "js/views/feedback_notification", "sinon", "js/base
|
||||
@clock.restore()
|
||||
|
||||
it "should send an update on reorder", ->
|
||||
OverviewDragger.dragState.dropDestination = $('#unit-4')
|
||||
OverviewDragger.dragState.attachMethod = "after"
|
||||
OverviewDragger.dragState.parentList = $('#subsection-2')
|
||||
Overview.overviewDragger.dragState.dropDestination = $('#unit-4')
|
||||
Overview.overviewDragger.dragState.attachMethod = "after"
|
||||
Overview.overviewDragger.dragState.parentList = $('#subsection-2')
|
||||
# Drag Unit 1 from Subsection 1 to the end of Subsection 2.
|
||||
$('#unit-1').offset(
|
||||
top: $('#unit-4').offset().top + 10
|
||||
left: $('#unit-4').offset().left
|
||||
)
|
||||
OverviewDragger.onDragEnd(
|
||||
Overview.overviewDragger.onDragEnd(
|
||||
{element: $('#unit-1')},
|
||||
null,
|
||||
{clientX: $('#unit-1').offset().left}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
define ["backbone", "jquery", "underscore", "gettext", "xblock/runtime.v1",
|
||||
"js/views/feedback_notification", "js/views/metadata", "js/collections/metadata"
|
||||
"jquery.inputnumber", "xmodule"],
|
||||
(Backbone, $, _, gettext, XBlock, NotificationView, MetadataView, MetadataCollection) ->
|
||||
"js/utils/modal", "jquery.inputnumber", "xmodule"],
|
||||
(Backbone, $, _, gettext, XBlock, NotificationView, MetadataView, MetadataCollection, ModalUtils) ->
|
||||
class ModuleEdit extends Backbone.View
|
||||
tagName: 'li'
|
||||
className: 'component'
|
||||
@@ -87,7 +87,7 @@ define ["backbone", "jquery", "underscore", "gettext", "xblock/runtime.v1",
|
||||
id: _this.model.id
|
||||
|
||||
data.metadata = _.extend(data.metadata || {}, @changedMetadata())
|
||||
@hideModal()
|
||||
ModalUtils.hideModalCover()
|
||||
saving = new NotificationView.Mini
|
||||
title: gettext('Saving…')
|
||||
saving.show()
|
||||
@@ -102,17 +102,12 @@ define ["backbone", "jquery", "underscore", "gettext", "xblock/runtime.v1",
|
||||
event.preventDefault()
|
||||
@$el.removeClass('editing')
|
||||
@$component_editor().slideUp(150)
|
||||
@hideModal()
|
||||
|
||||
hideModal: ->
|
||||
$modalCover = $(".modal-cover")
|
||||
$modalCover.hide()
|
||||
$modalCover.removeClass('is-fixed')
|
||||
ModalUtils.hideModalCover()
|
||||
|
||||
clickEditButton: (event) ->
|
||||
event.preventDefault()
|
||||
@$el.addClass('editing')
|
||||
$(".modal-cover").show().addClass('is-fixed')
|
||||
ModalUtils.showModalCover(true)
|
||||
@$component_editor().slideDown(150)
|
||||
@loadEdit()
|
||||
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
require(["domReady", "jquery", "underscore", "gettext", "js/views/feedback_notification", "js/views/feedback_prompt",
|
||||
"js/utils/cancel_on_escape", "jquery.ui", "jquery.timepicker", "jquery.leanModal", "jquery.form", "jquery.smoothScroll"],
|
||||
function(domReady, $, _, gettext, NotificationView, PromptView, CancelOnEscape) {
|
||||
"js/utils/get_date", "jquery.ui", "jquery.leanModal", "jquery.form", "jquery.smoothScroll"],
|
||||
function(domReady, $, _, gettext, NotificationView, PromptView, DateUtils) {
|
||||
|
||||
var $body;
|
||||
var $modal;
|
||||
var $modalCover;
|
||||
var $newComponentItem;
|
||||
var $changedInput;
|
||||
var $spinner;
|
||||
@@ -14,8 +12,6 @@ var $newComponentButton;
|
||||
|
||||
domReady(function() {
|
||||
$body = $('body');
|
||||
$modal = $('.history-modal');
|
||||
$modalCover = $('.modal-cover');
|
||||
|
||||
$newComponentItem = $('.new-component-item');
|
||||
$newComponentTypePicker = $('.new-component');
|
||||
@@ -23,12 +19,6 @@ domReady(function() {
|
||||
$newComponentButton = $('.new-component-button');
|
||||
$spinner = $('<span class="spinner-in-field-icon"></span>');
|
||||
|
||||
$('.expand-collapse-icon').bind('click', toggleSubmodules);
|
||||
$('.visibility-options').bind('change', setVisibility);
|
||||
|
||||
$modal.bind('click', hideModal);
|
||||
$modalCover.bind('click', hideModal);
|
||||
|
||||
$body.on('click', '.embeddable-xml-input', function() {
|
||||
$(this).select();
|
||||
});
|
||||
@@ -70,7 +60,7 @@ domReady(function() {
|
||||
$('.nav-dd .nav-item .wrapper-nav-sub').removeClass('is-shown');
|
||||
$title.addClass('is-selected');
|
||||
$subnav.addClass('is-shown');
|
||||
// if propogation is not stopped, the event will bubble up to the
|
||||
// if propagation is not stopped, the event will bubble up to the
|
||||
// body element, which will close the dropdown.
|
||||
e.stopPropagation();
|
||||
}
|
||||
@@ -94,14 +84,6 @@ domReady(function() {
|
||||
// tender feedback window scrolling
|
||||
$('a.show-tender').bind('click', smoothScrollTop);
|
||||
|
||||
// toggling overview section details
|
||||
$(function() {
|
||||
if ($('.courseware-section').length > 0) {
|
||||
$('.toggle-button-sections').addClass('is-shown');
|
||||
}
|
||||
});
|
||||
$('.toggle-button-sections').bind('click', toggleSections);
|
||||
|
||||
// autosave when leaving input field
|
||||
$body.on('change', '.subsection-display-name-input', saveSubsection);
|
||||
$('.subsection-display-name-input').each(function() {
|
||||
@@ -113,12 +95,8 @@ domReady(function() {
|
||||
// expand/collapse methods for optional date setters
|
||||
$('.set-date').bind('click', showDateSetter);
|
||||
$('.remove-date').bind('click', removeDateSetter);
|
||||
// add new/delete section
|
||||
$('.new-courseware-section-button').bind('click', addNewSection);
|
||||
$('.delete-section-button').bind('click', deleteSection);
|
||||
|
||||
// add new/delete subsection
|
||||
$('.new-subsection-item').bind('click', addNewSubsection);
|
||||
$('.delete-section-button').bind('click', deleteSection);
|
||||
$('.delete-subsection-button').bind('click', deleteSubsection);
|
||||
|
||||
$('.sync-date').bind('click', syncReleaseDate);
|
||||
@@ -126,12 +104,7 @@ domReady(function() {
|
||||
// section date setting
|
||||
$('.set-publish-date').bind('click', setSectionScheduleDate);
|
||||
$('.edit-section-start-cancel').bind('click', cancelSetSectionScheduleDate);
|
||||
$('.edit-section-start-save').bind('click', saveSetSectionScheduleDate);
|
||||
|
||||
$body.on('click', '.section-published-date .edit-button', editSectionPublishDate);
|
||||
$body.on('click', '.section-published-date .schedule-button', editSectionPublishDate);
|
||||
$body.on('click', '.edit-subsection-publish-settings .save-button', saveSetSectionScheduleDate);
|
||||
$body.on('click', '.edit-subsection-publish-settings .cancel-button', hideModal);
|
||||
$body.on('change', '.edit-subsection-publish-settings .start-date', function() {
|
||||
if ($('.edit-subsection-publish-settings').find('.start-time').val() == '') {
|
||||
$('.edit-subsection-publish-settings').find('.start-time').val('12:00am');
|
||||
@@ -171,44 +144,6 @@ function linkNewWindow(e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
function toggleSections(e) {
|
||||
e.preventDefault();
|
||||
|
||||
$section = $('.courseware-section');
|
||||
sectionCount = $section.length;
|
||||
$button = $(this);
|
||||
$labelCollapsed = $('<i class="icon-arrow-up"></i> <span class="label">' +
|
||||
gettext('Collapse All Sections') + '</span>');
|
||||
$labelExpanded = $('<i class="icon-arrow-down"></i> <span class="label">' +
|
||||
gettext('Expand All Sections') + '</span>');
|
||||
|
||||
var buttonLabel = $button.hasClass('is-activated') ? $labelCollapsed : $labelExpanded;
|
||||
$button.toggleClass('is-activated').html(buttonLabel);
|
||||
|
||||
if ($button.hasClass('is-activated')) {
|
||||
$section.addClass('collapsed');
|
||||
// first child in order to avoid the icons on the subsection lists which are not in the first child
|
||||
$section.find('header .expand-collapse-icon').removeClass('collapse').addClass('expand');
|
||||
} else {
|
||||
$section.removeClass('collapsed');
|
||||
// first child in order to avoid the icons on the subsection lists which are not in the first child
|
||||
$section.find('header .expand-collapse-icon').removeClass('expand').addClass('collapse');
|
||||
}
|
||||
}
|
||||
|
||||
function editSectionPublishDate(e) {
|
||||
e.preventDefault();
|
||||
$modal = $('.edit-subsection-publish-settings').show();
|
||||
$modal.attr('data-id', $(this).attr('data-id'));
|
||||
$modal.find('.start-date').val($(this).attr('data-date'));
|
||||
$modal.find('.start-time').val($(this).attr('data-time'));
|
||||
if ($modal.find('.start-date').val() == '' && $modal.find('.start-time').val() == '') {
|
||||
$modal.find('.save-button').hide();
|
||||
}
|
||||
$modal.find('.section-name').html('"' + $(this).closest('.courseware-section').find('.section-name-span').text() + '"');
|
||||
$modalCover.show();
|
||||
}
|
||||
|
||||
function syncReleaseDate(e) {
|
||||
e.preventDefault();
|
||||
$(this).closest('.notice').hide();
|
||||
@@ -216,21 +151,6 @@ function syncReleaseDate(e) {
|
||||
$("#start_time").val("");
|
||||
}
|
||||
|
||||
function getDatetime(datepickerInput, timepickerInput) {
|
||||
// given a pair of inputs (datepicker and timepicker), return a JS Date
|
||||
// object that corresponds to the datetime that they represent. Assume
|
||||
// UTC timezone, NOT the timezone of the user's browser.
|
||||
var date = $(datepickerInput).datepicker("getDate");
|
||||
var time = $(timepickerInput).timepicker("getTime");
|
||||
if(date && time) {
|
||||
return new Date(Date.UTC(
|
||||
date.getFullYear(), date.getMonth(), date.getDate(),
|
||||
time.getHours(), time.getMinutes()
|
||||
));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function autosaveInput(e) {
|
||||
var self = this;
|
||||
@@ -272,7 +192,7 @@ function saveSubsection() {
|
||||
// get datetimes for start and due, stick into metadata
|
||||
_(["start", "due"]).each(function(name) {
|
||||
|
||||
var datetime = getDatetime(
|
||||
var datetime = DateUtils(
|
||||
document.getElementById(name+"_date"),
|
||||
document.getElementById(name+"_time")
|
||||
);
|
||||
@@ -381,30 +301,6 @@ function _deleteItem($el, type) {
|
||||
confirm.show();
|
||||
}
|
||||
|
||||
function hideModal(e) {
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
// Unit editors do not want the modal cover to hide when users click outside
|
||||
// of the editor. Users must press Cancel or Save to exit the editor.
|
||||
// module_edit adds and removes the "is-fixed" class.
|
||||
if (!$modalCover.hasClass("is-fixed")) {
|
||||
$(".modal, .edit-subsection-publish-settings").hide();
|
||||
$modalCover.hide();
|
||||
}
|
||||
}
|
||||
|
||||
function toggleSubmodules(e) {
|
||||
e.preventDefault();
|
||||
$(this).toggleClass('expand').toggleClass('collapse');
|
||||
$(this).closest('.branch, .window').toggleClass('collapsed');
|
||||
}
|
||||
|
||||
function setVisibility(e) {
|
||||
$(this).find('.checked').removeClass('checked');
|
||||
$(e.target).closest('.option').addClass('checked');
|
||||
}
|
||||
|
||||
function showDateSetter(e) {
|
||||
e.preventDefault();
|
||||
var $block = $(this).closest('.due-date-input');
|
||||
@@ -422,7 +318,6 @@ function removeDateSetter(e) {
|
||||
$block.find('.time').val('');
|
||||
}
|
||||
|
||||
|
||||
function hideNotification(e) {
|
||||
(e).preventDefault();
|
||||
$(this).closest('.wrapper-notification').removeClass('is-shown').addClass('is-hiding').attr('aria-hidden', 'true');
|
||||
@@ -433,101 +328,6 @@ function hideAlert(e) {
|
||||
$(this).closest('.wrapper-alert').removeClass('is-shown');
|
||||
}
|
||||
|
||||
function addNewSection(e) {
|
||||
e.preventDefault();
|
||||
|
||||
$(e.target).addClass('disabled');
|
||||
|
||||
var $newSection = $($('#new-section-template').html());
|
||||
var $cancelButton = $newSection.find('.new-section-name-cancel');
|
||||
$('.courseware-overview').prepend($newSection);
|
||||
$newSection.find('.new-section-name').focus().select();
|
||||
$newSection.find('.section-name-form').bind('submit', saveNewSection);
|
||||
$cancelButton.bind('click', cancelNewSection);
|
||||
CancelOnEscape($cancelButton);
|
||||
}
|
||||
|
||||
function saveNewSection(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var $saveButton = $(this).find('.new-section-name-save');
|
||||
var parent = $saveButton.data('parent');
|
||||
var category = $saveButton.data('category');
|
||||
var display_name = $(this).find('.new-section-name').val();
|
||||
|
||||
analytics.track('Created a Section', {
|
||||
'course': course_location_analytics,
|
||||
'display_name': display_name
|
||||
});
|
||||
|
||||
$.post('/create_item', {
|
||||
'parent_location': parent,
|
||||
'category': category,
|
||||
'display_name': display_name
|
||||
},
|
||||
|
||||
function(data) {
|
||||
if (data.id != undefined) location.reload();
|
||||
});
|
||||
}
|
||||
|
||||
function cancelNewSection(e) {
|
||||
e.preventDefault();
|
||||
$('.new-courseware-section-button').removeClass('disabled');
|
||||
$(this).parents('section.new-section').remove();
|
||||
}
|
||||
|
||||
function addNewSubsection(e) {
|
||||
e.preventDefault();
|
||||
var $section = $(this).closest('.courseware-section');
|
||||
var $newSubsection = $($('#new-subsection-template').html());
|
||||
$section.find('.subsection-list > ol').append($newSubsection);
|
||||
$section.find('.new-subsection-name-input').focus().select();
|
||||
|
||||
var $saveButton = $newSubsection.find('.new-subsection-name-save');
|
||||
var $cancelButton = $newSubsection.find('.new-subsection-name-cancel');
|
||||
|
||||
var parent = $(this).parents("section.branch").data("id");
|
||||
|
||||
$saveButton.data('parent', parent);
|
||||
$saveButton.data('category', $(this).data('category'));
|
||||
|
||||
$newSubsection.find('.new-subsection-form').bind('submit', saveNewSubsection);
|
||||
$cancelButton.bind('click', cancelNewSubsection);
|
||||
CancelOnEscape($cancelButton);
|
||||
}
|
||||
|
||||
function saveNewSubsection(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var parent = $(this).find('.new-subsection-name-save').data('parent');
|
||||
var category = $(this).find('.new-subsection-name-save').data('category');
|
||||
var display_name = $(this).find('.new-subsection-name-input').val();
|
||||
|
||||
analytics.track('Created a Subsection', {
|
||||
'course': course_location_analytics,
|
||||
'display_name': display_name
|
||||
});
|
||||
|
||||
|
||||
$.post('/create_item', {
|
||||
'parent_location': parent,
|
||||
'category': category,
|
||||
'display_name': display_name
|
||||
},
|
||||
|
||||
function(data) {
|
||||
if (data.id != undefined) {
|
||||
location.reload();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function cancelNewSubsection(e) {
|
||||
e.preventDefault();
|
||||
$(this).parents('li.branch').remove();
|
||||
}
|
||||
|
||||
function setSectionScheduleDate(e) {
|
||||
e.preventDefault();
|
||||
$(this).closest("h4").hide();
|
||||
@@ -540,65 +340,6 @@ function cancelSetSectionScheduleDate(e) {
|
||||
$(this).parent().siblings("h4").show();
|
||||
}
|
||||
|
||||
function saveSetSectionScheduleDate(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var datetime = getDatetime(
|
||||
$('.edit-subsection-publish-settings .start-date'),
|
||||
$('.edit-subsection-publish-settings .start-time')
|
||||
);
|
||||
|
||||
var id = $modal.attr('data-id');
|
||||
|
||||
analytics.track('Edited Section Release Date', {
|
||||
'course': course_location_analytics,
|
||||
'id': id,
|
||||
'start': datetime
|
||||
});
|
||||
|
||||
var saving = new NotificationView.Mini({
|
||||
title: gettext("Saving…")
|
||||
});
|
||||
saving.show();
|
||||
// call into server to commit the new order
|
||||
$.ajax({
|
||||
url: "/save_item",
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
contentType: "application/json",
|
||||
data: JSON.stringify({
|
||||
'id': id,
|
||||
'metadata': {
|
||||
'start': datetime
|
||||
}
|
||||
})
|
||||
}).success(function() {
|
||||
var pad2 = function(number) {
|
||||
// pad a number to two places: useful for formatting months, days, hours, etc
|
||||
// when displaying a date/time
|
||||
return (number < 10 ? '0' : '') + number;
|
||||
};
|
||||
|
||||
var $thisSection = $('.courseware-section[data-id="' + id + '"]');
|
||||
var html = _.template(
|
||||
'<span class="published-status">' +
|
||||
'<strong>' + gettext("Will Release:") + ' </strong>' +
|
||||
gettext("{month}/{day}/{year} at {hour}:{minute} UTC") +
|
||||
'</span>' +
|
||||
'<a href="#" class="edit-button" data-date="{month}/{day}/{year}" data-time="{hour}:{minute}" data-id="{id}">' +
|
||||
gettext("Edit") +
|
||||
'</a>',
|
||||
{year: datetime.getUTCFullYear(), month: pad2(datetime.getUTCMonth() + 1), day: pad2(datetime.getUTCDate()),
|
||||
hour: pad2(datetime.getUTCHours()), minute: pad2(datetime.getUTCMinutes()),
|
||||
id: id},
|
||||
{interpolate: /\{(.+?)\}/g});
|
||||
$thisSection.find('.section-published-date').html(html);
|
||||
hideModal();
|
||||
saving.hide();
|
||||
});
|
||||
}
|
||||
// Add to window object for unit test (overview_spec).
|
||||
window.saveSetSectionScheduleDate = saveSetSectionScheduleDate;
|
||||
window.deleteSection = deleteSection;
|
||||
|
||||
}); // end require()
|
||||
|
||||
18
cms/static/js/utils/get_date.js
Normal file
18
cms/static/js/utils/get_date.js
Normal file
@@ -0,0 +1,18 @@
|
||||
define(["jquery", "jquery.ui", "jquery.timepicker"], function($) {
|
||||
var getDate = function (datepickerInput, timepickerInput) {
|
||||
// given a pair of inputs (datepicker and timepicker), return a JS Date
|
||||
// object that corresponds to the datetime.js that they represent. Assume
|
||||
// UTC timezone, NOT the timezone of the user's browser.
|
||||
var date = $(datepickerInput).datepicker("getDate");
|
||||
var time = $(timepickerInput).timepicker("getTime");
|
||||
if(date && time) {
|
||||
return new Date(Date.UTC(
|
||||
date.getFullYear(), date.getMonth(), date.getDate(),
|
||||
time.getHours(), time.getMinutes()
|
||||
));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
return getDate;
|
||||
});
|
||||
83
cms/static/js/utils/modal.js
Normal file
83
cms/static/js/utils/modal.js
Normal file
@@ -0,0 +1,83 @@
|
||||
define(["jquery"], function($) {
|
||||
/**
|
||||
* Hides the modal and modal cover, using the standard selectors.
|
||||
* Note though that the class "is-fixed" on the modal cover
|
||||
* prevents the closing operation.
|
||||
*/
|
||||
var hideModal = function(e) {
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
var $modalCover = getModalCover();
|
||||
|
||||
// Unit editors (module_edit) do not want the modal cover to hide when users click outside
|
||||
// of the editor. Users must press Cancel or Save to exit the editor.
|
||||
if (!$modalCover.hasClass("is-fixed")) {
|
||||
getModal().hide();
|
||||
hideModalCover($modalCover);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Hides just the modal cover. Caller can pass in a specific
|
||||
* element as the modal cover, otherwise the standard selector will be used.
|
||||
*
|
||||
* This method also unbinds the click handler on the modal cover.
|
||||
*/
|
||||
var hideModalCover = function (modalCover) {
|
||||
if (modalCover == undefined) {
|
||||
modalCover = getModalCover();
|
||||
}
|
||||
modalCover.hide();
|
||||
modalCover.removeClass("is-fixed");
|
||||
modalCover.unbind('click');
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows the modal and modal cover, using the standard selectors.
|
||||
*/
|
||||
var showModal = function () {
|
||||
getModal().show();
|
||||
showModalCover();
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows just the modal cover. The caller can optionally choose
|
||||
* to have the class "is-fixed" added to the cover, and
|
||||
* the user can also choose to specify a custom click handler
|
||||
* for the modal cover.
|
||||
*
|
||||
* This method returns the modal cover element.
|
||||
*/
|
||||
var showModalCover = function(addFixed, clickHandler) {
|
||||
var $modalCover = getModalCover();
|
||||
$modalCover.show();
|
||||
if (addFixed) {
|
||||
$modalCover.addClass("is-fixed");
|
||||
}
|
||||
$modalCover.unbind('click');
|
||||
if (clickHandler) {
|
||||
$modalCover.bind('click', clickHandler);
|
||||
}
|
||||
else {
|
||||
$modalCover.bind('click', hideModal);
|
||||
}
|
||||
return $modalCover;
|
||||
};
|
||||
|
||||
var getModalCover = function () {
|
||||
return $('.modal-cover');
|
||||
};
|
||||
|
||||
var getModal = function () {
|
||||
return $(".modal, .showAsModal");
|
||||
};
|
||||
|
||||
return {
|
||||
showModal: showModal,
|
||||
hideModal: hideModal,
|
||||
showModalCover: showModalCover,
|
||||
hideModalCover: hideModalCover
|
||||
};
|
||||
});
|
||||
@@ -1,7 +1,6 @@
|
||||
define(["backbone", "underscore", "codemirror", "js/views/feedback_notification", "js/views/course_info_helper"],
|
||||
function(Backbone, _, CodeMirror, NotificationView, CourseInfoHelper) {
|
||||
define(["backbone", "underscore", "codemirror", "js/views/feedback_notification", "js/views/course_info_helper", "js/utils/modal"],
|
||||
function(Backbone, _, CodeMirror, NotificationView, CourseInfoHelper, ModalUtils) {
|
||||
|
||||
var $modalCover = $(".modal-cover");
|
||||
// the handouts view is dumb right now; it needs tied to a model and all that jazz
|
||||
var CourseInfoHandoutsView = Backbone.View.extend({
|
||||
// collection is CourseUpdateCollection
|
||||
@@ -47,10 +46,7 @@ define(["backbone", "underscore", "codemirror", "js/views/feedback_notification"
|
||||
this.$codeMirror = CourseInfoHelper.editWithCodeMirror(
|
||||
self.model, 'data', self.options['base_asset_url'], this.$editor.get(0));
|
||||
|
||||
$modalCover.show();
|
||||
$modalCover.bind('click', function() {
|
||||
self.closeEditor();
|
||||
});
|
||||
ModalUtils.showModalCover(false, function() { self.closeEditor() });
|
||||
},
|
||||
|
||||
onSave: function(event) {
|
||||
@@ -81,8 +77,7 @@ define(["backbone", "underscore", "codemirror", "js/views/feedback_notification"
|
||||
|
||||
closeEditor: function() {
|
||||
this.$form.hide();
|
||||
$modalCover.unbind('click');
|
||||
$modalCover.hide();
|
||||
ModalUtils.hideModalCover();
|
||||
this.$form.find('.CodeMirror').remove();
|
||||
this.$codeMirror = null;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
define(["backbone", "underscore", "codemirror", "js/models/course_update",
|
||||
"js/views/feedback_prompt", "js/views/feedback_notification", "js/views/course_info_helper"],
|
||||
function(Backbone, _, CodeMirror, CourseUpdateModel, PromptView, NotificationView, CourseInfoHelper) {
|
||||
"js/views/feedback_prompt", "js/views/feedback_notification", "js/views/course_info_helper", "js/utils/modal"],
|
||||
function(Backbone, _, CodeMirror, CourseUpdateModel, PromptView, NotificationView, CourseInfoHelper, ModalUtils) {
|
||||
|
||||
var CourseInfoUpdateView = Backbone.View.extend({
|
||||
// collection is CourseUpdateCollection
|
||||
@@ -17,8 +17,6 @@ define(["backbone", "underscore", "codemirror", "js/models/course_update",
|
||||
this.render();
|
||||
// when the client refetches the updates as a whole, re-render them
|
||||
this.listenTo(this.collection, 'reset', this.render);
|
||||
|
||||
this.$modalCover = $(".modal-cover");
|
||||
},
|
||||
|
||||
render: function () {
|
||||
@@ -64,9 +62,9 @@ define(["backbone", "underscore", "codemirror", "js/models/course_update",
|
||||
$newForm.addClass('editing');
|
||||
this.$currentPost = $newForm.closest('li');
|
||||
|
||||
this.$modalCover.show();
|
||||
this.$modalCover.bind('click', function() {
|
||||
self.closeEditor(true);
|
||||
// Variable stored for unit test.
|
||||
this.$modalCover = ModalUtils.showModalCover(false, function() {
|
||||
self.closeEditor(true)
|
||||
});
|
||||
|
||||
$('.date').datepicker('destroy');
|
||||
@@ -91,7 +89,7 @@ define(["backbone", "underscore", "codemirror", "js/models/course_update",
|
||||
ele.remove();
|
||||
}
|
||||
});
|
||||
this.closeEditor();
|
||||
this.closeEditor(false);
|
||||
|
||||
analytics.track('Saved Course Update', {
|
||||
'course': course_location_analytics,
|
||||
@@ -121,10 +119,12 @@ define(["backbone", "underscore", "codemirror", "js/models/course_update",
|
||||
this.$codeMirror = CourseInfoHelper.editWithCodeMirror(
|
||||
targetModel, 'content', self.options['base_asset_url'], $textArea.get(0));
|
||||
|
||||
this.$modalCover.show();
|
||||
this.$modalCover.bind('click', function() {
|
||||
self.closeEditor(false);
|
||||
});
|
||||
// Variable stored for unit test.
|
||||
this.$modalCover = ModalUtils.showModalCover(false,
|
||||
function() {
|
||||
self.closeEditor(false)
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
onDelete: function(event) {
|
||||
@@ -198,8 +198,7 @@ define(["backbone", "underscore", "codemirror", "js/models/course_update",
|
||||
this.$currentPost.find('.CodeMirror').remove();
|
||||
}
|
||||
|
||||
this.$modalCover.unbind('click');
|
||||
this.$modalCover.hide();
|
||||
ModalUtils.hideModalCover(this.$modalCover);
|
||||
this.$codeMirror = null;
|
||||
},
|
||||
|
||||
|
||||
@@ -1,5 +1,204 @@
|
||||
define(["domReady", "jquery", "jquery.ui", "gettext", "js/views/feedback_notification", "draggabilly"],
|
||||
function (domReady, $, ui, gettext, NotificationView, Draggabilly) {
|
||||
define(["domReady", "jquery", "jquery.ui", "underscore", "gettext", "js/views/feedback_notification", "draggabilly",
|
||||
"js/utils/modal", "js/utils/cancel_on_escape", "js/utils/get_date"],
|
||||
function (domReady, $, ui, _, gettext, NotificationView, Draggabilly, ModalUtils, CancelOnEscape, DateUtils) {
|
||||
|
||||
var modalSelector = '.edit-subsection-publish-settings';
|
||||
|
||||
var toggleSections = function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
var $section = $('.courseware-section');
|
||||
var $button = $(this);
|
||||
var $labelCollapsed = $('<i class="icon-arrow-up"></i> <span class="label">' +
|
||||
gettext('Collapse All Sections') + '</span>');
|
||||
var $labelExpanded = $('<i class="icon-arrow-down"></i> <span class="label">' +
|
||||
gettext('Expand All Sections') + '</span>');
|
||||
|
||||
var buttonLabel = $button.hasClass('is-activated') ? $labelCollapsed : $labelExpanded;
|
||||
$button.toggleClass('is-activated').html(buttonLabel);
|
||||
|
||||
if ($button.hasClass('is-activated')) {
|
||||
$section.addClass('collapsed');
|
||||
// first child in order to avoid the icons on the subsection lists which are not in the first child
|
||||
$section.find('header .expand-collapse-icon').removeClass('collapse').addClass('expand');
|
||||
} else {
|
||||
$section.removeClass('collapsed');
|
||||
// first child in order to avoid the icons on the subsection lists which are not in the first child
|
||||
$section.find('header .expand-collapse-icon').removeClass('expand').addClass('collapse');
|
||||
}
|
||||
};
|
||||
|
||||
var toggleSubmodules = function(e) {
|
||||
e.preventDefault();
|
||||
$(this).toggleClass('expand').toggleClass('collapse');
|
||||
$(this).closest('.branch, .window').toggleClass('collapsed');
|
||||
};
|
||||
|
||||
var editSectionPublishDate = function (e) {
|
||||
e.preventDefault();
|
||||
var $modal = $(modalSelector);
|
||||
$modal.attr('data-id', $(this).attr('data-id'));
|
||||
$modal.find('.start-date').val($(this).attr('data-date'));
|
||||
$modal.find('.start-time').val($(this).attr('data-time'));
|
||||
if ($modal.find('.start-date').val() == '' && $modal.find('.start-time').val() == '') {
|
||||
$modal.find('.save-button').hide();
|
||||
}
|
||||
$modal.find('.section-name').html('"' + $(this).closest('.courseware-section').find('.section-name-span').text() + '"');
|
||||
ModalUtils.showModal();
|
||||
};
|
||||
|
||||
var saveSetSectionScheduleDate = function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
var datetime = DateUtils(
|
||||
$('.edit-subsection-publish-settings .start-date'),
|
||||
$('.edit-subsection-publish-settings .start-time')
|
||||
);
|
||||
|
||||
var id = $(modalSelector).attr('data-id');
|
||||
|
||||
analytics.track('Edited Section Release Date', {
|
||||
'course': course_location_analytics,
|
||||
'id': id,
|
||||
'start': datetime
|
||||
});
|
||||
|
||||
var saving = new NotificationView.Mini({
|
||||
title: gettext("Saving…")
|
||||
});
|
||||
saving.show();
|
||||
// call into server to commit the new order
|
||||
$.ajax({
|
||||
url: "/save_item",
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
contentType: "application/json",
|
||||
data: JSON.stringify({
|
||||
'id': id,
|
||||
'metadata': {
|
||||
'start': datetime
|
||||
}
|
||||
})
|
||||
}).success(function() {
|
||||
var pad2 = function(number) {
|
||||
// pad a number to two places: useful for formatting months, days, hours, etc
|
||||
// when displaying a date/time
|
||||
return (number < 10 ? '0' : '') + number;
|
||||
};
|
||||
|
||||
var $thisSection = $('.courseware-section[data-id="' + id + '"]');
|
||||
var html = _.template(
|
||||
'<span class="published-status">' +
|
||||
'<strong>' + gettext("Will Release:") + ' </strong>' +
|
||||
gettext("{month}/{day}/{year} at {hour}:{minute} UTC") +
|
||||
'</span>' +
|
||||
'<a href="#" class="edit-button" data-date="{month}/{day}/{year}" data-time="{hour}:{minute}" data-id="{id}">' +
|
||||
gettext("Edit") +
|
||||
'</a>',
|
||||
{year: datetime.getUTCFullYear(), month: pad2(datetime.getUTCMonth() + 1), day: pad2(datetime.getUTCDate()),
|
||||
hour: pad2(datetime.getUTCHours()), minute: pad2(datetime.getUTCMinutes()),
|
||||
id: id},
|
||||
{interpolate: /\{(.+?)\}/g});
|
||||
$thisSection.find('.section-published-date').html(html);
|
||||
ModalUtils.hideModal();
|
||||
saving.hide();
|
||||
});
|
||||
};
|
||||
|
||||
var addNewSection = function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
$(e.target).addClass('disabled');
|
||||
|
||||
var $newSection = $($('#new-section-template').html());
|
||||
var $cancelButton = $newSection.find('.new-section-name-cancel');
|
||||
$('.courseware-overview').prepend($newSection);
|
||||
$newSection.find('.new-section-name').focus().select();
|
||||
$newSection.find('.section-name-form').bind('submit', saveNewSection);
|
||||
$cancelButton.bind('click', cancelNewSection);
|
||||
CancelOnEscape($cancelButton);
|
||||
};
|
||||
|
||||
var saveNewSection = function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
var $saveButton = $(this).find('.new-section-name-save');
|
||||
var parent = $saveButton.data('parent');
|
||||
var category = $saveButton.data('category');
|
||||
var display_name = $(this).find('.new-section-name').val();
|
||||
|
||||
analytics.track('Created a Section', {
|
||||
'course': course_location_analytics,
|
||||
'display_name': display_name
|
||||
});
|
||||
|
||||
$.post('/create_item', {
|
||||
'parent_location': parent,
|
||||
'category': category,
|
||||
'display_name': display_name
|
||||
},
|
||||
|
||||
function(data) {
|
||||
if (data.id != undefined) location.reload();
|
||||
});
|
||||
};
|
||||
|
||||
var cancelNewSection = function (e) {
|
||||
e.preventDefault();
|
||||
$('.new-courseware-section-button').removeClass('disabled');
|
||||
$(this).parents('section.new-section').remove();
|
||||
};
|
||||
|
||||
var addNewSubsection = function (e) {
|
||||
e.preventDefault();
|
||||
var $section = $(this).closest('.courseware-section');
|
||||
var $newSubsection = $($('#new-subsection-template').html());
|
||||
$section.find('.subsection-list > ol').append($newSubsection);
|
||||
$section.find('.new-subsection-name-input').focus().select();
|
||||
|
||||
var $saveButton = $newSubsection.find('.new-subsection-name-save');
|
||||
var $cancelButton = $newSubsection.find('.new-subsection-name-cancel');
|
||||
|
||||
var parent = $(this).parents("section.branch").data("id");
|
||||
|
||||
$saveButton.data('parent', parent);
|
||||
$saveButton.data('category', $(this).data('category'));
|
||||
|
||||
$newSubsection.find('.new-subsection-form').bind('submit', saveNewSubsection);
|
||||
$cancelButton.bind('click', cancelNewSubsection);
|
||||
CancelOnEscape($cancelButton);
|
||||
};
|
||||
|
||||
var saveNewSubsection = function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
var parent = $(this).find('.new-subsection-name-save').data('parent');
|
||||
var category = $(this).find('.new-subsection-name-save').data('category');
|
||||
var display_name = $(this).find('.new-subsection-name-input').val();
|
||||
|
||||
analytics.track('Created a Subsection', {
|
||||
'course': course_location_analytics,
|
||||
'display_name': display_name
|
||||
});
|
||||
|
||||
|
||||
$.post('/create_item', {
|
||||
'parent_location': parent,
|
||||
'category': category,
|
||||
'display_name': display_name
|
||||
},
|
||||
|
||||
function(data) {
|
||||
if (data.id != undefined) {
|
||||
location.reload();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var cancelNewSubsection = function (e) {
|
||||
e.preventDefault();
|
||||
$(this).parents('li.branch').remove();
|
||||
};
|
||||
|
||||
var overviewDragger = {
|
||||
droppableClasses: 'drop-target drop-target-prepend drop-target-before drop-target-after',
|
||||
@@ -295,6 +494,24 @@ define(["domReady", "jquery", "jquery.ui", "gettext", "js/views/feedback_notific
|
||||
};
|
||||
|
||||
domReady(function() {
|
||||
// toggling overview section details
|
||||
$(function() {
|
||||
if ($('.courseware-section').length > 0) {
|
||||
$('.toggle-button-sections').addClass('is-shown');
|
||||
}
|
||||
});
|
||||
$('.toggle-button-sections').bind('click', toggleSections);
|
||||
$('.expand-collapse-icon').bind('click', toggleSubmodules);
|
||||
|
||||
var $body = $('body');
|
||||
$body.on('click', '.section-published-date .edit-button', editSectionPublishDate);
|
||||
$body.on('click', '.section-published-date .schedule-button', editSectionPublishDate);
|
||||
$body.on('click', '.edit-subsection-publish-settings .save-button', saveSetSectionScheduleDate);
|
||||
$body.on('click', '.edit-subsection-publish-settings .cancel-button', ModalUtils.hideModal);
|
||||
|
||||
$('.new-courseware-section-button').bind('click', addNewSection);
|
||||
$('.new-subsection-item').bind('click', addNewSubsection);
|
||||
|
||||
// Section
|
||||
overviewDragger.makeDraggable(
|
||||
'.courseware-section',
|
||||
@@ -318,5 +535,8 @@ define(["domReady", "jquery", "jquery.ui", "gettext", "js/views/feedback_notific
|
||||
);
|
||||
});
|
||||
|
||||
return overviewDragger;
|
||||
return {
|
||||
overviewDragger: overviewDragger,
|
||||
saveSetSectionScheduleDate: saveSetSectionScheduleDate
|
||||
};
|
||||
});
|
||||
|
||||
@@ -18,29 +18,25 @@
|
||||
<script type="text/javascript">
|
||||
require(["domReady", "jquery", "gettext", "js/models/asset", "js/collections/asset",
|
||||
"js/views/assets", "js/views/feedback_prompt",
|
||||
"js/views/feedback_notification", "jquery.fileupload"],
|
||||
function(domReady, $, gettext, AssetModel, AssetCollection, AssetsView, PromptView, NotificationView) {
|
||||
"js/views/feedback_notification", "js/utils/modal", "jquery.fileupload"],
|
||||
function(domReady, $, gettext, AssetModel, AssetCollection, AssetsView, PromptView, NotificationView, ModalUtils) {
|
||||
|
||||
var assets = new AssetCollection(${asset_list});
|
||||
assets.url = "${update_asset_callback_url}";
|
||||
var assetsView = new AssetsView({collection: assets, el: $('#asset_table_body')});
|
||||
var $modal = $(".upload-modal");
|
||||
var $modalCover = $(".modal-cover");
|
||||
|
||||
|
||||
var hideModal = function (e) {
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
$('.file-input').unbind('change.startUpload');
|
||||
$modal.hide();
|
||||
$modalCover.hide();
|
||||
}
|
||||
ModalUtils.hideModal();
|
||||
};
|
||||
|
||||
var showUploadModal = function (e) {
|
||||
e.preventDefault();
|
||||
resetUploadModal();
|
||||
$modal.show();
|
||||
ModalUtils.showModal();
|
||||
$('.file-input').bind('change', startUpload);
|
||||
$('.upload-modal .file-chooser').fileupload({
|
||||
dataType: 'json',
|
||||
@@ -63,8 +59,6 @@ require(["domReady", "jquery", "gettext", "js/models/asset", "js/collections/ass
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
$modalCover.show();
|
||||
};
|
||||
|
||||
var showFileSelectionMenu = function(e) {
|
||||
|
||||
@@ -225,7 +225,7 @@ require(["domReady!", "jquery", "js/models/location", "js/models/section", "js/v
|
||||
</div>
|
||||
<footer></footer>
|
||||
|
||||
<div class="edit-subsection-publish-settings">
|
||||
<div class="edit-subsection-publish-settings showAsModal">
|
||||
<div class="settings">
|
||||
<h3>${_("Section Release Date")}</h3>
|
||||
<div class="picker datepair">
|
||||
|
||||
Reference in New Issue
Block a user