123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312 |
- (function(factory) {
- if (typeof define === 'function' && define.amd) {
- // AMD. Register as an anonymous module.
- define(['jquery'], factory);
- } else if (typeof module === 'object' && module.exports) {
- // Node/CommonJS
- module.exports = factory(require('jquery'));
- } else {
- // Browser globals
- factory(window.jQuery);
- }
- }(function($) {
- $.extend($.summernote.plugins, {
- 'specialchars': function(context) {
- var self = this;
- var ui = $.summernote.ui;
- var $editor = context.layoutInfo.editor;
- var options = context.options;
- var lang = options.langInfo;
- var KEY = {
- UP: 38,
- DOWN: 40,
- LEFT: 37,
- RIGHT: 39,
- ENTER: 13,
- };
- var COLUMN_LENGTH = 12;
- var COLUMN_WIDTH = 35;
- var currentColumn = 0;
- var currentRow = 0;
- var totalColumn = 0;
- var totalRow = 0;
- // special characters data set
- var specialCharDataSet = [
- '"', '&', '<', '>', '¡', '¢',
- '£', '¤', '¥', '¦', '§',
- '¨', '©', 'ª', '«', '¬',
- '®', '¯', '°', '±', '²',
- '³', '´', 'µ', '¶', '·',
- '¸', '¹', 'º', '»', '¼',
- '½', '¾', '¿', '×', '÷',
- 'ƒ', 'ˆ', '˜', '–', '—',
- '‘', '’', '‚', '“', '”',
- '„', '†', '‡', '•', '…',
- '‰', '′', '″', '‹', '›',
- '‾', '⁄', '€', 'ℑ', '℘',
- 'ℜ', '™', 'ℵ', '←', '↑',
- '→', '↓', '↔', '↵', '⇐',
- '⇑', '⇒', '⇓', '⇔', '∀',
- '∂', '∃', '∅', '∇', '∈',
- '∉', '∋', '∏', '∑', '−',
- '∗', '√', '∝', '∞', '∠',
- '∧', '∨', '∩', '∪', '∫',
- '∴', '∼', '≅', '≈', '≠',
- '≡', '≤', '≥', '⊂', '⊃',
- '⊄', '⊆', '⊇', '⊕', '⊗',
- '⊥', '⋅', '⌈', '⌉', '⌊',
- '⌋', '◊', '♠', '♣', '♥',
- '♦',
- ];
- context.memo('button.specialchars', function() {
- return ui.button({
- contents: '<i class="fa fa-font fa-flip-vertical"></i>',
- tooltip: lang.specialChar.specialChar,
- click: function() {
- self.show();
- },
- }).render();
- });
- /**
- * Make Special Characters Table
- *
- * @member plugin.specialChar
- * @private
- * @return {jQuery}
- */
- this.makeSpecialCharSetTable = function() {
- var $table = $('<table></table>');
- $.each(specialCharDataSet, function(idx, text) {
- var $td = $('<td></td>').addClass('note-specialchar-node');
- var $tr = (idx % COLUMN_LENGTH === 0) ? $('<tr></tr>') : $table.find('tr').last();
- var $button = ui.button({
- callback: function($node) {
- $node.html(text);
- $node.attr('title', text);
- $node.attr('data-value', encodeURIComponent(text));
- $node.css({
- width: COLUMN_WIDTH,
- 'margin-right': '2px',
- 'margin-bottom': '2px',
- });
- },
- }).render();
- $td.append($button);
- $tr.append($td);
- if (idx % COLUMN_LENGTH === 0) {
- $table.append($tr);
- }
- });
- totalRow = $table.find('tr').length;
- totalColumn = COLUMN_LENGTH;
- return $table;
- };
- this.initialize = function() {
- var $container = options.dialogsInBody ? $(document.body) : $editor;
- var body = '<div class="form-group row-fluid">' + this.makeSpecialCharSetTable()[0].outerHTML + '</div>';
- this.$dialog = ui.dialog({
- title: lang.specialChar.select,
- body: body,
- }).render().appendTo($container);
- };
- this.show = function() {
- var text = context.invoke('editor.getSelectedText');
- context.invoke('editor.saveRange');
- this.showSpecialCharDialog(text).then(function(selectChar) {
- context.invoke('editor.restoreRange');
- // build node
- var $node = $('<span></span>').html(selectChar)[0];
- if ($node) {
- // insert video node
- context.invoke('editor.insertNode', $node);
- }
- }).fail(function() {
- context.invoke('editor.restoreRange');
- });
- };
- /**
- * show image dialog
- *
- * @param {jQuery} $dialog
- * @return {Promise}
- */
- this.showSpecialCharDialog = function(text) {
- return $.Deferred(function(deferred) {
- var $specialCharDialog = self.$dialog;
- var $specialCharNode = $specialCharDialog.find('.note-specialchar-node');
- var $selectedNode = null;
- var ARROW_KEYS = [KEY.UP, KEY.DOWN, KEY.LEFT, KEY.RIGHT];
- var ENTER_KEY = KEY.ENTER;
- function addActiveClass($target) {
- if (!$target) {
- return;
- }
- $target.find('button').addClass('active');
- $selectedNode = $target;
- }
- function removeActiveClass($target) {
- $target.find('button').removeClass('active');
- $selectedNode = null;
- }
- // find next node
- function findNextNode(row, column) {
- var findNode = null;
- $.each($specialCharNode, function(idx, $node) {
- var findRow = Math.ceil((idx + 1) / COLUMN_LENGTH);
- var findColumn = ((idx + 1) % COLUMN_LENGTH === 0) ? COLUMN_LENGTH : (idx + 1) % COLUMN_LENGTH;
- if (findRow === row && findColumn === column) {
- findNode = $node;
- return false;
- }
- });
- return $(findNode);
- }
- function arrowKeyHandler(keyCode) {
- // left, right, up, down key
- var $nextNode;
- var lastRowColumnLength = $specialCharNode.length % totalColumn;
- if (KEY.LEFT === keyCode) {
- if (currentColumn > 1) {
- currentColumn = currentColumn - 1;
- } else if (currentRow === 1 && currentColumn === 1) {
- currentColumn = lastRowColumnLength;
- currentRow = totalRow;
- } else {
- currentColumn = totalColumn;
- currentRow = currentRow - 1;
- }
- } else if (KEY.RIGHT === keyCode) {
- if (currentRow === totalRow && lastRowColumnLength === currentColumn) {
- currentColumn = 1;
- currentRow = 1;
- } else if (currentColumn < totalColumn) {
- currentColumn = currentColumn + 1;
- } else {
- currentColumn = 1;
- currentRow = currentRow + 1;
- }
- } else if (KEY.UP === keyCode) {
- if (currentRow === 1 && lastRowColumnLength < currentColumn) {
- currentRow = totalRow - 1;
- } else {
- currentRow = currentRow - 1;
- }
- } else if (KEY.DOWN === keyCode) {
- currentRow = currentRow + 1;
- }
- if (currentRow === totalRow && currentColumn > lastRowColumnLength) {
- currentRow = 1;
- } else if (currentRow > totalRow) {
- currentRow = 1;
- } else if (currentRow < 1) {
- currentRow = totalRow;
- }
- $nextNode = findNextNode(currentRow, currentColumn);
- if ($nextNode) {
- removeActiveClass($selectedNode);
- addActiveClass($nextNode);
- }
- }
- function enterKeyHandler() {
- if (!$selectedNode) {
- return;
- }
- deferred.resolve(decodeURIComponent($selectedNode.find('button').attr('data-value')));
- $specialCharDialog.modal('hide');
- }
- function keyDownEventHandler(event) {
- event.preventDefault();
- var keyCode = event.keyCode;
- if (keyCode === undefined || keyCode === null) {
- return;
- }
- // check arrowKeys match
- if (ARROW_KEYS.indexOf(keyCode) > -1) {
- if ($selectedNode === null) {
- addActiveClass($specialCharNode.eq(0));
- currentColumn = 1;
- currentRow = 1;
- return;
- }
- arrowKeyHandler(keyCode);
- } else if (keyCode === ENTER_KEY) {
- enterKeyHandler();
- }
- return false;
- }
- // remove class
- removeActiveClass($specialCharNode);
- // find selected node
- if (text) {
- for (var i = 0; i < $specialCharNode.length; i++) {
- var $checkNode = $($specialCharNode[i]);
- if ($checkNode.text() === text) {
- addActiveClass($checkNode);
- currentRow = Math.ceil((i + 1) / COLUMN_LENGTH);
- currentColumn = (i + 1) % COLUMN_LENGTH;
- }
- }
- }
- ui.onDialogShown(self.$dialog, function() {
- $(document).on('keydown', keyDownEventHandler);
- self.$dialog.find('button').tooltip();
- $specialCharNode.on('click', function(event) {
- event.preventDefault();
- deferred.resolve(decodeURIComponent($(event.currentTarget).find('button').attr('data-value')));
- ui.hideDialog(self.$dialog);
- });
- });
- ui.onDialogHidden(self.$dialog, function() {
- $specialCharNode.off('click');
- self.$dialog.find('button').tooltip();
- $(document).off('keydown', keyDownEventHandler);
- if (deferred.state() === 'pending') {
- deferred.reject();
- }
- });
- ui.showDialog(self.$dialog);
- });
- };
- },
- });
- }));
|