Language Guide
See the Elemental Programming Language documentation and guide.
Writing a Web View
A web view is a URL handler on the server that calls into the library by interpreting
a resource in that library named by the requested URL. The Agent System binds to the
/page/
site URL and everything else following maps into the library by using it as a
slash-separated path indexing an interface or activity document. Navigating and updating
the library can be done directly using the website or by uploading a package.
For example, the URL /page/home/Itham/site/search
might be constructed by uploading
a package like such:
interfaces/home/Itham/site:: search($view):: <input type="text" id="input"> <button onclick="parent.search(this)">Go</button>
Markup-Defined View
This introduces an upload format and an interface document (YAML, extended) syntax.
By default, accessing the URL will render the search
$view as HTML, meaning a search
bar page with basic functionality. Pages defined like this are typically accessible
in a site menu Task Window, meaning the window.parent might expose a search API.
Next we update the interface document with an additional linked resource:
interfaces/home/Itham/site:: search($view):: <script src="/page/home/Itham/site/library.js" type="text/javascript" /> <input type="text" id="input"> <button onclick="parent.search(getSearchQuery(this))">Go</button> library.js($view): content-type: text/javascript content:: function getSearchQuery() { return btn.ownerDocument.getElementById('input').value; }
The javascript resource URL now responds setting the right content type.
Now we want to access the system more deeply whenever this web view is requested.
interfaces/home/Itham/site:: data.js($view): context($trigger):: context['model'] = 'home/Itham/search/model'(':'.join(path)) response['content_type'] = 'text/javascript' template:: var model = {{ model.json|safe }};
The template
is a Django template, but it is only rendered to the response stream
after the context
$trigger is done evaluating so that the context code can
initialize the dataspace before rendering. In this example, the trigger accesses
the path
parameter set by the server which contains a sequence of all following
URL path components that did not match past the library path: home/Itham/site/
.
In other words, everything after the matching part of the path is then used in
constructing an identifier passed to the search/model
method.
Alternatively, the template can be omitted by setting the content directly:
data($view): context($trigger):: model = 'home/Itham/search/model'(':'.join(path)) response['content_type'] = 'application/json' response['content'] = 'text/json/dumps'(model)
Search then becomes:
interfaces: home/Itham/site:: search($view):: <script src="/page/org/example/search-interface.js" type="text/javascript" /> <script src="/page/home/Itham/site/library.js" type="text/javascript" /> <script type="text/javascript"> $.get('/page/home/Itham/search/data', function (model) { search = SearchInterface(model); }); </script> <input type="text" id="input"> <button onclick="search.fromQuery(getSearchQuery(this))">Go</button> org/example:: search-interface.js($view):: class SearchInterface { function constructor(model) { self.data = model; } function fromQuery(text) { ... }
Security Note
By defining a web view (with $view
), this means that its the URL may be publically accessible.
Specify a security
value on the view to control this access:
allow
,allow all
,allow-all
default
,path
: the user must be permitted toread
the path of the view. This is the default security setting.
A view can also use request.user.checkAccessError
whenever protecting a resource's computational charge:
interfaces/home/Itham/public:: edit($view): context($trigger):: if request.method == 'POST': request.user.checkAccessError('write', 'home/Itham/storage/resource') 'kernel/structure'('resource').setText('kernel/edit'('home/Itham/storage'), ...)
checkAccessError
will raise an NoAccessException
if the user of the request
doesn't have permission.
Defining a Service
An endpoint can be implemented by simply defining a function in an activity module:
home/Itham/service:: def endpoint$name(arg1, arg2): 'kernel/info'('[endpoint] ' + string(arg1) + ': ' + string(arg2))
Then, call the service endpoint:
'home/Itham/service/endpoint$name'('Category', 'Value')
Using a remote interface, call the endpoint on a remote machine:
agent = $.network.portal.session('remote.thetaplane.com', 'itham', 'password') agent.script("'home/Itham/service/endpoint$name'('Remote-Category', 'Remote-Value')")
Or:
r = initialize('services/source/loopback') \ .path$bind('services/source/deployment/code') .(r('services/source/deployment/wiki/programming'))
Documentation
Documentation for a function is provided by defining another function
with the same name but followed by '$doc
'. This new function returns
an InlineText object or string object describing the original function.