jQuery and Parse.com - FRONT-END PROTOTYPING - Rapid Prototyping with JS: Agile JavaScript Development (2014)

Rapid Prototyping with JS: Agile JavaScript Development (2014)

II. FRONT-END PROTOTYPING

3. jQuery and Parse.com

Summary: overview of main jQuery functions, Twitter Bootstrap scaffolding, main LESS components; definitions of JSON, AJAX and CORS; illustrations of JSONP calls on Twitter REST API example; explanations on how to build Chat front-end only application with jQuery and Parse.com; step-by-step instructions on deployment to Heroku and Windows Azure.

“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”Tony Hoare

3.1 Definitions

3.1.1 JavaScript Object Notation

Here is the definition of JavaScript Object Notation, or JSON, from json.org:

JavaScript Object Notation, or JSON, is a lightweight data-interchange format. It is easy for humans to read and write. It is easy for machines to parse and generate. It is based on a subset of the JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999. JSON is a text format that is completely language independent but uses conventions that are familiar to programmers of the C-family of languages, including C, C++, C#, Java, JavaScript, Perl, Python, and many others. These properties make JSON an ideal data-interchange language.

JSON has become a standard for transferring data between different components of web/mobile applications and third-party services. JSON is also widely used inside the applications as a format for configuration, locales, translation files or any other data.

Typical JSON object looks like this:

1 {

2 "a": "value of a",

3 "b": "value of b"

4 }

