demo/demo/controllers/root.py | 4
docs/main/HelloWorld.rst | 211 ++++++++++++++++++++++++++++++++++--------
2 files changed, 175 insertions(+), 40 deletions(-)
New commits:
commit 701e95ae2c7ba5f5804eaece5d5135c7ef63e79b
Author: Luke Macken <lmacken(a)redhat.com>
Date: Tue Nov 30 17:19:41 2010 -0500
Lots of documentation updates for our Hello World demo
diff --git a/demo/demo/controllers/root.py b/demo/demo/controllers/root.py
index d31128c..9486d9d 100644
--- a/demo/demo/controllers/root.py
+++ b/demo/demo/controllers/root.py
@@ -22,7 +22,7 @@ class Root(object):
@expose('mako:demo.templates.model')
def model(self, *args, **kwargs):
from demo.model import DBSession, HelloWorldModel
- entries = DBSession.query(HelloWorldModel).all()
+ entries = DBSession.query(HelloWorldModel).limit(10).all()
return dict(entries=entries)
@expose('mako:demo.templates.model')
@@ -35,4 +35,4 @@ class Root(object):
def _get_entries(self, *args, **kwargs):
from demo.model import DBSession, HelloWorldModel
- return DBSession.query(HelloWorldModel).all()
+ return DBSession.query(HelloWorldModel).limit(10).all()
diff --git a/docs/main/HelloWorld.rst b/docs/main/HelloWorld.rst
index 2dc335d..5983190 100644
--- a/docs/main/HelloWorld.rst
+++ b/docs/main/HelloWorld.rst
@@ -10,9 +10,9 @@ basic "Hello World" components in one demo.
The Controller
--------------
-This is the most basic of controllers.
+This is the most basic of TurboGears controllers.
-`demo/controllers/root.py`
+``demo/controllers/root.py``
.. code-block:: python
@@ -25,15 +25,19 @@ This is the most basic of controllers.
return 'Hello World!'
-Ok, so here we have a trivial TurboGears controller. How do we plug this into
-Moksha and actually run it?
+Ok, so here we have a trivial TurboGears controller that simply renders "Hello
+World". So how do we plug this into Moksha and actually run it?
-Let's say we want this index method to be the root of our application. To
-accomplish this we add it to the `[moksha.root]` entry-point in our setup.py::
+Let's say we want this controller method to be the root of our application. To
+accomplish this we add it to the ``[moksha.root]`` entry-point in our ``setup.py``::
[moksha.root]
root = demo.controllers.root:Root
+.. note::
+
+ Any time you modify any entry-points in your setup.py/pavement.py, you must regenerate
+ the egg info by running ``python setup.py egg_info``
.. seealso::
@@ -42,31 +46,34 @@ accomplish this we add it to the `[moksha.root]` entry-point in our setup.py::
Running the Moksha stack
------------------------
+The Moksha Stack is comprised of a WSGI application, Orbited, and the Moksha
+Hub. These pieces can be deployed and run in a variety of ways (see the
+:doc:`Deployment` guide for more information), but the easiest way to get them
+running is with the :doc:`MokshaCLI`.
+
.. code-block:: bash
$ moksha start
+Now when we fetch the index page, Moksha will dispatch the request to our new controller.
+
.. code-block:: bash
$ curl http://localhost:8080/
Hello World
-.. seealso::
-
- :doc:`MokshaCLI`
-
Bringing a templating engine into the mix
-----------------------------------------
The previous example just returned a string from our controller. What if we
want to use one of the many powerful templating engines out there?
-TurboGears supports a variety of engines, including Genshi, Mako, Jinja, etc.
+TurboGears supports a variety of engines, including Genshi, Mako, Jinja, Cheetah, etc.
-So, lets create a dead simple Mako template.
+For this example let's just create a dead simple `Mako <http://makotemplates.org>`_ template.
-`demo/templates/template.mak`
+``demo/templates/template.mak``
.. code-block:: html
@@ -89,29 +96,47 @@ Now let's plug in our Mako template into our Root controller.
Building a basic Widget
-----------------------
+A "Widget" is simply a Python object that contains references to CSS/JavaScript
+resources, a template, and server-side render-time logic.
+
.. image:: ../_static/widget.png
+In TurboGears, and thus Moksha, the widget framework of choice is `ToscaWidget
+<http://toscawidgets.org>`_, which allows you to create modular components that
+can be re-used throughout your application.
+
.. code-block:: python
from tw.api import Widget
class HelloWorldWidget(Widget):
- params = ['msg']
- msg = 'Hello World'
- template = '${msg}'
- engine_name = 'mako'
+ params = ['msg'] # The parameters that this widget takes
+ msg = 'Hello World' # The default message value
+ template = '${msg}' # The widget template, which has access to all of the `params`.
+ # The template can be either a string or also an external reference like,
+ # template = 'mako:myproject.templates.widgettemplate'
+ engine_name = 'mako' # The template engine. Unnecessary if referencing an external template.
def update_params(self, d):
""" Render-time logic """
super(HelloWorldWidget, self).update_params(d)
+ # This code will be executed when the widget is rendering during each request.
+ # The argument `d` contains the widget data and params.
+ # So d.msg would currently be be 'Hello World'
+
+You can then plug this widget into the ``[moksha.widget]`` entry-point.
-`setup.py`
+``setup.py``
.. code-block:: python
[moksha.widget]
- helloworld = demo.widgets:HelloWorldWidget
+ basic = demo.widgets:HelloWorldWidget
+
+
+Moksha will expose your widget on the /widgets/$NAME URL. Since we named this widget 'basic' on the
+entry-point, we can fetch it like so:
.. code-block:: bash
@@ -124,6 +149,9 @@ Building a basic Widget
<body>Hello World</body>
</html>
+
+You can also pass in different parameters to your widget via the URL.
+
.. code-block:: bash
$ curl http://localhost:8080/widgets/basic?msg=foobar
@@ -139,11 +167,41 @@ Building a basic Widget
:doc:`Widgets`
+.. seealso::
+
+ `TG2 TW docs <http://turbogears.org/2.1/docs/main/ToscaWidgets/ToscaWidgets.html>`_
+
+
+Real-time Messaging
+-------------------
+
+Now that we've got the basics out of the way, we can finally move on to the fun stuff -- *messaging*.
+
+One of the features that makes Moksha unique in the web framework world is that
+it encorporates a Message Broker into the mix, allowing you to create highly
+responsive and interactive web applications.
+
+Traditionally, the messaging world is full of acronyms (AMQP, STOMP) and
+complexity (queues, exchanges, binding keys, flow control). Moksha, on the
+other hand, aims to provide a high level abstraction on top of these concepts,
+while offering a trivial API for people to utilize them with ease.
+The primary messaging concepts that Moksha defines are **Producers** and
+**Consumers**. These are objects that produce messages, along with objects
+that consume them. Each of which communicate over specific **Topics**.
+
+.. seealso::
+
+ :doc:`Messaging`
Creating a message producer
---------------------------
+A Producer in Moksha does what you would expect, sends messages to the broker.
+Let's say you want a Producer that wakes up every 3 seconds, performs some
+task, and sends a message. Moksha provides a ``PollingProducer`` class that
+can do just this.
+
.. code-block:: python
from datetime import timedelta
@@ -155,9 +213,16 @@ Creating a message producer
def poll(self):
self.send_message('helloworld', {'msg': 'Hello World!'})
-.. seealso::
+This ``HelloWorldProducer``, which will be initialized by the :doc:`MokshaHub`,
+wakes up every 3 seconds, and sends a 'Hello World!' message to the
+``helloworld`` :doc:`Topic`.
- :doc:`Messaging`
+.. note::
+
+ As with all of the other examples above, you must plug your object into a
+ moksha entry-point in your setup.py. For the case of producers, it is the
+ ``[moksha.producer]`` entry-point. This allows the ``moksha-hub`` to detect
+ your plugin and initialize/run it as necessary.
.. seealso::
@@ -166,7 +231,11 @@ Creating a message producer
Creating a message consumer
---------------------------
-`demo/consumer.py`
+The moksha Consumer API lets you create a simple Python object with a consume
+method that will be executed with each new message as it is received from the
+broker.
+
+``demo/consumer.py``
.. code-block:: python
@@ -179,6 +248,9 @@ Creating a message consumer
def consume(self, message):
self.log.info('Received message: ' + message['body']['msg'])
+
+This example listens to the ``helloworld`` topic, and simply logs each message that it receives.
+
.. seealso::
:doc:`Consumers`
@@ -186,9 +258,16 @@ Creating a message consumer
Running the Moksha Hub
----------------------
+The ``moksha-hub`` is a service that runs outside of the web application. It
+handles loading all of the producers and consumers, as well as communicating
+with the message broker.
+
.. image:: ../_static/moksha-hub.png
-<consumer output>
+.. note::
+
+ The Moksha Hub is automatically started when you run ``moksha start``, but you
+ can also start it by running ``moksha-hub``.
.. seealso::
@@ -197,12 +276,11 @@ Running the Moksha Hub
Creating a Live Widget!
-----------------------
-Ok, on to the fun stuff.
+So producers and consumers work inside of the moksha-hub. Moksha's Live Widgets, on the other hand, can produce and consume messages **in the web browser**.
-Moksha provides an API for creating "live widgets". A widget is a re-usable
-bundle of HTML/JavaScript/CSS/Server-side logic Making it "live" entails
-having the widget "subscribe" to "topics" and perform some action upon
-new messages as they arrive in the users web browser.
+Moksha provides an API for creating "live widgets". Making a widget "live"
+entails having it "subscribe" to "topics" and perform some action upon new
+messages as they arrive in the users web browser.
.. image:: ../_static/live_widgets.png
@@ -222,9 +300,21 @@ new messages as they arrive in the users web browser.
$('<li/>').text(json.msg).prependTo('#data');
"""
-<add to entry point>
+.. note::
-<rendering the widget>
+ To make moksha aware of this widget, you have to add it to the
+ ``[moksha.widget]`` entry-point in your setup.py
+
+This widget will automatically be subscribed to the ``helloworld`` topic, and
+the ``onmessage`` javascript callback will be run every time a new message
+arrives with the decode JSON data available in the ``json`` variable. Moksha
+handles all of the work behind the scenes subscribing to the appropriate
+message queues, decoding JSON data, and dispatching messages to the appropriate
+widgets.
+
+You can view this widget multiple ways. First being via the standard ``/widgets/`` URL. If you place your widget on the ``[moksha.widget]`` entry-point named 'live', then you can view your live widget by going to ``/widgets/live?live=True``. Passing in the ``live=True`` variable tells Moksha to inject the Moksha Live Socket along with the widget. This is needed to setup the realtime pipes.
+
+If you want to integrate the widget in your controller, you can do something like the following:
.. code-block:: python
@@ -234,13 +324,19 @@ new messages as they arrive in the users web browser.
tmpl_context.moksha_socket = moksha.get_widget('moksha_socket')
return dict(options={})
+Moksha provides a widget template that will render ``tmpl_context.widget`` with
+the provided ``options``. It will also inject the moksha_socket if that exists
+on the template context as well.
+
+From here you can view your widget by going to ``/livewidget``. You should see
+a new "Hello World!" message appear on the page every 3 seconds.
.. seealso::
:doc:`LiveWidget`
-Sending messages to from the Live Widget
-----------------------------------------
+Sending messages from the Live Widget
+-------------------------------------
You can send messages with Moksha's JavaScript API using the following function:
@@ -248,8 +344,8 @@ You can send messages with Moksha's JavaScript API using the following function:
moksha.send_message('helloworld', {'foo': 'bar'});
-So let's add a simple little text field to our HelloWorldWidget that allows people
-to send messages to the `helloworld` topic:
+So let's add a simple little text field to our ``HelloWorldWidget`` that allows
+people to send their own messages to the `helloworld` topic:
.. code-block:: python
@@ -275,11 +371,16 @@ to send messages to the `helloworld` topic:
$('<li/>').text(json.msg).prependTo('#data');
"""
+TODO: <screenshot>
Creating a database model
-------------------------
-`demo.model.model.py`
+Let's say we want to store every new message on the ``helloworld`` topic in a SQL database.
+
+Here is an example of a simple SQLAlchemy model that can be used to store our messages.
+
+``demo.model.model.py``
.. code-block:: python
@@ -294,13 +395,24 @@ Creating a database model
message = Column(Text)
timestamp = Column(DateTime, default=datetime.now)
+When you hook your controller up to moksha via the ``[moksha.application]``
+entry-point, Moksha will automatically detect your ``model`` module if it
+exists, and will try and initialize it.
+
.. seealso::
`Working with SQLAlchemy and your data model <http://turbogears.org/2.1/docs/main/SQLAlchemy.html>`_
Populating our database
~~~~~~~~~~~~~~~~~~~~~~~
-<via the consumer upon message arrival>
+
+Now let's plug our database model into our consumer and create a new entry for
+each message as it arrives.
+
+When you specify the name of your ``app`` in your Consumer, as it is defined on
+the ``[moksha.application]`` entry-point, Moksha will automatically hook up a
+SQLAlchemy engine connected to your model as ``self.engine``, and a SQLAlchemy
+ORM session as ``self.DBSession``.
.. code-block:: python
@@ -323,6 +435,9 @@ Populating our database
Querying our database
~~~~~~~~~~~~~~~~~~~~~
+Next up, we're going to create a controller method to query our database and
+display the last 10 entries in our database
+
.. code-block:: python
from demo.model import DBSession, HelloWorldModel
@@ -331,9 +446,25 @@ Querying our database
@expose('mako:demo.templates.model')
def model(self, *args, **kwargs):
- entries = DBSession.query(HelloWorldModel).all()
+ entries = DBSession.query(HelloWorldModel).limit(10).all()
return dict(entries=entries)
+
+Then we create a simple template that displays the entries.
+
+``demo/templates/model.mak``
+
+.. code-block:: html
+
+ <h1>Entries in the HelloWorld model</h1>
+
+ <ul>
+ % for entry in entries:
+ <li>${str(entry.id)} - ${entry.message} - ${str(entry.timestamp)}</li>
+ % endfor
+ </ul>
+
+
.. seealso::
`SQLAlchemy documentation <http://www.sqlalchemy.org/docs>`_
@@ -341,6 +472,10 @@ Querying our database
Caching
-------
+The last step to our demo is to do some caching. As an example, we'll cache
+the previous controller method, so we don't query the database every time
+someone wants to view the latest entries.
+
.. code-block:: python
from pylons import cache
@@ -356,7 +491,7 @@ Caching
return dict(entries=entries)
def _get_entries(self, *args, **kwargs):
- return DBSession.query(HelloWorldModel).all()
+ return DBSession.query(HelloWorldModel).limit(10).all()
.. seealso::
demo/demo/widgets/live.py | 12 ++++++
development.ini | 2 +
docs/_templates/indexcontent.html | 4 ++
docs/main/HelloWorld.rst | 39 +++++++++++++++++++++-
docs/main/UsingLiveSocketOutsideOfMoksha.rst | 34 +++++++++++++++++++
moksha/api/widgets/amqp/amqp.py | 4 +-
moksha/api/widgets/stomp/stomp.py | 4 +-
moksha/apps/demo/MokshaJQPlotDemo/development.ini | 3 +
8 files changed, 96 insertions(+), 6 deletions(-)
New commits:
commit 49288d37bb85ea614449fe47e4a64009b01bcc49
Author: Luke Macken <lmacken(a)redhat.com>
Date: Tue Nov 23 15:54:26 2010 -0500
Add an example of using moksha.send_message in our HelloWorld docs
diff --git a/docs/main/HelloWorld.rst b/docs/main/HelloWorld.rst
index 56ca93f..2dc335d 100644
--- a/docs/main/HelloWorld.rst
+++ b/docs/main/HelloWorld.rst
@@ -248,6 +248,34 @@ You can send messages with Moksha's JavaScript API using the following function:
moksha.send_message('helloworld', {'foo': 'bar'});
+So let's add a simple little text field to our HelloWorldWidget that allows people
+to send messages to the `helloworld` topic:
+
+.. code-block:: python
+
+ class HelloWorldWidget(LiveWidget):
+ topic = "helloworld"
+ template = """
+ <b>Hello World Widget</b>
+ <form onsubmit="return send_msg()">
+ <input name="text" id="text"/>
+ </form>
+
+ <ul id="data"/>
+
+ <script>
+ function send_msg() {
+ moksha.send_message('helloworld', {'msg': $('#text').val()});
+ $('#text').val('');
+ return false;
+ }
+ </script>
+ """
+ onmessage = """
+ $('<li/>').text(json.msg).prependTo('#data');
+ """
+
+
Creating a database model
-------------------------
commit 74a2e0825f3029b6d3a3164221d11fbdf551b8d1
Author: Luke Macken <lmacken(a)redhat.com>
Date: Tue Nov 23 15:03:10 2010 -0500
Allow people to send messages in our basic HelloWorldWidget demo
diff --git a/demo/demo/widgets/live.py b/demo/demo/widgets/live.py
index f9d0ad4..d77e974 100644
--- a/demo/demo/widgets/live.py
+++ b/demo/demo/widgets/live.py
@@ -4,7 +4,19 @@ class HelloWorldWidget(LiveWidget):
topic = "helloworld"
template = """
<b>Hello World Widget</b>
+ <form onsubmit="return send_msg()">
+ <input name="text" id="text"/>
+ </form>
+
<ul id="data"/>
+
+ <script>
+ function send_msg() {
+ moksha.send_message('helloworld', {'msg': $('#text').val()});
+ $('#text').val('');
+ return false;
+ }
+ </script>
"""
onmessage = """
$('<li/>').text(json.msg).prependTo('#data');
commit b9323c9e0f5fa5394faf0523dd4c7b57d359055b
Author: Luke Macken <lmacken(a)redhat.com>
Date: Tue Nov 23 14:41:17 2010 -0500
Use jQuery.parseJSON in our live widgets, which will use the native browser
JSON mechanisms if available.
diff --git a/moksha/api/widgets/amqp/amqp.py b/moksha/api/widgets/amqp/amqp.py
index 86589b6..d1c907e 100644
--- a/moksha/api/widgets/amqp/amqp.py
+++ b/moksha/api/widgets/amqp/amqp.py
@@ -89,7 +89,7 @@ class AMQPSocket(Widget):
var dest = msg.header.delivery_properties.routing_key;
var json = null;
try {
- var json = $.secureEvalJSON(msg.body);
+ var json = $.parseJSON(msg.body);
} catch(err) {
moksha.error("Unable to decode JSON message body");
moksha.error(msg);
diff --git a/moksha/api/widgets/stomp/stomp.py b/moksha/api/widgets/stomp/stomp.py
index dafa2ab..a332d75 100644
--- a/moksha/api/widgets/stomp/stomp.py
+++ b/moksha/api/widgets/stomp/stomp.py
@@ -114,7 +114,7 @@ class StompWidget(Widget):
var dest = f.headers.destination;
var json = null;
try {
- var json = $.secureEvalJSON(f.body);
+ var json = $.parseJSON(f.body);
} catch(err) {
moksha.error("Unable to decode JSON message body");
moksha.error(msg);
commit 8a2ec5e9df4d36e3bf6196db36723efa8f600736
Author: Luke Macken <lmacken(a)redhat.com>
Date: Tue Nov 23 14:38:30 2010 -0500
Use moksha.error instead of debug
diff --git a/moksha/api/widgets/amqp/amqp.py b/moksha/api/widgets/amqp/amqp.py
index 785a1a5..86589b6 100644
--- a/moksha/api/widgets/amqp/amqp.py
+++ b/moksha/api/widgets/amqp/amqp.py
@@ -92,7 +92,7 @@ class AMQPSocket(Widget):
var json = $.secureEvalJSON(msg.body);
} catch(err) {
moksha.error("Unable to decode JSON message body");
- moksha.debug(msg);
+ moksha.error(msg);
}
if (moksha_callbacks[dest]) {
for (var i=0; i < moksha_callbacks[dest].length; i++) {
diff --git a/moksha/api/widgets/stomp/stomp.py b/moksha/api/widgets/stomp/stomp.py
index 51c7c13..dafa2ab 100644
--- a/moksha/api/widgets/stomp/stomp.py
+++ b/moksha/api/widgets/stomp/stomp.py
@@ -117,7 +117,7 @@ class StompWidget(Widget):
var json = $.secureEvalJSON(f.body);
} catch(err) {
moksha.error("Unable to decode JSON message body");
- moksha.debug(msg);
+ moksha.error(msg);
}
if (moksha_callbacks[dest]) {
for (var i=0; i < moksha_callbacks[dest].length; i++) {
commit 9b23967191316df31aa55f7e61b8594e162367c1
Author: Luke Macken <lmacken(a)redhat.com>
Date: Tue Nov 23 14:38:02 2010 -0500
Specify the mako compiled templates directory
diff --git a/development.ini b/development.ini
index 21e350d..7b938e8 100644
--- a/development.ini
+++ b/development.ini
@@ -151,6 +151,8 @@ sqlalchemy.pool_recycle = 3600
# Uses python's logging config file format
# http://docs.python.org/lib/logging-config-fileformat.html
+templating.mako.compiled_templates_dir = %(here)s/data/templates
+
[loggers]
keys = root, moksha, sqlalchemy, tg, auth, pylons
diff --git a/moksha/apps/demo/MokshaJQPlotDemo/development.ini b/moksha/apps/demo/MokshaJQPlotDemo/development.ini
index e28d11d..0305c5d 100644
--- a/moksha/apps/demo/MokshaJQPlotDemo/development.ini
+++ b/moksha/apps/demo/MokshaJQPlotDemo/development.ini
@@ -68,7 +68,8 @@ templating.mako.reloadfromdisk = true
# you'll most certainly want to have apache or nginx to write in a directory
# that does not contain any source code in any form for obvious security reasons.
#
-#templating.mako.compiled_templates_dir = /some/dir/where/webserver/has/access
+templating.mako.compiled_templates_dir = %(here)s/data/templates
+
# WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT*
# Debug mode will enable the interactive debugging tool, allowing ANYONE to
commit 4f5bf842b49a4999abc28c58de6925749caac061
Author: Luke Macken <lmacken(a)redhat.com>
Date: Thu Nov 18 16:43:44 2010 -0500
Document Sending messages to from the Live Widget in our Hello World doc
diff --git a/docs/main/HelloWorld.rst b/docs/main/HelloWorld.rst
index 0f8616e..56ca93f 100644
--- a/docs/main/HelloWorld.rst
+++ b/docs/main/HelloWorld.rst
@@ -239,6 +239,15 @@ new messages as they arrive in the users web browser.
:doc:`LiveWidget`
+Sending messages to from the Live Widget
+----------------------------------------
+
+You can send messages with Moksha's JavaScript API using the following function:
+
+.. code-block:: javascript
+
+ moksha.send_message('helloworld', {'foo': 'bar'});
+
Creating a database model
-------------------------
commit 49ea3990bbd57abdb968961735eea9708d1bb0a2
Author: Luke Macken <lmacken(a)redhat.com>
Date: Thu Nov 18 16:43:27 2010 -0500
Link to the demo source in our Hello World doc
diff --git a/docs/main/HelloWorld.rst b/docs/main/HelloWorld.rst
index 729c75a..0f8616e 100644
--- a/docs/main/HelloWorld.rst
+++ b/docs/main/HelloWorld.rst
@@ -5,7 +5,7 @@ Hello World Moksha Demo
The goal of this tutorial is to show the simplicity of Moksha's API by creating
basic "Hello World" components in one demo.
-<link to directory of code and tarball>
+:Demo Source: https://fedorahosted.org/moksha/browser/demo
The Controller
--------------
commit 61f9d561826244e1597257f6282b19be74a7a8ba
Author: Luke Macken <lmacken(a)redhat.com>
Date: Thu Nov 18 16:43:11 2010 -0500
Link to our new docs from our main index
diff --git a/docs/_templates/indexcontent.html b/docs/_templates/indexcontent.html
index fc32192..ecfeb3c 100644
--- a/docs/_templates/indexcontent.html
+++ b/docs/_templates/indexcontent.html
@@ -7,6 +7,8 @@
<span class="linkdescr">High-level goals and concepts</span></p>
<p class="biglink"><a class="biglink" href="{{ pathto("main/GettingStarted") }}">Getting Started</a><br/>
<span class="linkdescr">Instructions for diving in</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("main/HelloWorld") }}">Hello World Demo</a><br/>
+ <span class="linkdescr">A simple Hello World demo</span></p>
<p class="biglink"><a class="biglink" href="{{ pathto("main/MokshaLabs") }}">Moksha Labs</a><br/>
<span class="linkdescr">Experimental apps and widgets</span></p>
<p class="biglink"><a class="biglink" href="{{ pathto("main/Messaging") }}">Messaging</a><br/>
@@ -22,6 +24,8 @@
<span class="linkdescr">Features of and the technology behind them</span></p>
<p class="biglink"><a class="biglink" href="{{ pathto("main/QuickstartTemplates") }}">Quickstart Templates</a><br/>
<span class="linkdescr">Quickly create Moksha components</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("main/UsingLiveSocketOutsideOfMoksha") }}">Using the Live Socket outside of Moksha</a><br/>
+ <span class="linkdescr">Hook any web page up to your message broker</span></p>
<p class="biglink"><a class="biglink" href="{{ pathto("main/PluginEntryPoints") }}">Plugin Entry Points</a><br/>
<span class="linkdescr">Details on plugging in various components</span></p>
<p class="biglink"><a class="biglink" href="{{ pathto("main/IntegratingWithTG2") }}">TurboGears2</a><br/>
commit 291bd0e842fc98f9e70285c4b34d997671523f8f
Author: Luke Macken <lmacken(a)redhat.com>
Date: Thu Nov 18 16:42:51 2010 -0500
Add an initial doc on using Moksha's real-time pipes outside of Python
diff --git a/docs/main/UsingLiveSocketOutsideOfMoksha.rst b/docs/main/UsingLiveSocketOutsideOfMoksha.rst
new file mode 100644
index 0000000..37dc9ed
--- /dev/null
+++ b/docs/main/UsingLiveSocketOutsideOfMoksha.rst
@@ -0,0 +1,34 @@
+Using Moksha's real-time pipes outside of Python
+================================================
+
+Want to add realtime functionality to your existing web site, but don't want to
+have to learn Python or TurboGears?
+
+Thankfully, Moksha allows you to leverage it's realtime pipes on any existing
+web page without having to write a line of Python code.
+
+Add code snippet to your web page
+Configure your message broker
+Start Moksha
+
+.. code-block:: html
+
+ <html>
+ <head>
+ <script src="http://code.jquery.com/jquery-latest.min.js"></script>
+ </head>
+ <body>
+ <ul id="data"/>
+ </body>
+ <script>
+ function consume_message(msg) {
+ $('<li/>').text(msg).appendTo('#data')
+ }
+ </script>
+ <script type="text/javascript" src="http://localhost:8080/livesocket?topic=helloworld&callback=consume_message"></script>
+ </html>
+
+Caveats
+-------
+
+Must be under the same domain name.