diff --git a/.bowerrc b/.bowerrc new file mode 100644 index 000000000..6866ac2ca --- /dev/null +++ b/.bowerrc @@ -0,0 +1,3 @@ +{ + "directory": "vendor" +} diff --git a/.gitignore b/.gitignore index 0da380cdb..49c404872 100644 --- a/.gitignore +++ b/.gitignore @@ -2,10 +2,10 @@ bower_components/ build/ doc/ gh_pages/ -lib/ node_modules/ tests/lib tests/css +vendor/ .DS_Store .stage *.swo diff --git a/.release.json b/.release.json deleted file mode 100644 index 15d358eb3..000000000 --- a/.release.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "non-interactive": false, - "dry-run": false, - "verbose": false, - "force": false, - "pkgFiles": ["package.json", "bower.json"], - "increment": "patch", - "commitMessage": "Release %s", - "tagName": "v%s", - "tagAnnotation": "Release %s", - "buildCommand": "grunt dist", - "distRepo": false, - "distStageDir": ".stage", - "distBase": "", - "distFiles": ["dist/**/*"], - "publish": false -} diff --git a/CHANGELOG.md b/CHANGELOG.md index 3943ca7b8..4ff4e366e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,33 @@ # Ember Table Changelog +### Ember Table 0.2.2 _(September 25, 2014)_ + +* Dasherize stylename for output + * `styleBindings` definitions are now auto-dasherized +* Check against both undefined and null instead of just undefined +* Fix state deprecation, add quotes to column header sort action name +* Resolve Ember CLI style view references. + * Now, `tableCellView: 'message/preview'` is also valid +* Check that selection is not null +* Store row objects in _selection rather than their contents +* Automatically publish updated docs with every release +* Add community examples page, and other small docs improvements +* Add multiselect functionality + * API: `selectionMode="{single|multiple|none}"` +* Upgrade grunt-bower-task and use grunt-release-it +* Use more standard ~ for handlebars version + +### Ember Table 0.2.1 _(June 30, 2014)_ + +* Hide fixedColumns table when numFixedColumns is 0 +* Revert "Fix a few minor UI bugs" (fixes antiscroll issue) + * Fixes #92, where rows are dynamically inserted +* Fix updateLayout to make antiscroll update its dimensions +* Use intersect rather than pointer for sortable +* Header cell span css fix +* Use row rather than content of row object proxy in table cells + * It's now necessary to use row.get('property') rather than row.property + ### Ember Table 0.2.0 _(May 19, 2014)_ * Add versions to proper files; add CHANGELOG.md to manage versions diff --git a/Gruntfile.js b/Gruntfile.js index c09bd4a40..b0fd51bc1 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -17,6 +17,7 @@ module.exports = function (grunt) { grunt.loadNpmTasks('grunt-banner'); grunt.loadNpmTasks('grunt-text-replace'); grunt.loadNpmTasks('grunt-bower-task'); + grunt.loadNpmTasks('grunt-release-it'); // Project configuration. grunt.initConfig({ @@ -25,8 +26,10 @@ module.exports = function (grunt) { bower: { install: { options: { - cleanup: true, - layout: 'byComponent' + targetDir: 'vendor', + layout: 'byComponent', + verbose: true, + copy: false } } }, @@ -121,21 +124,29 @@ module.exports = function (grunt) { dest: 'gh_pages/index.html' }, { expand: true, - flatten: true, cwd: 'dependencies/', src: ['**/*.js'], dest: 'gh_pages/lib' }, { expand: true, - flatten: true, + cwd: 'vendor/', + src: ['**/*.js'], + dest: 'gh_pages/lib' + }, { + expand: true, cwd: 'dependencies/', src: ['**/*.css'], - dest: 'gh_pages/css' + dest: 'gh_pages/lib' }, { expand: true, - cwd: 'lib/font-awesome/font/', + cwd: 'vendor/', + src: ['**/*.css'], + dest: 'gh_pages/lib' + }, { + expand: true, + cwd: 'vendor/font-awesome/font/', src: ['**'], - dest: 'gh_pages/font' + dest: 'gh_pages/lib/font-awesome/font' }, { expand: true, cwd: 'app/assets/font/', @@ -152,17 +163,22 @@ module.exports = function (grunt) { tests: { files: [ { - expand: true, - flatten: true, - cwd: 'dependencies/', - src: ['**/*.js'], - dest: 'tests/lib' + src: ['vendor/qunit/qunit/qunit.css'], + dest: 'tests/css/qunit.css' }, { - expand: true, flatten: true, - cwd: 'dependencies/', - src: ['**/*.css'], - dest: 'tests/css' + expand: true, + src: [ + 'vendor/qunit/qunit/qunit.js', + 'vendor/ember/ember.js', + 'vendor/handlebars/handlebars.js', + 'vendor/modernizr/modernizr.js', + 'vendor/d3/d3.js', + 'vendor/jquery/jquery.js', + 'vendor/jquery-ui/ui/jquery-ui.custom.js', + 'vendor/jquery-mousewheel/jquery.mousewheel.js' + ], + dest: 'tests/lib/' } ] } @@ -220,6 +236,14 @@ module.exports = function (grunt) { from: /Ember.Table.VERSION = '.*\..*\..*'/, to: "Ember.Table.VERSION = '<%=pkg.version%>'" }] + }, + overview_page: { + src: ['app/templates/ember_table/overview.hbs'], + overwrite: true, + replacements: [{ + from: /The current version is .*\..*\..*./, + to: "The current version is <%=pkg.version%>." + }] } }, @@ -229,7 +253,7 @@ module.exports = function (grunt) { tasks: ["default"] }, code: { - files: ["src/**/*.coffee", "app/**/*.coffee", "dependencies/**/*.js", "lib/**/*.js"], + files: ["src/**/*.coffee", "app/**/*.coffee", "dependencies/**/*.js", "vendor/**/*.js"], tasks: ["coffee", "neuter"] }, handlebars: { @@ -244,15 +268,31 @@ module.exports = function (grunt) { files: ["app/index.html"], tasks: ["copy"] } + }, + + "release-it": { + options: { + "pkgFiles": ["package.json", "bower.json"], + "commitMessage": "Release %s", + "tagName": "v%s", + "tagAnnotation": "Release %s", + "increment": "patch", + "buildCommand": "grunt dist", + "distRepo": "-b gh-pages git@github.com:addepar/ember-table", + "distStageDir": ".stage", + "distBase": "gh_pages", + "distFiles": ["**/*"], + "publish": false + } } }); - // Default tasks. + // Build tasks grunt.registerTask("build_srcs", ["coffee:srcs", "emberTemplates", "neuter"]); - grunt.registerTask("build_app", ["coffee:app", "emberTemplates", "neuter"]); - grunt.registerTask("dist", ["replace", "build_srcs", "build_app", "less", "copy", "uglify", "usebanner"]); + grunt.registerTask("dist", ["bower", "replace", "build_srcs", "build_app", "less", "copy", "uglify", "usebanner"]); - grunt.registerTask("default", ["bower", "replace", "build_srcs", "build_app", "less", "copy", "uglify", "usebanner", "watch"]); + grunt.registerTask("default", ["dist", "watch"]); }; + diff --git a/README.md b/README.md index 8f6329890..a3d2ffe8b 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ http://addepar.github.com/ember-table/ #### JS Bin Starter Kit -http://emberjs.jsbin.com/feqih/1/edit +http://emberjs.jsbin.com/rikon/1/edit #### Installation @@ -41,6 +41,8 @@ To view examples, start the node server. From the root directory: You can view the examples at http://localhost:8000/gh_pages. +You can run the tests at http://localhost:8000/tests. + ## Dependencies * ember * jquery-ui @@ -71,17 +73,26 @@ In a nutshell, this means: ### Maintainers -Update version numbers and release using https://github.com/webpro/release-it. Install: +Update version numbers and release using https://github.com/webpro/grunt-release-it: + ``` -$ npm install -g release-it -$ alias release="release-it" +$ vim CHANGELOG.md +$ grunt release-it: ``` -Release process: + +By default, this will release a new patch version. Other suggested commands: + ``` -$ vim CHANGELOG.md -$ release +$ grunt release-it:minor +$ grunt release-it:major +$ grunt release-it:X.Y.Z ``` +Ember Table uses the "distribution repository" feature of `release-it` to push to +the `gh-pages` branch and update documentation. When prompted, do NOT update the +tag for the distribution repository. We'll streamline the release process a bit +more soon. + ## Copyright and License Copyright © 2013 Addepar, Inc. All Rights Reserved diff --git a/VERSION b/VERSION index 0ea3a944b..ee1372d33 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.2.0 +0.2.2 diff --git a/app/app.coffee b/app/app.coffee index fa5ff1538..7ad803ab0 100644 --- a/app/app.coffee +++ b/app/app.coffee @@ -1,6 +1,6 @@ # Ember-Table Dependencies -require 'lib/bootstrap/bootstrap' -require 'lib/antiscroll/antiscroll' +require 'vendor/bootstrap/dist/js/bootstrap' +require 'vendor/antiscroll/antiscroll' require 'dependencies/ember-addepar-mixins/resize_handler' require 'dependencies/ember-addepar-mixins/style_bindings' require 'dist/ember-table' @@ -9,7 +9,7 @@ require 'dist/ember-table' require 'dependencies/date' # Editable Horizon and Sparkline dependency -require 'lib/d3/d3' +require 'vendor/d3/d3' require 'dependencies/horizon' window.App = Ember.Application.create diff --git a/app/assets/css/app.less b/app/assets/css/app.less index f4e92cd1a..9db434c20 100644 --- a/app/assets/css/app.less +++ b/app/assets/css/app.less @@ -4,9 +4,8 @@ // External Libraries on which addepar-components.css relies // ------------------------- -@import "../../../lib/bootstrap/bootstrap.css"; -@import '../../../lib/jquery-ui/jquery-ui.css'; -@import '../../../dependencies/addepar-bootstrap-theme/addepar-bootstrap-theme.less'; +@import "../lib/bootstrap/dist/css/bootstrap.css"; +@import '../lib/jquery-ui/themes/base/jquery-ui.css'; // Ember Table // ------------------------- @@ -93,6 +92,10 @@ h3 { h4 { font: 500 15px/1.5 @sansFontFamily; font-family: 'Univers Next W01 Medium'; + + &.byline { + margin-bottom: 2px; + } } h5 { @@ -126,6 +129,13 @@ p, font: normal 11px/1.4 @sansFontFamily; font-family: 'UniversNextW01-Regular'; } + + &.byline { + font: normal 12px/1.4 @sansFontFamily; + font-family: 'Univers Next W01 Light'; + margin-top: 2px; + margin-bottom: 6px; + } } .styled li { @@ -188,7 +198,8 @@ strong { /* Code Sample Styles */ code, pre { - display: block; + background-color: #f8f8f8; + color: black; font-family : 'SourceCodePro-Regular', Menlo, Monaco, Consolas, monospace; font-size: 12px; white-space: pre !important; @@ -196,9 +207,9 @@ code, pre { } pre { + display: block; .border-radius(1px); border: none; - background-color: #f8f8f8; } /* Buttons diff --git a/app/assets/img/community_examples/preview_server_side_sorting.png b/app/assets/img/community_examples/preview_server_side_sorting.png new file mode 100644 index 000000000..1ca0910a3 Binary files /dev/null and b/app/assets/img/community_examples/preview_server_side_sorting.png differ diff --git a/app/controllers/financial.coffee b/app/controllers/financial.coffee index ef87b1d76..e77b735c1 100644 --- a/app/controllers/financial.coffee +++ b/app/controllers/financial.coffee @@ -85,7 +85,6 @@ App.FinancialTableComponent = Ember.Table.EmberTableComponent.extend # custom properties sortAscending: no sortColumn: null - selection: null actions: toggleTableCollapse: (event) -> diff --git a/app/controllers/treetable.coffee b/app/controllers/treetable.coffee index 1e170a951..8827ae019 100644 --- a/app/controllers/treetable.coffee +++ b/app/controllers/treetable.coffee @@ -136,7 +136,6 @@ Ember.Table.EmberTableComponent.extend App.TreeTableExample.TreeDataAdapter, # custom properties sortAscending: no sortColumn: null - selection: null toggleTableCollapse: (event) -> @toggleProperty 'isCollapsed' diff --git a/app/index.html b/app/index.html index 6bf8a39ac..1527873cf 100644 --- a/app/index.html +++ b/app/index.html @@ -4,26 +4,26 @@ Addepar | Ember Table - + - - - + + + - - - - - - - - + + + + + + + + diff --git a/app/router.coffee b/app/router.coffee index 2d71bcb50..e0a71b597 100644 --- a/app/router.coffee +++ b/app/router.coffee @@ -7,6 +7,7 @@ App.Router.map -> @resource 'emberTable', path: '/ember-table', -> @route 'overview' @route 'documentation' + @route 'migration-guides' @route 'ajax' @route 'bars' @route 'dynamic-bars' @@ -16,6 +17,7 @@ App.Router.map -> @route 'horizon' @route 'simple' @route 'sparkline' + @route 'community-examples' App.IndexRoute = Ember.Route.extend redirect: -> @@ -24,3 +26,12 @@ App.IndexRoute = Ember.Route.extend App.EmberTableIndexRoute = Ember.Route.extend redirect: -> @transitionTo 'emberTable.overview' + +App.EmberTableOverviewRoute = Ember.Route.extend + activate: -> + controller = @controllerFor('emberTable') + controller.set 'showLargeHero', yes + + deactivate: -> + controller = @controllerFor('emberTable') + controller.set 'showLargeHero', no diff --git a/app/templates/_footer.hbs b/app/templates/_footer.hbs index 9a68e163a..c938d54d7 100644 --- a/app/templates/_footer.hbs +++ b/app/templates/_footer.hbs @@ -2,13 +2,18 @@ @@ -163,7 +160,6 @@ App.FinancialTableHeaderTreeCell = Ember.Table.HeaderCell.extend # custom properties sortAscending: no sortColumn: null - selection: null actions: toggleTableCollapse: (event) -> diff --git a/app/templates/ember_table/migration-guides.hbs b/app/templates/ember_table/migration-guides.hbs new file mode 100644 index 000000000..68296a0a1 --- /dev/null +++ b/app/templates/ember_table/migration-guides.hbs @@ -0,0 +1,47 @@ +{{!-- To add shadow main-content-container-shadow --}} +
+

Migration Guides

+
+
+

Migrating from old versions to version 0.1.0

+

Version 0.1.0 of Ember Table is a bit of a restructure - we’re hoping that the new organization will make it simpler and easier to set up, but for existing users, you’ll have to make a few changes to upgrade to the new Ember Table. This guide is intended to walk you through that process.

