Commit 8ffe7c65 by Peter Fogg

Merge pull request #8397 from edx/peter-fogg/category-subnavigation

TNL-1891 Browse Teams: Category Subnavigation
parents a5204310 17d3906c
......@@ -18,4 +18,4 @@ class TeamsPage(CoursePage):
def get_body_text(self):
""" Returns the current dummy text. This will be changed once there is more content on the page. """
return self.q(css='.teams-text').text[0]
return self.q(css='.page-content-main').text[0]
define(["jquery", "teams/js/teams_tab_factory"],
function($, TeamsTabFactory) {
define(["jquery", "backbone", "teams/js/teams_tab_factory"],
function($, Backbone, TeamsTabFactory) {
'use strict';
describe("teams django app", function() {
......@@ -10,6 +10,10 @@ define(["jquery", "teams/js/teams_tab_factory"],
teamsTab = new TeamsTabFactory();
});
afterEach(function() {
Backbone.history.stop();
});
it("can load templates", function() {
expect($("body").text()).toContain("This is the new Teams tab");
});
......
......@@ -6,8 +6,8 @@
'gettext',
'js/components/header/views/header',
'js/components/header/models/header',
'text!teams/templates/teams-tab.underscore'],
function (Backbone, _, gettext, HeaderView, HeaderModel, teamsTabTemplate) {
'js/components/tabbed/views/tabbed_view'],
function (Backbone, _, gettext, HeaderView, HeaderModel, TabbedView) {
var TeamTabView = Backbone.View.extend({
initialize: function() {
this.headerModel = new HeaderModel({
......@@ -17,12 +17,35 @@
this.headerView = new HeaderView({
model: this.headerModel
});
// TODO replace this with actual views!
var TempTabView = Backbone.View.extend({
initialize: function (options) {
this.text = options.text;
},
render: function () {
this.$el.text(this.text)
}
});
this.tabbedView = new TabbedView({
tabs: [{
title: gettext('My Teams'),
url: 'teams',
view: new TempTabView({text: 'This is the new Teams tab.'})
}, {
title: gettext('Browse'),
url: 'browse',
view: new TempTabView({text: 'Browse team topics here.'})
}]
});
Backbone.history.start();
},
render: function() {
this.$el.html(_.template(teamsTabTemplate, {}));
this.$el.prepend(this.headerView.$el);
this.$el.append(this.headerView.$el);
this.headerView.render();
this.$el.append(this.tabbedView.$el);
this.tabbedView.render();
}
});
......
<p class="teams-text">This is the new Teams tab.</p>
;(function (define) {
'use strict';
define(['backbone',
'underscore',
'jquery',
'text!templates/components/tabbed/tabbed_view.underscore',
'text!templates/components/tabbed/tab.underscore'],
function (Backbone, _, $, tabbedViewTemplate, tabTemplate) {
var TabbedView = Backbone.View.extend({
events: {
'click .nav-item': 'switchTab'
},
template: _.template(tabbedViewTemplate),
/**
* View for a tabbed interface. Expects a list of tabs
* in its options object, each of which should contain the
* following properties:
* view (Backbone.View): the view to render for this tab.
* title (string): The title to display for this tab.
* url (string): The URL fragment which will navigate to this tab.
*/
initialize: function (options) {
this.router = new Backbone.Router();
this.$el.html(this.template({}));
var self = this;
this.tabs = options.tabs;
_.each(this.tabs, function(tabInfo, index) {
var tabEl = $(_.template(tabTemplate, {
index: index,
title: tabInfo.title
}));
self.$('.page-content-nav').append(tabEl);
self.router.route(tabInfo.url, function () {
self.setActiveTab(index);
});
});
this.setActiveTab(0);
},
setActiveTab: function (index) {
this.$('a.is-active').removeClass('is-active').attr('aria-selected', 'false');
this.$('a[data-index='+index+']').addClass('is-active').attr('aria-selected', 'true');
var view = this.tabs[index].view;
view.render();
this.$('.page-content-main').html(view.$el.html());
this.$('.sr-is-focusable').focus();
},
switchTab: function (event) {
event.preventDefault();
this.setActiveTab($(event.currentTarget).data('index'));
}
});
return TabbedView;
});
}).call(this, define || RequireJS.define);
(function (define) {
'use strict';
define(['jquery',
'underscore',
'backbone',
'js/components/tabbed/views/tabbed_view'
],
function($, _, Backbone, TabbedView) {
var view,
TestSubview = Backbone.View.extend({
initialize: function (options) {
this.text = options.text;
},
render: function () {
this.$el.text(this.text);
}
});
describe('TabbedView component', function () {
beforeEach(function () {
spyOn(Backbone.history, 'navigate').andCallThrough();
Backbone.history.start();
view = new TabbedView({
tabs: [{
url: 'test 1',
title: 'Test 1',
view: new TestSubview({text: 'this is test text'})
}, {
url: 'test 2',
title: 'Test 2',
view: new TestSubview({text: 'other text'})
}]
});
});
afterEach(function () {
Backbone.history.stop();
});
it('can render itself', function () {
expect(view.$el.html()).toContain('<nav class="page-content-nav" role="tablist">')
});
it('shows its first tab by default', function () {
expect(view.$el.text()).toContain('this is test text');
expect(view.$el.text()).not.toContain('other text');
});
it('displays titles for each tab', function () {
expect(view.$el.text()).toContain('Test 1');
expect(view.$el.text()).toContain('Test 2');
});
it('can switch tabs', function () {
view.$('.nav-item[data-index=1]').click();
expect(view.$el.text()).not.toContain('this is test text');
expect(view.$el.text()).toContain('other text');
});
it('changes tabs on navigation', function () {
expect(view.$('.nav-item.is-active').data('index')).toEqual(0);
Backbone.history.navigate('test 2', {trigger: true});
expect(view.$('.nav-item.is-active').data('index')).toEqual(1);
});
it('marks the active tab as selected using aria attributes', function () {
expect(view.$('.nav-item[data-index=0]')).toHaveAttr('aria-selected', 'true');
expect(view.$('.nav-item[data-index=1]')).toHaveAttr('aria-selected', 'false');
view.$('.nav-item[data-index=1]').click();
expect(view.$('.nav-item[data-index=0]')).toHaveAttr('aria-selected', 'false');
expect(view.$('.nav-item[data-index=1]')).toHaveAttr('aria-selected', 'true');
});
});
}
);
}).call(this, define || RequireJS.define);
......@@ -579,6 +579,7 @@
// Run the LMS tests
'lms/include/teams/js/spec/teams_factory_spec.js',
'lms/include/js/spec/components/header/header_spec.js',
'lms/include/js/spec/components/tabbed/tabbed_view_spec.js',
'lms/include/js/spec/photocapture_spec.js',
'lms/include/js/spec/staff_debug_actions_spec.js',
'lms/include/js/spec/views/notification_spec.js',
......
......@@ -92,10 +92,10 @@ fixture_paths:
- templates/verify_student
- templates/file-upload.underscore
- templates/components/header
- templates/components/tabbed
- js/fixtures/edxnotes
- js/fixtures/search
- templates/search
- teams/templates
- templates/discovery
requirejs:
......
<a class="nav-item" href="" data-index="<%= index %>" role="tab" aria-selected="false"><%- title %></a>
<div class="page-content">
<nav class="page-content-nav" role="tablist"></nav>
<div class="sr-is-focusable" tabindex="-1"></div>
<div class="page-content-main"></div>
</div>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment