[Fwd: A variation on Rado's graph editor]

15 views
Skip to first unread message

Pat LeSmithe

unread,
Jul 3, 2009, 1:18:23 PM7/3/09
to sage-...@googlegroups.com
I'm still reading through the replies to my off-list message, which I've
included below. They're provoking much thought! Please let me know if
it's OK to post them here, too, or feel free to bring them into the light...

-------- Original Message --------
Subject: A variation on Rado's graph editor
Date: Thu, 02 Jul 2009 13:29:37 -0700
From: Pat LeSmithe <qed777>
To: jason, rkirov, beezer


Hi Jason, Rado, and Rob!

Feeling a bit inspired, I put together a preliminary experiment with
contentEditable divs and Rado's graph editor:

http://www.math.uiuc.edu/~rkirov2/processing/grapheditor_live.html

I've attached an archive of a few files. The main file is
contedit.html, which pulls graphed.html, which pulls
processing.editor.min.js. Google provides jQuery/UI.

I tried using processingjs.org's processing.min.js, but it seemed the
strain on my computer was even greater. However, I don't know much
about *any* flavor of Processing. It's also quite possible that I broke
something during the mischief. One oddity: The canvas's location on
the page seems to affect the accuracy of clicks, at least in Firefox 3.5.

Other issues: Re-opening multiple editors can trigger a reload, or
perhaps just the randomizing routine. The styles may clash. I'm sure
there are many more...

Of course, this is only an example. There's also much to do, e.g.,
making the whole framework generic, working with selections, ensuring
editor instances don't clash, integrating with the notebook, maybe
converting the editor to pure JavaScript, etc.

I found this contentEditable demo somewhat informative:

http://www.quirksmode.org/dom/execCommand/

Take care!

Sincerely,
Mitesh Patel


contedit.tbz2

Rob Beezer

unread,
Jul 3, 2009, 1:41:51 PM7/3/09
to sage-devel
(my reply off-list)

This is very promising! This all worked very smoothly on my machine,
the window-in-a-window and the graph editor itself. I'm on just
Firefox 3.0.11.

I don't see anything in the Sage output or Latex output tabs, but
maybe I'm not suppose to? To the right of the tabs I have a couple of
stray buttons. I know it is an example, so if this what you expect,
then its no problem - just thought I'd mention it.

For output you can write

g=Graph( data = {0:[1]}, pos = {0:[2.0,3.0], 1:[5.6,3.4]} )

so all the properties can be combined in one call. Not sure if you or
Rado are building that output. ;-)

Rob

Jason Grout

unread,
Jul 3, 2009, 2:39:45 PM7/3/09
to sage-...@googlegroups.com
Pat LeSmithe wrote:
> I'm still reading through the replies to my off-list message, which I've
> included below. They're provoking much thought! Please let me know if
> it's OK to post them here, too, or feel free to bring them into the light...
>
> -------- Original Message --------
> Subject: A variation on Rado's graph editor
> Date: Thu, 02 Jul 2009 13:29:37 -0700
> From: Pat LeSmithe <qed777>
> To: jason, rkirov, beezer
>
>
> Hi Jason, Rado, and Rob!
>
> Feeling a bit inspired, I put together a preliminary experiment with
> contentEditable divs and Rado's graph editor:

This is really great! Thanks for posting the code!

Looking at this code last night helped me to have a better idea of what
I'm thinking as well.

I envision the sage code cells having javascript plugins. A plugin
would be a javascript object or something that, given a piece of sage
code, could return an html "widget" that represents that sage code in
some nice, possibly interactive way, and could be queried for a string
of Sage code that represents the current state of the widget.

The sage code cell (a designmode iframe or contenteditable div) would
then provide some way of activating the widget from a text selection (or
from an empty string, if no text is selected). When a widget is
activated, the following sort of thing is inserted into the code cell,
either replacing the selected text or just at the current position if no
text is selected:

<div class="widgetcontainer"><div class="code">sage code that the widget
represents</div><div class="widget">html code returned by the
plugin</span></div>

