Sending/Receiving JSON Data
This section explains the working of an embedded webpage solution that uses JSON source data. A list of books in JSON format is sent from the webpage (screenshot below) to an embedded IFrame (framed in blue). Here, the list can be edited using a MobileTogether solution. On saving the changes in the IFrame, the edited book list is sent to the webpage.
The embedded webpage solution consists of the HTML webpage (jsonBooks.html) and a MobileTogether design (jsonBooks.mtd). Both files are located in your (My) Documents MobileTogether folder: MobileTogetherDesignerExamples\Tutorials\EmbeddedWebpageSolutions. To try out the files, deploy the MTD file to your server and enable it to be accessed anonymously. If needed, modify the HTML code so that the IFrame correctly targets the workflow on the server. Open the webpage in a browser and click the Load button to start.
The description below contains the complete HTML code listing of the webpage, followed by a color-coded explanation of how the HTML code interacts with the solution.
HTML code listing
The HTML code listing of the file jsonBooks.html. An explanation of the code is given in the next section below. Please note that some JavaScript functionality used in this example might not be available in all browsers. In this case, please modify the JavaScript to suit your browser.
<!DOCTYPE html> <html> <head> <style> * { font-family: Segoe UI, Tahoma, Arial, Helvetica, sans-serif; } iframe { width: 100%; height: 400px; border: 2px solid blue; border-radius: 5px; margin: 10px 0px; } code { font-size: small; } </style> <script> // The initial book list is stored in a variable in JSON format // It can be easily handled in JavaScript var books = { "books": [ { "author": "Mary Shelley", "title": "Frankenstein; or, The Modern Prometheus", "year": 1818, "pages": 280 }, { "author": "Bram Stoker", "title": "Dracula", "year": 1897, "pages": 302 } ] };
// Posts variable 'books' to IFrame (from where 'books' is forwarded to MT Server) function sendbooks() { document.querySelector('iframe').contentWindow.postMessage(books, '*'); }
// Contents of variable 'books' converted to string and displayed inside HTML element CODE function showbooks() { document.querySelector('code').innerText = JSON.stringify(books, null, ' '); }
// m = HTML message event; data = container for message from server // m.data.json = contents of the 'json' object that was sent from the server function receivebooks(m) { books = m.data.json; showbooks(); }
// Handler to receive messages from server via solution in IFrame window.addEventListener('message', receivebooks);
// Handler to show initial book list in webpage on page load document.addEventListener('DOMContentLoaded', showbooks);
</script> </head>
<body> <h4>Example showing how to interact with a single JSON source</h4> <h5>The books we want to edit:</h5> <!-- Send the JSON book list from the webpage to the IFrame --> <button onclick="sendbooks()">Load</button> <pre><code><!-- The SHOWBOOKS function displays the book list here --></code></pre> <h5> Click LOAD to load the book list into the IFrame. In the IFrame, edit the list. You can add, delete, and/or modify entries. Click SAVE to save changes. Notice that changes are propagated to the list in the webpage. </h5> <iframe src="http://localhost:8083/run?d=/public/jsonBooks" frameborder="0"></iframe> </body>
</html>
|
How it works
In this explanatory part, different background colors are used to indicate what's happening in the individual parts of the mechanism (webpage–solution–workflow):
Webpage: user actions and how the HTML/JavaScript code works | |
Solution: actions carried out by the solution in the IFrame | |
Workflow: processing on the server (based on the MT design) |
On loading the HTML page:
A JavaScript variable named books is read. It contains a JSON object named books.
var books = { "books": [ { "author": "Mary Shelley", "title": "Frankenstein; or, The Modern Prometheus", "year": 1818, "pages": 280 }, { "author": "Bram Stoker", "title": "Dracula", "year": 1897, "pages": 302 } ] };
The content of the books variable is displayed inside the HTML code element by using an event listener (that listens for a DOMContentLoaded event) and a JavaScript function (showbooks):
document.addEventListener('DOMContentLoaded', showbooks);
function showbooks() { document.querySelector('code').innerText = JSON.stringify(books, null, ' '); }
<pre><code></code></pre>
This enables us to see the contents of the books variable when the HTML document is loaded. (Later, we will use the same JavaScript function to check whether the books variable has been updated.)
|
The IFrame loads the solution jsonBooks (targeted in the src attribute of the iframe element):
<iframe src="http://localhost:8083/run?d=/public/jsonBooks" frameborder="0">
|
On clicking the Load button:
<button onclick="sendbooks()">Load</button>
A JavaScript function uses postMessage() to send the contents of the books variable to the IFrame.
function sendbooks() { document.querySelector('iframe').contentWindow.postMessage(books, '*'); }
|
{books} is automatically sent to the workflow on the server (in serialized JSON form). |
Since page event OnEmbeddedMessage has an action defined, ... ... the page source $MT_EMBEDDEDMESSAGE is automatically loaded with the {books} data. For this to work as intended in the design, the structure of the page source (defined at design time) must correspond to the structure of the incoming JSON data. Note that the item node in the page source corresponds to each item in the JSON array. (If the incoming JSON data does not match the structure defined for the page source, it will be loaded anyway—with its own structure. But since XPath expressions in the design will reference the defined structure, the structure loaded at runtime will not be reached by these XPath expressions.) The design contains a repeating table of item nodes. Cells of the table are linked, respectively, to the author, title, year, and pages page source nodes. As a result,... |
...the solution in the IFrame is updated. The repeating table is populated with the data in the workflow's $MT_EMBEDDEDMESSAGE page source. |
On editing the books data in the solution, the $MT_EMBEDDEDMESSAGE page source is continually updated. On clicking Save, an OnButtonClick event handler is triggered. |
The OnButtonClick event specifies that an Embedded Message Back action be performed. This sends the contents of the entire page source $MT_EMBEDDEDMESSAGE as a message event to the IFrame. (Note that $MT_EMBEDDEDMESSAGE now contains the edited book list.) |
An event listener has been registered to listen for the message event. On picking up a message event, a JavaScript function (receivebooks) is called:
window.addEventListener('message', receivebooks);
The receivebooks function (see below) takes the message event (m) as its parameter (data is the data of the message event), and assigns the content of the json object in the received message to the books variable. The books variable now contains the contents of the json object, which is the updated book list from the server. The structure of the modified book list is the same as that of the original book list (but with more or fewer book items in the books array).
function receivebooks(m) { books = m.data.json; showbooks(); }
The showbooks function displays the updated book list in the webpage:
function showbooks() { document.querySelector('code').innerText = JSON.stringify(books, null, ' '); }
<pre><code></code></pre>
|