This final post will discuss the final piece; the UI and how it all comes together.
The User Interface
The default project uses the jQuery mobile plugin to target mobile devices. The jQuery mobile plugin is touch-optimized for smartphones and tablets and it targets iOS, Android, Blackberry, Bada, Windows Phone, Palm WebOS, Symbian and MeeGo.
Lets start with the JavaScript logic, which will perform the interaction between the HTML UI and the JSON web service.
1. In the Scripts folder, add a folder called com then mobile underneath that and finally babyfeeding underneath that
2. In the final babyfeeding folder, add a JavaScript file and called it proxy.js
3. Copy and paste the following code into the js file
if (mobile == undefined) var mobile;
if (!mobile) mobile = {};
//Constructor
mobile.Proxy = function (siteBaseUrl) {
// constructor
mobile.Proxy.prototype.baseUrl = siteBaseUrl;
mobile.Proxy.prototype.heartBeatUrl = siteBaseUrl + "/Services/BabyMonitorService.svc/HeartBeat";
mobile.Proxy.prototype.FeeedingUrl = siteBaseUrl + "/Services/BabyMonitorService.svc/AddFeedingEntry"
mobile.Proxy.prototype.DiaperingUrl = siteBaseUrl + "/Services/BabyMonitorService.svc/AddDiaperingEntry"
}
mobile.Proxy.prototype = {
CallWebService: function (url, input, successCallBack, errorCallBack) {
//Uncomment the next line to support JSONP
//url = url + "?callback=?";
$.ajax({
async: false,
cache: false,
type: "GET",
contentType: "application/json; charset=utf-8",
url: url,
dataType: "json",
data: input,
success: successCallBack,
error: errorCallBack
});
},
HeartBeat: function (successFunction, failFunction) {
this.CallWebService(this.heartBeatUrl, "", successFunction, failFunction);
},
AddFeeding: function (UserId, FeedType, FeedAmount, successFunction, failFunction) {
var input = "UserId=" + UserId + "&FeedType=" + FeedType + "&FeedAmount=" + FeedAmount;
this.CallWebService(this.FeeedingUrl, input, successFunction, failFunction);
},
AddDiapering: function (UserId, DiaperType, successFunction, failFunction) {
var input = "UserId=" + UserId + "&DiaperType=" + DiaperType;
this.CallWebService(this.DiaperingUrl, input, successFunction, failFunction);
}
};
4. The JavaScript is structured using objects and namespaces. Every JavaScript object contains an inner class called Prototype. By defining methods on this inner class, we can encapsulate object variables and methods and share them across concrete instances of the class. In the code above, the Proxy object defines the following methods:
- CallWebService - helper method for invoking the JSON service
- HearBeat - invokes the Heat method call for diagnostics
- AddFeeding - creates a feed entry by taking input from the form and invoking the web service
- AddDiapering - creates an entry for a diaper change by taking input from the form and invoking the web service
Finally, we encapsulate the Proxy object inside the mobile object to create a namespace so that the proxy object can be referenced like so: mobile.Proxy
The Index.cshtml View
Copy and paste the following code for the Index page
@{
ViewBag.Title = "Baby Log Home";
}
<script type="text/javascript">
$(document).ready(function () {
$("#btnSubmit").click(function () {
$("#txtLastEntry").val("Last: ");
// Create the proxt class
var proxy = new mobile.Proxy("@Request.Url.GetLeftPart(UriPartial.Authority)");
// Add the feeding entry
if ($("#chkFeed").attr("checked") != undefined && $("#chkFeed").attr("checked") == "checked") {
proxy.AddFeeding("@Membership.GetUser().UserName", $("#drpType").val(), $("#drpAmount").val(),
function (result) {
// succeeded
$("#txtLastEntry").val($("#txtLastEntry").val() + $("#drpAmount option:selected").text() +
" of " + $("#drpType option:selected").text());
},
function (jqXHR, textStatus, errorThrown) {
// failed
var err = "Details: " + textStatus;
if (errorThrown != undefined) {
err += "\rMore details : " + errorThrown;
}
alert(err);
});
}
// Add the diapering entry
if ($("#chkDiaper").attr("checked") != undefined && $("#chkDiaper").attr("checked") == "checked") {
proxy.AddDiapering("@Membership.GetUser().UserName",
$("#drpDiaper").val(),
function (result) {
// succeeded
$("#txtLastEntry").val($("#txtLastEntry").val() + ", " +
$("#drpDiaper option:selected").text() + " diaper");
},
function (jqXHR, textStatus, errorThrown) {
// failed
var err = "Details: " + textStatus;
if (errorThrown != undefined) {
err += "\rMore details : " + errorThrown;
}
alert(err);
});
}
});
});
</script>
<div data-role="fieldcontain" data-inset="true">
<fieldset data-role="controlgroup">
<legend>Feed Details</legend>
<input id='chkFeed' name='chkFeed-1' type="checkbox" checked="checked" class="custom" />
<label for="chkFeed">
Log Feed</label>
</fieldset>
<fieldset data-role="controlgroup">
<legend>Feed Type:</legend>
@Html.DropDownList("drpType", new List<SelectListItem> {
new SelectListItem { Text="Bottle", Value="Bottle", Selected=true },
new SelectListItem { Text="Left", Value="Left" },
new SelectListItem { Text="Right", Value="Right" },
})
</fieldset>
<fieldset data-role="controlgroup">
<legend>Amount:</legend>
@Html.DropDownList("drpAmount", new List<SelectListItem> {
new SelectListItem { Text="0.5 oz.", Value="0_5" },
new SelectListItem { Text="1.0 oz.", Value="1_0" },
new SelectListItem { Text="1.5 oz.", Value="1_5" },
new SelectListItem { Text="2.0 oz.", Value="2_0" },
new SelectListItem { Text="2.5 oz.", Value="2_5", Selected=true },
new SelectListItem { Text="3.0 oz.", Value="3_0" },
new SelectListItem { Text="3.5 oz.", Value="3_5" },
new SelectListItem { Text="4.0 oz.", Value="4_0" },
new SelectListItem { Text="4.5 oz.", Value="4_5" },
new SelectListItem { Text="5.0 oz.", Value="5_0" },
new SelectListItem { Text="5.5 oz.", Value="5_5" },
new SelectListItem { Text="6.0 oz.", Value="6_0" },
new SelectListItem { Text="6.5 oz.", Value="6_5" },
new SelectListItem { Text="7.0 oz.", Value="7_0" },
new SelectListItem { Text="7.5 oz.", Value="7_5" },
new SelectListItem { Text="8.0 oz.", Value="8_0" },
new SelectListItem { Text="8.5 oz.", Value="8_5" },
new SelectListItem { Text="9.0 oz.", Value="9_0" }
})
</fieldset>
</div>
<div data-role="fieldcontain" data-inset="true">
<fieldset data-role="controlgroup">
<legend>Diaper Details</legend>
<input id='chkDiaper' name='chkDiaper-1' type="checkbox" class="custom" />
<label for="chkDiaper">
Log Diaper</label>
</fieldset>
<fieldset data-role="controlgroup">
<legend>Diaper:</legend>
@Html.DropDownList("drpDiaper", new List<SelectListItem> {
new SelectListItem { Text="Wet", Value="wet", Selected=true },
new SelectListItem { Text="Dirty", Value="dirty" },
new SelectListItem { Text="Both", Value="both" }
})
</fieldset>
</div>
<div data-role="fieldcontain" data-inset="true">
<input id="btnSubmit" type="submit" value="Submit" data-role="button" />
<fieldset data-role="controlgroup">
<input id="txtLastEntry" readonly="readonly" type="text" />
</fieldset>
</div>
The HTML code builds the input form for entering the feed and diaper change details and the Javascript code collects the input, creates the proxy class and calls its methods to invoke the web service.
Notice how the @ tag is used to inject runtime variables, such as the logged on user and the base url.