mirror of
https://github.com/zadam/trilium.git
synced 2025-11-15 09:45:52 +01:00
Initial prototype commit
This commit is contained in:
@@ -0,0 +1,315 @@
|
||||
(function (factory) {
|
||||
/* global define */
|
||||
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 = 15;
|
||||
var COLUMN_WIDTH = 35;
|
||||
|
||||
var currentColumn, currentRow, totalColumn, totalRow = 0;
|
||||
|
||||
// special characters data set
|
||||
var specialCharDataSet = [
|
||||
'"', '&', '<', '>', '¡', '¢',
|
||||
'£', '¤', '¥', '¦', '§',
|
||||
'¨', '©', 'ª', '«', '¬',
|
||||
'®', '¯', '°', '±', '²',
|
||||
'³', '´', 'µ', '¶', '·',
|
||||
'¸', '¹', 'º', '»', '¼',
|
||||
'½', '¾', '¿', '×', '÷',
|
||||
'ƒ', 'ˆ', '˜', '–', '—',
|
||||
'‘', '’', '‚', '“', '”',
|
||||
'„', '†', '‡', '•', '…',
|
||||
'‰', '′', '″', '‹', '›',
|
||||
'‾', '⁄', '€', 'ℑ', '℘',
|
||||
'ℜ', '™', 'ℵ', '←', '↑',
|
||||
'→', '↓', '↔', '↵', '⇐',
|
||||
'⇑', '⇒', '⇓', '⇔', '∀',
|
||||
'∂', '∃', '∅', '∇', '∈',
|
||||
'∉', '∋', '∏', '∑', '−',
|
||||
'∗', '√', '∝', '∞', '∠',
|
||||
'∧', '∨', '∩', '∪', '∫',
|
||||
'∴', '∼', '≅', '≈', '≠',
|
||||
'≡', '≤', '≥', '⊂', '⊃',
|
||||
'⊄', '⊆', '⊇', '⊕', '⊗',
|
||||
'⊥', '⋅', '⌈', '⌉', '⌊',
|
||||
'⌋', '◊', '♠', '♣', '♥',
|
||||
'♦'
|
||||
];
|
||||
|
||||
context.memo('button.specialCharacter', function () {
|
||||
return ui.button({
|
||||
contents: '<i class="fa fa-font fa-flip-vertical">',
|
||||
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/>');
|
||||
$.each(specialCharDataSet, function (idx, text) {
|
||||
var $td = $('<td/>').addClass('note-specialchar-node');
|
||||
var $tr = (idx % COLUMN_LENGTH === 0) ? $('<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('destroy');
|
||||
|
||||
$(document).off('keydown', keyDownEventHandler);
|
||||
|
||||
if (deferred.state() === 'pending') {
|
||||
deferred.reject();
|
||||
}
|
||||
});
|
||||
|
||||
ui.showDialog(self.$dialog);
|
||||
});
|
||||
};
|
||||
}
|
||||
});
|
||||
}));
|
||||
2
frontend/js/summernote/plugin/specialchars/summernote-ext-specialchars.min.js
vendored
Normal file
2
frontend/js/summernote/plugin/specialchars/summernote-ext-specialchars.min.js
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/*! Summernote v0.8.3 | (c) 2013-2015 Alan Hong and other contributors | MIT license */
|
||||
!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof module&&module.exports?module.exports=a(require("jquery")):a(window.jQuery)}(function(a){a.extend(a.summernote.plugins,{specialchars:function(b){var c,d,e,f=this,g=a.summernote.ui,h=b.layoutInfo.editor,i=b.options,j=i.langInfo,k={UP:38,DOWN:40,LEFT:37,RIGHT:39,ENTER:13},l=0,m=[""","&","<",">","¡","¢","£","¤","¥","¦","§","¨","©","ª","«","¬","®","¯","°","±","²","³","´","µ","¶","·","¸","¹","º","»","¼","½","¾","¿","×","÷","ƒ","ˆ","˜","–","—","‘","’","‚","“","”","„","†","‡","•","…","‰","′","″","‹","›","‾","⁄","€","ℑ","℘","ℜ","™","ℵ","←","↑","→","↓","↔","↵","⇐","⇑","⇒","⇓","⇔","∀","∂","∃","∅","∇","∈","∉","∋","∏","∑","−","∗","√","∝","∞","∠","∧","∨","∩","∪","∫","∴","∼","≅","≈","≠","≡","≤","≥","⊂","⊃","⊄","⊆","⊇","⊕","⊗","⊥","⋅","⌈","⌉","⌊","⌋","◊","♠","♣","♥","♦"];b.memo("button.specialCharacter",function(){return g.button({contents:'<i class="fa fa-font fa-flip-vertical">',tooltip:j.specialChar.specialChar,click:function(){f.show()}}).render()}),this.makeSpecialCharSetTable=function(){var b=a("<table/>");return a.each(m,function(c,d){var e=a("<td/>").addClass("note-specialchar-node"),f=c%15==0?a("<tr/>"):b.find("tr").last(),h=g.button({callback:function(a){a.html(d),a.attr("title",d),a.attr("data-value",encodeURIComponent(d)),a.css({width:35,"margin-right":"2px","margin-bottom":"2px"})}}).render();e.append(h),f.append(e),c%15==0&&b.append(f)}),l=b.find("tr").length,e=15,b},this.initialize=function(){var b=i.dialogsInBody?a(document.body):h,c='<div class="form-group row-fluid">'+this.makeSpecialCharSetTable()[0].outerHTML+"</div>";this.$dialog=g.dialog({title:j.specialChar.select,body:c}).render().appendTo(b)},this.show=function(){var c=b.invoke("editor.getSelectedText");b.invoke("editor.saveRange"),this.showSpecialCharDialog(c).then(function(c){b.invoke("editor.restoreRange");var d=a("<span></span>").html(c)[0];d&&b.invoke("editor.insertNode",d)}).fail(function(){b.invoke("editor.restoreRange")})},this.showSpecialCharDialog=function(b){return a.Deferred(function(h){function i(a){a&&(a.find("button").addClass("active"),s=a)}function j(a){a.find("button").removeClass("active"),s=null}function m(b,c){var d=null;return a.each(r,function(a,e){var f=Math.ceil((a+1)/15),g=(a+1)%15==0?15:(a+1)%15;if(f===b&&g===c)return d=e,!1}),a(d)}function n(a){var b,f=r.length%e;k.LEFT===a?c>1?c-=1:1===d&&1===c?(c=f,d=l):(c=e,d-=1):k.RIGHT===a?d===l&&f===c?(c=1,d=1):c<e?c+=1:(c=1,d+=1):k.UP===a?1===d&&f<c?d=l-1:d-=1:k.DOWN===a&&(d+=1),d===l&&c>f?d=1:d>l?d=1:d<1&&(d=l),(b=m(d,c))&&(j(s),i(b))}function o(){s&&(h.resolve(decodeURIComponent(s.find("button").attr("data-value"))),q.modal("hide"))}function p(a){a.preventDefault();var b=a.keyCode;if(void 0!==b&&null!==b){if(t.indexOf(b)>-1){if(null===s)return i(r.eq(0)),c=1,void(d=1);n(b)}else b===u&&o();return!1}}var q=f.$dialog,r=q.find(".note-specialchar-node"),s=null,t=[k.UP,k.DOWN,k.LEFT,k.RIGHT],u=k.ENTER;if(j(r),b)for(var v=0;v<r.length;v++){var w=a(r[v]);w.text()===b&&(i(w),d=Math.ceil((v+1)/15),c=(v+1)%15)}g.onDialogShown(f.$dialog,function(){a(document).on("keydown",p),f.$dialog.find("button").tooltip(),r.on("click",function(b){b.preventDefault(),h.resolve(decodeURIComponent(a(b.currentTarget).find("button").attr("data-value"))),g.hideDialog(f.$dialog)})}),g.onDialogHidden(f.$dialog,function(){r.off("click"),f.$dialog.find("button").tooltip("destroy"),a(document).off("keydown",p),"pending"===h.state()&&h.reject()}),g.showDialog(f.$dialog)})}}})});
|
||||
Reference in New Issue
Block a user