diff --git a/static/js/inline-attachment.js b/static/js/inline-attachment.js
new file mode 100644
index 0000000..39154c9
--- /dev/null
+++ b/static/js/inline-attachment.js
@@ -0,0 +1,449 @@
+/*! inline-attachment - v2.0.3 - 2016-08-20 */
+/*jslint newcap: true */
+/*global XMLHttpRequest: false, FormData: false */
+/*
+ * Inline Text Attachment
+ *
+ * Author: Roy van Kaathoven
+ * Contact: ik@royvankaathoven.nl
+ */
+(function(document, window) {
+ 'use strict';
+
+ var inlineAttachment = function(options, instance) {
+ this.settings = inlineAttachment.util.merge(options, inlineAttachment.defaults);
+ this.editor = instance;
+ this.filenameTag = '{filename}';
+ this.lastValue = null;
+ };
+
+ /**
+ * Will holds the available editors
+ *
+ * @type {Object}
+ */
+ inlineAttachment.editors = {};
+
+ /**
+ * Utility functions
+ */
+ inlineAttachment.util = {
+
+ /**
+ * Simple function to merge the given objects
+ *
+ * @param {Object[]} object Multiple object parameters
+ * @returns {Object}
+ */
+ merge: function() {
+ var result = {};
+ for (var i = arguments.length - 1; i >= 0; i--) {
+ var obj = arguments[i];
+ for (var k in obj) {
+ if (obj.hasOwnProperty(k)) {
+ result[k] = obj[k];
+ }
+ }
+ }
+ return result;
+ },
+
+ /**
+ * Append a line of text at the bottom, ensuring there aren't unnecessary newlines
+ *
+ * @param {String} appended Current content
+ * @param {String} previous Value which should be appended after the current content
+ */
+ appendInItsOwnLine: function(previous, appended) {
+ return (previous + "\n\n[[D]]" + appended)
+ .replace(/(\n{2,})\[\[D\]\]/, "\n\n")
+ .replace(/^(\n*)/, "");
+ },
+
+ /**
+ * Inserts the given value at the current cursor position of the textarea element
+ *
+ * @param {HtmlElement} el
+ * @param {String} value Text which will be inserted at the cursor position
+ */
+ insertTextAtCursor: function(el, text) {
+ var scrollPos = el.scrollTop,
+ strPos = 0,
+ browser = false,
+ range;
+
+ if ((el.selectionStart || el.selectionStart === '0')) {
+ browser = "ff";
+ } else if (document.selection) {
+ browser = "ie";
+ }
+
+ if (browser === "ie") {
+ el.focus();
+ range = document.selection.createRange();
+ range.moveStart('character', -el.value.length);
+ strPos = range.text.length;
+ } else if (browser === "ff") {
+ strPos = el.selectionStart;
+ }
+
+ var front = (el.value).substring(0, strPos);
+ var back = (el.value).substring(strPos, el.value.length);
+ el.value = front + text + back;
+ strPos = strPos + text.length;
+ if (browser === "ie") {
+ el.focus();
+ range = document.selection.createRange();
+ range.moveStart('character', -el.value.length);
+ range.moveStart('character', strPos);
+ range.moveEnd('character', 0);
+ range.select();
+ } else if (browser === "ff") {
+ el.selectionStart = strPos;
+ el.selectionEnd = strPos;
+ el.focus();
+ }
+ el.scrollTop = scrollPos;
+ }
+ };
+
+ /**
+ * Default configuration options
+ *
+ * @type {Object}
+ */
+ inlineAttachment.defaults = {
+ /**
+ * URL where the file will be send
+ */
+ uploadUrl: 'upload_attachment.php',
+
+ /**
+ * Which method will be used to send the file to the upload URL
+ */
+ uploadMethod: 'POST',
+
+ /**
+ * Name in which the file will be placed
+ */
+ uploadFieldName: 'file',
+
+ /**
+ * Extension which will be used when a file extension could not
+ * be detected
+ */
+ defaultExtension: 'png',
+
+ /**
+ * JSON field which refers to the uploaded file URL
+ */
+ jsonFieldName: 'filename',
+
+ /**
+ * Allowed MIME types
+ */
+ allowedTypes: [
+ 'image/jpeg',
+ 'image/png',
+ 'image/jpg',
+ 'image/gif'
+ ],
+
+ /**
+ * Text which will be inserted when dropping or pasting a file.
+ * Acts as a placeholder which will be replaced when the file is done with uploading
+ */
+ progressText: '![Uploading file...]()',
+
+ /**
+ * When a file has successfully been uploaded the progressText
+ * will be replaced by the urlText, the {filename} tag will be replaced
+ * by the filename that has been returned by the server
+ */
+ urlText: "![file]({filename})",
+
+ /**
+ * Text which will be used when uploading has failed
+ */
+ errorText: "Error uploading file",
+
+ /**
+ * Extra parameters which will be send when uploading a file
+ */
+ extraParams: {},
+
+ /**
+ * Extra headers which will be send when uploading a file
+ */
+ extraHeaders: {},
+
+ /**
+ * Before the file is send
+ */
+ beforeFileUpload: function() {
+ return true;
+ },
+
+ /**
+ * Triggers when a file is dropped or pasted
+ */
+ onFileReceived: function() {},
+
+ /**
+ * Custom upload handler
+ *
+ * @return {Boolean} when false is returned it will prevent default upload behavior
+ */
+ onFileUploadResponse: function() {
+ return true;
+ },
+
+ /**
+ * Custom error handler. Runs after removing the placeholder text and before the alert().
+ * Return false from this function to prevent the alert dialog.
+ *
+ * @return {Boolean} when false is returned it will prevent default error behavior
+ */
+ onFileUploadError: function() {
+ return true;
+ },
+
+ /**
+ * When a file has succesfully been uploaded
+ */
+ onFileUploaded: function() {}
+ };
+
+ /**
+ * Uploads the blob
+ *
+ * @param {Blob} file blob data received from event.dataTransfer object
+ * @return {XMLHttpRequest} request object which sends the file
+ */
+ inlineAttachment.prototype.uploadFile = function(file) {
+ var me = this,
+ formData = new FormData(),
+ xhr = new XMLHttpRequest(),
+ settings = this.settings,
+ extension = settings.defaultExtension || settings.defualtExtension;
+
+ if (typeof settings.setupFormData === 'function') {
+ settings.setupFormData(formData, file);
+ }
+
+ // Attach the file. If coming from clipboard, add a default filename (only works in Chrome for now)
+ // http://stackoverflow.com/questions/6664967/how-to-give-a-blob-uploaded-as-formdata-a-file-name
+ if (file.name) {
+ var fileNameMatches = file.name.match(/\.(.+)$/);
+ if (fileNameMatches) {
+ extension = fileNameMatches[1];
+ }
+ }
+
+ var remoteFilename = "image-" + Date.now() + "." + extension;
+ if (typeof settings.remoteFilename === 'function') {
+ remoteFilename = settings.remoteFilename(file);
+ }
+
+ formData.append(settings.uploadFieldName, file, remoteFilename);
+
+ // Append the extra parameters to the formdata
+ if (typeof settings.extraParams === "object") {
+ for (var key in settings.extraParams) {
+ if (settings.extraParams.hasOwnProperty(key)) {
+ formData.append(key, settings.extraParams[key]);
+ }
+ }
+ }
+
+ xhr.open('POST', settings.uploadUrl);
+
+ // Add any available extra headers
+ if (typeof settings.extraHeaders === "object") {
+ for (var header in settings.extraHeaders) {
+ if (settings.extraHeaders.hasOwnProperty(header)) {
+ xhr.setRequestHeader(header, settings.extraHeaders[header]);
+ }
+ }
+ }
+
+ xhr.onload = function() {
+ // If HTTP status is OK or Created
+ if (xhr.status === 200 || xhr.status === 201) {
+ me.onFileUploadResponse(xhr);
+ } else {
+ me.onFileUploadError(xhr);
+ }
+ };
+ if (settings.beforeFileUpload(xhr) !== false) {
+ xhr.send(formData);
+ }
+ return xhr;
+ };
+
+ /**
+ * Returns if the given file is allowed to handle
+ *
+ * @param {File} clipboard data file
+ */
+ inlineAttachment.prototype.isFileAllowed = function(file) {
+ if (file.kind === 'string') { return false; }
+ if (this.settings.allowedTypes.indexOf('*') === 0){
+ return true;
+ } else {
+ return this.settings.allowedTypes.indexOf(file.type) >= 0;
+ }
+ };
+
+ /**
+ * Handles upload response
+ *
+ * @param {XMLHttpRequest} xhr
+ * @return {Void}
+ */
+ inlineAttachment.prototype.onFileUploadResponse = function(xhr) {
+ if (this.settings.onFileUploadResponse.call(this, xhr) !== false) {
+ var result = JSON.parse(xhr.responseText),
+ filename = result[this.settings.jsonFieldName];
+
+ if (result && filename) {
+ var newValue;
+ if (typeof this.settings.urlText === 'function') {
+ newValue = this.settings.urlText.call(this, filename, result);
+ } else {
+ newValue = this.settings.urlText.replace(this.filenameTag, filename);
+ }
+ var text = this.editor.getValue().replace(this.lastValue, newValue);
+ this.editor.setValue(text);
+ this.settings.onFileUploaded.call(this, filename);
+ }
+ }
+ };
+
+
+ /**
+ * Called when a file has failed to upload
+ *
+ * @param {XMLHttpRequest} xhr
+ * @return {Void}
+ */
+ inlineAttachment.prototype.onFileUploadError = function(xhr) {
+ if (this.settings.onFileUploadError.call(this, xhr) !== false) {
+ var text = this.editor.getValue().replace(this.lastValue, "");
+ this.editor.setValue(text);
+ }
+ };
+
+ /**
+ * Called when a file has been inserted, either by drop or paste
+ *
+ * @param {File} file
+ * @return {Void}
+ */
+ inlineAttachment.prototype.onFileInserted = function(file) {
+ if (this.settings.onFileReceived.call(this, file) !== false) {
+ this.lastValue = this.settings.progressText;
+ this.editor.insertValue(this.lastValue);
+ }
+ };
+
+
+ /**
+ * Called when a paste event occured
+ * @param {Event} e
+ * @return {Boolean} if the event was handled
+ */
+ inlineAttachment.prototype.onPaste = function(e) {
+ var result = false,
+ clipboardData = e.clipboardData,
+ items;
+
+ if (typeof clipboardData === "object") {
+ items = clipboardData.items || clipboardData.files || [];
+
+ for (var i = 0; i < items.length; i++) {
+ var item = items[i];
+ if (this.isFileAllowed(item)) {
+ result = true;
+ this.onFileInserted(item.getAsFile());
+ this.uploadFile(item.getAsFile());
+ }
+ }
+ }
+
+ if (result) { e.preventDefault(); }
+
+ return result;
+ };
+
+ /**
+ * Called when a drop event occures
+ * @param {Event} e
+ * @return {Boolean} if the event was handled
+ */
+ inlineAttachment.prototype.onDrop = function(e) {
+ var result = false;
+ for (var i = 0; i < e.dataTransfer.files.length; i++) {
+ var file = e.dataTransfer.files[i];
+ if (this.isFileAllowed(file)) {
+ result = true;
+ this.onFileInserted(file);
+ this.uploadFile(file);
+ }
+ }
+
+ return result;
+ };
+
+ window.inlineAttachment = inlineAttachment;
+
+})(document, window);
+
+/*jslint newcap: true */
+/*global inlineAttachment: false */
+(function() {
+ 'use strict';
+
+ inlineAttachment.editors.input = {
+ Editor: function(instance) {
+
+ var input = instance;
+
+ return {
+ getValue: function() {
+ return input.value;
+ },
+ insertValue: function(val) {
+ inlineAttachment.util.insertTextAtCursor(input, val);
+ },
+ setValue: function(val) {
+ input.value = val;
+ }
+ };
+ },
+ attachToInput: function(input, options) {
+ options = options || {};
+
+ var editor = new inlineAttachment.editors.input.Editor(input),
+ inlineattach = new inlineAttachment(options, editor);
+
+ input.addEventListener('paste', function(e) {
+ inlineattach.onPaste(e);
+ }, false);
+ input.addEventListener('drop', function(e) {
+ e.stopPropagation();
+ e.preventDefault();
+ inlineattach.onDrop(e);
+ }, false);
+ input.addEventListener('dragenter', function(e) {
+ e.stopPropagation();
+ e.preventDefault();
+ }, false);
+ input.addEventListener('dragover', function(e) {
+ e.stopPropagation();
+ e.preventDefault();
+ }, false);
+ }
+ };
+
+})();
\ No newline at end of file
diff --git a/static/js/jquery.inline-attachment.js b/static/js/jquery.inline-attachment.js
new file mode 100644
index 0000000..73ee1a9
--- /dev/null
+++ b/static/js/jquery.inline-attachment.js
@@ -0,0 +1,467 @@
+/*! inline-attachment - v2.0.3 - 2016-08-20 */
+/*jslint newcap: true */
+/*global XMLHttpRequest: false, FormData: false */
+/*
+ * Inline Text Attachment
+ *
+ * Author: Roy van Kaathoven
+ * Contact: ik@royvankaathoven.nl
+ */
+(function(document, window) {
+ 'use strict';
+
+ var inlineAttachment = function(options, instance) {
+ this.settings = inlineAttachment.util.merge(options, inlineAttachment.defaults);
+ this.editor = instance;
+ this.filenameTag = '{filename}';
+ this.lastValue = null;
+ };
+
+ /**
+ * Will holds the available editors
+ *
+ * @type {Object}
+ */
+ inlineAttachment.editors = {};
+
+ /**
+ * Utility functions
+ */
+ inlineAttachment.util = {
+
+ /**
+ * Simple function to merge the given objects
+ *
+ * @param {Object[]} object Multiple object parameters
+ * @returns {Object}
+ */
+ merge: function() {
+ var result = {};
+ for (var i = arguments.length - 1; i >= 0; i--) {
+ var obj = arguments[i];
+ for (var k in obj) {
+ if (obj.hasOwnProperty(k)) {
+ result[k] = obj[k];
+ }
+ }
+ }
+ return result;
+ },
+
+ /**
+ * Append a line of text at the bottom, ensuring there aren't unnecessary newlines
+ *
+ * @param {String} appended Current content
+ * @param {String} previous Value which should be appended after the current content
+ */
+ appendInItsOwnLine: function(previous, appended) {
+ return (previous + "\n\n[[D]]" + appended)
+ .replace(/(\n{2,})\[\[D\]\]/, "\n\n")
+ .replace(/^(\n*)/, "");
+ },
+
+ /**
+ * Inserts the given value at the current cursor position of the textarea element
+ *
+ * @param {HtmlElement} el
+ * @param {String} value Text which will be inserted at the cursor position
+ */
+ insertTextAtCursor: function(el, text) {
+ var scrollPos = el.scrollTop,
+ strPos = 0,
+ browser = false,
+ range;
+
+ if ((el.selectionStart || el.selectionStart === '0')) {
+ browser = "ff";
+ } else if (document.selection) {
+ browser = "ie";
+ }
+
+ if (browser === "ie") {
+ el.focus();
+ range = document.selection.createRange();
+ range.moveStart('character', -el.value.length);
+ strPos = range.text.length;
+ } else if (browser === "ff") {
+ strPos = el.selectionStart;
+ }
+
+ var front = (el.value).substring(0, strPos);
+ var back = (el.value).substring(strPos, el.value.length);
+ el.value = front + text + back;
+ strPos = strPos + text.length;
+ if (browser === "ie") {
+ el.focus();
+ range = document.selection.createRange();
+ range.moveStart('character', -el.value.length);
+ range.moveStart('character', strPos);
+ range.moveEnd('character', 0);
+ range.select();
+ } else if (browser === "ff") {
+ el.selectionStart = strPos;
+ el.selectionEnd = strPos;
+ el.focus();
+ }
+ el.scrollTop = scrollPos;
+ }
+ };
+
+ /**
+ * Default configuration options
+ *
+ * @type {Object}
+ */
+ inlineAttachment.defaults = {
+ /**
+ * URL where the file will be send
+ */
+ uploadUrl: 'upload_attachment.php',
+
+ /**
+ * Which method will be used to send the file to the upload URL
+ */
+ uploadMethod: 'POST',
+
+ /**
+ * Name in which the file will be placed
+ */
+ uploadFieldName: 'file',
+
+ /**
+ * Extension which will be used when a file extension could not
+ * be detected
+ */
+ defaultExtension: 'png',
+
+ /**
+ * JSON field which refers to the uploaded file URL
+ */
+ jsonFieldName: 'filename',
+
+ /**
+ * Allowed MIME types
+ */
+ allowedTypes: [
+ 'image/jpeg',
+ 'image/png',
+ 'image/jpg',
+ 'image/gif'
+ ],
+
+ /**
+ * Text which will be inserted when dropping or pasting a file.
+ * Acts as a placeholder which will be replaced when the file is done with uploading
+ */
+ progressText: '![Uploading file...]()',
+
+ /**
+ * When a file has successfully been uploaded the progressText
+ * will be replaced by the urlText, the {filename} tag will be replaced
+ * by the filename that has been returned by the server
+ */
+ urlText: "![file]({filename})",
+
+ /**
+ * Text which will be used when uploading has failed
+ */
+ errorText: "Error uploading file",
+
+ /**
+ * Extra parameters which will be send when uploading a file
+ */
+ extraParams: {},
+
+ /**
+ * Extra headers which will be send when uploading a file
+ */
+ extraHeaders: {},
+
+ /**
+ * Before the file is send
+ */
+ beforeFileUpload: function() {
+ return true;
+ },
+
+ /**
+ * Triggers when a file is dropped or pasted
+ */
+ onFileReceived: function() {},
+
+ /**
+ * Custom upload handler
+ *
+ * @return {Boolean} when false is returned it will prevent default upload behavior
+ */
+ onFileUploadResponse: function() {
+ return true;
+ },
+
+ /**
+ * Custom error handler. Runs after removing the placeholder text and before the alert().
+ * Return false from this function to prevent the alert dialog.
+ *
+ * @return {Boolean} when false is returned it will prevent default error behavior
+ */
+ onFileUploadError: function() {
+ return true;
+ },
+
+ /**
+ * When a file has succesfully been uploaded
+ */
+ onFileUploaded: function() {}
+ };
+
+ /**
+ * Uploads the blob
+ *
+ * @param {Blob} file blob data received from event.dataTransfer object
+ * @return {XMLHttpRequest} request object which sends the file
+ */
+ inlineAttachment.prototype.uploadFile = function(file) {
+ var me = this,
+ formData = new FormData(),
+ xhr = new XMLHttpRequest(),
+ settings = this.settings,
+ extension = settings.defaultExtension || settings.defualtExtension;
+
+ if (typeof settings.setupFormData === 'function') {
+ settings.setupFormData(formData, file);
+ }
+
+ // Attach the file. If coming from clipboard, add a default filename (only works in Chrome for now)
+ // http://stackoverflow.com/questions/6664967/how-to-give-a-blob-uploaded-as-formdata-a-file-name
+ if (file.name) {
+ var fileNameMatches = file.name.match(/\.(.+)$/);
+ if (fileNameMatches) {
+ extension = fileNameMatches[1];
+ }
+ }
+
+ var remoteFilename = "image-" + Date.now() + "." + extension;
+ if (typeof settings.remoteFilename === 'function') {
+ remoteFilename = settings.remoteFilename(file);
+ }
+
+ formData.append(settings.uploadFieldName, file, remoteFilename);
+
+ // Append the extra parameters to the formdata
+ if (typeof settings.extraParams === "object") {
+ for (var key in settings.extraParams) {
+ if (settings.extraParams.hasOwnProperty(key)) {
+ formData.append(key, settings.extraParams[key]);
+ }
+ }
+ }
+
+ xhr.open('POST', settings.uploadUrl);
+
+ // Add any available extra headers
+ if (typeof settings.extraHeaders === "object") {
+ for (var header in settings.extraHeaders) {
+ if (settings.extraHeaders.hasOwnProperty(header)) {
+ xhr.setRequestHeader(header, settings.extraHeaders[header]);
+ }
+ }
+ }
+
+ xhr.onload = function() {
+ // If HTTP status is OK or Created
+ if (xhr.status === 200 || xhr.status === 201) {
+ me.onFileUploadResponse(xhr);
+ } else {
+ me.onFileUploadError(xhr);
+ }
+ };
+ if (settings.beforeFileUpload(xhr) !== false) {
+ xhr.send(formData);
+ }
+ return xhr;
+ };
+
+ /**
+ * Returns if the given file is allowed to handle
+ *
+ * @param {File} clipboard data file
+ */
+ inlineAttachment.prototype.isFileAllowed = function(file) {
+ if (file.kind === 'string') { return false; }
+ if (this.settings.allowedTypes.indexOf('*') === 0){
+ return true;
+ } else {
+ return this.settings.allowedTypes.indexOf(file.type) >= 0;
+ }
+ };
+
+ /**
+ * Handles upload response
+ *
+ * @param {XMLHttpRequest} xhr
+ * @return {Void}
+ */
+ inlineAttachment.prototype.onFileUploadResponse = function(xhr) {
+ if (this.settings.onFileUploadResponse.call(this, xhr) !== false) {
+ var result = JSON.parse(xhr.responseText),
+ filename = result[this.settings.jsonFieldName];
+
+ if (result && filename) {
+ var newValue;
+ if (typeof this.settings.urlText === 'function') {
+ newValue = this.settings.urlText.call(this, filename, result);
+ } else {
+ newValue = this.settings.urlText.replace(this.filenameTag, filename);
+ }
+ var text = this.editor.getValue().replace(this.lastValue, newValue);
+ this.editor.setValue(text);
+ this.settings.onFileUploaded.call(this, filename);
+ }
+ }
+ };
+
+
+ /**
+ * Called when a file has failed to upload
+ *
+ * @param {XMLHttpRequest} xhr
+ * @return {Void}
+ */
+ inlineAttachment.prototype.onFileUploadError = function(xhr) {
+ if (this.settings.onFileUploadError.call(this, xhr) !== false) {
+ var text = this.editor.getValue().replace(this.lastValue, "");
+ this.editor.setValue(text);
+ }
+ };
+
+ /**
+ * Called when a file has been inserted, either by drop or paste
+ *
+ * @param {File} file
+ * @return {Void}
+ */
+ inlineAttachment.prototype.onFileInserted = function(file) {
+ if (this.settings.onFileReceived.call(this, file) !== false) {
+ this.lastValue = this.settings.progressText;
+ this.editor.insertValue(this.lastValue);
+ }
+ };
+
+
+ /**
+ * Called when a paste event occured
+ * @param {Event} e
+ * @return {Boolean} if the event was handled
+ */
+ inlineAttachment.prototype.onPaste = function(e) {
+ var result = false,
+ clipboardData = e.clipboardData,
+ items;
+
+ if (typeof clipboardData === "object") {
+ items = clipboardData.items || clipboardData.files || [];
+
+ for (var i = 0; i < items.length; i++) {
+ var item = items[i];
+ if (this.isFileAllowed(item)) {
+ result = true;
+ this.onFileInserted(item.getAsFile());
+ this.uploadFile(item.getAsFile());
+ }
+ }
+ }
+
+ if (result) { e.preventDefault(); }
+
+ return result;
+ };
+
+ /**
+ * Called when a drop event occures
+ * @param {Event} e
+ * @return {Boolean} if the event was handled
+ */
+ inlineAttachment.prototype.onDrop = function(e) {
+ var result = false;
+ for (var i = 0; i < e.dataTransfer.files.length; i++) {
+ var file = e.dataTransfer.files[i];
+ if (this.isFileAllowed(file)) {
+ result = true;
+ this.onFileInserted(file);
+ this.uploadFile(file);
+ }
+ }
+
+ return result;
+ };
+
+ window.inlineAttachment = inlineAttachment;
+
+})(document, window);
+
+/*jslint newcap: true */
+/*global inlineAttachment: false, jQuery: false */
+/**
+ * jQuery plugin for inline attach
+ *
+ * @param {document} document
+ * @param {window} window
+ * @param {jQuery} $
+ */
+(function(document, window, $) {
+ 'use strict';
+
+ inlineAttachment.editors.jquery = {};
+
+ /**
+ * Creates a new editor using jQuery
+ */
+ var editor = function(instance) {
+
+ var $this = $(instance);
+
+ return {
+ getValue: function() {
+ return $this.val();
+ },
+ insertValue: function(val) {
+ inlineAttachment.util.insertTextAtCursor($this[0], val);
+ },
+ setValue: function(val) {
+ $this.val(val);
+ }
+ };
+ };
+
+ $.fn.inlineattachment = function(options) {
+
+ var set = $(this);
+
+ set.each(function() {
+
+ var $this = $(this),
+ ed = new editor($this),
+ inlineattach = new inlineAttachment(options, ed);
+
+ $this.bind({
+ 'paste': function(e) {
+ inlineattach.onPaste(e.originalEvent);
+ },
+ 'drop': function(e) {
+ e.stopPropagation();
+ e.preventDefault();
+ inlineattach.onDrop(e.originalEvent);
+ },
+ 'dragenter dragover': function(e) {
+ e.stopPropagation();
+ e.preventDefault();
+ }
+ });
+ });
+
+ return this;
+ };
+
+ inlineAttachment.editors.jquery.Editor = editor;
+
+})(document, window, jQuery);
\ No newline at end of file
diff --git a/templates/index.tmpl b/templates/index.tmpl
index 44f9d93..94b0218 100755
--- a/templates/index.tmpl
+++ b/templates/index.tmpl
@@ -23,6 +23,8 @@
+
+
@@ -481,7 +483,13 @@ Use Markdown for formatting and links (also make links like [[this]])." id="user
-
+