]> git.ipfire.org Git - ipfire.org.git/blame - src/static/js/editor.js
wiki: Add keyboard shortcuts to edit text
[ipfire.org.git] / src / static / js / editor.js
CommitLineData
feeace6e
MT
1class Editor {
2 constructor(parent) {
3 this.parent = $(parent);
4
5 // Get the textarea
6 this.textarea = this.parent.find("textarea");
7
8 // Make the textarea magic
9 this.activateTextArea();
10
11 // Bind all keys
12 this.bindKeys();
13
14 console.log("Editor initialised for " + this.parent);
15 }
16
17 activateTextArea() {
18 var editor = this;
19
20 // Remember any selected text
18c36357 21 this.textarea.on("select keyup click", function(e) {
eea47e20
MT
22 // Ignore any keyboard shortcuts
23 if (e.ctrlKey)
24 return;
25
26 // Save selected text
feeace6e
MT
27 editor.selection = {
28 start : this.selectionStart,
29 end : this.selectionEnd,
18c36357
MT
30 text : this.value.slice(this.selectionStart, this.selectionEnd),
31 length: this.selectionEnd - this.selectionStart,
feeace6e
MT
32 };
33
34 console.debug("Something got selected:");
35 console.debug(editor.selection);
36 })
eea47e20
MT
37
38 // Bind keyboard shortcuts
39 this.textarea.on("keyup", function(e) {
40 // If Ctrl wasn't pressed this isn't for us
41 if (!e.ctrlKey)
42 return;
43
44 switch (e.which) {
45 // B - Bold
46 case 66:
47 editor.bold();
48 break;
49
50 // I - Italic
51 case 73:
52 editor.italic();
53 break;
54
55 // H - Headline
56 case 72:
57 editor.headline();
58 break;
59 }
60 });
feeace6e
MT
61 }
62
63 bindKeys() {
18c36357 64 // Typography
feeace6e
MT
65 this.parent.find("#bold").click(this.bold.bind(this));
66 this.parent.find("#italic").click(this.italic.bind(this));
18c36357
MT
67
68 // Headlines
69 this.parent.find("#headline").click(this.headline.bind(this));
70 this.parent.find("#headline-down").click(this.headline_down.bind(this));
71 this.parent.find("#headline-up").click(this.headline_up.bind(this));
feeace6e
MT
72 }
73
74 // Functions to modify the text
75
76 replaceSelection(replacement) {
6eb53879
MT
77 // Get the DOM element
78 var textarea = this.textarea.get(0);
feeace6e 79
6eb53879
MT
80 // Write text to textarea and move the cursor to the end
81 textarea.setRangeText(replacement,
82 this.selection.start, this.selection.end, "end");
feeace6e
MT
83 }
84
18c36357
MT
85 insertAtCursor(insertion) {
86 this.replaceSelection(insertion);
87 }
88
feeace6e
MT
89 bold() {
90 console.debug("Converting into bold: " + this.selection.text);
91 this.replaceSelection("**" + this.selection.text + "**");
92 }
93
94 italic() {
95 console.debug("Converting into italic: " + this.selection.text);
96 this.replaceSelection("*" + this.selection.text + "*");
97 }
18c36357
MT
98
99 // Headlines
100
101 findLevel() {
102 // Get all text between start and cursor position
103 var text = this.textarea.val().slice(0, this.selection.start);
104
105 // Split it in lines and reverse
106 var lines = text.split("\n");
107 lines.reverse();
108
109 for (var line of lines) {
110 console.debug(line);
111
112 // Return the number of # found in the nearest headline
113 var match = line.match("^(#+)");
114 if (match) {
115 return match[1].length;
116 }
117 }
118
119 // If nothing was found, we are on level one
120 return 1;
121 }
122
123 insertHeadline(offset) {
124 // Find level of headlines
125 var level = Math.max(this.findLevel() + offset, 1);
126
127 console.debug("Adding headline (" + level + ")");
128 var headline = "#".repeat(level);
129
130 if (this.selection.length == 0) {
131 headline += " ...";
132 } else {
133 // Add some space if we don't have any, yet
134 if (!this.selection.text.startsWith(" "))
135 headline += " ";
136
137 headline += this.selection.text + "\n\n";
138 }
139
140 this.replaceSelection(headline);
141 }
142
143 headline() {
144 return this.insertHeadline(0);
145 }
146
147 headline_down() {
148 return this.insertHeadline(1);
149 }
150
151 headline_up() {
152 return this.insertHeadline(-1);
153 }
feeace6e
MT
154}
155
156$(document).ready(function() {
157 // Initialise all editors
158 $(".editor").each(function(i, e) {
159 new Editor(e);
160 });
161});