ui_bibz 3.0.13 → 4.0.0.beta3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (294) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +3 -3
  3. data/.github/workflows/linter.yml +13 -12
  4. data/.overcommit.yml +6 -0
  5. data/.rubocop.yml +6 -0
  6. data/.ruby-version +1 -1
  7. data/Gemfile +19 -12
  8. data/Gemfile.lock +178 -138
  9. data/app/assets/config/ui_bibz.js +12 -0
  10. data/app/assets/javascripts/forms/formula.js +82 -0
  11. data/app/assets/javascripts/forms/input-connected.js +132 -0
  12. data/app/assets/javascripts/forms/jquery.multi-select-extend.js +52 -0
  13. data/app/assets/javascripts/forms.js +160 -0
  14. data/app/assets/javascripts/interfaces.js +56 -0
  15. data/app/assets/javascripts/tables.js +49 -0
  16. data/app/assets/javascripts/ui_bibz_js.js +37 -0
  17. data/app/assets/stylesheets/navigations/_nav.sass +2 -0
  18. data/app/assets/stylesheets/navigations/_navbar.sass +12 -0
  19. data/app/assets/stylesheets/navigations/_progress_bar.sass +2 -0
  20. data/app/assets/stylesheets/navigations/_toolbar.sass +3 -0
  21. data/app/assets/stylesheets/sass/_boxes.sass +1 -0
  22. data/app/assets/stylesheets/sass/_containers.sass +2 -0
  23. data/app/assets/stylesheets/sass/_fixes.sass +2 -0
  24. data/app/assets/stylesheets/sass/_forms.sass +8 -0
  25. data/app/assets/stylesheets/sass/_navigations.sass +4 -0
  26. data/app/assets/stylesheets/sass/_notifications.sass +4 -0
  27. data/app/assets/stylesheets/sass/_tables.sass +2 -0
  28. data/app/assets/stylesheets/sass/_variables_mixins_functions.sass +3 -0
  29. data/app/assets/stylesheets/sass/boxes/_card.sass +4 -0
  30. data/app/assets/stylesheets/sass/containers/_panel.scss +330 -0
  31. data/app/assets/stylesheets/sass/forms/_bootstrap_select.sass +5 -0
  32. data/app/assets/stylesheets/sass/forms/_button.sass +3 -0
  33. data/app/assets/stylesheets/sass/forms/_date_picker.sass +3 -0
  34. data/app/assets/stylesheets/sass/forms/_form_check.sass +10 -0
  35. data/app/assets/stylesheets/sass/forms/_formula_field.sass +17 -0
  36. data/app/assets/stylesheets/sass/forms/_multiselect.sass +44 -0
  37. data/app/assets/stylesheets/sass/forms/_range.sass +44 -0
  38. data/app/assets/stylesheets/sass/forms/_slider.sass +136 -0
  39. data/app/assets/stylesheets/sass/forms/_surround_field.sass +25 -0
  40. data/app/assets/stylesheets/sass/notifications/_badge.sass +5 -0
  41. data/app/assets/stylesheets/sass/notifications/_glyph.sass +3 -0
  42. data/app/assets/stylesheets/sass/notifications/_star.sass +2 -0
  43. data/app/assets/stylesheets/sass/notifications/_toast.sass +3 -0
  44. data/app/assets/stylesheets/sass/tables/_table.sass +39 -0
  45. data/app/assets/stylesheets/sass/tables/_table_card.sass +39 -0
  46. data/app/assets/stylesheets/ui_bibz.sass +26 -0
  47. data/bin/test +3 -5
  48. data/config/importmap.rb +19 -0
  49. data/config/initializers/assets.rb +5 -0
  50. data/config/initializers/will_paginate.rb +1 -3
  51. data/lib/ui_bibz/builders/data_html_options_builder.rb +118 -0
  52. data/lib/ui_bibz/builders/html_classes_builder.rb +89 -0
  53. data/lib/ui_bibz/builders/html_options_builder.rb +22 -0
  54. data/lib/ui_bibz/factory_methods/component_initialize_factory_method.rb +33 -0
  55. data/lib/ui_bibz/helpers/ui/core/boxes_helper.rb +12 -12
  56. data/lib/ui_bibz/helpers/ui/core/forms_helper.rb +50 -50
  57. data/lib/ui_bibz/helpers/ui/core/icons_helper.rb +6 -6
  58. data/lib/ui_bibz/helpers/ui/core/layouts_helper.rb +2 -2
  59. data/lib/ui_bibz/helpers/ui/core/lists_helper.rb +2 -2
  60. data/lib/ui_bibz/helpers/ui/core/navigations_helper.rb +12 -12
  61. data/lib/ui_bibz/helpers/ui/core/notifications_helper.rb +4 -4
  62. data/lib/ui_bibz/helpers/ui/core/windows_helper.rb +10 -2
  63. data/lib/ui_bibz/helpers/ui/ux_helper.rb +2 -2
  64. data/lib/ui_bibz/helpers/utils_helper.rb +2 -2
  65. data/lib/ui_bibz/infos.rb +3 -3
  66. data/lib/ui_bibz/inputs/ui_bibz_form/ui_bibz_form_builder.rb +12 -12
  67. data/lib/ui_bibz/inputs/ui_bibz_inputs/collection_input.rb +1 -1
  68. data/lib/ui_bibz/rails/engine.rb +21 -4
  69. data/lib/ui_bibz/strategies/component_initialize_abstract_strategy.rb +27 -0
  70. data/lib/ui_bibz/strategies/component_initialize_block_strategy.rb +31 -0
  71. data/lib/ui_bibz/strategies/component_initialize_hash_strategy.rb +18 -0
  72. data/lib/ui_bibz/strategies/component_initialize_standard_strategy.rb +18 -0
  73. data/lib/ui_bibz/ui/concerns/card_itemable_concern.rb +4 -4
  74. data/lib/ui_bibz/ui/concerns/notification_concern.rb +1 -1
  75. data/lib/ui_bibz/ui/core/boxes/card.rb +1 -1
  76. data/lib/ui_bibz/ui/core/boxes/card_accordion.rb +4 -4
  77. data/lib/ui_bibz/ui/core/boxes/card_column.rb +1 -1
  78. data/lib/ui_bibz/ui/core/boxes/card_deck.rb +1 -1
  79. data/lib/ui_bibz/ui/core/boxes/card_grid.rb +0 -3
  80. data/lib/ui_bibz/ui/core/boxes/card_group.rb +1 -1
  81. data/lib/ui_bibz/ui/core/boxes/components/card_body.rb +9 -9
  82. data/lib/ui_bibz/ui/core/boxes/components/card_col.rb +2 -2
  83. data/lib/ui_bibz/ui/core/boxes/components/card_list_group.rb +1 -1
  84. data/lib/ui_bibz/ui/core/boxes/components/card_row.rb +1 -1
  85. data/lib/ui_bibz/ui/core/component.rb +13 -62
  86. data/lib/ui_bibz/ui/core/forms/buttons/button.rb +3 -1
  87. data/lib/ui_bibz/ui/core/forms/buttons/button_group.rb +11 -11
  88. data/lib/ui_bibz/ui/core/forms/choices/box_switch_field.rb +7 -7
  89. data/lib/ui_bibz/ui/core/forms/choices/checkbox_field.rb +2 -2
  90. data/lib/ui_bibz/ui/core/forms/choices/choice_group.rb +5 -6
  91. data/lib/ui_bibz/ui/core/forms/choices/components/choice.rb +1 -1
  92. data/lib/ui_bibz/ui/core/forms/dates/date_picker_field.rb +15 -15
  93. data/lib/ui_bibz/ui/core/forms/dropdowns/components/dropdown_link.rb +1 -1
  94. data/lib/ui_bibz/ui/core/forms/dropdowns/dropdown.rb +5 -5
  95. data/lib/ui_bibz/ui/core/forms/numbers/slider_field.rb +1 -1
  96. data/lib/ui_bibz/ui/core/forms/selects/dropdown_select_field.rb +10 -10
  97. data/lib/ui_bibz/ui/core/forms/selects/multi_column_field.rb +2 -2
  98. data/lib/ui_bibz/ui/core/forms/surrounds/surround_field.rb +32 -32
  99. data/lib/ui_bibz/ui/core/forms/textareas/markdown_editor_field.rb +7 -8
  100. data/lib/ui_bibz/ui/core/icons/components/glyph_text.rb +1 -1
  101. data/lib/ui_bibz/ui/core/icons/glyph.rb +4 -3
  102. data/lib/ui_bibz/ui/core/layouts/row.rb +2 -2
  103. data/lib/ui_bibz/ui/core/lists/components/list.rb +4 -4
  104. data/lib/ui_bibz/ui/core/lists/list_group.rb +1 -1
  105. data/lib/ui_bibz/ui/core/navigations/breadcrumb.rb +6 -4
  106. data/lib/ui_bibz/ui/core/navigations/components/nav_link_span.rb +1 -2
  107. data/lib/ui_bibz/ui/core/navigations/components/navbar_form.rb +6 -5
  108. data/lib/ui_bibz/ui/core/navigations/components/toolbar_form.rb +2 -2
  109. data/lib/ui_bibz/ui/core/navigations/nav.rb +10 -6
  110. data/lib/ui_bibz/ui/core/navigations/navbar.rb +21 -19
  111. data/lib/ui_bibz/ui/core/navigations/pagination.rb +3 -3
  112. data/lib/ui_bibz/ui/core/navigations/toolbar.rb +5 -5
  113. data/lib/ui_bibz/ui/core/notifications/alert.rb +4 -5
  114. data/lib/ui_bibz/ui/core/notifications/badge.rb +6 -2
  115. data/lib/ui_bibz/ui/core/notifications/components/toast_header.rb +1 -1
  116. data/lib/ui_bibz/ui/core/notifications/progress_bar.rb +3 -3
  117. data/lib/ui_bibz/ui/core/notifications/toast.rb +8 -9
  118. data/lib/ui_bibz/ui/core/windows/components/offcanvas_body.rb +47 -0
  119. data/lib/ui_bibz/ui/core/windows/components/offcanvas_header.rb +54 -0
  120. data/lib/ui_bibz/ui/core/windows/modal.rb +9 -9
  121. data/lib/ui_bibz/ui/core/windows/offcanvas.rb +84 -0
  122. data/lib/ui_bibz/ui/extensions/core/component/glyph_extension.rb +4 -20
  123. data/lib/ui_bibz/ui/extensions/core/component/klass_extension.rb +11 -19
  124. data/lib/ui_bibz/ui/extensions/core/forms/connect_extension.rb +1 -1
  125. data/lib/ui_bibz/ui/ux/containers/components/panel_column.rb +3 -3
  126. data/lib/ui_bibz/ui/ux/containers/components/panel_deck.rb +3 -3
  127. data/lib/ui_bibz/ui/ux/containers/components/panel_group.rb +3 -3
  128. data/lib/ui_bibz/ui/ux/containers/components/panel_header.rb +4 -4
  129. data/lib/ui_bibz/ui/ux/containers/panel.rb +13 -13
  130. data/lib/ui_bibz/ui/ux/tables/components/actions.rb +4 -4
  131. data/lib/ui_bibz/ui/ux/tables/components/column.rb +1 -1
  132. data/lib/ui_bibz/ui/ux/tables/components/columns.rb +2 -2
  133. data/lib/ui_bibz/ui/ux/tables/extensions/sortable.rb +1 -1
  134. data/lib/ui_bibz/ui/ux/tables/table.rb +5 -5
  135. data/lib/ui_bibz/ui/ux/tables/table_card.rb +6 -6
  136. data/lib/ui_bibz/ui/ux/tables/table_search_field.rb +1 -1
  137. data/lib/ui_bibz/utils/breakdown_class_name_generator.rb +3 -3
  138. data/lib/ui_bibz/utils/screwdriver.rb +1 -1
  139. data/lib/ui_bibz/view_objects/glyph_component_view_object.rb +38 -0
  140. data/lib/ui_bibz.rb +25 -0
  141. data/test/builders/data_html_classes_builder_test.rb +37 -0
  142. data/test/builders/html_classes_builder_test.rb +76 -0
  143. data/test/dummy/Rakefile +1 -1
  144. data/test/dummy/app/assets/stylesheets/application.css +1 -15
  145. data/test/dummy/app/channels/application_cable/channel.rb +6 -0
  146. data/test/dummy/app/channels/application_cable/connection.rb +6 -0
  147. data/test/dummy/app/jobs/application_job.rb +9 -0
  148. data/test/dummy/app/mailers/application_mailer.rb +6 -0
  149. data/test/dummy/app/views/layouts/application.html.erb +10 -12
  150. data/test/dummy/app/views/layouts/mailer.html.erb +13 -0
  151. data/test/dummy/app/views/layouts/mailer.text.erb +1 -0
  152. data/test/dummy/bin/rails +3 -3
  153. data/test/dummy/bin/rake +2 -2
  154. data/test/dummy/bin/setup +12 -12
  155. data/test/dummy/config/application.rb +13 -17
  156. data/test/dummy/config/boot.rb +3 -3
  157. data/test/dummy/config/database.yml +2 -2
  158. data/test/dummy/config/environment.rb +1 -1
  159. data/test/dummy/config/environments/development.rb +21 -16
  160. data/test/dummy/config/environments/production.rb +16 -41
  161. data/test/dummy/config/environments/test.rb +19 -8
  162. data/test/dummy/config/importmap.rb +11 -0
  163. data/test/dummy/config/initializers/content_security_policy.rb +21 -24
  164. data/test/dummy/config/initializers/filter_parameter_logging.rb +6 -2
  165. data/test/dummy/config/initializers/inflections.rb +4 -4
  166. data/test/dummy/config/initializers/permissions_policy.rb +12 -0
  167. data/test/dummy/config/locales/en.yml +13 -3
  168. data/test/dummy/config/puma.rb +7 -2
  169. data/test/dummy/config/storage.yml +5 -5
  170. data/test/dummy/config.ru +2 -1
  171. data/test/simple_form_test.rb +24 -24
  172. data/test/ui/core/boxes/card_test.rb +2 -1
  173. data/test/ui/core/component_test.rb +2 -2
  174. data/test/ui/core/forms/buttons/button_group_test.rb +1 -1
  175. data/test/ui/core/forms/buttons/button_link_test.rb +1 -1
  176. data/test/ui/core/forms/buttons/button_refresh_test.rb +1 -1
  177. data/test/ui/core/forms/buttons/button_test.rb +2 -2
  178. data/test/ui/core/forms/choices/box_switch_field_test.rb +10 -10
  179. data/test/ui/core/forms/choices/checkbox_field_test.rb +1 -1
  180. data/test/ui/core/forms/choices/choice_group_test.rb +1 -1
  181. data/test/ui/core/forms/dropdowns/dropdown_test.rb +1 -1
  182. data/test/ui/core/forms/numbers/formula_field_test.rb +1 -1
  183. data/test/ui/core/forms/selects/dropdown_select_field_test.rb +2 -2
  184. data/test/ui/core/forms/selects/select_field_test.rb +1 -1
  185. data/test/ui/core/forms/surrounds/surround_field_test.rb +4 -4
  186. data/test/ui/core/forms/texts/auto_complete_field_test.rb +2 -2
  187. data/test/ui/core/icons/glyph_test.rb +8 -4
  188. data/test/ui/core/icons/star_test.rb +12 -6
  189. data/test/ui/core/navigations/breadcrumb_test.rb +1 -1
  190. data/test/ui/core/navigations/link_test.rb +1 -1
  191. data/test/ui/core/navigations/nav_test.rb +11 -0
  192. data/test/ui/core/notifications/alert_test.rb +1 -1
  193. data/test/ui/core/notifications/badge_test.rb +3 -3
  194. data/test/ui/core/notifications/popover_test.rb +4 -4
  195. data/test/ui/core/notifications/spinner_test.rb +1 -1
  196. data/test/ui/core/notifications/toast_test.rb +1 -1
  197. data/test/ui/core/notifications/tooltip_test.rb +4 -4
  198. data/test/ui/core/windows/offcanvas_test.rb +27 -0
  199. data/test/ui/ux/containers/panel_test.rb +1 -1
  200. data/test/ui/ux/tables/table_test.rb +3 -3
  201. data/test/view_objects/glyph_component_view_object_test.rb +17 -0
  202. data/ui_bibz.gemspec +6 -20
  203. data/vendor/assets/fonts/fontawesome/fa-brands-400.ttf +0 -0
  204. data/vendor/assets/fonts/fontawesome/fa-brands-400.woff2 +0 -0
  205. data/vendor/assets/fonts/fontawesome/fa-regular-400.ttf +0 -0
  206. data/vendor/assets/fonts/fontawesome/fa-regular-400.woff2 +0 -0
  207. data/vendor/assets/fonts/fontawesome/fa-solid-900.ttf +0 -0
  208. data/vendor/assets/fonts/fontawesome/fa-solid-900.woff2 +0 -0
  209. data/vendor/assets/fonts/fontawesome/fa-v4compatibility.ttf +0 -0
  210. data/vendor/assets/fonts/fontawesome/fa-v4compatibility.woff2 +0 -0
  211. data/vendor/assets/javascripts/bootstrap-markdown.js +1 -1555
  212. data/vendor/assets/javascripts/bootstrap-multiselect.min.js +40 -1176
  213. data/vendor/assets/javascripts/bootstrap-switch.min.js +9 -21
  214. data/vendor/assets/javascripts/bs-custom-file-input.min.js +0 -1
  215. data/vendor/assets/javascripts/fontawesome/all.js +5977 -0
  216. data/vendor/assets/javascripts/fontawesome/all.min.js +6 -0
  217. data/vendor/assets/javascripts/fontawesome/brands.js +749 -0
  218. data/vendor/assets/javascripts/fontawesome/brands.min.js +6 -0
  219. data/vendor/assets/javascripts/fontawesome/conflict-detection.js +1138 -0
  220. data/vendor/assets/javascripts/fontawesome/conflict-detection.min.js +6 -0
  221. data/vendor/assets/javascripts/fontawesome/fontawesome.js +3126 -0
  222. data/vendor/assets/javascripts/fontawesome/fontawesome.min.js +6 -0
  223. data/vendor/assets/javascripts/fontawesome/regular.js +445 -0
  224. data/vendor/assets/javascripts/fontawesome/regular.min.js +6 -0
  225. data/vendor/assets/javascripts/fontawesome/solid.js +1672 -0
  226. data/vendor/assets/javascripts/fontawesome/solid.min.js +6 -0
  227. data/vendor/assets/javascripts/fontawesome/v4-shims.js +225 -0
  228. data/vendor/assets/javascripts/fontawesome/v4-shims.min.js +6 -0
  229. data/vendor/assets/javascripts/fuzzysort.js +562 -0
  230. data/vendor/assets/javascripts/jquery-3.7.0.min.js +2 -0
  231. data/vendor/assets/javascripts/jquery.multi-select.min.js +725 -1
  232. data/vendor/assets/stylesheets/bootstrap-multiselect.sass +115 -0
  233. data/vendor/assets/stylesheets/bootstrap-switch.scss +211 -0
  234. data/vendor/assets/stylesheets/fontawesome/_animated.scss +142 -9
  235. data/vendor/assets/stylesheets/fontawesome/_bordered-pulled.scss +13 -13
  236. data/vendor/assets/stylesheets/fontawesome/_core.scss +28 -6
  237. data/vendor/assets/stylesheets/fontawesome/_fixed-width.scss +2 -1
  238. data/vendor/assets/stylesheets/fontawesome/_functions.scss +57 -0
  239. data/vendor/assets/stylesheets/fontawesome/_icons.scss +7 -1438
  240. data/vendor/assets/stylesheets/fontawesome/_list.scss +4 -4
  241. data/vendor/assets/stylesheets/fontawesome/_mixins.scss +53 -34
  242. data/vendor/assets/stylesheets/fontawesome/_rotated-flipped.scss +25 -18
  243. data/vendor/assets/stylesheets/fontawesome/_screen-reader.scss +12 -3
  244. data/vendor/assets/stylesheets/fontawesome/_shims.scss +640 -664
  245. data/vendor/assets/stylesheets/fontawesome/_sizing.scss +16 -0
  246. data/vendor/assets/stylesheets/fontawesome/_stacked.scss +5 -4
  247. data/vendor/assets/stylesheets/fontawesome/_variables.scss +4896 -1393
  248. data/vendor/assets/stylesheets/fontawesome/brands.scss +17 -10
  249. data/vendor/assets/stylesheets/fontawesome/fontawesome.scss +7 -2
  250. data/vendor/assets/stylesheets/fontawesome/regular.scss +13 -10
  251. data/vendor/assets/stylesheets/fontawesome/solid.scss +13 -11
  252. data/vendor/assets/stylesheets/fontawesome/v4-shims.scss +6 -1
  253. data/vendor/assets/stylesheets/multi-select.css +92 -0
  254. metadata +120 -348
  255. data/.gitlab-ci.yml +0 -17
  256. data/.travis.yml +0 -24
  257. data/lib/ui_bibz/ui/extensions/core/component/popover_extension.rb +0 -70
  258. data/structure.md +0 -68
  259. data/test/dummy/README.rdoc +0 -28
  260. data/test/dummy/app/assets/javascripts/application.js +0 -13
  261. data/test/dummy/app/javascripts/packs/index.js +0 -3
  262. data/test/dummy/config/initializers/application_controller_renderer.rb +0 -9
  263. data/test/dummy/config/initializers/assets.rb +0 -14
  264. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -8
  265. data/test/dummy/config/initializers/cookies_serializer.rb +0 -7
  266. data/test/dummy/config/initializers/mime_types.rb +0 -5
  267. data/test/dummy/config/initializers/session_store.rb +0 -5
  268. data/test/dummy/config/initializers/ui_bibz.rb +0 -5
  269. data/test/dummy/config/initializers/wrap_parameters.rb +0 -16
  270. data/test/dummy/config/secrets.yml +0 -22
  271. data/test/dummy/config/spring.rb +0 -8
  272. data/test/dummy/test/models/user_test.rb +0 -9
  273. data/vendor/assets/fonts/fa-brands-400.eot +0 -0
  274. data/vendor/assets/fonts/fa-brands-400.svg +0 -3570
  275. data/vendor/assets/fonts/fa-brands-400.ttf +0 -0
  276. data/vendor/assets/fonts/fa-brands-400.woff +0 -0
  277. data/vendor/assets/fonts/fa-brands-400.woff2 +0 -0
  278. data/vendor/assets/fonts/fa-regular-400.eot +0 -0
  279. data/vendor/assets/fonts/fa-regular-400.svg +0 -803
  280. data/vendor/assets/fonts/fa-regular-400.ttf +0 -0
  281. data/vendor/assets/fonts/fa-regular-400.woff +0 -0
  282. data/vendor/assets/fonts/fa-regular-400.woff2 +0 -0
  283. data/vendor/assets/fonts/fa-solid-900.eot +0 -0
  284. data/vendor/assets/fonts/fa-solid-900.svg +0 -4938
  285. data/vendor/assets/fonts/fa-solid-900.ttf +0 -0
  286. data/vendor/assets/fonts/fa-solid-900.woff +0 -0
  287. data/vendor/assets/fonts/fa-solid-900.woff2 +0 -0
  288. data/vendor/assets/javascripts/all.js +0 -4441
  289. data/vendor/assets/javascripts/all.min.js +0 -5
  290. data/vendor/assets/stylesheets/all.min.css +0 -5
  291. data/vendor/assets/stylesheets/fontawesome/_larger.scss +0 -23
  292. data/vendor/assets/stylesheets/svg-with-js.css +0 -5
  293. /data/{test/dummy/app/mailers/.keep → app/assets/stylesheets/sass/forms/_dropdown.sass} +0 -0
  294. /data/{test/dummy/app/views/users/index.html.erb → app/assets/stylesheets/sass/forms/_input_refresh_button.sass} +0 -0