+ +
    +
  1. Upgrade ember-table.js and ember-table.css. If you’re not on the latest version of Ember.js, now might be a good time to upgrade that as well. This guide was written using Ember 1.0.0 and Ember Table 0.1.0. You can grab Ember 1.0.0 here.
  2. +
  3. The major change is moving from separate table Views and Controllers to a unified table Component. You can read up on Ember Components here. So instead of having lines like this:

    +
    +
    App.MyTableController = Ember.Table.TableController.extend (...)
    +App.MyTableView = EmberTable.TableContainerView.extend (...)
    +
    + + You’ll have everything in one place: +
    +
    App.MyTableController = Ember.Controller.extend (...)
    +
    + + For starters, just change the type of your MyTableController from the old version to the new. +
  4. +
  5. Update your handlebars file. Before, it might have looked like:
    +
    +
    {{view Ember.Table.TablesContainer …}}
    +
    + After the restructure, it should look like this:
    +
    +
    {{table-component …}}
    +
    +
  6. +
  7. While you’re modifying that handlebars file, you may want to make sure it looks like the structure of the new Ember Table examples. You can see one {{#link-to 'emberTable.simple'}}here{{/link-to}}. In particular, you might get errors if you don’t properly bind your columns and content of the table, using “columnsBinding=” and “contentBinding=”.

    + Both of these settings refer to variables in the corresponding controller (which here should be MyTableController), such that if you set “columnsBinding=exampleVariable”, then the columns will be bound to “exampleVariable” in the controller. This gives you control over the look and content of the table.

    + Before, you may have had “controllerBinding=” here. You don’t need this any more: the controller being used with this template will be used for the table too, by default.
  8. +
  9. Move any properties you had defined in your TableContainerView (if you had one) into the controller. See the examples for more information on how table properties should be set now.
  10. +
+
+
+

Troubleshooting

+
    +
  • If you were using old Ember Table objects like the RowArrayProxy, take another look and consider whether you really need it. During my migration I was able to remove it by changing the “contentBinding=” in my handlebars file to a more appropriate variable for content.
  • +
  • If you are having errors with template names not being found, it may be due to a change with inferring names. For me, my old template names used hyphens, and changing them to underscores automatically connected them to the rest of my application.
  • +
+
+
+
diff --git a/app/templates/ember_table/overview.hbs b/app/templates/ember_table/overview.hbs index fdf7d5937..d57c50843 100644 --- a/app/templates/ember_table/overview.hbs +++ b/app/templates/ember_table/overview.hbs @@ -13,9 +13,6 @@ {{view App.FinancialTableComponent dataBinding="data"}} -
-

Ember-Table with financial theme. Table with half a million rows. Read more →

-
@@ -25,20 +22,20 @@

Dependencies

@@ -52,58 +49,59 @@ {{#link-to 'emberTable.simple'}}

Hello World Table

- +
{{/link-to}} {{#link-to 'emberTable.ajax'}}

AJAX cells

- +
{{/link-to}} {{#link-to 'emberTable.bars'}}

Bar cells

- +
{{/link-to}} {{#link-to 'emberTable.dynamic-bars'}}

Dynamic bar cells

- +
{{/link-to}} {{#link-to 'emberTable.financial'}}

Tree & financial table

- +
{{/link-to}} {{#link-to 'emberTable.editable'}}

Editable cell

- +
{{/link-to}} {{#link-to 'emberTable.sparkline'}}

Sparkline cell using D3.js

- +
{{/link-to}} {{#link-to 'emberTable.horizon'}}

Horizon cell using D3.js

- +
{{/link-to}} {{#link-to 'emberTable.fluid'}}

Fluid table

- +
{{/link-to}} +

Looking for more ways to extend ember-table? Check out the {{#link-to 'emberTable.community-examples'}}Community Examples{{/link-to}}.

@@ -112,35 +110,33 @@

Getting Started

You will need node installed as a development dependency.

-

Clone it from Github or download the ZIP repo

+

Clone it from Github or download the ZIP repo

$ npm install -g grunt-cli
 $ npm install
 $ grunt
 $ node examples.js
-

Go to your browser and navigate to localhost:8000/gh_pages

+

Go to your browser and navigate to localhost:8000/gh_pages


-

Changelog

+

Contributing

+

You can contribute to this project in one of two ways:

    -
  • v0.1 - October 21, 2013. Branch: master →
  • -
  • v0.0.1 - December 20, 2012. Branch: version-0.1 →
  • +
  • Browse the ember-table issues and report bugs
  • +
  • Clone the ember-table repo, make some changes according to our development guidelines and issue a pull-request with your changes.
+

We keep the ember-table.js code to the minimum necessary, giving users as much control as possible.


-

Contributing

-

You can contribute to this project in one of two ways: -

    -
  • Browse the ember-table issues and report bugs
  • -
  • Clone the ember-table repo, make some changes according to our development guidelines and issue a pull-request with your changes.
  • -
-

We keep the ember-table.js code to the minimum necessary, giving users as much control as possible.

+

Changelog

+

The current version is 0.2.2. +

For the full list of changes, please see CHANGELOG.md.


diff --git a/app/views/mixins.coffee b/app/views/mixins.coffee index ae37b241e..c04345086 100644 --- a/app/views/mixins.coffee +++ b/app/views/mixins.coffee @@ -6,7 +6,9 @@ App.CodePrettyPrintMixin = Ember.Mixin.create App.LargeHeroAffixMixin = Ember.Mixin.create didInsertElement: -> @_super() - $('.sub-navigation-sidebar').affix offset: top: 500 + $('.sub-navigation-sidebar').affix offset: + top: 500 + bottom: 450 # in case affix is already initialized and won't let us update options # we don't care, and just set it anyways $('.sub-navigation-sidebar').data('bs.affix').options.offset.top = 500 @@ -14,7 +16,9 @@ App.LargeHeroAffixMixin = Ember.Mixin.create App.SmallHeroAffixMixin = Ember.Mixin.create didInsertElement: -> @_super() - $('.sub-navigation-sidebar').affix offset: top: 150 + $('.sub-navigation-sidebar').affix offset: + top: 150 + bottom: 450 # in case affix is already initialized and won't let us update options # we don't care, and just set it anyways $('.sub-navigation-sidebar').data('bs.affix').options.offset.top = 150 diff --git a/bower.json b/bower.json index c5cd1db29..817df40a4 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "ember-table", - "version": "0.2.0", + "version": "0.2.2", "description": "Table built using ember.js that lazily renders rows.", "keywords": [ "ember", @@ -26,12 +26,12 @@ "package.json" ], "dependencies": { - "antiscroll": "fa3f81d3c07b647a63036da1de859fcaf1355993", + "antiscroll": "daviesgeek/antiscroll#9b67eb3c01b530ab86484e6874e743518fa65579", "bootstrap": "3.0.0", "ember": "1.4.0", - "handlebars": "1.3.0", + "handlebars": "~1.3.0", "jquery": "1.10.2", - "jquery-mousewheel": "3.1.4", + "jquery-mousewheel": "~3.1.4", "jquery-ui": "1.10.1" }, "devDependencies": { @@ -48,4 +48,4 @@ ] } } -} \ No newline at end of file +} diff --git a/dependencies/ember-addepar-mixins/style_bindings.js b/dependencies/ember-addepar-mixins/style_bindings.js index c8113d33a..b372eaa3e 100644 --- a/dependencies/ember-addepar-mixins/style_bindings.js +++ b/dependencies/ember-addepar-mixins/style_bindings.js @@ -7,13 +7,13 @@ Ember.AddeparMixins.StyleBindingsMixin = Ember.Mixin.create({ createStyleString: function(styleName, property) { var value; value = this.get(property); - if (value === void 0) { + if (Ember.isNone(value)) { return; } if (Ember.typeOf(value) === 'number') { value = value + this.get('unitType'); } - return "" + styleName + ":" + value + ";"; + return Ember.String.dasherize("" + styleName) + ":" + value + ";"; }, applyStyleBindings: function() { var lookup, properties, styleBindings, styleComputed, styles, diff --git a/dist/ember-table.css b/dist/ember-table.css index ae1ce8bfe..5fedf42fe 100644 --- a/dist/ember-table.css +++ b/dist/ember-table.css @@ -1,5 +1,5 @@ /*! -* ember-table v0.2.0 +* ember-table v0.2.2 * Copyright 2012-2014 Addepar Inc. * See LICENSE. */ diff --git a/dist/ember-table.js b/dist/ember-table.js index ac7042b4b..1ae46891c 100644 --- a/dist/ember-table.js +++ b/dist/ember-table.js @@ -1,5 +1,5 @@ /*! -* ember-table v0.2.0 +* ember-table v0.2.2 * Copyright 2012-2014 Addepar Inc. * See LICENSE. */ @@ -14,10 +14,12 @@ var _ref; Ember.TEMPLATES["body-container"] = Ember.Handlebars.template(function anonymous(Handlebars,depth0,helpers,partials,data) { this.compilerInfo = [4,'>= 1.0.0']; helpers = this.merge(helpers, Ember.Handlebars.helpers); data = data || {}; - var buffer = '', escapeExpression=this.escapeExpression; - + var buffer = '', stack1, escapeExpression=this.escapeExpression, self=this; - data.buffer.push("
\n
\n
\n "); +function program1(depth0,data) { + + var buffer = ''; + data.buffer.push("\n "); data.buffer.push(escapeExpression(helpers.view.call(depth0, "Ember.Table.LazyTableBlock", {hash:{ 'classNames': ("ember-table-left-table-block"), 'contentBinding': ("controller.bodyContent"), @@ -28,6 +30,13 @@ helpers = this.merge(helpers, Ember.Handlebars.helpers); data = data || {}; 'startIndexBinding': ("controller._startIndex") },hashTypes:{'classNames': "STRING",'contentBinding': "STRING",'columnsBinding': "STRING",'widthBinding': "STRING",'numItemsShowingBinding': "STRING",'scrollTopBinding': "STRING",'startIndexBinding': "STRING"},hashContexts:{'classNames': depth0,'contentBinding': depth0,'columnsBinding': depth0,'widthBinding': depth0,'numItemsShowingBinding': depth0,'scrollTopBinding': depth0,'startIndexBinding': depth0},contexts:[depth0],types:["ID"],data:data}))); data.buffer.push("\n "); + return buffer; + } + + data.buffer.push("
\n
\n
\n "); + stack1 = helpers['if'].call(depth0, "controller.numFixedColumns", {hash:{},hashTypes:{},hashContexts:{},inverse:self.noop,fn:self.program(1, program1, data),contexts:[depth0],types:["ID"],data:data}); + if(stack1 || stack1 === 0) { data.buffer.push(stack1); } + data.buffer.push("\n "); data.buffer.push(escapeExpression(helpers.view.call(depth0, "Ember.Table.LazyTableBlock", {hash:{ 'classNames': ("ember-table-right-table-block"), 'contentBinding': ("controller.bodyContent"), @@ -85,10 +94,12 @@ function program3(depth0,data) { Ember.TEMPLATES["footer-container"] = Ember.Handlebars.template(function anonymous(Handlebars,depth0,helpers,partials,data) { this.compilerInfo = [4,'>= 1.0.0']; helpers = this.merge(helpers, Ember.Handlebars.helpers); data = data || {}; - var buffer = '', escapeExpression=this.escapeExpression; - + var buffer = '', stack1, escapeExpression=this.escapeExpression, self=this; - data.buffer.push("
\n "); +function program1(depth0,data) { + + var buffer = ''; + data.buffer.push("\n "); data.buffer.push(escapeExpression(helpers.view.call(depth0, "Ember.Table.TableBlock", {hash:{ 'classNames': ("ember-table-left-table-block"), 'contentBinding': ("controller.footerContent"), @@ -97,6 +108,13 @@ helpers = this.merge(helpers, Ember.Handlebars.helpers); data = data || {}; 'heightBinding': ("controller.footerHeight") },hashTypes:{'classNames': "STRING",'contentBinding': "STRING",'columnsBinding': "STRING",'widthBinding': "STRING",'heightBinding': "STRING"},hashContexts:{'classNames': depth0,'contentBinding': depth0,'columnsBinding': depth0,'widthBinding': depth0,'heightBinding': depth0},contexts:[depth0],types:["ID"],data:data}))); data.buffer.push("\n "); + return buffer; + } + + data.buffer.push("
\n "); + stack1 = helpers['if'].call(depth0, "controller.numFixedColumns", {hash:{},hashTypes:{},hashContexts:{},inverse:self.noop,fn:self.program(1, program1, data),contexts:[depth0],types:["ID"],data:data}); + if(stack1 || stack1 === 0) { data.buffer.push(stack1); } + data.buffer.push("\n "); data.buffer.push(escapeExpression(helpers.view.call(depth0, "Ember.Table.TableBlock", {hash:{ 'classNames': ("ember-table-right-table-block"), 'contentBinding': ("controller.footerContent"), @@ -117,7 +135,7 @@ helpers = this.merge(helpers, Ember.Handlebars.helpers); data = data || {}; data.buffer.push("
\n \n "); stack1 = helpers._triageMustache.call(depth0, "view.content.headerCellName", {hash:{},hashTypes:{},hashContexts:{},contexts:[depth0],types:["ID"],data:data}); if(stack1 || stack1 === 0) { data.buffer.push(stack1); } @@ -129,10 +147,12 @@ helpers = this.merge(helpers, Ember.Handlebars.helpers); data = data || {}; Ember.TEMPLATES["header-container"] = Ember.Handlebars.template(function anonymous(Handlebars,depth0,helpers,partials,data) { this.compilerInfo = [4,'>= 1.0.0']; helpers = this.merge(helpers, Ember.Handlebars.helpers); data = data || {}; - var buffer = '', escapeExpression=this.escapeExpression; - + var buffer = '', stack1, escapeExpression=this.escapeExpression, self=this; - data.buffer.push("
\n "); +function program1(depth0,data) { + + var buffer = ''; + data.buffer.push("\n "); data.buffer.push(escapeExpression(helpers.view.call(depth0, "Ember.Table.HeaderBlock", {hash:{ 'classNames': ("ember-table-left-table-block"), 'columnsBinding': ("controller.fixedColumns"), @@ -140,6 +160,13 @@ helpers = this.merge(helpers, Ember.Handlebars.helpers); data = data || {}; 'heightBinding': ("controller.headerHeight") },hashTypes:{'classNames': "STRING",'columnsBinding': "STRING",'widthBinding': "STRING",'heightBinding': "STRING"},hashContexts:{'classNames': depth0,'columnsBinding': depth0,'widthBinding': depth0,'heightBinding': depth0},contexts:[depth0],types:["ID"],data:data}))); data.buffer.push("\n "); + return buffer; + } + + data.buffer.push("
\n "); + stack1 = helpers['if'].call(depth0, "controller.numFixedColumns", {hash:{},hashTypes:{},hashContexts:{},inverse:self.noop,fn:self.program(1, program1, data),contexts:[depth0],types:["ID"],data:data}); + if(stack1 || stack1 === 0) { data.buffer.push(stack1); } + data.buffer.push("\n "); data.buffer.push(escapeExpression(helpers.view.call(depth0, "Ember.Table.HeaderBlock", {hash:{ 'classNames': ("ember-table-right-table-block"), 'columnsBinding': ("controller.tableColumns"), @@ -217,7 +244,7 @@ helpers = this.merge(helpers, Ember.Handlebars.helpers); data = data || {}; Ember.Table = Ember.Namespace.create(); -Ember.Table.VERSION = '0.2.0'; +Ember.Table.VERSION = '0.2.2'; if ((_ref = Ember.libraries) != null) { _ref.register('Ember Table', Ember.Table.VERSION); @@ -290,13 +317,13 @@ Ember.AddeparMixins.StyleBindingsMixin = Ember.Mixin.create({ createStyleString: function(styleName, property) { var value; value = this.get(property); - if (value === void 0) { + if (Ember.isNone(value)) { return; } if (Ember.typeOf(value) === 'number') { value = value + this.get('unitType'); } - return "" + styleName + ":" + value + ";"; + return Ember.String.dasherize("" + styleName) + ":" + value + ";"; }, applyStyleBindings: function() { var lookup, properties, styleBindings, styleComputed, styles, @@ -402,7 +429,14 @@ Ember.LazyContainerView = Ember.ContainerView.extend(Ember.AddeparMixins.StyleBi onNumChildViewsDidChange: Ember.observer(function() { var itemViewClass, newNumViews, numViewsToInsert, oldNumViews, view, viewsToAdd, viewsToRemove, _i, _results; view = this; - itemViewClass = Ember.get(this.get('itemViewClass')); + itemViewClass = this.get('itemViewClass'); + if (typeof itemViewClass === 'string') { + if (/[A-Z]+/.exec(itemViewClass)) { + itemViewClass = Ember.get(Ember.lookup, itemViewClass); + } else { + itemViewClass = this.container.lookupFactory("view:" + itemViewClass); + } + } newNumViews = this.get('numChildViews'); if (!(itemViewClass && newNumViews)) { return; @@ -496,7 +530,11 @@ Ember.MultiItemViewCollectionView = Ember.CollectionView.extend(Ember.AddeparMix itemViewClassField = this.get('itemViewClassField'); itemViewClass = attrs.content.get(itemViewClassField); if (typeof itemViewClass === 'string') { - itemViewClass = Ember.get(Ember.lookup, itemViewClass); + if (/[A-Z]+/.exec(itemViewClass)) { + itemViewClass = Ember.get(Ember.lookup, itemViewClass); + } else { + itemViewClass = this.container.lookupFactory("view:" + itemViewClass); + } } return this._super(itemViewClass, attrs); } @@ -620,11 +658,6 @@ Ember.Table.ShowHorizontalScrollMixin = Ember.Mixin.create({ })(); (function() { -/** - * Column Definition - * @class - * @alias Ember.Table.ColumnDefinition -*/ Ember.Table.ColumnDefinition = Ember.Object.extend({ headerCellName: void 0, @@ -632,80 +665,41 @@ Ember.Table.ColumnDefinition = Ember.Object.extend({ minWidth: void 0, maxWidth: void 0, defaultColumnWidth: 150, - columnWidth: Ember.computed.oneWay('defaultColumnWidth'), isResizable: true, isSortable: true, textAlign: 'text-align-right', canAutoResize: true, - headerCellViewClass: 'Ember.Table.HeaderCell', - tableCellViewClass: 'Ember.Table.TableCell', - resize: function(width) { - return this.set('columnWidth', width); - }, - /** - * Get Cell Content - This gives a formatted value e.g. $20,000,000 - * @memberof Ember.Table.ColumnDefinition - * @instance - * @argument row {Ember.Table.Row} - * @todo More detailed doc needed! - */ - + headerCellView: 'Ember.Table.HeaderCell', + headerCellViewClass: Ember.computed.alias('headerCellView'), + tableCellView: 'Ember.Table.TableCell', + tableCellViewClass: Ember.computed.alias('tableCellView'), getCellContent: function(row) { var path; path = this.get('contentPath'); Ember.assert("You must either provide a contentPath or override " + "getCellContent in your column definition", path != null); return Ember.get(row, path); }, - /** - * Set Cell Content - * @memberof Ember.Table.ColumnDefinition - * @instance - */ - - setCellContent: Ember.K + setCellContent: Ember.K, + columnWidth: Ember.computed.oneWay('defaultColumnWidth'), + resize: function(width) { + return this.set('columnWidth', width); + } }); -/** - * Table Row - * @class - * @alias Ember.Table.Row -*/ + +})(); +(function() { Ember.Table.Row = Ember.ObjectProxy.extend({ - /** - * Content of the row - * @memberof Ember.Table.Row - * @member content - * @instance - */ - content: null, - /** - * Is Selected? - * @memberof Ember.Table.Row - * @member {Boolean} isSelected - * @instance - */ - - isSelected: Ember.computed(function() { - return this.get('parentController.selection') === this.get('content'); - }).property('parentController.selection', 'content'), - /** - * Is Showing? - * @memberof Ember.Table.Row - * @member {Boolean} isShowing - * @instance - */ - + isSelected: Ember.computed(function(key, val) { + if (arguments.length > 1) { + this.get('parentController').setSelected(this, val); + } + return this.get('parentController').isSelected(this); + }).property('parentController._selection.[]'), isShowing: true, - /** - * Is Active? - * @memberof Ember.Table.Row - * @member {Boolean} isHovered - * @instance - */ - isHovered: false }); @@ -713,27 +707,12 @@ Ember.Table.Row = Ember.ObjectProxy.extend({ })(); (function() { -/** -* Table Container -* @class -* @alias Ember.Table.TableContainer -* @mixes Ember.AddeparMixins.StyleBindingsMixin -*/ Ember.Table.TableContainer = Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixin, { classNames: ['ember-table-table-container'], styleBindings: ['height', 'width'] }); -/** -* Table Block -* @class -* @alias Ember.Table.TableBlock -* @mixes Ember.AddeparMixins.StyleBindingsMixin -* @todo This should be a mixin -*/ - - Ember.Table.TableBlock = Ember.CollectionView.extend(Ember.AddeparMixins.StyleBindingsMixin, { classNames: ['ember-table-table-block'], styleBindings: ['width', 'height'], @@ -741,12 +720,6 @@ Ember.Table.TableBlock = Ember.CollectionView.extend(Ember.AddeparMixins.StyleBi columns: null, content: null, scrollLeft: null, - /** - * On scroll left did change callback - * @memberof Ember.Table.TableBlock - * @instance - */ - onScrollLeftDidChange: Ember.observer(function() { return this.$().scrollLeft(this.get('scrollLeft')); }, 'scrollLeft'), @@ -755,13 +728,6 @@ Ember.Table.TableBlock = Ember.CollectionView.extend(Ember.AddeparMixins.StyleBi }).property('controller._headerHeight') }); -/** -* Lazy Table Block -* @class -* @alias Ember.Table.LazyTableBlock -*/ - - Ember.Table.LazyTableBlock = Ember.LazyContainerView.extend({ classNames: ['ember-table-table-block'], styleBindings: ['width'], @@ -771,24 +737,11 @@ Ember.Table.LazyTableBlock = Ember.LazyContainerView.extend({ content: null, scrollLeft: null, scrollTop: null, - /** - * On scroll left did change callback - * @memberof Ember.Table.LazyTableBlock - * @instance - */ - onScrollLeftDidChange: Ember.observer(function() { return this.$().scrollLeft(this.get('scrollLeft')); }, 'scrollLeft') }); -/** -* Table Row -* @class -* @alias Ember.Table.TableRow -*/ - - Ember.Table.TableRow = Ember.LazyItemView.extend({ templateName: 'table-row', classNames: 'ember-table-table-row', @@ -801,13 +754,6 @@ Ember.Table.TableRow = Ember.LazyItemView.extend({ isLastRow: Ember.computed(function() { return this.get('row') === this.get('controller.bodyContent.lastObject'); }).property('controller.bodyContent.lastObject', 'row'), - /** - * Mouse enter callback - * @memberof Ember.Table.TableRow - * @instance - * @param event jQuery event - */ - mouseEnter: function(event) { var row; row = this.get('row'); @@ -815,13 +761,6 @@ Ember.Table.TableRow = Ember.LazyItemView.extend({ return row.set('isHovered', true); } }, - /** - * Mouse leave callback - * @memberof Ember.Table.TableRow - * @instance - * @param event jQuery event - */ - mouseLeave: function(event) { var row; row = this.get('row'); @@ -829,12 +768,6 @@ Ember.Table.TableRow = Ember.LazyItemView.extend({ return row.set('isHovered', false); } }, - /** - * Teardown content - * @memberof Ember.Table.TableRow - * @instance - */ - teardownContent: function() { var row; row = this.get('row'); @@ -844,27 +777,19 @@ Ember.Table.TableRow = Ember.LazyItemView.extend({ } }); -/** -* Table Cell -* @class -* @alias Ember.Table.TableCell -* @mixes Ember.AddeparMixins.StyleBindingsMixin -*/ - - Ember.Table.TableCell = Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixin, { templateName: 'table-cell', classNames: ['ember-table-cell'], classNameBindings: 'column.textAlign', styleBindings: 'width', - row: Ember.computed.alias('parentView.row'), - column: Ember.computed.alias('content'), - width: Ember.computed.alias('column.columnWidth'), init: function() { this._super(); this.contentPathDidChange(); return this.contentDidChange(); }, + row: Ember.computed.alias('parentView.row'), + column: Ember.computed.alias('content'), + width: Ember.computed.alias('column.columnWidth'), contentDidChange: function() { return this.notifyPropertyChange('cellContent'); }, @@ -882,12 +807,6 @@ Ember.Table.TableCell = Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixin return this.addObserver("row." + contentPath, this, this.contentDidChange); } }).observesBefore('column.contentPath'), - /** - * Computed Cell Content - * @memberof Ember.Table.TableCell - * @instance - */ - cellContent: Ember.computed(function(key, value) { var column, row; row = this.get('row'); @@ -904,36 +823,14 @@ Ember.Table.TableCell = Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixin }).property('row.isLoaded', 'column') }); -/** -* HeaderBlock -* @class -* @alias Ember.Table.HeaderBlock -* @augments Ember.Table.TableBlock -*/ - - Ember.Table.HeaderBlock = Ember.Table.TableBlock.extend({ classNames: ['ember-table-header-block'], itemViewClass: 'Ember.Table.HeaderRow', - /** - * Computed Content - * @memberof Ember.Table.HeaderBlock - * @instance - */ - content: Ember.computed(function() { return [this.get('columns')]; }).property('columns') }); -/** -* Header Row -* @class -* @alias Ember.Table.HeaderRow -* @mixes Ember.AddeparMixins.StyleBindingsMixin -*/ - - Ember.Table.HeaderRow = Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixin, { templateName: 'header-row', classNames: ['ember-table-table-row', 'ember-table-header-row'], @@ -941,12 +838,6 @@ Ember.Table.HeaderRow = Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixin columns: Ember.computed.alias('content'), width: Ember.computed.alias('controller._rowWidth'), scrollLeft: Ember.computed.alias('controller._tableScrollLeft'), - /** - * Options for jQuery UI sortable - * @memberof Ember.Table.HeaderRow - * @instance - */ - sortableOption: Ember.computed(function() { return { axis: 'x', @@ -995,14 +886,6 @@ Ember.Table.HeaderRow = Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixin } }); -/** -* Header Cell -* @class -* @alias Ember.Table.HeaderCell -* @mixes Ember.AddeparMixins.StyleBindingsMixin -*/ - - Ember.Table.HeaderCell = Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixin, { templateName: 'header-cell', classNames: ['ember-table-cell', 'ember-table-header-cell'], @@ -1013,12 +896,6 @@ Ember.Table.HeaderCell = Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixi height: Ember.computed(function() { return this.get('controller._headerHeight'); }).property('controller._headerHeight'), - /** - * jQuery UI resizable option - * @memberof Ember.Table.HeaderCell - * @instance - */ - resizableOption: Ember.computed(function() { return { handles: 'e', @@ -1030,12 +907,6 @@ Ember.Table.HeaderCell = Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixi stop: jQuery.proxy(this.onColumnResize, this) }; }), - /** - * Did insert element callback - * @memberof Ember.Table.HeaderCell - * @instance - */ - didInsertElement: function() { this.elementSizeDidChange(); if (this.get('column.isResizable')) { @@ -1043,13 +914,6 @@ Ember.Table.HeaderCell = Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixi this._resizableWidget = this.$().resizable('widget'); } }, - /** - * On column resize callback - * @memberof Ember.Table.HeaderCell - * @instance - * @argument event jQuery event - */ - onColumnResize: function(event, ui) { this.elementSizeDidChange(); if (this.get('controller.forceFillColumns') && this.get('controller.columns').filterProperty('canAutoResize').length > 1) { @@ -1079,16 +943,6 @@ Ember.Table.ColumnSortableIndicator = Ember.View.extend(Ember.AddeparMixins.Styl height: Ember.computed.alias('controller._height') }); -/** -* Header Table Container -* @class -* @alias Ember.Table.HeaderTableContainer -* @augments Ember.Table.TableContainer -* @mixes Ember.MouseWheelHandlerMixin -* @mixes Ember.TouchMoveHandlerMixin -*/ - - Ember.Table.HeaderTableContainer = Ember.Table.TableContainer.extend(Ember.Table.ShowHorizontalScrollMixin, { templateName: 'header-container', classNames: ['ember-table-table-container', 'ember-table-fixed-table-container', 'ember-table-header-container'], @@ -1096,16 +950,6 @@ Ember.Table.HeaderTableContainer = Ember.Table.TableContainer.extend(Ember.Table width: Ember.computed.alias('controller._tableContainerWidth') }); -/** -* Body Table Container -* @class -* @alias Ember.Table.BodyTableContainer -* @mixes Ember.MouseWheelHandlerMixin -* @mixes Ember.TouchMoveHandlerMixin -* @mixes Ember.ScrollHandlerMixin -*/ - - Ember.Table.BodyTableContainer = Ember.Table.TableContainer.extend(Ember.MouseWheelHandlerMixin, Ember.TouchMoveHandlerMixin, Ember.ScrollHandlerMixin, Ember.Table.ShowHorizontalScrollMixin, { templateName: 'body-container', classNames: ['ember-table-table-container', 'ember-table-body-container', 'antiscroll-wrap'], @@ -1114,27 +958,10 @@ Ember.Table.BodyTableContainer = Ember.Table.TableContainer.extend(Ember.MouseWh scrollTop: Ember.computed.alias('controller._tableScrollTop'), scrollLeft: Ember.computed.alias('controller._tableScrollLeft'), scrollElementSelector: '.antiscroll-inner', - /** - * On scroll callback - * @memberof Ember.Table.BodyTableContainer - * @instance - * @argument event jQuery event - */ - onScroll: function(event) { this.set('scrollTop', event.target.scrollTop); return event.preventDefault(); }, - /** - * On mouse wheel callback callback - * @memberof Ember.Table.BodyTableContainer - * @instance - * @argument event jQuery event - * @argument delta - * @argument deltaX {Integer} - * @argument deltaY {Integer} - */ - onMouseWheel: function(event, delta, deltaX, deltaY) { var scrollLeft; if (!(Math.abs(deltaX) > Math.abs(deltaY))) { @@ -1144,15 +971,6 @@ Ember.Table.BodyTableContainer = Ember.Table.TableContainer.extend(Ember.MouseWh this.set('scrollLeft', scrollLeft); return event.preventDefault(); }, - /** - * On touch move callback - * @memberof Ember.Table.BodyTableContainer - * @instance - * @argument event jQuery event - * @argument deltaX {Integer} - * @argument deltaY {Integer} - */ - onTouchMove: function(event, deltaX, deltaY) { var scrollLeft; if (!(Math.abs(deltaX) > Math.abs(deltaY))) { @@ -1164,15 +982,6 @@ Ember.Table.BodyTableContainer = Ember.Table.TableContainer.extend(Ember.MouseWh } }); -/** -* Footer Table Container -* @class -* @alias Ember.Table.FooterTableContainer -* @mixes Ember.MouseWheelHandlerMixin -* @mixes Ember.TouchMoveHandlerMixin -*/ - - Ember.Table.FooterTableContainer = Ember.Table.TableContainer.extend(Ember.MouseWheelHandlerMixin, Ember.TouchMoveHandlerMixin, Ember.Table.ShowHorizontalScrollMixin, { templateName: 'footer-container', classNames: ['ember-table-table-container', 'ember-table-fixed-table-container', 'ember-table-footer-container'], @@ -1205,15 +1014,6 @@ Ember.Table.FooterTableContainer = Ember.Table.TableContainer.extend(Ember.Mouse } }); -/** -* Scroll Container -* @class -* @alias Ember.Table.ScrollContainer -* @mixes Ember.AddeparMixins.StyleBindingsMixin -* @mixes Ember.ScrollHandlerMixin -*/ - - Ember.Table.ScrollContainer = Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixin, Ember.ScrollHandlerMixin, { templateName: 'scroll-container', classNames: ['ember-table-scroll-container'], @@ -1228,23 +1028,10 @@ Ember.Table.ScrollContainer = Ember.View.extend(Ember.AddeparMixins.StyleBinding this._super(); return this.onScrollLeftDidChange(); }, - /** - * On scroll callback - * @memberof Ember.Table.ScrollContainer - * @instance - * @argument event jQuery event - */ - onScroll: function(event) { this.set('scrollLeft', event.target.scrollLeft); return event.preventDefault(); }, - /** - * On scroll left did change observer - * @memberof Ember.Table.ScrollContainer - * @instance - */ - onScrollLeftDidChange: Ember.observer(function() { var selector; selector = this.get('scrollElementSelector'); @@ -1252,14 +1039,6 @@ Ember.Table.ScrollContainer = Ember.View.extend(Ember.AddeparMixins.StyleBinding }, 'scrollLeft', 'scrollElementSelector') }); -/** -* ScrollPanel -* @class -* @alias Ember.Table.ScrollPanel -* @mixes Ember.AddeparMixins.StyleBindingsMixin -*/ - - Ember.Table.ScrollPanel = Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixin, { classNames: ['ember-table-scroll-panel'], styleBindings: ['width', 'height'], @@ -1271,18 +1050,13 @@ Ember.Table.ScrollPanel = Ember.View.extend(Ember.AddeparMixins.StyleBindingsMix })(); (function() { -/** -* Table Component -* @class -* @alias Ember.Table.EmberTableComponent -*/ Ember.Table.EmberTableComponent = Ember.Component.extend(Ember.AddeparMixins.StyleBindingsMixin, Ember.AddeparMixins.ResizeHandlerMixin, { layoutName: 'components/ember-table', classNames: ['ember-table-tables-container'], classNameBindings: ['enableContentSelection:ember-table-content-selectable'], styleBindings: ['height'], - height: Ember.computed.alias('_tablesContainerHeight'), + content: null, columns: null, numFixedColumns: 0, numFooterRow: 0, @@ -1294,8 +1068,30 @@ Ember.Table.EmberTableComponent = Ember.Component.extend(Ember.AddeparMixins.Sty forceFillColumns: false, enableColumnReorder: true, enableContentSelection: false, - selection: null, - tableRowViewClass: 'Ember.Table.TableRow', + selectionMode: 'single', + selection: Ember.computed(function(key, val) { + var content, _i, _len, _ref, _ref1; + if (arguments.length > 1 && val) { + if (this.get('selectionMode') === 'single') { + this.get('persistedSelection').clear(); + this.get('persistedSelection').add(this.findRow(val)); + } else { + this.get('persistedSelection').clear(); + for (_i = 0, _len = val.length; _i < _len; _i++) { + content = val[_i]; + this.get('persistedSelection').add(this.findRow(content)); + } + } + this.get('rangeSelection').clear(); + } + if (this.get('selectionMode') === 'single') { + return (_ref = this.get('_selection')) != null ? (_ref1 = _ref[0]) != null ? _ref1.get('content') : void 0 : void 0; + } else { + return this.get('_selection').toArray().map(function(row) { + return row.get('content'); + }); + } + }).property('_selection.[]', 'selectionMode'), init: function() { this._super(); if (!$.ui) { @@ -1312,18 +1108,15 @@ Ember.Table.EmberTableComponent = Ember.Component.extend(Ember.AddeparMixins.Sty addColumn: Ember.K, sortByColumn: Ember.K }, + height: Ember.computed.alias('_tablesContainerHeight'), + tableRowView: 'Ember.Table.TableRow', + tableRowViewClass: Ember.computed.alias('tableRowView'), onColumnSort: function(column, newIndex) { var columns; columns = this.get('tableColumns'); columns.removeObject(column); return columns.insertAt(newIndex, column); }, - /** - * Table Body Content - Array of Ember.Table.Row - * @memberof Ember.Table.EmberTableComponent - * @instance - */ - bodyContent: Ember.computed(function() { return Ember.Table.RowArrayController.create({ target: this, @@ -1333,12 +1126,6 @@ Ember.Table.EmberTableComponent = Ember.Component.extend(Ember.AddeparMixins.Sty content: this.get('content') }); }).property('content'), - /** - * Table Footer Content - Array of Ember.Table.Row - * @memberof Ember.Table.EmberTableComponent - * @instance - */ - footerContent: Ember.computed(function(key, value) { if (value) { return value; @@ -1346,13 +1133,6 @@ Ember.Table.EmberTableComponent = Ember.Component.extend(Ember.AddeparMixins.Sty return Ember.A(); } }).property(), - /** - * Table Fixed Columns - * @memberof Ember.Table.EmberTableComponent - * @instance - * @todo Much more doc needed - */ - fixedColumns: Ember.computed(function() { var columns, numFixedColumns; columns = this.get('columns'); @@ -1364,13 +1144,6 @@ Ember.Table.EmberTableComponent = Ember.Component.extend(Ember.AddeparMixins.Sty this.prepareTableColumns(columns); return columns; }).property('columns.@each', 'numFixedColumns'), - /** - * Table Columns - * @memberof Ember.Table.EmberTableComponent - * @instance - * @todo Much more doc needed - */ - tableColumns: Ember.computed(function() { var columns, numFixedColumns; columns = this.get('columns'); @@ -1390,23 +1163,11 @@ Ember.Table.EmberTableComponent = Ember.Component.extend(Ember.AddeparMixins.Sty this.set('_tableScrollTop', 0); return this.elementSizeDidChange(); }, - /** - * On resize end callback - * @memberof Ember.Table.EmberTableComponent - * @instance - */ - onResizeEnd: function() { return Ember.run(this, this.elementSizeDidChange); }, - /** - * Element size did change callback - * @memberof Ember.Table.EmberTableComponent - * @instance - */ - elementSizeDidChange: function() { - if (this.get('state') !== 'inDOM') { + if ((this.get('_state') || this.get('state')) !== 'inDOM') { return; } this.set('_width', this.$().parent().outerWidth()); @@ -1414,7 +1175,7 @@ Ember.Table.EmberTableComponent = Ember.Component.extend(Ember.AddeparMixins.Sty return Ember.run.next(this, this.updateLayout); }, updateLayout: function() { - if (this.get('state') !== 'inDOM') { + if ((this.get('_state') || this.get('state')) !== 'inDOM') { return; } this.$('.antiscroll-wrap').antiscroll().data('antiscroll').rebuild(); @@ -1478,23 +1239,9 @@ Ember.Table.EmberTableComponent = Ember.Component.extend(Ember.AddeparMixins.Sty return height; } }).property('_height', '_tableContentHeight', '_headerHeight', '_footerHeight'), - /** - * Actual width of the fixed columns (frozen columns) - * @memberof Ember.Table.EmberTableComponent - * @instance - * @private - */ - _fixedColumnsWidth: Ember.computed(function() { return this._getTotalWidth(this.get('fixedColumns')); }).property('fixedColumns.@each.columnWidth'), - /** - * Actual width of the table columns (non-frozen columns) - * @memberof Ember.Table.EmberTableComponent - * @instance - * @private - */ - _tableColumnsWidth: Ember.computed(function() { var availableWidth, contentWidth; contentWidth = (this._getTotalWidth(this.get('tableColumns'))) + 3; @@ -1505,13 +1252,6 @@ Ember.Table.EmberTableComponent = Ember.Component.extend(Ember.AddeparMixins.Sty return availableWidth; } }).property('tableColumns.@each.columnWidth', '_width', '_fixedColumnsWidth'), - /** - * Computed Row Width - * @memberof Ember.Table.EmberTableComponent - * @instance - * @private - */ - _rowWidth: Ember.computed(function() { var columnsWidth, nonFixedTableWidth; columnsWidth = this.get('_tableColumnsWidth'); @@ -1538,13 +1278,6 @@ Ember.Table.EmberTableComponent = Ember.Component.extend(Ember.AddeparMixins.Sty return 0; } }).property('footerHeight', 'hasFooter'), - /** - * Computed Body Height - * @memberof Ember.Table.EmberTableComponent - * @instance - * @private - */ - _bodyHeight: Ember.computed(function() { var bodyHeight; bodyHeight = this.get('_tablesContainerHeight'); @@ -1556,64 +1289,22 @@ Ember.Table.EmberTableComponent = Ember.Component.extend(Ember.AddeparMixins.Sty } return bodyHeight; }).property('_tablesContainerHeight', '_hasHorizontalScrollbar', '_headerHeight', 'footerHeight', 'hasHeader', 'hasFooter'), - /** - * Computed Table Block Width - * @memberof Ember.Table.EmberTableComponent - * @instance - * @private - */ - _tableBlockWidth: Ember.computed(function() { return this.get('_width') - this.get('_fixedColumnsWidth'); }).property('_width', '_fixedColumnsWidth'), _fixedBlockWidthBinding: '_fixedColumnsWidth', - /** - * Computed Table Content Height - * @memberof Ember.Table.EmberTableComponent - * @instance - * @private - */ - _tableContentHeight: Ember.computed(function() { return this.get('rowHeight') * this.get('bodyContent.length'); }).property('rowHeight', 'bodyContent.length'), - /** - * Table Container Width - * @memberof Ember.Table.EmberTableComponent - * @instance - * @private - */ - _tableContainerWidth: Ember.computed(function() { return this.get('_width'); }).property('_width'), - /** - * Computed Scroll Container Width - * @memberof Ember.Table.EmberTableComponent - * @instance - * @private - */ - _scrollContainerWidth: Ember.computed(function() { return this.get('_width') - this.get('_fixedColumnsWidth'); }).property('_width', '_fixedColumnsWidth'), - /** - * Computed number of items showing - * @memberof Ember.Table.EmberTableComponent - * @instance - * @private - */ - _numItemsShowing: Ember.computed(function() { return Math.floor(this.get('_bodyHeight') / this.get('rowHeight')); }).property('_bodyHeight', 'rowHeight'), - /** - * Computed Start Index - * @memberof Ember.Table.EmberTableComponent - * @instance - * @raw - */ - _startIndex: Ember.computed(function() { var index, numContent, numViews, rowHeight, scrollTop; numContent = this.get('bodyContent.length'); @@ -1630,14 +1321,6 @@ Ember.Table.EmberTableComponent = Ember.Component.extend(Ember.AddeparMixins.Sty return index; } }).property('bodyContent.length', '_numItemsShowing', 'rowHeight', '_tableScrollTop'), - /** - * Get Total Width - * @memberof Ember.Table.EmberTableComponent - * @instance - * @private - * @argument columns Columns to calculate width for - */ - _getTotalWidth: function(columns, columnWidthPath) { var widths; if (columnWidthPath == null) { @@ -1651,13 +1334,79 @@ Ember.Table.EmberTableComponent = Ember.Component.extend(Ember.AddeparMixins.Sty return total + w; }), 0); }, + isSelected: function(row) { + return this.get('_selection').contains(row); + }, + setSelected: function(row, val) { + this.persistSelection(); + if (val) { + return this.get('persistedSelection').add(row); + } else { + return this.get('persistedSelection').remove(row); + } + }, + persistedSelection: Ember.computed(function() { + return new Ember.Set(); + }), + rangeSelection: Ember.computed(function() { + return new Ember.Set(); + }), + _selection: Ember.computed(function() { + return this.get('persistedSelection').copy().addEach(this.get('rangeSelection')); + }).property('persistedSelection.[]', 'rangeSelection.[]'), click: function(event) { - var row; + var curIndex, lastIndex, maxIndex, minIndex, row; row = this.getRowForEvent(event); if (!row) { return; } - return this.set('selection', row.get('content')); + if (this.get('selectionMode') === 'none') { + return; + } + if (this.get('selectionMode') === 'single') { + this.get('persistedSelection').clear(); + return this.get('persistedSelection').add(row); + } else { + if (event.shiftKey) { + this.get('rangeSelection').clear(); + lastIndex = this.rowIndex(this.get('lastSelected')); + curIndex = this.rowIndex(this.getRowForEvent(event)); + minIndex = Math.min(lastIndex, curIndex); + maxIndex = Math.max(lastIndex, curIndex); + return this.get('rangeSelection').addObjects(this.get('bodyContent').slice(minIndex, maxIndex + 1)); + } else { + if (!event.ctrlKey && !event.metaKey) { + this.get('persistedSelection').clear(); + this.get('rangeSelection').clear(); + } else { + this.persistSelection(); + } + if (this.get('persistedSelection').contains(row)) { + this.get('persistedSelection').remove(row); + } else { + this.get('persistedSelection').add(row); + } + return this.set('lastSelected', row); + } + } + }, + findRow: function(content) { + var row, _i, _len, _ref; + _ref = this.get('bodyContent'); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + row = _ref[_i]; + if (row.get('content') === content) { + return row; + } + } + }, + rowIndex: function(row) { + var _ref; + return (_ref = this.get('bodyContent')) != null ? _ref.indexOf(row) : void 0; + }, + persistSelection: function() { + this.get('persistedSelection').addEach(this.get('rangeSelection')); + return this.get('rangeSelection').clear(); }, getRowForEvent: function(event) { var $rowView, view; diff --git a/dist/ember-table.min.js b/dist/ember-table.min.js index 624ad48c5..6b0f04aed 100644 --- a/dist/ember-table.min.js +++ b/dist/ember-table.min.js @@ -1,7 +1,7 @@ /*! -* ember-table v0.2.0 +* ember-table v0.2.2 * Copyright 2012-2014 Addepar Inc. * See LICENSE. */ -!function(){Ember.TEMPLATES["body-container"]=Ember.Handlebars.template(function(a,b,c,d,e){this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,Ember.Handlebars.helpers),e=e||{};var f="",g=this.escapeExpression;return e.buffer.push('
\n
\n
\n '),e.buffer.push(g(c.view.call(b,"Ember.Table.LazyTableBlock",{hash:{classNames:"ember-table-left-table-block",contentBinding:"controller.bodyContent",columnsBinding:"controller.fixedColumns",widthBinding:"controller._fixedBlockWidth",numItemsShowingBinding:"controller._numItemsShowing",scrollTopBinding:"controller._scrollTop",startIndexBinding:"controller._startIndex"},hashTypes:{classNames:"STRING",contentBinding:"STRING",columnsBinding:"STRING",widthBinding:"STRING",numItemsShowingBinding:"STRING",scrollTopBinding:"STRING",startIndexBinding:"STRING"},hashContexts:{classNames:b,contentBinding:b,columnsBinding:b,widthBinding:b,numItemsShowingBinding:b,scrollTopBinding:b,startIndexBinding:b},contexts:[b],types:["ID"],data:e}))),e.buffer.push("\n "),e.buffer.push(g(c.view.call(b,"Ember.Table.LazyTableBlock",{hash:{classNames:"ember-table-right-table-block",contentBinding:"controller.bodyContent",columnsBinding:"controller.tableColumns",scrollLeftBinding:"controller._tableScrollLeft",widthBinding:"controller._tableBlockWidth",numItemsShowingBinding:"controller._numItemsShowing",scrollTopBinding:"controller._scrollTop",startIndexBinding:"controller._startIndex"},hashTypes:{classNames:"STRING",contentBinding:"STRING",columnsBinding:"STRING",scrollLeftBinding:"STRING",widthBinding:"STRING",numItemsShowingBinding:"STRING",scrollTopBinding:"STRING",startIndexBinding:"STRING"},hashContexts:{classNames:b,contentBinding:b,columnsBinding:b,scrollLeftBinding:b,widthBinding:b,numItemsShowingBinding:b,scrollTopBinding:b,startIndexBinding:b},contexts:[b],types:["ID"],data:e}))),e.buffer.push("\n
\n
\n
"),f}),Ember.TEMPLATES["components/ember-table"]=Ember.Handlebars.template(function(a,b,c,d,e){function f(a,b){var d="";return b.buffer.push("\n "),b.buffer.push(j(c.view.call(a,"Ember.Table.HeaderTableContainer",{hash:{},hashTypes:{},hashContexts:{},contexts:[a],types:["ID"],data:b}))),b.buffer.push("\n"),d}function g(a,b){var d="";return b.buffer.push("\n "),b.buffer.push(j(c.view.call(a,"Ember.Table.FooterTableContainer",{hash:{},hashTypes:{},hashContexts:{},contexts:[a],types:["ID"],data:b}))),b.buffer.push("\n"),d}this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,Ember.Handlebars.helpers),e=e||{};var h,i="",j=this.escapeExpression,k=this;return h=c["if"].call(b,"controller.hasHeader",{hash:{},hashTypes:{},hashContexts:{},inverse:k.noop,fn:k.program(1,f,e),contexts:[b],types:["ID"],data:e}),(h||0===h)&&e.buffer.push(h),e.buffer.push("\n"),e.buffer.push(j(c.view.call(b,"Ember.Table.BodyTableContainer",{hash:{},hashTypes:{},hashContexts:{},contexts:[b],types:["ID"],data:e}))),e.buffer.push("\n"),h=c["if"].call(b,"controller.hasFooter",{hash:{},hashTypes:{},hashContexts:{},inverse:k.noop,fn:k.program(3,g,e),contexts:[b],types:["ID"],data:e}),(h||0===h)&&e.buffer.push(h),e.buffer.push("\n"),e.buffer.push(j(c.view.call(b,"Ember.Table.ScrollContainer",{hash:{},hashTypes:{},hashContexts:{},contexts:[b],types:["ID"],data:e}))),e.buffer.push("\n"),e.buffer.push(j(c.view.call(b,"Ember.Table.ColumnSortableIndicator",{hash:{},hashTypes:{},hashContexts:{},contexts:[b],types:["ID"],data:e}))),e.buffer.push("\n"),i}),Ember.TEMPLATES["footer-container"]=Ember.Handlebars.template(function(a,b,c,d,e){this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,Ember.Handlebars.helpers),e=e||{};var f="",g=this.escapeExpression;return e.buffer.push('
\n '),e.buffer.push(g(c.view.call(b,"Ember.Table.TableBlock",{hash:{classNames:"ember-table-left-table-block",contentBinding:"controller.footerContent",columnsBinding:"controller.fixedColumns",widthBinding:"controller._fixedBlockWidth",heightBinding:"controller.footerHeight"},hashTypes:{classNames:"STRING",contentBinding:"STRING",columnsBinding:"STRING",widthBinding:"STRING",heightBinding:"STRING"},hashContexts:{classNames:b,contentBinding:b,columnsBinding:b,widthBinding:b,heightBinding:b},contexts:[b],types:["ID"],data:e}))),e.buffer.push("\n "),e.buffer.push(g(c.view.call(b,"Ember.Table.TableBlock",{hash:{classNames:"ember-table-right-table-block",contentBinding:"controller.footerContent",columnsBinding:"controller.tableColumns",scrollLeftBinding:"controller._tableScrollLeft",widthBinding:"controller._tableBlockWidth",heightBinding:"controller.footerHeight"},hashTypes:{classNames:"STRING",contentBinding:"STRING",columnsBinding:"STRING",scrollLeftBinding:"STRING",widthBinding:"STRING",heightBinding:"STRING"},hashContexts:{classNames:b,contentBinding:b,columnsBinding:b,scrollLeftBinding:b,widthBinding:b,heightBinding:b},contexts:[b],types:["ID"],data:e}))),e.buffer.push("\n
\n"),f}),Ember.TEMPLATES["header-cell"]=Ember.Handlebars.template(function(a,b,c,d,e){this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,Ember.Handlebars.helpers),e=e||{};var f,g="",h=this.escapeExpression;return e.buffer.push('
\n \n '),f=c._triageMustache.call(b,"view.content.headerCellName",{hash:{},hashTypes:{},hashContexts:{},contexts:[b],types:["ID"],data:e}),(f||0===f)&&e.buffer.push(f),e.buffer.push("\n \n
"),g}),Ember.TEMPLATES["header-container"]=Ember.Handlebars.template(function(a,b,c,d,e){this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,Ember.Handlebars.helpers),e=e||{};var f="",g=this.escapeExpression;return e.buffer.push('
\n '),e.buffer.push(g(c.view.call(b,"Ember.Table.HeaderBlock",{hash:{classNames:"ember-table-left-table-block",columnsBinding:"controller.fixedColumns",widthBinding:"controller._fixedBlockWidth",heightBinding:"controller.headerHeight"},hashTypes:{classNames:"STRING",columnsBinding:"STRING",widthBinding:"STRING",heightBinding:"STRING"},hashContexts:{classNames:b,columnsBinding:b,widthBinding:b,heightBinding:b},contexts:[b],types:["ID"],data:e}))),e.buffer.push("\n "),e.buffer.push(g(c.view.call(b,"Ember.Table.HeaderBlock",{hash:{classNames:"ember-table-right-table-block",columnsBinding:"controller.tableColumns",scrollLeftBinding:"controller._tableScrollLeft",widthBinding:"controller._tableBlockWidth",heightBinding:"controller.headerHeight"},hashTypes:{classNames:"STRING",columnsBinding:"STRING",scrollLeftBinding:"STRING",widthBinding:"STRING",heightBinding:"STRING"},hashContexts:{classNames:b,columnsBinding:b,scrollLeftBinding:b,widthBinding:b,heightBinding:b},contexts:[b],types:["ID"],data:e}))),e.buffer.push("\n
\n"),f}),Ember.TEMPLATES["header-row"]=Ember.Handlebars.template(function(a,b,c,d,e){this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,Ember.Handlebars.helpers),e=e||{};var f="",g=this.escapeExpression;return e.buffer.push(g(c.view.call(b,"Ember.MultiItemViewCollectionView",{hash:{contentBinding:"view.content",itemViewClassField:"headerCellViewClass",widthBinding:"controller._tableColumnsWidth"},hashTypes:{contentBinding:"STRING",itemViewClassField:"STRING",widthBinding:"STRING"},hashContexts:{contentBinding:b,itemViewClassField:b,widthBinding:b},contexts:[b],types:["ID"],data:e}))),e.buffer.push("\n"),f}),Ember.TEMPLATES["scroll-container"]=Ember.Handlebars.template(function(a,b,c,d,e){this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,Ember.Handlebars.helpers),e=e||{};var f="",g=this.escapeExpression;return e.buffer.push('
\n
\n '),e.buffer.push(g(c.view.call(b,"Ember.Table.ScrollPanel",{hash:{},hashTypes:{},hashContexts:{},contexts:[b],types:["ID"],data:e}))),e.buffer.push("\n
\n
\n"),f}),Ember.TEMPLATES["table-cell"]=Ember.Handlebars.template(function(a,b,c,d,e){this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,Ember.Handlebars.helpers),e=e||{};var f,g="";return e.buffer.push('\n '),f=c._triageMustache.call(b,"view.cellContent",{hash:{},hashTypes:{},hashContexts:{},contexts:[b],types:["ID"],data:e}),(f||0===f)&&e.buffer.push(f),e.buffer.push("\n"),g}),Ember.TEMPLATES["table-row"]=Ember.Handlebars.template(function(a,b,c,d,e){this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,Ember.Handlebars.helpers),e=e||{};var f="",g=this.escapeExpression;return e.buffer.push(g(c.view.call(b,"Ember.MultiItemViewCollectionView",{hash:{rowBinding:"view.row",contentBinding:"view.columns",itemViewClassField:"tableCellViewClass",widthBinding:"controller._tableColumnsWidth"},hashTypes:{rowBinding:"STRING",contentBinding:"STRING",itemViewClassField:"STRING",widthBinding:"STRING"},hashContexts:{rowBinding:b,contentBinding:b,itemViewClassField:b,widthBinding:b},contexts:[b],types:["ID"],data:e}))),e.buffer.push("\n"),f})}(),function(){Ember.Table=Ember.Namespace.create(),Ember.Table.VERSION="0.2.0",null!=(_ref=Ember.libraries)&&_ref.register("Ember Table",Ember.Table.VERSION)}(),function(){Ember.AddeparMixins=Ember.AddeparMixins||Ember.Namespace.create(),Ember.AddeparMixins.ResizeHandlerMixin=Ember.Mixin.create({resizeEndDelay:200,resizing:!1,onResizeStart:Ember.K,onResizeEnd:Ember.K,onResize:Ember.K,endResize:Ember.computed(function(){return function(a){return this.isDestroyed?void 0:(this.set("resizing",!1),"function"==typeof this.onResizeEnd?this.onResizeEnd(a):void 0)}}),handleWindowResize:function(a){return this.get("resizing")||(this.set("resizing",!0),"function"==typeof this.onResizeStart&&this.onResizeStart(a)),"function"==typeof this.onResize&&this.onResize(a),Ember.run.debounce(this,this.get("endResize"),a,this.get("resizeEndDelay"))},didInsertElement:function(){return this._super(),this._setupDocumentHandlers()},willDestroyElement:function(){return this._removeDocumentHandlers(),this._super()},_setupDocumentHandlers:function(){return this._resizeHandler?void 0:(this._resizeHandler=jQuery.proxy(this.get("handleWindowResize"),this),jQuery(window).on("resize."+this.elementId,this._resizeHandler))},_removeDocumentHandlers:function(){return jQuery(window).off("resize."+this.elementId,this._resizeHandler),this._resizeHandler=null}})}(),function(){Ember.AddeparMixins=Ember.AddeparMixins||Ember.Namespace.create(),Ember.AddeparMixins.StyleBindingsMixin=Ember.Mixin.create({concatenatedProperties:["styleBindings"],attributeBindings:["style"],unitType:"px",createStyleString:function(a,b){var c;return c=this.get(b),void 0!==c?("number"===Ember.typeOf(c)&&(c+=this.get("unitType")),""+a+":"+c+";"):void 0},applyStyleBindings:function(){var a,b,c,d,e,f=this;return(c=this.styleBindings)?(a={},c.forEach(function(b){var c,d,e;e=b.split(":"),c=e[0],d=e[1],a[d||c]=c}),e=Ember.keys(a),b=e.map(function(b){return a[b]}),d=Ember.computed(function(){var b,c;return c=e.map(function(b){return f.createStyleString(b,a[b])}),b=c.join(""),0!==b.length?b:void 0}),d.property.apply(d,b),Ember.defineProperty(this,"style",d)):void 0},init:function(){return this.applyStyleBindings(),this._super()}})}(),function(){jQuery.browser||!function(){var a,b,c;return b=void 0,a=void 0,jQuery.uaMatch=function(a){var b;return a=a.toLowerCase(),b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[],{browser:b[1]||"",version:b[2]||"0"}},b=jQuery.uaMatch(navigator.userAgent),a={},b.browser&&(a[b.browser]=!0,a.version=b.version),a.chrome?a.webkit=!0:a.webkit&&(a.safari=!0),c=jQuery.browser=a}()}(),function(){Ember.LazyContainerView=Ember.ContainerView.extend(Ember.AddeparMixins.StyleBindingsMixin,{classNames:"lazy-list-container",styleBindings:["height"],content:null,itemViewClass:null,rowHeight:null,scrollTop:null,startIndex:null,init:function(){return this._super(),this.onNumChildViewsDidChange()},height:Ember.computed(function(){return this.get("content.length")*this.get("rowHeight")}).property("content.length","rowHeight"),numChildViews:Ember.computed(function(){return this.get("numItemsShowing")+2}).property("numItemsShowing"),onNumChildViewsDidChange:Ember.observer(function(){var a,b,c,d,e,f,g,h;return e=this,a=Ember.get(this.get("itemViewClass")),b=this.get("numChildViews"),a&&b?(d=this.get("length"),c=b-d,0>c?(g=this.slice(b,d),this.removeObjects(g)):c>0?(f=function(){h=[];for(var a=0;c>=0?c>a:a>c;c>=0?a++:a--)h.push(a);return h}.apply(this).map(function(){return e.createChildView(a)}),this.pushObjects(f)):void 0):void 0},"numChildViews","itemViewClass"),viewportDidChange:Ember.observer(function(){var a,b,c,d;return b=this.get("content")||[],a=b.get("length"),c=Math.min(this.get("length"),a),d=this.get("startIndex"),d+c>=a&&(d=a-c),0>d&&(d=0),this.forEach(function(a,e){var f,g;return e>=c?(a=this.objectAt(e),void a.set("content",null)):(g=d+e,a=this.objectAt(g%c),f=b.objectAt(g),f!==a.get("content")?(a.teardownContent(),a.set("itemIndex",g),a.set("content",f),a.prepareContent()):void 0)},this)},"content.length","length","startIndex")}),Ember.LazyItemView=Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixin,{itemIndex:null,prepareContent:Ember.K,teardownContent:Ember.K,rowHeightBinding:"parentView.rowHeight",styleBindings:["width","top","display"],top:Ember.computed(function(){return this.get("itemIndex")*this.get("rowHeight")}).property("itemIndex","rowHeight"),display:Ember.computed(function(){return this.get("content")?void 0:"none"}).property("content")})}(),function(){Ember.MultiItemViewCollectionView=Ember.CollectionView.extend(Ember.AddeparMixins.StyleBindingsMixin,{styleBindings:"width",itemViewClassField:null,createChildView:function(a,b){var c,d;return d=this.get("itemViewClassField"),c=b.content.get(d),"string"==typeof c&&(c=Ember.get(Ember.lookup,c)),this._super(c,b)}}),Ember.MouseWheelHandlerMixin=Ember.Mixin.create({onMouseWheel:Ember.K,didInsertElement:function(){var a=this;return this._super(),this.$().bind("mousewheel",function(b,c,d,e){return Ember.run(a,a.onMouseWheel,b,c,d,e)})},willDestroyElement:function(){var a;return null!=(a=this.$())&&a.unbind("mousewheel"),this._super()}}),Ember.ScrollHandlerMixin=Ember.Mixin.create({onScroll:Ember.K,scrollElementSelector:"",didInsertElement:function(){var a=this;return this._super(),this.$(this.get("scrollElementSelector")).bind("scroll",function(b){return Ember.run(a,a.onScroll,b)})},willDestroyElement:function(){var a;return null!=(a=this.$(this.get("scrollElementSelector")))&&a.unbind("scroll"),this._super()}}),Ember.TouchMoveHandlerMixin=Ember.Mixin.create({onTouchMove:Ember.K,didInsertElement:function(){var a,b,c=this;return this._super(),a=b=0,this.$().bind("touchstart",function(c){a=c.originalEvent.targetTouches[0].pageX,b=c.originalEvent.targetTouches[0].pageY}),this.$().bind("touchmove",function(d){var e,f,g,h;g=d.originalEvent.targetTouches[0].pageX,h=d.originalEvent.targetTouches[0].pageY,e=-(g-a),f=-(h-b),Ember.run(c,c.onTouchMove,d,e,f),a=g,b=h})},willDestroy:function(){var a;return null!=(a=this.$())&&a.unbind("touchmove"),this._super()}}),Ember.Table.RowArrayController=Ember.ArrayController.extend({itemController:null,content:null,rowContent:Ember.computed(function(){return[]}).property(),controllerAt:function(a,b){var c,d,e;return c=this.get("container"),e=this.get("_subControllers"),(d=e[a])?d:(d=this.get("itemController").create({target:this,parentController:this.get("parentController")||this,content:b}),e[a]=d,d)}}),Ember.Table.ShowHorizontalScrollMixin=Ember.Mixin.create({mouseEnter:function(a){var b,c;return c=$(a.target).parents(".ember-table-tables-container"),b=c.find(".antiscroll-scrollbar-horizontal"),b.addClass("antiscroll-scrollbar-shown")},mouseLeave:function(a){var b,c;return c=$(a.target).parents(".ember-table-tables-container"),b=c.find(".antiscroll-scrollbar-horizontal"),b.removeClass("antiscroll-scrollbar-shown")}})}(),function(){Ember.Table.ColumnDefinition=Ember.Object.extend({headerCellName:void 0,contentPath:void 0,minWidth:void 0,maxWidth:void 0,defaultColumnWidth:150,columnWidth:Ember.computed.oneWay("defaultColumnWidth"),isResizable:!0,isSortable:!0,textAlign:"text-align-right",canAutoResize:!0,headerCellViewClass:"Ember.Table.HeaderCell",tableCellViewClass:"Ember.Table.TableCell",resize:function(a){return this.set("columnWidth",a)},getCellContent:function(a){var b;return b=this.get("contentPath"),Ember.assert("You must either provide a contentPath or override getCellContent in your column definition",null!=b),Ember.get(a,b)},setCellContent:Ember.K}),Ember.Table.Row=Ember.ObjectProxy.extend({content:null,isSelected:Ember.computed(function(){return this.get("parentController.selection")===this.get("content")}).property("parentController.selection","content"),isShowing:!0,isHovered:!1})}(),function(){Ember.Table.TableContainer=Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixin,{classNames:["ember-table-table-container"],styleBindings:["height","width"]}),Ember.Table.TableBlock=Ember.CollectionView.extend(Ember.AddeparMixins.StyleBindingsMixin,{classNames:["ember-table-table-block"],styleBindings:["width","height"],itemViewClass:Ember.computed.alias("controller.tableRowViewClass"),columns:null,content:null,scrollLeft:null,onScrollLeftDidChange:Ember.observer(function(){return this.$().scrollLeft(this.get("scrollLeft"))},"scrollLeft"),height:Ember.computed(function(){return this.get("controller._headerHeight")}).property("controller._headerHeight")}),Ember.Table.LazyTableBlock=Ember.LazyContainerView.extend({classNames:["ember-table-table-block"],styleBindings:["width"],itemViewClass:Ember.computed.alias("controller.tableRowViewClass"),rowHeight:Ember.computed.alias("controller.rowHeight"),columns:null,content:null,scrollLeft:null,scrollTop:null,onScrollLeftDidChange:Ember.observer(function(){return this.$().scrollLeft(this.get("scrollLeft"))},"scrollLeft")}),Ember.Table.TableRow=Ember.LazyItemView.extend({templateName:"table-row",classNames:"ember-table-table-row",classNameBindings:["row.isHovered:ember-table-hover","row.isSelected:ember-table-selected","row.rowStyle","isLastRow:ember-table-last-row"],styleBindings:["width","height"],row:Ember.computed.alias("content"),columns:Ember.computed.alias("parentView.columns"),width:Ember.computed.alias("controller._rowWidth"),height:Ember.computed.alias("controller.rowHeight"),isLastRow:Ember.computed(function(){return this.get("row")===this.get("controller.bodyContent.lastObject")}).property("controller.bodyContent.lastObject","row"),mouseEnter:function(){var a;return a=this.get("row"),a?a.set("isHovered",!0):void 0},mouseLeave:function(){var a;return a=this.get("row"),a?a.set("isHovered",!1):void 0},teardownContent:function(){var a;return a=this.get("row"),a?a.set("isHovered",!1):void 0}}),Ember.Table.TableCell=Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixin,{templateName:"table-cell",classNames:["ember-table-cell"],classNameBindings:"column.textAlign",styleBindings:"width",row:Ember.computed.alias("parentView.row"),column:Ember.computed.alias("content"),width:Ember.computed.alias("column.columnWidth"),init:function(){return this._super(),this.contentPathDidChange(),this.contentDidChange()},contentDidChange:function(){return this.notifyPropertyChange("cellContent")},contentPathWillChange:function(){var a;return a=this.get("column.contentPath"),a?this.removeObserver("row."+a,this,this.contentDidChange):void 0}.observesBefore("column.contentPath"),contentPathDidChange:function(){var a;return a=this.get("column.contentPath"),a?this.addObserver("row."+a,this,this.contentDidChange):void 0}.observesBefore("column.contentPath"),cellContent:Ember.computed(function(a,b){var c,d;return d=this.get("row"),c=this.get("column"),d&&c?(1===arguments.length?b=c.getCellContent(d):c.setCellContent(d,b),b):void 0}).property("row.isLoaded","column")}),Ember.Table.HeaderBlock=Ember.Table.TableBlock.extend({classNames:["ember-table-header-block"],itemViewClass:"Ember.Table.HeaderRow",content:Ember.computed(function(){return[this.get("columns")]}).property("columns")}),Ember.Table.HeaderRow=Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixin,{templateName:"header-row",classNames:["ember-table-table-row","ember-table-header-row"],styleBindings:["width"],columns:Ember.computed.alias("content"),width:Ember.computed.alias("controller._rowWidth"),scrollLeft:Ember.computed.alias("controller._tableScrollLeft"),sortableOption:Ember.computed(function(){return{axis:"x",containment:"parent",cursor:"move",helper:"clone",items:".ember-table-header-cell.sortable",opacity:.9,placeholder:"ui-state-highlight",scroll:!0,tolerance:"intersect",update:jQuery.proxy(this.onColumnSortDone,this),stop:jQuery.proxy(this.onColumnSortStop,this),sort:jQuery.proxy(this.onColumnSortChange,this)}}),onScrollLeftDidChange:Ember.observer(function(){return this.$().scrollLeft(this.get("scrollLeft"))},"scrollLeft"),didInsertElement:function(){return this._super(),this.get("controller.enableColumnReorder")?this.$("> div").sortable(this.get("sortableOption")):void 0},onScroll:function(a){return this.set("scrollLeft",a.target.scrollLeft),a.preventDefault()},onColumnSortStop:function(){return this.set("controller._isShowingSortableIndicator",!1)},onColumnSortChange:function(){var a;return a=this.$(".ui-state-highlight").offset().left-this.$().closest(".ember-table-tables-container").offset().left,this.set("controller._isShowingSortableIndicator",!0),this.set("controller._sortableIndicatorLeft",a)},onColumnSortDone:function(a,b){var c,d,e;return d=b.item.index(),e=Ember.View.views[b.item.attr("id")],c=e.get("column"),this.get("controller").onColumnSort(c,d),this.set("controller._isShowingSortableIndicator",!1)}}),Ember.Table.HeaderCell=Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixin,{templateName:"header-cell",classNames:["ember-table-cell","ember-table-header-cell"],classNameBindings:["column.isSortable:sortable","column.textAlign"],styleBindings:["width","height"],column:Ember.computed.alias("content"),width:Ember.computed.alias("column.columnWidth"),height:Ember.computed(function(){return this.get("controller._headerHeight")}).property("controller._headerHeight"),resizableOption:Ember.computed(function(){return{handles:"e",minHeight:40,minWidth:this.get("column.minWidth")||100,maxWidth:this.get("column.maxWidth")||500,grid:this.get("column.snapGrid"),resize:jQuery.proxy(this.onColumnResize,this),stop:jQuery.proxy(this.onColumnResize,this)}}),didInsertElement:function(){this.elementSizeDidChange(),this.get("column.isResizable")&&(this.$().resizable(this.get("resizableOption")),this._resizableWidget=this.$().resizable("widget"))},onColumnResize:function(a,b){return this.elementSizeDidChange(),this.get("controller.forceFillColumns")&&this.get("controller.columns").filterProperty("canAutoResize").length>1&&this.set("column.canAutoResize",!1),this.get("column").resize(b.size.width)},elementSizeDidChange:function(){var a;a=0,$(".ember-table-header-block .ember-table-content").each(function(){var b;return b=$(this).outerHeight(),b>a?a=b:void 0}),this.set("controller._contentHeaderHeight",a)}}),Ember.Table.ColumnSortableIndicator=Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixin,{classNames:"ember-table-column-sortable-indicator",classNameBindings:"controller._isShowingSortableIndicator:active",styleBindings:["left","height"],left:Ember.computed.alias("controller._sortableIndicatorLeft"),height:Ember.computed.alias("controller._height")}),Ember.Table.HeaderTableContainer=Ember.Table.TableContainer.extend(Ember.Table.ShowHorizontalScrollMixin,{templateName:"header-container",classNames:["ember-table-table-container","ember-table-fixed-table-container","ember-table-header-container"],height:Ember.computed.alias("controller._headerHeight"),width:Ember.computed.alias("controller._tableContainerWidth")}),Ember.Table.BodyTableContainer=Ember.Table.TableContainer.extend(Ember.MouseWheelHandlerMixin,Ember.TouchMoveHandlerMixin,Ember.ScrollHandlerMixin,Ember.Table.ShowHorizontalScrollMixin,{templateName:"body-container",classNames:["ember-table-table-container","ember-table-body-container","antiscroll-wrap"],height:Ember.computed.alias("controller._bodyHeight"),width:Ember.computed.alias("controller._width"),scrollTop:Ember.computed.alias("controller._tableScrollTop"),scrollLeft:Ember.computed.alias("controller._tableScrollLeft"),scrollElementSelector:".antiscroll-inner",onScroll:function(a){return this.set("scrollTop",a.target.scrollTop),a.preventDefault()},onMouseWheel:function(a,b,c,d){var e;if(Math.abs(c)>Math.abs(d))return e=this.$(".ember-table-right-table-block").scrollLeft()+c,this.set("scrollLeft",e),a.preventDefault()},onTouchMove:function(a,b,c){var d;if(Math.abs(b)>Math.abs(c))return d=this.$(".ember-table-right-table-block").scrollLeft()+b,this.set("scrollLeft",d),a.preventDefault()}}),Ember.Table.FooterTableContainer=Ember.Table.TableContainer.extend(Ember.MouseWheelHandlerMixin,Ember.TouchMoveHandlerMixin,Ember.Table.ShowHorizontalScrollMixin,{templateName:"footer-container",classNames:["ember-table-table-container","ember-table-fixed-table-container","ember-table-footer-container"],styleBindings:"top",height:Ember.computed.alias("controller.footerHeight"),width:Ember.computed.alias("controller._tableContainerWidth"),scrollLeft:Ember.computed.alias("controller._tableScrollLeft"),top:Ember.computed(function(){var a,b,c;return c=this.get("controller._headerHeight"),b=this.get("controller._tableContentHeight")+c,a=this.get("controller._bodyHeight")+c,a>b?b:a}).property("controller._bodyHeight","controller._headerHeight","controller._tableContentHeight"),onMouseWheel:function(a,b,c){var d;return d=this.$(".ember-table-right-table-block").scrollLeft()+c,this.set("scrollLeft",d),a.preventDefault()},onTouchMove:function(a,b){var c;return c=this.$(".ember-table-right-table-block").scrollLeft()+b,this.set("scrollLeft",c),a.preventDefault()}}),Ember.Table.ScrollContainer=Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixin,Ember.ScrollHandlerMixin,{templateName:"scroll-container",classNames:["ember-table-scroll-container"],styleBindings:["left","width","height"],scrollElementSelector:".antiscroll-inner",width:Ember.computed.alias("controller._scrollContainerWidth"),height:10,left:Ember.computed.alias("controller._fixedColumnsWidth"),scrollTop:Ember.computed.alias("controller._tableScrollTop"),scrollLeft:Ember.computed.alias("controller._tableScrollLeft"),didInsertElement:function(){return this._super(),this.onScrollLeftDidChange()},onScroll:function(a){return this.set("scrollLeft",a.target.scrollLeft),a.preventDefault()},onScrollLeftDidChange:Ember.observer(function(){var a;return a=this.get("scrollElementSelector"),this.$(a).scrollLeft(this.get("scrollLeft"))},"scrollLeft","scrollElementSelector")}),Ember.Table.ScrollPanel=Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixin,{classNames:["ember-table-scroll-panel"],styleBindings:["width","height"],width:Ember.computed.alias("controller._tableColumnsWidth"),height:Ember.computed.alias("controller._tableContentHeight")})}(),function(){Ember.Table.EmberTableComponent=Ember.Component.extend(Ember.AddeparMixins.StyleBindingsMixin,Ember.AddeparMixins.ResizeHandlerMixin,{layoutName:"components/ember-table",classNames:["ember-table-tables-container"],classNameBindings:["enableContentSelection:ember-table-content-selectable"],styleBindings:["height"],height:Ember.computed.alias("_tablesContainerHeight"),columns:null,numFixedColumns:0,numFooterRow:0,rowHeight:30,minHeaderHeight:30,footerHeight:30,hasHeader:!0,hasFooter:!0,forceFillColumns:!1,enableColumnReorder:!0,enableContentSelection:!1,selection:null,tableRowViewClass:"Ember.Table.TableRow",init:function(){if(this._super(),!$.ui)throw"Missing dependency: jquery-ui";if(!$().mousewheel)throw"Missing dependency: jquery-mousewheel";if(!$().antiscroll)throw"Missing dependency: antiscroll.js"},actions:{addColumn:Ember.K,sortByColumn:Ember.K},onColumnSort:function(a,b){var c;return c=this.get("tableColumns"),c.removeObject(a),c.insertAt(b,a)},bodyContent:Ember.computed(function(){return Ember.Table.RowArrayController.create({target:this,parentController:this,container:this.get("container"),itemController:Ember.Table.Row,content:this.get("content")})}).property("content"),footerContent:Ember.computed(function(a,b){return b?b:Ember.A()}).property(),fixedColumns:Ember.computed(function(){var a,b;return(a=this.get("columns"))?(b=this.get("numFixedColumns")||0,a=a.slice(0,b)||[],this.prepareTableColumns(a),a):Ember.A()}).property("columns.@each","numFixedColumns"),tableColumns:Ember.computed(function(){var a,b;return(a=this.get("columns"))?(b=this.get("numFixedColumns")||0,a=a.slice(b,a.get("length"))||[],this.prepareTableColumns(a),a):Ember.A()}).property("columns.@each","numFixedColumns"),prepareTableColumns:function(a){return a.setEach("controller",this)},didInsertElement:function(){return this._super(),this.set("_tableScrollTop",0),this.elementSizeDidChange()},onResizeEnd:function(){return Ember.run(this,this.elementSizeDidChange)},elementSizeDidChange:function(){return"inDOM"===this.get("state")?(this.set("_width",this.$().parent().outerWidth()),this.set("_height",this.$().parent().outerHeight()),Ember.run.next(this,this.updateLayout)):void 0},updateLayout:function(){return"inDOM"===this.get("state")?(this.$(".antiscroll-wrap").antiscroll().data("antiscroll").rebuild(),this.get("forceFillColumns")?this.doForceFillColumns():void 0):void 0},doForceFillColumns:function(){var a,b,c,d,e,f,g,h;return h=this.get("_width"),e=this.get("_fixedColumnsWidth"),g=this.get("tableColumns"),d=this._getTotalWidth(g),b=h-e,f=b-d,c=g.filterProperty("canAutoResize"),a=Math.floor(f/c.length),c.forEach(function(b){var c;return c=b.get("columnWidth")+a,b.set("columnWidth",c)})},onBodyContentLengthDidChange:Ember.observer(function(){return Ember.run.next(this,function(){return Ember.run.once(this,this.updateLayout)})},"bodyContent.length"),_tableScrollTop:0,_tableScrollLeft:0,_width:null,_height:null,_contentHeaderHeight:null,_hasVerticalScrollbar:Ember.computed(function(){var a,b;return b=this.get("_height"),a=this.get("_tableContentHeight")+this.get("_headerHeight")+this.get("_footerHeight"),a>b?!0:!1}).property("_height","_tableContentHeight","_headerHeight","_footerHeight"),_hasHorizontalScrollbar:Ember.computed(function(){var a,b;return a=this.get("_tableColumnsWidth"),b=this.get("_width")-this.get("_fixedColumnsWidth"),a>b?!0:!1}).property("_tableColumnsWidth","_width","_fixedColumnsWidth"),_tablesContainerHeight:Ember.computed(function(){var a,b;return b=this.get("_height"),a=this.get("_tableContentHeight")+this.get("_headerHeight")+this.get("_footerHeight"),b>a?a:b}).property("_height","_tableContentHeight","_headerHeight","_footerHeight"),_fixedColumnsWidth:Ember.computed(function(){return this._getTotalWidth(this.get("fixedColumns"))}).property("fixedColumns.@each.columnWidth"),_tableColumnsWidth:Ember.computed(function(){var a,b;return b=this._getTotalWidth(this.get("tableColumns"))+3,a=this.get("_width")-this.get("_fixedColumnsWidth"),b>a?b:a}).property("tableColumns.@each.columnWidth","_width","_fixedColumnsWidth"),_rowWidth:Ember.computed(function(){var a,b;return a=this.get("_tableColumnsWidth"),b=this.get("_tableContainerWidth")-this.get("_fixedColumnsWidth"),b>a?b:a}).property("_fixedColumnsWidth","_tableColumnsWidth","_tableContainerWidth"),_headerHeight:Ember.computed(function(){var a,b;return b=this.get("minHeaderHeight"),a=this.get("_contentHeaderHeight"),b>a?b:a}).property("_contentHeaderHeight","minHeaderHeight"),_footerHeight:Ember.computed(function(){return this.get("hasFooter")?this.get("footerHeight"):0}).property("footerHeight","hasFooter"),_bodyHeight:Ember.computed(function(){var a; -return a=this.get("_tablesContainerHeight"),this.get("hasHeader")&&(a-=this.get("_headerHeight")),this.get("hasFooter")&&(a-=this.get("footerHeight")),a}).property("_tablesContainerHeight","_hasHorizontalScrollbar","_headerHeight","footerHeight","hasHeader","hasFooter"),_tableBlockWidth:Ember.computed(function(){return this.get("_width")-this.get("_fixedColumnsWidth")}).property("_width","_fixedColumnsWidth"),_fixedBlockWidthBinding:"_fixedColumnsWidth",_tableContentHeight:Ember.computed(function(){return this.get("rowHeight")*this.get("bodyContent.length")}).property("rowHeight","bodyContent.length"),_tableContainerWidth:Ember.computed(function(){return this.get("_width")}).property("_width"),_scrollContainerWidth:Ember.computed(function(){return this.get("_width")-this.get("_fixedColumnsWidth")}).property("_width","_fixedColumnsWidth"),_numItemsShowing:Ember.computed(function(){return Math.floor(this.get("_bodyHeight")/this.get("rowHeight"))}).property("_bodyHeight","rowHeight"),_startIndex:Ember.computed(function(){var a,b,c,d,e;return b=this.get("bodyContent.length"),c=this.get("_numItemsShowing"),d=this.get("rowHeight"),e=this.get("_tableScrollTop"),a=Math.floor(e/d),a+c>=b&&(a=b-c),0>a?0:a}).property("bodyContent.length","_numItemsShowing","rowHeight","_tableScrollTop"),_getTotalWidth:function(a,b){var c;return null==b&&(b="columnWidth"),a?(c=a.getEach(b)||[],c.reduce(function(a,b){return a+b},0)):0},click:function(a){var b;return(b=this.getRowForEvent(a))?this.set("selection",b.get("content")):void 0},getRowForEvent:function(a){var b,c;return b=$(a.target).parents(".ember-table-table-row"),c=Ember.View.views[b.attr("id")],c?c.get("row"):void 0}}),Ember.Handlebars.helper("table-component",Ember.Table.EmberTableComponent)}(); \ No newline at end of file +!function(){Ember.TEMPLATES["body-container"]=Ember.Handlebars.template(function(a,b,c,d,e){function f(a,b){var d="";return b.buffer.push("\n "),b.buffer.push(i(c.view.call(a,"Ember.Table.LazyTableBlock",{hash:{classNames:"ember-table-left-table-block",contentBinding:"controller.bodyContent",columnsBinding:"controller.fixedColumns",widthBinding:"controller._fixedBlockWidth",numItemsShowingBinding:"controller._numItemsShowing",scrollTopBinding:"controller._scrollTop",startIndexBinding:"controller._startIndex"},hashTypes:{classNames:"STRING",contentBinding:"STRING",columnsBinding:"STRING",widthBinding:"STRING",numItemsShowingBinding:"STRING",scrollTopBinding:"STRING",startIndexBinding:"STRING"},hashContexts:{classNames:a,contentBinding:a,columnsBinding:a,widthBinding:a,numItemsShowingBinding:a,scrollTopBinding:a,startIndexBinding:a},contexts:[a],types:["ID"],data:b}))),b.buffer.push("\n "),d}this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,Ember.Handlebars.helpers),e=e||{};var g,h="",i=this.escapeExpression,j=this;return e.buffer.push('
\n
\n
\n '),g=c["if"].call(b,"controller.numFixedColumns",{hash:{},hashTypes:{},hashContexts:{},inverse:j.noop,fn:j.program(1,f,e),contexts:[b],types:["ID"],data:e}),(g||0===g)&&e.buffer.push(g),e.buffer.push("\n "),e.buffer.push(i(c.view.call(b,"Ember.Table.LazyTableBlock",{hash:{classNames:"ember-table-right-table-block",contentBinding:"controller.bodyContent",columnsBinding:"controller.tableColumns",scrollLeftBinding:"controller._tableScrollLeft",widthBinding:"controller._tableBlockWidth",numItemsShowingBinding:"controller._numItemsShowing",scrollTopBinding:"controller._scrollTop",startIndexBinding:"controller._startIndex"},hashTypes:{classNames:"STRING",contentBinding:"STRING",columnsBinding:"STRING",scrollLeftBinding:"STRING",widthBinding:"STRING",numItemsShowingBinding:"STRING",scrollTopBinding:"STRING",startIndexBinding:"STRING"},hashContexts:{classNames:b,contentBinding:b,columnsBinding:b,scrollLeftBinding:b,widthBinding:b,numItemsShowingBinding:b,scrollTopBinding:b,startIndexBinding:b},contexts:[b],types:["ID"],data:e}))),e.buffer.push("\n
\n
\n
"),h}),Ember.TEMPLATES["components/ember-table"]=Ember.Handlebars.template(function(a,b,c,d,e){function f(a,b){var d="";return b.buffer.push("\n "),b.buffer.push(j(c.view.call(a,"Ember.Table.HeaderTableContainer",{hash:{},hashTypes:{},hashContexts:{},contexts:[a],types:["ID"],data:b}))),b.buffer.push("\n"),d}function g(a,b){var d="";return b.buffer.push("\n "),b.buffer.push(j(c.view.call(a,"Ember.Table.FooterTableContainer",{hash:{},hashTypes:{},hashContexts:{},contexts:[a],types:["ID"],data:b}))),b.buffer.push("\n"),d}this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,Ember.Handlebars.helpers),e=e||{};var h,i="",j=this.escapeExpression,k=this;return h=c["if"].call(b,"controller.hasHeader",{hash:{},hashTypes:{},hashContexts:{},inverse:k.noop,fn:k.program(1,f,e),contexts:[b],types:["ID"],data:e}),(h||0===h)&&e.buffer.push(h),e.buffer.push("\n"),e.buffer.push(j(c.view.call(b,"Ember.Table.BodyTableContainer",{hash:{},hashTypes:{},hashContexts:{},contexts:[b],types:["ID"],data:e}))),e.buffer.push("\n"),h=c["if"].call(b,"controller.hasFooter",{hash:{},hashTypes:{},hashContexts:{},inverse:k.noop,fn:k.program(3,g,e),contexts:[b],types:["ID"],data:e}),(h||0===h)&&e.buffer.push(h),e.buffer.push("\n"),e.buffer.push(j(c.view.call(b,"Ember.Table.ScrollContainer",{hash:{},hashTypes:{},hashContexts:{},contexts:[b],types:["ID"],data:e}))),e.buffer.push("\n"),e.buffer.push(j(c.view.call(b,"Ember.Table.ColumnSortableIndicator",{hash:{},hashTypes:{},hashContexts:{},contexts:[b],types:["ID"],data:e}))),e.buffer.push("\n"),i}),Ember.TEMPLATES["footer-container"]=Ember.Handlebars.template(function(a,b,c,d,e){function f(a,b){var d="";return b.buffer.push("\n "),b.buffer.push(i(c.view.call(a,"Ember.Table.TableBlock",{hash:{classNames:"ember-table-left-table-block",contentBinding:"controller.footerContent",columnsBinding:"controller.fixedColumns",widthBinding:"controller._fixedBlockWidth",heightBinding:"controller.footerHeight"},hashTypes:{classNames:"STRING",contentBinding:"STRING",columnsBinding:"STRING",widthBinding:"STRING",heightBinding:"STRING"},hashContexts:{classNames:a,contentBinding:a,columnsBinding:a,widthBinding:a,heightBinding:a},contexts:[a],types:["ID"],data:b}))),b.buffer.push("\n "),d}this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,Ember.Handlebars.helpers),e=e||{};var g,h="",i=this.escapeExpression,j=this;return e.buffer.push('
\n '),g=c["if"].call(b,"controller.numFixedColumns",{hash:{},hashTypes:{},hashContexts:{},inverse:j.noop,fn:j.program(1,f,e),contexts:[b],types:["ID"],data:e}),(g||0===g)&&e.buffer.push(g),e.buffer.push("\n "),e.buffer.push(i(c.view.call(b,"Ember.Table.TableBlock",{hash:{classNames:"ember-table-right-table-block",contentBinding:"controller.footerContent",columnsBinding:"controller.tableColumns",scrollLeftBinding:"controller._tableScrollLeft",widthBinding:"controller._tableBlockWidth",heightBinding:"controller.footerHeight"},hashTypes:{classNames:"STRING",contentBinding:"STRING",columnsBinding:"STRING",scrollLeftBinding:"STRING",widthBinding:"STRING",heightBinding:"STRING"},hashContexts:{classNames:b,contentBinding:b,columnsBinding:b,scrollLeftBinding:b,widthBinding:b,heightBinding:b},contexts:[b],types:["ID"],data:e}))),e.buffer.push("\n
\n"),h}),Ember.TEMPLATES["header-cell"]=Ember.Handlebars.template(function(a,b,c,d,e){this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,Ember.Handlebars.helpers),e=e||{};var f,g="",h=this.escapeExpression;return e.buffer.push('
\n \n '),f=c._triageMustache.call(b,"view.content.headerCellName",{hash:{},hashTypes:{},hashContexts:{},contexts:[b],types:["ID"],data:e}),(f||0===f)&&e.buffer.push(f),e.buffer.push("\n \n
"),g}),Ember.TEMPLATES["header-container"]=Ember.Handlebars.template(function(a,b,c,d,e){function f(a,b){var d="";return b.buffer.push("\n "),b.buffer.push(i(c.view.call(a,"Ember.Table.HeaderBlock",{hash:{classNames:"ember-table-left-table-block",columnsBinding:"controller.fixedColumns",widthBinding:"controller._fixedBlockWidth",heightBinding:"controller.headerHeight"},hashTypes:{classNames:"STRING",columnsBinding:"STRING",widthBinding:"STRING",heightBinding:"STRING"},hashContexts:{classNames:a,columnsBinding:a,widthBinding:a,heightBinding:a},contexts:[a],types:["ID"],data:b}))),b.buffer.push("\n "),d}this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,Ember.Handlebars.helpers),e=e||{};var g,h="",i=this.escapeExpression,j=this;return e.buffer.push('
\n '),g=c["if"].call(b,"controller.numFixedColumns",{hash:{},hashTypes:{},hashContexts:{},inverse:j.noop,fn:j.program(1,f,e),contexts:[b],types:["ID"],data:e}),(g||0===g)&&e.buffer.push(g),e.buffer.push("\n "),e.buffer.push(i(c.view.call(b,"Ember.Table.HeaderBlock",{hash:{classNames:"ember-table-right-table-block",columnsBinding:"controller.tableColumns",scrollLeftBinding:"controller._tableScrollLeft",widthBinding:"controller._tableBlockWidth",heightBinding:"controller.headerHeight"},hashTypes:{classNames:"STRING",columnsBinding:"STRING",scrollLeftBinding:"STRING",widthBinding:"STRING",heightBinding:"STRING"},hashContexts:{classNames:b,columnsBinding:b,scrollLeftBinding:b,widthBinding:b,heightBinding:b},contexts:[b],types:["ID"],data:e}))),e.buffer.push("\n
\n"),h}),Ember.TEMPLATES["header-row"]=Ember.Handlebars.template(function(a,b,c,d,e){this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,Ember.Handlebars.helpers),e=e||{};var f="",g=this.escapeExpression;return e.buffer.push(g(c.view.call(b,"Ember.MultiItemViewCollectionView",{hash:{contentBinding:"view.content",itemViewClassField:"headerCellViewClass",widthBinding:"controller._tableColumnsWidth"},hashTypes:{contentBinding:"STRING",itemViewClassField:"STRING",widthBinding:"STRING"},hashContexts:{contentBinding:b,itemViewClassField:b,widthBinding:b},contexts:[b],types:["ID"],data:e}))),e.buffer.push("\n"),f}),Ember.TEMPLATES["scroll-container"]=Ember.Handlebars.template(function(a,b,c,d,e){this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,Ember.Handlebars.helpers),e=e||{};var f="",g=this.escapeExpression;return e.buffer.push('
\n
\n '),e.buffer.push(g(c.view.call(b,"Ember.Table.ScrollPanel",{hash:{},hashTypes:{},hashContexts:{},contexts:[b],types:["ID"],data:e}))),e.buffer.push("\n
\n
\n"),f}),Ember.TEMPLATES["table-cell"]=Ember.Handlebars.template(function(a,b,c,d,e){this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,Ember.Handlebars.helpers),e=e||{};var f,g="";return e.buffer.push('\n '),f=c._triageMustache.call(b,"view.cellContent",{hash:{},hashTypes:{},hashContexts:{},contexts:[b],types:["ID"],data:e}),(f||0===f)&&e.buffer.push(f),e.buffer.push("\n"),g}),Ember.TEMPLATES["table-row"]=Ember.Handlebars.template(function(a,b,c,d,e){this.compilerInfo=[4,">= 1.0.0"],c=this.merge(c,Ember.Handlebars.helpers),e=e||{};var f="",g=this.escapeExpression;return e.buffer.push(g(c.view.call(b,"Ember.MultiItemViewCollectionView",{hash:{rowBinding:"view.row",contentBinding:"view.columns",itemViewClassField:"tableCellViewClass",widthBinding:"controller._tableColumnsWidth"},hashTypes:{rowBinding:"STRING",contentBinding:"STRING",itemViewClassField:"STRING",widthBinding:"STRING"},hashContexts:{rowBinding:b,contentBinding:b,itemViewClassField:b,widthBinding:b},contexts:[b],types:["ID"],data:e}))),e.buffer.push("\n"),f})}(),function(){Ember.Table=Ember.Namespace.create(),Ember.Table.VERSION="0.2.2",null!=(_ref=Ember.libraries)&&_ref.register("Ember Table",Ember.Table.VERSION)}(),function(){Ember.AddeparMixins=Ember.AddeparMixins||Ember.Namespace.create(),Ember.AddeparMixins.ResizeHandlerMixin=Ember.Mixin.create({resizeEndDelay:200,resizing:!1,onResizeStart:Ember.K,onResizeEnd:Ember.K,onResize:Ember.K,endResize:Ember.computed(function(){return function(a){return this.isDestroyed?void 0:(this.set("resizing",!1),"function"==typeof this.onResizeEnd?this.onResizeEnd(a):void 0)}}),handleWindowResize:function(a){return this.get("resizing")||(this.set("resizing",!0),"function"==typeof this.onResizeStart&&this.onResizeStart(a)),"function"==typeof this.onResize&&this.onResize(a),Ember.run.debounce(this,this.get("endResize"),a,this.get("resizeEndDelay"))},didInsertElement:function(){return this._super(),this._setupDocumentHandlers()},willDestroyElement:function(){return this._removeDocumentHandlers(),this._super()},_setupDocumentHandlers:function(){return this._resizeHandler?void 0:(this._resizeHandler=jQuery.proxy(this.get("handleWindowResize"),this),jQuery(window).on("resize."+this.elementId,this._resizeHandler))},_removeDocumentHandlers:function(){return jQuery(window).off("resize."+this.elementId,this._resizeHandler),this._resizeHandler=null}})}(),function(){Ember.AddeparMixins=Ember.AddeparMixins||Ember.Namespace.create(),Ember.AddeparMixins.StyleBindingsMixin=Ember.Mixin.create({concatenatedProperties:["styleBindings"],attributeBindings:["style"],unitType:"px",createStyleString:function(a,b){var c;return c=this.get(b),Ember.isNone(c)?void 0:("number"===Ember.typeOf(c)&&(c+=this.get("unitType")),Ember.String.dasherize(""+a)+":"+c+";")},applyStyleBindings:function(){var a,b,c,d,e,f=this;return(c=this.styleBindings)?(a={},c.forEach(function(b){var c,d,e;e=b.split(":"),c=e[0],d=e[1],a[d||c]=c}),e=Ember.keys(a),b=e.map(function(b){return a[b]}),d=Ember.computed(function(){var b,c;return c=e.map(function(b){return f.createStyleString(b,a[b])}),b=c.join(""),0!==b.length?b:void 0}),d.property.apply(d,b),Ember.defineProperty(this,"style",d)):void 0},init:function(){return this.applyStyleBindings(),this._super()}})}(),function(){jQuery.browser||!function(){var a,b,c;return b=void 0,a=void 0,jQuery.uaMatch=function(a){var b;return a=a.toLowerCase(),b=/(chrome)[ \/]([\w.]+)/.exec(a)||/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||a.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(a)||[],{browser:b[1]||"",version:b[2]||"0"}},b=jQuery.uaMatch(navigator.userAgent),a={},b.browser&&(a[b.browser]=!0,a.version=b.version),a.chrome?a.webkit=!0:a.webkit&&(a.safari=!0),c=jQuery.browser=a}()}(),function(){Ember.LazyContainerView=Ember.ContainerView.extend(Ember.AddeparMixins.StyleBindingsMixin,{classNames:"lazy-list-container",styleBindings:["height"],content:null,itemViewClass:null,rowHeight:null,scrollTop:null,startIndex:null,init:function(){return this._super(),this.onNumChildViewsDidChange()},height:Ember.computed(function(){return this.get("content.length")*this.get("rowHeight")}).property("content.length","rowHeight"),numChildViews:Ember.computed(function(){return this.get("numItemsShowing")+2}).property("numItemsShowing"),onNumChildViewsDidChange:Ember.observer(function(){var a,b,c,d,e,f,g,h;return e=this,a=this.get("itemViewClass"),"string"==typeof a&&(a=/[A-Z]+/.exec(a)?Ember.get(Ember.lookup,a):this.container.lookupFactory("view:"+a)),b=this.get("numChildViews"),a&&b?(d=this.get("length"),c=b-d,0>c?(g=this.slice(b,d),this.removeObjects(g)):c>0?(f=function(){h=[];for(var a=0;c>=0?c>a:a>c;c>=0?a++:a--)h.push(a);return h}.apply(this).map(function(){return e.createChildView(a)}),this.pushObjects(f)):void 0):void 0},"numChildViews","itemViewClass"),viewportDidChange:Ember.observer(function(){var a,b,c,d;return b=this.get("content")||[],a=b.get("length"),c=Math.min(this.get("length"),a),d=this.get("startIndex"),d+c>=a&&(d=a-c),0>d&&(d=0),this.forEach(function(a,e){var f,g;return e>=c?(a=this.objectAt(e),void a.set("content",null)):(g=d+e,a=this.objectAt(g%c),f=b.objectAt(g),f!==a.get("content")?(a.teardownContent(),a.set("itemIndex",g),a.set("content",f),a.prepareContent()):void 0)},this)},"content.length","length","startIndex")}),Ember.LazyItemView=Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixin,{itemIndex:null,prepareContent:Ember.K,teardownContent:Ember.K,rowHeightBinding:"parentView.rowHeight",styleBindings:["width","top","display"],top:Ember.computed(function(){return this.get("itemIndex")*this.get("rowHeight")}).property("itemIndex","rowHeight"),display:Ember.computed(function(){return this.get("content")?void 0:"none"}).property("content")})}(),function(){Ember.MultiItemViewCollectionView=Ember.CollectionView.extend(Ember.AddeparMixins.StyleBindingsMixin,{styleBindings:"width",itemViewClassField:null,createChildView:function(a,b){var c,d;return d=this.get("itemViewClassField"),c=b.content.get(d),"string"==typeof c&&(c=/[A-Z]+/.exec(c)?Ember.get(Ember.lookup,c):this.container.lookupFactory("view:"+c)),this._super(c,b)}}),Ember.MouseWheelHandlerMixin=Ember.Mixin.create({onMouseWheel:Ember.K,didInsertElement:function(){var a=this;return this._super(),this.$().bind("mousewheel",function(b,c,d,e){return Ember.run(a,a.onMouseWheel,b,c,d,e)})},willDestroyElement:function(){var a;return null!=(a=this.$())&&a.unbind("mousewheel"),this._super()}}),Ember.ScrollHandlerMixin=Ember.Mixin.create({onScroll:Ember.K,scrollElementSelector:"",didInsertElement:function(){var a=this;return this._super(),this.$(this.get("scrollElementSelector")).bind("scroll",function(b){return Ember.run(a,a.onScroll,b)})},willDestroyElement:function(){var a;return null!=(a=this.$(this.get("scrollElementSelector")))&&a.unbind("scroll"),this._super()}}),Ember.TouchMoveHandlerMixin=Ember.Mixin.create({onTouchMove:Ember.K,didInsertElement:function(){var a,b,c=this;return this._super(),a=b=0,this.$().bind("touchstart",function(c){a=c.originalEvent.targetTouches[0].pageX,b=c.originalEvent.targetTouches[0].pageY}),this.$().bind("touchmove",function(d){var e,f,g,h;g=d.originalEvent.targetTouches[0].pageX,h=d.originalEvent.targetTouches[0].pageY,e=-(g-a),f=-(h-b),Ember.run(c,c.onTouchMove,d,e,f),a=g,b=h})},willDestroy:function(){var a;return null!=(a=this.$())&&a.unbind("touchmove"),this._super()}}),Ember.Table.RowArrayController=Ember.ArrayController.extend({itemController:null,content:null,rowContent:Ember.computed(function(){return[]}).property(),controllerAt:function(a,b){var c,d,e;return c=this.get("container"),e=this.get("_subControllers"),(d=e[a])?d:(d=this.get("itemController").create({target:this,parentController:this.get("parentController")||this,content:b}),e[a]=d,d)}}),Ember.Table.ShowHorizontalScrollMixin=Ember.Mixin.create({mouseEnter:function(a){var b,c;return c=$(a.target).parents(".ember-table-tables-container"),b=c.find(".antiscroll-scrollbar-horizontal"),b.addClass("antiscroll-scrollbar-shown")},mouseLeave:function(a){var b,c;return c=$(a.target).parents(".ember-table-tables-container"),b=c.find(".antiscroll-scrollbar-horizontal"),b.removeClass("antiscroll-scrollbar-shown")}})}(),function(){Ember.Table.ColumnDefinition=Ember.Object.extend({headerCellName:void 0,contentPath:void 0,minWidth:void 0,maxWidth:void 0,defaultColumnWidth:150,isResizable:!0,isSortable:!0,textAlign:"text-align-right",canAutoResize:!0,headerCellView:"Ember.Table.HeaderCell",headerCellViewClass:Ember.computed.alias("headerCellView"),tableCellView:"Ember.Table.TableCell",tableCellViewClass:Ember.computed.alias("tableCellView"),getCellContent:function(a){var b;return b=this.get("contentPath"),Ember.assert("You must either provide a contentPath or override getCellContent in your column definition",null!=b),Ember.get(a,b)},setCellContent:Ember.K,columnWidth:Ember.computed.oneWay("defaultColumnWidth"),resize:function(a){return this.set("columnWidth",a)}})}(),function(){Ember.Table.Row=Ember.ObjectProxy.extend({content:null,isSelected:Ember.computed(function(a,b){return arguments.length>1&&this.get("parentController").setSelected(this,b),this.get("parentController").isSelected(this)}).property("parentController._selection.[]"),isShowing:!0,isHovered:!1})}(),function(){Ember.Table.TableContainer=Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixin,{classNames:["ember-table-table-container"],styleBindings:["height","width"]}),Ember.Table.TableBlock=Ember.CollectionView.extend(Ember.AddeparMixins.StyleBindingsMixin,{classNames:["ember-table-table-block"],styleBindings:["width","height"],itemViewClass:Ember.computed.alias("controller.tableRowViewClass"),columns:null,content:null,scrollLeft:null,onScrollLeftDidChange:Ember.observer(function(){return this.$().scrollLeft(this.get("scrollLeft"))},"scrollLeft"),height:Ember.computed(function(){return this.get("controller._headerHeight")}).property("controller._headerHeight")}),Ember.Table.LazyTableBlock=Ember.LazyContainerView.extend({classNames:["ember-table-table-block"],styleBindings:["width"],itemViewClass:Ember.computed.alias("controller.tableRowViewClass"),rowHeight:Ember.computed.alias("controller.rowHeight"),columns:null,content:null,scrollLeft:null,scrollTop:null,onScrollLeftDidChange:Ember.observer(function(){return this.$().scrollLeft(this.get("scrollLeft"))},"scrollLeft")}),Ember.Table.TableRow=Ember.LazyItemView.extend({templateName:"table-row",classNames:"ember-table-table-row",classNameBindings:["row.isHovered:ember-table-hover","row.isSelected:ember-table-selected","row.rowStyle","isLastRow:ember-table-last-row"],styleBindings:["width","height"],row:Ember.computed.alias("content"),columns:Ember.computed.alias("parentView.columns"),width:Ember.computed.alias("controller._rowWidth"),height:Ember.computed.alias("controller.rowHeight"),isLastRow:Ember.computed(function(){return this.get("row")===this.get("controller.bodyContent.lastObject")}).property("controller.bodyContent.lastObject","row"),mouseEnter:function(){var a;return a=this.get("row"),a?a.set("isHovered",!0):void 0},mouseLeave:function(){var a;return a=this.get("row"),a?a.set("isHovered",!1):void 0},teardownContent:function(){var a;return a=this.get("row"),a?a.set("isHovered",!1):void 0}}),Ember.Table.TableCell=Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixin,{templateName:"table-cell",classNames:["ember-table-cell"],classNameBindings:"column.textAlign",styleBindings:"width",init:function(){return this._super(),this.contentPathDidChange(),this.contentDidChange()},row:Ember.computed.alias("parentView.row"),column:Ember.computed.alias("content"),width:Ember.computed.alias("column.columnWidth"),contentDidChange:function(){return this.notifyPropertyChange("cellContent")},contentPathWillChange:function(){var a;return a=this.get("column.contentPath"),a?this.removeObserver("row."+a,this,this.contentDidChange):void 0}.observesBefore("column.contentPath"),contentPathDidChange:function(){var a;return a=this.get("column.contentPath"),a?this.addObserver("row."+a,this,this.contentDidChange):void 0}.observesBefore("column.contentPath"),cellContent:Ember.computed(function(a,b){var c,d;return d=this.get("row"),c=this.get("column"),d&&c?(1===arguments.length?b=c.getCellContent(d):c.setCellContent(d,b),b):void 0}).property("row.isLoaded","column")}),Ember.Table.HeaderBlock=Ember.Table.TableBlock.extend({classNames:["ember-table-header-block"],itemViewClass:"Ember.Table.HeaderRow",content:Ember.computed(function(){return[this.get("columns")]}).property("columns")}),Ember.Table.HeaderRow=Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixin,{templateName:"header-row",classNames:["ember-table-table-row","ember-table-header-row"],styleBindings:["width"],columns:Ember.computed.alias("content"),width:Ember.computed.alias("controller._rowWidth"),scrollLeft:Ember.computed.alias("controller._tableScrollLeft"),sortableOption:Ember.computed(function(){return{axis:"x",containment:"parent",cursor:"move",helper:"clone",items:".ember-table-header-cell.sortable",opacity:.9,placeholder:"ui-state-highlight",scroll:!0,tolerance:"intersect",update:jQuery.proxy(this.onColumnSortDone,this),stop:jQuery.proxy(this.onColumnSortStop,this),sort:jQuery.proxy(this.onColumnSortChange,this)}}),onScrollLeftDidChange:Ember.observer(function(){return this.$().scrollLeft(this.get("scrollLeft"))},"scrollLeft"),didInsertElement:function(){return this._super(),this.get("controller.enableColumnReorder")?this.$("> div").sortable(this.get("sortableOption")):void 0},onScroll:function(a){return this.set("scrollLeft",a.target.scrollLeft),a.preventDefault()},onColumnSortStop:function(){return this.set("controller._isShowingSortableIndicator",!1)},onColumnSortChange:function(){var a;return a=this.$(".ui-state-highlight").offset().left-this.$().closest(".ember-table-tables-container").offset().left,this.set("controller._isShowingSortableIndicator",!0),this.set("controller._sortableIndicatorLeft",a)},onColumnSortDone:function(a,b){var c,d,e;return d=b.item.index(),e=Ember.View.views[b.item.attr("id")],c=e.get("column"),this.get("controller").onColumnSort(c,d),this.set("controller._isShowingSortableIndicator",!1)}}),Ember.Table.HeaderCell=Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixin,{templateName:"header-cell",classNames:["ember-table-cell","ember-table-header-cell"],classNameBindings:["column.isSortable:sortable","column.textAlign"],styleBindings:["width","height"],column:Ember.computed.alias("content"),width:Ember.computed.alias("column.columnWidth"),height:Ember.computed(function(){return this.get("controller._headerHeight")}).property("controller._headerHeight"),resizableOption:Ember.computed(function(){return{handles:"e",minHeight:40,minWidth:this.get("column.minWidth")||100,maxWidth:this.get("column.maxWidth")||500,grid:this.get("column.snapGrid"),resize:jQuery.proxy(this.onColumnResize,this),stop:jQuery.proxy(this.onColumnResize,this)}}),didInsertElement:function(){this.elementSizeDidChange(),this.get("column.isResizable")&&(this.$().resizable(this.get("resizableOption")),this._resizableWidget=this.$().resizable("widget"))},onColumnResize:function(a,b){return this.elementSizeDidChange(),this.get("controller.forceFillColumns")&&this.get("controller.columns").filterProperty("canAutoResize").length>1&&this.set("column.canAutoResize",!1),this.get("column").resize(b.size.width)},elementSizeDidChange:function(){var a;a=0,$(".ember-table-header-block .ember-table-content").each(function(){var b;return b=$(this).outerHeight(),b>a?a=b:void 0}),this.set("controller._contentHeaderHeight",a)}}),Ember.Table.ColumnSortableIndicator=Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixin,{classNames:"ember-table-column-sortable-indicator",classNameBindings:"controller._isShowingSortableIndicator:active",styleBindings:["left","height"],left:Ember.computed.alias("controller._sortableIndicatorLeft"),height:Ember.computed.alias("controller._height")}),Ember.Table.HeaderTableContainer=Ember.Table.TableContainer.extend(Ember.Table.ShowHorizontalScrollMixin,{templateName:"header-container",classNames:["ember-table-table-container","ember-table-fixed-table-container","ember-table-header-container"],height:Ember.computed.alias("controller._headerHeight"),width:Ember.computed.alias("controller._tableContainerWidth")}),Ember.Table.BodyTableContainer=Ember.Table.TableContainer.extend(Ember.MouseWheelHandlerMixin,Ember.TouchMoveHandlerMixin,Ember.ScrollHandlerMixin,Ember.Table.ShowHorizontalScrollMixin,{templateName:"body-container",classNames:["ember-table-table-container","ember-table-body-container","antiscroll-wrap"],height:Ember.computed.alias("controller._bodyHeight"),width:Ember.computed.alias("controller._width"),scrollTop:Ember.computed.alias("controller._tableScrollTop"),scrollLeft:Ember.computed.alias("controller._tableScrollLeft"),scrollElementSelector:".antiscroll-inner",onScroll:function(a){return this.set("scrollTop",a.target.scrollTop),a.preventDefault()},onMouseWheel:function(a,b,c,d){var e;if(Math.abs(c)>Math.abs(d))return e=this.$(".ember-table-right-table-block").scrollLeft()+c,this.set("scrollLeft",e),a.preventDefault()},onTouchMove:function(a,b,c){var d;if(Math.abs(b)>Math.abs(c))return d=this.$(".ember-table-right-table-block").scrollLeft()+b,this.set("scrollLeft",d),a.preventDefault()}}),Ember.Table.FooterTableContainer=Ember.Table.TableContainer.extend(Ember.MouseWheelHandlerMixin,Ember.TouchMoveHandlerMixin,Ember.Table.ShowHorizontalScrollMixin,{templateName:"footer-container",classNames:["ember-table-table-container","ember-table-fixed-table-container","ember-table-footer-container"],styleBindings:"top",height:Ember.computed.alias("controller.footerHeight"),width:Ember.computed.alias("controller._tableContainerWidth"),scrollLeft:Ember.computed.alias("controller._tableScrollLeft"),top:Ember.computed(function(){var a,b,c;return c=this.get("controller._headerHeight"),b=this.get("controller._tableContentHeight")+c,a=this.get("controller._bodyHeight")+c,a>b?b:a}).property("controller._bodyHeight","controller._headerHeight","controller._tableContentHeight"),onMouseWheel:function(a,b,c){var d;return d=this.$(".ember-table-right-table-block").scrollLeft()+c,this.set("scrollLeft",d),a.preventDefault()},onTouchMove:function(a,b){var c;return c=this.$(".ember-table-right-table-block").scrollLeft()+b,this.set("scrollLeft",c),a.preventDefault()}}),Ember.Table.ScrollContainer=Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixin,Ember.ScrollHandlerMixin,{templateName:"scroll-container",classNames:["ember-table-scroll-container"],styleBindings:["left","width","height"],scrollElementSelector:".antiscroll-inner",width:Ember.computed.alias("controller._scrollContainerWidth"),height:10,left:Ember.computed.alias("controller._fixedColumnsWidth"),scrollTop:Ember.computed.alias("controller._tableScrollTop"),scrollLeft:Ember.computed.alias("controller._tableScrollLeft"),didInsertElement:function(){return this._super(),this.onScrollLeftDidChange()},onScroll:function(a){return this.set("scrollLeft",a.target.scrollLeft),a.preventDefault()},onScrollLeftDidChange:Ember.observer(function(){var a;return a=this.get("scrollElementSelector"),this.$(a).scrollLeft(this.get("scrollLeft"))},"scrollLeft","scrollElementSelector")}),Ember.Table.ScrollPanel=Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixin,{classNames:["ember-table-scroll-panel"],styleBindings:["width","height"],width:Ember.computed.alias("controller._tableColumnsWidth"),height:Ember.computed.alias("controller._tableContentHeight")})}(),function(){Ember.Table.EmberTableComponent=Ember.Component.extend(Ember.AddeparMixins.StyleBindingsMixin,Ember.AddeparMixins.ResizeHandlerMixin,{layoutName:"components/ember-table",classNames:["ember-table-tables-container"],classNameBindings:["enableContentSelection:ember-table-content-selectable"],styleBindings:["height"],content:null,columns:null,numFixedColumns:0,numFooterRow:0,rowHeight:30,minHeaderHeight:30,footerHeight:30,hasHeader:!0,hasFooter:!0,forceFillColumns:!1,enableColumnReorder:!0,enableContentSelection:!1,selectionMode:"single",selection:Ember.computed(function(a,b){var c,d,e,f,g;if(arguments.length>1&&b){if("single"===this.get("selectionMode"))this.get("persistedSelection").clear(),this.get("persistedSelection").add(this.findRow(b));else for(this.get("persistedSelection").clear(),d=0,e=b.length;e>d;d++)c=b[d],this.get("persistedSelection").add(this.findRow(c));this.get("rangeSelection").clear()}return"single"===this.get("selectionMode")?null!=(f=this.get("_selection"))&&null!=(g=f[0])?g.get("content"):void 0:this.get("_selection").toArray().map(function(a){return a.get("content")})}).property("_selection.[]","selectionMode"),init:function(){if(this._super(),!$.ui)throw"Missing dependency: jquery-ui";if(!$().mousewheel)throw"Missing dependency: jquery-mousewheel";if(!$().antiscroll)throw"Missing dependency: antiscroll.js"},actions:{addColumn:Ember.K,sortByColumn:Ember.K},height:Ember.computed.alias("_tablesContainerHeight"),tableRowView:"Ember.Table.TableRow",tableRowViewClass:Ember.computed.alias("tableRowView"),onColumnSort:function(a,b){var c;return c=this.get("tableColumns"),c.removeObject(a),c.insertAt(b,a)},bodyContent:Ember.computed(function(){return Ember.Table.RowArrayController.create({target:this,parentController:this,container:this.get("container"),itemController:Ember.Table.Row,content:this.get("content")})}).property("content"),footerContent:Ember.computed(function(a,b){return b?b:Ember.A()}).property(),fixedColumns:Ember.computed(function(){var a,b;return(a=this.get("columns"))?(b=this.get("numFixedColumns")||0,a=a.slice(0,b)||[],this.prepareTableColumns(a),a):Ember.A()}).property("columns.@each","numFixedColumns"),tableColumns:Ember.computed(function(){var a,b;return(a=this.get("columns"))?(b=this.get("numFixedColumns")||0,a=a.slice(b,a.get("length"))||[],this.prepareTableColumns(a),a):Ember.A()}).property("columns.@each","numFixedColumns"),prepareTableColumns:function(a){return a.setEach("controller",this)},didInsertElement:function(){return this._super(),this.set("_tableScrollTop",0),this.elementSizeDidChange()},onResizeEnd:function(){return Ember.run(this,this.elementSizeDidChange)},elementSizeDidChange:function(){return"inDOM"===(this.get("_state")||this.get("state"))?(this.set("_width",this.$().parent().outerWidth()),this.set("_height",this.$().parent().outerHeight()),Ember.run.next(this,this.updateLayout)):void 0},updateLayout:function(){return"inDOM"===(this.get("_state")||this.get("state"))?(this.$(".antiscroll-wrap").antiscroll().data("antiscroll").rebuild(),this.get("forceFillColumns")?this.doForceFillColumns():void 0):void 0},doForceFillColumns:function(){var a,b,c,d,e,f,g,h;return h=this.get("_width"),e=this.get("_fixedColumnsWidth"),g=this.get("tableColumns"),d=this._getTotalWidth(g),b=h-e,f=b-d,c=g.filterProperty("canAutoResize"),a=Math.floor(f/c.length),c.forEach(function(b){var c;return c=b.get("columnWidth")+a,b.set("columnWidth",c)})},onBodyContentLengthDidChange:Ember.observer(function(){return Ember.run.next(this,function(){return Ember.run.once(this,this.updateLayout) +})},"bodyContent.length"),_tableScrollTop:0,_tableScrollLeft:0,_width:null,_height:null,_contentHeaderHeight:null,_hasVerticalScrollbar:Ember.computed(function(){var a,b;return b=this.get("_height"),a=this.get("_tableContentHeight")+this.get("_headerHeight")+this.get("_footerHeight"),a>b?!0:!1}).property("_height","_tableContentHeight","_headerHeight","_footerHeight"),_hasHorizontalScrollbar:Ember.computed(function(){var a,b;return a=this.get("_tableColumnsWidth"),b=this.get("_width")-this.get("_fixedColumnsWidth"),a>b?!0:!1}).property("_tableColumnsWidth","_width","_fixedColumnsWidth"),_tablesContainerHeight:Ember.computed(function(){var a,b;return b=this.get("_height"),a=this.get("_tableContentHeight")+this.get("_headerHeight")+this.get("_footerHeight"),b>a?a:b}).property("_height","_tableContentHeight","_headerHeight","_footerHeight"),_fixedColumnsWidth:Ember.computed(function(){return this._getTotalWidth(this.get("fixedColumns"))}).property("fixedColumns.@each.columnWidth"),_tableColumnsWidth:Ember.computed(function(){var a,b;return b=this._getTotalWidth(this.get("tableColumns"))+3,a=this.get("_width")-this.get("_fixedColumnsWidth"),b>a?b:a}).property("tableColumns.@each.columnWidth","_width","_fixedColumnsWidth"),_rowWidth:Ember.computed(function(){var a,b;return a=this.get("_tableColumnsWidth"),b=this.get("_tableContainerWidth")-this.get("_fixedColumnsWidth"),b>a?b:a}).property("_fixedColumnsWidth","_tableColumnsWidth","_tableContainerWidth"),_headerHeight:Ember.computed(function(){var a,b;return b=this.get("minHeaderHeight"),a=this.get("_contentHeaderHeight"),b>a?b:a}).property("_contentHeaderHeight","minHeaderHeight"),_footerHeight:Ember.computed(function(){return this.get("hasFooter")?this.get("footerHeight"):0}).property("footerHeight","hasFooter"),_bodyHeight:Ember.computed(function(){var a;return a=this.get("_tablesContainerHeight"),this.get("hasHeader")&&(a-=this.get("_headerHeight")),this.get("hasFooter")&&(a-=this.get("footerHeight")),a}).property("_tablesContainerHeight","_hasHorizontalScrollbar","_headerHeight","footerHeight","hasHeader","hasFooter"),_tableBlockWidth:Ember.computed(function(){return this.get("_width")-this.get("_fixedColumnsWidth")}).property("_width","_fixedColumnsWidth"),_fixedBlockWidthBinding:"_fixedColumnsWidth",_tableContentHeight:Ember.computed(function(){return this.get("rowHeight")*this.get("bodyContent.length")}).property("rowHeight","bodyContent.length"),_tableContainerWidth:Ember.computed(function(){return this.get("_width")}).property("_width"),_scrollContainerWidth:Ember.computed(function(){return this.get("_width")-this.get("_fixedColumnsWidth")}).property("_width","_fixedColumnsWidth"),_numItemsShowing:Ember.computed(function(){return Math.floor(this.get("_bodyHeight")/this.get("rowHeight"))}).property("_bodyHeight","rowHeight"),_startIndex:Ember.computed(function(){var a,b,c,d,e;return b=this.get("bodyContent.length"),c=this.get("_numItemsShowing"),d=this.get("rowHeight"),e=this.get("_tableScrollTop"),a=Math.floor(e/d),a+c>=b&&(a=b-c),0>a?0:a}).property("bodyContent.length","_numItemsShowing","rowHeight","_tableScrollTop"),_getTotalWidth:function(a,b){var c;return null==b&&(b="columnWidth"),a?(c=a.getEach(b)||[],c.reduce(function(a,b){return a+b},0)):0},isSelected:function(a){return this.get("_selection").contains(a)},setSelected:function(a,b){return this.persistSelection(),b?this.get("persistedSelection").add(a):this.get("persistedSelection").remove(a)},persistedSelection:Ember.computed(function(){return new Ember.Set}),rangeSelection:Ember.computed(function(){return new Ember.Set}),_selection:Ember.computed(function(){return this.get("persistedSelection").copy().addEach(this.get("rangeSelection"))}).property("persistedSelection.[]","rangeSelection.[]"),click:function(a){var b,c,d,e,f;return f=this.getRowForEvent(a),f&&"none"!==this.get("selectionMode")?"single"===this.get("selectionMode")?(this.get("persistedSelection").clear(),this.get("persistedSelection").add(f)):a.shiftKey?(this.get("rangeSelection").clear(),c=this.rowIndex(this.get("lastSelected")),b=this.rowIndex(this.getRowForEvent(a)),e=Math.min(c,b),d=Math.max(c,b),this.get("rangeSelection").addObjects(this.get("bodyContent").slice(e,d+1))):(a.ctrlKey||a.metaKey?this.persistSelection():(this.get("persistedSelection").clear(),this.get("rangeSelection").clear()),this.get("persistedSelection").contains(f)?this.get("persistedSelection").remove(f):this.get("persistedSelection").add(f),this.set("lastSelected",f)):void 0},findRow:function(a){var b,c,d,e;for(e=this.get("bodyContent"),c=0,d=e.length;d>c;c++)if(b=e[c],b.get("content")===a)return b},rowIndex:function(a){var b;return null!=(b=this.get("bodyContent"))?b.indexOf(a):void 0},persistSelection:function(){return this.get("persistedSelection").addEach(this.get("rangeSelection")),this.get("rangeSelection").clear()},getRowForEvent:function(a){var b,c;return b=$(a.target).parents(".ember-table-table-row"),c=Ember.View.views[b.attr("id")],c?c.get("row"):void 0}}),Ember.Handlebars.helper("table-component",Ember.Table.EmberTableComponent)}(); \ No newline at end of file diff --git a/package.json b/package.json index 5189229d7..6bfc60ed6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ember-table", - "version": "0.2.0", + "version": "0.2.2", "private": true, "main": "Gruntfile.js", "scripts": { @@ -27,6 +27,7 @@ "lockdown": "0.0.5", "grunt-banner": "~0.2.2", "grunt-text-replace": "~0.3.11", - "grunt-bower-task": "~0.3.4" + "grunt-bower-task": "~0.4.0", + "grunt-release-it": "~0.2.0" } } \ No newline at end of file diff --git a/src/column.coffee b/src/column.coffee index a5fc1381d..9197bc353 100644 --- a/src/column.coffee +++ b/src/column.coffee @@ -1,95 +1,75 @@ -###* - * Column Definition - * @class - * @alias Ember.Table.ColumnDefinition - ### Ember.Table.ColumnDefinition = Ember.Object.extend - # Name of the column - # TODO(Peter): change it to columnName - headerCellName:undefined - # Path of the content for this cell. Given a row object, the content path - # communicate what needs to be extracted from the row - contentPath: undefined - # Min column width + + # --------------------------------------------------------------------------- + # API - Inputs + # --------------------------------------------------------------------------- + + # Name of the column, to be displayed in the header. + # TODO(new-api): Change to `columnName` + headerCellName: undefined + + # Path of the content for this cell. If the row object is a hash of keys + # and values to specify data for each column, `contentPath` corresponds to + # the key. + contentPath: undefined + + # Minimum column width. Affects both manual resizing and automatic resizing + # (in `forceFillColumns` mode). minWidth: undefined - # Max column width + + # Maximum column width. Affects both manual resizing and automatic resizing + # (in `forceFillColumns` mode). maxWidth: undefined - # column width + + # Default column width. Specifies the initial width of the column; if the + # column is later resized automatically, it will be proportional to this. defaultColumnWidth: 150 - # TODO(Peter): Rename it to width - columnWidth: Ember.computed.oneWay 'defaultColumnWidth' - # wether the colum is resizable + + # Whether the column can be manually resized. isResizable: yes - # wether the column is sortable + + # Whether the column can be rearranged with other columns. Only matters if + # the table's `enableColumnReorder` property is set to true (the default). + # TODO(new-api): Rename to `isReorderable` isSortable: yes - # text align left | center | right + + # Alignment of the text in the cell. Possible values are "left", "center", + # and "right". textAlign: 'text-align-right' + + # Whether the column can automatically resize to fill space in the table. + # Only matters if the table is in `forceFillColumns` mode. canAutoResize: yes - # The view class we want to use for the header - headerCellViewClass: 'Ember.Table.HeaderCell' - # The view class we want to use for the table cells - tableCellViewClass: 'Ember.Table.TableCell' + # TODO(new-api): Remove `headerCellViewClass` + # Override to specify a custom view to use for the header cell. + headerCellView: 'Ember.Table.HeaderCell' + headerCellViewClass: Ember.computed.alias 'headerCellView' - resize: (width) -> @set 'columnWidth', width + # TODO(new-api): Remove `tableCellViewClass` + # Override to specify a custom view to use for table cells. + tableCellView: 'Ember.Table.TableCell' + tableCellViewClass: Ember.computed.alias 'tableCellView' - ###* - * Get Cell Content - This gives a formatted value e.g. $20,000,000 - * @memberof Ember.Table.ColumnDefinition - * @instance - * @argument row {Ember.Table.Row} - * @todo More detailed doc needed! - ### + # Override to customize how the column gets data from each row object. + # Given a row, should return a formatted cell value, e.g. $20,000,000. getCellContent: (row) -> path = @get 'contentPath' Ember.assert "You must either provide a contentPath or override " + "getCellContent in your column definition", path? Ember.get row, path - ###* - * Set Cell Content - * @memberof Ember.Table.ColumnDefinition - * @instance - ### + # Override to maintain a consistent path to update cell values. + # Recommended to make this a function which takes (row, value) and updates + # the row value. setCellContent: Ember.K -###* - * Table Row - * @class - * @alias Ember.Table.Row - ### -Ember.Table.Row = Ember.ObjectProxy.extend - ###* - * Content of the row - * @memberof Ember.Table.Row - * @member content - * @instance - ### - content: null - - ###* - * Is Selected? - * @memberof Ember.Table.Row - * @member {Boolean} isSelected - * @instance - ### - isSelected: Ember.computed -> - @get('parentController.selection') is @get('content') - .property 'parentController.selection', 'content' - - ###* - * Is Showing? - * @memberof Ember.Table.Row - * @member {Boolean} isShowing - * @instance - ### - isShowing: yes - - ###* - * Is Active? - * @memberof Ember.Table.Row - * @member {Boolean} isHovered - * @instance - ### - isHovered: no + # --------------------------------------------------------------------------- + # Internal properties + # --------------------------------------------------------------------------- + # Internal: width of the column. + # TODO: Rename to `width` + columnWidth: Ember.computed.oneWay 'defaultColumnWidth' + + resize: (width) -> @set 'columnWidth', width diff --git a/src/component.coffee b/src/component.coffee index e273e3b3f..772298210 100644 --- a/src/component.coffee +++ b/src/component.coffee @@ -1,69 +1,128 @@ -###* -* Table Component -* @class -* @alias Ember.Table.EmberTableComponent -### Ember.Table.EmberTableComponent = Ember.Component.extend Ember.AddeparMixins.StyleBindingsMixin, Ember.AddeparMixins.ResizeHandlerMixin, - layoutName: 'components/ember-table' - classNames: ['ember-table-tables-container'] + layoutName: 'components/ember-table' + classNames: ['ember-table-tables-container'] classNameBindings: ['enableContentSelection:ember-table-content-selectable'] - styleBindings: ['height'] - height: Ember.computed.alias '_tablesContainerHeight' - # Array of Ember.Table.ColumnDefinition + # --------------------------------------------------------------------------- + # API - Inputs + # --------------------------------------------------------------------------- + + # Values which are bound to the table's style attr. See + # `Ember.StyleBindingsMixin` documentation for more details. + styleBindings: ['height'] + + # An array of row objects. Usually a hash where the keys are column names and + # the values are the rows's values. However, could be any object, since each + # column can define a function to return the column value given the row + # object. See `Ember.Table.ColumnDefinition.getCellContent`. + content: null + + # An array of column definitions: see `Ember.Table.ColumnDefinition`. Allows + # each column to have its own configuration. columns: null - # The number of frozen column on the left table + # The number of fixed columns on the left side of the table. Fixed columns + # are always visible, even when the table is scrolled horizontally. numFixedColumns: 0 - # The number of footer rows + # The number of footer rows in the table. Footer rows appear at the bottom of + # the table and are always visible. + # TODO(new-api): Rename to `numFooterRows` numFooterRow: 0 - # The height per row. We need to know this for the lazy rendering. - # TODO: The following three variables should be shared with LESS file + # The row height in pixels. A consistent row height is necessary to calculate + # which rows are being shown, to enable lazy rendering. + # TODO: Currently must be kept in sync with the LESS file. rowHeight: 30 + # The minimum header height in pixels. Headers will grow in height if given + # more content than they can display. + # TODO: Currently must be kept in sync with the LESS file. minHeaderHeight: 30 + # The footer height in pixels. + # TODO: Currently must be kept in sync with the LESS file. footerHeight: 30 + # Enables or disables the header block. hasHeader: yes + # Enables or disables the footer block. + # TODO(new-api): Default to no hasFooter: yes + # If true, columns with `canAutoResize=true` (the default setting) will + # attempt to fill the width of the table when possible. After a column is + # manually resized, any other columns with `canAutoResize=true` will + # distribute the change in width between them. Once manually resized, a + # column will no longer automatically resize. forceFillColumns: no + # Allow the columns to be rearranged by drag-and-drop. Only columns with + # `isSortable=true` (the default setting) will be affected. enableColumnReorder: yes + # Allow users to select the content of table cells. enableContentSelection: no - selection: null - - # specify the view class to use for rendering the table rows - tableRowViewClass: 'Ember.Table.TableRow' + # Sets which row selection behavior to follow. Possible values are 'none' + # (clicking on a row does nothing), 'single' (clicking on a row selects it + # and deselects other rows), and 'multiple' (multiple rows can be selected + # through ctrl/cmd-click or shift-click). + selectionMode: 'single' + + # --------------------------------------------------------------------------- + # API - Outputs + # --------------------------------------------------------------------------- + + # An array of the rows currently selected. If `selectionMode` is set to + # 'single', the array will contain either one or zero elements. + selection: Ember.computed (key, val) -> + if arguments.length > 1 and val + if @get('selectionMode') is 'single' + @get('persistedSelection').clear() + @get('persistedSelection').add(@findRow val) + else + @get('persistedSelection').clear() + for content in val + @get('persistedSelection').add(@findRow content) + @get('rangeSelection').clear() + if @get('selectionMode') is 'single' + return @get('_selection')?[0]?.get('content') + else + return @get('_selection').toArray().map (row) -> row.get('content') + .property '_selection.[]', 'selectionMode' + + # --------------------------------------------------------------------------- + # Internal properties + # --------------------------------------------------------------------------- init: -> - this._super() + @_super() if !$.ui then throw 'Missing dependency: jquery-ui' if !$().mousewheel then throw 'Missing dependency: jquery-mousewheel' if !$().antiscroll then throw 'Missing dependency: antiscroll.js' + # TODO: Document actions: addColumn: Ember.K sortByColumn: Ember.K + height: Ember.computed.alias '_tablesContainerHeight' + + # TODO(new-api): eliminate view alias + # specify the view class to use for rendering the table rows + tableRowView: 'Ember.Table.TableRow' + tableRowViewClass: Ember.computed.alias 'tableRowView' + onColumnSort: (column, newIndex) -> columns = @get 'tableColumns' columns.removeObject column columns.insertAt newIndex, column - ###* - * Table Body Content - Array of Ember.Table.Row - * @memberof Ember.Table.EmberTableComponent - * @instance - ### + # An array of Ember.Table.Row computed based on `content` bodyContent: Ember.computed -> Ember.Table.RowArrayController.create target: this @@ -73,21 +132,11 @@ Ember.AddeparMixins.ResizeHandlerMixin, content: @get('content') .property 'content' - ###* - * Table Footer Content - Array of Ember.Table.Row - * @memberof Ember.Table.EmberTableComponent - * @instance - ### + # An array of Ember.Table.Row footerContent: Ember.computed (key, value) -> if value then value else Ember.A() .property() - ###* - * Table Fixed Columns - * @memberof Ember.Table.EmberTableComponent - * @instance - * @todo Much more doc needed - ### fixedColumns: Ember.computed -> columns = @get 'columns' return Ember.A() unless columns @@ -97,12 +146,6 @@ Ember.AddeparMixins.ResizeHandlerMixin, columns .property 'columns.@each', 'numFixedColumns' - ###* - * Table Columns - * @memberof Ember.Table.EmberTableComponent - * @instance - * @todo Much more doc needed - ### tableColumns: Ember.computed -> columns = @get 'columns' return Ember.A() unless columns @@ -115,19 +158,15 @@ Ember.AddeparMixins.ResizeHandlerMixin, prepareTableColumns: (columns) -> columns.setEach 'controller', this - ############################################################################## + # --------------------------------------------------------------------------- # View concerns - ############################################################################## + # --------------------------------------------------------------------------- + didInsertElement: -> @_super() @set '_tableScrollTop', 0 @elementSizeDidChange() - ###* - * On resize end callback - * @memberof Ember.Table.EmberTableComponent - * @instance - ### onResizeEnd: -> # we need to put this on the run loop, because resize event came from # window. Otherwise, we get this warning when used in tests. You have @@ -136,13 +175,8 @@ Ember.AddeparMixins.ResizeHandlerMixin, # Ember.run Ember.run this, @elementSizeDidChange - ###* - * Element size did change callback - * @memberof Ember.Table.EmberTableComponent - * @instance - ### elementSizeDidChange: -> - return unless @get('state') is 'inDOM' + return unless (@get('_state') or @get('state')) is 'inDOM' @set '_width', @$().parent().outerWidth() @set '_height', @$().parent().outerHeight() # we need to wait for the table to be fully rendered before antiscroll can @@ -151,7 +185,7 @@ Ember.AddeparMixins.ResizeHandlerMixin, updateLayout: -> # updating antiscroll - return unless @get('state') is 'inDOM' + return unless (@get('_state') or @get('state')) is 'inDOM' this.$('.antiscroll-wrap').antiscroll().data('antiscroll').rebuild(); @doForceFillColumns() if @get('forceFillColumns') @@ -173,9 +207,10 @@ Ember.AddeparMixins.ResizeHandlerMixin, Ember.run.next this, -> Ember.run.once this, @updateLayout , 'bodyContent.length' - ############################################################################## - # private variables - ############################################################################## + # --------------------------------------------------------------------------- + # Private variables + # --------------------------------------------------------------------------- + _tableScrollTop: 0 _tableScrollLeft: 0 @@ -204,22 +239,12 @@ Ember.AddeparMixins.ResizeHandlerMixin, if contentHeight < height then contentHeight else height .property('_height', '_tableContentHeight', '_headerHeight', '_footerHeight') - ###* - * Actual width of the fixed columns (frozen columns) - * @memberof Ember.Table.EmberTableComponent - * @instance - * @private - ### + # Actual width of the fixed columns _fixedColumnsWidth: Ember.computed -> @_getTotalWidth @get('fixedColumns') .property 'fixedColumns.@each.columnWidth' - ###* - * Actual width of the table columns (non-frozen columns) - * @memberof Ember.Table.EmberTableComponent - * @instance - * @private - ### + # Actual width of the (non-fixed) columns _tableColumnsWidth: Ember.computed -> # Hack: We add 3px padding to the right of the table content so that we can # reorder into the last column. @@ -228,12 +253,6 @@ Ember.AddeparMixins.ResizeHandlerMixin, if contentWidth > availableWidth then contentWidth else availableWidth .property 'tableColumns.@each.columnWidth', '_width', '_fixedColumnsWidth' - ###* - * Computed Row Width - * @memberof Ember.Table.EmberTableComponent - * @instance - * @private - ### _rowWidth: Ember.computed -> columnsWidth = @get '_tableColumnsWidth' nonFixedTableWidth = @get('_tableContainerWidth') - @get('_fixedColumnsWidth') @@ -241,24 +260,18 @@ Ember.AddeparMixins.ResizeHandlerMixin, columnsWidth .property '_fixedColumnsWidth', '_tableColumnsWidth', '_tableContainerWidth' - # Dynamic Header Height that adjusts according to the header content height + # Dynamic header height that adjusts according to the header content height _headerHeight: Ember.computed -> minHeight = @get('minHeaderHeight') contentHeaderHeight = @get('_contentHeaderHeight') if contentHeaderHeight < minHeight then minHeight else contentHeaderHeight .property('_contentHeaderHeight', 'minHeaderHeight') - # Dynamic Header Height that adjusts according to the header content height + # Dynamic footer height that adjusts according to the footer content height _footerHeight: Ember.computed -> if @get('hasFooter') then @get('footerHeight') else 0 .property('footerHeight', 'hasFooter') - ###* - * Computed Body Height - * @memberof Ember.Table.EmberTableComponent - * @instance - * @private - ### _bodyHeight: Ember.computed -> bodyHeight = @get '_tablesContainerHeight' bodyHeight -= @get('_headerHeight') if @get('hasHeader') @@ -267,64 +280,28 @@ Ember.AddeparMixins.ResizeHandlerMixin, .property('_tablesContainerHeight', '_hasHorizontalScrollbar', '_headerHeight', 'footerHeight', 'hasHeader', 'hasFooter') - ###* - * Computed Table Block Width - * @memberof Ember.Table.EmberTableComponent - * @instance - * @private - ### _tableBlockWidth: Ember.computed -> @get('_width') - @get('_fixedColumnsWidth') .property '_width', '_fixedColumnsWidth' _fixedBlockWidthBinding: '_fixedColumnsWidth' - ###* - * Computed Table Content Height - * @memberof Ember.Table.EmberTableComponent - * @instance - * @private - ### _tableContentHeight: Ember.computed -> @get('rowHeight') * @get('bodyContent.length') .property 'rowHeight', 'bodyContent.length' - ###* - * Table Container Width - * @memberof Ember.Table.EmberTableComponent - * @instance - * @private - ### _tableContainerWidth: Ember.computed -> @get('_width') .property '_width' - ###* - * Computed Scroll Container Width - * @memberof Ember.Table.EmberTableComponent - * @instance - * @private - ### _scrollContainerWidth: Ember.computed -> @get('_width') - @get('_fixedColumnsWidth') .property '_width', '_fixedColumnsWidth' - ###* - * Computed number of items showing - * @memberof Ember.Table.EmberTableComponent - * @instance - * @private - ### _numItemsShowing: Ember.computed -> Math.floor @get('_bodyHeight') / @get('rowHeight') .property '_bodyHeight', 'rowHeight' - ###* - * Computed Start Index - * @memberof Ember.Table.EmberTableComponent - * @instance - * @raw - ### _startIndex: Ember.computed -> numContent = @get 'bodyContent.length' numViews = @get '_numItemsShowing' @@ -338,25 +315,78 @@ Ember.AddeparMixins.ResizeHandlerMixin, .property('bodyContent.length', '_numItemsShowing', 'rowHeight', '_tableScrollTop') - ###* - * Get Total Width - * @memberof Ember.Table.EmberTableComponent - * @instance - * @private - * @argument columns Columns to calculate width for - ### _getTotalWidth: (columns, columnWidthPath = 'columnWidth') -> return 0 unless columns widths = columns.getEach(columnWidthPath) or [] widths.reduce ((total, w) -> total + w), 0 - ############################################################################## - # selection - ############################################################################## + # --------------------------------------------------------------------------- + # Selection + # TODO: Make private or reorganize into a new section + # --------------------------------------------------------------------------- + + isSelected: (row) -> + @get('_selection').contains row + + setSelected: (row, val) -> + @persistSelection() + if val + @get('persistedSelection').add row + else + @get('persistedSelection').remove row + + # rows that were selected directly or as part of a previous + # range selection (shift-click) + persistedSelection: Ember.computed -> new Ember.Set() + + # rows that are part of the currently editable range selection + rangeSelection: Ember.computed -> new Ember.Set() + + _selection: Ember.computed -> + @get('persistedSelection').copy().addEach(@get('rangeSelection')) + .property 'persistedSelection.[]', 'rangeSelection.[]' + click: (event) -> row = @getRowForEvent event return unless row - @set 'selection', row.get('content') + return if @get('selectionMode') is 'none' + if @get('selectionMode') is 'single' + @get('persistedSelection').clear() + @get('persistedSelection').add row + else + if event.shiftKey + @get('rangeSelection').clear() + + lastIndex = @rowIndex(@get('lastSelected')) + curIndex = @rowIndex(@getRowForEvent(event)) + + minIndex = Math.min(lastIndex, curIndex) + maxIndex = Math.max(lastIndex, curIndex) + + @get('rangeSelection').addObjects @get('bodyContent').slice(minIndex, maxIndex + 1) + else + if !event.ctrlKey && !event.metaKey + @get('persistedSelection').clear() + @get('rangeSelection').clear() + else + @persistSelection() + if @get('persistedSelection').contains row + @get('persistedSelection').remove row + else + @get('persistedSelection').add row + @set('lastSelected', row) + + findRow: (content) -> + for row in @get('bodyContent') + if row.get('content') is content + return row + + rowIndex: (row) -> + @get('bodyContent')?.indexOf(row) + + persistSelection: () -> + @get('persistedSelection').addEach(@get('rangeSelection')) + @get('rangeSelection').clear() getRowForEvent: (event) -> $rowView = $(event.target).parents('.ember-table-table-row') diff --git a/src/main.coffee b/src/main.coffee index 4cfdee9f2..323aa9745 100644 --- a/src/main.coffee +++ b/src/main.coffee @@ -2,7 +2,7 @@ require 'build/src/templates' ## Used for bundling files together using neuter Ember.Table = Ember.Namespace.create() -Ember.Table.VERSION = '0.2.0' +Ember.Table.VERSION = '0.2.2' Ember.libraries?.register 'Ember Table', Ember.Table.VERSION @@ -17,5 +17,6 @@ require 'build/src/utils/utils' # Ember-Table require 'build/src/column' +require 'build/src/row' require 'build/src/views' require 'build/src/component' diff --git a/src/row.coffee b/src/row.coffee new file mode 100644 index 000000000..1ac50740d --- /dev/null +++ b/src/row.coffee @@ -0,0 +1,12 @@ +Ember.Table.Row = Ember.ObjectProxy.extend + content: null + + isSelected: Ember.computed (key, val) -> + if arguments.length > 1 + @get('parentController').setSelected this, val + @get('parentController').isSelected this + .property 'parentController._selection.[]' + + isShowing: yes + + isHovered: no diff --git a/src/templates/body-container.hbs b/src/templates/body-container.hbs index 1a07364b8..11f09df70 100644 --- a/src/templates/body-container.hbs +++ b/src/templates/body-container.hbs @@ -1,14 +1,16 @@
- {{view Ember.Table.LazyTableBlock classNames="ember-table-left-table-block" - contentBinding="controller.bodyContent" - columnsBinding="controller.fixedColumns" - widthBinding="controller._fixedBlockWidth" - numItemsShowingBinding="controller._numItemsShowing" - scrollTopBinding="controller._scrollTop" - startIndexBinding="controller._startIndex" - }} + {{#if controller.numFixedColumns}} + {{view Ember.Table.LazyTableBlock classNames="ember-table-left-table-block" + contentBinding="controller.bodyContent" + columnsBinding="controller.fixedColumns" + widthBinding="controller._fixedBlockWidth" + numItemsShowingBinding="controller._numItemsShowing" + scrollTopBinding="controller._scrollTop" + startIndexBinding="controller._startIndex" + }} + {{/if}} {{view Ember.Table.LazyTableBlock classNames="ember-table-right-table-block" contentBinding="controller.bodyContent" columnsBinding="controller.tableColumns" diff --git a/src/templates/footer-container.hbs b/src/templates/footer-container.hbs index 4c256c003..a4ba8287d 100644 --- a/src/templates/footer-container.hbs +++ b/src/templates/footer-container.hbs @@ -1,10 +1,12 @@
- {{view Ember.Table.TableBlock classNames="ember-table-left-table-block" - contentBinding="controller.footerContent" - columnsBinding="controller.fixedColumns" - widthBinding="controller._fixedBlockWidth" - heightBinding="controller.footerHeight" - }} + {{#if controller.numFixedColumns}} + {{view Ember.Table.TableBlock classNames="ember-table-left-table-block" + contentBinding="controller.footerContent" + columnsBinding="controller.fixedColumns" + widthBinding="controller._fixedBlockWidth" + heightBinding="controller.footerHeight" + }} + {{/if}} {{view Ember.Table.TableBlock classNames="ember-table-right-table-block" contentBinding="controller.footerContent" columnsBinding="controller.tableColumns" diff --git a/src/templates/header-cell.hbs b/src/templates/header-cell.hbs index f8269283c..fb512c31e 100644 --- a/src/templates/header-cell.hbs +++ b/src/templates/header-cell.hbs @@ -1,4 +1,4 @@ -
+
{{view.content.headerCellName}} diff --git a/src/templates/header-container.hbs b/src/templates/header-container.hbs index ef0b7c13f..cd456d77e 100644 --- a/src/templates/header-container.hbs +++ b/src/templates/header-container.hbs @@ -1,9 +1,11 @@
- {{view Ember.Table.HeaderBlock classNames="ember-table-left-table-block" - columnsBinding="controller.fixedColumns" - widthBinding="controller._fixedBlockWidth" - heightBinding="controller.headerHeight" - }} + {{#if controller.numFixedColumns}} + {{view Ember.Table.HeaderBlock classNames="ember-table-left-table-block" + columnsBinding="controller.fixedColumns" + widthBinding="controller._fixedBlockWidth" + heightBinding="controller.headerHeight" + }} + {{/if}} {{view Ember.Table.HeaderBlock classNames="ember-table-right-table-block" columnsBinding="controller.tableColumns" scrollLeftBinding="controller._tableScrollLeft" diff --git a/src/utils/lazy_container_view.coffee b/src/utils/lazy_container_view.coffee index 0c70552b6..0a95e1a44 100644 --- a/src/utils/lazy_container_view.coffee +++ b/src/utils/lazy_container_view.coffee @@ -23,7 +23,15 @@ Ember.ContainerView.extend Ember.AddeparMixins.StyleBindingsMixin, onNumChildViewsDidChange: Ember.observer -> view = this # We are getting the class from a string e.g. "Ember.Table.Row" - itemViewClass = Ember.get @get('itemViewClass') + itemViewClass = @get('itemViewClass') + if typeof itemViewClass is 'string' + if /[A-Z]+/.exec itemViewClass + # Global var lookup - 'App.MessagePreviewView' + itemViewClass = Ember.get Ember.lookup, itemViewClass + else + # Ember CLI Style lookup - 'message/preview' + itemViewClass = @container.lookupFactory "view:#{itemViewClass}" + newNumViews = @get 'numChildViews' return unless itemViewClass and newNumViews oldNumViews = @get('length') diff --git a/src/utils/utils.coffee b/src/utils/utils.coffee index f27210807..5e5d9706a 100644 --- a/src/utils/utils.coffee +++ b/src/utils/utils.coffee @@ -11,7 +11,13 @@ Ember.CollectionView.extend Ember.AddeparMixins.StyleBindingsMixin, itemViewClassField = @get 'itemViewClassField' itemViewClass = attrs.content.get(itemViewClassField) if typeof itemViewClass is 'string' - itemViewClass = Ember.get Ember.lookup, itemViewClass + if /[A-Z]+/.exec itemViewClass + # Global var lookup - 'App.MessagePreviewView' + itemViewClass = Ember.get Ember.lookup, itemViewClass + else + # Ember CLI Style lookup - 'message/preview' + itemViewClass = @container.lookupFactory "view:#{itemViewClass}" + @_super(itemViewClass, attrs) Ember.MouseWheelHandlerMixin = Ember.Mixin.create diff --git a/src/views.coffee b/src/views.coffee index e7053a168..261bfffcf 100644 --- a/src/views.coffee +++ b/src/views.coffee @@ -1,21 +1,10 @@ -###* -* Table Container -* @class -* @alias Ember.Table.TableContainer -* @mixes Ember.AddeparMixins.StyleBindingsMixin -### Ember.Table.TableContainer = Ember.View.extend Ember.AddeparMixins.StyleBindingsMixin, classNames: ['ember-table-table-container'] styleBindings: ['height', 'width'] -###* -* Table Block -* @class -* @alias Ember.Table.TableBlock -* @mixes Ember.AddeparMixins.StyleBindingsMixin -* @todo This should be a mixin -### + +# TODO: This should be a mixin Ember.Table.TableBlock = Ember.CollectionView.extend Ember.AddeparMixins.StyleBindingsMixin, classNames: ['ember-table-table-block'] @@ -25,11 +14,6 @@ Ember.CollectionView.extend Ember.AddeparMixins.StyleBindingsMixin, content: null scrollLeft: null - ###* - * On scroll left did change callback - * @memberof Ember.Table.TableBlock - * @instance - ### onScrollLeftDidChange: Ember.observer -> @$().scrollLeft @get('scrollLeft') , 'scrollLeft' @@ -38,11 +22,7 @@ Ember.CollectionView.extend Ember.AddeparMixins.StyleBindingsMixin, @get('controller._headerHeight') .property('controller._headerHeight') -###* -* Lazy Table Block -* @class -* @alias Ember.Table.LazyTableBlock -### + Ember.Table.LazyTableBlock = Ember.LazyContainerView.extend classNames: ['ember-table-table-block'] styleBindings: ['width'] @@ -53,20 +33,11 @@ Ember.Table.LazyTableBlock = Ember.LazyContainerView.extend scrollLeft: null scrollTop: null - ###* - * On scroll left did change callback - * @memberof Ember.Table.LazyTableBlock - * @instance - ### onScrollLeftDidChange: Ember.observer -> @$().scrollLeft @get('scrollLeft') , 'scrollLeft' -###* -* Table Row -* @class -* @alias Ember.Table.TableRow -### + Ember.Table.TableRow = Ember.LazyItemView.extend templateName: 'table-row' classNames: 'ember-table-table-row' @@ -82,56 +53,45 @@ Ember.Table.TableRow = Ember.LazyItemView.extend @get('row') is @get('controller.bodyContent.lastObject') .property 'controller.bodyContent.lastObject', 'row' - ###* - * Mouse enter callback - * @memberof Ember.Table.TableRow - * @instance - * @param event jQuery event - ### mouseEnter: (event) -> row = @get 'row' row.set 'isHovered', yes if row - ###* - * Mouse leave callback - * @memberof Ember.Table.TableRow - * @instance - * @param event jQuery event - ### mouseLeave: (event) -> row = @get 'row' row.set 'isHovered', no if row - ###* - * Teardown content - * @memberof Ember.Table.TableRow - * @instance - ### teardownContent: -> row = @get 'row' row.set 'isHovered', no if row -###* -* Table Cell -* @class -* @alias Ember.Table.TableCell -* @mixes Ember.AddeparMixins.StyleBindingsMixin -### + Ember.Table.TableCell = Ember.View.extend Ember.AddeparMixins.StyleBindingsMixin, - templateName: 'table-cell' + + # --------------------------------------------------------------------------- + # API - Inputs + # --------------------------------------------------------------------------- + + # TODO: Doc + templateName: 'table-cell' classNames: ['ember-table-cell'] classNameBindings: 'column.textAlign' styleBindings: 'width' - row: Ember.computed.alias 'parentView.row' - column: Ember.computed.alias 'content' - width: Ember.computed.alias 'column.columnWidth' + + # --------------------------------------------------------------------------- + # Internal properties + # --------------------------------------------------------------------------- init: -> @_super() @contentPathDidChange() @contentDidChange() + row: Ember.computed.alias 'parentView.row' + column: Ember.computed.alias 'content' + width: Ember.computed.alias 'column.columnWidth' + contentDidChange: -> @notifyPropertyChange 'cellContent' @@ -147,11 +107,6 @@ Ember.View.extend Ember.AddeparMixins.StyleBindingsMixin, @addObserver("row.#{contentPath}", this, this.contentDidChange) ).observesBefore 'column.contentPath' - ###* - * Computed Cell Content - * @memberof Ember.Table.TableCell - * @instance - ### cellContent: Ember.computed (key, value) -> row = @get 'row' column = @get 'column' @@ -163,36 +118,18 @@ Ember.View.extend Ember.AddeparMixins.StyleBindingsMixin, value .property 'row.isLoaded', 'column' -################################################################################ -###* -* HeaderBlock -* @class -* @alias Ember.Table.HeaderBlock -* @augments Ember.Table.TableBlock -### Ember.Table.HeaderBlock = Ember.Table.TableBlock.extend classNames: ['ember-table-header-block'] itemViewClass: 'Ember.Table.HeaderRow' - ###* - * Computed Content - * @memberof Ember.Table.HeaderBlock - * @instance - ### content: Ember.computed -> [@get('columns')] .property 'columns' + # We hacked this. There is an inconsistency at the level in which we are # handling scroll event... - -###* -* Header Row -* @class -* @alias Ember.Table.HeaderRow -* @mixes Ember.AddeparMixins.StyleBindingsMixin -### Ember.Table.HeaderRow = Ember.View.extend Ember.AddeparMixins.StyleBindingsMixin, templateName: 'header-row' @@ -202,11 +139,7 @@ Ember.View.extend Ember.AddeparMixins.StyleBindingsMixin, width: Ember.computed.alias 'controller._rowWidth' scrollLeft: Ember.computed.alias 'controller._tableScrollLeft' - ###* - * Options for jQuery UI sortable - * @memberof Ember.Table.HeaderRow - * @instance - ### + # Options for jQuery UI sortable sortableOption: Ember.computed -> axis: 'x' containment: 'parent' @@ -250,29 +183,31 @@ Ember.View.extend Ember.AddeparMixins.StyleBindingsMixin, @get('controller').onColumnSort column, newIndex @set 'controller._isShowingSortableIndicator', no -###* -* Header Cell -* @class -* @alias Ember.Table.HeaderCell -* @mixes Ember.AddeparMixins.StyleBindingsMixin -### + Ember.Table.HeaderCell = Ember.View.extend Ember.AddeparMixins.StyleBindingsMixin, + + # --------------------------------------------------------------------------- + # API - Inputs + # --------------------------------------------------------------------------- + + # TODO: Doc templateName: 'header-cell' classNames: ['ember-table-cell', 'ember-table-header-cell'] classNameBindings: ['column.isSortable:sortable', 'column.textAlign'] styleBindings: ['width', 'height'] + + # --------------------------------------------------------------------------- + # Internal properties + # --------------------------------------------------------------------------- + column: Ember.computed.alias 'content' width: Ember.computed.alias 'column.columnWidth' height: Ember.computed -> @get('controller._headerHeight') .property('controller._headerHeight') - ###* - * jQuery UI resizable option - * @memberof Ember.Table.HeaderCell - * @instance - ### + # jQuery UI resizable option resizableOption: Ember.computed -> handles: 'e' minHeight: 40 @@ -282,11 +217,6 @@ Ember.View.extend Ember.AddeparMixins.StyleBindingsMixin, resize: jQuery.proxy(@onColumnResize, this) stop: jQuery.proxy(@onColumnResize, this) - ###* - * Did insert element callback - * @memberof Ember.Table.HeaderCell - * @instance - ### didInsertElement: -> @elementSizeDidChange() if @get('column.isResizable') @@ -294,12 +224,7 @@ Ember.View.extend Ember.AddeparMixins.StyleBindingsMixin, @_resizableWidget = @$().resizable('widget') return - ###* - * On column resize callback - * @memberof Ember.Table.HeaderCell - * @instance - * @argument event jQuery event - ### + # `event` here is a jQuery event onColumnResize: (event, ui) -> @elementSizeDidChange() # Special case for force-filled columns: if this is the last column you @@ -319,7 +244,6 @@ Ember.View.extend Ember.AddeparMixins.StyleBindingsMixin, @set 'controller._contentHeaderHeight', maxHeight return -################################################################################ Ember.Table.ColumnSortableIndicator = Ember.View.extend Ember.AddeparMixins.StyleBindingsMixin, @@ -329,14 +253,7 @@ Ember.View.extend Ember.AddeparMixins.StyleBindingsMixin, left: Ember.computed.alias 'controller._sortableIndicatorLeft' height: Ember.computed.alias 'controller._height' -###* -* Header Table Container -* @class -* @alias Ember.Table.HeaderTableContainer -* @augments Ember.Table.TableContainer -* @mixes Ember.MouseWheelHandlerMixin -* @mixes Ember.TouchMoveHandlerMixin -### + Ember.Table.HeaderTableContainer = Ember.Table.TableContainer.extend Ember.Table.ShowHorizontalScrollMixin, templateName: 'header-container' @@ -346,14 +263,7 @@ Ember.Table.TableContainer.extend Ember.Table.ShowHorizontalScrollMixin, height: Ember.computed.alias 'controller._headerHeight' width: Ember.computed.alias 'controller._tableContainerWidth' -###* -* Body Table Container -* @class -* @alias Ember.Table.BodyTableContainer -* @mixes Ember.MouseWheelHandlerMixin -* @mixes Ember.TouchMoveHandlerMixin -* @mixes Ember.ScrollHandlerMixin -### + Ember.Table.BodyTableContainer = Ember.Table.TableContainer.extend Ember.MouseWheelHandlerMixin, Ember.TouchMoveHandlerMixin, Ember.ScrollHandlerMixin, @@ -367,52 +277,25 @@ Ember.Table.ShowHorizontalScrollMixin, scrollLeft: Ember.computed.alias 'controller._tableScrollLeft' scrollElementSelector: '.antiscroll-inner' - ###* - * On scroll callback - * @memberof Ember.Table.BodyTableContainer - * @instance - * @argument event jQuery event - ### + # `event` here is a jQuery event onScroll: (event) -> @set 'scrollTop', event.target.scrollTop event.preventDefault() - ###* - * On mouse wheel callback callback - * @memberof Ember.Table.BodyTableContainer - * @instance - * @argument event jQuery event - * @argument delta - * @argument deltaX {Integer} - * @argument deltaY {Integer} - ### + # `event` here is a jQuery event onMouseWheel: (event, delta, deltaX, deltaY) -> return unless Math.abs(deltaX) > Math.abs(deltaY) scrollLeft = @$('.ember-table-right-table-block').scrollLeft() + deltaX @set 'scrollLeft', scrollLeft event.preventDefault() - ###* - * On touch move callback - * @memberof Ember.Table.BodyTableContainer - * @instance - * @argument event jQuery event - * @argument deltaX {Integer} - * @argument deltaY {Integer} - ### onTouchMove: (event, deltaX, deltaY) -> return unless (Math.abs(deltaX) > Math.abs(deltaY)) scrollLeft = @$('.ember-table-right-table-block').scrollLeft() + deltaX @set 'scrollLeft', scrollLeft event.preventDefault() -###* -* Footer Table Container -* @class -* @alias Ember.Table.FooterTableContainer -* @mixes Ember.MouseWheelHandlerMixin -* @mixes Ember.TouchMoveHandlerMixin -### + Ember.Table.FooterTableContainer = Ember.Table.TableContainer.extend Ember.MouseWheelHandlerMixin, Ember.TouchMoveHandlerMixin, Ember.Table.ShowHorizontalScrollMixin, @@ -442,13 +325,7 @@ Ember.TouchMoveHandlerMixin, Ember.Table.ShowHorizontalScrollMixin, @set 'scrollLeft', scrollLeft event.preventDefault() -###* -* Scroll Container -* @class -* @alias Ember.Table.ScrollContainer -* @mixes Ember.AddeparMixins.StyleBindingsMixin -* @mixes Ember.ScrollHandlerMixin -### + Ember.Table.ScrollContainer = Ember.View.extend Ember.AddeparMixins.StyleBindingsMixin, Ember.ScrollHandlerMixin, @@ -470,32 +347,17 @@ Ember.ScrollHandlerMixin, @_super() @onScrollLeftDidChange() - ###* - * On scroll callback - * @memberof Ember.Table.ScrollContainer - * @instance - * @argument event jQuery event - ### + # `event` here is a jQuery event onScroll: (event) -> @set 'scrollLeft', event.target.scrollLeft event.preventDefault() - ###* - * On scroll left did change observer - * @memberof Ember.Table.ScrollContainer - * @instance - ### onScrollLeftDidChange: Ember.observer -> selector = @get('scrollElementSelector') @$(selector).scrollLeft @get('scrollLeft') , 'scrollLeft', 'scrollElementSelector' -###* -* ScrollPanel -* @class -* @alias Ember.Table.ScrollPanel -* @mixes Ember.AddeparMixins.StyleBindingsMixin -### + Ember.Table.ScrollPanel = Ember.View.extend Ember.AddeparMixins.StyleBindingsMixin, classNames: ['ember-table-scroll-panel'] styleBindings: ['width', 'height'] diff --git a/tests/index.html b/tests/index.html index 27ecc7a4b..a0b97ca17 100644 --- a/tests/index.html +++ b/tests/index.html @@ -10,13 +10,13 @@ - - - + + + - +