forked from GitHub/gf-core
Improvements of "gf -server" mode and related setup
"gf -server" mode now contains everything needed to run the minibar and the grammar editor (including example-based grammar writing). The Setup.hs script installs the required files where gf -server can find them. These files have been moved to a new directory: src/www. The separate server program pgf-http is now obsolete.
This commit is contained in:
@@ -1,180 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html> <head>
|
||||
<title>About Minibar</title>
|
||||
<link rel=stylesheet type="text/css" href="minibar.css">
|
||||
<meta charset="UTF-8">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>About Minibar</h1>
|
||||
|
||||
<a href="minibar.html">Minibar</a> is an alternative implementation of the
|
||||
<a href="http://www.grammaticalframework.org/">GF</a> web app
|
||||
<a href="http://www.grammaticalframework.org:41296/fridge/">Fridge Poetry</a>.
|
||||
It doesn't do everything the original Fridge Poetry does (e.g. drag-and-drop is missing),
|
||||
so I refer to it as a minibar rather than a full refrigerator :-)
|
||||
|
||||
<p>
|
||||
Some implementation details:
|
||||
|
||||
<ul class=space>
|
||||
<li>It is implemented directly in JavaScipt. It does not use Google Web Toolkit or any big JavaScript libraries.
|
||||
<li>It has been tested and found to work in the following browsers:
|
||||
<ul>
|
||||
<li>On the Mac: Firefox 3.5 & 3.6, Safari 4.0, Opera 10.10 and
|
||||
Google Chrome 4.0.249.49.
|
||||
<li>On Linux: Firefox 3.0.18 & 3.5, Opera 10.10.
|
||||
<li>On the Android Dev Phone: Android Mobile Safari 3.0.4 & 3.1.2
|
||||
and Android Opera Mini 4.2.
|
||||
</ul>
|
||||
It does not seem work in Internet Explorer 7
|
||||
(there are both styling and scripting issues).
|
||||
There seems to be some rendering bugs in Chrome 5.0.342.9 β.
|
||||
<li>The implementation consist of two JavaScript files:
|
||||
<a href="minibar.js">minibar.js</a> and <a href="support.js">support.js</a>
|
||||
The latter is also used in
|
||||
<a href="http://spraakbanken.gu.se/swe/forskning/saldo/ordspel">a couple of
|
||||
small web apps</a> based on the
|
||||
<a href="http://spraakbanken.gu.se/sal/ws/">SALDO web services</a>.
|
||||
<li>To access the GF web service, it uses the
|
||||
<a href="http://en.wikipedia.org/wiki/JSON#JSONP">JSONP method</a>
|
||||
mentioned in the GF
|
||||
web services paper, which allows the web app to be hosted on a different server
|
||||
from the GF web service. (To demonstrate this, I put the Minibar demo on
|
||||
www.cs.chalmers.se, while the GF server that it calls is on
|
||||
www.grammaticalframework.org.)
|
||||
<li>As an experiment, it does no use the <code>grammars.xml</code> file,
|
||||
but instead calls a little CGI script,
|
||||
<a href="http://www.grammaticalframework.org:41296/grammars/grammars.cgi.txt">grammars.cgi</a>
|
||||
which lists the .pgf files in the directory, in JSONP format.
|
||||
(Note: if you want to install this on your own computer,
|
||||
<ul>
|
||||
<li>if you click on the link,
|
||||
the CGI script will be downloaded as <code>grammars.cgi.txt</code>,
|
||||
but it should be called <code>grammars.cgi</code> and stored on the server
|
||||
in the same directory as the grammar files.
|
||||
<li>for CGI scripts to work with lighttpd, <code>"mod_cgi"</code> needs
|
||||
to be included in the definition of <code>server.modules</code> in the
|
||||
<code>lighttpd.conf</code> file.)
|
||||
</ul>
|
||||
<li>[Added 2010-02-16] There is a button for generating random sentences.
|
||||
<li>[Added 2010-02-23] All translations are shown, not just the first one,
|
||||
if there are multiple parses.
|
||||
<li>[Added 2010-02-25] Next to each translation, there is now a little tree
|
||||
icon that you can click on to see a drawing of an abstract syntax tree or a
|
||||
parse tree. If you click on a drawing it collapses back into a tree icon.
|
||||
<li>[Added 2010-04-09] Preparations to support different ways to access the
|
||||
grammar: currently we access a PGF server via JSONP, but I would also like
|
||||
to support AJAX, and local/downloaded JavaScript grammars.
|
||||
<li>[Added 2010-04-19] A text entry field appears when you click in
|
||||
the sentence area (with a dashed border). This allows you to enter words by
|
||||
typing on the keyboard. As you start typing word magnets that don't match what
|
||||
you are typing are removed. When only one magnet remains, you can press enter
|
||||
to complete the word.
|
||||
<li>[Added 2010-04-19] There is a menu for choosing the output language:
|
||||
you can pick "All" to translate to all available languages, or pick one
|
||||
particular language.
|
||||
<li>[Added 2010-04-19] You can pass options to the function
|
||||
<code>start_minibar</code> to customize the user interface. The default is
|
||||
<code>{show_abstract:true,show_trees:true}</code> to show the abstract syntax
|
||||
of parsed sentences, and to show icons that expand to syntax/parse trees next
|
||||
each translation.
|
||||
These features can be turned off by setting the fields to <code>false</code>.
|
||||
<li>[Added 2010-04-30] The grammar menu is omitted if there is only one
|
||||
grammar in the grammar list.
|
||||
<li>[Added 2010-04-30] Fewer hardwired constants and new
|
||||
<code>start_minibar</code> options (server, grammars_url, grammar_list,
|
||||
show_grouped_translations, delete_button_text) to make
|
||||
<code>minibar.js</code> more resuable.)
|
||||
<li>[Added 2010-05-26] The magnets are now created with
|
||||
<code><input type=button></code> tags to make them clickable in more
|
||||
browsers.
|
||||
<li>[Added 2010-05-26] The text entry field is now visible from the start,
|
||||
and it is removed when no more words can be added to the sentence. When you
|
||||
press enter, a word is added if there is only one magnet left,
|
||||
<em>or</em> if what you have entered exactly matches one of the remaining
|
||||
magnet.
|
||||
<li>[Added 2010-05-28] Added a link to make it easy to try the same sentence in
|
||||
<a href="http://translate.google.com">Google Translate</a>.This can be
|
||||
turned off by passing the option <code>{try_google:false}</code> to
|
||||
<code>start_minibar</code>.
|
||||
<li>[Added 2010-06-02] Added support for Help and Feedback buttons, controlled
|
||||
by the options <code>feedback_url</code> and <code>help_url</code> passed to
|
||||
<code>start_minibar</code>.
|
||||
<li>[Added 2010-06-02] New option: <code>default_source_language</code>.
|
||||
<li>[Added 2010-09-10] Minibar now automatically uses
|
||||
<a href="http://en.wikipedia.org/wiki/XMLHttpRequest">XHR</a>
|
||||
instead of JSONP when possible (i.e. when the HTML document and the
|
||||
PGF service are on the same server).
|
||||
<li>[Added 2010-09-10] The default input language is now the user's preferred
|
||||
language, if possible. This is implemented by consulting the
|
||||
<code>userLanguage</code> field in the grammar info output by pgf-server.
|
||||
<li>[Added 2010-10-27] Keyboard input and completion should now work much
|
||||
more smoothly:
|
||||
<ul>
|
||||
<li>When you press space, the current word will be completed (if incomplete)
|
||||
and a new magnet will be created. If there is more than one possible
|
||||
completion, no magnet is created, but the common prefix of the possible
|
||||
completions is added to the text box.
|
||||
<li>Instead of asking the server for possible completions every time a new
|
||||
letter is added to the curent word, minibar only ask for completions for
|
||||
whole words and then filters the list locally when more letters are entered,
|
||||
speeding things up when server responses are slow.
|
||||
</ul>
|
||||
<li>[Added 2010-10-27] Code restructuring:
|
||||
<ul>
|
||||
<li>The PGF server API has been moved to its own file:
|
||||
<a href="pgf_online.js">pgf_online.js</a>. This
|
||||
allows it to be reused in other applicaitons without importing the entire
|
||||
minibar. It also allows minibar to be used with different server
|
||||
interfaces. <a href="minibar.html">minibar.html</a> has been updated to
|
||||
show how you use the new <a href="minibar.js">minibar.js</a> and
|
||||
<a href="pgf_online.js">pgf_online.js</a>.
|
||||
<li>The minibar code has been rewritten to avoid storing state information
|
||||
in the document tree and accessing it by referring to named document
|
||||
elements. The code now also avoids using string literals containing
|
||||
the names of top-level functions to specify event handlers for buttons
|
||||
and menus. (The code is no longer introspective, so α conversion
|
||||
will not change its meaning.)
|
||||
</ul>
|
||||
<li>[Added 2010-11-09] Some new documentation:
|
||||
<ul>
|
||||
<li><a href="gf-web-api-examples.html">gf-web-api-examples.html</a>:
|
||||
examples illustrating the PGF server API provided by
|
||||
<a href="pgf_online.js">pgf_online.js</a>.
|
||||
<li><a href="example.html">example.html</a>: a minimal example of a web
|
||||
page that uses <a href="pgf_online.js">pgf_online.js</a> to talk to the
|
||||
PGF server.
|
||||
</ul>
|
||||
<li>[Added 2011-03-03] Added a button to display word alignment.
|
||||
<li>[Changed 2011-03-22] Don't force focus to the typed input field
|
||||
after every word. On touch-based devices, the on-screen keyboard kept
|
||||
popping up after every word, which was very annoying if you were
|
||||
entering a sentence by tapping on the magnets.
|
||||
<li>[Changed 2011-08-03] Moved the initialization code in minibar.html to
|
||||
<a href="minibar_online.js">minibar_online.js</a>.
|
||||
<li>[Changed 2011-08-08] For improved modularity and reusability,
|
||||
two smaller objects have been factored out from the Minibar object:
|
||||
Input and Translations. These have been placed in two separate files:
|
||||
<a href="minibar_input.js">minibar_input.js</a> and
|
||||
<a href="minibar_translations.js">minibar_translations.js</a>.
|
||||
Some common auxiliary functions have also been moved to a separate file:
|
||||
<a href="minibar_support.js">minibar_support.js</a>.
|
||||
<li>[Added 2011-08-09] Added some <a href="minibar-api.html">Minibar API</a>
|
||||
documentation.
|
||||
<li>[Changed 2011-08-22] Quick fix to allow literals to be entered:
|
||||
if you press Enter, the current word will be accepted, even if there are no
|
||||
matching completions.
|
||||
(You can now use names of people when constructing sentences in the Letter
|
||||
grammar, for example.)
|
||||
</ul>
|
||||
|
||||
<hr>
|
||||
<small class=modtime>
|
||||
<!-- hhmts start --> Last modified: Mon Aug 22 19:31:37 CEST 2011 <!-- hhmts end -->
|
||||
</small>
|
||||
<address>
|
||||
<a href="http://www.cs.chalmers.se/~hallgren/">TH</a>
|
||||
<img src="http://www.altocumulus.org/~hallgren/online.cgi?icon" alt=""></address>
|
||||
</address>
|
||||
</body> </html>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 138 B |
Binary file not shown.
|
Before Width: | Height: | Size: 35 KiB |
@@ -1,57 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html> <head>
|
||||
<title>PGF online server example</title>
|
||||
<style type="text/css">
|
||||
body { background: #ddd; }
|
||||
h1, h2, h3, small, th { font-family: sans-serif; }
|
||||
div.modtime { float: right; }
|
||||
.modtime { color: #666; white-space: nowrap; }
|
||||
</style>
|
||||
<script type="text/JavaScript" src="support.js"></script>
|
||||
<script type="text/JavaScript" src="pgf_online.js"></script>
|
||||
<script type="text/JavaScript">
|
||||
|
||||
var server_options={
|
||||
grammars_url: "http://www.grammaticalframework.org/grammars/",
|
||||
grammar_list: ["Foods.pgf"]
|
||||
}
|
||||
var pgf_server = pgf_online(server_options);
|
||||
|
||||
function call_server() {
|
||||
pgf_server.parse({from:"FoodsEng",input:document.forms[0].input.value},
|
||||
show_output)
|
||||
}
|
||||
|
||||
function show_output(parsed) {
|
||||
document.getElementById("output").innerHTML=parsed[0].trees[0]
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>PGF online server example</h1>
|
||||
|
||||
<form onsubmit="call_server(); return false">
|
||||
Input:
|
||||
<input name=input size=50 value="this cheese is expensive">
|
||||
<input type=submit value=Parse>
|
||||
|
||||
<p>
|
||||
Output:
|
||||
<span id=output></span>
|
||||
</form>
|
||||
|
||||
|
||||
<h2>Documentation</h2>
|
||||
<ul>
|
||||
<li><a href="gf-web-api-examples.html">GF Web API examples</a>
|
||||
</ul>
|
||||
|
||||
<hr>
|
||||
<div class=modtime><small>
|
||||
<!-- hhmts start --> Last modified: Wed Aug 3 16:52:51 CEST 2011 <!-- hhmts end -->
|
||||
</small></div>
|
||||
<address><a href="http://www.cse.chalmers.se/~hallgren/">TH</a></address>
|
||||
</body> </html>
|
||||
@@ -1,44 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
bin=bin
|
||||
AUTOHEADER=no
|
||||
. $bin/cgistart.sh
|
||||
|
||||
save_feedback() {
|
||||
getquery
|
||||
|
||||
if [ -n "$feedback_path" ] &&
|
||||
echo "t=$(date +%F+%T)&ip=$REMOTE_ADDR&$query&accept_language=$HTTP_ACCEPT_LANGUAGE&user_agent=$(echo -n $HTTP_USER_AGENT | plain2url)" >> "$feedback_path"
|
||||
then
|
||||
|
||||
pagestart "Thank you!"
|
||||
echo "Your feedback has been saved."
|
||||
begin script type="text/javascript"
|
||||
echo "setTimeout(function(){window.close()},4000);"
|
||||
end
|
||||
pageend
|
||||
|
||||
else
|
||||
|
||||
pagestart "Feedback error"
|
||||
echo "Your feedback could not be saved. Sorry."
|
||||
p
|
||||
tag 'input type=button onclick="javascript:history.back()" value="<- Go back"'
|
||||
pageend
|
||||
|
||||
fi
|
||||
}
|
||||
|
||||
view_feedback() {
|
||||
charset="UTF-8"
|
||||
pagestart "Collected Feedback"
|
||||
begin pre class=feedbacklist
|
||||
Reg show reverse drop color_depth,pixel_depth,outer_size,inner_size,available_screen_size from-url <"$PATH_TRANSLATED" | plain2html
|
||||
end
|
||||
pageend
|
||||
}
|
||||
|
||||
case "$PATH_TRANSLATED" in
|
||||
"") save_feedback ;;
|
||||
*) view_feedback
|
||||
esac
|
||||
@@ -1,48 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html> <head>
|
||||
<title>Feedback</title>
|
||||
<link rel=stylesheet type="text/css" href="minibar.css">
|
||||
<script type="text/JavaScript" src="support.js"></script>
|
||||
<script type="text/JavaScript" src="minibar.js"></script>
|
||||
<meta name = "viewport" content = "width = device-width">
|
||||
|
||||
</head>
|
||||
|
||||
<body onload="prefill_feedback_form()">
|
||||
|
||||
<h2><span id=grammar></span> Feedback</h2>
|
||||
|
||||
<form class=feedback name=feedback action="feedback.cgi" method="post">
|
||||
<input type=hidden name="grammar">
|
||||
|
||||
<p>
|
||||
<input type=hidden name="from"> <span class=field id=from>...</span> input:
|
||||
<input type=hidden name="input"> <span class=field id=input>...</span>
|
||||
|
||||
<div id=translation_box>
|
||||
<p><input type=hidden name="to"> <span class=field id="to">...</span> translation:
|
||||
<input type=hidden name="translation"> <span class=field id=translation>...</span>
|
||||
|
||||
<p><label accesskey="S">Suggest a better translation:
|
||||
<textarea rows=3 name="improvement"></textarea></label>
|
||||
</div>
|
||||
|
||||
<p><label accesskey="C">Comments:
|
||||
<br><textarea rows=5 name="comment"></textarea></label>
|
||||
|
||||
<p>
|
||||
<input type=submit value="Submit Feedback">
|
||||
<input type=button value="Cancel" onclick="window.close()">
|
||||
|
||||
|
||||
<input type=hidden name="inner_size">
|
||||
<input type=hidden name="outer_size">
|
||||
<input type=hidden name="screen_size">
|
||||
<input type=hidden name="available_screen_size">
|
||||
<input type=hidden name="color_depth">
|
||||
<input type=hidden name="pixel_depth">
|
||||
|
||||
</form>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,151 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>GF web services API examples</title>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
<style type="text/css">
|
||||
body { background: #ddd; }
|
||||
h1, h2, h3, small, th { font-family: sans-serif; }
|
||||
|
||||
dt { background: #cef; }
|
||||
dt.js { background: white; margin-bottom: 1ex; }
|
||||
dt.js em { color: #36f; }
|
||||
dd { background: #ffc; margin-top: 1ex; margin-bottom: 1ex; }
|
||||
|
||||
dl.apiexamples>dt, dl.apiexamples>dd { font-family: monospace; }
|
||||
dl.apiexamples>dd { white-space: pre; }
|
||||
|
||||
div.modtime { float: right; }
|
||||
.modtime { color: #666; white-space: nowrap; }
|
||||
|
||||
@media projection {
|
||||
div.intro { display: none; }
|
||||
|
||||
body {
|
||||
font-size: 150%;
|
||||
}
|
||||
|
||||
h2 { page-break-before: always; }
|
||||
|
||||
dl.apiexamples dd {
|
||||
page-break-after: always;
|
||||
/*border-style: none;*/
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<body>
|
||||
<h1>GF web services API examples</h1>
|
||||
|
||||
GF can be used interactively from the GF Shell. Some of the functionality
|
||||
availiable in the GF shell is also available via the GF web services API.
|
||||
|
||||
<p>
|
||||
The
|
||||
<a href="http://code.google.com/p/grammatical-framework/wiki/GFWebServiceAPI">GF
|
||||
Web Service API page</a> describes the calls supported by the GF web service
|
||||
API. Below, we illustrate these calls by examples, and also show
|
||||
how to make these calls from JavaScript using the API defined in
|
||||
<a href="pgf_online.js"><code>pgf_online.js</code></a>.
|
||||
|
||||
<p>
|
||||
<strong>Note</strong> that <code>pgf_online.js</code> was initially developed
|
||||
with one particular web application in mind (the minibar), so the server API was
|
||||
incomplete. It was simplified and generalized in August 2011 to support the
|
||||
full API.
|
||||
|
||||
<dl>
|
||||
<dt class=js>These boxes show what the calls look like in the JavaScript
|
||||
API defined in <code>pgf_online.js</code>.
|
||||
<dt>These boxes show the corresponding URLs sent to the PGF server.
|
||||
<dd>These boxes show the JSON (JavaScript data structures) returned by the PGF
|
||||
server. This will be passed to the callback function supplied in the
|
||||
call.
|
||||
</dl>
|
||||
|
||||
<h2>Initialization</h2>
|
||||
<dl class=apiexamples>
|
||||
<dt class=js>
|
||||
<em>// Select which server and grammars to use:</em>
|
||||
<br>var server_options = {
|
||||
<br> grammars_url: "http://www.grammaticalframework.org/grammars/",
|
||||
<br> grammar_list: ["Foods.pgf"] <em>// It's ok to skip this</em>
|
||||
<br>}
|
||||
<br>var server = pgf_online(server_options);
|
||||
</dl>
|
||||
|
||||
<h2>Examples</h2>
|
||||
|
||||
<dl class=apiexamples>
|
||||
<dt class=js> <em>// Get the list of available grammars</em>
|
||||
<br>server.get_grammarlist(callback)
|
||||
<dt>http://localhost:41296/grammars/grammars.cgi
|
||||
<dd>["Foods.pgf","Phrasebook.pgf"]
|
||||
<dt class=js> <em>// Select which grammar to use</em>
|
||||
<br>server.switch_grammar("Foods.pgf")
|
||||
<dt class=js><em>// Get list of concrete languages and other grammar info</em>
|
||||
<br>server.grammar_info(callback)
|
||||
<dt>http://localhost:41296/grammars/Foods.pgf
|
||||
<dd>{"name":"Foods",
|
||||
"userLanguage":"FoodsEng",
|
||||
"categories":["Comment","Float","Int","Item","Kind","Quality","String"],
|
||||
"functions":["Boring","Cheese","Delicious","Expensive","Fish","Fresh",
|
||||
"Italian","Mod","Pizza","Pred","That","These","This","Those","Very",
|
||||
"Warm","Wine"],
|
||||
"languages":[{"name":"FoodsBul","languageCode":""},
|
||||
{"name":"FoodsEng","languageCode":"en-US"},
|
||||
{"name":"FoodsFin","languageCode":""},
|
||||
{"name":"FoodsSwe","languageCode":"sv-SE"},
|
||||
...]
|
||||
}
|
||||
<dt class=js><em>// Get a random syntax tree</em>
|
||||
<br>server.get_random({},callback)
|
||||
<dt>http://localhost:41296/grammars/Foods.pgf?command=random
|
||||
<dd>[{"tree":"Pred (That Pizza) (Very Boring)"}]
|
||||
<dt class=js><em>// Linearize a syntax tree</em>
|
||||
<br>server.linearize({tree:"Pred (That Pizza) (Very Boring)",to:"FoodsEng"},callback)
|
||||
<dt>http://localhost:41296/grammars/Foods.pgf?command=linearize&tree=Pred+(That+Pizza)+(Very+Boring)&to=FoodsEng
|
||||
<dd>[{"to":"FoodsEng","text":"that pizza is very boring"}]
|
||||
<dt class=js>server.linearize({tree:"Pred (That Pizza) (Very Boring)"},callback)
|
||||
<dt>http://localhost:41296/grammars/Foods.pgf?command=linearize&tree=Pred+(That+Pizza)+(Very+Boring)
|
||||
<dd>[{"to":"FoodsBul","text":"онази пица е много еднообразна"},
|
||||
{"to":"FoodsEng","text":"that pizza is very boring"},
|
||||
{"to":"FoodsFin","text":"tuo pizza on erittäin tylsä"},
|
||||
{"to":"FoodsSwe","text":"den där pizzan är mycket tråkig"},
|
||||
...
|
||||
]
|
||||
<dt class=js><em>// Parse a string</em>
|
||||
<br>server.parse({from:"FoodsEng",input:"that pizza is very boring"},callback)
|
||||
<dt>http://localhost:41296/grammars/Foods.pgf?command=parse&input=that+pizza+is+very+boring&from=FoodsEng
|
||||
<dd>[{"from":"FoodsEng",
|
||||
"brackets":{"cat":"Comment","fid":10,"index":0,"children":[{"cat":"Item","fid":7,"index":0,"children":[{"token":"that"},{"cat":"Kind","fid":6,"index":0,"children":[{"token":"pizza"}]}]},{"token":"is"},{"cat":"Quality","fid":9,"index":0,"children":[{"token":"very"},{"cat":"Quality","fid":8,"index":0,"children":[{"token":"boring"}]}]}]},
|
||||
"trees":["Pred (That Pizza) (Very Boring)"]}]
|
||||
<dt class=js><em>// Translate to all available languages</em>
|
||||
<br>server.translate({from:"FoodsEng",input:"that pizza is very boring"},callback)
|
||||
<dd>...
|
||||
<dt class=js><em>// Translate to one language</em>
|
||||
<br>server.translate({input:"that pizza is very boring", from:"FoodsEng", to:"FoodsSwe"}, callback)
|
||||
<dt>http://localhost:41296/grammars/Foods.pgf?command=translate&input=that+pizza+is+very+boring&from=FoodsEng&to=FoodsSwe
|
||||
<dd>[{"from":"FoodsEng",
|
||||
"brackets":{"cat":"Comment","fid":10,"index":0,"children":[{"cat":"Item","fid":7,"index":0,"children":[{"token":"that"},{"cat":"Kind","fid":6,"index":0,"children":[{"token":"pizza"}]}]},{"token":"is"},{"cat":"Quality","fid":9,"index":0,"children":[{"token":"very"},{"cat":"Quality","fid":8,"index":0,"children":[{"token":"boring"}]}]}]},
|
||||
"translations":
|
||||
[{"tree":"Pred (That Pizza) (Very Boring)",
|
||||
"linearizations":
|
||||
[{"to":"FoodsSwe",
|
||||
"text":"den där pizzan är mycket tråkig"}]}]}]
|
||||
<dt class=js><em>// Get completions (what words could come next)</em>
|
||||
<br>server.complete({from:"FoodsEng",input:"that pizza is very "},callback)
|
||||
<dt>http://localhost:41296/grammars/Foods.pgf?command=complete&input=that+pizza+is+very+&from=FoodsEng
|
||||
<dd>[{"from":"FoodsEng",
|
||||
"brackets":{"cat":"_","fid":0,"index":0,"children":[{"cat":"Item","fid":7,"index":0,"children":[{"token":"that"},{"cat":"Kind","fid":6,"index":0,"children":[{"token":"pizza"}]}]},{"token":"is"},{"token":"very"}]},
|
||||
"completions":["boring","delicious","expensive","fresh","Italian","very","warm"],
|
||||
"text":""}]
|
||||
</dl>
|
||||
<hr>
|
||||
<div class=modtime><small>
|
||||
<!-- hhmts start --> Last modified: Sun Aug 21 10:52:43 CEST 2011 <!-- hhmts end -->
|
||||
</small></div>
|
||||
<address><a href="http://www.cse.chalmers.se/~hallgren/">TH</a></address>
|
||||
|
||||
@@ -1,235 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>GF web services API examples</title>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
<style type="text/css">
|
||||
body { background: #eee; }
|
||||
h1, h2, h3, small, th { font-family: sans-serif; }
|
||||
th { text-align: left; }
|
||||
h1,h2 { border-bottom: 2px solid black }
|
||||
dt { background: #cef; }
|
||||
code { background: #ffc; }
|
||||
dt.js { background: white; margin-bottom: 1ex; }
|
||||
dt.js em { color: #36f; }
|
||||
dd { background: #ffc; margin-top: 1ex; margin-bottom: 1ex; }
|
||||
|
||||
dl.apiexamples>dt, dl.apiexamples>dd { font-family: monospace; }
|
||||
dl.apiexamples>dd { white-space: pre; }
|
||||
|
||||
table.border { border-collapse: collapse; margin-top: 1ex; margin-bottom: 1ex; }
|
||||
table.border td, table.border th { border: 1px solid black; background: #fcfcfc; }
|
||||
|
||||
div.modtime { float: right; }
|
||||
.modtime { color: #666; white-space: nowrap; }
|
||||
|
||||
</style>
|
||||
|
||||
<body>
|
||||
<h1>Minibar API</h1>
|
||||
|
||||
The Minibar web app consists of the following objects:
|
||||
|
||||
<ul>
|
||||
<li><a href="#Minibar">Minibar</a>
|
||||
<li><a href="#Input">Input</a>
|
||||
<li><a href="#Translations">Translations</a>
|
||||
</ul>
|
||||
|
||||
They are described below.
|
||||
|
||||
<h2 id=Minibar>The Minibar object</h2>
|
||||
|
||||
<p>
|
||||
This object implements the complete Minibar web app. It is defined in
|
||||
<a href="minibar.js">minibar.js</a>. It also uses the <code>Input</code>
|
||||
and <code>Translations</code> objects described below, and some auxiliary
|
||||
functions defined in <a href="minibar_support.js">minibar_support.js</a>
|
||||
and <a href="support.js">support.js</a>, so to use it in an
|
||||
HTML file, you would normally include at least the following:
|
||||
|
||||
<blockquote><pre>
|
||||
<script type="text/JavaScript" src="minibar.js"></script>
|
||||
<script type="text/JavaScript" src="minibar_input.js"></script>
|
||||
<script type="text/JavaScript" src="minibar_translations.js"></script>
|
||||
<script type="text/JavaScript" src="minibar_support.js"></script>
|
||||
<script type="text/JavaScript" src="support.js"></script>
|
||||
</pre></blockquote>
|
||||
|
||||
<p>
|
||||
For an example, see <a href="minibar.html">minibar.html</a>.
|
||||
|
||||
<h3>Constructor</h3>
|
||||
|
||||
<code>var minibar=new Minibar(server,options,target)</code>
|
||||
|
||||
<ul>
|
||||
<li><code>server</code> is the PGF service object.
|
||||
<li><code>options</code> is an object where the following properties
|
||||
can be set to override various default options:
|
||||
<table class=border>
|
||||
<tr><th>Option<th>Default<th>Description
|
||||
<tr><td>show_abstract<td>false<td rowspan=3>See Translations,
|
||||
not used directly by Minibar
|
||||
<tr><td>show_trees<td>false
|
||||
<tr><td>show_grouped_translations<td>true
|
||||
<tr><td>delete_button_text<td>"⌫"<td rowspan=3>See Input,
|
||||
not used directly by Minibar
|
||||
<tr><td>default_source_language<td>null
|
||||
<tr><td>random_button<td>true
|
||||
<tr><td>try_google<td>true<td>Include a button to try the current
|
||||
sentence in Google Translate
|
||||
<tr><td>feedback_url<td>null<td>Include a button to open a feedback
|
||||
form. The HTTP server must be configured to handle form submissions
|
||||
for this to work.
|
||||
<tr><td>help_url<td>null<td>Include a button to open a help text.
|
||||
</table>
|
||||
<li><code>target</code> is the <code>id</code> of the HTML element inside
|
||||
which the minibar user interface is created. It can be omitted if
|
||||
the <code>id</code> is <code>minibar</code>. The HTML document should
|
||||
contain something like this:
|
||||
<blockquote><code><div id="minibar"></div></code></blockquote>
|
||||
</ul>
|
||||
|
||||
<h3>Methods</h3>
|
||||
There are several internal methods, but since this is a self-contained
|
||||
web app, there is usually no need to call any methods from outside.
|
||||
|
||||
<h2 id=Input>The Input object</h2>
|
||||
|
||||
This object handles user input. Text can be entered by typing or by clicking
|
||||
on the "refrigerator magnets".
|
||||
<p>
|
||||
It is defined in
|
||||
<a href="minibar_input.js">minibar_input.js</a>.
|
||||
It also uses some auxiliary functions defined
|
||||
in <a href="minibar_support.js">minibar_support.js</a>
|
||||
and <a href="support.js">support.js</a>, so to use it in an
|
||||
HTML file, you would normally include at least the following:
|
||||
|
||||
<blockquote><pre>
|
||||
<script type="text/JavaScript" src="minibar_input.js"></script>
|
||||
<script type="text/JavaScript" src="minibar_support.js"></script>
|
||||
<script type="text/JavaScript" src="support.js"></script>
|
||||
</pre></blockquote>
|
||||
|
||||
<h3>Constructor</h3>
|
||||
|
||||
<code>var input=new Input(server,translations,options)</code>
|
||||
|
||||
<ul>
|
||||
<li><code>server</code> is the PGF service object
|
||||
<li><code>options</code> is an object where the following properties
|
||||
can be set to override various default options:
|
||||
<table class=border>
|
||||
<tr><th>Option<th>Default<th>Description
|
||||
<tr><td>delete_button_text<td>"⌫"<td>the label for the button that deletes the last word
|
||||
<tr><td>default_source_language<td>null<td>the concrete language to
|
||||
use for input in case the user's browers doesn't supply a suitable
|
||||
default. If none is provided the first language in alphabetical
|
||||
order will be used.
|
||||
<tr><td>random_button<td>true<td>include a button to generate a
|
||||
random sentence
|
||||
</table>
|
||||
|
||||
<li><code>translations</code> is the object that is notified when the input
|
||||
has changed. In the minibar, this is the object that display translations, but
|
||||
other apps might of course use the entered text for other purposes.
|
||||
The following methods will be called:
|
||||
<ul>
|
||||
<li><code>translations.clear()</code> is called when there no entered
|
||||
text.
|
||||
<li><code>translations.translateFrom({from:<var>conc</var>,input:<var>string</var>})</code>
|
||||
is called when the user has entered some text. The <code>from</code>
|
||||
property is the name of the concrete syntax and the <code>input</code>
|
||||
property is the entered text.
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
<h3>Properties and user interface</h3>
|
||||
|
||||
The <code>input</code> object created by the <code>Input</code> constructor
|
||||
contains two field that the caller should add to the user interface:
|
||||
<ul>
|
||||
<li><code>input.main</code> is the main user interface where the current
|
||||
input and the refrigerator magnets are displayed.
|
||||
<li><code>input.menus</code> contains the menu for selecting input language,
|
||||
and buttons for deleting the last word, clearing the input and generating
|
||||
a random sentence (if enabled in the options)
|
||||
</ul>
|
||||
|
||||
<h3>Methods</h3>
|
||||
|
||||
<ul>
|
||||
<li><code>input.change_grammar(grammar_info)</code> should be called
|
||||
after a different grammar is selected in the <code>server</code> object. It
|
||||
will clear away old input and magnets, and update the input language menu
|
||||
with the languages available in the new grammar.
|
||||
|
||||
</ul>
|
||||
|
||||
<h2 id=Translations>The Translations object</h2>
|
||||
|
||||
This object display translations. It is defined in
|
||||
<a href="minibar_translations.js">minibar_translations.js</a>.
|
||||
It also uses some auxiliary functions defined
|
||||
in <a href="minibar_support.js">minibar_support.js</a>
|
||||
and <a href="support.js">support.js</a>, so to use it in an
|
||||
HTML file, you would normally include at least the following:
|
||||
|
||||
<blockquote><pre>
|
||||
<script type="text/JavaScript" src="minibar_input.js"></script>
|
||||
<script type="text/JavaScript" src="minibar_support.js"></script>
|
||||
<script type="text/JavaScript" src="support.js"></script>
|
||||
</pre></blockquote>
|
||||
|
||||
<h3>Constructor</h3>
|
||||
<code>var translations=new Translations(server,options)</code>
|
||||
<ul>
|
||||
<li><code>server</code> is the PGF service object.
|
||||
<li><p><code>options</code> is an object where the following properties
|
||||
can be set to override various default options:
|
||||
<table class=border>
|
||||
<tr><th>Option<th>Default<th>Description
|
||||
<tr><td>show_abstract<td>false<td>show the abstract syntax in addition
|
||||
to the concrete syntax for the translations
|
||||
<tr><td>show_trees<td>false<td>add buttons to display syntax trees
|
||||
next to translations.
|
||||
<tr><td>show_grouped_translations<td>true<td>in case there are
|
||||
multiple translations, group them by concrete language
|
||||
</table>
|
||||
|
||||
</ul>
|
||||
|
||||
<h3>Properties and user interface</h3>
|
||||
|
||||
|
||||
The <code>translations</code> object created by the
|
||||
<code>Translations</code> constructor contains two field that the caller
|
||||
should add to the user interface:
|
||||
<ul>
|
||||
<li><code>input.main</code> is the main user interface where the current
|
||||
translations are displayed.
|
||||
<li><code>input.menus</code> contains the menu for selecting target language.
|
||||
</ul>
|
||||
|
||||
<h3>Methods</h3>
|
||||
<ul>
|
||||
<li><code>translations.change_grammar(grammar_info)</code> should be called
|
||||
after a different grammar is selected in the <code>server</code> object. It
|
||||
will clear away old translations and update the target language menu
|
||||
with the languages available in the new grammar.
|
||||
</ul>
|
||||
|
||||
|
||||
<hr>
|
||||
<div class=modtime>
|
||||
<small class=modtime>
|
||||
HTML <!-- hhmts start --> Last modified: Sun Aug 21 19:11:35 CEST 2011 <!-- hhmts end -->
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<address>
|
||||
<a href="Http://www.cse.chalmers.se/~hallgren/">TH</a>
|
||||
</address>
|
||||
@@ -1,53 +0,0 @@
|
||||
body {
|
||||
background: #ccc url("brushed-metal.png");
|
||||
}
|
||||
|
||||
h1, h2, h3, small, th { font-family: sans-serif; }
|
||||
|
||||
th, td { vertical-align: baseline; text-align: left; }
|
||||
|
||||
div#surface {
|
||||
min-height: 3ex;
|
||||
margin: 5px;
|
||||
padding: 5px;
|
||||
border: 3px dashed #e0e0e0;
|
||||
}
|
||||
|
||||
div#words {
|
||||
min-height: 3ex;
|
||||
margin: 5px;
|
||||
padding: 6px;
|
||||
border: 3px solid #e0e0e0;
|
||||
}
|
||||
|
||||
div.word, span.word, div#words div, div#words input[type=button] {
|
||||
display: inline-block;
|
||||
font-family: sans-serif;
|
||||
font-size: 100%;
|
||||
background-color: white;
|
||||
border: 1px solid black;
|
||||
padding: 3px;
|
||||
margin: 3px;
|
||||
}
|
||||
|
||||
.invalid { color: red; }
|
||||
|
||||
div.modtime { float: right; }
|
||||
.modtime { color: #666; white-space: nowrap; }
|
||||
|
||||
ul.space>li { margin-top: 0.75ex; }
|
||||
|
||||
div#saldospel input[type=button] { font-size: 100%; }
|
||||
|
||||
div#saldospel input.correct { color: green; }
|
||||
div#saldospel input.incorrect { color: red; }
|
||||
|
||||
#surface input[type=text] { width: 5em; }
|
||||
|
||||
.feedback textarea { width: 95%; }
|
||||
|
||||
span.field { background-color: #eee; }
|
||||
|
||||
pre.feedbacklist { background: white }
|
||||
|
||||
img.button { padding: 1px; }
|
||||
@@ -1,41 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Minibar</title>
|
||||
<link rel=stylesheet type="text/css" href="minibar.css">
|
||||
|
||||
<meta name = "viewport" content = "width = device-width">
|
||||
<meta charset="UTF-8">
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>Minibar online</h2>
|
||||
<div id=minibar></div>
|
||||
|
||||
<noscript>This page doesn't works unless JavaScript is enabled.</noscript>
|
||||
|
||||
<hr>
|
||||
|
||||
<small>
|
||||
[<a href="about.html">About Minibar</a>
|
||||
| <a href="http://www.grammaticalframework.org:41296/fridge/">Original Fridge Poetry</a>
|
||||
& <a href="http://www.grammaticalframework.org:41296/translate/">Translator</a>]
|
||||
</small>
|
||||
<small class=modtime>
|
||||
HTML <!-- hhmts start --> Last modified: Mon Aug 8 18:04:22 CEST 2011 <!-- hhmts end -->
|
||||
</small>
|
||||
<address>
|
||||
<a href="http://www.cse.chalmers.se/~hallgren/">TH</a>
|
||||
<img src="http://www.altocumulus.org/~hallgren/online.cgi?icon" alt=""></address>
|
||||
|
||||
<script type="text/JavaScript" src="support.js"></script>
|
||||
<script type="text/JavaScript" src="minibar.js"></script>
|
||||
<script type="text/JavaScript" src="minibar_input.js"></script>
|
||||
<script type="text/JavaScript" src="minibar_translations.js"></script>
|
||||
<script type="text/JavaScript" src="minibar_support.js"></script>
|
||||
<script type="text/JavaScript" src="pgf_online.js"></script>
|
||||
<script type="text/javascript" src="minibar_online.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,176 +0,0 @@
|
||||
/* minibar.js
|
||||
needs: minibar_support.js, minibar_input.js, minibar_translations.js, support.js
|
||||
*/
|
||||
|
||||
/*
|
||||
// This is essentially what happens when you call start_minibar:
|
||||
if(server.grammar_list) grammars=server.grammar_list;
|
||||
else grammars=server.get_grammarlist();
|
||||
show_grammarlist(grammars)
|
||||
select_grammar(grammars[0])
|
||||
grammar_info=server.get_languages()
|
||||
show_languages(grammar_info)
|
||||
new_language()
|
||||
complete_output=get_completions()
|
||||
show_completions(complete_output)
|
||||
*/
|
||||
|
||||
// For backward compatibility:
|
||||
function start_minibar(server,opts,target) {
|
||||
if(target) opts.target=target;
|
||||
return new Minibar(server,opts);
|
||||
}
|
||||
|
||||
/* --- Main Minibar object -------------------------------------------------- */
|
||||
function Minibar(server,opts) {
|
||||
// Contructor, typically called when the HTML document is loaded
|
||||
|
||||
/* --- Configuration ---------------------------------------------------- */
|
||||
|
||||
// default values for options:
|
||||
this.options={
|
||||
target: "minibar",
|
||||
try_google: true,
|
||||
feedback_url: null,
|
||||
help_url: null
|
||||
}
|
||||
|
||||
// Apply supplied options
|
||||
if(opts) for(var o in opts) this.options[o]=opts[o];
|
||||
|
||||
/* --- Creating the components of the minibar --------------------------- */
|
||||
this.translations=new Translations(server,this.options)
|
||||
this.input=new Input(server,this.translations,this.options)
|
||||
|
||||
/* --- Creating user interface elements --------------------------------- */
|
||||
|
||||
this.menubar=empty("div");
|
||||
this.extra=div_id("extra");
|
||||
|
||||
this.minibar=element(this.options.target);
|
||||
this.minibar.innerHTML="";
|
||||
with(this) {
|
||||
appendChildren(menubar,[input.menus,translations.menus,input.buttons])
|
||||
appendChildren(minibar,[menubar,input.main,translations.main,extra]);
|
||||
append_extra_buttons(extra,options);
|
||||
}
|
||||
|
||||
/* --- Minibar client state initialisation ------------------------------ */
|
||||
this.grammar=null;
|
||||
|
||||
this.server=server;
|
||||
|
||||
/* --- Main program, this gets things going ----------------------------- */
|
||||
with(this) {
|
||||
if(server.grammar_list) show_grammarlist(server.grammar_list);
|
||||
else server.get_grammarlist(bind(show_grammarlist,this));
|
||||
}
|
||||
}
|
||||
|
||||
Minibar.prototype.show_grammarlist=function(grammars) {
|
||||
this.grammar_menu=empty_id("select","grammar_menu");
|
||||
with(this) {
|
||||
if(grammars.length>1) {
|
||||
function opt(g) { return option(g,g); }
|
||||
appendChildren(grammar_menu,map(opt,grammars));
|
||||
grammar_menu.onchange=
|
||||
bind(function() { select_grammar(grammar_menu.value); },this);
|
||||
insertFirst(menubar,grammar_menu);
|
||||
insertFirst(menubar,text("Grammar: "));
|
||||
}
|
||||
if(options.help_url)
|
||||
menubar.appendChild(button("Help",bind(open_help,this)));
|
||||
select_grammar(grammars[0]);
|
||||
}
|
||||
}
|
||||
|
||||
Minibar.prototype.select_grammar=function(grammar_name) {
|
||||
var t=this;
|
||||
//debug("select_grammar ");
|
||||
function change_grammar() {
|
||||
t.server.grammar_info(bind(t.change_grammar,t));
|
||||
}
|
||||
t.server.switch_grammar(grammar_name,change_grammar);
|
||||
}
|
||||
|
||||
Minibar.prototype.change_grammar=function(grammar_info) {
|
||||
var t=this;
|
||||
with(t) {
|
||||
//debug("show_languages ");
|
||||
grammar=grammar_info;
|
||||
|
||||
input.change_grammar(grammar)
|
||||
translations.change_grammar(grammar)
|
||||
}
|
||||
}
|
||||
|
||||
Minibar.prototype.append_extra_buttons=function(extra,options) {
|
||||
with(this) {
|
||||
if(options.try_google)
|
||||
extra.appendChild(button("Try Google Translate",bind(try_google,this)));
|
||||
if(options.feedback_url)
|
||||
appendChildren(extra,[text(" "),button("Feedback",bind(open_feedback,this))]);
|
||||
}
|
||||
}
|
||||
|
||||
Minibar.prototype.try_google=function() {
|
||||
with(this) {
|
||||
var to=translations.target_lang();
|
||||
var s=input.current.input;
|
||||
if(input.surface.typed) s+=input.surface.typed.value;
|
||||
var url="http://translate.google.com/?sl="
|
||||
+langpart(input.current.from,grammar.name);
|
||||
if(to!="All") url+="&tl="+to;
|
||||
url+="&q="+encodeURIComponent(s);
|
||||
window.open(url);
|
||||
}
|
||||
}
|
||||
|
||||
Minibar.prototype.open_help=function() {
|
||||
with(this) open_popup(options.help_url,"help");
|
||||
}
|
||||
|
||||
Minibar.prototype.open_feedback=function() {
|
||||
with(this) {
|
||||
// make the minibar state easily accessible from the feedback page:
|
||||
minibar.state={grammar:grammar,current:input.current,
|
||||
to:translations.to_menu.value,
|
||||
translations:translations.translations};
|
||||
open_popup(options.feedback_url,'feedback');
|
||||
}
|
||||
}
|
||||
|
||||
// This function is called from feedback.html
|
||||
function prefill_feedback_form() {
|
||||
var state=opener_element("minibar").state;
|
||||
var trans=state.translations;
|
||||
var gn=state.grammar.name
|
||||
var to=langpart(state.to,gn);
|
||||
|
||||
var form=document.forms.namedItem("feedback");
|
||||
setField(form,"grammar",gn);
|
||||
setField(form,"from",langpart(state.current.from,gn));
|
||||
setField(form,"input",state.current.input);
|
||||
setField(form,"to",to);
|
||||
if(to=="All") element("translation_box").style.display="none";
|
||||
else setField(form,"translation",trans.single_translation.join(" / "));
|
||||
|
||||
// Browser info:
|
||||
form["inner_size"].value=window.innerWidth+"×"+window.innerHeight;
|
||||
form["outer_size"].value=window.outerWidth+"×"+window.outerHeight;
|
||||
form["screen_size"].value=screen.width+"×"+screen.height;
|
||||
form["available_screen_size"].value=screen.availWidth+"×"+screen.availHeight;
|
||||
form["color_depth"].value=screen.colorDepth;
|
||||
form["pixel_depth"].value=screen.pixelDepth;
|
||||
|
||||
window.focus();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
se.chalmers.cs.gf.gwt.TranslateApp/align-btn.png
|
||||
|
||||
GET /grammars/Foods.pgf?&command=abstrtree&tree=Pred+(This+Fish)+(Very+Fresh)
|
||||
GET /grammars/Foods.pgf?&command=parsetree&tree=Pred+(This+Fish)+Expensive&from=FoodsAfr
|
||||
GET /grammars/Foods.pgf?&command=alignment&tree=Pred+(This+Fish)+Expensive
|
||||
*/
|
||||
@@ -1,277 +0,0 @@
|
||||
|
||||
/* --- Input object --------------------------------------------------------- */
|
||||
|
||||
function Input(server,translations,opts) { // Input object constructor
|
||||
this.server=server;
|
||||
this.translations=translations;
|
||||
|
||||
// Default values for options:
|
||||
this.options={
|
||||
delete_button_text: "⌫",
|
||||
default_source_language: null,
|
||||
random_button: true,
|
||||
}
|
||||
|
||||
// Apply supplied options
|
||||
if(opts) for(var o in opts) this.options[o]=opts[o];
|
||||
|
||||
// User interface elements
|
||||
this.main=empty("div");
|
||||
this.menus=empty("span");
|
||||
this.buttons=empty("span");
|
||||
this.surface=div_id("surface");
|
||||
this.words=div_id("words");
|
||||
this.from_menu=empty("select");
|
||||
|
||||
with(this) {
|
||||
appendChildren(main,[surface,words]);
|
||||
appendChildren(menus,[text(" From: "),from_menu])
|
||||
appendChildren(buttons,
|
||||
[button(options.delete_button_text,bind(delete_last,this),"H"),
|
||||
button("Clear",bind(clear_all,this),"L")]);
|
||||
if(options.random_button)
|
||||
buttons.appendChild(button("Random",bind(generate_random,this),"R"));
|
||||
}
|
||||
|
||||
/* --- Input client state initialization --- */
|
||||
this.current={from: null, input: ""};
|
||||
this.previous=null;
|
||||
|
||||
this.from_menu.onchange=bind(this.change_language,this);
|
||||
}
|
||||
|
||||
Input.prototype.change_grammar=function (grammar) {
|
||||
update_language_menu(this.from_menu,grammar);
|
||||
set_initial_language(this.options,this.from_menu,grammar);
|
||||
this.change_language();
|
||||
}
|
||||
|
||||
Input.prototype.change_language=function () {
|
||||
this.current.from=this.from_menu.value;
|
||||
this.clear_all();
|
||||
}
|
||||
|
||||
|
||||
Input.prototype.clear_all1=function() {
|
||||
with(this) {
|
||||
remove_typed_input();
|
||||
current.input="";
|
||||
previous=null;
|
||||
surface.innerHTML="";
|
||||
translations.clear();
|
||||
}
|
||||
}
|
||||
|
||||
Input.prototype.clear_all=function() {
|
||||
with(this) {
|
||||
clear_all1();
|
||||
get_completions();
|
||||
}
|
||||
}
|
||||
|
||||
Input.prototype.get_completions=function() {
|
||||
with(this) {
|
||||
//debug("get_completions ");
|
||||
words.innerHTML="...";
|
||||
server.complete({from:current.from,input:current.input},
|
||||
bind(show_completions,this));
|
||||
}
|
||||
}
|
||||
|
||||
Input.prototype.show_completions=function(complete_output) {
|
||||
with(this) {
|
||||
//debug("show_completions ");
|
||||
var completions=complete_output[0].completions;
|
||||
var emptycnt=add_completions(completions)
|
||||
if(true/*emptycnt>0*/) translations.translateFrom(current);
|
||||
else translations.clear();
|
||||
if(surface.typed && emptycnt==completions.length) {
|
||||
if(surface.typed.value=="") remove_typed_input();
|
||||
}
|
||||
else add_typed_input();
|
||||
}
|
||||
}
|
||||
|
||||
Input.prototype.add_completions=function(completions) {
|
||||
with(this) {
|
||||
if(words.timeout) clearTimeout(words.timeout),words.timeout=null;
|
||||
words.innerHTML="";
|
||||
words.completions=completions;
|
||||
words.word=[];
|
||||
var t=surface.typed ? surface.typed.value : "";
|
||||
var emptycnt=0;
|
||||
for(var i=0;i<completions.length;i++) {
|
||||
var s=completions[i];
|
||||
if(s.length>0) {
|
||||
var w=word(s);
|
||||
words.appendChild(w);
|
||||
words.word[i]=w;
|
||||
}
|
||||
else emptycnt++;
|
||||
}
|
||||
filter_completions(t,true);
|
||||
return emptycnt;
|
||||
}
|
||||
}
|
||||
|
||||
Input.prototype.filter_completions=function(t,dim) {
|
||||
with(this) {
|
||||
if(words.timeout) clearTimeout(words.timeout),words.timeout=null;
|
||||
words.filtered=t;
|
||||
//if(dim) debug('filter "'+t+'"');
|
||||
var w=words.word;
|
||||
words.count=0;
|
||||
var dimmed=0;
|
||||
var prefix=""; // longest common prefix, for completion
|
||||
for(var i=0;i<w.length;i++) {
|
||||
var s=words.completions[i];
|
||||
var keep=hasPrefix(s,t);
|
||||
if(keep) {
|
||||
if(words.count==0) prefix=s;
|
||||
else prefix=(commonPrefix(prefix,s));
|
||||
words.count++;
|
||||
}
|
||||
if(dim) {
|
||||
w[i].style.opacity= keep ? "1" : "0.5";
|
||||
if(keep) w[i].style.display="inline";
|
||||
else dimmed++;
|
||||
}
|
||||
else
|
||||
w[i].style.display=keep ? "inline" : "none";
|
||||
}
|
||||
words.theword=prefix;
|
||||
if(dimmed>0)
|
||||
words.timeout=setTimeout(function(){ filter_completions(t,false)},1000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Input.prototype.add_typed_input=function() {
|
||||
with(this) {
|
||||
if(!surface.typed) {
|
||||
var inp=empty("input","type","text");
|
||||
inp.value="";
|
||||
inp.setAttribute("accesskey","t");
|
||||
inp.style.width="10em";
|
||||
inp.onkeyup=bind(complete_typed,this);
|
||||
surface.appendChild(inp);
|
||||
surface.typed=inp;
|
||||
inp.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Input.prototype.remove_typed_input=function() {
|
||||
with(this) {
|
||||
if(surface.typed) {
|
||||
surface.typed.parentNode.removeChild(surface.typed);
|
||||
surface.typed=null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Input.prototype.complete_typed=function(event) {
|
||||
with(this) {
|
||||
//element("debug").innerHTML=show_props(event,"event");
|
||||
var inp=surface.typed;
|
||||
//debug('"'+inp.value+'"');
|
||||
var s=inp.value;
|
||||
var ws=s.split(" ");
|
||||
if(ws.length>1 || event.keyCode==13) {
|
||||
if(ws[0]!=words.filtered) filter_completions(ws[0],true);
|
||||
if(words.count==1) add_word(words.theword);
|
||||
else if(event.keyCode==13) add_word(ws[0]) // for literals
|
||||
else if(elem(ws[0],words.completions)) add_word(ws[0]);
|
||||
else if(words.theword.length>ws[0].length) inp.value=words.theword;
|
||||
}
|
||||
else if(s!=words.filtered) filter_completions(s,true)
|
||||
}
|
||||
}
|
||||
|
||||
Input.prototype.generate_random=function() {
|
||||
var t=this;
|
||||
function show_random(random) {
|
||||
t.clear_all1();
|
||||
t.add_words(random[0].text);
|
||||
}
|
||||
|
||||
function lin_random(abs) {
|
||||
t.server.linearize({tree:abs[0].tree,to:t.current.from},show_random);
|
||||
}
|
||||
t.server.get_random({},lin_random);
|
||||
}
|
||||
|
||||
Input.prototype.add_words=function(s) {
|
||||
with(this) {
|
||||
var ws=s.split(" ");
|
||||
for(var i=0;i<ws.length;i++)
|
||||
add_word1(ws[i]+" ");
|
||||
get_completions();
|
||||
}
|
||||
}
|
||||
|
||||
Input.prototype.word=function(s) {
|
||||
var t=this;
|
||||
function click_word() {
|
||||
if(t.surface.typed) t.surface.typed.value="";
|
||||
t.add_word(s);
|
||||
}
|
||||
return button(s,click_word);
|
||||
}
|
||||
|
||||
Input.prototype.add_word=function(s) {
|
||||
with(this) {
|
||||
add_word1(s+" ");
|
||||
if(surface.typed) {
|
||||
var s2;
|
||||
if(hasPrefix(s2=surface.typed.value,s)) {
|
||||
s2=s2.substr(s.length);
|
||||
while(s2.length>0 && s2[0]==" ") s2=s2.substr(1);
|
||||
surface.typed.value=s2;
|
||||
}
|
||||
else surface.typed.value="";
|
||||
}
|
||||
get_completions();
|
||||
}
|
||||
}
|
||||
|
||||
Input.prototype.add_word1=function(s) {
|
||||
with(this) {
|
||||
previous={ input: current.input, previous: previous };
|
||||
current.input+=s;
|
||||
var w=span_class("word",text(s));
|
||||
if(surface.typed) surface.insertBefore(w,surface.typed);
|
||||
else surface.appendChild(w);
|
||||
}
|
||||
}
|
||||
|
||||
Input.prototype.delete_last=function() {
|
||||
with(this) {
|
||||
if(surface.typed && surface.typed.value!="")
|
||||
surface.typed.value="";
|
||||
else if(previous) {
|
||||
current.input=previous.input;
|
||||
previous=previous.previous;
|
||||
if(surface.typed) {
|
||||
surface.removeChild(surface.typed.previousSibling);
|
||||
surface.typed.focus();
|
||||
}
|
||||
else surface.removeChild(surface.lastChild);
|
||||
translations.clear();
|
||||
get_completions();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* --- Auxiliary functions -------------------------------------------------- */
|
||||
|
||||
function set_initial_language(options,menu,grammar) {
|
||||
if(grammar.userLanguage) menu.value=grammar.userLanguage;
|
||||
else if(options.default_source_language) {
|
||||
for(var i=0;i<menu.options.length;i++) {
|
||||
var o=menu.options[i].value;
|
||||
var l=langpart(o,grammar.name);
|
||||
if(l==options.default_source_language) menu.value=o;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
// minibar_demo.js, assumes that minibar.js and pgf_online.js have been loaded.
|
||||
|
||||
var online_options={
|
||||
//grammars_url: "http://www.grammaticalframework.org/grammars/",
|
||||
//grammars_url: "http://tournesol.cs.chalmers.se:41296/grammars/",
|
||||
//grammars_url: "http://localhost:41296/grammars/",
|
||||
//grammar_list: ["Foods.pgf"], // leave undefined to get list from server
|
||||
}
|
||||
|
||||
|
||||
if(/^\?\/tmp\//.test(location.search)) {
|
||||
online_options.grammars_url=location.search.substr(1);
|
||||
}
|
||||
|
||||
var server=pgf_online(online_options);
|
||||
|
||||
var minibar_options= {
|
||||
show_abstract: true,
|
||||
show_trees: true,
|
||||
show_grouped_translations: false,
|
||||
default_source_language: "Eng",
|
||||
//feedback_url: "feedback.html",
|
||||
try_google: true
|
||||
}
|
||||
var minibar=new Minibar(server,minibar_options);
|
||||
@@ -1,46 +0,0 @@
|
||||
|
||||
/* --- Auxiliary functions -------------------------------------------------- */
|
||||
|
||||
function langpart(conc,abs) { // langpart("FoodsEng","Foods") == "Eng"
|
||||
return hasPrefix(conc,abs) ? conc.substr(abs.length) : conc;
|
||||
}
|
||||
|
||||
function update_language_menu(menu,grammar) {
|
||||
// Replace the options in the menu with the languages in the grammar
|
||||
var lang=grammar.languages;
|
||||
menu.innerHTML="";
|
||||
|
||||
for(var i=0; i<lang.length; i++) {
|
||||
var ln=lang[i].name;
|
||||
if(!hasPrefix(ln,"Disamb")) {
|
||||
var lp=langpart(ln,grammar.name);
|
||||
menu.appendChild(option(lp,ln));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function button_img(url,action) {
|
||||
var i=img(url);
|
||||
i.setAttribute("class","button");
|
||||
i.setAttribute("onclick",action);
|
||||
return i;
|
||||
}
|
||||
|
||||
function toggle_img(i) {
|
||||
var tmp=i.src;
|
||||
i.src=i.other;
|
||||
i.other=tmp;
|
||||
}
|
||||
|
||||
function setField(form,name,value) {
|
||||
form[name].value=value;
|
||||
var el=element(name);
|
||||
if(el) el.innerHTML=value;
|
||||
}
|
||||
|
||||
function open_popup(url,target) {
|
||||
var w=window.open(url,target,'toolbar=no,location=no,status=no,menubar=no');
|
||||
w.focus();
|
||||
}
|
||||
|
||||
function opener_element(id) { with(window.opener) return element(id); }
|
||||
@@ -1,162 +0,0 @@
|
||||
/* --- Translations object -------------------------------------------------- */
|
||||
|
||||
var tree_icon="tree-btn.png";
|
||||
var alignment_icon="align-btn.png";
|
||||
|
||||
function Translations(server,opts) {
|
||||
this.server=server;
|
||||
|
||||
// Default values for options:
|
||||
this.options={
|
||||
show_abstract: false,
|
||||
show_trees: false,
|
||||
show_grouped_translations: true,
|
||||
}
|
||||
|
||||
// Apply supplied options
|
||||
if(opts) for(var o in opts) this.options[o]=opts[o];
|
||||
|
||||
this.main=empty("div");
|
||||
this.menus=empty("span");
|
||||
|
||||
this.to_menu=empty_id("select","to_menu");
|
||||
|
||||
appendChildren(this.menus,[text(" To: "), this.to_menu])
|
||||
this.to_menu.onchange=bind(this.get_translations,this);
|
||||
|
||||
}
|
||||
|
||||
Translations.prototype.change_grammar=function(grammar) {
|
||||
this.grammar=grammar;
|
||||
|
||||
update_language_menu(this.to_menu,grammar);
|
||||
insertFirst(this.to_menu,option("All","All"));
|
||||
this.to_menu.value="All";
|
||||
}
|
||||
|
||||
Translations.prototype.clear=function() {
|
||||
this.main.innerHTML="";
|
||||
}
|
||||
|
||||
Translations.prototype.translateFrom=function(current) {
|
||||
this.current=current;
|
||||
this.get_translations();
|
||||
}
|
||||
|
||||
Translations.prototype.get_translations=function() {
|
||||
with(this) {
|
||||
var c=current;
|
||||
if(options.show_grouped_translations)
|
||||
server.translategroup({from:c.from,input:c.input},
|
||||
bind(show_groupedtranslations,this));
|
||||
else
|
||||
server.translate({from:c.from,input:c.input},
|
||||
bind(show_translations,this));
|
||||
}
|
||||
}
|
||||
|
||||
Translations.prototype.tdt=function(tree_btn,txt) {
|
||||
with(this) {
|
||||
return options.show_trees ? tda([tree_btn,txt]) : td(txt);
|
||||
}
|
||||
}
|
||||
|
||||
Translations.prototype.target_lang=function() {
|
||||
with(this) return langpart(to_menu.value,grammar.name);
|
||||
}
|
||||
|
||||
Translations.prototype.show_translations=function(translationResults) {
|
||||
with(this) {
|
||||
var trans=main;
|
||||
//var to=target_lang(); // wrong
|
||||
var to=to_menu.value;
|
||||
var cnt=translationResults.length;
|
||||
//trans.translations=translations;
|
||||
trans.single_translation=[];
|
||||
trans.innerHTML="";
|
||||
/*
|
||||
trans.appendChild(wrap("h3",text(cnt<1 ? "No translations?" :
|
||||
cnt>1 ? ""+cnt+" translations:":
|
||||
"One translation:")));
|
||||
*/
|
||||
for(p=0;p<cnt;p++) {
|
||||
var tra=translationResults[p];
|
||||
if (tra.translations != null) {
|
||||
for (q = 0; q < tra.translations.length; q++) {
|
||||
var t = tra.translations[q];
|
||||
var lin=t.linearizations;
|
||||
var tbody=empty("tbody");
|
||||
if(options.show_abstract && t.tree)
|
||||
tbody.appendChild(
|
||||
tr([th(text("Abstract: ")),
|
||||
tdt(node("span",{},[abstree_button(t.tree),
|
||||
alignment_button(t.tree)]),
|
||||
text(" "+t.tree))]));
|
||||
for(var i=0;i<lin.length;i++) {
|
||||
if(lin[i].to==to)
|
||||
trans.single_translation.push(lin[i].text);
|
||||
if(to=="All" || lin[i].to==to)
|
||||
tbody.appendChild(tr([th(text(langpart(lin[i].to,grammar.name)+": ")),
|
||||
tdt(parsetree_button(t.tree,lin[i].to),
|
||||
text(lin[i].text))]));
|
||||
}
|
||||
trans.appendChild(wrap("table",tbody));
|
||||
}
|
||||
}
|
||||
else if(tra.typeErrors) {
|
||||
var errs=tra.typeErrors;
|
||||
for(var i=0;i<errs.length;i++)
|
||||
trans.appendChild(wrap("pre",text(errs[i].msg)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Translations.prototype.show_groupedtranslations=function(translationsResult) {
|
||||
with(this) {
|
||||
var trans=main;
|
||||
var to=target_lang();
|
||||
//var to=to_menu.value // wrong
|
||||
var cnt=translationsResult.length;
|
||||
//trans.translations=translationsResult;
|
||||
trans.single_translation=[];
|
||||
trans.innerHTML="";
|
||||
for(p=0;p<cnt;p++) {
|
||||
var t=translationsResult[p];
|
||||
if(to=="All" || t.to==to) {
|
||||
var lin=t.linearizations;
|
||||
var tbody=empty("tbody");
|
||||
if(to=="All") tbody.appendChild(tr([th(text(t.to+":"))]));
|
||||
for(var i=0;i<lin.length;i++) {
|
||||
if(to!="All") trans.single_translation[i]=lin[i].text;
|
||||
tbody.appendChild(tr([td(text(lin[i].text))]));
|
||||
if (lin.length > 1) tbody.appendChild(tr([td(text(lin[i].tree))]));
|
||||
}
|
||||
trans.appendChild(wrap("table",tbody));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function abstree_button(abs) {
|
||||
var i=button_img(tree_icon,"toggle_img(this)");
|
||||
i.title="Click to display abstract syntax tree"
|
||||
i.other=server.current_grammar_url+"?command=abstrtree&tree="+encodeURIComponent(abs);
|
||||
return i;
|
||||
}
|
||||
|
||||
function alignment_button(abs) {
|
||||
var i=button_img(alignment_icon,"toggle_img(this)");
|
||||
i.title="Click to display word alignment"
|
||||
i.other=server.current_grammar_url+"?command=alignment&tree="+encodeURIComponent(abs);
|
||||
return i;
|
||||
}
|
||||
|
||||
function parsetree_button(abs,lang) {
|
||||
var i=button_img(tree_icon,"toggle_img(this)");
|
||||
i.title="Click to display parse tree"
|
||||
i.other=server.current_grammar_url
|
||||
+"?command=parsetree&from="+lang+"&tree="+encodeURIComponent(abs);
|
||||
return i;
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
// Assumes that Services.js has been loaded
|
||||
|
||||
function pgf_offline(options) {
|
||||
var server = {
|
||||
// State variables (private):
|
||||
grammars_url: "",
|
||||
grammar_list: ["Foods.pgf"],
|
||||
|
||||
current_grammar_url: null,
|
||||
pgf : null,
|
||||
|
||||
// Methods:
|
||||
switch_grammar: function(grammar_url,cont) {
|
||||
//debug("switch_grammar ");
|
||||
var new_grammar_url=this.grammars_url+grammar_url;
|
||||
var self=this;
|
||||
var update_pgf=function(pgfbinary) {
|
||||
debug("Got "+new_grammar_url+", length="
|
||||
+pgfbinary.length+", parsing... ");
|
||||
self.pgf = {v: Services_decodePGF.v({v:pgfbinary}) }
|
||||
//debug("done")
|
||||
self.current_grammar_url=new_grammar_url;
|
||||
cont();
|
||||
}
|
||||
ajax_http_get_binary(new_grammar_url,update_pgf);
|
||||
},
|
||||
get_grammarlist: function(cont) { cont([this.grammar_list]); },
|
||||
|
||||
get_languages: function(cont) {
|
||||
cont(fromJSValue(Services_grammar.v(this.pgf)))
|
||||
},
|
||||
grammar_info: function(cont) {
|
||||
cont(fromJSValue(Services_grammar.v(this.pgf)))
|
||||
},
|
||||
|
||||
get_random: function(cont) {
|
||||
alert("Random generation not supported yet in the offline version");
|
||||
},
|
||||
linearize: function(args,cont) {
|
||||
cont(fromJSValue(Services_linearize.v(this.pgf)(v(args.tree))(v(args.to))));
|
||||
},
|
||||
complete: function(args,cont) {
|
||||
cont(fromJSValue(Services_complete.v(this.pgf)(v(args.from))(v(args.input))));
|
||||
},
|
||||
parse: function(args,cont) {
|
||||
cont(fromJSValue(Services_parse.v(this.pgf)(v(args.from))(v(args.input))));
|
||||
},
|
||||
translate: function(args,cont) {
|
||||
cont(fromJSValue(Services_translate.v(this.pgf)(v(args.from))(v(args.input))));
|
||||
},
|
||||
translategroup: function(args,cont) {
|
||||
cont(fromJSValue(Services_translategroup.v(this.pgf)(v(args.from))(v(args.input))));
|
||||
}
|
||||
};
|
||||
for(var o in options) server[o]=options[o];
|
||||
return server;
|
||||
};
|
||||
|
||||
|
||||
|
||||
// See https://developer.mozilla.org/En/XMLHttpRequest/Using_XMLHttpRequest
|
||||
function ajax_http_get_binary(url,callback) {
|
||||
var http=GetXmlHttpObject()
|
||||
if (http==null) {
|
||||
alert ("Browser does not support HTTP Request")
|
||||
return
|
||||
}
|
||||
var statechange=function() {
|
||||
if (http.readyState==4 || http.readyState=="complete") {
|
||||
if(http.status==200) {
|
||||
var buffer=http.mozResponseArrayBuffer;
|
||||
if(buffer) callback(bufferToString(buffer)) // Gecko 2 (Firefox 4)
|
||||
else callback(http.responseText); // other browsers
|
||||
}
|
||||
else alert("Request for "+url+" failed: "
|
||||
+http.status+" "+http.statusText);
|
||||
}
|
||||
}
|
||||
http.onreadystatechange=statechange;
|
||||
http.open("GET",url,true);
|
||||
http.overrideMimeType('text/plain; charset=x-user-defined');
|
||||
http.send(null);
|
||||
//dump("http get "+url+"\n")
|
||||
return http;
|
||||
}
|
||||
|
||||
function bufferToString(buffer) {
|
||||
// This function converts to the current representation of ByteString,
|
||||
// but it would be better to use binary buffers for ByteStrings as well.
|
||||
debug("bufferToString");
|
||||
var u=new Uint8Array(buffer);
|
||||
var a=new Array(u.length);
|
||||
for(var i=0;i<u.length;i++)
|
||||
a[i]=String.fromCharCode(u[i]);
|
||||
return a.join("");
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
|
||||
/* --- Grammar access object ------------------------------------------------ */
|
||||
|
||||
function pgf_online(options) {
|
||||
var server = {
|
||||
// State variables (private):
|
||||
grammars_url: "/grammars/",
|
||||
grammar_list: null,
|
||||
current_grammar_url: null,
|
||||
|
||||
// Methods:
|
||||
switch_grammar: function(grammar_url,cont) {
|
||||
this.current_grammar_url=this.grammars_url+grammar_url;
|
||||
if(cont) cont();
|
||||
},
|
||||
get_grammarlist: function(cont) {
|
||||
http_get_json(this.grammars_url+"grammars.cgi",cont);
|
||||
},
|
||||
pgf_call: function(cmd,args,cont) {
|
||||
var url=this.current_grammar_url+"?command="+cmd+encodeArgs(args)
|
||||
http_get_json(url,cont);
|
||||
},
|
||||
|
||||
get_languages: function(cont) { this.pgf_call("grammar",{},cont); },
|
||||
grammar_info: function(cont) { this.pgf_call("grammar",{},cont); },
|
||||
|
||||
get_random: function(args,cont) { // cat, limit
|
||||
args.random=Math.random(); // side effect!!
|
||||
this.pgf_call("random",args,cont);
|
||||
},
|
||||
linearize: function(args,cont) { // tree, to
|
||||
this.pgf_call("linearize",args,cont);
|
||||
},
|
||||
complete: function(args,cont) { // from, input, cat, limit
|
||||
this.pgf_call("complete",args,cont);
|
||||
},
|
||||
parse: function(args,cont) { // from, input, cat
|
||||
this.pgf_call("parse",args,cont);
|
||||
},
|
||||
translate: function(args,cont) { // from, input, cat, to
|
||||
this.pgf_call("translate",args,cont);
|
||||
},
|
||||
translategroup: function(args,cont) { // from, input, cat, to
|
||||
this.pgf_call("translategroup",args,cont);
|
||||
}
|
||||
|
||||
};
|
||||
for(var o in options) server[o]=options[o];
|
||||
if(server.grammar_list && server.grammar_list.length>0)
|
||||
server.switch_grammar(server.grammar_list[0]);
|
||||
return server;
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Phrasebook</title>
|
||||
<link rel=stylesheet type="text/css" href="minibar.css">
|
||||
<meta charset="UTF-8">
|
||||
<meta name = "viewport" content = "width = device-width">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id=minibar></div>
|
||||
|
||||
<hr>
|
||||
|
||||
<small>
|
||||
|
||||
Powered by <a href="http://www.grammaticalframework.org/">GF</a>,
|
||||
see <a href="http://www.grammaticalframework.org/examples/phrasebook/doc-phrasebook.html">doc</a>.
|
||||
|
||||
</small>
|
||||
|
||||
<script type="text/JavaScript" src="support.js"></script>
|
||||
<script type="text/JavaScript" src="minibar.js"></script>
|
||||
<script type="text/JavaScript" src="minibar_input.js"></script>
|
||||
<script type="text/JavaScript" src="minibar_translations.js"></script>
|
||||
<script type="text/JavaScript" src="minibar_support.js"></script>
|
||||
<script type="text/JavaScript" src="pgf_online.js"></script>
|
||||
|
||||
<script type="text/JavaScript">
|
||||
|
||||
var online_options={
|
||||
// grammars_url: "http://www.grammaticalframework.org/grammars/",
|
||||
//grammars_url: "http://tournesol.cs.chalmers.se:41296/grammars",
|
||||
//grammars_url: "http://localhost:41296/grammars/",
|
||||
grammar_list: ["Phrasebook.pgf"] // leave undefined to get list from server
|
||||
}
|
||||
|
||||
var server=pgf_online(online_options);
|
||||
|
||||
var phrasebook_options={
|
||||
delete_button_text: "Del",
|
||||
help_url: "http://www.grammaticalframework.org/examples/phrasebook/help-phrasebook.html",
|
||||
feedback_url: "feedback.html",
|
||||
default_source_language: "Eng"
|
||||
}
|
||||
|
||||
start_minibar(server,phrasebook_options)
|
||||
</script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html> <head>
|
||||
<title>Saldotest</title>
|
||||
<link rel=stylesheet type="text/css" href="minibar.css">
|
||||
<script type="text/JavaScript" src="support.js"></script>
|
||||
<script type="text/JavaScript" src="saldotest.js"></script>
|
||||
<meta name = "viewport" content = "width = device-width">
|
||||
</head>
|
||||
|
||||
<body onload="start_saldotest();start_saldospel()">
|
||||
|
||||
<h2>Vilket ord ska bort?</h2>
|
||||
<div id=saldospel>
|
||||
</div>
|
||||
|
||||
<h2>Hel- och halvspöke</h2>
|
||||
<div id=saldotest>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<small>
|
||||
[Baserad på <a href="http://spraakbanken.gu.se/sal/ws/">SALDOs nättjänster</a>]
|
||||
</small>
|
||||
<small class=modtime>
|
||||
HTML <!-- hhmts start --> Last modified: Thu May 27 14:02:42 CEST 2010 <!-- hhmts end -->
|
||||
</small>
|
||||
<address>TH <img src="http://www.altocumulus.org/~hallgren/online.cgi?icon" alt=""></address>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,340 +0,0 @@
|
||||
|
||||
var Saldo_ws_url = "http://spraakbanken.gu.se/ws/saldo-ws/";
|
||||
//var Saldo_ff_url = Saldo_ws_url+"ff/json+remember_completions/";
|
||||
var Saldo_lid_url = Saldo_ws_url+"lid/json";
|
||||
|
||||
function saldo_ws(fn,fmt,arg,cont_name) {
|
||||
jsonp(Saldo_ws_url+fn+"/"+fmt+(cont_name ? "+"+cont_name : "")+"/"+arg,"");
|
||||
}
|
||||
|
||||
function saldo_json(fn,arg,cont_name) { saldo_ws(fn,"json",arg,cont_name); }
|
||||
function saldo_lid(arg,cont_name) { saldo_json("lid",arg,cont_name); }
|
||||
function saldo_lid_rnd(cont_name) { saldo_lid("rnd?"+Math.random(),cont_name); }
|
||||
|
||||
var ordlista=[];
|
||||
var current="";
|
||||
|
||||
function start_saldotest() {
|
||||
appendChildren(element("saldotest"),
|
||||
[button("Slumpa","random_word()"),
|
||||
button("Rensa","clear_all()"),
|
||||
button("⌫","delete_last()"),
|
||||
//button("Ordlista","show_ordlista()"),
|
||||
button("Visa tänkbara drag","show_moves()"),
|
||||
button("Gör ett drag","make_a_move()"),
|
||||
//button("Visa prefix","show_prefixes()"),
|
||||
div_id("surface"),
|
||||
div_id("words"),
|
||||
div_id("translations")])
|
||||
var style0="min-height: 3ex; margin: 5px; padding: 5px;";
|
||||
element("surface").setAttribute("style",style0+"border: 3px dashed #e0e0e0;");
|
||||
element("words").setAttribute("style",style0+"border: 3px solid #e0e0e0;");
|
||||
clear_all();
|
||||
}
|
||||
|
||||
function random_word() {
|
||||
saldo_lid_rnd("show_random");
|
||||
}
|
||||
|
||||
function show_random(lid) {
|
||||
var lex=lid.lex;
|
||||
reset_all(lex.substring(0,lex.indexOf('.')));
|
||||
}
|
||||
|
||||
function clear_all() { reset_all(""); }
|
||||
|
||||
function reset_all(s) {
|
||||
current=s;
|
||||
element("surface").innerHTML=s;
|
||||
element("translations").innerHTML="";
|
||||
get_completions();
|
||||
}
|
||||
|
||||
function delete_last() {
|
||||
var len=current.length;
|
||||
if(len>0) {
|
||||
current=current.substring(0,len-1);
|
||||
var s=element("surface");
|
||||
s.innerHTML=current;
|
||||
element("translations").innerHTML="";
|
||||
get_completions();
|
||||
}
|
||||
}
|
||||
|
||||
function with_completions(s,cont) {
|
||||
var c=ordlista[s];
|
||||
if(c && c.a) cont(c);
|
||||
else {
|
||||
//if(c) alert("c already has fields"+field_names(c));
|
||||
ordlista[s]={put: function(c) { ordlista[s]=c; cont(c); }};
|
||||
var url=Saldo_ws_url+"ff/json+ordlista[\""+s+"\"].put/"+encodeURIComponent(s);
|
||||
jsonp(url,"");
|
||||
}
|
||||
}
|
||||
|
||||
function get_completions() {
|
||||
with_completions(current,show_completions);
|
||||
}
|
||||
|
||||
function word(s) {
|
||||
//var w=span_class("word",text(s));
|
||||
//if(s==" ") w.innerHTML=" ";
|
||||
//w.setAttribute("onclick",'extend_current("'+s+'")');
|
||||
//return w;
|
||||
return button(s,'extend_current("'+s+'")');
|
||||
}
|
||||
|
||||
function extend_current(s) {
|
||||
current+=s;
|
||||
element("words").innerHTML="";
|
||||
element("surface").innerHTML=current;
|
||||
get_completions();
|
||||
}
|
||||
|
||||
function show_completions(saldo_ff) {
|
||||
var box=element("words");
|
||||
box.innerHTML="";
|
||||
//var c=saldo_ff.c.split("");
|
||||
var c=filter(allowed,saldo_ff.c);
|
||||
sort(c);
|
||||
for(var i=0;i<c.length;i++) {
|
||||
var s=c[i];
|
||||
if(s!='-')
|
||||
box.appendChild(word(s));
|
||||
}
|
||||
show_translations(saldo_ff.a);
|
||||
}
|
||||
|
||||
function allowed(c) {
|
||||
switch(c) {
|
||||
case 'å':
|
||||
case 'ä':
|
||||
case 'ö':
|
||||
case 'é':
|
||||
case 'ü':
|
||||
return true;
|
||||
default:
|
||||
return 'a'<=c && c<='z';
|
||||
}
|
||||
}
|
||||
|
||||
// ordklasser: mxc sxc (förekommer bara som prefix),
|
||||
// *h (förekommer bara som suffix)
|
||||
function ignore(msd) {
|
||||
switch(msd) {
|
||||
case "c":
|
||||
case "ci":
|
||||
case "cm":
|
||||
case "seg":
|
||||
case "sms":
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function count_wordforms(a) {
|
||||
var cnt=0;
|
||||
for(var i=0;i<a.length;i++)
|
||||
if(!ignore(a[i].msd)) cnt++;
|
||||
return cnt;
|
||||
}
|
||||
|
||||
function pad(s) {
|
||||
return s.length>0 ? " "+s : "";
|
||||
}
|
||||
|
||||
function show_translations(a) {
|
||||
var tr=element("translations");
|
||||
tr.innerHTML="";
|
||||
//if(!a) alert("a undefined in show_translations");
|
||||
if(count_wordforms(a)<1) {
|
||||
tr.appendChild(p(text(a.length<1 ? "Detta är inte en giltig ordform"
|
||||
: "Denna form förekommer bara i sammansättningar")));
|
||||
element("surface").setAttribute("class","invalid");
|
||||
}
|
||||
else {
|
||||
element("surface").setAttribute("class","valid");
|
||||
for(var i=0;i<a.length;i++)
|
||||
if(!ignore(a[i].msd))
|
||||
tr.appendChild(p(text(a[i].gf+" ("+a[i].pos+pad(a[i].is)+", "+a[i].msd+")")));
|
||||
}
|
||||
}
|
||||
|
||||
function show_ordlista() {
|
||||
var trans=element("translations");
|
||||
trans.innerHTML="Följande ord har slagits upp: ";
|
||||
var apnd=function(el) { trans.appendChild(el) };
|
||||
for(var i in ordlista) {
|
||||
apnd(empty("br"));
|
||||
apnd(span_class(ordlista[i].a.length<1 ? "invalid" : "valid",text(" "+i)));
|
||||
apnd(text(": "+(ordlista[i].ok!=null ? ordlista[i].ok.length : "?")
|
||||
+"/"+(ordlista[i].allowed!=null ? ordlista[i].allowed.length : "?")));
|
||||
}
|
||||
}
|
||||
|
||||
function extend_ordlista(s,cs,cont) {
|
||||
if(cs.length<1) cont();
|
||||
else {
|
||||
var c=cs[0];
|
||||
var cs2=cs.substring(1);
|
||||
with_completions(s+c,function(o){extend_ordlista(s,cs2,cont)});
|
||||
}
|
||||
}
|
||||
|
||||
function known_possible_moves(s,cont) {
|
||||
var c=implode(sort(filter(allowed,ordlista[s].c)));
|
||||
ordlista[s].allowed=c;
|
||||
extend_ordlista(s,c,function() {
|
||||
var ok="";
|
||||
for(var i=0;i<c.length;i++) {
|
||||
var next=s+c[i];
|
||||
var ff=ordlista[next];
|
||||
//if(!ff.a) alert(show_props(ff,"ff"));
|
||||
if(next.length<2 || count_wordforms(ff.a)<1) ok+=c[i];
|
||||
}
|
||||
ordlista[s].ok=ok;
|
||||
cont(ok);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function unknown_possible_moves(s,cont) {
|
||||
with_completions(s,function(c){known_possible_moves(s,cont);});
|
||||
}
|
||||
|
||||
function currently_possible_moves(cont) {
|
||||
known_possible_moves(current,cont);
|
||||
}
|
||||
|
||||
function show_moves() {
|
||||
var trans=element("translations");
|
||||
trans.innerHTML="Letar efter möjliga drag";
|
||||
currently_possible_moves(function(ok) {
|
||||
trans.innerHTML="Tänkbara drag: "+ok;
|
||||
winning_moves(trans,ok);
|
||||
});
|
||||
}
|
||||
|
||||
function winning_moves(trans,ok) {
|
||||
var ws=map(function(c){return current+c;},ok);
|
||||
mapc(unknown_possible_moves,ws,function(oks){
|
||||
var winning="";
|
||||
for(i=0;i<oks.length;i++)
|
||||
if(oks[i].length<1) winning+=ok[i];
|
||||
trans.innerHTML+="<br>Vinnande drag: "+winning;
|
||||
});
|
||||
}
|
||||
|
||||
function make_a_move() {
|
||||
currently_possible_moves(function(ok) {
|
||||
if(ok.length<1) element("translations").innerHTML="Hittade inga möjliga drag!";
|
||||
else {
|
||||
var i=Math.floor(Math.random()*ok.length);
|
||||
extend_current(ok[i]);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function show_prefixes_of(trans,s) {
|
||||
if(s.length>0) {
|
||||
var p=s.substr(0,s.length-1);
|
||||
with_completions(p,function(c) {
|
||||
if(count_wordforms(c.a)>0) trans.innerHTML+="<br>"+p;
|
||||
show_prefixes_of(trans,p);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function show_prefixes() {
|
||||
var trans=element("translations");
|
||||
trans.innerHTML="Prefix av "+current+":";
|
||||
show_prefixes_of(trans,current);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
var spel={ antal_ord: 4, // antal närbesläktade ord att visa
|
||||
antal_korrekta_svar: 0,
|
||||
antal_felaktiga_svar: 0
|
||||
};
|
||||
|
||||
function start_saldospel() {
|
||||
spel.hylla=div_id("hylla");
|
||||
spel.status=div_id("status");
|
||||
//element("saldospel").innerHTML="<span id=score></span>";
|
||||
appendChildren(element("saldospel"),
|
||||
[spel.hylla,spel.status,
|
||||
p(text("")),
|
||||
button("Nya ord","spel0()"),
|
||||
text(" "),
|
||||
wrap("b",span_id("score"))]);
|
||||
spel.score=element("score");
|
||||
show_score();
|
||||
spel0();
|
||||
}
|
||||
|
||||
function spel0() { // Välj ord 1
|
||||
saldo_lid_rnd("spel1");
|
||||
}
|
||||
|
||||
function spel1(lid) { // Slå upp md1 för ord 1
|
||||
spel.lid=lid;
|
||||
saldo_json("md1",lid.lex,"spel2");
|
||||
}
|
||||
|
||||
function spel2(md1) { // Kontrollera att det finns minst 4 ord i md1 för ord1
|
||||
if(md1.length<spel.antal_ord) spel0();
|
||||
else {
|
||||
spel.md1=md1;
|
||||
spel3();
|
||||
}
|
||||
}
|
||||
|
||||
function spel3() { // Välj ord 2
|
||||
saldo_lid_rnd("spel4");
|
||||
}
|
||||
|
||||
function spel4(lid) { // Slå upp md1 för ord 2
|
||||
spel.lid2=lid;
|
||||
saldo_json("md1",lid.lex,"spel5");
|
||||
}
|
||||
|
||||
function spel5(md1) { // Kontrollera att ord 1 och ord 2 inte har något gemensamt
|
||||
var ordlista1=map(wf,spel.md1);
|
||||
var ord2=wf(spel.lid2.lex);
|
||||
var ordlista2=map(wf,md1).concat(ord2);
|
||||
if(overlaps(ordlista1,ordlista2)) spel3();
|
||||
else spel6(ordlista1,ord2);
|
||||
}
|
||||
|
||||
function spel6(ordlista1,ord2) {
|
||||
spel.ord2=ord2;
|
||||
var pos=Math.floor(Math.random()*spel.antal_ord);
|
||||
var ordlista=shuffle(shuffle(ordlista1).slice(0,spel.antal_ord).concat(ord2));
|
||||
spel.hylla.innerHTML="";
|
||||
var lista=empty_class("div","space");
|
||||
for(var i=0;i<ordlista.length;i++)
|
||||
lista.appendChild((button(ordlista[i],"spel7(this)")));
|
||||
spel.hylla.appendChild(lista);
|
||||
}
|
||||
|
||||
function spel7(btn) {
|
||||
btn.disabled=true;
|
||||
var ok=btn.value==spel.ord2;
|
||||
//btn.setAttribute("class",ok ? "correct" : "incorrect");
|
||||
btn.setAttribute("style",ok ? "color: green" : "color: red");
|
||||
if(ok) spel.antal_korrekta_svar++; else spel.antal_felaktiga_svar++;
|
||||
show_score();
|
||||
if(ok) spel0();
|
||||
}
|
||||
|
||||
function show_score() {
|
||||
spel.score.innerHTML=""+spel.antal_korrekta_svar+" rätt, "
|
||||
+spel.antal_felaktiga_svar+" fel";
|
||||
}
|
||||
|
||||
function wf(ord) { // word form, wf("band..1") == "band"
|
||||
return ord.split(".",1)[0].split("_").join(" ");
|
||||
}
|
||||
@@ -1,300 +0,0 @@
|
||||
/* --- Accessing document elements ------------------------------------------ */
|
||||
|
||||
function element(id) {
|
||||
return document.getElementById(id);
|
||||
}
|
||||
|
||||
/* --- JavaScript tricks ---------------------------------------------------- */
|
||||
|
||||
// To be able to use object methods that refer to "this" as callbacks
|
||||
// See section 3.3 of https://github.com/spencertipping/js-in-ten-minutes/raw/master/js-in-ten-minutes.pdf
|
||||
function bind(f, this_value) {
|
||||
return function () {return f.apply (this_value, arguments)};
|
||||
};
|
||||
|
||||
/* --- JSONP ---------------------------------------------------------------- */
|
||||
|
||||
// Inspired by the function jsonp from
|
||||
// http://www.west-wind.com/Weblog/posts/107136.aspx
|
||||
// See also http://niryariv.wordpress.com/2009/05/05/jsonp-quickly/
|
||||
// http://en.wikipedia.org/wiki/JSON#JSONP
|
||||
function jsonp(url,callback)
|
||||
{
|
||||
if (url.indexOf("?") > -1)
|
||||
url += "&jsonp="
|
||||
else
|
||||
url += "?jsonp="
|
||||
url += callback;
|
||||
//url += "&" + new Date().getTime().toString(); // prevent caching
|
||||
|
||||
var script = empty("script");
|
||||
script.setAttribute("src",url);
|
||||
script.setAttribute("type","text/javascript");
|
||||
document.body.appendChild(script);
|
||||
}
|
||||
|
||||
var json = {next:0};
|
||||
|
||||
// Like jsonp, but instead of passing the name of the callback function, you
|
||||
// pass the callback function directly, making it possible to use anonymous
|
||||
// functions.
|
||||
function jsonpf(url,callback)
|
||||
{
|
||||
var name="callback"+(json.next++);
|
||||
json[name]=function(x) { delete json[name]; callback(x); }
|
||||
jsonp(url,"json."+name);
|
||||
}
|
||||
|
||||
/* --- AJAX ----------------------------------------------------------------- */
|
||||
|
||||
function GetXmlHttpObject(handler)
|
||||
{
|
||||
var objXMLHttp=null
|
||||
if (window.XMLHttpRequest)
|
||||
{
|
||||
// See http://www.w3.org/TR/XMLHttpRequest/
|
||||
// https://developer.mozilla.org/en/xmlhttprequest
|
||||
objXMLHttp=new XMLHttpRequest()
|
||||
}
|
||||
else if (window.ActiveXObject)
|
||||
{
|
||||
objXMLHttp=new ActiveXObject("Microsoft.XMLHTTP")
|
||||
}
|
||||
return objXMLHttp
|
||||
}
|
||||
|
||||
function ajax_http(method,url,body,callback,errorcallback) {
|
||||
var http=GetXmlHttpObject()
|
||||
if (!http) {
|
||||
var errortext="Browser does not support HTTP Request";
|
||||
if(errorcallback) errorcallback(errortext,500)
|
||||
else alert(errortext)
|
||||
}
|
||||
else {
|
||||
var statechange=function() {
|
||||
if (http.readyState==4 || http.readyState=="complete") {
|
||||
if(http.status<300) callback(http.responseText,http.status);
|
||||
else if(errorcallback) errorcallback(http.responseText,http.status);
|
||||
else alert("Request for "+url+" failed: "
|
||||
+http.status+" "+http.statusText);
|
||||
}
|
||||
}
|
||||
http.onreadystatechange=statechange;
|
||||
http.open(method,url,true)
|
||||
http.send(body)
|
||||
}
|
||||
return http
|
||||
}
|
||||
|
||||
function ajax_http_get(url,callback,errorcallback) {
|
||||
ajax_http("GET",url,null,callback,errorcallback)
|
||||
}
|
||||
|
||||
function ajax_http_post(url,formdata,callback,errorcallback) {
|
||||
ajax_http("POST",url,formdata,callback,errorcallback)
|
||||
// See https://developer.mozilla.org/En/XMLHttpRequest/Using_XMLHttpRequest#Using_FormData_objects
|
||||
}
|
||||
|
||||
// JSON via AJAX
|
||||
function ajax_http_get_json(url,cont) {
|
||||
ajax_http_get(url,function(txt) { cont(eval("("+txt+")")); });
|
||||
}
|
||||
|
||||
function sameOrigin(url) {
|
||||
var a=empty("a");
|
||||
a.href=url; // converts to an absolute URL
|
||||
return hasPrefix(a.href,location.protocol+"//"+location.host+"/");
|
||||
}
|
||||
|
||||
// Use AJAX when possible, fallback to JSONP
|
||||
function http_get_json(url,cont) {
|
||||
if(sameOrigin(url)) ajax_http_get_json(url,cont);
|
||||
else jsonpf(url,cont);
|
||||
}
|
||||
|
||||
/* --- URL construction ----------------------------------------------------- */
|
||||
|
||||
function encodeArgs(args) {
|
||||
var q=""
|
||||
for(var arg in args)
|
||||
if(args[arg]!=undefined)
|
||||
q+="&"+arg+"="+encodeURIComponent(args[arg]);
|
||||
return q;
|
||||
}
|
||||
|
||||
/* --- HTML construction ---------------------------------------------------- */
|
||||
function text(s) { return document.createTextNode(s); }
|
||||
|
||||
function node(tag,as,ds) {
|
||||
var n=document.createElement(tag);
|
||||
for(var a in as) n.setAttribute(a,as[a]);
|
||||
for(var i in ds) n.appendChild(ds[i]);
|
||||
return n;
|
||||
}
|
||||
|
||||
function empty(tag,name,value) {
|
||||
var el=node(tag,{},[])
|
||||
if(name && value) el.setAttribute(name,value);
|
||||
return el;
|
||||
}
|
||||
|
||||
function empty_id(tag,id) { return empty(tag,"id",id); }
|
||||
function empty_class(tag,cls) { return empty(tag,"class",cls); }
|
||||
|
||||
function div_id(id) { return empty_id("div",id); }
|
||||
function span_id(id) { return empty_id("span",id); }
|
||||
|
||||
function wrap(tag,contents) { return node(tag,{},[contents]); }
|
||||
|
||||
function wrap_class(tag,cls,contents) {
|
||||
var el=empty_class(tag,cls);
|
||||
if(contents) el.appendChild(contents);
|
||||
return el;
|
||||
}
|
||||
|
||||
function span_class(cls,contents) { return wrap_class("span",cls,contents); }
|
||||
function div_class(cls,contents) { return wrap_class("div",cls,contents); }
|
||||
|
||||
function p(contents) { return wrap("p",contents); }
|
||||
function dt(contents) { return wrap("dt",contents); }
|
||||
function li(contents) { return wrap("li",contents); }
|
||||
|
||||
function th(contents) { return wrap("th",contents); }
|
||||
function td(contents) { return wrap("td",contents); }
|
||||
|
||||
function tr(cells) { return node("tr",{},cells); }
|
||||
|
||||
function button(label,action,key) {
|
||||
var el=node("input",{"type":"button","value":label},[]);
|
||||
if(typeof action=="string") el.setAttribute("onclick",action);
|
||||
else el.onclick=action;
|
||||
if(key) el.setAttribute("accesskey",key);
|
||||
return el;
|
||||
}
|
||||
|
||||
function option(label,value) {
|
||||
return node("option",{"value":value},[text(label)]);
|
||||
}
|
||||
|
||||
function appendChildren(el,ds) {
|
||||
for(var i in ds) el.appendChild(ds[i]);
|
||||
return el;
|
||||
}
|
||||
|
||||
function insertFirst(parent,child) {
|
||||
parent.insertBefore(child,parent.firstChild);
|
||||
}
|
||||
|
||||
function tda(cs) { return node("td",{},cs); }
|
||||
|
||||
function img(src) { return empty("img","src",src); }
|
||||
|
||||
/* --- Debug ---------------------------------------------------------------- */
|
||||
|
||||
function debug(s) {
|
||||
var d=element("debug");
|
||||
if(d) d.appendChild(text(s+"\n"))
|
||||
}
|
||||
|
||||
function show_props(obj, objName) {
|
||||
var result = "";
|
||||
for (var i in obj) {
|
||||
result += objName + "." + i + " = " + obj[i] + "<br>";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function field_names(obj) {
|
||||
var result = "";
|
||||
for (var i in obj) {
|
||||
result += " " + i;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --- Data manipulation ---------------------------------------------------- */
|
||||
function swap(a,i,j) { // Note: this doesn't work on strings.
|
||||
var tmp=a[i];
|
||||
a[i]=a[j];
|
||||
a[j]=tmp;
|
||||
return a;
|
||||
}
|
||||
|
||||
function sort(a) {
|
||||
// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/sort
|
||||
return a.sort();
|
||||
/* // Note: this doesn't work on strings.
|
||||
for(var i=0;i<a.length-1;i++) {
|
||||
var min=i;
|
||||
for(var j=i+1;j<a.length;j++)
|
||||
if(a[j]<a[min]) min=j;
|
||||
if(min!=i) swap(a,i,min);
|
||||
}
|
||||
return a;
|
||||
*/
|
||||
}
|
||||
|
||||
function filter(p,xs) {
|
||||
var ys=[];
|
||||
for(var i=0;i<xs.length;i++)
|
||||
if(p(xs[i])) ys[ys.length]=xs[i];
|
||||
return ys;
|
||||
}
|
||||
|
||||
function implode(cs) { // array of strings to string
|
||||
/*
|
||||
var s="";
|
||||
for(var i=0;i<cs.length;i++)
|
||||
s+=cs[i];
|
||||
return s;
|
||||
*/
|
||||
return cs.join("");
|
||||
}
|
||||
|
||||
function hasPrefix(s,pre) { return s.substr(0,pre.length)==pre; }
|
||||
|
||||
function commonPrefix(s1,s2) {
|
||||
for(var i=0;i<s1.length && i<s2.length && s1[i]==s2[i];i++);
|
||||
return s1.substr(0,i);
|
||||
}
|
||||
|
||||
/*
|
||||
function all(p,xs) {
|
||||
for(var i=0;i<xs.length;i++)
|
||||
if(!p(xs[i])) return false;
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
function map(f,xs) {
|
||||
var ys=[];
|
||||
for(var i=0;i<xs.length;i++) ys[i]=f(xs[i]);
|
||||
return ys;
|
||||
}
|
||||
|
||||
// map in continuation passing style
|
||||
function mapc(f,xs,cont) { mapc_from(f,xs,0,[],cont); }
|
||||
|
||||
function mapc_from(f,xs,i,ys,cont) {
|
||||
if(i<xs.length)
|
||||
f(xs[i],function(y){ys[i]=y;mapc_from(f,xs,i+1,ys,cont)});
|
||||
else
|
||||
cont(ys);
|
||||
}
|
||||
|
||||
function overlaps(as,bs) {
|
||||
for(var i=0;i<as.length;i++)
|
||||
if(elem(as[i],bs)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
function elem(a,as) {
|
||||
for(var i=0;i<as.length;i++)
|
||||
if(a==as[i]) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
function shuffle(a) {
|
||||
for(i=0;i<a.length;i++) swap(a,i,Math.floor(Math.random()*a.length))
|
||||
return a;
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 149 B |
Reference in New Issue
Block a user