faalis 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (286) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +339 -0
  3. data/README.md +45 -0
  4. data/Rakefile +42 -0
  5. data/app/assets/fonts/DroidNaskh-Bold.ttf +0 -0
  6. data/app/assets/fonts/DroidNaskh-Regular.ttf +0 -0
  7. data/app/assets/fonts/OpenSans-Bold.ttf +0 -0
  8. data/app/assets/fonts/OpenSans-BoldItalic.ttf +0 -0
  9. data/app/assets/fonts/OpenSans-ExtraBold.ttf +0 -0
  10. data/app/assets/fonts/OpenSans-ExtraBoldItalic.ttf +0 -0
  11. data/app/assets/fonts/OpenSans-Italic.ttf +0 -0
  12. data/app/assets/fonts/OpenSans-Light.ttf +0 -0
  13. data/app/assets/fonts/OpenSans-LightItalic.ttf +0 -0
  14. data/app/assets/fonts/OpenSans-Regular.ttf +0 -0
  15. data/app/assets/fonts/OpenSans-Semibold.ttf +0 -0
  16. data/app/assets/fonts/OpenSans-SemiboldItalic.ttf +0 -0
  17. data/app/assets/images/faalis/select2-spinner.gif +0 -0
  18. data/app/assets/images/faalis/select2.png +0 -0
  19. data/app/assets/images/faalis/select2x2.png +0 -0
  20. data/app/assets/javascripts/faalis/application.js +20 -0
  21. data/app/assets/javascripts/faalis/dashboard/angular.js +9 -0
  22. data/app/assets/javascripts/faalis/dashboard/app.js +75 -0
  23. data/app/assets/javascripts/faalis/dashboard/application.js.erb +21 -0
  24. data/app/assets/javascripts/faalis/dashboard/functions.js.erb +91 -0
  25. data/app/assets/javascripts/faalis/dashboard/init.js +38 -0
  26. data/app/assets/javascripts/faalis/dashboard/lib/angular-animate.js +1226 -0
  27. data/app/assets/javascripts/faalis/dashboard/lib/angular-gettext.js +202 -0
  28. data/app/assets/javascripts/faalis/dashboard/lib/angular-resource.js +578 -0
  29. data/app/assets/javascripts/faalis/dashboard/lib/angular-route.js +880 -0
  30. data/app/assets/javascripts/faalis/dashboard/lib/angular.js +20031 -0
  31. data/app/assets/javascripts/faalis/dashboard/lib/lodash.underscore.js +4893 -0
  32. data/app/assets/javascripts/faalis/dashboard/lib/ng-grid.js +3260 -0
  33. data/app/assets/javascripts/faalis/dashboard/lib/ng-quick-date.js +297 -0
  34. data/app/assets/javascripts/faalis/dashboard/lib/restangular.js +1066 -0
  35. data/app/assets/javascripts/faalis/dashboard/lib/select2.js +3255 -0
  36. data/app/assets/javascripts/faalis/dashboard/lib/ui.select2.js +217 -0
  37. data/app/assets/javascripts/faalis/dashboard/locale/translations.js +5 -0
  38. data/app/assets/javascripts/faalis/dashboard/modules/anim.js +32 -0
  39. data/app/assets/javascripts/faalis/dashboard/modules/api.js +32 -0
  40. data/app/assets/javascripts/faalis/dashboard/modules/auth/auth.js +34 -0
  41. data/app/assets/javascripts/faalis/dashboard/modules/auth/group.js +174 -0
  42. data/app/assets/javascripts/faalis/dashboard/modules/auth/profile.js +59 -0
  43. data/app/assets/javascripts/faalis/dashboard/modules/auth/user.js +123 -0
  44. data/app/assets/javascripts/faalis/dashboard/modules/errors.js +47 -0
  45. data/app/assets/javascripts/faalis/dashboard/modules/filter.js +44 -0
  46. data/app/assets/javascripts/faalis/dashboard/modules/list-view.js +310 -0
  47. data/app/assets/javascripts/faalis/dashboard/modules/logs.js +41 -0
  48. data/app/assets/javascripts/faalis/dashboard/modules/modules.js +50 -0
  49. data/app/assets/javascripts/faalis/dashboard/modules/nav.js.erb +97 -0
  50. data/app/assets/javascripts/faalis/dashboard/templates/application.handlebars.erb +42 -0
  51. data/app/assets/javascripts/faalis/dashboard/templates/auth/groups/details.handlebars.erb +15 -0
  52. data/app/assets/javascripts/faalis/dashboard/templates/auth/groups/index.handlebars.erb +7 -0
  53. data/app/assets/javascripts/faalis/dashboard/templates/auth/groups/new.handlebars.erb +39 -0
  54. data/app/assets/javascripts/faalis/dashboard/templates/auth/index.handlebars.erb +31 -0
  55. data/app/assets/javascripts/faalis/dashboard/templates/auth/users/details.handlebars.erb +15 -0
  56. data/app/assets/javascripts/faalis/dashboard/templates/auth/users/index.handlebars.erb +11 -0
  57. data/app/assets/javascripts/faalis/dashboard/templates/auth/users/new.handlebars.erb +33 -0
  58. data/app/assets/javascripts/faalis/dashboard/templates/components/list-view.handlebars.erb +59 -0
  59. data/app/assets/javascripts/faalis/dashboard/templates/components/model-form.handlebars.erb +3 -0
  60. data/app/assets/javascripts/faalis/dashboard/templates/modules.handlebars.erb +15 -0
  61. data/app/assets/javascripts/faalis/dashboard/templates/navigation.handlebars.erb +43 -0
  62. data/app/assets/javascripts/faalis/dashboard/templates/widgets.handlebars +23 -0
  63. data/app/assets/javascripts/faalis/dashboard/variables.js.erb +17 -0
  64. data/app/assets/javascripts/faalis/groups.js +2 -0
  65. data/app/assets/javascripts/faalis/home.js +2 -0
  66. data/app/assets/javascripts/faalis/i18n.js +13 -0
  67. data/app/assets/javascripts/faalis/locale/en.json +27 -0
  68. data/app/assets/javascripts/faalis/locale/fa.json +27 -0
  69. data/app/assets/javascripts/faalis/users.js +2 -0
  70. data/app/assets/stylesheets/faalis/base.css.scss +264 -0
  71. data/app/assets/stylesheets/faalis/dashboard/dashboard.css.scss +226 -0
  72. data/app/assets/stylesheets/faalis/dashboard/list_view.css.scss +169 -0
  73. data/app/assets/stylesheets/faalis/dashboard/ltr/application.css +26 -0
  74. data/app/assets/stylesheets/faalis/dashboard/ltr/base.css.scss.erb +28 -0
  75. data/app/assets/stylesheets/faalis/dashboard/ltr/buttons.css.scss.erb +48 -0
  76. data/app/assets/stylesheets/faalis/dashboard/ltr/direction.css.scss +38 -0
  77. data/app/assets/stylesheets/faalis/dashboard/ltr/foundation_and_overrides.css.scss +1014 -0
  78. data/app/assets/stylesheets/faalis/dashboard/ng-grid.css.scss +442 -0
  79. data/app/assets/stylesheets/faalis/dashboard/ng-quick-date-default-theme.css.scss +20 -0
  80. data/app/assets/stylesheets/faalis/dashboard/ng-quick-date.css.scss +19 -0
  81. data/app/assets/stylesheets/faalis/dashboard/rtl/application.css +26 -0
  82. data/app/assets/stylesheets/faalis/dashboard/rtl/base.css.scss.erb +31 -0
  83. data/app/assets/stylesheets/faalis/dashboard/rtl/base.css_flymake.scss +25 -0
  84. data/app/assets/stylesheets/faalis/dashboard/rtl/buttons.css.scss.erb +45 -0
  85. data/app/assets/stylesheets/faalis/dashboard/rtl/direction.css.scss +37 -0
  86. data/app/assets/stylesheets/faalis/dashboard/rtl/foundation_and_overrides.css.scss +1014 -0
  87. data/app/assets/stylesheets/faalis/dashboard/select2.css.scss.erb +618 -0
  88. data/app/assets/stylesheets/faalis/dashboard/sidebar.css.scss +93 -0
  89. data/app/assets/stylesheets/faalis/devise.css.scss +34 -0
  90. data/app/assets/stylesheets/faalis/groups.css +4 -0
  91. data/app/assets/stylesheets/faalis/home.css.scss +14 -0
  92. data/app/assets/stylesheets/faalis/ltr/application.css +20 -0
  93. data/app/assets/stylesheets/faalis/ltr/buttons.css.scss.erb +48 -0
  94. data/app/assets/stylesheets/faalis/ltr/foundation_and_overrides.scss.erb +1012 -0
  95. data/app/assets/stylesheets/faalis/mixins.css.scss +15 -0
  96. data/app/assets/stylesheets/faalis/rtl/application.css +20 -0
  97. data/app/assets/stylesheets/faalis/rtl/buttons.css.scss.erb +48 -0
  98. data/app/assets/stylesheets/faalis/rtl/foundation_and_overrides.scss.erb +1012 -0
  99. data/app/assets/stylesheets/faalis/users.css +4 -0
  100. data/app/assets/stylesheets/faalis/variables.css.scss +102 -0
  101. data/app/controllers/faalis/api/v1/groups_controller.rb +75 -0
  102. data/app/controllers/faalis/api/v1/logs_controller.rb +12 -0
  103. data/app/controllers/faalis/api/v1/permissions_controller.rb +17 -0
  104. data/app/controllers/faalis/api/v1/profiles_controller.rb +42 -0
  105. data/app/controllers/faalis/api/v1/users_controller.rb +75 -0
  106. data/app/controllers/faalis/api_controller.rb +51 -0
  107. data/app/controllers/faalis/application_controller.rb +34 -0
  108. data/app/controllers/faalis/dashboard_controller.rb +44 -0
  109. data/app/controllers/faalis/home_controller.rb +19 -0
  110. data/app/controllers/faalis/omniauth/callbacks_controller.rb +43 -0
  111. data/app/helpers/faalis/application_helper.rb +4 -0
  112. data/app/helpers/faalis/dashboard_helper.rb +5 -0
  113. data/app/helpers/faalis/groups_helper.rb +4 -0
  114. data/app/helpers/faalis/home_helper.rb +4 -0
  115. data/app/helpers/faalis/users_helper.rb +4 -0
  116. data/app/models/ability.rb +42 -0
  117. data/app/models/faalis/group.rb +27 -0
  118. data/app/models/faalis/permission.rb +15 -0
  119. data/app/models/faalis/user.rb +81 -0
  120. data/app/views/angularjs_templates/#index.html# +8 -0
  121. data/app/views/angularjs_templates/auth/groups/details.html +21 -0
  122. data/app/views/angularjs_templates/auth/groups/index.html +5 -0
  123. data/app/views/angularjs_templates/auth/groups/new.html +41 -0
  124. data/app/views/angularjs_templates/auth/index.html +30 -0
  125. data/app/views/angularjs_templates/auth/profile/edit.html +54 -0
  126. data/app/views/angularjs_templates/auth/users/details.html +28 -0
  127. data/app/views/angularjs_templates/auth/users/index.html +6 -0
  128. data/app/views/angularjs_templates/auth/users/new.html +56 -0
  129. data/app/views/angularjs_templates/filter/index.html +15 -0
  130. data/app/views/angularjs_templates/index.html +8 -0
  131. data/app/views/angularjs_templates/list-view/index.html +81 -0
  132. data/app/views/angularjs_templates/locale/fa.po +25 -0
  133. data/app/views/angularjs_templates/locale/templates.pot +24 -0
  134. data/app/views/angularjs_templates/logs/index.html +6 -0
  135. data/app/views/angularjs_templates/modules.html +17 -0
  136. data/app/views/angularjs_templates/nav.html.erb +38 -0
  137. data/app/views/devise/confirmations/new.html.erb +34 -0
  138. data/app/views/devise/mailer/confirmation_instructions.html.erb +5 -0
  139. data/app/views/devise/mailer/reset_password_instructions.html.erb +8 -0
  140. data/app/views/devise/mailer/unlock_instructions.html.erb +7 -0
  141. data/app/views/devise/passwords/edit.html.erb +44 -0
  142. data/app/views/devise/passwords/new.html.erb +32 -0
  143. data/app/views/devise/registrations/edit.html.erb +29 -0
  144. data/app/views/devise/registrations/new.html.erb +91 -0
  145. data/app/views/devise/sessions/new.html.erb +98 -0
  146. data/app/views/devise/shared/_links.erb +25 -0
  147. data/app/views/devise/unlocks/new.html.erb +30 -0
  148. data/app/views/faalis/api/v1/groups/create.json.jbuilder +4 -0
  149. data/app/views/faalis/api/v1/groups/destroy.html.erb +2 -0
  150. data/app/views/faalis/api/v1/groups/destroy.json.jbuilder +1 -0
  151. data/app/views/faalis/api/v1/groups/edit.html.erb +2 -0
  152. data/app/views/faalis/api/v1/groups/index.html.erb +2 -0
  153. data/app/views/faalis/api/v1/groups/index.json.jbuilder +6 -0
  154. data/app/views/faalis/api/v1/groups/new.html.erb +2 -0
  155. data/app/views/faalis/api/v1/groups/show.html.erb +2 -0
  156. data/app/views/faalis/api/v1/groups/show.json.jbuilder +5 -0
  157. data/app/views/faalis/api/v1/groups/update.json.jbuilder +4 -0
  158. data/app/views/faalis/api/v1/logs/index.json.jbuilder +1 -0
  159. data/app/views/faalis/api/v1/permissions/index.json.jbuilder +1 -0
  160. data/app/views/faalis/api/v1/users/create.html.erb +2 -0
  161. data/app/views/faalis/api/v1/users/create.json.jbuilder +1 -0
  162. data/app/views/faalis/api/v1/users/destroy.json.jbuilder +1 -0
  163. data/app/views/faalis/api/v1/users/distroy.html.erb +2 -0
  164. data/app/views/faalis/api/v1/users/edit.html.erb +2 -0
  165. data/app/views/faalis/api/v1/users/index.html.erb +2 -0
  166. data/app/views/faalis/api/v1/users/index.json.jbuilder +4 -0
  167. data/app/views/faalis/api/v1/users/show.html.erb +2 -0
  168. data/app/views/faalis/api/v1/users/show.json.jbuilder +2 -0
  169. data/app/views/faalis/api/v1/users/update.json.jbuilder +1 -0
  170. data/app/views/faalis/dashboard/index.html.erb +37 -0
  171. data/app/views/faalis/dashboard/login_required_page.html.erb +5 -0
  172. data/app/views/faalis/home/index.html.erb +119 -0
  173. data/app/views/layouts/faalis/application.html.erb +90 -0
  174. data/app/views/layouts/faalis/dashboard.html.erb +21 -0
  175. data/config/initializers/devise.rb +28 -0
  176. data/config/locales/devise.en.yml +59 -0
  177. data/config/locales/devise.fa.yml +56 -0
  178. data/config/locales/fa/LC_MESSAGES/faalis.mo +0 -0
  179. data/config/locales/fa/faalis.po +181 -0
  180. data/config/locales/fa/messages.mo +0 -0
  181. data/config/locales/faalis.pot +181 -0
  182. data/config/routes.rb +36 -0
  183. data/db/migrate/20131013091000_devise_create_red_base_users.rb +64 -0
  184. data/db/migrate/20131020124701_create_red_base_groups.rb +9 -0
  185. data/db/migrate/20131021170923_create_red_base_permissions.rb +10 -0
  186. data/db/migrate/20131123120422_add_permissions_groups_table.rb +8 -0
  187. data/db/seeds.rb +15 -0
  188. data/lib/faalis.rb +30 -0
  189. data/lib/faalis/active_record.rb +64 -0
  190. data/lib/faalis/api.rb +61 -0
  191. data/lib/faalis/api/groups_api.rb +41 -0
  192. data/lib/faalis/api/permissions_api.rb +24 -0
  193. data/lib/faalis/api/root.rb +15 -0
  194. data/lib/faalis/api/users_api.rb +20 -0
  195. data/lib/faalis/cucumber.rb +25 -0
  196. data/lib/faalis/cucumber/auth.rb +45 -0
  197. data/lib/faalis/cucumber/exceptions.rb +40 -0
  198. data/lib/faalis/cucumber/interaction.rb +43 -0
  199. data/lib/faalis/cucumber/query.rb +28 -0
  200. data/lib/faalis/cucumber/urls.rb +76 -0
  201. data/lib/faalis/dashboard.rb +60 -0
  202. data/lib/faalis/dashboard/controller.rb +42 -0
  203. data/lib/faalis/dashboard/module.rb +45 -0
  204. data/lib/faalis/engine.rb +128 -0
  205. data/lib/faalis/exceptions.rb +26 -0
  206. data/lib/faalis/i18n.rb +35 -0
  207. data/lib/faalis/initialize.rb +7 -0
  208. data/lib/faalis/omniauth.rb +24 -0
  209. data/lib/faalis/omniauth/callbacks.rb +58 -0
  210. data/lib/faalis/plugins.rb +44 -0
  211. data/lib/faalis/version.rb +22 -0
  212. data/lib/faalis_plugin.rb +476 -0
  213. data/lib/generators/faalis/USAGE +8 -0
  214. data/lib/generators/faalis/angularjs_resource_generator.rb +74 -0
  215. data/lib/generators/faalis/install_all_generator.rb +38 -0
  216. data/lib/generators/faalis/install_generator.rb +42 -0
  217. data/lib/generators/faalis/install_specs_generator.rb +48 -0
  218. data/lib/generators/faalis/js_scaffold_generator.rb +273 -0
  219. data/lib/generators/faalis/templates/README +41 -0
  220. data/lib/generators/faalis/templates/SPECS +13 -0
  221. data/lib/generators/faalis/templates/angularjs/details.html.erb +20 -0
  222. data/lib/generators/faalis/templates/angularjs/index.html.erb +62 -0
  223. data/lib/generators/faalis/templates/angularjs/module.js.erb +309 -0
  224. data/lib/generators/faalis/templates/angularjs/new.html.erb +105 -0
  225. data/lib/generators/faalis/templates/api/controller.rb.erb +56 -0
  226. data/lib/generators/faalis/templates/devise.rb +251 -0
  227. data/lib/generators/faalis/templates/faalis.rb +14 -0
  228. data/lib/generators/faalis/templates/fast_gettext.rb +4 -0
  229. data/lib/generators/faalis/templates/features/api.feature +92 -0
  230. data/lib/generators/faalis/templates/features/api.step.rb +7 -0
  231. data/lib/generators/faalis/templates/features/step_definitions/email_steps.rb +206 -0
  232. data/lib/generators/faalis/templates/features/support/email_spec.rb +1 -0
  233. data/lib/generators/faalis/templates/features/support/env.rb +79 -0
  234. data/lib/generators/faalis/templates/formtastic.rb +76 -0
  235. data/lib/generators/faalis/templates/js_scaffold.README +25 -0
  236. data/lib/generators/faalis/templates/seeds.rb +1 -0
  237. data/lib/generators/faalis/templates/spec/factories/groups.rb +5 -0
  238. data/lib/generators/faalis/templates/spec/factories/users.rb +10 -0
  239. data/lib/generators/faalis/templates/spec/spec_helper.rb +69 -0
  240. data/lib/generators/faalis/templates/spec/support/devise.rb +3 -0
  241. data/lib/generators/faalis/templates/views/create.json.jbuilder.erb +2 -0
  242. data/lib/generators/faalis/templates/views/destroy.json.jbuilder.erb +1 -0
  243. data/lib/generators/faalis/templates/views/index.json.jbuilder.erb +10 -0
  244. data/lib/generators/faalis/templates/views/show.json.jbuilder.erb +7 -0
  245. data/lib/generators/faalis/templates/views/update.json.jbuilder.erb +6 -0
  246. data/lib/generators/faalis/views_generator.rb +41 -0
  247. data/lib/tasks/faalis_tasks.rake +23 -0
  248. data/lib/tasks/grunt/Gruntfile.js +25 -0
  249. data/spec/dummy/README.rdoc +28 -0
  250. data/spec/dummy/Rakefile +6 -0
  251. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  252. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  253. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  254. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  255. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  256. data/spec/dummy/bin/bundle +3 -0
  257. data/spec/dummy/bin/rails +4 -0
  258. data/spec/dummy/bin/rake +4 -0
  259. data/spec/dummy/config.ru +4 -0
  260. data/spec/dummy/config/application.rb +23 -0
  261. data/spec/dummy/config/boot.rb +5 -0
  262. data/spec/dummy/config/database.yml +25 -0
  263. data/spec/dummy/config/environment.rb +5 -0
  264. data/spec/dummy/config/environments/development.rb +29 -0
  265. data/spec/dummy/config/environments/production.rb +80 -0
  266. data/spec/dummy/config/environments/test.rb +36 -0
  267. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  268. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  269. data/spec/dummy/config/initializers/inflections.rb +16 -0
  270. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  271. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  272. data/spec/dummy/config/initializers/session_store.rb +3 -0
  273. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  274. data/spec/dummy/config/locales/en.yml +23 -0
  275. data/spec/dummy/config/routes.rb +4 -0
  276. data/spec/dummy/db/test.sqlite3 +0 -0
  277. data/spec/dummy/log/development.log +0 -0
  278. data/spec/dummy/log/test.log +15 -0
  279. data/spec/dummy/public/404.html +58 -0
  280. data/spec/dummy/public/422.html +58 -0
  281. data/spec/dummy/public/500.html +57 -0
  282. data/spec/dummy/public/favicon.ico +0 -0
  283. data/spec/dummy/tmp/ember-rails/ember-data.js +10204 -0
  284. data/spec/dummy/tmp/ember-rails/ember.js +36991 -0
  285. data/spec/spec_helper.rb +52 -0
  286. metadata +678 -0
