Show More
@@ -34,7 +34,7 b' var IPython = (function (IPython) {' | |||||
34 | this.element = null; |
|
34 | this.element = null; | |
35 | this.metadata = {}; |
|
35 | this.metadata = {}; | |
36 | // load this from metadata later ? |
|
36 | // load this from metadata later ? | |
37 |
this.user_highlight = |
|
37 | this.user_highlight = 'auto'; | |
38 | this.create_element(); |
|
38 | this.create_element(); | |
39 | if (this.element !== null) { |
|
39 | if (this.element !== null) { | |
40 | this.element.data("cell", this); |
|
40 | this.element.data("cell", this); |
@@ -159,7 +159,7 b' var IPython = (function (IPython) {' | |||||
159 | this.send(document.cookie); |
|
159 | this.send(document.cookie); | |
160 | }; |
|
160 | }; | |
161 | var already_called_onclose = false; // only alert once |
|
161 | var already_called_onclose = false; // only alert once | |
162 | ws_closed_early = function(evt){ |
|
162 | var ws_closed_early = function(evt){ | |
163 | if (already_called_onclose){ |
|
163 | if (already_called_onclose){ | |
164 | return; |
|
164 | return; | |
165 | } |
|
165 | } | |
@@ -168,7 +168,7 b' var IPython = (function (IPython) {' | |||||
168 | that._websocket_closed(ws_url, true); |
|
168 | that._websocket_closed(ws_url, true); | |
169 | } |
|
169 | } | |
170 | }; |
|
170 | }; | |
171 | ws_closed_late = function(evt){ |
|
171 | var ws_closed_late = function(evt){ | |
172 | if (already_called_onclose){ |
|
172 | if (already_called_onclose){ | |
173 | return; |
|
173 | return; | |
174 | } |
|
174 | } | |
@@ -379,7 +379,7 b' var IPython = (function (IPython) {' | |||||
379 |
|
379 | |||
380 |
|
380 | |||
381 | Kernel.prototype._handle_shell_reply = function (e) { |
|
381 | Kernel.prototype._handle_shell_reply = function (e) { | |
382 | reply = $.parseJSON(e.data); |
|
382 | var reply = $.parseJSON(e.data); | |
383 | $([IPython.events]).trigger('shell_reply.Kernel', {kernel: this, reply:reply}); |
|
383 | $([IPython.events]).trigger('shell_reply.Kernel', {kernel: this, reply:reply}); | |
384 | var header = reply.header; |
|
384 | var header = reply.header; | |
385 | var content = reply.content; |
|
385 | var content = reply.content; |
@@ -87,15 +87,15 b' var IPython = (function (IPython) {' | |||||
87 | $(document).keydown(function (event) { |
|
87 | $(document).keydown(function (event) { | |
88 | // console.log(event); |
|
88 | // console.log(event); | |
89 | if (that.read_only) return true; |
|
89 | if (that.read_only) return true; | |
90 |
|
90 | |||
91 |
// Save (CTRL+S) or (AppleKey+S) |
|
91 | // Save (CTRL+S) or (AppleKey+S) | |
92 | //metaKey = applekey on mac |
|
92 | //metaKey = applekey on mac | |
93 |
if ((event.ctrlKey || event.metaKey) && event.keyCode==83) { |
|
93 | if ((event.ctrlKey || event.metaKey) && event.keyCode==83) { | |
94 | that.save_notebook(); |
|
94 | that.save_notebook(); | |
95 | event.preventDefault(); |
|
95 | event.preventDefault(); | |
96 | return false; |
|
96 | return false; | |
97 | } else if (event.which === key.ESC) { |
|
97 | } else if (event.which === key.ESC) { | |
98 |
// Intercept escape at highest level to avoid closing |
|
98 | // Intercept escape at highest level to avoid closing | |
99 | // websocket connection with firefox |
|
99 | // websocket connection with firefox | |
100 | event.preventDefault(); |
|
100 | event.preventDefault(); | |
101 | } else if (event.which === key.SHIFT) { |
|
101 | } else if (event.which === key.SHIFT) { | |
@@ -280,7 +280,7 b' var IPython = (function (IPython) {' | |||||
280 | } |
|
280 | } | |
281 |
|
281 | |||
282 | this.element.bind('collapse_pager', function (event,extrap) { |
|
282 | this.element.bind('collapse_pager', function (event,extrap) { | |
283 | time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast'; |
|
283 | var time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast'; | |
284 | collapse_time(time); |
|
284 | collapse_time(time); | |
285 | }); |
|
285 | }); | |
286 |
|
286 | |||
@@ -288,12 +288,12 b' var IPython = (function (IPython) {' | |||||
288 | var app_height = $('div#main_app').height(); // content height |
|
288 | var app_height = $('div#main_app').height(); // content height | |
289 | var splitter_height = $('div#pager_splitter').outerHeight(true); |
|
289 | var splitter_height = $('div#pager_splitter').outerHeight(true); | |
290 | var pager_height = $('div#pager').outerHeight(true); |
|
290 | var pager_height = $('div#pager').outerHeight(true); | |
291 |
var new_height = app_height - pager_height - splitter_height; |
|
291 | var new_height = app_height - pager_height - splitter_height; | |
292 | that.element.animate({height : new_height + 'px'}, time); |
|
292 | that.element.animate({height : new_height + 'px'}, time); | |
293 | } |
|
293 | } | |
294 |
|
294 | |||
295 | this.element.bind('expand_pager', function (event, extrap) { |
|
295 | this.element.bind('expand_pager', function (event, extrap) { | |
296 | time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast'; |
|
296 | var time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast'; | |
297 | expand_time(time); |
|
297 | expand_time(time); | |
298 | }); |
|
298 | }); | |
299 |
|
299 | |||
@@ -317,7 +317,7 b' var IPython = (function (IPython) {' | |||||
317 | var time = time || 0; |
|
317 | var time = time || 0; | |
318 | cell_number = Math.min(cells.length-1,cell_number); |
|
318 | cell_number = Math.min(cells.length-1,cell_number); | |
319 | cell_number = Math.max(0 ,cell_number); |
|
319 | cell_number = Math.max(0 ,cell_number); | |
320 |
scroll_value = cells[cell_number].element.position().top-cells[0].element.position().top ; |
|
320 | var scroll_value = cells[cell_number].element.position().top-cells[0].element.position().top ; | |
321 | this.element.animate({scrollTop:scroll_value}, time); |
|
321 | this.element.animate({scrollTop:scroll_value}, time); | |
322 | return scroll_value; |
|
322 | return scroll_value; | |
323 | }; |
|
323 | }; | |
@@ -447,11 +447,11 b' var IPython = (function (IPython) {' | |||||
447 |
|
447 | |||
448 | Notebook.prototype.select = function (index) { |
|
448 | Notebook.prototype.select = function (index) { | |
449 | if (index !== undefined && index >= 0 && index < this.ncells()) { |
|
449 | if (index !== undefined && index >= 0 && index < this.ncells()) { | |
450 | sindex = this.get_selected_index() |
|
450 | var sindex = this.get_selected_index() | |
451 | if (sindex !== null && index !== sindex) { |
|
451 | if (sindex !== null && index !== sindex) { | |
452 | this.get_cell(sindex).unselect(); |
|
452 | this.get_cell(sindex).unselect(); | |
453 | }; |
|
453 | }; | |
454 | var cell = this.get_cell(index) |
|
454 | var cell = this.get_cell(index); | |
455 | cell.select(); |
|
455 | cell.select(); | |
456 | if (cell.cell_type === 'heading') { |
|
456 | if (cell.cell_type === 'heading') { | |
457 | $([IPython.events]).trigger('selected_cell_type_changed.Notebook', |
|
457 | $([IPython.events]).trigger('selected_cell_type_changed.Notebook', | |
@@ -651,7 +651,7 b' var IPython = (function (IPython) {' | |||||
651 | var source_element = this.get_cell_element(i); |
|
651 | var source_element = this.get_cell_element(i); | |
652 | var source_cell = source_element.data("cell"); |
|
652 | var source_cell = source_element.data("cell"); | |
653 | if (!(source_cell instanceof IPython.CodeCell)) { |
|
653 | if (!(source_cell instanceof IPython.CodeCell)) { | |
654 | target_cell = this.insert_cell_below('code',i); |
|
654 | var target_cell = this.insert_cell_below('code',i); | |
655 | var text = source_cell.get_text(); |
|
655 | var text = source_cell.get_text(); | |
656 | if (text === source_cell.placeholder) { |
|
656 | if (text === source_cell.placeholder) { | |
657 | text = ''; |
|
657 | text = ''; | |
@@ -673,7 +673,7 b' var IPython = (function (IPython) {' | |||||
673 | var source_element = this.get_cell_element(i); |
|
673 | var source_element = this.get_cell_element(i); | |
674 | var source_cell = source_element.data("cell"); |
|
674 | var source_cell = source_element.data("cell"); | |
675 | if (!(source_cell instanceof IPython.MarkdownCell)) { |
|
675 | if (!(source_cell instanceof IPython.MarkdownCell)) { | |
676 | target_cell = this.insert_cell_below('markdown',i); |
|
676 | var target_cell = this.insert_cell_below('markdown',i); | |
677 | var text = source_cell.get_text(); |
|
677 | var text = source_cell.get_text(); | |
678 | if (text === source_cell.placeholder) { |
|
678 | if (text === source_cell.placeholder) { | |
679 | text = ''; |
|
679 | text = ''; | |
@@ -816,7 +816,7 b' var IPython = (function (IPython) {' | |||||
816 | var cell_data = this.clipboard; |
|
816 | var cell_data = this.clipboard; | |
817 | var new_cell = this.insert_cell_above(cell_data.cell_type); |
|
817 | var new_cell = this.insert_cell_above(cell_data.cell_type); | |
818 | new_cell.fromJSON(cell_data); |
|
818 | new_cell.fromJSON(cell_data); | |
819 | old_cell = this.get_next_cell(new_cell); |
|
819 | var old_cell = this.get_next_cell(new_cell); | |
820 | this.delete_cell(this.find_cell_index(old_cell)); |
|
820 | this.delete_cell(this.find_cell_index(old_cell)); | |
821 | this.select(this.find_cell_index(new_cell)); |
|
821 | this.select(this.find_cell_index(new_cell)); | |
822 | }; |
|
822 | }; | |
@@ -874,8 +874,8 b' var IPython = (function (IPython) {' | |||||
874 | // Todo: implement spliting for other cell types. |
|
874 | // Todo: implement spliting for other cell types. | |
875 | var cell = this.get_selected_cell(); |
|
875 | var cell = this.get_selected_cell(); | |
876 | if (cell.is_splittable()) { |
|
876 | if (cell.is_splittable()) { | |
877 | texta = cell.get_pre_cursor(); |
|
877 | var texta = cell.get_pre_cursor(); | |
878 | textb = cell.get_post_cursor(); |
|
878 | var textb = cell.get_post_cursor(); | |
879 | if (cell instanceof IPython.CodeCell) { |
|
879 | if (cell instanceof IPython.CodeCell) { | |
880 | cell.set_text(texta); |
|
880 | cell.set_text(texta); | |
881 | var new_cell = this.insert_cell_below('code'); |
|
881 | var new_cell = this.insert_cell_below('code'); | |
@@ -903,9 +903,9 b' var IPython = (function (IPython) {' | |||||
903 | var index = this.get_selected_index(); |
|
903 | var index = this.get_selected_index(); | |
904 | var cell = this.get_cell(index); |
|
904 | var cell = this.get_cell(index); | |
905 | if (index > 0) { |
|
905 | if (index > 0) { | |
906 | upper_cell = this.get_cell(index-1); |
|
906 | var upper_cell = this.get_cell(index-1); | |
907 | upper_text = upper_cell.get_text(); |
|
907 | var upper_text = upper_cell.get_text(); | |
908 | text = cell.get_text(); |
|
908 | var text = cell.get_text(); | |
909 | if (cell instanceof IPython.CodeCell) { |
|
909 | if (cell instanceof IPython.CodeCell) { | |
910 | cell.set_text(upper_text+'\n'+text); |
|
910 | cell.set_text(upper_text+'\n'+text); | |
911 | } else if (cell instanceof IPython.MarkdownCell || cell instanceof IPython.HTMLCell) { |
|
911 | } else if (cell instanceof IPython.MarkdownCell || cell instanceof IPython.HTMLCell) { | |
@@ -923,9 +923,9 b' var IPython = (function (IPython) {' | |||||
923 | var index = this.get_selected_index(); |
|
923 | var index = this.get_selected_index(); | |
924 | var cell = this.get_cell(index); |
|
924 | var cell = this.get_cell(index); | |
925 | if (index < this.ncells()-1) { |
|
925 | if (index < this.ncells()-1) { | |
926 | lower_cell = this.get_cell(index+1); |
|
926 | var lower_cell = this.get_cell(index+1); | |
927 | lower_text = lower_cell.get_text(); |
|
927 | var lower_text = lower_cell.get_text(); | |
928 | text = cell.get_text(); |
|
928 | var text = cell.get_text(); | |
929 | if (cell instanceof IPython.CodeCell) { |
|
929 | if (cell instanceof IPython.CodeCell) { | |
930 | cell.set_text(text+'\n'+lower_text); |
|
930 | cell.set_text(text+'\n'+lower_text); | |
931 | } else if (cell instanceof IPython.MarkdownCell || cell instanceof IPython.HTMLCell) { |
|
931 | } else if (cell instanceof IPython.MarkdownCell || cell instanceof IPython.HTMLCell) { | |
@@ -1073,7 +1073,7 b' var IPython = (function (IPython) {' | |||||
1073 | Notebook.prototype.execute_selected_cell = function (options) { |
|
1073 | Notebook.prototype.execute_selected_cell = function (options) { | |
1074 | // add_new: should a new cell be added if we are at the end of the nb |
|
1074 | // add_new: should a new cell be added if we are at the end of the nb | |
1075 | // terminal: execute in terminal mode, which stays in the current cell |
|
1075 | // terminal: execute in terminal mode, which stays in the current cell | |
1076 | default_options = {terminal: false, add_new: true}; |
|
1076 | var default_options = {terminal: false, add_new: true}; | |
1077 | $.extend(default_options, options); |
|
1077 | $.extend(default_options, options); | |
1078 | var that = this; |
|
1078 | var that = this; | |
1079 | var cell = that.get_selected_cell(); |
|
1079 | var cell = that.get_selected_cell(); | |
@@ -1173,7 +1173,7 b' var IPython = (function (IPython) {' | |||||
1173 | if (cell_data.cell_type === 'plaintext'){ |
|
1173 | if (cell_data.cell_type === 'plaintext'){ | |
1174 | cell_data.cell_type = 'raw'; |
|
1174 | cell_data.cell_type = 'raw'; | |
1175 | } |
|
1175 | } | |
1176 |
|
1176 | |||
1177 | new_cell = this.insert_cell_below(cell_data.cell_type); |
|
1177 | new_cell = this.insert_cell_below(cell_data.cell_type); | |
1178 | new_cell.fromJSON(cell_data); |
|
1178 | new_cell.fromJSON(cell_data); | |
1179 | }; |
|
1179 | }; | |
@@ -1306,10 +1306,10 b' var IPython = (function (IPython) {' | |||||
1306 | var that = this; |
|
1306 | var that = this; | |
1307 | var orig_vs = 'v' + data.nbformat + '.' + data.orig_nbformat_minor; |
|
1307 | var orig_vs = 'v' + data.nbformat + '.' + data.orig_nbformat_minor; | |
1308 | var this_vs = 'v' + data.nbformat + '.' + this.nbformat_minor; |
|
1308 | var this_vs = 'v' + data.nbformat + '.' + this.nbformat_minor; | |
1309 | msg = "This notebook is version " + orig_vs + ", but we only fully support up to " + |
|
1309 | var msg = "This notebook is version " + orig_vs + ", but we only fully support up to " + | |
1310 | this_vs + ". You can still work with this notebook, but some features " + |
|
1310 | this_vs + ". You can still work with this notebook, but some features " + | |
1311 | "introduced in later notebook versions may not be available." |
|
1311 | "introduced in later notebook versions may not be available." | |
1312 |
|
1312 | |||
1313 | var dialog = $('<div/>'); |
|
1313 | var dialog = $('<div/>'); | |
1314 | dialog.html(msg); |
|
1314 | dialog.html(msg); | |
1315 | this.element.append(dialog); |
|
1315 | this.element.append(dialog); | |
@@ -1326,7 +1326,7 b' var IPython = (function (IPython) {' | |||||
1326 | }, |
|
1326 | }, | |
1327 | width: 400 |
|
1327 | width: 400 | |
1328 | }); |
|
1328 | }); | |
1329 |
|
1329 | |||
1330 | } |
|
1330 | } | |
1331 | // Create the kernel after the notebook is completely loaded to prevent |
|
1331 | // Create the kernel after the notebook is completely loaded to prevent | |
1332 | // code execution upon loading, which is a security risk. |
|
1332 | // code execution upon loading, which is a security risk. | |
@@ -1339,7 +1339,7 b' var IPython = (function (IPython) {' | |||||
1339 |
|
1339 | |||
1340 | Notebook.prototype.load_notebook_error = function (xhr, textStatus, errorThrow) { |
|
1340 | Notebook.prototype.load_notebook_error = function (xhr, textStatus, errorThrow) { | |
1341 | if (xhr.status === 500) { |
|
1341 | if (xhr.status === 500) { | |
1342 | msg = "An error occurred while loading this notebook. Most likely " + |
|
1342 | var msg = "An error occurred while loading this notebook. Most likely " + | |
1343 | "this notebook is in a newer format than is supported by this " + |
|
1343 | "this notebook is in a newer format than is supported by this " + | |
1344 | "version of IPython. This version can load notebook formats " + |
|
1344 | "version of IPython. This version can load notebook formats " + | |
1345 | "v"+this.nbformat+" or earlier."; |
|
1345 | "v"+this.nbformat+" or earlier."; | |
@@ -1361,7 +1361,7 b' var IPython = (function (IPython) {' | |||||
1361 | }); |
|
1361 | }); | |
1362 | } |
|
1362 | } | |
1363 | } |
|
1363 | } | |
1364 |
|
1364 | |||
1365 | IPython.Notebook = Notebook; |
|
1365 | IPython.Notebook = Notebook; | |
1366 |
|
1366 | |||
1367 |
|
1367 |
@@ -80,7 +80,7 b' $(document).ready(function () {' | |||||
80 | IPython.layout_manager.do_resize(); |
|
80 | IPython.layout_manager.do_resize(); | |
81 | $([IPython.events]).on('notebook_loaded.Notebook', function () { |
|
81 | $([IPython.events]).on('notebook_loaded.Notebook', function () { | |
82 | IPython.layout_manager.do_resize(); |
|
82 | IPython.layout_manager.do_resize(); | |
83 | }) |
|
83 | }); | |
84 | IPython.notebook.load_notebook($('body').data('notebookId')); |
|
84 | IPython.notebook.load_notebook($('body').data('notebookId')); | |
85 |
|
85 | |||
86 | }); |
|
86 | }); |
@@ -47,7 +47,7 b' var IPython = (function (IPython) {' | |||||
47 | if(this.widget_dict[name] == undefined) { |
|
47 | if(this.widget_dict[name] == undefined) { | |
48 | return this.new_notification_widget(name); |
|
48 | return this.new_notification_widget(name); | |
49 | } |
|
49 | } | |
50 | return this.get_widget(name); |
|
50 | return this.get_widget(name); | |
51 | }; |
|
51 | }; | |
52 |
|
52 | |||
53 | NotificationArea.prototype.get_widget = function(name) { |
|
53 | NotificationArea.prototype.get_widget = function(name) { |
@@ -69,12 +69,12 b' var IPython = (function (IPython) {' | |||||
69 | var that = this; |
|
69 | var that = this; | |
70 |
|
70 | |||
71 | this.pager_element.bind('collapse_pager', function (event, extrap) { |
|
71 | this.pager_element.bind('collapse_pager', function (event, extrap) { | |
72 | time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast'; |
|
72 | var time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast'; | |
73 | that.pager_element.hide(time); |
|
73 | that.pager_element.hide(time); | |
74 | }); |
|
74 | }); | |
75 |
|
75 | |||
76 | this.pager_element.bind('expand_pager', function (event, extrap) { |
|
76 | this.pager_element.bind('expand_pager', function (event, extrap) { | |
77 | time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast'; |
|
77 | var time = (extrap != undefined) ? ((extrap.duration != undefined ) ? extrap.duration : 'fast') : 'fast'; | |
78 | that.pager_element.show(time); |
|
78 | that.pager_element.show(time); | |
79 | }); |
|
79 | }); | |
80 |
|
80 |
@@ -71,7 +71,7 b' IPython.utils = (function (IPython) {' | |||||
71 | separator2, match, lastIndex, lastLength; |
|
71 | separator2, match, lastIndex, lastLength; | |
72 | str += ""; // Type-convert |
|
72 | str += ""; // Type-convert | |
73 |
|
73 | |||
74 | compliantExecNpcg = typeof(/()??/.exec("")[1]) === "undefined" |
|
74 | var compliantExecNpcg = typeof(/()??/.exec("")[1]) === "undefined" | |
75 | if (!compliantExecNpcg) { |
|
75 | if (!compliantExecNpcg) { | |
76 | // Doesn't need flags gy, but they don't hurt |
|
76 | // Doesn't need flags gy, but they don't hurt | |
77 | separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags); |
|
77 | separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags); | |
@@ -157,7 +157,7 b' IPython.utils = (function (IPython) {' | |||||
157 |
|
157 | |||
158 |
|
158 | |||
159 | //Map from terminal commands to CSS classes |
|
159 | //Map from terminal commands to CSS classes | |
160 | ansi_colormap = { |
|
160 | var ansi_colormap = { | |
161 | "30":"ansiblack", "31":"ansired", |
|
161 | "30":"ansiblack", "31":"ansired", | |
162 | "32":"ansigreen", "33":"ansiyellow", |
|
162 | "32":"ansigreen", "33":"ansiyellow", | |
163 | "34":"ansiblue", "35":"ansipurple","36":"ansicyan", |
|
163 | "34":"ansiblue", "35":"ansipurple","36":"ansicyan", | |
@@ -192,7 +192,7 b' IPython.utils = (function (IPython) {' | |||||
192 | // Remove chunks that should be overridden by the effect of |
|
192 | // Remove chunks that should be overridden by the effect of | |
193 | // carriage return characters |
|
193 | // carriage return characters | |
194 | function fixCarriageReturn(txt) { |
|
194 | function fixCarriageReturn(txt) { | |
195 | tmp = txt; |
|
195 | var tmp = txt; | |
196 | do { |
|
196 | do { | |
197 | txt = tmp; |
|
197 | txt = tmp; | |
198 | tmp = txt.replace(/\r+\n/gm, '\n'); // \r followed by \n --> newline |
|
198 | tmp = txt.replace(/\r+\n/gm, '\n'); // \r followed by \n --> newline | |
@@ -263,14 +263,14 b' IPython.utils = (function (IPython) {' | |||||
263 | }; |
|
263 | }; | |
264 |
|
264 | |||
265 |
|
265 | |||
266 | points_to_pixels = function (points) { |
|
266 | var points_to_pixels = function (points) { | |
267 | // A reasonably good way of converting between points and pixels. |
|
267 | // A reasonably good way of converting between points and pixels. | |
268 | var test = $('<div style="display: none; width: 10000pt; padding:0; border:0;"></div>'); |
|
268 | var test = $('<div style="display: none; width: 10000pt; padding:0; border:0;"></div>'); | |
269 | $(body).append(test); |
|
269 | $(body).append(test); | |
270 | var pixel_per_point = test.width()/10000; |
|
270 | var pixel_per_point = test.width()/10000; | |
271 | test.remove(); |
|
271 | test.remove(); | |
272 | return Math.floor(points*pixel_per_point); |
|
272 | return Math.floor(points*pixel_per_point); | |
273 | } |
|
273 | }; | |
274 |
|
274 | |||
275 |
|
275 | |||
276 | return { |
|
276 | return { |
General Comments 0
You need to be logged in to leave comments.
Login now