-
Notifications
You must be signed in to change notification settings - Fork 2
/
handlers.js
163 lines (141 loc) · 4.83 KB
/
handlers.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// handler functions for non-printable keys
Richie.prototype.enterKey = function( evt ) {
var cursor = this.m_cursor;
// char code is 10 on iphone for some reason
if( evt.keyCode == 13 || evt.keyCode == 10 ) {
Richie.trace( 'handling enter key' );
var ins = document.createElement( 'p' );
var restofline = cursor.nextSibling;
var nextparagraph = cursor.parentNode.nextSibling;
var outernode = cursor.parentNode.parentNode;
//var outernode = cursor.parentNode;
ins.appendChild( cursor );
if( restofline != null ) {
ins.appendChild( restofline );
}
outernode.insertBefore( ins, nextparagraph );
evt.preventDefault();
}
}
Richie.prototype.backspaceKey = function( evt ) {
var cursor = this.m_cursor;
// backspace
// iphone registers 127, other browsers use 8
if( evt.keyCode == 8 || evt.keyCode == 127 ) {
if( cursor.previousSibling ) {
Richie.trace( "backspace: prev sibling found" );
var prevlength = cursor.previousSibling.nodeValue.length;
Richie.trace( "prevlength: " + prevlength );
// workaround for iphone which doesn't update length of text node correctly
// we have to remove two chars, and I don't know why. The first backspace
// removes two chars, but subsequent calls remove only one.
if( Richie.isIphone ) {
cursor.previousSibling.splitText( prevlength - 2 );
}
else {
cursor.previousSibling.splitText( prevlength - 1 );
}
cursor.parentElement.removeChild( cursor.previousSibling );
}
// if we hit the end of a node, we merge the two nodes
else {
Richie.trace( "end of node" );
var contents = cursor.parentNode.innerHTML;
var nodeToDelete = cursor.parentNode;
var previousNode = nodeToDelete.previousSibling;
cursor.parentNode.parentNode.removeChild( nodeToDelete );
previousNode.innerHTML += contents;
}
}
}
Richie.prototype.leftArrow = function( evt ) {
var cursor = this.m_cursor;
// navigation
// should work on mobile devices that support arrow keys, iphone does not.
if( evt.keyCode == 37 ) { // left arrow
var rng = document.createRange();
var prev = cursor.previousSibling;
// we are at the edge of the node
if( prev == null ) {
Richie.trace( "node edge reached" );
// if prev is still null, either we are either traversing an empty
// node or we need to go up a level in the dom tree...
// in the case that we find a previous non-empty element, we need
// to not offset the range like we do for the nominal case below.
// TODO: handle these cases.
prev = cursor.parentNode.previousSibling.lastChild;
// try to navigate up in tree
/*
if( prev == null ) {
// check if we have reached the beginning of document
if( cursor.parentNode.parentNode == content ) { return; }
prev = cursor.parentNode.parentNode.lastChild;
}
*/
}
// length of the previous node - assumed to be text node
if( prev.nodeValue ) {
var prevlength = prev.nodeValue.length;
rng.setStart( prev, prevlength - 1 );
rng.setEnd( prev, prevlength - 1 );
rng.insertNode( cursor );
}
else {
cursor.parentNode.previousSibling.appendChild( cursor );
}
}
}
Richie.prototype.rightArrow = function( evt ) {
var cursor = this.m_cursor;
// right arrow
if( evt.keyCode == 39 ) {
var rng = document.createRange();
var next = cursor.nextSibling;
// we are at the edge of the node
if( next == null ) {
Richie.trace( "node edge reached" );
next = cursor.parentNode.nextSibling;
// detect end of document
if( next == null ) { return; }
}
// length of the next node - assumed to be text node
// we only need this to avoid errors if node is zero length
// var nextlength = cursor.previousSibling.nodeValue.length;
rng.setStart( next, 1 );
rng.setEnd( next, 1 );
rng.insertNode( cursor );
}
}
Richie.prototype.tabKey = function( evt ) {
var cursor = this.m_cursor;
// tab
if( evt.keyCode == 9 ) {
var text = this.convertCharcode( evt.keyCode );
// can't find a 'non-breaking tab', so insert nbsp
var textNode = document.createTextNode( "\u00a0\u00a0\u00a0\u00a0" );
cursor.parentNode.insertBefore( textNode, cursor );
// keeps browser in focus
evt.preventDefault();
evt.stopPropagation();
}
}
Richie.prototype.upArrow = function( evt ) {
var cursor = this.m_cursor;
// TODO: how to find correct position when traversing up
// and down. currently we just go to end of line
if( evt.keyCode == 38 ) { // up arrow
var previousParagraph = cursor.parentNode.previousSibling;
previousParagraph.appendChild( cursor );
// not sure if we really need preventdefault with arrow keys
evt.preventDefault();
}
}
Richie.prototype.downArrow = function( evt ) {
var cursor = this.m_cursor;
if( evt.keyCode == 40 ) { // down arrow
var previousParagraph = cursor.parentNode.nextSibling;
previousParagraph.appendChild( cursor );
// not sure if we really need preventdefault with arrow keys
evt.preventDefault();
}
}