proclaim 0.5.6 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. checksums.yaml +5 -5
  2. data/Rakefile +5 -38
  3. data/app/assets/config/proclaim_manifest.js +2 -0
  4. data/app/assets/images/{ajax_loader.gif → proclaim/ajax_loader.gif} +0 -0
  5. data/app/assets/javascripts/proclaim.js +7 -7
  6. data/app/assets/javascripts/proclaim/{comments_handler.js.coffee → comments_handler.coffee} +16 -10
  7. data/app/assets/javascripts/proclaim/editor.coffee +55 -0
  8. data/app/assets/stylesheets/{proclaim.css.scss → proclaim.scss} +7 -8
  9. data/app/assets/stylesheets/proclaim/{comments.css.scss → comments.scss} +0 -0
  10. data/app/assets/stylesheets/proclaim/{posts.css.scss → posts.scss} +60 -25
  11. data/app/assets/stylesheets/proclaim/{subscriptions.css.scss → subscriptions.scss} +0 -0
  12. data/app/controllers/proclaim/application_controller.rb +60 -56
  13. data/app/controllers/proclaim/comments_controller.rb +13 -42
  14. data/app/controllers/proclaim/posts_controller.rb +25 -57
  15. data/app/controllers/proclaim/subscriptions_controller.rb +3 -3
  16. data/app/jobs/proclaim/application_job.rb +4 -0
  17. data/app/mailers/proclaim/application_mailer.rb +5 -0
  18. data/app/mailers/proclaim/subscription_mailer.rb +19 -17
  19. data/app/models/proclaim/application_record.rb +5 -0
  20. data/app/models/proclaim/comment.rb +6 -1
  21. data/app/models/proclaim/post.rb +20 -28
  22. data/app/models/proclaim/subscription.rb +33 -11
  23. data/app/views/layouts/proclaim/subscription_mailer.html.erb +15 -36
  24. data/app/views/proclaim/comments/_comment.html.erb +7 -7
  25. data/app/views/proclaim/comments/_form.html.erb +7 -5
  26. data/app/views/proclaim/posts/_form.html.erb +34 -21
  27. data/app/views/proclaim/posts/show.html.erb +16 -3
  28. data/app/views/proclaim/subscription_mailer/welcome_email.html.erb +2 -6
  29. data/config/initializers/friendly_id.rb +20 -1
  30. data/config/routes.rb +1 -5
  31. data/db/migrate/20141108222616_create_proclaim_posts.rb +8 -1
  32. data/db/migrate/20141114235359_create_proclaim_comments.rb +1 -1
  33. data/db/migrate/20141115022230_create_proclaim_comment_hierarchies.rb +1 -1
  34. data/db/migrate/20141210234057_create_proclaim_subscriptions.rb +5 -4
  35. data/db/migrate/20150213015321_create_friendly_id_slugs.rb +1 -1
  36. data/lib/generators/proclaim/install_generator.rb +1 -1
  37. data/lib/generators/proclaim/templates/initialize_proclaim.rb +31 -29
  38. data/lib/generators/proclaim/views_generator.rb +1 -1
  39. data/lib/proclaim.rb +15 -15
  40. data/lib/proclaim/engine.rb +21 -19
  41. data/lib/proclaim/version.rb +1 -1
  42. data/vendor/assets/fonts/KaTeX_AMS-Regular.ttf +0 -0
  43. data/vendor/assets/fonts/KaTeX_AMS-Regular.woff +0 -0
  44. data/vendor/assets/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  45. data/vendor/assets/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
  46. data/vendor/assets/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
  47. data/vendor/assets/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  48. data/vendor/assets/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
  49. data/vendor/assets/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
  50. data/vendor/assets/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  51. data/vendor/assets/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
  52. data/vendor/assets/fonts/KaTeX_Fraktur-Bold.woff +0 -0
  53. data/vendor/assets/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  54. data/vendor/assets/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
  55. data/vendor/assets/fonts/KaTeX_Fraktur-Regular.woff +0 -0
  56. data/vendor/assets/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  57. data/vendor/assets/fonts/KaTeX_Main-Bold.ttf +0 -0
  58. data/vendor/assets/fonts/KaTeX_Main-Bold.woff +0 -0
  59. data/vendor/assets/fonts/KaTeX_Main-Bold.woff2 +0 -0
  60. data/vendor/assets/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
  61. data/vendor/assets/fonts/KaTeX_Main-BoldItalic.woff +0 -0
  62. data/vendor/assets/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  63. data/vendor/assets/fonts/KaTeX_Main-Italic.ttf +0 -0
  64. data/vendor/assets/fonts/KaTeX_Main-Italic.woff +0 -0
  65. data/vendor/assets/fonts/KaTeX_Main-Italic.woff2 +0 -0
  66. data/vendor/assets/fonts/KaTeX_Main-Regular.ttf +0 -0
  67. data/vendor/assets/fonts/KaTeX_Main-Regular.woff +0 -0
  68. data/vendor/assets/fonts/KaTeX_Main-Regular.woff2 +0 -0
  69. data/vendor/assets/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
  70. data/vendor/assets/fonts/KaTeX_Math-BoldItalic.woff +0 -0
  71. data/vendor/assets/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  72. data/vendor/assets/fonts/KaTeX_Math-Italic.ttf +0 -0
  73. data/vendor/assets/fonts/KaTeX_Math-Italic.woff +0 -0
  74. data/vendor/assets/fonts/KaTeX_Math-Italic.woff2 +0 -0
  75. data/vendor/assets/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
  76. data/vendor/assets/fonts/KaTeX_SansSerif-Bold.woff +0 -0
  77. data/vendor/assets/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  78. data/vendor/assets/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
  79. data/vendor/assets/fonts/KaTeX_SansSerif-Italic.woff +0 -0
  80. data/vendor/assets/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  81. data/vendor/assets/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
  82. data/vendor/assets/fonts/KaTeX_SansSerif-Regular.woff +0 -0
  83. data/vendor/assets/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  84. data/vendor/assets/fonts/KaTeX_Script-Regular.ttf +0 -0
  85. data/vendor/assets/fonts/KaTeX_Script-Regular.woff +0 -0
  86. data/vendor/assets/fonts/KaTeX_Script-Regular.woff2 +0 -0
  87. data/vendor/assets/fonts/KaTeX_Size1-Regular.ttf +0 -0
  88. data/vendor/assets/fonts/KaTeX_Size1-Regular.woff +0 -0
  89. data/vendor/assets/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  90. data/vendor/assets/fonts/KaTeX_Size2-Regular.ttf +0 -0
  91. data/vendor/assets/fonts/KaTeX_Size2-Regular.woff +0 -0
  92. data/vendor/assets/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  93. data/vendor/assets/fonts/KaTeX_Size3-Regular.ttf +0 -0
  94. data/vendor/assets/fonts/KaTeX_Size3-Regular.woff +0 -0
  95. data/vendor/assets/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  96. data/vendor/assets/fonts/KaTeX_Size4-Regular.ttf +0 -0
  97. data/vendor/assets/fonts/KaTeX_Size4-Regular.woff +0 -0
  98. data/vendor/assets/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  99. data/vendor/assets/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
  100. data/vendor/assets/fonts/KaTeX_Typewriter-Regular.woff +0 -0
  101. data/vendor/assets/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  102. data/vendor/assets/javascripts/contrib/auto-render.js +339 -0
  103. data/vendor/assets/javascripts/contrib/auto-render.min.js +1 -0
  104. data/vendor/assets/javascripts/contrib/auto-render.mjs +215 -0
  105. data/vendor/assets/javascripts/contrib/copy-tex.css +14 -0
  106. data/vendor/assets/javascripts/contrib/copy-tex.js +213 -0
  107. data/vendor/assets/javascripts/contrib/copy-tex.min.css +1 -0
  108. data/vendor/assets/javascripts/contrib/copy-tex.min.js +1 -0
  109. data/vendor/assets/javascripts/contrib/copy-tex.mjs +85 -0
  110. data/vendor/assets/javascripts/contrib/mathtex-script-type.js +137 -0
  111. data/vendor/assets/javascripts/contrib/mathtex-script-type.min.js +1 -0
  112. data/vendor/assets/javascripts/contrib/mathtex-script-type.mjs +24 -0
  113. data/vendor/assets/javascripts/contrib/mhchem.js +3241 -0
  114. data/vendor/assets/javascripts/contrib/mhchem.min.js +1 -0
  115. data/vendor/assets/javascripts/contrib/mhchem.mjs +3109 -0
  116. data/vendor/assets/javascripts/katex.js +16517 -0
  117. data/vendor/assets/javascripts/katex.min.js +1 -0
  118. data/vendor/assets/javascripts/katex.mjs +16122 -0
  119. data/vendor/assets/javascripts/quill.core.js +8522 -0
  120. data/vendor/assets/javascripts/quill.js +11489 -0
  121. data/vendor/assets/javascripts/quill.min.js +8 -0
  122. data/vendor/assets/javascripts/quill.min.js.map +1 -0
  123. data/vendor/assets/stylesheets/katex.css +1011 -0
  124. data/vendor/assets/stylesheets/katex.min.css +1 -0
  125. data/vendor/assets/stylesheets/quill.bubble.css +952 -0
  126. data/vendor/assets/stylesheets/quill.core.css +397 -0
  127. data/vendor/assets/stylesheets/quill.snow.css +945 -0
  128. metadata +169 -278
  129. data/CHANGELOG +0 -77
  130. data/Gemfile +0 -14
  131. data/VERSION +0 -1
  132. data/app/assets/javascripts/proclaim/editor.js.coffee +0 -52
  133. data/app/assets/javascripts/proclaim/images.js.coffee +0 -3
  134. data/app/assets/javascripts/proclaim/subscriptions.js.coffee +0 -3
  135. data/app/assets/stylesheets/proclaim/images.scss +0 -3
  136. data/app/controllers/proclaim/images_controller.rb +0 -67
  137. data/app/helpers/proclaim/comments_helper.rb +0 -4
  138. data/app/helpers/proclaim/images_helper.rb +0 -4
  139. data/app/helpers/proclaim/subscriptions_helper.rb +0 -4
  140. data/app/models/proclaim/image.rb +0 -19
  141. data/app/policies/proclaim/image_policy.rb +0 -29
  142. data/app/uploaders/proclaim/image_uploader.rb +0 -82
  143. data/db/migrate/20141222224905_create_proclaim_images.rb +0 -12
  144. data/db/migrate/20150123115226_add_name_to_subscriptions.rb +0 -7
  145. data/db/migrate/20150213015850_add_slug_to_posts.rb +0 -20
  146. data/proclaim.gemspec +0 -51
  147. data/test/controllers/proclaim/comments_controller_test.rb +0 -228
  148. data/test/controllers/proclaim/images_controller_test.rb +0 -166
  149. data/test/controllers/proclaim/posts_controller_test.rb +0 -465
  150. data/test/controllers/proclaim/subscriptions_controller_test.rb +0 -154
  151. data/test/dummy/README.rdoc +0 -28
  152. data/test/dummy/Rakefile +0 -6
  153. data/test/dummy/app/assets/javascripts/application.js +0 -14
  154. data/test/dummy/app/assets/stylesheets/application.css +0 -16
  155. data/test/dummy/app/controllers/application_controller.rb +0 -15
  156. data/test/dummy/app/helpers/application_helper.rb +0 -28
  157. data/test/dummy/app/models/user.rb +0 -7
  158. data/test/dummy/app/views/layouts/application.html.erb +0 -16
  159. data/test/dummy/bin/bundle +0 -3
  160. data/test/dummy/bin/rails +0 -4
  161. data/test/dummy/bin/rake +0 -4
  162. data/test/dummy/config.ru +0 -4
  163. data/test/dummy/config/application.rb +0 -24
  164. data/test/dummy/config/boot.rb +0 -5
  165. data/test/dummy/config/database.yml +0 -25
  166. data/test/dummy/config/environment.rb +0 -5
  167. data/test/dummy/config/environments/development.rb +0 -45
  168. data/test/dummy/config/environments/production.rb +0 -80
  169. data/test/dummy/config/environments/test.rb +0 -49
  170. data/test/dummy/config/initializers/assets.rb +0 -8
  171. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
  172. data/test/dummy/config/initializers/cookies_serializer.rb +0 -3
  173. data/test/dummy/config/initializers/filter_parameter_logging.rb +0 -4
  174. data/test/dummy/config/initializers/inflections.rb +0 -16
  175. data/test/dummy/config/initializers/mime_types.rb +0 -4
  176. data/test/dummy/config/initializers/session_store.rb +0 -3
  177. data/test/dummy/config/initializers/wrap_parameters.rb +0 -14
  178. data/test/dummy/config/locales/en.yml +0 -23
  179. data/test/dummy/config/routes.rb +0 -5
  180. data/test/dummy/config/secrets.yml +0 -22
  181. data/test/dummy/db/migrate/20141117214323_create_users.rb +0 -10
  182. data/test/dummy/db/schema.rb +0 -91
  183. data/test/dummy/public/404.html +0 -67
  184. data/test/dummy/public/422.html +0 -67
  185. data/test/dummy/public/500.html +0 -66
  186. data/test/dummy/public/favicon.ico +0 -0
  187. data/test/factories/proclaim/comment.rb +0 -11
  188. data/test/factories/proclaim/image.rb +0 -6
  189. data/test/factories/proclaim/post.rb +0 -14
  190. data/test/factories/proclaim/subscription.rb +0 -14
  191. data/test/factories/user.rb +0 -6
  192. data/test/helpers/proclaim/comments_helper_test.rb +0 -6
  193. data/test/helpers/proclaim/posts_helper_test.rb +0 -6
  194. data/test/helpers/proclaim/subscriptions_helper_test.rb +0 -6
  195. data/test/integration/with_javascript/comment_test.rb +0 -391
  196. data/test/integration/with_javascript/post_form_test.rb +0 -225
  197. data/test/integration/with_javascript/post_show_test.rb +0 -47
  198. data/test/integration/with_javascript/post_subscription_test.rb +0 -302
  199. data/test/integration/without_javascript/blog_subscription_test.rb +0 -114
  200. data/test/integration/without_javascript/manage_subscriptions_test.rb +0 -37
  201. data/test/integration/without_javascript/post_test.rb +0 -234
  202. data/test/integration/without_javascript/subscription_email_test.rb +0 -95
  203. data/test/integration/without_javascript/unsubscribe_test.rb +0 -32
  204. data/test/mailers/previews/proclaim/subscription_mailer_preview.rb +0 -22
  205. data/test/mailers/proclaim/subscription_mailer_test.rb +0 -91
  206. data/test/models/proclaim/comment_test.rb +0 -41
  207. data/test/models/proclaim/image_test.rb +0 -70
  208. data/test/models/proclaim/post_test.rb +0 -193
  209. data/test/models/proclaim/subscription_test.rb +0 -77
  210. data/test/policies/application_policy_test.rb +0 -87
  211. data/test/policies/proclaim/comment_policy_test.rb +0 -71
  212. data/test/policies/proclaim/image_policy_test.rb +0 -83
  213. data/test/policies/proclaim/post_policy_test.rb +0 -98
  214. data/test/policies/proclaim/subscription_policy_test.rb +0 -103
  215. data/test/proclaim_test.rb +0 -7
  216. data/test/support/images/test.jpg +0 -0
  217. data/test/support/pages/posts/edit_page.rb +0 -5
  218. data/test/support/pages/posts/show_page.rb +0 -47
  219. data/test/support/wait_for_ajax.rb +0 -11
  220. data/test/test_helper.rb +0 -71
  221. data/test/unit/proclaim/new_comment_callback_test.rb +0 -62
  222. data/test/unit/proclaim/new_subscription_callback_test.rb +0 -62
  223. data/test/unit/proclaim/post_published_callback_test.rb +0 -74
  224. data/vendor/assets/images/link.png +0 -0
  225. data/vendor/assets/images/remove.png +0 -0
  226. data/vendor/assets/images/resize-bigger.png +0 -0
  227. data/vendor/assets/images/resize-smaller.png +0 -0
  228. data/vendor/assets/images/unlink.png +0 -0
  229. data/vendor/assets/javascripts/addons/medium-editor-insert-embeds.js +0 -197
  230. data/vendor/assets/javascripts/addons/medium-editor-insert-images.js +0 -572
  231. data/vendor/assets/javascripts/addons/medium-editor-insert-maps.js +0 -50
  232. data/vendor/assets/javascripts/addons/medium-editor-insert-plugin.js +0 -496
  233. data/vendor/assets/javascripts/addons/medium-editor-insert-tables.js +0 -132
  234. data/vendor/assets/javascripts/medium-editor-insert-plugin.all.js +0 -1415
  235. data/vendor/assets/stylesheets/medium-editor-insert-plugin-frontend.css.scss +0 -55
  236. data/vendor/assets/stylesheets/medium-editor-insert-plugin.css.scss +0 -277
