##// END OF EJS Templates
Add linewrapping to text cells (new feature in CodeMirror).
Fernando Perez -
Show More
@@ -1,287 +1,288 b''
1 1 //----------------------------------------------------------------------------
2 2 // Copyright (C) 2008-2011 The IPython Development Team
3 3 //
4 4 // Distributed under the terms of the BSD License. The full license is in
5 5 // the file COPYING, distributed as part of this software.
6 6 //----------------------------------------------------------------------------
7 7
8 8 //============================================================================
9 9 // TextCell
10 10 //============================================================================
11 11
12 12 var IPython = (function (IPython) {
13 13
14 14 // TextCell base class
15 15
16 16 var TextCell = function (notebook) {
17 17 this.code_mirror_mode = this.code_mirror_mode || 'htmlmixed';
18 18 IPython.Cell.apply(this, arguments);
19 19 this.rendered = false;
20 20 this.cell_type = this.cell_type || 'text';
21 21 };
22 22
23 23
24 24 TextCell.prototype = new IPython.Cell();
25 25
26 26
27 27 TextCell.prototype.create_element = function () {
28 28 var cell = $("<div>").addClass('cell text_cell border-box-sizing');
29 29 cell.attr('tabindex','2');
30 30 var input_area = $('<div/>').addClass('text_cell_input border-box-sizing');
31 31 this.code_mirror = CodeMirror(input_area.get(0), {
32 32 indentUnit : 4,
33 33 mode: this.code_mirror_mode,
34 34 theme: 'default',
35 35 value: this.placeholder,
36 36 readOnly: this.read_only,
37 lineWrapping : true,
37 38 onKeyEvent: $.proxy(this.handle_codemirror_keyevent,this)
38 39 });
39 40 // The tabindex=-1 makes this div focusable.
40 41 var render_area = $('<div/>').addClass('text_cell_render border-box-sizing').
41 42 addClass('rendered_html').attr('tabindex','-1');
42 43 cell.append(input_area).append(render_area);
43 44 this.element = cell;
44 45 };
45 46
46 47
47 48 TextCell.prototype.bind_events = function () {
48 49 IPython.Cell.prototype.bind_events.apply(this);
49 50 var that = this;
50 51 this.element.keydown(function (event) {
51 52 if (event.which === 13) {
52 53 if (that.rendered) {
53 54 that.edit();
54 55 return false;
55 56 };
56 57 };
57 58 });
58 59 this.element.dblclick(function () {
59 60 that.edit();
60 61 });
61 62 };
62 63
63 64
64 65 TextCell.prototype.handle_codemirror_keyevent = function (editor, event) {
65 66 // This method gets called in CodeMirror's onKeyDown/onKeyPress
66 67 // handlers and is used to provide custom key handling. Its return
67 68 // value is used to determine if CodeMirror should ignore the event:
68 69 // true = ignore, false = don't ignore.
69 70
70 71 if (event.keyCode === 13 && (event.shiftKey || event.ctrlKey)) {
71 72 // Always ignore shift-enter in CodeMirror as we handle it.
72 73 return true;
73 74 }
74 75 return false;
75 76 };
76 77
77 78
78 79 TextCell.prototype.select = function () {
79 80 IPython.Cell.prototype.select.apply(this);
80 81 var output = this.element.find("div.text_cell_render");
81 82 output.trigger('focus');
82 83 };
83 84
84 85
85 86 TextCell.prototype.unselect = function() {
86 87 // render on selection of another cell
87 88 this.render();
88 89 IPython.Cell.prototype.unselect.apply(this);
89 90 };
90 91
91 92
92 93 TextCell.prototype.edit = function () {
93 94 if ( this.read_only ) return;
94 95 if (this.rendered === true) {
95 96 var text_cell = this.element;
96 97 var output = text_cell.find("div.text_cell_render");
97 98 output.hide();
98 99 text_cell.find('div.text_cell_input').show();
99 100 this.code_mirror.refresh();
100 101 this.code_mirror.focus();
101 102 // We used to need an additional refresh() after the focus, but
102 103 // it appears that this has been fixed in CM. This bug would show
103 104 // up on FF when a newly loaded markdown cell was edited.
104 105 this.rendered = false;
105 106 if (this.get_text() === this.placeholder) {
106 107 this.set_text('');
107 108 this.refresh();
108 109 }
109 110 }
110 111 };
111 112
112 113
113 114 // Subclasses must define render.
114 115 TextCell.prototype.render = function () {};
115 116
116 117
117 118 TextCell.prototype.get_text = function() {
118 119 return this.code_mirror.getValue();
119 120 };
120 121
121 122
122 123 TextCell.prototype.set_text = function(text) {
123 124 this.code_mirror.setValue(text);
124 125 this.code_mirror.refresh();
125 126 };
126 127
127 128
128 129 TextCell.prototype.get_rendered = function() {
129 130 return this.element.find('div.text_cell_render').html();
130 131 };
131 132
132 133
133 134 TextCell.prototype.set_rendered = function(text) {
134 135 this.element.find('div.text_cell_render').html(text);
135 136 };
136 137
137 138
138 139 TextCell.prototype.at_top = function () {
139 140 if (this.rendered) {
140 141 return true;
141 142 } else {
142 143 return false;
143 144 }
144 145 };
145 146
146 147
147 148 TextCell.prototype.at_bottom = function () {
148 149 if (this.rendered) {
149 150 return true;
150 151 } else {
151 152 return false;
152 153 }
153 154 };
154 155
155 156
156 157 TextCell.prototype.fromJSON = function (data) {
157 158 if (data.cell_type === this.cell_type) {
158 159 if (data.source !== undefined) {
159 160 this.set_text(data.source);
160 161 this.set_rendered(data.rendered || '');
161 162 this.rendered = false;
162 163 this.render();
163 164 }
164 165 }
165 166 };
166 167
167 168
168 169 TextCell.prototype.toJSON = function () {
169 170 var data = {};
170 171 data.cell_type = this.cell_type;
171 172 data.source = this.get_text();
172 173 return data;
173 174 };
174 175
175 176
176 177 // HTMLCell
177 178
178 179 var HTMLCell = function (notebook) {
179 180 this.placeholder = "Type <strong>HTML</strong> and LaTeX: $\\alpha^2$";
180 181 IPython.TextCell.apply(this, arguments);
181 182 this.cell_type = 'html';
182 183 };
183 184
184 185
185 186 HTMLCell.prototype = new TextCell();
186 187
187 188
188 189 HTMLCell.prototype.render = function () {
189 190 if (this.rendered === false) {
190 191 var text = this.get_text();
191 192 if (text === "") { text = this.placeholder; }
192 193 this.set_rendered(text);
193 194 this.typeset();
194 195 this.element.find('div.text_cell_input').hide();
195 196 this.element.find("div.text_cell_render").show();
196 197 this.rendered = true;
197 198 }
198 199 };
199 200
200 201
201 202 // MarkdownCell
202 203
203 204 var MarkdownCell = function (notebook) {
204 205 this.placeholder = "Type *Markdown* and LaTeX: $\\alpha^2$";
205 206 IPython.TextCell.apply(this, arguments);
206 207 this.cell_type = 'markdown';
207 208 };
208 209
209 210
210 211 MarkdownCell.prototype = new TextCell();
211 212
212 213
213 214 MarkdownCell.prototype.render = function () {
214 215 if (this.rendered === false) {
215 216 var text = this.get_text();
216 217 if (text === "") { text = this.placeholder; }
217 218 var html = IPython.markdown_converter.makeHtml(text);
218 219 this.set_rendered(html);
219 220 this.typeset()
220 221 this.element.find('div.text_cell_input').hide();
221 222 this.element.find("div.text_cell_render").show();
222 223 var code_snippets = this.element.find("pre > code");
223 224 code_snippets.replaceWith(function () {
224 225 var code = $(this).html();
225 226 /* Substitute br for newlines and &nbsp; for spaces
226 227 before highlighting, since prettify doesn't
227 228 preserve those on all browsers */
228 229 code = code.replace(/(\r\n|\n|\r)/gm, "<br/>");
229 230 code = code.replace(/ /gm, '&nbsp;');
230 231 code = prettyPrintOne(code);
231 232
232 233 return '<code class="prettyprint">' + code + '</code>';
233 234 });
234 235 this.rendered = true;
235 236 }
236 237 };
237 238
238 239
239 240 // RSTCell
240 241
241 242 var RSTCell = function (notebook) {
242 243 this.placeholder = "Type *ReStructured Text* and LaTeX: $\\alpha^2$";
243 244 IPython.TextCell.apply(this, arguments);
244 245 this.cell_type = 'rst';
245 246 };
246 247
247 248
248 249 RSTCell.prototype = new TextCell();
249 250
250 251
251 252 RSTCell.prototype.render = function () {
252 253 if (this.rendered === false) {
253 254 var text = this.get_text();
254 255 if (text === "") { text = this.placeholder; }
255 256 var settings = {
256 257 processData : false,
257 258 cache : false,
258 259 type : "POST",
259 260 data : text,
260 261 headers : {'Content-Type': 'application/x-rst'},
261 262 success : $.proxy(this.handle_render,this)
262 263 };
263 264 $.ajax("/rstservice/render", settings);
264 265 this.element.find('div.text_cell_input').hide();
265 266 this.element.find("div.text_cell_render").show();
266 267 this.set_rendered("Rendering...");
267 268 }
268 269 };
269 270
270 271
271 272 RSTCell.prototype.handle_render = function (data, status, xhr) {
272 273 this.set_rendered(data);
273 274 this.typeset();
274 275 this.rendered = true;
275 276 };
276 277
277 278
278 279 IPython.TextCell = TextCell;
279 280 IPython.HTMLCell = HTMLCell;
280 281 IPython.MarkdownCell = MarkdownCell;
281 282 IPython.RSTCell = RSTCell;
282 283
283 284
284 285 return IPython;
285 286
286 287 }(IPython));
287 288
General Comments 0
You need to be logged in to leave comments. Login now