11 | Permission is hereby granted, free of charge, to any person
12 | obtaining a copy of this software and associated documentation
13 | files (the "Software"), to deal in the Software without
14 | restriction, including without limitation the rights to use,
15 | copy, modify, merge, publish, distribute, sublicense, and/or sell
16 | copies of the Software, and to permit persons to whom the
17 | Software is furnished to do so, subject to the following
18 | conditions:
19 |
20 |
21 |
22 | The above copyright notice and this permission notice shall be
23 | included in all copies or substantial portions of the Software.
24 |
25 |
26 |
27 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
29 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
31 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
32 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
33 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
34 | OTHER DEALINGS IN THE SOFTWARE.
35 |
The default Footer class is an abstract class that only defines
20 | a number of required constructor parameters. If you wish to
21 | append additional information to the end of a table you must
22 | subclass Footer and supply the class to the Grid
23 | constructor.
Body is the intermediary view that coordinates between the various
27 | parts of the grid. Specifically, the default implementation is
28 | responsible for re-rendering the rows when any model is inserted into,
29 | removed from, or reordered in the underlying collection, including
30 | sorting. See the JSDoc for
31 | details.
It is not necessary to create an extension project if you simply want
9 | to customize or extend some Backgrid.js classes for your own private
10 | use; however, if you have one or more Backgrid.js components that add
11 | new features that may be generalized, you may consider packaging them up
12 | to share with the world.
13 |
A Backgrid.js extension is a directory structure that packages
14 | the necessary JS, CSS, tests, and document files.
The following is a guideline for extension development:
19 |
20 |
There should be 1 .js file and 1 .css file. If your code base
21 | gets too large, consider breaking it into multiple extensions.
22 |
There should be 1 .min.js file and 1 .min.css file produced
23 | for distribution.
24 |
Your Gruntfile should emulate other extensions as closely as
25 | possible. For the most part, as long as your extension project's
26 | directory structure is the same, you can simply copy and paste the
27 | Gruntfile from other extensions and change the file names.
28 |
You should use recess to lint your CSS file(s).
29 |
You should follow the JS coding style defined here.
31 |
Your .gitignore file inside the extension directory should
32 | ignore all output files.
33 |
You should wrap your JS file in an immediately invoked anonymous
34 | function that lists out your dependencies in the parameter list. For
35 | extra credit, you can wrap the IIFE in a UMD block.
37 |
Your extension should live under the Backgrid.Extension
38 | module. Specifically, your exported objects should have a reference
39 | under that module namespace regardless of which packaging mechanism
40 | you choose.
41 |
You should clearly specify your dependencies in the README
42 | file if your extension relies on any libraries other than
43 | Backgrid.js and its dependencies.
44 |
When in doubt, look at the other extensions for clues in
45 | organizing your code.
TextCell is a string cell type that renders a form with a text
28 | area in a modal dialog instead of
29 | an <input type="text" /> editor. It
30 | is best suited for entering a large body of text.
A Column is a placeholder for a column definition.
26 |
You usually don't need to create an instance of this class
27 | yourself, as a collection of column instances will be created for
28 | you from a list of column object literals you provide to the
29 | Backgrid view class constructors.
30 |
Internally, columns are stored as a collection in the form of
31 | Backgrid.Columns. In addition, all parent views will convert the
32 | column definition into
33 | a Backgrid.Columns
34 | collection and pass a reference to any subviews that require
35 | it.
Occasionally, you may want to listen to column attribute change
41 | events. In that case, you can choose to initialize a
42 | Backgrid.Columns collection and listen to events from the
43 | individual models.
Out of the box, Backgrid.js generates simple semantic HTML
12 | table elements that you can style with pure CSS. This section is
13 | only going to briefly describe some of the more important
14 | classes, and things that you should be aware of when
15 | styling.
This is the class that you should put into any container
23 | element that will hold the generated table. By default, it
24 | has a fixed maximum height and 100% width with no borders
25 | and paddings. It also serves as a positioned
26 | element so if you need to absolutely position any elements
27 | inside your custom table element classes, you can position
28 | them against this container.
This is the class that will be applied to every Backgrid.js
51 | generated table. All other Backgrid.js default styles on
52 | table elements will only apply to descendents
53 | of tables of this class.
54 |
66 |
67 |
68 |
69 |
Although usually unnecessary, if you want to completely
70 | remove all Backgrid.js styles, you can supply
71 | a className attribute to
72 | the Backgrid.Grid constructor:
Every cell class Backgrid.js defines has a CSS class
86 | applied to them of the same, but dasherized name. The
87 | default styles apply a text-align: left to text
88 | cells and text-align: right to numeric and
89 | datetime cells.
90 |
Backgrid comes with a default header section, a header row and a
30 | header cell implementation that renders a sorter if the column is
31 | sortable. The text inside the header cells comes from the column
32 | definitions. If a label is not defined in a
33 | column definition, its name is used as the label instead.
34 |
The default header cell implementation supports sorting in ascending
35 | or descending order, using the column's natural ordering. The
36 | sorter will also allow cycling back to the table's default
37 | sorting order, which is sorting by the model client IDs.
If you want to change the default sort behavior to only toggle
47 | between sorting in ascending or descending order, you do this by
48 | passing sortType: "toggle" as part of your column
49 | definition.
50 |
64 |
Advanced Usage
65 |
You are allow to use a different header cell class on
66 | columns. There is no restriction on what a header cell must do. In fact,
67 | any Backbone.View class can be
69 | used. However, if you wish to modify how the sorter behaves, you
70 | must implement the sorting protocol. See
71 | the JSDoc for details.
While the core DatetimeCell is light-weight and does the job of
28 | formatting IS0-8601 datetime strings fairly well, it may not be
29 | well suited when the datatime strings are not in ISO
30 | format.
The default MomentCell acts just like DatetimeCell, so if you
42 | have a column with datetime values, the default MomentCell is
43 | almost a drop-in replacement, with the only difference being
44 | that an offset is always present in the output.
45 |
In addition to the ability to read and write ISO-8601 datetime
46 | strings. By specifying the model and display formats, MomentCell
47 | can convert and validated any datetime values moment.js
48 | understands.
49 |
Like the core cell types, you can configure MomentCell
50 | simply by extending it.
Backgrid aims to be a highly modular and flexible library that aims
12 | to provide you with a set of basic building blocks for creating all
13 | kinds of data grids.
Backgrid is primarily comprised of a set of highly reusable Backbone.View subclasses and a number of
20 | internal models and helper classes. In
22 | practical terms, this architecture ensures that if you are already
23 | familiar with Backbone, you can carry that knowledge over and apply to
24 | Backgrid directly.
Backgrid's View components are, borrowing from Marionette's
30 | parlance, primarily CollectionView and ItemView
31 | components, which means the components are to be layed out
32 | sequentially. However, the Grid's root element itself can be inserted
33 | to any where in the DOM.
Another notable architectural choice Backgrid has made involves how
43 | it handles events. Backgrid takes advantage of the fact that every
44 | Backbone class implements the Backbone.Events interface. Internally,
45 | every Backgrid object shares one or more of Columns, Column,
46 | Collection and Model, Backgrid simply treats them as "event buses" to
47 | enable cross-component communication without requiring every Backgrid
48 | component to know of the existence and implementation of each other.
49 |
50 |
Since all Model events will bubble up to the collection, interested
51 | components can simply treat the Columns and Collection instances as
52 | "event queues" and "subscribe" to the Backgrid events. All Backgrid
53 | events are effectively notifications of state changes, any objects
54 | that mixes in Backbone.Events can react to these state changes. You
55 | can find a list of relevant events in this document.
If you are coming from a jQuery background, you'd notice that most of
60 | the jQuery plugins, no matter how "good" that are, for some measure of
61 | "goodness", are extremely difficult to customize. Most jQuery plugins
62 | with a modicum of complexity will give you at least dozens of
63 | options. The general rule of thumb is, if it doesn't work the way you
64 | want it, ask the author to throw more options at the problem. Failing
65 | that, spend an inordinate amount of time to source for another similar
66 | plugin. If all else failed, you have to roll your own plugin.
67 |
Your laziness has backfired, but that doesn't have to be the case.
68 |
The inherant problem with the jQuery plugin model is that it doesn't
69 | offer you any help other than giving you a namespace, and the combined
70 | laziness of plugin authors and users have created an ecosystem full of
71 | opaque plugins that produce DOM structures that are hard to
72 | comprehend, hard to style and behaviors impossible to alter, no matter
73 | how trivial they should be.
74 |
75 | Backgrid offers 3 levels of customization:
76 |
77 |
78 |
79 | Options to the Grid constructor - Used for required parameters and
80 | generic behavior provide by Backgrid that you want to switch on or
81 | off.
82 |
83 |
84 | Styling via CSS - Backgrid's generated DOM structure consists
85 | solely of your plain old <table> HTML elements,
86 | just style them as such.
87 |
88 |
89 | Inheritance - Subclass a Backgrid component, give it your
90 | preferred behavior, give the new class to the Grid constructor and
91 | voila.
92 |
You can also use this extension in concert with Backbone.PageableCollection. In
85 | which case SelectAll will select across all pages by default, whether
86 | the PageableCollection is in server, client or infinite mode. See this
87 | example.
At any point during the lifetime of your program, if you'd like
100 | to get an array of the currently selected models after you've
101 | rendered your grid, you can easily do so:
102 |
114 |
115 |
116 |
117 |
118 |
Pro Tip
119 |
Each SelectRowCell will trigger a backgrid:selected
120 | event directly from the selected models when its checkbox value
121 | changes, so if you want to react to those events, you can attach
122 | your event handlers on the collection.
Sometimes, you might want to set the grid to a sorted state before
91 | displaying it, you can do that by calling Grid#sort()
92 | with a column name and a direction:
93 |
100 |
Sometime you may want to render a grid in a sorted state, probably
101 | based on a previously saved sorting state. You can supply a
102 | direction to a column definition and a sorted collection to
103 | a grid's constructor before you render it:
Backgrid.Extension.Paginator needs a Backbone.Collection
33 | subclass that supports pagination. Luckily, there is already one
34 | available specially written for this purpose
35 | - Backbone.PageableCollection.
37 |
Backbone.PageableCollection is a strict superset of the vanilla
38 | Backbone.Collection with additional pagination and sorting
39 | functionality. If you like, you can use
40 | Backbone.PageableCollection throughout your application and it
41 | will work exactly the same as Backbone.Collection.
Out of the box, Backbone.PageableCollection works with RESTful
50 | APIs that accept Ruby's will_paginate pagination query
51 | parameters but you are able to configure the query string
52 | mapping anyway you like. The following example works with
53 | Github's API:
Backgrid.Extension.Paginator supports a number of configuration
96 | options to adjust to the size of the result set. You can control the
97 | default window size, how many pages to slide an whether the grid
98 | should go back to the first page after sorting.
You can control how the control and page handles are rendered, you
161 | can even control how the sliding window algorithm works. Please refer
162 | to the JSDoc for details.
In Backgrid, cell formatters serves the purpose of converting values
24 | between JSON value types and strings, and validation. Writing
25 | formatters for value conversion and validation is easy as you only
26 | have to conform to a very simple protocol.
27 |
Pro Tip
28 |
Formatters are used for string formatting, not manipulating
29 | the DOM and styling. Use render for that.
Any formatters must have the following two methods defined:
35 |
42 |
fromRaw() is called by Backgrid.Cell and its
43 | subclasses whenever a raw model value needs to be formatted into
44 | a humanized form for display.
45 |
toRaw() is called by Backgrid.CellEditor and its
46 | subclasses whenever a user input string needs to be converted back
47 | to a raw JSON value for model persistence.
48 |
The model parameter is not used by any built-in
49 | formatters, but sometimes you may want to decide how to format your
50 | values depending on the other values in the model. You can use it in
51 | your custom formatters if that's the case.
In addition to user input conversion, toRaw() also
56 | validates the user input during conversion. If the user input is
57 | invalid or cannot be converted to a JSON value,
58 | toRaw()MUST return
59 | undefined instead of throwing an Error.
60 |
In addition to using formatters to do simple yes or no
61 | validations, if your model class has
62 | a validate() method defined,
64 | it will also be used for validation after trying with the
65 | formatter.
The most common formatter you'll override is probably
70 | SelectFormatter. Suppose your column expects an integer, due to a
71 | limitation of the DOM, the default toRaw() implementation
72 | will simply return the selected value from the DOM, which is always a
73 | string.
74 |
If you need to store a different type, you should override the
75 | formatter to provide a toRaw() implementation that returns a
76 | correct type:
77 |
84 |
If you want to use a SelectCell with multiple select, and if the type
85 | of your model value is not string, you have to override
86 | toRaw to return an array of values:
A custom formatter supplied to a column definition will be used
100 | instead of the cell's default:
101 |
114 |
To make your custom cell and custom formatter reuseable, you can
115 | package them up together and give your custom cell to a column
116 | definition:
Select2Cell is a very simple extension of the default SelectCell. You can configure individual
43 | instances by supplying a select2Options object hash
44 | during extension, in addition to the options SelectCell supports.
The Select2Cell and its superclass SelectCell assumes that the data for the select
100 | box will have been loaded before the grid is rendered. As a
101 | consequence of this design decision, select's ability to load its
102 | options dynamically is rendered useless.
103 |
The reason for this design is when the cell is in display mode, it
104 | needs to render a label, not its database ID value, so the data will
105 | have been already loaded even before the Select2CellEditor goes into
106 | effect.
107 |
To keep your optionValues fresh, you can try one of the following
108 | approaches:
152 | Permission is hereby granted, free of charge, to any person
153 | obtaining a copy of this software and associated documentation
154 | files (the "Software"), to deal in the Software without
155 | restriction, including without limitation the rights to use,
156 | copy, modify, merge, publish, distribute, sublicense, and/or sell
157 | copies of the Software, and to permit persons to whom the
158 | Software is furnished to do so, subject to the following
159 | conditions:
160 |
161 |
162 |
163 | The above copyright notice and this permission notice shall be
164 | included in all copies or substantial portions of the Software.
165 |
166 |
167 |
168 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
169 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
170 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
171 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
172 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
173 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
174 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
175 | OTHER DEALINGS IN THE SOFTWARE.
176 |
The default Footer class is an abstract class that only defines
161 | a number of required constructor parameters. If you wish to
162 | append additional information to the end of a table you must
163 | subclass Footer and supply the class to the Grid
164 | constructor.
A row is simply an intermediary view class that constructs the
161 | appropriate Cell class instances for rendering the model
162 | columns.
163 |
If you would like to override how a row is rendered, you may
164 | define your own Row subclass and give it to the Grid constructor
165 | as an option:
Body is the intermediary view that coordinates between the various
168 | parts of the grid. Specifically, the default implementation is
169 | responsible for re-rendering the rows when any model is inserted into,
170 | removed from, or reordered in the underlying collection, including
171 | sorting. See the JSDoc for
172 | details.
It is not necessary to create an extension project if you simply want
150 | to customize or extend some Backgrid.js classes for your own private
151 | use; however, if you have one or more Backgrid.js components that add
152 | new features that may be generalized, you may consider packaging them up
153 | to share with the world.
154 |
A Backgrid.js extension is a directory structure that packages
155 | the necessary JS, CSS, tests, and document files.
The following is a guideline for extension development:
160 |
161 |
There should be 1 .js file and 1 .css file. If your code base
162 | gets too large, consider breaking it into multiple extensions.
163 |
There should be 1 .min.js file and 1 .min.css file produced
164 | for distribution.
165 |
Your Gruntfile should emulate other extensions as closely as
166 | possible. For the most part, as long as your extension project's
167 | directory structure is the same, you can simply copy and paste the
168 | Gruntfile from other extensions and change the file names.
169 |
You should use recess to lint your CSS file(s).
170 |
You should follow the JS coding style defined here.
172 |
Your .gitignore file inside the extension directory should
173 | ignore all output files.
174 |
You should wrap your JS file in an immediately invoked anonymous
175 | function that lists out your dependencies in the parameter list. For
176 | extra credit, you can wrap the IIFE in a UMD block.
178 |
Your extension should live under the Backgrid.Extension
179 | module. Specifically, your exported objects should have a reference
180 | under that module namespace regardless of which packaging mechanism
181 | you choose.
182 |
You should clearly specify your dependencies in the README
183 | file if your extension relies on any libraries other than
184 | Backgrid.js and its dependencies.
185 |
When in doubt, look at the other extensions for clues in
186 | organizing your code.
It is quite common to want to use a cell that acts on an entire
20 | row. You may want to pop up a modal, delete the row, or toggle
21 | editibility for all the columns. The possibilities are endless. For
22 | those cases, you can write a custom ActionCell, and then
23 | pass it to the column definition.
The easiest way to do it is to extend your models from a
57 | Backbone.Model subclass that supports computed
58 | properties and accessing them via the same get/set
59 | interface. There are a numberofBackboneplugins readily available for
68 | this. Should all else failed, you can roll your own fairly
71 | easily.
Some data grid widgets out there support a technique
150 | called adaptive scrolling, meaning the DOM elements will be
151 | swapped out of a viewport and new ones appended as the
152 | models are loaded from the server, thus keeping the memory
153 | more or less constant while providing an illusion to
154 | end-users that there's no limit to the number of rows the
155 | data grid can handle.
156 |
Backgrid.js has something better and achieves the same
157 | effect with much cleaner code -
158 | paginator extension, which
159 | uses backbone.paginator. The paginator
161 | supports both paging on the server-side, or preloading all the
162 | models and paging purely through the browser. Paginated
163 | Backgrid.Grid instances only render one page of DOM nodes at a
164 | time to save memory and keep your web page responsive.
No, because it is not the goal of this project to produce a
173 | full-fledged web-based spreadsheet. However, doing aggregation is
174 | trivial using Underscore.js methods.
175 |
180 |
If you use a Backbone plugin that supports computed values, you may also treat the
182 | computed values as a column as well.
Inside a Backgrid grid, every cell listens to the change event
191 | for its model value. The cells will rerender themselves during
192 | display mode upon changes in the model values. However, this
193 | functionality is only meant for synchronizing data automatically
194 | across multiple grids on the same page. If you are attempting to
195 | synchronize data changes across multiple processes, you will
196 | need some kind of a locking mechanism for the individual cells,
197 | Backgrid.js provides no help for that and you have to do this
198 | yourself. Implementing such web-based spreadsheet-like broker
199 | system is outside of the scope of this project, pull requests
200 | are welcome however.
TextCell is a string cell type that renders a form with a text
169 | area in a modal dialog instead of
170 | an <input type="text" /> editor. It
171 | is best suited for entering a large body of text.
A Column is a placeholder for a column definition.
167 |
You usually don't need to create an instance of this class
168 | yourself, as a collection of column instances will be created for
169 | you from a list of column object literals you provide to the
170 | Backgrid view class constructors.
171 |
Internally, columns are stored as a collection in the form of
172 | Backgrid.Columns. In addition, all parent views will convert the
173 | column definition into
174 | a Backgrid.Columns
175 | collection and pass a reference to any subviews that require
176 | it.
Occasionally, you may want to listen to column attribute change
182 | events. In that case, you can choose to initialize a
183 | Backgrid.Columns collection and listen to events from the
184 | individual models.
ServerSideFilter is suitable if you have a server where you send the
42 | search queries to get back a result. The follow example will create a
43 | collection that uses Github's excellent API to search for Github
44 | users. See here for the valid search terms
47 | to use.
ClientSideFilter and LunrFilter won't work unless the collection
152 | contains all the data for filtering at the time the filters are
153 | initialized. If you are fetching data after the filters were
154 | initialized and using Backbone 1.0.0+, you should pass {remove:
155 | true} or {reset: true} to
156 | Collection#fetch() due to the change to
157 | Collection#set() after fetching.
160 |
Out of the box, Backgrid.js generates simple semantic HTML
153 | table elements that you can style with pure CSS. This section is
154 | only going to briefly describe some of the more important
155 | classes, and things that you should be aware of when
156 | styling.
This is the class that you should put into any container
164 | element that will hold the generated table. By default, it
165 | has a fixed maximum height and 100% width with no borders
166 | and paddings. It also serves as a positioned
167 | element so if you need to absolutely position any elements
168 | inside your custom table element classes, you can position
169 | them against this container.
This is the class that will be applied to every Backgrid.js
192 | generated table. All other Backgrid.js default styles on
193 | table elements will only apply to descendents
194 | of tables of this class.
195 |
207 |
208 |
209 |
210 |
Although usually unnecessary, if you want to completely
211 | remove all Backgrid.js styles, you can supply
212 | a className attribute to
213 | the Backgrid.Grid constructor:
Every cell class Backgrid.js defines has a CSS class
227 | applied to them of the same, but dasherized name. The
228 | default styles apply a text-align: left to text
229 | cells and text-align: right to numeric and
230 | datetime cells.
231 |