summernote-ext-attach.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. (function (factory) {
  2. /* global define */
  3. if (typeof define === 'function' && define.amd) {
  4. // AMD. Register as an anonymous module.
  5. define(['jquery'], factory);
  6. } else if (typeof module === 'object' && module.exports) {
  7. // Node/CommonJS
  8. module.exports = factory(require('jquery'));
  9. } else {
  10. // Browser globals
  11. factory(window.jQuery);
  12. }
  13. }(function ($) {
  14. // Extends plugins for adding hello.
  15. // - plugin is external module for customizing.
  16. $.extend($.summernote.plugins, {
  17. /**
  18. * @param {Object} context - context object has status of editor.
  19. */
  20. 'attachment': function (context) {
  21. var self = this;
  22. // ui has renders to build ui elements.
  23. // - you can create a button with `ui.button`
  24. var ui = $.summernote.ui;
  25. var $editor = context.layoutInfo.editor;
  26. var options = context.options;
  27. var lang = options.langInfo;
  28. // add hello button
  29. context.memo('button.attachment', function () {
  30. // create button
  31. var button = ui.button({
  32. contents: '<i class="fa fa-paperclip" aria-hidden="true"></i>',
  33. tooltip: '上传附件',
  34. click:function(){
  35. self.show();
  36. }
  37. });
  38. // create jQuery object from button instance.
  39. var $hello = button.render();
  40. return $hello;
  41. });
  42. // This events will be attached when editor is initialized.
  43. this.events = {
  44. // This will be called after modules are initialized.
  45. 'summernote.init': function (we, e) {
  46. console.log('summernote initialized', we, e);
  47. },
  48. // This will be called when user releases a key on editable.
  49. 'summernote.keyup': function (we, e) {
  50. console.log('summernote keyup', we, e);
  51. }
  52. };
  53. // This method will be called when editor is initialized by $('..').summernote();
  54. // You can create elements for plugin
  55. this.initialize = function () {
  56. var $container = options.dialogsInBody ? $(document.body) : $editor;
  57. var attachmentLimitation = '';
  58. if (options.maximumattachmentFileSize) {
  59. var unit = Math.floor(Math.log(options.maximumattachmentFileSize) / Math.log(1024));
  60. var readableSize = (options.maximumattachmentFileSize / Math.pow(1024, unit)).toFixed(2) * 1 +
  61. ' ' + ' KMGTP'[unit] + 'B';
  62. attachmentLimitation = '<small>' + lang.attachment.maximumFileSize + ' : ' + readableSize + '</small>';
  63. }
  64. var body = '<div class="form-group note-group-select-from-files">' +
  65. '<label>' + lang.image.selectFromFiles + '</label>' +
  66. '<input class="note-attachment-input form-control" type="file" name="files" accept="application/zip,application/x-gzip,application/pdf,application/msword,application/ocelet-stream,application/x-tar,video/mp4" />' +
  67. attachmentLimitation +
  68. '</div>';
  69. var footer = '<button href="#" class="btn btn-primary note-attachment-btn">确认</button>';
  70. self.$dialog = ui.dialog({
  71. title: '插入附件',
  72. fade: options.dialogsFade,
  73. body: body,
  74. footer: footer
  75. }).render().appendTo($container);
  76. };
  77. self.show = function () {
  78. context.invoke('editor.saveRange');
  79. self.showAttachDialog().then(function (data) {
  80. // [workaround] hide dialog before restore range for IE range focus
  81. ui.hideDialog(self.$dialog);
  82. context.invoke('editor.restoreRange');
  83. if (typeof data === 'string') { // image url
  84. console.log('string:'+data);
  85. //context.invoke('editor.insertAttachment', data);
  86. } else { // array of files
  87. var linkData = {isNewWindow:true};
  88. var forData = new FormData();
  89. console.log(data[0]);
  90. forData.append("file", data[0]);
  91. $.ajax({
  92. data: forData,
  93. type: "POST",
  94. dataType : 'json',
  95. url: "/attach/upload",
  96. cache: false,
  97. contentType: false,
  98. processData: false,
  99. success: function(result) {
  100. if( result.code!=0 ){
  101. alert('上传失败:'+result.message);
  102. return false;
  103. }
  104. linkData.text = result.message.name;
  105. linkData.url = result.message.url;
  106. context.invoke('editor.createLink',linkData);
  107. },
  108. error:function(){
  109. alert('文件上传失败!');
  110. }
  111. });
  112. console.log('upload:'+data);
  113. //context.invoke('editor.insertAttachmentOrCallback', data);
  114. }
  115. }).fail(function () {
  116. context.invoke('editor.restoreRange');
  117. });
  118. };
  119. self.showAttachDialog = function () {
  120. return $.Deferred(function (deferred) {
  121. var $attachmentInput = self.$dialog.find('.note-attachment-input'),
  122. $attachmentUrl = self.$dialog.find('.note-attachment-url'),
  123. $attachmentBtn = self.$dialog.find('.note-attachment-btn');
  124. ui.onDialogShown(self.$dialog, function () {
  125. context.triggerEvent('dialog.shown');
  126. // Cloning attachmentInput to clear element.
  127. $attachmentInput.replaceWith($attachmentInput.clone()
  128. .on('change', function () {
  129. deferred.resolve(this.files || this.value);
  130. })
  131. .val('')
  132. );
  133. $attachmentBtn.click(function (event) {
  134. event.preventDefault();
  135. deferred.resolve($attachmentUrl.val());
  136. });
  137. $attachmentUrl.on('keyup paste', function () {
  138. var url = $attachmentUrl.val();
  139. ui.toggleBtn($attachmentBtn, url);
  140. }).val('').trigger('focus');
  141. self.bindEnterKey($attachmentUrl, $attachmentBtn);
  142. });
  143. ui.onDialogHidden(self.$dialog, function () {
  144. $attachmentInput.off('change');
  145. $attachmentUrl.off('keyup paste keypress');
  146. $attachmentBtn.off('click');
  147. if (deferred.state() === 'pending') {
  148. deferred.reject();
  149. }
  150. });
  151. ui.showDialog(self.$dialog);
  152. });
  153. };
  154. /**
  155. * insert image
  156. *
  157. * @param {String} src
  158. * @param {String|Function} param
  159. * @return {Promise}
  160. */
  161. this.insertAttach = function (src, param) {
  162. return async.createImage(src, param).then(function ($image) {
  163. beforeCommand();
  164. if (typeof param === 'function') {
  165. param($image);
  166. } else {
  167. if (typeof param === 'string') {
  168. $image.attr('data-filename', param);
  169. }
  170. $image.css('width', Math.min($editable.width(), $image.width()));
  171. }
  172. $image.show();
  173. range.create(editable).insertNode($image[0]);
  174. range.createFromNodeAfter($image[0]).select();
  175. afterCommand();
  176. }).fail(function (e) {
  177. context.triggerEvent('image.upload.error', e);
  178. });
  179. };
  180. /**
  181. * insertImages
  182. * @param {File[]} files
  183. */
  184. this.insertAttaches = function (files) {
  185. $.each(files, function (idx, file) {
  186. var filename = file.name;
  187. if (options.maximumImageFileSize && options.maximumImageFileSize < file.size) {
  188. context.triggerEvent('attach.upload.error', lang.image.maximumFileSizeError);
  189. } else {
  190. async.readFileAsDataURL(file).then(function (dataURL) {
  191. return self.insertAttach(dataURL, filename);
  192. }).fail(function () {
  193. context.triggerEvent('image.upload.error');
  194. });
  195. }
  196. });
  197. };
  198. /**
  199. * insertImagesOrCallback
  200. * @param {File[]} files
  201. */
  202. this.insertAttachesOrCallback = function (files) {
  203. var callbacks = options.callbacks;
  204. // If onImageUpload options setted
  205. if (callbacks.onImageUpload) {
  206. context.triggerEvent('attach.upload', files);
  207. // else insert Image as dataURL
  208. }else{
  209. console.log('upload error');
  210. }
  211. };
  212. // This methods will be called when editor is destroyed by $('..').summernote('destroy');
  213. // You should remove elements on `initialize`.
  214. this.destroy = function () {
  215. this.$panel.remove();
  216. this.$panel = null;
  217. };
  218. this.bindEnterKey = function ($input, $btn) {
  219. $input.on('keypress', function (event) {
  220. if (event.keyCode === 13) {
  221. $btn.trigger('click');
  222. }
  223. });
  224. };
  225. }
  226. });
  227. }));