ab_admin 0.3.6 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (419) hide show
  1. checksums.yaml +7 -0
  2. data/{LICENSE.txt → MIT-LICENSE} +2 -4
  3. data/README.md +3 -3
  4. data/Rakefile +21 -3
  5. data/app/assets/images/admin/flags/b_de.png +0 -0
  6. data/app/assets/images/admin/flags/b_es.png +0 -0
  7. data/app/assets/images/admin/flags/b_fr.png +0 -0
  8. data/app/assets/images/admin/flags/flag_de.gif +0 -0
  9. data/app/assets/images/admin/flags/flag_de_nonact.gif +0 -0
  10. data/app/assets/images/admin/flags/flag_es.gif +0 -0
  11. data/app/assets/images/admin/flags/flag_es_nonact.gif +0 -0
  12. data/app/assets/images/admin/flags/flag_fr.gif +0 -0
  13. data/app/assets/images/admin/flags/flag_fr_nonact.gif +0 -0
  14. data/app/assets/javascripts/ab_admin/components/admin_assets.js.coffee +50 -60
  15. data/app/assets/javascripts/ab_admin/components/base_assets.js.coffee +86 -0
  16. data/app/assets/javascripts/ab_admin/components/croppable_image.js.coffee +4 -4
  17. data/app/assets/javascripts/ab_admin/components/gmaps.js.coffee +5 -0
  18. data/app/assets/javascripts/ab_admin/components/google_translate.js.coffee +0 -1
  19. data/app/assets/javascripts/ab_admin/components/in_place_edit.js.coffee +7 -3
  20. data/app/assets/javascripts/ab_admin/components/locator.js.coffee +1 -1
  21. data/app/assets/javascripts/ab_admin/components/select2_bridge.js.coffee +152 -0
  22. data/app/assets/javascripts/ab_admin/components/sortable_tree.js.coffee +1 -1
  23. data/app/assets/javascripts/ab_admin/core/batch_actions.js.coffee +5 -4
  24. data/app/assets/javascripts/ab_admin/core/columns_hider.js.coffee +4 -11
  25. data/app/assets/javascripts/ab_admin/core/confirmation.js.coffee +4 -43
  26. data/app/assets/javascripts/ab_admin/core/deprecated_utils.js.coffee +44 -0
  27. data/app/assets/javascripts/ab_admin/core/init.js.coffee +8 -25
  28. data/app/assets/javascripts/ab_admin/core/pjax.js.coffee +18 -4
  29. data/app/assets/javascripts/ab_admin/core/search_form.js.coffee +5 -5
  30. data/app/assets/javascripts/ab_admin/core/ui_utils.js.coffee +15 -86
  31. data/app/assets/javascripts/ab_admin/core/utils.js.coffee +38 -51
  32. data/app/assets/javascripts/ab_admin/core/view_layout.js.coffee +1 -1
  33. data/app/assets/javascripts/ab_admin/inputs/datetime_input.js.coffee +16 -18
  34. data/app/assets/javascripts/ab_admin/main.js +7 -7
  35. data/app/assets/stylesheets/ab_admin/bootstrap_and_overrides.css.scss +21 -8
  36. data/app/assets/stylesheets/ab_admin/components/_admin_comments.css.scss +17 -5
  37. data/app/assets/stylesheets/ab_admin/components/_base.css.scss +4 -0
  38. data/app/assets/stylesheets/ab_admin/components/_colored_tabs.css.scss +1 -4
  39. data/app/assets/stylesheets/ab_admin/components/_columns_hider.css.scss +5 -0
  40. data/app/assets/stylesheets/ab_admin/components/_form.css.scss +45 -16
  41. data/app/assets/stylesheets/ab_admin/components/_grid_view.css.scss +11 -0
  42. data/app/assets/stylesheets/ab_admin/components/_locale_tabs.css.scss +1 -1
  43. data/app/assets/stylesheets/ab_admin/components/_navigation.css.scss +11 -9
  44. data/app/assets/stylesheets/ab_admin/components/_table_view.css.scss +1 -1
  45. data/app/assets/stylesheets/ab_admin/components/_translations.css.scss +1 -0
  46. data/app/assets/stylesheets/ab_admin/components/{_sortable_tree.css.scss → _tree_view.css.scss} +8 -3
  47. data/app/assets/stylesheets/ab_admin/fileupload.css.scss +51 -43
  48. data/app/assets/stylesheets/ab_admin/main.css.scss +1 -3
  49. data/app/controllers/admin/admin_comments_controller.rb +14 -4
  50. data/app/controllers/admin/assets_controller.rb +44 -35
  51. data/app/controllers/admin/base_controller.rb +93 -38
  52. data/app/controllers/admin/locators_controller.rb +3 -2
  53. data/app/controllers/admin/manager_controller.rb +20 -9
  54. data/app/controllers/admin/structures_controller.rb +9 -1
  55. data/app/controllers/admin/users_controller.rb +1 -2
  56. data/app/views/ab_admin/devise/sessions/new.html.slim +1 -1
  57. data/app/views/admin/admin_comments/_comment.html.slim +21 -7
  58. data/app/views/admin/admin_comments/_comments.html.slim +1 -1
  59. data/app/views/admin/admin_comments/_form.html.slim +8 -3
  60. data/app/views/admin/admin_comments/_list_block.html.slim +7 -0
  61. data/app/views/admin/admin_comments/create.js.erb +3 -2
  62. data/app/views/admin/admin_comments/destroy.js.erb +1 -1
  63. data/app/views/admin/admin_comments/index.js.erb +14 -0
  64. data/app/views/admin/assets/batch_edit.html.slim +14 -0
  65. data/app/views/admin/base/_modal_form_layout.html.slim +12 -0
  66. data/app/views/admin/base/_search_layout.html.slim +4 -3
  67. data/app/views/admin/base/_table.html.slim +2 -2
  68. data/app/views/admin/base/create.js.erb +13 -8
  69. data/app/views/admin/base/history.html.slim +18 -0
  70. data/app/views/admin/base/index.html.slim +3 -3
  71. data/app/views/admin/base/new.js.erb +14 -8
  72. data/app/views/admin/base/show.html.slim +1 -2
  73. data/app/views/admin/base/show.js.erb +7 -0
  74. data/app/views/admin/fileupload/_asset_templates.html.slim +29 -0
  75. data/app/views/admin/fileupload/_container.html.slim +13 -12
  76. data/app/views/admin/fileupload/_file.html.slim +2 -2
  77. data/app/views/admin/fileupload/_image.html.slim +8 -0
  78. data/app/views/admin/fileupload/_video.html.slim +2 -2
  79. data/app/views/admin/headers/_form.html.slim +2 -0
  80. data/app/views/admin/locators/edit.html.slim +1 -1
  81. data/app/views/admin/locators/show.html.slim +1 -2
  82. data/app/views/admin/manager/_form.html.slim +17 -3
  83. data/app/views/admin/manager/_modal_form.html.slim +19 -0
  84. data/app/views/admin/manager/_table.html.slim +3 -3
  85. data/app/views/admin/manager/show.html.slim +1 -0
  86. data/app/views/admin/shared/_content_actions.html.slim +39 -0
  87. data/app/views/admin/shared/_locale_tabs.html.slim +3 -3
  88. data/app/views/admin/shared/inputs/_checkbox_tree.html.slim +9 -3
  89. data/app/views/admin/structures/_form.html.slim +4 -7
  90. data/app/views/admin/users/_form.html.slim +2 -4
  91. data/app/views/admin/users/_search_form.html.slim +0 -1
  92. data/app/views/admin/users/_table.html.slim +8 -10
  93. data/app/views/layouts/admin/_footer.html.slim +3 -4
  94. data/app/views/layouts/admin/_navigation.html.slim +2 -2
  95. data/app/views/layouts/admin/application.html.slim +7 -9
  96. data/app/views/layouts/admin/devise.html.slim +3 -4
  97. data/config/locales/de.yml +319 -0
  98. data/config/locales/en.devise.yml +44 -31
  99. data/config/locales/en.yml +166 -143
  100. data/config/locales/it.devise.yml +54 -41
  101. data/config/locales/it.yml +178 -163
  102. data/config/locales/ru.devise.yml +70 -56
  103. data/config/locales/ru.yml +280 -264
  104. data/config/routes.rb +6 -3
  105. data/db/migrate/20130101000001_create_users.rb +7 -11
  106. data/db/migrate/20130101000003_create_assets.rb +5 -5
  107. data/db/migrate/20130101000004_create_headers.rb +2 -6
  108. data/db/migrate/20130101000005_create_static_pages.rb +1 -5
  109. data/db/migrate/20130101000006_create_structures.rb +5 -9
  110. data/db/migrate/20130101000007_base_translations.rb +3 -1
  111. data/db/migrate/20130101000008_create_admin_comments.rb +5 -5
  112. data/db/migrate/20130101000009_create_tracks.rb +20 -0
  113. data/lib/ab_admin.rb +36 -4
  114. data/lib/ab_admin/abstract_resource.rb +28 -7
  115. data/lib/ab_admin/carrierwave/base_uploader.rb +85 -5
  116. data/lib/ab_admin/carrierwave/glue.rb +6 -1
  117. data/lib/ab_admin/concerns/admin_addition.rb +26 -9
  118. data/lib/ab_admin/concerns/asset_human_names.rb +23 -0
  119. data/lib/ab_admin/concerns/fileuploads.rb +102 -0
  120. data/lib/ab_admin/concerns/has_tracking.rb +32 -0
  121. data/lib/ab_admin/concerns/nested_set.rb +9 -9
  122. data/lib/ab_admin/concerns/silencer.rb +5 -5
  123. data/lib/ab_admin/concerns/utilities.rb +28 -16
  124. data/lib/ab_admin/concerns/validations.rb +1 -1
  125. data/lib/ab_admin/config/base.rb +10 -2
  126. data/lib/ab_admin/controllers/callbacks.rb +2 -2
  127. data/lib/ab_admin/controllers/can_can_manager_resource.rb +3 -2
  128. data/lib/ab_admin/controllers/fv.rb +16 -0
  129. data/lib/ab_admin/controllers/head_options.rb +6 -4
  130. data/lib/ab_admin/core_ext/hash.rb +25 -70
  131. data/lib/ab_admin/core_ext/string.rb +17 -4
  132. data/lib/ab_admin/engine.rb +2 -8
  133. data/lib/ab_admin/hooks.rb +8 -3
  134. data/lib/ab_admin/hooks/active_model_hooks.rb +1 -1
  135. data/lib/ab_admin/hooks/globalize_hooks.rb +35 -0
  136. data/lib/ab_admin/hooks/paginate_hooks.rb +3 -1
  137. data/lib/ab_admin/i18n_tools/model_translator.rb +1 -1
  138. data/lib/ab_admin/menu/abstract_builder.rb +14 -0
  139. data/lib/ab_admin/menu/base_group.rb +26 -0
  140. data/lib/ab_admin/menu/builder.rb +16 -0
  141. data/lib/ab_admin/menu/group.rb +24 -0
  142. data/lib/ab_admin/menu/item.rb +23 -0
  143. data/lib/ab_admin/models/admin_comment.rb +68 -0
  144. data/lib/ab_admin/models/asset.rb +30 -19
  145. data/lib/ab_admin/models/attachment_file.rb +2 -1
  146. data/lib/ab_admin/models/header.rb +15 -0
  147. data/lib/ab_admin/models/locator.rb +1 -3
  148. data/lib/ab_admin/models/settings.rb +10 -10
  149. data/lib/ab_admin/models/structure.rb +20 -9
  150. data/lib/ab_admin/models/track.rb +61 -0
  151. data/lib/ab_admin/models/type_model.rb +30 -17
  152. data/lib/ab_admin/models/user.rb +18 -49
  153. data/lib/ab_admin/utils.rb +16 -7
  154. data/lib/ab_admin/utils/logger.rb +11 -7
  155. data/lib/ab_admin/utils/mysql.rb +10 -0
  156. data/lib/ab_admin/version.rb +1 -1
  157. data/lib/ab_admin/views/admin_helpers.rb +20 -9
  158. data/lib/ab_admin/views/admin_navigation_helpers.rb +44 -21
  159. data/lib/ab_admin/views/content_only_wrapper.rb +14 -0
  160. data/lib/ab_admin/views/form_builder.rb +27 -89
  161. data/lib/ab_admin/views/helpers.rb +1 -28
  162. data/lib/ab_admin/views/inputs/capture_block_input.rb +16 -0
  163. data/lib/ab_admin/views/inputs/date_time_picker_input.rb +45 -0
  164. data/lib/ab_admin/views/inputs/token_input.rb +2 -1
  165. data/lib/ab_admin/views/inputs/uploader_input.rb +101 -0
  166. data/lib/ab_admin/views/manager_helpers.rb +12 -0
  167. data/lib/ab_admin/views/search_form_builder.rb +36 -13
  168. data/lib/generators/ab_admin/ckeditor_assets/ckeditor_assets_generator.rb +1 -1
  169. data/lib/generators/ab_admin/install/install_generator.rb +3 -2
  170. data/lib/generators/ab_admin/install/templates/config/ab_admin.rb.erb +1 -1
  171. data/lib/generators/ab_admin/install/templates/config/admin_menu.rb +1 -1
  172. data/lib/generators/ab_admin/install/templates/config/i18n-js.yml +1 -1
  173. data/lib/generators/ab_admin/install/templates/config/nginx.conf +22 -9
  174. data/lib/generators/ab_admin/install/templates/config/robots.txt +7 -0
  175. data/lib/generators/ab_admin/install/templates/config/seeds.rb +2 -1
  176. data/lib/generators/ab_admin/install/templates/models/ability.rb +2 -7
  177. data/lib/generators/ab_admin/install/templates/models/admin_comment.rb +3 -28
  178. data/lib/generators/ab_admin/install/templates/models/asset.rb +4 -2
  179. data/lib/generators/ab_admin/install/templates/models/attachment_file.rb +1 -1
  180. data/lib/generators/ab_admin/install/templates/models/avatar.rb +2 -2
  181. data/lib/generators/ab_admin/install/templates/models/gender_type.rb +1 -1
  182. data/lib/generators/ab_admin/install/templates/models/header.rb +2 -2
  183. data/lib/generators/ab_admin/install/templates/models/locator.rb +0 -1
  184. data/lib/generators/ab_admin/install/templates/models/picture.rb +1 -1
  185. data/lib/generators/ab_admin/install/templates/models/settings.rb +1 -1
  186. data/lib/generators/ab_admin/install/templates/models/structure.rb +6 -8
  187. data/lib/generators/ab_admin/install/templates/models/track.rb +5 -0
  188. data/lib/generators/ab_admin/install/templates/models/user.rb +2 -3
  189. data/lib/generators/ab_admin/install/templates/script/unicorn.sh +0 -2
  190. data/lib/generators/ab_admin/install/templates/spec/factories/user_factory.rb +1 -2
  191. data/lib/generators/ab_admin/install/templates/uploaders/attachment_file_uploader.rb +1 -1
  192. data/lib/generators/ab_admin/install/templates/uploaders/avatar_uploader.rb +1 -1
  193. data/lib/generators/ab_admin/install/templates/uploaders/picture_uploader.rb +1 -1
  194. data/lib/generators/ab_admin/model/templates/resource.erb +1 -1
  195. data/lib/generators/ab_admin/resource/templates/_form.slim.erb +49 -45
  196. data/lib/generators/ab_admin/resource/templates/_table.slim.erb +1 -1
  197. data/lib/generators/template.rb +32 -56
  198. data/lib/tasks/assets.rake +1 -0
  199. metadata +197 -698
  200. data/.gitignore +0 -41
  201. data/Gemfile +0 -77
  202. data/Guardfile +0 -35
  203. data/TODO +0 -4
  204. data/ab_admin.gemspec +0 -59
  205. data/app/views/admin/fileupload/_asset.html.slim +0 -8
  206. data/app/views/admin/fileupload/_ftmpl.html.slim +0 -6
  207. data/app/views/admin/fileupload/_tmpl.html.slim +0 -9
  208. data/app/views/admin/fileupload/_vtmpl.html.slim +0 -10
  209. data/app/views/admin/shared/_batch_actions.html.slim +0 -27
  210. data/cucumber.yml +0 -10
  211. data/features/dsl/action_items.feature +0 -79
  212. data/features/dsl/admin_comments.feature +0 -30
  213. data/features/dsl/batch_actions.feature +0 -69
  214. data/features/dsl/config.feature +0 -44
  215. data/features/dsl/custom_actions.feature +0 -62
  216. data/features/dsl/export.feature +0 -42
  217. data/features/dsl/form.feature +0 -77
  218. data/features/dsl/in_place_edit.feature +0 -26
  219. data/features/dsl/list_edit.feature +0 -46
  220. data/features/dsl/parent_resource.feature +0 -18
  221. data/features/dsl/resource_action_items.feature +0 -40
  222. data/features/dsl/search.feature +0 -41
  223. data/features/dsl/show.feature +0 -37
  224. data/features/dsl/table.feature +0 -71
  225. data/features/dsl/tree.feature +0 -37
  226. data/features/index_views/table.feature +0 -20
  227. data/features/locators.feature +0 -40
  228. data/features/menu.feature +0 -35
  229. data/features/settings.feature +0 -36
  230. data/features/step_definitions/configuration_steps.rb +0 -94
  231. data/features/step_definitions/dsl/action_items_steps.rb +0 -13
  232. data/features/step_definitions/dsl/admin_comments_steps.rb +0 -12
  233. data/features/step_definitions/dsl/batch_actions_steps.rb +0 -27
  234. data/features/step_definitions/dsl/in_place_edit_steps.rb +0 -7
  235. data/features/step_definitions/dsl/parent_resource_steps.rb +0 -8
  236. data/features/step_definitions/dsl/resource_action_items_steps.rb +0 -14
  237. data/features/step_definitions/dsl/show_steps.rb +0 -8
  238. data/features/step_definitions/dsl/table_steps.rb +0 -38
  239. data/features/step_definitions/dsl/tree_steps.rb +0 -28
  240. data/features/step_definitions/menu_steps.rb +0 -20
  241. data/features/step_definitions/settings_steps.rb +0 -7
  242. data/features/step_definitions/structure_steps.rb +0 -7
  243. data/features/step_definitions/table_steps.rb +0 -23
  244. data/features/step_definitions/user_steps.rb +0 -72
  245. data/features/step_definitions/web_steps/browsing_steps.rb +0 -108
  246. data/features/step_definitions/web_steps/debug_steps.rb +0 -6
  247. data/features/step_definitions/web_steps/form_steps.rb +0 -190
  248. data/features/step_definitions/web_steps/i18n_steps.rb +0 -8
  249. data/features/step_definitions/web_steps/step_scoper.rb +0 -9
  250. data/features/step_definitions/web_steps/transforms_steps.rb +0 -3
  251. data/features/structure/tree.feature +0 -21
  252. data/features/support/capybara_helpers.rb +0 -15
  253. data/features/support/carrierwave.rb +0 -21
  254. data/features/support/env.rb +0 -40
  255. data/features/support/paths.rb +0 -55
  256. data/features/support/selector_helpers.rb +0 -9
  257. data/features/support/selectors.rb +0 -43
  258. data/features/support/tolerance_for_selenium_sync_issues.rb +0 -27
  259. data/features/user/sign_in.feature +0 -27
  260. data/features/user/sign_out.feature +0 -11
  261. data/features/user/user_edit.feature +0 -19
  262. data/features/user/user_show.feature +0 -9
  263. data/lib/ab_admin/hooks/quiet_scope_page.rb +0 -16
  264. data/lib/ab_admin/hooks/simple_form_hooks.rb +0 -31
  265. data/lib/ab_admin/menu_builder.rb +0 -89
  266. data/lib/ab_admin/views/inputs/date_time_input.rb +0 -65
  267. data/lib/generators/ab_admin/install/templates/models/user_state.rb +0 -6
  268. data/lib/generators/ab_admin/resource/templates/_form.haml.erb +0 -71
  269. data/lib/generators/ab_admin/resource/templates/_search_form.haml.erb +0 -35
  270. data/lib/generators/ab_admin/resource/templates/_table.haml.erb +0 -33
  271. data/spec/ab_admin_spec.rb +0 -23
  272. data/spec/dummy/Rakefile +0 -7
  273. data/spec/dummy/app/assets/images/rails.png +0 -0
  274. data/spec/dummy/app/assets/javascripts/application.js +0 -15
  275. data/spec/dummy/app/assets/stylesheets/application.css +0 -13
  276. data/spec/dummy/app/controllers/application_controller.rb +0 -3
  277. data/spec/dummy/app/controllers/products_controller.rb +0 -5
  278. data/spec/dummy/app/controllers/welcome_controller.rb +0 -5
  279. data/spec/dummy/app/mailers/.gitkeep +0 -0
  280. data/spec/dummy/app/models/ab_admin/ab_admin_catalogue.rb +0 -5
  281. data/spec/dummy/app/models/ab_admin/ab_admin_collection.rb +0 -35
  282. data/spec/dummy/app/models/ab_admin/ab_admin_product.rb +0 -74
  283. data/spec/dummy/app/models/admin_menu.rb +0 -18
  284. data/spec/dummy/app/models/catalogue.rb +0 -10
  285. data/spec/dummy/app/models/ckeditor/asset.rb +0 -7
  286. data/spec/dummy/app/models/ckeditor/attachment_file.rb +0 -7
  287. data/spec/dummy/app/models/ckeditor/picture.rb +0 -7
  288. data/spec/dummy/app/models/collection.rb +0 -20
  289. data/spec/dummy/app/models/product.rb +0 -32
  290. data/spec/dummy/app/uploaders/ckeditor_attachment_file_uploader.rb +0 -42
  291. data/spec/dummy/app/uploaders/ckeditor_picture_uploader.rb +0 -53
  292. data/spec/dummy/app/views/admin/collections/_form.html.slim +0 -24
  293. data/spec/dummy/app/views/layouts/application.html.erb +0 -14
  294. data/spec/dummy/app/views/products/show.html.erb +0 -2
  295. data/spec/dummy/app/views/welcome/index.html.erb +0 -2
  296. data/spec/dummy/config.ru +0 -4
  297. data/spec/dummy/config/application.rb +0 -82
  298. data/spec/dummy/config/boot.rb +0 -10
  299. data/spec/dummy/config/database.yml +0 -26
  300. data/spec/dummy/config/environment.rb +0 -5
  301. data/spec/dummy/config/environments/development.rb +0 -37
  302. data/spec/dummy/config/environments/production.rb +0 -67
  303. data/spec/dummy/config/environments/test.rb +0 -37
  304. data/spec/dummy/config/i18n-js.yml +0 -21
  305. data/spec/dummy/config/initializers/ab_admin.rb +0 -15
  306. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
  307. data/spec/dummy/config/initializers/ckeditor.rb +0 -18
  308. data/spec/dummy/config/initializers/devise.rb +0 -232
  309. data/spec/dummy/config/initializers/inflections.rb +0 -15
  310. data/spec/dummy/config/initializers/mime_types.rb +0 -5
  311. data/spec/dummy/config/initializers/secret_token.rb +0 -7
  312. data/spec/dummy/config/initializers/session_store.rb +0 -8
  313. data/spec/dummy/config/initializers/simple_form.rb +0 -142
  314. data/spec/dummy/config/initializers/simple_form_bootstrap.rb +0 -45
  315. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -14
  316. data/spec/dummy/config/locales/devise.en.yml +0 -60
  317. data/spec/dummy/config/locales/en.yml +0 -5
  318. data/spec/dummy/config/locales/simple_form.en.yml +0 -26
  319. data/spec/dummy/config/routes.rb +0 -14
  320. data/spec/dummy/config/settings/development.local.yml +0 -9
  321. data/spec/dummy/config/settings/development.yml +0 -7
  322. data/spec/dummy/db/migrate/20130129151853_create_ckeditor_assets.rb +0 -26
  323. data/spec/dummy/db/migrate/20130130161853_create_collections.rb +0 -10
  324. data/spec/dummy/db/migrate/20130130162046_create_products.rb +0 -13
  325. data/spec/dummy/db/migrate/20130130175446_create_globalize_collection_product.rb +0 -11
  326. data/spec/dummy/db/migrate/20130207224516_create_catalogues.rb +0 -16
  327. data/spec/dummy/db/migrate/20130209223506_add_lat_lon_zoom_to_products.rb +0 -7
  328. data/spec/dummy/db/seeds.rb +0 -46
  329. data/spec/dummy/lib/assets/.gitkeep +0 -0
  330. data/spec/dummy/lib/capybara_irb.rb +0 -42
  331. data/spec/dummy/lib/tasks/.gitkeep +0 -0
  332. data/spec/dummy/lib/tasks/cucumber.rake +0 -65
  333. data/spec/dummy/lib/templates/slim/scaffold/_form.html.slim +0 -10
  334. data/spec/dummy/log/.gitkeep +0 -0
  335. data/spec/dummy/public/404.html +0 -26
  336. data/spec/dummy/public/422.html +0 -26
  337. data/spec/dummy/public/500.html +0 -25
  338. data/spec/dummy/public/favicon.ico +0 -0
  339. data/spec/dummy/script/cucumber +0 -10
  340. data/spec/dummy/script/rails +0 -6
  341. data/spec/factories/assets.rb +0 -52
  342. data/spec/factories/catalogues.rb +0 -7
  343. data/spec/factories/collections.rb +0 -8
  344. data/spec/factories/files/rails.png +0 -0
  345. data/spec/factories/products.rb +0 -17
  346. data/spec/factories/sequences.rb +0 -7
  347. data/spec/factories/structures.rb +0 -17
  348. data/spec/factories/users.rb +0 -30
  349. data/spec/generators/ckeditor_assets_generator_spec.rb +0 -19
  350. data/spec/generators/install_generator_spec.rb +0 -48
  351. data/spec/generators/model_generator_spec.rb +0 -31
  352. data/spec/generators/resource_generator_spec.rb +0 -36
  353. data/spec/models/ab_admin/abstract_resource_spec.rb +0 -5
  354. data/spec/models/avatar_spec.rb +0 -162
  355. data/spec/models/picture_uploader_spec.rb +0 -49
  356. data/spec/models/structure_spec.rb +0 -69
  357. data/spec/models/user_spec.rb +0 -159
  358. data/spec/shared_behaviors/concerns.rb +0 -20
  359. data/spec/spec_helper.rb +0 -96
  360. data/spec/support/controller_macros.rb +0 -52
  361. data/spec/support/custom_capybara_matchers.rb +0 -58
  362. data/spec/support/mailer_macros.rb +0 -17
  363. data/spec/support/shared_connection.rb +0 -11
  364. data/vendor/assets/images/ab_admin/clear.png +0 -0
  365. data/vendor/assets/images/ab_admin/loading.gif +0 -0
  366. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/core.js +0 -899
  367. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/index.js +0 -2
  368. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/locales/bootstrap-datepicker.bg.js +0 -14
  369. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/locales/bootstrap-datepicker.br.js +0 -13
  370. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/locales/bootstrap-datepicker.cs.js +0 -14
  371. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/locales/bootstrap-datepicker.da.js +0 -14
  372. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/locales/bootstrap-datepicker.de.js +0 -14
  373. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/locales/bootstrap-datepicker.es.js +0 -14
  374. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/locales/bootstrap-datepicker.fi.js +0 -14
  375. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/locales/bootstrap-datepicker.fr.js +0 -14
  376. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/locales/bootstrap-datepicker.id.js +0 -13
  377. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/locales/bootstrap-datepicker.is.js +0 -14
  378. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/locales/bootstrap-datepicker.it.js +0 -14
  379. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/locales/bootstrap-datepicker.ja.js +0 -13
  380. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/locales/bootstrap-datepicker.kr.js +0 -13
  381. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/locales/bootstrap-datepicker.lt.js +0 -15
  382. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/locales/bootstrap-datepicker.lv.js +0 -16
  383. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/locales/bootstrap-datepicker.ms.js +0 -14
  384. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/locales/bootstrap-datepicker.nb.js +0 -14
  385. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/locales/bootstrap-datepicker.nl.js +0 -14
  386. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/locales/bootstrap-datepicker.pl.js +0 -14
  387. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/locales/bootstrap-datepicker.pt-BR.js +0 -14
  388. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/locales/bootstrap-datepicker.pt.js +0 -14
  389. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/locales/bootstrap-datepicker.ro.js +0 -15
  390. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/locales/bootstrap-datepicker.ru.js +0 -14
  391. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/locales/bootstrap-datepicker.sk.js +0 -14
  392. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/locales/bootstrap-datepicker.sl.js +0 -14
  393. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/locales/bootstrap-datepicker.sv.js +0 -14
  394. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/locales/bootstrap-datepicker.th.js +0 -14
  395. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/locales/bootstrap-datepicker.tr.js +0 -15
  396. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/locales/bootstrap-datepicker.zh-CN.js +0 -14
  397. data/vendor/assets/javascripts/ab_admin/bootstrap-datepicker/locales/bootstrap-datepicker.zh-TW.js +0 -13
  398. data/vendor/assets/javascripts/ab_admin/bootstrap-editable-inline.js +0 -2895
  399. data/vendor/assets/javascripts/ab_admin/bootstrap-editable.js +0 -4523
  400. data/vendor/assets/javascripts/ab_admin/bootstrap-tab-multi.js +0 -135
  401. data/vendor/assets/javascripts/ab_admin/bootstrap-timepicker.js +0 -377
  402. data/vendor/assets/javascripts/ab_admin/fileupload/admin-fileuploader.js.coffee +0 -111
  403. data/vendor/assets/javascripts/ab_admin/fileupload/fileuploader.js +0 -1301
  404. data/vendor/assets/javascripts/ab_admin/jquery.Jcrop.js +0 -1083
  405. data/vendor/assets/javascripts/ab_admin/jquery_nested_form.js.coffee +0 -66
  406. data/vendor/assets/javascripts/bootstrap-wysihtml5/locales/ru.js +0 -48
  407. data/vendor/assets/javascripts/handlebars.min.js +0 -1
  408. data/vendor/assets/javascripts/jquery.cookie.js +0 -42
  409. data/vendor/assets/javascripts/jquery.hotkeys.js +0 -106
  410. data/vendor/assets/javascripts/jquery.pjax.js +0 -688
  411. data/vendor/assets/javascripts/jquery.tmpl.min.js +0 -10
  412. data/vendor/assets/javascripts/jquery.ui.nestedSortable.js +0 -356
  413. data/vendor/assets/javascripts/jquery/jquery-ui.min.js +0 -15
  414. data/vendor/assets/javascripts/jquery/jquery.min.js +0 -4
  415. data/vendor/assets/javascripts/underscore.min.js +0 -5
  416. data/vendor/assets/stylesheets/ab_admin/bootstrap-datepicker.css.scss +0 -274
  417. data/vendor/assets/stylesheets/ab_admin/bootstrap-editable.scss +0 -461
  418. data/vendor/assets/stylesheets/ab_admin/bootstrap-timepicker.css.scss +0 -88
  419. data/vendor/assets/stylesheets/ab_admin/jquery.Jcrop.min.css.scss +0 -28
