I may try that.
>
> Of course, other options are:
>
> * you can revert your feature request to have shift-enter submit the cell :)
> (apparently you've personally done that...)
Yep, and it sucks and drives me crazy not having shift-enter submit...
Why can't TinyMCE just read my mind?
> * is there another shortcut key that you'd like?
What about control-enter? Can you make it so
control-enter = linebreak
shift-enter = submit
?
>
> Also, I've been thinking about how to add Rado's graph editor, an equation
> editor, and other nice input methods to the code cells. Basically, I'm
> looking at how to replace a small section of Sage code with a "widget" that
> represents the code nicely, all inside of the code cell. Requirements that
> make sense to me include:
>
> 1. When the cell is recreated (on page creation, for example), the user
> should see the widget, not the generated Sage code
> 2. The user should be able to highlight some Sage code and convert it to the
> widget (replacing the highlighted part with the graphical div). If the sage
> code is not understood by the widget, then some sort of error should be
> signaled (maybe an alert box?) and the code should remain in the cell.
> 3. The user should be able to toggle between seeing the Sage code text and
> the widget representation, on a widget-by-widget basis.
>
> Point (1) requires that the cell understand that some sort of widget
> represents the code between character positions x and y. What's the easiest
> way to store/send that sort of metadata along with the cell?
>
> We probably don't want to use tinymce---it's way too heavyweight for this
> and has *lots* of unneeded functionality.
>
> This will probably necessitate subtle changes in the existing javascript for
> code cells, as we can't use textareas anymore, but instead will use some
> sort of contentEditable divs for code cells. This also exposes us to lots
> of cross-browser support issues, I believe. It seems that a major issue for
> the html wysiwyg editors is how well they support different browsers.
>
> What do you think?
Ouch. Oh the pain. I would have to see a demo. I have never tried
any sort of contentEditable div before. I'm amazed how far we've gone
using textareas, to be honest.
-- William
Control-enter is bound to spliteval_cell. To make control-shift-enter,
say, insert a line break, try augmenting notebook.py's tinyMCE.init()'s
setup with some code ripped from the Safari plug-in:
// Around line 1840 of sage/server/notebook/notebook.py
setup : function(ed) {
ed.onKeyDown.add(function(ed, e) {
// Make ctrl-shift-enter insert a line break. Copied from
the Safari plug-in.
if (e.keyCode == 13 && e.shiftKey && e.ctrlKey) {
// Workaround for missing shift+enter support,
http://bugs.webkit.org/show_bug.cgi?id=16973
var dom = ed.dom, s = ed.selection, r = s.getRng(), br;
// Insert BR element
r.insertNode(br = dom.create('br'));
// Place caret after BR
r.setStartAfter(br);
r.setEndAfter(br);
s.setRng(r);
// Could not place caret after BR then insert an nbsp
entity and move the caret
if (s.getSel().focusNode == br.previousSibling) {
s.select(dom.insertAfter(dom.doc.createTextNode('\u00a0'), br));
s.collapse(1);
}
// Scroll to new position, scrollIntoView can't be
used due to bug: http://bugs.webkit.org/show_bug.cgi?id=16117
ed.getWin().scrollTo(0,
dom.getPos(s.getRng().startContainer).y);
tinymce.dom.Event.cancel(e);
}
});
// Make shift-enter quit editing. This is the "old" code.
ed.onKeyDown.add(function(ed, e) {
if (key_enter_shift(key_event(e))) {
$(ed.formElement).submit();
}
})
}
This seems to work on Linux in Firefox, Opera, and the Qt 4.5 WebKit
demo browser (e.g., /usr/lib64/qt4/demos/browser/browser).
Actually, that's how TinyMCE is implemented, so you've been using lots
of these contentEditable divs lately (well, probably actually an
ancestor to contentEditable divs). Since textareas can't contain
anything but text currently, we can't implement any sort of wysiwyg
mathematics with just a textarea.
What I'm talking about is a lightweight tinymce-like control that would
be able to sections of represent Sage code with a graphical widget, like
replacing Graph({0:[2,3], 1:[3],2:[3,4]}) with Rado's graph editor, or a
symbolic expression with Davide's equation editor. So in a cell, you
would see something like:
-----------------------------------------------------------------------
| ____________________________________________________ |
| | XX| |
| | Rado's graph editor | |
| G= | | |
| | | |
| ---------------------------------------------------- |
| |
----------------------------------------------------------------------
Clicking on the small XX in the upper right corner would replace the
graph editor with the corresponding code.
On the other hand, you could highlight "Graph({0:[2,3], 1:[3],2:[3,4]})"
in a cell and click a "Graph Editor" button that would then replace the
text with Rado's editor, as sketched above.
Does anyone here have experience with contentEditable divs? I don't,
but I'm learning slowly as I have time. Does anyone have good
experience with a very lightweight online edit control that lets us
easily replace random text with a div (containing the representing
widget)? I've looked at lots of different possibilities, but I don't
have experience with any other than TinyMCE. I haven't found anything
that strikes me as easy to modify for what we need and as lightweight as
we need.
Jason
I was primarily thinking of a way to *input* things with widgets, such
that the state (and widget) could be exactly reconstructed only from the
text when the notebook page was reloaded. It seems like it is a simpler
concept since you only have to rely on the text of the worksheet.
In your case, when the worksheet is reloaded, are all your graphical
changes to G lost? I was trying to think of a way to avoid this.
(Hence the insistence that any widget correspond to an exactly
equivalent piece of text in a cell, so that the widget could be
reconstructed from the text, and vice versa.)
Once you have that, though, you could do something like William's
concept with an @interact to continuously reset a graph to a different
value. I could see something like William's suggestion:
@interact
def (g=Widget('Graph()')):
global G = g
That would provide a graph control that keeps updating the global G.
Then you have the case of your prior example. In fact, it could be
arranged that G.visual_edit() pops up a cell that does exactly the above
code.
In this case, Widget(A) constructs a widget from the text A. Or you
could just have @interact automatically put Rado's graph editor in when
you do g=Graph().
Thanks for the discussion!
Jason