Yesterday, I wanted to make an interact widget that showed an animation more
complicated than the animate command allows. So, on a plane trip, I hacked up
the following. It's a bit rough, and not a proper patch, etc. However, those
who care can paste it into a notebook and check it out.
The idea is simple. You want your interact to get updated every second with
some time dependence -- so add a timer, set the timeout to 1000 (milliseconds).
Note, this isn't an interact widget. It only produces the HTML that a widget
would -- so you can't actually use this in an interact yet -- but worry not,
I'll probably hack that up on the way home.
{{{
def html_timer(id, timeout, callback, wait_for_internet = True):
# if wait_for_internet:
# timeout = 'Math.max(%s,4*current_network_latency)'%timeout
#TODO: keep track of network latency by recording AJAX response times
# probably don't want to add overhead of recording every response,
# so time the keep_alive pings or something.
s = """
def html_timer(id, timeout, callback, wait_for_internet = True):
# if wait_for_internet:
# timeout = 'Math.max(%s,4*current_network_latency)'%timeout
s = """
<input type='hidden' id='%s' value='off'>
<input type='hidden' id='time_%s' value=0>
<table><tr>
<td><input type='button'
value='start'
id='start_%s'
onClick='var timer = get_element("time_%s");
var control = get_element("%s");
if(control.value == "on") return;
control.value = "on"
timer.value = 0;
timer.onClick(0);'></td>
<td><input type='button'
value='pause'
id='stop_%s'
onClick='get_element("%s").value="off";'></td>
<td><input type='button'
value='continue'
id='continue_%s'
onClick='var timer = get_element("time_%s");
var control = get_element("%s");
if(control.value == "on") return;
control.value = "on"
timer.onClick(eval(timer.value));'></td>
</tr></table>
"""%(id,id,id,id,id,id,id,id,id,id)
run_once = """
get_element("time_%s").onClick = function(time_last) {
var TIMER = get_element("time_%s");
var CONTROL = get_element("%s");
if(CONTROL.value != "on") return; //quit!
var time = eval(TIMER.value);
if(time != time_last) return; //break extraneous time loops
TIMER.value = time+1;
%s
setTimeout("get_element(\\'time_%s\\').onClick("+(time+1)+")", %s);
}
"""%(id,id,id,callback,id,timeout)
#convert lines to concatenated strings
#warning -- we messed up the callback if it had single-quotes
#in it. TODO: fix that
run_once = "+".join("'"+r+"\\n'" for r in run_once.split("\n"))
s+= """
<script>setTimeout(%s);</script>
"""%(run_once)
return s
}}}
The following is the only reasonable example right now, since I haven't
actually made the widget. Don't do alerts unless you want to crash your
browser.
{{{
t = "<span id='foo'></span>"
t+= html_timer('timer-007',10,'get_element("foo").innerHTML = time;',False)
print t
print html(t)
}}}
Comments? I think that it'd be best to hide useless buttons (stop while
already stopped, start & continue while running). Other than that, I like it.
--~--~---------~--~----~------------~-------~--~----~
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at http://groups.google.com/group/sage-devel
URLs: http://www.sagemath.org
-~----------~----~----~----~------~----~------~--~---