@@ -1,14 +0,0 @@
1
- /**
2
- * Simplified Chinese translation for bootstrap-datepicker
3
- * Yuan Cheung <advanimal@gmail.com>
4
- */
5
- ;(function($){
6
- $.fn.datepicker.dates['zh-CN'] = {
7
- days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"],
8
- daysShort: ["周日", "周一", "周二", "周三", "周四", "周五", "周六", "周日"],
9
- daysMin: ["日", "一", "二", "三", "四", "五", "六", "日"],
10
- months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
11
- monthsShort: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
12
- today: "今日"
13
- };
14
- }(jQuery));
@@ -1,13 +0,0 @@
1
- /**
2
- * Traditional Chinese translation for bootstrap-datepicker
3
- * Rung-Sheng Jang <daniel@i-trend.co.cc>
4
- */
5
- ;(function($){
6
- $.fn.datepicker.dates['zh-TW'] = {
7
- days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"],
8
- daysShort: ["周日", "周一", "周二", "周三", "周四", "周五", "周六", "周日"],
9
- daysMin: ["日", "一", "二", "三", "四", "五", "六", "日"],
10
- months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"],
11
- monthsShort: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"]
12
- };
13
- }(jQuery));
@@ -1,2895 +0,0 @@
1
- // !!! removed datepicker
2
- /*! X-editable - v1.3.0
3
- * In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery
4
- * http://github.com/vitalets/x-editable
5
- * Copyright (c) 2012 Vitaliy Potapov; Licensed MIT */
6
-
7
- /**
8
- Form with single input element, two buttons and two states: normal/loading.
9
- Applied as jQuery method to DIV tag (not to form tag!). This is because form can be in loading state when spinner shown.
10
- Editableform is linked with one of input types, e.g. 'text', 'select' etc.
11
-
12
- @class editableform
13
- @uses text
14
- @uses textarea
15
- **/
16
- (function ($) {
17
-
18
- var EditableForm = function (div, options) {
19
- this.options = $.extend({}, $.fn.editableform.defaults, options);
20
- this.$div = $(div); //div, containing form. Not form tag! Not editable-element.
21
- if(!this.options.scope) {
22
- this.options.scope = this;
23
- }
24
- this.initInput();
25
- };
26
-
27
- EditableForm.prototype = {
28
- constructor: EditableForm,
29
- initInput: function() { //called once
30
- var TypeConstructor, typeOptions;
31
-
32
- //create input of specified type
33
- if(typeof $.fn.editabletypes[this.options.type] === 'function') {
34
- TypeConstructor = $.fn.editabletypes[this.options.type];
35
- typeOptions = $.fn.editableutils.sliceObj(this.options, $.fn.editableutils.objectKeys(TypeConstructor.defaults));
36
- this.input = new TypeConstructor(typeOptions);
37
- } else {
38
- $.error('Unknown type: '+ this.options.type);
39
- return;
40
- }
41
-
42
- this.value = this.input.str2value(this.options.value);
43
- },
44
- initTemplate: function() {
45
- this.$form = $($.fn.editableform.template);
46
- },
47
- initButtons: function() {
48
- this.$form.find('.editable-buttons').append($.fn.editableform.buttons);
49
- },
50
- /**
51
- Renders editableform
52
-
53
- @method render
54
- **/
55
- render: function() {
56
- this.$loading = $($.fn.editableform.loading);
57
- this.$div.empty().append(this.$loading);
58
- this.showLoading();
59
-
60
- //init form template and buttons
61
- this.initTemplate();
62
- if(this.options.showbuttons) {
63
- this.initButtons();
64
- } else {
65
- this.$form.find('.editable-buttons').remove();
66
- }
67
-
68
- /**
69
- Fired when rendering starts
70
- @event rendering
71
- @param {Object} event event object
72
- **/
73
- this.$div.triggerHandler('rendering');
74
-
75
- //render input
76
- $.when(this.input.render())
77
- .then($.proxy(function () {
78
- //input
79
- this.$form.find('div.editable-input').append(this.input.$input);
80
-
81
- //automatically submit inputs when no buttons shown
82
- if(!this.options.showbuttons) {
83
- this.input.autosubmit();
84
- }
85
-
86
- //"clear" link
87
- if(this.input.$clear) {
88
- this.$form.find('div.editable-input').append($('<div class="editable-clear">').append(this.input.$clear));
89
- }
90
-
91
- //append form to container
92
- this.$div.append(this.$form);
93
-
94
- //attach 'cancel' handler
95
- this.$form.find('.editable-cancel').click($.proxy(this.cancel, this));
96
-
97
- if(this.input.error) {
98
- this.error(this.input.error);
99
- this.$form.find('.editable-submit').attr('disabled', true);
100
- this.input.$input.attr('disabled', true);
101
- //prevent form from submitting
102
- this.$form.submit(function(e){ e.preventDefault(); });
103
- } else {
104
- this.error(false);
105
- this.input.$input.removeAttr('disabled');
106
- this.$form.find('.editable-submit').removeAttr('disabled');
107
- this.input.value2input(this.value);
108
- //attach submit handler
109
- this.$form.submit($.proxy(this.submit, this));
110
- }
111
-
112
- /**
113
- Fired when form is rendered
114
- @event rendered
115
- @param {Object} event event object
116
- **/
117
- this.$div.triggerHandler('rendered');
118
-
119
- this.showForm();
120
- }, this));
121
- },
122
- cancel: function() {
123
- /**
124
- Fired when form was cancelled by user
125
- @event cancel
126
- @param {Object} event event object
127
- **/
128
- this.$div.triggerHandler('cancel');
129
- },
130
- showLoading: function() {
131
- var w;
132
- if(this.$form) {
133
- //set loading size equal to form
134
- this.$loading.width(this.$form.outerWidth());
135
- this.$loading.height(this.$form.outerHeight());
136
- this.$form.hide();
137
- } else {
138
- //stretch loading to fill container width
139
- w = this.$loading.parent().width();
140
- if(w) {
141
- this.$loading.width(w);
142
- }
143
- }
144
- this.$loading.show();
145
- },
146
-
147
- showForm: function(activate) {
148
- this.$loading.hide();
149
- this.$form.show();
150
- if(activate !== false) {
151
- this.input.activate();
152
- }
153
- /**
154
- Fired when form is shown
155
- @event show
156
- @param {Object} event event object
157
- **/
158
- this.$div.triggerHandler('show');
159
- },
160
-
161
- error: function(msg) {
162
- var $group = this.$form.find('.control-group'),
163
- $block = this.$form.find('.editable-error-block');
164
-
165
- if(msg === false) {
166
- $group.removeClass($.fn.editableform.errorGroupClass);
167
- $block.removeClass($.fn.editableform.errorBlockClass).empty().hide();
168
- } else {
169
- $group.addClass($.fn.editableform.errorGroupClass);
170
- $block.addClass($.fn.editableform.errorBlockClass).text(msg).show();
171
- }
172
- },
173
-
174
- submit: function(e) {
175
- e.stopPropagation();
176
- e.preventDefault();
177
-
178
- var error,
179
- newValue = this.input.input2value(); //get new value from input
180
-
181
- //validation
182
- if (error = this.validate(newValue)) {
183
- this.error(error);
184
- this.showForm();
185
- return;
186
- }
187
-
188
- //if value not changed --> trigger 'nochange' event and return
189
- /*jslint eqeq: true*/
190
- if (!this.options.savenochange && this.input.value2str(newValue) == this.input.value2str(this.value)) {
191
- /*jslint eqeq: false*/
192
- /**
193
- Fired when value not changed but form is submitted. Requires savenochange = false.
194
- @event nochange
195
- @param {Object} event event object
196
- **/
197
- this.$div.triggerHandler('nochange');
198
- return;
199
- }
200
-
201
- //sending data to server
202
- $.when(this.save(newValue))
203
- .done($.proxy(function(response) {
204
- //run success callback
205
- var res = typeof this.options.success === 'function' ? this.options.success.call(this.options.scope, response, newValue) : null;
206
-
207
- //if success callback returns false --> keep form open and do not activate input
208
- if(res === false) {
209
- this.error(false);
210
- this.showForm(false);
211
- return;
212
- }
213
-
214
- //if success callback returns string --> keep form open, show error and activate input
215
- if(typeof res === 'string') {
216
- this.error(res);
217
- this.showForm();
218
- return;
219
- }
220
-
221
- //if success callback returns object like {newValue: <something>} --> use that value instead of submitted
222
- if(res && typeof res === 'object' && res.hasOwnProperty('newValue')) {
223
- newValue = res.newValue;
224
- }
225
-
226
- //clear error message
227
- this.error(false);
228
- this.value = newValue;
229
- /**
230
- Fired when form is submitted
231
- @event save
232
- @param {Object} event event object
233
- @param {Object} params additional params
234
- @param {mixed} params.newValue submitted value
235
- @param {Object} params.response ajax response
236
-
237
- @example
238
- $('#form-div').on('save'), function(e, params){
239
- if(params.newValue === 'username') {...}
240
- });
241
- **/
242
- this.$div.triggerHandler('save', {newValue: newValue, response: response});
243
- }, this))
244
- .fail($.proxy(function(xhr) {
245
- this.error(typeof xhr === 'string' ? xhr : xhr.responseText || xhr.statusText || 'Unknown error!');
246
- this.showForm();
247
- }, this));
248
- },
249
-
250
- save: function(newValue) {
251
- //convert value for submitting to server
252
- var submitValue = this.input.value2submit(newValue);
253
-
254
- //try parse composite pk defined as json string in data-pk
255
- this.options.pk = $.fn.editableutils.tryParseJson(this.options.pk, true);
256
-
257
- var pk = (typeof this.options.pk === 'function') ? this.options.pk.call(this.options.scope) : this.options.pk,
258
- send = !!(typeof this.options.url === 'function' || (this.options.url && ((this.options.send === 'always') || (this.options.send === 'auto' && pk)))),
259
- params;
260
-
261
- if (send) { //send to server
262
- this.showLoading();
263
-
264
- //standard params
265
- params = {
266
- name: this.options.name || '',
267
- value: submitValue,
268
- pk: pk
269
- };
270
-
271
- //additional params
272
- if(typeof this.options.params === 'function') {
273
- params = this.options.params.call(this.options.scope, params);
274
- } else {
275
- //try parse json in single quotes (from data-params attribute)
276
- this.options.params = $.fn.editableutils.tryParseJson(this.options.params, true);
277
- $.extend(params, this.options.params);
278
- }
279
-
280
- if(typeof this.options.url === 'function') { //user's function
281
- return this.options.url.call(this.options.scope, params);
282
- } else {
283
- //send ajax to server and return deferred object
284
- return $.ajax($.extend({
285
- url : this.options.url,
286
- data : params,
287
- type : 'POST'
288
- }, this.options.ajaxOptions));
289
- }
290
- }
291
- },
292
-
293
- validate: function (value) {
294
- if (value === undefined) {
295
- value = this.value;
296
- }
297
- if (typeof this.options.validate === 'function') {
298
- return this.options.validate.call(this.options.scope, value);
299
- }
300
- },
301
-
302
- option: function(key, value) {
303
- this.options[key] = value;
304
- if(key === 'value') {
305
- this.setValue(value);
306
- }
307
- },
308
-
309
- setValue: function(value, convertStr) {
310
- if(convertStr) {
311
- this.value = this.input.str2value(value);
312
- } else {
313
- this.value = value;
314
- }
315
- }
316
- };
317
-
318
- /*
319
- Initialize editableform. Applied to jQuery object.
320
-
321
- @method $().editableform(options)
322
- @params {Object} options
323
- @example
324
- var $form = $('&lt;div&gt;').editableform({
325
- type: 'text',
326
- name: 'username',
327
- url: '/post',
328
- value: 'vitaliy'
329
- });
330
-
331
- //to display form you should call 'render' method
332
- $form.editableform('render');
333
- */
334
- $.fn.editableform = function (option) {
335
- var args = arguments;
336
- return this.each(function () {
337
- var $this = $(this),
338
- data = $this.data('editableform'),
339
- options = typeof option === 'object' && option;
340
- if (!data) {
341
- $this.data('editableform', (data = new EditableForm(this, options)));
342
- }
343
-
344
- if (typeof option === 'string') { //call method
345
- data[option].apply(data, Array.prototype.slice.call(args, 1));
346
- }
347
- });
348
- };
349
-
350
- //keep link to constructor to allow inheritance
351
- $.fn.editableform.Constructor = EditableForm;
352
-
353
- //defaults
354
- $.fn.editableform.defaults = {
355
- /* see also defaults for input */
356
-
357
- /**
358
- Type of input. Can be <code>text|textarea|select|date|checklist</code>
359
-
360
- @property type
361
- @type string
362
- @default 'text'
363
- **/
364
- type: 'text',
365
- /**
366
- Url for submit, e.g. <code>'/post'</code>
367
- If function - it will be called instead of ajax. Function can return deferred object to run fail/done callbacks.
368
-
369
- @property url
370
- @type string|function
371
- @default null
372
- @example
373
- url: function(params) {
374
- if(params.value === 'abc') {
375
- var d = new $.Deferred;
376
- return d.reject('field cannot be "abc"'); //returning error via deferred object
377
- } else {
378
- someModel.set(params.name, params.value); //save data in some js model
379
- }
380
- }
381
- **/
382
- url:null,
383
- /**
384
- Additional params for submit. If defined as <code>object</code> - it is **appended** to original ajax data (pk, name and value).
385
- If defined as <code>function</code> - returned object **overwrites** original ajax data.
386
- @example
387
- params: function(params) {
388
- //originally params contain pk, name and value
389
- params.a = 1;
390
- return params;
391
- }
392
-
393
- @property params
394
- @type object|function
395
- @default null
396
- **/
397
- params:null,
398
- /**
399
- Name of field. Will be submitted on server. Can be taken from <code>id</code> attribute
400
-
401
- @property name
402
- @type string
403
- @default null
404
- **/
405
- name: null,
406
- /**
407
- Primary key of editable object (e.g. record id in database). For composite keys use object, e.g. <code>{id: 1, lang: 'en'}</code>.
408
- Can be calculated dynamically via function.
409
-
410
- @property pk
411
- @type string|object|function
412
- @default null
413
- **/
414
- pk: null,
415
- /**
416
- Initial value. If not defined - will be taken from element's content.
417
- For __select__ type should be defined (as it is ID of shown text).
418
-
419
- @property value
420
- @type string|object
421
- @default null
422
- **/
423
- value: null,
424
- /**
425
- Strategy for sending data on server. Can be <code>auto|always|never</code>.
426
- When 'auto' data will be sent on server only if pk defined, otherwise new value will be stored in element.
427
-
428
- @property send
429
- @type string
430
- @default 'auto'
431
- **/
432
- send: 'auto',
433
- /**
434
- Function for client-side validation. If returns string - means validation not passed and string showed as error.
435
-
436
- @property validate
437
- @type function
438
- @default null
439
- @example
440
- validate: function(value) {
441
- if($.trim(value) == '') {
442
- return 'This field is required';
443
- }
444
- }
445
- **/
446
- validate: null,
447
- /**
448
- Success callback. Called when value successfully sent on server and **response status = 200**.
449
- Useful to work with json response. For example, if your backend response can be <code>{success: true}</code>
450
- or <code>{success: false, msg: "server error"}</code> you can check it inside this callback.
451
- If it returns **string** - means error occured and string is shown as error message.
452
- If it returns **object like** <code>{newValue: &lt;something&gt;}</code> - it overwrites value, submitted by user.
453
- Otherwise newValue simply rendered into element.
454
-
455
- @property success
456
- @type function
457
- @default null
458
- @example
459
- success: function(response, newValue) {
460
- if(!response.success) return response.msg;
461
- }
462
- **/
463
- success: null,
464
- /**
465
- Additional options for ajax request.
466
- List of values: http://api.jquery.com/jQuery.ajax
467
-
468
- @property ajaxOptions
469
- @type object
470
- @default null
471
- @since 1.1.1
472
- **/
473
- ajaxOptions: null,
474
- /**
475
- Whether to show buttons or not.
476
- Form without buttons can be auto-submitted by input or by onblur = 'submit'.
477
- @example
478
- ajaxOptions: {
479
- method: 'PUT',
480
- dataType: 'xml'
481
- }
482
-
483
- @property showbuttons
484
- @type boolean
485
- @default true
486
- @since 1.1.1
487
- **/
488
- showbuttons: true,
489
- /**
490
- Scope for callback methods (success, validate).
491
- If <code>null</code> means editableform instance itself.
492
-
493
- @property scope
494
- @type DOMElement|object
495
- @default null
496
- @since 1.2.0
497
- @private
498
- **/
499
- scope: null,
500
- /**
501
- Whether to save or cancel value when it was not changed but form was submitted
502
-
503
- @property savenochange
504
- @type boolean
505
- @default false
506
- @since 1.2.0
507
- **/
508
- savenochange: false
509
- };
510
-
511
- /*
512
- Note: following params could redefined in engine: bootstrap or jqueryui:
513
- Classes 'control-group' and 'editable-error-block' must always present!
514
- */
515
- $.fn.editableform.template = '<form class="form-inline editableform">'+
516
- '<div class="control-group">' +
517
- '<div><div class="editable-input"></div><div class="editable-buttons"></div></div>'+
518
- '<div class="editable-error-block"></div>' +
519
- '</div>' +
520
- '</form>';
521
-
522
- //loading div
523
- $.fn.editableform.loading = '<div class="editableform-loading"></div>';
524
-
525
- //buttons
526
- $.fn.editableform.buttons = '<button type="submit" class="editable-submit">ok</button>'+
527
- '<button type="button" class="editable-cancel">cancel</button>';
528
-
529
- //error class attached to control-group
530
- $.fn.editableform.errorGroupClass = null;
531
-
532
- //error class attached to editable-error-block
533
- $.fn.editableform.errorBlockClass = 'editable-error';
534
- }(window.jQuery));
535
- /**
536
- * EditableForm utilites
537
- */
538
- (function ($) {
539
- //utils
540
- $.fn.editableutils = {
541
- /**
542
- * classic JS inheritance function
543
- */
544
- inherit: function (Child, Parent) {
545
- var F = function() { };
546
- F.prototype = Parent.prototype;
547
- Child.prototype = new F();
548
- Child.prototype.constructor = Child;
549
- Child.superclass = Parent.prototype;
550
- },
551
-
552
- /**
553
- * set caret position in input
554
- * see http://stackoverflow.com/questions/499126/jquery-set-cursor-position-in-text-area
555
- */
556
- setCursorPosition: function(elem, pos) {
557
- if (elem.setSelectionRange) {
558
- elem.setSelectionRange(pos, pos);
559
- } else if (elem.createTextRange) {
560
- var range = elem.createTextRange();
561
- range.collapse(true);
562
- range.moveEnd('character', pos);
563
- range.moveStart('character', pos);
564
- range.select();
565
- }
566
- },
567
-
568
- /**
569
- * function to parse JSON in *single* quotes. (jquery automatically parse only double quotes)
570
- * That allows such code as: <a data-source="{'a': 'b', 'c': 'd'}">
571
- * safe = true --> means no exception will be thrown
572
- * for details see http://stackoverflow.com/questions/7410348/how-to-set-json-format-to-html5-data-attributes-in-the-jquery
573
- */
574
- tryParseJson: function(s, safe) {
575
- if (typeof s === 'string' && s.length && s.match(/^[\{\[].*[\}\]]$/)) {
576
- if (safe) {
577
- try {
578
- /*jslint evil: true*/
579
- s = (new Function('return ' + s))();
580
- /*jslint evil: false*/
581
- } catch (e) {} finally {
582
- return s;
583
- }
584
- } else {
585
- /*jslint evil: true*/
586
- s = (new Function('return ' + s))();
587
- /*jslint evil: false*/
588
- }
589
- }
590
- return s;
591
- },
592
-
593
- /**
594
- * slice object by specified keys
595
- */
596
- sliceObj: function(obj, keys, caseSensitive /* default: false */) {
597
- var key, keyLower, newObj = {};
598
-
599
- if (!$.isArray(keys) || !keys.length) {
600
- return newObj;
601
- }
602
-
603
- for (var i = 0; i < keys.length; i++) {
604
- key = keys[i];
605
- if (obj.hasOwnProperty(key)) {
606
- newObj[key] = obj[key];
607
- }
608
-
609
- if(caseSensitive === true) {
610
- continue;
611
- }
612
-
613
- //when getting data-* attributes via $.data() it's converted to lowercase.
614
- //details: http://stackoverflow.com/questions/7602565/using-data-attributes-with-jquery
615
- //workaround is code below.
616
- keyLower = key.toLowerCase();
617
- if (obj.hasOwnProperty(keyLower)) {
618
- newObj[key] = obj[keyLower];
619
- }
620
- }
621
-
622
- return newObj;
623
- },
624
-
625
- /**
626
- * exclude complex objects from $.data() before pass to config
627
- */
628
- getConfigData: function($element) {
629
- var data = {};
630
- $.each($element.data(), function(k, v) {
631
- if(typeof v !== 'object' || (v && typeof v === 'object' && v.constructor === Object)) {
632
- data[k] = v;
633
- }
634
- });
635
- return data;
636
- },
637
-
638
- objectKeys: function(o) {
639
- if (Object.keys) {
640
- return Object.keys(o);
641
- } else {
642
- if (o !== Object(o)) {
643
- throw new TypeError('Object.keys called on a non-object');
644
- }
645
- var k=[], p;
646
- for (p in o) {
647
- if (Object.prototype.hasOwnProperty.call(o,p)) {
648
- k.push(p);
649
- }
650
- }
651
- return k;
652
- }
653
-
654
- },
655
-
656
- /**
657
- method to escape html.
658
- **/
659
- escape: function(str) {
660
- return $('<div>').text(str).html();
661
- }
662
- };
663
- }(window.jQuery));
664
- /**
665
- Attaches stand-alone container with editable-form to HTML element. Element is used only for positioning, value is not stored anywhere.<br>
666
- This method applied internally in <code>$().editable()</code>. You should subscribe on it's events (save / cancel) to get profit of it.<br>
667
- Final realization can be different: bootstrap-popover, jqueryui-tooltip, poshytip, inline-div. It depends on which js file you include.<br>
668
- Applied as jQuery method.
669
-
670
- @class editableContainer
671
- @uses editableform
672
- **/
673
- (function ($) {
674
-
675
- var EditableContainer = function (element, options) {
676
- this.init(element, options);
677
- };
678
-
679
- //methods
680
- EditableContainer.prototype = {
681
- containerName: null, //tbd in child class
682
- innerCss: null, //tbd in child class
683
- init: function(element, options) {
684
- this.$element = $(element);
685
- //todo: what is in priority: data or js?
686
- this.options = $.extend({}, $.fn.editableContainer.defaults, $.fn.editableutils.getConfigData(this.$element), options);
687
- this.splitOptions();
688
- this.initContainer();
689
-
690
- //bind 'destroyed' listener to destroy container when element is removed from dom
691
- this.$element.on('destroyed', $.proxy(function(){
692
- this.destroy();
693
- }, this));
694
-
695
- //attach document handlers (once)
696
- if(!$(document).data('editable-handlers-attached')) {
697
- //close all on escape
698
- $(document).on('keyup.editable', function (e) {
699
- if (e.which === 27) {
700
- $('.editable-open').editableContainer('hide');
701
- //todo: return focus on element
702
- }
703
- });
704
-
705
- //close containers when click outside
706
- $(document).on('click.editable', function(e) {
707
- var $target = $(e.target);
708
-
709
- //if click inside some editableContainer --> no nothing
710
- if($target.is('.editable-container') || $target.parents('.editable-container').length || $target.parents('.ui-datepicker-header').length) {
711
- return;
712
- } else {
713
- //close all open containers (except one)
714
- EditableContainer.prototype.closeOthers(e.target);
715
- }
716
- });
717
-
718
- $(document).data('editable-handlers-attached', true);
719
- }
720
- },
721
-
722
- //split options on containerOptions and formOptions
723
- splitOptions: function() {
724
- this.containerOptions = {};
725
- this.formOptions = {};
726
- var cDef = $.fn[this.containerName].defaults;
727
- for(var k in this.options) {
728
- if(k in cDef) {
729
- this.containerOptions[k] = this.options[k];
730
- } else {
731
- this.formOptions[k] = this.options[k];
732
- }
733
- }
734
- },
735
-
736
- initContainer: function(){
737
- this.call(this.containerOptions);
738
- },
739
-
740
- initForm: function() {
741
- this.formOptions.scope = this.$element[0]; //set scope of form callbacks to element
742
- this.$form = $('<div>')
743
- .editableform(this.formOptions)
744
- .on({
745
- save: $.proxy(this.save, this),
746
- cancel: $.proxy(function(){ this.hide('cancel'); }, this),
747
- nochange: $.proxy(function(){ this.hide('nochange'); }, this),
748
- show: $.proxy(this.setPosition, this), //re-position container every time form is shown (occurs each time after loading state)
749
- rendering: $.proxy(this.setPosition, this), //this allows to place container correctly when loading shown
750
- rendered: $.proxy(function(){
751
- /**
752
- Fired when container is shown and form is rendered (for select will wait for loading dropdown options)
753
-
754
- @event shown
755
- @param {Object} event event object
756
- @example
757
- $('#username').on('shown', function() {
758
- var $tip = $(this).data('editableContainer').tip();
759
- $tip.find('input').val('overwriting value of input..');
760
- });
761
- **/
762
- this.$element.triggerHandler('shown');
763
- }, this)
764
- });
765
- return this.$form;
766
- },
767
-
768
- /*
769
- Returns jquery object of container
770
- @method tip()
771
- */
772
- tip: function() {
773
- return this.container().$tip;
774
- },
775
-
776
- container: function() {
777
- return this.$element.data(this.containerName);
778
- },
779
-
780
- call: function() {
781
- this.$element[this.containerName].apply(this.$element, arguments);
782
- },
783
-
784
- /**
785
- Shows container with form
786
- @method show()
787
- @param {boolean} closeAll Whether to close all other editable containers when showing this one. Default true.
788
- **/
789
- show: function (closeAll) {
790
- this.$element.addClass('editable-open');
791
- if(closeAll !== false) {
792
- //close all open containers (except this)
793
- this.closeOthers(this.$element[0]);
794
- }
795
-
796
- this.innerShow();
797
- },
798
-
799
- /* internal show method. To be overwritten in child classes */
800
- innerShow: function () {
801
- this.call('show');
802
- this.tip().addClass('editable-container');
803
- this.initForm();
804
- this.tip().find(this.innerCss).empty().append(this.$form);
805
- this.$form.editableform('render');
806
- },
807
-
808
- /**
809
- Hides container with form
810
- @method hide()
811
- @param {string} reason Reason caused hiding. Can be <code>save|cancel|onblur|nochange|undefined (=manual)</code>
812
- **/
813
- hide: function(reason) {
814
- if(!this.tip() || !this.tip().is(':visible') || !this.$element.hasClass('editable-open')) {
815
- return;
816
- }
817
- this.$element.removeClass('editable-open');
818
- this.innerHide();
819
- /**
820
- Fired when container was hidden. It occurs on both save or cancel.
821
-
822
- @event hidden
823
- @param {object} event event object
824
- @param {string} reason Reason caused hiding. Can be <code>save|cancel|onblur|nochange|undefined (=manual)</code>
825
- @example
826
- $('#username').on('hidden', function(e, reason) {
827
- if(reason === 'save' || reason === 'cancel') {
828
- //auto-open next editable
829
- $(this).closest('tr').next().find('.editable').editable('show');
830
- }
831
- });
832
- **/
833
- this.$element.triggerHandler('hidden', reason);
834
- },
835
-
836
- /* internal hide method. To be overwritten in child classes */
837
- innerHide: function () {
838
- this.call('hide');
839
- },
840
-
841
- /**
842
- Toggles container visibility (show / hide)
843
- @method toggle()
844
- @param {boolean} closeAll Whether to close all other editable containers when showing this one. Default true.
845
- **/
846
- toggle: function(closeAll) {
847
- if(this.tip && this.tip().is(':visible')) {
848
- this.hide();
849
- } else {
850
- this.show(closeAll);
851
- }
852
- },
853
-
854
- /*
855
- Updates the position of container when content changed.
856
- @method setPosition()
857
- */
858
- setPosition: function() {
859
- //tbd in child class
860
- },
861
-
862
- save: function(e, params) {
863
- this.hide('save');
864
- /**
865
- Fired when new value was submitted. You can use <code>$(this).data('editableContainer')</code> inside handler to access to editableContainer instance
866
-
867
- @event save
868
- @param {Object} event event object
869
- @param {Object} params additional params
870
- @param {mixed} params.newValue submitted value
871
- @param {Object} params.response ajax response
872
- @example
873
- $('#username').on('save', function(e, params) {
874
- //assuming server response: '{success: true}'
875
- var pk = $(this).data('editableContainer').options.pk;
876
- if(params.response && params.response.success) {
877
- alert('value: ' + params.newValue + ' with pk: ' + pk + ' saved!');
878
- } else {
879
- alert('error!');
880
- }
881
- });
882
- **/
883
- this.$element.triggerHandler('save', params);
884
- },
885
-
886
- /**
887
- Sets new option
888
-
889
- @method option(key, value)
890
- @param {string} key
891
- @param {mixed} value
892
- **/
893
- option: function(key, value) {
894
- this.options[key] = value;
895
- if(key in this.containerOptions) {
896
- this.containerOptions[key] = value;
897
- this.setContainerOption(key, value);
898
- } else {
899
- this.formOptions[key] = value;
900
- if(this.$form) {
901
- this.$form.editableform('option', key, value);
902
- }
903
- }
904
- },
905
-
906
- setContainerOption: function(key, value) {
907
- this.call('option', key, value);
908
- },
909
-
910
- /**
911
- Destroys the container instance
912
- @method destroy()
913
- **/
914
- destroy: function() {
915
- this.call('destroy');
916
- },
917
-
918
- /*
919
- Closes other containers except one related to passed element.
920
- Other containers can be cancelled or submitted (depends on onblur option)
921
- */
922
- closeOthers: function(element) {
923
- $('.editable-open').each(function(i, el){
924
- //do nothing with passed element and it's children
925
- if(el === element || $(el).find(element).length) {
926
- return;
927
- }
928
-
929
- //otherwise cancel or submit all open containers
930
- var $el = $(el),
931
- ec = $el.data('editableContainer');
932
-
933
- if(!ec) {
934
- return;
935
- }
936
-
937
- if(ec.options.onblur === 'cancel') {
938
- $el.data('editableContainer').hide('onblur');
939
- } else if(ec.options.onblur === 'submit') {
940
- $el.data('editableContainer').tip().find('form').submit();
941
- }
942
- });
943
-
944
- },
945
-
946
- /**
947
- Activates input of visible container (e.g. set focus)
948
- @method activate()
949
- **/
950
- activate: function() {
951
- if(this.tip && this.tip().is(':visible') && this.$form) {
952
- this.$form.data('editableform').input.activate();
953
- }
954
- }
955
-
956
- };
957
-
958
- /**
959
- jQuery method to initialize editableContainer.
960
-
961
- @method $().editableContainer(options)
962
- @params {Object} options
963
- @example
964
- $('#edit').editableContainer({
965
- type: 'text',
966
- url: '/post',
967
- pk: 1,
968
- value: 'hello'
969
- });
970
- **/
971
- $.fn.editableContainer = function (option) {
972
- var args = arguments;
973
- return this.each(function () {
974
- var $this = $(this),
975
- dataKey = 'editableContainer',
976
- data = $this.data(dataKey),
977
- options = typeof option === 'object' && option;
978
-
979
- if (!data) {
980
- $this.data(dataKey, (data = new EditableContainer(this, options)));
981
- }
982
-
983
- if (typeof option === 'string') { //call method
984
- data[option].apply(data, Array.prototype.slice.call(args, 1));
985
- }
986
- });
987
- };
988
-
989
- //store constructor
990
- $.fn.editableContainer.Constructor = EditableContainer;
991
-
992
- //defaults
993
- $.fn.editableContainer.defaults = {
994
- /**
995
- Initial value of form input
996
-
997
- @property value
998
- @type mixed
999
- @default null
1000
- @private
1001
- **/
1002
- value: null,
1003
- /**
1004
- Placement of container relative to element. Can be <code>top|right|bottom|left</code>. Not used for inline container.
1005
-
1006
- @property placement
1007
- @type string
1008
- @default 'top'
1009
- **/
1010
- placement: 'top',
1011
- /**
1012
- Whether to hide container on save/cancel.
1013
-
1014
- @property autohide
1015
- @type boolean
1016
- @default true
1017
- @private
1018
- **/
1019
- autohide: true,
1020
- /**
1021
- Action when user clicks outside the container. Can be <code>cancel|submit|ignore</code>.
1022
- Setting <code>ignore</code> allows to have several containers open.
1023
-
1024
- @property onblur
1025
- @type string
1026
- @default 'cancel'
1027
- @since 1.1.1
1028
- **/
1029
- onblur: 'cancel'
1030
- };
1031
-
1032
- /*
1033
- * workaround to have 'destroyed' event to destroy popover when element is destroyed
1034
- * see http://stackoverflow.com/questions/2200494/jquery-trigger-event-when-an-element-is-removed-from-the-dom
1035
- */
1036
- jQuery.event.special.destroyed = {
1037
- remove: function(o) {
1038
- if (o.handler) {
1039
- o.handler();
1040
- }
1041
- }
1042
- };
1043
-
1044
- }(window.jQuery));
1045
-
1046
- /**
1047
- Makes editable any HTML element on the page. Applied as jQuery method.
1048
-
1049
- @class editable
1050
- @uses editableContainer
1051
- **/
1052
- (function ($) {
1053
-
1054
- var Editable = function (element, options) {
1055
- this.$element = $(element);
1056
- this.options = $.extend({}, $.fn.editable.defaults, $.fn.editableutils.getConfigData(this.$element), options);
1057
- this.init();
1058
- };
1059
-
1060
- Editable.prototype = {
1061
- constructor: Editable,
1062
- init: function () {
1063
- var TypeConstructor,
1064
- isValueByText = false,
1065
- doAutotext,
1066
- finalize;
1067
-
1068
- //editableContainer must be defined
1069
- if(!$.fn.editableContainer) {
1070
- $.error('You must define $.fn.editableContainer via including corresponding file (e.g. editable-popover.js)');
1071
- return;
1072
- }
1073
-
1074
- //name
1075
- this.options.name = this.options.name || this.$element.attr('id');
1076
-
1077
- //create input of specified type. Input will be used for converting value, not in form
1078
- if(typeof $.fn.editabletypes[this.options.type] === 'function') {
1079
- TypeConstructor = $.fn.editabletypes[this.options.type];
1080
- this.typeOptions = $.fn.editableutils.sliceObj(this.options, $.fn.editableutils.objectKeys(TypeConstructor.defaults));
1081
- this.input = new TypeConstructor(this.typeOptions);
1082
- } else {
1083
- $.error('Unknown type: '+ this.options.type);
1084
- return;
1085
- }
1086
-
1087
- //set value from settings or by element's text
1088
- if (this.options.value === undefined || this.options.value === null) {
1089
- this.value = this.input.html2value($.trim(this.$element.html()));
1090
- isValueByText = true;
1091
- } else {
1092
- /*
1093
- value can be string when received from 'data-value' attribute
1094
- for complext objects value can be set as json string in data-value attribute,
1095
- e.g. data-value="{city: 'Moscow', street: 'Lenina'}"
1096
- */
1097
- this.options.value = $.fn.editableutils.tryParseJson(this.options.value, true);
1098
- if(typeof this.options.value === 'string') {
1099
- this.value = this.input.str2value(this.options.value);
1100
- } else {
1101
- this.value = this.options.value;
1102
- }
1103
- }
1104
-
1105
- //add 'editable' class to every editable element
1106
- this.$element.addClass('editable');
1107
-
1108
- //attach handler activating editable. In disabled mode it just prevent default action (useful for links)
1109
- if(this.options.toggle !== 'manual') {
1110
- this.$element.addClass('editable-click');
1111
- this.$element.on(this.options.toggle + '.editable', $.proxy(function(e){
1112
- e.preventDefault();
1113
- //stop propagation not required anymore because in document click handler it checks event target
1114
- //e.stopPropagation();
1115
-
1116
- if(this.options.toggle === 'mouseenter') {
1117
- //for hover only show container
1118
- this.show();
1119
- } else {
1120
- //when toggle='click' we should not close all other containers as they will be closed automatically in document click listener
1121
- var closeAll = (this.options.toggle !== 'click');
1122
- this.toggle(closeAll);
1123
- }
1124
- }, this));
1125
- } else {
1126
- this.$element.attr('tabindex', -1); //do not stop focus on element when toggled manually
1127
- }
1128
-
1129
- //check conditions for autotext:
1130
- //if value was generated by text or value is empty, no sense to run autotext
1131
- doAutotext = !isValueByText && this.value !== null && this.value !== undefined;
1132
- doAutotext &= (this.options.autotext === 'always') || (this.options.autotext === 'auto' && !this.$element.text().length);
1133
- $.when(doAutotext ? this.render() : true).then($.proxy(function() {
1134
- if(this.options.disabled) {
1135
- this.disable();
1136
- } else {
1137
- this.enable();
1138
- }
1139
- /**
1140
- Fired when element was initialized by editable method.
1141
-
1142
- @event init
1143
- @param {Object} event event object
1144
- @param {Object} editable editable instance
1145
- @since 1.2.0
1146
- **/
1147
- this.$element.triggerHandler('init', this);
1148
- }, this));
1149
- },
1150
-
1151
- /*
1152
- Renders value into element's text.
1153
- Can call custom display method from options.
1154
- Can return deferred object.
1155
- @method render()
1156
- */
1157
- render: function() {
1158
- //do not display anything
1159
- if(this.options.display === false) {
1160
- return;
1161
- }
1162
- //if it is input with source, we pass callback in third param to be called when source is loaded
1163
- if(this.input.options.hasOwnProperty('source')) {
1164
- return this.input.value2html(this.value, this.$element[0], this.options.display);
1165
- //if display method defined --> use it
1166
- } else if(typeof this.options.display === 'function') {
1167
- return this.options.display.call(this.$element[0], this.value);
1168
- //else use input's original value2html() method
1169
- } else {
1170
- return this.input.value2html(this.value, this.$element[0]);
1171
- }
1172
- },
1173
-
1174
- /**
1175
- Enables editable
1176
- @method enable()
1177
- **/
1178
- enable: function() {
1179
- this.options.disabled = false;
1180
- this.$element.removeClass('editable-disabled');
1181
- this.handleEmpty();
1182
- if(this.options.toggle !== 'manual') {
1183
- if(this.$element.attr('tabindex') === '-1') {
1184
- this.$element.removeAttr('tabindex');
1185
- }
1186
- }
1187
- },
1188
-
1189
- /**
1190
- Disables editable
1191
- @method disable()
1192
- **/
1193
- disable: function() {
1194
- this.options.disabled = true;
1195
- this.hide();
1196
- this.$element.addClass('editable-disabled');
1197
- this.handleEmpty();
1198
- //do not stop focus on this element
1199
- this.$element.attr('tabindex', -1);
1200
- },
1201
-
1202
- /**
1203
- Toggles enabled / disabled state of editable element
1204
- @method toggleDisabled()
1205
- **/
1206
- toggleDisabled: function() {
1207
- if(this.options.disabled) {
1208
- this.enable();
1209
- } else {
1210
- this.disable();
1211
- }
1212
- },
1213
-
1214
- /**
1215
- Sets new option
1216
-
1217
- @method option(key, value)
1218
- @param {string|object} key option name or object with several options
1219
- @param {mixed} value option new value
1220
- @example
1221
- $('.editable').editable('option', 'pk', 2);
1222
- **/
1223
- option: function(key, value) {
1224
- //set option(s) by object
1225
- if(key && typeof key === 'object') {
1226
- $.each(key, $.proxy(function(k, v){
1227
- this.option($.trim(k), v);
1228
- }, this));
1229
- return;
1230
- }
1231
-
1232
- //set option by string
1233
- this.options[key] = value;
1234
-
1235
- //disabled
1236
- if(key === 'disabled') {
1237
- if(value) {
1238
- this.disable();
1239
- } else {
1240
- this.enable();
1241
- }
1242
- return;
1243
- }
1244
-
1245
- //value
1246
- if(key === 'value') {
1247
- this.setValue(value);
1248
- }
1249
-
1250
- //transfer new option to container!
1251
- if(this.container) {
1252
- this.container.option(key, value);
1253
- }
1254
- },
1255
-
1256
- /*
1257
- * set emptytext if element is empty (reverse: remove emptytext if needed)
1258
- */
1259
- handleEmpty: function () {
1260
- //do not handle empty if we do not display anything
1261
- if(this.options.display === false) {
1262
- return;
1263
- }
1264
-
1265
- var emptyClass = 'editable-empty';
1266
- //emptytext shown only for enabled
1267
- if(!this.options.disabled) {
1268
- if ($.trim(this.$element.text()) === '') {
1269
- this.$element.addClass(emptyClass).text(this.options.emptytext);
1270
- } else {
1271
- this.$element.removeClass(emptyClass);
1272
- }
1273
- } else {
1274
- //below required if element disable property was changed
1275
- if(this.$element.hasClass(emptyClass)) {
1276
- this.$element.empty();
1277
- this.$element.removeClass(emptyClass);
1278
- }
1279
- }
1280
- },
1281
-
1282
- /**
1283
- Shows container with form
1284
- @method show()
1285
- @param {boolean} closeAll Whether to close all other editable containers when showing this one. Default true.
1286
- **/
1287
- show: function (closeAll) {
1288
- if(this.options.disabled) {
1289
- return;
1290
- }
1291
-
1292
- //init editableContainer: popover, tooltip, inline, etc..
1293
- if(!this.container) {
1294
- var containerOptions = $.extend({}, this.options, {
1295
- value: this.value
1296
- });
1297
- this.$element.editableContainer(containerOptions);
1298
- this.$element.on("save.internal", $.proxy(this.save, this));
1299
- this.container = this.$element.data('editableContainer');
1300
- } else if(this.container.tip().is(':visible')) {
1301
- return;
1302
- }
1303
-
1304
- //show container
1305
- this.container.show(closeAll);
1306
- },
1307
-
1308
- /**
1309
- Hides container with form
1310
- @method hide()
1311
- **/
1312
- hide: function () {
1313
- if(this.container) {
1314
- this.container.hide();
1315
- }
1316
- },
1317
-
1318
- /**
1319
- Toggles container visibility (show / hide)
1320
- @method toggle()
1321
- @param {boolean} closeAll Whether to close all other editable containers when showing this one. Default true.
1322
- **/
1323
- toggle: function(closeAll) {
1324
- if(this.container && this.container.tip().is(':visible')) {
1325
- this.hide();
1326
- } else {
1327
- this.show(closeAll);
1328
- }
1329
- },
1330
-
1331
- /*
1332
- * called when form was submitted
1333
- */
1334
- save: function(e, params) {
1335
- //if url is not user's function and value was not sent to server and value changed --> mark element with unsaved css.
1336
- if(typeof this.options.url !== 'function' && this.options.display !== false && params.response === undefined && this.input.value2str(this.value) !== this.input.value2str(params.newValue)) {
1337
- this.$element.addClass('editable-unsaved');
1338
- } else {
1339
- this.$element.removeClass('editable-unsaved');
1340
- }
1341
-
1342
- // this.hide();
1343
- this.setValue(params.newValue);
1344
-
1345
- /**
1346
- Fired when new value was submitted. You can use <code>$(this).data('editable')</code> to access to editable instance
1347
-
1348
- @event save
1349
- @param {Object} event event object
1350
- @param {Object} params additional params
1351
- @param {mixed} params.newValue submitted value
1352
- @param {Object} params.response ajax response
1353
- @example
1354
- $('#username').on('save', function(e, params) {
1355
- //assuming server response: '{success: true}'
1356
- var pk = $(this).data('editable').options.pk;
1357
- if(params.response && params.response.success) {
1358
- alert('value: ' + params.newValue + ' with pk: ' + pk + ' saved!');
1359
- } else {
1360
- alert('error!');
1361
- }
1362
- });
1363
- **/
1364
- //event itself is triggered by editableContainer. Description here is only for documentation
1365
- },
1366
-
1367
- validate: function () {
1368
- if (typeof this.options.validate === 'function') {
1369
- return this.options.validate.call(this, this.value);
1370
- }
1371
- },
1372
-
1373
- /**
1374
- Sets new value of editable
1375
- @method setValue(value, convertStr)
1376
- @param {mixed} value new value
1377
- @param {boolean} convertStr whether to convert value from string to internal format
1378
- **/
1379
- setValue: function(value, convertStr) {
1380
- if(convertStr) {
1381
- this.value = this.input.str2value(value);
1382
- } else {
1383
- this.value = value;
1384
- }
1385
- if(this.container) {
1386
- this.container.option('value', this.value);
1387
- }
1388
- $.when(this.render())
1389
- .then($.proxy(function() {
1390
- this.handleEmpty();
1391
- }, this));
1392
- },
1393
-
1394
- /**
1395
- Activates input of visible container (e.g. set focus)
1396
- @method activate()
1397
- **/
1398
- activate: function() {
1399
- if(this.container) {
1400
- this.container.activate();
1401
- }
1402
- }
1403
- };
1404
-
1405
- /* EDITABLE PLUGIN DEFINITION
1406
- * ======================= */
1407
-
1408
- /**
1409
- jQuery method to initialize editable element.
1410
-
1411
- @method $().editable(options)
1412
- @params {Object} options
1413
- @example
1414
- $('#username').editable({
1415
- type: 'text',
1416
- url: '/post',
1417
- pk: 1
1418
- });
1419
- **/
1420
- $.fn.editable = function (option) {
1421
- //special API methods returning non-jquery object
1422
- var result = {}, args = arguments, datakey = 'editable';
1423
- switch (option) {
1424
- /**
1425
- Runs client-side validation for all matched editables
1426
-
1427
- @method validate()
1428
- @returns {Object} validation errors map
1429
- @example
1430
- $('#username, #fullname').editable('validate');
1431
- // possible result:
1432
- {
1433
- username: "username is required",
1434
- fullname: "fullname should be minimum 3 letters length"
1435
- }
1436
- **/
1437
- case 'validate':
1438
- this.each(function () {
1439
- var $this = $(this), data = $this.data(datakey), error;
1440
- if (data && (error = data.validate())) {
1441
- result[data.options.name] = error;
1442
- }
1443
- });
1444
- return result;
1445
-
1446
- /**
1447
- Returns current values of editable elements. If value is <code>null</code> or <code>undefined</code> it will not be returned
1448
- @method getValue()
1449
- @returns {Object} object of element names and values
1450
- @example
1451
- $('#username, #fullname').editable('validate');
1452
- // possible result:
1453
- {
1454
- username: "superuser",
1455
- fullname: "John"
1456
- }
1457
- **/
1458
- case 'getValue':
1459
- this.each(function () {
1460
- var $this = $(this), data = $this.data(datakey);
1461
- if (data && data.value !== undefined && data.value !== null) {
1462
- result[data.options.name] = data.input.value2submit(data.value);
1463
- }
1464
- });
1465
- return result;
1466
-
1467
- /**
1468
- This method collects values from several editable elements and submit them all to server.
1469
- Internally it runs client-side validation for all fields and submits only in case of success.
1470
- See <a href="#newrecord">creating new records</a> for details.
1471
-
1472
- @method submit(options)
1473
- @param {object} options
1474
- @param {object} options.url url to submit data
1475
- @param {object} options.data additional data to submit
1476
- @param {object} options.ajaxOptions additional ajax options
1477
- @param {function} options.error(obj) error handler
1478
- @param {function} options.success(obj,config) success handler
1479
- @returns {Object} jQuery object
1480
- **/
1481
- case 'submit': //collects value, validate and submit to server for creating new record
1482
- var config = arguments[1] || {},
1483
- $elems = this,
1484
- errors = this.editable('validate'),
1485
- values;
1486
-
1487
- if($.isEmptyObject(errors)) {
1488
- values = this.editable('getValue');
1489
- if(config.data) {
1490
- $.extend(values, config.data);
1491
- }
1492
-
1493
- $.ajax($.extend({
1494
- url: config.url,
1495
- data: values,
1496
- type: 'POST'
1497
- }, config.ajaxOptions))
1498
- .success(function(response) {
1499
- //successful response 200 OK
1500
- if(typeof config.success === 'function') {
1501
- config.success.call($elems, response, config);
1502
- }
1503
- })
1504
- .error(function(){ //ajax error
1505
- if(typeof config.error === 'function') {
1506
- config.error.apply($elems, arguments);
1507
- }
1508
- });
1509
- } else { //client-side validation error
1510
- if(typeof config.error === 'function') {
1511
- config.error.call($elems, errors);
1512
- }
1513
- }
1514
- return this;
1515
- }
1516
-
1517
- //return jquery object
1518
- return this.each(function () {
1519
- var $this = $(this),
1520
- data = $this.data(datakey),
1521
- options = typeof option === 'object' && option;
1522
-
1523
- if (!data) {
1524
- $this.data(datakey, (data = new Editable(this, options)));
1525
- }
1526
-
1527
- if (typeof option === 'string') { //call method
1528
- data[option].apply(data, Array.prototype.slice.call(args, 1));
1529
- }
1530
- });
1531
- };
1532
-
1533
-
1534
- $.fn.editable.defaults = {
1535
- /**
1536
- Type of input. Can be <code>text|textarea|select|date|checklist</code> and more
1537
-
1538
- @property type
1539
- @type string
1540
- @default 'text'
1541
- **/
1542
- type: 'text',
1543
- /**
1544
- Sets disabled state of editable
1545
-
1546
- @property disabled
1547
- @type boolean
1548
- @default false
1549
- **/
1550
- disabled: false,
1551
- /**
1552
- How to toggle editable. Can be <code>click|dblclick|mouseenter|manual</code>.
1553
- When set to <code>manual</code> you should manually call <code>show/hide</code> methods of editable.
1554
- **Note**: if you call <code>show</code> or <code>toggle</code> inside **click** handler of some DOM element,
1555
- you need to apply <code>e.stopPropagation()</code> because containers are being closed on any click on document.
1556
-
1557
- @example
1558
- $('#edit-button').click(function(e) {
1559
- e.stopPropagation();
1560
- $('#username').editable('toggle');
1561
- });
1562
-
1563
- @property toggle
1564
- @type string
1565
- @default 'click'
1566
- **/
1567
- toggle: 'click',
1568
- /**
1569
- Text shown when element is empty.
1570
-
1571
- @property emptytext
1572
- @type string
1573
- @default 'Empty'
1574
- **/
1575
- emptytext: 'Empty',
1576
- /**
1577
- Allows to automatically set element's text based on it's value. Can be <code>auto|always|never</code>. Useful for select and date.
1578
- For example, if dropdown list is <code>{1: 'a', 2: 'b'}</code> and element's value set to <code>1</code>, it's html will be automatically set to <code>'a'</code>.
1579
- <code>auto</code> - text will be automatically set only if element is empty.
1580
- <code>always|never</code> - always(never) try to set element's text.
1581
-
1582
- @property autotext
1583
- @type string
1584
- @default 'auto'
1585
- **/
1586
- autotext: 'auto',
1587
- /**
1588
- Initial value of input. Taken from <code>data-value</code> or element's text.
1589
-
1590
- @property value
1591
- @type mixed
1592
- @default element's text
1593
- **/
1594
- value: null,
1595
- /**
1596
- Callback to perform custom displaying of value in element's text.
1597
- If <code>null</code>, default input's value2html() will be called.
1598
- If <code>false</code>, no displaying methods will be called, element's text will no change.
1599
- Runs under element's scope.
1600
- Second parameter __sourceData__ is passed for inputs with source (select, checklist).
1601
-
1602
- @property display
1603
- @type function|boolean
1604
- @default null
1605
- @since 1.2.0
1606
- @example
1607
- display: function(value, sourceData) {
1608
- var escapedValue = $('<div>').text(value).html();
1609
- $(this).html('<b>'+escapedValue+'</b>');
1610
- }
1611
- **/
1612
- display: null
1613
- };
1614
-
1615
- }(window.jQuery));
1616
-
1617
- /**
1618
- AbstractInput - base class for all editable inputs.
1619
- It defines interface to be implemented by any input type.
1620
- To create your own input you can inherit from this class.
1621
-
1622
- @class abstractinput
1623
- **/
1624
- (function ($) {
1625
-
1626
- //types
1627
- $.fn.editabletypes = {};
1628
-
1629
- var AbstractInput = function () { };
1630
-
1631
- AbstractInput.prototype = {
1632
- /**
1633
- Initializes input
1634
-
1635
- @method init()
1636
- **/
1637
- init: function(type, options, defaults) {
1638
- this.type = type;
1639
- this.options = $.extend({}, defaults, options);
1640
- this.$input = null;
1641
- this.$clear = null;
1642
- this.error = null;
1643
- },
1644
-
1645
- /**
1646
- Renders input from tpl. Can return jQuery deferred object.
1647
-
1648
- @method render()
1649
- **/
1650
- render: function() {
1651
- this.$input = $(this.options.tpl);
1652
- if(this.options.inputclass) {
1653
- this.$input.addClass(this.options.inputclass);
1654
- }
1655
-
1656
- if (this.options.placeholder) {
1657
- this.$input.attr('placeholder', this.options.placeholder);
1658
- }
1659
- },
1660
-
1661
- /**
1662
- Sets element's html by value.
1663
-
1664
- @method value2html(value, element)
1665
- @param {mixed} value
1666
- @param {DOMElement} element
1667
- **/
1668
- value2html: function(value, element) {
1669
- $(element).text(value);
1670
- },
1671
-
1672
- /**
1673
- Converts element's html to value
1674
-
1675
- @method html2value(html)
1676
- @param {string} html
1677
- @returns {mixed}
1678
- **/
1679
- html2value: function(html) {
1680
- return $('<div>').html(html).text();
1681
- },
1682
-
1683
- /**
1684
- Converts value to string (for internal compare). For submitting to server used value2submit().
1685
-
1686
- @method value2str(value)
1687
- @param {mixed} value
1688
- @returns {string}
1689
- **/
1690
- value2str: function(value) {
1691
- return value;
1692
- },
1693
-
1694
- /**
1695
- Converts string received from server into value.
1696
-
1697
- @method str2value(str)
1698
- @param {string} str
1699
- @returns {mixed}
1700
- **/
1701
- str2value: function(str) {
1702
- return str;
1703
- },
1704
-
1705
- /**
1706
- Converts value for submitting to server
1707
-
1708
- @method value2submit(value)
1709
- @param {mixed} value
1710
- @returns {mixed}
1711
- **/
1712
- value2submit: function(value) {
1713
- return value;
1714
- },
1715
-
1716
- /**
1717
- Sets value of input.
1718
-
1719
- @method value2input(value)
1720
- @param {mixed} value
1721
- **/
1722
- value2input: function(value) {
1723
- this.$input.val(value);
1724
- },
1725
-
1726
- /**
1727
- Returns value of input. Value can be object (e.g. datepicker)
1728
-
1729
- @method input2value()
1730
- **/
1731
- input2value: function() {
1732
- return this.$input.val();
1733
- },
1734
-
1735
- /**
1736
- Activates input. For text it sets focus.
1737
-
1738
- @method activate()
1739
- **/
1740
- activate: function() {
1741
- if(this.$input.is(':visible')) {
1742
- this.$input.focus();
1743
- }
1744
- },
1745
-
1746
- /**
1747
- Creates input.
1748
-
1749
- @method clear()
1750
- **/
1751
- clear: function() {
1752
- this.$input.val(null);
1753
- },
1754
-
1755
- /**
1756
- method to escape html.
1757
- **/
1758
- escape: function(str) {
1759
- return $('<div>').text(str).html();
1760
- },
1761
-
1762
- /**
1763
- attach handler to automatically submit form when value changed (useful when buttons not shown)
1764
- **/
1765
- autosubmit: function() {
1766
-
1767
- }
1768
- };
1769
-
1770
- AbstractInput.defaults = {
1771
- /**
1772
- HTML template of input. Normally you should not change it.
1773
-
1774
- @property tpl
1775
- @type string
1776
- @default ''
1777
- **/
1778
- tpl: '',
1779
- /**
1780
- CSS class automatically applied to input
1781
-
1782
- @property inputclass
1783
- @type string
1784
- @default input-medium
1785
- **/
1786
- inputclass: 'input-medium',
1787
- /**
1788
- Name attribute of input
1789
-
1790
- @property name
1791
- @type string
1792
- @default null
1793
- **/
1794
- name: null
1795
- };
1796
-
1797
- $.extend($.fn.editabletypes, {abstractinput: AbstractInput});
1798
-
1799
- }(window.jQuery));
1800
-
1801
- /**
1802
- List - abstract class for inputs that have source option loaded from js array or via ajax
1803
-
1804
- @class list
1805
- @extends abstractinput
1806
- **/
1807
- (function ($) {
1808
-
1809
- var List = function (options) {
1810
-
1811
- };
1812
-
1813
- $.fn.editableutils.inherit(List, $.fn.editabletypes.abstractinput);
1814
-
1815
- $.extend(List.prototype, {
1816
- render: function () {
1817
- List.superclass.render.call(this);
1818
- var deferred = $.Deferred();
1819
- this.error = null;
1820
- this.sourceData = null;
1821
- this.prependData = null;
1822
- this.onSourceReady(function () {
1823
- this.renderList();
1824
- deferred.resolve();
1825
- }, function () {
1826
- this.error = this.options.sourceError;
1827
- deferred.resolve();
1828
- });
1829
-
1830
- return deferred.promise();
1831
- },
1832
-
1833
- html2value: function (html) {
1834
- return null; //can't set value by text
1835
- },
1836
-
1837
- value2html: function (value, element, display) {
1838
- var deferred = $.Deferred();
1839
- this.onSourceReady(function () {
1840
- if(typeof display === 'function') {
1841
- //custom display method
1842
- display.call(element, value, this.sourceData);
1843
- } else {
1844
- this.value2htmlFinal(value, element);
1845
- }
1846
- deferred.resolve();
1847
- }, function () {
1848
- //do nothing with element
1849
- deferred.resolve();
1850
- });
1851
-
1852
- return deferred.promise();
1853
- },
1854
-
1855
- // ------------- additional functions ------------
1856
-
1857
- onSourceReady: function (success, error) {
1858
- //if allready loaded just call success
1859
- if($.isArray(this.sourceData)) {
1860
- success.call(this);
1861
- return;
1862
- }
1863
-
1864
- // try parse json in single quotes (for double quotes jquery does automatically)
1865
- try {
1866
- this.options.source = $.fn.editableutils.tryParseJson(this.options.source, false);
1867
- } catch (e) {
1868
- error.call(this);
1869
- return;
1870
- }
1871
-
1872
- //loading from url
1873
- if (typeof this.options.source === 'string') {
1874
- //try to get from cache
1875
- if(this.options.sourceCache) {
1876
- var cacheID = this.options.source + (this.options.name ? '-' + this.options.name : ''),
1877
- cache;
1878
-
1879
- if (!$(document).data(cacheID)) {
1880
- $(document).data(cacheID, {});
1881
- }
1882
- cache = $(document).data(cacheID);
1883
-
1884
- //check for cached data
1885
- if (cache.loading === false && cache.sourceData) { //take source from cache
1886
- this.sourceData = cache.sourceData;
1887
- success.call(this);
1888
- return;
1889
- } else if (cache.loading === true) { //cache is loading, put callback in stack to be called later
1890
- cache.callbacks.push($.proxy(function () {
1891
- this.sourceData = cache.sourceData;
1892
- success.call(this);
1893
- }, this));
1894
-
1895
- //also collecting error callbacks
1896
- cache.err_callbacks.push($.proxy(error, this));
1897
- return;
1898
- } else { //no cache yet, activate it
1899
- cache.loading = true;
1900
- cache.callbacks = [];
1901
- cache.err_callbacks = [];
1902
- }
1903
- }
1904
-
1905
- //loading sourceData from server
1906
- $.ajax({
1907
- url: this.options.source,
1908
- type: 'get',
1909
- cache: false,
1910
- data: this.options.name ? {name: this.options.name} : {},
1911
- dataType: 'json',
1912
- success: $.proxy(function (data) {
1913
- if(cache) {
1914
- cache.loading = false;
1915
- }
1916
- this.sourceData = this.makeArray(data);
1917
- if($.isArray(this.sourceData)) {
1918
- this.doPrepend();
1919
- success.call(this);
1920
- if(cache) {
1921
- //store result in cache
1922
- cache.sourceData = this.sourceData;
1923
- $.each(cache.callbacks, function () { this.call(); }); //run success callbacks for other fields
1924
- }
1925
- } else {
1926
- error.call(this);
1927
- if(cache) {
1928
- $.each(cache.err_callbacks, function () { this.call(); }); //run error callbacks for other fields
1929
- }
1930
- }
1931
- }, this),
1932
- error: $.proxy(function () {
1933
- error.call(this);
1934
- if(cache) {
1935
- cache.loading = false;
1936
- //run error callbacks for other fields
1937
- $.each(cache.err_callbacks, function () { this.call(); });
1938
- }
1939
- }, this)
1940
- });
1941
- } else { //options as json/array
1942
- this.sourceData = this.makeArray(this.options.source);
1943
- if($.isArray(this.sourceData)) {
1944
- this.doPrepend();
1945
- success.call(this);
1946
- } else {
1947
- error.call(this);
1948
- }
1949
- }
1950
- },
1951
-
1952
- doPrepend: function () {
1953
- if(this.options.prepend === null || this.options.prepend === undefined) {
1954
- return;
1955
- }
1956
-
1957
- if(!$.isArray(this.prependData)) {
1958
- //try parse json in single quotes
1959
- this.options.prepend = $.fn.editableutils.tryParseJson(this.options.prepend, true);
1960
- if (typeof this.options.prepend === 'string') {
1961
- this.options.prepend = {'': this.options.prepend};
1962
- }
1963
- this.prependData = this.makeArray(this.options.prepend);
1964
- }
1965
-
1966
- if($.isArray(this.prependData) && $.isArray(this.sourceData)) {
1967
- this.sourceData = this.prependData.concat(this.sourceData);
1968
- }
1969
- },
1970
-
1971
- /*
1972
- renders input list
1973
- */
1974
- renderList: function() {
1975
- // this method should be overwritten in child class
1976
- },
1977
-
1978
- /*
1979
- set element's html by value
1980
- */
1981
- value2htmlFinal: function(value, element) {
1982
- // this method should be overwritten in child class
1983
- },
1984
-
1985
- /**
1986
- * convert data to array suitable for sourceData, e.g. [{value: 1, text: 'abc'}, {...}]
1987
- */
1988
- makeArray: function(data) {
1989
- var count, obj, result = [], iterateEl;
1990
- if(!data || typeof data === 'string') {
1991
- return null;
1992
- }
1993
-
1994
- if($.isArray(data)) { //array
1995
- iterateEl = function (k, v) {
1996
- obj = {value: k, text: v};
1997
- if(count++ >= 2) {
1998
- return false;// exit each if object has more than one value
1999
- }
2000
- };
2001
-
2002
- for(var i = 0; i < data.length; i++) {
2003
- if(typeof data[i] === 'object') {
2004
- count = 0;
2005
- $.each(data[i], iterateEl);
2006
- if(count === 1) {
2007
- result.push(obj);
2008
- } else if(count > 1 && data[i].hasOwnProperty('value') && data[i].hasOwnProperty('text')) {
2009
- result.push(data[i]);
2010
- } else {
2011
- //data contains incorrect objects
2012
- }
2013
- } else {
2014
- result.push({value: data[i], text: data[i]});
2015
- }
2016
- }
2017
- } else { //object
2018
- $.each(data, function (k, v) {
2019
- result.push({value: k, text: v});
2020
- });
2021
- }
2022
- return result;
2023
- },
2024
-
2025
- //search for item by particular value
2026
- itemByVal: function(val) {
2027
- if($.isArray(this.sourceData)) {
2028
- for(var i=0; i<this.sourceData.length; i++){
2029
- /*jshint eqeqeq: false*/
2030
- if(this.sourceData[i].value == val) {
2031
- /*jshint eqeqeq: true*/
2032
- return this.sourceData[i];
2033
- }
2034
- }
2035
- }
2036
- }
2037
-
2038
- });
2039
-
2040
- List.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
2041
- /**
2042
- Source data for list. If string - considered ajax url to load items. Otherwise should be an array.
2043
- Array format is: <code>[{value: 1, text: "text"}, {...}]</code><br>
2044
- For compability it also supports format <code>{value1: "text1", value2: "text2" ...}</code> but it does not guarantee elements order.
2045
- If source is **string**, results will be cached for fields with the same source and name. See also <code>sourceCache</code> option.
2046
-
2047
- @property source
2048
- @type string|array|object
2049
- @default null
2050
- **/
2051
- source:null,
2052
- /**
2053
- Data automatically prepended to the beginning of dropdown list.
2054
-
2055
- @property prepend
2056
- @type string|array|object
2057
- @default false
2058
- **/
2059
- prepend:false,
2060
- /**
2061
- Error message when list cannot be loaded (e.g. ajax error)
2062
-
2063
- @property sourceError
2064
- @type string
2065
- @default Error when loading list
2066
- **/
2067
- sourceError: 'Error when loading list',
2068
- /**
2069
- if <code>true</code> and source is **string url** - results will be cached for fields with the same source and name.
2070
- Usefull for editable grids.
2071
-
2072
- @property sourceCache
2073
- @type boolean
2074
- @default true
2075
- @since 1.2.0
2076
- **/
2077
- sourceCache: true
2078
- });
2079
-
2080
- $.fn.editabletypes.list = List;
2081
-
2082
- }(window.jQuery));
2083
- /**
2084
- Text input
2085
-
2086
- @class text
2087
- @extends abstractinput
2088
- @final
2089
- @example
2090
- <a href="#" id="username" data-type="text" data-pk="1">awesome</a>
2091
- <script>
2092
- $(function(){
2093
- $('#username').editable({
2094
- url: '/post',
2095
- title: 'Enter username'
2096
- });
2097
- });
2098
- </script>
2099
- **/
2100
- (function ($) {
2101
- var Text = function (options) {
2102
- this.init('text', options, Text.defaults);
2103
- };
2104
-
2105
- $.fn.editableutils.inherit(Text, $.fn.editabletypes.abstractinput);
2106
-
2107
- $.extend(Text.prototype, {
2108
- activate: function() {
2109
- if(this.$input.is(':visible')) {
2110
- this.$input.focus();
2111
- $.fn.editableutils.setCursorPosition(this.$input.get(0), this.$input.val().length);
2112
- }
2113
- }
2114
- });
2115
-
2116
- Text.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
2117
- /**
2118
- @property tpl
2119
- @default <input type="text">
2120
- **/
2121
- tpl: '<input type="text">',
2122
- /**
2123
- Placeholder attribute of input. Shown when input is empty.
2124
-
2125
- @property placeholder
2126
- @type string
2127
- @default null
2128
- **/
2129
- placeholder: null
2130
- });
2131
-
2132
- $.fn.editabletypes.text = Text;
2133
-
2134
- }(window.jQuery));
2135
-
2136
- /**
2137
- Textarea input
2138
-
2139
- @class textarea
2140
- @extends abstractinput
2141
- @final
2142
- @example
2143
- <a href="#" id="comments" data-type="textarea" data-pk="1">awesome comment!</a>
2144
- <script>
2145
- $(function(){
2146
- $('#comments').editable({
2147
- url: '/post',
2148
- title: 'Enter comments'
2149
- });
2150
- });
2151
- </script>
2152
- **/
2153
- (function ($) {
2154
-
2155
- var Textarea = function (options) {
2156
- this.init('textarea', options, Textarea.defaults);
2157
- };
2158
-
2159
- $.fn.editableutils.inherit(Textarea, $.fn.editabletypes.abstractinput);
2160
-
2161
- $.extend(Textarea.prototype, {
2162
- render: function () {
2163
- Textarea.superclass.render.call(this);
2164
-
2165
- //ctrl + enter
2166
- this.$input.keydown(function (e) {
2167
- if (e.ctrlKey && e.which === 13) {
2168
- $(this).closest('form').submit();
2169
- }
2170
- });
2171
- },
2172
-
2173
- value2html: function(value, element) {
2174
- var html = '', lines;
2175
- if(value) {
2176
- lines = value.split("\n");
2177
- for (var i = 0; i < lines.length; i++) {
2178
- lines[i] = $('<div>').text(lines[i]).html();
2179
- }
2180
- html = lines.join('<br>');
2181
- }
2182
- $(element).html(html);
2183
- },
2184
-
2185
- html2value: function(html) {
2186
- if(!html) {
2187
- return '';
2188
- }
2189
- var lines = html.split(/<br\s*\/?>/i);
2190
- for (var i = 0; i < lines.length; i++) {
2191
- lines[i] = $('<div>').html(lines[i]).text();
2192
- }
2193
- return lines.join("\n");
2194
- },
2195
-
2196
- activate: function() {
2197
- if(this.$input.is(':visible')) {
2198
- $.fn.editableutils.setCursorPosition(this.$input.get(0), this.$input.val().length);
2199
- this.$input.focus();
2200
- }
2201
- }
2202
- });
2203
-
2204
- Textarea.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
2205
- /**
2206
- @property tpl
2207
- @default <textarea></textarea>
2208
- **/
2209
- tpl:'<textarea></textarea>',
2210
- /**
2211
- @property inputclass
2212
- @default input-large
2213
- **/
2214
- inputclass: 'input-large',
2215
- /**
2216
- Placeholder attribute of input. Shown when input is empty.
2217
-
2218
- @property placeholder
2219
- @type string
2220
- @default null
2221
- **/
2222
- placeholder: null
2223
- });
2224
-
2225
- $.fn.editabletypes.textarea = Textarea;
2226
-
2227
- }(window.jQuery));
2228
-
2229
- /**
2230
- Select (dropdown)
2231
-
2232
- @class select
2233
- @extends list
2234
- @final
2235
- @example
2236
- <a href="#" id="status" data-type="select" data-pk="1" data-url="/post" data-original-title="Select status"></a>
2237
- <script>
2238
- $(function(){
2239
- $('#status').editable({
2240
- value: 2,
2241
- source: [
2242
- {value: 1, text: 'Active'},
2243
- {value: 2, text: 'Blocked'},
2244
- {value: 3, text: 'Deleted'}
2245
- ]
2246
- }
2247
- });
2248
- });
2249
- </script>
2250
- **/
2251
- (function ($) {
2252
-
2253
- var Select = function (options) {
2254
- this.init('select', options, Select.defaults);
2255
- };
2256
-
2257
- $.fn.editableutils.inherit(Select, $.fn.editabletypes.list);
2258
-
2259
- $.extend(Select.prototype, {
2260
- renderList: function() {
2261
- if(!$.isArray(this.sourceData)) {
2262
- return;
2263
- }
2264
-
2265
- for(var i=0; i<this.sourceData.length; i++) {
2266
- this.$input.append($('<option>', {value: this.sourceData[i].value}).text(this.sourceData[i].text));
2267
- }
2268
-
2269
- //enter submit
2270
- this.$input.on('keydown.editable', function (e) {
2271
- if (e.which === 13) {
2272
- $(this).closest('form').submit();
2273
- }
2274
- });
2275
- },
2276
-
2277
- value2htmlFinal: function(value, element) {
2278
- var text = '', item = this.itemByVal(value);
2279
- if(item) {
2280
- text = item.text;
2281
- }
2282
- Select.superclass.constructor.superclass.value2html(text, element);
2283
- },
2284
-
2285
- autosubmit: function() {
2286
- this.$input.off('keydown.editable').on('change.editable', function(){
2287
- $(this).closest('form').submit();
2288
- });
2289
- }
2290
- });
2291
-
2292
- Select.defaults = $.extend({}, $.fn.editabletypes.list.defaults, {
2293
- /**
2294
- @property tpl
2295
- @default <select></select>
2296
- **/
2297
- tpl:'<select></select>'
2298
- });
2299
-
2300
- $.fn.editabletypes.select = Select;
2301
-
2302
- }(window.jQuery));
2303
- /**
2304
- List of checkboxes.
2305
- Internally value stored as javascript array of values.
2306
-
2307
- @class checklist
2308
- @extends list
2309
- @final
2310
- @example
2311
- <a href="#" id="options" data-type="checklist" data-pk="1" data-url="/post" data-original-title="Select options"></a>
2312
- <script>
2313
- $(function(){
2314
- $('#options').editable({
2315
- value: [2, 3],
2316
- source: [
2317
- {value: 1, text: 'option1'},
2318
- {value: 2, text: 'option2'},
2319
- {value: 3, text: 'option3'}
2320
- ]
2321
- }
2322
- });
2323
- });
2324
- </script>
2325
- **/
2326
- (function ($) {
2327
-
2328
- var Checklist = function (options) {
2329
- this.init('checklist', options, Checklist.defaults);
2330
- };
2331
-
2332
- $.fn.editableutils.inherit(Checklist, $.fn.editabletypes.list);
2333
-
2334
- $.extend(Checklist.prototype, {
2335
- renderList: function() {
2336
- var $label, $div;
2337
- if(!$.isArray(this.sourceData)) {
2338
- return;
2339
- }
2340
-
2341
- for(var i=0; i<this.sourceData.length; i++) {
2342
- $label = $('<label>').append($('<input>', {
2343
- type: 'checkbox',
2344
- value: this.sourceData[i].value,
2345
- name: this.options.name
2346
- }))
2347
- .append($('<span>').text(' '+this.sourceData[i].text));
2348
-
2349
- $('<div>').append($label).appendTo(this.$input);
2350
- }
2351
- },
2352
-
2353
- value2str: function(value) {
2354
- return $.isArray(value) ? value.sort().join($.trim(this.options.separator)) : '';
2355
- },
2356
-
2357
- //parse separated string
2358
- str2value: function(str) {
2359
- var reg, value = null;
2360
- if(typeof str === 'string' && str.length) {
2361
- reg = new RegExp('\\s*'+$.trim(this.options.separator)+'\\s*');
2362
- value = str.split(reg);
2363
- } else if($.isArray(str)) {
2364
- value = str;
2365
- }
2366
- return value;
2367
- },
2368
-
2369
- //set checked on required checkboxes
2370
- value2input: function(value) {
2371
- var $checks = this.$input.find('input[type="checkbox"]');
2372
- $checks.removeAttr('checked');
2373
- if($.isArray(value) && value.length) {
2374
- $checks.each(function(i, el) {
2375
- var $el = $(el);
2376
- // cannot use $.inArray as it performs strict comparison
2377
- $.each(value, function(j, val){
2378
- /*jslint eqeq: true*/
2379
- if($el.val() == val) {
2380
- /*jslint eqeq: false*/
2381
- $el.attr('checked', 'checked');
2382
- }
2383
- });
2384
- });
2385
- }
2386
- },
2387
-
2388
- input2value: function() {
2389
- var checked = [];
2390
- this.$input.find('input:checked').each(function(i, el) {
2391
- checked.push($(el).val());
2392
- });
2393
- return checked;
2394
- },
2395
-
2396
- //collect text of checked boxes
2397
- value2htmlFinal: function(value, element) {
2398
- var html = [],
2399
- /*jslint eqeq: true*/
2400
- checked = $.grep(this.sourceData, function(o){
2401
- return $.grep(value, function(v){ return v == o.value; }).length;
2402
- });
2403
- /*jslint eqeq: false*/
2404
- if(checked.length) {
2405
- $.each(checked, function(i, v) { html.push($.fn.editableutils.escape(v.text)); });
2406
- $(element).html(html.join('<br>'));
2407
- } else {
2408
- $(element).empty();
2409
- }
2410
- },
2411
-
2412
- activate: function() {
2413
- this.$input.find('input[type="checkbox"]').first().focus();
2414
- },
2415
-
2416
- autosubmit: function() {
2417
- this.$input.find('input[type="checkbox"]').on('keydown', function(e){
2418
- if (e.which === 13) {
2419
- $(this).closest('form').submit();
2420
- }
2421
- });
2422
- }
2423
- });
2424
-
2425
- Checklist.defaults = $.extend({}, $.fn.editabletypes.list.defaults, {
2426
- /**
2427
- @property tpl
2428
- @default <div></div>
2429
- **/
2430
- tpl:'<div></div>',
2431
-
2432
- /**
2433
- @property inputclass
2434
- @type string
2435
- @default editable-checklist
2436
- **/
2437
- inputclass: 'editable-checklist',
2438
-
2439
- /**
2440
- Separator of values when reading from 'data-value' string
2441
-
2442
- @property separator
2443
- @type string
2444
- @default ', '
2445
- **/
2446
- separator: ','
2447
- });
2448
-
2449
- $.fn.editabletypes.checklist = Checklist;
2450
-
2451
- }(window.jQuery));
2452
-
2453
- /**
2454
- HTML5 input types.
2455
- Following types are supported:
2456
-
2457
- * password
2458
- * email
2459
- * url
2460
- * tel
2461
- * number
2462
- * range
2463
-
2464
- Learn more about html5 inputs:
2465
- http://www.w3.org/wiki/HTML5_form_additions
2466
- To check browser compatibility please see:
2467
- https://developer.mozilla.org/en-US/docs/HTML/Element/Input
2468
-
2469
- @class html5types
2470
- @extends text
2471
- @final
2472
- @since 1.3.0
2473
- @example
2474
- <a href="#" id="email" data-type="email" data-pk="1">admin@example.com</a>
2475
- <script>
2476
- $(function(){
2477
- $('#email').editable({
2478
- url: '/post',
2479
- title: 'Enter email'
2480
- });
2481
- });
2482
- </script>
2483
- **/
2484
-
2485
- /**
2486
- @property tpl
2487
- @default depends on type
2488
- **/
2489
-
2490
- /*
2491
- Password
2492
- */
2493
- (function ($) {
2494
- var Password = function (options) {
2495
- this.init('password', options, Password.defaults);
2496
- };
2497
- $.fn.editableutils.inherit(Password, $.fn.editabletypes.text);
2498
- $.extend(Password.prototype, {
2499
- //do not display password, show '[hidden]' instead
2500
- value2html: function(value, element) {
2501
- if(value) {
2502
- $(element).text('[hidden]');
2503
- } else {
2504
- $(element).empty();
2505
- }
2506
- },
2507
- //as password not displayed, should not set value by html
2508
- html2value: function(html) {
2509
- return null;
2510
- }
2511
- });
2512
- Password.defaults = $.extend({}, $.fn.editabletypes.text.defaults, {
2513
- tpl: '<input type="password">'
2514
- });
2515
- $.fn.editabletypes.password = Password;
2516
- }(window.jQuery));
2517
-
2518
-
2519
- /*
2520
- Email
2521
- */
2522
- (function ($) {
2523
- var Email = function (options) {
2524
- this.init('email', options, Email.defaults);
2525
- };
2526
- $.fn.editableutils.inherit(Email, $.fn.editabletypes.text);
2527
- Email.defaults = $.extend({}, $.fn.editabletypes.text.defaults, {
2528
- tpl: '<input type="email">'
2529
- });
2530
- $.fn.editabletypes.email = Email;
2531
- }(window.jQuery));
2532
-
2533
-
2534
- /*
2535
- Url
2536
- */
2537
- (function ($) {
2538
- var Url = function (options) {
2539
- this.init('url', options, Url.defaults);
2540
- };
2541
- $.fn.editableutils.inherit(Url, $.fn.editabletypes.text);
2542
- Url.defaults = $.extend({}, $.fn.editabletypes.text.defaults, {
2543
- tpl: '<input type="url">'
2544
- });
2545
- $.fn.editabletypes.url = Url;
2546
- }(window.jQuery));
2547
-
2548
-
2549
- /*
2550
- Tel
2551
- */
2552
- (function ($) {
2553
- var Tel = function (options) {
2554
- this.init('tel', options, Tel.defaults);
2555
- };
2556
- $.fn.editableutils.inherit(Tel, $.fn.editabletypes.text);
2557
- Tel.defaults = $.extend({}, $.fn.editabletypes.text.defaults, {
2558
- tpl: '<input type="tel">'
2559
- });
2560
- $.fn.editabletypes.tel = Tel;
2561
- }(window.jQuery));
2562
-
2563
-
2564
- /*
2565
- Number
2566
- */
2567
- (function ($) {
2568
- var NumberInput = function (options) {
2569
- this.init('number', options, NumberInput.defaults);
2570
- };
2571
- $.fn.editableutils.inherit(NumberInput, $.fn.editabletypes.text);
2572
- $.extend(NumberInput.prototype, {
2573
- render: function () {
2574
- NumberInput.superclass.render.call(this);
2575
-
2576
- if (this.options.min !== null) {
2577
- this.$input.attr('min', this.options.min);
2578
- }
2579
-
2580
- if (this.options.max !== null) {
2581
- this.$input.attr('max', this.options.max);
2582
- }
2583
-
2584
- if (this.options.step !== null) {
2585
- this.$input.attr('step', this.options.step);
2586
- }
2587
- }
2588
- });
2589
- NumberInput.defaults = $.extend({}, $.fn.editabletypes.text.defaults, {
2590
- tpl: '<input type="number">',
2591
- inputclass: 'input-mini',
2592
- min: null,
2593
- max: null,
2594
- step: null
2595
- });
2596
- $.fn.editabletypes.number = NumberInput;
2597
- }(window.jQuery));
2598
-
2599
-
2600
- /*
2601
- Range (inherit from number)
2602
- */
2603
- (function ($) {
2604
- var Range = function (options) {
2605
- this.init('range', options, Range.defaults);
2606
- };
2607
- $.fn.editableutils.inherit(Range, $.fn.editabletypes.number);
2608
- $.extend(Range.prototype, {
2609
- render: function () {
2610
- this.$input = $(this.options.tpl);
2611
- var $slider = this.$input.filter('input');
2612
- if(this.options.inputclass) {
2613
- $slider.addClass(this.options.inputclass);
2614
- }
2615
- if (this.options.min !== null) {
2616
- $slider.attr('min', this.options.min);
2617
- }
2618
-
2619
- if (this.options.max !== null) {
2620
- $slider.attr('max', this.options.max);
2621
- }
2622
-
2623
- if (this.options.step !== null) {
2624
- $slider.attr('step', this.options.step);
2625
- }
2626
-
2627
- $slider.on('input', function(){
2628
- $(this).siblings('output').text($(this).val());
2629
- });
2630
- },
2631
- activate: function() {
2632
- this.$input.filter('input').focus();
2633
- }
2634
- });
2635
- Range.defaults = $.extend({}, $.fn.editabletypes.number.defaults, {
2636
- tpl: '<input type="range"><output style="width: 30px; display: inline-block"></output>',
2637
- inputclass: 'input-medium'
2638
- });
2639
- $.fn.editabletypes.range = Range;
2640
- }(window.jQuery));
2641
- /*
2642
- Editableform based on Twitter Bootstrap
2643
- */
2644
- (function ($) {
2645
-
2646
- $.extend($.fn.editableform.Constructor.prototype, {
2647
- initTemplate: function() {
2648
- this.$form = $($.fn.editableform.template);
2649
- this.$form.find('.editable-error-block').addClass('help-block');
2650
- }
2651
- });
2652
-
2653
- //buttons
2654
- $.fn.editableform.buttons = '<button type="submit" class="btn btn-primary editable-submit"><i class="icon-ok icon-white"></i></button>'+
2655
- '<button type="button" class="btn editable-cancel"><i class="icon-remove"></i></button>';
2656
-
2657
- //error classes
2658
- $.fn.editableform.errorGroupClass = 'error';
2659
- $.fn.editableform.errorBlockClass = null;
2660
-
2661
- }(window.jQuery));
2662
- /**
2663
- * Editable Inline
2664
- * ---------------------
2665
- */
2666
- (function ($) {
2667
-
2668
- //extend methods
2669
- $.extend($.fn.editableContainer.Constructor.prototype, {
2670
- containerName: 'editableform',
2671
- innerCss: null,
2672
-
2673
- initContainer: function(){
2674
- //no init for container
2675
- //only convert anim to miliseconds (int)
2676
- if(!this.options.anim) {
2677
- this.options.anim = 0;
2678
- }
2679
- },
2680
-
2681
- splitOptions: function() {
2682
- this.containerOptions = {};
2683
- this.formOptions = this.options;
2684
- },
2685
-
2686
- tip: function() {
2687
- return this.$form;
2688
- },
2689
-
2690
- innerShow: function () {
2691
- this.$element.hide();
2692
-
2693
- if(this.$form) {
2694
- this.$form.remove();
2695
- }
2696
-
2697
- this.initForm();
2698
- this.tip().addClass('editable-container').addClass('editable-inline');
2699
- this.$form.insertAfter(this.$element);
2700
- this.$form.show(this.options.anim);
2701
- this.$form.editableform('render');
2702
- },
2703
-
2704
- innerHide: function () {
2705
- this.$form.hide(this.options.anim, $.proxy(function() {
2706
- this.$element.show();
2707
- }, this));
2708
- },
2709
-
2710
- destroy: function() {
2711
- this.tip().remove();
2712
- }
2713
- });
2714
-
2715
- //defaults
2716
- $.fn.editableContainer.defaults = $.extend({}, $.fn.editableContainer.defaults, {
2717
- anim: 'fast'
2718
- });
2719
-
2720
-
2721
- }(window.jQuery));
2722
- /**
2723
- Bootstrap-datepicker.
2724
- Description and examples: http://vitalets.github.com/bootstrap-datepicker.
2725
- For localization you can include js file from here: https://github.com/eternicode/bootstrap-datepicker/tree/master/js/locales
2726
-
2727
- @class date
2728
- @extends abstractinput
2729
- @final
2730
- @example
2731
- <a href="#" id="dob" data-type="date" data-pk="1" data-url="/post" data-original-title="Select date">15/05/1984</a>
2732
- <script>
2733
- $(function(){
2734
- $('#dob').editable({
2735
- format: 'yyyy-mm-dd',
2736
- viewformat: 'dd/mm/yyyy',
2737
- datepicker: {
2738
- weekStart: 1
2739
- }
2740
- }
2741
- });
2742
- });
2743
- </script>
2744
- **/
2745
- (function ($) {
2746
-
2747
- var Date = function (options) {
2748
- this.init('date', options, Date.defaults);
2749
-
2750
- //set popular options directly from settings or data-* attributes
2751
- var directOptions = $.fn.editableutils.sliceObj(this.options, ['format']);
2752
-
2753
- //overriding datepicker config (as by default jQuery extend() is not recursive)
2754
- this.options.datepicker = $.extend({}, Date.defaults.datepicker, directOptions, options.datepicker);
2755
-
2756
- //by default viewformat equals to format
2757
- if(!this.options.viewformat) {
2758
- this.options.viewformat = this.options.datepicker.format;
2759
- }
2760
-
2761
- //language
2762
- this.options.datepicker.language = this.options.datepicker.language || 'en';
2763
-
2764
- //store DPglobal
2765
- this.dpg = $.fn.datepicker.DPGlobal;
2766
-
2767
- //store parsed formats
2768
- this.parsedFormat = this.dpg.parseFormat(this.options.datepicker.format);
2769
- this.parsedViewFormat = this.dpg.parseFormat(this.options.viewformat);
2770
- };
2771
-
2772
- $.fn.editableutils.inherit(Date, $.fn.editabletypes.abstractinput);
2773
-
2774
- $.extend(Date.prototype, {
2775
- render: function () {
2776
- Date.superclass.render.call(this);
2777
- this.$input.datepicker(this.options.datepicker);
2778
-
2779
- if(this.options.clear) {
2780
- this.$clear = $('<a href="#"></a>').html(this.options.clear).click($.proxy(function(e){
2781
- e.preventDefault();
2782
- e.stopPropagation();
2783
- this.clear();
2784
- }, this));
2785
- }
2786
- },
2787
-
2788
- value2html: function(value, element) {
2789
- var text = value ? this.dpg.formatDate(value, this.parsedViewFormat, this.options.datepicker.language) : '';
2790
- Date.superclass.value2html(text, element);
2791
- },
2792
-
2793
- html2value: function(html) {
2794
- return html ? this.dpg.parseDate(html, this.parsedViewFormat, this.options.datepicker.language) : null;
2795
- },
2796
-
2797
- value2str: function(value) {
2798
- return value ? this.dpg.formatDate(value, this.parsedFormat, this.options.datepicker.language) : '';
2799
- },
2800
-
2801
- str2value: function(str) {
2802
- return str ? this.dpg.parseDate(str, this.parsedFormat, this.options.datepicker.language) : null;
2803
- },
2804
-
2805
- value2submit: function(value) {
2806
- return this.value2str(value);
2807
- },
2808
-
2809
- value2input: function(value) {
2810
- this.$input.datepicker('update', value);
2811
- },
2812
-
2813
- input2value: function() {
2814
- return this.$input.data('datepicker').date;
2815
- },
2816
-
2817
- activate: function() {
2818
- },
2819
-
2820
- clear: function() {
2821
- this.$input.data('datepicker').date = null;
2822
- this.$input.find('.active').removeClass('active');
2823
- },
2824
-
2825
- autosubmit: function() {
2826
- this.$input.on('changeDate', function(e){
2827
- var $form = $(this).closest('form');
2828
- setTimeout(function() {
2829
- $form.submit();
2830
- }, 200);
2831
- });
2832
- }
2833
-
2834
- });
2835
-
2836
- Date.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
2837
- /**
2838
- @property tpl
2839
- @default <div></div>
2840
- **/
2841
- tpl:'<div></div>',
2842
- /**
2843
- @property inputclass
2844
- @default editable-date well
2845
- **/
2846
- inputclass: 'editable-date well',
2847
- /**
2848
- Format used for sending value to server. Also applied when converting date from <code>data-value</code> attribute.<br>
2849
- Possible tokens are: <code>d, dd, m, mm, yy, yyyy</code>
2850
-
2851
- @property format
2852
- @type string
2853
- @default yyyy-mm-dd
2854
- **/
2855
- format:'yyyy-mm-dd',
2856
- /**
2857
- Format used for displaying date. Also applied when converting date from element's text on init.
2858
- If not specified equals to <code>format</code>
2859
-
2860
- @property viewformat
2861
- @type string
2862
- @default null
2863
- **/
2864
- viewformat: null,
2865
- /**
2866
- Configuration of datepicker.
2867
- Full list of options: http://vitalets.github.com/bootstrap-datepicker
2868
-
2869
- @property datepicker
2870
- @type object
2871
- @default {
2872
- weekStart: 0,
2873
- startView: 0,
2874
- autoclose: false
2875
- }
2876
- **/
2877
- datepicker:{
2878
- weekStart: 0,
2879
- startView: 0,
2880
- autoclose: false
2881
- },
2882
- /**
2883
- Text shown as clear date button.
2884
- If <code>false</code> clear button will not be rendered.
2885
-
2886
- @property clear
2887
- @type boolean|string
2888
- @default 'x clear'
2889
- **/
2890
- clear: '&times; clear'
2891
- });
2892
-
2893
- $.fn.editabletypes.date = Date;
2894
-
2895
- }(window.jQuery));