<< Click to Display Table of Contents >> Navigation: Languages > JavaScript > Tutorial > To Do Web Application |
The following guide walks you through the creation of a minimal yet functional To Do web application using IntraWeb 17. This app lets users manage tasks by organizing them across three distinct stages: To Do, In Progress, and Done, with manual controls for moving tasks between categories.
Before getting started, ensure your Apache Server is running and properly configured to serve IWML-based applications. Also, confirm that the basic setup steps for IntraWeb 17 development have been successfully completed.
Project Setup
First, navigate to the directory where your IntraWeb 17 projects are stored: C:\src\IW17\Demos.
Inside this folder, create a new directory named ToDo. This will be the root folder of your application.
Next, create the following three files inside the ToDo folder:
•index.html – the main HTML entry point for the application.
•Index.iwml – the IWML layout file describing the visual structure.
•Index.js – the JavaScript logic file containing application behavior.
Once these files are created, you can begin implementing the structure and logic of your To Do web application.
Editing index.html
Replace the contents of the index.html file with the following code:
<!DOCTYPE html>
<html lang="en">
<head>
<title>To Do</title>
<meta charset="utf-8" />
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="-1">
<meta http-equiv="CACHE-CONTROL" content="NO-CACHE">
<script src="/IW17/IntraWeb/IntraWeb.js"></script>
</head>
<body>
Loading IntraWeb...
</body>
</html>
This file sets up a basic HTML page and loads the core IntraWeb JavaScript framework, which is required to run IWML applications.
Editing Index.iwml
ACORN 1.0 IWML 1.0
# Binds the IWML layout to the logic defined in Index.js
ToDo.Index
# Top-level horizontal layout to contain three columns
SimpleStack
Orientation: Horizontal
# --- To Do Column ---
SimpleStack
Text [b]To Do
# Row containing task input field and button
SimpleStack:InputRow
Orientation: Horizontal
Edit:TaskInput
Hint: Enter task name
Button:AddTaskButton Add Task
# Container for dynamic list of tasks in "To Do"
SimpleStack:ToDoList
Gap 20
# --- In Progress Column ---
SimpleStack
Text [b]In Progress
# Container for dynamic list of tasks in "In Progress"
SimpleStack:InProgressList
Gap 20
# --- Done Column ---
SimpleStack
Text [b]Done
# Container for dynamic list of tasks in "Done"
SimpleStack:DoneList
This layout defines the three columns used in the application: "To Do", "In Progress", and "Done". Each column uses a SimpleStack layout, and the "To Do" section includes a horizontal input row for entering new tasks.
Editing Index.js
// Declare the namespace for the application
var ToDo;
(function (ToDo) {
// Main page logic class, extends IntraWeb.Code
class Index extends IntraWeb.Code {
constructor() {
super(...arguments);
// Three arrays to store tasks by their current state
this._ToDoItems = [];
this._InProgressItems = [];
this._DoneItems = [];
// Field input visibility and references
this._TaskInputVisible = false;
this._TaskInputCell = null;
this._TaskInputParent = null;
}
// Called once the page is fully loaded
WhenPageHasLoaded() {
// Detach the input field until it's needed
if (this.TaskInput?.Cell?.Parent) {
this._TaskInputCell = this.TaskInput.Cell;
this._TaskInputParent = this.TaskInput.Cell.Parent;
this._TaskInputParent.Cells.Remove(this.TaskInput);
this._TaskInputParent.DoRender();
this._TaskInputVisible = false;
// Render initial lists (empty)
this.RenderLists();
}
}
// Handles clicks on the "Add Task" / "Save" button
WhenAddTaskButtonClicked() {
// If input is hidden, show it
if (!this._TaskInputVisible) {
this._TaskInputParent.Cells.Add(this.TaskInput, 0); // insert before the button
this.AddTaskButton.Text.Value = 'Save'; // update button label
this._TaskInputParent.DoRender();
this._TaskInputVisible = true;
this.TaskInput.Focus(); // focus input
} else {
// If input is visible, treat as Save action
const xTaskText = this.TaskInput.Text.Value.trim();
if (xTaskText) this._ToDoItems.push(xTaskText); // add to To Do list
this.TaskInput.Text.Value = ''; // clear field
this._TaskInputParent.Cells.Remove(this.TaskInput); // hide input again
this._TaskInputParent.DoRender();
this._TaskInputVisible = false;
this.AddTaskButton.Text.Value = 'Add Task'; // restore button label
if (xTaskText) this.RenderLists(); // refresh tasks
}
}
// Moves a task from one list to another
MoveTask(aTask, aFrom, aTo) {
if (aFrom === aTo) return;
const xFromList = this.GetList(aFrom);
const xToList = this.GetList(aTo);
const xIndex = xFromList.indexOf(aTask);
if (xIndex >= 0) {
xFromList.splice(xIndex, 1); // remove from source
xToList.push(aTask); // add to target
this.RenderLists(); // re-render
}
}
// Returns the internal task array by its name
GetList(aName) {
switch (aName) {
case 'todo': return this._ToDoItems;
case 'inprogress': return this._InProgressItems;
case 'done': return this._DoneItems;
default: return [];
}
}
// Triggers rendering of all three columns
RenderLists() {
this.RenderColumn(this.ToDoList, this._ToDoItems, 'todo');
this.RenderColumn(this.InProgressList, this._InProgressItems, 'inprogress');
this.RenderColumn(this.DoneList, this._DoneItems, 'done');
}
// Renders a single task list column
RenderColumn(aContainer, aItems, aFrom) {
aContainer.Cells.Clear(); // remove existing children
for (const xItem of aItems) {
const xStack = IntraWeb.Controls.SimpleStack.Create();
xStack.Orientation.Value = IntraWeb.LayoutOrientationEnum.Horizontal;
aContainer.Cells.Add(xStack); // required before populating children
const xText = IntraWeb.Controls.Text.Create();
xText.Text.Value = xItem;
// Add task and buttons based on list type
if (aFrom === 'todo') {
xStack.Cells.Add(xText);
xStack.Cells.Add(this.MakeButton('→', 'inprogress', xItem, aFrom));
} else if (aFrom === 'inprogress') {
xStack.Cells.Add(this.MakeButton('←', 'todo', xItem, aFrom));
xStack.Cells.Add(xText);
xStack.Cells.Add(this.MakeButton('→', 'done', xItem, aFrom));
} else if (aFrom === 'done') {
xStack.Cells.Add(this.MakeButton('←', 'inprogress', xItem, aFrom));
xStack.Cells.Add(xText);
}
}
aContainer.DoRender(); // apply layout updates
}
// Helper to create a button that moves a task between lists
MakeButton(aLabel, aTarget, aTask, aFrom) {
const xButton = IntraWeb.Controls.Button.Create();
xButton.Text.Value = aLabel;
xButton.Clicked.Attach(() => this.MoveTask(aTask, aFrom, aTarget));
return xButton;
}
}
// Register the class inside the namespace
ToDo.Index = Index;
})(ToDo || (ToDo = {}));
Running the Application
Now that the web application is ready, launch the Apache server and navigate to: http://127.0.0.1/demo/ToDo/.
This URL will display the fully functional version of your To Do application.