We have an object with key-value pairs. Keys are on the left and values are on the right side of colons (:). In Computer Science terminology, JSON is equivalent to a hash table, a keyed list or an associative array (depending on a particular language). The only big difference between JSON and JS object literal notation (native JS objects) is that the former is more stringent and requires double quotes (") for key identifiers and string values. Both types can be serialized into a string representation with JSON.stringify() and deserialized with JSON.parse() assuming we have a valid JSON object in a string format.

However, every member of an object can be an array, primitive, or another object; for example:

1 {

2 "posts": [{

3 "title": "Get your mind in shape!",

4 "votes": 9,

5 "comments": ["nice!", "good link"]

6 }, {

7 "title": "Yet another post",

8 "votes":0,

9 "comments": []

10 }

11 ],

12 "totalPost":2,

13 "getData": function () {

14 return new Data().getDate();

15 }

16 }

In the above example, we have an object with the posts property. The value of the posts property is an array of objects with each one of them having title, votes and comments keys. The votes property holds a number primitive, while comments is an array of strings. We also can have function as values; in this case, key is called a method, i.e., getData.

JSON is much more flexible and compact than XML or other data formats as outlined in this article — JSON: The Fat-Free Alternative to XML. Conveniently, MongoDB uses a JSON-like format called BSON, or Binary JSON. More on BSON later in the Node.js and MongoDB chapter.

3.1.2 AJAX

AJAX stands for Asynchronous JavaScript and XML, and is used on a client-side (browser) to send and receive data from the server by utilizing an XMLHttpRequest object in JavaScript language. Despite the name, the use of XML is not required, and JSON is often used instead. That’s why developers almost never say AJAX anymore. Keep in mind that HTTP requests could be made synchronously, but it’s not a good practice to do so. The most typical example of a sync request would be the script tag inclusion.

3.1.3 Cross-Domain Calls

For security reasons, the initial implementation of a XMLHTTPRequest object did not allow for cross-domain calls, i.e., when a client-side code and a server-side one are on different domains. There are methods to work around this issue.

One of them is to use JSONP — JSON with padding/prefix. It’s basically a dynamically, via DOM manipulation, generated script tag. Script tags don’t fall into the same domain limitation. The JSONP request includes a name of a callback function in a request query string. For example, thejQuery.ajax() function automatically generates a unique function name and appends it to the request (which is a one string broken into multiple lines for readability):

1 https://graph.facebook.com/search

2 ?type=post

3 &limit=20

4 &q=Gatsby

5 &callback=jQuery16207184716751798987_1368412972614&_=1368412984735

The second approach is to use Cross-Origin Resource Sharing, or CORS, which is a better solution but it requires control over the server-side to modify response headers. We’ll use this technique in the final version of the Chat example application.

Example of CORS server response header:

1 Access-Control-Allow-Origin: *

More about CORS: Resources by Enable CORS and [Using CORS by HTML5 Rocks Tutorials] (http://www.html5rocks.com/en/tutorials/cors/). Test CORS requests at test-cors.org.

3.2 jQuery

During the training we’ll be using jQuery (http://jquery.com/) for DOM manipulations, HTTP Requests and JSONP calls. jQuery became a de facto standard because of its $ object/function, which provides a simple yet efficient way to access any HTML DOM element on a page by its ID, class, tag name, attribute value, structure or by any combination of thereof. The syntax is very similar to CSS, where we use # for id and . for class selection, e.g.:

1 $("#main").hide();

2 $("p.large").attr("style","color:red");

3 $("#main").show().html("<div>new div</div>");

Here is the list of most commonly used jQuery API functions:

· find(): Selects elements based on the provided selector string

· hide(): Hides an element if it was visible

· show(): Shows an element if it was hidden

· html(): Gets or sets an inner HTML of an element

· append() Injects an element into the DOM after the selected element

· prepend() Injects an element into the DOM before the selected element

· on(): Attaches an event listener to an element

· off() Detaches an event listener from an element

· css(): Gets or sets the style attribute value of an element

· attr() Gets or sets any attribute of an element

· val(): Gets or sets the value attribute of an element

· text(): Gets the combined text of an element and its children

· each(): Iterates over a set of matched elements

Most jQuery functions act not only on a single element, on which they are called, but on a set of matched elements if the result of selection has multiples items. This is a common pitfall that leads to bugs, and it usually happens when a jQuery selector is too broad.

Also, jQuery has many plug-ins and libraries, e.g., jQuery UI, jQuery Mobile, which provide a rich user interface or other functionality.

3.3 Twitter Bootstrap

Twitter Bootstrap is a collection of CSS/LESS rules and JavaScript plug-ins for creating good User Interface and User Experience without spending a lot of time on such details as round-edge buttons, cross-compatibility, responsiveness, etc. This collection or framework is perfect for rapid prototyping of your ideas. Nevertheless, due to its ability to be customized, Twitter Bootstrap is also a good foundation for serious projects. The source code is written in LESS, but plain CSS could be downloaded and used as well.

Here is a simple example of using Twitter Bootstrap scaffolding. The structure of the project should look like this:

1 /bootstrap

2 -index.html

3 /css

4 -bootstrap.min.css

5 ... (other files if needed)

6 /img

7 glyphicons-halflings.png

8 ... (other files if needed)

First let’s create the index.html file with proper tags:

1 <!DOCTYPE html>

2 <html lang="en">

3 <head>

4

5 </head>

6 <body>

7 </body>

8 </html>

Include Twitter Bootstrap library as a minified CSS file:

1 <!DOCTYPE html>

2 <html lang="en">

3 <head>

4 <link

5 type="text/css"

6 rel="stylesheet"

7 href="css/bootstrap.min.css" />

8 </head>

9 <body>

10 </body>

11 </html>

Apply scaffolding with container-fluid and row-fluid classes:

1 <body >

2 <div class="container-fluid">

3 <div class="row-fluid">

4 </div> <!-- row-fluid -->

5 </div> <!-- container-fluid -->

6 </body>

Twitter Bootstrap uses a 12-column grid. The size of an individual cell could be specified by classes spanN, e.g.,”span1”, “span2”, “span12”. There are also classes offsetN, e.g., “offset1”, “offset2”, … “offset12” classes to move cells to the right. A complete reference is available athttp://twitter.github.com/bootstrap/scaffolding.html.

We’ll use span12 and hero-unit classes for the main content block:

1 <div class="row-fluid">

2 <div class="span12">

3 <div id="content">

4 <div class="row-fluid">

5 <div class="span12">

6 <div class="hero-unit">

7 <h1>

8 Welcome to Super

9 Simple Backbone

10 Starter Kit

11 </h1>

12 <p>

13 This is your home page.

14 To edit it just modify

15 <i>index.html</i> file!

16 </p>

17 <p>

18 <a

19 class="btn btn-primary btn-large"

20 href="http://twitter.github.com/bootstrap"

21 target="_blank">

22 Learn more

23 </a>

24 </p>

25 </div> <!-- hero-unit -->

26 </div> <!-- span12 -->

27 </div> <!-- row-fluid -->

28 </div> <!-- content -->

29 </div> <!-- span12 -->

30 </div> <!-- row-fluid -->

The full source code of the index.html from rpjs/boostrap:

1 <!DOCTYPE html>

2 <html lang="en">

3 <head>

4 <link

5 type="text/css"

6 rel="stylesheet"

7 href="css/bootstrap.min.css" />

8 </head>

9 <body >

10 <div class="container-fluid">

11 <div class="row-fluid">

12 <div class="span12">

13 <div id="content">

14 <div class="row-fluid">

15 <div class="span12">

16 <div class="hero-unit">

17 <h1>

18 Welcome to Super

19 Simple Backbone

20 Starter Kit

21 </h1>

22 <p>

23 This is your home page.

24 To edit it just modify

25 <i>index.html</i> file!

26 </p>

27 <p>

28 <a

29 class="btn btn-primary btn-large"

30 href="http://twitter.github.com/bootstrap"

31 target="_blank">

32 Learn more

33 </a>

34 </p>

35 </div> <!-- hero-unit -->

36 </div> <!-- span12 -->

37 </div> <!-- row-fluid -->

38 </div> <!-- content -->

39 </div> <!-- span12 -->

40 </div> <!-- row-fluid -->

41 </div> <!-- container-fluid -->

42 </body>

43 </html>

This example is available for downloading/pulling at GitHub public repository github.com/azat-co/rpjs under rpjs/bootstrap folder.

Other useful tools - CSS frameworks and CSS preprocessors worth checking out:

· Compass: CSS framework

· SASS: extension of CSS3 and analog to LESS

· Blueprint: CSS framework

· Foundation: responsive front-end framework

· Bootswatch: collection of customized Twitter Bootstrap themes

· WrapBootstrap: market place for customized Bootstrap themes

3.4 LESS

LESS is the dynamic stylesheet language. Sometimes, and in this case, it’s true that less is more and more is less. :-)

The browser cannot interpret LESS syntax, so LESS source code must be compiled to CSS in one of the three ways:

1. In the browser by LESS JavaScript library

2. On the server-side by language/framework, i.e., for Node.js there is the LESS module

3. Locally on your Mac OS X machine by LESS App, SimpLESS or a similar app

warning

Warning

Option 1. is okay for a development environment but suboptimal for a production environment.

LESS has variables, mixins and operators, which make it faster for developers to reuse CSS rules. Here is an example of a variable:

3.4.1 Variables

Variables reduce redundancy and allow developers to change values fast by having them in one canonical place. And we know that in design (and styling) we often have to change values very frequently!

LESS code:

1 @color: #4D926F;

2 #header {

3 color: @color;

4 }

5 h2 {

6 color: @color;

7 }

Equivalent in CSS:

1 #header {

2 color: #4D926F;

3 }

