vendor: 2,702 bytes, lines 1-70
1(function(factory) { 2 if (typeof define === 'function' && define.amd) { 3 // AMD. Register as an anonymous module. 4 define(['jquery'], factory); 5 } else if (typeof module === 'object' && module.exports) { 6 // Node/CommonJS 7 module.exports = factory(require('jquery')); 8 } else { 9 // Browser globals 10 factory(window.jQuery); 11 } 12}(function($) { 13 $.extend($.summernote.plugins, { 14 'specialchars': function(context) { 15 var self = this; 16 var ui = $.summernote.ui; 17 18 var $editor = context.layoutInfo.editor; 19 var options = context.options; 20 var lang = options.langInfo; 21 22 var KEY = { 23 UP: 38, 24 DOWN: 40, 25 LEFT: 37, 26 RIGHT: 39, 27 ENTER: 13, 28 }; 29 var COLUMN_LENGTH = 12; 30 var COLUMN_WIDTH = 35; 31 32 var currentColumn = 0; 33 var currentRow = 0; 34 var totalColumn = 0; 35 var totalRow = 0; 36 37 // special characters data set 38 var specialCharDataSet = [ 39 '"', '&', '<', '>', '¡', '¢', 40 '£', '¤', '¥', '¦', '§', 41 '¨', '©', 'ª', '«', '¬', 42 '®', '¯', '°', '±', '²', 43 '³', '´', 'µ', '¶', '·', 44 '¸', '¹', 'º', '»', '¼', 45 '½', '¾', '¿', '×', '÷', 46 'ƒ', 'ˆ', '˜', '–', '—', 47 '‘', '’', '‚', '“', '”', 48 '„', '†', '‡', '•', '…', 49 '‰', '′', '″', '‹', '›', 50 '‾', '⁄', '€', 'ℑ', '℘', 51 'ℜ', '™', 'ℵ', '←', '↑', 52 '→', '↓', '↔', '↵', '⇐', 53 '⇑', '⇒', '⇓', '⇔', '∀', 54 '∂', '∃', '∅', '∇', '∈', 55 '∉', '∋', '∏', '∑', '−', 56 '∗', '√', '∝', '∞', '∠', 57 '∧', '∨', '∩', '∪', '∫', 58 '∴', '∼', '≅', '≈', '≠', 59 '≡', '≤', '≥', '⊂', '⊃', 60 '⊄', '⊆', '⊇', '⊕', '⊗', 61 '⊥', '⋅', '⌈', '⌉', '⌊', 62 '⌋', '◊', '♠', '♣', '♥', 63 '♦', 64 ]; 65 66 context.memo('button.specialchars', function() { 67 return ui.button({ 68 contents: '<i class="fa fa-font fa-flip-vertical"></i>', 69 tooltip: lang.specialChar.specialChar, 70 container: '.note-editor.note-frame'
vendor: 7,805 bytes, lines 70-312
70, 71 click: function() { 72 self.show(); 73 }, 74 }).render(); 75 }); 76 77 /** 78 * Make Special Characters Table 79 * 80 * @member plugin.specialChar 81 * @private 82 * @return {jQuery} 83 */ 84 this.makeSpecialCharSetTable = function() { 85 var $table = $('<table></table>'); 86 $.each(specialCharDataSet, function(idx, text) { 87 var $td = $('<td></td>').addClass('note-specialchar-node'); 88 var $tr = (idx % COLUMN_LENGTH === 0) ? $('<tr></tr>') : $table.find('tr').last(); 89 90 var $button = ui.button({ 91 callback: function($node) { 92 $node.html(text); 93 $node.attr('title', text); 94 $node.attr('data-value', encodeURIComponent(text)); 95 $node.css({ 96 width: COLUMN_WIDTH, 97 'margin-right': '2px', 98 'margin-bottom': '2px', 99 }); 100 }, 101 }).render(); 102 103 $td.append($button); 104 105 $tr.append($td); 106 if (idx % COLUMN_LENGTH === 0) { 107 $table.append($tr); 108 } 109 }); 110 111 totalRow = $table.find('tr').length; 112 totalColumn = COLUMN_LENGTH; 113 114 return $table; 115 }; 116 117 this.initialize = function() { 118 var $container = options.dialogsInBody ? $(document.body) : $editor; 119 120 var body = '<div class="form-group row-fluid">' + this.makeSpecialCharSetTable()[0].outerHTML + '</div>'; 121 122 this.$dialog = ui.dialog({ 123 title: lang.specialChar.select, 124 body: body, 125 }).render().appendTo($container); 126 }; 127 128 this.show = function() { 129 var text = context.invoke('editor.getSelectedText'); 130 context.invoke('editor.saveRange'); 131 this.showSpecialCharDialog(text).then(function(selectChar) { 132 context.invoke('editor.restoreRange'); 133 134 // build node 135 var $node = $('<span></span>').html(selectChar)[0]; 136 137 if ($node) { 138 // insert video node 139 context.invoke('editor.insertNode', $node); 140 } 141 }).fail(function() { 142 context.invoke('editor.restoreRange'); 143 }); 144 }; 145 146 /** 147 * show image dialog 148 * 149 * @param {jQuery} $dialog 150 * @return {Promise} 151 */ 152 this.showSpecialCharDialog = function(text) { 153 return $.Deferred(function(deferred) { 154 var $specialCharDialog = self.$dialog; 155 var $specialCharNode = $specialCharDialog.find('.note-specialchar-node'); 156 var $selectedNode = null; 157 var ARROW_KEYS = [KEY.UP, KEY.DOWN, KEY.LEFT, KEY.RIGHT]; 158 var ENTER_KEY = KEY.ENTER; 159 160 function addActiveClass($target) { 161 if (!$target) { 162 return; 163 } 164 $target.find('button').addClass('active'); 165 $selectedNode = $target; 166 } 167 168 function removeActiveClass($target) { 169 $target.find('button').removeClass('active'); 170 $selectedNode = null; 171 } 172 173 // find next node 174 function findNextNode(row, column) { 175 var findNode = null; 176 $.each($specialCharNode, function(idx, $node) { 177 var findRow = Math.ceil((idx + 1) / COLUMN_LENGTH); 178 var findColumn = ((idx + 1) % COLUMN_LENGTH === 0) ? COLUMN_LENGTH : (idx + 1) % COLUMN_LENGTH; 179 if (findRow === row && findColumn === column) { 180 findNode = $node; 181 return false; 182 } 183 }); 184 return $(findNode); 185 } 186 187 function arrowKeyHandler(keyCode) { 188 // left, right, up, down key 189 var $nextNode; 190 var lastRowColumnLength = $specialCharNode.length % totalColumn; 191 192 if (KEY.LEFT === keyCode) { 193 if (currentColumn > 1) { 194 currentColumn = currentColumn - 1; 195 } else if (currentRow === 1 && currentColumn === 1) { 196 currentColumn = lastRowColumnLength; 197 currentRow = totalRow; 198 } else { 199 currentColumn = totalColumn; 200 currentRow = currentRow - 1; 201 } 202 } else if (KEY.RIGHT === keyCode) { 203 if (currentRow === totalRow && lastRowColumnLength === currentColumn) { 204 currentColumn = 1; 205 currentRow = 1; 206 } else if (currentColumn < totalColumn) { 207 currentColumn = currentColumn + 1; 208 } else { 209 currentColumn = 1; 210 currentRow = currentRow + 1; 211 } 212 } else if (KEY.UP === keyCode) { 213 if (currentRow === 1 && lastRowColumnLength < currentColumn) { 214 currentRow = totalRow - 1; 215 } else { 216 currentRow = currentRow - 1; 217 } 218 } else if (KEY.DOWN === keyCode) { 219 currentRow = currentRow + 1; 220 } 221 222 if (currentRow === totalRow && currentColumn > lastRowColumnLength) { 223 currentRow = 1; 224 } else if (currentRow > totalRow) { 225 currentRow = 1; 226 } else if (currentRow < 1) { 227 currentRow = totalRow; 228 } 229 230 $nextNode = findNextNode(currentRow, currentColumn); 231 232 if ($nextNode) { 233 removeActiveClass($selectedNode); 234 addActiveClass($nextNode); 235 } 236 } 237 238 function enterKeyHandler() { 239 if (!$selectedNode) { 240 return; 241 } 242 243 deferred.resolve(decodeURIComponent($selectedNode.find('button').attr('data-value'))); 244 $specialCharDialog.modal('hide'); 245 } 246 247 function keyDownEventHandler(event) { 248 event.preventDefault(); 249 var keyCode = event.keyCode; 250 if (keyCode === undefined || keyCode === null) { 251 return; 252 } 253 // check arrowKeys match 254 if (ARROW_KEYS.indexOf(keyCode) > -1) { 255 if ($selectedNode === null) { 256 addActiveClass($specialCharNode.eq(0)); 257 currentColumn = 1; 258 currentRow = 1; 259 return; 260 } 261 arrowKeyHandler(keyCode); 262 } else if (keyCode === ENTER_KEY) { 263 enterKeyHandler(); 264 } 265 return false; 266 } 267 268 // remove class 269 removeActiveClass($specialCharNode); 270 271 // find selected node 272 if (text) { 273 for (var i = 0; i < $specialCharNode.length; i++) { 274 var $checkNode = $($specialCharNode[i]); 275 if ($checkNode.text() === text) { 276 addActiveClass($checkNode); 277 currentRow = Math.ceil((i + 1) / COLUMN_LENGTH); 278 currentColumn = (i + 1) % COLUMN_LENGTH; 279 } 280 } 281 } 282 283 ui.onDialogShown(self.$dialog, function() { 284 $(document).on('keydown', keyDownEventHandler); 285 286 self.$dialog.find('button').tooltip(); 287 288 $specialCharNode.on('click', function(event) { 289 event.preventDefault(); 290 deferred.resolve(decodeURIComponent($(event.currentTarget).find('button').attr('data-value'))); 291 ui.hideDialog(self.$dialog); 292 }); 293 }); 294 295 ui.onDialogHidden(self.$dialog, function() { 296 $specialCharNode.off('click'); 297 298 self.$dialog.find('button').tooltip(); 299 300 $(document).off('keydown', keyDownEventHandler); 301 302 if (deferred.state() === 'pending') { 303 deferred.reject(); 304 } 305 }); 306 307 ui.showDialog(self.$dialog); 308 }); 309 }; 310 }, 311 }); 312}));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.