github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/public/js/wysiwyg/bootstrap-wysiwyg.js (about) 1 /* http://github.com/mindmup/bootstrap-wysiwyg */ 2 /*global jQuery, $, FileReader*/ 3 /*jslint browser:true*/ 4 (function ($) { 5 'use strict'; 6 var readFileIntoDataUrl = function (fileInfo) { 7 var loader = $.Deferred(), 8 fReader = new FileReader(); 9 fReader.onload = function (e) { 10 loader.resolve(e.target.result); 11 }; 12 fReader.onerror = loader.reject; 13 fReader.onprogress = loader.notify; 14 fReader.readAsDataURL(fileInfo); 15 return loader.promise(); 16 }; 17 $.fn.cleanHtml = function () { 18 var html = $(this).html(); 19 return html && html.replace(/(<br>|\s|<div><br><\/div>| )*$/, ''); 20 }; 21 $.fn.wysiwyg = function (userOptions) { 22 var editor = this, 23 selectedRange, 24 options, 25 toolbarBtnSelector, 26 updateToolbar = function () { 27 if (options.activeToolbarClass) { 28 $(options.toolbarSelector).find(toolbarBtnSelector).each(function () { 29 var command = $(this).data(options.commandRole); 30 if (document.queryCommandState(command)) { 31 $(this).addClass(options.activeToolbarClass); 32 } else { 33 $(this).removeClass(options.activeToolbarClass); 34 } 35 }); 36 } 37 }, 38 execCommand = function (commandWithArgs, valueArg) { 39 var commandArr = commandWithArgs.split(' '), 40 command = commandArr.shift(), 41 args = commandArr.join(' ') + (valueArg || ''); 42 document.execCommand(command, 0, args); 43 updateToolbar(); 44 }, 45 bindHotkeys = function (hotKeys) { 46 $.each(hotKeys, function (hotkey, command) { 47 editor.keydown(hotkey, function (e) { 48 if (editor.attr('contenteditable') && editor.is(':visible')) { 49 e.preventDefault(); 50 e.stopPropagation(); 51 execCommand(command); 52 } 53 }).keyup(hotkey, function (e) { 54 if (editor.attr('contenteditable') && editor.is(':visible')) { 55 e.preventDefault(); 56 e.stopPropagation(); 57 } 58 }); 59 }); 60 }, 61 getCurrentRange = function () { 62 var sel = window.getSelection(); 63 if (sel.getRangeAt && sel.rangeCount) { 64 return sel.getRangeAt(0); 65 } 66 }, 67 saveSelection = function () { 68 selectedRange = getCurrentRange(); 69 }, 70 restoreSelection = function () { 71 var selection = window.getSelection(); 72 if (selectedRange) { 73 try { 74 selection.removeAllRanges(); 75 } catch (ex) { 76 document.body.createTextRange().select(); 77 document.selection.empty(); 78 } 79 80 selection.addRange(selectedRange); 81 } 82 }, 83 insertFiles = function (files) { 84 editor.focus(); 85 $.each(files, function (idx, fileInfo) { 86 if (/^image\//.test(fileInfo.type)) { 87 $.when(readFileIntoDataUrl(fileInfo)).done(function (dataUrl) { 88 execCommand('insertimage', dataUrl); 89 }).fail(function (e) { 90 options.fileUploadError("file-reader", e); 91 }); 92 } else { 93 options.fileUploadError("unsupported-file-type", fileInfo.type); 94 } 95 }); 96 }, 97 markSelection = function (input, color) { 98 restoreSelection(); 99 if (document.queryCommandSupported('hiliteColor')) { 100 document.execCommand('hiliteColor', 0, color || 'transparent'); 101 } 102 saveSelection(); 103 input.data(options.selectionMarker, color); 104 }, 105 bindToolbar = function (toolbar, options) { 106 toolbar.find(toolbarBtnSelector).click(function () { 107 restoreSelection(); 108 editor.focus(); 109 execCommand($(this).data(options.commandRole)); 110 saveSelection(); 111 }); 112 toolbar.find('[data-toggle=dropdown]').click(restoreSelection); 113 114 toolbar.find('input[type=text][data-' + options.commandRole + ']').on('webkitspeechchange change', function () { 115 var newValue = this.value; /* ugly but prevents fake double-calls due to selection restoration */ 116 this.value = ''; 117 restoreSelection(); 118 if (newValue) { 119 editor.focus(); 120 execCommand($(this).data(options.commandRole), newValue); 121 } 122 saveSelection(); 123 }).on('focus', function () { 124 var input = $(this); 125 if (!input.data(options.selectionMarker)) { 126 markSelection(input, options.selectionColor); 127 input.focus(); 128 } 129 }).on('blur', function () { 130 var input = $(this); 131 if (input.data(options.selectionMarker)) { 132 markSelection(input, false); 133 } 134 }); 135 toolbar.find('input[type=file][data-' + options.commandRole + ']').change(function () { 136 restoreSelection(); 137 if (this.type === 'file' && this.files && this.files.length > 0) { 138 insertFiles(this.files); 139 } 140 saveSelection(); 141 this.value = ''; 142 }); 143 }, 144 initFileDrops = function () { 145 editor.on('dragenter dragover', false) 146 .on('drop', function (e) { 147 var dataTransfer = e.originalEvent.dataTransfer; 148 e.stopPropagation(); 149 e.preventDefault(); 150 if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) { 151 insertFiles(dataTransfer.files); 152 } 153 }); 154 }; 155 options = $.extend({}, $.fn.wysiwyg.defaults, userOptions); 156 toolbarBtnSelector = 'a[data-' + options.commandRole + '],button[data-' + options.commandRole + '],input[type=button][data-' + options.commandRole + ']'; 157 bindHotkeys(options.hotKeys); 158 if (options.dragAndDropImages) { 159 initFileDrops(); 160 } 161 bindToolbar($(options.toolbarSelector), options); 162 editor.attr('contenteditable', true) 163 .on('mouseup keyup mouseout', function () { 164 saveSelection(); 165 updateToolbar(); 166 }); 167 $(window).bind('touchend', function (e) { 168 var isInside = (editor.is(e.target) || editor.has(e.target).length > 0), 169 currentRange = getCurrentRange(), 170 clear = currentRange && (currentRange.startContainer === currentRange.endContainer && currentRange.startOffset === currentRange.endOffset); 171 if (!clear || isInside) { 172 saveSelection(); 173 updateToolbar(); 174 } 175 }); 176 return this; 177 }; 178 $.fn.wysiwyg.defaults = { 179 hotKeys: { 180 'ctrl+b meta+b': 'bold', 181 'ctrl+i meta+i': 'italic', 182 'ctrl+u meta+u': 'underline', 183 'ctrl+z meta+z': 'undo', 184 'ctrl+y meta+y meta+shift+z': 'redo', 185 'ctrl+l meta+l': 'justifyleft', 186 'ctrl+r meta+r': 'justifyright', 187 'ctrl+e meta+e': 'justifycenter', 188 'ctrl+j meta+j': 'justifyfull', 189 'shift+tab': 'outdent', 190 'tab': 'indent' 191 }, 192 toolbarSelector: '[data-role=editor-toolbar]', 193 commandRole: 'edit', 194 activeToolbarClass: 'btn-info', 195 selectionMarker: 'edit-focus-marker', 196 selectionColor: 'darkgrey', 197 dragAndDropImages: true, 198 fileUploadError: function (reason, detail) { console.log("File upload error", reason, detail); } 199 }; 200 }(window.jQuery));