Skip to content
This repository has been archived by the owner on Apr 2, 2019. It is now read-only.

Commit

Permalink
Merge pull request #626 from dulldave/accessibility_features
Browse files Browse the repository at this point in the history
Add accessibility features as noted in Feature Request #612.
  • Loading branch information
wyuenho committed Jun 6, 2016
2 parents 4b17a42 + 624745c commit 8b0c114
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 35 deletions.
10 changes: 8 additions & 2 deletions lib/backgrid.js
Original file line number Diff line number Diff line change
Expand Up @@ -2077,7 +2077,7 @@ var HeaderCell = Backgrid.HeaderCell = Backbone.View.extend({

/** @property */
events: {
"click a": "onClick"
"click button": "onClick"
},

/**
Expand Down Expand Up @@ -2176,7 +2176,7 @@ var HeaderCell = Backgrid.HeaderCell = Backbone.View.extend({
var sortable = Backgrid.callByNeed(column.sortable(), column, this.collection);
var label;
if(sortable){
label = $("<a>").text(column.get("label")).append("<b class='sort-caret'></b>");
label = $("<button>").text(column.get("label")).append("<span class='sort-caret' aria-hidden='true'></span>");
} else {
label = document.createTextNode(column.get("label"));
}
Expand Down Expand Up @@ -2819,6 +2819,8 @@ var Grid = Backgrid.Grid = Backbone.View.extend({
options.columns = new Columns(options.columns || this.columns);
}
this.columns = options.columns;

this.caption = options.caption;

var filteredOptions = _.omit(options, ["el", "id", "attributes",
"className", "tagName", "events"]);
Expand Down Expand Up @@ -2904,6 +2906,10 @@ var Grid = Backgrid.Grid = Backbone.View.extend({
*/
render: function () {
this.$el.empty();

if (this.caption) {
this.$el.append($("<caption>").text(this.caption));
}

if (this.header) {
this.$el.append(this.header.render().$el);
Expand Down
5 changes: 4 additions & 1 deletion src/backgrid.css
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,11 @@
background-color: #f9f9f9;
}

.backgrid thead th a {
.backgrid thead th button {
display: block;
border: none;
background: none;
padding: 0;
}

.backgrid.backgrid-striped tbody tr:nth-child(even) {
Expand Down
9 changes: 8 additions & 1 deletion src/grid.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ var Grid = Backgrid.Grid = Backbone.View.extend({
@param {Object} options
@param {Backbone.Collection.<Backgrid.Columns>|Array.<Backgrid.Column>|Array.<Object>} options.columns Column metadata.
@param {Backbone.Collection} options.collection The collection of tabular model data to display.
@param {string} [options.caption=string] An optional caption to be added to the table.
@param {Backgrid.Header} [options.header=Backgrid.Header] An optional Header class to override the default.
@param {Backgrid.Body} [options.body=Backgrid.Body] An optional Body class to override the default.
@param {Backgrid.Row} [options.row=Backgrid.Row] An optional Row class to override the default.
Expand All @@ -88,6 +89,8 @@ var Grid = Backgrid.Grid = Backbone.View.extend({
options.columns = new Columns(options.columns || this.columns);
}
this.columns = options.columns;

this.caption = options.caption;

var filteredOptions = _.omit(options, ["el", "id", "attributes",
"className", "tagName", "events"]);
Expand Down Expand Up @@ -167,12 +170,16 @@ var Grid = Backgrid.Grid = Backbone.View.extend({
},

/**
Renders the grid's header, then footer, then finally the body. Triggers a
Renders the grid's caption, then header, then footer, then finally the body. Triggers a
Backbone `backgrid:rendered` event along with a reference to the grid when
the it has successfully been rendered.
*/
render: function () {
this.$el.empty();

if (this.caption) {
this.$el.append($("<caption>").text(this.caption));
}

if (this.header) {
this.$el.append(this.header.render().$el);
Expand Down
4 changes: 2 additions & 2 deletions src/header.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ var HeaderCell = Backgrid.HeaderCell = Backbone.View.extend({

/** @property */
events: {
"click a": "onClick"
"click button": "onClick"
},

/**
Expand Down Expand Up @@ -120,7 +120,7 @@ var HeaderCell = Backgrid.HeaderCell = Backbone.View.extend({
var sortable = Backgrid.callByNeed(column.sortable(), column, this.collection);
var label;
if(sortable){
label = $("<a>").text(column.get("label")).append("<b class='sort-caret'></b>");
label = $("<button>").text(column.get("label")).append("<span class='sort-caret' aria-hidden='true'></span>");
} else {
label = document.createTextNode(column.get("label"));
}
Expand Down
21 changes: 19 additions & 2 deletions test/grid.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,23 @@ describe("A Grid", function () {
expect(grid.body.rows[0].className).not.toBe("class-name");
expect(grid.footer.className).not.toBe("class-name");
});

it("will render a table with a caption element", function () {
var caption = "Table of data"
grid = new Backgrid.Grid({
columns: [{
name: "title",
cell: "string"
}],
collection: books,
caption: caption,
});

grid.render();

expect($(grid.el).find("caption"));
expect($(grid.el).find("caption").text()).toBe(caption);
});

it("will clean up all its decendant views when remove is called", function () {
expect(grid.remove().constructor).toBe(Backgrid.Grid);
Expand Down Expand Up @@ -122,8 +139,8 @@ describe("A Grid", function () {
var thead = grid.el.childNodes[0];
expect(thead.tagName == "THEAD").toBe(true);
expect($(thead).find("tr").length).toBe(1);
expect($(thead).find("tr > th.editable.sortable.renderable.id > a > b.sort-caret").length).toBe(1);
expect($(thead).find("tr > th.editable.sortable.renderable.id > a").text()).toBe("id");
expect($(thead).find("tr > th.editable.sortable.renderable.id > button > span.sort-caret").length).toBe(1);
expect($(thead).find("tr > th.editable.sortable.renderable.id > button").text()).toBe("id");

var tfoot = grid.el.childNodes[1];
expect(tfoot.tagName == "TFOOT").toBe(true);
Expand Down
55 changes: 28 additions & 27 deletions test/header.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ describe("A HeaderCell", function () {

it("renders a table header cell with the label text and an optional anchor with sort-caret", function () {
expect(cell.el.tagName).toBe("TH");
expect(cell.$el.find("a").text()).toBe("id");
expect(cell.$el.find("button").text()).toBe("id");
expect(cell.$el.find(".sort-caret").length).toBe(1);
expect(cell.$el.find(".sort-caret").attr("aria-hidden")).toEqual("true");

cell.column.set("sortable", false);
cell.render();
Expand Down Expand Up @@ -124,15 +125,15 @@ describe("A HeaderCell", function () {
});

it("will rerender with the column name and/or label changes", function () {
expect(cell.$el.find("a").text(), "id");
expect(cell.$el.find("button").text(), "id");
expect(cell.$el.hasClass("id"), true);

cell.column.set("name", "name");
expect(cell.$el.find("name"), true);
expect(cell.$el.hasClass("name"), true);

cell.column.set("label", "Name");
expect(cell.$el.find("a").text(), "Name");
expect(cell.$el.find("button").text(), "Name");
expect(cell.$el.hasClass("Name"), true);
});

Expand All @@ -149,15 +150,15 @@ describe("A HeaderCell", function () {
cell.render();

expect(cell.el.tagName).toBe("TH");
expect(cell.$el.find("a").text()).toBe("id");
expect(cell.$el.find("button").text()).toBe("id");
expect(cell.$el.find(".sort-caret").length).toBe(1);
expect(cell.$el.hasClass("descending")).toBe(true);
});

it("triggers `backgrid:sort` with the column and direction set to 'ascending' if the column's direction is not set", function () {
var column, direction;
cell.collection.on("backgrid:sort", function (col, dir) { column = col; direction = dir; });
cell.$el.find("a").click();
cell.$el.find("button").click();
expect(column).toBe(cell.column);
expect(direction).toBe("ascending");
});
Expand All @@ -166,7 +167,7 @@ describe("A HeaderCell", function () {
var column, direction;
cell.collection.on("backgrid:sort", function (col, dir) { column = col; direction = dir; });
cell.column.set("direction", "ascending");
cell.$el.find("a").click();
cell.$el.find("button").click();
expect(column).toBe(cell.column);
expect(direction).toBe("descending");
});
Expand All @@ -175,7 +176,7 @@ describe("A HeaderCell", function () {
var column, direction;
cell.collection.on("backgrid:sort", function (col, dir) { column = col; direction = dir; });
cell.column.set("direction", "descending");
cell.$el.find("a").click();
cell.$el.find("button").click();
expect(column).toBe(cell.column);
expect(direction).toBeNull();
});
Expand Down Expand Up @@ -224,7 +225,7 @@ describe("A HeaderCell", function () {
var column, direction;
cell.column.set("sortType", "toggle");
cell.collection.on("backgrid:sort", function (col, dir) { column = col; direction = dir; });
cell.$el.find("a").click();
cell.$el.find("button").click();
expect(column).toBe(cell.column);
expect(direction).toBe("ascending");
});
Expand All @@ -234,7 +235,7 @@ describe("A HeaderCell", function () {
cell.column.set("sortType", "toggle");
cell.column.set("direction", "ascending");
cell.collection.on("backgrid:sort", function (col, dir) { column = col; direction = dir; });
cell.$el.find("a").click();
cell.$el.find("button").click();
expect(column).toBe(cell.column);
expect(direction).toBe("descending");
});
Expand All @@ -244,7 +245,7 @@ describe("A HeaderCell", function () {
cell.column.set("sortType", "toggle");
cell.column.set("direction", "descending");
cell.collection.on("backgrid:sort", function (col, dir) { column = col; direction = dir; });
cell.$el.find("a").click();
cell.$el.find("button").click();
expect(column).toBe(cell.column);
expect(direction).toBe("ascending");
});
Expand Down Expand Up @@ -296,23 +297,23 @@ describe("A HeaderRow", function () {
expect(th1.hasClass("sortable")).toBe(true);
expect(th1.hasClass("renderable")).toBe(true);
expect(th1.hasClass("name")).toBe(true);
expect(th1.find("a").text()).toBe("name");
expect(th1.find("a").eq(1).is($("b", {className: "sort-caret"})));
expect(th1.find("button").text()).toBe("name");
expect(th1.find("button").eq(1).is($("b", {className: "sort-caret"})));

var th2 = $(row.el.childNodes[1]);
expect(th2.hasClass("editable")).toBe(true);
expect(th2.hasClass("sortable")).toBe(true);
expect(th2.hasClass("renderable")).toBe(true);
expect(th2.hasClass("year")).toBe(true);
expect(th2.find("a").text()).toBe("year");
expect(th2.find("a > b:last-child").eq(0).hasClass("sort-caret")).toBe(true);
expect(th2.find("button").text()).toBe("year");
expect(th2.find("button > span:last-child").eq(0).hasClass("sort-caret")).toBe(true);
});

it("resets the carets of the non-sorting columns", function () {
row.$el.find("a").eq(0).click(); // ascending
row.$el.find("a").eq(1).click(); // ascending, resets the previous
expect(row.$el.find("a").eq(0).hasClass("ascending")).toBe(false);
expect(row.$el.find("a").eq(1).hasClass("ascending")).toBe(false);
row.$el.find("button").eq(0).click(); // ascending
row.$el.find("button").eq(1).click(); // ascending, resets the previous
expect(row.$el.find("button").eq(0).hasClass("ascending")).toBe(false);
expect(row.$el.find("button").eq(1).hasClass("ascending")).toBe(false);
});

it("inserts or removes a cell if a column is added or removed", function () {
Expand All @@ -323,12 +324,12 @@ describe("A HeaderRow", function () {
expect(lastTh.hasClass("sortable")).toBe(true);
expect(lastTh.hasClass("renderable")).toBe(true);
expect(lastTh.hasClass("price")).toBe(true);
expect(lastTh.find("a").text()).toBe("price");
expect(lastTh.find("a > b:last-child").eq(0).hasClass("sort-caret")).toBe(true);
expect(lastTh.find("button").text()).toBe("price");
expect(lastTh.find("button > span:last-child").eq(0).hasClass("sort-caret")).toBe(true);

row.columns.add({name: "publisher", cell: "string", renderable: false});
expect(row.$el.children().length).toBe(4);
expect(row.$el.children().last().find("a").text()).toBe("publisher");
expect(row.$el.children().last().find("button").text()).toBe("publisher");
expect(row.$el.children().last().hasClass("renderable")).toBe(false);

row.columns.remove(row.columns.first());
Expand All @@ -338,8 +339,8 @@ describe("A HeaderRow", function () {
expect(firstTh.hasClass("sortable")).toBe(true);
expect(firstTh.hasClass("renderable")).toBe(true);
expect(firstTh.hasClass("year")).toBe(true);
expect(firstTh.find("a").text()).toBe("year");
expect(firstTh.find("a > b:last-child").eq(0).hasClass("sort-caret")).toBe(true);
expect(firstTh.find("button").text()).toBe("year");
expect(firstTh.find("button > span:last-child").eq(0).hasClass("sort-caret")).toBe(true);
});

});
Expand Down Expand Up @@ -390,16 +391,16 @@ describe("A Header", function () {
expect(th1.hasClass("sortable")).toBe(true);
expect(th1.hasClass("renderable")).toBe(true);
expect(th1.hasClass("name")).toBe(true);
expect(th1.find("a").text()).toBe("name");
expect(th1.find("a").eq(1).is($("b", {className: "sort-caret"})));
expect(th1.find("button").text()).toBe("name");
expect(th1.find("button").eq(1).is($("b", {className: "sort-caret"})));

var th2 = $(head.row.el.childNodes[1]);
expect(th2.hasClass("editable")).toBe(true);
expect(th2.hasClass("sortable")).toBe(true);
expect(th2.hasClass("renderable")).toBe(true);
expect(th2.hasClass("year")).toBe(true);
expect(th2.find("a").text()).toBe("year");
expect(th2.find("a > b:last-child").eq(0).hasClass("sort-caret")).toBe(true);
expect(th2.find("button").text()).toBe("year");
expect(th2.find("button > span:last-child").eq(0).hasClass("sort-caret")).toBe(true);
});

});

0 comments on commit 8b0c114

Please sign in to comment.