The code cell would provide a way to toggle the text and the widget
spans visible or hidden (or deleting it completely). Both the text and
the widget update each other on a change (i.e., if the user changes the
text, the widget updates; if the user changes the widget, the text
updates). Obviously there can be some shortcuts here if one or the
other is not visible.

When the code cell is evaluated, the text is extracted from each
widgetcontainer. In addition, metadata is sent to the sage server
marking where the widgets are (e.g., widget "GraphEditor" surrounds the
text from character position 120 to 133).

Here are some other plugins that could be implemented:

1. An image representation. When first invoked, it has a blank space.
Click on the blank space and a small javascript window opens up that
allows you to upload an image to the sage server. Then the widget
contains a picture of the image. The underlying Sage code is the sage
code that references the image file.

2. A list of points constructor -- if you want a series of 2d points,
then get something like Rado's editor to just return the list of
coordinates.

3. Like Rob Beezer has mentioned, an equation editor, matrix editor, etc.

4. A widget that helps you choose the sloane sequence (i.e., provides a
search form, displays the sequence, etc.). The underlying Sage code is
"sloane_sequence(<whatever sequence number you picked>)".

Really, with a flexible, easy plugin framework, the sky is the limit!

What do you think? I've started working on something like this from the
code that was attached above (thanks!), but really, there are people
that are way better at this (and may have more time) than me! Feel free
to jump in!

Thanks,

Jason

Pat LeSmithe

unread,
Jul 4, 2009, 12:59:24 AM7/4/09
to sage-...@googlegroups.com
Jason Grout wrote:
> I envision the sage code cells having javascript plugins. A plugin
> would be a javascript object or something that, given a piece of sage
> code, could return an html "widget" that represents that sage code in
> some nice, possibly interactive way, and could be queried for a string
> of Sage code that represents the current state of the widget.

Thanks to everyone for their comments, ideas, and contributions, whether
they're either already here or forthcoming!

A quick note: I've posted a newer version at

http://trac.sagemath.org/sage_trac/ticket/6460

It should now work in Firefox 3/3.5 and sundry other browsers. But most
of the other the changes are cosmetic. I'm sure Jason is working on his
uber-cells...

By the way, does anyone have experience with the desktop package Tulip:

http://www.labri.fr/perso/auber/projects/tulip/

? Its focus appears to be 2D/3D interactive manipulation and
visualization of large graphs:

http://www.labri.fr/perso/auber/projects/tulip/samples.php

Rado

unread,
Jul 4, 2009, 5:13:18 AM7/4/09
to sage-devel
Alright, it was a struggle debugging javascript (i feel sorry for the
people that have to code in it for a living), but finally I am done
with the hook between the graph editor and sage notebook. Here is the
first prototype:

1) get http://www.math.uiuc.edu/~rkirov2/sage/graph_editor.zip

2) exact all files in %sage_dir%/local/notebook/javascript/
graph_editor/
(create that folder it wont be there)

3)open a notebook and run
load %sage_dir%/local/notebook/javascript/graph_editor/jquery.py
(replacing sage_dir with your sage directory)
or just copy/paste the file in question

4)try
g=graphs.PetersenGraph()
graph_editor(g)

A few known bugs(limitations):
- update button only updates the cell text, its up to you to hit
"evaluate" to send the new data to the server (can't do much about it,
since i dont want to mess with the server-side code).
- update puts graph named g by default.
- the remove edge by draggin only works in the iframe box

I agree with Jason that with the power of js these days, we can make
many cool plug-ins for SAGE (like the graph editor;) ). However,
practice it was quite a struggle to get this to work (it took me
almost as long to make it work with SAGE as to write the thing).

We have to decide how would plug-ins work:

1)Make a basic API for plug-ins to communicate directly with SAGE
server in some generic form (i think JSON is a standard for that
although i never used it). Currently, the server is made to talk only
to a cell because it spits out things like cell id and such.
~or~
2)Force all plug-ins go through updating cells first (like the
graph_editor does now for lack of alternative) by jquery trickery. I
dont like that this ties any client implementation with the notebook,
which is already quite heavy machinary (i stared at js.py for quite
some time). But then again this is already working, so no rewrite
needed.

