Jaxer WikiLite Guide [edit]

This page explains the WikiLite sample application included with Jaxer.

Contents

Introduction to the WikiLite application

Your Jaxer installation includes an example of a very basic Wiki web application. This simple application allows you to enable text editing, write a few text characters, save your text to a file, and reload your data into the web page when you re-enter or refresh the page.

The diagram below shows the basic flow of this application.

Image:WikiLiteOverview.png

This application consists of a single HTML file (WikiLite/index.html) that contains style information and a bit of JavaScript. Open this page in Aptana Studio to follow along as the following sections walk you through the application code.

Viewing the sample application

Your Jaxer installation (whether as a standalone Jaxer Package or in Aptana Studio) includes the WikiLite application.

To access the WikiLite application from within Aptana Studio:

  1. In the Samples View, expand the Aptana Jaxer folder.
  2. Select the WikiLite example.
  3. Click either the Preview Sample button Image:iconPreviewSample.png to do a quick preview of the sample, or click the Import Sample button Image:iconImportSample.png to import the sample as a project into your workspace.

To access the WikiLite application from a standalone Jaxer Package installation:

  1. Navigate to your Jaxer installation folder, and double-click the StartServers.bat file.
  2. In your web browser, navigate to the following URL: http://localhost:8081/aptana/
  3. From the column on the left, click the Apps and Tools link.
  4. Click the WikiLite link.

About the client-side WikiLite code

Before we what happens on the server with the WikiLite application, let's take a look at the client-side code, including how the web page is laid out.

Style information

The head tag of this web page contains some basic CSS styling, contained in a set of style tags:

[html,N]<style> html { height: 95%; width: 99%; padding: 0; margin: 0; } body { font: 10pt verdana; font-family: verdana; height: 100%; padding: 10px; margin: 0; } #contents { width: 100%; height: 95%; } #editOrSave { width: 100%; } .readonly { font: 8pt verdana; background-color: #f0f0ff; border: none; padding: 8px; } </style>

This styling formats the text area slightly differently than the rest of the page. The .readonly class displays the textarea with a different font and background color when the page is in read-only mode.

The body area

The body of the HTML page consists of a single text area and an input button:

[html,N]<body onserverload="init()">

<textarea id="contents"></textarea>

<input type="button" id="editOrSave" onclick="editOrSave()">

</body>

The textarea holds the contents of the wiki, and the input button has an onclick event handler that toggles the "edit" functionality on when the page is read-only. The button also saves the textarea contents when the page is in "edit" mode.

Note: The body tag also has an onserverload event handler. We'll discuss the functionality of this event handler later on in this article.

Client-side scripting

The head tag contains a script tag with the JavaScript for the WikiLite application. Five of the functions in this script tag perform client-side functionality:

init()

The <tt>init() function is called when the page loads. It sets the page to read-only mode on the page load. It also calls the readAndFill() function, which reads the contents of a file and displays them in the textarea on this page. We'll discuss this in more depth later on in this article.

[javascript,1]function init() { setEditing(false); readAndFill(); }

setEditing()

The setEditing() function sets the mode (read-only or read-write) of the contents area by using the <tt>readOnly and className attributes of "contents". If the "contents" are not "editable", the "contents" are then "readonly".

This function also sets the value of the editOrSave button. If the "contents" are read-only, the button reads "edit". If the "contents" are "editable", the button reads "save", and the function sets the focus to the "contents" area, so that a user can easily type something in the textarea.

