GPQAPP
311 строк · 10.2 Кб
1(function(factory) {2if (typeof define === 'function' && define.amd) {3// AMD. Register as an anonymous module.4define(['jquery'], factory);5} else if (typeof module === 'object' && module.exports) {6// Node/CommonJS7module.exports = factory(require('jquery'));8} else {9// Browser globals10factory(window.jQuery);11}12}(function($) {13$.extend($.summernote.plugins, {14'specialchars': function(context) {15var self = this;16var ui = $.summernote.ui;17
18var $editor = context.layoutInfo.editor;19var options = context.options;20var lang = options.langInfo;21
22var KEY = {23UP: 38,24DOWN: 40,25LEFT: 37,26RIGHT: 39,27ENTER: 13,28};29var COLUMN_LENGTH = 12;30var COLUMN_WIDTH = 35;31
32var currentColumn = 0;33var currentRow = 0;34var totalColumn = 0;35var totalRow = 0;36
37// special characters data set38var 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
66context.memo('button.specialchars', function() {67return ui.button({68contents: '<i class="fa fa-font fa-flip-vertical"></i>',69tooltip: lang.specialChar.specialChar,70click: function() {71self.show();72},73}).render();74});75
76/**77* Make Special Characters Table
78*
79* @member plugin.specialChar
80* @private
81* @return {jQuery}
82*/
83this.makeSpecialCharSetTable = function() {84var $table = $('<table></table>');85$.each(specialCharDataSet, function(idx, text) {86var $td = $('<td></td>').addClass('note-specialchar-node');87var $tr = (idx % COLUMN_LENGTH === 0) ? $('<tr></tr>') : $table.find('tr').last();88
89var $button = ui.button({90callback: function($node) {91$node.html(text);92$node.attr('title', text);93$node.attr('data-value', encodeURIComponent(text));94$node.css({95width: COLUMN_WIDTH,96'margin-right': '2px',97'margin-bottom': '2px',98});99},100}).render();101
102$td.append($button);103
104$tr.append($td);105if (idx % COLUMN_LENGTH === 0) {106$table.append($tr);107}108});109
110totalRow = $table.find('tr').length;111totalColumn = COLUMN_LENGTH;112
113return $table;114};115
116this.initialize = function() {117var $container = options.dialogsInBody ? $(document.body) : $editor;118
119var body = '<div class="form-group row-fluid">' + this.makeSpecialCharSetTable()[0].outerHTML + '</div>';120
121this.$dialog = ui.dialog({122title: lang.specialChar.select,123body: body,124}).render().appendTo($container);125};126
127this.show = function() {128var text = context.invoke('editor.getSelectedText');129context.invoke('editor.saveRange');130this.showSpecialCharDialog(text).then(function(selectChar) {131context.invoke('editor.restoreRange');132
133// build node134var $node = $('<span></span>').html(selectChar)[0];135
136if ($node) {137// insert video node138context.invoke('editor.insertNode', $node);139}140}).fail(function() {141context.invoke('editor.restoreRange');142});143};144
145/**146* show image dialog
147*
148* @param {jQuery} $dialog
149* @return {Promise}
150*/
151this.showSpecialCharDialog = function(text) {152return $.Deferred(function(deferred) {153var $specialCharDialog = self.$dialog;154var $specialCharNode = $specialCharDialog.find('.note-specialchar-node');155var $selectedNode = null;156var ARROW_KEYS = [KEY.UP, KEY.DOWN, KEY.LEFT, KEY.RIGHT];157var ENTER_KEY = KEY.ENTER;158
159function addActiveClass($target) {160if (!$target) {161return;162}163$target.find('button').addClass('active');164$selectedNode = $target;165}166
167function removeActiveClass($target) {168$target.find('button').removeClass('active');169$selectedNode = null;170}171
172// find next node173function findNextNode(row, column) {174var findNode = null;175$.each($specialCharNode, function(idx, $node) {176var findRow = Math.ceil((idx + 1) / COLUMN_LENGTH);177var findColumn = ((idx + 1) % COLUMN_LENGTH === 0) ? COLUMN_LENGTH : (idx + 1) % COLUMN_LENGTH;178if (findRow === row && findColumn === column) {179findNode = $node;180return false;181}182});183return $(findNode);184}185
186function arrowKeyHandler(keyCode) {187// left, right, up, down key188var $nextNode;189var lastRowColumnLength = $specialCharNode.length % totalColumn;190
191if (KEY.LEFT === keyCode) {192if (currentColumn > 1) {193currentColumn = currentColumn - 1;194} else if (currentRow === 1 && currentColumn === 1) {195currentColumn = lastRowColumnLength;196currentRow = totalRow;197} else {198currentColumn = totalColumn;199currentRow = currentRow - 1;200}201} else if (KEY.RIGHT === keyCode) {202if (currentRow === totalRow && lastRowColumnLength === currentColumn) {203currentColumn = 1;204currentRow = 1;205} else if (currentColumn < totalColumn) {206currentColumn = currentColumn + 1;207} else {208currentColumn = 1;209currentRow = currentRow + 1;210}211} else if (KEY.UP === keyCode) {212if (currentRow === 1 && lastRowColumnLength < currentColumn) {213currentRow = totalRow - 1;214} else {215currentRow = currentRow - 1;216}217} else if (KEY.DOWN === keyCode) {218currentRow = currentRow + 1;219}220
221if (currentRow === totalRow && currentColumn > lastRowColumnLength) {222currentRow = 1;223} else if (currentRow > totalRow) {224currentRow = 1;225} else if (currentRow < 1) {226currentRow = totalRow;227}228
229$nextNode = findNextNode(currentRow, currentColumn);230
231if ($nextNode) {232removeActiveClass($selectedNode);233addActiveClass($nextNode);234}235}236
237function enterKeyHandler() {238if (!$selectedNode) {239return;240}241
242deferred.resolve(decodeURIComponent($selectedNode.find('button').attr('data-value')));243$specialCharDialog.modal('hide');244}245
246function keyDownEventHandler(event) {247event.preventDefault();248var keyCode = event.keyCode;249if (keyCode === undefined || keyCode === null) {250return;251}252// check arrowKeys match253if (ARROW_KEYS.indexOf(keyCode) > -1) {254if ($selectedNode === null) {255addActiveClass($specialCharNode.eq(0));256currentColumn = 1;257currentRow = 1;258return;259}260arrowKeyHandler(keyCode);261} else if (keyCode === ENTER_KEY) {262enterKeyHandler();263}264return false;265}266
267// remove class268removeActiveClass($specialCharNode);269
270// find selected node271if (text) {272for (var i = 0; i < $specialCharNode.length; i++) {273var $checkNode = $($specialCharNode[i]);274if ($checkNode.text() === text) {275addActiveClass($checkNode);276currentRow = Math.ceil((i + 1) / COLUMN_LENGTH);277currentColumn = (i + 1) % COLUMN_LENGTH;278}279}280}281
282ui.onDialogShown(self.$dialog, function() {283$(document).on('keydown', keyDownEventHandler);284
285self.$dialog.find('button').tooltip();286
287$specialCharNode.on('click', function(event) {288event.preventDefault();289deferred.resolve(decodeURIComponent($(event.currentTarget).find('button').attr('data-value')));290ui.hideDialog(self.$dialog);291});292});293
294ui.onDialogHidden(self.$dialog, function() {295$specialCharNode.off('click');296
297self.$dialog.find('button').tooltip();298
299$(document).off('keydown', keyDownEventHandler);300
301if (deferred.state() === 'pending') {302deferred.reject();303}304});305
306ui.showDialog(self.$dialog);307});308};309},310});311}));312