Store the expanded locators on the page.
STUD-2038
This commit is contained in:
@@ -277,7 +277,11 @@ define(["jquery", "jquery.ui", "underscore", "gettext", "js/views/feedback_notif
|
||||
|
||||
refreshParent = function (element) {
|
||||
var refresh = element.data('refresh');
|
||||
if (_.isFunction(refresh)) { refresh(); }
|
||||
// If drop was into a collapsed parent, the parent will have been
|
||||
// expanded. Views using this class may need to track the
|
||||
// collapse/expand state, so send it with the refresh callback.
|
||||
var collapsed = element.hasClass(this.collapsedClass);
|
||||
if (_.isFunction(refresh)) { refresh(collapsed); }
|
||||
|
||||
};
|
||||
// If the parent has changed, update the children of the old parent.
|
||||
|
||||
@@ -24,12 +24,7 @@ define(["jquery", "underscore", "js/views/xblock_outline", "js/views/utils/view_
|
||||
},
|
||||
|
||||
shouldExpandChildren: function() {
|
||||
// Expand the children if this xblock's locator is in the initially expanded state
|
||||
if (this.initialState && _.contains(this.initialState.expanded_locators, this.model.id)) {
|
||||
return true;
|
||||
}
|
||||
// Only expand the course and its chapters (aka sections) initially
|
||||
return this.model.isCourse() || this.model.isChapter();
|
||||
return this.expandedLocators.contains(this.model.get('id'));
|
||||
},
|
||||
|
||||
shouldRenderChildren: function() {
|
||||
@@ -42,22 +37,12 @@ define(["jquery", "underscore", "js/views/xblock_outline", "js/views/utils/view_
|
||||
model: xblockInfo,
|
||||
parentInfo: parentInfo,
|
||||
initialState: this.initialState,
|
||||
expandedLocators: this.expandedLocators,
|
||||
template: this.template,
|
||||
parentView: parentView || this
|
||||
});
|
||||
},
|
||||
|
||||
getExpandedLocators: function() {
|
||||
var expandedLocators = [];
|
||||
this.$('.outline-item.is-collapsible').each(function(index, rawElement) {
|
||||
var element = $(rawElement);
|
||||
if (!element.hasClass('is-collapsed')) {
|
||||
expandedLocators.push(element.data('locator'));
|
||||
}
|
||||
});
|
||||
return expandedLocators;
|
||||
},
|
||||
|
||||
/**
|
||||
* Refresh the containing section (if there is one) or else refresh the entire course.
|
||||
* Note that the refresh will preserve the expanded state of this view and all of its
|
||||
@@ -76,13 +61,26 @@ define(["jquery", "underscore", "js/views/xblock_outline", "js/views/utils/view_
|
||||
};
|
||||
|
||||
view = getViewToRefresh(this);
|
||||
expandedLocators = view.getExpandedLocators();
|
||||
viewState = viewState || {};
|
||||
viewState.expanded_locators = expandedLocators.concat(viewState.expanded_locators || []);
|
||||
view.initialState = viewState;
|
||||
return view.model.fetch({});
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates the collapse/expand state for this outline element, and then calls refresh.
|
||||
* @param isCollapsed true if the element should be collapsed, else false
|
||||
*/
|
||||
refreshWithCollapsedState: function(isCollapsed) {
|
||||
var locator = this.model.get('id');
|
||||
if (isCollapsed) {
|
||||
this.expandedLocators.remove(locator);
|
||||
}
|
||||
else {
|
||||
this.expandedLocators.add(locator);
|
||||
}
|
||||
this.refresh();
|
||||
},
|
||||
|
||||
onChildAdded: function(locator, category, event) {
|
||||
if (category === 'vertical') {
|
||||
// For units, redirect to the new unit's page in inline edit mode
|
||||
@@ -113,6 +111,7 @@ define(["jquery", "underscore", "js/views/xblock_outline", "js/views/utils/view_
|
||||
sectionInfo.fetch().done(function() {
|
||||
sectionView = self.createChildView(sectionInfo, self.model, self);
|
||||
sectionView.initialState = initialState;
|
||||
sectionView.expandedLocators = self.expandedLocators;
|
||||
sectionView.render();
|
||||
self.addChildView(sectionView);
|
||||
sectionView.setViewState(initialState);
|
||||
@@ -136,10 +135,10 @@ define(["jquery", "underscore", "js/views/xblock_outline", "js/views/utils/view_
|
||||
},
|
||||
|
||||
createNewItemViewState: function(locator, scrollOffset) {
|
||||
this.expandedLocators.add(locator);
|
||||
return {
|
||||
locator_to_show: locator,
|
||||
edit_display_name: true,
|
||||
expanded_locators: [ locator ],
|
||||
scroll_offset: scrollOffset || 0
|
||||
};
|
||||
},
|
||||
@@ -168,7 +167,7 @@ define(["jquery", "underscore", "js/views/xblock_outline", "js/views/utils/view_
|
||||
handleClass: '.section-drag-handle',
|
||||
droppableClass: 'ol.list-sections',
|
||||
parentLocationSelector: 'article.outline',
|
||||
refresh: this.refresh.bind(this)
|
||||
refresh: this.refreshWithCollapsedState.bind(this)
|
||||
});
|
||||
}
|
||||
else if ($(element).hasClass("outline-subsection")) {
|
||||
@@ -177,7 +176,7 @@ define(["jquery", "underscore", "js/views/xblock_outline", "js/views/utils/view_
|
||||
handleClass: '.subsection-drag-handle',
|
||||
droppableClass: 'ol.list-subsections',
|
||||
parentLocationSelector: 'li.outline-section',
|
||||
refresh: this.refresh.bind(this)
|
||||
refresh: this.refreshWithCollapsedState.bind(this)
|
||||
});
|
||||
}
|
||||
else if ($(element).hasClass("outline-unit")) {
|
||||
@@ -186,7 +185,7 @@ define(["jquery", "underscore", "js/views/xblock_outline", "js/views/utils/view_
|
||||
handleClass: '.unit-drag-handle',
|
||||
droppableClass: 'ol.list-units',
|
||||
parentLocationSelector: 'li.outline-subsection',
|
||||
refresh: this.refresh.bind(this)
|
||||
refresh: this.refreshWithCollapsedState.bind(this)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
define(["jquery", "underscore", "gettext", "js/views/pages/base_page", "js/views/utils/xblock_utils",
|
||||
"js/views/course_outline"],
|
||||
function ($, _, gettext, BasePage, XBlockViewUtils, CourseOutlineView) {
|
||||
var CourseOutlinePage = BasePage.extend({
|
||||
var expandedLocators, CourseOutlinePage;
|
||||
|
||||
CourseOutlinePage = BasePage.extend({
|
||||
// takes XBlockInfo as a model
|
||||
|
||||
events: {
|
||||
@@ -36,12 +38,32 @@ define(["jquery", "underscore", "gettext", "js/views/pages/base_page", "js/views
|
||||
},
|
||||
|
||||
renderPage: function() {
|
||||
var setInitialExpandState = function (xblockInfo, expandedLocators) {
|
||||
if (xblockInfo.isCourse() || xblockInfo.isChapter()) {
|
||||
expandedLocators.add(xblockInfo.get('id'));
|
||||
}
|
||||
};
|
||||
|
||||
this.setCollapseExpandVisibility();
|
||||
this.expandedLocators = expandedLocators;
|
||||
this.expandedLocators.clear();
|
||||
if (this.model.get('child_info')) {
|
||||
_.each(this.model.get('child_info').children, function (childXBlockInfo) {
|
||||
setInitialExpandState(childXBlockInfo, this.expandedLocators);
|
||||
}, this);
|
||||
}
|
||||
setInitialExpandState(this.model, this.expandedLocators);
|
||||
|
||||
if (this.initialState && this.initialState.expanded_locators) {
|
||||
this.expandedLocators.addAll(this.initialState.expanded_locators);
|
||||
}
|
||||
|
||||
this.outlineView = new CourseOutlineView({
|
||||
el: this.$('.outline'),
|
||||
model: this.model,
|
||||
isRoot: true,
|
||||
initialState: this.initialState
|
||||
initialState: this.initialState,
|
||||
expandedLocators: this.expandedLocators
|
||||
});
|
||||
this.outlineView.render();
|
||||
this.outlineView.setViewState(this.initialState || {});
|
||||
@@ -65,8 +87,67 @@ define(["jquery", "underscore", "gettext", "js/views/pages/base_page", "js/views
|
||||
element.removeClass('is-collapsed');
|
||||
}
|
||||
});
|
||||
if (this.model.get('child_info')) {
|
||||
_.each(this.model.get('child_info').children, function (childXBlockInfo) {
|
||||
if (collapse) {
|
||||
this.expandedLocators.remove(childXBlockInfo.get('id'));
|
||||
}
|
||||
else {
|
||||
this.expandedLocators.add(childXBlockInfo.get('id'));
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Represents the set of locators that should be expanded for the page.
|
||||
*/
|
||||
expandedLocators = {
|
||||
locators: [],
|
||||
|
||||
/**
|
||||
* Add the locator to the set if it is not already present.
|
||||
*/
|
||||
add: function (locator) {
|
||||
if (!this.contains(locator)) {
|
||||
this.locators.push(locator);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Accepts an array of locators and adds them all to the set if not already present.
|
||||
*/
|
||||
addAll: function(locators) {
|
||||
_.each(locators, function(locator) {
|
||||
this.add(locator);
|
||||
}, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove the locator from the set if it is present.
|
||||
*/
|
||||
remove: function (locator) {
|
||||
var index = this.locators.indexOf(locator);
|
||||
if (index >= 0) {
|
||||
this.locators.splice(index, 1);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true iff the locator is present in the set.
|
||||
*/
|
||||
contains: function (locator) {
|
||||
return this.locators.indexOf(locator) >= 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Clears all expanded locators from the set.
|
||||
*/
|
||||
clear: function () {
|
||||
this.locators = [];
|
||||
}
|
||||
};
|
||||
|
||||
return CourseOutlinePage;
|
||||
}); // end define();
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
*
|
||||
* The view can be constructed with an initialState option which is a JSON structure representing
|
||||
* the desired initial state. The parameters are as follows:
|
||||
* - expanded_locators - the locators that should be shown as expanded in addition to the defaults
|
||||
* - locator_to_show - the locator for the xblock which is the one being explicitly shown
|
||||
* - scroll_offset - the scroll offset to use for the locator being shown
|
||||
* - edit_display_name - true if the shown xblock's display name should be in inline edit mode
|
||||
@@ -30,6 +29,7 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/utils/
|
||||
initialize: function() {
|
||||
BaseView.prototype.initialize.call(this);
|
||||
this.initialState = this.options.initialState;
|
||||
this.expandedLocators = this.options.expandedLocators;
|
||||
this.template = this.options.template;
|
||||
if (!this.template) {
|
||||
this.template = this.loadTemplate(this.templateName);
|
||||
@@ -37,7 +37,7 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/utils/
|
||||
this.parentInfo = this.options.parentInfo;
|
||||
this.parentView = this.options.parentView;
|
||||
this.renderedChildren = false;
|
||||
this.model.on('sync', this.onXBlockChange, this);
|
||||
this.model.on('sync', this.onSync, this);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
@@ -47,6 +47,9 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/utils/
|
||||
if (this.shouldRenderChildren() && this.shouldExpandChildren()) {
|
||||
this.renderChildren();
|
||||
}
|
||||
else {
|
||||
this.renderedChildren = false;
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
@@ -132,6 +135,17 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/utils/
|
||||
},
|
||||
|
||||
toggleExpandCollapse: function(event) {
|
||||
// The course outline page tracks expanded locators. The unit location sidebar does not.
|
||||
if (this.expandedLocators) {
|
||||
var locator = this.model.get('id');
|
||||
var wasExpanded = this.expandedLocators.contains(locator);
|
||||
if (wasExpanded) {
|
||||
this.expandedLocators.remove(locator);
|
||||
}
|
||||
else {
|
||||
this.expandedLocators.add(locator);
|
||||
}
|
||||
}
|
||||
// Ensure that the children have been rendered before expanding
|
||||
if (this.shouldRenderChildren() && !this.renderedChildren) {
|
||||
this.renderChildren();
|
||||
@@ -164,6 +178,7 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/utils/
|
||||
model: xblockInfo,
|
||||
parentInfo: parentInfo,
|
||||
initialState: this.initialState,
|
||||
expandedLocators: this.expandedLocators,
|
||||
template: this.template,
|
||||
parentView: parentView || this
|
||||
});
|
||||
@@ -181,6 +196,12 @@ define(["jquery", "underscore", "gettext", "js/views/baseview", "js/views/utils/
|
||||
return xblockType;
|
||||
},
|
||||
|
||||
onSync: function(event) {
|
||||
if (ViewUtils.hasChangedAttributes(this.model, ['visibility_state', 'child_info', 'display_name'])) {
|
||||
this.onXBlockChange();
|
||||
}
|
||||
},
|
||||
|
||||
onXBlockChange: function() {
|
||||
var oldElement = this.$el,
|
||||
viewState = this.initialState;
|
||||
|
||||
Reference in New Issue
Block a user