@@ -0,0 +1,3260 @@
1
+ /***********************************************
2
+ * ng-grid JavaScript Library
3
+ * Authors: https://github.com/angular-ui/ng-grid/blob/master/README.md
4
+ * License: MIT (http://www.opensource.org/licenses/mit-license.php)
5
+ * Compiled At: 07/06/2013 13:50
6
+ ***********************************************/
7
+ (function(window, $) {
8
+ 'use strict';
9
+
10
+ var EXCESS_ROWS = 6;
11
+ var SCROLL_THRESHOLD = 4;
12
+ var ASC = "asc";
13
+
14
+ var DESC = "desc";
15
+
16
+ var NG_FIELD = '_ng_field_';
17
+ var NG_DEPTH = '_ng_depth_';
18
+ var NG_HIDDEN = '_ng_hidden_';
19
+ var NG_COLUMN = '_ng_column_';
20
+ var CUSTOM_FILTERS = /CUSTOM_FILTERS/g;
21
+ var COL_FIELD = /COL_FIELD/g;
22
+ var DISPLAY_CELL_TEMPLATE = /DISPLAY_CELL_TEMPLATE/g;
23
+ var EDITABLE_CELL_TEMPLATE = /EDITABLE_CELL_TEMPLATE/g;
24
+ var TEMPLATE_REGEXP = /<.+>/;
25
+ window.ngGrid = {};
26
+ window.ngGrid.i18n = {};
27
+ var ngGridServices = angular.module('ngGrid.services', []);
28
+ var ngGridDirectives = angular.module('ngGrid.directives', []);
29
+ var ngGridFilters = angular.module('ngGrid.filters', []);
30
+
31
+ angular.module('ngGrid', ['ngGrid.services', 'ngGrid.directives', 'ngGrid.filters']);
32
+
33
+ var ngMoveSelectionHandler = function($scope, elm, evt, grid) {
34
+ if ($scope.selectionProvider.selectedItems === undefined) {
35
+ return true;
36
+ }
37
+
38
+ var charCode = evt.which || evt.keyCode,
39
+ newColumnIndex,
40
+ lastInRow = false,
41
+ firstInRow = false,
42
+ rowIndex = $scope.selectionProvider.lastClickedRow === undefined ? 1 : $scope.selectionProvider.lastClickedRow.rowIndex,
43
+ visibleCols = $scope.columns.filter(function(c) { return c.visible; }),
44
+ pinnedCols = $scope.columns.filter(function(c) { return c.pinned; });
45
+
46
+ if ($scope.col) {
47
+ newColumnIndex = visibleCols.indexOf($scope.col);
48
+ }
49
+
50
+ if (charCode !== 37 && charCode !== 38 && charCode !== 39 && charCode !== 40 && charCode !== 9 && charCode !== 13) {
51
+ return true;
52
+ }
53
+ if ($scope.enableCellSelection) {
54
+ if (charCode === 9) {
55
+ evt.preventDefault();
56
+ }
57
+
58
+ var focusedOnFirstColumn = $scope.showSelectionCheckbox ? $scope.col.index === 1 : $scope.col.index === 0;
59
+ var focusedOnFirstVisibleColumns = $scope.$index === 1 || $scope.$index === 0;
60
+ var focusedOnLastVisibleColumns = $scope.$index === ($scope.renderedColumns.length - 1) || $scope.$index === ($scope.renderedColumns.length - 2);
61
+ var focusedOnLastColumn = visibleCols.indexOf($scope.col) === (visibleCols.length - 1);
62
+ var focusedOnLastPinnedColumn = pinnedCols.indexOf($scope.col) === (pinnedCols.length - 1);
63
+ if (charCode === 37 || charCode === 9 && evt.shiftKey) {
64
+ var scrollTo = 0;
65
+
66
+ if (!focusedOnFirstColumn) {
67
+ newColumnIndex -= 1;
68
+ }
69
+
70
+ if (focusedOnFirstVisibleColumns) {
71
+ if (focusedOnFirstColumn && charCode === 9 && evt.shiftKey){
72
+ scrollTo = grid.$canvas.width();
73
+ newColumnIndex = visibleCols.length - 1;
74
+ firstInRow = true;
75
+ }
76
+ else {
77
+ scrollTo = grid.$viewport.scrollLeft() - $scope.col.width;
78
+ }
79
+ }
80
+ else if (pinnedCols.length > 0) {
81
+ scrollTo = grid.$viewport.scrollLeft() - visibleCols[newColumnIndex].width;
82
+ }
83
+
84
+ grid.$viewport.scrollLeft(scrollTo);
85
+ }
86
+ else if (charCode === 39 || charCode === 9 && !evt.shiftKey) {
87
+ if (focusedOnLastVisibleColumns) {
88
+ if (focusedOnLastColumn && charCode === 9 && !evt.shiftKey) {
89
+ grid.$viewport.scrollLeft(0);
90
+ newColumnIndex = $scope.showSelectionCheckbox ? 1 : 0;
91
+ lastInRow = true;
92
+ }
93
+ else {
94
+ grid.$viewport.scrollLeft(grid.$viewport.scrollLeft() + $scope.col.width);
95
+ }
96
+ }
97
+ else if (focusedOnLastPinnedColumn) {
98
+ grid.$viewport.scrollLeft(0);
99
+ }
100
+
101
+ if (!focusedOnLastColumn) {
102
+ newColumnIndex += 1;
103
+ }
104
+ }
105
+ }
106
+ var items;
107
+ if ($scope.configGroups.length > 0) {
108
+ items = grid.rowFactory.parsedData.filter(function (row) {
109
+ return !row.isAggRow;
110
+ });
111
+ }
112
+ else {
113
+ items = grid.filteredRows;
114
+ }
115
+ var offset = 0;
116
+ if (rowIndex !== 0 && (charCode === 38 || charCode === 13 && evt.shiftKey || charCode === 9 && evt.shiftKey && firstInRow)) {
117
+ offset = -1;
118
+ }
119
+ else if (rowIndex !== items.length - 1 && (charCode === 40 || charCode === 13 && !evt.shiftKey || charCode === 9 && lastInRow)) {
120
+ offset = 1;
121
+ }
122
+ if (offset) {
123
+ var r = items[rowIndex + offset];
124
+ if (r.beforeSelectionChange(r, evt)) {
125
+ r.continueSelection(evt);
126
+ $scope.$emit('ngGridEventDigestGridParent');
127
+
128
+ if ($scope.selectionProvider.lastClickedRow.renderedRowIndex >= $scope.renderedRows.length - EXCESS_ROWS - 2) {
129
+ grid.$viewport.scrollTop(grid.$viewport.scrollTop() + $scope.rowHeight);
130
+ }
131
+ else if ($scope.selectionProvider.lastClickedRow.renderedRowIndex <= EXCESS_ROWS + 2) {
132
+ grid.$viewport.scrollTop(grid.$viewport.scrollTop() - $scope.rowHeight);
133
+ }
134
+ }
135
+ }
136
+ if ($scope.enableCellSelection) {
137
+ setTimeout(function(){
138
+ $scope.domAccessProvider.focusCellElement($scope, $scope.renderedColumns.indexOf(visibleCols[newColumnIndex]));
139
+ }, 3);
140
+ }
141
+
142
+ return false;
143
+ };
144
+
145
+ if (!String.prototype.trim) {
146
+ String.prototype.trim = function() {
147
+ return this.replace(/^\s+|\s+$/g, '');
148
+ };
149
+ }
150
+ if (!Array.prototype.indexOf) {
151
+ Array.prototype.indexOf = function(elt ) {
152
+ var len = this.length >>> 0;
153
+ var from = Number(arguments[1]) || 0;
154
+ from = (from < 0) ? Math.ceil(from) : Math.floor(from);
155
+ if (from < 0) {
156
+ from += len;
157
+ }
158
+ for (; from < len; from++) {
159
+ if (from in this && this[from] === elt) {
160
+ return from;
161
+ }
162
+ }
163
+ return -1;
164
+ };
165
+ }
166
+ if (!Array.prototype.filter) {
167
+ Array.prototype.filter = function(fun ) {
168
+ "use strict";
169
+ var t = Object(this);
170
+ var len = t.length >>> 0;
171
+ if (typeof fun !== "function") {
172
+ throw new TypeError();
173
+ }
174
+ var res = [];
175
+ var thisp = arguments[1];
176
+ for (var i = 0; i < len; i++) {
177
+ if (i in t) {
178
+ var val = t[i];
179
+ if (fun.call(thisp, val, i, t)) {
180
+ res.push(val);
181
+ }
182
+ }
183
+ }
184
+ return res;
185
+ };
186
+ }
187
+ ngGridFilters.filter('checkmark', function() {
188
+ return function(input) {
189
+ return input ? '\u2714' : '\u2718';
190
+ };
191
+ });
192
+ ngGridFilters.filter('ngColumns', function() {
193
+ return function(input) {
194
+ return input.filter(function(col) {
195
+ return !col.isAggCol;
196
+ });
197
+ };
198
+ });
199
+ angular.module('ngGrid.services').factory('$domUtilityService',['$utilityService', function($utils) {
200
+ var domUtilityService = {};
201
+ var regexCache = {};
202
+ var getWidths = function() {
203
+ var $testContainer = $('<div></div>');
204
+ $testContainer.appendTo('body');
205
+ $testContainer.height(100).width(100).css("position", "absolute").css("overflow", "scroll");
206
+ $testContainer.append('<div style="height: 400px; width: 400px;"></div>');
207
+ domUtilityService.ScrollH = ($testContainer.height() - $testContainer[0].clientHeight);
208
+ domUtilityService.ScrollW = ($testContainer.width() - $testContainer[0].clientWidth);
209
+ $testContainer.empty();
210
+ $testContainer.attr('style', '');
211
+ $testContainer.append('<span style="font-family: Verdana, Helvetica, Sans-Serif; font-size: 14px;"><strong>M</strong></span>');
212
+ domUtilityService.LetterW = $testContainer.children().first().width();
213
+ $testContainer.remove();
214
+ };
215
+ domUtilityService.eventStorage = {};
216
+ domUtilityService.AssignGridContainers = function($scope, rootEl, grid) {
217
+ grid.$root = $(rootEl);
218
+ grid.$topPanel = grid.$root.find(".ngTopPanel");
219
+ grid.$groupPanel = grid.$root.find(".ngGroupPanel");
220
+ grid.$headerContainer = grid.$topPanel.find(".ngHeaderContainer");
221
+ $scope.$headerContainer = grid.$headerContainer;
222
+
223
+ grid.$headerScroller = grid.$topPanel.find(".ngHeaderScroller");
224
+ grid.$headers = grid.$headerScroller.children();
225
+ grid.$viewport = grid.$root.find(".ngViewport");
226
+ grid.$canvas = grid.$viewport.find(".ngCanvas");
227
+ grid.$footerPanel = grid.$root.find(".ngFooterPanel");
228
+ $scope.$watch(function () {
229
+ return grid.$viewport.scrollLeft();
230
+ }, function (newLeft) {
231
+ return grid.$headerContainer.scrollLeft(newLeft);
232
+ });
233
+ domUtilityService.UpdateGridLayout($scope, grid);
234
+ };
235
+ domUtilityService.getRealWidth = function (obj) {
236
+ var width = 0;
237
+ var props = { visibility: "hidden", display: "block" };
238
+ var hiddenParents = obj.parents().andSelf().not(':visible');
239
+ $.swap(hiddenParents[0], props, function () {
240
+ width = obj.outerWidth();
241
+ });
242
+ return width;
243
+ };
244
+ domUtilityService.UpdateGridLayout = function($scope, grid) {
245
+ var scrollTop = grid.$viewport.scrollTop();
246
+ grid.elementDims.rootMaxW = grid.$root.width();
247
+ if (grid.$root.is(':hidden')) {
248
+ grid.elementDims.rootMaxW = domUtilityService.getRealWidth(grid.$root);
249
+ }
250
+ grid.elementDims.rootMaxH = grid.$root.height();
251
+ grid.refreshDomSizes();
252
+ $scope.adjustScrollTop(scrollTop, true);
253
+ };
254
+ domUtilityService.numberOfGrids = 0;
255
+ domUtilityService.BuildStyles = function($scope, grid, digest) {
256
+ var rowHeight = grid.config.rowHeight,
257
+ $style = grid.$styleSheet,
258
+ gridId = grid.gridId,
259
+ css,
260
+ cols = $scope.columns,
261
+ sumWidth = 0;
262
+
263
+ if (!$style) {
264
+ $style = $('#' + gridId);
265
+ if (!$style[0]) {
266
+ $style = $("<style id='" + gridId + "' type='text/css' rel='stylesheet' />").appendTo(grid.$root);
267
+ }
268
+ }
269
+ $style.empty();
270
+ var trw = $scope.totalRowWidth();
271
+ css = "." + gridId + " .ngCanvas { width: " + trw + "px; }" +
272
+ "." + gridId + " .ngRow { width: " + trw + "px; }" +
273
+ "." + gridId + " .ngCanvas { width: " + trw + "px; }" +
274
+ "." + gridId + " .ngHeaderScroller { width: " + (trw + domUtilityService.ScrollH) + "px}";
275
+
276
+ for (var i = 0; i < cols.length; i++) {
277
+ var col = cols[i];
278
+ if (col.visible !== false) {
279
+ css += "." + gridId + " .col" + i + " { width: " + col.width + "px; left: " + sumWidth + "px; height: " + rowHeight + "px }" +
280
+ "." + gridId + " .colt" + i + " { width: " + col.width + "px; }";
281
+ sumWidth += col.width;
282
+ }
283
+ }
284
+
285
+ if ($utils.isIe) {
286
+ $style[0].styleSheet.cssText = css;
287
+ }
288
+
289
+ else {
290
+ $style[0].appendChild(document.createTextNode(css));
291
+ }
292
+
293
+ grid.$styleSheet = $style;
294
+ $scope.adjustScrollLeft(grid.$viewport.scrollLeft());
295
+ if (digest) {
296
+ domUtilityService.digest($scope);
297
+ }
298
+ };
299
+ domUtilityService.setColLeft = function(col, colLeft, grid) {
300
+ if (grid.$styleSheet) {
301
+ var regex = regexCache[col.index];
302
+ if (!regex) {
303
+ regex = regexCache[col.index] = new RegExp(".col" + col.index + " { width: [0-9]+px; left: [0-9]+px");
304
+ }
305
+ var str = grid.$styleSheet.html();
306
+ var newStr = str.replace(regex, ".col" + col.index + " { width: " + col.width + "px; left: " + colLeft + "px");
307
+ if ($utils.isIe) {
308
+ setTimeout(function() {
309
+ grid.$styleSheet.html(newStr);
310
+ });
311
+ }
312
+ else {
313
+ grid.$styleSheet.html(newStr);
314
+ }
315
+ }
316
+ };
317
+ domUtilityService.setColLeft.immediate = 1;
318
+ domUtilityService.RebuildGrid = function($scope, grid){
319
+ domUtilityService.UpdateGridLayout($scope, grid);
320
+ if (grid.config.maintainColumnRatios == null || grid.config.maintainColumnRatios) {
321
+ grid.configureColumnWidths();
322
+ }
323
+ $scope.adjustScrollLeft(grid.$viewport.scrollLeft());
324
+ domUtilityService.BuildStyles($scope, grid, true);
325
+ };
326
+
327
+ domUtilityService.digest = function($scope) {
328
+ if (!$scope.$root.$$phase) {
329
+ $scope.$digest();
330
+ }
331
+ };
332
+ domUtilityService.ScrollH = 17;
333
+ domUtilityService.ScrollW = 17;
334
+ domUtilityService.LetterW = 10;
335
+ getWidths();
336
+ return domUtilityService;
337
+ }]);
338
+ angular.module('ngGrid.services').factory('$sortService', ['$parse', function($parse) {
339
+ var sortService = {};
340
+ sortService.colSortFnCache = {};
341
+ sortService.guessSortFn = function(item) {
342
+ var itemType = typeof(item);
343
+ switch (itemType) {
344
+ case "number":
345
+ return sortService.sortNumber;
346
+ case "boolean":
347
+ return sortService.sortBool;
348
+ case "string":
349
+ return item.match(/^[-+]?[£$¤]?[\d,.]+%?$/) ? sortService.sortNumberStr : sortService.sortAlpha;
350
+ default:
351
+ if (Object.prototype.toString.call(item) === '[object Date]') {
352
+ return sortService.sortDate;
353
+ }
354
+ else {
355
+ return sortService.basicSort;
356
+ }
357
+ }
358
+ };
359
+ sortService.basicSort = function(a, b) {
360
+ if (a === b) {
361
+ return 0;
362
+ }
363
+ if (a < b) {
364
+ return -1;
365
+ }
366
+ return 1;
367
+ };
368
+ sortService.sortNumber = function(a, b) {
369
+ return a - b;
370
+ };
371
+ sortService.sortNumberStr = function(a, b) {
372
+ var numA, numB, badA = false, badB = false;
373
+ numA = parseFloat(a.replace(/[^0-9.-]/g, ''));
374
+ if (isNaN(numA)) {
375
+ badA = true;
376
+ }
377
+ numB = parseFloat(b.replace(/[^0-9.-]/g, ''));
378
+ if (isNaN(numB)) {
379
+ badB = true;
380
+ }
381
+ if (badA && badB) {
382
+ return 0;
383
+ }
384
+ if (badA) {
385
+ return 1;
386
+ }
387
+ if (badB) {
388
+ return -1;
389
+ }
390
+ return numA - numB;
391
+ };
392
+ sortService.sortAlpha = function(a, b) {
393
+ var strA = a.toLowerCase(),
394
+ strB = b.toLowerCase();
395
+ return strA === strB ? 0 : (strA < strB ? -1 : 1);
396
+ };
397
+ sortService.sortDate = function(a, b) {
398
+ var timeA = a.getTime(),
399
+ timeB = b.getTime();
400
+ return timeA === timeB ? 0 : (timeA < timeB ? -1 : 1);
401
+ };
402
+ sortService.sortBool = function(a, b) {
403
+ if (a && b) {
404
+ return 0;
405
+ }
406
+ if (!a && !b) {
407
+ return 0;
408
+ } else {
409
+ return a ? 1 : -1;
410
+ }
411
+ };
412
+ sortService.sortData = function(sortInfo, data ) {
413
+ if (!data || !sortInfo) {
414
+ return;
415
+ }
416
+ var l = sortInfo.fields.length,
417
+ order = sortInfo.fields,
418
+ col,
419
+ direction,
420
+ d = data.slice(0);
421
+ data.sort(function (itemA, itemB) {
422
+ var tem = 0,
423
+ indx = 0,
424
+ sortFn;
425
+ while (tem === 0 && indx < l) {
426
+ col = sortInfo.columns[indx];
427
+ direction = sortInfo.directions[indx];
428
+ sortFn = sortService.getSortFn(col, d);
429
+ var propA = $parse(order[indx])(itemA);
430
+ var propB = $parse(order[indx])(itemB);
431
+ if ((!propA && propA !== 0) || (!propB && propB !== 0)) {
432
+ if (!propB && !propA) {
433
+ tem = 0;
434
+ }
435
+ else if (!propA) {
436
+ tem = 1;
437
+ }
438
+ else if (!propB) {
439
+ tem = -1;
440
+ }
441
+ }
442
+ else {
443
+ tem = sortFn(propA, propB);
444
+ }
445
+ indx++;
446
+ }
447
+ if (direction === ASC) {
448
+ return tem;
449
+ } else {
450
+ return 0 - tem;
451
+ }
452
+ });
453
+ };
454
+ sortService.Sort = function(sortInfo, data) {
455
+ if (sortService.isSorting) {
456
+ return;
457
+ }
458
+ sortService.isSorting = true;
459
+ sortService.sortData(sortInfo, data);
460
+ sortService.isSorting = false;
461
+ };
462
+ sortService.getSortFn = function(col, data) {
463
+ var sortFn, item;
464
+ if (sortService.colSortFnCache[col.field]) {
465
+ sortFn = sortService.colSortFnCache[col.field];
466
+ }
467
+ else if (col.sortingAlgorithm !== undefined) {
468
+ sortFn = col.sortingAlgorithm;
469
+ sortService.colSortFnCache[col.field] = col.sortingAlgorithm;
470
+ }
471
+ else {
472
+ item = data[0];
473
+ if (!item) {
474
+ return sortFn;
475
+ }
476
+ sortFn = sortService.guessSortFn($parse(col.field)(item));
477
+ if (sortFn) {
478
+ sortService.colSortFnCache[col.field] = sortFn;
479
+ } else {
480
+ sortFn = sortService.sortAlpha;
481
+ }
482
+ }
483
+ return sortFn;
484
+ };
485
+ return sortService;
486
+ }]);
487
+
488
+ angular.module('ngGrid.services').factory('$utilityService', ['$parse', function ($parse) {
489
+ var funcNameRegex = /function (.{1,})\(/;
490
+ var utils = {
491
+ visualLength: function(node) {
492
+ var elem = document.getElementById('testDataLength');
493
+ if (!elem) {
494
+ elem = document.createElement('SPAN');
495
+ elem.id = "testDataLength";
496
+ elem.style.visibility = "hidden";
497
+ document.body.appendChild(elem);
498
+ }
499
+ $(elem).css('font', $(node).css('font'));
500
+ $(elem).css('font-size', $(node).css('font-size'));
501
+ $(elem).css('font-family', $(node).css('font-family'));
502
+ elem.innerHTML = $(node).text();
503
+ return elem.offsetWidth;
504
+ },
505
+ forIn: function(obj, action) {
506
+ for (var prop in obj) {
507
+ if (obj.hasOwnProperty(prop)) {
508
+ action(obj[prop], prop);
509
+ }
510
+ }
511
+ },
512
+ evalProperty: function (entity, path) {
513
+ return $parse(path)(entity);
514
+ },
515
+ endsWith: function(str, suffix) {
516
+ if (!str || !suffix || typeof str !== "string") {
517
+ return false;
518
+ }
519
+ return str.indexOf(suffix, str.length - suffix.length) !== -1;
520
+ },
521
+ isNullOrUndefined: function(obj) {
522
+ if (obj === undefined || obj === null) {
523
+ return true;
524
+ }
525
+ return false;
526
+ },
527
+ getElementsByClassName: function(cl) {
528
+ var retnode = [];
529
+ var myclass = new RegExp('\\b' + cl + '\\b');
530
+ var elem = document.getElementsByTagName('*');
531
+ for (var i = 0; i < elem.length; i++) {
532
+ var classes = elem[i].className;
533
+ if (myclass.test(classes)) {
534
+ retnode.push(elem[i]);
535
+ }
536
+ }
537
+ return retnode;
538
+ },
539
+ newId: (function() {
540
+ var seedId = new Date().getTime();
541
+ return function() {
542
+ return seedId += 1;
543
+ };
544
+ })(),
545
+ seti18n: function($scope, language) {
546
+ var $langPack = window.ngGrid.i18n[language];
547
+ for (var label in $langPack) {
548
+ $scope.i18n[label] = $langPack[label];
549
+ }
550
+ },
551
+ getInstanceType: function (o) {
552
+ var results = (funcNameRegex).exec(o.constructor.toString());
553
+ if (results && results.length > 1) {
554
+ var instanceType = results[1].replace(/^\s+|\s+$/g, "");
555
+ return instanceType;
556
+ }
557
+ else {
558
+ return "";
559
+ }
560
+ },
561
+ ieVersion: (function() {
562
+ var version = 3, div = document.createElement('div'), iElems = div.getElementsByTagName('i');
563
+ do{
564
+ div.innerHTML = '<!--[if gt IE ' + (++version) + ']><i></i><![endif]-->';
565
+ }while(iElems[0]);
566
+ return version > 4 ? version : undefined;
567
+ })()
568
+ };
569
+
570
+ $.extend(utils, {
571
+ isIe: (function() {
572
+ return utils.ieVersion !== undefined;
573
+ })()
574
+ });
575
+ return utils;
576
+ }]);
577
+
578
+ var ngAggregate = function (aggEntity, rowFactory, rowHeight, groupInitState) {
579
+ this.rowIndex = 0;
580
+ this.offsetTop = this.rowIndex * rowHeight;
581
+ this.entity = aggEntity;
582
+ this.label = aggEntity.gLabel;
583
+ this.field = aggEntity.gField;
584
+ this.depth = aggEntity.gDepth;
585
+ this.parent = aggEntity.parent;
586
+ this.children = aggEntity.children;
587
+ this.aggChildren = aggEntity.aggChildren;
588
+ this.aggIndex = aggEntity.aggIndex;
589
+ this.collapsed = groupInitState;
590
+ this.groupInitState = groupInitState;
591
+ this.rowFactory = rowFactory;
592
+ this.rowHeight = rowHeight;
593
+ this.isAggRow = true;
594
+ this.offsetLeft = aggEntity.gDepth * 25;
595
+ this.aggLabelFilter = aggEntity.aggLabelFilter;
596
+ };
597
+
598
+ ngAggregate.prototype.toggleExpand = function () {
599
+ this.collapsed = this.collapsed ? false : true;
600
+ if (this.orig) {
601
+ this.orig.collapsed = this.collapsed;
602
+ }
603
+ this.notifyChildren();
604
+ };
605
+ ngAggregate.prototype.setExpand = function (state) {
606
+ this.collapsed = state;
607
+ this.notifyChildren();
608
+ };
609
+ ngAggregate.prototype.notifyChildren = function () {
610
+ var longest = Math.max(this.rowFactory.aggCache.length, this.children.length);
611
+ for (var i = 0; i < longest; i++) {
612
+ if (this.aggChildren[i]) {
613
+ this.aggChildren[i].entity[NG_HIDDEN] = this.collapsed;
614
+ if (this.collapsed) {
615
+ this.aggChildren[i].setExpand(this.collapsed);
616
+ }
617
+ }
618
+ if (this.children[i]) {
619
+ this.children[i][NG_HIDDEN] = this.collapsed;
620
+ }
621
+ if (i > this.aggIndex && this.rowFactory.aggCache[i]) {
622
+ var agg = this.rowFactory.aggCache[i];
623
+ var offset = (30 * this.children.length);
624
+ agg.offsetTop = this.collapsed ? agg.offsetTop - offset : agg.offsetTop + offset;
625
+ }
626
+ }
627
+ this.rowFactory.renderedChange();
628
+ };
629
+ ngAggregate.prototype.aggClass = function () {
630
+ return this.collapsed ? "ngAggArrowCollapsed" : "ngAggArrowExpanded";
631
+ };
632
+ ngAggregate.prototype.totalChildren = function () {
633
+ if (this.aggChildren.length > 0) {
634
+ var i = 0;
635
+ var recurse = function (cur) {
636
+ if (cur.aggChildren.length > 0) {
637
+ angular.forEach(cur.aggChildren, function (a) {
638
+ recurse(a);
639
+ });
640
+ } else {
641
+ i += cur.children.length;
642
+ }
643
+ };
644
+ recurse(this);
645
+ return i;
646
+ } else {
647
+ return this.children.length;
648
+ }
649
+ };
650
+ ngAggregate.prototype.copy = function () {
651
+ var ret = new ngAggregate(this.entity, this.rowFactory, this.rowHeight, this.groupInitState);
652
+ ret.orig = this;
653
+ return ret;
654
+ };
655
+ var ngColumn = function (config, $scope, grid, domUtilityService, $templateCache, $utils) {
656
+ var self = this,
657
+ colDef = config.colDef,
658
+ delay = 500,
659
+ clicks = 0,
660
+ timer = null;
661
+ self.colDef = config.colDef;
662
+ self.width = colDef.width;
663
+ self.groupIndex = 0;
664
+ self.isGroupedBy = false;
665
+ self.minWidth = !colDef.minWidth ? 50 : colDef.minWidth;
666
+ self.maxWidth = !colDef.maxWidth ? 9000 : colDef.maxWidth;
667
+ self.enableCellEdit = colDef.enableCellEdit !== undefined ? colDef.enableCellEdit : (config.enableCellEdit || config.enableCellEditOnFocus);
668
+
669
+ self.headerRowHeight = config.headerRowHeight;
670
+ self.displayName = (colDef.displayName === undefined) ? colDef.field : colDef.displayName;
671
+
672
+ self.index = config.index;
673
+ self.isAggCol = config.isAggCol;
674
+ self.cellClass = colDef.cellClass;
675
+ self.sortPriority = undefined;
676
+ self.cellFilter = colDef.cellFilter ? colDef.cellFilter : "";
677
+ self.field = colDef.field;
678
+ self.aggLabelFilter = colDef.cellFilter || colDef.aggLabelFilter;
679
+ self.visible = $utils.isNullOrUndefined(colDef.visible) || colDef.visible;
680
+ self.sortable = false;
681
+ self.resizable = false;
682
+ self.pinnable = false;
683
+ self.pinned = (config.enablePinning && colDef.pinned);
684
+ self.originalIndex = config.originalIndex == null ? self.index : config.originalIndex;
685
+ self.groupable = $utils.isNullOrUndefined(colDef.groupable) || colDef.groupable;
686
+ if (config.enableSort) {
687
+ self.sortable = $utils.isNullOrUndefined(colDef.sortable) || colDef.sortable;
688
+ }
689
+ if (config.enableResize) {
690
+ self.resizable = $utils.isNullOrUndefined(colDef.resizable) || colDef.resizable;
691
+ }
692
+ if (config.enablePinning) {
693
+ self.pinnable = $utils.isNullOrUndefined(colDef.pinnable) || colDef.pinnable;
694
+ }
695
+ self.sortDirection = undefined;
696
+ self.sortingAlgorithm = colDef.sortFn;
697
+ self.headerClass = colDef.headerClass;
698
+ self.cursor = self.sortable ? 'pointer' : 'default';
699
+ self.headerCellTemplate = colDef.headerCellTemplate || $templateCache.get('headerCellTemplate.html');
700
+ self.cellTemplate = colDef.cellTemplate || $templateCache.get('cellTemplate.html').replace(CUSTOM_FILTERS, self.cellFilter ? "|" + self.cellFilter : "");
701
+ if(self.enableCellEdit) {
702
+ self.cellEditTemplate = $templateCache.get('cellEditTemplate.html');
703
+ self.editableCellTemplate = colDef.editableCellTemplate || $templateCache.get('editableCellTemplate.html');
704
+ }
705
+ if (colDef.cellTemplate && !TEMPLATE_REGEXP.test(colDef.cellTemplate)) {
706
+ self.cellTemplate = $.ajax({
707
+ type: "GET",
708
+ url: colDef.cellTemplate,
709
+ async: false
710
+ }).responseText;
711
+ }
712
+ if (self.enableCellEdit && colDef.editableCellTemplate && !TEMPLATE_REGEXP.test(colDef.editableCellTemplate)) {
713
+ self.editableCellTemplate = $.ajax({
714
+ type: "GET",
715
+ url: colDef.editableCellTemplate,
716
+ async: false
717
+ }).responseText;
718
+ }
719
+ if (colDef.headerCellTemplate && !TEMPLATE_REGEXP.test(colDef.headerCellTemplate)) {
720
+ self.headerCellTemplate = $.ajax({
721
+ type: "GET",
722
+ url: colDef.headerCellTemplate,
723
+ async: false
724
+ }).responseText;
725
+ }
726
+ self.colIndex = function () {
727
+ var classes = self.pinned ? "pinned " : "";
728
+ classes += "col" + self.index + " colt" + self.index;
729
+ if (self.cellClass) {
730
+ classes += " " + self.cellClass;
731
+ }
732
+ return classes;
733
+ };
734
+ self.groupedByClass = function() {
735
+ return self.isGroupedBy ? "ngGroupedByIcon" : "ngGroupIcon";
736
+ };
737
+ self.toggleVisible = function() {
738
+ self.visible = !self.visible;
739
+ };
740
+ self.showSortButtonUp = function() {
741
+ return self.sortable ? self.sortDirection === DESC : self.sortable;
742
+ };
743
+ self.showSortButtonDown = function() {
744
+ return self.sortable ? self.sortDirection === ASC : self.sortable;
745
+ };
746
+ self.noSortVisible = function() {
747
+ return !self.sortDirection;
748
+ };
749
+ self.sort = function(evt) {
750
+ if (!self.sortable) {
751
+ return true;
752
+ }
753
+ var dir = self.sortDirection === ASC ? DESC : ASC;
754
+ self.sortDirection = dir;
755
+ config.sortCallback(self, evt);
756
+ return false;
757
+ };
758
+ self.gripClick = function() {
759
+ clicks++;
760
+ if (clicks === 1) {
761
+ timer = setTimeout(function() {
762
+ clicks = 0;
763
+ }, delay);
764
+ } else {
765
+ clearTimeout(timer);
766
+ config.resizeOnDataCallback(self);
767
+ clicks = 0;
768
+ }
769
+ };
770
+ self.gripOnMouseDown = function(event) {
771
+ $scope.isColumnResizing = true;
772
+ if (event.ctrlKey && !self.pinned) {
773
+ self.toggleVisible();
774
+ domUtilityService.BuildStyles($scope, grid);
775
+ return true;
776
+ }
777
+ event.target.parentElement.style.cursor = 'col-resize';
778
+ self.startMousePosition = event.clientX;
779
+ self.origWidth = self.width;
780
+ $(document).mousemove(self.onMouseMove);
781
+ $(document).mouseup(self.gripOnMouseUp);
782
+ return false;
783
+ };
784
+ self.onMouseMove = function(event) {
785
+ var diff = event.clientX - self.startMousePosition;
786
+ var newWidth = diff + self.origWidth;
787
+ self.width = (newWidth < self.minWidth ? self.minWidth : (newWidth > self.maxWidth ? self.maxWidth : newWidth));
788
+ $scope.hasUserChangedGridColumnWidths = true;
789
+ domUtilityService.BuildStyles($scope, grid);
790
+ return false;
791
+ };
792
+ self.gripOnMouseUp = function (event) {
793
+ $(document).off('mousemove', self.onMouseMove);
794
+ $(document).off('mouseup', self.gripOnMouseUp);
795
+ event.target.parentElement.style.cursor = 'default';
796
+ domUtilityService.digest($scope);
797
+ $scope.isColumnResizing = false;
798
+ return false;
799
+ };
800
+ self.copy = function() {
801
+ var ret = new ngColumn(config, $scope, grid, domUtilityService, $templateCache);
802
+ ret.isClone = true;
803
+ ret.orig = self;
804
+ return ret;
805
+ };
806
+ self.setVars = function (fromCol) {
807
+ self.orig = fromCol;
808
+ self.width = fromCol.width;
809
+ self.groupIndex = fromCol.groupIndex;
810
+ self.isGroupedBy = fromCol.isGroupedBy;
811
+ self.displayName = fromCol.displayName;
812
+ self.index = fromCol.index;
813
+ self.isAggCol = fromCol.isAggCol;
814
+ self.cellClass = fromCol.cellClass;
815
+ self.cellFilter = fromCol.cellFilter;
816
+ self.field = fromCol.field;
817
+ self.aggLabelFilter = fromCol.aggLabelFilter;
818
+ self.visible = fromCol.visible;
819
+ self.sortable = fromCol.sortable;
820
+ self.resizable = fromCol.resizable;
821
+ self.pinnable = fromCol.pinnable;
822
+ self.pinned = fromCol.pinned;
823
+ self.originalIndex = fromCol.originalIndex;
824
+ self.sortDirection = fromCol.sortDirection;
825
+ self.sortingAlgorithm = fromCol.sortingAlgorithm;
826
+ self.headerClass = fromCol.headerClass;
827
+ self.headerCellTemplate = fromCol.headerCellTemplate;
828
+ self.cellTemplate = fromCol.cellTemplate;
829
+ self.cellEditTemplate = fromCol.cellEditTemplate;
830
+ };
831
+ };
832
+
833
+ var ngDimension = function (options) {
834
+ this.outerHeight = null;
835
+ this.outerWidth = null;
836
+ $.extend(this, options);
837
+ };
838
+ var ngDomAccessProvider = function (grid) {
839
+ this.previousColumn = null;
840
+ this.grid = grid;
841
+
842
+ };
843
+
844
+ ngDomAccessProvider.prototype.changeUserSelect = function (elm, value) {
845
+ elm.css({
846
+ '-webkit-touch-callout': value,
847
+ '-webkit-user-select': value,
848
+ '-khtml-user-select': value,
849
+ '-moz-user-select': value === 'none' ? '-moz-none' : value,
850
+ '-ms-user-select': value,
851
+ 'user-select': value
852
+ });
853
+ };
854
+ ngDomAccessProvider.prototype.focusCellElement = function ($scope, index) {
855
+ if ($scope.selectionProvider.lastClickedRow) {
856
+ var columnIndex = index !== undefined ? index : this.previousColumn;
857
+ var elm = $scope.selectionProvider.lastClickedRow.clone ? $scope.selectionProvider.lastClickedRow.clone.elm : $scope.selectionProvider.lastClickedRow.elm;
858
+ if (columnIndex !== undefined && elm) {
859
+ var columns = angular.element(elm[0].children).filter(function () { return this.nodeType !== 8; });
860
+ var i = Math.max(Math.min($scope.renderedColumns.length - 1, columnIndex), 0);
861
+ if (this.grid.config.showSelectionCheckbox && angular.element(columns[i]).scope() && angular.element(columns[i]).scope().col.index === 0) {
862
+ i = 1;
863
+ }
864
+ if (columns[i]) {
865
+ columns[i].children[1].children[0].focus();
866
+ }
867
+ this.previousColumn = columnIndex;
868
+ }
869
+ }
870
+ };
871
+ ngDomAccessProvider.prototype.selectionHandlers = function ($scope, elm) {
872
+ var doingKeyDown = false;
873
+ var self = this;
874
+ elm.bind('keydown', function (evt) {
875
+ if (evt.keyCode === 16) {
876
+ self.changeUserSelect(elm, 'none', evt);
877
+ return true;
878
+ } else if (!doingKeyDown) {
879
+ doingKeyDown = true;
880
+ var ret = ngMoveSelectionHandler($scope, elm, evt, self.grid);
881
+ doingKeyDown = false;
882
+ return ret;
883
+ }
884
+ return true;
885
+ });
886
+ elm.bind('keyup', function (evt) {
887
+ if (evt.keyCode === 16) {
888
+ self.changeUserSelect(elm, 'text', evt);
889
+ }
890
+ return true;
891
+ });
892
+ };
893
+ var ngEventProvider = function (grid, $scope, domUtilityService, $timeout) {
894
+ var self = this;
895
+ self.colToMove = undefined;
896
+ self.groupToMove = undefined;
897
+ self.assignEvents = function() {
898
+ if (grid.config.jqueryUIDraggable && !grid.config.enablePinning) {
899
+ grid.$groupPanel.droppable({
900
+ addClasses: false,
901
+ drop: function(event) {
902
+ self.onGroupDrop(event);
903
+ }
904
+ });
905
+ } else {
906
+ grid.$groupPanel.on('mousedown', self.onGroupMouseDown).on('dragover', self.dragOver).on('drop', self.onGroupDrop);
907
+ grid.$headerScroller.on('mousedown', self.onHeaderMouseDown).on('dragover', self.dragOver);
908
+ if (grid.config.enableColumnReordering && !grid.config.enablePinning) {
909
+ grid.$headerScroller.on('drop', self.onHeaderDrop);
910
+ }
911
+ }
912
+ $scope.$watch('renderedColumns', function() {
913
+ $timeout(self.setDraggables);
914
+ });
915
+ };
916
+ self.dragStart = function(evt){
917
+ evt.dataTransfer.setData('text', '');
918
+ };
919
+ self.dragOver = function(evt) {
920
+ evt.preventDefault();
921
+ };
922
+ self.setDraggables = function() {
923
+ if (!grid.config.jqueryUIDraggable) {
924
+ var columns = grid.$root.find('.ngHeaderSortColumn');
925
+ angular.forEach(columns, function(col){
926
+ if(col.className && col.className.indexOf("ngHeaderSortColumn") !== -1){
927
+ col.setAttribute('draggable', 'true');
928
+ if (col.addEventListener) {
929
+ col.addEventListener('dragstart', self.dragStart);
930
+ }
931
+ }
932
+ });
933
+ if (navigator.userAgent.indexOf("MSIE") !== -1){
934
+ grid.$root.find('.ngHeaderSortColumn').bind('selectstart', function () {
935
+ this.dragDrop();
936
+ return false;
937
+ });
938
+ }
939
+ } else {
940
+ grid.$root.find('.ngHeaderSortColumn').draggable({
941
+ helper: 'clone',
942
+ appendTo: 'body',
943
+ stack: 'div',
944
+ addClasses: false,
945
+ start: function(event) {
946
+ self.onHeaderMouseDown(event);
947
+ }
948
+ }).droppable({
949
+ drop: function(event) {
950
+ self.onHeaderDrop(event);
951
+ }
952
+ });
953
+ }
954
+ };
955
+ self.onGroupMouseDown = function(event) {
956
+ var groupItem = $(event.target);
957
+ if (groupItem[0].className !== 'ngRemoveGroup') {
958
+ var groupItemScope = angular.element(groupItem).scope();
959
+ if (groupItemScope) {
960
+ if (!grid.config.jqueryUIDraggable) {
961
+ groupItem.attr('draggable', 'true');
962
+ if(this.addEventListener){
963
+ this.addEventListener('dragstart', self.dragStart);
964
+ }
965
+ if (navigator.userAgent.indexOf("MSIE") !== -1){
966
+ groupItem.bind('selectstart', function () {
967
+ this.dragDrop();
968
+ return false;
969
+ });
970
+ }
971
+ }
972
+ self.groupToMove = { header: groupItem, groupName: groupItemScope.group, index: groupItemScope.$index };
973
+ }
974
+ } else {
975
+ self.groupToMove = undefined;
976
+ }
977
+ };
978
+ self.onGroupDrop = function(event) {
979
+ event.stopPropagation();
980
+ var groupContainer;
981
+ var groupScope;
982
+ if (self.groupToMove) {
983
+ groupContainer = $(event.target).closest('.ngGroupElement');
984
+ if (groupContainer.context.className === 'ngGroupPanel') {
985
+ $scope.configGroups.splice(self.groupToMove.index, 1);
986
+ $scope.configGroups.push(self.groupToMove.groupName);
987
+ } else {
988
+ groupScope = angular.element(groupContainer).scope();
989
+ if (groupScope) {
990
+ if (self.groupToMove.index !== groupScope.$index) {
991
+ $scope.configGroups.splice(self.groupToMove.index, 1);
992
+ $scope.configGroups.splice(groupScope.$index, 0, self.groupToMove.groupName);
993
+ }
994
+ }
995
+ }
996
+ self.groupToMove = undefined;
997
+ grid.fixGroupIndexes();
998
+ } else if (self.colToMove) {
999
+ if ($scope.configGroups.indexOf(self.colToMove.col) === -1) {
1000
+ groupContainer = $(event.target).closest('.ngGroupElement');
1001
+ if (groupContainer.context.className === 'ngGroupPanel' || groupContainer.context.className === 'ngGroupPanelDescription ng-binding') {
1002
+ $scope.groupBy(self.colToMove.col);
1003
+ } else {
1004
+ groupScope = angular.element(groupContainer).scope();
1005
+ if (groupScope) {
1006
+ $scope.removeGroup(groupScope.$index);
1007
+ }
1008
+ }
1009
+ }
1010
+ self.colToMove = undefined;
1011
+ }
1012
+ if (!$scope.$$phase) {
1013
+ $scope.$apply();
1014
+ }
1015
+ };
1016
+ self.onHeaderMouseDown = function(event) {
1017
+ var headerContainer = $(event.target).closest('.ngHeaderSortColumn');
1018
+ var headerScope = angular.element(headerContainer).scope();
1019
+ if (headerScope) {
1020
+ self.colToMove = { header: headerContainer, col: headerScope.col };
1021
+ }
1022
+ };
1023
+ self.onHeaderDrop = function(event) {
1024
+ if (!self.colToMove || self.colToMove.col.pinned) {
1025
+ return;
1026
+ }
1027
+ var headerContainer = $(event.target).closest('.ngHeaderSortColumn');
1028
+ var headerScope = angular.element(headerContainer).scope();
1029
+ if (headerScope) {
1030
+ if (self.colToMove.col === headerScope.col) {
1031
+ return;
1032
+ }
1033
+ $scope.columns.splice(self.colToMove.col.index, 1);
1034
+ $scope.columns.splice(headerScope.col.index, 0, self.colToMove.col);
1035
+ grid.fixColumnIndexes();
1036
+ self.colToMove = undefined;
1037
+ domUtilityService.digest($scope);
1038
+ }
1039
+ };
1040
+
1041
+ self.assignGridEventHandlers = function() {
1042
+ if (grid.config.tabIndex === -1) {
1043
+ grid.$viewport.attr('tabIndex', domUtilityService.numberOfGrids);
1044
+ domUtilityService.numberOfGrids++;
1045
+ } else {
1046
+ grid.$viewport.attr('tabIndex', grid.config.tabIndex);
1047
+ }
1048
+ var windowThrottle;
1049
+ $(window).resize(function(){
1050
+ clearTimeout(windowThrottle);
1051
+ windowThrottle = setTimeout(function() {
1052
+ domUtilityService.RebuildGrid($scope,grid);
1053
+ }, 100);
1054
+ });
1055
+ var parentThrottle;
1056
+ $(grid.$root.parent()).on('resize', function() {
1057
+ clearTimeout(parentThrottle);
1058
+ parentThrottle = setTimeout(function() {
1059
+ domUtilityService.RebuildGrid($scope,grid);
1060
+ }, 100);
1061
+ });
1062
+ };
1063
+ self.assignGridEventHandlers();
1064
+ self.assignEvents();
1065
+ };
1066
+
1067
+ var ngFooter = function ($scope, grid) {
1068
+ $scope.maxRows = function () {
1069
+ var ret = Math.max($scope.totalServerItems, grid.data.length);
1070
+ return ret;
1071
+ };
1072
+ $scope.multiSelect = (grid.config.enableRowSelection && grid.config.multiSelect);
1073
+ $scope.selectedItemCount = grid.selectedItemCount;
1074
+ $scope.maxPages = function () {
1075
+ return Math.ceil($scope.maxRows() / $scope.pagingOptions.pageSize);
1076
+ };
1077
+
1078
+ $scope.pageForward = function() {
1079
+ var page = $scope.pagingOptions.currentPage;
1080
+ if ($scope.totalServerItems > 0) {
1081
+ $scope.pagingOptions.currentPage = Math.min(page + 1, $scope.maxPages());
1082
+ } else {
1083
+ $scope.pagingOptions.currentPage++;
1084
+ }
1085
+ };
1086
+
1087
+ $scope.pageBackward = function() {
1088
+ var page = $scope.pagingOptions.currentPage;
1089
+ $scope.pagingOptions.currentPage = Math.max(page - 1, 1);
1090
+ };
1091
+
1092
+ $scope.pageToFirst = function() {
1093
+ $scope.pagingOptions.currentPage = 1;
1094
+ };
1095
+
1096
+ $scope.pageToLast = function() {
1097
+ var maxPages = $scope.maxPages();
1098
+ $scope.pagingOptions.currentPage = maxPages;
1099
+ };
1100
+
1101
+ $scope.cantPageForward = function() {
1102
+ var curPage = $scope.pagingOptions.currentPage;
1103
+ var maxPages = $scope.maxPages();
1104
+ if ($scope.totalServerItems > 0) {
1105
+ return curPage >= maxPages;
1106
+ } else {
1107
+ return grid.data.length < 1;
1108
+ }
1109
+
1110
+ };
1111
+ $scope.cantPageToLast = function() {
1112
+ if ($scope.totalServerItems > 0) {
1113
+ return $scope.cantPageForward();
1114
+ } else {
1115
+ return true;
1116
+ }
1117
+ };
1118
+ $scope.cantPageBackward = function() {
1119
+ var curPage = $scope.pagingOptions.currentPage;
1120
+ return curPage <= 1;
1121
+ };
1122
+ };
1123
+
1124
+ var ngGrid = function ($scope, options, sortService, domUtilityService, $filter, $templateCache, $utils, $timeout, $parse, $http, $q) {
1125
+ var defaults = {
1126
+ aggregateTemplate: undefined,
1127
+ afterSelectionChange: function() {
1128
+ },
1129
+ beforeSelectionChange: function() {
1130
+ return true;
1131
+ },
1132
+ checkboxCellTemplate: undefined,
1133
+ checkboxHeaderTemplate: undefined,
1134
+ columnDefs: undefined,
1135
+ data: [],
1136
+ dataUpdated: function() {
1137
+ },
1138
+ enableCellEdit: false,
1139
+ enableCellEditOnFocus: false,
1140
+ enableCellSelection: false,
1141
+ enableColumnResize: false,
1142
+ enableColumnReordering: false,
1143
+ enableColumnHeavyVirt: false,
1144
+ enablePaging: false,
1145
+ enablePinning: false,
1146
+ enableRowSelection: true,
1147
+ enableSorting: true,
1148
+ enableHighlighting: false,
1149
+ excludeProperties: [],
1150
+ filterOptions: {
1151
+ filterText: "",
1152
+ useExternalFilter: false
1153
+ },
1154
+ footerRowHeight: 55,
1155
+ footerTemplate: undefined,
1156
+ groups: [],
1157
+ groupsCollapsedByDefault: true,
1158
+ headerRowHeight: 30,
1159
+ headerRowTemplate: undefined,
1160
+ jqueryUIDraggable: false,
1161
+ jqueryUITheme: false,
1162
+ keepLastSelected: true,
1163
+ maintainColumnRatios: undefined,
1164
+ menuTemplate: undefined,
1165
+ multiSelect: true,
1166
+ pagingOptions: {
1167
+ pageSizes: [250, 500, 1000],
1168
+ pageSize: 250,
1169
+ currentPage: 1
1170
+ },
1171
+ pinSelectionCheckbox: false,
1172
+ plugins: [],
1173
+ primaryKey: undefined,
1174
+ rowHeight: 30,
1175
+ rowTemplate: undefined,
1176
+ selectedItems: [],
1177
+ selectWithCheckboxOnly: false,
1178
+ showColumnMenu: false,
1179
+ showFilter: false,
1180
+ showFooter: false,
1181
+ showGroupPanel: false,
1182
+ showSelectionCheckbox: false,
1183
+ sortInfo: {fields: [], columns: [], directions: [] },
1184
+ tabIndex: -1,
1185
+ totalServerItems: 0,
1186
+ useExternalSorting: false,
1187
+ i18n: 'en',
1188
+ virtualizationThreshold: 50
1189
+ },
1190
+ self = this;
1191
+ self.maxCanvasHt = 0;
1192
+ self.config = $.extend(defaults, window.ngGrid.config, options);
1193
+ self.config.showSelectionCheckbox = (self.config.showSelectionCheckbox && self.config.enableColumnHeavyVirt === false);
1194
+ self.config.enablePinning = (self.config.enablePinning && self.config.enableColumnHeavyVirt === false);
1195
+ self.config.selectWithCheckboxOnly = (self.config.selectWithCheckboxOnly && self.config.showSelectionCheckbox !== false);
1196
+ self.config.pinSelectionCheckbox = self.config.enablePinning;
1197
+
1198
+ if (typeof options.columnDefs === "string") {
1199
+ self.config.columnDefs = $scope.$eval(options.columnDefs);
1200
+ }
1201
+ self.rowCache = [];
1202
+ self.rowMap = [];
1203
+ self.gridId = "ng" + $utils.newId();
1204
+ self.$root = null;
1205
+ self.$groupPanel = null;
1206
+ self.$topPanel = null;
1207
+ self.$headerContainer = null;
1208
+ self.$headerScroller = null;
1209
+ self.$headers = null;
1210
+ self.$viewport = null;
1211
+ self.$canvas = null;
1212
+ self.rootDim = self.config.gridDim;
1213
+ self.data = [];
1214
+ self.lateBindColumns = false;
1215
+ self.filteredRows = [];
1216
+
1217
+ self.initTemplates = function() {
1218
+ var templates = ['rowTemplate', 'aggregateTemplate', 'headerRowTemplate', 'checkboxCellTemplate', 'checkboxHeaderTemplate', 'menuTemplate', 'footerTemplate'];
1219
+
1220
+ var promises = [];
1221
+ angular.forEach(templates, function(template) {
1222
+ promises.push( self.getTemplate(template) );
1223
+ });
1224
+
1225
+ return $q.all(promises);
1226
+ };
1227
+ self.getTemplate = function (key) {
1228
+ var t = self.config[key];
1229
+ var uKey = self.gridId + key + ".html";
1230
+ var p = $q.defer();
1231
+ if (t && !TEMPLATE_REGEXP.test(t)) {
1232
+ $http.get(t, {
1233
+ cache: $templateCache
1234
+ })
1235
+ .success(function(data){
1236
+ $templateCache.put(uKey, data);
1237
+ p.resolve();
1238
+ })
1239
+ .error(function(err){
1240
+ p.reject("Could not load template: " + t);
1241
+ });
1242
+ } else if (t) {
1243
+ $templateCache.put(uKey, t);
1244
+ p.resolve();
1245
+ } else {
1246
+ var dKey = key + ".html";
1247
+ $templateCache.put(uKey, $templateCache.get(dKey));
1248
+ p.resolve();
1249
+ }
1250
+
1251
+ return p.promise;
1252
+ };
1253
+
1254
+ if (typeof self.config.data === "object") {
1255
+ self.data = self.config.data;
1256
+ }
1257
+ self.calcMaxCanvasHeight = function() {
1258
+ var calculatedHeight;
1259
+ if(self.config.groups.length > 0){
1260
+ calculatedHeight = self.rowFactory.parsedData.filter(function(e) {
1261
+ return !e[NG_HIDDEN];
1262
+ }).length * self.config.rowHeight;
1263
+ } else {
1264
+ calculatedHeight = self.filteredRows.length * self.config.rowHeight;
1265
+ }
1266
+ return calculatedHeight;
1267
+ };
1268
+ self.elementDims = {
1269
+ scrollW: 0,
1270
+ scrollH: 0,
1271
+ rowIndexCellW: 25,
1272
+ rowSelectedCellW: 25,
1273
+ rootMaxW: 0,
1274
+ rootMaxH: 0
1275
+ };
1276
+ self.setRenderedRows = function (newRows) {
1277
+ $scope.renderedRows.length = newRows.length;
1278
+ for (var i = 0; i < newRows.length; i++) {
1279
+ if (!$scope.renderedRows[i] || (newRows[i].isAggRow || $scope.renderedRows[i].isAggRow)) {
1280
+ $scope.renderedRows[i] = newRows[i].copy();
1281
+ $scope.renderedRows[i].collapsed = newRows[i].collapsed;
1282
+ if (!newRows[i].isAggRow) {
1283
+ $scope.renderedRows[i].setVars(newRows[i]);
1284
+ }
1285
+ } else {
1286
+ $scope.renderedRows[i].setVars(newRows[i]);
1287
+ }
1288
+ $scope.renderedRows[i].rowIndex = newRows[i].rowIndex;
1289
+ $scope.renderedRows[i].offsetTop = newRows[i].offsetTop;
1290
+ $scope.renderedRows[i].selected = newRows[i].selected;
1291
+ newRows[i].renderedRowIndex = i;
1292
+ }
1293
+ self.refreshDomSizes();
1294
+ $scope.$emit('ngGridEventRows', newRows);
1295
+ };
1296
+ self.minRowsToRender = function() {
1297
+ var viewportH = $scope.viewportDimHeight() || 1;
1298
+ return Math.floor(viewportH / self.config.rowHeight);
1299
+ };
1300
+ self.refreshDomSizes = function() {
1301
+ var dim = new ngDimension();
1302
+ dim.outerWidth = self.elementDims.rootMaxW;
1303
+ dim.outerHeight = self.elementDims.rootMaxH;
1304
+ self.rootDim = dim;
1305
+ self.maxCanvasHt = self.calcMaxCanvasHeight();
1306
+ };
1307
+ self.buildColumnDefsFromData = function () {
1308
+ self.config.columnDefs = [];
1309
+ var item = self.data[0];
1310
+ if (!item) {
1311
+ self.lateBoundColumns = true;
1312
+ return;
1313
+ }
1314
+ $utils.forIn(item, function (prop, propName) {
1315
+ if (self.config.excludeProperties.indexOf(propName) === -1) {
1316
+ self.config.columnDefs.push({
1317
+ field: propName
1318
+ });
1319
+ }
1320
+ });
1321
+ };
1322
+ self.buildColumns = function() {
1323
+ var columnDefs = self.config.columnDefs,
1324
+ cols = [];
1325
+ if (!columnDefs) {
1326
+ self.buildColumnDefsFromData();
1327
+ columnDefs = self.config.columnDefs;
1328
+ }
1329
+ if (self.config.showSelectionCheckbox) {
1330
+ cols.push(new ngColumn({
1331
+ colDef: {
1332
+ field: '\u2714',
1333
+ width: self.elementDims.rowSelectedCellW,
1334
+ sortable: false,
1335
+ resizable: false,
1336
+ groupable: false,
1337
+ headerCellTemplate: $templateCache.get($scope.gridId + 'checkboxHeaderTemplate.html'),
1338
+ cellTemplate: $templateCache.get($scope.gridId + 'checkboxCellTemplate.html'),
1339
+ pinned: self.config.pinSelectionCheckbox
1340
+ },
1341
+ index: 0,
1342
+ headerRowHeight: self.config.headerRowHeight,
1343
+ sortCallback: self.sortData,
1344
+ resizeOnDataCallback: self.resizeOnData,
1345
+ enableResize: self.config.enableColumnResize,
1346
+ enableSort: self.config.enableSorting,
1347
+ enablePinning: self.config.enablePinning
1348
+ }, $scope, self, domUtilityService, $templateCache, $utils));
1349
+ }
1350
+ if (columnDefs.length > 0) {
1351
+ var checkboxOffset = self.config.showSelectionCheckbox ? 1 : 0;
1352
+ var groupOffset = $scope.configGroups.length;
1353
+ $scope.configGroups.length = 0;
1354
+ angular.forEach(columnDefs, function(colDef, i) {
1355
+ i += checkboxOffset;
1356
+ var column = new ngColumn({
1357
+ colDef: colDef,
1358
+ index: i + groupOffset,
1359
+ originalIndex: i,
1360
+ headerRowHeight: self.config.headerRowHeight,
1361
+ sortCallback: self.sortData,
1362
+ resizeOnDataCallback: self.resizeOnData,
1363
+ enableResize: self.config.enableColumnResize,
1364
+ enableSort: self.config.enableSorting,
1365
+ enablePinning: self.config.enablePinning,
1366
+ enableCellEdit: self.config.enableCellEdit || self.config.enableCellEditOnFocus
1367
+ }, $scope, self, domUtilityService, $templateCache, $utils);
1368
+ var indx = self.config.groups.indexOf(colDef.field);
1369
+ if (indx !== -1) {
1370
+ column.isGroupedBy = true;
1371
+ $scope.configGroups.splice(indx, 0, column);
1372
+ column.groupIndex = $scope.configGroups.length;
1373
+ }
1374
+ cols.push(column);
1375
+ });
1376
+ $scope.columns = cols;
1377
+ if (self.config.groups.length > 0) {
1378
+ self.rowFactory.getGrouping(self.config.groups);
1379
+ }
1380
+ }
1381
+ };
1382
+ self.configureColumnWidths = function() {
1383
+ var asterisksArray = [],
1384
+ percentArray = [],
1385
+ asteriskNum = 0,
1386
+ totalWidth = 0;
1387
+ var indexMap = {};
1388
+ angular.forEach($scope.columns, function(ngCol, i) {
1389
+ if (!$utils.isNullOrUndefined(ngCol.originalIndex)) {
1390
+ var origIndex = ngCol.originalIndex;
1391
+ if (self.config.showSelectionCheckbox) {
1392
+ if(ngCol.originalIndex === 0 && ngCol.visible){
1393
+ totalWidth += 25;
1394
+ }
1395
+ origIndex--;
1396
+ }
1397
+ indexMap[origIndex] = i;
1398
+ }
1399
+ });
1400
+
1401
+ angular.forEach(self.config.columnDefs, function(colDef, i) {
1402
+ var ngColumn = $scope.columns[indexMap[i]];
1403
+
1404
+ colDef.index = i;
1405
+
1406
+ var isPercent = false, t;
1407
+ if ($utils.isNullOrUndefined(colDef.width)) {
1408
+ colDef.width = "*";
1409
+ } else {
1410
+ isPercent = isNaN(colDef.width) ? $utils.endsWith(colDef.width, "%") : false;
1411
+ t = isPercent ? colDef.width : parseInt(colDef.width, 10);
1412
+ }
1413
+ if (isNaN(t) && !$scope.hasUserChangedGridColumnWidths) {
1414
+ t = colDef.width;
1415
+ if (t === 'auto') {
1416
+ ngColumn.width = ngColumn.minWidth;
1417
+ totalWidth += ngColumn.width;
1418
+ var temp = ngColumn;
1419
+
1420
+ $scope.$on("ngGridEventData", function () {
1421
+ self.resizeOnData(temp);
1422
+ });
1423
+ return;
1424
+ } else if (t.indexOf("*") !== -1) {
1425
+ if (ngColumn.visible !== false) {
1426
+ asteriskNum += t.length;
1427
+ }
1428
+ asterisksArray.push(colDef);
1429
+ return;
1430
+ } else if (isPercent) {
1431
+ percentArray.push(colDef);
1432
+ return;
1433
+ } else {
1434
+ throw "unable to parse column width, use percentage (\"10%\",\"20%\", etc...) or \"*\" to use remaining width of grid";
1435
+ }
1436
+ } else if (ngColumn.visible !== false) {
1437
+ totalWidth += ngColumn.width = parseInt(ngColumn.width, 10);
1438
+ }
1439
+ });
1440
+ if (percentArray.length > 0) {
1441
+ self.config.maintainColumnRatios = self.config.maintainColumnRatios !== false;
1442
+ var percentWidth = 0;
1443
+ var hiddenPercent = 0;
1444
+ angular.forEach(percentArray, function(colDef) {
1445
+ var ngColumn = $scope.columns[indexMap[colDef.index]];
1446
+ var t = colDef.width;
1447
+ var percent = parseInt(t.slice(0, -1), 10) / 100;
1448
+ percentWidth += percent;
1449
+
1450
+ if (!ngColumn.visible) {
1451
+ hiddenPercent += percent;
1452
+ }
1453
+ });
1454
+ var percentWidthUsed = percentWidth - hiddenPercent;
1455
+ angular.forEach(percentArray, function(colDef) {
1456
+ var ngColumn = $scope.columns[indexMap[colDef.index]];
1457
+ var t = colDef.width;
1458
+ var percent = parseInt(t.slice(0, -1), 10) / 100;
1459
+ if (hiddenPercent > 0) {
1460
+ percent = percent / percentWidthUsed;
1461
+ }
1462
+ else {
1463
+ percent = percent / percentWidth;
1464
+ }
1465
+
1466
+ var pixelsForPercentBasedWidth = self.rootDim.outerWidth * percentWidth;
1467
+ ngColumn.width = Math.floor(pixelsForPercentBasedWidth * percent);
1468
+ totalWidth += ngColumn.width;
1469
+ });
1470
+ }
1471
+ if (asterisksArray.length > 0) {
1472
+ self.config.maintainColumnRatios = self.config.maintainColumnRatios !== false;
1473
+ var remainingWidth = self.rootDim.outerWidth - totalWidth;
1474
+ if (self.maxCanvasHt > $scope.viewportDimHeight()) {
1475
+ remainingWidth -= domUtilityService.ScrollW;
1476
+ }
1477
+ var asteriskVal = Math.floor(remainingWidth / asteriskNum);
1478
+ angular.forEach(asterisksArray, function(colDef, i) {
1479
+ var ngColumn = $scope.columns[indexMap[colDef.index]];
1480
+ ngColumn.width = asteriskVal * colDef.width.length;
1481
+ if (ngColumn.visible !== false) {
1482
+ totalWidth += ngColumn.width;
1483
+ }
1484
+
1485
+ var isLast = (i === (asterisksArray.length - 1));
1486
+ if(isLast && totalWidth < self.rootDim.outerWidth){
1487
+ var gridWidthDifference = self.rootDim.outerWidth - totalWidth;
1488
+ if(self.maxCanvasHt > $scope.viewportDimHeight()){
1489
+ gridWidthDifference -= domUtilityService.ScrollW;
1490
+ }
1491
+ ngColumn.width += gridWidthDifference;
1492
+ }
1493
+ });
1494
+ }
1495
+ };
1496
+ self.init = function() {
1497
+ return self.initTemplates().then(function(){
1498
+ $scope.selectionProvider = new ngSelectionProvider(self, $scope, $parse);
1499
+ $scope.domAccessProvider = new ngDomAccessProvider(self);
1500
+ self.rowFactory = new ngRowFactory(self, $scope, domUtilityService, $templateCache, $utils);
1501
+ self.searchProvider = new ngSearchProvider($scope, self, $filter);
1502
+ self.styleProvider = new ngStyleProvider($scope, self);
1503
+ $scope.$watch('configGroups', function(a) {
1504
+ var tempArr = [];
1505
+ angular.forEach(a, function(item) {
1506
+ tempArr.push(item.field || item);
1507
+ });
1508
+ self.config.groups = tempArr;
1509
+ self.rowFactory.filteredRowsChanged();
1510
+ $scope.$emit('ngGridEventGroups', a);
1511
+ }, true);
1512
+ $scope.$watch('columns', function (a) {
1513
+ if(!$scope.isColumnResizing){
1514
+ domUtilityService.RebuildGrid($scope, self);
1515
+ }
1516
+ $scope.$emit('ngGridEventColumns', a);
1517
+ }, true);
1518
+ $scope.$watch(function() {
1519
+ return options.i18n;
1520
+ }, function(newLang) {
1521
+ $utils.seti18n($scope, newLang);
1522
+ });
1523
+ self.maxCanvasHt = self.calcMaxCanvasHeight();
1524
+
1525
+ if (self.config.sortInfo.fields && self.config.sortInfo.fields.length > 0) {
1526
+ $scope.$watch(function() {
1527
+ return self.config.sortInfo;
1528
+ }, function(sortInfo){
1529
+ if (!sortService.isSorting) {
1530
+ self.sortColumnsInit();
1531
+ $scope.$emit('ngGridEventSorted', self.config.sortInfo);
1532
+ }
1533
+ },true);
1534
+ }
1535
+ });
1536
+ };
1537
+ self.resizeOnData = function(col) {
1538
+ var longest = col.minWidth;
1539
+ var arr = $utils.getElementsByClassName('col' + col.index);
1540
+ angular.forEach(arr, function(elem, index) {
1541
+ var i;
1542
+ if (index === 0) {
1543
+ var kgHeaderText = $(elem).find('.ngHeaderText');
1544
+ i = $utils.visualLength(kgHeaderText) + 10;
1545
+ } else {
1546
+ var ngCellText = $(elem).find('.ngCellText');
1547
+ i = $utils.visualLength(ngCellText) + 10;
1548
+ }
1549
+ if (i > longest) {
1550
+ longest = i;
1551
+ }
1552
+ });
1553
+ col.width = col.longest = Math.min(col.maxWidth, longest + 7);
1554
+ domUtilityService.BuildStyles($scope, self, true);
1555
+ };
1556
+ self.lastSortedColumns = [];
1557
+ self.sortData = function(col, evt) {
1558
+ if (evt && evt.shiftKey && self.config.sortInfo) {
1559
+ var indx = self.config.sortInfo.columns.indexOf(col);
1560
+ if (indx === -1) {
1561
+ if (self.config.sortInfo.columns.length === 1) {
1562
+ self.config.sortInfo.columns[0].sortPriority = 1;
1563
+ }
1564
+ self.config.sortInfo.columns.push(col);
1565
+ col.sortPriority = self.config.sortInfo.columns.length;
1566
+ self.config.sortInfo.fields.push(col.field);
1567
+ self.config.sortInfo.directions.push(col.sortDirection);
1568
+ self.lastSortedColumns.push(col);
1569
+ } else {
1570
+ self.config.sortInfo.directions[indx] = col.sortDirection;
1571
+ }
1572
+ } else {
1573
+ var isArr = $.isArray(col);
1574
+ self.config.sortInfo.columns.length = 0;
1575
+ self.config.sortInfo.fields.length = 0;
1576
+ self.config.sortInfo.directions.length = 0;
1577
+ var push = function (c) {
1578
+ self.config.sortInfo.columns.push(c);
1579
+ self.config.sortInfo.fields.push(c.field);
1580
+ self.config.sortInfo.directions.push(c.sortDirection);
1581
+ self.lastSortedColumns.push(c);
1582
+ };
1583
+ if (isArr) {
1584
+ self.clearSortingData();
1585
+ angular.forEach(col, function (c, i) {
1586
+ c.sortPriority = i + 1;
1587
+ push(c);
1588
+ });
1589
+ } else {
1590
+ self.clearSortingData(col);
1591
+ col.sortPriority = undefined;
1592
+ push(col);
1593
+ }
1594
+ }
1595
+ self.sortActual();
1596
+ self.searchProvider.evalFilter();
1597
+ $scope.$emit('ngGridEventSorted', self.config.sortInfo);
1598
+ };
1599
+ self.sortColumnsInit = function() {
1600
+ if (self.config.sortInfo.columns) {
1601
+ self.config.sortInfo.columns.length = 0;
1602
+ } else {
1603
+ self.config.sortInfo.columns = [];
1604
+ }
1605
+ angular.forEach($scope.columns, function(c) {
1606
+ var i = self.config.sortInfo.fields.indexOf(c.field);
1607
+ if (i !== -1) {
1608
+ c.sortDirection = self.config.sortInfo.directions[i] || 'asc';
1609
+ self.config.sortInfo.columns[i] = c;
1610
+ }
1611
+ });
1612
+ angular.forEach(self.config.sortInfo.columns, function(c){
1613
+ self.sortData(c);
1614
+ });
1615
+ };
1616
+ self.sortActual = function() {
1617
+ if (!self.config.useExternalSorting) {
1618
+ var tempData = self.data.slice(0);
1619
+ angular.forEach(tempData, function(item, i) {
1620
+ var e = self.rowMap[i];
1621
+ if (e !== undefined) {
1622
+ var v = self.rowCache[e];
1623
+ if (v !== undefined) {
1624
+ item.preSortSelected = v.selected;
1625
+ item.preSortIndex = i;
1626
+ }
1627
+ }
1628
+ });
1629
+ sortService.Sort(self.config.sortInfo, tempData);
1630
+ angular.forEach(tempData, function(item, i) {
1631
+ self.rowCache[i].entity = item;
1632
+ self.rowCache[i].selected = item.preSortSelected;
1633
+ self.rowMap[item.preSortIndex] = i;
1634
+ delete item.preSortSelected;
1635
+ delete item.preSortIndex;
1636
+ });
1637
+ }
1638
+ };
1639
+
1640
+ self.clearSortingData = function (col) {
1641
+ if (!col) {
1642
+ angular.forEach(self.lastSortedColumns, function (c) {
1643
+ c.sortDirection = "";
1644
+ c.sortPriority = null;
1645
+ });
1646
+ self.lastSortedColumns = [];
1647
+ } else {
1648
+ angular.forEach(self.lastSortedColumns, function (c) {
1649
+ if (col.index !== c.index) {
1650
+ c.sortDirection = "";
1651
+ c.sortPriority = null;
1652
+ }
1653
+ });
1654
+ self.lastSortedColumns[0] = col;
1655
+ self.lastSortedColumns.length = 1;
1656
+ }
1657
+ };
1658
+ self.fixColumnIndexes = function() {
1659
+ for (var i = 0; i < $scope.columns.length; i++) {
1660
+ $scope.columns[i].index = i;
1661
+ }
1662
+ };
1663
+ self.fixGroupIndexes = function() {
1664
+ angular.forEach($scope.configGroups, function(item, i) {
1665
+ item.groupIndex = i + 1;
1666
+ });
1667
+ };
1668
+ $scope.elementsNeedMeasuring = true;
1669
+ $scope.columns = [];
1670
+ $scope.renderedRows = [];
1671
+ $scope.renderedColumns = [];
1672
+ $scope.headerRow = null;
1673
+ $scope.rowHeight = self.config.rowHeight;
1674
+ $scope.jqueryUITheme = self.config.jqueryUITheme;
1675
+ $scope.showSelectionCheckbox = self.config.showSelectionCheckbox;
1676
+ $scope.enableCellSelection = self.config.enableCellSelection;
1677
+ $scope.enableCellEditOnFocus = self.config.enableCellEditOnFocus;
1678
+ $scope.footer = null;
1679
+ $scope.selectedItems = self.config.selectedItems;
1680
+ $scope.multiSelect = self.config.multiSelect;
1681
+ $scope.showFooter = self.config.showFooter;
1682
+ $scope.footerRowHeight = $scope.showFooter ? self.config.footerRowHeight : 0;
1683
+ $scope.showColumnMenu = self.config.showColumnMenu;
1684
+ $scope.showMenu = false;
1685
+ $scope.configGroups = [];
1686
+ $scope.gridId = self.gridId;
1687
+ $scope.enablePaging = self.config.enablePaging;
1688
+ $scope.pagingOptions = self.config.pagingOptions;
1689
+ $scope.i18n = {};
1690
+ $utils.seti18n($scope, self.config.i18n);
1691
+ $scope.adjustScrollLeft = function (scrollLeft) {
1692
+ var colwidths = 0,
1693
+ totalLeft = 0,
1694
+ x = $scope.columns.length,
1695
+ newCols = [],
1696
+ dcv = !self.config.enableColumnHeavyVirt;
1697
+ var r = 0;
1698
+ var addCol = function (c) {
1699
+ if (dcv) {
1700
+ newCols.push(c);
1701
+ } else {
1702
+ if (!$scope.renderedColumns[r]) {
1703
+ $scope.renderedColumns[r] = c.copy();
1704
+ } else {
1705
+ $scope.renderedColumns[r].setVars(c);
1706
+ }
1707
+ }
1708
+ r++;
1709
+ };
1710
+ for (var i = 0; i < x; i++) {
1711
+ var col = $scope.columns[i];
1712
+ if (col.visible !== false) {
1713
+ var w = col.width + colwidths;
1714
+ if (col.pinned) {
1715
+ addCol(col);
1716
+ var newLeft = i > 0 ? (scrollLeft + totalLeft) : scrollLeft;
1717
+ domUtilityService.setColLeft(col, newLeft, self);
1718
+ totalLeft += col.width;
1719
+ } else {
1720
+ if (w >= scrollLeft) {
1721
+ if (colwidths <= scrollLeft + self.rootDim.outerWidth) {
1722
+ addCol(col);
1723
+ }
1724
+ }
1725
+ }
1726
+ colwidths += col.width;
1727
+ }
1728
+ }
1729
+ if (dcv) {
1730
+ $scope.renderedColumns = newCols;
1731
+ }
1732
+ };
1733
+ self.prevScrollTop = 0;
1734
+ self.prevScrollIndex = 0;
1735
+ $scope.adjustScrollTop = function(scrollTop, force) {
1736
+ if (self.prevScrollTop === scrollTop && !force) {
1737
+ return;
1738
+ }
1739
+ if (scrollTop > 0 && self.$viewport[0].scrollHeight - scrollTop <= self.$viewport.outerHeight()) {
1740
+ $scope.$emit('ngGridEventScroll');
1741
+ }
1742
+ var rowIndex = Math.floor(scrollTop / self.config.rowHeight);
1743
+ var newRange;
1744
+ if (self.filteredRows.length > self.config.virtualizationThreshold) {
1745
+ if (self.prevScrollTop < scrollTop && rowIndex < self.prevScrollIndex + SCROLL_THRESHOLD) {
1746
+ return;
1747
+ }
1748
+ if (self.prevScrollTop > scrollTop && rowIndex > self.prevScrollIndex - SCROLL_THRESHOLD) {
1749
+ return;
1750
+ }
1751
+ newRange = new ngRange(Math.max(0, rowIndex - EXCESS_ROWS), rowIndex + self.minRowsToRender() + EXCESS_ROWS);
1752
+ } else {
1753
+ var maxLen = $scope.configGroups.length > 0 ? self.rowFactory.parsedData.length : self.data.length;
1754
+ newRange = new ngRange(0, Math.max(maxLen, self.minRowsToRender() + EXCESS_ROWS));
1755
+ }
1756
+ self.prevScrollTop = scrollTop;
1757
+ self.rowFactory.UpdateViewableRange(newRange);
1758
+ self.prevScrollIndex = rowIndex;
1759
+ };
1760
+ $scope.toggleShowMenu = function() {
1761
+ $scope.showMenu = !$scope.showMenu;
1762
+ };
1763
+ $scope.toggleSelectAll = function(state, selectOnlyVisible) {
1764
+ $scope.selectionProvider.toggleSelectAll(state, false, selectOnlyVisible);
1765
+ };
1766
+ $scope.totalFilteredItemsLength = function() {
1767
+ return self.filteredRows.length;
1768
+ };
1769
+ $scope.showGroupPanel = function() {
1770
+ return self.config.showGroupPanel;
1771
+ };
1772
+ $scope.topPanelHeight = function() {
1773
+ return self.config.showGroupPanel === true ? self.config.headerRowHeight + 32 : self.config.headerRowHeight;
1774
+ };
1775
+
1776
+ $scope.viewportDimHeight = function() {
1777
+ return Math.max(0, self.rootDim.outerHeight - $scope.topPanelHeight() - $scope.footerRowHeight - 2);
1778
+ };
1779
+ $scope.groupBy = function (col) {
1780
+ if (self.data.length < 1 || !col.groupable || !col.field) {
1781
+ return;
1782
+ }
1783
+ if (!col.sortDirection) {
1784
+ col.sort({ shiftKey: $scope.configGroups.length > 0 ? true : false });
1785
+ }
1786
+
1787
+ var indx = $scope.configGroups.indexOf(col);
1788
+ if (indx === -1) {
1789
+ col.isGroupedBy = true;
1790
+ $scope.configGroups.push(col);
1791
+ col.groupIndex = $scope.configGroups.length;
1792
+ } else {
1793
+ $scope.removeGroup(indx);
1794
+ }
1795
+ self.$viewport.scrollTop(0);
1796
+ domUtilityService.digest($scope);
1797
+ };
1798
+ $scope.removeGroup = function(index) {
1799
+ var col = $scope.columns.filter(function(item) {
1800
+ return item.groupIndex === (index + 1);
1801
+ })[0];
1802
+ col.isGroupedBy = false;
1803
+ col.groupIndex = 0;
1804
+ if ($scope.columns[index].isAggCol) {
1805
+ $scope.columns.splice(index, 1);
1806
+ $scope.configGroups.splice(index, 1);
1807
+ self.fixGroupIndexes();
1808
+ }
1809
+ if ($scope.configGroups.length === 0) {
1810
+ self.fixColumnIndexes();
1811
+ domUtilityService.digest($scope);
1812
+ }
1813
+ $scope.adjustScrollLeft(0);
1814
+ };
1815
+ $scope.togglePin = function (col) {
1816
+ var indexFrom = col.index;
1817
+ var indexTo = 0;
1818
+ for (var i = 0; i < $scope.columns.length; i++) {
1819
+ if (!$scope.columns[i].pinned) {
1820
+ break;
1821
+ }
1822
+ indexTo++;
1823
+ }
1824
+ if (col.pinned) {
1825
+ indexTo = Math.max(col.originalIndex, indexTo - 1);
1826
+ }
1827
+ col.pinned = !col.pinned;
1828
+ $scope.columns.splice(indexFrom, 1);
1829
+ $scope.columns.splice(indexTo, 0, col);
1830
+ self.fixColumnIndexes();
1831
+ domUtilityService.BuildStyles($scope, self, true);
1832
+ self.$viewport.scrollLeft(self.$viewport.scrollLeft() - col.width);
1833
+ };
1834
+ $scope.totalRowWidth = function() {
1835
+ var totalWidth = 0,
1836
+ cols = $scope.columns;
1837
+ for (var i = 0; i < cols.length; i++) {
1838
+ if (cols[i].visible !== false) {
1839
+ totalWidth += cols[i].width;
1840
+ }
1841
+ }
1842
+ return totalWidth;
1843
+ };
1844
+ $scope.headerScrollerDim = function() {
1845
+ var viewportH = $scope.viewportDimHeight(),
1846
+ maxHeight = self.maxCanvasHt,
1847
+ vScrollBarIsOpen = (maxHeight > viewportH),
1848
+ newDim = new ngDimension();
1849
+
1850
+ newDim.autoFitHeight = true;
1851
+ newDim.outerWidth = $scope.totalRowWidth();
1852
+ if (vScrollBarIsOpen) {
1853
+ newDim.outerWidth += self.elementDims.scrollW;
1854
+ } else if ((maxHeight - viewportH) <= self.elementDims.scrollH) {
1855
+ newDim.outerWidth += self.elementDims.scrollW;
1856
+ }
1857
+ return newDim;
1858
+ };
1859
+ };
1860
+
1861
+ var ngRange = function (top, bottom) {
1862
+ this.topRow = top;
1863
+ this.bottomRow = bottom;
1864
+ };
1865
+ var ngRow = function (entity, config, selectionProvider, rowIndex, $utils) {
1866
+ this.entity = entity;
1867
+ this.config = config;
1868
+ this.selectionProvider = selectionProvider;
1869
+ this.rowIndex = rowIndex;
1870
+ this.utils = $utils;
1871
+ this.selected = selectionProvider.getSelection(entity);
1872
+ this.cursor = this.config.enableRowSelection ? 'pointer' : 'default';
1873
+ this.beforeSelectionChange = config.beforeSelectionChangeCallback;
1874
+ this.afterSelectionChange = config.afterSelectionChangeCallback;
1875
+ this.offsetTop = this.rowIndex * config.rowHeight;
1876
+ this.rowDisplayIndex = 0;
1877
+ };
1878
+
1879
+ ngRow.prototype.setSelection = function (isSelected) {
1880
+ this.selectionProvider.setSelection(this, isSelected);
1881
+ this.selectionProvider.lastClickedRow = this;
1882
+ };
1883
+ ngRow.prototype.continueSelection = function (event) {
1884
+ this.selectionProvider.ChangeSelection(this, event);
1885
+ };
1886
+ ngRow.prototype.ensureEntity = function (expected) {
1887
+ if (this.entity !== expected) {
1888
+ this.entity = expected;
1889
+ this.selected = this.selectionProvider.getSelection(this.entity);
1890
+ }
1891
+ };
1892
+ ngRow.prototype.toggleSelected = function (event) {
1893
+ if (!this.config.enableRowSelection && !this.config.enableCellSelection) {
1894
+ return true;
1895
+ }
1896
+ var element = event.target || event;
1897
+ if (element.type === "checkbox" && element.parentElement.className !== "ngSelectionCell ng-scope") {
1898
+ return true;
1899
+ }
1900
+ if (this.config.selectWithCheckboxOnly && element.type !== "checkbox") {
1901
+ this.selectionProvider.lastClickedRow = this;
1902
+ return true;
1903
+ }
1904
+ if (this.beforeSelectionChange(this, event)) {
1905
+ this.continueSelection(event);
1906
+ }
1907
+ return false;
1908
+ };
1909
+ ngRow.prototype.alternatingRowClass = function () {
1910
+ var isEven = (this.rowIndex % 2) === 0;
1911
+ var classes = {
1912
+ 'ngRow' : true,
1913
+ 'selected': this.selected,
1914
+ 'even': isEven,
1915
+ 'odd': !isEven,
1916
+ 'ui-state-default': this.config.jqueryUITheme && isEven,
1917
+ 'ui-state-active': this.config.jqueryUITheme && !isEven
1918
+ };
1919
+ return classes;
1920
+ };
1921
+ ngRow.prototype.getProperty = function (path) {
1922
+ return this.utils.evalProperty(this.entity, path);
1923
+ };
1924
+ ngRow.prototype.copy = function () {
1925
+ this.clone = new ngRow(this.entity, this.config, this.selectionProvider, this.rowIndex, this.utils);
1926
+ this.clone.isClone = true;
1927
+ this.clone.elm = this.elm;
1928
+ this.clone.orig = this;
1929
+ return this.clone;
1930
+ };
1931
+ ngRow.prototype.setVars = function (fromRow) {
1932
+ fromRow.clone = this;
1933
+ this.entity = fromRow.entity;
1934
+ this.selected = fromRow.selected;
1935
+ this.orig = fromRow;
1936
+ };
1937
+ var ngRowFactory = function (grid, $scope, domUtilityService, $templateCache, $utils) {
1938
+ var self = this;
1939
+ self.aggCache = {};
1940
+ self.parentCache = [];
1941
+ self.dataChanged = true;
1942
+ self.parsedData = [];
1943
+ self.rowConfig = {};
1944
+ self.selectionProvider = $scope.selectionProvider;
1945
+ self.rowHeight = 30;
1946
+ self.numberOfAggregates = 0;
1947
+ self.groupedData = undefined;
1948
+ self.rowHeight = grid.config.rowHeight;
1949
+ self.rowConfig = {
1950
+ enableRowSelection: grid.config.enableRowSelection,
1951
+ rowClasses: grid.config.rowClasses,
1952
+ selectedItems: $scope.selectedItems,
1953
+ selectWithCheckboxOnly: grid.config.selectWithCheckboxOnly,
1954
+ beforeSelectionChangeCallback: grid.config.beforeSelectionChange,
1955
+ afterSelectionChangeCallback: grid.config.afterSelectionChange,
1956
+ jqueryUITheme: grid.config.jqueryUITheme,
1957
+ enableCellSelection: grid.config.enableCellSelection,
1958
+ rowHeight: grid.config.rowHeight
1959
+ };
1960
+
1961
+ self.renderedRange = new ngRange(0, grid.minRowsToRender() + EXCESS_ROWS);
1962
+ self.buildEntityRow = function(entity, rowIndex) {
1963
+ return new ngRow(entity, self.rowConfig, self.selectionProvider, rowIndex, $utils);
1964
+ };
1965
+
1966
+ self.buildAggregateRow = function(aggEntity, rowIndex) {
1967
+ var agg = self.aggCache[aggEntity.aggIndex];
1968
+ if (!agg) {
1969
+ agg = new ngAggregate(aggEntity, self, self.rowConfig.rowHeight, grid.config.groupsCollapsedByDefault);
1970
+ self.aggCache[aggEntity.aggIndex] = agg;
1971
+ }
1972
+ agg.rowIndex = rowIndex;
1973
+ agg.offsetTop = rowIndex * self.rowConfig.rowHeight;
1974
+ return agg;
1975
+ };
1976
+ self.UpdateViewableRange = function(newRange) {
1977
+ self.renderedRange = newRange;
1978
+ self.renderedChange();
1979
+ };
1980
+ self.filteredRowsChanged = function() {
1981
+ if (grid.lateBoundColumns && grid.filteredRows.length > 0) {
1982
+ grid.config.columnDefs = undefined;
1983
+ grid.buildColumns();
1984
+ grid.lateBoundColumns = false;
1985
+ $scope.$evalAsync(function() {
1986
+ $scope.adjustScrollLeft(0);
1987
+ });
1988
+ }
1989
+ self.dataChanged = true;
1990
+ if (grid.config.groups.length > 0) {
1991
+ self.getGrouping(grid.config.groups);
1992
+ }
1993
+ self.UpdateViewableRange(self.renderedRange);
1994
+ };
1995
+
1996
+ self.renderedChange = function() {
1997
+ if (!self.groupedData || grid.config.groups.length < 1) {
1998
+ self.renderedChangeNoGroups();
1999
+ grid.refreshDomSizes();
2000
+ return;
2001
+ }
2002
+ self.wasGrouped = true;
2003
+ self.parentCache = [];
2004
+ var x = 0;
2005
+ var temp = self.parsedData.filter(function (e) {
2006
+ if (e.isAggRow) {
2007
+ if (e.parent && e.parent.collapsed) {
2008
+ return false;
2009
+ }
2010
+ return true;
2011
+ }
2012
+ if (!e[NG_HIDDEN]) {
2013
+ e.rowIndex = x++;
2014
+ }
2015
+ return !e[NG_HIDDEN];
2016
+ });
2017
+ self.totalRows = temp.length;
2018
+ var rowArr = [];
2019
+ for (var i = self.renderedRange.topRow; i < self.renderedRange.bottomRow; i++) {
2020
+ if (temp[i]) {
2021
+ temp[i].offsetTop = i * grid.config.rowHeight;
2022
+ rowArr.push(temp[i]);
2023
+ }
2024
+ }
2025
+ grid.setRenderedRows(rowArr);
2026
+ };
2027
+
2028
+ self.renderedChangeNoGroups = function () {
2029
+ var rowArr = [];
2030
+ for (var i = self.renderedRange.topRow; i < self.renderedRange.bottomRow; i++) {
2031
+ if (grid.filteredRows[i]) {
2032
+ grid.filteredRows[i].rowIndex = i;
2033
+ grid.filteredRows[i].offsetTop = i * grid.config.rowHeight;
2034
+ rowArr.push(grid.filteredRows[i]);
2035
+ }
2036
+ }
2037
+ grid.setRenderedRows(rowArr);
2038
+ };
2039
+
2040
+ self.fixRowCache = function () {
2041
+ var newLen = grid.data.length;
2042
+ var diff = newLen - grid.rowCache.length;
2043
+ if (diff < 0) {
2044
+ grid.rowCache.length = grid.rowMap.length = newLen;
2045
+ } else {
2046
+ for (var i = grid.rowCache.length; i < newLen; i++) {
2047
+ grid.rowCache[i] = grid.rowFactory.buildEntityRow(grid.data[i], i);
2048
+ }
2049
+ }
2050
+ };
2051
+ self.parseGroupData = function(g) {
2052
+ if (g.values) {
2053
+ for (var x = 0; x < g.values.length; x++){
2054
+ self.parentCache[self.parentCache.length - 1].children.push(g.values[x]);
2055
+ self.parsedData.push(g.values[x]);
2056
+ }
2057
+ } else {
2058
+ for (var prop in g) {
2059
+ if (prop === NG_FIELD || prop === NG_DEPTH || prop === NG_COLUMN) {
2060
+ continue;
2061
+ } else if (g.hasOwnProperty(prop)) {
2062
+ var agg = self.buildAggregateRow({
2063
+ gField: g[NG_FIELD],
2064
+ gLabel: prop,
2065
+ gDepth: g[NG_DEPTH],
2066
+ isAggRow: true,
2067
+ '_ng_hidden_': false,
2068
+ children: [],
2069
+ aggChildren: [],
2070
+ aggIndex: self.numberOfAggregates,
2071
+ aggLabelFilter: g[NG_COLUMN].aggLabelFilter
2072
+ }, 0);
2073
+ self.numberOfAggregates++;
2074
+ agg.parent = self.parentCache[agg.depth - 1];
2075
+ if (agg.parent) {
2076
+ agg.parent.collapsed = false;
2077
+ agg.parent.aggChildren.push(agg);
2078
+ }
2079
+ self.parsedData.push(agg);
2080
+ self.parentCache[agg.depth] = agg;
2081
+ self.parseGroupData(g[prop]);
2082
+ }
2083
+ }
2084
+ }
2085
+ };
2086
+ self.getGrouping = function(groups) {
2087
+ self.aggCache = [];
2088
+ self.numberOfAggregates = 0;
2089
+ self.groupedData = {};
2090
+ var rows = grid.filteredRows,
2091
+ maxDepth = groups.length,
2092
+ cols = $scope.columns;
2093
+
2094
+ function filterCols(cols, group) {
2095
+ return cols.filter(function(c) {
2096
+ return c.field === group;
2097
+ });
2098
+ }
2099
+
2100
+ for (var x = 0; x < rows.length; x++) {
2101
+ var model = rows[x].entity;
2102
+ if (!model) {
2103
+ return;
2104
+ }
2105
+ rows[x][NG_HIDDEN] = grid.config.groupsCollapsedByDefault;
2106
+ var ptr = self.groupedData;
2107
+
2108
+ for (var y = 0; y < groups.length; y++) {
2109
+ var group = groups[y];
2110
+
2111
+ var col = filterCols(cols, group)[0];
2112
+
2113
+ var val = $utils.evalProperty(model, group);
2114
+ val = val ? val.toString() : 'null';
2115
+ if (!ptr[val]) {
2116
+ ptr[val] = {};
2117
+ }
2118
+ if (!ptr[NG_FIELD]) {
2119
+ ptr[NG_FIELD] = group;
2120
+ }
2121
+ if (!ptr[NG_DEPTH]) {
2122
+ ptr[NG_DEPTH] = y;
2123
+ }
2124
+ if (!ptr[NG_COLUMN]) {
2125
+ ptr[NG_COLUMN] = col;
2126
+ }
2127
+ ptr = ptr[val];
2128
+ }
2129
+ if (!ptr.values) {
2130
+ ptr.values = [];
2131
+ }
2132
+ ptr.values.push(rows[x]);
2133
+ }
2134
+ if(cols.length > 0) {
2135
+ for (var z = 0; z < groups.length; z++) {
2136
+ if (!cols[z].isAggCol && z <= maxDepth) {
2137
+ cols.splice(0, 0, new ngColumn({
2138
+ colDef: {
2139
+ field: '',
2140
+ width: 25,
2141
+ sortable: false,
2142
+ resizable: false,
2143
+ headerCellTemplate: '<div class="ngAggHeader"></div>',
2144
+ pinned: grid.config.pinSelectionCheckbox
2145
+ },
2146
+ enablePinning: grid.config.enablePinning,
2147
+ isAggCol: true,
2148
+ headerRowHeight: grid.config.headerRowHeight
2149
+ }, $scope, grid, domUtilityService, $templateCache, $utils));
2150
+ }
2151
+ }
2152
+ }
2153
+
2154
+ grid.fixColumnIndexes();
2155
+ $scope.adjustScrollLeft(0);
2156
+ self.parsedData.length = 0;
2157
+ self.parseGroupData(self.groupedData);
2158
+ self.fixRowCache();
2159
+ };
2160
+
2161
+ if (grid.config.groups.length > 0 && grid.filteredRows.length > 0) {
2162
+ self.getGrouping(grid.config.groups);
2163
+ }
2164
+ };
2165
+ var ngSearchProvider = function ($scope, grid, $filter) {
2166
+ var self = this,
2167
+ searchConditions = [];
2168
+
2169
+ self.extFilter = grid.config.filterOptions.useExternalFilter;
2170
+ $scope.showFilter = grid.config.showFilter;
2171
+ $scope.filterText = '';
2172
+
2173
+ self.fieldMap = {};
2174
+
2175
+ var searchEntireRow = function(condition, item, fieldMap){
2176
+ var result;
2177
+ for (var prop in item) {
2178
+ if (item.hasOwnProperty(prop)) {
2179
+ var c = fieldMap[prop.toLowerCase()];
2180
+ if (!c) {
2181
+ continue;
2182
+ }
2183
+ var pVal = item[prop];
2184
+ if(typeof pVal === 'object'){
2185
+ return searchEntireRow(condition, pVal, c);
2186
+ } else {
2187
+ var f = null,
2188
+ s = null;
2189
+ if (c && c.cellFilter) {
2190
+ s = c.cellFilter.split(':');
2191
+ f = $filter(s[0]);
2192
+ }
2193
+ if (pVal !== null && pVal !== undefined) {
2194
+ if (typeof f === "function") {
2195
+ var filterRes = f(pVal, s[1]).toString();
2196
+ result = condition.regex.test(filterRes);
2197
+ } else {
2198
+ result = condition.regex.test(pVal.toString());
2199
+ }
2200
+ if (result) {
2201
+ return true;
2202
+ }
2203
+ }
2204
+ }
2205
+ }
2206
+ }
2207
+ return false;
2208
+ };
2209
+
2210
+ var searchColumn = function(condition, item){
2211
+ var result;
2212
+ var col = self.fieldMap[condition.columnDisplay];
2213
+ if (!col) {
2214
+ return false;
2215
+ }
2216
+ var sp = col.cellFilter.split(':');
2217
+ var filter = col.cellFilter ? $filter(sp[0]) : null;
2218
+ var value = item[condition.column] || item[col.field.split('.')[0]];
2219
+ if (value === null || value === undefined) {
2220
+ return false;
2221
+ }
2222
+ if (typeof filter === "function") {
2223
+ var filterResults = filter(typeof value === "object" ? evalObject(value, col.field) : value, sp[1]).toString();
2224
+ result = condition.regex.test(filterResults);
2225
+ }
2226
+ else {
2227
+ result = condition.regex.test(typeof value === "object" ? evalObject(value, col.field).toString() : value.toString());
2228
+ }
2229
+ if (result) {
2230
+ return true;
2231
+ }
2232
+ return false;
2233
+ };
2234
+
2235
+ var filterFunc = function(item) {
2236
+ for (var x = 0, len = searchConditions.length; x < len; x++) {
2237
+ var condition = searchConditions[x];
2238
+ var result;
2239
+ if (!condition.column) {
2240
+ result = searchEntireRow(condition, item, self.fieldMap);
2241
+ } else {
2242
+ result = searchColumn(condition, item);
2243
+ }
2244
+ if(!result) {
2245
+ return false;
2246
+ }
2247
+ }
2248
+ return true;
2249
+ };
2250
+
2251
+ self.evalFilter = function () {
2252
+ if (searchConditions.length === 0) {
2253
+ grid.filteredRows = grid.rowCache;
2254
+ } else {
2255
+ grid.filteredRows = grid.rowCache.filter(function(row) {
2256
+ return filterFunc(row.entity);
2257
+ });
2258
+ }
2259
+ for (var i = 0; i < grid.filteredRows.length; i++)
2260
+ {
2261
+ grid.filteredRows[i].rowIndex = i;
2262
+ }
2263
+ grid.rowFactory.filteredRowsChanged();
2264
+ };
2265
+ var evalObject = function (obj, columnName) {
2266
+ if (typeof obj !== "object" || typeof columnName !== "string") {
2267
+ return obj;
2268
+ }
2269
+ var args = columnName.split('.');
2270
+ var cObj = obj;
2271
+ if (args.length > 1) {
2272
+ for (var i = 1, len = args.length; i < len; i++) {
2273
+ cObj = cObj[args[i]];
2274
+ if (!cObj) {
2275
+ return obj;
2276
+ }
2277
+ }
2278
+ return cObj;
2279
+ }
2280
+ return obj;
2281
+ };
2282
+ var getRegExp = function (str, modifiers) {
2283
+ try {
2284
+ return new RegExp(str, modifiers);
2285
+ } catch (err) {
2286
+ return new RegExp(str.replace(/(\^|\$|\(|\)|<|>|\[|\]|\{|\}|\\|\||\.|\*|\+|\?)/g, '\\$1'));
2287
+ }
2288
+ };
2289
+ var buildSearchConditions = function (a) {
2290
+ searchConditions = [];
2291
+ var qStr;
2292
+ if (!(qStr = $.trim(a))) {
2293
+ return;
2294
+ }
2295
+ var columnFilters = qStr.split(";");
2296
+ for (var i = 0; i < columnFilters.length; i++) {
2297
+ var args = columnFilters[i].split(':');
2298
+ if (args.length > 1) {
2299
+ var columnName = $.trim(args[0]);
2300
+ var columnValue = $.trim(args[1]);
2301
+ if (columnName && columnValue) {
2302
+ searchConditions.push({
2303
+ column: columnName,
2304
+ columnDisplay: columnName.replace(/\s+/g, '').toLowerCase(),
2305
+ regex: getRegExp(columnValue, 'i')
2306
+ });
2307
+ }
2308
+ } else {
2309
+ var val = $.trim(args[0]);
2310
+ if (val) {
2311
+ searchConditions.push({
2312
+ column: '',
2313
+ regex: getRegExp(val, 'i')
2314
+ });
2315
+ }
2316
+ }
2317
+ }
2318
+ };
2319
+
2320
+ if (!self.extFilter) {
2321
+ $scope.$watch('columns', function (cs) {
2322
+ for (var i = 0; i < cs.length; i++) {
2323
+ var col = cs[i];
2324
+ if (col.field) {
2325
+ if(col.field.match(/\./g)){
2326
+ var properties = col.field.split('.');
2327
+ var currentProperty = self.fieldMap;
2328
+ for(var j = 0; j < properties.length - 1; j++) {
2329
+ currentProperty[ properties[j] ] = currentProperty[ properties[j] ] || {};
2330
+ currentProperty = currentProperty[properties[j]];
2331
+ }
2332
+ currentProperty[ properties[properties.length - 1] ] = col;
2333
+ } else {
2334
+ self.fieldMap[col.field.toLowerCase()] = col;
2335
+ }
2336
+ }
2337
+ if (col.displayName) {
2338
+ self.fieldMap[col.displayName.toLowerCase().replace(/\s+/g, '')] = col;
2339
+ }
2340
+ }
2341
+ });
2342
+ }
2343
+
2344
+ $scope.$watch(
2345
+ function () {
2346
+ return grid.config.filterOptions.filterText;
2347
+ },
2348
+ function (a) {
2349
+ $scope.filterText = a;
2350
+ }
2351
+ );
2352
+
2353
+ $scope.$watch('filterText', function(a){
2354
+ if (!self.extFilter) {
2355
+ $scope.$emit('ngGridEventFilter', a);
2356
+ buildSearchConditions(a);
2357
+ self.evalFilter();
2358
+ }
2359
+ });
2360
+ };
2361
+ var ngSelectionProvider = function (grid, $scope, $parse) {
2362
+ var self = this;
2363
+ self.multi = grid.config.multiSelect;
2364
+ self.selectedItems = grid.config.selectedItems;
2365
+ self.selectedIndex = grid.config.selectedIndex;
2366
+ self.lastClickedRow = undefined;
2367
+ self.ignoreSelectedItemChanges = false;
2368
+ self.pKeyParser = $parse(grid.config.primaryKey);
2369
+ self.ChangeSelection = function (rowItem, evt) {
2370
+ var charCode = evt.which || evt.keyCode;
2371
+ var isUpDownKeyPress = (charCode === 40 || charCode === 38);
2372
+
2373
+ if (evt && evt.shiftKey && !evt.keyCode && self.multi && grid.config.enableRowSelection) {
2374
+ if (self.lastClickedRow) {
2375
+ var rowsArr;
2376
+ if ($scope.configGroups.length > 0) {
2377
+ rowsArr = grid.rowFactory.parsedData.filter(function(row) {
2378
+ return !row.isAggRow;
2379
+ });
2380
+ }
2381
+ else {
2382
+ rowsArr = grid.filteredRows;
2383
+ }
2384
+
2385
+ var thisIndx = rowItem.rowIndex;
2386
+ var prevIndx = self.lastClickedRowIndex;
2387
+ if (thisIndx === prevIndx) {
2388
+ return false;
2389
+ }
2390
+
2391
+ if (thisIndx < prevIndx) {
2392
+ thisIndx = thisIndx ^ prevIndx;
2393
+ prevIndx = thisIndx ^ prevIndx;
2394
+ thisIndx = thisIndx ^ prevIndx;
2395
+ thisIndx--;
2396
+ }
2397
+ else {
2398
+ prevIndx++;
2399
+ }
2400
+
2401
+ var rows = [];
2402
+ for (; prevIndx <= thisIndx; prevIndx++) {
2403
+ rows.push(rowsArr[prevIndx]);
2404
+ }
2405
+
2406
+ if (rows[rows.length - 1].beforeSelectionChange(rows, evt)) {
2407
+ for (var i = 0; i < rows.length; i++) {
2408
+ var ri = rows[i];
2409
+ var selectionState = ri.selected;
2410
+ ri.selected = !selectionState;
2411
+ if (ri.clone) {
2412
+ ri.clone.selected = ri.selected;
2413
+ }
2414
+ var index = self.selectedItems.indexOf(ri.entity);
2415
+ if (index === -1) {
2416
+ self.selectedItems.push(ri.entity);
2417
+ }
2418
+ else {
2419
+ self.selectedItems.splice(index, 1);
2420
+ }
2421
+ }
2422
+ rows[rows.length - 1].afterSelectionChange(rows, evt);
2423
+ }
2424
+ self.lastClickedRow = rowItem;
2425
+ self.lastClickedRowIndex = rowItem.rowIndex;
2426
+
2427
+ return true;
2428
+ }
2429
+ }
2430
+ else if (!self.multi) {
2431
+ if (self.lastClickedRow === rowItem) {
2432
+ self.setSelection(self.lastClickedRow, grid.config.keepLastSelected ? true : !rowItem.selected);
2433
+ } else {
2434
+ if (self.lastClickedRow) {
2435
+ self.setSelection(self.lastClickedRow, false);
2436
+ }
2437
+ self.setSelection(rowItem, !rowItem.selected);
2438
+ }
2439
+ }
2440
+ else if (!evt.keyCode || isUpDownKeyPress && !grid.config.selectWithCheckboxOnly) {
2441
+ self.setSelection(rowItem, !rowItem.selected);
2442
+ }
2443
+ self.lastClickedRow = rowItem;
2444
+ self.lastClickedRowIndex = rowItem.rowIndex;
2445
+ return true;
2446
+ };
2447
+
2448
+ self.getSelection = function (entity) {
2449
+ var isSelected = false;
2450
+ if (grid.config.primaryKey) {
2451
+ var val = self.pKeyParser(entity);
2452
+ angular.forEach(self.selectedItems, function (c) {
2453
+ if (val === self.pKeyParser(c)) {
2454
+ isSelected = true;
2455
+ }
2456
+ });
2457
+ }
2458
+ else {
2459
+ isSelected = self.selectedItems.indexOf(entity) !== -1;
2460
+ }
2461
+ return isSelected;
2462
+ };
2463
+ self.setSelection = function (rowItem, isSelected) {
2464
+ if(grid.config.enableRowSelection){
2465
+ if (!isSelected) {
2466
+ var indx = self.selectedItems.indexOf(rowItem.entity);
2467
+ if (indx !== -1) {
2468
+ self.selectedItems.splice(indx, 1);
2469
+ }
2470
+ }
2471
+ else {
2472
+ if (self.selectedItems.indexOf(rowItem.entity) === -1) {
2473
+ if (!self.multi && self.selectedItems.length > 0) {
2474
+ self.toggleSelectAll(false, true);
2475
+ }
2476
+ self.selectedItems.push(rowItem.entity);
2477
+ }
2478
+ }
2479
+ rowItem.selected = isSelected;
2480
+ if (rowItem.orig) {
2481
+ rowItem.orig.selected = isSelected;
2482
+ }
2483
+ if (rowItem.clone) {
2484
+ rowItem.clone.selected = isSelected;
2485
+ }
2486
+ rowItem.afterSelectionChange(rowItem);
2487
+ }
2488
+ };
2489
+ self.toggleSelectAll = function (checkAll, bypass, selectFiltered) {
2490
+ var rows = selectFiltered ? grid.filteredRows : grid.rowCache;
2491
+ if (bypass || grid.config.beforeSelectionChange(rows, checkAll)) {
2492
+ var selectedlength = self.selectedItems.length;
2493
+ if (selectedlength > 0) {
2494
+ self.selectedItems.length = 0;
2495
+ }
2496
+ for (var i = 0; i < rows.length; i++) {
2497
+ rows[i].selected = checkAll;
2498
+ if (rows[i].clone) {
2499
+ rows[i].clone.selected = checkAll;
2500
+ }
2501
+ if (checkAll) {
2502
+ self.selectedItems.push(rows[i].entity);
2503
+ }
2504
+ }
2505
+ if (!bypass) {
2506
+ grid.config.afterSelectionChange(rows, checkAll);
2507
+ }
2508
+ }
2509
+ };
2510
+ };
2511
+ var ngStyleProvider = function($scope, grid) {
2512
+ $scope.headerCellStyle = function(col) {
2513
+ return { "height": col.headerRowHeight + "px" };
2514
+ };
2515
+ $scope.rowStyle = function (row) {
2516
+ var ret = { "top": row.offsetTop + "px", "height": $scope.rowHeight + "px" };
2517
+ if (row.isAggRow) {
2518
+ ret.left = row.offsetLeft;
2519
+ }
2520
+ return ret;
2521
+ };
2522
+ $scope.canvasStyle = function() {
2523
+ return { "height": grid.maxCanvasHt + "px" };
2524
+ };
2525
+ $scope.headerScrollerStyle = function() {
2526
+ return { "height": grid.config.headerRowHeight + "px" };
2527
+ };
2528
+ $scope.topPanelStyle = function() {
2529
+ return { "width": grid.rootDim.outerWidth + "px", "height": $scope.topPanelHeight() + "px" };
2530
+ };
2531
+ $scope.headerStyle = function() {
2532
+ return { "width": grid.rootDim.outerWidth + "px", "height": grid.config.headerRowHeight + "px" };
2533
+ };
2534
+ $scope.groupPanelStyle = function () {
2535
+ return { "width": grid.rootDim.outerWidth + "px", "height": "32px" };
2536
+ };
2537
+ $scope.viewportStyle = function() {
2538
+ return { "width": grid.rootDim.outerWidth + "px", "height": $scope.viewportDimHeight() + "px" };
2539
+ };
2540
+ $scope.footerStyle = function() {
2541
+ return { "width": grid.rootDim.outerWidth + "px", "height": $scope.footerRowHeight + "px" };
2542
+ };
2543
+ };
2544
+ ngGridDirectives.directive('ngCellHasFocus', ['$domUtilityService',
2545
+ function (domUtilityService) {
2546
+ var focusOnInputElement = function($scope, elm) {
2547
+ $scope.isFocused = true;
2548
+ domUtilityService.digest($scope);
2549
+
2550
+ $scope.$broadcast('ngGridEventStartCellEdit');
2551
+
2552
+ $scope.$on('ngGridEventEndCellEdit', function() {
2553
+ $scope.isFocused = false;
2554
+ domUtilityService.digest($scope);
2555
+ });
2556
+ };
2557
+
2558
+ return function($scope, elm) {
2559
+ var isFocused = false;
2560
+ var isCellEditableOnMouseDown = false;
2561
+
2562
+ $scope.editCell = function() {
2563
+ if(!$scope.enableCellEditOnFocus) {
2564
+ setTimeout(function() {
2565
+ focusOnInputElement($scope,elm);
2566
+ }, 0);
2567
+ }
2568
+ };
2569
+ elm.bind('mousedown', function(evt) {
2570
+ if($scope.enableCellEditOnFocus) {
2571
+ isCellEditableOnMouseDown = true;
2572
+ } else {
2573
+ elm.focus();
2574
+ }
2575
+ return true;
2576
+ });
2577
+ elm.bind('click', function(evt) {
2578
+ if($scope.enableCellEditOnFocus) {
2579
+ evt.preventDefault();
2580
+ isCellEditableOnMouseDown = false;
2581
+ focusOnInputElement($scope,elm);
2582
+ }
2583
+ });
2584
+ elm.bind('focus', function(evt) {
2585
+ isFocused = true;
2586
+ if($scope.enableCellEditOnFocus && !isCellEditableOnMouseDown) {
2587
+ focusOnInputElement($scope,elm);
2588
+ }
2589
+ return true;
2590
+ });
2591
+ elm.bind('blur', function() {
2592
+ isFocused = false;
2593
+ return true;
2594
+ });
2595
+ elm.bind('keydown', function(evt) {
2596
+ if(!$scope.enableCellEditOnFocus) {
2597
+ if (isFocused && evt.keyCode !== 37 && evt.keyCode !== 38 && evt.keyCode !== 39 && evt.keyCode !== 40 && evt.keyCode !== 9 && !evt.shiftKey && evt.keyCode !== 13) {
2598
+ focusOnInputElement($scope,elm);
2599
+ }
2600
+ if (isFocused && evt.shiftKey && (evt.keyCode >= 65 && evt.keyCode <= 90)) {
2601
+ focusOnInputElement($scope, elm);
2602
+ }
2603
+ if (evt.keyCode === 27) {
2604
+ elm.focus();
2605
+ }
2606
+ }
2607
+ return true;
2608
+ });
2609
+ };
2610
+ }]);
2611
+ ngGridDirectives.directive('ngCellText',
2612
+ function () {
2613
+ return function(scope, elm) {
2614
+ elm.bind('mouseover', function(evt) {
2615
+ evt.preventDefault();
2616
+ elm.css({
2617
+ 'cursor': 'text'
2618
+ });
2619
+ });
2620
+ elm.bind('mouseleave', function(evt) {
2621
+ evt.preventDefault();
2622
+ elm.css({
2623
+ 'cursor': 'default'
2624
+ });
2625
+ });
2626
+ };
2627
+ });
2628
+ ngGridDirectives.directive('ngCell', ['$compile', '$domUtilityService', function ($compile, domUtilityService) {
2629
+ var ngCell = {
2630
+ scope: false,
2631
+ compile: function() {
2632
+ return {
2633
+ pre: function($scope, iElement) {
2634
+ var html;
2635
+ var cellTemplate = $scope.col.cellTemplate.replace(COL_FIELD, 'row.entity.' + $scope.col.field);
2636
+
2637
+ if ($scope.col.enableCellEdit) {
2638
+ html = $scope.col.cellEditTemplate;
2639
+ html = html.replace(DISPLAY_CELL_TEMPLATE, cellTemplate);
2640
+ html = html.replace(EDITABLE_CELL_TEMPLATE, $scope.col.editableCellTemplate.replace(COL_FIELD, 'row.entity.' + $scope.col.field));
2641
+ } else {
2642
+ html = cellTemplate;
2643
+ }
2644
+
2645
+ var cellElement = $compile(html)($scope);
2646
+
2647
+ if ($scope.enableCellSelection && cellElement[0].className.indexOf('ngSelectionCell') === -1) {
2648
+ cellElement[0].setAttribute('tabindex', 0);
2649
+ cellElement.addClass('ngCellElement');
2650
+ }
2651
+
2652
+ iElement.append(cellElement);
2653
+ },
2654
+ post: function($scope, iElement) {
2655
+ if ($scope.enableCellSelection) {
2656
+ $scope.domAccessProvider.selectionHandlers($scope, iElement);
2657
+ }
2658
+ $scope.$on('ngGridEventDigestCell', function() {
2659
+ domUtilityService.digest($scope);
2660
+ });
2661
+ }
2662
+ };
2663
+ }
2664
+ };
2665
+ return ngCell;
2666
+ }]);
2667
+
2668
+ ngGridDirectives.directive('ngEditCellIf', [function () {
2669
+ return {
2670
+ transclude: 'element',
2671
+ priority: 1000,
2672
+ terminal: true,
2673
+ restrict: 'A',
2674
+ compile: function (e, a, transclude) {
2675
+ return function (scope, element, attr) {
2676
+
2677
+ var childElement;
2678
+ var childScope;
2679
+ scope.$watch(attr['ngEditCellIf'], function (newValue) {
2680
+ if (childElement) {
2681
+ childElement.remove();
2682
+ childElement = undefined;
2683
+ }
2684
+ if (childScope) {
2685
+ childScope.$destroy();
2686
+ childScope = undefined;
2687
+ }
2688
+
2689
+ if (newValue) {
2690
+ childScope = scope.$new();
2691
+ transclude(childScope, function (clone) {
2692
+ childElement = clone;
2693
+ element.after(clone);
2694
+ });
2695
+ }
2696
+ });
2697
+ };
2698
+ }
2699
+ };
2700
+ }]);
2701
+ ngGridDirectives.directive('ngGridFooter', ['$compile', '$templateCache', function ($compile, $templateCache) {
2702
+ var ngGridFooter = {
2703
+ scope: false,
2704
+ compile: function () {
2705
+ return {
2706
+ pre: function ($scope, iElement) {
2707
+ if (iElement.children().length === 0) {
2708
+ iElement.append($compile($templateCache.get($scope.gridId + 'footerTemplate.html'))($scope));
2709
+ }
2710
+ }
2711
+ };
2712
+ }
2713
+ };
2714
+ return ngGridFooter;
2715
+ }]);
2716
+ ngGridDirectives.directive('ngGridMenu', ['$compile', '$templateCache', function ($compile, $templateCache) {
2717
+ var ngGridMenu = {
2718
+ scope: false,
2719
+ compile: function () {
2720
+ return {
2721
+ pre: function ($scope, iElement) {
2722
+ if (iElement.children().length === 0) {
2723
+ iElement.append($compile($templateCache.get($scope.gridId + 'menuTemplate.html'))($scope));
2724
+ }
2725
+ }
2726
+ };
2727
+ }
2728
+ };
2729
+ return ngGridMenu;
2730
+ }]);
2731
+ ngGridDirectives.directive('ngGrid', ['$compile', '$filter', '$templateCache', '$sortService', '$domUtilityService', '$utilityService', '$timeout', '$parse', '$http', '$q', function ($compile, $filter, $templateCache, sortService, domUtilityService, $utils, $timeout, $parse, $http, $q) {
2732
+ var ngGridDirective = {
2733
+ scope: true,
2734
+ compile: function() {
2735
+ return {
2736
+ pre: function($scope, iElement, iAttrs) {
2737
+ var $element = $(iElement);
2738
+ var options = $scope.$eval(iAttrs.ngGrid);
2739
+
2740
+ options.gridDim = new ngDimension({ outerHeight: $($element).height(), outerWidth: $($element).width() });
2741
+
2742
+ var grid = new ngGrid($scope, options, sortService, domUtilityService, $filter, $templateCache, $utils, $timeout, $parse, $http, $q);
2743
+ return grid.init().then(function() {
2744
+ if (typeof options.columnDefs === "string") {
2745
+ $scope.$parent.$watch(options.columnDefs, function (a) {
2746
+ if (!a) {
2747
+ grid.refreshDomSizes();
2748
+ grid.buildColumns();
2749
+ return;
2750
+ }
2751
+ grid.lateBoundColumns = false;
2752
+ $scope.columns = [];
2753
+ grid.config.columnDefs = a;
2754
+ grid.buildColumns();
2755
+ grid.eventProvider.assignEvents();
2756
+ domUtilityService.RebuildGrid($scope, grid);
2757
+ }, true);
2758
+ }
2759
+ else {
2760
+ grid.buildColumns();
2761
+ }
2762
+ if (typeof options.totalServerItems === "string") {
2763
+ $scope.$parent.$watch(options.totalServerItems, function (newTotal, oldTotal) {
2764
+ if (!angular.isDefined(newTotal)) {
2765
+ $scope.totalServerItems = 0;
2766
+ }
2767
+ else {
2768
+ $scope.totalServerItems = newTotal;
2769
+ }
2770
+ });
2771
+ }
2772
+ else {
2773
+ $scope.totalServerItems = 0;
2774
+ }
2775
+ if (typeof options.data === "string") {
2776
+ var dataWatcher = function (a) {
2777
+ grid.data = $.extend([], a);
2778
+ grid.rowFactory.fixRowCache();
2779
+ angular.forEach(grid.data, function (item, j) {
2780
+ var indx = grid.rowMap[j] || j;
2781
+ if (grid.rowCache[indx]) {
2782
+ grid.rowCache[indx].ensureEntity(item);
2783
+ }
2784
+ grid.rowMap[indx] = j;
2785
+ });
2786
+ grid.searchProvider.evalFilter();
2787
+ grid.configureColumnWidths();
2788
+ grid.refreshDomSizes();
2789
+ if (grid.config.sortInfo.fields.length > 0) {
2790
+ grid.sortColumnsInit();
2791
+ $scope.$emit('ngGridEventSorted', grid.config.sortInfo);
2792
+ }
2793
+ $scope.$emit("ngGridEventData", grid.gridId);
2794
+ };
2795
+ $scope.$parent.$watch(options.data, dataWatcher);
2796
+ $scope.$parent.$watch(options.data + '.length', function() {
2797
+ dataWatcher($scope.$eval(options.data));
2798
+ });
2799
+ }
2800
+ grid.footerController = new ngFooter($scope, grid);
2801
+ iElement.addClass("ngGrid").addClass(grid.gridId.toString());
2802
+ if (!options.enableHighlighting) {
2803
+ iElement.addClass("unselectable");
2804
+ }
2805
+ if (options.jqueryUITheme) {
2806
+ iElement.addClass('ui-widget');
2807
+ }
2808
+ iElement.append($compile($templateCache.get('gridTemplate.html'))($scope));
2809
+ domUtilityService.AssignGridContainers($scope, iElement, grid);
2810
+ grid.eventProvider = new ngEventProvider(grid, $scope, domUtilityService, $timeout);
2811
+ options.selectRow = function (rowIndex, state) {
2812
+ if (grid.rowCache[rowIndex]) {
2813
+ if (grid.rowCache[rowIndex].clone) {
2814
+ grid.rowCache[rowIndex].clone.setSelection(state ? true : false);
2815
+ }
2816
+ grid.rowCache[rowIndex].setSelection(state ? true : false);
2817
+ }
2818
+ };
2819
+ options.selectItem = function (itemIndex, state) {
2820
+ options.selectRow(grid.rowMap[itemIndex], state);
2821
+ };
2822
+ options.selectAll = function (state) {
2823
+ $scope.toggleSelectAll(state);
2824
+ };
2825
+ options.selectVisible = function (state) {
2826
+ $scope.toggleSelectAll(state, true);
2827
+ };
2828
+ options.groupBy = function (field) {
2829
+ if (field) {
2830
+ $scope.groupBy($scope.columns.filter(function(c) {
2831
+ return c.field === field;
2832
+ })[0]);
2833
+ } else {
2834
+ var arr = $.extend(true, [], $scope.configGroups);
2835
+ angular.forEach(arr, $scope.groupBy);
2836
+ }
2837
+ };
2838
+ options.sortBy = function (field) {
2839
+ var col = $scope.columns.filter(function (c) {
2840
+ return c.field === field;
2841
+ })[0];
2842
+ if (col) {
2843
+ col.sort();
2844
+ }
2845
+ };
2846
+ options.gridId = grid.gridId;
2847
+ options.ngGrid = grid;
2848
+ options.$gridScope = $scope;
2849
+ options.$gridServices = { SortService: sortService, DomUtilityService: domUtilityService, UtilityService: $utils };
2850
+ $scope.$on('ngGridEventDigestGrid', function(){
2851
+ domUtilityService.digest($scope.$parent);
2852
+ });
2853
+ $scope.$on('ngGridEventDigestGridParent', function(){
2854
+ domUtilityService.digest($scope.$parent);
2855
+ });
2856
+ $scope.$evalAsync(function() {
2857
+ $scope.adjustScrollLeft(0);
2858
+ });
2859
+ angular.forEach(options.plugins, function (p) {
2860
+ if (typeof p === "function") {
2861
+ p = new p();
2862
+ }
2863
+ p.init($scope.$new(), grid, options.$gridServices);
2864
+ options.plugins[$utils.getInstanceType(p)] = p;
2865
+ });
2866
+ if (typeof options.init === "function") {
2867
+ options.init(grid, $scope);
2868
+ }
2869
+ return null;
2870
+ });
2871
+ }
2872
+ };
2873
+ }
2874
+ };
2875
+ return ngGridDirective;
2876
+ }]);
2877
+
2878
+ ngGridDirectives.directive('ngHeaderCell', ['$compile', function($compile) {
2879
+ var ngHeaderCell = {
2880
+ scope: false,
2881
+ compile: function() {
2882
+ return {
2883
+ pre: function($scope, iElement) {
2884
+ iElement.append($compile($scope.col.headerCellTemplate)($scope));
2885
+ }
2886
+ };
2887
+ }
2888
+ };
2889
+ return ngHeaderCell;
2890
+ }]);
2891
+ ngGridDirectives.directive('ngInput', [function() {
2892
+ return {
2893
+ require: 'ngModel',
2894
+ link: function (scope, elm, attrs, ngModel) {
2895
+ var oldCellValue;
2896
+ var dereg = scope.$watch('ngModel', function() {
2897
+ oldCellValue = ngModel.$modelValue;
2898
+ dereg();
2899
+ });
2900
+ elm.bind('keydown', function(evt) {
2901
+ switch (evt.keyCode) {
2902
+ case 37:
2903
+ case 38:
2904
+ case 39:
2905
+ case 40:
2906
+ evt.stopPropagation();
2907
+ break;
2908
+ case 27:
2909
+ if (!scope.$$phase) {
2910
+ scope.$apply(function() {
2911
+ ngModel.$setViewValue(oldCellValue);
2912
+ elm.blur();
2913
+ });
2914
+ }
2915
+ break;
2916
+ case 13:
2917
+ if(scope.enableCellEditOnFocus && scope.totalFilteredItemsLength() - 1 > scope.row.rowIndex && scope.row.rowIndex > 0 || scope.enableCellEdit) {
2918
+ elm.blur();
2919
+ }
2920
+ break;
2921
+ }
2922
+
2923
+ return true;
2924
+ });
2925
+
2926
+ elm.bind('click', function(evt) {
2927
+ evt.stopPropagation();
2928
+ });
2929
+ elm.bind('mousedown', function(evt) {
2930
+ evt.stopPropagation();
2931
+ });
2932
+ scope.$on('ngGridEventStartCellEdit', function () {
2933
+ elm.focus();
2934
+ elm.select();
2935
+ });
2936
+
2937
+ angular.element(elm).bind('blur', function () {
2938
+ scope.$emit('ngGridEventEndCellEdit');
2939
+ });
2940
+ }
2941
+ };
2942
+ }]);
2943
+ ngGridDirectives.directive('ngRow', ['$compile', '$domUtilityService', '$templateCache', function ($compile, domUtilityService, $templateCache) {
2944
+ var ngRow = {
2945
+ scope: false,
2946
+ compile: function() {
2947
+ return {
2948
+ pre: function($scope, iElement) {
2949
+ $scope.row.elm = iElement;
2950
+ if ($scope.row.clone) {
2951
+ $scope.row.clone.elm = iElement;
2952
+ }
2953
+ if ($scope.row.isAggRow) {
2954
+ var html = $templateCache.get($scope.gridId + 'aggregateTemplate.html');
2955
+ if ($scope.row.aggLabelFilter) {
2956
+ html = html.replace(CUSTOM_FILTERS, '| ' + $scope.row.aggLabelFilter);
2957
+ } else {
2958
+ html = html.replace(CUSTOM_FILTERS, "");
2959
+ }
2960
+ iElement.append($compile(html)($scope));
2961
+ } else {
2962
+ iElement.append($compile($templateCache.get($scope.gridId + 'rowTemplate.html'))($scope));
2963
+ }
2964
+ $scope.$on('ngGridEventDigestRow', function(){
2965
+ domUtilityService.digest($scope);
2966
+ });
2967
+ }
2968
+ };
2969
+ }
2970
+ };
2971
+ return ngRow;
2972
+ }]);
2973
+ ngGridDirectives.directive('ngViewport', [function() {
2974
+ return function($scope, elm) {
2975
+ var isMouseWheelActive;
2976
+ var prevScollLeft;
2977
+ var prevScollTop = 0;
2978
+ elm.bind('scroll', function(evt) {
2979
+ var scrollLeft = evt.target.scrollLeft,
2980
+ scrollTop = evt.target.scrollTop;
2981
+ if ($scope.$headerContainer) {
2982
+ $scope.$headerContainer.scrollLeft(scrollLeft);
2983
+ }
2984
+ $scope.adjustScrollLeft(scrollLeft);
2985
+ $scope.adjustScrollTop(scrollTop);
2986
+ if (!$scope.$root.$$phase) {
2987
+ $scope.$digest();
2988
+ }
2989
+ prevScollLeft = scrollLeft;
2990
+ prevScollTop = scrollTop;
2991
+ isMouseWheelActive = false;
2992
+ return true;
2993
+ });
2994
+ elm.bind("mousewheel DOMMouseScroll", function() {
2995
+ isMouseWheelActive = true;
2996
+ if (elm.focus) { elm.focus(); }
2997
+ return true;
2998
+ });
2999
+ if (!$scope.enableCellSelection) {
3000
+ $scope.domAccessProvider.selectionHandlers($scope, elm);
3001
+ }
3002
+ };
3003
+ }]);
3004
+ window.ngGrid.i18n['da'] = {
3005
+ ngAggregateLabel: 'artikler',
3006
+ ngGroupPanelDescription: 'Grupér rækker udfra en kolonne ved at trække dens overskift hertil.',
3007
+ ngSearchPlaceHolder: 'Søg...',
3008
+ ngMenuText: 'Vælg kolonner:',
3009
+ ngShowingItemsLabel: 'Viste rækker:',
3010
+ ngTotalItemsLabel: 'Rækker totalt:',
3011
+ ngSelectedItemsLabel: 'Valgte rækker:',
3012
+ ngPageSizeLabel: 'Side størrelse:',
3013
+ ngPagerFirstTitle: 'Første side',
3014
+ ngPagerNextTitle: 'Næste side',
3015
+ ngPagerPrevTitle: 'Forrige side',
3016
+ ngPagerLastTitle: 'Sidste side'
3017
+ };
3018
+ window.ngGrid.i18n['de'] = {
3019
+ ngAggregateLabel: 'artikel',
3020
+ ngGroupPanelDescription: 'Ziehen Sie eine Spaltenüberschrift hier und legen Sie es der Gruppe nach dieser Spalte.',
3021
+ ngSearchPlaceHolder: 'Suche...',
3022
+ ngMenuText: 'Spalten auswählen:',
3023
+ ngShowingItemsLabel: 'Zeige Artikel:',
3024
+ ngTotalItemsLabel: 'Meiste Artikel:',
3025
+ ngSelectedItemsLabel: 'Ausgewählte Artikel:',
3026
+ ngPageSizeLabel: 'Größe Seite:',
3027
+ ngPagerFirstTitle: 'Erste Page',
3028
+ ngPagerNextTitle: 'Nächste Page',
3029
+ ngPagerPrevTitle: 'Vorherige Page',
3030
+ ngPagerLastTitle: 'Letzte Page'
3031
+ };
3032
+ window.ngGrid.i18n['en'] = {
3033
+ ngAggregateLabel: 'items',
3034
+ ngGroupPanelDescription: 'Drag a column header here and drop it to group by that column.',
3035
+ ngSearchPlaceHolder: 'Search...',
3036
+ ngMenuText: 'Choose Columns:',
3037
+ ngShowingItemsLabel: 'Showing Items:',
3038
+ ngTotalItemsLabel: 'Total Items:',
3039
+ ngSelectedItemsLabel: 'Selected Items:',
3040
+ ngPageSizeLabel: 'Page Size:',
3041
+ ngPagerFirstTitle: 'First Page',
3042
+ ngPagerNextTitle: 'Next Page',
3043
+ ngPagerPrevTitle: 'Previous Page',
3044
+ ngPagerLastTitle: 'Last Page'
3045
+ };
3046
+ window.ngGrid.i18n['es'] = {
3047
+ ngAggregateLabel: 'Artículos',
3048
+ ngGroupPanelDescription: 'Arrastre un encabezado de columna aquí y soltarlo para agrupar por esa columna.',
3049
+ ngSearchPlaceHolder: 'Buscar...',
3050
+ ngMenuText: 'Elegir columnas:',
3051
+ ngShowingItemsLabel: 'Artículos Mostrando:',
3052
+ ngTotalItemsLabel: 'Artículos Totales:',
3053
+ ngSelectedItemsLabel: 'Artículos Seleccionados:',
3054
+ ngPageSizeLabel: 'Tamaño de Página:',
3055
+ ngPagerFirstTitle: 'Primera Página',
3056
+ ngPagerNextTitle: 'Página Siguiente',
3057
+ ngPagerPrevTitle: 'Página Anterior',
3058
+ ngPagerLastTitle: 'Última Página'
3059
+ };
3060
+ window.ngGrid.i18n['fr'] = {
3061
+ ngAggregateLabel: 'articles',
3062
+ ngGroupPanelDescription: 'Faites glisser un en-tête de colonne ici et déposez-le vers un groupe par cette colonne.',
3063
+ ngSearchPlaceHolder: 'Recherche...',
3064
+ ngMenuText: 'Choisir des colonnes:',
3065
+ ngShowingItemsLabel: 'Articles Affichage des:',
3066
+ ngTotalItemsLabel: 'Nombre total d\'articles:',
3067
+ ngSelectedItemsLabel: 'Éléments Articles:',
3068
+ ngPageSizeLabel: 'Taille de page:',
3069
+ ngPagerFirstTitle: 'Première page',
3070
+ ngPagerNextTitle: 'Page Suivante',
3071
+ ngPagerPrevTitle: 'Page précédente',
3072
+ ngPagerLastTitle: 'Dernière page'
3073
+ };
3074
+ window.ngGrid.i18n['pt-br'] = {
3075
+ ngAggregateLabel: 'items',
3076
+ ngGroupPanelDescription: 'Arraste e solte uma coluna aqui para agrupar por essa coluna',
3077
+ ngSearchPlaceHolder: 'Procurar...',
3078
+ ngMenuText: 'Selecione as colunas:',
3079
+ ngShowingItemsLabel: 'Mostrando os Items:',
3080
+ ngTotalItemsLabel: 'Total de Items:',
3081
+ ngSelectedItemsLabel: 'Items Selecionados:',
3082
+ ngPageSizeLabel: 'Tamanho da Página:',
3083
+ ngPagerFirstTitle: 'Primeira Página',
3084
+ ngPagerNextTitle: 'Próxima Página',
3085
+ ngPagerPrevTitle: 'Página Anterior',
3086
+ ngPagerLastTitle: 'Última Página'
3087
+ };
3088
+ window.ngGrid.i18n['zh-cn'] = {
3089
+ ngAggregateLabel: '条目',
3090
+ ngGroupPanelDescription: '拖曳表头到此处以进行分组',
3091
+ ngSearchPlaceHolder: '搜索...',
3092
+ ngMenuText: '数据分组与选择列:',
3093
+ ngShowingItemsLabel: '当前显示条目:',
3094
+ ngTotalItemsLabel: '条目总数:',
3095
+ ngSelectedItemsLabel: '选中条目:',
3096
+ ngPageSizeLabel: '每页显示数:',
3097
+ ngPagerFirstTitle: '回到首页',
3098
+ ngPagerNextTitle: '下一页',
3099
+ ngPagerPrevTitle: '上一页',
3100
+ ngPagerLastTitle: '前往尾页'
3101
+ };
3102
+
3103
+ window.ngGrid.i18n['zh-tw'] = {
3104
+ ngAggregateLabel: '筆',
3105
+ ngGroupPanelDescription: '拖拉表頭到此處以進行分組',
3106
+ ngSearchPlaceHolder: '搜尋...',
3107
+ ngMenuText: '選擇欄位:',
3108
+ ngShowingItemsLabel: '目前顯示筆數:',
3109
+ ngTotalItemsLabel: '總筆數:',
3110
+ ngSelectedItemsLabel: '選取筆數:',
3111
+ ngPageSizeLabel: '每頁顯示:',
3112
+ ngPagerFirstTitle: '第一頁',
3113
+ ngPagerNextTitle: '下一頁',
3114
+ ngPagerPrevTitle: '上一頁',
3115
+ ngPagerLastTitle: '最後頁'
3116
+ };
3117
+
3118
+ angular.module("ngGrid").run(["$templateCache", function($templateCache) {
3119
+
3120
+ $templateCache.put("aggregateTemplate.html",
3121
+ "<div ng-click=\"row.toggleExpand()\" ng-style=\"rowStyle(row)\" class=\"ngAggregate\">" +
3122
+ " <span class=\"ngAggregateText\">{{row.label CUSTOM_FILTERS}} ({{row.totalChildren()}} {{AggItemsLabel}})</span>" +
3123
+ " <div class=\"{{row.aggClass()}}\"></div>" +
3124
+ "</div>" +
3125
+ ""
3126
+ );
3127
+
3128
+ $templateCache.put("cellEditTemplate.html",
3129
+ "<div ng-cell-has-focus ng-dblclick=\"editCell()\">" +
3130
+ " <div ng-edit-cell-if=\"!isFocused\"> " +
3131
+ " DISPLAY_CELL_TEMPLATE" +
3132
+ " </div>" +
3133
+ " <div ng-edit-cell-if=\"isFocused\">" +
3134
+ " EDITABLE_CELL_TEMPLATE" +
3135
+ " </div>" +
3136
+ "</div>"
3137
+ );
3138
+
3139
+ $templateCache.put("cellTemplate.html",
3140
+ "<div class=\"ngCellText\" ng-class=\"col.colIndex()\"><span ng-cell-text>{{COL_FIELD CUSTOM_FILTERS}}</span></div>"
3141
+ );
3142
+
3143
+ $templateCache.put("checkboxCellTemplate.html",
3144
+ "<div class=\"ngSelectionCell\"><input tabindex=\"-1\" class=\"ngSelectionCheckbox\" type=\"checkbox\" ng-checked=\"row.selected\" /></div>"
3145
+ );
3146
+
3147
+ $templateCache.put("checkboxHeaderTemplate.html",
3148
+ "<input class=\"ngSelectionHeader\" type=\"checkbox\" ng-show=\"multiSelect\" ng-model=\"allSelected\" ng-change=\"toggleSelectAll(allSelected, true)\"/>"
3149
+ );
3150
+
3151
+ $templateCache.put("editableCellTemplate.html",
3152
+ "<input ng-class=\"'colt' + col.index\" ng-input=\"COL_FIELD\" ng-model=\"COL_FIELD\" />"
3153
+ );
3154
+
3155
+ $templateCache.put("footerTemplate.html",
3156
+ "<div ng-show=\"showFooter\" class=\"ngFooterPanel\" ng-class=\"{'ui-widget-content': jqueryUITheme, 'ui-corner-bottom': jqueryUITheme}\" ng-style=\"footerStyle()\">" +
3157
+ " <div class=\"ngTotalSelectContainer\" >" +
3158
+ " <div class=\"ngFooterTotalItems\" ng-class=\"{'ngNoMultiSelect': !multiSelect}\" >" +
3159
+ " <span class=\"ngLabel\">{{i18n.ngTotalItemsLabel}} {{maxRows()}}</span><span ng-show=\"filterText.length > 0\" class=\"ngLabel\">({{i18n.ngShowingItemsLabel}} {{totalFilteredItemsLength()}})</span>" +
3160
+ " </div>" +
3161
+ " <div class=\"ngFooterSelectedItems\" ng-show=\"multiSelect\">" +
3162
+ " <span class=\"ngLabel\">{{i18n.ngSelectedItemsLabel}} {{selectedItems.length}}</span>" +
3163
+ " </div>" +
3164
+ " </div>" +
3165
+ " <div class=\"ngPagerContainer\" style=\"float: right; margin-top: 10px;\" ng-show=\"enablePaging\" ng-class=\"{'ngNoMultiSelect': !multiSelect}\">" +
3166
+ " <div style=\"float:left; margin-right: 10px;\" class=\"ngRowCountPicker\">" +
3167
+ " <span style=\"float: left; margin-top: 3px;\" class=\"ngLabel\">{{i18n.ngPageSizeLabel}}</span>" +
3168
+ " <select style=\"float: left;height: 27px; width: 100px\" ng-model=\"pagingOptions.pageSize\" >" +
3169
+ " <option ng-repeat=\"size in pagingOptions.pageSizes\">{{size}}</option>" +
3170
+ " </select>" +
3171
+ " </div>" +
3172
+ " <div style=\"float:left; margin-right: 10px; line-height:25px;\" class=\"ngPagerControl\" style=\"float: left; min-width: 135px;\">" +
3173
+ " <button class=\"ngPagerButton\" ng-click=\"pageToFirst()\" ng-disabled=\"cantPageBackward()\" title=\"{{i18n.ngPagerFirstTitle}}\"><div class=\"ngPagerFirstTriangle\"><div class=\"ngPagerFirstBar\"></div></div></button>" +
3174
+ " <button class=\"ngPagerButton\" ng-click=\"pageBackward()\" ng-disabled=\"cantPageBackward()\" title=\"{{i18n.ngPagerPrevTitle}}\"><div class=\"ngPagerFirstTriangle ngPagerPrevTriangle\"></div></button>" +
3175
+ " <input class=\"ngPagerCurrent\" min=\"1\" max=\"{{maxPages()}}\" type=\"number\" style=\"width:50px; height: 24px; margin-top: 1px; padding: 0 4px;\" ng-model=\"pagingOptions.currentPage\"/>" +
3176
+ " <button class=\"ngPagerButton\" ng-click=\"pageForward()\" ng-disabled=\"cantPageForward()\" title=\"{{i18n.ngPagerNextTitle}}\"><div class=\"ngPagerLastTriangle ngPagerNextTriangle\"></div></button>" +
3177
+ " <button class=\"ngPagerButton\" ng-click=\"pageToLast()\" ng-disabled=\"cantPageToLast()\" title=\"{{i18n.ngPagerLastTitle}}\"><div class=\"ngPagerLastTriangle\"><div class=\"ngPagerLastBar\"></div></div></button>" +
3178
+ " </div>" +
3179
+ " </div>" +
3180
+ "</div>"
3181
+ );
3182
+
3183
+ $templateCache.put("gridTemplate.html",
3184
+ "<div class=\"ngTopPanel\" ng-class=\"{'ui-widget-header':jqueryUITheme, 'ui-corner-top': jqueryUITheme}\" ng-style=\"topPanelStyle()\">" +
3185
+ " <div class=\"ngGroupPanel\" ng-show=\"showGroupPanel()\" ng-style=\"groupPanelStyle()\">" +
3186
+ " <div class=\"ngGroupPanelDescription\" ng-show=\"configGroups.length == 0\">{{i18n.ngGroupPanelDescription}}</div>" +
3187
+ " <ul ng-show=\"configGroups.length > 0\" class=\"ngGroupList\">" +
3188
+ " <li class=\"ngGroupItem\" ng-repeat=\"group in configGroups\">" +
3189
+ " <span class=\"ngGroupElement\">" +
3190
+ " <span class=\"ngGroupName\">{{group.displayName}}" +
3191
+ " <span ng-click=\"removeGroup($index)\" class=\"ngRemoveGroup\">x</span>" +
3192
+ " </span>" +
3193
+ " <span ng-hide=\"$last\" class=\"ngGroupArrow\"></span>" +
3194
+ " </span>" +
3195
+ " </li>" +
3196
+ " </ul>" +
3197
+ " </div>" +
3198
+ " <div class=\"ngHeaderContainer\" ng-style=\"headerStyle()\">" +
3199
+ " <div class=\"ngHeaderScroller\" ng-style=\"headerScrollerStyle()\" ng-include=\"gridId + 'headerRowTemplate.html'\"></div>" +
3200
+ " </div>" +
3201
+ " <div ng-grid-menu></div>" +
3202
+ "</div>" +
3203
+ "<div class=\"ngViewport\" unselectable=\"on\" ng-viewport ng-class=\"{'ui-widget-content': jqueryUITheme}\" ng-style=\"viewportStyle()\">" +
3204
+ " <div class=\"ngCanvas\" ng-style=\"canvasStyle()\">" +
3205
+ " <div ng-style=\"rowStyle(row)\" ng-repeat=\"row in renderedRows\" ng-click=\"row.toggleSelected($event)\" ng-class=\"row.alternatingRowClass()\" ng-row></div>" +
3206
+ " </div>" +
3207
+ "</div>" +
3208
+ "<div ng-grid-footer></div>" +
3209
+ ""
3210
+ );
3211
+
3212
+ $templateCache.put("headerCellTemplate.html",
3213
+ "<div class=\"ngHeaderSortColumn {{col.headerClass}}\" ng-style=\"{'cursor': col.cursor}\" ng-class=\"{ 'ngSorted': !noSortVisible }\">" +
3214
+ " <div ng-click=\"col.sort($event)\" ng-class=\"'colt' + col.index\" class=\"ngHeaderText\">{{col.displayName}}</div>" +
3215
+ " <div class=\"ngSortButtonDown\" ng-show=\"col.showSortButtonDown()\"></div>" +
3216
+ " <div class=\"ngSortButtonUp\" ng-show=\"col.showSortButtonUp()\"></div>" +
3217
+ " <div class=\"ngSortPriority\">{{col.sortPriority}}</div>" +
3218
+ " <div ng-class=\"{ ngPinnedIcon: col.pinned, ngUnPinnedIcon: !col.pinned }\" ng-click=\"togglePin(col)\" ng-show=\"col.pinnable\"></div>" +
3219
+ "</div>" +
3220
+ "<div ng-show=\"col.resizable\" class=\"ngHeaderGrip\" ng-click=\"col.gripClick($event)\" ng-mousedown=\"col.gripOnMouseDown($event)\"></div>"
3221
+ );
3222
+
3223
+ $templateCache.put("headerRowTemplate.html",
3224
+ "<div ng-style=\"{ height: col.headerRowHeight }\" ng-repeat=\"col in renderedColumns\" ng-class=\"col.colIndex()\" class=\"ngHeaderCell\">" +
3225
+ " <div class=\"ngVerticalBar\" ng-style=\"{height: col.headerRowHeight}\" ng-class=\"{ ngVerticalBarVisible: !$last }\">&nbsp;</div>" +
3226
+ " <div ng-header-cell></div>" +
3227
+ "</div>"
3228
+ );
3229
+
3230
+ $templateCache.put("menuTemplate.html",
3231
+ "<div ng-show=\"showColumnMenu || showFilter\" class=\"ngHeaderButton\" ng-click=\"toggleShowMenu()\">" +
3232
+ " <div class=\"ngHeaderButtonArrow\"></div>" +
3233
+ "</div>" +
3234
+ "<div ng-show=\"showMenu\" class=\"ngColMenu\">" +
3235
+ " <div ng-show=\"showFilter\">" +
3236
+ " <input placeholder=\"{{i18n.ngSearchPlaceHolder}}\" type=\"text\" ng-model=\"filterText\"/>" +
3237
+ " </div>" +
3238
+ " <div ng-show=\"showColumnMenu\">" +
3239
+ " <span class=\"ngMenuText\">{{i18n.ngMenuText}}</span>" +
3240
+ " <ul class=\"ngColList\">" +
3241
+ " <li class=\"ngColListItem\" ng-repeat=\"col in columns | ngColumns\">" +
3242
+ " <label><input ng-disabled=\"col.pinned\" type=\"checkbox\" class=\"ngColListCheckbox\" ng-model=\"col.visible\"/>{{col.displayName}}</label>" +
3243
+ " <a title=\"Group By\" ng-class=\"col.groupedByClass()\" ng-show=\"col.groupable && col.visible\" ng-click=\"groupBy(col)\"></a>" +
3244
+ " <span class=\"ngGroupingNumber\" ng-show=\"col.groupIndex > 0\">{{col.groupIndex}}</span> " +
3245
+ " </li>" +
3246
+ " </ul>" +
3247
+ " </div>" +
3248
+ "</div>"
3249
+ );
3250
+
3251
+ $templateCache.put("rowTemplate.html",
3252
+ "<div ng-style=\"{ 'cursor': row.cursor }\" ng-repeat=\"col in renderedColumns\" ng-class=\"col.colIndex()\" class=\"ngCell {{col.cellClass}}\">" +
3253
+ " <div class=\"ngVerticalBar\" ng-style=\"{height: rowHeight}\" ng-class=\"{ ngVerticalBarVisible: !$last }\">&nbsp;</div>" +
3254
+ " <div ng-cell></div>" +
3255
+ "</div>"
3256
+ );
3257
+
3258
+ }]);
3259
+
3260
+ }(window, jQuery));