guara 0.0.1.rc

Sign up to get free protection for your applications and to get access to all the features.
Files changed (512) hide show
  1. data/.gitignore +23 -0
  2. data/.rspec +2 -0
  3. data/.travis.yml +33 -0
  4. data/Gemfile +82 -0
  5. data/Gemfile.lock +323 -0
  6. data/Guardfile +32 -0
  7. data/MIT-LICENSE +20 -0
  8. data/README.md +8 -0
  9. data/Rakefile +7 -0
  10. data/app/admin/business_activities.rb +3 -0
  11. data/app/admin/business_departments.rb +3 -0
  12. data/app/admin/business_segments.rb +13 -0
  13. data/app/admin/cities.rb +3 -0
  14. data/app/admin/company_businesses.rb +3 -0
  15. data/app/admin/dashboard.rb +39 -0
  16. data/app/admin/districts.rb +3 -0
  17. data/app/admin/states.rb +3 -0
  18. data/app/admin/task_types.rb +3 -0
  19. data/app/admin/user_groups.rb +3 -0
  20. data/app/admin/users.rb +3 -0
  21. data/app/assets/images/close.gif +0 -0
  22. data/app/assets/images/custom/logo.png +0 -0
  23. data/app/assets/images/custom/nav_logo.png +0 -0
  24. data/app/assets/images/custom/nav_logo.psd +0 -0
  25. data/app/assets/images/rails.png +0 -0
  26. data/app/assets/javascripts/active_admin.js +5 -0
  27. data/app/assets/javascripts/application.js +97 -0
  28. data/app/assets/javascripts/business_departments.js.coffee +3 -0
  29. data/app/assets/javascripts/company_businesses.js.coffee +3 -0
  30. data/app/assets/javascripts/crm.js.coffee +14 -0
  31. data/app/assets/javascripts/fcbk.js +556 -0
  32. data/app/assets/javascripts/jquery-ui-timepicker-addon.js +1326 -0
  33. data/app/assets/javascripts/jquery.mask.1.3.js +7 -0
  34. data/app/assets/javascripts/jquery.multiselect.filter.xjs +173 -0
  35. data/app/assets/javascripts/jquery.multiselect.xjs +668 -0
  36. data/app/assets/javascripts/system_task_status.js.coffee +3 -0
  37. data/app/assets/javascripts/tests/ajaxes.js.coffee +3 -0
  38. data/app/assets/stylesheets/abilities.css.scss +6 -0
  39. data/app/assets/stylesheets/active_admin.css.scss +65 -0
  40. data/app/assets/stylesheets/application.css +19 -0
  41. data/app/assets/stylesheets/business_departments.css.scss +3 -0
  42. data/app/assets/stylesheets/company_businesses.css.scss +3 -0
  43. data/app/assets/stylesheets/custom.css.scss +322 -0
  44. data/app/assets/stylesheets/customer.scss +7 -0
  45. data/app/assets/stylesheets/fcbk.css +165 -0
  46. data/app/assets/stylesheets/guara.css.scss +159 -0
  47. data/app/assets/stylesheets/jquery-ui.css +567 -0
  48. data/app/assets/stylesheets/jquery_bootstrap.css.scss +92 -0
  49. data/app/assets/stylesheets/jquery_multiselect_filter.xcss +3 -0
  50. data/app/assets/stylesheets/scaffolds.css.scss +42 -0
  51. data/app/assets/stylesheets/users.css.scss +10 -0
  52. data/app/controllers/abilities_controller.rb +37 -0
  53. data/app/controllers/application_controller.rb +12 -0
  54. data/app/controllers/business_activities_controller.rb +87 -0
  55. data/app/controllers/business_departments_controller.rb +90 -0
  56. data/app/controllers/business_segments_controller.rb +88 -0
  57. data/app/controllers/company_businesses_controller.rb +46 -0
  58. data/app/controllers/contacts_controller.rb +105 -0
  59. data/app/controllers/customers_controller.rb +117 -0
  60. data/app/controllers/microposts_controller.rb +31 -0
  61. data/app/controllers/sessions_controller.rb +32 -0
  62. data/app/controllers/static_pages_controller.rb +23 -0
  63. data/app/controllers/system_task_status_controller.rb +84 -0
  64. data/app/controllers/task_feedbacks_controller.rb +6 -0
  65. data/app/controllers/task_types_controller.rb +85 -0
  66. data/app/controllers/tasks_controller.rb +107 -0
  67. data/app/controllers/tests/ajaxes_controller.rb +115 -0
  68. data/app/controllers/tests/lab_ajax_controller.rb +27 -0
  69. data/app/controllers/users_controller.rb +62 -0
  70. data/app/helpers/ability_helper.rb +15 -0
  71. data/app/helpers/application_helper.rb +32 -0
  72. data/app/helpers/business_activities_helper.rb +2 -0
  73. data/app/helpers/business_departments_helper.rb +2 -0
  74. data/app/helpers/business_segments_helper.rb +2 -0
  75. data/app/helpers/company_businesses_helper.rb +2 -0
  76. data/app/helpers/contacts_helper.rb +2 -0
  77. data/app/helpers/customers_helper.rb +23 -0
  78. data/app/helpers/email_helper.rb +8 -0
  79. data/app/helpers/form_ajax_helper.rb +8 -0
  80. data/app/helpers/guara_views_helper.rb +38 -0
  81. data/app/helpers/locale_helper.rb +24 -0
  82. data/app/helpers/menu_helper.rb +55 -0
  83. data/app/helpers/sessions_helper.rb +56 -0
  84. data/app/helpers/tasks_helper.rb +20 -0
  85. data/app/helpers/tests/ajaxes_helper.rb +2 -0
  86. data/app/helpers/user_abilities_helper.rb +12 -0
  87. data/app/helpers/users_helper.rb +29 -0
  88. data/app/mailers/.gitkeep +0 -0
  89. data/app/models/.gitkeep +0 -0
  90. data/app/models/ability.rb +52 -0
  91. data/app/models/address.rb +7 -0
  92. data/app/models/business_activity.rb +5 -0
  93. data/app/models/business_department.rb +3 -0
  94. data/app/models/business_segment.rb +5 -0
  95. data/app/models/city.rb +7 -0
  96. data/app/models/company_business.rb +6 -0
  97. data/app/models/contact.rb +69 -0
  98. data/app/models/customer.rb +117 -0
  99. data/app/models/customer_activity.rb +9 -0
  100. data/app/models/customer_financial.rb +10 -0
  101. data/app/models/customer_has_customers.rb +7 -0
  102. data/app/models/customer_pf.rb +13 -0
  103. data/app/models/customer_pj.rb +71 -0
  104. data/app/models/customer_pj_has_customers_pj.rb +7 -0
  105. data/app/models/customer_product.rb +3 -0
  106. data/app/models/customer_segment.rb +9 -0
  107. data/app/models/district.rb +6 -0
  108. data/app/models/email.rb +7 -0
  109. data/app/models/micropost.rb +10 -0
  110. data/app/models/relationship.rb +9 -0
  111. data/app/models/search.rb +17 -0
  112. data/app/models/state.rb +3 -0
  113. data/app/models/system_ability.rb +16 -0
  114. data/app/models/system_module.rb +16 -0
  115. data/app/models/system_task_resolution.rb +26 -0
  116. data/app/models/system_task_status.rb +19 -0
  117. data/app/models/task.rb +76 -0
  118. data/app/models/task_feedback.rb +11 -0
  119. data/app/models/task_type.rb +12 -0
  120. data/app/models/tests.rb +5 -0
  121. data/app/models/tests/ajax.rb +3 -0
  122. data/app/models/user.rb +126 -0
  123. data/app/models/user_ability.rb +23 -0
  124. data/app/models/user_group.rb +9 -0
  125. data/app/models/user_type.rb +9 -0
  126. data/app/models/users_has_groups.rb +9 -0
  127. data/app/validators/customer_cnpj_validator.rb +14 -0
  128. data/app/validators/email_validator.rb +21 -0
  129. data/app/views/abilities/index.html.erb +25 -0
  130. data/app/views/active_extend/_one_to_many_inputs.html.erb +7 -0
  131. data/app/views/active_extend/_one_to_many_inputs_fields.html.erb +10 -0
  132. data/app/views/active_extend/_one_to_many_inputs_with_glyph.html.erb +21 -0
  133. data/app/views/business_activities/_business_activity.html.erb +0 -0
  134. data/app/views/business_activities/_form.html.erb +25 -0
  135. data/app/views/business_activities/edit.html.erb +6 -0
  136. data/app/views/business_activities/index.html.erb +33 -0
  137. data/app/views/business_activities/new.html.erb +5 -0
  138. data/app/views/business_activities/show.html.erb +15 -0
  139. data/app/views/business_departments/_form.html.erb +10 -0
  140. data/app/views/business_departments/edit.html.erb +6 -0
  141. data/app/views/business_departments/index.html.erb +33 -0
  142. data/app/views/business_departments/new.html.erb +5 -0
  143. data/app/views/business_departments/show.html.erb +15 -0
  144. data/app/views/business_segments/_business_segment.html.erb +8 -0
  145. data/app/views/business_segments/_form.html.erb +25 -0
  146. data/app/views/business_segments/edit.html.erb +6 -0
  147. data/app/views/business_segments/index.html.erb +33 -0
  148. data/app/views/business_segments/new.html.erb +5 -0
  149. data/app/views/business_segments/show.html.erb +15 -0
  150. data/app/views/company_businesses/_form.html.erb +10 -0
  151. data/app/views/company_businesses/edit.html.erb +6 -0
  152. data/app/views/company_businesses/index.html.erb +25 -0
  153. data/app/views/company_businesses/new.html.erb +5 -0
  154. data/app/views/company_businesses/show.html.erb +15 -0
  155. data/app/views/contacts/_form.html.erb +53 -0
  156. data/app/views/contacts/_header.html.erb +3 -0
  157. data/app/views/contacts/_list.html.erb +46 -0
  158. data/app/views/contacts/_side_panel.html.erb +61 -0
  159. data/app/views/contacts/edit.html.erb +6 -0
  160. data/app/views/contacts/index.html.erb +72 -0
  161. data/app/views/contacts/new.html.erb +5 -0
  162. data/app/views/contacts/show.html.erb +52 -0
  163. data/app/views/customers/_businesses_done.html.erb +18 -0
  164. data/app/views/customers/_customer_segment.html.erb +9 -0
  165. data/app/views/customers/_form.html.erb +177 -0
  166. data/app/views/customers/_form_search.html.erb +119 -0
  167. data/app/views/customers/_modules.html.erb +6 -0
  168. data/app/views/customers/_navbar.html.erb +23 -0
  169. data/app/views/customers/_segment.html.erb +10 -0
  170. data/app/views/customers/edit.html.erb +8 -0
  171. data/app/views/customers/index.html.erb +46 -0
  172. data/app/views/customers/new.pj.html.erb +4 -0
  173. data/app/views/customers/show.pj.html.erb +200 -0
  174. data/app/views/devise/confirmations/new.html.erb +12 -0
  175. data/app/views/devise/mailer/confirmation_instructions.html.erb +5 -0
  176. data/app/views/devise/mailer/reset_password_instructions.html.erb +8 -0
  177. data/app/views/devise/mailer/unlock_instructions.html.erb +7 -0
  178. data/app/views/devise/passwords/edit.html.erb +16 -0
  179. data/app/views/devise/passwords/new.html.erb +12 -0
  180. data/app/views/devise/registrations/edit.html.erb +25 -0
  181. data/app/views/devise/registrations/new.html.erb +18 -0
  182. data/app/views/devise/sessions/new.html.erb +24 -0
  183. data/app/views/devise/shared/_links.erb +25 -0
  184. data/app/views/devise/unlocks/new.html.erb +12 -0
  185. data/app/views/emails/_email_fields.html.erb +1 -0
  186. data/app/views/layouts/_active_admin_footer.html.erb +4 -0
  187. data/app/views/layouts/_active_admin_header.html.erb +5 -0
  188. data/app/views/layouts/_footer.html.erb +12 -0
  189. data/app/views/layouts/_header.html.erb +51 -0
  190. data/app/views/layouts/_shim.html.erb +3 -0
  191. data/app/views/layouts/active_admin.html.arb +1 -0
  192. data/app/views/layouts/application.html.erb +24 -0
  193. data/app/views/microposts/_micropost.html.erb +11 -0
  194. data/app/views/sessions/new.html.erb +18 -0
  195. data/app/views/shared/_calendar.html.erb +17 -0
  196. data/app/views/shared/_error_messages.html.erb +13 -0
  197. data/app/views/shared/_feed.html.erb +10 -0
  198. data/app/views/shared/_feed_item.html.erb +15 -0
  199. data/app/views/shared/_micropost_form.html.erb +7 -0
  200. data/app/views/shared/_multi_selection.html.erb +16 -0
  201. data/app/views/shared/_multi_selection.html_checkbox.erb +11 -0
  202. data/app/views/shared/_multi_selection_autocomple.html.erb +5 -0
  203. data/app/views/shared/_notifies.html.erb +17 -0
  204. data/app/views/shared/_user_info.html.erb +14 -0
  205. data/app/views/static_pages/about.html.erb +5 -0
  206. data/app/views/static_pages/contact.html.erb +5 -0
  207. data/app/views/static_pages/help.html.erb +5 -0
  208. data/app/views/static_pages/home.html.erb +37 -0
  209. data/app/views/static_pages/news.html.erb +2 -0
  210. data/app/views/system_task_status/_form.html.erb +9 -0
  211. data/app/views/system_task_status/edit.html.erb +6 -0
  212. data/app/views/system_task_status/index.html.erb +23 -0
  213. data/app/views/system_task_status/new.html.erb +5 -0
  214. data/app/views/system_task_status/show.html.erb +10 -0
  215. data/app/views/task_feedbacks/_list.html.erb +51 -0
  216. data/app/views/task_feedbacks/_side_form.html.erb +56 -0
  217. data/app/views/task_feedbacks/_side_panel.html.erb +64 -0
  218. data/app/views/task_types/_form.html.erb +10 -0
  219. data/app/views/task_types/edit.html.erb +6 -0
  220. data/app/views/task_types/index.html.erb +23 -0
  221. data/app/views/task_types/new.html.erb +5 -0
  222. data/app/views/task_types/show.html.erb +10 -0
  223. data/app/views/tasks/_form.html.erb +52 -0
  224. data/app/views/tasks/_header.html.erb +3 -0
  225. data/app/views/tasks/_list.html.erb +50 -0
  226. data/app/views/tasks/_side_panel.html.erb +64 -0
  227. data/app/views/tasks/create.js.erb +1 -0
  228. data/app/views/tasks/edit.html.erb +6 -0
  229. data/app/views/tasks/index.html.erb +61 -0
  230. data/app/views/tasks/new.html.erb +5 -0
  231. data/app/views/tasks/show.html.erb +46 -0
  232. data/app/views/tests/ajaxes/_form.html.erb +10 -0
  233. data/app/views/tests/ajaxes/_list.html.erb +6 -0
  234. data/app/views/tests/ajaxes/add_and_update.html.erb +22 -0
  235. data/app/views/tests/ajaxes/all.js.erb +2 -0
  236. data/app/views/tests/ajaxes/edit.html.erb +6 -0
  237. data/app/views/tests/ajaxes/index.html.erb +25 -0
  238. data/app/views/tests/ajaxes/new.html.erb +5 -0
  239. data/app/views/tests/ajaxes/show.html.erb +15 -0
  240. data/app/views/tests/js.js +51 -0
  241. data/app/views/tests/lab_ajax/multiselection.html.erb +84 -0
  242. data/app/views/users/_user.html.erb +8 -0
  243. data/app/views/users/edit.html.erb +27 -0
  244. data/app/views/users/index.html.erb +9 -0
  245. data/app/views/users/new.html.erb +24 -0
  246. data/app/views/users/show.html.erb +26 -0
  247. data/bundle +0 -0
  248. data/config.ru +4 -0
  249. data/config/application.rb +73 -0
  250. data/config/boot.rb +6 -0
  251. data/config/database.yml +38 -0
  252. data/config/environment.rb +31 -0
  253. data/config/environments/development.rb +42 -0
  254. data/config/environments/production.rb +68 -0
  255. data/config/environments/test.rb +39 -0
  256. data/config/guara/menus.rb +34 -0
  257. data/config/initializers/active_admin.rb +210 -0
  258. data/config/initializers/backtrace_silencers.rb +7 -0
  259. data/config/initializers/cmgb_rules.rb +2 -0
  260. data/config/initializers/devise.rb +216 -0
  261. data/config/initializers/formtastic.rb +77 -0
  262. data/config/initializers/inflections.rb +19 -0
  263. data/config/initializers/json_paches_utf8.rb +13 -0
  264. data/config/initializers/kaminari.rb +21 -0
  265. data/config/initializers/locale.rb +7 -0
  266. data/config/initializers/meta_search.rb +10 -0
  267. data/config/initializers/mime_types.rb +5 -0
  268. data/config/initializers/secret_token.rb +7 -0
  269. data/config/initializers/session_store.rb +8 -0
  270. data/config/initializers/string.rb +9 -0
  271. data/config/initializers/wrap_parameters.rb +14 -0
  272. data/config/locales/devise.en.yml +57 -0
  273. data/config/locales/devise.pt-BR.yml +62 -0
  274. data/config/locales/pt-BR.yml +404 -0
  275. data/config/routes.rb +129 -0
  276. data/db/migrate/20120610142404_create_users.rb +10 -0
  277. data/db/migrate/20120610183820_add_index_to_users_email.rb +5 -0
  278. data/db/migrate/20120610185217_add_password_digest_to_users.rb +5 -0
  279. data/db/migrate/20120612000411_add_remember_token_to_users.rb +6 -0
  280. data/db/migrate/20120616162515_add_admin_to_users.rb +5 -0
  281. data/db/migrate/20120616215835_create_microposts.rb +11 -0
  282. data/db/migrate/20120617224530_create_relationships.rb +14 -0
  283. data/db/migrate/20120621095918_create_customers.rb +36 -0
  284. data/db/migrate/20120621100528_create_customer_pfs.rb +14 -0
  285. data/db/migrate/20120621100534_create_customer_pjs.rb +13 -0
  286. data/db/migrate/20120621100557_create_emails.rb +13 -0
  287. data/db/migrate/20120621100618_create_tasks.rb +26 -0
  288. data/db/migrate/20120621100639_create_customer_products.rb +14 -0
  289. data/db/migrate/20120621100705_create_districts.rb +11 -0
  290. data/db/migrate/20120621100720_create_cities.rb +11 -0
  291. data/db/migrate/20120624192444_create_business_segments.rb +10 -0
  292. data/db/migrate/20120624224245_create_business_activities.rb +13 -0
  293. data/db/migrate/20120628092744_create_customer_activities.rb +9 -0
  294. data/db/migrate/20120628092754_create_customer_segments.rb +9 -0
  295. data/db/migrate/20120703102859_create_states.rb +10 -0
  296. data/db/migrate/20120705121011_create_contacts.rb +18 -0
  297. data/db/migrate/20120711233943_add_devise_to_users.rb +56 -0
  298. data/db/migrate/20120723102847_create_user_abilities.rb +10 -0
  299. data/db/migrate/20120723104500_create_system_modules.rb +9 -0
  300. data/db/migrate/20120723104639_create_system_abilities.rb +9 -0
  301. data/db/migrate/20120728181903_create_user_groups.rb +10 -0
  302. data/db/migrate/20120729112600_create_users_has_groups.rb +14 -0
  303. data/db/migrate/20120729121922_add_groups_to_users.rb +6 -0
  304. data/db/migrate/20120910002835_create_system_task_status.rb +7 -0
  305. data/db/migrate/20120910010153_create_system_task_resolutions.rb +7 -0
  306. data/db/migrate/20120911021535_create_task_types.rb +10 -0
  307. data/db/migrate/20120911070836_create_task_feedbacks.rb +14 -0
  308. data/db/migrate/20120924022719_create_tests_ajaxes.rb +10 -0
  309. data/db/migrate/20121007131035_create_business_departments.rb +10 -0
  310. data/db/migrate/20121013120849_add_notes_and_other_contacts_to_customer.rb +5 -0
  311. data/db/migrate/20121014201255_create_company_businesses.rb +10 -0
  312. data/db/migrate/20121014202449_add_company_business_to_task_type.rb +6 -0
  313. data/db/migrate/20121014212430_add_primary_company_business_to_user.rb +5 -0
  314. data/db/migrate/20121015101844_add_parent_id_to_system_task_resolution.rb +5 -0
  315. data/db/migrate/20121026231241_create_customer_has_customers.rb +10 -0
  316. data/db/migrate/20121026232755_create_customer_pj_has_customers_pjs.rb +10 -0
  317. data/db/migrate/20121029094047_create_admin_notes.rb +17 -0
  318. data/db/migrate/20121029094048_move_admin_notes_to_comments.rb +25 -0
  319. data/db/migrate/20121103183646_add_enabled_to_cities.rb +5 -0
  320. data/db/migrate/20121104135014_create_customer_financials.rb +17 -0
  321. data/db/migrate/20121104141751_create_addresses.rb +19 -0
  322. data/db/migrate/20121205150619_add_type_id_to_users.rb +5 -0
  323. data/db/schema.rb~ +378 -0
  324. data/db/seeds.rb +99 -0
  325. data/gemfiles/Gemfile.rails.3.2.x +82 -0
  326. data/guara.gemspec +31 -0
  327. data/lib/active_extend/README.md +19 -0
  328. data/lib/active_extend/active_disablable.rb +59 -0
  329. data/lib/active_extend/string_helper.rb +9 -0
  330. data/lib/active_migration.rb +4 -0
  331. data/lib/active_migration/converters/rtf_to_html.rb +123 -0
  332. data/lib/active_migration/dictionary.rb +19 -0
  333. data/lib/active_migration/migration.rb +211 -0
  334. data/lib/active_migration/schemas.rb +143 -0
  335. data/lib/active_migration/spelling_fix.rb +20 -0
  336. data/lib/active_migration/transformer/grouped_field_fixed_spelling.rb +110 -0
  337. data/lib/assets/.gitkeep +0 -0
  338. data/lib/cmgb_rules/app/models/task.rb +19 -0
  339. data/lib/guara/version.rb +3 -0
  340. data/lib/spec/asserts/sheet1.xls +0 -0
  341. data/lib/spec/lib/active_migration_schemas_spec.rb +40 -0
  342. data/lib/spec/lib/active_migration_spec.rb +78 -0
  343. data/lib/spec/spec_helper.rb +121 -0
  344. data/lib/spec/support/active_migration_helper.rb +109 -0
  345. data/lib/spec/support/utilities.rb +7 -0
  346. data/lib/tasks/.gitkeep +0 -0
  347. data/lib/tasks/add_privilegies.rake +6 -0
  348. data/lib/tasks/external_migration.rake +22 -0
  349. data/lib/tasks/sample_data.rake +77 -0
  350. data/lib/tasks/smaple_data_test.rake +13 -0
  351. data/lib/templates/erb/scaffold/_form.html.erb +11 -0
  352. data/public/404.html +26 -0
  353. data/public/422.html +26 -0
  354. data/public/500.html +25 -0
  355. data/public/data.txt +1 -0
  356. data/public/favicon.ico +0 -0
  357. data/public/javascripts/autocomplete-rails.js +16 -0
  358. data/public/robots.txt +5 -0
  359. data/script/create_db +5 -0
  360. data/script/rails +6 -0
  361. data/script/recreate_db +5 -0
  362. data/script/recreate_db.bat +9 -0
  363. data/script/recreate_db_test +5 -0
  364. data/script/recreate_development_db +10 -0
  365. data/spec/controllers/business_activities_controller_spec.disabled +167 -0
  366. data/spec/controllers/business_departments_controller_spec.disabled +164 -0
  367. data/spec/controllers/business_segments_controller_spec.disabled +165 -0
  368. data/spec/controllers/company_businesses_controller_spec.disabled +164 -0
  369. data/spec/controllers/system_task_status_controller_spec.disabled +164 -0
  370. data/spec/controllers/system_task_status_spec.disabled +11 -0
  371. data/spec/controllers/task_types_controller_spec.disabled +164 -0
  372. data/spec/controllers/tasks_controller_spec.disabled +23 -0
  373. data/spec/controllers/tests/ajaxes_controller_spec.disabled +164 -0
  374. data/spec/factories.rb +101 -0
  375. data/spec/factories/addresses.rb +13 -0
  376. data/spec/factories/business_departments.rb +8 -0
  377. data/spec/factories/company_businesses.rb +8 -0
  378. data/spec/factories/customer_financials.rb +11 -0
  379. data/spec/factories/customer_has_customers.rb +8 -0
  380. data/spec/factories/customer_pj_has_customers_pjs.rb +8 -0
  381. data/spec/factories/system_task_resolutions.rb +7 -0
  382. data/spec/factories/system_task_status.rb +7 -0
  383. data/spec/factories/task.rb +17 -0
  384. data/spec/factories/task_feedbacks.rb +19 -0
  385. data/spec/factories/task_types.rb +8 -0
  386. data/spec/factories/tests_ajaxes.rb +8 -0
  387. data/spec/helpers/business_activities_helper_spec.rb +15 -0
  388. data/spec/helpers/business_departments_helper_spec.rb +15 -0
  389. data/spec/helpers/business_segments_helper_spec.rb +15 -0
  390. data/spec/helpers/company_businesses_helper_spec.rb +15 -0
  391. data/spec/helpers/customers/contacts_helper_spec.rb +15 -0
  392. data/spec/helpers/menu_helper_spec.rb +25 -0
  393. data/spec/helpers/tests/ajaxes_helper_spec.rb +15 -0
  394. data/spec/helpers/users_helpers_spec.rb +32 -0
  395. data/spec/models/address_spec.rb +5 -0
  396. data/spec/models/business_activity_spec.rb +5 -0
  397. data/spec/models/business_department_spec.rb +5 -0
  398. data/spec/models/business_segment_spec.rb +5 -0
  399. data/spec/models/city_spec.rb +5 -0
  400. data/spec/models/company_business_spec.rb +19 -0
  401. data/spec/models/contact_spec.rb +60 -0
  402. data/spec/models/customer_activity_spec.rb +5 -0
  403. data/spec/models/customer_financial_spec.rb +48 -0
  404. data/spec/models/customer_has_customers_spec.rb +18 -0
  405. data/spec/models/customer_pf_spec.rb +24 -0
  406. data/spec/models/customer_pj_has_customers_pj_spec.rb +34 -0
  407. data/spec/models/customer_pj_spec.rb +72 -0
  408. data/spec/models/customer_product_spec.rb +5 -0
  409. data/spec/models/customer_segment_spec.rb +5 -0
  410. data/spec/models/customer_spec.rb +135 -0
  411. data/spec/models/district_spec.rb +5 -0
  412. data/spec/models/emails_spec.rb +24 -0
  413. data/spec/models/micropost_spec.rb +49 -0
  414. data/spec/models/relationship_spec.rb +38 -0
  415. data/spec/models/state_spec.rb +5 -0
  416. data/spec/models/system_ability_spec.rb +5 -0
  417. data/spec/models/system_module_spec.rb +5 -0
  418. data/spec/models/system_task_resolution_spec.rb +17 -0
  419. data/spec/models/system_task_status_spec.rb +17 -0
  420. data/spec/models/task_feedback_spec.rb +46 -0
  421. data/spec/models/task_spec.rb +176 -0
  422. data/spec/models/task_type_spec.rb +27 -0
  423. data/spec/models/tests/ajax_spec.rb +5 -0
  424. data/spec/models/user_ability_spec.rb +35 -0
  425. data/spec/models/user_group_spec.rb +26 -0
  426. data/spec/models/user_spec.rb +274 -0
  427. data/spec/models/users_has_groups_spec.rb +29 -0
  428. data/spec/requests/authentication_pages_spec.rb +157 -0
  429. data/spec/requests/business_activities_spec.rb +7 -0
  430. data/spec/requests/business_departments_spec.rb +7 -0
  431. data/spec/requests/business_segments_spec.rb +7 -0
  432. data/spec/requests/company_businesses_spec.rb +11 -0
  433. data/spec/requests/customer_contacts_pages_spec.rb +96 -0
  434. data/spec/requests/customer_pages_spec.rb +60 -0
  435. data/spec/requests/micropost_pages_spec.rb +58 -0
  436. data/spec/requests/static_pages_spec.rb +57 -0
  437. data/spec/requests/task_pages_spec.rb +124 -0
  438. data/spec/requests/tests/tests_ajaxes_spec.rb +11 -0
  439. data/spec/requests/user_abilities_pages_spec.rb +73 -0
  440. data/spec/requests/user_pages_spec.rb +116 -0
  441. data/spec/routing/business_activities_routing_spec.rb +35 -0
  442. data/spec/routing/business_departments_routing_spec.rb +35 -0
  443. data/spec/routing/business_segments_routing_spec.rb +35 -0
  444. data/spec/routing/company_businesses_routing_spec.rb +35 -0
  445. data/spec/routing/system_task_status_routing_spec.rb +35 -0
  446. data/spec/routing/task_types_routing_spec.rb +35 -0
  447. data/spec/routing/tests/ajaxes_routing_spec.rb +35 -0
  448. data/spec/spec_helper.rb +123 -0
  449. data/spec/support/custom_matchers.rb +9 -0
  450. data/spec/support/utilities.rb +120 -0
  451. data/spec/views/business_departments/edit.html.erb_spec.rb +20 -0
  452. data/spec/views/business_departments/index.html.erb_spec.disabled +23 -0
  453. data/spec/views/business_departments/new.html.erb_spec.rb +20 -0
  454. data/spec/views/business_departments/show.html.erb_spec.rb +17 -0
  455. data/spec/views/company_businesses/edit.html.erb_spec.rb +20 -0
  456. data/spec/views/company_businesses/index.html.erb_spec.rb +23 -0
  457. data/spec/views/company_businesses/new.html.erb_spec.rb +20 -0
  458. data/spec/views/company_businesses/show.html.erb_spec.rb +17 -0
  459. data/spec/views/task_types/edit.html.erb_spec.rb +18 -0
  460. data/spec/views/task_types/index.html.erb_spec.rb +20 -0
  461. data/spec/views/task_types/new.html.erb_spec.rb +18 -0
  462. data/spec/views/task_types/show.html.erb_spec.rb +15 -0
  463. data/test/fixtures/.gitkeep +0 -0
  464. data/test/functional/.gitkeep +0 -0
  465. data/test/integration/.gitkeep +0 -0
  466. data/test/performance/browsing_test.rb +12 -0
  467. data/test/test_helper.rb +13 -0
  468. data/test/unit/.gitkeep +0 -0
  469. data/vendor/assets/javascripts/.gitkeep +0 -0
  470. data/vendor/assets/stylesheets/.gitkeep +0 -0
  471. data/vendor/assets/stylesheets/active_admin/_base.css.scss +45 -0
  472. data/vendor/assets/stylesheets/active_admin/_forms.css.scss +270 -0
  473. data/vendor/assets/stylesheets/active_admin/_header.css.scss +137 -0
  474. data/vendor/assets/stylesheets/active_admin/_mixins.css.scss +1 -0
  475. data/vendor/assets/stylesheets/active_admin/_typography.css.scss +100 -0
  476. data/vendor/assets/stylesheets/active_admin/components/_batch_actions.css.scss +11 -0
  477. data/vendor/assets/stylesheets/active_admin/components/_blank_slates.scss +31 -0
  478. data/vendor/assets/stylesheets/active_admin/components/_breadcrumbs.scss +20 -0
  479. data/vendor/assets/stylesheets/active_admin/components/_buttons.scss +11 -0
  480. data/vendor/assets/stylesheets/active_admin/components/_columns.scss +3 -0
  481. data/vendor/assets/stylesheets/active_admin/components/_comments.css.scss +40 -0
  482. data/vendor/assets/stylesheets/active_admin/components/_date_picker.css.scss +123 -0
  483. data/vendor/assets/stylesheets/active_admin/components/_dropdown_menu.scss +151 -0
  484. data/vendor/assets/stylesheets/active_admin/components/_flash_messages.css.scss +39 -0
  485. data/vendor/assets/stylesheets/active_admin/components/_grid.scss +9 -0
  486. data/vendor/assets/stylesheets/active_admin/components/_links.scss +5 -0
  487. data/vendor/assets/stylesheets/active_admin/components/_pagination.scss +34 -0
  488. data/vendor/assets/stylesheets/active_admin/components/_panels.scss +6 -0
  489. data/vendor/assets/stylesheets/active_admin/components/_popovers.css.scss +123 -0
  490. data/vendor/assets/stylesheets/active_admin/components/_scopes.scss +10 -0
  491. data/vendor/assets/stylesheets/active_admin/components/_status_tags.scss +12 -0
  492. data/vendor/assets/stylesheets/active_admin/components/_table_tools.css.scss +94 -0
  493. data/vendor/assets/stylesheets/active_admin/components/_tables.css.scss +108 -0
  494. data/vendor/assets/stylesheets/active_admin/mixins/_all.css.scss +11 -0
  495. data/vendor/assets/stylesheets/active_admin/mixins/_buttons.css.scss +66 -0
  496. data/vendor/assets/stylesheets/active_admin/mixins/_gradients.css.scss +37 -0
  497. data/vendor/assets/stylesheets/active_admin/mixins/_icons.css.scss +24 -0
  498. data/vendor/assets/stylesheets/active_admin/mixins/_reset.css.scss +165 -0
  499. data/vendor/assets/stylesheets/active_admin/mixins/_rounded.css.scss +43 -0
  500. data/vendor/assets/stylesheets/active_admin/mixins/_sections.css.scss +36 -0
  501. data/vendor/assets/stylesheets/active_admin/mixins/_shadows.css.scss +22 -0
  502. data/vendor/assets/stylesheets/active_admin/mixins/_typography.scss +3 -0
  503. data/vendor/assets/stylesheets/active_admin/mixins/_utilities.scss +26 -0
  504. data/vendor/assets/stylesheets/active_admin/mixins/_variables.css.scss +24 -0
  505. data/vendor/assets/stylesheets/active_admin/pages/_dashboard.scss +5 -0
  506. data/vendor/assets/stylesheets/active_admin/pages/_logged_out.scss +44 -0
  507. data/vendor/assets/stylesheets/active_admin/print.css.scss +290 -0
  508. data/vendor/assets/stylesheets/active_admin/structure/_footer.scss +14 -0
  509. data/vendor/assets/stylesheets/active_admin/structure/_main_structure.scss +26 -0
  510. data/vendor/assets/stylesheets/active_admin/structure/_title_bar.scss +44 -0
  511. data/vendor/plugins/.gitkeep +0 -0
  512. metadata +731 -0