@@ -16,1558 +16,4 @@
16
16
  * See the License for the specific language governing permissions and
17
17
  * limitations under the License.
18
18
  * ========================================================== */
19
- (function(factory) {
20
- if (typeof define === "function" && define.amd) {
21
- // RequireJS
22
- define(["jquery"], factory);
23
- } else if (typeof exports === 'object') {
24
- // Backbone.js
25
- factory(require('jquery'));
26
- } else {
27
- // jQuery plugin
28
- factory(jQuery);
29
- }
30
- }(function($) {
31
- "use strict";
32
-
33
- /* MARKDOWN CLASS DEFINITION
34
- * ========================== */
35
-
36
- var Markdown = function(element, options) {
37
- // @TODO : remove this BC on next major release
38
- // @see : https://github.com/toopay/bootstrap-markdown/issues/109
39
- var opts = ['autofocus', 'savable', 'hideable', 'width',
40
- 'height', 'resize', 'iconlibrary', 'language',
41
- 'footer', 'fullscreen', 'hiddenButtons', 'disabledButtons'
42
- ];
43
- $.each(opts, function(_, opt) {
44
- if (typeof $(element).data(opt) !== 'undefined') {
45
- options = typeof options == 'object' ? options : {};
46
- options[opt] = $(element).data(opt);
47
- }
48
- });
49
- // End BC
50
-
51
- // Class Properties
52
- this.$ns = 'bootstrap-markdown';
53
- this.$element = $(element);
54
- this.$editable = {
55
- el: null,
56
- type: null,
57
- attrKeys: [],
58
- attrValues: [],
59
- content: null
60
- };
61
- this.$options = $.extend(true, {}, $.fn.markdown.defaults, options, this.$element.data('options'));
62
- this.$oldContent = null;
63
- this.$isPreview = false;
64
- this.$isFullscreen = false;
65
- this.$editor = null;
66
- this.$textarea = null;
67
- this.$handler = [];
68
- this.$callback = [];
69
- this.$nextTab = [];
70
-
71
- this.showEditor();
72
- };
73
-
74
- Markdown.prototype = {
75
-
76
- constructor: Markdown,
77
- __alterButtons: function(name, alter) {
78
- var handler = this.$handler,
79
- isAll = (name == 'all'),
80
- that = this;
81
-
82
- $.each(handler, function(k, v) {
83
- var halt = true;
84
- if (isAll) {
85
- halt = false;
86
- } else {
87
- halt = v.indexOf(name) < 0;
88
- }
89
-
90
- if (halt === false) {
91
- alter(that.$editor.find('button[data-handler="' + v + '"]'));
92
- }
93
- });
94
- },
95
- __buildButtons: function(buttonsArray, container) {
96
- var i,
97
- ns = this.$ns,
98
- handler = this.$handler,
99
- callback = this.$callback;
100
-
101
- for (i = 0; i < buttonsArray.length; i++) {
102
- // Build each group container
103
- var y, btnGroups = buttonsArray[i];
104
- for (y = 0; y < btnGroups.length; y++) {
105
- // Build each button group
106
- var z,
107
- buttons = btnGroups[y].data,
108
- btnGroupContainer = $('<div/>', {
109
- 'class': 'btn-group'
110
- });
111
-
112
- for (z = 0; z < buttons.length; z++) {
113
- var button = buttons[z],
114
- buttonContainer, buttonIconContainer,
115
- buttonHandler = ns + '-' + button.name,
116
- buttonIcon = this.__getIcon(button),
117
- btnText = button.btnText ? button.btnText : '',
118
- btnClass = button.btnClass ? button.btnClass : 'btn',
119
- tabIndex = button.tabIndex ? button.tabIndex : '-1',
120
- hotkey = typeof button.hotkey !== 'undefined' ? button.hotkey : '',
121
- hotkeyCaption = typeof jQuery.hotkeys !== 'undefined' && hotkey !== '' ? ' (' + hotkey + ')' : '';
122
-
123
- // Construct the button object
124
- buttonContainer = $('<button></button>');
125
- buttonContainer.text(' ' + this.__localize(btnText)).addClass('btn-default btn-sm').addClass(btnClass);
126
- if (btnClass.match(/btn\-(primary|success|info|warning|danger|link)/)) {
127
- buttonContainer.removeClass('btn-default');
128
- }
129
- buttonContainer.attr({
130
- 'type': 'button',
131
- 'title': this.__localize(button.title) + hotkeyCaption,
132
- 'tabindex': tabIndex,
133
- 'data-provider': ns,
134
- 'data-handler': buttonHandler,
135
- 'data-hotkey': hotkey
136
- });
137
- if (button.toggle === true) {
138
- buttonContainer.attr('data-toggle', 'button');
139
- }
140
- buttonIconContainer = $('<span/>');
141
- buttonIconContainer.addClass(buttonIcon);
142
- buttonIconContainer.prependTo(buttonContainer);
143
-
144
- // Attach the button object
145
- btnGroupContainer.append(buttonContainer);
146
-
147
- // Register handler and callback
148
- handler.push(buttonHandler);
149
- callback.push(button.callback);
150
- }
151
-
152
- // Attach the button group into container DOM
153
- container.append(btnGroupContainer);
154
- }
155
- }
156
-
157
- return container;
158
- },
159
- __setListener: function() {
160
- // Set size and resizable Properties
161
- var hasRows = typeof this.$textarea.attr('rows') !== 'undefined',
162
- maxRows = this.$textarea.val().split("\n").length > 5 ? this.$textarea.val().split("\n").length : '5',
163
- rowsVal = hasRows ? this.$textarea.attr('rows') : maxRows;
164
-
165
- this.$textarea.attr('rows', rowsVal);
166
- if (this.$options.resize) {
167
- this.$textarea.css('resize', this.$options.resize);
168
- }
169
-
170
- // Re-attach markdown data
171
- this.$textarea.data('markdown', this);
172
- },
173
- __setEventListeners: function() {
174
- this.$textarea.on({
175
- 'focus': $.proxy(this.focus, this),
176
- 'keyup': $.proxy(this.keyup, this),
177
- 'change': $.proxy(this.change, this),
178
- 'select': $.proxy(this.select, this)
179
- });
180
-
181
- if (this.eventSupported('keydown')) {
182
- this.$textarea.on('keydown', $.proxy(this.keydown, this));
183
- }
184
-
185
- if (this.eventSupported('keypress')) {
186
- this.$textarea.on('keypress', $.proxy(this.keypress, this));
187
- }
188
- },
189
- __handle: function(e) {
190
- var target = $(e.currentTarget),
191
- handler = this.$handler,
192
- callback = this.$callback,
193
- handlerName = target.attr('data-handler'),
194
- callbackIndex = handler.indexOf(handlerName),
195
- callbackHandler = callback[callbackIndex];
196
-
197
- // Trigger the focusin
198
- $(e.currentTarget).focus();
199
-
200
- callbackHandler(this);
201
-
202
- // Trigger onChange for each button handle
203
- this.change(this);
204
-
205
- // Unless it was the save handler,
206
- // focusin the textarea
207
- if (handlerName.indexOf('cmdSave') < 0) {
208
- this.$textarea.focus();
209
- }
210
-
211
- e.preventDefault();
212
- },
213
- __localize: function(string) {
214
- var messages = $.fn.markdown.messages,
215
- language = this.$options.language;
216
- if (
217
- typeof messages !== 'undefined' &&
218
- typeof messages[language] !== 'undefined' &&
219
- typeof messages[language][string] !== 'undefined'
220
- ) {
221
- return messages[language][string];
222
- }
223
- return string;
224
- },
225
- __getIcon: function(src) {
226
- if(typeof src == 'object'){
227
- var customIcon = this.$options.customIcons[src.name];
228
- // console.log(customIcon)
229
- // console.log(this.$options)
230
- return typeof customIcon == 'undefined' ? src.icon[this.$options.iconlibrary] : customIcon;
231
- } else {
232
- return src;
233
- }
234
- },
235
- setFullscreen: function(mode) {
236
- var $editor = this.$editor,
237
- $textarea = this.$textarea;
238
-
239
- if (mode === true) {
240
- $editor.addClass('md-fullscreen-mode');
241
- $('body').addClass('md-nooverflow');
242
- this.$options.onFullscreen(this);
243
- } else {
244
- $editor.removeClass('md-fullscreen-mode');
245
- $('body').removeClass('md-nooverflow');
246
- this.$options.onFullscreenExit(this);
247
-
248
- if (this.$isPreview === true)
249
- this.hidePreview().showPreview();
250
- }
251
-
252
- this.$isFullscreen = mode;
253
- $textarea.focus();
254
- },
255
- showEditor: function() {
256
- var instance = this,
257
- textarea,
258
- ns = this.$ns,
259
- container = this.$element,
260
- originalHeigth = container.css('height'),
261
- originalWidth = container.css('width'),
262
- editable = this.$editable,
263
- handler = this.$handler,
264
- callback = this.$callback,
265
- options = this.$options,
266
- editor = $('<div/>', {
267
- 'class': 'md-editor',
268
- click: function() {
269
- instance.focus();
270
- }
271
- });
272
-
273
- // Prepare the editor
274
- if (this.$editor === null) {
275
- // Create the panel
276
- var editorHeader = $('<div/>', {
277
- 'class': 'md-header btn-toolbar'
278
- });
279
-
280
- // Merge the main & additional button groups together
281
- var allBtnGroups = [];
282
- if (options.buttons.length > 0) allBtnGroups = allBtnGroups.concat(options.buttons[0]);
283
- if (options.additionalButtons.length > 0) {
284
- // iterate the additional button groups
285
- $.each(options.additionalButtons[0], function(idx, buttonGroup) {
286
-
287
- // see if the group name of the additional group matches an existing group
288
- var matchingGroups = $.grep(allBtnGroups, function(allButtonGroup, allIdx) {
289
- return allButtonGroup.name === buttonGroup.name;
290
- });
291
-
292
- // if it matches add the additional buttons to that group, if not just add it to the all buttons group
293
- if (matchingGroups.length > 0) {
294
- matchingGroups[0].data = matchingGroups[0].data.concat(buttonGroup.data);
295
- } else {
296
- allBtnGroups.push(options.additionalButtons[0][idx]);
297
- }
298
-
299
- });
300
- }
301
-
302
- // Reduce and/or reorder the button groups
303
- if (options.reorderButtonGroups.length > 0) {
304
- allBtnGroups = allBtnGroups
305
- .filter(function(btnGroup) {
306
- return options.reorderButtonGroups.indexOf(btnGroup.name) > -1;
307
- })
308
- .sort(function(a, b) {
309
- if (options.reorderButtonGroups.indexOf(a.name) < options.reorderButtonGroups.indexOf(b.name)) return -1;
310
- if (options.reorderButtonGroups.indexOf(a.name) > options.reorderButtonGroups.indexOf(b.name)) return 1;
311
- return 0;
312
- });
313
- }
314
-
315
- // Build the buttons
316
- if (allBtnGroups.length > 0) {
317
- editorHeader = this.__buildButtons([allBtnGroups], editorHeader);
318
- }
319
-
320
- if (options.fullscreen.enable) {
321
- editorHeader.append('<div class="md-controls"><a class="md-control md-control-fullscreen" href="#"><span class="' + this.__getIcon(options.fullscreen.icons.fullscreenOn) + '"></span></a></div>').on('click', '.md-control-fullscreen', function(e) {
322
- e.preventDefault();
323
- instance.setFullscreen(true);
324
- });
325
- }
326
-
327
- editor.append(editorHeader);
328
-
329
- // Wrap the textarea
330
- if (container.is('textarea')) {
331
- container.before(editor);
332
- textarea = container;
333
- textarea.addClass('md-input');
334
- editor.append(textarea);
335
- } else {
336
- var rawContent = (typeof toMarkdown == 'function') ? toMarkdown(container.html()) : container.html(),
337
- currentContent = $.trim(rawContent);
338
-
339
- // This is some arbitrary content that could be edited
340
- textarea = $('<textarea/>', {
341
- 'class': 'md-input',
342
- 'val': currentContent
343
- });
344
-
345
- editor.append(textarea);
346
-
347
- // Save the editable
348
- editable.el = container;
349
- editable.type = container.prop('tagName').toLowerCase();
350
- editable.content = container.html();
351
-
352
- $(container[0].attributes).each(function() {
353
- editable.attrKeys.push(this.nodeName);
354
- editable.attrValues.push(this.nodeValue);
355
- });
356
-
357
- // Set editor to block the original container
358
- container.replaceWith(editor);
359
- }
360
-
361
- var editorFooter = $('<div/>', {
362
- 'class': 'md-footer'
363
- }),
364
- createFooter = false,
365
- footer = '';
366
- // Create the footer if savable
367
- if (options.savable) {
368
- createFooter = true;
369
- var saveHandler = 'cmdSave';
370
-
371
- // Register handler and callback
372
- handler.push(saveHandler);
373
- callback.push(options.onSave);
374
-
375
- editorFooter.append('<button class="btn btn-success" data-provider="' +
376
- ns +
377
- '" data-handler="' +
378
- saveHandler +
379
- '"><i class="icon icon-white icon-ok"></i> ' +
380
- this.__localize('Save') +
381
- '</button>');
382
-
383
-
384
- }
385
-
386
- footer = typeof options.footer === 'function' ? options.footer(this) : options.footer;
387
-
388
- if ($.trim(footer) !== '') {
389
- createFooter = true;
390
- editorFooter.append(footer);
391
- }
392
-
393
- if (createFooter) editor.append(editorFooter);
394
-
395
- // Set width
396
- if (options.width && options.width !== 'inherit') {
397
- if (jQuery.isNumeric(options.width)) {
398
- editor.css('display', 'table');
399
- textarea.css('width', options.width + 'px');
400
- } else {
401
- editor.addClass(options.width);
402
- }
403
- }
404
-
405
- // Set height
406
- if (options.height && options.height !== 'inherit') {
407
- if (jQuery.isNumeric(options.height)) {
408
- var height = options.height;
409
- if (editorHeader) height = Math.max(0, height - editorHeader.outerHeight());
410
- if (editorFooter) height = Math.max(0, height - editorFooter.outerHeight());
411
- textarea.css('height', height + 'px');
412
- } else {
413
- editor.addClass(options.height);
414
- }
415
- }
416
-
417
- // Reference
418
- this.$editor = editor;
419
- this.$textarea = textarea;
420
- this.$editable = editable;
421
- this.$oldContent = this.getContent();
422
-
423
- this.__setListener();
424
- this.__setEventListeners();
425
-
426
- // Set editor attributes, data short-hand API and listener
427
- this.$editor.attr('id', (new Date()).getTime());
428
- this.$editor.on('click', '[data-provider="bootstrap-markdown"]', $.proxy(this.__handle, this));
429
-
430
- if (this.$element.is(':disabled') || this.$element.is('[readonly]')) {
431
- this.$editor.addClass('md-editor-disabled');
432
- this.disableButtons('all');
433
- }
434
-
435
- if (this.eventSupported('keydown') && typeof jQuery.hotkeys === 'object') {
436
- editorHeader.find('[data-provider="bootstrap-markdown"]').each(function() {
437
- var $button = $(this),
438
- hotkey = $button.attr('data-hotkey');
439
- if (hotkey.toLowerCase() !== '') {
440
- textarea.bind('keydown', hotkey, function() {
441
- $button.trigger('click');
442
- return false;
443
- });
444
- }
445
- });
446
- }
447
-
448
- if (options.initialstate === 'preview') {
449
- this.showPreview();
450
- } else if (options.initialstate === 'fullscreen' && options.fullscreen.enable) {
451
- this.setFullscreen(true);
452
- }
453
-
454
- } else {
455
- this.$editor.show();
456
- }
457
-
458
- if (options.autofocus) {
459
- this.$textarea.focus();
460
- this.$editor.addClass('active');
461
- }
462
-
463
- if (options.fullscreen.enable && options.fullscreen !== false) {
464
- this.$editor.append('<div class="md-fullscreen-controls">' +
465
- '<a href="#" class="exit-fullscreen" title="Exit fullscreen"><span class="' + this.__getIcon(options.fullscreen.icons.fullscreenOff) + '">' +
466
- '</span></a>' +
467
- '</div>');
468
- this.$editor.on('click', '.exit-fullscreen', function(e) {
469
- e.preventDefault();
470
- instance.setFullscreen(false);
471
- });
472
- }
473
-
474
- // hide hidden buttons from options
475
- this.hideButtons(options.hiddenButtons);
476
-
477
- // disable disabled buttons from options
478
- this.disableButtons(options.disabledButtons);
479
-
480
- // enable dropZone if available and configured
481
- if (options.dropZoneOptions) {
482
- if (this.$editor.dropzone) {
483
- if(!options.dropZoneOptions.init) {
484
- options.dropZoneOptions.init = function() {
485
- var caretPos = 0;
486
- this.on('drop', function(e) {
487
- caretPos = textarea.prop('selectionStart');
488
- });
489
- this.on('success', function(file, path) {
490
- var text = textarea.val();
491
- textarea.val(text.substring(0, caretPos) + '\n![description](' + path + ')\n' + text.substring(caretPos));
492
- });
493
- this.on('error', function(file, error, xhr) {
494
- console.log('Error:', error);
495
- });
496
- };
497
- }
498
- this.$editor.addClass('dropzone');
499
- this.$editor.dropzone(options.dropZoneOptions);
500
- } else {
501
- console.log('dropZoneOptions was configured, but DropZone was not detected.');
502
- }
503
- }
504
-
505
- // enable data-uris via drag and drop
506
- if (options.enableDropDataUri === true) {
507
- this.$editor.on('drop', function(e) {
508
- var caretPos = textarea.prop('selectionStart');
509
- e.stopPropagation();
510
- e.preventDefault();
511
- $.each(e.originalEvent.dataTransfer.files, function(index, file){
512
- var fileReader = new FileReader();
513
- fileReader.onload = (function(file) {
514
- var type = file.type.split('/')[0];
515
- return function(e) {
516
- var text = textarea.val();
517
- if (type === 'image')
518
- textarea.val(text.substring(0, caretPos) + '\n<img src="'+ e.target.result +'" />\n' + text.substring(caretPos) );
519
- else
520
- textarea.val(text.substring(0, caretPos) + '\n<a href="'+ e.target.result +'">Download ' + file.name + '</a>\n' + text.substring(caretPos) );
521
- };
522
- })(file);
523
- fileReader.readAsDataURL(file);
524
- });
525
- });
526
- }
527
-
528
- // Trigger the onShow hook
529
- options.onShow(this);
530
-
531
- return this;
532
- },
533
- parseContent: function(val) {
534
- var content;
535
-
536
- // parse with supported markdown parser
537
- val = val || this.$textarea.val();
538
-
539
- if (this.$options.parser) {
540
- content = this.$options.parser(val);
541
- } else if (typeof markdown == 'object') {
542
- content = markdown.toHTML(val);
543
- } else if (typeof marked == 'function') {
544
- content = marked(val);
545
- } else {
546
- content = val;
547
- }
548
-
549
- return content;
550
- },
551
- showPreview: function() {
552
- var options = this.$options,
553
- container = this.$textarea,
554
- afterContainer = container.next(),
555
- replacementContainer = $('<div/>', {
556
- 'class': 'md-preview',
557
- 'data-provider': 'markdown-preview'
558
- }),
559
- content,
560
- callbackContent;
561
-
562
- if (this.$isPreview === true) {
563
- // Avoid sequenced element creation on misused scenario
564
- // @see https://github.com/toopay/bootstrap-markdown/issues/170
565
- return this;
566
- }
567
-
568
- // Give flag that tells the editor to enter preview mode
569
- this.$isPreview = true;
570
- // Disable all buttons
571
- this.disableButtons('all').enableButtons('cmdPreview');
572
-
573
- // Try to get the content from callback
574
- callbackContent = options.onPreview(this, replacementContainer);
575
- // Set the content based on the callback content if string, otherwise parse value from textarea
576
- content = typeof callbackContent == 'string' ? callbackContent : this.parseContent();
577
-
578
- // Build preview element
579
- replacementContainer.html(content);
580
-
581
- if (afterContainer && afterContainer.attr('class') == 'md-footer') {
582
- // If there is footer element, insert the preview container before it
583
- replacementContainer.insertBefore(afterContainer);
584
- } else {
585
- // Otherwise, just append it after textarea
586
- container.parent().append(replacementContainer);
587
- }
588
-
589
- // Set the preview element dimensions
590
- replacementContainer.css({
591
- "width": container.outerWidth() + 'px',
592
- "min-height": container.outerHeight() + 'px',
593
- "height": "auto"
594
- });
595
-
596
- if (this.$options.resize) {
597
- replacementContainer.css('resize', this.$options.resize);
598
- }
599
-
600
- // Hide the last-active textarea
601
- container.hide();
602
-
603
- // Attach the editor instances
604
- replacementContainer.data('markdown', this);
605
-
606
- if (this.$element.is(':disabled') || this.$element.is('[readonly]')) {
607
- this.$editor.addClass('md-editor-disabled');
608
- this.disableButtons('all');
609
- }
610
-
611
- return this;
612
- },
613
- hidePreview: function() {
614
- // Give flag that tells the editor to quit preview mode
615
- this.$isPreview = false;
616
-
617
- // Obtain the preview container
618
- var container = this.$editor.find('div[data-provider="markdown-preview"]');
619
-
620
- // Remove the preview container
621
- container.remove();
622
-
623
- // Enable all buttons
624
- this.enableButtons('all');
625
- // Disable configured disabled buttons
626
- this.disableButtons(this.$options.disabledButtons);
627
-
628
- // Perform any callbacks
629
- this.$options.onPreviewEnd(this);
630
-
631
- // Back to the editor
632
- this.$textarea.show();
633
- this.__setListener();
634
-
635
- return this;
636
- },
637
- isDirty: function() {
638
- return this.$oldContent != this.getContent();
639
- },
640
- getContent: function() {
641
- return this.$textarea.val();
642
- },
643
- setContent: function(content) {
644
- this.$textarea.val(content);
645
-
646
- return this;
647
- },
648
- findSelection: function(chunk) {
649
- var content = this.getContent(),
650
- startChunkPosition;
651
-
652
- if (startChunkPosition = content.indexOf(chunk), startChunkPosition >= 0 && chunk.length > 0) {
653
- var oldSelection = this.getSelection(),
654
- selection;
655
-
656
- this.setSelection(startChunkPosition, startChunkPosition + chunk.length);
657
- selection = this.getSelection();
658
-
659
- this.setSelection(oldSelection.start, oldSelection.end);
660
-
661
- return selection;
662
- } else {
663
- return null;
664
- }
665
- },
666
- getSelection: function() {
667
-
668
- var e = this.$textarea[0];
669
-
670
- return (
671
-
672
- ('selectionStart' in e && function() {
673
- var l = e.selectionEnd - e.selectionStart;
674
- return {
675
- start: e.selectionStart,
676
- end: e.selectionEnd,
677
- length: l,
678
- text: e.value.substr(e.selectionStart, l)
679
- };
680
- }) ||
681
-
682
- /* browser not supported */
683
- function() {
684
- return null;
685
- }
686
-
687
- )();
688
-
689
- },
690
- setSelection: function(start, end) {
691
-
692
- var e = this.$textarea[0];
693
-
694
- return (
695
-
696
- ('selectionStart' in e && function() {
697
- e.selectionStart = start;
698
- e.selectionEnd = end;
699
- return;
700
- }) ||
701
-
702
- /* browser not supported */
703
- function() {
704
- return null;
705
- }
706
-
707
- )();
708
-
709
- },
710
- replaceSelection: function(text) {
711
-
712
- var e = this.$textarea[0];
713
-
714
- return (
715
-
716
- ('selectionStart' in e && function() {
717
- e.value = e.value.substr(0, e.selectionStart) + text + e.value.substr(e.selectionEnd, e.value.length);
718
- // Set cursor to the last replacement end
719
- e.selectionStart = e.value.length;
720
- return this;
721
- }) ||
722
-
723
- /* browser not supported */
724
- function() {
725
- e.value += text;
726
- return jQuery(e);
727
- }
728
-
729
- )();
730
- },
731
- getNextTab: function() {
732
- // Shift the nextTab
733
- if (this.$nextTab.length === 0) {
734
- return null;
735
- } else {
736
- var nextTab, tab = this.$nextTab.shift();
737
-
738
- if (typeof tab == 'function') {
739
- nextTab = tab();
740
- } else if (typeof tab == 'object' && tab.length > 0) {
741
- nextTab = tab;
742
- }
743
-
744
- return nextTab;
745
- }
746
- },
747
- setNextTab: function(start, end) {
748
- // Push new selection into nextTab collections
749
- if (typeof start == 'string') {
750
- var that = this;
751
- this.$nextTab.push(function() {
752
- return that.findSelection(start);
753
- });
754
- } else if (typeof start == 'number' && typeof end == 'number') {
755
- var oldSelection = this.getSelection();
756
-
757
- this.setSelection(start, end);
758
- this.$nextTab.push(this.getSelection());
759
-
760
- this.setSelection(oldSelection.start, oldSelection.end);
761
- }
762
-
763
- return;
764
- },
765
- __parseButtonNameParam: function(names) {
766
- return typeof names == 'string' ?
767
- names.split(' ') :
768
- names;
769
-
770
- },
771
- enableButtons: function(name) {
772
- var buttons = this.__parseButtonNameParam(name),
773
- that = this;
774
-
775
- $.each(buttons, function(i, v) {
776
- that.__alterButtons(buttons[i], function(el) {
777
- el.removeAttr('disabled');
778
- });
779
- });
780
-
781
- return this;
782
- },
783
- disableButtons: function(name) {
784
- var buttons = this.__parseButtonNameParam(name),
785
- that = this;
786
-
787
- $.each(buttons, function(i, v) {
788
- that.__alterButtons(buttons[i], function(el) {
789
- el.attr('disabled', 'disabled');
790
- });
791
- });
792
-
793
- return this;
794
- },
795
- hideButtons: function(name) {
796
- var buttons = this.__parseButtonNameParam(name),
797
- that = this;
798
-
799
- $.each(buttons, function(i, v) {
800
- that.__alterButtons(buttons[i], function(el) {
801
- el.addClass('hidden');
802
- });
803
- });
804
-
805
- return this;
806
- },
807
- showButtons: function(name) {
808
- var buttons = this.__parseButtonNameParam(name),
809
- that = this;
810
-
811
- $.each(buttons, function(i, v) {
812
- that.__alterButtons(buttons[i], function(el) {
813
- el.removeClass('hidden');
814
- });
815
- });
816
-
817
- return this;
818
- },
819
- eventSupported: function(eventName) {
820
- var isSupported = eventName in this.$element;
821
- if (!isSupported) {
822
- this.$element.setAttribute(eventName, 'return;');
823
- isSupported = typeof this.$element[eventName] === 'function';
824
- }
825
- return isSupported;
826
- },
827
- keyup: function(e) {
828
- var blocked = false;
829
- switch (e.keyCode) {
830
- case 40: // down arrow
831
- case 38: // up arrow
832
- case 16: // shift
833
- case 17: // ctrl
834
- case 18: // alt
835
- break;
836
-
837
- case 9: // tab
838
- var nextTab;
839
- if (nextTab = this.getNextTab(), nextTab !== null) {
840
- // Get the nextTab if exists
841
- var that = this;
842
- setTimeout(function() {
843
- that.setSelection(nextTab.start, nextTab.end);
844
- }, 500);
845
-
846
- blocked = true;
847
- } else {
848
- // The next tab's memory contains nothing...
849
- // check the cursor position to determine tab action
850
- var cursor = this.getSelection();
851
-
852
- if (cursor.start == cursor.end && cursor.end == this.getContent().length) {
853
- // The cursor has reached the end of the content
854
- blocked = false;
855
- } else {
856
- // Put the cursor to the end
857
- this.setSelection(this.getContent().length, this.getContent().length);
858
-
859
- blocked = true;
860
- }
861
- }
862
-
863
- break;
864
-
865
- case 13: // enter
866
- blocked = false;
867
- var chars = this.getContent().split('');
868
- var enterIndex = this.getSelection().start;
869
- var priorNewlineIndex = -1; // initial line break at before index 0
870
-
871
- // traverse backwards through chars to check if last line break was num/bullet item
872
- for (var i = enterIndex - 2; i >= 0; i--) {
873
- if (chars[i] === '\n') {
874
- priorNewlineIndex = i;
875
- break;
876
- }
877
- }
878
-
879
- var charFollowingLastLineBreak = chars[priorNewlineIndex + 1];
880
- if (charFollowingLastLineBreak === '-') {
881
- this.addBullet(enterIndex);
882
- } else if ($.isNumeric(charFollowingLastLineBreak)) {
883
- var numBullet = this.getBulletNumber(priorNewlineIndex + 1);
884
- if (numBullet) {
885
- this.addNumberedBullet(enterIndex, numBullet);
886
- }
887
- }
888
- break;
889
-
890
- case 27: // escape
891
- if (this.$isFullscreen) this.setFullscreen(false);
892
- blocked = false;
893
- break;
894
-
895
- default:
896
- blocked = false;
897
- }
898
-
899
- if (blocked) {
900
- e.stopPropagation();
901
- e.preventDefault();
902
- }
903
-
904
- this.$options.onChange(this);
905
- },
906
- insertContent: function(index, content) {
907
- var firstHalf = this.getContent().slice(0, index);
908
- var secondHalf = this.getContent().slice(index + 1);
909
- this.setContent(firstHalf.concat(content).concat(secondHalf));
910
- },
911
- addBullet: function(index) {
912
- this.insertContent(index, '- \n');
913
- this.setSelection(index + 2, index + 2); // Put the cursor after the bullet
914
- },
915
- addNumberedBullet: function(index, num) {
916
- var numBullet = (num + 1) + '. \n';
917
- this.insertContent(index, numBullet);
918
-
919
- var prefixLength = num.toString().length + 2;
920
- this.setSelection(index + prefixLength, index + prefixLength); // Put the cursor after the number
921
- },
922
- getBulletNumber: function(startIndex) {
923
- var bulletNum = this.getContent().slice(startIndex).split('.')[0];
924
- return $.isNumeric(bulletNum) ? parseInt(bulletNum) : null;
925
- },
926
- change: function(e) {
927
- this.$options.onChange(this);
928
- return this;
929
- },
930
- select: function(e) {
931
- this.$options.onSelect(this);
932
- return this;
933
- },
934
- focus: function(e) {
935
- var options = this.$options,
936
- isHideable = options.hideable,
937
- editor = this.$editor;
938
-
939
- editor.addClass('active');
940
-
941
- // Blur other markdown(s)
942
- $(document).find('.md-editor').each(function() {
943
- if ($(this).attr('id') !== editor.attr('id')) {
944
- var attachedMarkdown;
945
-
946
- if (attachedMarkdown = $(this).find('textarea').data('markdown'),
947
- attachedMarkdown === null) {
948
- attachedMarkdown = $(this).find('div[data-provider="markdown-preview"]').data('markdown');
949
- }
950
-
951
- if (attachedMarkdown) {
952
- attachedMarkdown.blur();
953
- }
954
- }
955
- });
956
-
957
- // Trigger the onFocus hook
958
- options.onFocus(this);
959
-
960
- return this;
961
- },
962
- blur: function(e) {
963
- var options = this.$options,
964
- isHideable = options.hideable,
965
- editor = this.$editor,
966
- editable = this.$editable;
967
-
968
- if (editor.hasClass('active') || this.$element.parent().length === 0) {
969
- editor.removeClass('active');
970
-
971
- if (isHideable) {
972
- // Check for editable elements
973
- if (editable.el !== null) {
974
- // Build the original element
975
- var oldElement = $('<' + editable.type + '/>'),
976
- content = this.getContent(),
977
- currentContent = this.parseContent(content);
978
-
979
- $(editable.attrKeys).each(function(k, v) {
980
- oldElement.attr(editable.attrKeys[k], editable.attrValues[k]);
981
- });
982
-
983
- // Get the editor content
984
- oldElement.html(currentContent);
985
-
986
- editor.replaceWith(oldElement);
987
- } else {
988
- editor.hide();
989
- }
990
- }
991
-
992
- // Trigger the onBlur hook
993
- options.onBlur(this);
994
- }
995
-
996
- return this;
997
- }
998
-
999
- };
1000
-
1001
- /* MARKDOWN PLUGIN DEFINITION
1002
- * ========================== */
1003
-
1004
- var old = $.fn.markdown;
1005
-
1006
- $.fn.markdown = function(option) {
1007
- return this.each(function() {
1008
- var $this = $(this),
1009
- data = $this.data('markdown'),
1010
- options = typeof option == 'object' && option;
1011
- if (!data)
1012
- $this.data('markdown', (data = new Markdown(this, options)));
1013
- });
1014
- };
1015
-
1016
- $.fn.markdown.messages = {};
1017
-
1018
- $.fn.markdown.defaults = {
1019
- /* Editor Properties */
1020
- autofocus: false,
1021
- hideable: false,
1022
- savable: false,
1023
- width: 'inherit',
1024
- height: 'inherit',
1025
- resize: 'none',
1026
- iconlibrary: 'glyph',
1027
- language: 'en',
1028
- initialstate: 'editor',
1029
- parser: null,
1030
- dropZoneOptions: null,
1031
- enableDropDataUri: false,
1032
-
1033
- /* Buttons Properties */
1034
- buttons: [
1035
- [{
1036
- name: 'groupFont',
1037
- data: [{
1038
- name: 'cmdBold',
1039
- hotkey: 'Ctrl+B',
1040
- title: 'Bold',
1041
- icon: {
1042
- glyph: 'glyphicon glyphicon-bold',
1043
- fa: 'fa fa-bold',
1044
- 'fa-3': 'icon-bold',
1045
- 'fa-5': 'fas fa-bold',
1046
- octicons: 'octicon octicon-bold'
1047
- },
1048
- callback: function(e) {
1049
- // Give/remove ** surround the selection
1050
- var chunk, cursor, selected = e.getSelection(),
1051
- content = e.getContent();
1052
-
1053
- if (selected.length === 0) {
1054
- // Give extra word
1055
- chunk = e.__localize('strong text');
1056
- } else {
1057
- chunk = selected.text;
1058
- }
1059
-
1060
- // transform selection and set the cursor into chunked text
1061
- if (content.substr(selected.start - 2, 2) === '**' &&
1062
- content.substr(selected.end, 2) === '**') {
1063
- e.setSelection(selected.start - 2, selected.end + 2);
1064
- e.replaceSelection(chunk);
1065
- cursor = selected.start - 2;
1066
- } else {
1067
- e.replaceSelection('**' + chunk + '**');
1068
- cursor = selected.start + 2;
1069
- }
1070
-
1071
- // Set the cursor
1072
- e.setSelection(cursor, cursor + chunk.length);
1073
- }
1074
- }, {
1075
- name: 'cmdItalic',
1076
- title: 'Italic',
1077
- hotkey: 'Ctrl+I',
1078
- icon: {
1079
- glyph: 'glyphicon glyphicon-italic',
1080
- fa: 'fa fa-italic',
1081
- 'fa-3': 'icon-italic',
1082
- 'fa-5': 'fas fa-italic',
1083
- octicons: 'octicon octicon-italic'
1084
- },
1085
- callback: function(e) {
1086
- // Give/remove * surround the selection
1087
- var chunk, cursor, selected = e.getSelection(),
1088
- content = e.getContent();
1089
-
1090
- if (selected.length === 0) {
1091
- // Give extra word
1092
- chunk = e.__localize('emphasized text');
1093
- } else {
1094
- chunk = selected.text;
1095
- }
1096
-
1097
- // transform selection and set the cursor into chunked text
1098
- if (content.substr(selected.start - 1, 1) === '_' &&
1099
- content.substr(selected.end, 1) === '_') {
1100
- e.setSelection(selected.start - 1, selected.end + 1);
1101
- e.replaceSelection(chunk);
1102
- cursor = selected.start - 1;
1103
- } else {
1104
- e.replaceSelection('_' + chunk + '_');
1105
- cursor = selected.start + 1;
1106
- }
1107
-
1108
- // Set the cursor
1109
- e.setSelection(cursor, cursor + chunk.length);
1110
- }
1111
- }, {
1112
- name: 'cmdHeading',
1113
- title: 'Heading',
1114
- hotkey: 'Ctrl+H',
1115
- icon: {
1116
- glyph: 'glyphicon glyphicon-header',
1117
- fa: 'fa fa-header',
1118
- 'fa-3': 'icon-font',
1119
- 'fa-5': 'fas fa-heading',
1120
- octicons: 'octicon octicon-text-size'
1121
- },
1122
- callback: function(e) {
1123
- // Append/remove ### surround the selection
1124
- var chunk, cursor, selected = e.getSelection(),
1125
- content = e.getContent(),
1126
- pointer, prevChar;
1127
-
1128
- if (selected.length === 0) {
1129
- // Give extra word
1130
- chunk = e.__localize('heading text');
1131
- } else {
1132
- chunk = selected.text + '\n';
1133
- }
1134
-
1135
- // transform selection and set the cursor into chunked text
1136
- if ((pointer = 4, content.substr(selected.start - pointer, pointer) === '### ') ||
1137
- (pointer = 3, content.substr(selected.start - pointer, pointer) === '###')) {
1138
- e.setSelection(selected.start - pointer, selected.end);
1139
- e.replaceSelection(chunk);
1140
- cursor = selected.start - pointer;
1141
- } else if (selected.start > 0 && (prevChar = content.substr(selected.start - 1, 1), !!prevChar && prevChar != '\n')) {
1142
- e.replaceSelection('\n\n### ' + chunk);
1143
- cursor = selected.start + 6;
1144
- } else {
1145
- // Empty string before element
1146
- e.replaceSelection('### ' + chunk);
1147
- cursor = selected.start + 4;
1148
- }
1149
-
1150
- // Set the cursor
1151
- e.setSelection(cursor, cursor + chunk.length);
1152
- }
1153
- }]
1154
- }, {
1155
- name: 'groupLink',
1156
- data: [{
1157
- name: 'cmdUrl',
1158
- title: 'URL/Link',
1159
- hotkey: 'Ctrl+L',
1160
- icon: {
1161
- glyph: 'glyphicon glyphicon-link',
1162
- fa: 'fa fa-link',
1163
- 'fa-3': 'icon-link',
1164
- 'fa-5': 'fas fa-link',
1165
- octicons: 'octicon octicon-link'
1166
- },
1167
- callback: function(e) {
1168
- // Give [] surround the selection and prepend the link
1169
- var chunk, cursor, selected = e.getSelection(),
1170
- content = e.getContent(),
1171
- link;
1172
-
1173
- if (selected.length === 0) {
1174
- // Give extra word
1175
- chunk = e.__localize('enter link description here');
1176
- } else {
1177
- chunk = selected.text;
1178
- }
1179
-
1180
- link = prompt(e.__localize('Insert Hyperlink'), 'http://');
1181
-
1182
- var urlRegex = new RegExp('^((http|https)://|(mailto:)|(//))[a-z0-9]', 'i');
1183
- if (link !== null && link !== '' && link !== 'http://' && urlRegex.test(link)) {
1184
- var sanitizedLink = $('<div>' + link + '</div>').text();
1185
-
1186
- // transform selection and set the cursor into chunked text
1187
- e.replaceSelection('[' + chunk + '](' + sanitizedLink + ')');
1188
- cursor = selected.start + 1;
1189
-
1190
- // Set the cursor
1191
- e.setSelection(cursor, cursor + chunk.length);
1192
- }
1193
- }
1194
- }, {
1195
- name: 'cmdImage',
1196
- title: 'Image',
1197
- hotkey: 'Ctrl+G',
1198
- icon: {
1199
- glyph: 'glyphicon glyphicon-picture',
1200
- fa: 'fa fa-picture-o',
1201
- 'fa-3': 'icon-picture',
1202
- 'fa-5': 'far fa-image',
1203
- octicons: 'octicon octicon-file-media'
1204
- },
1205
- callback: function(e) {
1206
- // Give ![] surround the selection and prepend the image link
1207
- var chunk, cursor, selected = e.getSelection(),
1208
- content = e.getContent(),
1209
- link;
1210
-
1211
- if (selected.length === 0) {
1212
- // Give extra word
1213
- chunk = e.__localize('enter image description here');
1214
- } else {
1215
- chunk = selected.text;
1216
- }
1217
-
1218
- link = prompt(e.__localize('Insert Image Hyperlink'), 'http://');
1219
-
1220
- var urlRegex = new RegExp('^((http|https)://|(//))[a-z0-9]', 'i');
1221
- if (link !== null && link !== '' && link !== 'http://' && urlRegex.test(link)) {
1222
- var sanitizedLink = $('<div>' + link + '</div>').text();
1223
-
1224
- // transform selection and set the cursor into chunked text
1225
- e.replaceSelection('![' + chunk + '](' + sanitizedLink + ' "' + e.__localize('enter image title here') + '")');
1226
- cursor = selected.start + 2;
1227
-
1228
- // Set the next tab
1229
- e.setNextTab(e.__localize('enter image title here'));
1230
-
1231
- // Set the cursor
1232
- e.setSelection(cursor, cursor + chunk.length);
1233
- }
1234
- }
1235
- }]
1236
- }, {
1237
- name: 'groupMisc',
1238
- data: [{
1239
- name: 'cmdList',
1240
- hotkey: 'Ctrl+U',
1241
- title: 'Unordered List',
1242
- icon: {
1243
- glyph: 'glyphicon glyphicon-list',
1244
- fa: 'fa fa-list',
1245
- 'fa-3': 'icon-list-ul',
1246
- 'fa-5': 'fas fa-list-ul',
1247
- octicons: 'octicon octicon-list-unordered'
1248
- },
1249
- callback: function(e) {
1250
- // Prepend/Give - surround the selection
1251
- var chunk, cursor, selected = e.getSelection(),
1252
- content = e.getContent();
1253
-
1254
- // transform selection and set the cursor into chunked text
1255
- if (selected.length === 0) {
1256
- // Give extra word
1257
- chunk = e.__localize('list text here');
1258
-
1259
- e.replaceSelection('- ' + chunk);
1260
- // Set the cursor
1261
- cursor = selected.start + 2;
1262
- } else {
1263
- if (selected.text.indexOf('\n') < 0) {
1264
- chunk = selected.text;
1265
-
1266
- e.replaceSelection('- ' + chunk);
1267
-
1268
- // Set the cursor
1269
- cursor = selected.start + 2;
1270
- } else {
1271
- var list = [];
1272
-
1273
- list = selected.text.split('\n');
1274
- chunk = list[0];
1275
-
1276
- $.each(list, function(k, v) {
1277
- list[k] = '- ' + v;
1278
- });
1279
-
1280
- e.replaceSelection('\n\n' + list.join('\n'));
1281
-
1282
- // Set the cursor
1283
- cursor = selected.start + 4;
1284
- }
1285
- }
1286
-
1287
- // Set the cursor
1288
- e.setSelection(cursor, cursor + chunk.length);
1289
- }
1290
- }, {
1291
- name: 'cmdListO',
1292
- hotkey: 'Ctrl+O',
1293
- title: 'Ordered List',
1294
- icon: {
1295
- glyph: 'glyphicon glyphicon-th-list',
1296
- fa: 'fa fa-list-ol',
1297
- 'fa-3': 'icon-list-ol',
1298
- 'fa-5': 'fas fa-list-ol',
1299
- octicons: 'octicon octicon-list-ordered'
1300
- },
1301
- callback: function(e) {
1302
-
1303
- // Prepend/Give - surround the selection
1304
- var chunk, cursor, selected = e.getSelection(),
1305
- content = e.getContent();
1306
-
1307
- // transform selection and set the cursor into chunked text
1308
- if (selected.length === 0) {
1309
- // Give extra word
1310
- chunk = e.__localize('list text here');
1311
- e.replaceSelection('1. ' + chunk);
1312
- // Set the cursor
1313
- cursor = selected.start + 3;
1314
- } else {
1315
- if (selected.text.indexOf('\n') < 0) {
1316
- chunk = selected.text;
1317
-
1318
- e.replaceSelection('1. ' + chunk);
1319
-
1320
- // Set the cursor
1321
- cursor = selected.start + 3;
1322
- } else {
1323
- var i = 1;
1324
- var list = [];
1325
-
1326
- list = selected.text.split('\n');
1327
- chunk = list[0];
1328
-
1329
- $.each(list, function(k, v) {
1330
- list[k] = i + '. ' + v;
1331
- i++;
1332
- });
1333
-
1334
- e.replaceSelection('\n\n' + list.join('\n'));
1335
-
1336
- // Set the cursor
1337
- cursor = selected.start + 5;
1338
- }
1339
- }
1340
-
1341
- // Set the cursor
1342
- e.setSelection(cursor, cursor + chunk.length);
1343
- }
1344
- }, {
1345
- name: 'cmdCode',
1346
- hotkey: 'Ctrl+K',
1347
- title: 'Code',
1348
- icon: {
1349
- glyph: 'glyphicon glyphicon-console',
1350
- fa: 'fa fa-code',
1351
- 'fa-3': 'icon-code',
1352
- 'fa-5': 'fas fa-code',
1353
- octicons: 'octicon octicon-code'
1354
- },
1355
- callback: function(e) {
1356
- // Give/remove ** surround the selection
1357
- var chunk, cursor, selected = e.getSelection(),
1358
- content = e.getContent();
1359
-
1360
- if (selected.length === 0) {
1361
- // Give extra word
1362
- chunk = e.__localize('code text here');
1363
- } else {
1364
- chunk = selected.text;
1365
- }
1366
-
1367
- // transform selection and set the cursor into chunked text
1368
- if (content.substr(selected.start - 4, 4) === '```\n' &&
1369
- content.substr(selected.end, 4) === '\n```') {
1370
- e.setSelection(selected.start - 4, selected.end + 4);
1371
- e.replaceSelection(chunk);
1372
- cursor = selected.start - 4;
1373
- } else if (content.substr(selected.start - 1, 1) === '`' &&
1374
- content.substr(selected.end, 1) === '`') {
1375
- e.setSelection(selected.start - 1, selected.end + 1);
1376
- e.replaceSelection(chunk);
1377
- cursor = selected.start - 1;
1378
- } else if (content.indexOf('\n') > -1) {
1379
- e.replaceSelection('```\n' + chunk + '\n```');
1380
- cursor = selected.start + 4;
1381
- } else {
1382
- e.replaceSelection('`' + chunk + '`');
1383
- cursor = selected.start + 1;
1384
- }
1385
-
1386
- // Set the cursor
1387
- e.setSelection(cursor, cursor + chunk.length);
1388
- }
1389
- }, {
1390
- name: 'cmdQuote',
1391
- hotkey: 'Ctrl+Q',
1392
- title: 'Quote',
1393
- icon: {
1394
- glyph: 'glyphicon glyphicon-comment',
1395
- fa: 'fa fa-quote-left',
1396
- 'fa-3': 'icon-quote-left',
1397
- 'fa-5': 'fas fa-quote-left',
1398
- octicons: 'octicon octicon-quote'
1399
- },
1400
- callback: function(e) {
1401
- // Prepend/Give - surround the selection
1402
- var chunk, cursor, selected = e.getSelection(),
1403
- content = e.getContent();
1404
-
1405
- // transform selection and set the cursor into chunked text
1406
- if (selected.length === 0) {
1407
- // Give extra word
1408
- chunk = e.__localize('quote here');
1409
-
1410
- e.replaceSelection('> ' + chunk);
1411
-
1412
- // Set the cursor
1413
- cursor = selected.start + 2;
1414
- } else {
1415
- if (selected.text.indexOf('\n') < 0) {
1416
- chunk = selected.text;
1417
-
1418
- e.replaceSelection('> ' + chunk);
1419
-
1420
- // Set the cursor
1421
- cursor = selected.start + 2;
1422
- } else {
1423
- var list = [];
1424
-
1425
- list = selected.text.split('\n');
1426
- chunk = list[0];
1427
-
1428
- $.each(list, function(k, v) {
1429
- list[k] = '> ' + v;
1430
- });
1431
-
1432
- e.replaceSelection('\n\n' + list.join('\n'));
1433
-
1434
- // Set the cursor
1435
- cursor = selected.start + 4;
1436
- }
1437
- }
1438
-
1439
- // Set the cursor
1440
- e.setSelection(cursor, cursor + chunk.length);
1441
- }
1442
- }]
1443
- }, {
1444
- name: 'groupUtil',
1445
- data: [{
1446
- name: 'cmdPreview',
1447
- toggle: true,
1448
- hotkey: 'Ctrl+P',
1449
- title: 'Preview',
1450
- btnText: 'Preview',
1451
- btnClass: 'btn btn-primary btn-sm',
1452
- icon: {
1453
- glyph: 'glyphicon glyphicon-search',
1454
- fa: 'fa fa-search',
1455
- 'fa-3': 'icon-search',
1456
- 'fa-5': 'fas fa-search',
1457
- octicons: 'octicon octicon-search'
1458
- },
1459
- callback: function(e) {
1460
- // Check the preview mode and toggle based on this flag
1461
- var isPreview = e.$isPreview,
1462
- content;
1463
-
1464
- if (isPreview === false) {
1465
- // Give flag that tells the editor to enter preview mode
1466
- e.showPreview();
1467
- } else {
1468
- e.hidePreview();
1469
- }
1470
- }
1471
- }]
1472
- }]
1473
- ],
1474
- customIcons: {},
1475
- additionalButtons: [], // Place to hook more buttons by code
1476
- reorderButtonGroups: [],
1477
- hiddenButtons: [], // Default hidden buttons
1478
- disabledButtons: [], // Default disabled buttons
1479
- footer: '',
1480
- fullscreen: {
1481
- enable: true,
1482
- icons: {
1483
- fullscreenOn: {
1484
- name: "fullscreenOn",
1485
- icon: {
1486
- fa: 'fa fa-expand',
1487
- glyph: 'glyphicon glyphicon-fullscreen',
1488
- 'fa-3': 'icon-resize-full',
1489
- 'fa-5': 'fas fa-expand-arrows-alt',
1490
- octicons: 'octicon octicon-link-external'
1491
- }
1492
- },
1493
- fullscreenOff: {
1494
- name: "fullscreenOff",
1495
- icon: {
1496
- fa: 'fa fa-compress',
1497
- glyph: 'glyphicon glyphicon-fullscreen',
1498
- 'fa-3': 'icon-resize-small',
1499
- 'fa-5': 'fas fa-compress',
1500
- octicons: 'octicon octicon-browser'
1501
- }
1502
- }
1503
- }
1504
- },
1505
-
1506
- /* Events hook */
1507
- onShow: function(e) {},
1508
- onPreview: function(e) {},
1509
- onPreviewEnd: function(e) {},
1510
- onSave: function(e) {},
1511
- onBlur: function(e) {},
1512
- onFocus: function(e) {},
1513
- onChange: function(e) {},
1514
- onFullscreen: function(e) {},
1515
- onFullscreenExit: function(e) {},
1516
- onSelect: function(e) {}
1517
- };
1518
-
1519
- $.fn.markdown.Constructor = Markdown;
1520
-
1521
-
1522
- /* MARKDOWN NO CONFLICT
1523
- * ==================== */
1524
-
1525
- $.fn.markdown.noConflict = function() {
1526
- $.fn.markdown = old;
1527
- return this;
1528
- };
1529
-
1530
- /* MARKDOWN GLOBAL FUNCTION & DATA-API
1531
- * ==================================== */
1532
- var initMarkdown = function(el) {
1533
- var $this = el;
1534
-
1535
- if ($this.data('markdown')) {
1536
- $this.data('markdown').showEditor();
1537
- return;
1538
- }
1539
-
1540
- $this.markdown();
1541
- };
1542
-
1543
- var blurNonFocused = function(e) {
1544
- var $activeElement = $(document.activeElement);
1545
-
1546
- // Blur event
1547
- $(document).find('.md-editor').each(function() {
1548
- var $this = $(this),
1549
- focused = $activeElement.closest('.md-editor')[0] === this,
1550
- attachedMarkdown = $this.find('textarea').data('markdown') ||
1551
- $this.find('div[data-provider="markdown-preview"]').data('markdown');
1552
-
1553
- if (attachedMarkdown && !focused) {
1554
- attachedMarkdown.blur();
1555
- }
1556
- });
1557
- };
1558
-
1559
- $(document)
1560
- .on('click.markdown.data-api', '[data-provide="markdown-editable"]', function(e) {
1561
- initMarkdown($(this));
1562
- e.preventDefault();
1563
- })
1564
- .on('click focusin', function(e) {
1565
- blurNonFocused(e);
1566
- })
1567
- .ready(function() {
1568
- $('textarea[data-provide="markdown"]').each(function() {
1569
- initMarkdown($(this));
1570
- });
1571
- });
1572
-
1573
- }));
19
+ !function(t){"function"==typeof define&&define.amd?define(["jquery"],t):t("object"==typeof exports?require("jquery"):jQuery)}(function(t){"use strict";var e=function(e,n){t.each(["autofocus","savable","hideable","width","height","resize","iconlibrary","language","footer","fullscreen","hiddenButtons","disabledButtons"],function(i,o){void 0!==t(e).data(o)&&((n="object"==typeof n?n:{})[o]=t(e).data(o))}),this.$ns="bootstrap-markdown",this.$element=t(e),this.$editable={el:null,type:null,attrKeys:[],attrValues:[],content:null},this.$options=t.extend(!0,{},t.fn.markdown.defaults,n,this.$element.data("options")),this.$oldContent=null,this.$isPreview=!1,this.$isFullscreen=!1,this.$editor=null,this.$textarea=null,this.$handler=[],this.$callback=[],this.$nextTab=[],this.showEditor()};e.prototype={constructor:e,__alterButtons:function(e,n){var i=this.$handler,o="all"==e,a=this;t.each(i,function(t,i){var s=!0;!1==(s=!o&&0>i.indexOf(e))&&n(a.$editor.find('button[data-handler="'+i+'"]'))})},__buildButtons:function(e,n){var i,o=this.$ns,a=this.$handler,s=this.$callback;for(i=0;i<e.length;i++){var r,l=e[i];for(r=0;r<l.length;r++){var c,h=l[r].data,d=t("<div/>",{class:"btn-group"});for(c=0;c<h.length;c++){var u,f,p=h[c],g=o+"-"+p.name,v=this.__getIcon(p),m=p.btnText?p.btnText:"",b=p.btnClass?p.btnClass:"btn",y=p.tabIndex?p.tabIndex:"-1",x=void 0!==p.hotkey?p.hotkey:"",w=void 0!==jQuery.hotkeys&&""!==x?" ("+x+")":"";(u=t("<button></button>")).text(" "+this.__localize(m)).addClass("btn-default btn-sm").addClass(b),b.match(/btn\-(primary|success|info|warning|danger|link)/)&&u.removeClass("btn-default"),u.attr({type:"button",title:this.__localize(p.title)+w,tabindex:y,"data-provider":o,"data-handler":g,"data-hotkey":x}),!0===p.toggle&&u.attr("data-toggle","button"),(f=t("<span/>")).addClass(v),f.prependTo(u),d.append(u),a.push(g),s.push(p.callback)}n.append(d)}}return n},__setListener:function(){var t=void 0!==this.$textarea.attr("rows"),e=this.$textarea.val().split("\n").length>5?this.$textarea.val().split("\n").length:"5",n=t?this.$textarea.attr("rows"):e;this.$textarea.attr("rows",n),this.$options.resize&&this.$textarea.css("resize",this.$options.resize),this.$textarea.data("markdown",this)},__setEventListeners:function(){this.$textarea.on({focus:t.proxy(this.focus,this),keyup:t.proxy(this.keyup,this),change:t.proxy(this.change,this),select:t.proxy(this.select,this)}),this.eventSupported("keydown")&&this.$textarea.on("keydown",t.proxy(this.keydown,this)),this.eventSupported("keypress")&&this.$textarea.on("keypress",t.proxy(this.keypress,this))},__handle:function(e){var n=t(e.currentTarget),i=this.$handler,o=this.$callback,a=n.attr("data-handler"),s=o[i.indexOf(a)];t(e.currentTarget).focus(),s(this),this.change(this),0>a.indexOf("cmdSave")&&this.$textarea.focus(),e.preventDefault()},__localize:function(e){var n=t.fn.markdown.messages,i=this.$options.language;return void 0!==n&&void 0!==n[i]&&void 0!==n[i][e]?n[i][e]:e},__getIcon:function(t){if("object"!=typeof t)return t;var e=this.$options.customIcons[t.name];return void 0===e?t.icon[this.$options.iconlibrary]:e},setFullscreen:function(e){var n=this.$editor,i=this.$textarea;!0===e?(n.addClass("md-fullscreen-mode"),t("body").addClass("md-nooverflow"),this.$options.onFullscreen(this)):(n.removeClass("md-fullscreen-mode"),t("body").removeClass("md-nooverflow"),this.$options.onFullscreenExit(this),!0===this.$isPreview&&this.hidePreview().showPreview()),this.$isFullscreen=e,i.focus()},showEditor:function(){var e,n=this,i=this.$ns,o=this.$element,a=(o.css("height"),o.css("width"),this.$editable),s=this.$handler,r=this.$callback,l=this.$options,c=t("<div/>",{class:"md-editor",click:function(){n.focus()}});if(null===this.$editor){var h=t("<div/>",{class:"md-header btn-toolbar"}),d=[];if(l.buttons.length>0&&(d=d.concat(l.buttons[0])),l.additionalButtons.length>0&&t.each(l.additionalButtons[0],function(e,n){var i=t.grep(d,function(t,e){return t.name===n.name});i.length>0?i[0].data=i[0].data.concat(n.data):d.push(l.additionalButtons[0][e])}),l.reorderButtonGroups.length>0&&(d=d.filter(function(t){return l.reorderButtonGroups.indexOf(t.name)>-1}).sort(function(t,e){return l.reorderButtonGroups.indexOf(t.name)<l.reorderButtonGroups.indexOf(e.name)?-1:l.reorderButtonGroups.indexOf(t.name)>l.reorderButtonGroups.indexOf(e.name)?1:0})),d.length>0&&(h=this.__buildButtons([d],h)),l.fullscreen.enable&&h.append('<div class="md-controls"><a class="md-control md-control-fullscreen" href="#"><span class="'+this.__getIcon(l.fullscreen.icons.fullscreenOn)+'"></span></a></div>').on("click",".md-control-fullscreen",function(t){t.preventDefault(),n.setFullscreen(!0)}),c.append(h),o.is("textarea"))o.before(c),(e=o).addClass("md-input"),c.append(e);else{var u="function"==typeof toMarkdown?toMarkdown(o.html()):o.html(),f=t.trim(u);e=t("<textarea/>",{class:"md-input",val:f}),c.append(e),a.el=o,a.type=o.prop("tagName").toLowerCase(),a.content=o.html(),t(o[0].attributes).each(function(){a.attrKeys.push(this.nodeName),a.attrValues.push(this.nodeValue)}),o.replaceWith(c)}var p=t("<div/>",{class:"md-footer"}),g=!1,v="";if(l.savable){g=!0;var m="cmdSave";s.push(m),r.push(l.onSave),p.append('<button class="btn btn-success" data-provider="'+i+'" data-handler="'+m+'"><i class="icon icon-white icon-ok"></i> '+this.__localize("Save")+"</button>")}if(v="function"==typeof l.footer?l.footer(this):l.footer,""!==t.trim(v)&&(g=!0,p.append(v)),g&&c.append(p),l.width&&"inherit"!==l.width&&(jQuery.isNumeric(l.width)?(c.css("display","table"),e.css("width",l.width+"px")):c.addClass(l.width)),l.height&&"inherit"!==l.height){if(jQuery.isNumeric(l.height)){var b=l.height;h&&(b=Math.max(0,b-h.outerHeight())),p&&(b=Math.max(0,b-p.outerHeight())),e.css("height",b+"px")}else c.addClass(l.height)}this.$editor=c,this.$textarea=e,this.$editable=a,this.$oldContent=this.getContent(),this.__setListener(),this.__setEventListeners(),this.$editor.attr("id",new Date().getTime()),this.$editor.on("click",'[data-provider="bootstrap-markdown"]',t.proxy(this.__handle,this)),(this.$element.is(":disabled")||this.$element.is("[readonly]"))&&(this.$editor.addClass("md-editor-disabled"),this.disableButtons("all")),this.eventSupported("keydown")&&"object"==typeof jQuery.hotkeys&&h.find('[data-provider="bootstrap-markdown"]').each(function(){var n=t(this),i=n.attr("data-hotkey");""!==i.toLowerCase()&&e.bind("keydown",i,function(){return n.trigger("click"),!1})}),"preview"===l.initialstate?this.showPreview():"fullscreen"===l.initialstate&&l.fullscreen.enable&&this.setFullscreen(!0)}else this.$editor.show();return l.autofocus&&(this.$textarea.focus(),this.$editor.addClass("active")),l.fullscreen.enable&&!1!==l.fullscreen&&(this.$editor.append('<div class="md-fullscreen-controls"><a href="#" class="exit-fullscreen" title="Exit fullscreen"><span class="'+this.__getIcon(l.fullscreen.icons.fullscreenOff)+'"></span></a></div>'),this.$editor.on("click",".exit-fullscreen",function(t){t.preventDefault(),n.setFullscreen(!1)})),this.hideButtons(l.hiddenButtons),this.disableButtons(l.disabledButtons),l.dropZoneOptions&&(this.$editor.dropzone?(l.dropZoneOptions.init||(l.dropZoneOptions.init=function(){var t=0;this.on("drop",function(n){t=e.prop("selectionStart")}),this.on("success",function(n,i){var o=e.val();e.val(o.substring(0,t)+"\n![description]("+i+")\n"+o.substring(t))}),this.on("error",function(t,e,n){console.log("Error:",e)})}),this.$editor.addClass("dropzone"),this.$editor.dropzone(l.dropZoneOptions)):console.log("dropZoneOptions was configured, but DropZone was not detected.")),!0===l.enableDropDataUri&&this.$editor.on("drop",function(n){var i=e.prop("selectionStart");n.stopPropagation(),n.preventDefault(),t.each(n.originalEvent.dataTransfer.files,function(t,n){var o,a,s=new FileReader;s.onload=(a=(o=n).type.split("/")[0],function(t){var n=e.val();"image"===a?e.val(n.substring(0,i)+'\n<img src="'+t.target.result+'" />\n'+n.substring(i)):e.val(n.substring(0,i)+'\n<a href="'+t.target.result+'">Download '+o.name+"</a>\n"+n.substring(i))}),s.readAsDataURL(n)})}),l.onShow(this),this},parseContent:function(t){var e;return t=t||this.$textarea.val(),e=this.$options.parser?this.$options.parser(t):"object"==typeof markdown?markdown.toHTML(t):"function"==typeof marked?marked(t):t},showPreview:function(){var e,n,i=this.$options,o=this.$textarea,a=o.next(),s=t("<div/>",{class:"md-preview","data-provider":"markdown-preview"});return!0===this.$isPreview||(this.$isPreview=!0,this.disableButtons("all").enableButtons("cmdPreview"),e="string"==typeof(n=i.onPreview(this,s))?n:this.parseContent(),s.html(e),a&&"md-footer"==a.attr("class")?s.insertBefore(a):o.parent().append(s),s.css({width:o.outerWidth()+"px","min-height":o.outerHeight()+"px",height:"auto"}),this.$options.resize&&s.css("resize",this.$options.resize),o.hide(),s.data("markdown",this),(this.$element.is(":disabled")||this.$element.is("[readonly]"))&&(this.$editor.addClass("md-editor-disabled"),this.disableButtons("all"))),this},hidePreview:function(){return this.$isPreview=!1,this.$editor.find('div[data-provider="markdown-preview"]').remove(),this.enableButtons("all"),this.disableButtons(this.$options.disabledButtons),this.$options.onPreviewEnd(this),this.$textarea.show(),this.__setListener(),this},isDirty:function(){return this.$oldContent!=this.getContent()},getContent:function(){return this.$textarea.val()},setContent:function(t){return this.$textarea.val(t),this},findSelection:function(t){if(!((e=this.getContent().indexOf(t))>=0)||!(t.length>0))return null;var e,n,i=this.getSelection();return this.setSelection(e,e+t.length),n=this.getSelection(),this.setSelection(i.start,i.end),n},getSelection:function(){var t=this.$textarea[0];return("selectionStart"in t&&function(){var e=t.selectionEnd-t.selectionStart;return{start:t.selectionStart,end:t.selectionEnd,length:e,text:t.value.substr(t.selectionStart,e)}}||function(){return null})()},setSelection:function(t,e){var n=this.$textarea[0];return("selectionStart"in n&&function(){n.selectionStart=t,n.selectionEnd=e}||function(){return null})()},replaceSelection:function(t){var e=this.$textarea[0];return("selectionStart"in e&&function(){return e.value=e.value.substr(0,e.selectionStart)+t+e.value.substr(e.selectionEnd,e.value.length),e.selectionStart=e.value.length,this}||function(){return e.value+=t,jQuery(e)})()},getNextTab:function(){if(0===this.$nextTab.length)return null;var t,e=this.$nextTab.shift();return"function"==typeof e?t=e():"object"==typeof e&&e.length>0&&(t=e),t},setNextTab:function(t,e){if("string"==typeof t){var n=this;this.$nextTab.push(function(){return n.findSelection(t)})}else if("number"==typeof t&&"number"==typeof e){var i=this.getSelection();this.setSelection(t,e),this.$nextTab.push(this.getSelection()),this.setSelection(i.start,i.end)}},__parseButtonNameParam:function(t){return"string"==typeof t?t.split(" "):t},enableButtons:function(e){var n=this.__parseButtonNameParam(e),i=this;return t.each(n,function(t,e){i.__alterButtons(n[t],function(t){t.removeAttr("disabled")})}),this},disableButtons:function(e){var n=this.__parseButtonNameParam(e),i=this;return t.each(n,function(t,e){i.__alterButtons(n[t],function(t){t.attr("disabled","disabled")})}),this},hideButtons:function(e){var n=this.__parseButtonNameParam(e),i=this;return t.each(n,function(t,e){i.__alterButtons(n[t],function(t){t.addClass("hidden")})}),this},showButtons:function(e){var n=this.__parseButtonNameParam(e),i=this;return t.each(n,function(t,e){i.__alterButtons(n[t],function(t){t.removeClass("hidden")})}),this},eventSupported:function(t){var e=t in this.$element;return e||(this.$element.setAttribute(t,"return;"),e="function"==typeof this.$element[t]),e},keyup:function(e){var n,i=!1;switch(e.keyCode){case 40:case 38:case 16:case 17:case 18:break;case 9:if(null!==(n=this.getNextTab())){var o=this;setTimeout(function(){o.setSelection(n.start,n.end)},500),i=!0}else{var a=this.getSelection();a.start==a.end&&a.end==this.getContent().length?i=!1:(this.setSelection(this.getContent().length,this.getContent().length),i=!0)}break;case 13:i=!1;for(var s=this.getContent().split(""),r=this.getSelection().start,l=-1,c=r-2;c>=0;c--)if("\n"===s[c]){l=c;break}var h=s[l+1];if("-"===h)this.addBullet(r);else if(t.isNumeric(h)){var d=this.getBulletNumber(l+1);d&&this.addNumberedBullet(r,d)}break;case 27:this.$isFullscreen&&this.setFullscreen(!1),i=!1;break;default:i=!1}i&&(e.stopPropagation(),e.preventDefault()),this.$options.onChange(this)},insertContent:function(t,e){var n=this.getContent().slice(0,t),i=this.getContent().slice(t+1);this.setContent(n.concat(e).concat(i))},addBullet:function(t){this.insertContent(t,"- \n"),this.setSelection(t+2,t+2)},addNumberedBullet:function(t,e){this.insertContent(t,e+1+". \n");var n=e.toString().length+2;this.setSelection(t+n,t+n)},getBulletNumber:function(e){var n=this.getContent().slice(e).split(".")[0];return t.isNumeric(n)?parseInt(n):null},change:function(t){return this.$options.onChange(this),this},select:function(t){return this.$options.onSelect(this),this},focus:function(e){var n=this.$options,i=(n.hideable,this.$editor);return i.addClass("active"),t(document).find(".md-editor").each(function(){if(t(this).attr("id")!==i.attr("id")){var e;null===(e=t(this).find("textarea").data("markdown"))&&(e=t(this).find('div[data-provider="markdown-preview"]').data("markdown")),e&&e.blur()}}),n.onFocus(this),this},blur:function(e){var n=this.$options,i=n.hideable,o=this.$editor,a=this.$editable;if(o.hasClass("active")||0===this.$element.parent().length){if(o.removeClass("active"),i){if(null!==a.el){var s=t("<"+a.type+"/>"),r=this.getContent(),l=this.parseContent(r);t(a.attrKeys).each(function(t,e){s.attr(a.attrKeys[t],a.attrValues[t])}),s.html(l),o.replaceWith(s)}else o.hide()}n.onBlur(this)}return this}};var n=t.fn.markdown;t.fn.markdown=function(n){return this.each(function(){var i=t(this),o=i.data("markdown");o||i.data("markdown",o=new e(this,"object"==typeof n&&n))})},t.fn.markdown.messages={},t.fn.markdown.defaults={autofocus:!1,hideable:!1,savable:!1,width:"inherit",height:"inherit",resize:"none",iconlibrary:"glyph",language:"en",initialstate:"editor",parser:null,dropZoneOptions:null,enableDropDataUri:!1,buttons:[[{name:"groupFont",data:[{name:"cmdBold",hotkey:"Ctrl+B",title:"Bold",icon:{glyph:"glyphicon glyphicon-bold",fa:"fa fa-bold","fa-3":"icon-bold","fa-5":"fa-solid fa-bold",octicons:"octicon octicon-bold"},callback:function(t){var e,n,i=t.getSelection(),o=t.getContent();e=0===i.length?t.__localize("strong text"):i.text,"**"===o.substr(i.start-2,2)&&"**"===o.substr(i.end,2)?(t.setSelection(i.start-2,i.end+2),t.replaceSelection(e),n=i.start-2):(t.replaceSelection("**"+e+"**"),n=i.start+2),t.setSelection(n,n+e.length)}},{name:"cmdItalic",title:"Italic",hotkey:"Ctrl+I",icon:{glyph:"glyphicon glyphicon-italic",fa:"fa fa-italic","fa-3":"icon-italic","fa-5":"fa-solid fa-italic",octicons:"octicon octicon-italic"},callback:function(t){var e,n,i=t.getSelection(),o=t.getContent();e=0===i.length?t.__localize("emphasized text"):i.text,"_"===o.substr(i.start-1,1)&&"_"===o.substr(i.end,1)?(t.setSelection(i.start-1,i.end+1),t.replaceSelection(e),n=i.start-1):(t.replaceSelection("_"+e+"_"),n=i.start+1),t.setSelection(n,n+e.length)}},{name:"cmdHeading",title:"Heading",hotkey:"Ctrl+H",icon:{glyph:"glyphicon glyphicon-header",fa:"fa fa-header","fa-3":"icon-font","fa-5":"fa-solid fa-heading",octicons:"octicon octicon-text-size"},callback:function(t){var e,n,i,o,a=t.getSelection(),s=t.getContent();e=0===a.length?t.__localize("heading text"):a.text+"\n",(i=4,"### "===s.substr(a.start-i,i)||(i=3,"###"===s.substr(a.start-i,i)))?(t.setSelection(a.start-i,a.end),t.replaceSelection(e),n=a.start-i):a.start>0&&(o=s.substr(a.start-1,1))&&"\n"!=o?(t.replaceSelection("\n\n### "+e),n=a.start+6):(t.replaceSelection("### "+e),n=a.start+4),t.setSelection(n,n+e.length)}}]},{name:"groupLink",data:[{name:"cmdUrl",title:"URL/Link",hotkey:"Ctrl+L",icon:{glyph:"glyphicon glyphicon-link",fa:"fa fa-link","fa-3":"icon-link","fa-5":"fa-solid fa-link",octicons:"octicon octicon-link"},callback:function(e){var n,i,o,a=e.getSelection();e.getContent(),n=0===a.length?e.__localize("enter link description here"):a.text,o=prompt(e.__localize("Insert Hyperlink"),"http://");var s=RegExp("^((http|https)://|(mailto:)|(//))[a-z0-9]","i");if(null!==o&&""!==o&&"http://"!==o&&s.test(o)){var r=t("<div>"+o+"</div>").text();e.replaceSelection("["+n+"]("+r+")"),i=a.start+1,e.setSelection(i,i+n.length)}}},{name:"cmdImage",title:"Image",hotkey:"Ctrl+G",icon:{glyph:"glyphicon glyphicon-picture",fa:"fa fa-picture-o","fa-3":"icon-picture","fa-5":"fa-regular fa-image",octicons:"octicon octicon-file-media"},callback:function(e){var n,i,o,a=e.getSelection();e.getContent(),n=0===a.length?e.__localize("enter image description here"):a.text,o=prompt(e.__localize("Insert Image Hyperlink"),"http://");var s=RegExp("^((http|https)://|(//))[a-z0-9]","i");if(null!==o&&""!==o&&"http://"!==o&&s.test(o)){var r=t("<div>"+o+"</div>").text();e.replaceSelection("!["+n+"]("+r+' "'+e.__localize("enter image title here")+'")'),i=a.start+2,e.setNextTab(e.__localize("enter image title here")),e.setSelection(i,i+n.length)}}}]},{name:"groupMisc",data:[{name:"cmdList",hotkey:"Ctrl+U",title:"Unordered List",icon:{glyph:"glyphicon glyphicon-list",fa:"fa fa-list","fa-3":"icon-list-ul","fa-5":"fa-solid fa-list-ul",octicons:"octicon octicon-list-unordered"},callback:function(e){var n,i,o=e.getSelection();if(e.getContent(),0===o.length)n=e.__localize("list text here"),e.replaceSelection("- "+n),i=o.start+2;else if(0>o.text.indexOf("\n"))n=o.text,e.replaceSelection("- "+n),i=o.start+2;else{var a=[];n=(a=o.text.split("\n"))[0],t.each(a,function(t,e){a[t]="- "+e}),e.replaceSelection("\n\n"+a.join("\n")),i=o.start+4}e.setSelection(i,i+n.length)}},{name:"cmdListO",hotkey:"Ctrl+O",title:"Ordered List",icon:{glyph:"glyphicon glyphicon-th-list",fa:"fa fa-list-ol","fa-3":"icon-list-ol","fa-5":"fa-solid fa-list-ol",octicons:"octicon octicon-list-ordered"},callback:function(e){var n,i,o=e.getSelection();if(e.getContent(),0===o.length)n=e.__localize("list text here"),e.replaceSelection("1. "+n),i=o.start+3;else if(0>o.text.indexOf("\n"))n=o.text,e.replaceSelection("1. "+n),i=o.start+3;else{var a=1,s=[];n=(s=o.text.split("\n"))[0],t.each(s,function(t,e){s[t]=a+". "+e,a++}),e.replaceSelection("\n\n"+s.join("\n")),i=o.start+5}e.setSelection(i,i+n.length)}},{name:"cmdCode",hotkey:"Ctrl+K",title:"Code",icon:{glyph:"glyphicon glyphicon-console",fa:"fa fa-code","fa-3":"icon-code","fa-5":"fa-solid fa-code",octicons:"octicon octicon-code"},callback:function(t){var e,n,i=t.getSelection(),o=t.getContent();e=0===i.length?t.__localize("code text here"):i.text,"```\n"===o.substr(i.start-4,4)&&"\n```"===o.substr(i.end,4)?(t.setSelection(i.start-4,i.end+4),t.replaceSelection(e),n=i.start-4):"`"===o.substr(i.start-1,1)&&"`"===o.substr(i.end,1)?(t.setSelection(i.start-1,i.end+1),t.replaceSelection(e),n=i.start-1):o.indexOf("\n")>-1?(t.replaceSelection("```\n"+e+"\n```"),n=i.start+4):(t.replaceSelection("`"+e+"`"),n=i.start+1),t.setSelection(n,n+e.length)}},{name:"cmdQuote",hotkey:"Ctrl+Q",title:"Quote",icon:{glyph:"glyphicon glyphicon-comment",fa:"fa fa-quote-left","fa-3":"icon-quote-left","fa-5":"fa-solid fa-quote-left",octicons:"octicon octicon-quote"},callback:function(e){var n,i,o=e.getSelection();if(e.getContent(),0===o.length)n=e.__localize("quote here"),e.replaceSelection("> "+n),i=o.start+2;else if(0>o.text.indexOf("\n"))n=o.text,e.replaceSelection("> "+n),i=o.start+2;else{var a=[];n=(a=o.text.split("\n"))[0],t.each(a,function(t,e){a[t]="> "+e}),e.replaceSelection("\n\n"+a.join("\n")),i=o.start+4}e.setSelection(i,i+n.length)}}]},{name:"groupUtil",data:[{name:"cmdPreview",toggle:!0,hotkey:"Ctrl+P",title:"Preview",btnText:"Preview",btnClass:"btn btn-primary btn-sm",icon:{glyph:"glyphicon glyphicon-search",fa:"fa fa-search","fa-3":"icon-search","fa-5":"fa-solid fa-search",octicons:"octicon octicon-search"},callback:function(t){!1===t.$isPreview?t.showPreview():t.hidePreview()}}]}]],customIcons:{},additionalButtons:[],reorderButtonGroups:[],hiddenButtons:[],disabledButtons:[],footer:"",fullscreen:{enable:!0,icons:{fullscreenOn:{name:"fullscreenOn",icon:{fa:"fa fa-expand",glyph:"glyphicon glyphicon-fullscreen","fa-3":"icon-resize-full","fa-5":"fa-solid fa-expand-arrows-alt",octicons:"octicon octicon-link-external"}},fullscreenOff:{name:"fullscreenOff",icon:{fa:"fa fa-compress",glyph:"glyphicon glyphicon-fullscreen","fa-3":"icon-resize-small","fa-5":"fa-solid fa-compress",octicons:"octicon octicon-browser"}}}},onShow:function(t){},onPreview:function(t){},onPreviewEnd:function(t){},onSave:function(t){},onBlur:function(t){},onFocus:function(t){},onChange:function(t){},onFullscreen:function(t){},onFullscreenExit:function(t){},onSelect:function(t){}},t.fn.markdown.Constructor=e,t.fn.markdown.noConflict=function(){return t.fn.markdown=n,this};var i=function(t){var e=t;if(e.data("markdown")){e.data("markdown").showEditor();return}e.markdown()},o=function(e){var n=t(document.activeElement);t(document).find(".md-editor").each(function(){var e=t(this),i=n.closest(".md-editor")[0]===this,o=e.find("textarea").data("markdown")||e.find('div[data-provider="markdown-preview"]').data("markdown");o&&!i&&o.blur()})};t(document).on("click.markdown.data-api",'[data-provide="markdown-editable"]',function(e){i(t(this)),e.preventDefault()}).on("click focusin",function(t){o(t)}).ready(function(){t('textarea[data-provide="markdown"]').each(function(){i(t(this))})})});