incline 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (303) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/Gemfile +17 -0
  4. data/Gemfile.lock +186 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.rdoc +208 -0
  7. data/Rakefile +37 -0
  8. data/app/assets/fonts/incline/.keep +0 -0
  9. data/app/assets/images/incline/.keep +0 -0
  10. data/app/assets/images/incline/barcode-B.svg +181 -0
  11. data/app/assets/javascripts/incline/activate_classed_items.js +11 -0
  12. data/app/assets/javascripts/incline/application.js +30 -0
  13. data/app/assets/javascripts/incline/bootstrap-datepicker.js +1800 -0
  14. data/app/assets/javascripts/incline/datatables.js +22193 -0
  15. data/app/assets/javascripts/incline/escapeHtml.js +10 -0
  16. data/app/assets/javascripts/incline/inline_actions.js +479 -0
  17. data/app/assets/javascripts/incline/jquery.doubleScroll.js +112 -0
  18. data/app/assets/javascripts/incline/jquery.number.js +764 -0
  19. data/app/assets/javascripts/incline/regexMask.js +27 -0
  20. data/app/assets/javascripts/incline/select2/i18n/en.js +3 -0
  21. data/app/assets/javascripts/incline/select2/select2.full.js +6436 -0
  22. data/app/assets/stylesheets/incline/application.css +18 -0
  23. data/app/assets/stylesheets/incline/bootstrap-theme.min.css +5 -0
  24. data/app/assets/stylesheets/incline/custom.scss +279 -0
  25. data/app/assets/stylesheets/incline/datatables.css +494 -0
  26. data/app/assets/stylesheets/incline/datepicker3.css +790 -0
  27. data/app/assets/stylesheets/incline/select2.css +484 -0
  28. data/app/controllers/incline/access_groups_controller.rb +127 -0
  29. data/app/controllers/incline/access_test_controller.rb +30 -0
  30. data/app/controllers/incline/account_activations_controller.rb +28 -0
  31. data/app/controllers/incline/application_controller.rb +11 -0
  32. data/app/controllers/incline/contact_controller.rb +34 -0
  33. data/app/controllers/incline/password_resets_controller.rb +113 -0
  34. data/app/controllers/incline/security_controller.rb +100 -0
  35. data/app/controllers/incline/sessions_controller.rb +50 -0
  36. data/app/controllers/incline/users_controller.rb +304 -0
  37. data/app/controllers/incline/welcome_controller.rb +19 -0
  38. data/app/helpers/incline/.keep +0 -0
  39. data/app/mailers/incline/application_mailer_base.rb +11 -0
  40. data/app/mailers/incline/contact_form.rb +19 -0
  41. data/app/mailers/incline/user_mailer.rb +45 -0
  42. data/app/models/incline/access_group.rb +121 -0
  43. data/app/models/incline/access_group_group_member.rb +12 -0
  44. data/app/models/incline/access_group_user_member.rb +10 -0
  45. data/app/models/incline/action_group.rb +12 -0
  46. data/app/models/incline/action_security.rb +222 -0
  47. data/app/models/incline/contact_message.rb +37 -0
  48. data/app/models/incline/disable_info.rb +20 -0
  49. data/app/models/incline/password_reset.rb +14 -0
  50. data/app/models/incline/password_reset_request.rb +14 -0
  51. data/app/models/incline/user.rb +437 -0
  52. data/app/models/incline/user_login_history.rb +30 -0
  53. data/app/views/incline/access_groups/_details.json.jbuilder +10 -0
  54. data/app/views/incline/access_groups/_form.html.erb +19 -0
  55. data/app/views/incline/access_groups/_list.html.erb +60 -0
  56. data/app/views/incline/access_groups/_messages.json.jbuilder +6 -0
  57. data/app/views/incline/access_groups/edit.html.erb +2 -0
  58. data/app/views/incline/access_groups/index.html.erb +6 -0
  59. data/app/views/incline/access_groups/index.json.jbuilder +16 -0
  60. data/app/views/incline/access_groups/new.html.erb +2 -0
  61. data/app/views/incline/access_groups/show.html.erb +9 -0
  62. data/app/views/incline/access_groups/show.json.jbuilder +11 -0
  63. data/app/views/incline/contact/new.html.erb +22 -0
  64. data/app/views/incline/contact_form/contact.html.erb +16 -0
  65. data/app/views/incline/contact_form/contact.text.erb +13 -0
  66. data/app/views/incline/password_resets/edit.html.erb +16 -0
  67. data/app/views/incline/password_resets/new.html.erb +12 -0
  68. data/app/views/incline/security/_details.json.jbuilder +7 -0
  69. data/app/views/incline/security/_form.html.erb +20 -0
  70. data/app/views/incline/security/_list.html.erb +89 -0
  71. data/app/views/incline/security/_messages.json.jbuilder +6 -0
  72. data/app/views/incline/security/edit.html.erb +2 -0
  73. data/app/views/incline/security/index.html.erb +6 -0
  74. data/app/views/incline/security/index.json.jbuilder +16 -0
  75. data/app/views/incline/security/show.html.erb +31 -0
  76. data/app/views/incline/security/show.json.jbuilder +11 -0
  77. data/app/views/incline/sessions/new.html.erb +26 -0
  78. data/app/views/incline/user_mailer/account_activation.html.erb +7 -0
  79. data/app/views/incline/user_mailer/account_activation.text.erb +6 -0
  80. data/app/views/incline/user_mailer/invalid_password_reset.html.erb +3 -0
  81. data/app/views/incline/user_mailer/invalid_password_reset.text.erb +5 -0
  82. data/app/views/incline/user_mailer/password_reset.html.erb +8 -0
  83. data/app/views/incline/user_mailer/password_reset.text.erb +7 -0
  84. data/app/views/incline/users/_details.json.jbuilder +32 -0
  85. data/app/views/incline/users/_form.html.erb +21 -0
  86. data/app/views/incline/users/_list.html.erb +102 -0
  87. data/app/views/incline/users/_messages.json.jbuilder +6 -0
  88. data/app/views/incline/users/disable_confirm.html.erb +19 -0
  89. data/app/views/incline/users/edit.html.erb +5 -0
  90. data/app/views/incline/users/index.html.erb +6 -0
  91. data/app/views/incline/users/index.json.jbuilder +16 -0
  92. data/app/views/incline/users/new.html.erb +5 -0
  93. data/app/views/incline/users/show.html.erb +12 -0
  94. data/app/views/incline/users/show.json.jbuilder +11 -0
  95. data/app/views/incline/welcome/home.html.erb +5 -0
  96. data/app/views/layouts/application.html.erb +1 -0
  97. data/app/views/layouts/incline/_account_menu.html.erb +18 -0
  98. data/app/views/layouts/incline/_app_menu_anon.html.erb +1 -0
  99. data/app/views/layouts/incline/_app_menu_authenticated.html.erb +1 -0
  100. data/app/views/layouts/incline/_footer.html.erb +13 -0
  101. data/app/views/layouts/incline/_header.html.erb +21 -0
  102. data/app/views/layouts/incline/_html_mailer.html.erb +5 -0
  103. data/app/views/layouts/incline/_incline_app.html.erb +25 -0
  104. data/app/views/layouts/incline/_messages.html.erb +3 -0
  105. data/app/views/layouts/incline/_shim.html.erb +3 -0
  106. data/app/views/layouts/incline/_text_mailer.text.erb +1 -0
  107. data/app/views/layouts/incline/application.html.erb +1 -0
  108. data/app/views/layouts/mailer.html.erb +2 -0
  109. data/app/views/layouts/mailer.text.erb +2 -0
  110. data/bin/rails +12 -0
  111. data/bin/test_scaffold.sh +10 -0
  112. data/config/routes.rb +61 -0
  113. data/db/migrate/20170511230126_create_incline_users.rb +26 -0
  114. data/db/migrate/20170515003052_create_incline_access_groups.rb +10 -0
  115. data/db/migrate/20170515003221_create_incline_user_login_histories.rb +12 -0
  116. data/db/migrate/20170515150908_create_incline_access_group_user_members.rb +11 -0
  117. data/db/migrate/20170515151058_create_incline_access_group_group_members.rb +11 -0
  118. data/db/migrate/20170517193432_add_comments_to_incline_user.rb +5 -0
  119. data/db/migrate/20170622132700_create_incline_action_securities.rb +16 -0
  120. data/db/migrate/20170622172712_create_incline_action_groups.rb +11 -0
  121. data/db/migrate/20170622195742_add_non_standard_to_action_security.rb +5 -0
  122. data/db/migrate/20170622230422_add_visible_to_action_security.rb +5 -0
  123. data/db/seeds.rb +81 -0
  124. data/exe/new_incline_app +42 -0
  125. data/lib/generators/incline/install_generator.rb +259 -0
  126. data/lib/generators/incline/templates/_app_menu_anon.html.erb +1 -0
  127. data/lib/generators/incline/templates/_app_menu_authenticated.html.erb +1 -0
  128. data/lib/generators/incline/templates/incline_application.css +17 -0
  129. data/lib/generators/incline/templates/incline_application.html.erb +1 -0
  130. data/lib/generators/incline/templates/incline_application.js +12 -0
  131. data/lib/generators/incline/templates/incline_database.yml +25 -0
  132. data/lib/generators/incline/templates/incline_email.yml +20 -0
  133. data/lib/generators/incline/templates/incline_mailer.html.erb +2 -0
  134. data/lib/generators/incline/templates/incline_mailer.text.erb +2 -0
  135. data/lib/generators/incline/templates/incline_users.yml +64 -0
  136. data/lib/generators/incline/templates/incline_version.rb +3 -0
  137. data/lib/incline/auth_engine_base.rb +52 -0
  138. data/lib/incline/data_tables_request.rb +336 -0
  139. data/lib/incline/date_time_formats.rb +6 -0
  140. data/lib/incline/engine.rb +212 -0
  141. data/lib/incline/errors.rb +15 -0
  142. data/lib/incline/extensions/action_controller_base.rb +526 -0
  143. data/lib/incline/extensions/action_mailer_base.rb +66 -0
  144. data/lib/incline/extensions/action_view_base.rb +489 -0
  145. data/lib/incline/extensions/active_record_base.rb +308 -0
  146. data/lib/incline/extensions/application.rb +137 -0
  147. data/lib/incline/extensions/application_configuration.rb +50 -0
  148. data/lib/incline/extensions/connection_adapter.rb +55 -0
  149. data/lib/incline/extensions/date_time_value.rb +123 -0
  150. data/lib/incline/extensions/date_value.rb +77 -0
  151. data/lib/incline/extensions/decimal_value.rb +55 -0
  152. data/lib/incline/extensions/erb_scaffold_generator.rb +31 -0
  153. data/lib/incline/extensions/float_value.rb +59 -0
  154. data/lib/incline/extensions/form_builder.rb +617 -0
  155. data/lib/incline/extensions/integer_value.rb +54 -0
  156. data/lib/incline/extensions/jbuilder_generator.rb +38 -0
  157. data/lib/incline/extensions/jbuilder_template.rb +39 -0
  158. data/lib/incline/extensions/main_app.rb +40 -0
  159. data/lib/incline/extensions/numeric.rb +63 -0
  160. data/lib/incline/extensions/object.rb +31 -0
  161. data/lib/incline/extensions/resource_route_generator.rb +53 -0
  162. data/lib/incline/extensions/session.rb +113 -0
  163. data/lib/incline/extensions/string.rb +50 -0
  164. data/lib/incline/extensions/test_case.rb +764 -0
  165. data/lib/incline/extensions/time_zone_converter.rb +40 -0
  166. data/lib/incline/global_status.rb +236 -0
  167. data/lib/incline/helpers/route_hash_formatter.rb +46 -0
  168. data/lib/incline/json_log_formatter.rb +96 -0
  169. data/lib/incline/json_logger.rb +17 -0
  170. data/lib/incline/log.rb +153 -0
  171. data/lib/incline/number_formats.rb +17 -0
  172. data/lib/incline/recaptcha.rb +346 -0
  173. data/lib/incline/user_manager.rb +212 -0
  174. data/lib/incline/validators/email_validator.rb +45 -0
  175. data/lib/incline/validators/ip_address_validator.rb +32 -0
  176. data/lib/incline/validators/recaptcha_validator.rb +37 -0
  177. data/lib/incline/validators/safe_name_validator.rb +31 -0
  178. data/lib/incline/version.rb +3 -0
  179. data/lib/incline/work_path.rb +75 -0
  180. data/lib/incline.rb +197 -0
  181. data/lib/tasks/incline_tasks.rake +4 -0
  182. data/lib/templates/erb/scaffold/_form.html.erb +43 -0
  183. data/lib/templates/erb/scaffold/_list.html.erb +81 -0
  184. data/lib/templates/erb/scaffold/edit.html.erb +1 -0
  185. data/lib/templates/erb/scaffold/index.html.erb +6 -0
  186. data/lib/templates/erb/scaffold/new.html.erb +1 -0
  187. data/lib/templates/erb/scaffold/show.html.erb +34 -0
  188. data/lib/templates/jbuilder/scaffold/_details.json.jbuilder +20 -0
  189. data/lib/templates/jbuilder/scaffold/index.json.jbuilder +16 -0
  190. data/lib/templates/jbuilder/scaffold/show.json.jbuilder +16 -0
  191. data/lib/templates/rails/scaffold_controller/controller.rb +128 -0
  192. data/test/controllers/incline/access_groups_controller_test.rb +65 -0
  193. data/test/controllers/incline/access_test_controller_test.rb +53 -0
  194. data/test/controllers/incline/contact_controller_test.rb +32 -0
  195. data/test/controllers/incline/security_controller_test.rb +39 -0
  196. data/test/controllers/incline/welcome_controller_test.rb +16 -0
  197. data/test/dummy/README.rdoc +28 -0
  198. data/test/dummy/Rakefile +6 -0
  199. data/test/dummy/app/assets/images/.keep +0 -0
  200. data/test/dummy/app/assets/javascripts/application.js +12 -0
  201. data/test/dummy/app/assets/stylesheets/application.css +17 -0
  202. data/test/dummy/app/controllers/application_controller.rb +5 -0
  203. data/test/dummy/app/controllers/concerns/.keep +0 -0
  204. data/test/dummy/app/helpers/application_helper.rb +2 -0
  205. data/test/dummy/app/mailers/.keep +0 -0
  206. data/test/dummy/app/models/.keep +0 -0
  207. data/test/dummy/app/models/concerns/.keep +0 -0
  208. data/test/dummy/app/views/layouts/application.html.erb +1 -0
  209. data/test/dummy/app/views/layouts/incline/_app_menu_anon.html.erb +1 -0
  210. data/test/dummy/app/views/layouts/incline/_app_menu_authenticated.html.erb +1 -0
  211. data/test/dummy/app/views/layouts/mailer.html.erb +2 -0
  212. data/test/dummy/app/views/layouts/mailer.text.erb +2 -0
  213. data/test/dummy/bin/bundle +3 -0
  214. data/test/dummy/bin/rails +4 -0
  215. data/test/dummy/bin/rake +4 -0
  216. data/test/dummy/bin/setup +29 -0
  217. data/test/dummy/config/application.rb +38 -0
  218. data/test/dummy/config/boot.rb +5 -0
  219. data/test/dummy/config/database.yml +34 -0
  220. data/test/dummy/config/email.yml +24 -0
  221. data/test/dummy/config/environment.rb +5 -0
  222. data/test/dummy/config/environments/development.rb +45 -0
  223. data/test/dummy/config/environments/production.rb +85 -0
  224. data/test/dummy/config/environments/test.rb +44 -0
  225. data/test/dummy/config/initializers/assets.rb +11 -0
  226. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  227. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  228. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  229. data/test/dummy/config/initializers/inflections.rb +16 -0
  230. data/test/dummy/config/initializers/mime_types.rb +4 -0
  231. data/test/dummy/config/initializers/session_store.rb +3 -0
  232. data/test/dummy/config/initializers/to_time_preserves_timezone.rb +10 -0
  233. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  234. data/test/dummy/config/locales/en.yml +23 -0
  235. data/test/dummy/config/routes.rb +6 -0
  236. data/test/dummy/config.ru +4 -0
  237. data/test/dummy/db/schema.rb +108 -0
  238. data/test/dummy/lib/assets/.keep +0 -0
  239. data/test/dummy/log/.keep +0 -0
  240. data/test/dummy/public/404.html +67 -0
  241. data/test/dummy/public/422.html +67 -0
  242. data/test/dummy/public/500.html +66 -0
  243. data/test/dummy/public/favicon.ico +0 -0
  244. data/test/extensions/action_controller_base_extensions_test.rb +21 -0
  245. data/test/extensions/action_mailer_base_extensions_test.rb +20 -0
  246. data/test/extensions/action_view_base_extensions_test.rb +267 -0
  247. data/test/extensions/active_record_extensions_test.rb +173 -0
  248. data/test/extensions/application_configuration_extensions_test.rb +46 -0
  249. data/test/extensions/application_extensions_test.rb +23 -0
  250. data/test/extensions/connection_adapter_extensions_test.rb +54 -0
  251. data/test/extensions/date_time_value_extensions_test.rb +104 -0
  252. data/test/extensions/date_value_extensions_test.rb +102 -0
  253. data/test/extensions/decimal_value_extensions_test.rb +85 -0
  254. data/test/extensions/erb_scaffold_generator_extensions_test.rb +17 -0
  255. data/test/extensions/float_value_extensions_test.rb +78 -0
  256. data/test/extensions/form_builder_extensions_test.rb +28 -0
  257. data/test/extensions/integer_value_extensions_test.rb +78 -0
  258. data/test/extensions/jbuilder_generator_extensions_test.rb +21 -0
  259. data/test/extensions/jbuilder_template_extensions_test.rb +47 -0
  260. data/test/extensions/main_app_extensions_test.rb +55 -0
  261. data/test/extensions/numeric_extensions_test.rb +76 -0
  262. data/test/extensions/object_extensions_test.rb +104 -0
  263. data/test/extensions/session_extensions_test.rb +69 -0
  264. data/test/extensions/string_extensions_test.rb +32 -0
  265. data/test/extensions/test_case_extensions_test.rb +538 -0
  266. data/test/extensions/time_zone_converter_extensions_test.rb +10 -0
  267. data/test/fixtures/incline/access_group_group_members.yml +1 -0
  268. data/test/fixtures/incline/access_group_user_members.yml +1 -0
  269. data/test/fixtures/incline/access_groups.yml +13 -0
  270. data/test/fixtures/incline/action_groups.yml +6 -0
  271. data/test/fixtures/incline/action_securities.yml +18 -0
  272. data/test/fixtures/incline/user_login_histories.yml +1 -0
  273. data/test/fixtures/incline/users.yml +64 -0
  274. data/test/incline_test.rb +63 -0
  275. data/test/integration/incline/users_edit_test.rb +180 -0
  276. data/test/integration/incline/users_login_test.rb +105 -0
  277. data/test/integration/incline/users_signup_test.rb +147 -0
  278. data/test/integration/navigation_test.rb +11 -0
  279. data/test/lib/data_tables_request_test.rb +245 -0
  280. data/test/lib/date_time_formats_test.rb +111 -0
  281. data/test/lib/global_status_test.rb +89 -0
  282. data/test/lib/json_log_formatter_test.rb +43 -0
  283. data/test/lib/log_test.rb +36 -0
  284. data/test/lib/recaptcha_test.rb +75 -0
  285. data/test/lib/user_manager_test.rb +47 -0
  286. data/test/lib/work_path_test.rb +18 -0
  287. data/test/models/incline/access_group_group_member_test.rb +30 -0
  288. data/test/models/incline/access_group_test.rb +60 -0
  289. data/test/models/incline/access_group_user_member_test.rb +29 -0
  290. data/test/models/incline/action_group_test.rb +27 -0
  291. data/test/models/incline/action_security_test.rb +176 -0
  292. data/test/models/incline/contact_message_test.rb +66 -0
  293. data/test/models/incline/disable_info_test.rb +29 -0
  294. data/test/models/incline/password_reset_request_test.rb +35 -0
  295. data/test/models/incline/password_reset_test.rb +51 -0
  296. data/test/models/incline/user_login_history_test.rb +31 -0
  297. data/test/models/incline/user_test.rb +91 -0
  298. data/test/test_helper.rb +42 -0
  299. data/test/validators/email_validator_test.rb +102 -0
  300. data/test/validators/ip_address_validator_test.rb +107 -0
  301. data/test/validators/recaptcha_validator_test.rb +57 -0
  302. data/test/validators/safe_name_validator_test.rb +101 -0
  303. metadata +584 -0
