diff --git a/lib/backgrid.css b/lib/backgrid.css index 4fd93371..80db7c9a 100644 --- a/lib/backgrid.css +++ b/lib/backgrid.css @@ -2,7 +2,7 @@ backgrid http://github.com/wyuenho/backgrid - Copyright (c) 2012 Jimmy Yuen Ho Wong + Copyright (c) 2013 Jimmy Yuen Ho Wong Licensed under the MIT @license. */ diff --git a/lib/backgrid.js b/lib/backgrid.js index 2bf56064..d608cb9c 100644 --- a/lib/backgrid.js +++ b/lib/backgrid.js @@ -9,57 +9,73 @@ "use strict"; - var window = root; - - var Backgrid = root.Backgrid = { - VERSION: "0.1", - Extension: {} - }; - - function trim(s) { - if (String.prototype.trim) { - return String.prototype.trim.call(s, s); - } else { - return s.replace(/^\s+|\s+$/g, ""); - } - } +/* + backgrid + http://github.com/wyuenho/backgrid - function capitalize(s) { - return String.fromCharCode(s.charCodeAt(0) - 32) + s.slice(1); - } + Copyright (c) 2013 Jimmy Yuen Ho Wong + Licensed under the MIT @license. +*/ - 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 += padstr; - } - return padding + str; +var window = root; + +var Backgrid = root.Backgrid = { + VERSION: "0.1", + Extension: {} +}; + +function trim(s) { + if (String.prototype.trim) { + return String.prototype.trim.call(s, s); } - function requireOptions(options, requireOptionKeys) { - for (var i = 0; i < requireOptionKeys.length; i++) { - var key = requireOptionKeys[i]; - if (_.isUndefined(options[key])) { - throw new TypeError("'" + key + "' is required"); - } + return s.replace(/^\s+|\s+$/g, ""); +} + +function capitalize(s) { + return String.fromCharCode(s.charCodeAt(0) - 32) + s.slice(1); +} + +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; +} + +function requireOptions(options, requireOptionKeys) { + for (var i = 0; i < requireOptionKeys.length; i++) { + var key = requireOptionKeys[i]; + if (_.isUndefined(options[key])) { + throw new TypeError("'" + key + "' is required"); } } - - function resolveNameToClass(name, suffix) { - if (_.isString(name)) { - var key = capitalize(name) + suffix; - var klass = Backgrid[key] || Backgrid.Extension[key]; - if (_.isUndefined(klass)) { - throw new ReferenceError("Class '" + key + "' not found"); - } - return klass; +} + +function resolveNameToClass(name, suffix) { + if (_.isString(name)) { + var key = capitalize(name) + suffix; + var klass = Backgrid[key] || Backgrid.Extension[key]; + if (_.isUndefined(klass)) { + throw new ReferenceError("Class '" + key + "' not found"); } - return name; + return klass; } - /** + return name; +} +/* + backgrid + http://github.com/wyuenho/backgrid + + Copyright (c) 2013 Jimmy Yuen Ho Wong + Licensed under the MIT @license. +*/ + +/** Just a convenient class for interested parties to subclass. The default Cell classes don't require the formatter to be a subclass of @@ -70,20 +86,21 @@ @class Backgrid.CellFormatter @constructor */ - var CellFormatter = Backgrid.CellFormatter = function() {}; +var CellFormatter = Backgrid.CellFormatter = function () {}; +_.extend(CellFormatter.prototype, { - _.extend(CellFormatter.prototype, { - /** + /** Takes a raw value from a model and returns a formatted string for display. @member Backgrid.CellFormatter @param {*} rawData @return {string} */ - fromRaw: function(rawData) { - return rawData; - }, - /** + fromRaw: function (rawData) { + return rawData; + }, + + /** Takes a formatted string, usually from user input, and returns a appropriately typed value for persistence in the model. @@ -94,12 +111,13 @@ @param {string} formattedData @return {*|undefined} */ - toRaw: function(formattedData) { - return formattedData; - } - }); + toRaw: function (formattedData) { + return formattedData; + } - /** +}); + +/** A floating point number formatter. Doesn't understand notation at the moment. @class Backgrid.NumberFormatter @@ -107,18 +125,18 @@ @constructor @throws {RangeError} If decimals < 0 or > 20. */ - var NumberFormatter = Backgrid.NumberFormatter = function(options) { - options = options ? _.clone(options) : {}; - _.extend(this, this.defaults, options); - if (this.decimals < 0 || this.decimals > 20) { - throw new RangeError("decimals must be between 0 and 20"); - } - }; +var NumberFormatter = Backgrid.NumberFormatter = function (options) { + options = options ? _.clone(options) : {}; + _.extend(this, this.defaults, options); - NumberFormatter.prototype = new CellFormatter(); + if (this.decimals < 0 || this.decimals > 20) { + throw new RangeError("decimals must be between 0 and 20"); + } +}; +NumberFormatter.prototype = new CellFormatter; +_.extend(NumberFormatter.prototype, { - _.extend(NumberFormatter.prototype, { - /** + /** @member Backgrid.NumberFormatter @cfg {Object} options @@ -130,13 +148,15 @@ @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, - /** + 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 @@ -146,17 +166,19 @@ @param {number} number @return {string} */ - fromRaw: function(number) { - if (isNaN(number) || null === 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; - }, - /** + fromRaw: function (number) { + if (isNaN(number) || number === null) 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. @@ -165,30 +187,31 @@ @return {number|undefined} Undefined if the string cannot be converted to a number. */ - toRaw: function(formattedData) { - var rawData = ""; - var thousands = trim(formattedData).split(this.orderSeparator); - 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 = 1 * (1 * rawData).toFixed(~~this.decimals); - if (_.isNumber(result) && !_.isNaN(result)) { - return result; - } else { - return void 0; - } + toRaw: function (formattedData) { + var rawData = ''; + + var thousands = trim(formattedData).split(this.orderSeparator); + 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; + } + +}); + +/** Formatter to converts between various datetime string formats. This class only understands ISO-8601 formatted datetime strings. See @@ -200,18 +223,18 @@ @constructor @throws {Error} If both `includeDate` and `includeTime` are false. */ - var DatetimeFormatter = Backgrid.DatetimeFormatter = function(options) { - options = options ? _.clone(options) : {}; - _.extend(this, this.defaults, options); - if (!this.includeDate && !this.includeTime) { - throw new Error("Either includeDate or includeTime must be true"); - } - }; +var DatetimeFormatter = Backgrid.DatetimeFormatter = function (options) { + options = options ? _.clone(options) : {}; + _.extend(this, this.defaults, options); - DatetimeFormatter.prototype = new CellFormatter(); + if (!this.includeDate && !this.includeTime) { + throw new Error("Either includeDate or includeTime must be true"); + } +}; +DatetimeFormatter.prototype = new CellFormatter; +_.extend(DatetimeFormatter.prototype, { - _.extend(DatetimeFormatter.prototype, { - /** + /** @member Backgrid.DatetimeFormatter @cfg {Object} options @@ -225,52 +248,63 @@ @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) { - data = trim(data); - var parts = data.split(this.ISO_SPLITTER_RE) || []; - var date = this.DATE_RE.test(parts[0]) ? parts[0] : ""; - var time = date && parts[1] ? parts[1] : this.TIME_RE.test(parts[0]) ? parts[0] : ""; - 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(1 * YYYYMMDD[1] || 0, 1 * YYYYMMDD[2] - 1 || 0, 1 * YYYYMMDD[3] || 0, 1 * HHmmssSSS[1] || null, 1 * HHmmssSSS[2] || null, 1 * HHmmssSSS[3] || null, 1 * HHmmssSSS[5] || 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"; + 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) { + data = trim(data); + var parts = data.split(this.ISO_SPLITTER_RE) || []; + + var date = this.DATE_RE.test(parts[0]) ? parts[0] : ''; + var time = date && parts[1] ? parts[1] : this.TIME_RE.test(parts[0]) ? parts[0] : ''; + + 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); } - return result; - }, - /** + } + + 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. @@ -278,10 +312,11 @@ @param {string} rawData @return {string} ISO-8601 string in UTC. */ - fromRaw: function(rawData) { - return this._convert(rawData); - }, - /** + fromRaw: function (rawData) { + 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 @@ -295,12 +330,21 @@ or if `includeDate` is true and a date is not found, or if `includeTime` is true and a time is not found. */ - toRaw: function(formattedData) { - return this._convert(formattedData, true); - } - }); + toRaw: function (formattedData) { + return this._convert(formattedData, true); + } - /** +}); + +/* + backgrid + http://github.com/wyuenho/backgrid + + Copyright (c) 2013 Jimmy Yuen Ho Wong + Licensed under the MIT @license. +*/ + +/** Generic cell editor base class. Only defines an initializer for a number of required parameters. @@ -308,8 +352,9 @@ @class Backgrid.CellEditor @extends Backbone.View */ - var CellEditor = Backgrid.CellEditor = Backbone.View.extend({ - /** +var CellEditor = Backgrid.CellEditor = Backbone.View.extend({ + + /** Initializer. @param {Object} options @@ -321,30 +366,32 @@ @throws {TypeError} If `formatter` is not a formatter instance, or when `model` or `column` are undefined. */ - initialize: function(options) { - requireOptions(options, [ "formatter", "column", "model" ]); - this.parent = options.parent; - this.formatter = options.formatter; - this.column = options.column; - if (!(this.column instanceof Column)) { - this.column = new Column(this.column); - } - if (this.parent && _.isFunction(this.parent.on)) { - this.listenTo(this.parent, "editing", this.postRender); - } - }, - /** + initialize: function (options) { + requireOptions(options, ["formatter", "column", "model"]); + this.parent = options.parent; + this.formatter = options.formatter; + this.column = options.column; + if (!(this.column instanceof Column)) { + this.column = new Column(this.column); + } + if (this.parent && _.isFunction(this.parent.on)) { + this.listenTo(this.parent, "editing", this.postRender); + } + }, + + /** 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. */ - postRender: function() { - this.$el.focus(); - return this; - } - }); + postRender: function () { + this.$el.focus(); + 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. @@ -352,19 +399,23 @@ @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" - }, - /** +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. @@ -374,22 +425,26 @@ @param {Backbone.Model} options.model @param {string} [options.placeholder] */ - initialize: function(options) { - CellEditor.prototype.initialize.apply(this, arguments); - if (options.placeholder) { - this.$el.attr("placeholder", options.placeholder); - } - this.listenTo(this, "done", this.remove); - }, - /** + initialize: function (options) { + CellEditor.prototype.initialize.apply(this, arguments); + + if (options.placeholder) { + this.$el.attr("placeholder", options.placeholder); + } + + this.listenTo(this, "done", this.remove); + }, + + /** Renders a text input with the cell value formatted for display, if it exists. */ - render: function() { - this.$el.val(this.formatter.fromRaw(this.model.get(this.column.get("name")))); - return this; - }, - /** + render: function () { + this.$el.val(this.formatter.fromRaw(this.model.get(this.column.get("name")))); + return this; + }, + + /** If the key pressed is `enter` or `tab`, converts the value in the editor to a raw value for the model using the formatter. @@ -406,53 +461,58 @@ @param {Event} e */ - saveOrCancel: function(e) { - if ("keydown" === e.type) { - // enter or tab - if (13 === e.keyCode || 9 === e.keyCode) { - e.preventDefault(); - var valueToSet = this.formatter.toRaw(this.$el.val()); - if (_.isUndefined(valueToSet) || !this.model.set(this.column.get("name"), valueToSet, { - validate: true - })) { - this.trigger("error"); - } else { - this.trigger("done"); - } - } else { - if (27 === e.keyCode) { - // undo - e.stopPropagation(); - this.trigger("done"); - } + saveOrCancel: function (e) { + if (e.type === "keydown") { + // enter or tab + if (e.keyCode === 13 || e.keyCode === 9) { + e.preventDefault(); + var valueToSet = this.formatter.toRaw(this.$el.val()); + + if (_.isUndefined(valueToSet) || + !this.model.set(this.column.get("name"), valueToSet, + {validate: true})) { + this.trigger("error"); } - } else { - if ("blur" === e.type) { - if (this.formatter.fromRaw(this.model.get(this.column.get("name"))) === this.$el.val()) { - this.trigger("done"); - } else { - var self = this; - var timeout = window.setTimeout(function() { - self.$el.focus(); - window.clearTimeout(timeout); - }, 1); - } + else { + this.trigger("done"); } } - }, - postRender: function() { - // move the cursor to the end on firefox if text is right aligned - if ("right" === this.$el.css("text-align")) { - var val = this.$el.val(); - this.$el.focus().val(null).val(val); - } else { - this.$el.focus(); + // esc + else if (e.keyCode === 27) { + // undo + e.stopPropagation(); + this.trigger("done"); } - return this; } - }); + else if (e.type === "blur") { + if (this.formatter.fromRaw(this.model.get(this.column.get("name"))) === this.$el.val()) { + this.trigger("done"); + } + else { + var self = this; + var timeout = window.setTimeout(function () { + self.$el.focus(); + window.clearTimeout(timeout); + }, 1); + } + } + }, - /** + postRender: function () { + // 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(); + } + 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 @@ -464,26 +524,31 @@ @class Backgrid.Cell @extends Backbone.View */ - var Cell = Backgrid.Cell = Backbone.View.extend({ - /** @property */ - tagName: "td", - /** +var Cell = Backgrid.Cell = Backbone.View.extend({ + + /** @property */ + tagName: "td", + + /** @property {Backgrid.CellFormatter|Object|string} [formatter=new CellFormatter()] */ - formatter: new CellFormatter(), - /** + formatter: new CellFormatter(), + + /** @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" - }, - /** + editor: InputCellEditor, + + /** @property */ + events: { + "click": "enterEditMode" + }, + + /** Initializer. @param {Object} options @@ -493,24 +558,26 @@ @throws {ReferenceError} If formatter is a string but a formatter class of said name cannot be found in the Backgrid module. */ - initialize: function(options) { - requireOptions(options, [ "model", "column" ]); - this.column = options.column; - if (!(this.column instanceof Column)) { - this.column = new Column(this.column); - } - this.formatter = resolveNameToClass(this.formatter, "Formatter"); - this.editor = resolveNameToClass(this.editor, "CellEditor"); - }, - /** + initialize: function (options) { + requireOptions(options, ["model", "column"]); + this.column = options.column; + if (!(this.column instanceof Column)) { + this.column = new Column(this.column); + } + this.formatter = resolveNameToClass(this.formatter, "Formatter"); + this.editor = resolveNameToClass(this.editor, "CellEditor"); + }, + + /** 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().text(this.formatter.fromRaw(this.model.get(this.column.get("name")))); - return this; - }, - /** + render: function () { + this.$el.empty().text(this.formatter.fromRaw(this.model.get(this.column.get("name")))); + return this; + }, + + /** If this column is editable, a new CellEditor instance is instantiated with its required parameters and listens on the editor's `done` and `error` events. When the editor is `done`, edit mode is exited. When the editor @@ -518,15 +585,17 @@ current user input to an apprpriate value for the model's column. An `editor` CSS class is added to the cell upon entering edit mode. */ - enterEditMode: function(e) { - if (this.column.get("editable")) { - this.currentEditor = new this.editor({ - parent: this, - column: this.column, - model: this.model, - formatter: this.formatter - }); - /** + enterEditMode: function (e) { + if (this.column.get("editable")) { + + this.currentEditor = new this.editor({ + parent: this, + column: this.column, + model: this.model, + formatter: this.formatter + }); + + /** Backbone Event. Fired when a cell is entering edit mode and an editor instance has been constructed, but before it is rendered and inserted into the DOM. @@ -535,63 +604,74 @@ @param {Backgrid.Cell} cell This cell instance. @param {Backgrid.CellEditor} editor The cell editor constructed. */ - this.trigger("edit", this, this.currentEditor); - this.listenTo(this.currentEditor, "done", this.exitEditMode); - this.listenTo(this.currentEditor, "error", this.renderError); - this.$el.empty(); - this.undelegateEvents(); - this.$el.append(this.currentEditor.$el); - this.currentEditor.render(); - this.$el.addClass("editor"); - /** + this.trigger("edit", this, this.currentEditor); + + this.listenTo(this.currentEditor, "done", this.exitEditMode); + this.listenTo(this.currentEditor, "error", this.renderError); + + this.$el.empty(); + this.undelegateEvents(); + this.$el.append(this.currentEditor.$el); + this.currentEditor.render(); + this.$el.addClass("editor"); + + /** Backbone Event. Fired when a cell has finished switching to edit mode. @event editing @param {Backgrid.Cell} cell This cell instance. @param {Backgrid.CellEditor} editor The cell editor constructed. */ - this.trigger("editing", this, this.currentEditor); - } - }, - /** + this.trigger("editing", this, this.currentEditor); + } + }, + + /** Put an `error` CSS class on the table cell. */ - renderError: function() { - this.$el.addClass("error"); - }, - /** + renderError: function () { + this.$el.addClass("error"); + }, + + /** Removes the editor and re-render in display mode. */ - exitEditMode: function() { - this.$el.removeClass("error"); - this.currentEditor.off(null, null, this); + exitEditMode: function () { + this.$el.removeClass("error"); + this.currentEditor.off(null, null, this); + this.currentEditor.remove(); + delete this.currentEditor; + this.$el.removeClass("editor"); + this.render(); + this.delegateEvents(); + }, + + remove: function () { + Backbone.View.prototype.remove.apply(this, arguments); + if (this.currentEditor) { this.currentEditor.remove(); delete this.currentEditor; - this.$el.removeClass("editor"); - this.render(); - this.delegateEvents(); - }, - remove: function() { - Backbone.View.prototype.remove.apply(this, arguments); - if (this.currentEditor) { - this.currentEditor.remove(); - delete this.currentEditor; - } } - }); + } - /** +}); + +/** 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" - }); +var StringCell = Backgrid.StringCell = Cell.extend({ - /** + /** @property */ + className: "string-cell" + + // No formatter needed. Strings call auto-escaped by jQuery on insertion. + +}); + +/** UriCell renders an HTML `` anchor for the value and accepts URIs as user input values. A URI input is URI encoded using `encodeURI()` before writing to the underlying model. @@ -599,31 +679,35 @@ @class Backgrid.UriCell @extends Backgrid.Cell */ - var UriCell = Backgrid.UriCell = Cell.extend({ - /** @property */ - className: "uri-cell", - formatter: { - fromRaw: function(rawData) { - return rawData; - }, - toRaw: function(formattedData) { - var result = encodeURI(formattedData); - return "undefined" === result ? void 0 : result; - } +var UriCell = Backgrid.UriCell = Cell.extend({ + + /** @property */ + className: "uri-cell", + + formatter: { + fromRaw: function (rawData) { + return rawData; }, - render: function() { - this.$el.empty(); - var formattedValue = this.formatter.fromRaw(this.model.get(this.column.get("name"))); - this.$el.append($("", { - href: formattedValue, - title: formattedValue, - target: "_blank" - }).text(formattedValue)); - return this; + toRaw: function (formattedData) { + var result = encodeURI(formattedData); + return result === "undefined" ? undefined : result; } - }); + }, + + render: function () { + this.$el.empty(); + var formattedValue = this.formatter.fromRaw(this.model.get(this.column.get("name"))); + this.$el.append($("", { + href: formattedValue, + title: formattedValue, + target: "_blank" + }).text(formattedValue)); + return this; + } - /** +}); + +/** Like Backgrid.UriCell, EmailCell renders an HTML `` 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. @@ -631,71 +715,80 @@ @class Backgrid.EmailCell @extends Backgrid.Cell */ - var EmailCell = Backgrid.EmailCell = Cell.extend({ - /** @property */ - className: "email-cell", - formatter: { - fromRaw: function(rawData) { - return rawData; - }, - toRaw: function(formattedData) { - var parts = formattedData.split("@"); - if (2 === parts.length && _.all(parts)) { - return formattedData; - } else { - return void 0; - } - } +var EmailCell = Backgrid.EmailCell = Cell.extend({ + + /** @property */ + className: "email-cell", + + formatter: { + fromRaw: function (rawData) { + return rawData; }, - render: function() { - this.$el.empty(); - var formattedValue = this.formatter.fromRaw(this.model.get(this.column.get("name"))); - this.$el.append($("", { - href: "mailto:" + formattedValue, - title: formattedValue - }).text(formattedValue)); - return this; + toRaw: function (formattedData) { + var parts = formattedData.split("@"); + if (parts.length === 2 && _.all(parts)) { + return formattedData; + } } - }); + }, + + render: function () { + this.$el.empty(); + var formattedValue = this.formatter.fromRaw(this.model.get(this.column.get("name"))); + this.$el.append($("", { + href: "mailto:" + formattedValue, + title: formattedValue + }).text(formattedValue)); + 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", - /** +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, - /** + 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) { - Cell.prototype.initialize.apply(this, arguments); - this.formatter = new this.formatter({ - decimals: this.decimals, - decimalSeparator: this.decimalSeparator, - orderSeparator: this.orderSeparator - }); - } - }); + initialize: function (options) { + Cell.prototype.initialize.apply(this, arguments); + this.formatter = new this.formatter({ + decimals: this.decimals, + decimalSeparator: this.decimalSeparator, + orderSeparator: this.orderSeparator + }); + } - /** +}); + +/** 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. @@ -703,16 +796,18 @@ @class Backgrid.IntegerCell @extends Backgrid.NumberCell */ - var IntegerCell = Backgrid.IntegerCell = NumberCell.extend({ - /** @property */ - className: "integer-cell", - /** +var IntegerCell = Backgrid.IntegerCell = NumberCell.extend({ + + /** @property */ + className: "integer-cell", + + /** @property {number} decimals Must be an integer. */ - decimals: 0 - }); + 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 @@ -726,76 +821,91 @@ - Backgrid.Extension.MomentCell - Backgrid.DatetimeFormatter */ - var DatetimeCell = Backgrid.DatetimeCell = Cell.extend({ - /** @property */ - className: "datetime-cell", - /** +var DatetimeCell = Backgrid.DatetimeCell = Cell.extend({ + + /** @property */ + className: "datetime-cell", + + /** @property {boolean} [includeDate=true] */ - includeDate: DatetimeFormatter.prototype.defaults.includeDate, - /** + includeDate: DatetimeFormatter.prototype.defaults.includeDate, + + /** @property {boolean} [includeTime=true] */ - includeTime: DatetimeFormatter.prototype.defaults.includeTime, - /** + includeTime: DatetimeFormatter.prototype.defaults.includeTime, + + /** @property {boolean} [includeMilli=false] */ - includeMilli: DatetimeFormatter.prototype.defaults.includeMilli, - /** @property {Backgrid.CellFormatter} [formatter=Backgrid.DatetimeFormatter] */ - formatter: DatetimeFormatter, - /** + 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) { - Cell.prototype.initialize.apply(this, arguments); - this.formatter = new this.formatter({ - includeDate: this.includeDate, - includeTime: this.includeTime, - includeMilli: this.includeMilli - }); - 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 - }) - }); - } - }); + initialize: function (options) { + Cell.prototype.initialize.apply(this, arguments); + this.formatter = new this.formatter({ + includeDate: this.includeDate, + includeTime: this.includeTime, + includeMilli: this.includeMilli + }); + + 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 - }); +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 - }); +var TimeCell = Backgrid.TimeCell = DatetimeCell.extend({ - /** + /** @property */ + className: "time-cell", + + /** @property */ + includeDate: false + +}); + +/** BooleanCell is a different kind of cell in that there's no difference between display mode and edit mode and this cell type always renders a checkbox for selection. @@ -803,146 +913,164 @@ @class Backgrid.BooleanCell @extends Backgrid.Cell */ - var BooleanCell = Backgrid.BooleanCell = Cell.extend({ - /** @property */ - className: "boolean-cell", - /** +var BooleanCell = Backgrid.BooleanCell = Cell.extend({ + + /** @property */ + className: "boolean-cell", + + /** BooleanCell simple uses a default HTML checkbox template instead of a CellEditor instance. @property {function(Object, ?Object=): string} editor The Underscore.js template to render the editor. */ - editor: _.template(" />'"), - /** + editor: _.template(" />'"), + + /** Since the editor is not an instance of a CellEditor subclass, more things need to be done in BooleanCell class to listen to editor mode events. */ - events: { - click: "enterEditMode", - "blur input[type=checkbox]": "exitEditMode", - "change input[type=checkbox]": "save" - }, - /** + events: { + "click": "enterEditMode", + "blur input[type=checkbox]": "exitEditMode", + "change input[type=checkbox]": "save" + }, + + /** Renders a checkbox and check it if the model value of this column is true, uncheck otherwise. */ - render: function() { - this.$el.empty(); - this.currentEditor = $(this.editor({ - checked: this.formatter.fromRaw(this.model.get(this.column.get("name"))) - })); - this.$el.append(this.currentEditor); - return this; - }, - /** + render: function () { + this.$el.empty(); + this.currentEditor = $(this.editor({ + checked: this.formatter.fromRaw(this.model.get(this.column.get("name"))) + })); + this.$el.append(this.currentEditor); + return this; + }, + + /** Simple focuses the checkbox and add an `editor` CSS class to the cell. */ - enterEditMode: function(e) { - this.$el.addClass("editor"); - this.currentEditor.focus(); - }, - /** + enterEditMode: function (e) { + this.$el.addClass("editor"); + this.currentEditor.focus(); + }, + + /** Removed the `editor` CSS class from the cell. */ - exitEditMode: function(e) { - this.$el.removeClass("editor"); - }, - /** + exitEditMode: function (e) { + this.$el.removeClass("editor"); + }, + + /** Set true to the model attribute if the checkbox is checked, false otherwise. */ - save: function(e) { - var val = this.formatter.toRaw(this.currentEditor.prop("checked")); - this.model.set(this.column.get("name"), val); - } - }); + save: function (e) { + var val = this.formatter.toRaw(this.currentEditor.prop("checked")); + this.model.set(this.column.get("name"), val); + } - /** +}); + +/** SelectCellEditor renders an HTML ` />'"),events:{click:"enterEditMode","blur input[type=checkbox]":"exitEditMode","change input[type=checkbox]":"save"},render:function(){return this.$el.empty(),this.currentEditor=t(this.editor({checked:this.formatter.fromRaw(this.model.get(this.column.get("name")))})),this.$el.append(this.currentEditor),this},enterEditMode:function(){this.$el.addClass("editor"),this.currentEditor.focus()},exitEditMode:function(){this.$el.removeClass("editor")},save:function(){var e=this.formatter.toRaw(this.currentEditor.prop("checked"));this.model.set(this.column.get("name"),e)}});var C=d.SelectCellEditor=f.extend({tagName:"select",events:{change:"save",blur:"save"},template:i.template(''),setOptionValues:function(e){this.optionValues=e},_renderOptions:function(e,t){for(var i="",n=0;e.length>n;n++)i+=this.template({text:e[n][0],value:e[n][1],selected:t==e[n][1]});return i},render:function(){this.$el.empty();var e=i.result(this,"optionValues"),n=this.model.get(this.column.get("name"));if(!i.isArray(e))throw TypeError("optionValues must be an array");for(var r=null,o=null,r=null,l=null,s=null,a=0;e.length>a;a++){var r=e[a];if(i.isArray(r))o=r[0],r=r[1],this.$el.append(this.template({text:o,value:r,selected:r==n}));else{if(!i.isObject(r))throw TypeError("optionValues elements must be a name-value pair or an object hash of { name: 'optgroup label', value: [option name-value pairs] }");l=r.name,s=t("",{label:l}),s.append(this._renderOptions(r.values,n)),this.$el.append(s)}}return this},save:function(){this.model.set(this.column.get("name"),this.formatter.toRaw(this.$el.val())),this.trigger("done")}});d.SelectCell=v.extend({className:"select-cell",editor:C,optionValues:void 0,initialize:function(){v.prototype.initialize.apply(this,arguments),s(this,["optionValues"]),this.optionValues=i.result(this,"optionValues"),this.listenTo(this,"edit",this.setOptionValues)},setOptionValues:function(e,t){t.setOptionValues(this.optionValues)},render:function(){this.$el.empty();var e=this.optionValues,t=this.formatter.fromRaw(this.model.get(this.column.get("name")));try{if(!i.isArray(e)||i.isEmpty(e))throw new TypeError;for(var n=0;e.length>n;n++){var r=e[n];if(i.isArray(r)){var o=r[0],r=r[1];if(r==t){this.$el.append(o);break}}else{if(!i.isObject(r))throw new TypeError;for(var l=r.values,s=0;l.length>s;s++){var a=l[s];if(a[1]==t){this.$el.append(a[0]);break}}}}}catch(c){if(c instanceof TypeError)throw TypeError("'optionValues' must be of type {Array.|Array.<{name: string, values: Array.}>}");throw c}return this}});var y=d.Column=n.Model.extend({defaults:{name:void 0,label:void 0,sortable:!0,editable:!0,renderable:!0,formatter:void 0,cell:void 0,headerCell:void 0},initialize:function(e){s(e,["cell","name"]),this.has("label")||this.set({label:this.get("name")},{silent:!0});var t=a(this.get("cell"),"Cell");this.set({cell:t},{silent:!0})}}),E=d.Columns=n.Collection.extend({model:y}),$=d.Row=n.View.extend({tagName:"tr",initialize:function(e){var t=this;s(e,["columns","model"]);var r=t.columns=e.columns;r instanceof n.Collection||(r=t.columns=new E(r)),t.listenTo(r,"change:renderable",t.renderColumn);for(var o=t.cells=[],l=0;r.length>l;l++){var a=r.at(l);o.push(new(a.get("cell"))({column:a,model:t.model}))}t.listenTo(r,"add",function(e,n,r){r=i.defaults(r||{},{render:!0});var l=n.indexOf(e),s=new(e.get("cell"))({column:e,model:t.model});o.splice(l,0,s),t.renderColumn(e,e.get("renderable")&&r.render)}),t.listenTo(r,"remove",function(e){t.renderColumn(e,!1)})},renderColumn:function(e,t){for(var i=this,n=i.cells,r=i.columns,o=-1,l=0;n.length>l;l++){var s=n[l];if(s.column.get("name")==e.get("name")){o=l;break}}if(-1!=o){var a=i.$el;if(t){var s=n[o];0===o?a.prepend(s.render().$el):o===r.length-1?a.append(s.render().$el):a.children().eq(o).before(s.render().$el)}else a.children().eq(o).detach()}},render:function(){this.$el.empty();for(var e=0;this.cells.length>e;e++){var t=this.cells[e];t.column.get("renderable")&&this.$el.append(t.render().$el)}return this}}),b=d.HeaderCell=n.View.extend({tagName:"th",events:{"click a":"onClick"},_direction:null,initialize:function(e){s(e,["column","collection"]),this.column=e.column,this.column instanceof y||(this.column=new y(this.column)),this.listenTo(n,"backgrid:sort",this._resetCellDirection)},direction:function(e){return arguments.length&&(this._direction&&this.$el.removeClass(this._direction),e&&this.$el.addClass(e),this._direction=e),this._direction},_resetCellDirection:function(e,t,i,n){n==this.collection&&(e!==this.column.get("name")?this.direction(null):this.direction(t))},onClick:function(e){e.preventDefault();var t=this.column.get("name");this.column.get("sortable")&&("ascending"===this.direction()?this.sort(t,"descending",function(e,i){var n=e.get(t),r=i.get(t);return n===r?0:n>r?-1:1}):"descending"===this.direction()?this.sort(t,null):this.sort(t,"ascending",function(e,i){var n=e.get(t),r=i.get(t);return n===r?0:r>n?-1:1}))},sort:function(e,t,i){i=i||this._cidComparator;var r=this.collection;if(r instanceof n.PageableCollection){var o;o="ascending"===t?-1:"descending"===t?1:null,r.setSorting(o?e:null,o),"client"==r.mode?(r.fullCollection.comparator||(r.fullCollection.comparator=i),r.fullCollection.sort()):r.fetch()}else r.comparator=i,r.sort();n.trigger("backgrid:sort",e,t,i,this.collection)},_cidComparator:function(e,t){var n=e.cid,r=t.cid;if(!i.isUndefined(n)&&!i.isUndefined(r)){if(r>n)return-1;if(n>r)return 1}return 0},render:function(){this.$el.empty();var e=t("").text(this.column.get("label")).append("");return this.$el.append(e),this}});d.HeaderRow=d.Row.extend({initialize:function(e){var t=this;s(e,["columns","collection"]);var r=t.columns=e.columns;r instanceof n.Collection||(r=t.columns=new E(r)),t.listenTo(r,"change:renderable",t.renderColumn);for(var o=t.cells=[],l=0;r.length>l;l++){var a=r.at(l),c=a.get("headerCell")||e.headerCell||b;o.push(new c({column:a,collection:t.collection}))}t.listenTo(r,"add",function(n,r,l){l=i.defaults(l||{},{render:!0});var s=r.indexOf(n),a=n.get("headerCell")||e.headerCell||b;a=new a({column:n,collection:t.collection}),o.splice(s,0,a),t.renderColumn(n,n.get("renderable")&&l.render)}),t.listenTo(r,"remove",function(e){t.renderColumn(e,!1)})}});var T=d.Header=n.View.extend({tagName:"thead",initialize:function(e){s(e,["columns","collection"]),this.columns=e.columns,this.columns instanceof n.Collection||(this.columns=new E(this.columns)),this.row=new d.HeaderRow({columns:this.columns,collection:this.collection})},render:function(){return this.$el.append(this.row.render().$el),this}}),x=d.Body=n.View.extend({tagName:"tbody",initialize:function(e){s(e,["columns","collection"]);var t=this;t.columns=e.columns,t.columns instanceof n.Collection||(t.columns=new E(t.columns)),t.row=e.row||$,t.rows=t.collection.map(function(e){var i=new t.row({columns:t.columns,model:e});return i}),t.listenTo(t.collection,"add",t.insertRow),t.listenTo(t.collection,"remove",t.removeRow),t.listenTo(t.collection,"sort",t.refresh),t.listenTo(t.collection,"reset",t.refresh)},insertRow:function(e,t,r){if(t instanceof n.Collection||r){r=r||{};var o=new this.row({columns:this.columns,model:e}),l=t.indexOf(e);this.rows.splice(l,0,o),(i.isUndefined(r.render)||r.render)&&(l>=this.$el.children().length?this.$el.children().last().after(o.render().$el):this.$el.children().eq(l).before(o.render().$el))}else this.collection.add(e,r=t)},removeRow:function(e,t,n){n?((i.isUndefined(n.render)||n.render)&&this.rows[n.index].remove(),this.rows.splice(n.index,1)):this.collection.remove(e,n=t)},refresh:function(){var e=this;return i.each(e.rows,function(e){e.remove()}),e.rows=e.collection.map(function(t){var i=new e.row({columns:e.columns,model:t});return i}),e.render(),n.trigger("backgrid:refresh"),e},render:function(){var e=this;return e.$el.empty(),i.each(e.rows,function(t){e.$el.append(t.render().$el)}),this}});d.Footer=n.View.extend({tagName:"tfoot",initialize:function(e){s(e,["columns","collection"]),this.parent=e.parent,this.columns=e.columns,this.columns instanceof n.Collection||(this.columns=new d.Columns(this.columns))}}),d.Grid=n.View.extend({tagName:"table",className:"backgrid",header:T,body:x,footer:null,initialize:function(e){s(e,["columns","collection"]),this.columns=e.columns,this.columns instanceof n.Collection||(this.columns=new d.Columns(this.columns)),this.header=e.header||this.header,this.header=new this.header({columns:this.columns,collection:this.collection}),this.body=e.body||this.body,this.body=new this.body({columns:this.columns,collection:this.collection}),this.footer=e.footer||this.footer,this.footer&&(this.footer=new this.footer({columns:this.columns,collection:this.collection}))},insertRow:function(e,t,i){return this.body.insertRow(e,t,i)},removeRow:function(e,t,i){return this.body.removeRow(e,t,i)},insertColumn:function(e,t){var i=this;return t=t||{render:!0},i.columns.add(e,t),i},removeColumn:function(e,t){var i=this;return i.columns.remove(e,t),i},render:function(){return this.$el.empty(),this.$el.append(this.header.render().$el),this.footer&&this.$el.append(this.footer.render().$el),this.$el.append(this.body.render().$el),this.trigger("rendered"),this}})})(this,$,_,Backbone); \ No newline at end of file +(function(e,t,i,n){"use strict";function r(e){return String.prototype.trim?String.prototype.trim.call(e,e):e.replace(/^\s+|\s+$/g,"")}function o(e){return String.fromCharCode(e.charCodeAt(0)-32)+e.slice(1)}function l(e,t,i){var n=t-(e+"").length;n=0>n?0:n;for(var r="",o=0;n>o;o++)r+=i;return r+e}function s(e,t){for(var n=0;t.length>n;n++){var r=t[n];if(i.isUndefined(e[r]))throw new TypeError("'"+r+"' is required")}}function a(e,t){if(i.isString(e)){var n=o(e)+t,r=d[n]||d.Extension[n];if(i.isUndefined(r))throw new ReferenceError("Class '"+n+"' not found");return r}return e}var c=e,d=e.Backgrid={VERSION:"0.1",Extension:{}},u=d.CellFormatter=function(){};i.extend(u.prototype,{fromRaw:function(e){return e},toRaw:function(e){return e}});var h=d.NumberFormatter=function(e){if(e=e?i.clone(e):{},i.extend(this,this.defaults,e),0>this.decimals||this.decimals>20)throw new RangeError("decimals must be between 0 and 20")};h.prototype=new u,i.extend(h.prototype,{defaults:{decimals:2,decimalSeparator:".",orderSeparator:","},HUMANIZED_NUM_RE:/(\d)(?=(?:\d{3})+$)/g,fromRaw:function(e){if(isNaN(e)||null===e)return"";e=e.toFixed(~~this.decimals);var t=e.split("."),i=t[0],n=t[1]?(this.decimalSeparator||".")+t[1]:"";return i.replace(this.HUMANIZED_NUM_RE,"$1"+this.orderSeparator)+n},toRaw:function(e){for(var t="",n=r(e).split(this.orderSeparator),o=0;n.length>o;o++)t+=n[o];var l=t.split(this.decimalSeparator);t="";for(var o=0;l.length>o;o++)t=t+l[o]+".";"."===t[t.length-1]&&(t=t.slice(0,t.length-1));var s=1*(1*t).toFixed(~~this.decimals);return i.isNumber(s)&&!i.isNaN(s)?s:void 0}});var m=d.DatetimeFormatter=function(e){if(e=e?i.clone(e):{},i.extend(this,this.defaults,e),!this.includeDate&&!this.includeTime)throw Error("Either includeDate or includeTime must be true")};m.prototype=new u,i.extend(m.prototype,{defaults:{includeDate:!0,includeTime:!0,includeMilli:!1},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(e,t){e=r(e);var n=e.split(this.ISO_SPLITTER_RE)||[],o=this.DATE_RE.test(n[0])?n[0]:"",s=o&&n[1]?n[1]:this.TIME_RE.test(n[0])?n[0]:"",a=this.DATE_RE.exec(o)||[],c=this.TIME_RE.exec(s)||[];if(t){if(this.includeDate&&i.isUndefined(a[0]))return;if(this.includeTime&&i.isUndefined(c[0]))return;if(!this.includeDate&&o)return;if(!this.includeTime&&s)return}var d=new Date(Date.UTC(1*a[1]||0,1*a[2]-1||0,1*a[3]||0,1*c[1]||null,1*c[2]||null,1*c[3]||null,1*c[5]||null)),u="";return this.includeDate&&(u=l(d.getUTCFullYear(),4,0)+"-"+l(d.getUTCMonth()+1,2,0)+"-"+l(d.getUTCDate(),2,0)),this.includeTime&&(u=u+(this.includeDate?"T":"")+l(d.getUTCHours(),2,0)+":"+l(d.getUTCMinutes(),2,0)+":"+l(d.getUTCSeconds(),2,0),this.includeMilli&&(u=u+"."+l(d.getUTCMilliseconds(),3,0))),this.includeDate&&this.includeTime&&(u+="Z"),u},fromRaw:function(e){return this._convert(e)},toRaw:function(e){return this._convert(e,!0)}});var f=d.CellEditor=n.View.extend({initialize:function(e){s(e,["formatter","column","model"]),this.parent=e.parent,this.formatter=e.formatter,this.column=e.column,this.column instanceof y||(this.column=new y(this.column)),this.parent&&i.isFunction(this.parent.on)&&this.listenTo(this.parent,"editing",this.postRender)},postRender:function(){return this.$el.focus(),this}}),p=d.InputCellEditor=f.extend({tagName:"input",attributes:{type:"text"},events:{blur:"saveOrCancel",keydown:"saveOrCancel"},initialize:function(e){f.prototype.initialize.apply(this,arguments),e.placeholder&&this.$el.attr("placeholder",e.placeholder),this.listenTo(this,"done",this.remove)},render:function(){return this.$el.val(this.formatter.fromRaw(this.model.get(this.column.get("name")))),this},saveOrCancel:function(e){if("keydown"===e.type)if(13===e.keyCode||9===e.keyCode){e.preventDefault();var t=this.formatter.toRaw(this.$el.val());i.isUndefined(t)||!this.model.set(this.column.get("name"),t,{validate:!0})?this.trigger("error"):this.trigger("done")}else 27===e.keyCode&&(e.stopPropagation(),this.trigger("done"));else if("blur"===e.type)if(this.formatter.fromRaw(this.model.get(this.column.get("name")))===this.$el.val())this.trigger("done");else var n=this,r=c.setTimeout(function(){n.$el.focus(),c.clearTimeout(r)},1)},postRender:function(){if("right"===this.$el.css("text-align")){var e=this.$el.val();this.$el.focus().val(null).val(e)}else this.$el.focus();return this}}),v=d.Cell=n.View.extend({tagName:"td",formatter:new u,editor:p,events:{click:"enterEditMode"},initialize:function(e){s(e,["model","column"]),this.column=e.column,this.column instanceof y||(this.column=new y(this.column)),this.formatter=a(this.formatter,"Formatter"),this.editor=a(this.editor,"CellEditor")},render:function(){return this.$el.empty().text(this.formatter.fromRaw(this.model.get(this.column.get("name")))),this},enterEditMode:function(){this.column.get("editable")&&(this.currentEditor=new this.editor({parent:this,column:this.column,model:this.model,formatter:this.formatter}),this.trigger("edit",this,this.currentEditor),this.listenTo(this.currentEditor,"done",this.exitEditMode),this.listenTo(this.currentEditor,"error",this.renderError),this.$el.empty(),this.undelegateEvents(),this.$el.append(this.currentEditor.$el),this.currentEditor.render(),this.$el.addClass("editor"),this.trigger("editing",this,this.currentEditor))},renderError:function(){this.$el.addClass("error")},exitEditMode:function(){this.$el.removeClass("error"),this.currentEditor.off(null,null,this),this.currentEditor.remove(),delete this.currentEditor,this.$el.removeClass("editor"),this.render(),this.delegateEvents()},remove:function(){n.View.prototype.remove.apply(this,arguments),this.currentEditor&&(this.currentEditor.remove(),delete this.currentEditor)}});d.StringCell=v.extend({className:"string-cell"}),d.UriCell=v.extend({className:"uri-cell",formatter:{fromRaw:function(e){return e},toRaw:function(e){var t=encodeURI(e);return"undefined"===t?void 0:t}},render:function(){this.$el.empty();var e=this.formatter.fromRaw(this.model.get(this.column.get("name")));return this.$el.append(t("",{href:e,title:e,target:"_blank"}).text(e)),this}}),d.EmailCell=v.extend({className:"email-cell",formatter:{fromRaw:function(e){return e},toRaw:function(e){var t=e.split("@");return 2===t.length&&i.all(t)?e:void 0}},render:function(){this.$el.empty();var e=this.formatter.fromRaw(this.model.get(this.column.get("name")));return this.$el.append(t("",{href:"mailto:"+e,title:e}).text(e)),this}});var g=d.NumberCell=v.extend({className:"number-cell",decimals:h.prototype.defaults.decimals,decimalSeparator:h.prototype.defaults.decimalSeparator,orderSeparator:h.prototype.defaults.orderSeparator,formatter:h,initialize:function(){v.prototype.initialize.apply(this,arguments),this.formatter=new this.formatter({decimals:this.decimals,decimalSeparator:this.decimalSeparator,orderSeparator:this.orderSeparator})}});d.IntegerCell=g.extend({className:"integer-cell",decimals:0});var w=d.DatetimeCell=v.extend({className:"datetime-cell",includeDate:m.prototype.defaults.includeDate,includeTime:m.prototype.defaults.includeTime,includeMilli:m.prototype.defaults.includeMilli,formatter:m,initialize:function(){v.prototype.initialize.apply(this,arguments),this.formatter=new this.formatter({includeDate:this.includeDate,includeTime:this.includeTime,includeMilli:this.includeMilli});var e=this.includeDate?"YYYY-MM-DD":"";e+=this.includeDate&&this.includeTime?"T":"",e+=this.includeTime?"HH:mm:ss":"",e+=this.includeTime&&this.includeMilli?".SSS":"",this.editor=this.editor.extend({attributes:i.extend({},this.editor.prototype.attributes,this.editor.attributes,{placeholder:e})})}});d.DateCell=w.extend({className:"date-cell",includeTime:!1}),d.TimeCell=w.extend({className:"time-cell",includeDate:!1}),d.BooleanCell=v.extend({className:"boolean-cell",editor:i.template(" />'"),events:{click:"enterEditMode","blur input[type=checkbox]":"exitEditMode","change input[type=checkbox]":"save"},render:function(){return this.$el.empty(),this.currentEditor=t(this.editor({checked:this.formatter.fromRaw(this.model.get(this.column.get("name")))})),this.$el.append(this.currentEditor),this},enterEditMode:function(){this.$el.addClass("editor"),this.currentEditor.focus()},exitEditMode:function(){this.$el.removeClass("editor")},save:function(){var e=this.formatter.toRaw(this.currentEditor.prop("checked"));this.model.set(this.column.get("name"),e)}});var C=d.SelectCellEditor=f.extend({tagName:"select",events:{change:"save",blur:"save"},template:i.template(''),setOptionValues:function(e){this.optionValues=e},_renderOptions:function(e,t){for(var i="",n=0;e.length>n;n++)i+=this.template({text:e[n][0],value:e[n][1],selected:t==e[n][1]});return i},render:function(){this.$el.empty();var e=i.result(this,"optionValues"),n=this.model.get(this.column.get("name"));if(!i.isArray(e))throw TypeError("optionValues must be an array");for(var r=null,o=null,r=null,l=null,s=null,a=0;e.length>a;a++){var r=e[a];if(i.isArray(r))o=r[0],r=r[1],this.$el.append(this.template({text:o,value:r,selected:r==n}));else{if(!i.isObject(r))throw TypeError("optionValues elements must be a name-value pair or an object hash of { name: 'optgroup label', value: [option name-value pairs] }");l=r.name,s=t("",{label:l}),s.append(this._renderOptions(r.values,n)),this.$el.append(s)}}return this},save:function(){this.model.set(this.column.get("name"),this.formatter.toRaw(this.$el.val())),this.trigger("done")}});d.SelectCell=v.extend({className:"select-cell",editor:C,optionValues:void 0,initialize:function(){v.prototype.initialize.apply(this,arguments),s(this,["optionValues"]),this.optionValues=i.result(this,"optionValues"),this.listenTo(this,"edit",this.setOptionValues)},setOptionValues:function(e,t){t.setOptionValues(this.optionValues)},render:function(){this.$el.empty();var e=this.optionValues,t=this.formatter.fromRaw(this.model.get(this.column.get("name")));try{if(!i.isArray(e)||i.isEmpty(e))throw new TypeError;for(var n=0;e.length>n;n++){var r=e[n];if(i.isArray(r)){var o=r[0],r=r[1];if(r==t){this.$el.append(o);break}}else{if(!i.isObject(r))throw new TypeError;for(var l=r.values,s=0;l.length>s;s++){var a=l[s];if(a[1]==t){this.$el.append(a[0]);break}}}}}catch(c){if(c instanceof TypeError)throw TypeError("'optionValues' must be of type {Array.|Array.<{name: string, values: Array.}>}");throw c}return this}});var y=d.Column=n.Model.extend({defaults:{name:void 0,label:void 0,sortable:!0,editable:!0,renderable:!0,formatter:void 0,cell:void 0,headerCell:void 0},initialize:function(e){s(e,["cell","name"]),this.has("label")||this.set({label:this.get("name")},{silent:!0});var t=a(this.get("cell"),"Cell");this.set({cell:t},{silent:!0})}}),E=d.Columns=n.Collection.extend({model:y}),$=d.Row=n.View.extend({tagName:"tr",initialize:function(e){var t=this;s(e,["columns","model"]);var r=t.columns=e.columns;r instanceof n.Collection||(r=t.columns=new E(r)),t.listenTo(r,"change:renderable",t.renderColumn);for(var o=t.cells=[],l=0;r.length>l;l++){var a=r.at(l);o.push(new(a.get("cell"))({column:a,model:t.model}))}t.listenTo(r,"add",function(e,n,r){r=i.defaults(r||{},{render:!0});var l=n.indexOf(e),s=new(e.get("cell"))({column:e,model:t.model});o.splice(l,0,s),t.renderColumn(e,e.get("renderable")&&r.render)}),t.listenTo(r,"remove",function(e){t.renderColumn(e,!1)})},renderColumn:function(e,t){for(var i=this,n=i.cells,r=i.columns,o=-1,l=0;n.length>l;l++){var s=n[l];if(s.column.get("name")==e.get("name")){o=l;break}}if(-1!=o){var a=i.$el;if(t){var s=n[o];0===o?a.prepend(s.render().$el):o===r.length-1?a.append(s.render().$el):a.children().eq(o).before(s.render().$el)}else a.children().eq(o).detach()}},render:function(){this.$el.empty();for(var e=0;this.cells.length>e;e++){var t=this.cells[e];t.column.get("renderable")&&this.$el.append(t.render().$el)}return this}}),b=d.HeaderCell=n.View.extend({tagName:"th",events:{"click a":"onClick"},_direction:null,initialize:function(e){s(e,["column","collection"]),this.column=e.column,this.column instanceof y||(this.column=new y(this.column)),this.listenTo(n,"backgrid:sort",this._resetCellDirection)},direction:function(e){return arguments.length&&(this._direction&&this.$el.removeClass(this._direction),e&&this.$el.addClass(e),this._direction=e),this._direction},_resetCellDirection:function(e,t,i,n){n==this.collection&&(e!==this.column.get("name")?this.direction(null):this.direction(t))},onClick:function(e){e.preventDefault();var t=this.column.get("name");this.column.get("sortable")&&("ascending"===this.direction()?this.sort(t,"descending",function(e,i){var n=e.get(t),r=i.get(t);return n===r?0:n>r?-1:1}):"descending"===this.direction()?this.sort(t,null):this.sort(t,"ascending",function(e,i){var n=e.get(t),r=i.get(t);return n===r?0:r>n?-1:1}))},sort:function(e,t,i){i=i||this._cidComparator;var r=this.collection;if(r instanceof n.PageableCollection){var o;o="ascending"===t?-1:"descending"===t?1:null,r.setSorting(o?e:null,o),"client"==r.mode?(r.fullCollection.comparator||(r.fullCollection.comparator=i),r.fullCollection.sort()):r.fetch()}else r.comparator=i,r.sort();n.trigger("backgrid:sort",e,t,i,this.collection)},_cidComparator:function(e,t){var n=e.cid,r=t.cid;if(!i.isUndefined(n)&&!i.isUndefined(r)){if(r>n)return-1;if(n>r)return 1}return 0},render:function(){this.$el.empty();var e=t("").text(this.column.get("label")).append("");return this.$el.append(e),this}});d.HeaderRow=d.Row.extend({initialize:function(e){var t=this;s(e,["columns","collection"]);var r=t.columns=e.columns;r instanceof n.Collection||(r=t.columns=new E(r)),t.listenTo(r,"change:renderable",t.renderColumn);for(var o=t.cells=[],l=0;r.length>l;l++){var a=r.at(l),c=a.get("headerCell")||e.headerCell||b;o.push(new c({column:a,collection:t.collection}))}t.listenTo(r,"add",function(n,r,l){l=i.defaults(l||{},{render:!0});var s=r.indexOf(n),a=n.get("headerCell")||e.headerCell||b;a=new a({column:n,collection:t.collection}),o.splice(s,0,a),t.renderColumn(n,n.get("renderable")&&l.render)}),t.listenTo(r,"remove",function(e){t.renderColumn(e,!1)})}});var T=d.Header=n.View.extend({tagName:"thead",initialize:function(e){s(e,["columns","collection"]),this.columns=e.columns,this.columns instanceof n.Collection||(this.columns=new E(this.columns)),this.row=new d.HeaderRow({columns:this.columns,collection:this.collection})},render:function(){return this.$el.append(this.row.render().$el),this}}),x=d.Body=n.View.extend({tagName:"tbody",initialize:function(e){s(e,["columns","collection"]);var t=this;t.columns=e.columns,t.columns instanceof n.Collection||(t.columns=new E(t.columns)),t.row=e.row||$,t.rows=t.collection.map(function(e){var i=new t.row({columns:t.columns,model:e});return i}),t.listenTo(t.collection,"add",t.insertRow),t.listenTo(t.collection,"remove",t.removeRow),t.listenTo(t.collection,"sort",t.refresh),t.listenTo(t.collection,"reset",t.refresh)},insertRow:function(e,t,r){if(!(t instanceof n.Collection||r))return this.collection.add(e,r=t),void 0;r=r||{};var o=new this.row({columns:this.columns,model:e}),l=t.indexOf(e);this.rows.splice(l,0,o),(i.isUndefined(r.render)||r.render)&&(l>=this.$el.children().length?this.$el.children().last().after(o.render().$el):this.$el.children().eq(l).before(o.render().$el))},removeRow:function(e,t,n){return n?((i.isUndefined(n.render)||n.render)&&this.rows[n.index].remove(),this.rows.splice(n.index,1),void 0):(this.collection.remove(e,n=t),void 0)},refresh:function(){var e=this;return i.each(e.rows,function(e){e.remove()}),e.rows=e.collection.map(function(t){var i=new e.row({columns:e.columns,model:t});return i}),e.render(),n.trigger("backgrid:refresh"),e},render:function(){var e=this;return e.$el.empty(),i.each(e.rows,function(t){e.$el.append(t.render().$el)}),this}});d.Footer=n.View.extend({tagName:"tfoot",initialize:function(e){s(e,["columns","collection"]),this.parent=e.parent,this.columns=e.columns,this.columns instanceof n.Collection||(this.columns=new d.Columns(this.columns))}}),d.Grid=n.View.extend({tagName:"table",className:"backgrid",header:T,body:x,footer:null,initialize:function(e){s(e,["columns","collection"]),this.columns=e.columns,this.columns instanceof n.Collection||(this.columns=new d.Columns(this.columns)),this.header=e.header||this.header,this.header=new this.header({columns:this.columns,collection:this.collection}),this.body=e.body||this.body,this.body=new this.body({columns:this.columns,collection:this.collection}),this.footer=e.footer||this.footer,this.footer&&(this.footer=new this.footer({columns:this.columns,collection:this.collection}))},insertRow:function(e,t,i){return this.body.insertRow(e,t,i)},removeRow:function(e,t,i){return this.body.removeRow(e,t,i)},insertColumn:function(e,t){var i=this;return t=t||{render:!0},i.columns.add(e,t),i},removeColumn:function(e,t){var i=this;return i.columns.remove(e,t),i},render:function(){return this.$el.empty(),this.$el.append(this.header.render().$el),this.footer&&this.$el.append(this.footer.render().$el),this.$el.append(this.body.render().$el),this.trigger("rendered"),this}})})(this,$,_,Backbone); \ No newline at end of file diff --git a/lib/extensions/moment-cell/backgrid-moment-cell.css b/lib/extensions/moment-cell/backgrid-moment-cell.css index 380d5bdd..b896e071 100644 --- a/lib/extensions/moment-cell/backgrid-moment-cell.css +++ b/lib/extensions/moment-cell/backgrid-moment-cell.css @@ -2,7 +2,7 @@ backgrid-moment-cell http://github.com/wyuenho/backgrid - Copyright (c) 2012 Jimmy Yuen Ho Wong + Copyright (c) 2013 Jimmy Yuen Ho Wong Licensed under the MIT @license. */ .backgrid .moment-cell { diff --git a/lib/extensions/moment-cell/backgrid-moment-cell.js b/lib/extensions/moment-cell/backgrid-moment-cell.js index c226c53f..79989836 100644 --- a/lib/extensions/moment-cell/backgrid-moment-cell.js +++ b/lib/extensions/moment-cell/backgrid-moment-cell.js @@ -2,7 +2,7 @@ backgrid-moment-cell http://github.com/wyuenho/backgrid - Copyright (c) 2012 Jimmy Yuen Ho Wong + Copyright (c) 2013 Jimmy Yuen Ho Wong Licensed under the MIT @license. */ (function ($, _, Backbone, Backgrid, moment) { diff --git a/lib/extensions/paginator/backgrid-paginator.css b/lib/extensions/paginator/backgrid-paginator.css index 68f0aa09..db3d397d 100644 --- a/lib/extensions/paginator/backgrid-paginator.css +++ b/lib/extensions/paginator/backgrid-paginator.css @@ -2,7 +2,7 @@ backgrid-paginator http://github.com/wyuenho/backgrid - Copyright (c) 2012 Jimmy Yuen Ho Wong + Copyright (c) 2013 Jimmy Yuen Ho Wong Licensed under the MIT @license. */ diff --git a/lib/extensions/paginator/backgrid-paginator.js b/lib/extensions/paginator/backgrid-paginator.js index 2c5d7fd8..d7ee9bf6 100644 --- a/lib/extensions/paginator/backgrid-paginator.js +++ b/lib/extensions/paginator/backgrid-paginator.js @@ -2,7 +2,7 @@ backgrid-paginator http://github.com/wyuenho/backgrid - Copyright (c) 2012 Jimmy Yuen Ho Wong + Copyright (c) 2013 Jimmy Yuen Ho Wong Licensed under the MIT @license. */ diff --git a/lib/extensions/select2-cell/backgrid-select2-cell.js b/lib/extensions/select2-cell/backgrid-select2-cell.js index b03c1b11..728bc248 100644 --- a/lib/extensions/select2-cell/backgrid-select2-cell.js +++ b/lib/extensions/select2-cell/backgrid-select2-cell.js @@ -2,7 +2,7 @@ backgrid-select2-cell http://github.com/wyuenho/backgrid - Copyright (c) 2012 Jimmy Yuen Ho Wong + Copyright (c) 2013 Jimmy Yuen Ho Wong Licensed under the MIT @license. */ diff --git a/lib/extensions/text-cell/backgrid-text-cell.css b/lib/extensions/text-cell/backgrid-text-cell.css index 9e67bba9..1d04a833 100644 --- a/lib/extensions/text-cell/backgrid-text-cell.css +++ b/lib/extensions/text-cell/backgrid-text-cell.css @@ -2,7 +2,7 @@ backgrid-text-cell http://github.com/wyuenho/backgrid - Copyright (c) 2012 Jimmy Yuen Ho Wong + Copyright (c) 2013 Jimmy Yuen Ho Wong Licensed under the MIT @license. */ diff --git a/lib/extensions/text-cell/backgrid-text-cell.js b/lib/extensions/text-cell/backgrid-text-cell.js index 01f96b98..55776cc6 100644 --- a/lib/extensions/text-cell/backgrid-text-cell.js +++ b/lib/extensions/text-cell/backgrid-text-cell.js @@ -2,7 +2,7 @@ backgrid-text-cell http://github.com/wyuenho/backgrid - Copyright (c) 2012 Jimmy Yuen Ho Wong + Copyright (c) 2013 Jimmy Yuen Ho Wong Licensed under the MIT @license. */ diff --git a/src/Makefile b/src/Makefile index 8a6c661d..13ceb59f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -19,10 +19,7 @@ CSS_OUTFILE = $(PROJECT_NAME).css CSS_OUTFILE_MIN = $(PROJECT_NAME).min.css UGLIFY = uglifyjs -UGLIFY_BEAUTIFY_FLAGS = --beautify indent-level=2,indent-start=2,bracketize=true \ - --compress sequences=false,properties=false,dead-code=false,unsafe=false,conditionals=false,comparisons=false,evaluate=false,booleans=false,loops=false,unused=false,hoist-funs=false,hoist-vars=false,join-vars=false,cascade=false,warnings=true \ - --comments '/^(?!jshint|global)([.\s\S](?!@license))+$$/' -UGLIFY_MINIFY_FLAGS = --compress --mangle +UGLIFY_FLAGS = --compress --mangle all: clean dist test @@ -38,7 +35,7 @@ FORCE: */" | cat - $@ > "/tmp/`basename $@`" && mv -f "/tmp/`basename $@`" $@ js: - $(UGLIFY) $(JS_FILES) $(UGLIFY_BEAUTIFY_FLAGS) --output $(JS_OUTFILE) + cat $(JS_FILES) > $(JS_OUTFILE) echo "(function (root, $$, _, Backbone) {\n\n \"use strict\";\n" | cat - $(JS_OUTFILE) > /tmp/$(JS_OUTFILE) && mv -f /tmp/$(JS_OUTFILE) $(JS_OUTFILE) echo "}(this, $$, _, Backbone));" >> $(JS_OUTFILE) make $(JS_OUTFILE) @@ -47,7 +44,7 @@ csslint: recess $(CSS_FILES) --noIDS --noUniversalSelectors --compile > /tmp/$(CSS_OUTFILE) && mv -f /tmp/$(CSS_OUTFILE) $(CSS_OUTFILE); minify: js - $(UGLIFY) $(JS_OUTFILE) $(UGLIFY_MINIFY_FLAGS) --output $(JS_OUTFILE_MIN) + $(UGLIFY) $(JS_OUTFILE) $(UGLIFY_FLAGS) --output $(JS_OUTFILE_MIN) recess $(CSS_FILES) --noIDS --noUniversalSelectors --compress > /tmp/$(CSS_OUTFILE_MIN) && mv -f /tmp/$(CSS_OUTFILE_MIN) $(CSS_OUTFILE_MIN); build: minify