@@ -0,0 +1,7 @@
1
+ /*
2
+ Masked Input plugin for jQuery
3
+ Copyright (c) 2007-2011 Josh Bush (digitalbush.com)
4
+ Licensed under the MIT license (http://digitalbush.com/projects/masked-input-plugin/#license)
5
+ Version: 1.3
6
+ */
7
+ (function(a){var b=(a.browser.msie?"paste":"input")+".mask",c=window.orientation!=undefined;a.mask={definitions:{9:"[0-9]",a:"[A-Za-z]","*":"[A-Za-z0-9]"},dataName:"rawMaskFn"},a.fn.extend({caret:function(a,b){if(this.length!=0){if(typeof a=="number"){b=typeof b=="number"?b:a;return this.each(function(){if(this.setSelectionRange)this.setSelectionRange(a,b);else if(this.createTextRange){var c=this.createTextRange();c.collapse(!0),c.moveEnd("character",b),c.moveStart("character",a),c.select()}})}if(this[0].setSelectionRange)a=this[0].selectionStart,b=this[0].selectionEnd;else if(document.selection&&document.selection.createRange){var c=document.selection.createRange();a=0-c.duplicate().moveStart("character",-1e5),b=a+c.text.length}return{begin:a,end:b}}},unmask:function(){return this.trigger("unmask")},mask:function(d,e){if(!d&&this.length>0){var f=a(this[0]);return f.data(a.mask.dataName)()}e=a.extend({placeholder:"_",completed:null},e);var g=a.mask.definitions,h=[],i=d.length,j=null,k=d.length;a.each(d.split(""),function(a,b){b=="?"?(k--,i=a):g[b]?(h.push(new RegExp(g[b])),j==null&&(j=h.length-1)):h.push(null)});return this.trigger("unmask").each(function(){function v(a){var b=f.val(),c=-1;for(var d=0,g=0;d<k;d++)if(h[d]){l[d]=e.placeholder;while(g++<b.length){var m=b.charAt(g-1);if(h[d].test(m)){l[d]=m,c=d;break}}if(g>b.length)break}else l[d]==b.charAt(g)&&d!=i&&(g++,c=d);if(!a&&c+1<i)f.val(""),t(0,k);else if(a||c+1>=i)u(),a||f.val(f.val().substring(0,c+1));return i?d:j}function u(){return f.val(l.join("")).val()}function t(a,b){for(var c=a;c<b&&c<k;c++)h[c]&&(l[c]=e.placeholder)}function s(a){var b=a.which,c=f.caret();if(a.ctrlKey||a.altKey||a.metaKey||b<32)return!0;if(b){c.end-c.begin!=0&&(t(c.begin,c.end),p(c.begin,c.end-1));var d=n(c.begin-1);if(d<k){var g=String.fromCharCode(b);if(h[d].test(g)){q(d),l[d]=g,u();var i=n(d);f.caret(i),e.completed&&i>=k&&e.completed.call(f)}}return!1}}function r(a){var b=a.which;if(b==8||b==46||c&&b==127){var d=f.caret(),e=d.begin,g=d.end;g-e==0&&(e=b!=46?o(e):g=n(e-1),g=b==46?n(g):g),t(e,g),p(e,g-1);return!1}if(b==27){f.val(m),f.caret(0,v());return!1}}function q(a){for(var b=a,c=e.placeholder;b<k;b++)if(h[b]){var d=n(b),f=l[b];l[b]=c;if(d<k&&h[d].test(f))c=f;else break}}function p(a,b){if(!(a<0)){for(var c=a,d=n(b);c<k;c++)if(h[c]){if(d<k&&h[c].test(l[d]))l[c]=l[d],l[d]=e.placeholder;else break;d=n(d)}u(),f.caret(Math.max(j,a))}}function o(a){while(--a>=0&&!h[a]);return a}function n(a){while(++a<=k&&!h[a]);return a}var f=a(this),l=a.map(d.split(""),function(a,b){if(a!="?")return g[a]?e.placeholder:a}),m=f.val();f.data(a.mask.dataName,function(){return a.map(l,function(a,b){return h[b]&&a!=e.placeholder?a:null}).join("")}),f.attr("readonly")||f.one("unmask",function(){f.unbind(".mask").removeData(a.mask.dataName)}).bind("focus.mask",function(){m=f.val();var b=v();u();var c=function(){b==d.length?f.caret(0,b):f.caret(b)};(a.browser.msie?c:function(){setTimeout(c,0)})()}).bind("blur.mask",function(){v(),f.val()!=m&&f.change()}).bind("keydown.mask",r).bind("keypress.mask",s).bind(b,function(){setTimeout(function(){f.caret(v(!0))},0)}),v()})}})})(jQuery)
@@ -0,0 +1,173 @@
1
+ /* jshint forin:true, noarg:true, noempty:true, eqeqeq:true, boss:true, undef:true, curly:true, browser:true, jquery:true */
2
+ /*
3
+ * jQuery MultiSelect UI Widget Filtering Plugin 1.4
4
+ * Copyright (c) 2011 Eric Hynds
5
+ *
6
+ * http://www.erichynds.com/jquery/jquery-ui-multiselect-widget/
7
+ *
8
+ * Depends:
9
+ * - jQuery UI MultiSelect widget
10
+ *
11
+ * Dual licensed under the MIT and GPL licenses:
12
+ * http://www.opensource.org/licenses/mit-license.php
13
+ * http://www.gnu.org/licenses/gpl.html
14
+ *
15
+ */
16
+ (function($){
17
+ var rEscape = /[\-\[\]{}()*+?.,\\\^$|#\s]/g;
18
+
19
+ $.widget("ech.multiselectfilter", {
20
+
21
+ options: {
22
+ label: "Filter:",
23
+ width: null, /* override default width set in css file (px). null will inherit */
24
+ placeholder: "Enter keywords",
25
+ autoReset: false
26
+ },
27
+
28
+ _create: function(){
29
+ var self = this,
30
+ opts = this.options,
31
+ instance = (this.instance = $(this.element).data("multiselect")),
32
+
33
+ // store header; add filter class so the close/check all/uncheck all links can be positioned correctly
34
+ header = (this.header = instance.menu.find(".ui-multiselect-header").addClass("ui-multiselect-hasfilter")),
35
+
36
+ // wrapper elem
37
+ wrapper = (this.wrapper = $('<div class="ui-multiselect-filter">'+(opts.label.length ? opts.label : '')+'<input placeholder="'+opts.placeholder+'" type="search"' + (/\d/.test(opts.width) ? 'style="width:'+opts.width+'px"' : '') + ' /></div>').prependTo( this.header ));
38
+
39
+ // reference to the actual inputs
40
+ this.inputs = instance.menu.find('input[type="checkbox"], input[type="radio"]');
41
+
42
+ // build the input box
43
+ this.input = wrapper
44
+ .find("input")
45
+ .bind({
46
+ keydown: function( e ){
47
+ // prevent the enter key from submitting the form / closing the widget
48
+ if( e.which === 13 ){
49
+ e.preventDefault();
50
+ }
51
+ },
52
+ keyup: $.proxy(self._handler, self),
53
+ click: $.proxy(self._handler, self)
54
+ });
55
+
56
+ // cache input values for searching
57
+ this.updateCache();
58
+
59
+ // rewrite internal _toggleChecked fn so that when checkAll/uncheckAll is fired,
60
+ // only the currently filtered elements are checked
61
+ instance._toggleChecked = function(flag, group){
62
+ var $inputs = (group && group.length) ?
63
+ group :
64
+ this.labels.find('input'),
65
+
66
+ _self = this,
67
+
68
+ // do not include hidden elems if the menu isn't open.
69
+ selector = self.instance._isOpen ?
70
+ ":disabled, :hidden" :
71
+ ":disabled";
72
+
73
+ $inputs = $inputs.not( selector ).each(this._toggleState('checked', flag));
74
+
75
+ // update text
76
+ this.update();
77
+
78
+ // figure out which option tags need to be selected
79
+ var values = $inputs.map(function(){
80
+ return this.value;
81
+ }).get();
82
+
83
+ // select option tags
84
+ this.element
85
+ .find('option')
86
+ .filter(function(){
87
+ if( !this.disabled && $.inArray(this.value, values) > -1 ){
88
+ _self._toggleState('selected', flag).call( this );
89
+ }
90
+ });
91
+ };
92
+
93
+ // rebuild cache when multiselect is updated
94
+ var doc = $(document).bind("multiselectrefresh", function(){
95
+ self.updateCache();
96
+ self._handler();
97
+ });
98
+
99
+ // automatically reset the widget on close?
100
+ if(this.options.autoReset) {
101
+ doc.bind("multiselectclose", $.proxy(this._reset, this));
102
+ }
103
+ },
104
+
105
+ // thx for the logic here ben alman
106
+ _handler: function( e ){
107
+ var term = $.trim( this.input[0].value.toLowerCase() ),
108
+
109
+ // speed up lookups
110
+ rows = this.rows, inputs = this.inputs, cache = this.cache;
111
+
112
+ if( !term ){
113
+ rows.show();
114
+ } else {
115
+ rows.hide();
116
+
117
+ var regex = new RegExp(term.replace(rEscape, "\\$&"), 'gi');
118
+
119
+ this._trigger( "filter", e, $.map(cache, function(v, i){
120
+ if( v.search(regex) !== -1 ){
121
+ rows.eq(i).show();
122
+ return inputs.get(i);
123
+ }
124
+
125
+ return null;
126
+ }));
127
+ }
128
+
129
+ // show/hide optgroups
130
+ this.instance.menu.find(".ui-multiselect-optgroup-label").each(function(){
131
+ var $this = $(this);
132
+ var isVisible = $this.nextUntil('.ui-multiselect-optgroup-label').filter(function(){
133
+ return $.css(this, "display") !== 'none';
134
+ }).length;
135
+
136
+ $this[ isVisible ? 'show' : 'hide' ]();
137
+ });
138
+ },
139
+
140
+ _reset: function() {
141
+ this.input.val('').trigger('keyup');
142
+ },
143
+
144
+ updateCache: function(){
145
+ // each list item
146
+ this.rows = this.instance.menu.find(".ui-multiselect-checkboxes li:not(.ui-multiselect-optgroup-label)");
147
+
148
+ // cache
149
+ this.cache = this.element.children().map(function(){
150
+ var self = $(this);
151
+
152
+ // account for optgroups
153
+ if( this.tagName.toLowerCase() === "optgroup" ){
154
+ self = self.children();
155
+ }
156
+
157
+ return self.map(function(){
158
+ return this.innerHTML.toLowerCase();
159
+ }).get();
160
+ }).get();
161
+ },
162
+
163
+ widget: function(){
164
+ return this.wrapper;
165
+ },
166
+
167
+ destroy: function(){
168
+ $.Widget.prototype.destroy.call( this );
169
+ this.input.val('').trigger("keyup");
170
+ this.wrapper.remove();
171
+ }
172
+ });
173
+ })(jQuery);
@@ -0,0 +1,668 @@
1
+ /* jshint forin:true, noarg:true, noempty:true, eqeqeq:true, boss:true, undef:true, curly:true, browser:true, jquery:true */
2
+ /*
3
+ * jQuery MultiSelect UI Widget 1.12
4
+ * Copyright (c) 2011 Eric Hynds
5
+ *
6
+ * http://www.erichynds.com/jquery/jquery-ui-multiselect-widget/
7
+ *
8
+ * Depends:
9
+ * - jQuery 1.4.2+
10
+ * - jQuery UI 1.8 widget factory
11
+ *
12
+ * Optional:
13
+ * - jQuery UI effects
14
+ * - jQuery UI position utility
15
+ *
16
+ * Dual licensed under the MIT and GPL licenses:
17
+ * http://www.opensource.org/licenses/mit-license.php
18
+ * http://www.gnu.org/licenses/gpl.html
19
+ *
20
+ */
21
+ (function($, undefined){
22
+
23
+ var multiselectID = 0;
24
+
25
+ $.widget("ech.multiselect", {
26
+
27
+ // default options
28
+ options: {
29
+ header: true,
30
+ height: 175,
31
+ minWidth: 225,
32
+ classes: '',
33
+ checkAllText: 'Check all',
34
+ uncheckAllText: 'Uncheck all',
35
+ noneSelectedText: 'Select options',
36
+ selectedText: '# selected',
37
+ selectedList: 0,
38
+ show: '',
39
+ hide: '',
40
+ autoOpen: false,
41
+ multiple: true,
42
+ position: {}
43
+ },
44
+
45
+ _create: function(){
46
+ var el = this.element.hide(),
47
+ o = this.options;
48
+
49
+ this.speed = $.fx.speeds._default; // default speed for effects
50
+ this._isOpen = false; // assume no
51
+
52
+ var
53
+ button = (this.button = $('<button type="button"><span class="ui-icon ui-icon-triangle-2-n-s"></span></button>'))
54
+ .addClass('ui-multiselect ui-widget ui-state-default ui-corner-all')
55
+ .addClass( o.classes )
56
+ .attr({ 'title':el.attr('title'), 'aria-haspopup':true, 'tabIndex':el.attr('tabIndex') })
57
+ .insertAfter( el ),
58
+
59
+ buttonlabel = (this.buttonlabel = $('<span />'))
60
+ .html( o.noneSelectedText )
61
+ .appendTo( button ),
62
+
63
+ menu = (this.menu = $('<div />'))
64
+ .addClass('ui-multiselect-menu ui-widget ui-widget-content ui-corner-all')
65
+ .addClass( o.classes )
66
+ .appendTo( document.body ),
67
+
68
+ header = (this.header = $('<div />'))
69
+ .addClass('ui-widget-header ui-corner-all ui-multiselect-header ui-helper-clearfix')
70
+ .appendTo( menu ),
71
+
72
+ headerLinkContainer = (this.headerLinkContainer = $('<ul />'))
73
+ .addClass('ui-helper-reset')
74
+ .html(function(){
75
+ if( o.header === true ){
76
+ return '<li><a class="ui-multiselect-all" href="#"><span class="ui-icon ui-icon-check"></span><span>' + o.checkAllText + '</span></a></li><li><a class="ui-multiselect-none" href="#"><span class="ui-icon ui-icon-closethick"></span><span>' + o.uncheckAllText + '</span></a></li>';
77
+ } else if(typeof o.header === "string"){
78
+ return '<li>' + o.header + '</li>';
79
+ } else {
80
+ return '';
81
+ }
82
+ })
83
+ .append('<li class="ui-multiselect-close"><a href="#" class="ui-multiselect-close"><span class="ui-icon ui-icon-circle-close"></span></a></li>')
84
+ .appendTo( header ),
85
+
86
+ checkboxContainer = (this.checkboxContainer = $('<ul />'))
87
+ .addClass('ui-multiselect-checkboxes ui-helper-reset')
88
+ .appendTo( menu );
89
+
90
+ // perform event bindings
91
+ this._bindEvents();
92
+
93
+ // build menu
94
+ this.refresh( true );
95
+
96
+ // some addl. logic for single selects
97
+ if( !o.multiple ){
98
+ menu.addClass('ui-multiselect-single');
99
+ }
100
+ },
101
+
102
+ _init: function(){
103
+ if( this.options.header === false ){
104
+ this.header.hide();
105
+ }
106
+ if( !this.options.multiple ){
107
+ this.headerLinkContainer.find('.ui-multiselect-all, .ui-multiselect-none').hide();
108
+ }
109
+ if( this.options.autoOpen ){
110
+ this.open();
111
+ }
112
+ if( this.element.is(':disabled') ){
113
+ this.disable();
114
+ }
115
+ },
116
+
117
+ refresh: function( init ){
118
+ var el = this.element,
119
+ o = this.options,
120
+ menu = this.menu,
121
+ checkboxContainer = this.checkboxContainer,
122
+ optgroups = [],
123
+ html = [],
124
+ id = el.attr('id') || multiselectID++; // unique ID for the label & option tags
125
+
126
+ // build items
127
+ el.find('option').each(function( i ){
128
+ var $this = $(this),
129
+ parent = this.parentNode,
130
+ title = this.innerHTML,
131
+ description = this.title,
132
+ value = this.value,
133
+ inputID = this.id || 'ui-multiselect-' + id + '-option-' + i,
134
+ isDisabled = this.disabled,
135
+ isSelected = this.selected,
136
+ labelClasses = ['ui-corner-all'],
137
+ optLabel;
138
+
139
+ // is this an optgroup?
140
+ if( parent.tagName.toLowerCase() === 'optgroup' ){
141
+ optLabel = parent.getAttribute('label');
142
+
143
+ // has this optgroup been added already?
144
+ if( $.inArray(optLabel, optgroups) === -1 ){
145
+ html.push('<li class="ui-multiselect-optgroup-label"><a href="#">' + optLabel + '</a></li>');
146
+ optgroups.push( optLabel );
147
+ }
148
+ }
149
+
150
+ if( isDisabled ){
151
+ labelClasses.push('ui-state-disabled');
152
+ }
153
+
154
+ // browsers automatically select the first option
155
+ // by default with single selects
156
+ if( isSelected && !o.multiple ){
157
+ labelClasses.push('ui-state-active');
158
+ }
159
+
160
+ html.push('<li class="' + (isDisabled ? 'ui-multiselect-disabled' : '') + '">');
161
+
162
+ // create the label
163
+ html.push('<label for="' + inputID + '" title="' + description + '" class="' + labelClasses.join(' ') + '">');
164
+ html.push('<input id="' + inputID + '" name="multiselect_' + id + '" type="' + (o.multiple ? "checkbox" : "radio") + '" value="' + value + '" title="' + title + '"');
165
+
166
+ // pre-selected?
167
+ if( isSelected ){
168
+ html.push(' checked="checked"');
169
+ html.push(' aria-selected="true"');
170
+ }
171
+
172
+ // disabled?
173
+ if( isDisabled ){
174
+ html.push(' disabled="disabled"');
175
+ html.push(' aria-disabled="true"');
176
+ }
177
+
178
+ // add the title and close everything off
179
+ html.push(' /><span>' + title + '</span></label></li>');
180
+ });
181
+
182
+ // insert into the DOM
183
+ checkboxContainer.html( html.join('') );
184
+
185
+ // cache some moar useful elements
186
+ this.labels = menu.find('label');
187
+
188
+ // set widths
189
+ this._setButtonWidth();
190
+ this._setMenuWidth();
191
+
192
+ // remember default value
193
+ this.button[0].defaultValue = this.update();
194
+
195
+ // broadcast refresh event; useful for widgets
196
+ if( !init ){
197
+ this._trigger('refresh');
198
+ }
199
+ },
200
+
201
+ // updates the button text. call refresh() to rebuild
202
+ update: function(){
203
+ var o = this.options,
204
+ $inputs = this.labels.find('input'),
205
+ $checked = $inputs.filter('[checked]'),
206
+ numChecked = $checked.length,
207
+ value;
208
+
209
+ if( numChecked === 0 ){
210
+ value = o.noneSelectedText;
211
+ } else {
212
+ if($.isFunction( o.selectedText )){
213
+ value = o.selectedText.call(this, numChecked, $inputs.length, $checked.get());
214
+ } else if( /\d/.test(o.selectedList) && o.selectedList > 0 && numChecked <= o.selectedList){
215
+ value = $checked.map(function(){ return $(this).next().text(); }).get().join(', ');
216
+ } else {
217
+ value = o.selectedText.replace('#', numChecked).replace('#', $inputs.length);
218
+ }
219
+ }
220
+
221
+ this.buttonlabel.html( value );
222
+ return value;
223
+ },
224
+
225
+ // binds events
226
+ _bindEvents: function(){
227
+ var self = this, button = this.button;
228
+
229
+ function clickHandler(){
230
+ self[ self._isOpen ? 'close' : 'open' ]();
231
+ return false;
232
+ }
233
+
234
+ // webkit doesn't like it when you click on the span :(
235
+ button
236
+ .find('span')
237
+ .bind('click.multiselect', clickHandler);
238
+
239
+ // button events
240
+ button.bind({
241
+ click: clickHandler,
242
+ keypress: function( e ){
243
+ switch(e.which){
244
+ case 27: // esc
245
+ case 38: // up
246
+ case 37: // left
247
+ self.close();
248
+ break;
249
+ case 39: // right
250
+ case 40: // down
251
+ self.open();
252
+ break;
253
+ }
254
+ },
255
+ mouseenter: function(){
256
+ if( !button.hasClass('ui-state-disabled') ){
257
+ $(this).addClass('ui-state-hover');
258
+ }
259
+ },
260
+ mouseleave: function(){
261
+ $(this).removeClass('ui-state-hover');
262
+ },
263
+ focus: function(){
264
+ if( !button.hasClass('ui-state-disabled') ){
265
+ $(this).addClass('ui-state-focus');
266
+ }
267
+ },
268
+ blur: function(){
269
+ $(this).removeClass('ui-state-focus');
270
+ }
271
+ });
272
+
273
+ // header links
274
+ this.header
275
+ .delegate('a', 'click.multiselect', function( e ){
276
+ // close link
277
+ if( $(this).hasClass('ui-multiselect-close') ){
278
+ self.close();
279
+
280
+ // check all / uncheck all
281
+ } else {
282
+ self[ $(this).hasClass('ui-multiselect-all') ? 'checkAll' : 'uncheckAll' ]();
283
+ }
284
+
285
+ e.preventDefault();
286
+ });
287
+
288
+ // optgroup label toggle support
289
+ this.menu
290
+ .delegate('li.ui-multiselect-optgroup-label a', 'click.multiselect', function( e ){
291
+ e.preventDefault();
292
+
293
+ var $this = $(this),
294
+ $inputs = $this.parent().nextUntil('li.ui-multiselect-optgroup-label').find('input:visible:not(:disabled)'),
295
+ nodes = $inputs.get(),
296
+ label = $this.parent().text();
297
+
298
+ // trigger event and bail if the return is false
299
+ if( self._trigger('beforeoptgrouptoggle', e, { inputs:nodes, label:label }) === false ){
300
+ return;
301
+ }
302
+
303
+ // toggle inputs
304
+ self._toggleChecked(
305
+ $inputs.filter('[checked]').length !== $inputs.length,
306
+ $inputs
307
+ );
308
+
309
+ self._trigger('optgrouptoggle', e, {
310
+ inputs: nodes,
311
+ label: label,
312
+ checked: nodes[0].checked
313
+ });
314
+ })
315
+ .delegate('label', 'mouseenter.multiselect', function(){
316
+ if( !$(this).hasClass('ui-state-disabled') ){
317
+ self.labels.removeClass('ui-state-hover');
318
+ $(this).addClass('ui-state-hover').find('input').focus();
319
+ }
320
+ })
321
+ .delegate('label', 'keydown.multiselect', function( e ){
322
+ e.preventDefault();
323
+
324
+ switch(e.which){
325
+ case 9: // tab
326
+ case 27: // esc
327
+ self.close();
328
+ break;
329
+ case 38: // up
330
+ case 40: // down
331
+ case 37: // left
332
+ case 39: // right
333
+ self._traverse(e.which, this);
334
+ break;
335
+ case 13: // enter
336
+ $(this).find('input')[0].click();
337
+ break;
338
+ }
339
+ })
340
+ .delegate('input[type="checkbox"], input[type="radio"]', 'click.multiselect', function( e ){
341
+ var $this = $(this),
342
+ val = this.value,
343
+ checked = this.checked,
344
+ tags = self.element.find('option');
345
+
346
+ // bail if this input is disabled or the event is cancelled
347
+ if( this.disabled || self._trigger('click', e, { value: val, text: this.title, checked: checked }) === false ){
348
+ e.preventDefault();
349
+ return;
350
+ }
351
+
352
+ // make sure the input has focus. otherwise, the esc key
353
+ // won't close the menu after clicking an item.
354
+ $this.focus();
355
+
356
+ // toggle aria state
357
+ $this.attr('aria-selected', checked);
358
+
359
+ // change state on the original option tags
360
+ tags.each(function(){
361
+ if( this.value === val ){
362
+ this.selected = checked;
363
+ } else if( !self.options.multiple ){
364
+ this.selected = false;
365
+ }
366
+ });
367
+
368
+ // some additional single select-specific logic
369
+ if( !self.options.multiple ){
370
+ self.labels.removeClass('ui-state-active');
371
+ $this.closest('label').toggleClass('ui-state-active', checked );
372
+
373
+ // close menu
374
+ self.close();
375
+ }
376
+
377
+ // fire change on the select box
378
+ self.element.trigger("change");
379
+
380
+ // setTimeout is to fix multiselect issue #14 and #47. caused by jQuery issue #3827
381
+ // http://bugs.jquery.com/ticket/3827
382
+ setTimeout($.proxy(self.update, self), 10);
383
+ });
384
+
385
+ // close each widget when clicking on any other element/anywhere else on the page
386
+ $(document).bind('mousedown.multiselect', function( e ){
387
+ if(self._isOpen && !$.contains(self.menu[0], e.target) && !$.contains(self.button[0], e.target) && e.target !== self.button[0]){
388
+ self.close();
389
+ }
390
+ });
391
+
392
+ // deal with form resets. the problem here is that buttons aren't
393
+ // restored to their defaultValue prop on form reset, and the reset
394
+ // handler fires before the form is actually reset. delaying it a bit
395
+ // gives the form inputs time to clear.
396
+ $(this.element[0].form).bind('reset.multiselect', function(){
397
+ setTimeout($.proxy(self.refresh, self), 10);
398
+ });
399
+ },
400
+
401
+ // set button width
402
+ _setButtonWidth: function(){
403
+ var width = this.element.outerWidth(),
404
+ o = this.options;
405
+
406
+ if( /\d/.test(o.minWidth) && width < o.minWidth){
407
+ width = o.minWidth;
408
+ }
409
+
410
+ // set widths
411
+ this.button.width( width );
412
+ },
413
+
414
+ // set menu width
415
+ _setMenuWidth: function(){
416
+ var m = this.menu,
417
+ width = this.button.outerWidth()-
418
+ parseInt(m.css('padding-left'),10)-
419
+ parseInt(m.css('padding-right'),10)-
420
+ parseInt(m.css('border-right-width'),10)-
421
+ parseInt(m.css('border-left-width'),10);
422
+
423
+ m.width( width || this.button.outerWidth() );
424
+ },
425
+
426
+ // move up or down within the menu
427
+ _traverse: function( which, start ){
428
+ var $start = $(start),
429
+ moveToLast = which === 38 || which === 37,
430
+
431
+ // select the first li that isn't an optgroup label / disabled
432
+ $next = $start.parent()[moveToLast ? 'prevAll' : 'nextAll']('li:not(.ui-multiselect-disabled, .ui-multiselect-optgroup-label)')[ moveToLast ? 'last' : 'first']();
433
+
434
+ // if at the first/last element
435
+ if( !$next.length ){
436
+ var $container = this.menu.find('ul').last();
437
+
438
+ // move to the first/last
439
+ this.menu.find('label')[ moveToLast ? 'last' : 'first' ]().trigger('mouseover');
440
+
441
+ // set scroll position
442
+ $container.scrollTop( moveToLast ? $container.height() : 0 );
443
+
444
+ } else {
445
+ $next.find('label').trigger('mouseover');
446
+ }
447
+ },
448
+
449
+ // This is an internal function to toggle the checked property and
450
+ // other related attributes of a checkbox.
451
+ //
452
+ // The context of this function should be a checkbox; do not proxy it.
453
+ _toggleState: function( prop, flag ){
454
+ return function(){
455
+ if( !this.disabled ) {
456
+ this[ prop ] = flag;
457
+ }
458
+
459
+ if( flag ){
460
+ this.setAttribute('aria-selected', true);
461
+ } else {
462
+ this.removeAttribute('aria-selected');
463
+ }
464
+ };
465
+ },
466
+
467
+ _toggleChecked: function( flag, group ){
468
+ var $inputs = (group && group.length) ?
469
+ group :
470
+ this.labels.find('input'),
471
+
472
+ self = this;
473
+
474
+ // toggle state on inputs
475
+ $inputs.each(this._toggleState('checked', flag));
476
+
477
+ // give the first input focus
478
+ $inputs.eq(0).focus();
479
+
480
+ // update button text
481
+ this.update();
482
+
483
+ // gather an array of the values that actually changed
484
+ var values = $inputs.map(function(){
485
+ return this.value;
486
+ }).get();
487
+
488
+ // toggle state on original option tags
489
+ this.element
490
+ .find('option')
491
+ .each(function(){
492
+ if( !this.disabled && $.inArray(this.value, values) > -1 ){
493
+ self._toggleState('selected', flag).call( this );
494
+ }
495
+ });
496
+
497
+ // trigger the change event on the select
498
+ if( $inputs.length ) {
499
+ this.element.trigger("change");
500
+ }
501
+ },
502
+
503
+ _toggleDisabled: function( flag ){
504
+ this.button
505
+ .attr({ 'disabled':flag, 'aria-disabled':flag })[ flag ? 'addClass' : 'removeClass' ]('ui-state-disabled');
506
+
507
+ this.menu
508
+ .find('input')
509
+ .attr({ 'disabled':flag, 'aria-disabled':flag })
510
+ .parent()[ flag ? 'addClass' : 'removeClass' ]('ui-state-disabled');
511
+
512
+ this.element
513
+ .attr({ 'disabled':flag, 'aria-disabled':flag });
514
+ },
515
+
516
+ // open the menu
517
+ open: function( e ){
518
+ var self = this,
519
+ button = this.button,
520
+ menu = this.menu,
521
+ speed = this.speed,
522
+ o = this.options;
523
+
524
+ // bail if the multiselectopen event returns false, this widget is disabled, or is already open
525
+ if( this._trigger('beforeopen') === false || button.hasClass('ui-state-disabled') || this._isOpen ){
526
+ return;
527
+ }
528
+
529
+ var $container = menu.find('ul').last(),
530
+ effect = o.show,
531
+ pos = button.offset();
532
+
533
+ // figure out opening effects/speeds
534
+ if( $.isArray(o.show) ){
535
+ effect = o.show[0];
536
+ speed = o.show[1] || self.speed;
537
+ }
538
+
539
+ // set the scroll of the checkbox container
540
+ $container.scrollTop(0).height(o.height);
541
+
542
+ // position and show menu
543
+ if( $.ui.position && !$.isEmptyObject(o.position) ){
544
+ o.position.of = o.position.of || button;
545
+
546
+ menu
547
+ .show()
548
+ .position( o.position )
549
+ .hide()
550
+ .show( effect, speed );
551
+
552
+ // if position utility is not available...
553
+ } else {
554
+ menu.css({
555
+ top: pos.top + button.outerHeight(),
556
+ left: pos.left
557
+ }).show( effect, speed );
558
+ }
559
+
560
+ // select the first option
561
+ // triggering both mouseover and mouseover because 1.4.2+ has a bug where triggering mouseover
562
+ // will actually trigger mouseenter. the mouseenter trigger is there for when it's eventually fixed
563
+ this.labels.eq(0).trigger('mouseover').trigger('mouseenter').find('input').trigger('focus');
564
+
565
+ button.addClass('ui-state-active');
566
+ this._isOpen = true;
567
+ this._trigger('open');
568
+ },
569
+
570
+ // close the menu
571
+ close: function(){
572
+ if(this._trigger('beforeclose') === false){
573
+ return;
574
+ }
575
+
576
+ var o = this.options, effect = o.hide, speed = this.speed;
577
+
578
+ // figure out opening effects/speeds
579
+ if( $.isArray(o.hide) ){
580
+ effect = o.hide[0];
581
+ speed = o.hide[1] || this.speed;
582
+ }
583
+
584
+ this.menu.hide(effect, speed);
585
+ this.button.removeClass('ui-state-active').trigger('blur').trigger('mouseleave');
586
+ this._isOpen = false;
587
+ this._trigger('close');
588
+ },
589
+
590
+ enable: function(){
591
+ this._toggleDisabled(false);
592
+ },
593
+
594
+ disable: function(){
595
+ this._toggleDisabled(true);
596
+ },
597
+
598
+ checkAll: function( e ){
599
+ this._toggleChecked(true);
600
+ this._trigger('checkAll');
601
+ },
602
+
603
+ uncheckAll: function(){
604
+ this._toggleChecked(false);
605
+ this._trigger('uncheckAll');
606
+ },
607
+
608
+ getChecked: function(){
609
+ return this.menu.find('input').filter('[checked]');
610
+ },
611
+
612
+ destroy: function(){
613
+ // remove classes + data
614
+ $.Widget.prototype.destroy.call( this );
615
+
616
+ this.button.remove();
617
+ this.menu.remove();
618
+ this.element.show();
619
+
620
+ return this;
621
+ },
622
+
623
+ isOpen: function(){
624
+ return this._isOpen;
625
+ },
626
+
627
+ widget: function(){
628
+ return this.menu;
629
+ },
630
+
631
+ // react to option changes after initialization
632
+ _setOption: function( key, value ){
633
+ var menu = this.menu;
634
+
635
+ switch(key){
636
+ case 'header':
637
+ menu.find('div.ui-multiselect-header')[ value ? 'show' : 'hide' ]();
638
+ break;
639
+ case 'checkAllText':
640
+ menu.find('a.ui-multiselect-all span').eq(-1).text(value);
641
+ break;
642
+ case 'uncheckAllText':
643
+ menu.find('a.ui-multiselect-none span').eq(-1).text(value);
644
+ break;
645
+ case 'height':
646
+ menu.find('ul').last().height( parseInt(value,10) );
647
+ break;
648
+ case 'minWidth':
649
+ this.options[ key ] = parseInt(value,10);
650
+ this._setButtonWidth();
651
+ this._setMenuWidth();
652
+ break;
653
+ case 'selectedText':
654
+ case 'selectedList':
655
+ case 'noneSelectedText':
656
+ this.options[key] = value; // these all needs to update immediately for the update() call
657
+ this.update();
658
+ break;
659
+ case 'classes':
660
+ menu.add(this.button).removeClass(this.options.classes).addClass(value);
661
+ break;
662
+ }
663
+
664
+ $.Widget.prototype._setOption.apply( this, arguments );
665
+ }
666
+ });
667
+
668
+ })(jQuery);