2013-12-10 08:00:06 +00:00
/ * !
2013-04-23 00:35:04 +00:00
backgrid
http : //github.com/wyuenho/backgrid
2013-12-10 08:00:06 +00:00
Copyright ( c ) 2013 Jimmy Yuen Ho Wong and contributors < wyuenho @ gmail . com >
Licensed under the MIT license .
2013-04-23 00:35:04 +00:00
* /
2013-12-10 08:00:06 +00:00
( function ( factory ) {
// CommonJS
if ( typeof exports == "object" ) {
module . exports = factory ( module . exports ,
require ( "underscore" ) ,
require ( "backbone" ) ) ;
}
// Browser
else if ( typeof _ !== "undefined" &&
typeof Backbone !== "undefined" ) {
factory ( window , _ , Backbone ) ;
}
} ( function ( root , _ , Backbone ) {
2013-04-23 00:35:04 +00:00
"use strict" ;
/ *
backgrid
http : //github.com/wyuenho/backgrid
Copyright ( c ) 2013 Jimmy Yuen Ho Wong and contributors
2013-12-10 08:00:06 +00:00
Licensed under the MIT license .
2013-04-23 00:35:04 +00:00
* /
// Copyright 2009, 2010 Kristopher Michael Kowal
// https://github.com/kriskowal/es5-shim
// ES5 15.5.4.20
// http://es5.github.com/#x15.5.4.20
var ws = "\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003" +
"\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028" +
"\u2029\uFEFF" ;
if ( ! String . prototype . trim || ws . trim ( ) ) {
// http://blog.stevenlevithan.com/archives/faster-trim-javascript
// http://perfectionkills.com/whitespace-deviations/
ws = "[" + ws + "]" ;
var trimBeginRegexp = new RegExp ( "^" + ws + ws + "*" ) ,
trimEndRegexp = new RegExp ( ws + ws + "*$" ) ;
String . prototype . trim = function trim ( ) {
if ( this === undefined || this === null ) {
throw new TypeError ( "can't convert " + this + " to object" ) ;
}
return String ( this )
. replace ( trimBeginRegexp , "" )
. replace ( trimEndRegexp , "" ) ;
} ;
}
function lpad ( str , length , padstr ) {
var paddingLen = length - ( str + '' ) . length ;
paddingLen = paddingLen < 0 ? 0 : paddingLen ;
var padding = '' ;
for ( var i = 0 ; i < paddingLen ; i ++ ) {
padding = padding + padstr ;
}
return padding + str ;
}
2013-12-10 08:00:06 +00:00
var $ = Backbone . $ ;
2013-05-12 15:22:54 +00:00
var Backgrid = root . Backgrid = {
2013-12-10 08:00:06 +00:00
VERSION : "0.3.0" ,
2013-05-12 15:22:54 +00:00
Extension : { } ,
resolveNameToClass : function ( name , suffix ) {
if ( _ . isString ( name ) ) {
2013-12-10 08:00:06 +00:00
var key = _ . map ( name . split ( '-' ) , function ( e ) {
return e . slice ( 0 , 1 ) . toUpperCase ( ) + e . slice ( 1 ) ;
} ) . join ( '' ) + suffix ;
2013-05-12 15:22:54 +00:00
var klass = Backgrid [ key ] || Backgrid . Extension [ key ] ;
if ( _ . isUndefined ( klass ) ) {
throw new ReferenceError ( "Class '" + key + "' not found" ) ;
}
return klass ;
2013-04-23 00:35:04 +00:00
}
2013-05-12 15:22:54 +00:00
return name ;
2013-12-10 08:00:06 +00:00
} ,
callByNeed : function ( ) {
var value = arguments [ 0 ] ;
if ( ! _ . isFunction ( value ) ) return value ;
var context = arguments [ 1 ] ;
var args = [ ] . slice . call ( arguments , 2 ) ;
return value . apply ( context , ! ! ( args + '' ) ? args : void 0 ) ;
2013-04-23 00:35:04 +00:00
}
2013-12-10 08:00:06 +00:00
2013-05-12 15:22:54 +00:00
} ;
_ . extend ( Backgrid , Backbone . Events ) ;
/ * *
Command translates a DOM Event into commands that Backgrid
recognizes . Interested parties can listen on selected Backgrid events that
come with an instance of this class and act on the commands .
It is also possible to globally rebind the keyboard shortcuts by replacing
the methods in this class ' prototype .
@ class Backgrid . Command
@ constructor
* /
var Command = Backgrid . Command = function ( evt ) {
_ . extend ( this , {
altKey : ! ! evt . altKey ,
2013-12-10 08:00:06 +00:00
"char" : evt [ "char" ] ,
2013-05-12 15:22:54 +00:00
charCode : evt . charCode ,
ctrlKey : ! ! evt . ctrlKey ,
key : evt . key ,
keyCode : evt . keyCode ,
locale : evt . locale ,
location : evt . location ,
metaKey : ! ! evt . metaKey ,
repeat : ! ! evt . repeat ,
shiftKey : ! ! evt . shiftKey ,
which : evt . which
} ) ;
} ;
_ . extend ( Command . prototype , {
/ * *
Up Arrow
@ member Backgrid . Command
* /
moveUp : function ( ) { return this . keyCode == 38 ; } ,
/ * *
Down Arrow
@ member Backgrid . Command
* /
moveDown : function ( ) { return this . keyCode === 40 ; } ,
/ * *
Shift Tab
@ member Backgrid . Command
* /
moveLeft : function ( ) { return this . shiftKey && this . keyCode === 9 ; } ,
/ * *
Tab
@ member Backgrid . Command
* /
moveRight : function ( ) { return ! this . shiftKey && this . keyCode === 9 ; } ,
/ * *
Enter
@ member Backgrid . Command
* /
save : function ( ) { return this . keyCode === 13 ; } ,
/ * *
Esc
@ member Backgrid . Command
* /
cancel : function ( ) { return this . keyCode === 27 ; } ,
/ * *
None of the above .
@ member Backgrid . Command
* /
passThru : function ( ) {
return ! ( this . moveUp ( ) || this . moveDown ( ) || this . moveLeft ( ) ||
this . moveRight ( ) || this . save ( ) || this . cancel ( ) ) ;
}
} ) ;
2013-04-23 00:35:04 +00:00
2013-12-10 08:00:06 +00:00
2013-04-23 00:35:04 +00:00
/ *
backgrid
http : //github.com/wyuenho/backgrid
Copyright ( c ) 2013 Jimmy Yuen Ho Wong and contributors
2013-12-10 08:00:06 +00:00
Licensed under the MIT license .
2013-04-23 00:35:04 +00:00
* /
/ * *
Just a convenient class for interested parties to subclass .
The default Cell classes don ' t require the formatter to be a subclass of
Formatter as long as the fromRaw ( rawData ) and toRaw ( formattedData ) methods
are defined .
@ abstract
@ class Backgrid . CellFormatter
@ constructor
* /
var CellFormatter = Backgrid . CellFormatter = function ( ) { } ;
_ . extend ( CellFormatter . prototype , {
/ * *
Takes a raw value from a model and returns an optionally formatted string
for display . The default implementation simply returns the supplied value
as is without any type conversion .
@ member Backgrid . CellFormatter
@ param { * } rawData
2013-12-10 08:00:06 +00:00
@ param { Backbone . Model } model Used for more complicated formatting
2013-04-23 00:35:04 +00:00
@ return { * }
* /
2013-12-10 08:00:06 +00:00
fromRaw : function ( rawData , model ) {
2013-04-23 00:35:04 +00:00
return rawData ;
} ,
/ * *
Takes a formatted string , usually from user input , and returns a
appropriately typed value for persistence in the model .
If the user input is invalid or unable to be converted to a raw value
suitable for persistence in the model , toRaw must return ` undefined ` .
@ member Backgrid . CellFormatter
@ param { string } formattedData
2013-12-10 08:00:06 +00:00
@ param { Backbone . Model } model Used for more complicated formatting
2013-04-23 00:35:04 +00:00
@ return { * | undefined }
* /
2013-12-10 08:00:06 +00:00
toRaw : function ( formattedData , model ) {
2013-04-23 00:35:04 +00:00
return formattedData ;
}
} ) ;
/ * *
2013-12-10 08:00:06 +00:00
A floating point number formatter . Doesn ' t understand scientific notation at
the moment .
2013-04-23 00:35:04 +00:00
@ class Backgrid . NumberFormatter
@ extends Backgrid . CellFormatter
@ constructor
@ throws { RangeError } If decimals < 0 or > 20.
* /
var NumberFormatter = Backgrid . NumberFormatter = function ( options ) {
2013-12-10 08:00:06 +00:00
_ . extend ( this , this . defaults , options || { } ) ;
2013-04-23 00:35:04 +00:00
if ( this . decimals < 0 || this . decimals > 20 ) {
throw new RangeError ( "decimals must be between 0 and 20" ) ;
}
} ;
NumberFormatter . prototype = new CellFormatter ( ) ;
_ . extend ( NumberFormatter . prototype , {
/ * *
@ member Backgrid . NumberFormatter
@ cfg { Object } options
@ cfg { number } [ options . decimals = 2 ] Number of decimals to display . Must be an integer .
@ cfg { string } [ options . decimalSeparator = '.' ] The separator to use when
displaying decimals .
@ cfg { string } [ options . orderSeparator = ',' ] The separator to use to
separator thousands . May be an empty string .
* /
defaults : {
decimals : 2 ,
decimalSeparator : '.' ,
orderSeparator : ','
} ,
HUMANIZED _NUM _RE : /(\d)(?=(?:\d{3})+$)/g ,
/ * *
Takes a floating point number and convert it to a formatted string where
every thousand is separated by ` orderSeparator ` , with a ` decimal ` number of
decimals separated by ` decimalSeparator ` . The number returned is rounded
the usual way .
@ member Backgrid . NumberFormatter
@ param { number } number
2013-12-10 08:00:06 +00:00
@ param { Backbone . Model } model Used for more complicated formatting
2013-04-23 00:35:04 +00:00
@ return { string }
* /
2013-12-10 08:00:06 +00:00
fromRaw : function ( number , model ) {
2013-04-23 00:35:04 +00:00
if ( _ . isNull ( number ) || _ . isUndefined ( number ) ) return '' ;
number = number . toFixed ( ~ ~ this . decimals ) ;
var parts = number . split ( '.' ) ;
var integerPart = parts [ 0 ] ;
var decimalPart = parts [ 1 ] ? ( this . decimalSeparator || '.' ) + parts [ 1 ] : '' ;
return integerPart . replace ( this . HUMANIZED _NUM _RE , '$1' + this . orderSeparator ) + decimalPart ;
} ,
/ * *
Takes a string , possibly formatted with ` orderSeparator ` and / or
` decimalSeparator ` , and convert it back to a number .
@ member Backgrid . NumberFormatter
@ param { string } formattedData
2013-12-10 08:00:06 +00:00
@ param { Backbone . Model } model Used for more complicated formatting
2013-04-23 00:35:04 +00:00
@ return { number | undefined } Undefined if the string cannot be converted to
a number .
* /
2013-12-10 08:00:06 +00:00
toRaw : function ( formattedData , model ) {
formattedData = formattedData . trim ( ) ;
if ( formattedData === '' ) return null ;
2013-04-23 00:35:04 +00:00
var rawData = '' ;
2013-12-10 08:00:06 +00:00
var thousands = formattedData . split ( this . orderSeparator ) ;
2013-04-23 00:35:04 +00:00
for ( var i = 0 ; i < thousands . length ; i ++ ) {
rawData += thousands [ i ] ;
}
var decimalParts = rawData . split ( this . decimalSeparator ) ;
rawData = '' ;
for ( var i = 0 ; i < decimalParts . length ; i ++ ) {
rawData = rawData + decimalParts [ i ] + '.' ;
}
if ( rawData [ rawData . length - 1 ] === '.' ) {
rawData = rawData . slice ( 0 , rawData . length - 1 ) ;
}
var result = ( rawData * 1 ) . toFixed ( ~ ~ this . decimals ) * 1 ;
if ( _ . isNumber ( result ) && ! _ . isNaN ( result ) ) return result ;
}
} ) ;
/ * *
2013-05-12 15:22:54 +00:00
Formatter to converts between various datetime formats .
2013-04-23 00:35:04 +00:00
2013-05-12 15:22:54 +00:00
This class only understands ISO - 8601 formatted datetime strings and UNIX
offset ( number of milliseconds since UNIX Epoch ) . See
2013-04-23 00:35:04 +00:00
Backgrid . Extension . MomentFormatter if you need a much more flexible datetime
formatter .
@ class Backgrid . DatetimeFormatter
@ extends Backgrid . CellFormatter
@ constructor
@ throws { Error } If both ` includeDate ` and ` includeTime ` are false .
* /
var DatetimeFormatter = Backgrid . DatetimeFormatter = function ( options ) {
2013-12-10 08:00:06 +00:00
_ . extend ( this , this . defaults , options || { } ) ;
2013-04-23 00:35:04 +00:00
if ( ! this . includeDate && ! this . includeTime ) {
throw new Error ( "Either includeDate or includeTime must be true" ) ;
}
} ;
DatetimeFormatter . prototype = new CellFormatter ( ) ;
_ . extend ( DatetimeFormatter . prototype , {
/ * *
@ member Backgrid . DatetimeFormatter
@ cfg { Object } options
@ cfg { boolean } [ options . includeDate = true ] Whether the values include the
date part .
@ cfg { boolean } [ options . includeTime = true ] Whether the values include the
time part .
@ cfg { boolean } [ options . includeMilli = false ] If ` includeTime ` is true ,
whether to include the millisecond part , if it exists .
* /
defaults : {
includeDate : true ,
includeTime : true ,
includeMilli : false
} ,
DATE _RE : /^([+\-]?\d{4})-(\d{2})-(\d{2})$/ ,
TIME _RE : /^(\d{2}):(\d{2}):(\d{2})(\.(\d{3}))?$/ ,
ISO _SPLITTER _RE : /T|Z| +/ ,
_convert : function ( data , validate ) {
2013-12-10 08:00:06 +00:00
if ( ( data + '' ) . trim ( ) === '' ) return null ;
2013-05-12 15:22:54 +00:00
var date , time = null ;
if ( _ . isNumber ( data ) ) {
var jsDate = new Date ( data ) ;
date = lpad ( jsDate . getUTCFullYear ( ) , 4 , 0 ) + '-' + lpad ( jsDate . getUTCMonth ( ) + 1 , 2 , 0 ) + '-' + lpad ( jsDate . getUTCDate ( ) , 2 , 0 ) ;
time = lpad ( jsDate . getUTCHours ( ) , 2 , 0 ) + ':' + lpad ( jsDate . getUTCMinutes ( ) , 2 , 0 ) + ':' + lpad ( jsDate . getUTCSeconds ( ) , 2 , 0 ) ;
}
else {
data = data . trim ( ) ;
var parts = data . split ( this . ISO _SPLITTER _RE ) || [ ] ;
date = this . DATE _RE . test ( parts [ 0 ] ) ? parts [ 0 ] : '' ;
time = date && parts [ 1 ] ? parts [ 1 ] : this . TIME _RE . test ( parts [ 0 ] ) ? parts [ 0 ] : '' ;
}
2013-04-23 00:35:04 +00:00
var YYYYMMDD = this . DATE _RE . exec ( date ) || [ ] ;
var HHmmssSSS = this . TIME _RE . exec ( time ) || [ ] ;
if ( validate ) {
if ( this . includeDate && _ . isUndefined ( YYYYMMDD [ 0 ] ) ) return ;
if ( this . includeTime && _ . isUndefined ( HHmmssSSS [ 0 ] ) ) return ;
if ( ! this . includeDate && date ) return ;
if ( ! this . includeTime && time ) return ;
}
var jsDate = new Date ( Date . UTC ( YYYYMMDD [ 1 ] * 1 || 0 ,
YYYYMMDD [ 2 ] * 1 - 1 || 0 ,
YYYYMMDD [ 3 ] * 1 || 0 ,
HHmmssSSS [ 1 ] * 1 || null ,
HHmmssSSS [ 2 ] * 1 || null ,
HHmmssSSS [ 3 ] * 1 || null ,
HHmmssSSS [ 5 ] * 1 || null ) ) ;
var result = '' ;
if ( this . includeDate ) {
result = lpad ( jsDate . getUTCFullYear ( ) , 4 , 0 ) + '-' + lpad ( jsDate . getUTCMonth ( ) + 1 , 2 , 0 ) + '-' + lpad ( jsDate . getUTCDate ( ) , 2 , 0 ) ;
}
if ( this . includeTime ) {
result = result + ( this . includeDate ? 'T' : '' ) + lpad ( jsDate . getUTCHours ( ) , 2 , 0 ) + ':' + lpad ( jsDate . getUTCMinutes ( ) , 2 , 0 ) + ':' + lpad ( jsDate . getUTCSeconds ( ) , 2 , 0 ) ;
if ( this . includeMilli ) {
result = result + '.' + lpad ( jsDate . getUTCMilliseconds ( ) , 3 , 0 ) ;
}
}
if ( this . includeDate && this . includeTime ) {
result += "Z" ;
}
return result ;
} ,
/ * *
Converts an ISO - 8601 formatted datetime string to a datetime string , date
string or a time string . The timezone is ignored if supplied .
@ member Backgrid . DatetimeFormatter
@ param { string } rawData
2013-12-10 08:00:06 +00:00
@ param { Backbone . Model } model Used for more complicated formatting
2013-04-23 00:35:04 +00:00
@ return { string | null | undefined } ISO - 8601 string in UTC . Null and undefined
values are returned as is .
* /
2013-12-10 08:00:06 +00:00
fromRaw : function ( rawData , model ) {
2013-04-23 00:35:04 +00:00
if ( _ . isNull ( rawData ) || _ . isUndefined ( rawData ) ) return '' ;
return this . _convert ( rawData ) ;
} ,
/ * *
Converts an ISO - 8601 formatted datetime string to a datetime string , date
string or a time string . The timezone is ignored if supplied . This method
parses the input values exactly the same way as
Backgrid . Extension . MomentFormatter # fromRaw ( ) , in addition to doing some
sanity checks .
@ member Backgrid . DatetimeFormatter
@ param { string } formattedData
2013-12-10 08:00:06 +00:00
@ param { Backbone . Model } model Used for more complicated formatting
2013-04-23 00:35:04 +00:00
@ return { string | undefined } ISO - 8601 string in UTC . Undefined if a date is
found when ` includeDate ` is false , or a time is found when ` includeTime ` is
false , or if ` includeDate ` is true and a date is not found , or if
` includeTime ` is true and a time is not found .
* /
2013-12-10 08:00:06 +00:00
toRaw : function ( formattedData , model ) {
2013-04-23 00:35:04 +00:00
return this . _convert ( formattedData , true ) ;
}
} ) ;
/ * *
Formatter to convert any value to string .
@ class Backgrid . StringFormatter
@ extends Backgrid . CellFormatter
@ constructor
* /
var StringFormatter = Backgrid . StringFormatter = function ( ) { } ;
StringFormatter . prototype = new CellFormatter ( ) ;
_ . extend ( StringFormatter . prototype , {
/ * *
Converts any value to a string using Ecmascript ' s implicit type
conversion . If the given value is ` null ` or ` undefined ` , an empty string is
returned instead .
@ member Backgrid . StringFormatter
@ param { * } rawValue
2013-12-10 08:00:06 +00:00
@ param { Backbone . Model } model Used for more complicated formatting
2013-04-23 00:35:04 +00:00
@ return { string }
* /
2013-12-10 08:00:06 +00:00
fromRaw : function ( rawValue , model ) {
2013-04-23 00:35:04 +00:00
if ( _ . isUndefined ( rawValue ) || _ . isNull ( rawValue ) ) return '' ;
return rawValue + '' ;
}
} ) ;
/ * *
Simple email validation formatter .
@ class Backgrid . EmailFormatter
@ extends Backgrid . CellFormatter
@ constructor
* /
var EmailFormatter = Backgrid . EmailFormatter = function ( ) { } ;
EmailFormatter . prototype = new CellFormatter ( ) ;
_ . extend ( EmailFormatter . prototype , {
/ * *
Return the input if it is a string that contains an '@' character and if
the strings before and after '@' are non - empty . If the input does not
validate , ` undefined ` is returned .
@ member Backgrid . EmailFormatter
@ param { * } formattedData
2013-12-10 08:00:06 +00:00
@ param { Backbone . Model } model Used for more complicated formatting
2013-04-23 00:35:04 +00:00
@ return { string | undefined }
* /
2013-12-10 08:00:06 +00:00
toRaw : function ( formattedData , model ) {
2013-04-23 00:35:04 +00:00
var parts = formattedData . trim ( ) . split ( "@" ) ;
if ( parts . length === 2 && _ . all ( parts ) ) {
return formattedData ;
}
}
} ) ;
2013-05-12 15:22:54 +00:00
/ * *
Formatter for SelectCell .
@ class Backgrid . SelectFormatter
@ extends Backgrid . CellFormatter
@ constructor
* /
var SelectFormatter = Backgrid . SelectFormatter = function ( ) { } ;
SelectFormatter . prototype = new CellFormatter ( ) ;
_ . extend ( SelectFormatter . prototype , {
/ * *
Normalizes raw scalar or array values to an array .
@ member Backgrid . SelectFormatter
@ param { * } rawValue
2013-12-10 08:00:06 +00:00
@ param { Backbone . Model } model Used for more complicated formatting
2013-05-12 15:22:54 +00:00
@ return { Array . < * > }
* /
2013-12-10 08:00:06 +00:00
fromRaw : function ( rawValue , model ) {
2013-05-12 15:22:54 +00:00
return _ . isArray ( rawValue ) ? rawValue : rawValue != null ? [ rawValue ] : [ ] ;
}
} ) ;
2013-12-10 08:00:06 +00:00
2013-04-23 00:35:04 +00:00
/ *
backgrid
http : //github.com/wyuenho/backgrid
Copyright ( c ) 2013 Jimmy Yuen Ho Wong and contributors
2013-12-10 08:00:06 +00:00
Licensed under the MIT license .
2013-04-23 00:35:04 +00:00
* /
/ * *
Generic cell editor base class . Only defines an initializer for a number of
required parameters .
@ abstract
@ class Backgrid . CellEditor
@ extends Backbone . View
* /
var CellEditor = Backgrid . CellEditor = Backbone . View . extend ( {
/ * *
Initializer .
@ param { Object } options
@ param { Backgrid . CellFormatter } options . formatter
@ param { Backgrid . Column } options . column
@ param { Backbone . Model } options . model
@ throws { TypeError } If ` formatter ` is not a formatter instance , or when
` model ` or ` column ` are undefined .
* /
initialize : function ( options ) {
this . formatter = options . formatter ;
this . column = options . column ;
if ( ! ( this . column instanceof Column ) ) {
this . column = new Column ( this . column ) ;
}
2013-05-12 15:22:54 +00:00
this . listenTo ( this . model , "backgrid:editing" , this . postRender ) ;
2013-04-23 00:35:04 +00:00
} ,
/ * *
Post - rendering setup and initialization . Focuses the cell editor ' s ` el ` in
this default implementation . * * Should * * be called by Cell classes after
calling Backgrid . CellEditor # render .
* /
2013-05-12 15:22:54 +00:00
postRender : function ( model , column ) {
if ( column == null || column . get ( "name" ) == this . column . get ( "name" ) ) {
this . $el . focus ( ) ;
}
2013-04-23 00:35:04 +00:00
return this ;
}
} ) ;
/ * *
InputCellEditor the cell editor type used by most core cell types . This cell
editor renders a text input box as its editor . The input will render a
placeholder if the value is empty on supported browsers .
@ class Backgrid . InputCellEditor
@ extends Backgrid . CellEditor
* /
var InputCellEditor = Backgrid . InputCellEditor = CellEditor . extend ( {
/** @property */
tagName : "input" ,
/** @property */
attributes : {
type : "text"
} ,
/** @property */
events : {
"blur" : "saveOrCancel" ,
"keydown" : "saveOrCancel"
} ,
/ * *
Initializer . Removes this ` el ` from the DOM when a ` done ` event is
triggered .
@ param { Object } options
@ param { Backgrid . CellFormatter } options . formatter
@ param { Backgrid . Column } options . column
@ param { Backbone . Model } options . model
@ param { string } [ options . placeholder ]
* /
initialize : function ( options ) {
2013-12-10 08:00:06 +00:00
InputCellEditor . _ _super _ _ . initialize . apply ( this , arguments ) ;
2013-04-23 00:35:04 +00:00
if ( options . placeholder ) {
this . $el . attr ( "placeholder" , options . placeholder ) ;
}
} ,
/ * *
Renders a text input with the cell value formatted for display , if it
exists .
* /
render : function ( ) {
2013-12-10 08:00:06 +00:00
var model = this . model
this . $el . val ( this . formatter . fromRaw ( model . get ( this . column . get ( "name" ) ) , model ) ) ;
2013-04-23 00:35:04 +00:00
return this ;
} ,
/ * *
2013-05-12 15:22:54 +00:00
If the key pressed is ` enter ` , ` tab ` , ` up ` , or ` down ` , converts the value
in the editor to a raw value for saving into the model using the formatter .
2013-04-23 00:35:04 +00:00
If the key pressed is ` esc ` the changes are undone .
2013-05-12 15:22:54 +00:00
If the editor goes out of focus ( ` blur ` ) but the value is invalid , the
event is intercepted and cancelled so the cell remains in focus pending for
further action . The changes are saved otherwise .
2013-04-23 00:35:04 +00:00
2013-05-12 15:22:54 +00:00
Triggers a Backbone ` backgrid:edited ` event from the model when successful ,
and ` backgrid:error ` if the value cannot be converted . Classes listening to
the ` error ` event , usually the Cell classes , should respond appropriately ,
usually by rendering some kind of error feedback .
2013-04-23 00:35:04 +00:00
@ param { Event } e
* /
saveOrCancel : function ( e ) {
var formatter = this . formatter ;
var model = this . model ;
var column = this . column ;
2013-05-12 15:22:54 +00:00
var command = new Command ( e ) ;
var blurred = e . type === "blur" ;
if ( command . moveUp ( ) || command . moveDown ( ) || command . moveLeft ( ) || command . moveRight ( ) ||
command . save ( ) || blurred ) {
2013-04-23 00:35:04 +00:00
e . preventDefault ( ) ;
2013-05-12 15:22:54 +00:00
e . stopPropagation ( ) ;
var val = this . $el . val ( ) ;
2013-12-10 08:00:06 +00:00
var newValue = formatter . toRaw ( val , model ) ;
2013-05-12 15:22:54 +00:00
if ( _ . isUndefined ( newValue ) ) {
model . trigger ( "backgrid:error" , model , column , val ) ;
2013-04-23 00:35:04 +00:00
}
else {
2013-05-12 15:22:54 +00:00
model . set ( column . get ( "name" ) , newValue ) ;
model . trigger ( "backgrid:edited" , model , column , command ) ;
2013-04-23 00:35:04 +00:00
}
}
// esc
2013-05-12 15:22:54 +00:00
else if ( command . cancel ( ) ) {
2013-04-23 00:35:04 +00:00
// undo
e . stopPropagation ( ) ;
2013-05-12 15:22:54 +00:00
model . trigger ( "backgrid:edited" , model , column , command ) ;
2013-04-23 00:35:04 +00:00
}
} ,
2013-05-12 15:22:54 +00:00
postRender : function ( model , column ) {
if ( column == null || column . get ( "name" ) == this . column . get ( "name" ) ) {
// move the cursor to the end on firefox if text is right aligned
if ( this . $el . css ( "text-align" ) === "right" ) {
var val = this . $el . val ( ) ;
this . $el . focus ( ) . val ( null ) . val ( val ) ;
}
else this . $el . focus ( ) ;
2013-04-23 00:35:04 +00:00
}
return this ;
}
} ) ;
/ * *
The super - class for all Cell types . By default , this class renders a plain
table cell with the model value converted to a string using the
formatter . The table cell is clickable , upon which the cell will go into
editor mode , which is rendered by a Backgrid . InputCellEditor instance by
2013-05-12 15:22:54 +00:00
default . Upon encountering any formatting errors , this class will add an
` error ` CSS class to the table cell .
2013-04-23 00:35:04 +00:00
@ abstract
@ class Backgrid . Cell
@ extends Backbone . View
* /
var Cell = Backgrid . Cell = Backbone . View . extend ( {
/** @property */
tagName : "td" ,
/ * *
2013-12-10 08:00:06 +00:00
@ property { Backgrid . CellFormatter | Object | string } [ formatter = CellFormatter ]
2013-04-23 00:35:04 +00:00
* /
2013-12-10 08:00:06 +00:00
formatter : CellFormatter ,
2013-04-23 00:35:04 +00:00
/ * *
@ property { Backgrid . CellEditor } [ editor = Backgrid . InputCellEditor ] The
default editor for all cell instances of this class . This value must be a
class , it will be automatically instantiated upon entering edit mode .
See Backgrid . CellEditor
* /
editor : InputCellEditor ,
/** @property */
events : {
"click" : "enterEditMode"
} ,
/ * *
Initializer .
@ param { Object } options
@ param { Backbone . Model } options . model
@ param { Backgrid . Column } options . column
@ throws { ReferenceError } If formatter is a string but a formatter class of
said name cannot be found in the Backgrid module .
* /
initialize : function ( options ) {
this . column = options . column ;
if ( ! ( this . column instanceof Column ) ) {
this . column = new Column ( this . column ) ;
}
2013-12-10 08:00:06 +00:00
var column = this . column , model = this . model , $el = this . $el ;
var formatter = Backgrid . resolveNameToClass ( column . get ( "formatter" ) ||
this . formatter , "Formatter" ) ;
if ( ! _ . isFunction ( formatter . fromRaw ) && ! _ . isFunction ( formatter . toRaw ) ) {
formatter = new formatter ( ) ;
}
this . formatter = formatter ;
2013-05-12 15:22:54 +00:00
this . editor = Backgrid . resolveNameToClass ( this . editor , "CellEditor" ) ;
2013-12-10 08:00:06 +00:00
this . listenTo ( model , "change:" + column . get ( "name" ) , function ( ) {
if ( ! $el . hasClass ( "editor" ) ) this . render ( ) ;
2013-04-23 00:35:04 +00:00
} ) ;
2013-12-10 08:00:06 +00:00
this . listenTo ( model , "backgrid:error" , this . renderError ) ;
this . listenTo ( column , "change:editable change:sortable change:renderable" ,
function ( column ) {
var changed = column . changedAttributes ( ) ;
for ( var key in changed ) {
if ( changed . hasOwnProperty ( key ) ) {
$el . toggleClass ( key , changed [ key ] ) ;
}
}
} ) ;
if ( column . get ( "editable" ) ) $el . addClass ( "editable" ) ;
if ( column . get ( "sortable" ) ) $el . addClass ( "sortable" ) ;
if ( column . get ( "renderable" ) ) $el . addClass ( "renderable" ) ;
2013-04-23 00:35:04 +00:00
} ,
/ * *
Render a text string in a table cell . The text is converted from the
model 's raw value for this cell' s column .
* /
render : function ( ) {
this . $el . empty ( ) ;
2013-12-10 08:00:06 +00:00
var model = this . model ;
this . $el . text ( this . formatter . fromRaw ( model . get ( this . column . get ( "name" ) ) , model ) ) ;
2013-04-23 00:35:04 +00:00
this . delegateEvents ( ) ;
return this ;
} ,
/ * *
If this column is editable , a new CellEditor instance is instantiated with
2013-05-12 15:22:54 +00:00
its required parameters . An ` editor ` CSS class is added to the cell upon
2013-04-23 00:35:04 +00:00
entering edit mode .
2013-05-12 15:22:54 +00:00
This method triggers a Backbone ` backgrid:edit ` event from the model when
the cell is entering edit mode and an editor instance has been constructed ,
but before it is rendered and inserted into the DOM . The cell and the
constructed cell editor instance are sent as event parameters when this
event is triggered .
2013-04-23 00:35:04 +00:00
When this cell has finished switching to edit mode , a Backbone
2013-05-12 15:22:54 +00:00
` backgrid:editing ` event is triggered from the model . The cell and the
constructed cell instance are also sent as parameters in the event .
When the model triggers a ` backgrid:error ` event , it means the editor is
unable to convert the current user input to an apprpriate value for the
model ' s column , and an ` error ` CSS class is added to the cell accordingly .
2013-04-23 00:35:04 +00:00
* /
enterEditMode : function ( ) {
2013-05-12 15:22:54 +00:00
var model = this . model ;
var column = this . column ;
2013-12-10 08:00:06 +00:00
var editable = Backgrid . callByNeed ( column . editable ( ) , column , model ) ;
if ( editable ) {
2013-04-23 00:35:04 +00:00
this . currentEditor = new this . editor ( {
column : this . column ,
model : this . model ,
formatter : this . formatter
} ) ;
2013-05-12 15:22:54 +00:00
model . trigger ( "backgrid:edit" , model , column , this , this . currentEditor ) ;
2013-04-23 00:35:04 +00:00
2013-05-12 15:22:54 +00:00
// Need to redundantly undelegate events for Firefox
2013-04-23 00:35:04 +00:00
this . undelegateEvents ( ) ;
2013-05-12 15:22:54 +00:00
this . $el . empty ( ) ;
2013-04-23 00:35:04 +00:00
this . $el . append ( this . currentEditor . $el ) ;
this . currentEditor . render ( ) ;
this . $el . addClass ( "editor" ) ;
2013-05-12 15:22:54 +00:00
model . trigger ( "backgrid:editing" , model , column , this , this . currentEditor ) ;
2013-04-23 00:35:04 +00:00
}
} ,
/ * *
Put an ` error ` CSS class on the table cell .
* /
2013-05-12 15:22:54 +00:00
renderError : function ( model , column ) {
if ( column == null || column . get ( "name" ) == this . column . get ( "name" ) ) {
this . $el . addClass ( "error" ) ;
}
2013-04-23 00:35:04 +00:00
} ,
/ * *
Removes the editor and re - render in display mode .
* /
exitEditMode : function ( ) {
this . $el . removeClass ( "error" ) ;
2013-05-12 15:22:54 +00:00
this . currentEditor . remove ( ) ;
2013-04-23 00:35:04 +00:00
this . stopListening ( this . currentEditor ) ;
delete this . currentEditor ;
this . $el . removeClass ( "editor" ) ;
this . render ( ) ;
} ,
/ * *
Clean up this cell .
@ chainable
2013-05-12 15:22:54 +00:00
* /
2013-04-23 00:35:04 +00:00
remove : function ( ) {
if ( this . currentEditor ) {
2013-12-10 08:00:06 +00:00
this . currentEditor . remove . apply ( this . currentEditor , arguments ) ;
2013-04-23 00:35:04 +00:00
delete this . currentEditor ;
}
2013-12-10 08:00:06 +00:00
return Cell . _ _super _ _ . remove . apply ( this , arguments ) ;
2013-04-23 00:35:04 +00:00
}
} ) ;
/ * *
StringCell displays HTML escaped strings and accepts anything typed in .
@ class Backgrid . StringCell
@ extends Backgrid . Cell
* /
var StringCell = Backgrid . StringCell = Cell . extend ( {
/** @property */
className : "string-cell" ,
2013-12-10 08:00:06 +00:00
formatter : StringFormatter
2013-04-23 00:35:04 +00:00
} ) ;
/ * *
UriCell renders an HTML ` <a> ` anchor for the value and accepts URIs as user
input values . No type conversion or URL validation is done by the formatter
of this cell . Users who need URL validation are encourage to subclass UriCell
to take advantage of the parsing capabilities of the HTMLAnchorElement
available on HTML5 - capable browsers or using a third - party library like
[ URI . js ] ( https : //github.com/medialize/URI.js).
@ class Backgrid . UriCell
@ extends Backgrid . Cell
* /
var UriCell = Backgrid . UriCell = Cell . extend ( {
/** @property */
className : "uri-cell" ,
2013-12-10 08:00:06 +00:00
/ * *
@ property { string } [ title ] The title attribute of the generated anchor . It
uses the display value formatted by the ` formatter.fromRaw ` by default .
* /
title : null ,
/ * *
@ property { string } [ target = "_blank" ] The target attribute of the generated
anchor .
* /
target : "_blank" ,
initialize : function ( options ) {
UriCell . _ _super _ _ . initialize . apply ( this , arguments ) ;
this . title = options . title || this . title ;
this . target = options . target || this . target ;
} ,
2013-04-23 00:35:04 +00:00
render : function ( ) {
this . $el . empty ( ) ;
2013-12-10 08:00:06 +00:00
var rawValue = this . model . get ( this . column . get ( "name" ) ) ;
var formattedValue = this . formatter . fromRaw ( rawValue , this . model ) ;
2013-04-23 00:35:04 +00:00
this . $el . append ( $ ( "<a>" , {
2013-05-12 15:22:54 +00:00
tabIndex : - 1 ,
2013-12-10 08:00:06 +00:00
href : rawValue ,
title : this . title || formattedValue ,
target : this . target ,
2013-04-23 00:35:04 +00:00
} ) . text ( formattedValue ) ) ;
this . delegateEvents ( ) ;
return this ;
}
} ) ;
/ * *
Like Backgrid . UriCell , EmailCell renders an HTML ` <a> ` anchor for the
value . The ` href ` in the anchor is prefixed with ` mailto: ` . EmailCell will
complain if the user enters a string that doesn ' t contain the ` @ ` sign .
@ class Backgrid . EmailCell
@ extends Backgrid . StringCell
* /
var EmailCell = Backgrid . EmailCell = StringCell . extend ( {
/** @property */
className : "email-cell" ,
2013-12-10 08:00:06 +00:00
formatter : EmailFormatter ,
2013-04-23 00:35:04 +00:00
render : function ( ) {
this . $el . empty ( ) ;
2013-12-10 08:00:06 +00:00
var model = this . model ;
var formattedValue = this . formatter . fromRaw ( model . get ( this . column . get ( "name" ) ) , model ) ;
2013-04-23 00:35:04 +00:00
this . $el . append ( $ ( "<a>" , {
2013-05-12 15:22:54 +00:00
tabIndex : - 1 ,
2013-04-23 00:35:04 +00:00
href : "mailto:" + formattedValue ,
title : formattedValue
} ) . text ( formattedValue ) ) ;
this . delegateEvents ( ) ;
return this ;
}
} ) ;
/ * *
NumberCell is a generic cell that renders all numbers . Numbers are formatted
using a Backgrid . NumberFormatter .
@ class Backgrid . NumberCell
@ extends Backgrid . Cell
* /
var NumberCell = Backgrid . NumberCell = Cell . extend ( {
/** @property */
className : "number-cell" ,
/ * *
@ property { number } [ decimals = 2 ] Must be an integer .
* /
decimals : NumberFormatter . prototype . defaults . decimals ,
/** @property {string} [decimalSeparator='.'] */
decimalSeparator : NumberFormatter . prototype . defaults . decimalSeparator ,
/** @property {string} [orderSeparator=','] */
orderSeparator : NumberFormatter . prototype . defaults . orderSeparator ,
/** @property {Backgrid.CellFormatter} [formatter=Backgrid.NumberFormatter] */
formatter : NumberFormatter ,
/ * *
Initializes this cell and the number formatter .
@ param { Object } options
@ param { Backbone . Model } options . model
@ param { Backgrid . Column } options . column
* /
initialize : function ( options ) {
2013-12-10 08:00:06 +00:00
NumberCell . _ _super _ _ . initialize . apply ( this , arguments ) ;
var formatter = this . formatter ;
formatter . decimals = this . decimals ;
formatter . decimalSeparator = this . decimalSeparator ;
formatter . orderSeparator = this . orderSeparator ;
2013-04-23 00:35:04 +00:00
}
} ) ;
/ * *
An IntegerCell is just a Backgrid . NumberCell with 0 decimals . If a floating
point number is supplied , the number is simply rounded the usual way when
displayed .
@ class Backgrid . IntegerCell
@ extends Backgrid . NumberCell
* /
var IntegerCell = Backgrid . IntegerCell = NumberCell . extend ( {
/** @property */
className : "integer-cell" ,
/ * *
@ property { number } decimals Must be an integer .
* /
decimals : 0
} ) ;
/ * *
DatetimeCell is a basic cell that accepts datetime string values in RFC - 2822
or W3C ' s subset of ISO - 8601 and displays them in ISO - 8601 format . For a much
more sophisticated date time cell with better datetime formatting , take a
look at the Backgrid . Extension . MomentCell extension .
@ class Backgrid . DatetimeCell
@ extends Backgrid . Cell
See :
- Backgrid . Extension . MomentCell
- Backgrid . DatetimeFormatter
* /
var DatetimeCell = Backgrid . DatetimeCell = Cell . extend ( {
/** @property */
className : "datetime-cell" ,
/ * *
@ property { boolean } [ includeDate = true ]
* /
includeDate : DatetimeFormatter . prototype . defaults . includeDate ,
/ * *
@ property { boolean } [ includeTime = true ]
* /
includeTime : DatetimeFormatter . prototype . defaults . includeTime ,
/ * *
@ property { boolean } [ includeMilli = false ]
* /
includeMilli : DatetimeFormatter . prototype . defaults . includeMilli ,
/** @property {Backgrid.CellFormatter} [formatter=Backgrid.DatetimeFormatter] */
formatter : DatetimeFormatter ,
/ * *
Initializes this cell and the datetime formatter .
@ param { Object } options
@ param { Backbone . Model } options . model
@ param { Backgrid . Column } options . column
* /
initialize : function ( options ) {
2013-12-10 08:00:06 +00:00
DatetimeCell . _ _super _ _ . initialize . apply ( this , arguments ) ;
var formatter = this . formatter ;
formatter . includeDate = this . includeDate ;
formatter . includeTime = this . includeTime ;
formatter . includeMilli = this . includeMilli ;
2013-04-23 00:35:04 +00:00
var placeholder = this . includeDate ? "YYYY-MM-DD" : "" ;
placeholder += ( this . includeDate && this . includeTime ) ? "T" : "" ;
placeholder += this . includeTime ? "HH:mm:ss" : "" ;
placeholder += ( this . includeTime && this . includeMilli ) ? ".SSS" : "" ;
this . editor = this . editor . extend ( {
attributes : _ . extend ( { } , this . editor . prototype . attributes , this . editor . attributes , {
placeholder : placeholder
} )
} ) ;
}
} ) ;
/ * *
DateCell is a Backgrid . DatetimeCell without the time part .
@ class Backgrid . DateCell
@ extends Backgrid . DatetimeCell
* /
var DateCell = Backgrid . DateCell = DatetimeCell . extend ( {
/** @property */
className : "date-cell" ,
/** @property */
includeTime : false
} ) ;
/ * *
TimeCell is a Backgrid . DatetimeCell without the date part .
@ class Backgrid . TimeCell
@ extends Backgrid . DatetimeCell
* /
var TimeCell = Backgrid . TimeCell = DatetimeCell . extend ( {
/** @property */
className : "time-cell" ,
/** @property */
includeDate : false
} ) ;
/ * *
2013-05-12 15:22:54 +00:00
BooleanCellEditor renders a checkbox as its editor .
2013-04-23 00:35:04 +00:00
2013-05-12 15:22:54 +00:00
@ class Backgrid . BooleanCellEditor
@ extends Backgrid . CellEditor
2013-04-23 00:35:04 +00:00
* /
2013-05-12 15:22:54 +00:00
var BooleanCellEditor = Backgrid . BooleanCellEditor = CellEditor . extend ( {
2013-04-23 00:35:04 +00:00
/** @property */
2013-05-12 15:22:54 +00:00
tagName : "input" ,
2013-04-23 00:35:04 +00:00
2013-05-12 15:22:54 +00:00
/** @property */
attributes : {
tabIndex : - 1 ,
type : "checkbox"
} ,
2013-04-23 00:35:04 +00:00
2013-05-12 15:22:54 +00:00
/** @property */
2013-04-23 00:35:04 +00:00
events : {
2013-05-12 15:22:54 +00:00
"mousedown" : function ( ) {
this . mouseDown = true ;
} ,
"blur" : "enterOrExitEditMode" ,
"mouseup" : function ( ) {
this . mouseDown = false ;
} ,
"change" : "saveOrCancel" ,
"keydown" : "saveOrCancel"
2013-04-23 00:35:04 +00:00
} ,
/ * *
Renders a checkbox and check it if the model value of this column is true ,
uncheck otherwise .
* /
render : function ( ) {
2013-12-10 08:00:06 +00:00
var model = this . model ;
var val = this . formatter . fromRaw ( model . get ( this . column . get ( "name" ) ) , model ) ;
2013-05-12 15:22:54 +00:00
this . $el . prop ( "checked" , val ) ;
2013-04-23 00:35:04 +00:00
return this ;
} ,
/ * *
2013-05-12 15:22:54 +00:00
Event handler . Hack to deal with the case where ` blur ` is fired before
` change ` and ` click ` on a checkbox .
2013-04-23 00:35:04 +00:00
* /
2013-05-12 15:22:54 +00:00
enterOrExitEditMode : function ( e ) {
if ( ! this . mouseDown ) {
var model = this . model ;
model . trigger ( "backgrid:edited" , model , this . column , new Command ( e ) ) ;
}
2013-04-23 00:35:04 +00:00
} ,
/ * *
2013-05-12 15:22:54 +00:00
Event handler . Save the value into the model if the event is ` change ` or
one of the keyboard navigation key presses . Exit edit mode without saving
if ` escape ` was pressed .
2013-04-23 00:35:04 +00:00
* /
2013-05-12 15:22:54 +00:00
saveOrCancel : function ( e ) {
var model = this . model ;
var column = this . column ;
var formatter = this . formatter ;
var command = new Command ( e ) ;
// skip ahead to `change` when space is pressed
if ( command . passThru ( ) && e . type != "change" ) return true ;
if ( command . cancel ( ) ) {
e . stopPropagation ( ) ;
model . trigger ( "backgrid:edited" , model , column , command ) ;
}
var $el = this . $el ;
if ( command . save ( ) || command . moveLeft ( ) || command . moveRight ( ) || command . moveUp ( ) ||
command . moveDown ( ) ) {
e . preventDefault ( ) ;
e . stopPropagation ( ) ;
2013-12-10 08:00:06 +00:00
var val = formatter . toRaw ( $el . prop ( "checked" ) , model ) ;
2013-05-12 15:22:54 +00:00
model . set ( column . get ( "name" ) , val ) ;
model . trigger ( "backgrid:edited" , model , column , command ) ;
}
else if ( e . type == "change" ) {
2013-12-10 08:00:06 +00:00
var val = formatter . toRaw ( $el . prop ( "checked" ) , model ) ;
2013-05-12 15:22:54 +00:00
model . set ( column . get ( "name" ) , val ) ;
$el . focus ( ) ;
}
}
} ) ;
/ * *
BooleanCell renders a checkbox both during display mode and edit mode . The
checkbox is checked if the model value is true , unchecked otherwise .
@ class Backgrid . BooleanCell
@ extends Backgrid . Cell
* /
var BooleanCell = Backgrid . BooleanCell = Cell . extend ( {
/** @property */
className : "boolean-cell" ,
/** @property */
editor : BooleanCellEditor ,
/** @property */
events : {
"click" : "enterEditMode"
2013-04-23 00:35:04 +00:00
} ,
/ * *
2013-05-12 15:22:54 +00:00
Renders a checkbox and check it if the model value of this column is true ,
uncheck otherwise .
2013-04-23 00:35:04 +00:00
* /
2013-05-12 15:22:54 +00:00
render : function ( ) {
this . $el . empty ( ) ;
2013-12-10 08:00:06 +00:00
var model = this . model , column = this . column ;
var editable = Backgrid . callByNeed ( column . editable ( ) , column , model ) ;
2013-05-12 15:22:54 +00:00
this . $el . append ( $ ( "<input>" , {
tabIndex : - 1 ,
type : "checkbox" ,
2013-12-10 08:00:06 +00:00
checked : this . formatter . fromRaw ( model . get ( column . get ( "name" ) ) , model ) ,
disabled : ! editable
2013-05-12 15:22:54 +00:00
} ) ) ;
this . delegateEvents ( ) ;
return this ;
2013-04-23 00:35:04 +00:00
}
} ) ;
/ * *
SelectCellEditor renders an HTML ` <select> ` fragment as the editor .
@ class Backgrid . SelectCellEditor
@ extends Backgrid . CellEditor
* /
var SelectCellEditor = Backgrid . SelectCellEditor = CellEditor . extend ( {
/** @property */
tagName : "select" ,
/** @property */
events : {
"change" : "save" ,
2013-05-12 15:22:54 +00:00
"blur" : "close" ,
"keydown" : "close"
2013-04-23 00:35:04 +00:00
} ,
/** @property {function(Object, ?Object=): string} template */
2013-12-10 08:00:06 +00:00
template : _ . template ( '<option value="<%- value %>" <%= selected ? \'selected="selected"\' : "" %>><%- text %></option>' , null , { variable : null } ) ,
2013-04-23 00:35:04 +00:00
setOptionValues : function ( optionValues ) {
this . optionValues = optionValues ;
2013-12-10 08:00:06 +00:00
this . optionValues = _ . result ( this , "optionValues" ) ;
2013-04-23 00:35:04 +00:00
} ,
2013-05-12 15:22:54 +00:00
setMultiple : function ( multiple ) {
this . multiple = multiple ;
this . $el . prop ( "multiple" , multiple ) ;
} ,
_renderOptions : function ( nvps , selectedValues ) {
2013-04-23 00:35:04 +00:00
var options = '' ;
for ( var i = 0 ; i < nvps . length ; i ++ ) {
options = options + this . template ( {
text : nvps [ i ] [ 0 ] ,
value : nvps [ i ] [ 1 ] ,
2013-05-12 15:22:54 +00:00
selected : selectedValues . indexOf ( nvps [ i ] [ 1 ] ) > - 1
2013-04-23 00:35:04 +00:00
} ) ;
}
return options ;
} ,
/ * *
Renders the options if ` optionValues ` is a list of name - value pairs . The
options are contained inside option groups if ` optionValues ` is a list of
object hashes . The name is rendered at the option text and the value is the
option value . If ` optionValues ` is a function , it is called without a
parameter .
* /
render : function ( ) {
this . $el . empty ( ) ;
var optionValues = _ . result ( this , "optionValues" ) ;
2013-12-10 08:00:06 +00:00
var model = this . model ;
var selectedValues = this . formatter . fromRaw ( model . get ( this . column . get ( "name" ) ) , model ) ;
2013-04-23 00:35:04 +00:00
2013-12-10 08:00:06 +00:00
if ( ! _ . isArray ( optionValues ) ) throw new TypeError ( "optionValues must be an array" ) ;
2013-04-23 00:35:04 +00:00
var optionValue = null ;
var optionText = null ;
var optionValue = null ;
var optgroupName = null ;
var optgroup = null ;
2013-05-12 15:22:54 +00:00
2013-04-23 00:35:04 +00:00
for ( var i = 0 ; i < optionValues . length ; i ++ ) {
var optionValue = optionValues [ i ] ;
if ( _ . isArray ( optionValue ) ) {
optionText = optionValue [ 0 ] ;
optionValue = optionValue [ 1 ] ;
this . $el . append ( this . template ( {
text : optionText ,
value : optionValue ,
2013-05-12 15:22:54 +00:00
selected : selectedValues . indexOf ( optionValue ) > - 1
2013-04-23 00:35:04 +00:00
} ) ) ;
}
else if ( _ . isObject ( optionValue ) ) {
optgroupName = optionValue . name ;
optgroup = $ ( "<optgroup></optgroup>" , { label : optgroupName } ) ;
2013-05-12 15:22:54 +00:00
optgroup . append ( this . _renderOptions ( optionValue . values , selectedValues ) ) ;
2013-04-23 00:35:04 +00:00
this . $el . append ( optgroup ) ;
}
else {
2013-12-10 08:00:06 +00:00
throw new TypeError ( "optionValues elements must be a name-value pair or an object hash of { name: 'optgroup label', value: [option name-value pairs] }" ) ;
2013-04-23 00:35:04 +00:00
}
}
this . delegateEvents ( ) ;
return this ;
} ,
/ * *
Saves the value of the selected option to the model attribute . Triggers a
2013-05-12 15:22:54 +00:00
` backgrid:edited ` Backbone event from the model .
2013-04-23 00:35:04 +00:00
* /
2013-05-12 15:22:54 +00:00
save : function ( e ) {
var model = this . model ;
var column = this . column ;
2013-12-10 08:00:06 +00:00
model . set ( column . get ( "name" ) , this . formatter . toRaw ( this . $el . val ( ) , model ) ) ;
2013-05-12 15:22:54 +00:00
model . trigger ( "backgrid:edited" , model , column , new Command ( e ) ) ;
2013-04-23 00:35:04 +00:00
} ,
/ * *
2013-05-12 15:22:54 +00:00
Triggers a ` backgrid:edited ` event from the model so the body can close
this editor .
* /
close : function ( e ) {
var model = this . model ;
var column = this . column ;
var command = new Command ( e ) ;
if ( command . cancel ( ) ) {
e . stopPropagation ( ) ;
model . trigger ( "backgrid:edited" , model , column , new Command ( e ) ) ;
}
else if ( command . save ( ) || command . moveLeft ( ) || command . moveRight ( ) ||
command . moveUp ( ) || command . moveDown ( ) || e . type == "blur" ) {
e . preventDefault ( ) ;
e . stopPropagation ( ) ;
if ( e . type == "blur" && this . $el . find ( "option" ) . length === 1 ) {
2013-12-10 08:00:06 +00:00
model . set ( column . get ( "name" ) , this . formatter . toRaw ( this . $el . val ( ) , model ) ) ;
2013-05-12 15:22:54 +00:00
}
model . trigger ( "backgrid:edited" , model , column , new Command ( e ) ) ;
}
2013-04-23 00:35:04 +00:00
}
} ) ;
/ * *
SelectCell is also a different kind of cell in that upon going into edit mode
2013-05-12 15:22:54 +00:00
the cell renders a list of options to pick from , as opposed to an input box .
2013-04-23 00:35:04 +00:00
SelectCell cannot be referenced by its string name when used in a column
2013-05-12 15:22:54 +00:00
definition because it requires an ` optionValues ` class attribute to be
2013-04-23 00:35:04 +00:00
defined . ` optionValues ` can either be a list of name - value pairs , to be
rendered as options , or a list of object hashes which consist of a key * name *
which is the option group name , and a key * values * which is a list of
name - value pairs to be rendered as options under that option group .
In addition , ` optionValues ` can also be a parameter - less function that
returns one of the above . If the options are static , it is recommended the
2013-05-12 15:22:54 +00:00
returned values to be memoized . ` _.memoize() ` is a good function to help with
2013-04-23 00:35:04 +00:00
that .
2013-05-12 15:22:54 +00:00
During display mode , the default formatter will normalize the raw model value
to an array of values whether the raw model value is a scalar or an
array . Each value is compared with the ` optionValues ` values using
2013-04-23 00:35:04 +00:00
Ecmascript ' s implicit type conversion rules . When exiting edit mode , no type
conversion is performed when saving into the model . This behavior is not
always desirable when the value type is anything other than string . To
control type conversion on the client - side , you should subclass SelectCell to
provide a custom formatter or provide the formatter to your column
definition .
2013-05-12 15:22:54 +00:00
See :
[ $ . fn . val ( ) ] ( http : //api.jquery.com/val/)
2013-04-23 00:35:04 +00:00
@ class Backgrid . SelectCell
@ extends Backgrid . Cell
* /
var SelectCell = Backgrid . SelectCell = Cell . extend ( {
/** @property */
className : "select-cell" ,
/** @property */
editor : SelectCellEditor ,
2013-05-12 15:22:54 +00:00
/** @property */
multiple : false ,
/** @property */
2013-12-10 08:00:06 +00:00
formatter : SelectFormatter ,
2013-05-12 15:22:54 +00:00
2013-04-23 00:35:04 +00:00
/ * *
@ property { Array . < Array > | Array . < { name : string , values : Array . < Array > } > } optionValues
* /
optionValues : undefined ,
2013-05-12 15:22:54 +00:00
/** @property */
delimiter : ', ' ,
2013-04-23 00:35:04 +00:00
/ * *
Initializer .
@ param { Object } options
@ param { Backbone . Model } options . model
@ param { Backgrid . Column } options . column
@ throws { TypeError } If ` optionsValues ` is undefined .
* /
initialize : function ( options ) {
2013-12-10 08:00:06 +00:00
SelectCell . _ _super _ _ . initialize . apply ( this , arguments ) ;
2013-05-12 15:22:54 +00:00
this . listenTo ( this . model , "backgrid:edit" , function ( model , column , cell , editor ) {
if ( column . get ( "name" ) == this . column . get ( "name" ) ) {
editor . setOptionValues ( this . optionValues ) ;
editor . setMultiple ( this . multiple ) ;
}
} ) ;
2013-04-23 00:35:04 +00:00
} ,
/ * *
Renders the label using the raw value as key to look up from ` optionValues ` .
@ throws { TypeError } If ` optionValues ` is malformed .
* /
render : function ( ) {
this . $el . empty ( ) ;
2013-12-10 08:00:06 +00:00
var optionValues = _ . result ( this , "optionValues" ) ;
var model = this . model ;
var rawData = this . formatter . fromRaw ( model . get ( this . column . get ( "name" ) ) , model ) ;
2013-04-23 00:35:04 +00:00
2013-05-12 15:22:54 +00:00
var selectedText = [ ] ;
2013-04-23 00:35:04 +00:00
try {
if ( ! _ . isArray ( optionValues ) || _ . isEmpty ( optionValues ) ) throw new TypeError ;
2013-05-12 15:22:54 +00:00
for ( var k = 0 ; k < rawData . length ; k ++ ) {
var rawDatum = rawData [ k ] ;
2013-04-23 00:35:04 +00:00
2013-05-12 15:22:54 +00:00
for ( var i = 0 ; i < optionValues . length ; i ++ ) {
var optionValue = optionValues [ i ] ;
2013-04-23 00:35:04 +00:00
2013-05-12 15:22:54 +00:00
if ( _ . isArray ( optionValue ) ) {
var optionText = optionValue [ 0 ] ;
var optionValue = optionValue [ 1 ] ;
if ( optionValue == rawDatum ) selectedText . push ( optionText ) ;
2013-04-23 00:35:04 +00:00
}
2013-05-12 15:22:54 +00:00
else if ( _ . isObject ( optionValue ) ) {
var optionGroupValues = optionValue . values ;
for ( var j = 0 ; j < optionGroupValues . length ; j ++ ) {
var optionGroupValue = optionGroupValues [ j ] ;
if ( optionGroupValue [ 1 ] == rawDatum ) {
selectedText . push ( optionGroupValue [ 0 ] ) ;
}
2013-04-23 00:35:04 +00:00
}
}
2013-05-12 15:22:54 +00:00
else {
throw new TypeError ;
}
2013-04-23 00:35:04 +00:00
}
}
2013-05-12 15:22:54 +00:00
this . $el . append ( selectedText . join ( this . delimiter ) ) ;
2013-04-23 00:35:04 +00:00
}
catch ( ex ) {
if ( ex instanceof TypeError ) {
2013-12-10 08:00:06 +00:00
throw new TypeError ( "'optionValues' must be of type {Array.<Array>|Array.<{name: string, values: Array.<Array>}>}" ) ;
2013-04-23 00:35:04 +00:00
}
throw ex ;
}
this . delegateEvents ( ) ;
return this ;
}
} ) ;
2013-12-10 08:00:06 +00:00
2013-04-23 00:35:04 +00:00
/ *
backgrid
http : //github.com/wyuenho/backgrid
Copyright ( c ) 2013 Jimmy Yuen Ho Wong and contributors
2013-12-10 08:00:06 +00:00
Licensed under the MIT license .
2013-04-23 00:35:04 +00:00
* /
/ * *
A Column is a placeholder for column metadata .
You usually don ' t need to create an instance of this class yourself as a
collection of column instances will be created for you from a list of column
attributes in the Backgrid . js view class constructors .
@ class Backgrid . Column
@ extends Backbone . Model
2013-12-10 08:00:06 +00:00
* /
2013-04-23 00:35:04 +00:00
var Column = Backgrid . Column = Backbone . Model . extend ( {
2013-12-10 08:00:06 +00:00
/ * *
@ cfg { Object } defaults Column defaults . To override any of these default
values , you can either change the prototype directly to override
Column . defaults globally or extend Column and supply the custom class to
Backgrid . Grid :
// Override Column defaults globally
Column . prototype . defaults . sortable = false ;
// Override Column defaults locally
var MyColumn = Column . extend ( {
defaults : _ . defaults ( {
editable : false
} , Column . prototype . defaults )
} ) ;
var grid = new Backgrid . Grid ( columns : new Columns ( [ { ... } , { ... } ] , {
model : MyColumn
} ) ) ;
@ cfg { string } [ defaults . name ] The default name of the model attribute .
@ cfg { string } [ defaults . label ] The default label to show in the header .
@ cfg { string | Backgrid . Cell } [ defaults . cell ] The default cell type . If this
is a string , the capitalized form will be used to look up a cell class in
Backbone , i . e . : string => StringCell . If a Cell subclass is supplied , it is
initialized with a hash of parameters . If a Cell instance is supplied , it
is used directly .
@ cfg { string | Backgrid . HeaderCell } [ defaults . headerCell ] The default header
cell type .
@ cfg { boolean | string } [ defaults . sortable = true ] Whether this column is
sortable . If the value is a string , a method will the same name will be
looked up from the column instance to determine whether the column should
be sortable . The method ' s signature must be ` function (Backgrid.Column,
Backbone . Model ) : boolean ` .
@ cfg { boolean | string } [ defaults . editable = true ] Whether this column is
editable . If the value is a string , a method will the same name will be
looked up from the column instance to determine whether the column should
be editable . The method ' s signature must be ` function (Backgrid.Column,
Backbone . Model ) : boolean ` .
@ cfg { boolean | string } [ defaults . renderable = true ] Whether this column is
renderable . If the value is a string , a method will the same name will be
looked up from the column instance to determine whether the column should
be renderable . The method ' s signature must be ` function (Backrid.Column,
Backbone . Model ) : boolean ` .
@ cfg { Backgrid . CellFormatter | Object | string } [ defaults . formatter ] The
formatter to use to convert between raw model values and user input .
@ cfg { "toggle" | "cycle" } [ defaults . sortType = "cycle" ] Whether sorting will
toggle between ascending and descending order , or cycle between insertion
order , ascending and descending order .
@ cfg { ( function ( Backbone . Model , string ) : * ) | string } [ defaults . sortValue ]
The function to use to extract a value from the model for comparison during
sorting . If this value is a string , a method with the same name will be
looked up from the column instance .
@ cfg { "ascending" | "descending" | null } [ defaults . direction = null ] The initial
sorting direction for this column . The default is ordered by
Backbone . Model . cid , which usually means the collection is ordered by
insertion order .
* /
2013-04-23 00:35:04 +00:00
defaults : {
name : undefined ,
label : undefined ,
sortable : true ,
editable : true ,
renderable : true ,
formatter : undefined ,
2013-12-10 08:00:06 +00:00
sortType : "cycle" ,
sortValue : undefined ,
direction : null ,
2013-04-23 00:35:04 +00:00
cell : undefined ,
headerCell : undefined
} ,
/ * *
Initializes this Column instance .
2013-12-10 08:00:06 +00:00
@ param { Object } attrs
@ param { string } attrs . name The model attribute this column is responsible
for .
@ param { string | Backgrid . Cell } attrs . cell The cell type to use to render
this column .
@ param { string } [ attrs . label ]
@ param { string | Backgrid . HeaderCell } [ attrs . headerCell ]
@ param { boolean | string } [ attrs . sortable = true ]
@ param { boolean | string } [ attrs . editable = true ]
@ param { boolean | string } [ attrs . renderable = true ]
@ param { Backgrid . CellFormatter | Object | string } [ attrs . formatter ]
@ param { "toggle" | "cycle" } [ attrs . sortType = "cycle" ]
@ param { ( function ( Backbone . Model , string ) : * ) | string } [ attrs . sortValue ]
2013-04-23 00:35:04 +00:00
@ throws { TypeError } If attrs . cell or attrs . options are not supplied .
2013-12-10 08:00:06 +00:00
@ throws { ReferenceError } If formatter is a string but a formatter class of
2013-04-23 00:35:04 +00:00
said name cannot be found in the Backgrid module .
See :
2013-12-10 08:00:06 +00:00
- Backgrid . Column . defaults
2013-04-23 00:35:04 +00:00
- Backgrid . Cell
- Backgrid . CellFormatter
* /
initialize : function ( attrs ) {
if ( ! this . has ( "label" ) ) {
this . set ( { label : this . get ( "name" ) } , { silent : true } ) ;
}
2013-05-12 15:22:54 +00:00
var headerCell = Backgrid . resolveNameToClass ( this . get ( "headerCell" ) , "HeaderCell" ) ;
2013-12-10 08:00:06 +00:00
2013-05-12 15:22:54 +00:00
var cell = Backgrid . resolveNameToClass ( this . get ( "cell" ) , "Cell" ) ;
2013-12-10 08:00:06 +00:00
this . set ( { cell : cell , headerCell : headerCell } , { silent : true } ) ;
} ,
/ * *
Returns an appropriate value extraction function from a model for sorting .
If the column model contains an attribute ` sortValue ` , if it is a string , a
method from the column instance identifified by the ` sortValue ` string is
returned . If it is a function , it it returned as is . If ` sortValue ` isn ' t
found from the column model ' s attributes , a default value extraction
function is returned which will compare according to the natural order of
the value ' s type .
@ return { function ( Backbone . Model , string ) : * }
* /
sortValue : function ( ) {
var sortValue = this . get ( "sortValue" ) ;
if ( _ . isString ( sortValue ) ) return this [ sortValue ] ;
else if ( _ . isFunction ( sortValue ) ) return sortValue ;
return function ( model , colName ) {
return model . get ( colName ) ;
} ;
2013-04-23 00:35:04 +00:00
}
2013-12-10 08:00:06 +00:00
/ * *
@ member Backgrid . Column
@ protected
@ method sortable
@ return { function ( Backgrid . Column , Backbone . Model ) : boolean | boolean }
* /
/ * *
@ member Backgrid . Column
@ protected
@ method editable
@ return { function ( Backgrid . Column , Backbone . Model ) : boolean | boolean }
* /
/ * *
@ member Backgrid . Column
@ protected
@ method renderable
@ return { function ( Backgrid . Column , Backbone . Model ) : boolean | boolean }
* /
} ) ;
_ . each ( [ "sortable" , "renderable" , "editable" ] , function ( key ) {
Column . prototype [ key ] = function ( ) {
var value = this . get ( key ) ;
if ( _ . isString ( value ) ) return this [ value ] ;
return ! ! value ;
} ;
2013-04-23 00:35:04 +00:00
} ) ;
/ * *
A Backbone collection of Column instances .
@ class Backgrid . Columns
@ extends Backbone . Collection
* /
var Columns = Backgrid . Columns = Backbone . Collection . extend ( {
/ * *
@ property { Backgrid . Column } model
* /
model : Column
} ) ;
2013-12-10 08:00:06 +00:00
2013-04-23 00:35:04 +00:00
/ *
backgrid
http : //github.com/wyuenho/backgrid
Copyright ( c ) 2013 Jimmy Yuen Ho Wong and contributors
2013-12-10 08:00:06 +00:00
Licensed under the MIT license .
2013-04-23 00:35:04 +00:00
* /
/ * *
Row is a simple container view that takes a model instance and a list of
column metadata describing how each of the model ' s attribute is to be
rendered , and apply the appropriate cell to each attribute .
@ class Backgrid . Row
@ extends Backbone . View
2013-05-12 15:22:54 +00:00
* /
2013-04-23 00:35:04 +00:00
var Row = Backgrid . Row = Backbone . View . extend ( {
/** @property */
tagName : "tr" ,
/ * *
Initializes a row view instance .
@ param { Object } options
@ param { Backbone . Collection . < Backgrid . Column > | Array . < Backgrid . Column > | Array . < Object > } options . columns Column metadata .
@ param { Backbone . Model } options . model The model instance to render .
@ throws { TypeError } If options . columns or options . model is undefined .
2013-05-12 15:22:54 +00:00
* /
2013-04-23 00:35:04 +00:00
initialize : function ( options ) {
var columns = this . columns = options . columns ;
if ( ! ( columns instanceof Backbone . Collection ) ) {
columns = this . columns = new Columns ( columns ) ;
}
var cells = this . cells = [ ] ;
for ( var i = 0 ; i < columns . length ; i ++ ) {
cells . push ( this . makeCell ( columns . at ( i ) , options ) ) ;
}
this . listenTo ( columns , "add" , function ( column , columns ) {
var i = columns . indexOf ( column ) ;
var cell = this . makeCell ( column , options ) ;
cells . splice ( i , 0 , cell ) ;
var $el = this . $el ;
if ( i === 0 ) {
$el . prepend ( cell . render ( ) . $el ) ;
}
else if ( i === columns . length - 1 ) {
$el . append ( cell . render ( ) . $el ) ;
}
else {
$el . children ( ) . eq ( i ) . before ( cell . render ( ) . $el ) ;
}
} ) ;
this . listenTo ( columns , "remove" , function ( column , columns , opts ) {
cells [ opts . index ] . remove ( ) ;
cells . splice ( opts . index , 1 ) ;
} ) ;
} ,
/ * *
Factory method for making a cell . Used by # initialize internally . Override
this to provide an appropriate cell instance for a custom Row subclass .
@ protected
@ param { Backgrid . Column } column
@ param { Object } options The options passed to # initialize .
@ return { Backgrid . Cell }
2013-05-12 15:22:54 +00:00
* /
2013-04-23 00:35:04 +00:00
makeCell : function ( column ) {
return new ( column . get ( "cell" ) ) ( {
column : column ,
model : this . model
} ) ;
} ,
/ * *
Renders a row of cells for this row ' s model .
2013-05-12 15:22:54 +00:00
* /
2013-04-23 00:35:04 +00:00
render : function ( ) {
this . $el . empty ( ) ;
var fragment = document . createDocumentFragment ( ) ;
for ( var i = 0 ; i < this . cells . length ; i ++ ) {
2013-12-10 08:00:06 +00:00
fragment . appendChild ( this . cells [ i ] . render ( ) . el ) ;
2013-04-23 00:35:04 +00:00
}
this . el . appendChild ( fragment ) ;
this . delegateEvents ( ) ;
return this ;
} ,
/ * *
Clean up this row and its cells .
@ chainable
2013-05-12 15:22:54 +00:00
* /
2013-04-23 00:35:04 +00:00
remove : function ( ) {
for ( var i = 0 ; i < this . cells . length ; i ++ ) {
var cell = this . cells [ i ] ;
cell . remove . apply ( cell , arguments ) ;
}
return Backbone . View . prototype . remove . apply ( this , arguments ) ;
}
} ) ;
2013-05-12 15:22:54 +00:00
/ * *
EmptyRow is a simple container view that takes a list of column and render a
row with a single column .
@ class Backgrid . EmptyRow
@ extends Backbone . View
* /
var EmptyRow = Backgrid . EmptyRow = Backbone . View . extend ( {
/** @property */
tagName : "tr" ,
/** @property */
emptyText : null ,
/ * *
Initializer .
@ param { Object } options
@ param { string } options . emptyText
@ param { Backbone . Collection . < Backgrid . Column > | Array . < Backgrid . Column > | Array . < Object > } options . columns Column metadata .
* /
initialize : function ( options ) {
this . emptyText = options . emptyText ;
this . columns = options . columns ;
} ,
/ * *
Renders an empty row .
* /
render : function ( ) {
this . $el . empty ( ) ;
var td = document . createElement ( "td" ) ;
td . setAttribute ( "colspan" , this . columns . length ) ;
td . textContent = this . emptyText ;
this . el . setAttribute ( "class" , "empty" ) ;
this . el . appendChild ( td ) ;
return this ;
}
} ) ;
2013-12-10 08:00:06 +00:00
2013-04-23 00:35:04 +00:00
/ *
backgrid
http : //github.com/wyuenho/backgrid
Copyright ( c ) 2013 Jimmy Yuen Ho Wong and contributors
2013-12-10 08:00:06 +00:00
Licensed under the MIT license .
2013-04-23 00:35:04 +00:00
* /
/ * *
HeaderCell is a special cell class that renders a column header cell . If the
column is sortable , a sorter is also rendered and will trigger a table
refresh after sorting .
@ class Backgrid . HeaderCell
@ extends Backbone . View
* /
var HeaderCell = Backgrid . HeaderCell = Backbone . View . extend ( {
/** @property */
tagName : "th" ,
/** @property */
events : {
"click a" : "onClick"
} ,
/ * *
Initializer .
@ param { Object } options
@ param { Backgrid . Column | Object } options . column
@ throws { TypeError } If options . column or options . collection is undefined .
* /
initialize : function ( options ) {
this . column = options . column ;
if ( ! ( this . column instanceof Column ) ) {
this . column = new Column ( this . column ) ;
}
2013-12-10 08:00:06 +00:00
2013-05-12 15:22:54 +00:00
this . listenTo ( this . collection , "backgrid:sort" , this . _resetCellDirection ) ;
2013-12-10 08:00:06 +00:00
var column = this . column , $el = this . $el ;
this . listenTo ( column , "change:editable change:sortable change:renderable" ,
function ( column ) {
var changed = column . changedAttributes ( ) ;
for ( var key in changed ) {
if ( changed . hasOwnProperty ( key ) ) {
$el . toggleClass ( key , changed [ key ] ) ;
}
}
} ) ;
this . listenTo ( column , "change:name change:label" , this . render ) ;
if ( column . get ( "editable" ) ) $el . addClass ( "editable" ) ;
if ( column . get ( "sortable" ) ) $el . addClass ( "sortable" ) ;
if ( column . get ( "renderable" ) ) $el . addClass ( "renderable" ) ;
2013-04-23 00:35:04 +00:00
} ,
/ * *
Gets or sets the direction of this cell . If called directly without
parameters , returns the current direction of this cell , otherwise sets
it . If a ` null ` is given , sets this cell back to the default order .
@ param { null | "ascending" | "descending" } dir
@ return { null | string } The current direction or the changed direction .
* /
direction : function ( dir ) {
if ( arguments . length ) {
2013-12-10 08:00:06 +00:00
var direction = this . column . get ( 'direction' ) ;
if ( direction ) this . $el . removeClass ( direction ) ;
2013-04-23 00:35:04 +00:00
if ( dir ) this . $el . addClass ( dir ) ;
2013-12-10 08:00:06 +00:00
this . column . set ( 'direction' , dir )
2013-04-23 00:35:04 +00:00
}
2013-12-10 08:00:06 +00:00
return this . column . get ( 'direction' ) ;
2013-04-23 00:35:04 +00:00
} ,
/ * *
Event handler for the Backbone ` backgrid:sort ` event . Resets this cell ' s
direction to default if sorting is being done on another column .
@ private
* /
2013-12-10 08:00:06 +00:00
_resetCellDirection : function ( columnToSort , direction ) {
if ( columnToSort !== this . column ) this . direction ( null ) ;
else this . direction ( direction ) ;
2013-04-23 00:35:04 +00:00
} ,
/ * *
Event handler for the ` click ` event on the cell ' s anchor . If the column is
sortable , clicking on the anchor will cycle through 3 sorting orderings -
` ascending ` , ` descending ` , and default .
* /
onClick : function ( e ) {
e . preventDefault ( ) ;
2013-12-10 08:00:06 +00:00
var collection = this . collection , event = "backgrid:sort" ;
2013-06-27 07:23:00 +00:00
2013-12-10 08:00:06 +00:00
function cycleSort ( header , col ) {
if ( header . direction ( ) === "ascending" ) collection . trigger ( event , col , "descending" ) ;
else if ( header . direction ( ) === "descending" ) collection . trigger ( event , col , null ) ;
else collection . trigger ( event , col , "ascending" ) ;
2013-04-23 00:35:04 +00:00
}
2013-12-10 08:00:06 +00:00
function toggleSort ( header , col ) {
if ( header . direction ( ) === "ascending" ) collection . trigger ( event , col , "descending" ) ;
else collection . trigger ( event , col , "ascending" ) ;
2013-04-23 00:35:04 +00:00
}
2013-12-10 08:00:06 +00:00
var column = this . column ;
var sortable = Backgrid . callByNeed ( column . sortable ( ) , column , this . collection ) ;
if ( sortable ) {
var sortType = column . get ( "sortType" ) ;
if ( sortType === "toggle" ) toggleSort ( this , column ) ;
else cycleSort ( this , column ) ;
2013-06-27 07:23:00 +00:00
}
2013-04-23 00:35:04 +00:00
} ,
/ * *
2013-12-10 08:00:06 +00:00
Renders a header cell with a sorter , a label , and a class name for this
column .
2013-04-23 00:35:04 +00:00
* /
render : function ( ) {
this . $el . empty ( ) ;
2013-12-10 08:00:06 +00:00
var column = this . column ;
var $label = $ ( "<a>" ) . text ( column . get ( "label" ) ) ;
var sortable = Backgrid . callByNeed ( column . sortable ( ) , column , this . collection ) ;
if ( sortable ) $label . append ( "<b class='sort-caret'></b>" ) ;
2013-04-23 00:35:04 +00:00
this . $el . append ( $label ) ;
2013-12-10 08:00:06 +00:00
this . $el . addClass ( column . get ( "name" ) ) ;
2013-04-23 00:35:04 +00:00
this . delegateEvents ( ) ;
2013-12-10 08:00:06 +00:00
this . direction ( column . get ( "direction" ) ) ;
2013-04-23 00:35:04 +00:00
return this ;
2013-12-10 08:00:06 +00:00
}
2013-04-23 00:35:04 +00:00
} ) ;
/ * *
HeaderRow is a controller for a row of header cells .
@ class Backgrid . HeaderRow
@ extends Backgrid . Row
* /
var HeaderRow = Backgrid . HeaderRow = Backgrid . Row . extend ( {
2013-05-12 15:22:54 +00:00
requiredOptions : [ "columns" , "collection" ] ,
2013-04-23 00:35:04 +00:00
/ * *
Initializer .
@ param { Object } options
@ param { Backbone . Collection . < Backgrid . Column > | Array . < Backgrid . Column > | Array . < Object > } options . columns
@ param { Backgrid . HeaderCell } [ options . headerCell ] Customized default
HeaderCell for all the columns . Supply a HeaderCell class or instance to a
the ` headerCell ` key in a column definition for column - specific header
rendering .
@ throws { TypeError } If options . columns or options . collection is undefined .
* /
initialize : function ( ) {
Backgrid . Row . prototype . initialize . apply ( this , arguments ) ;
} ,
makeCell : function ( column , options ) {
var headerCell = column . get ( "headerCell" ) || options . headerCell || HeaderCell ;
headerCell = new headerCell ( {
column : column ,
collection : this . collection
} ) ;
return headerCell ;
}
} ) ;
/ * *
Header is a special structural view class that renders a table head with a
single row of header cells .
@ class Backgrid . Header
@ extends Backbone . View
* /
var Header = Backgrid . Header = Backbone . View . extend ( {
/** @property */
tagName : "thead" ,
/ * *
Initializer . Initializes this table head view to contain a single header
row view .
@ param { Object } options
@ param { Backbone . Collection . < Backgrid . Column > | Array . < Backgrid . Column > | Array . < Object > } options . columns Column metadata .
@ param { Backbone . Model } options . model The model instance to render .
@ throws { TypeError } If options . columns or options . model is undefined .
* /
initialize : function ( options ) {
this . columns = options . columns ;
if ( ! ( this . columns instanceof Backbone . Collection ) ) {
this . columns = new Columns ( this . columns ) ;
}
this . row = new Backgrid . HeaderRow ( {
columns : this . columns ,
collection : this . collection
} ) ;
} ,
/ * *
Renders this table head with a single row of header cells .
* /
render : function ( ) {
this . $el . append ( this . row . render ( ) . $el ) ;
this . delegateEvents ( ) ;
return this ;
} ,
/ * *
Clean up this header and its row .
@ chainable
* /
remove : function ( ) {
this . row . remove . apply ( this . row , arguments ) ;
return Backbone . View . prototype . remove . apply ( this , arguments ) ;
}
} ) ;
2013-12-10 08:00:06 +00:00
2013-04-23 00:35:04 +00:00
/ *
backgrid
http : //github.com/wyuenho/backgrid
Copyright ( c ) 2013 Jimmy Yuen Ho Wong and contributors
2013-12-10 08:00:06 +00:00
Licensed under the MIT license .
2013-04-23 00:35:04 +00:00
* /
/ * *
Body is the table body which contains the rows inside a table . Body is
responsible for refreshing the rows after sorting , insertion and removal .
@ class Backgrid . Body
@ extends Backbone . View
* /
var Body = Backgrid . Body = Backbone . View . extend ( {
/** @property */
tagName : "tbody" ,
/ * *
Initializer .
@ param { Object } options
@ param { Backbone . Collection } options . collection
@ param { Backbone . Collection . < Backgrid . Column > | Array . < Backgrid . Column > | Array . < Object > } options . columns
2013-05-12 15:22:54 +00:00
Column metadata .
2013-04-23 00:35:04 +00:00
@ param { Backgrid . Row } [ options . row = Backgrid . Row ] The Row class to use .
2013-05-12 15:22:54 +00:00
@ param { string } [ options . emptyText ] The text to display in the empty row .
2013-04-23 00:35:04 +00:00
@ throws { TypeError } If options . columns or options . collection is undefined .
See Backgrid . Row .
* /
initialize : function ( options ) {
this . columns = options . columns ;
if ( ! ( this . columns instanceof Backbone . Collection ) ) {
this . columns = new Columns ( this . columns ) ;
}
this . row = options . row || Row ;
this . rows = this . collection . map ( function ( model ) {
var row = new this . row ( {
columns : this . columns ,
model : model
} ) ;
return row ;
} , this ) ;
2013-05-12 15:22:54 +00:00
this . emptyText = options . emptyText ;
this . _unshiftEmptyRowMayBe ( ) ;
2013-04-23 00:35:04 +00:00
var collection = this . collection ;
this . listenTo ( collection , "add" , this . insertRow ) ;
this . listenTo ( collection , "remove" , this . removeRow ) ;
this . listenTo ( collection , "sort" , this . refresh ) ;
this . listenTo ( collection , "reset" , this . refresh ) ;
2013-12-10 08:00:06 +00:00
this . listenTo ( collection , "backgrid:sort" , this . sort ) ;
2013-05-12 15:22:54 +00:00
this . listenTo ( collection , "backgrid:edited" , this . moveToNextCell ) ;
} ,
_unshiftEmptyRowMayBe : function ( ) {
if ( this . rows . length === 0 && this . emptyText != null ) {
this . rows . unshift ( new EmptyRow ( {
emptyText : this . emptyText ,
columns : this . columns
} ) ) ;
}
2013-04-23 00:35:04 +00:00
} ,
/ * *
This method can be called either directly or as a callback to a
[ Backbone . Collecton # add ] ( http : //backbonejs.org/#Collection-add) event.
When called directly , it accepts a model or an array of models and an
option hash just like
[ Backbone . Collection # add ] ( http : //backbonejs.org/#Collection-add) and
delegates to it . Once the model is added , a new row is inserted into the
body and automatically rendered .
When called as a callback of an ` add ` event , splices a new row into the
body and renders it .
@ param { Backbone . Model } model The model to render as a row .
@ param { Backbone . Collection } collection When called directly , this
parameter is actually the options to
[ Backbone . Collection # add ] ( http : //backbonejs.org/#Collection-add).
@ param { Object } options When called directly , this must be null .
See :
- [ Backbone . Collection # add ] ( http : //backbonejs.org/#Collection-add)
* /
insertRow : function ( model , collection , options ) {
2013-05-12 15:22:54 +00:00
if ( this . rows [ 0 ] instanceof EmptyRow ) this . rows . pop ( ) . remove ( ) ;
2013-04-23 00:35:04 +00:00
// insertRow() is called directly
if ( ! ( collection instanceof Backbone . Collection ) && ! options ) {
this . collection . add ( model , ( options = collection ) ) ;
return ;
}
options = _ . extend ( { render : true } , options || { } ) ;
var row = new this . row ( {
columns : this . columns ,
model : model
} ) ;
var index = collection . indexOf ( model ) ;
this . rows . splice ( index , 0 , row ) ;
var $el = this . $el ;
var $children = $el . children ( ) ;
var $rowEl = row . render ( ) . $el ;
if ( options . render ) {
if ( index >= $children . length ) {
$el . append ( $rowEl ) ;
}
else {
$children . eq ( index ) . before ( $rowEl ) ;
}
}
2013-12-10 08:00:06 +00:00
return this ;
2013-04-23 00:35:04 +00:00
} ,
/ * *
The method can be called either directly or as a callback to a
[ Backbone . Collection # remove ] ( http : //backbonejs.org/#Collection-remove)
event .
When called directly , it accepts a model or an array of models and an
option hash just like
[ Backbone . Collection # remove ] ( http : //backbonejs.org/#Collection-remove) and
delegates to it . Once the model is removed , a corresponding row is removed
from the body .
When called as a callback of a ` remove ` event , splices into the rows and
removes the row responsible for rendering the model .
@ param { Backbone . Model } model The model to remove from the body .
@ param { Backbone . Collection } collection When called directly , this
parameter is actually the options to
[ Backbone . Collection # remove ] ( http : //backbonejs.org/#Collection-remove).
@ param { Object } options When called directly , this must be null .
See :
- [ Backbone . Collection # remove ] ( http : //backbonejs.org/#Collection-remove)
* /
removeRow : function ( model , collection , options ) {
// removeRow() is called directly
if ( ! options ) {
this . collection . remove ( model , ( options = collection ) ) ;
2013-05-12 15:22:54 +00:00
this . _unshiftEmptyRowMayBe ( ) ;
2013-04-23 00:35:04 +00:00
return ;
}
if ( _ . isUndefined ( options . render ) || options . render ) {
this . rows [ options . index ] . remove ( ) ;
}
this . rows . splice ( options . index , 1 ) ;
2013-05-12 15:22:54 +00:00
this . _unshiftEmptyRowMayBe ( ) ;
2013-12-10 08:00:06 +00:00
return this ;
2013-04-23 00:35:04 +00:00
} ,
/ * *
Reinitialize all the rows inside the body and re - render them . Triggers a
2013-05-12 15:22:54 +00:00
Backbone ` backgrid:refresh ` event from the collection along with the body
instance as its sole parameter when done .
2013-04-23 00:35:04 +00:00
* /
refresh : function ( ) {
for ( var i = 0 ; i < this . rows . length ; i ++ ) {
this . rows [ i ] . remove ( ) ;
}
this . rows = this . collection . map ( function ( model ) {
var row = new this . row ( {
columns : this . columns ,
model : model
} ) ;
return row ;
} , this ) ;
2013-05-12 15:22:54 +00:00
this . _unshiftEmptyRowMayBe ( ) ;
2013-04-23 00:35:04 +00:00
this . render ( ) ;
2013-05-12 15:22:54 +00:00
this . collection . trigger ( "backgrid:refresh" , this ) ;
2013-04-23 00:35:04 +00:00
return this ;
} ,
/ * *
2013-05-12 15:22:54 +00:00
Renders all the rows inside this body . If the collection is empty and
` options.emptyText ` is defined and not null in the constructor , an empty
row is rendered , otherwise no row is rendered .
2013-04-23 00:35:04 +00:00
* /
render : function ( ) {
this . $el . empty ( ) ;
var fragment = document . createDocumentFragment ( ) ;
for ( var i = 0 ; i < this . rows . length ; i ++ ) {
var row = this . rows [ i ] ;
fragment . appendChild ( row . render ( ) . el ) ;
}
this . el . appendChild ( fragment ) ;
this . delegateEvents ( ) ;
return this ;
} ,
/ * *
Clean up this body and it ' s rows .
@ chainable
2013-05-12 15:22:54 +00:00
* /
2013-04-23 00:35:04 +00:00
remove : function ( ) {
for ( var i = 0 ; i < this . rows . length ; i ++ ) {
var row = this . rows [ i ] ;
row . remove . apply ( row , arguments ) ;
}
return Backbone . View . prototype . remove . apply ( this , arguments ) ;
2013-05-12 15:22:54 +00:00
} ,
2013-12-10 08:00:06 +00:00
/ * *
If the underlying collection is a Backbone . PageableCollection in
server - mode or infinite - mode , a page of models is fetched after sorting is
done on the server .
If the underlying collection is a Backbone . PageableCollection in
client - mode , or any
[ Backbone . Collection ] ( http : //backbonejs.org/#Collection) instance, sorting
is done on the client side . If the collection is an instance of a
Backbone . PageableCollection , sorting will be done globally on all the pages
and the current page will then be returned .
Triggers a Backbone ` backgrid:sort ` event from the collection when done
with the column , direction , comparator and a reference to the collection .
@ param { Backgrid . Column } column
@ param { null | "ascending" | "descending" } direction
See [ Backbone . Collection # comparator ] ( http : //backbonejs.org/#Collection-comparator)
* /
sort : function ( column , direction ) {
if ( _ . isString ( column ) ) column = this . columns . findWhere ( { name : column } ) ;
var collection = this . collection ;
var order ;
if ( direction === "ascending" ) order = - 1 ;
else if ( direction === "descending" ) order = 1 ;
else order = null ;
var comparator = this . makeComparator ( column . get ( "name" ) , order ,
order ?
column . sortValue ( ) :
function ( model ) {
return model . cid ;
} ) ;
if ( Backbone . PageableCollection &&
collection instanceof Backbone . PageableCollection ) {
collection . setSorting ( order && column . get ( "name" ) , order ,
{ sortValue : column . sortValue ( ) } ) ;
if ( collection . mode == "client" ) {
if ( collection . fullCollection . comparator == null ) {
collection . fullCollection . comparator = comparator ;
}
collection . fullCollection . sort ( ) ;
}
else collection . fetch ( { reset : true } ) ;
}
else {
collection . comparator = comparator ;
collection . sort ( ) ;
}
return this ;
} ,
makeComparator : function ( attr , order , func ) {
return function ( left , right ) {
// extract the values from the models
var l = func ( left , attr ) , r = func ( right , attr ) , t ;
// if descending order, swap left and right
if ( order === 1 ) t = l , l = r , r = t ;
// compare as usual
if ( l === r ) return 0 ;
else if ( l < r ) return - 1 ;
return 1 ;
} ;
} ,
2013-05-12 15:22:54 +00:00
/ * *
Moves focus to the next renderable and editable cell and return the
currently editing cell to display mode .
2013-04-23 00:35:04 +00:00
2013-05-12 15:22:54 +00:00
@ param { Backbone . Model } model The originating model
@ param { Backgrid . Column } column The originating model column
@ param { Backgrid . Command } command The Command object constructed from a DOM
Event
* /
moveToNextCell : function ( model , column , command ) {
var i = this . collection . indexOf ( model ) ;
var j = this . columns . indexOf ( column ) ;
2013-12-10 08:00:06 +00:00
var cell , renderable , editable ;
this . rows [ i ] . cells [ j ] . exitEditMode ( ) ;
2013-05-12 15:22:54 +00:00
if ( command . moveUp ( ) || command . moveDown ( ) || command . moveLeft ( ) ||
command . moveRight ( ) || command . save ( ) ) {
var l = this . columns . length ;
var maxOffset = l * this . collection . length ;
if ( command . moveUp ( ) || command . moveDown ( ) ) {
var row = this . rows [ i + ( command . moveUp ( ) ? - 1 : 1 ) ] ;
2013-12-10 08:00:06 +00:00
if ( row ) {
cell = row . cells [ j ] ;
if ( Backgrid . callByNeed ( cell . column . editable ( ) , cell . column , model ) ) {
cell . enterEditMode ( ) ;
}
}
2013-05-12 15:22:54 +00:00
}
else if ( command . moveLeft ( ) || command . moveRight ( ) ) {
var right = command . moveRight ( ) ;
for ( var offset = i * l + j + ( right ? 1 : - 1 ) ;
offset >= 0 && offset < maxOffset ;
right ? offset ++ : offset -- ) {
var m = ~ ~ ( offset / l ) ;
var n = offset - m * l ;
2013-12-10 08:00:06 +00:00
cell = this . rows [ m ] . cells [ n ] ;
renderable = Backgrid . callByNeed ( cell . column . renderable ( ) , cell . column , cell . model ) ;
editable = Backgrid . callByNeed ( cell . column . editable ( ) , cell . column , model ) ;
if ( renderable && editable ) {
2013-05-12 15:22:54 +00:00
cell . enterEditMode ( ) ;
break ;
}
}
}
}
2013-06-27 07:23:00 +00:00
2013-12-10 08:00:06 +00:00
return this ;
2013-05-12 15:22:54 +00:00
}
2013-04-23 00:35:04 +00:00
} ) ;
2013-12-10 08:00:06 +00:00
2013-04-23 00:35:04 +00:00
/ *
backgrid
http : //github.com/wyuenho/backgrid
Copyright ( c ) 2013 Jimmy Yuen Ho Wong and contributors
2013-12-10 08:00:06 +00:00
Licensed under the MIT license .
2013-04-23 00:35:04 +00:00
* /
/ * *
A Footer is a generic class that only defines a default tag ` tfoot ` and
number of required parameters in the initializer .
@ abstract
@ class Backgrid . Footer
@ extends Backbone . View
* /
var Footer = Backgrid . Footer = Backbone . View . extend ( {
/** @property */
tagName : "tfoot" ,
/ * *
Initializer .
@ param { Object } options
@ param { Backbone . Collection . < Backgrid . Column > | Array . < Backgrid . Column > | Array . < Object > } options . columns
Column metadata .
@ param { Backbone . Collection } options . collection
@ throws { TypeError } If options . columns or options . collection is undefined .
* /
initialize : function ( options ) {
this . columns = options . columns ;
if ( ! ( this . columns instanceof Backbone . Collection ) ) {
this . columns = new Backgrid . Columns ( this . columns ) ;
}
}
} ) ;
2013-12-10 08:00:06 +00:00
2013-04-23 00:35:04 +00:00
/ *
backgrid
http : //github.com/wyuenho/backgrid
Copyright ( c ) 2013 Jimmy Yuen Ho Wong and contributors
2013-12-10 08:00:06 +00:00
Licensed under the MIT license .
2013-04-23 00:35:04 +00:00
* /
/ * *
Grid represents a data grid that has a header , body and an optional footer .
By default , a Grid treats each model in a collection as a row , and each
attribute in a model as a column . To render a grid you must provide a list of
column metadata and a collection to the Grid constructor . Just like any
Backbone . View class , the grid is rendered as a DOM node fragment when you
call render ( ) .
var grid = Backgrid . Grid ( {
columns : [ { name : "id" , label : "ID" , type : "string" } ,
// ...
] ,
collections : books
} ) ;
$ ( "#table-container" ) . append ( grid . render ( ) . el ) ;
Optionally , if you want to customize the rendering of the grid ' s header and
footer , you may choose to extend Backgrid . Header and Backgrid . Footer , and
then supply that class or an instance of that class to the Grid constructor .
See the documentation for Header and Footer for further details .
var grid = Backgrid . Grid ( {
columns : [ { name : "id" , label : "ID" , type : "string" } ] ,
collections : books ,
header : Backgrid . Header . extend ( {
//...
} ) ,
footer : Backgrid . Paginator
} ) ;
Finally , if you want to override how the rows are rendered in the table body ,
you can supply a Body subclass as the ` body ` attribute that uses a different
Row class .
@ class Backgrid . Grid
@ extends Backbone . View
See :
- Backgrid . Column
- Backgrid . Header
- Backgrid . Body
- Backgrid . Row
- Backgrid . Footer
* /
var Grid = Backgrid . Grid = Backbone . View . extend ( {
/** @property */
tagName : "table" ,
/** @property */
className : "backgrid" ,
/** @property */
header : Header ,
/** @property */
body : Body ,
/** @property */
footer : null ,
/ * *
Initializes a Grid instance .
@ param { Object } options
2013-12-10 08:00:06 +00:00
@ param { Backbone . Collection . < Backgrid . Columns > | Array . < Backgrid . Column > | Array . < Object > } options . columns Column metadata .
2013-04-23 00:35:04 +00:00
@ param { Backbone . Collection } options . collection The collection of tabular model data to display .
@ 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 .
@ param { Backgrid . Footer } [ options . footer = Backgrid . Footer ] An optional Footer class .
* /
initialize : function ( options ) {
// Convert the list of column objects here first so the subviews don't have
// to.
if ( ! ( options . columns instanceof Backbone . Collection ) ) {
options . columns = new Columns ( options . columns ) ;
}
this . columns = options . columns ;
2013-12-10 08:00:06 +00:00
var filteredOptions = _ . omit ( options , [ "el" , "id" , "attributes" ,
"className" , "tagName" , "events" ] ) ;
2013-04-23 00:35:04 +00:00
2013-12-10 08:00:06 +00:00
// must construct body first so it listens to backgrid:sort first
2013-04-23 00:35:04 +00:00
this . body = options . body || this . body ;
2013-12-10 08:00:06 +00:00
this . body = new this . body ( filteredOptions ) ;
this . header = options . header || this . header ;
if ( this . header ) {
this . header = new this . header ( filteredOptions ) ;
}
2013-04-23 00:35:04 +00:00
this . footer = options . footer || this . footer ;
if ( this . footer ) {
2013-12-10 08:00:06 +00:00
this . footer = new this . footer ( filteredOptions ) ;
2013-04-23 00:35:04 +00:00
}
this . listenTo ( this . columns , "reset" , function ( ) {
2013-12-10 08:00:06 +00:00
if ( this . header ) {
this . header = new ( this . header . remove ( ) . constructor ) ( filteredOptions ) ;
}
this . body = new ( this . body . remove ( ) . constructor ) ( filteredOptions ) ;
2013-05-12 15:22:54 +00:00
if ( this . footer ) {
2013-12-10 08:00:06 +00:00
this . footer = new ( this . footer . remove ( ) . constructor ) ( filteredOptions ) ;
2013-05-12 15:22:54 +00:00
}
2013-04-23 00:35:04 +00:00
this . render ( ) ;
} ) ;
} ,
/ * *
Delegates to Backgrid . Body # insertRow .
* /
insertRow : function ( model , collection , options ) {
2013-12-10 08:00:06 +00:00
this . body . insertRow ( model , collection , options ) ;
return this ;
2013-04-23 00:35:04 +00:00
} ,
/ * *
Delegates to Backgrid . Body # removeRow .
* /
removeRow : function ( model , collection , options ) {
2013-12-10 08:00:06 +00:00
this . body . removeRow ( model , collection , options ) ;
return this ;
2013-04-23 00:35:04 +00:00
} ,
/ * *
Delegates to Backgrid . Columns # add for adding a column . Subviews can listen
to the ` add ` event from their internal ` columns ` if rerendering needs to
happen .
@ param { Object } [ options ] Options for ` Backgrid.Columns#add ` .
@ param { boolean } [ options . render = true ] Whether to render the column
immediately after insertion .
* /
insertColumn : function ( column , options ) {
options = options || { render : true } ;
this . columns . add ( column , options ) ;
return this ;
} ,
/ * *
Delegates to Backgrid . Columns # remove for removing a column . Subviews can
listen to the ` remove ` event from the internal ` columns ` if rerendering
needs to happen .
@ param { Object } [ options ] Options for ` Backgrid.Columns#remove ` .
* /
removeColumn : function ( column , options ) {
this . columns . remove ( column , options ) ;
return this ;
} ,
2013-12-10 08:00:06 +00:00
/ * *
Delegates to Backgrid . Body # sort .
* /
sort : function ( ) {
this . body . sort ( arguments ) ;
return this ;
} ,
2013-04-23 00:35:04 +00:00
/ * *
Renders the grid ' s 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 ( ) ;
2013-12-10 08:00:06 +00:00
if ( this . header ) {
this . $el . append ( this . header . render ( ) . $el ) ;
}
2013-04-23 00:35:04 +00:00
if ( this . footer ) {
this . $el . append ( this . footer . render ( ) . $el ) ;
}
this . $el . append ( this . body . render ( ) . $el ) ;
this . delegateEvents ( ) ;
this . trigger ( "backgrid:rendered" , this ) ;
return this ;
} ,
/ * *
Clean up this grid and its subviews .
@ chainable
* /
remove : function ( ) {
2013-12-10 08:00:06 +00:00
this . header && this . header . remove . apply ( this . header , arguments ) ;
2013-04-23 00:35:04 +00:00
this . body . remove . apply ( this . body , arguments ) ;
this . footer && this . footer . remove . apply ( this . footer , arguments ) ;
return Backbone . View . prototype . remove . apply ( this , arguments ) ;
}
} ) ;
2013-12-10 08:00:06 +00:00
return Backgrid ;
} ) ) ;