[javascript,1]function setEditing(editable) { $("contents").readOnly = !editable; $("contents").className = editable ? "" : "readonly"; $("editOrSave").value = editable ? "save" : "edit"; // set the button label if (editable) { $("contents").focus(); } }

$()

The $() function is a simple helper function to get elements by ID. If you were coding this on your own, you could choose to use the $() function of your favorite Ajax library.

[javascript,1]function $(id) { return document.getElementById(id); }

editOrSave()

The editOrSave() function first determines if you are already in edit mode or not. If you are in edit mode, it does a quick validation check on the contents of the text area, and if these validate, saves the contents and re-sets the page to read-only mode.

If the contents are not valid, editOrSave() throws an alert containing a message describing the error.

If you are not in edit mode, editOrSave() simply toggles off the read-only mode for the contents textarea.

[javascript,1]function editOrSave() { var isEditing = !$("contents").readOnly; if (isEditing) // try to save and get out of edit mode { try { var contents = $("contents").value; checkValid(contents); save(contents); setEditing(false); } catch (e) { alert(e); } } else // go into edit mode { setEditing(true); } }

checkValid()

The checkValid() function does a quick validation check on the number of characters input into "contents". If a user types more than 10000, it throws an error message saying "Too long!".

[javascript,1]function checkValid(contents) { if (contents.length > 10000) { throw "Too long!"; } }

Server-side scripting

Now that you have a basic idea of how the page is set up and how it functions, we'll examine how this page interacts with the Jaxer server. By adding server-side functionality, we're able to save the text that you type into "contents" and have it persist from one session to another.

Since we'll be running our JavaScript on the server, we need to specify this in our script tag. If you look at the script tag in our sample code, you'll see that we've added a runat="server" attribute:

[html, N]<script type="text/javascript" runat="server">

Determining which functions run where

Out of the functions described in the above section, we'll need several of them to be available both on the client and on the server. On line 54, we set the setEditing function to be available to be run on both:

[javascript,N]setEditing.runat = "both";

We need this function available both on the server when we prepare the page and on the client when the user toggles editing mode on and off.

On line 60, we set the $() function to run at both:

[javascript,N]$.runat = "both";

This is so that we can perform various Ajax functionality and DOM manipulation on both the front and back end of the application.

On line 93, we also set the checkValid function to run at both:

[javascript,N]checkValid.runat = "both";

We need to be able to validate the contents on both the client and the server. The client performs an initial check, but the server validation catches anything not caught by the client.

Because the editOrSave function is only applicable to the client, we set its runat value to "client"only.

[javascript,N]editOrSave.runat = "client";

Finally, remember the init() function that was attached to an event handler in the body tag? We want the page to be initialized when the server loads, so this is when we specify for init() to be called:

[html,N]<body onserverload="init()">

Server-side functions

The WikiLite application has three functions that are specific to server-side functionality:

readAndFill()

The readAndFill() function gets the contents of a file that is obtained by calling the getFilePath function. It checks if a file exists at the filepath, and if the file exists, gets the file contents and sets the value "contents" to those file contents. If the file does not exist, readAndFill() leaves "contents" blank.

[javascript,1]function readAndFill() { var filePath = getFilePath(); var fileExists = Jaxer.File.exists(filePath); $("contents").value = fileExists ? Jaxer.File.read(filePath) : ""; }

getFilePath()

The getFilePath() function returns the "contents.txt" file. (This has been hard-coded for the sake of the demo application):

[javascript,1]function getFilePath() { return "contents.txt"; }

save(contents)

The save(contents) function normalizes newline characters for Windows and Mac and then does an additional validation check on the contents. save then finally writes "contents" to the file at getFilePath.

[javascript,1]function save(contents) { contents = contents.replace(/\r\n/g, "\n"); // normalize newlines for Windows/IE; contents = contents.replace(/\r/g, "\n"); // normalize newlines for Mac; checkValid(contents); Jaxer.File.write(getFilePath(), contents); }


We set the proxy value of this function to "true" so that the function can be called from the client, but the contents are actually saved on the server.

[javascript,N]save.proxy = true;

Testing the WikiLite application

This section walks you through a few quick tests to see how the functionality of the WikiLite application works. You'll add some text to the page, save that text to a file on the server, and perform a validation check both on the client and then on the server.

Editing and saving text

To test the functionality of the WikiLite application:

  1. With the index.html file for the WikiLite application open, click the Firefox tab to preview the application in Firefox. The preview should look like the screen below.

    When the page loads, the onserverload event triggers the init() function, which in turn calls the setEditing function to set the text area to read-only. The init() function also calls readAndFill which reads the contents of a remote file (if it exists) and fills the text area with those contents .

    Image:WikiLite1.png

  2. Click the edit button.

    WikiLite enables the text area for typing, which switches from a blue background to a white background. It also changes the name of the button from "edit" to "save". These events happen as a result of calling the editOrSave function.

  3. In the text area, type a few characters, and click the save button.

    Clicking save calls editOrSave again and toggles edit mode off. It also calls the save function, which normalizes whitespace, validates the text contents, and writes the contents to a file on the Jaxer server.

Validating the text area contents

The checkValid function checks whether the text entered into "contents" meets its validity criteria. As currently written, the text must simply be less than 10000 characters. This function is run on the client when it is called by the editOrSave function, and it is also run on the server when it is called by the save function. To test this function yourself, you can make a couple of minor changes to the code.

To test validity checking on the client:

  1. Go to the checkValid function on line 87 in index.html.
  2. Change the length limit from 10000 to 10 (shown below):

    [javascript,1]function checkValid(contents) { if (contents.length > 10) { throw "Too long!"; } }

  3. Test the client-side validation:
    1. Click the Firefox preview tab to preview the page in Firefox.
    2. Click the edit button to toggle on edit mode.
    3. In the text area, type over 10 characters of text.
    4. Click the save button.

      The WikiLite app displays a "Too long!" error telling you that the text that you entered is too long.

To test validity on the server:

  1. Leave the checkValid function with the modification that you made above.
  2. Comment out the validity check on the client-side:
    1. Go to the editOrSave function (line 63).
    2. Comment out line 71, where the checkValid function is called (shown below):

      [javascript,1]function editOrSave() { var isEditing = !$("contents").readOnly; if (isEditing) // try to save and get out of edit mode { try { var contents = $("contents").value; //checkValid(contents); save(contents); setEditing(false); } catch (e) { alert(e); } } else // go into edit mode { setEditing(true); } }

    3. Test the client-side validation:
      1. Click the Firefox preview tab to preview the page in Firefox.
      2. Click the edit button to toggle on edit mode.
      3. In the text area, type over 10 characters of text.
      4. Click the save button.

        The WikiLite app displays a "Too long!" server error telling you that the text that you entered is too long.

    Complete WikiLite application code

    The following code sample is the entire page of code for the WikiLite application:

    [html,1]<html>

    <head>

    <title>WikiLite</title>

    <style> html { height: 95%; width: 99%; padding: 0; margin: 0; } body { font: 10pt verdana; font-family: verdana; height: 100%; padding: 10px; margin: 0; } #contents { width: 100%; height: 95%; } #editOrSave { width: 100%; } .readonly { font: 8pt verdana; background-color: #f0f0ff; border: none; padding: 8px; } </style>

    <script type="text/javascript" runat="server">

    function init() { setEditing(false); readAndFill(); }

    function setEditing(editable) { $("contents").readOnly = !editable; $("contents").className = editable ? "" : "readonly"; $("editOrSave").value = editable ? "save" : "edit"; // set the button label if (editable) { $("contents").focus(); } } setEditing.runat = "both";

    function $(id) { return document.getElementById(id); } $.runat = "both";

    function editOrSave() { var isEditing = !$("contents").readOnly; if (isEditing) // try to save and get out of edit mode { try { var contents = $("contents").value; checkValid(contents); save(contents); setEditing(false); } catch (e) { alert(e); } } else // go into edit mode { setEditing(true); } } editOrSave.runat = "client";

    function checkValid(contents) { if (contents.length > 10000) { throw "Too long!"; } } checkValid.runat = "both";

    function readAndFill() { var filePath = getFilePath(); var fileExists = Jaxer.File.exists(filePath); $("contents").value = fileExists ? Jaxer.File.read(filePath) : ""; }

    function getFilePath() { return "contents.txt"; }

    function save(contents) { contents = contents.replace(/\r\n/g, "\n"); // normalize newlines for Windows/IE; contents = contents.replace(/\r/g, "\n"); // normalize newlines for Mac; checkValid(contents); Jaxer.File.write(getFilePath(), contents); } save.proxy = true;

    </script>

    </head>

    <body onserverload="init()">

    <textarea id="contents"></textarea>

    <input type="button" id="editOrSave" onclick="editOrSave()">

    </body>

    </html>

    Related Topics