@@ -0,0 +1,764 @@
1
+ /**
2
+ * jQuery number plug-in 2.1.5
3
+ * Copyright 2012, Digital Fusion
4
+ * Licensed under the MIT license.
5
+ * http://opensource.teamdf.com/license/
6
+ *
7
+ * A jQuery plugin which implements a permutation of phpjs.org's number_format to provide
8
+ * simple number formatting, insertion, and as-you-type masking of a number.
9
+ *
10
+ * @author Sam Sehnert
11
+ * @docs http://www.teamdf.com/web/jquery-number-format-redux/196/
12
+ */
13
+ (function($){
14
+
15
+ "use strict";
16
+
17
+ /**
18
+ * Method for selecting a range of characters in an input/textarea.
19
+ *
20
+ * @param int rangeStart : Where we want the selection to start.
21
+ * @param int rangeEnd : Where we want the selection to end.
22
+ *
23
+ * @return void;
24
+ */
25
+ function setSelectionRange( rangeStart, rangeEnd )
26
+ {
27
+ // Check which way we need to define the text range.
28
+ if( this.createTextRange )
29
+ {
30
+ var range = this.createTextRange();
31
+ range.collapse( true );
32
+ range.moveStart( 'character', rangeStart );
33
+ range.moveEnd( 'character', rangeEnd-rangeStart );
34
+ range.select();
35
+ }
36
+
37
+ // Alternate setSelectionRange method for supporting browsers.
38
+ else if( this.setSelectionRange )
39
+ {
40
+ this.focus();
41
+ this.setSelectionRange( rangeStart, rangeEnd );
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Get the selection position for the given part.
47
+ *
48
+ * @param string part : Options, 'Start' or 'End'. The selection position to get.
49
+ *
50
+ * @return int : The index position of the selection part.
51
+ */
52
+ function getSelection( part )
53
+ {
54
+ var pos = this.value.length;
55
+
56
+ // Work out the selection part.
57
+ part = ( part.toLowerCase() == 'start' ? 'Start' : 'End' );
58
+
59
+ if( document.selection ){
60
+ // The current selection
61
+ var range = document.selection.createRange(), stored_range, selectionStart, selectionEnd;
62
+ // We'll use this as a 'dummy'
63
+ stored_range = range.duplicate();
64
+ // Select all text
65
+ //stored_range.moveToElementText( this );
66
+ stored_range.expand('textedit');
67
+ // Now move 'dummy' end point to end point of original range
68
+ stored_range.setEndPoint( 'EndToEnd', range );
69
+ // Now we can calculate start and end points
70
+ selectionStart = stored_range.text.length - range.text.length;
71
+ selectionEnd = selectionStart + range.text.length;
72
+ return part == 'Start' ? selectionStart : selectionEnd;
73
+ }
74
+
75
+ else if(typeof(this['selection'+part])!="undefined")
76
+ {
77
+ pos = this['selection'+part];
78
+ }
79
+ return pos;
80
+ }
81
+
82
+ /**
83
+ * Substitutions for keydown keycodes.
84
+ * Allows conversion from e.which to ascii characters.
85
+ */
86
+ var _keydown = {
87
+ codes : {
88
+ 46 : 127,
89
+ 188 : 44,
90
+ 109 : 45,
91
+ 190 : 46,
92
+ 191 : 47,
93
+ 192 : 96,
94
+ 220 : 92,
95
+ 222 : 39,
96
+ 221 : 93,
97
+ 219 : 91,
98
+ 173 : 45,
99
+ 187 : 61, //IE Key codes
100
+ 186 : 59, //IE Key codes
101
+ 189 : 45, //IE Key codes
102
+ 110 : 46 //IE Key codes
103
+ },
104
+ shifts : {
105
+ 96 : "~",
106
+ 49 : "!",
107
+ 50 : "@",
108
+ 51 : "#",
109
+ 52 : "$",
110
+ 53 : "%",
111
+ 54 : "^",
112
+ 55 : "&",
113
+ 56 : "*",
114
+ 57 : "(",
115
+ 48 : ")",
116
+ 45 : "_",
117
+ 61 : "+",
118
+ 91 : "{",
119
+ 93 : "}",
120
+ 92 : "|",
121
+ 59 : ":",
122
+ 39 : "\"",
123
+ 44 : "<",
124
+ 46 : ">",
125
+ 47 : "?"
126
+ }
127
+ };
128
+
129
+ /**
130
+ * jQuery number formatter plugin. This will allow you to format numbers on an element.
131
+ *
132
+ * @params proxied for format_number method.
133
+ *
134
+ * @return : The jQuery collection the method was called with.
135
+ */
136
+ $.fn.number = function( number, decimals, dec_point, thousands_sep ){
137
+
138
+ // Enter the default thousands separator, and the decimal placeholder.
139
+ thousands_sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep;
140
+ dec_point = (typeof dec_point === 'undefined') ? '.' : dec_point;
141
+ decimals = (typeof decimals === 'undefined' ) ? 0 : decimals;
142
+
143
+ // Work out the unicode character for the decimal placeholder.
144
+ var u_dec = ('\\u'+('0000'+(dec_point.charCodeAt(0).toString(16))).slice(-4)),
145
+ regex_dec_num = new RegExp('[^'+u_dec+'0-9]','g'),
146
+ regex_dec = new RegExp(u_dec,'g');
147
+
148
+ // If we've specified to take the number from the target element,
149
+ // we loop over the collection, and get the number.
150
+ if( number === true )
151
+ {
152
+ // If this element is a number, then we add a keyup
153
+ if( this.is('input:text') )
154
+ {
155
+ // Return the jquery collection.
156
+ return this.on({
157
+
158
+ /**
159
+ * Handles keyup events, re-formatting numbers.
160
+ *
161
+ * Uses 'data' object to keep track of important information.
162
+ *
163
+ * data.c
164
+ * This variable keeps track of where the caret *should* be. It works out the position as
165
+ * the number of characters from the end of the string. E.g., '1^,234.56' where ^ denotes the caret,
166
+ * would be index -7 (e.g., 7 characters from the end of the string). At the end of both the key down
167
+ * and key up events, we'll re-position the caret to wherever data.c tells us the cursor should be.
168
+ * This gives us a mechanism for incrementing the cursor position when we come across decimals, commas
169
+ * etc. This figure typically doesn't increment for each keypress when to the left of the decimal,
170
+ * but does when to the right of the decimal.
171
+ *
172
+ * @param object e : the keyup event object.s
173
+ *
174
+ * @return void;
175
+ */
176
+ 'keydown.format' : function(e){
177
+
178
+ // Define variables used in the code below.
179
+ var $this = $(this),
180
+ data = $this.data('numFormat'),
181
+ code = (e.keyCode ? e.keyCode : e.which),
182
+ chara = '', //unescape(e.originalEvent.keyIdentifier.replace('U+','%u')),
183
+ start = getSelection.apply(this,['start']),
184
+ end = getSelection.apply(this,['end']),
185
+ val = '',
186
+ setPos = false;
187
+
188
+ // Webkit (Chrome & Safari) on windows screws up the keyIdentifier detection
189
+ // for numpad characters. I've disabled this for now, because while keyCode munging
190
+ // below is hackish and ugly, it actually works cross browser & platform.
191
+
192
+ // if( typeof e.originalEvent.keyIdentifier !== 'undefined' )
193
+ // {
194
+ // chara = unescape(e.originalEvent.keyIdentifier.replace('U+','%u'));
195
+ // }
196
+ // else
197
+ // {
198
+ if (_keydown.codes.hasOwnProperty(code)) {
199
+ code = _keydown.codes[code];
200
+ }
201
+ if (!e.shiftKey && (code >= 65 && code <= 90)){
202
+ code += 32;
203
+ } else if (!e.shiftKey && (code >= 69 && code <= 105)){
204
+ code -= 48;
205
+ } else if (e.shiftKey && _keydown.shifts.hasOwnProperty(code)){
206
+ //get shifted keyCode value
207
+ chara = _keydown.shifts[code];
208
+ }
209
+
210
+ if( chara == '' ) chara = String.fromCharCode(code);
211
+ // }
212
+
213
+
214
+
215
+
216
+ // Stop executing if the user didn't type a number key, a decimal character, backspace, or delete.
217
+ if( code != 8 && code != 45 && code != 127 && chara != dec_point && !chara.match(/[0-9]/) )
218
+ {
219
+ // We need the original keycode now...
220
+ var key = (e.keyCode ? e.keyCode : e.which);
221
+ if( // Allow control keys to go through... (delete, backspace, tab, enter, escape etc)
222
+ key == 46 || key == 8 || key == 127 || key == 9 || key == 27 || key == 13 ||
223
+ // Allow: Ctrl+A, Ctrl+R, Ctrl+P, Ctrl+S, Ctrl+F, Ctrl+H, Ctrl+B, Ctrl+J, Ctrl+T, Ctrl+Z, Ctrl++, Ctrl+-, Ctrl+0
224
+ ( (key == 65 || key == 82 || key == 80 || key == 83 || key == 70 || key == 72 || key == 66 || key == 74 || key == 84 || key == 90|| key == 61 || key == 173 || key == 48) && ( e.ctrlKey || e.metaKey ) === true ) ||
225
+ // Allow: Ctrl+V, Ctrl+C, Ctrl+X
226
+ ( (key == 86 || key == 67 || key == 88) && ( e.ctrlKey || e.metaKey ) === true ) ||
227
+ // Allow: home, end, left, right
228
+ ( (key >= 35 && key <= 39) ) ||
229
+ // Allow: F1-F12
230
+ ( (key >= 112 && key <= 123) )
231
+ ){
232
+ return;
233
+ }
234
+ // But prevent all other keys.
235
+ e.preventDefault();
236
+ return false;
237
+ }
238
+
239
+ // The whole lot has been selected, or if the field is empty...
240
+ if( start == 0 && end == this.value.length ) //|| $this.val() == 0 )
241
+ {
242
+ if( code == 8 ) // Backspace
243
+ {
244
+ // Blank out the field, but only if the data object has already been instantiated.
245
+ start = end = 1;
246
+ this.value = '';
247
+
248
+ // Reset the cursor position.
249
+ data.init = (decimals>0?-1:0);
250
+ data.c = (decimals>0?-(decimals+1):0);
251
+ setSelectionRange.apply(this, [0,0]);
252
+ }
253
+ else if( chara == dec_point )
254
+ {
255
+ start = end = 1;
256
+ this.value = '0'+ dec_point + (new Array(decimals+1).join('0'));
257
+
258
+ // Reset the cursor position.
259
+ data.init = (decimals>0?1:0);
260
+ data.c = (decimals>0?-(decimals+1):0);
261
+ }
262
+ else if( code == 45 ) // Negative sign
263
+ {
264
+ start = end = 2;
265
+ this.value = '-0'+dec_point + (new Array(decimals+1).join('0'));
266
+
267
+ // Reset the cursor position.
268
+ data.init = (decimals>0?1:0);
269
+ data.c = (decimals>0?-(decimals+1):0);
270
+
271
+ setSelectionRange.apply(this, [2,2]);
272
+ }
273
+ else
274
+ {
275
+ // Reset the cursor position.
276
+ data.init = (decimals>0?-1:0);
277
+ data.c = (decimals>0?-(decimals):0);
278
+ }
279
+ }
280
+
281
+ // Otherwise, we need to reset the caret position
282
+ // based on the users selection.
283
+ else
284
+ {
285
+ data.c = end-this.value.length;
286
+ }
287
+
288
+ // Track if partial selection was used
289
+ data.isPartialSelection = start == end ? false : true;
290
+
291
+ // If the start position is before the decimal point,
292
+ // and the user has typed a decimal point, we need to move the caret
293
+ // past the decimal place.
294
+ if( decimals > 0 && chara == dec_point && start == this.value.length-decimals-1 )
295
+ {
296
+ data.c++;
297
+ data.init = Math.max(0,data.init);
298
+ e.preventDefault();
299
+
300
+ // Set the selection position.
301
+ setPos = this.value.length+data.c;
302
+ }
303
+
304
+ // Ignore negative sign unless at beginning of number (and it's not already present)
305
+ else if( code == 45 && (start != 0 || this.value.indexOf('-') == 0) )
306
+ {
307
+ e.preventDefault();
308
+ }
309
+
310
+ // If the user is just typing the decimal place,
311
+ // we simply ignore it.
312
+ else if( chara == dec_point )
313
+ {
314
+ data.init = Math.max(0,data.init);
315
+ e.preventDefault();
316
+ }
317
+
318
+ // If hitting the delete key, and the cursor is before a decimal place,
319
+ // we simply move the cursor to the other side of the decimal place.
320
+ else if( decimals > 0 && code == 127 && start == this.value.length-decimals-1 )
321
+ {
322
+ // Just prevent default but don't actually move the caret here because it's done in the keyup event
323
+ e.preventDefault();
324
+ }
325
+
326
+ // If hitting the backspace key, and the cursor is behind a decimal place,
327
+ // we simply move the cursor to the other side of the decimal place.
328
+ else if( decimals > 0 && code == 8 && start == this.value.length-decimals )
329
+ {
330
+ e.preventDefault();
331
+ data.c--;
332
+
333
+ // Set the selection position.
334
+ setPos = this.value.length+data.c;
335
+ }
336
+
337
+ // If hitting the delete key, and the cursor is to the right of the decimal
338
+ // we replace the character after the caret with a 0.
339
+ else if( decimals > 0 && code == 127 && start > this.value.length-decimals-1 )
340
+ {
341
+ if( this.value === '' ) return;
342
+
343
+ // If the character following is not already a 0,
344
+ // replace it with one.
345
+ if( this.value.slice(start, start+1) != '0' )
346
+ {
347
+ val = this.value.slice(0, start) + '0' + this.value.slice(start+1);
348
+ // The regex replacement below removes negative sign from numbers...
349
+ // not sure why they're necessary here when none of the other cases use them
350
+ //$this.val(val.replace(regex_dec_num,'').replace(regex_dec,dec_point));
351
+ $this.val(val);
352
+ }
353
+
354
+ e.preventDefault();
355
+
356
+ // Set the selection position.
357
+ setPos = this.value.length+data.c;
358
+ }
359
+
360
+ // If hitting the backspace key, and the cursor is to the right of the decimal
361
+ // (but not directly to the right) we replace the character preceding the
362
+ // caret with a 0.
363
+ else if( decimals > 0 && code == 8 && start > this.value.length-decimals )
364
+ {
365
+ if( this.value === '' ) return;
366
+
367
+ // If the character preceding is not already a 0,
368
+ // replace it with one.
369
+ if( this.value.slice(start-1, start) != '0' )
370
+ {
371
+ val = this.value.slice(0, start-1) + '0' + this.value.slice(start);
372
+ // The regex replacement below removes negative sign from numbers...
373
+ // not sure why they're necessary here when none of the other cases use them
374
+ //$this.val(val.replace(regex_dec_num,'').replace(regex_dec,dec_point));
375
+ $this.val(val);
376
+ }
377
+
378
+ e.preventDefault();
379
+ data.c--;
380
+
381
+ // Set the selection position.
382
+ setPos = this.value.length+data.c;
383
+ }
384
+
385
+ // If the delete key was pressed, and the character immediately
386
+ // after the caret is a thousands_separator character, simply
387
+ // step over it.
388
+ else if( code == 127 && this.value.slice(start, start+1) == thousands_sep )
389
+ {
390
+ // Just prevent default but don't actually move the caret here because it's done in the keyup event
391
+ e.preventDefault();
392
+ }
393
+
394
+ // If the backspace key was pressed, and the character immediately
395
+ // before the caret is a thousands_separator character, simply
396
+ // step over it.
397
+ else if( code == 8 && this.value.slice(start-1, start) == thousands_sep )
398
+ {
399
+ e.preventDefault();
400
+ data.c--;
401
+
402
+ // Set the selection position.
403
+ setPos = this.value.length+data.c;
404
+ }
405
+
406
+ // If the caret is to the right of the decimal place, and the user is entering a
407
+ // number, remove the following character before putting in the new one.
408
+ else if(
409
+ decimals > 0 &&
410
+ start == end &&
411
+ this.value.length > decimals+1 &&
412
+ start > this.value.length-decimals-1 && isFinite(+chara) &&
413
+ !e.metaKey && !e.ctrlKey && !e.altKey && chara.length === 1
414
+ )
415
+ {
416
+ // If the character preceding is not already a 0,
417
+ // replace it with one.
418
+ if( end === this.value.length )
419
+ {
420
+ val = this.value.slice(0, start-1);
421
+ }
422
+ else
423
+ {
424
+ val = this.value.slice(0, start)+this.value.slice(start+1);
425
+ }
426
+
427
+ // Reset the position.
428
+ this.value = val;
429
+ setPos = start;
430
+ }
431
+
432
+ // If we need to re-position the characters.
433
+ if( setPos !== false )
434
+ {
435
+ //console.log('Setpos keydown: ', setPos );
436
+ setSelectionRange.apply(this, [setPos, setPos]);
437
+ }
438
+
439
+ // Store the data on the element.
440
+ $this.data('numFormat', data);
441
+
442
+ },
443
+
444
+ /**
445
+ * Handles keyup events, re-formatting numbers.
446
+ *
447
+ * @param object e : the keyup event object.s
448
+ *
449
+ * @return void;
450
+ */
451
+ 'keyup.format' : function(e){
452
+
453
+ // Store these variables for use below.
454
+ var $this = $(this),
455
+ data = $this.data('numFormat'),
456
+ code = (e.keyCode ? e.keyCode : e.which),
457
+ start = getSelection.apply(this,['start']),
458
+ end = getSelection.apply(this,['end']),
459
+ setPos;
460
+
461
+
462
+ // Check for negative characters being entered at the start of the string.
463
+ // If there's any kind of selection, just ignore the input.
464
+ if( start === 0 && end === 0 && ( code === 189 || code === 109 ) )
465
+ {
466
+ $this.val('-'+$this.val());
467
+
468
+ start = 1;
469
+ data.c = 1-this.value.length;
470
+ data.init = 1;
471
+
472
+ $this.data('numFormat', data);
473
+
474
+ setPos = this.value.length+data.c;
475
+ setSelectionRange.apply(this, [setPos, setPos]);
476
+ }
477
+
478
+ // Stop executing if the user didn't type a number key, a decimal, or a comma.
479
+ if( this.value === '' || (code < 48 || code > 57) && (code < 96 || code > 105 ) && code !== 8 && code !== 46 && code !== 110 ) return;
480
+
481
+ // Re-format the textarea.
482
+ $this.val($this.val());
483
+
484
+ if( decimals > 0 )
485
+ {
486
+ // If we haven't marked this item as 'initialized'
487
+ // then do so now. It means we should place the caret just
488
+ // before the decimal. This will never be un-initialized before
489
+ // the decimal character itself is entered.
490
+ if( data.init < 1 )
491
+ {
492
+ start = this.value.length-decimals-( data.init < 0 ? 1 : 0 );
493
+ data.c = start-this.value.length;
494
+ data.init = 1;
495
+
496
+ $this.data('numFormat', data);
497
+ }
498
+
499
+ // Increase the cursor position if the caret is to the right
500
+ // of the decimal place, and the character pressed isn't the backspace key.
501
+ else if( start > this.value.length-decimals && code != 8 )
502
+ {
503
+ data.c++;
504
+
505
+ // Store the data, now that it's changed.
506
+ $this.data('numFormat', data);
507
+ }
508
+ }
509
+
510
+ // Move caret to the right after delete key pressed
511
+ if (code == 46 && !data.isPartialSelection)
512
+ {
513
+ data.c++;
514
+
515
+ // Store the data, now that it's changed.
516
+ $this.data('numFormat', data);
517
+ }
518
+
519
+ //console.log( 'Setting pos: ', start, decimals, this.value.length + data.c, this.value.length, data.c );
520
+
521
+ // Set the selection position.
522
+ setPos = this.value.length+data.c;
523
+ setSelectionRange.apply(this, [setPos, setPos]);
524
+ },
525
+
526
+ /**
527
+ * Reformat when pasting into the field.
528
+ *
529
+ * @param object e : jQuery event object.
530
+ *
531
+ * @return false : prevent default action.
532
+ */
533
+ 'paste.format' : function(e){
534
+
535
+ // Defint $this. It's used twice!.
536
+ var $this = $(this),
537
+ original = e.originalEvent,
538
+ val = null;
539
+
540
+ // Get the text content stream.
541
+ if (window.clipboardData && window.clipboardData.getData) { // IE
542
+ val = window.clipboardData.getData('Text');
543
+ } else if (original.clipboardData && original.clipboardData.getData) {
544
+ val = original.clipboardData.getData('text/plain');
545
+ }
546
+
547
+ // Do the reformat operation.
548
+ $this.val(val);
549
+
550
+ // Stop the actual content from being pasted.
551
+ e.preventDefault();
552
+ return false;
553
+ }
554
+
555
+ })
556
+
557
+ // Loop each element (which isn't blank) and do the format.
558
+ .each(function(){
559
+
560
+ var $this = $(this).data('numFormat',{
561
+ c : -(decimals+1),
562
+ decimals : decimals,
563
+ thousands_sep : thousands_sep,
564
+ dec_point : dec_point,
565
+ regex_dec_num : regex_dec_num,
566
+ regex_dec : regex_dec,
567
+ init : this.value.indexOf('.') ? true : false
568
+ });
569
+
570
+ // Return if the element is empty.
571
+ if( this.value === '' ) return;
572
+
573
+ // Otherwise... format!!
574
+ $this.val($this.val());
575
+ });
576
+ }
577
+ else
578
+ {
579
+ // return the collection.
580
+ return this.each(function(){
581
+ var $this = $(this), num = +$this.text().replace(regex_dec_num,'').replace(regex_dec,'.');
582
+ $this.number( !isFinite(num) ? 0 : +num, decimals, dec_point, thousands_sep );
583
+ });
584
+ }
585
+ }
586
+
587
+ // Add this number to the element as text.
588
+ return this.text( $.number.apply(window,arguments) );
589
+ };
590
+
591
+ //
592
+ // Create .val() hooks to get and set formatted numbers in inputs.
593
+ //
594
+
595
+ // We check if any hooks already exist, and cache
596
+ // them in case we need to re-use them later on.
597
+ var origHookGet = null, origHookSet = null;
598
+
599
+ // Check if a text valHook already exists.
600
+ if( $.isPlainObject( $.valHooks.text ) )
601
+ {
602
+ // Preserve the original valhook function
603
+ // we'll call this for values we're not
604
+ // explicitly handling.
605
+ if( $.isFunction( $.valHooks.text.get ) ) origHookGet = $.valHooks.text.get;
606
+ if( $.isFunction( $.valHooks.text.set ) ) origHookSet = $.valHooks.text.set;
607
+ }
608
+ else
609
+ {
610
+ // Define an object for the new valhook.
611
+ $.valHooks.text = {};
612
+ }
613
+
614
+ /**
615
+ * Define the valHook to return normalised field data against an input
616
+ * which has been tagged by the number formatter.
617
+ *
618
+ * @param object el : The raw DOM element that we're getting the value from.
619
+ *
620
+ * @return mixed : Returns the value that was written to the element as a
621
+ * javascript number, or undefined to let jQuery handle it normally.
622
+ */
623
+ $.valHooks.text.get = function( el ){
624
+
625
+ // Get the element, and its data.
626
+ var $this = $(el), num, negative,
627
+ data = $this.data('numFormat');
628
+
629
+ // Does this element have our data field?
630
+ if( !data )
631
+ {
632
+ // Check if the valhook function already existed
633
+ if( $.isFunction( origHookGet ) )
634
+ {
635
+ // There was, so go ahead and call it
636
+ return origHookGet(el);
637
+ }
638
+ else
639
+ {
640
+ // No previous function, return undefined to have jQuery
641
+ // take care of retrieving the value
642
+ return undefined;
643
+ }
644
+ }
645
+ else
646
+ {
647
+ // Remove formatting, and return as number.
648
+ if( el.value === '' ) return '';
649
+
650
+
651
+ // Convert to a number.
652
+ num = +(el.value
653
+ .replace( data.regex_dec_num, '' )
654
+ .replace( data.regex_dec, '.' ));
655
+
656
+ // If we've got a finite number, return it.
657
+ // Otherwise, simply return 0.
658
+ // Return as a string... thats what we're
659
+ // used to with .val()
660
+ return (el.value.indexOf('-') === 0 ? '-' : '')+( isFinite( num ) ? num : 0 );
661
+ }
662
+ };
663
+
664
+ /**
665
+ * A valhook which formats a number when run against an input
666
+ * which has been tagged by the number formatter.
667
+ *
668
+ * @param object el : The raw DOM element (input element).
669
+ * @param float : The number to set into the value field.
670
+ *
671
+ * @return mixed : Returns the value that was written to the element,
672
+ * or undefined to let jQuery handle it normally.
673
+ */
674
+ $.valHooks.text.set = function( el, val )
675
+ {
676
+ // Get the element, and its data.
677
+ var $this = $(el),
678
+ data = $this.data('numFormat');
679
+
680
+ // Does this element have our data field?
681
+ if( !data )
682
+ {
683
+
684
+ // Check if the valhook function already exists
685
+ if( $.isFunction( origHookSet ) )
686
+ {
687
+ // There was, so go ahead and call it
688
+ return origHookSet(el,val);
689
+ }
690
+ else
691
+ {
692
+ // No previous function, return undefined to have jQuery
693
+ // take care of retrieving the value
694
+ return undefined;
695
+ }
696
+ }
697
+ else
698
+ {
699
+ var num = $.number( val, data.decimals, data.dec_point, data.thousands_sep );
700
+
701
+ // Make sure empties are set with correct signs.
702
+ // if(val.indexOf('-') === 0 && +num === 0)
703
+ // {
704
+ // num = '-'+num;
705
+ // }
706
+
707
+ return $.isFunction(origHookSet) ? origHookSet(el, num) : el.value = num;
708
+ }
709
+ };
710
+
711
+ /**
712
+ * The (modified) excellent number formatting method from PHPJS.org.
713
+ * http://phpjs.org/functions/number_format/
714
+ *
715
+ * @modified by Sam Sehnert (teamdf.com)
716
+ * - don't redefine dec_point, thousands_sep... just overwrite with defaults.
717
+ * - don't redefine decimals, just overwrite as numeric.
718
+ * - Generate regex for normalizing pre-formatted numbers.
719
+ *
720
+ * @param float number : The number you wish to format, or TRUE to use the text contents
721
+ * of the element as the number. Please note that this won't work for
722
+ * elements which have child nodes with text content.
723
+ * @param int decimals : The number of decimal places that should be displayed. Defaults to 0.
724
+ * @param string dec_point : The character to use as a decimal point. Defaults to '.'.
725
+ * @param string thousands_sep : The character to use as a thousands separator. Defaults to ','.
726
+ *
727
+ * @return string : The formatted number as a string.
728
+ */
729
+ $.number = function( number, decimals, dec_point, thousands_sep ){
730
+ // Set the default values here, instead so we can use them in the replace below.
731
+ thousands_sep = (typeof thousands_sep === 'undefined') ? ( new Number(1000).toLocaleString() !== '1000' ? new Number(1000).toLocaleString().charAt(1) : '' ) : thousands_sep;
732
+ dec_point = (typeof dec_point === 'undefined') ? new Number(0.1).toLocaleString().charAt(1) : dec_point;
733
+ decimals = !isFinite(+decimals) ? 0 : Math.abs(decimals);
734
+
735
+ // Work out the unicode representation for the decimal place and thousand sep.
736
+ var u_dec = ('\\u'+('0000'+(dec_point.charCodeAt(0).toString(16))).slice(-4));
737
+ var u_sep = ('\\u'+('0000'+(thousands_sep.charCodeAt(0).toString(16))).slice(-4));
738
+
739
+ // Fix the number, so that it's an actual number.
740
+ number = (number + '')
741
+ .replace('\.', dec_point) // because the number if passed in as a float (having . as decimal point per definition) we need to replace this with the passed in decimal point character
742
+ .replace(new RegExp(u_sep,'g'),'')
743
+ .replace(new RegExp(u_dec,'g'),'.')
744
+ .replace(new RegExp('[^0-9+\-Ee.]','g'),'');
745
+
746
+ var n = !isFinite(+number) ? 0 : +number,
747
+ s = '',
748
+ toFixedFix = function (n, decimals) {
749
+ return '' + (+(Math.round(('' + n).indexOf('e') > 0 ? n : n + 'e+' + decimals) + 'e-' + decimals));
750
+ };
751
+
752
+ // Fix for IE parseFloat(0.55).toFixed(0) = 0;
753
+ s = (decimals ? toFixedFix(n, decimals) : '' + Math.round(n)).split('.');
754
+ if (s[0].length > 3) {
755
+ s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, thousands_sep);
756
+ }
757
+ if ((s[1] || '').length < decimals) {
758
+ s[1] = s[1] || '';
759
+ s[1] += new Array(decimals - s[1].length + 1).join('0');
760
+ }
761
+ return s.join(dec_point);
762
+ }
763
+
764
+ })(jQuery);