Also, does anyone know a more graceful way of passing variables to an
iframe other than the current href="graph_editor?g=.....data..." ?

Rado
PS. LeSmithe, if you have time try to add the cool jqueryui thing with
detaches the iframes. Note that there is no need to explicitly refer
to the id of the cell where it was contained, since I used relative
jquery selectors. I feel i finally understand jquery's tricky
functions (ooh that reminds me jquery in SAGE is old, 1.3 has a new
tag closest() which is kinda cool).

Rob Beezer

unread,
Jul 4, 2009, 1:15:02 PM7/4/09
to sage-devel
Rado,

Excellent!!! This is really, really nice and a *huge* step forward.
This looks usable in its current state, even though I know there's
lots more to think about with regards to plugging it in properly. And
I'll be interested to see what Pat LeSmithe could add. Thanks for
your hard work on this.

The only limitation I'm seeing, that wasn't advertised, is that I
can't "drop" a vertex outside of the editor canvas, or outside of the
frame with the scrollbar. So effectively, I can't remove a vertex.
But maybe with a restart it might behave - I've got a few other weird
things going on at the moment in my browser. Anyway, I'll experiment
some more in the next couple of days and report back if this behavior
persists.

Rob


On Jul 4, 2:13 am, Rado <rki...@gmail.com> wrote:
> Alright, it was a struggle debugging javascript (i feel sorry for the
> people that have to code in it for a living), but finally I am done
> with the hook between the graph editor and sage notebook. Here is the
> first prototype:
>
> 1) gethttp://www.math.uiuc.edu/~rkirov2/sage/graph_editor.zip

Pat LeSmithe

unread,
Jul 4, 2009, 2:37:34 PM7/4/09
to sage-...@googlegroups.com
The following off-list exchange between Rob and Rado preceded Rado's
first post to this thread. I apologize for mis-paraphrasing Rado's
remarks, Rob's response to which Rado has, in some respects, already
replied.

Rob Beezer wrote:
> Radoslav Kirov wrote:
>> [about an editor window that communicates directly with the server]
>
> Yes, this is more what I have in mind. But why not have the editor open
> as a method call on the graph? This would make the import button
> unnecessary, and there could be several windows open at once for several
> different graphs. In a way you would be binding the window to the
> graph, as a sort of property, I guess.
>
> I think Jason is thinking larger and is looking for a framework that
> will also allow for things like equation editors, or maybe pallettes for
> symbols, that sort of thing.
>
> Radoslav Kirov wrote:
>> [about the disadvantage of opening a window just for quick changes,
>> plus the potential overhead of real-time client-server communication]
>
> I hadn't considered the communication cost to a remote server. But then
> I don't think it has to be that expensive. I would not send the
> "dragging" information for a vertex, or highlighting a vertex for an
> edge change. I would send: vertex addition, vertex removal, new vertex
> location, edge addition, edge removal. As minor local changes, its not
> much information, and if the Graph class doesn't have the right methods
> to deal with them, we can add them. and they probably only happen at
> the rate of every few seconds.

Some ways, not necessarily graceful...

Pushed by the parent, if the timing is right:

var push = function (data) {
$('#iframe1').contents().find('div#hidden').val(data);
}
push(data);

Or call a frame's function:

$('#iframe1')[0].contentWindow.do_something(data);

A somewhat safer alternative:

var ifr = $('<iframe> ... </iframe>');
ifr.bind('load', function () { push(data) });
$('#something').append(ifr);

But 'load' can fire too early in Opera. A generic probabilistic workaround:

setTimeout('push(data)', 1000);

or

var wrap = function () {
push(data);
}
setTimeout(wrap, 1000);

Another way, pulled by the frame:

$(document).ready({
data = $('#textarea1', top.document).val();
});

Reply all
Reply to author
Forward
0 new messages