4 h2 {

5 color: #4D926F;

6 }

3.4.2 Mixins

This is the syntax for mixin, which acts like a function:

1 .rounded-corners (@radius: 5px) {

2 border-radius: @radius;

3 -webkit-border-radius: @radius;

4 -moz-border-radius: @radius;

5 }

6

7 #header {

8 .rounded-corners;

9 }

10 #footer {

11 .rounded-corners(10px);

12 }

Converts to this in CSS:

1 .rounded-corners (@radius: 5px) {

2 border-radius: @radius;

3 -webkit-border-radius: @radius;

4 -moz-border-radius: @radius;

5 }

6

7 #header {

8 border-radius: 5px;

9 -webkit-border-radius: 5px;

10 -moz-border-radius: 5px;

11 }

12 #footer {

13 border-radius: 10px;

14 -webkit-border-radius: 10px;

15 -moz-border-radius: 10px;

16 }

Mixins can be used without parameters, or with multiple parameters.

3.4.3 Operations

With operations, we can perform math functions on numbers, colors or variables.

Example of an operator in LESS:

1 @the-border: 1px;

2 @base-color: #111;

3 @red: #842210;

4

5 #header {

6 color: @base-color * 3;

7 border-left: @the-border;

8 border-right: @the-border * 2;

9 }

10 #footer {

11 color: @base-color + #003300;

12 border-color: desaturate(@red, 10%);

13 }

The above code compiles in this CSS:

1 @the-border: 1px;

2 @base-color: #111;

3 @red: #842210;

4

5 #header {

6 color: #333333;

7 border-left: 1px;

8 border-right: 2px;

9 }

10 #footer {

11 color: #114411;

12 border-color: #7d2717;

13 }

As you can see, LESS dramatically improves the reusability of plain CSS. Here are some online tools for compilation:

· LESS2CSS: slick browser-based LESS to CSS converter built on Express.js

· lessphp: online demo compiler

· Dopefly: online LESS converter

Other LESS features include:

· Pattern-matching

· Nested Rules

· Functions

· Namespaces

· Scope

· Comments

· Importing

3.5 Example of using third-party API (Twitter) and jQuery

The example is for purely demonstrative purposes. It is not a part of the main Chat application covered in later chapters. The goal is to just illustrate the combination of jQuery, JSONP, and REST API technologies. Please take a look through the code and don’t attempt to run it, because recently Twitter retired its API v1.0. This application most likely won’t runt as-is. If you still want to run this example do so at your own risk by following the instructions below, downloading it from GitHub or copy-pasting it from the PDF version.

information

Note

This example was built with Twitter API v1.0 and might not work with Twitter API v1.1, which requires user authentication for REST API calls. You can get the necessary keys at dev.twitter.com.

In this example, we’ll use jQuery’s $.ajax() function. It has the following syntax:

1 var request = $.ajax({

2 url: url,

3 dataType: "jsonp",

4 data: {page:page, ...},

5 jsonpCallback: "fetchData"+page,

6 type: "GET"

7 });

In the code fragment of an ajax() function above, we used following parameters:

· url is an endpoint of the API

· dataType is the type of data we expect from the server, e.g., “json”, “xml”

· data is the data to be sent to the server

· jsonpCallback is a name of the function, in a string format, to be called after the request comes back

· type is HTTP method of the request, e.g., “GET”, “POST”

For more parameters and examples of ajax() function, go to api.jquery.com/jQuery.ajax.

To assign our function to a user-triggered event, we need to use the click function from the jQuery library. The syntax is very simple:

