In this exercise, you will create a data source object that represents a "to-do" note and bind the elements of the noteArea
gadget to this object. All changes made to the data source object will be automatically reflected in bound boxes.
To complete the exercise, follow these steps:
Step 1: Create a new data source object named NoteItem - In a new JavaScript file, define an object that represents a "to-do" note, as well as the functions needed to manage data within the object.
Step 2: Instantiate the NoteItem object and add it to the DOM of the scene - In the noteArea
gadget's onInitialized
function, instantiate the NoteItem
object and then use the addDOMObject
method to add the NoteItem
object to the DOM of the scene.
Step 3: Change the code that modifies noteArea parts to use the data source object - Change the JavaScript functions that manipulate "to-do" item parts directly to use the NoteItem
data object instead.
Step 4: Bind the parts of the noteArea gadget to the data source object - In the noteAreaGadgets.box
file, bind the parts of the noteArea
gadget to the data source object.
Step 5: Testing your application - Run your application and verify that you can create and view "to-do" items.
Step 1: Create a new data source object named NoteItem
To get started, you must first define a data source object that represents a "to-do" note, as well as the functions needed to manage data within the object.
To do so, create a new JavaScript file named NoteItem.js
and add code to:
Create the NoteItem
JavaScript object and declare the following child properties: title
, date
, image
, and description
.
Create the following functions to manage the value stored in each property: setTitle
, setDate
, setImage
, and setDescription
. These functions must also call the notifyPropertyChange
function, which loops through all listeners for the object and notifies the listener of the change made to the property.
Create the following required internal functions:
implementsProtocol
- This function must be defined in the data-bound JavaScript object so that the Boxely UI Toolkit can determine if a box may be bound to the data object. Note: data-bound JavaScript objects must implement the EEObjectSource
protocol, which requires the following functions: addObjectListener
, removeObjectListener
, and notifyPropertyChange
. The Boxely UI Toolkit calls the implementsProtocol
function passing the protocol named ‘EEObjectSource' as a parameter to assure that your JavaScript object implements the EEObjectSource protocol.
addObjectListener
- The Boxely UI Toolkit calls this function when we bind a box to the data object; it adds the bound box to an array of listeners.
removeObjectListener
- The Boxely UI Toolkit calls this function when we unbind a box from the data object; it removes the bound box from the array of listeners.
notifyPropertyChange
- This function loops through all listeners for the object and notifies the listener of the change made to the JavaScript object.
You can create these functions on your own. Or, to save time, you can use the NoteItem.js
exercise file, which is located in the ToDoList/common
directory.
The contents of the NoteItem.js
file are shown here:
function NoteItem() {} NoteItem.prototype.title = ""; NoteItem.prototype.date = ""; NoteItem.prototype.image = ""; NoteItem.prototype.description = ""; NoteItem.prototype.listeners = []; NoteItem.prototype.setTitle = function (title) { this.title = title; this.notifyPropertyChange("title"); } NoteItem.prototype.setDate = function (date) { this.date = date; this.notifyPropertyChange("date"); } NoteItem.prototype.setImage = function (image) { this.image = image; this.notifyPropertyChange("image"); } NoteItem.prototype.setDescription = function (description) { this.description = description; this.notifyPropertyChange("description"); } NoteItem.prototype.addObjectListener = function (object) { this.listeners.push(object); } NoteItem.prototype.implementsProtocol = function (protocol) { return (protocol == "EEObjectSource"); } NoteItem.prototype.removeObjectListener = function (object) { for (i = 0; i < this.listeners.length; i++) { if (this.listeners[i] == object) { this.listeners[i] = null; this.listeners.splice(i, 1); break; } } } NoteItem.prototype.notifyPropertyChange = function (property) { if (this.listeners != null) { for (i = 0; i < this.listeners.length; i++) { if (this.listeners[i] != null) { this.listeners[i].onPropertyChanged(this, property); } } } }
Step 2: Instantiate the NoteItem object and add it to the DOM of the scene
Next, in the noteArea
gadget's onInitialized
function, you must instantiate the NoteItem
object and then use the addDOMObject
method to add the NoteItem
object to the DOM of the scene. (By adding the NoteItem
object to the DOM of the scene, it is made available to all JavaScript and .box files that make up the application.)
Open the noteAreaGadgets.js
file and add the code shown below in bold to complete this step:
component.prototype.onInitialized = function()
{
this.todoItem = new NoteItem();
this.scene.addDOMObject("todoItem", this.todoItem);
}
Step 3: Change the code that modifies noteArea parts to use the data source object
Now that you've created the data source object and instantiated it in the application, you need to change the JavaScript functions that manipulate the "to-do" item data to use the data object's methods.
In the noteAreaGadget's
setDisplay
function, locate the four statements that use the setAttribute
method to update parts within the gadget:
this._gadget.setAttribute("title", item["title"]); this._gadget.setAttribute("date", formatDate(item["date"])); this._gadget.setAttribute("description", item["description"]); this._gadget.setAttribute("image", item["image"]);
Replace these statements with the relevant todoItem
methods shown here:
// Using Data Binding this.todoItem.setTitle(item["title"]); this.todoItem.setDate(item["date"]); this.todoItem.setDescription(item["description"]); this.todoItem.setImage(item["image"]);
In the noteAreaGadget's
blankDisplay
function, locate the four statements that use the setAttribute
method to update parts within the gadget:
this._gadget.setAttribute("title", "[no note to display]"); this._gadget.setAttribute("date", ""); this._gadget.setAttribute("description", "Instructions: Add a note with the button 'Create To-Do Item' below."); this._gadget.setAttribute("image", gDefaultImage);
Replace these statements with the relevant todoItem
methods shown here:
this.todoItem.setTitle("[no note to display]"); this.todoItem.setDate(""); this.todoItem.setDescription ("Instructions: Add a note with the button 'Create To-Do Item' below."); this.todoItem.setImage(gDefaultImage);
Step 4: Bind the parts of the noteArea gadget to the data source object
To bind the parts of the noteArea
gadget to the NoteItem
data source object, use this procedure:
Open the noteAreaGadgets.box
file and add the script
element shown below in bold to load the NoteItem.js
file into the gadget.
<gadget id="noteArea" language="jscript"
code="noteAreaGadgets.js" >
<attributes title="" date="" description="" image="" />
<script id="common" language="jscript"
href="../../common/common.js" />
<script id="NoteItem" language="jscript"
href="../../common/NoteItem.js"/>
<parts>
<box:vbox id="itemContainer" dragMode="data" >
<box:label ignoreEvents="true" id="itemTitle"
inherits="value=title" />
<box:label ignoreEvents="true" id="itemDate"
inherits="value=date" />
<box:vbox ignoreEvents="true" id="descriptionContainer" >
<box:multilineLabel ignoreEvents="true" id="itemDescription"
inherits="value=description" />
</box:vbox>
<box:image ignoreEvents="true" id="itemImage" inherits="src=image" />
</box:vbox>
</parts>
<behavior>
<reaction event="initialized" action="gadget:onInitialized();" />
<reaction event="dragStart" action="gadget:onDragStart();" />
</behavior>
</gadget>
Bind the relevant parts of the noteArea
gadget to the data source object, using the code shown below in bold. (You can delete the inherits
attribute as it is no longer needed.)
<parts> <box:vbox id="itemContainer" dragMode="data" > <box:label ignoreEvents="true" id="itemTitle" > <box:binding objectSource="todoItem" targetProperty="value" path="title" method="oneWay" /> </box:label> <box:label ignoreEvents="true" id="itemDate" > <box:binding objectSource="todoItem" targetProperty="value" path="date" method="oneWay" /> </box:label> <box:vbox ignoreEvents="true" id="descriptionContainer" > <box:multilineLabel ignoreEvents="true" id="itemDescription" > <box:binding objectSource="todoItem" targetProperty="value" path="description" method="oneWay" /> </box:multilineLabel> </box:vbox> <box:image ignoreEvents="true" id="itemImage" inherits="src=image" > <box:binding objectSource="todoItem" targetProperty="src" path="image" method="oneWay" /> </box:image> </box:vbox> </parts>
Step 5: Testing your application
Now when you run your application, the "to-do" list items that you create and view are bound to the NoteItem
data source object. When the data source object is modified, the changes will automatically be reflected in the noteArea
gadget.