@@ -1,132 +0,0 @@
1
- /*!
2
- * medium-editor-insert-plugin v0.3.2 - jQuery insert plugin for MediumEditor
3
- *
4
- * https://github.com/orthes/medium-editor-insert-plugin
5
- *
6
- * Copyright (c) 2014 Pavel Linkesch (http://linkesch.sk)
7
- * Released under the MIT license
8
- */
9
-
10
- (function ($) {
11
-
12
- $.fn.mediumInsert.registerAddon('tables', {
13
-
14
- /**
15
- * Table default options
16
- */
17
-
18
- defaults: {
19
- defaultRows: 2,
20
- defaultCols: 2
21
- },
22
-
23
- /**
24
- * Tables initial function
25
- * @return {void}
26
- */
27
- init : function (options) {
28
- this.options = $.extend(this.defaults, options);
29
- this.$el = $.fn.mediumInsert.insert.$el;
30
- this.setTableButtonEvents();
31
- },
32
-
33
- insertButton : function (buttonLabels) {
34
- var label = 'Table';
35
- if (buttonLabels === 'fontawesome' || typeof buttonLabels === 'object' && !!(buttonLabels.fontawesome)) {
36
- label = '<i class="fa fa-table"></i>';
37
- }
38
-
39
- if (typeof buttonLabels === 'object' && buttonLabels.table) {
40
- label = buttonLabels.table;
41
- }
42
-
43
- return '<button data-addon="tables" data-action="add" class="medium-editor-action mediumInsert-action">' + label + '</button>';
44
- },
45
-
46
- /**
47
- * Add table to $placeholder
48
- * @param {element} $placeholder $placeholder to add embed to
49
- * @return {void}
50
- */
51
- add : function ($placeholder) {
52
- $.fn.mediumInsert.insert.deselect();
53
-
54
- var formHtml = '<div class="medium-editor-toolbar-form-anchor mediumInsert-tableDemoBox"><table><tr><td></td><td><label>cols:<input type="text" value="' + this.options.defaultCols + '" class="mediumInsert-tableCols" /></label></td></tr><tr><td><label>rows:<input type="text" value="' + this.options.defaultRows + '" class="mediumInsert-tableRows" /></label></td><td><table class="mediumInsert-demoTable"></table></td></tr><tr><td></td><td><label><button class="mediumInsert-tableReadyButton">insert</button></label></td></tr></table></</div>';
55
- $(formHtml).appendTo($placeholder.prev());
56
- this.updateDemoTable();
57
-
58
- setTimeout(function () {
59
- $placeholder.prev().find('input').focus();
60
- }, 50);
61
-
62
- $.fn.mediumInsert.insert.deselect();
63
- this.currentPlaceholder = $placeholder;
64
- },
65
-
66
- setTableButtonEvents : function () {
67
- var that = this;
68
-
69
- $(document).on('keyup',
70
- 'input.mediumInsert-tableRows, input.mediumInsert-tableCols',
71
- function() { that.updateDemoTable(); });
72
-
73
- $(document).on('click', function(e) {
74
- if ($(e.target).parents('.mediumInsert-buttons').length === 0) {
75
- that.removeToolbar();
76
- }
77
- });
78
-
79
- $(document).on('click', 'button.mediumInsert-tableReadyButton', function() {
80
- that.setEnterActionEvents();
81
- that.removeToolbar();
82
- });
83
- },
84
-
85
- getDimensions : function () {
86
- return {
87
- rows: parseFloat($('input.mediumInsert-tableRows').val()) || 1,
88
- cols: parseFloat($('input.mediumInsert-tableCols').val()) || 1
89
- };
90
- },
91
-
92
- buildTable : function (table) {
93
- var i, j, $row,
94
- dimensions = this.getDimensions(),
95
- $table = $(table);
96
-
97
- for (i = 0; i < dimensions.rows; i++) {
98
- $row = $('<tr>');
99
- for (j = 0; j < dimensions.cols; j++) {
100
- $row.append('<td>');
101
- }
102
- $table.append($row);
103
- }
104
- },
105
-
106
- updateDemoTable : function () {
107
- var $demoTable = $('table.mediumInsert-demoTable');
108
-
109
- $demoTable.empty();
110
- this.buildTable($demoTable);
111
- },
112
-
113
- setEnterActionEvents : function () {
114
- var that = this;
115
- if ($.fn.mediumInsert.settings.enabled === false) {
116
- return false;
117
- }
118
-
119
- var $table = $('<table class="mediumInsert-table">');
120
- that.buildTable($table);
121
-
122
- that.currentPlaceholder.append($table);
123
- that.currentPlaceholder.closest('[data-medium-element]').trigger('keyup').trigger('input');
124
- },
125
-
126
- removeToolbar : function () {
127
- $(".mediumInsert-tableDemoBox").remove();
128
- }
129
-
130
- });
131
-
132
- }(jQuery));
@@ -1,1415 +0,0 @@
1
- /*!
2
- * medium-editor-insert-plugin v0.3.2 - jQuery insert plugin for MediumEditor
3
- *
4
- * https://github.com/orthes/medium-editor-insert-plugin
5
- *
6
- * Copyright (c) 2014 Pavel Linkesch (http://linkesch.sk)
7
- * Released under the MIT license
8
- */
9
-
10
- /* global MediumEditor */
11
-
12
- (function ($) {
13
- /*
14
- * Private storage of registered addons
15
- */
16
- var addons = {};
17
-
18
- /**
19
- * Extend MediumEditor functions if the editor exists
20
- */
21
- if (MediumEditor && typeof(MediumEditor) === "function") {
22
- /**
23
- * Extend MediumEditor's serialize function to get rid of unnecesarry Medium Editor Insert Plugin stuff
24
- *
25
- * @return {object} content Object containing HTML content of each element
26
- */
27
-
28
- MediumEditor.prototype.serialize = function () {
29
- var i, j,
30
- elementid,
31
- content = {},
32
- $clone, $inserts, $insert, $insertData, html;
33
- for (i = 0; i < this.elements.length; i += 1) {
34
- elementid = (this.elements[i].id !== '') ? this.elements[i].id : 'element-' + i;
35
-
36
- $clone = $(this.elements[i]).clone();
37
- $inserts = $('.mediumInsert', $clone);
38
- for (j = 0; j < $inserts.length; j++) {
39
- $insert = $($inserts[j]);
40
- $insertData = $('.mediumInsert-placeholder', $insert).children();
41
- if ($insertData.length === 0) {
42
- $insert.remove();
43
- } else {
44
- $insert.removeAttr('contenteditable');
45
- $('img[draggable]', $insert).removeAttr('draggable');
46
- if ($insert.hasClass('small')) {
47
- $insertData.addClass('small');
48
- }
49
- $('.mediumInsert-buttons', $insert).remove();
50
- $insertData.unwrap();
51
- }
52
- }
53
-
54
- html = $clone.html().trim();
55
- content[elementid] = {
56
- value: html
57
- };
58
- }
59
- return content;
60
- };
61
-
62
- /**
63
- * Extend MediumEditor's deactivate function to call $.fn.mediumInsert.insert.disable function
64
- *
65
- * @return {void}
66
- */
67
-
68
- MediumEditor.prototype.deactivate = function () {
69
- var i;
70
- if (!this.isActive) {
71
- return false;
72
- }
73
- this.isActive = false;
74
-
75
- if (this.toolbar !== undefined) {
76
- this.toolbar.style.display = 'none';
77
- }
78
-
79
- document.documentElement.removeEventListener('mouseup', this.checkSelectionWrapper);
80
-
81
- for (i = 0; i < this.elements.length; i += 1) {
82
- this.elements[i].removeEventListener('keyup', this.checkSelectionWrapper);
83
- this.elements[i].removeEventListener('blur', this.checkSelectionWrapper);
84
- this.elements[i].removeAttribute('contentEditable');
85
- }
86
-
87
- if ($.fn.mediumInsert.insert.$el)
88
- $.fn.mediumInsert.insert.$el.mediumInsert('disable');
89
- };
90
-
91
- /**
92
- * Extend MediumEditor's activate function to call $.fn.mediumInsert.insert.enable function
93
- *
94
- * @return {void}
95
- */
96
-
97
- MediumEditor.prototype.activate = function () {
98
- var i;
99
- if (this.isActive) {
100
- return false;
101
- }
102
-
103
- if (this.toolbar !== undefined) {
104
- this.toolbar.style.display = 'block';
105
- }
106
-
107
- this.isActive = true;
108
- for (i = 0; i < this.elements.length; i += 1) {
109
- this.elements[i].setAttribute('contentEditable', true);
110
- }
111
- this.bindSelect();
112
-
113
- if ($.fn.mediumInsert.insert.$el)
114
- $.fn.mediumInsert.insert.$el.mediumInsert('enable');
115
- };
116
- }
117
-
118
- /**
119
- * Medium Editor Insert Plugin
120
- *
121
- * @param {object} options Options for the plugin
122
- * @param {void}
123
- */
124
-
125
- $.fn.mediumInsert = function (options) {
126
-
127
- if (typeof options === 'string' && $.fn.mediumInsert.insert[options]) {
128
- $.fn.mediumInsert.insert[options]();
129
- } else {
130
- $.fn.mediumInsert.settings = $.extend($.fn.mediumInsert.settings, options);
131
-
132
-
133
-
134
- /**
135
- * Initial plugin loop
136
- */
137
-
138
- return this.each(function () {
139
- $(this).addClass('medium-editor-insert-plugin');
140
-
141
- var blocks = 'p, h1, h2, h3, h4, h5, h6, ol, ul, blockquote';
142
- $(this).on('dragover drop', blocks, function (e) {
143
- e.preventDefault();
144
- return false;
145
- });
146
-
147
- $.fn.mediumInsert.insert.init($(this));
148
-
149
- $.each($.fn.mediumInsert.settings.addons, function (i) {
150
- if (typeof addons[i] !== 'undefined') {
151
- var addonOptions = $.fn.mediumInsert.settings.addons[i];
152
- addonOptions.$el = $.fn.mediumInsert.insert.$el;
153
- addons[i].init(addonOptions);
154
- }
155
- });
156
- });
157
- }
158
- };
159
-
160
-
161
- /**
162
- * Settings
163
- */
164
- $.fn.mediumInsert.settings = {
165
- enabled: true,
166
- beginning: false,
167
- addons: {
168
- images: {},
169
- embeds: {}
170
- }
171
- };
172
-
173
- /**
174
- * Register new addon
175
- */
176
- $.fn.mediumInsert.registerAddon = function(name, addon){
177
- addons[name] = addon;
178
- };
179
-
180
- /**
181
- * Get registered addon
182
- */
183
- $.fn.mediumInsert.getAddon = function(name){
184
- return addons[name];
185
- };
186
-
187
-
188
- /**
189
- * Addon Initialization
190
- */
191
-
192
- $.fn.mediumInsert.insert = {
193
-
194
- /**
195
- * Insert initial function
196
- *
197
- * @param {element} el Parent container element
198
- * @return {void}
199
- */
200
-
201
- init: function ($el) {
202
- this.$el = $el;
203
- this.isFirefox = navigator.userAgent.match(/firefox/i);
204
- this.setPlaceholders();
205
- this.setEvents();
206
- },
207
-
208
- /**
209
- * Deselect selected text
210
- *
211
- * @return {void}
212
- */
213
-
214
- deselect: function () {
215
- document.getSelection().removeAllRanges();
216
- },
217
-
218
- /**
219
- * Disable the plugin
220
- *
221
- * @return {void}
222
- */
223
-
224
- disable: function () {
225
- $.fn.mediumInsert.settings.enabled = false;
226
-
227
- $.fn.mediumInsert.insert.$el.find('.mediumInsert-buttons').addClass('hide');
228
- },
229
-
230
- /**
231
- * Enable the plugin
232
- *
233
- * @return {void}
234
- */
235
-
236
- enable: function () {
237
- $.fn.mediumInsert.settings.enabled = true;
238
-
239
- $.fn.mediumInsert.insert.$el.find('.mediumInsert-buttons').removeClass('hide');
240
- },
241
-
242
- /**
243
- * Return max id in #mediumInsert-*
244
- *
245
- * @return {int} max (Max number, -1 if no placeholders exist)
246
- */
247
- getMaxId: function () {
248
- var max = -1;
249
-
250
- $('div[id^="mediumInsert-"]').each(function () {
251
- var id = parseInt($(this).attr('id').split('-')[1], 10);
252
- if (id > max) {
253
- max = id;
254
- }
255
- });
256
-
257
- return max;
258
- },
259
-
260
- /**
261
- * Return insert buttons optionally filtered by addon name
262
- *
263
- * @param {string} addon Addon name of addon to display only
264
- * @return {void}
265
- */
266
- getButtons: function (addon) {
267
- var editor = $.fn.mediumInsert.settings.editor,
268
- buttonLabels = (editor && editor.options) ? editor.options.buttonLabels : '';
269
-
270
- var buttons;
271
- if($.fn.mediumInsert.settings.enabled) {
272
- buttons = '<div class="mediumInsert-buttons">'+
273
- '<a class="mediumInsert-buttonsShow">+</a>'+
274
- '<ul class="mediumInsert-buttonsOptions medium-editor-toolbar medium-editor-toolbar-active">';
275
- } else {
276
- buttons = '<div class="mediumInsert-buttons hide">'+
277
- '<a class="mediumInsert-buttonsShow">+</a>'+
278
- '<ul class="mediumInsert-buttonsOptions medium-editor-toolbar medium-editor-toolbar-active">';
279
- }
280
-
281
- if (Object.keys($.fn.mediumInsert.settings.addons).length === 0) {
282
- return false;
283
- }
284
-
285
- if (typeof addon === 'undefined') {
286
- $.each($.fn.mediumInsert.settings.addons, function (i) {
287
- if (typeof addons[i] === 'undefined') {
288
- console.log('Addon "' + i + '" is not available. Did you forgot to include the related file?');
289
- } else {
290
- buttons += '<li>' + addons[i].insertButton(buttonLabels) + '</li>';
291
- }
292
- });
293
- } else {
294
- buttons += '<li>' + addons[addon].insertButton(buttonLabels) + '</li>';
295
- }
296
-
297
- buttons += '</ul></div>';
298
-
299
- return buttons;
300
- },
301
-
302
- /**
303
- * Method setting placeholders
304
- *
305
- * @return {void}
306
- */
307
-
308
- setPlaceholders: function () {
309
- var that = this,
310
- $el = $.fn.mediumInsert.insert.$el,
311
- insertBlock = this.getButtons(),
312
- $firstEl;
313
-
314
- if (insertBlock === false) {
315
- return false;
316
- }
317
-
318
- insertBlock = '<div class="mediumInsert" contenteditable="false">'+
319
- insertBlock +
320
- '<div class="mediumInsert-placeholder"></div>'+
321
- '</div>';
322
-
323
- if ($el.is(':empty')) {
324
- $el.html('<p><br></p>');
325
- }
326
-
327
- $el.keyup(function () {
328
- var $lastChild = $el.children(':last'),
329
- i;
330
-
331
- // Fix #39
332
- // After deleting all content (ctrl+A and delete) in Firefox, all content is deleted and only <br> appears
333
- // To force placeholder to appear, set <p><br></p> as content of the $el
334
- if ($el.html() === '' || $el.html() === '<br>') {
335
- $el.html('<p><br></p>');
336
- }
337
-
338
- if ($lastChild.hasClass('mediumInsert') && $lastChild.find('.mediumInsert-placeholder').children().length > 0) {
339
- $el.append('<p><br></p>');
340
- }
341
-
342
- // Fix not deleting placeholder in Firefox
343
- // by removing all empty placeholders
344
- if (that.isFirefox){
345
- $('.mediumInsert .mediumInsert-placeholder:empty', $el).each(function () {
346
- $(this).parent().remove();
347
- });
348
- }
349
-
350
- i = that.getMaxId() +1;
351
-
352
- var blocks = 'p, h1, h2, h3, h4, h5, h6, ol, ul, blockquote';
353
-
354
- if ($.fn.mediumInsert.settings.beginning) {
355
- $firstEl = $el.children(blocks).first();
356
- if ($firstEl.prev().hasClass('mediumInsert') === false) {
357
- $firstEl.before(insertBlock);
358
- $firstEl.prev('.mediumInsert').attr('id', 'mediumInsert-'+ i).addClass('mediumInsert-first');
359
- i++;
360
- }
361
- }
362
-
363
- $el.children(blocks).each(function () {
364
- if ($(this).next().hasClass('mediumInsert') === false) {
365
- $(this).after(insertBlock);
366
- $(this).next('.mediumInsert').attr('id', 'mediumInsert-'+ i);
367
- }
368
- i++;
369
- });
370
-
371
- }).keyup();
372
- },
373
-
374
-
375
- /**
376
- * Set events on placeholders
377
- *
378
- * @return {void}
379
- */
380
-
381
- setEvents: function () {
382
- var that = this,
383
- $el = $.fn.mediumInsert.insert.$el;
384
-
385
- $el.on('selectstart mousedown', '.mediumInsert', function (e) {
386
- if ($(e.target).is('img') === false) {
387
- e.preventDefault();
388
- }
389
- });
390
-
391
- $el.on('blur', function () {
392
- var $clone = $(this).clone(),
393
- cloneHtml;
394
-
395
- $clone.find('.mediumInsert').remove();
396
- cloneHtml = $clone.html().replace(/^\s+|\s+$/g, '');
397
-
398
- if (cloneHtml === '' || cloneHtml === '<p><br></p>') {
399
- $(this).addClass('medium-editor-placeholder');
400
- }
401
- });
402
-
403
-
404
- // Fix #29
405
- // Sometimes in Firefox when you hit enter, <br type="_moz"> appears instead of <p><br></p>
406
- // If it happens, force to wrap the <br> into a paragraph
407
- $el.on('keypress', function (e) {
408
- if (that.isFirefox) {
409
- if (e.keyCode === 13) {
410
- //wrap content text in p to avoid firefox problems
411
- $el.contents().each((function() {
412
- return function(index, field) {
413
- if (field.nodeName === '#text' && field.textContent.trim() !== '') {
414
- document.execCommand('insertHTML', false, "<p>" + field.data + "</p>");
415
- return field.remove();
416
- }
417
- };
418
- })(this));
419
- // Removed because of #94 issue
420
- //
421
- // Firefox add extra br tag inside p tag
422
- // var latestPTag = $el.find('p').last();
423
- // if (latestPTag.text().length > 0) {
424
- // latestPTag.find('br').remove();
425
- // }
426
- }
427
- }
428
- });
429
-
430
- // Fix #39
431
- // For some reason Chrome doesn't "select-all", when the last placeholder is visible.
432
- // So it's needed to hide it when the user "selects all", and show it again when they presses any other key.
433
- $el.on('keydown', function (e) {
434
- // Fix Select-all using (ctrl + a) in chrome
435
- if (navigator.userAgent.match(/chrome/i)) {
436
- $el.children().last().removeClass('hide');
437
- if ( (e.ctrlKey || e.metaKey) && e.which === 65) {
438
- e.preventDefault();
439
- if($el.find('p').text().trim().length === 0) {
440
- return false;
441
- }
442
-
443
- $el.children().last().addClass('hide');
444
- return document.execCommand('selectAll', false, null);
445
- }
446
- }
447
- });
448
-
449
- $el.on('click', '.mediumInsert-buttons a.mediumInsert-buttonsShow', function () {
450
- var $options = $(this).siblings('.mediumInsert-buttonsOptions'),
451
- $placeholder = $(this).parent().siblings('.mediumInsert-placeholder');
452
-
453
- if ($(this).hasClass('active')) {
454
- $(this).removeClass('active');
455
- $options.hide();
456
-
457
- $('a', $options).show();
458
- } else {
459
- $(this).addClass('active');
460
- $options.show();
461
-
462
- $('a', $options).each(function () {
463
- var aClass = $(this).attr('class').split('action-')[1],
464
- plugin = aClass.split('-')[0];
465
- if ($('.mediumInsert-'+ plugin, $placeholder).length > 0) {
466
- $('a:not(.action-'+ aClass +')', $options).hide();
467
- }
468
- });
469
- }
470
-
471
- that.deselect();
472
- });
473
-
474
- $el.on('mouseleave', '.mediumInsert', function () {
475
- $('a.mediumInsert-buttonsShow', this).removeClass('active');
476
- $('.mediumInsert-buttonsOptions', this).hide();
477
- });
478
-
479
- $el.on('click', '.mediumInsert-buttons .mediumInsert-action', function (e) {
480
- e.preventDefault();
481
-
482
- var addon = $(this).data('addon'),
483
- action = $(this).data('action'),
484
- $placeholder = $(this).parents('.mediumInsert-buttons').siblings('.mediumInsert-placeholder');
485
-
486
- if (addons[addon] && addons[addon][action]) {
487
- addons[addon][action]($placeholder);
488
- }
489
-
490
- $(this).parents('.mediumInsert').mouseleave();
491
- });
492
- }
493
-
494
- };
495
-
496
- }(jQuery));
497
-
498
- (function ($) {
499
-
500
- $.fn.mediumInsert.registerAddon('embeds', {
501
-
502
- /**
503
- * Embed default options
504
- */
505
-
506
- defaults: {
507
- urlPlaceholder: 'Paste or type a link'
508
- //,oembedProxy: 'http://medium.iframe.ly/api/oembed?iframe=1'
509
- },
510
-
511
- /**
512
- * Embeds initial function
513
- * @return {void}
514
- */
515
- init : function (options) {
516
- this.options = $.extend(this.defaults, options);
517
- this.$el = $.fn.mediumInsert.insert.$el;
518
- this.setEmbedButtonEvents();
519
- this.preparePreviousEmbeds();
520
- },
521
-
522
- insertButton : function (buttonLabels) {
523
- var label = 'Embed';
524
- if (buttonLabels === 'fontawesome' || typeof buttonLabels === 'object' && !!(buttonLabels.fontawesome)) {
525
- label = '<i class="fa fa-code"></i>';
526
- }
527
-
528
- if (typeof buttonLabels === 'object' && buttonLabels.embed) {
529
- label = buttonLabels.embed;
530
- }
531
-
532
- return '<button data-addon="embeds" data-action="add" class="medium-editor-action mediumInsert-action">' + label + '</button>';
533
- },
534
-
535
- /**
536
- * Add embed to $placeholder
537
- * @param {element} $placeholder $placeholder to add embed to
538
- * @return {void}
539
- */
540
- add : function ($placeholder) {
541
- $.fn.mediumInsert.insert.deselect();
542
-
543
-
544
- var formHtml = '<div class="medium-editor-toolbar medium-editor-toolbar-active medium-editor-toolbar-form-anchor mediumInsert-embedsWire" style="display: block;"><input type="text" value="" placeholder="' + this.options.urlPlaceholder + '" class="mediumInsert-embedsText medium-editor-toolbar-anchor-input"></div>';
545
- $(formHtml).appendTo($placeholder.prev());
546
- setTimeout(function () {
547
- $placeholder.prev().find('input').focus();
548
- }, 50);
549
-
550
- $.fn.mediumInsert.insert.deselect();
551
-
552
- this.currentPlaceholder = $placeholder;
553
- $(".mediumInsert-embedsText").focus();
554
- },
555
-
556
- /**
557
- * Make existing embeds interactive
558
- *
559
- * @return {void}
560
- */
561
-
562
- preparePreviousEmbeds: function () {
563
- this.$el.find('.mediumInsert-embeds').each(function() {
564
- var $parent = $(this).parent();
565
- if (!$parent.hasClass('mediumInsert-placeholder')) {
566
- $parent.html('<div class="mediumInsert-placeholder" draggable="true">' + $parent.html() + '</div>');
567
- }
568
- });
569
- },
570
-
571
- setEmbedButtonEvents : function () {
572
- var that = this;
573
- $(document).on('keypress', 'input.mediumInsert-embedsText', function (e) {
574
- if ((e.which && e.which === 13) || (e.keyCode && e.keyCode === 13)) {
575
- that.setEnterActionEvents();
576
- that.removeToolbar();
577
- }
578
- });
579
-
580
- this.$el
581
- .on('blur', '.mediumInsert-embedsText', function () {
582
- that.removeToolbar();
583
- })
584
- // Fix #72
585
- // Workaround for CTRL+V not working in FF, when cleanPastedHTML and forcePlainText options on editor are set to true,
586
- // because editor steals the event and doesn't pass it to the plugin
587
- // https://github.com/orthes/medium-editor-insert-plugin/issues/72
588
- .on('paste', '.mediumInsert-embedsText', function (e) {
589
- if ($.fn.mediumInsert.insert.isFirefox && e.originalEvent.clipboardData) {
590
- $(this).val(e.originalEvent.clipboardData.getData('text/plain'));
591
- }
592
- });
593
-
594
- },
595
- setEnterActionEvents : function () {
596
- var that = this;
597
- if ($.fn.mediumInsert.settings.enabled === false) {
598
- return false;
599
- }
600
-
601
- var url = $("input.mediumInsert-embedsText").val();
602
- if (!url) {
603
- return false;
604
- }
605
-
606
- function processEmbedTag(embed_tag) {
607
- if (!embed_tag) {
608
- alert('Incorrect URL format specified');
609
- return false;
610
- } else {
611
- var returnedTag = embed_tag;
612
- var tagId = new Date().getTime();
613
- embed_tag = $('<div class="mediumInsert-embeds" id="' + tagId + '"></div>').append(embed_tag);
614
- that.currentPlaceholder.append(embed_tag);
615
- that.currentPlaceholder.closest('[data-medium-element]').trigger('keyup').trigger('input');
616
-
617
- if(returnedTag.indexOf("facebook") !== -1) {
618
- if (typeof(FB) !== 'undefined') {
619
- setTimeout(function() { FB.XFBML.parse();}, 2000);
620
- }
621
- }
622
- }
623
- }
624
-
625
- if (this.options.oembedProxy) {
626
- that.getOEmbedHTML(url, function(error, oebmed) {
627
-
628
- var html = !error && oebmed && oebmed.html;
629
-
630
- if (oebmed && !oebmed.html && oebmed.type === 'photo' && oebmed.url) {
631
- html = '<img src="' + oebmed.url + '" />';
632
- }
633
-
634
- processEmbedTag(html);
635
- });
636
- } else {
637
- var embed_tag = that.convertUrlToEmbedTag(url);
638
- return processEmbedTag(embed_tag);
639
- }
640
-
641
- },
642
-
643
- removeToolbar : function () {
644
- $(".mediumInsert-embedsWire").remove();
645
- },
646
-
647
- getOEmbedHTML: function(url, cb) {
648
- $.ajax({
649
- url: this.options.oembedProxy,
650
- dataType: "json",
651
- data: {
652
- url: url
653
- },
654
- success: function(data, textStatus, jqXHR) {
655
- cb(null, data, jqXHR);
656
- },
657
- error: function(jqXHR, textStatus, errorThrown) {
658
- var responseJSON = (function() {
659
- try {
660
- return JSON.parse(jqXHR.responseText);
661
- } catch(e) {}
662
- }());
663
-
664
- cb((responseJSON && responseJSON.error) || jqXHR.status || errorThrown.message, responseJSON, jqXHR);
665
- }
666
- });
667
- },
668
-
669
- convertUrlToEmbedTag : function (url) {
670
- // We didn't get something we expect so let's get out of here.
671
- if (!(new RegExp(['youtube', 'yout.be', 'vimeo', 'facebook', 'instagram'].join("|")).test(url))) return false;
672
-
673
- var embed_tag = url.replace(/\n?/g, '').replace(/^((http(s)?:\/\/)?(www\.)?(youtube\.com|youtu\.be)\/(watch\?v=|v\/)?)([a-zA-Z0-9\-_]+)(.*)?$/, '<div class="video"><iframe width="420" height="315" src="//www.youtube.com/embed/$7" frameborder="0" allowfullscreen></iframe></div>')
674
- .replace(/^http:\/\/vimeo\.com(\/.+)?\/([0-9]+)$/, '<iframe src="//player.vimeo.com/video/$2" width="500" height="281" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe>')
675
- //.replace(/^https:\/\/twitter\.com\/(\w+)\/status\/(\d+)\/?$/, '<blockquote class="twitter-tweet" align="center" lang="en"><a href="https://twitter.com/$1/statuses/$2"></a></blockquote><script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>')
676
- .replace(/^https:\/\/www\.facebook\.com\/(video.php|photo.php)\?v=(\d+).+$/, '<div class="fb-post" data-href="https://www.facebook.com/photo.php?v=$2"><div class="fb-xfbml-parse-ignore"><a href="https://www.facebook.com/photo.php?v=$2">Post</a></div></div>')
677
- .replace(/^http:\/\/instagram\.com\/p\/(.+)\/?$/, '<span class="instagram"><iframe src="//instagram.com/p/$1/embed/" width="612" height="710" frameborder="0" scrolling="no" allowtransparency="true"></iframe></span>');
678
-
679
-
680
- return (/<("[^"]*"|'[^']*'|[^'">])*>/).test(embed_tag) ? embed_tag : false;
681
- }
682
-
683
- });
684
-
685
- }(jQuery));
686
-
687
- (function ($) {
688
-
689
- $.fn.mediumInsert.registerAddon('images', {
690
-
691
- /**
692
- * Images default options
693
- */
694
-
695
- defaults: {
696
- /**
697
- * Active or inactive image's drag and drop
698
- */
699
- useDragAndDrop: true,
700
-
701
- /**
702
- * Relative path to a script that handles file uploads
703
- */
704
- imagesUploadScript: 'upload.php',
705
-
706
- /**
707
- * Relative path to a script that handles file deleting
708
- */
709
- imagesDeleteScript: 'delete.php',
710
-
711
- /**
712
- * Placeeholder text for inserting link
713
- */
714
- urlPlaceholder: 'Paste or type a link',
715
-
716
- /**
717
- * Format data before sending them to server while uploading an image
718
- *
719
- * @param {File} file File to upload
720
- * @return {object} formData FormData instance
721
- */
722
- formatData: function (file) {
723
- var formData = new FormData();
724
- formData.append('file', file);
725
- return formData;
726
- },
727
-
728
- /**
729
- * Upload single file
730
- *
731
- * @param {element} $placeholder Placeholder to add image to
732
- * @param {File} file File to upload
733
- * @param {object} that Context
734
- * @param {void}
735
- */
736
- uploadFile: function ($placeholder, file, that) {
737
- $.ajax({
738
- type: "post",
739
- url: that.options.imagesUploadScript,
740
- xhr: function () {
741
- var xhr = new XMLHttpRequest();
742
- xhr.upload.onprogress = that.updateProgressBar;
743
- return xhr;
744
- },
745
- cache: false,
746
- contentType: false,
747
- complete: function (jqxhr) {
748
- that.uploadCompleted(jqxhr, $placeholder);
749
- },
750
- processData: false,
751
- data: that.options.formatData(file)
752
- });
753
- },
754
-
755
- /**
756
- * Makes ajax call for deleting a file on a server
757
- *
758
- * @param {string} file File name
759
- * @param {object} that Context
760
- * @return {void}
761
- */
762
- deleteFile: function (file, that) {
763
- $.ajax({
764
- type: "post",
765
- url: that.options.imagesDeleteScript,
766
- data: {
767
- file: file
768
- }
769
- });
770
- }
771
- },
772
-
773
-
774
- /**
775
- * Images initial function
776
- *
777
- * @param {object} options Options to overide defaults
778
- * @return {void}
779
- */
780
-
781
- init: function (options) {
782
- if (options && options.$el) {
783
- this.$el = options.$el;
784
- }
785
- this.options = $.extend(this.defaults, options);
786
-
787
- this.setImageEvents();
788
-
789
- if (this.options.useDragAndDrop === true){
790
- this.setDragAndDropEvents();
791
- }
792
-
793
- this.preparePreviousImages();
794
-
795
- },
796
-
797
-
798
- /**
799
- * Returns insert button
800
- *
801
- * @param {string} buttonLabels
802
- * @return {string}
803
- */
804
-
805
- insertButton: function(buttonLabels){
806
- var label = 'Img';
807
- if (buttonLabels === 'fontawesome' || typeof buttonLabels === 'object' && !!(buttonLabels.fontawesome)) {
808
- label = '<i class="fa fa-picture-o"></i>';
809
- }
810
-
811
- if (typeof buttonLabels === 'object' && buttonLabels.img) {
812
- label = buttonLabels.img;
813
- }
814
-
815
- return '<button data-addon="images" data-action="add" class="medium-editor-action mediumInsert-action">'+label+'</button>';
816
- },
817
-
818
- /**
819
- * Make existing images interactive
820
- *
821
- * @return {void}
822
- */
823
-
824
- preparePreviousImages: function () {
825
- this.$el.find('.mediumInsert-images').each(function() {
826
- var $parent = $(this).parent();
827
- if (!$parent.hasClass('mediumInsert-placeholder')) {
828
- $parent.html($.fn.mediumInsert.insert.getButtons('images') +
829
- '<div class="mediumInsert-placeholder" draggable="true">' + $parent.html() + '</div>'
830
- );
831
- }
832
- });
833
- },
834
-
835
- /**
836
- * Add image to placeholder
837
- *
838
- * @param {element} $placeholder Placeholder to add image to
839
- * @return {element} $selectFile <input type="file"> element
840
- */
841
-
842
- add: function ($placeholder) {
843
- var that = this,
844
- $selectFile, files;
845
-
846
- $selectFile = $('<input type="file" multiple="multiple">').click();
847
- $selectFile.change(function () {
848
- files = this.files;
849
- that.uploadFiles($placeholder, files, that);
850
- });
851
-
852
- $.fn.mediumInsert.insert.deselect();
853
-
854
- return $selectFile;
855
- },
856
-
857
- /**
858
- * Update progressbar while upload
859
- *
860
- * @param {event} e XMLHttpRequest.upload.onprogress event
861
- * @return {void}
862
- */
863
-
864
- updateProgressBar: function (e) {
865
- var $progress = $('.progress:first', this.$el),
866
- complete;
867
-
868
- if (e.lengthComputable) {
869
- complete = e.loaded / e.total * 100;
870
- complete = complete ? complete : 0;
871
- $progress.attr('value', complete);
872
- $progress.html(complete);
873
- }
874
- },
875
-
876
- /**
877
- * Show uploaded image after upload completed
878
- *
879
- * @param {jqXHR} jqxhr jqXHR object
880
- * @return {void}
881
- */
882
-
883
- uploadCompleted: function (jqxhr, $placeholder) {
884
- var $progress = $('.progress:first', $placeholder),
885
- $img;
886
-
887
- $progress.attr('value', 100);
888
- $progress.html(100);
889
-
890
- if (jqxhr.responseText) {
891
- $progress.before('<figure class="mediumInsert-images"><img src="'+ jqxhr.responseText +'" draggable="true" alt=""></figure>');
892
- $img = $progress.siblings('img');
893
-
894
- $img.load(function () {
895
- $img.parent().mouseleave().mouseenter();
896
- });
897
- } else {
898
- $progress.before('<div class="mediumInsert-error">There was a problem uploading the file.</div>');
899
-
900
- setTimeout(function () {
901
- $('.mediumInsert-error:first', $placeholder).fadeOut(function () {
902
- $(this).remove();
903
- });
904
- }, 3000);
905
- }
906
-
907
- $progress.remove();
908
-
909
- $placeholder.closest('[data-medium-element]').trigger('keyup').trigger('input');
910
- },
911
-
912
- /**
913
- * Upload single file
914
- *
915
- * @param {element} $placeholder Placeholder to add image to
916
- * @param {File} file File to upload
917
- * @param {object} that Context
918
- * @param {void}
919
- */
920
-
921
- uploadFile: function ($placeholder, file, that) {
922
- return that.options.uploadFile($placeholder, file, that);
923
- },
924
-
925
- /**
926
- * Lopp though files, check file types and call uploadFile() function on each file that passes
927
- *
928
- * @param {element} placeholder Placeholder to add image to
929
- * @param {FileList} files Files to upload
930
- * @param {object} that Context
931
- * @return {void}
932
- */
933
-
934
- uploadFiles: function ($placeholder, files, that) {
935
- var acceptedTypes = {
936
- 'image/png': true,
937
- 'image/jpeg': true,
938
- 'image/gif': true
939
- };
940
-
941
- for (var i = 0; i < files.length; i++) {
942
- var file = files[i];
943
-
944
- if (acceptedTypes[file.type] === true) {
945
- $placeholder.append('<progress class="progress" min="0" max="100" value="0">0</progress>');
946
-
947
- that.uploadFile($placeholder, file, that);
948
- }
949
- }
950
- },
951
-
952
- /**
953
- * Makes ajax call for deleting a file on a server
954
- *
955
- * @param {string} file File name
956
- * @param {object} that Context
957
- * @return {void}
958
- */
959
-
960
- deleteFile: function (file, that) {
961
- return that.options.deleteFile(file, that);
962
- },
963
-
964
- /**
965
- * Set image events displaying remove and resize buttons
966
- *
967
- * @return {void}
968
- */
969
-
970
- setImageEvents: function () {
971
- var that = this;
972
-
973
- this.$el.on('mouseenter', '.mediumInsert-images', function () {
974
- var $img = $('img', this),
975
- positionTop,
976
- positionLeft;
977
-
978
- if ($.fn.mediumInsert.settings.enabled === false) {
979
- return;
980
- }
981
-
982
- if ($img.length > 0) {
983
- $(this).append('<a class="mediumInsert-imageIcon mediumInsert-imageRemove"></a>');
984
-
985
- if ($(this).prevAll().length === 0) {
986
- if ($(this).parent().parent().hasClass('small')) {
987
- $(this).append('<a class="mediumInsert-imageIcon mediumInsert-imageResizeBigger"></a>');
988
- } else {
989
- $(this).append('<a class="mediumInsert-imageIcon mediumInsert-imageResizeSmaller"></a>');
990
- }
991
- }
992
-
993
- if ($(this).siblings().length === 0) {
994
- if ($img.parent().is('a')) {
995
- $(this).append('<a class="mediumInsert-imageIcon mediumInsert-imageUnlink"></a>');
996
- } else {
997
- $(this).append('<a class="mediumInsert-imageIcon mediumInsert-imageLink"></a>');
998
- }
999
- }
1000
-
1001
- positionTop = $img.position().top + parseInt($img.css('margin-top'), 10);
1002
- positionLeft = $img.position().left + $img.width() -30;
1003
- $('.mediumInsert-imageRemove', this).css({
1004
- 'right': 'auto',
1005
- 'top': positionTop,
1006
- 'left': positionLeft
1007
- });
1008
- $('.mediumInsert-imageResizeBigger, .mediumInsert-imageResizeSmaller', this).css({
1009
- 'right': 'auto',
1010
- 'top': positionTop,
1011
- 'left': positionLeft-31
1012
- });
1013
- $('.mediumInsert-imageLink, .mediumInsert-imageUnlink', this).css({
1014
- 'right': 'auto',
1015
- 'top': positionTop,
1016
- 'left': positionLeft-62
1017
- });
1018
- }
1019
- });
1020
-
1021
- this.$el.on('mouseleave', '.mediumInsert-images', function () {
1022
- $('.mediumInsert-imageIcon', this).remove();
1023
- });
1024
-
1025
- this.$el.on('click', '.mediumInsert-imageResizeSmaller', function () {
1026
- $(this).parent().parent().parent().addClass('small');
1027
- $(this).parent().mouseleave().mouseleave();
1028
-
1029
- $.fn.mediumInsert.insert.deselect();
1030
- that.$el.trigger('keyup').trigger('input');
1031
- });
1032
-
1033
- this.$el.on('click', '.mediumInsert-imageResizeBigger', function () {
1034
- $(this).parent().parent().parent().removeClass('small');
1035
- $(this).parent().mouseleave().mouseleave();
1036
-
1037
- $.fn.mediumInsert.insert.deselect();
1038
- that.$el.trigger('keyup').trigger('input');
1039
- });
1040
-
1041
- this.$el.on('click', '.mediumInsert-imageRemove', function () {
1042
- var img = $(this).siblings('img').attr('src');
1043
-
1044
- if ($(this).parent().siblings().length === 0) {
1045
- $(this).parent().parent().parent().removeClass('small');
1046
- }
1047
- $(this).parent().remove();
1048
-
1049
- that.deleteFile(img, that);
1050
-
1051
- $.fn.mediumInsert.insert.deselect();
1052
-
1053
- that.$el.trigger('keyup').trigger('input');
1054
- });
1055
-
1056
- this.$el.on('click', '.mediumInsert-imageLink', function () {
1057
- var $placeholder = $(this).closest('.mediumInsert-placeholder'),
1058
- $formHtml = $('<div class="medium-editor-toolbar medium-editor-toolbar-active medium-editor-toolbar-form-anchor mediumInsert-imageLinkWire" style="display: block;"><input type="text" value="" placeholder="' + that.options.urlPlaceholder + '" class="mediumInsert-imageLinkText medium-editor-toolbar-anchor-input"></div>');
1059
-
1060
- $formHtml.appendTo($placeholder);
1061
- setTimeout(function () {
1062
- $formHtml.find('input').focus();
1063
- }, 50);
1064
-
1065
- $.fn.mediumInsert.insert.deselect();
1066
- });
1067
-
1068
- this.$el.on('click', '.mediumInsert-imageUnlink', function () {
1069
- var $figure = $(this).closest('.mediumInsert-images');
1070
-
1071
- $figure.find('img').unwrap();
1072
-
1073
- $(this).removeClass('mediumInsert-imageUnlink')
1074
- .addClass('mediumInsert-imageLink');
1075
-
1076
- that.$el.trigger('keyup').trigger('input');
1077
- });
1078
-
1079
- this.$el
1080
- .on('keypress', '.mediumInsert-imageLinkText', function (e) {
1081
- var $placeholder = $(this).closest('.mediumInsert-placeholder');
1082
-
1083
- if ((e.which && e.which === 13) || (e.keyCode && e.keyCode === 13)) {
1084
- $placeholder.find('.mediumInsert-images:first').find('img').wrap('<a href="'+ $(this).val() +'" target="_blank"></a>');
1085
- $placeholder.find('.mediumInsert-imageLink')
1086
- .removeClass('mediumInsert-imageLink')
1087
- .addClass('mediumInsert-imageUnlink');
1088
-
1089
- // Workaround for "Uncaught NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is no longer a child of this node. Perhaps it was moved in a 'blur' event handler?"
1090
- try {
1091
- $('.mediumInsert-imageLinkWire').remove();
1092
- } catch(err) {}
1093
-
1094
- that.$el.trigger('keyup').trigger('input');
1095
- }
1096
- })
1097
- .on('blur', '.mediumInsert-imageLinkText', function () {
1098
- $('.mediumInsert-imageLinkWire').remove();
1099
- })
1100
- .on('paste', '.mediumInsert-imageLinkText', function (e) {
1101
- if ($.fn.mediumInsert.insert.isFirefox && e.originalEvent.clipboardData) {
1102
- $(this).val(e.originalEvent.clipboardData.getData('text/plain'));
1103
- }
1104
- });
1105
- },
1106
-
1107
- /**
1108
- * Set drag and drop events
1109
- *
1110
- * @return {void}
1111
- */
1112
-
1113
- setDragAndDropEvents: function () {
1114
- var that = this,
1115
- dropSuccessful = false,
1116
- dropSort = false,
1117
- dropSortIndex, dropSortParent;
1118
-
1119
- $(document).on('dragover', 'body', function () {
1120
- if ($.fn.mediumInsert.settings.enabled === false) {
1121
- return;
1122
- }
1123
-
1124
- that.$el.addClass('hover');
1125
- });
1126
-
1127
- $(document).on('dragend', 'body', function () {
1128
- if ($.fn.mediumInsert.settings.enabled === false) {
1129
- return;
1130
- }
1131
-
1132
- that.$el.removeClass('hover');
1133
- });
1134
-
1135
- this.$el.on('dragover', '.mediumInsert', function () {
1136
- if ($.fn.mediumInsert.settings.enabled === false) {
1137
- return;
1138
- }
1139
-
1140
- $(this).addClass('hover');
1141
- $(this).attr('contenteditable', true);
1142
- });
1143
-
1144
- this.$el.on('dragleave', '.mediumInsert', function () {
1145
- if ($.fn.mediumInsert.settings.enabled === false) {
1146
- return;
1147
- }
1148
-
1149
- $(this).removeClass('hover');
1150
- $(this).attr('contenteditable', false);
1151
- });
1152
-
1153
- this.$el.on('dragstart', '.mediumInsert .mediumInsert-images img', function () {
1154
- if ($.fn.mediumInsert.settings.enabled === false) {
1155
- return;
1156
- }
1157
-
1158
- dropSortIndex = $(this).parent().index();
1159
- dropSortParent = $(this).parent().parent().parent().attr('id');
1160
- });
1161
-
1162
- this.$el.on('dragend', '.mediumInsert .mediumInsert-images img', function (e) {
1163
- if ($.fn.mediumInsert.settings.enabled === false) {
1164
- return;
1165
- }
1166
-
1167
- if (dropSuccessful === true) {
1168
- if ($(e.originalEvent.target.parentNode).siblings().length === 0) {
1169
- $(e.originalEvent.target.parentNode).parent().parent().removeClass('small');
1170
- }
1171
- $(e.originalEvent.target.parentNode).mouseleave();
1172
- $(e.originalEvent.target.parentNode).remove();
1173
- dropSuccessful = false;
1174
- dropSort = false;
1175
-
1176
- that.$el.trigger('keyup').trigger('input');
1177
- }
1178
- });
1179
-
1180
- this.$el.on('dragover', '.mediumInsert .mediumInsert-images img', function (e) {
1181
- if ($.fn.mediumInsert.settings.enabled === false) {
1182
- return;
1183
- }
1184
-
1185
- e.preventDefault();
1186
- });
1187
-
1188
- this.$el.on('drop', '.mediumInsert .mediumInsert-images img', function () {
1189
- var index, $dragged, finalIndex;
1190
-
1191
- if ($.fn.mediumInsert.settings.enabled === false) {
1192
- return;
1193
- }
1194
-
1195
-
1196
- if (dropSortParent !== $(this).parent().parent().parent().attr('id')) {
1197
- dropSort = false;
1198
- dropSortIndex = dropSortParent = null;
1199
- return;
1200
- }
1201
-
1202
- index = parseInt(dropSortIndex, 10);
1203
-
1204
- // Sort
1205
- $dragged = $(this).parent().parent().find('.mediumInsert-images:nth-child('+ (index+1) +')');
1206
- finalIndex = $(this).parent().index();
1207
- if(index < finalIndex) {
1208
- $dragged.insertAfter($(this).parent());
1209
- } else if(index > finalIndex) {
1210
- $dragged.insertBefore($(this).parent());
1211
- }
1212
-
1213
- $dragged.mouseleave();
1214
-
1215
- dropSort = true;
1216
- dropSortIndex = null;
1217
-
1218
- that.$el.trigger('keyup').trigger('input');
1219
- });
1220
-
1221
- this.$el.on('drop', '.mediumInsert', function (e) {
1222
- var files;
1223
-
1224
- e.preventDefault();
1225
-
1226
- if ($.fn.mediumInsert.settings.enabled === false) {
1227
- return;
1228
- }
1229
-
1230
- $(this).removeClass('hover');
1231
- that.$el.removeClass('hover');
1232
- $(this).attr('contenteditable', false);
1233
-
1234
- files = e.originalEvent.dataTransfer.files;
1235
- if (files.length > 0) {
1236
- // File upload
1237
- that.uploadFiles($('.mediumInsert-placeholder', this), files, that);
1238
- } else if (dropSort === true) {
1239
- dropSort = false;
1240
- } else {
1241
- // Image move from block to block
1242
- $('.mediumInsert-placeholder', this).append('<figure class="mediumInsert-images">'+ e.originalEvent.dataTransfer.getData('text/html') +'</figure>');
1243
- $('meta', this).remove();
1244
- dropSuccessful = true;
1245
- }
1246
- });
1247
- }
1248
- });
1249
- }(jQuery));
1250
-
1251
- (function ($) {
1252
-
1253
- $.fn.mediumInsert.registerAddon('maps', {
1254
-
1255
- /**
1256
- * Maps initial function
1257
- * @return {void}
1258
- */
1259
-
1260
- init: function () {
1261
- this.$el = $.fn.mediumInsert.insert.$el;
1262
- },
1263
-
1264
- insertButton: function(buttonLabels){
1265
- var label = 'Map';
1266
- if (buttonLabels === 'fontawesome' || typeof buttonLabels === 'object' && !!(buttonLabels.fontawesome)) {
1267
- label = '<i class="fa fa-map-marker"></i>';
1268
- }
1269
-
1270
- if (typeof buttonLabels === 'object' && buttonLabels.map) {
1271
- label = buttonLabels.map;
1272
- }
1273
-
1274
- return '<button data-addon="maps" data-action="add" class="medium-editor-action mediumInsert-action">'+label+'</button>';
1275
- },
1276
-
1277
- /**
1278
- * Add map to placeholder
1279
- * @param {element} placeholder Placeholder to add map to
1280
- * @return {void}
1281
- */
1282
-
1283
- add: function (placeholder) {
1284
- $.fn.mediumInsert.insert.deselect();
1285
-
1286
- placeholder.append('<div class="mediumInsert-maps">Map - Coming soon...</div>');
1287
- }
1288
-
1289
- });
1290
-
1291
- }(jQuery));
1292
-
1293
- (function ($) {
1294
-
1295
- $.fn.mediumInsert.registerAddon('tables', {
1296
-
1297
- /**
1298
- * Table default options
1299
- */
1300
-
1301
- defaults: {
1302
- defaultRows: 2,
1303
- defaultCols: 2
1304
- },
1305
-
1306
- /**
1307
- * Tables initial function
1308
- * @return {void}
1309
- */
1310
- init : function (options) {
1311
- this.options = $.extend(this.defaults, options);
1312
- this.$el = $.fn.mediumInsert.insert.$el;
1313
- this.setTableButtonEvents();
1314
- },
1315
-
1316
- insertButton : function (buttonLabels) {
1317
- var label = 'Table';
1318
- if (buttonLabels === 'fontawesome' || typeof buttonLabels === 'object' && !!(buttonLabels.fontawesome)) {
1319
- label = '<i class="fa fa-table"></i>';
1320
- }
1321
-
1322
- if (typeof buttonLabels === 'object' && buttonLabels.table) {
1323
- label = buttonLabels.table;
1324
- }
1325
-
1326
- return '<button data-addon="tables" data-action="add" class="medium-editor-action mediumInsert-action">' + label + '</button>';
1327
- },
1328
-
1329
- /**
1330
- * Add table to $placeholder
1331
- * @param {element} $placeholder $placeholder to add embed to
1332
- * @return {void}
1333
- */
1334
- add : function ($placeholder) {
1335
- $.fn.mediumInsert.insert.deselect();
1336
-
1337
- var formHtml = '<div class="medium-editor-toolbar-form-anchor mediumInsert-tableDemoBox"><table><tr><td></td><td><label>cols:<input type="text" value="' + this.options.defaultCols + '" class="mediumInsert-tableCols" /></label></td></tr><tr><td><label>rows:<input type="text" value="' + this.options.defaultRows + '" class="mediumInsert-tableRows" /></label></td><td><table class="mediumInsert-demoTable"></table></td></tr><tr><td></td><td><label><button class="mediumInsert-tableReadyButton">insert</button></label></td></tr></table></</div>';
1338
- $(formHtml).appendTo($placeholder.prev());
1339
- this.updateDemoTable();
1340
-
1341
- setTimeout(function () {
1342
- $placeholder.prev().find('input').focus();
1343
- }, 50);
1344
-
1345
- $.fn.mediumInsert.insert.deselect();
1346
- this.currentPlaceholder = $placeholder;
1347
- },
1348
-
1349
- setTableButtonEvents : function () {
1350
- var that = this;
1351
-
1352
- $(document).on('keyup',
1353
- 'input.mediumInsert-tableRows, input.mediumInsert-tableCols',
1354
- function() { that.updateDemoTable(); });
1355
-
1356
- $(document).on('click', function(e) {
1357
- if ($(e.target).parents('.mediumInsert-buttons').length === 0) {
1358
- that.removeToolbar();
1359
- }
1360
- });
1361
-
1362
- $(document).on('click', 'button.mediumInsert-tableReadyButton', function() {
1363
- that.setEnterActionEvents();
1364
- that.removeToolbar();
1365
- });
1366
- },
1367
-
1368
- getDimensions : function () {
1369
- return {
1370
- rows: parseFloat($('input.mediumInsert-tableRows').val()) || 1,
1371
- cols: parseFloat($('input.mediumInsert-tableCols').val()) || 1
1372
- };
1373
- },
1374
-
1375
- buildTable : function (table) {
1376
- var i, j, $row,
1377
- dimensions = this.getDimensions(),
1378
- $table = $(table);
1379
-
1380
- for (i = 0; i < dimensions.rows; i++) {
1381
- $row = $('<tr>');
1382
- for (j = 0; j < dimensions.cols; j++) {
1383
- $row.append('<td>');
1384
- }
1385
- $table.append($row);
1386
- }
1387
- },
1388
-
1389
- updateDemoTable : function () {
1390
- var $demoTable = $('table.mediumInsert-demoTable');
1391
-
1392
- $demoTable.empty();
1393
- this.buildTable($demoTable);
1394
- },
1395
-
1396
- setEnterActionEvents : function () {
1397
- var that = this;
1398
- if ($.fn.mediumInsert.settings.enabled === false) {
1399
- return false;
1400
- }
1401
-
1402
- var $table = $('<table class="mediumInsert-table">');
1403
- that.buildTable($table);
1404
-
1405
- that.currentPlaceholder.append($table);
1406
- that.currentPlaceholder.closest('[data-medium-element]').trigger('keyup').trigger('input');
1407
- },
1408
-
1409
- removeToolbar : function () {
1410
- $(".mediumInsert-tableDemoBox").remove();
1411
- }
1412
-
1413
- });
1414
-
1415
- }(jQuery));