1 $("#btn").click(function() {

2 ...

3 }

$("#btn") is a jQuery object which points to HTML element in the Document Object Model (DOM) with the id of “btn”. An HTML code for the button itself, with Twitter Bootstrap classes applied:

1 <input

2 type="button"

3 class="primary btn"

4 id="btn"

5 value="Show words in last 1000 tweets"/>

To make sure that all of the elements we want to access/use are in the DOM, we need to enclose all of the DOM manipulation code inside of the following jQuery function:

1 $(document).ready(function(){

2 ...

3 }

information

Note

This is a common mistake with dynamically generated HTML elements. They are not available before they have been created and injected into the DOM.

The following one-page application prints the words in a given Twitter user’s last 200 tweets sorted by frequency of use.

For example, if @jack had tweeted:

1 "hello world"

2 "hello everyone, and world"

3 "hi world"

The result could be:

1 world

2 hello

3 and

4 hi

5 everyone.

The source code is available under the rpjs/jquery folder. It’s just one file app — index.html, and the main JavaScript algorithm implemented this way:

1 $(document).ready(function(){

We use document.ready to postpone execution until the DOM is fully loaded.

1 $('#btn').click(function() {

This lets us attach the click event listener to an element with the “btn” class.

1 var username=$('#username').val();

2 //make ajax call, callback

3 var url =

4 'https://api.twitter.com/1/statuses/user_timeline.json?' +

5 'include_entities=true&include_rts=true&screen_name=' +

6 username + '&count=1000';

We instantiate the username variable and assign it a value from the input field with the username id attribute. On the next line we assign Twitter REST API endpoint URL to a url variable. The endpoint responds with tweets from a user’s timeline.

1 if (username!=''){

2 list = [ ]; //unique global list of words

3 counter = { };

4 var pages = 0;

5 getData(url);

6 }

7 else {

8 alert('Please enter Twitter username')

9 }

Checking for an empty username to avoid sending a bad request. If username is provided, getData() will make a request. We use a named function which we will have to define later, in order to prevent the callback from bloating (infamous pyramid of doom).

1 })

2 });

Closing click and ready callback constructions/blocks.

1 function getData (url) {

2 var request = $.ajax({

3 url: url,

4 dataType: 'jsonp',

5 data: {page:0},

6 jsonpCallback: 'fetchData',

7 type: 'GET'

8 });

9 }

The JSONP fetching function that magically (thanks to jQuery) makes cross-domain calls by injecting script tag, and appending the callback function name to the request query string.

We’ll use list array and counter object variables for the algorithm:

1 var list = [ ]; //unique global list of words

2 var counter = { }; //number of time each word is repeated

The actual function that performs matching and counting:

1 function fetchData (m) {

2 for (i = 0; i < m.length; i++){

3 var words=m[i].text.split(' ');

4 for (j = 0; j < words.length; j++){

5 words[j] = words[j].replace(/\,/g,'');

6 //some other code ...

7 if (words[j].substring(0,4)!="http"&&words[j]!='') {

8 if (list.indexOf(words[j])<0) {

9 list.push(words[j]);

10 counter[words[j]]=1;

11 }

12 else {

13 //add plus one to word coutner

14 counter[words[j]]++;

15 }

16 }

17 }

18 }

This code loops through words and uses hash as a lookup table and counter storage.

1 for (i=0;i<list.length;i++){

2 var max=counter[list[i]];

3 var p=0;

4 for (j=i;j<list.length;j++) {

5 if (counter[list[i]]<counter[list[j]]) {

6 p=list[i];

7 list[i]=list[j];

8 list[j]=p;

9 maxC=i;

10 }

11 }

12 }

The following fragment sorts words (by numbers of repetitions), and prints nicely by injecting output into the DOM:

1 var str='';

2 for (i=0;i<list.length;i++){

3 str+=counter[list[i]]+': '+list[i]+'\n';

4 }

5 $('#log').val(str);

6 $('#info').html('Analyzed: ' + list.length+

7 'word(s) form '+m.length +

8 'tweet(s).');

9 }

The full code of the index.html file:

1 $(document).ready(function(){

2 $('#btn').click(function() {

3 //replace loading image

4 var username=$('#username').val();

5 //make ajax call, callback

6 var url =

7 'https://api.twitter.com/1/statuses/user_timeline.json?' +

8 'include_entities=true&include_rts=true&screen_name=' +

9 username + '&count=1000';

10 if (username!=''){

11 list = [ ]; //unique global list of words

12 counter = { };

13 var pages = 0;

14 getData(url);

15 }

16 else {

17 alert('Please enter Twitter username')

18 }

19 })

20 });

21 function getData (url) {

22 var request = $.ajax({

23 url: url,

24 dataType: 'jsonp',

25 data: {page:0},

26 jsonpCallback: 'fetchData',

27 type: 'GET'

28 });

29 }

30 //ajax callback

31 var list = [ ]; //unique global list of words

32 var counter = { };

33 var pages = 0;

34

35 function fetchData (m) {

36 for (i = 0; i < m.length; i++){

37 var words=m[i].text.split(' ');

38 for (j = 0; j < words.length; j++){

39 words[j] = words[j].replace(/\,/g,'');

40 ...

41 if (words[j].substring(0,4)!="http"&&words[j]!='') {

42 if (list.indexOf(words[j])<0) {

43 list.push(words[j]);

44 counter[words[j]]=1;

45 }

46 else {

47 //add plus one to word couter

48 counter[words[j]]++;

49 }

50 }

51 }

52 }

53 //sort by number of repetitions

54 for (i=0;i<list.length;i++){

55 var max=counter[list[i]];

56 var p=0;

57 for (j=i;j<list.length;j++) {

58 if (counter[list[i]]<counter[list[j]]) {

59 p=list[i];

60 list[i]=list[j];

61 list[j]=p;

62 maxC=i;

63 }

64 }

65 }

66 //print sorted

67 //print nicely with number of repetition

68 var str='';

69 for (i=0; i<list.length; i++){

70 str+=counter[list[i]]+': '+list[i]+'\n';

71 }

72 $('#log').val(str);

73 $('#info').html('Analyzed: ' + list.length+

74 'word(s) form '+m.length +

75 'tweet(s).');

76 }

Try launching it and see if it works with or without the local HTTP server. Hint: It should not work without an HTTP server because of its reliance on JSONP technology.

information

Note

This example was built with Twitter API v1.0 and might not work with Twitter API v1.1, which requires user authentication for REST API calls. You can get the necessary keys at dev.twitter.com. If you feel that there must be a working example please submit your feedback to hi@rpjs.co.

3.6 Parse.com

Parse.com is a service which can be a substitute for a database and a server. It started as means to support mobile application development. Nevertheless, with REST API and JavaScript SDK, Parse.com can be used in any web, and desktop, applications for data storage (and much more), thus making it ideal for rapid prototyping.

Go to Parse.com and sign up for a free account. Create an application, and copy the Application ID, REST API Key, and JavaScript Key. We’ll need these keys to access our collection at Parse.com. Please note the “Data Browser” tab – that’s where you can see you collections and items.

We’ll create a simple application which will save values to the collections using Parse.com JavaScript SDK. Our application will consist of an index.html file and a app.js file. Here is the structure of our project folder:

1 /parse

2 -index.html

3 -app.js

The sample is available at the rpjs/parse folder on GitHub, but you are encouraged to type your own code from scratch. To start, create the index.html file:

1 <html lang="en">

2 <head>

Include the minified jQuery library from Google CDN:

1 <script

2 type="text/javascript"

3 src=

4 "http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js">

5 </script>

Include the Parse.com library from Parse CDN location:

1 <script

2 src="http://www.parsecdn.com/js/parse-1.0.14.min.js">

3 </script>

Include our app.js file:

1 <script type="text/javascript" src="app.js"></script>

2 </head>

3 <body>

4 <!-- We'll do something here -->

5 </body>

6 </html>

Create the app.js file and use the $(document).ready function to make sure that the DOM is ready for manipulation:

1 $(document).ready(function() {

Change parseApplicationId and parseJavaScriptKey to values from the Parse.com application dashboard:

1 var parseApplicationId="";

2 var parseJavaScriptKey="";

Since we’ve included the Parse JavaScript SDK library, we now have access to the global object Parse. We initialize a connection with the keys, and create a reference to a Test collection:

1 Parse.initialize(parseApplicationId, parseJavaScriptKey);

2 var Test = Parse.Object.extend("Test");

3 var test = new Test();

This simple code will save an object with the keys name and text to the Parse.com Test collection:

1 test.save({

2 name: "John",

3 text: "hi"}, {

Conveniently, the save() method accepts the callback parameters success and error just like the jQuery.ajax() function. To get a confirmation, we’ll just have to look at the browser console:

1 success: function(object) {

2 console.log("Parse.com object is saved: "+object);

3 //alternatively you could use

4 //alert("Parse.com object is saved");

5 },

It’s important to know why we failed to save an object:

1 error: function(object) {

2 console.log("Error! Parse.com object is not saved: "+object);

3 }

4 });

5 })

The full source code of index.html:

1 <html lang="en">

2 <head>

3 <script

4 type="text/javascript"

5 src=

6 "http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js">

7 </script>

8 <script

9 src="http://www.parsecdn.com/js/parse-1.0.14.min.js">

10 </script>

11 <script type="text/javascript" src="app.js"></script>

12 </head>

13 <body>

14 <!-- We'll do something here -->

15 </body>

16 </html>

The full source code of the app.js file:

1 $(document).ready(function() {

2 var parseApplicationId="";

3 var parseJavaScriptKey="";

4 Parse.initialize(parseApplicationId, parseJavaScriptKey);

5 var Test = Parse.Object.extend("Test");

6 var test = new Test();

7 test.save({

8 name: "John",

9 text: "hi"}, {

10 success: function(object) {

11 console.log("Parse.com object is saved: "+object);

12 //alternatively you could use

13 //alert("Parse.com object is saved");

14 },

15 error: function(object) {

16 console.log("Error! Parse.com object is not saved: "+object);

17 }

18 });

19 })

warning

Warning

We need to use the JavaScript SDK Key from the Parse.com dashboard with this approach. For the jQuery example, we’ll be using the REST API Key from the same webpage. If you get a 401 Unauthorized error from Parse.com, that’s probably because you have a wrong API key.

If everything was done properly, you should be able to see the Test in Parse.com’s Data Browser populated with values “John” and “hi”. Also, you should see the proper message in your browser’s console in Developer Tools. Parse.com automatically creates objectIDs and timestamps, which will be very useful in our Chat application.

Parse.com also has thorough instructions for the ‘Hello World’ application which are available at the Quick Start Guide sections for new projects and existing ones.

3.7 Chat with Parse.com Overview

The Chat will consist of an input field, a list of messages and a send button. We need to display a list of existing messages and be able to submit new messages. We’ll use Parse.com as a back-end for now, and later switch to Node.js with MongoDB.

You can get a free account at Parse.com. The JavaScript Guide is available at https://parse.com/docs/js_guide and JavaScript API is available at https://parse.com/docs/js/.

After signing up for Parse.com, go to the dashboard and create a new app if you haven’t done so already. Copy your newly created app’s Application ID and JavaScript key and REST API Key. We’ll need it later. There are a few ways to use Parse.com:

· REST API: We’re going to use this approach with the jQuery example

· JavaScript SDK: We just used this approach in our test example above, and we’ll use it in the Backbone.js example later

REST API is a more generic approach. Parse.com provides endpoints which we can request with the $.ajax() method from jQuery library. Here is the description of available URLs and methods: parse.com/docs/rest.

3.8 Chat with Parse.com: REST API and jQuery version

The full code is available under the rpjs/rest folder, but we encourage you to try to write your own application first.

We’ll use Parse.com’s REST API and jQuery. Parse.com supports different origin domain AJAX calls, so we won’t need JSONP.

information

Note

When you decide to deploy your back-end application, which will act as a substitute for Parse.com, on a different domain you’ll need to use either JSONP on the front-end or custom CORS headers on a back-end. This topic will be covered later in the book.

Right now the structure of the application should look like this:

1 index.html

2 css/bootstrap.min.css

3 css/style.css

4 js/app.js

Let’s create a visual representation for the Chat app. What we want is just to display a list of messages with names of users in chronological order. Therefore, a table will do just fine, and we can dynamically create <tr> elements and keep inserting them as we get new messages.

Create a simple HTML file index.html with the following content:

· Inclusion of JS and CSS files

· Responsive structure with Twitter Boostrap

· A table of messages

· A form for new messages

Let’s start with the head and dependencies. We’ll include CDN jQuery, local app.js, local minified Twitter Boostrap and custom stylesheet style.css:

1 <!DOCTYPE html>

2 <html lang="en">

3 <head>

4 <script

5 src=

6 "https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"

7 type ="text/javascript"

8 language ="javascript" ></script>

9 <script src="js/app.js" type="text/javascript"

10 language ="javascript" ></script>

11 <link href="css/bootstrap.min.css" type="text/css"

12 rel="stylesheet" />

13 <link href="css/bootstrap-responsive.min.css" type="text/css"

14 rel="stylesheet" />

15 <link href="css/style.css" type="text/css" rel="stylesheet" />

16 </head>

The body element will have typical Twitter Boostrap scaffolding elements defined by classes container-fluid and row-fluid:

1 <body>

2 <div class="container-fluid">

3 <div class="row-fluid">

4 <h1>Chat with Parse REST API</h1>

The table of messages is empty, because we’ll populate it programmatically from within the JS code:

1 <table class="table table-bordered table-striped">

2 <caption>Messages</caption>

3 <thead>

4 <tr>

5 <th>

6 Username

7 </th>

8 <th>

9 Message

10 </th>

11 </tr>

12 </thead>

13 <tbody>

14 <tr>

15 <td colspan="2">No messages</td>

16 </tr>

17 </tbody>

18 </table>

19 </div>

Another row and here is our new message form in which the SEND button uses Twitter Bootstrap classes btn and btn-primary:

1 <div class="row-fluid">

2 <form id="new-user">

3 <input type="text" name="username"

4 placeholder="Username" />

5 <input type="text" name="message"

6 placeholder="Message" />

7 <a id="send" class="btn btn-primary">SEND</a>

8 </form>

9 </div>

10 </div>

11 </body>

12 </html>

The full source code for index.html:

1 <!DOCTYPE html>

2 <html lang="en">

3 <head>

4 <script

5 src=

6 "https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"

7 type ="text/javascript"

8 language ="javascript" ></script>

9 <script src="js/app.js" type="text/javascript"

10 language ="javascript" ></script>

11 <link href="css/bootstrap.min.css" type="text/css"

12 rel="stylesheet" />

13 <link href="css/bootstrap-responsive.min.css" type="text/css"

14 rel="stylesheet" />

15 <link href="css/style.css" type="text/css" rel="stylesheet" />

16 </head>

17 <body>

18 <div class="container-fluid">

19 <div class="row-fluid">

20 <h1>Chat with Parse REST API</h1>

21 <table class="table table-bordered table-striped">

22 <caption>Messages</caption>

23 <thead>

24 <tr>

25 <th>

26 Username

27 </th>

28 <th>

29 Message

30 </th>

31 </tr>

32 </thead>

33 <tbody>

34 <tr>

35 <td colspan="2">No messages</td>

36 </tr>

37 </tbody>

38 </table>

39 </div>

40 <div class="row-fluid">

41 <form id="new-user">

42 <input type="text" name="username"

43 placeholder="Username" />

44 <input type="text" name="message"

45 placeholder="Message" />

46 <a id="send" class="btn btn-primary">SEND</a>

47 </form>

48 </div>

49 </div>

50 </body>

51 </html>

The table will contain our messages. The form will provide input for new messages.

Now we are going to write three main functions:

1. getMessages(): the function to get the messages

2. updateView(): the function to render the list of messages

3. $('#send').click(...): the function that triggers sending a new message

To keep things simple, we’ll put all of the logic in one file app.js. Of course, it a good idea to separate code base on the functionality when your project grows larger.

Replace these values with your own, and be careful to use the REST API Key (not the JavaScript SDK Key from the previous example):

1 var parseID='YOUR_APP_ID';

2 var parseRestKey='YOUR_REST_API_KEY';

Wrap everything in document.ready, fetch messages, and define SEND on click event:

1 $(document).ready(function(){

2 getMessages();

3 $("#send").click(function(){

4 var username = $('input[name=username]').attr('value');

5 var message = $('input[name=message]').attr('value');

6 console.log(username)

7 console.log('!'')

When we submit a new message, we make the HTTP call with the jQuery.ajax function:

1 $.ajax({

2 url: 'https://api.parse.com/1/classes/MessageBoard',

3 headers: {

4 'X-Parse-Application-Id': parseID,

5 'X-Parse-REST-API-Key': parseRestKey

6 },

7 contentType: 'application/json',

8 dataType: 'json',

9 processData: false,

10 data: JSON.stringify({

11 'username': username,

12 'message': message

13 }),

14 type: 'POST',

15 success: function() {

16 console.log('sent');

17 getMessages();

18 },

19 error: function() {

20 console.log('error');

21 }

22 });

23

24 });

25 })

The method to fetch messages from our remote REST API server also uses the jQuery.ajax function:

1 function getMessages() {

2 $.ajax({

3 url: 'https://api.parse.com/1/classes/MessageBoard',

4 headers: {

5 'X-Parse-Application-Id': parseID,

6 'X-Parse-REST-API-Key': parseRestKey

7 },

8 contentType: 'application/json',

9 dataType: 'json',

10 type: 'GET',

If the request is completed successfully (status 200 or similar), we call the updateView function:

1 success: function(data) {

2 console.log('get');

3 updateView(data);

4 },

5 error: function() {

6 console.log('error');

7 }

8 });

9 }

This function is rendering the list of messages which we get from the server:

1 function updateView(messages) {

We use the jQuery selector `.table tbody’ to create an object referencing that element. Then we clean all the innerHTML of that element:

1 var table=$('.table tbody');

2 table.html('');

We use the jQuery.each function to iterate through every message:

1 $.each(messages.results, function (index, value) {

2 var trEl =

The following code creates HTML elements (and the jQuery object of those elements) programmatically:

1 $('<tr><td>'

2 + value.username

3 + '</td><td>'

4 + value.message +

5 '</td></tr>');

And append (injects after) the table’s tbody element:

1 table.append(trEl);

2 });

3 console.log(messages);

4 }

Then all of app.js:

1 var parseID='YOUR_APP_ID';

2 var parseRestKey='YOUR_REST_API_KEY';

3

4 $(document).ready(function(){

5 getMessages();

6 $("#send").click(function(){

7 var username = $('input[name=username]').attr('value');

8 var message = $('input[name=message]').attr('value');

9 console.log(username)

10 console.log('!'')

11 $.ajax({

12 url: 'https://api.parse.com/1/classes/MessageBoard',

13 headers: {

14 'X-Parse-Application-Id': parseID,

15 'X-Parse-REST-API-Key': parseRestKey

16 },

17 contentType: 'application/json',

18 dataType: 'json',

19 processData: false,

20 data: JSON.stringify({

21 'username': username,

22 'message': message

23 }),

24 type: 'POST',

25 success: function() {

26 console.log('sent');

27 getMessages();

28 },

29 error: function() {

30 console.log('error');

31 }

32 });

33

34 });

35 })

36 function getMessages() {

37 $.ajax({

38 url: 'https://api.parse.com/1/classes/MessageBoard',

39 headers: {

40 'X-Parse-Application-Id': parseID,

41 'X-Parse-REST-API-Key': parseRestKey

42 },

43 contentType: 'application/json',

44 dataType: 'json',

45 type: 'GET',

46 success: function(data) {

47 console.log('get');

48 updateView(data);

49 },

50 error: function() {

51 console.log('error');

52 }

53 });

54 }

55

56 function updateView(messages) {

57 var table=$('.table tbody');

58 table.html('');

59 $.each(messages.results, function (index, value) {

60 var trEl =

61 $('<tr><td>'

62 + value.username

63 + '</td><td>'

64 + value.message +

65 '</td></tr>');

66 table.append(trEl);

67 });

68 console.log(messages);

69 }

What it will do is call the getMessages() function and make a GET request with the $.ajax function from the jQuery library. A full list of parameters for the ajax function is available at api.jquery.com/jQuery.ajax. The most important ones are URL, headers and type parameters.

Then, upon successful response, it will call the updateView() function, which clears the table tbody and iterates through results of the response using the $.each jQuery function (api.jquery.com/jQuery.each). Clicking on the send button will send a POST request to Parse.com REST API and then, upon successful response, get messages calling the getMessages() function.

Here is one of the ways to dynamically create the div HTML element using jQuery:

1 $("<div>");

3.9 Pushing to GitHub

To create a GitHub repository, go to github.com, log in and create a new repository. There will be an SSH address; copy it. In your terminal window, navigate to the project folder which you would like to push to GitHub.

1. Create a local Git and .git folder in the root of the project folder:

2. 1 $ git init

3. Add all of the files to the repository and start tracking them:

4. 1 $ git add .

5. Make the first commit:

6. 1 $ git commit -am "initial commit"

7. Add the GitHub remote destination:

8. 1 $ git remote add your-github-repo-ssh-url

It might look something like this:

1 $ git remote add origin git@github.com:azat-co/simple-message-board.git

9. Now everything should be set to push your local Git repository to the remote destination on GitHub with the following command:

10.1 $ git push origin master

11.You should be able to see your files at github.com under your account and repository.

Later, when you make changes to the file, there is no need to repeat all of the steps above. Just execute:

1 $ git add .

2 $ git commit -am "some message"

3 $ git push origin master

If there are no new untracked files which you want to start tracking:

1 $ git commit -am "some message"

2 $ git push origin master

To include changes from individual files, run:

1 $ git commit filename -m "some message"

2 $ git push origin master

To remove a file from the Git repository:

1 $ git rm filename

For more Git commands:

1 $ git --help

Deploying applications with Windows Azure or Heroku is as simple as pushing code/files to GitHub. The last three steps (#4-6) would be substituted with a different remote destination (URL) and a different alias.

3.10 Deployment to Windows Azure

You should be able to deploy to Windows Azure with Git.

1. Go to the Windows Azure Portal at https://windows.azure.com/, log in with your Live ID and create a Web Site if you haven’t done so already. Enable “Set up Git publishing” by providing a username and password (they should be different from your Live ID credentials). Copy your URL somewhere.

2. Create a local Git repository in the project folder which you would like to publish or deploy:

3. 1 $ git init

4. Add all of the files to the repository and start tracking them:

5. 1 $ git add .

6. Make the first commit:

7. 1 $ git commit -am "initial commit"

8. Add Windows Azure as a remote Git repository destination:

9. 1 $ git remote add azure your-url-for-remote-repository

In my case, this command looked like this:

1 $ git remote add

1 > azure https://azatazure@azat.scm.azurewebsites.net/azat.git

10.Push your local Git repository to the remote Windows Azure repository, which will deploy the files and application:

11.1 $ git push azure master

As with GitHub, there is no need to repeat the first few steps when you have updated the files later, since we already should have a local Git repository in the form of .git folder in the root of the project folder.

3.11 Deployment to Heroku

The only major difference is that Heroku uses Cedar Stack, which doesn’t support static projects, a.k.a. plain HTML applications like our Parse.com test application or Parse.com version of the Chat application. We can use a “fake” PHP project to get past this limitation. Create a fileindex.php on the same level as index.html in the project folder, which you would like to publish/deploy to Heroku with the following content:

1 <?php echo file_get_contents('index.html'); ?>

For your convenience, the index.php file is already included in rpjs/rest.

There is an even simpler way to publish static files on Heroku with Cedar stack which is described in the post Static Sites on Heroku Cedar. In order to make Cedar Stack work with your static files, all you need to do is to type and execute following commands in your project folder:

1 $ touch index.php

2 $ echo 'php_flag engine off' > .htaccess

Alternatively, you could use the Ruby Bamboo stack. In this case, we would need the following structure:

1 -project folder

2 -config.ru

3 /public

4 -index.html

5 -/css

6 app.js

7 ...

The path in index.html to CSS and other assets should be relative, i.e., ‘css/style.css’. The config.ru file should contain the following code:

1 use Rack::Static,

2 :urls => ["/stylesheets", "/images"],

3 :root => "public"

4

5 run lambda { |env|

6 [

7 200,

8 {

9 'Content-Type' => 'text/html',

10 'Cache-Control' => 'public, max-age=86400'

11 },

12 File.open('public/index.html', File::RDONLY)

13 ]

14 }

For more details, you could refer to devcenter.heroku.com/articles/static-sites-on-heroku.

Once you have all of the support files for Cedar stack, or Bamboo, follow these steps:

1. Create a local Git repository and .git folder if you haven’t done so already:

2. 1 $ git init

3. Add files:

4. 1 $ git add .

5. Commit files and changes:

6. 1 $ git commit -m "my first commit"

7. Create the Heroku Cedar stack application and add the remote destination:

8. 1 $ heroku create

If everything went well, it should tell you that the remote has been added and the app has been created, and give you the app name.

9. To look up the remote type and execute (optional):

10.1 $ git remote show

11.Deploy the code to Heroku with:

12.1 $ git push heroku master

Terminal logs should tell you whether or not the deployment went smoothly.

13.To open the app in your default browser, type:

14.1 $ heroku open

or just go to the URL of your app, something like “http://yourappname-NNNN.herokuapp.com”.

15.To look at the Heroku logs for this app, type:

16.1 $ heroku logs

To update the app with the new code, repeat the following steps only:

1 $ git add -A

2 $ git commit -m "commit for deploy to heroku"

3 $ git push -f heroku

information

Note

You’ll be assigned a new application URL each time you create a new Heroku app with the command: $ heroku create.

3.12 Updating and Deleting of Messages

In accordance with REST API, an update on an object is performed via the PUT method and delete — DELETE. Both of them can easily be performed with the same jQuery.ajax function that we’ve used for GET and POST, as long as we provide an ID of an object on which we want to execute an operation.