HTML5 vs. Native Mobile Applications – Who do you Back?

Recently, we have seen a surge in the ongoing debate of whether it is best to develop mobile applications using HTML5 in some responsive framework manner or as a standalone bespoke-application.

HTML5 Mobile Applications vs. Native Mobile Applications

Generally, the answer is completely dependant on an individual project specification and brief although according to a recent Gartner report amongst 478 developers in North America and Europe, 22% of developers are developing hybrid apps, 24% on mobile web-applications and 41% on native app development such as iOS or Android specific applications.

Consequently, the heated topic often leaves developers opting for one over the other, mostly down to personal preferences. However, developers are shifting more towards the significance of striking a balance between the ability to monetise their applications whilst providing a high quality, easily-understandable and friendly user experience.

The Difference in Development

Developing native applications is generally considered much easier than finding the perfect balance on a responsive website that suits all types of devices. Languages and their supported IDE’s, such as Objective-C and XCode, make rapid development of native mobile applications much easier to accomplish and typically, developers don’t require much understanding of the underlying principles of the platform and its language.

Developers will often find that bug-fixing in native applications is easier than identifying issues on hybrid or HTML5-specific apps. This is mostly due to the complex debugging tools an IDE will provide you with that can pinpoint the exact root and cause of a bug. However, the major disadvantage in development is the fact that every application is native to its OS, device and platform, so developers often need to release multiple versions to accommodate the wide spread of devices.

In contrast, HTML5 developers will often take a different approach with the development. Typically, the developers are familiar with creating web technologies, giving them the advantage that they have a wider skill base to approach the task, without necessarily needing to learn a new IDE or programming language. Also, HTML5 mobile applications can run on any device or platform that has access to a web browser, immediately increasing the development reach – although – you may end up spending equally as much time testing your application – similar to native applications per device testing – you’ll need to cross-browser check your application. With there being an enormous amount of mobile and tablet devices, you’ll need to strike a balance on the devices you want to target and those you decide not to officially support.

Delivering User Experience to Generate a Revenue Stream

If we look through a consumers perspective, monetisation and development are two different things entirely. If we take a game as an example, you’ll only be focusing initially on the visual appeal of the application and, once we have purchased the game, how easy it is to play. However, as a developer, you may set in stone additional ways your consumers can turn your app into a revenue stream – are you offering in-app purchases? If you’re using HTML5, how will you integrate the equivalent of in-app purchases to your users, what checkout will you integrate into, is there a charge?

With any application, you want to create something that’s visually appealing, powerful and has a look and feel that’s symbolic to your corporate branding – therefore the user interface (UI) design of your application is hugely important.

With native mobile applications, you have access to higher graphic rendering and better synchronisation that’ll often aid your consumers appeal knowing that the device they’re on can do more than a standalone static HTML5 web-application. Additionally, developing native mobile applications means consumers can take advantage of their devices hardware – you can integrate the camera, GPS, volume, search buttons, etc. directly into your application that can potentially update the UI. Of course this goes without saying, HTML5 has come a long way and developers have a batch of new API’s that allow them to access the devices battery, geolocation, though you’ll have to put the effect in to get these working on par with the native mobile application.

When it comes to HTML5, developers have the normal flexibility they have when designing websites. CSS3 allows you to control pretty much every aspect of your website, and, if it doesn’t support a selector you’re after you can always fallback to a Javascript/jQuery selector. However, if we are addressing games, HTML5 doesn’t provide the same level of sophistication we’d hope to implement (unless you get really dirty programming) although with HTML5 you can put together simple, streamline applications that are low in development cost, yet high in revenue. The less sophisticated an application design and development is, the more profit you’re likely to make and thus potentially the more preferable the option?

Performance

Performance is always a huge factor to the success of any application. Consumers want responsive (in the aspect of load times and non-sluggish behaviour), adaptive and flexible applications that are able to handle a high load of requests - in case the person using the application gets ‘click happy’ – you don’t just want the application to crash and ungraciously handle the issues.

Depending on the type of application you’re looking to develop will assess whether or not you need access to an Internet connection which can be the downfall of most web-applications. How do you access it when you’re stuck in a mobile signal dead spot? Native applications will typically aggressively cache all their content and resources, meaning you’re able to continue using the application when you go offline and simply synchronise all your data when you re-connect either through 3G, 4G or Wi-Fi. However, as applications become more socially connected, both types of application will suffer under the wrath of needing an ‘always connected’ device – even with native applications, there is typically something happening in the background, some form of asynchronous update.

Another factor you’ll want to consider is that of memory and optimisation. You always want to develop any application in the strictest standard possible. You want to ensure you’re not leaking memory on native mobile applications, and ensure you’re not hogging shared memory on web-applications. Native applications such as iOS applications have a huge selection of tools and utilities that able you to debug and test your application for leaks and assignment issues. Thankfully, with HTML5 web-applications you tend to bi-pass this issue altogether, or at least they’re not as major as most tablets, laptops and PC’s will have more resources available.

Overall, it’s valid to say that both native and web applications have an equal share of pitfalls when it comes to performance so it simply comes down to a matter of preference and what you know you’ll be able to manage and refactor when an issue does arise.

A Quick Roundup

As unhelpful as it may seem, I believe a conclusion on the matter is entirely opinion based and therefore biased towards what any developer prefers. If you’re well-versed in Objective-C, C, C++ or Java if you’re not, you may want to learn Objective-C - then you’d most likely enjoy and thus prefer developing native applications. Whilst if you’re already a web designer or developer, you’ll tend to sway towards the HTML5 responsive web-application approach – after all, that’ll cut down your development and provide a platform that can be accessed on all devices that have access to a web browser.

What Next?

Every great mobile application, whether HTML5 based or native to any platform, will require an API. We’ve put together some great articles on designing a REST API server for your mobile application and some programming guidelines for setting up and implementing OAuth2 in Objective-C (for iOS apps).

How to store array in mysql?

This is one of the mostly asked question by php programmer because mysql doesn’t has any array data type. So we can not store array directly into mysql database.

To do this we have to first convert array into string using php serialize() function then save it into mysql database.

php code to store array in database

1
2
3
4
5
6
7
<?
$array = array("foo", "bar", "hello", "world");
$conn=mysql_connect('localhost', 'mysql_user', 'mysql_password');
mysql_select_db("mysql_db",$conn);
$array_string=mysql_escape_string(serialize($array));
mysql_query("insert into table (column) values($array_string)",$conn);
?>

To retrieve array from database

1
2
3
4
5
6
7
8
9
10
<?
$conn=mysql_connect('localhost', 'mysql_user', 'mysql_password');
mysql_select_db("mysql_db",$conn);
$q=mysql_query("select column from table",$conn);
while($rs=mysql_fetch_assoc($q))
{
$array= unserialize($rs['column']);
print_r($array);
}
?>

How to send emails from localhost

For beginners in the field of web development, we usually find ourselves starting out with the XAMPP package to develop using PHP/MySQL. There are times that we need to send emails from our web applications using the PHP mail() function.

If you have access to your ISPs SMTP server. you may configure it in your PHP configuration file. You may use phpinfo() to help you find your configuration file. (in my xampp installation it is at F:\xampp\apache\bin\php.ini)

In your PHP.ini find the ff: lines and modify them using your ISPs SMTP server.

In this example I am using PLDT’s SMTP server. You may surf the web for SMTP servers of other ISPs like the one I found here

[mail function]

SMTP = smtpdsl4.pldtdsl.net

smtp_port = 587

 

For some cases, your ISP blocks you from using their SMTP servers, for those cases you may still be able to send emails using a gmail account. For this you need to have newer versions of XAMPP since older XAMPP packages have old sendmail files. You may still use an old XAMPP version if you replace the default sendmail folder that came with your package with a new sendmail folder from new XAMPP packages.

 

In your PHP.ini find the ff: lines and modify them

[mail function]

;SMTP = smtpdsl4.pldtdsl.net
;smtp_port = 587

sendmail_path = “F:\xampp\sendmail\sendmail.exe -t”
mail.add_x_header = Off

 

In your sendmail.ini (mine is at F:\xampp\sendmail\sendmail.ini)

find the [sendmail] block and add the ff: values.

You will need to input a gmail email address and password so I strongly suggest that you create a dummy account for this purpose.

DO NOT USE YOUR PERSONAL EMAIL ADDRESS

[sendmail]
smtp_server=smtp.gmail.com
smtp_port=587
error_logfile=error.log
debug_logfile=debug.log
auth_username=yourDummyGmailAccount@gmail.com
auth_password=yourDummyGmailAccountPassword
force_sender=myemail@gmail.com

 

restart apache and then try to send a test email

 

$headers = “Reply-To: noreply@mydomain.com\nFrom:noreply@mydomain.com\nContent-Type: text/html;charset=iso-2022-jp\nX-Mailer: PHP/” . phpversion();
$subject = “test email”
$to = “recipient_email@yahoo.com”;

$body = ‘test’;
echo mail($to, $subject ,$body , $headers);

Creating a Photo Tag Wall With Twilio Picture Messaging & PHP

Twilio’s recently announced Picture Messaging has vastly opened up what we can do with text messaging, now we can attach photos to our text messages and have them get used in different ways.

In our case, we are going to build a Photo Tag Wall, which will contain photos linked to tags that will be displayed on a website.

 

This can be handy for events, or parties, or just about anything where you want to associate photos and tags.

To process our photos, we’ll be doing a few different things; We’re going to resize them, we’ll also use pusher to add a little real-time updating to the wall, with the idea of having it displayed on a monitor somewhere and letting it update as needed for everyone to see what is displayed.

We’re going to use the Jolt Microframework for PHP, and Idiorm and Paris for our MySql handling.


Getting Started

Ok, first let’s set up our database:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
CREATE TABLE `tag`(
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL DEFAULT '',
`slug` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `name` (`name`),
KEY `slug` (`slug`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;
CREATE TABLE `photo`(
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`tag_id` bigint(20) NOT  NULL DEFAULT '0',
`file` varchar(255) NOT NULL DEFAULT '',
`from` varchar(255) NOT NULL DEFAULT '',
`country` varchar(255) NOT NULL DEFAULT '',
`datetime` timestamp DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `tag_id` (`tag_id`),
KEY `file` (`file`)
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;

We’re setting up two tables, one to store the tag, and one for the photos and the id to the tag they are associated with.

This table will store the tag, the image, and some meta data about the phone number that sent the photo.

We’re also going to need to download the Jolt framework, the Twilio PHP Library, and Idiorm and Paris.

The first thing you’ll want to do is grab these packages from their respective websites:

Now that you have all the packages downloaded to your computer, it’s time to setup your directory structure. We’ll be putting the files into our site’s root folder.

We’re putting the web services related files inside the Services folder, since it helps us watch where things are.

Ok, let’s set up our config.ini file, open up config.ini in your editor and modify the following settings:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
;site settings
site.name = my site
; rendering vars
views.root = views
views.layout = layout
; session vars
cookies.secret = IeNj0yt0sQu33zeflUFfym0nk1e
cookies.flash = _F
; db stuff
db.enabled = true
db.host = MY DATABASE HOST
db.name = MY DATABASE NAME
db.user = MY DATABASE USER
db.pass = MY DATABASE PASSWORD
; twilio stuff
twilio.accountsid = MY TWILIO ACCOUNT SID
twilio.authtoken = MY TWILIO AUTH TOKEN
twilio.from = MY TWILIO FROM NUMBER

You can see what you’ll have to fill in here, your site name, and URL, your database info and your Twilio info.


Now for the Coding!

To get started, let’s set up our models. We’ll create a file inside the system folder called models.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
class Tag extends Model{
   public function photos(){
      return $this->has_many('Photo');
   }
}
class Photo extends Model {
   public function tag(){
      return $this->belongs_to('Tag');
   }
}
?>

This is a pretty basic model layout, but one nice thing about it, is that we’re using Paris to establish a relationship with the tag table. In fact, because we’ve previously built our database to have a tag_id field in the photo table, this model knows to associate all photos with the tag_id, where tag_id is the table name and the primary key field in the tag table.

The same is true for the Photo class, where we’ve set it to belong to a tag as specified in the tag() function.

This is handy for building a quick model system without a lot of overhead.

We also want to create our functions.php file, which we will also keep inside the system folder:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
<?php
function slugify( $string ){
   $string = strtolower( trim($string) );
   $slug=preg_replace('/[^A-Za-z0-9-]+/', '-', $string);
   return $slug;
}
function cropResize($img,$out='',$dSize=170){
   $x = @getimagesize($img);
   $sw = $x[0];
   $sh = $x[1];
   $yOff = 0;
   $xOff = 0;
   if($sw < $sh) {
      $scale = $dSize / $sw;
      $yOff = $sh/2 - $dSize/$scale/2;
   } else {
      $scale = $dSize / $sh;
      $xOff = $sw/2 - $dSize/$scale/2;
}
$im = @ImageCreateFromJPEG ($img) or // Read JPEG Image
$im = @ImageCreateFromPNG ($img) or // or PNG Image
$im = @ImageCreateFromGIF ($img) or // or GIF Image
$im = false; // If image is not JPEG, PNG, or GIF
if (!$im) {
   readfile ($img);
} else {
   $thumb = @ImageCreateTrueColor ($dSize,$dSize);
   imagecopyresampled($thumb, $im,
   0, 0,
   $xOff,$yOff,
   $dSize, $dSize,
   $dSize / $scale ,$dSize / $scale);
}
if( $out == '' ){
   header('content-type:image/jpeg');
   imagejpeg($thumb);
}else{
   imagejpeg($thumb, $out);
}
}

functions.php will contain two core functions, one function, slugify(), will convert tag names into slugs, and the cropResize() function will take the image we pass to it, and save it within new dimensions.

We’ll be using these functions quite a lot coming up.

Most of our code will be stored inside index.php, so let’s set up the bare bones for it:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
include("system/jolt.php");
require 'system/idiorm.php';
require 'system/paris.php';
require 'system/models.php';
require 'Services/Twilio.php';
require 'system/functions.php';

Ok, we’ve included our files, and nothing happened. Now, let’s get Jolt up and running:

1
2
3
$app = new Jolt();
$app->option('source', 'config.ini');

The above code just sets up Jolt and tells it to read the config.ini file and set our configuration settings, now let’s connect to our database:

1
2
3
4
5
6
7
8
9
if( $app->option('db.enabled') != false ){
   ORM::configure('mysql:host='.$app->option('db.host').';dbname='.$app->option('db.name'));
   ORM::configure('username', $app->option('db.user') );
   ORM::configure('password', $app->option('db.pass') );
}

Our final piece of bootstrapping, we want to set up our Twilio client:

1
2
3
4
5
$client = new Services_Twilio($app->option('twilio.accountsid'), $app->option('twilio.authtoken') );
$fromNumber = $app->option('twilio.from');
$app->store('client',$client);

This is our bootstrap section, so far all we’ve done is included our files, set up our Jolt app, connected to our database and initialized our Twilio client.

Right now, if you run your app, you’ll get a few errors. This is fine, we’ll be taking care of those errors next.


Routing

Now we have to set up our routes and tell our app what to do based on certain rules. These rules will be either get or post.

Our initial rules will be the home page, the tag page, and the listener:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$app->get('/',function(){
$app = Jolt::getInstance();
});
$app->get('/tag/:tag',function($tag){
$app = Jolt::getInstance();
});
$app->post('/listener',function($tag){
$app = Jolt::getInstance();
});
$app->listen();

We’ve just set up the initial bare bones actions for our homepage, which is represented by the '/', our tag page, and our listener.

You’ll notice the listener is a post rather than a get, that is because this is the handler from Twilio when new messages are received.

Lastly, you’ll see the $app->listen(); method call. This is the most important method call we have, as it tells the app to start running.


There’s No Place Like Home

Let’s set up the home page, and build the view that we’ll be displaying for everybody.

Replace the original homepage route with this one:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
$app->get('/', function(){
$app = Jolt::getInstance();
$tags = Model::factory('Tag')->count();
if( isset($tags) ){
   $images = Model::factory('Photo')->count();
   $tagList = Model::factory('Tag')->find_many();
}else{
   $tags = 0;
   $images = 0;
   $tagList = array();
}
$app->render( 'home',array(
   'tags'=>$tags,
   'tagList' => $tagList,
   'fromNumber' => $app->option('twilio.from'),
   'images'=>$images
   ));
});

You’ll also notice that we tell it to render something called ‘home‘, in the views folder, there is a home.php file, open it up and edit it as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<p >Text <span><?php echo $fromNumber ?></span> a picture with the name of a tag.  Your image will be displayed on that tag.</p>
<div>
   <div>
      <p>Number of Tags: <?php echo $tags; ?></p>
      <p>Number of Images: <?php echo $images; ?></p>
   </div>
</div>
<hr />
<h3>Tags</h3>
<ul>
<?php   foreach($tagList as $tag){  ?>
   <li>
   <a href="<?php echo $uri?>/tag/<?php echo $tag->slug?>"><?php echo $tag->name?></a>
   </li>
<?php   }   ?>
</ul>

This file will take the variables we pass from the $app->render() function and make use of them here.

We’re going to display a count of total tags, along with total images, and a list of tags that a visitor can click on.

The actual page layout is controlled by a file called layout.php. Let’s go ahead and update that file now:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<html>
   <head>
      <title><?=$pageTitle?></title>
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet">
      <link href="<?=$uri?>/style.css" rel="stylesheet">
      <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
      <script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
   </head>
   <body>
      <div>
         <div>
            <ul>
               <li><a href="<?=$uri?>">Home</a></li>
            </ul>
            <h3>Photo Wall</h3>
         </div>
      <hr />
      <section>
         <?=$pageContent?>
      </section>
      </div>
   </body>
</html>

This is pretty bare bones HTML, but it covers what we’re needing. All output gets sent to the $pageContent variable in layout.php.


Picture Messaging!

Ok, now let’s handle the actual uploading of pictures from Twilio.

Log into your Twilio account and point a phone number to http://MYSITEURL/listener for SMS messages, where MYSITEURL is the address where you’ve uploaded your app.

We’re going to replace our listener route with this one:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
$app->post('/listener', function(){
$app = Jolt::getInstance();
if ( isset($_POST['NumMedia']) && $_POST['NumMedia'] > 0 ){
   //  let's find out what tag this is for.. or create a new one..
   $thetag = slugify( $_POST['Body'] );
   $tag  = Model::factory('Tag')->where_equal( 'slug', $thetag )->find_one();
   if( isset($tag->id) && !empty($tag->id) ){
      $tag_id = $tag->id;
   }else{
      //  no tag already exists...
      $tag                    = Model::factory('Tag')->create();
      $tag->name              = $_POST['Body'];
      $tag->slug              = slugify( $_POST['Body'] );
      $tag->save();
      $tag_id = $tag->id();
   }
   for ($i = 0; $i < $_POST['NumMedia']; $i++){
   if (strripos($_POST['MediaContentType'.$i], 'image') === False){
      continue;
   }
   $file = sha1($_POST['MediaUrl'.$i]).'.jpg';
   file_put_contents('images/original/'.$file, file_get_contents($_POST['MediaUrl'.$i]));
   chmod ('images/original/'.$file, 01777);
   // Edit image
   $in = 'images/original/'.$file;
   $out = 'images/processed/'.$file;
   cropResize($in,$out,250);
   chmod ('images/processed/'.$file, 01777);
   // Remove Original Image
   unlink('images/original/'.$file);
   $photo              =   Model::factory('Photo')->create();
   $photo->tag_id      =   $tag_id;
   $photo->file        =   $file;
   $photo->from        =   $_POST['From'];
   $photo->country     =   $_POST['FromCountry'];
   $photo->save();
   }
   $message = $app->store('client')->account->messages->sendMessage(
   $app->option('twilio.from'), // From a valid Twilio number
   $_POST['From'], // Text this number
   "Image(s) Added to <".strtolower(trim($_POST['Body']))."> Photo Wall Link: ".$app->option('site.url')."/tag/".strtolower(trim($_POST['Body']))
   );
   return true;
}else{
   if ( isset($_POST['From']) ){
   $message = $app->store('client')->account->messages->sendMessage(
   $app->option('twilio.from'), // From a valid Twilio number
   $_POST['From'], // Text this number
   "MMS error. Please try sending your image again."
   );
}
header('HTTP/1.1 400 Bad Request', true, 400);
return false;
}
});

There is no view associated with this action. Now, let’s go over what it does.

This is only called during a post, hence the $app->post() statement.

When it is activated by someone sending in a message, we check to see if there are any images attached, and if there are, then we cycle through them and save them in the database.

First, we check to see if there are any tags already stored in our database that match the tag we attached to our image, and if there is, then we grab the id from the database, otherwise, we save a new record containing that tag’s information.

Next, we cycle through the uploaded files and make sure they are images. Each image is downloaded locally and stored inside the images/original folder. We then resize and crop the images to be a more manageable size, and store the new files inside the images/processed folder.

Finally, we store the images inside the database, along with some meta data on the call itself, and send a text message back to the sender to tell him or her to check out the tag page.

If no images were attached, then we send them a message that there was an error.


The Photo Wall

Now, we’ve set up the home page, and we’ve set up the listener. What’s left, is to set up the photo wall itself.

This will go inside the $app->get(‘/tag/:tag') call.

Replace the original placeholder with the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// preload photos whenever a matching route has :tag in it
$app->filter('tag_slug', function ($tag_slug){
$app = Jolt::getInstance();
$tag = Model::factory('Tag')->where_equal('slug',$tag_slug)->find_one();
$photos = $tag->photos()->find_many();
$app->store('tag', $tag);
$app->store('photos', $photos);
});
$app->get('/tag/:tag_slug', function($tag_slug){
$app = Jolt::getInstance();
$tag = $app->store('tag');
$photos = $app->store('photos');
$app->render( 'gallery', array(
"pageTitle"=>"viewing Photos for {$tag->name}",
"tag"=>$tag,
"photos"=>$photos
));
});

Notice the $app->filter(), This is a handy method we can set up that will grab the tag and its photos each time the $tag_slug variable is passed, this lets us save on extra queries.

Now, we need to set up a gallery.php page inside views:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<div>
   <h1>#<?php echo $tag->name; ?></h1>
</div>
<hr />
<div>
   <div>
      <div id="container">
         <?php   foreach($photos as $photo){ ?>
         <?php if (file_exists('images/processed/'.$photo->file)){ ?>
      <div>
   <div>
   <a href="<?php echo $uri?>/images/processed/<?php echo $photo->file ?>" title="<?php echo $photo->datetime ?>" >
   <img src="<?php echo $uri?>/images/processed/<?php echo $photo->file ?>" /></a>
   <p><?php echo $photo->datetime?></p>
</div>
</div>
<?php } ?>
<?php } ?>
</div>
</div>
</div>
<script src="//cdnjs.cloudflare.com/ajax/libs/masonry/3.1.1/masonry.pkgd.min.js"></script>
<script type="text/javascript">
var container = document.querySelector('#container');
var msnry = new Masonry( container, {
itemSelector: '.image'
});
</script>

This will display the gallery, and use jQuery masonry to float all the images nicely.


In Conclusion

So that completes our app. You’ve now built a handy little photo wall that can be used to show photos from events. Be sure to checkout the links provided above to learn more about the libraries and frameworks used throughout this article. Thanks for reading.

Ember Components: A Deep Dive

Ember.js is a JavaScript MVC framework that allows developers to create ambitious web applications. Although pure MVC allows a developer to separate concerns, it does not provide you with all the tools and your application will need other constructs.  Today, I’m going to talk about one of those constructs. Ember components are essentially sandboxed re-usable chunks of UI.  If you are not familiar with Ember, please check out Getting Started With Ember.js or the Let’s Learn Ember Course. In this tutorial we will cover the Web Components specification, how to write a component in Ember, talk about composition, explain the difference between an Ember view and an Ember component, and integrating plugins with Ember components.

 


A Word About Web Components

Ember components are based off of the W3C Web Components specification. The specification is comprised of four smaller specifications; templates, decorators, shadow DOM, and custom elements. Of these four concepts only three of them have harden specifications, decorators being the exception. By having the specifications in place, framework developers have been able to polyfill these new APIs prior to them being implemented by browser vendors.

There are several important concepts to grasp when talking about components:

  • Components know nothing about the outside world unless explicitly passed in
  • Components should have a well defined interface to the outside world
  • Components cannot manipulate any JavaScript outside of the component
  • Components can broadcast events
  • Custom elements must be namespaced with a hyphen
  • Outside JavaScript cannot manipulate components

Web Components provide true encapsulation for UI widgets. Below is a diagram of how a component works at the most basic level.

Web Component Diagram

While Ember has successfully polyfilled a lot of a specification, frameworks like AngularJS, Dart, Polymer, and Xtags have similar solutions. The only caveat here is that Ember and Angular currently don’t scope styles to the component. Overtime these polyfill solutions will fade away, and frameworks will adopt the browser vendor’s implementation. This is a fundamentally different approach to development, as we can take advantage of future specifications without tying ourselves to experimental features in browsers.


The Most Basic Ember Component

Now with our knowledge of Web Components, lets implement the very basic my-name component from above, but in Ember. Let’s begin by downloading the Ember Starter Kit from the Ember website. At the time of this tutorial the version of Ember is 1.3.0. Once you have it downloaded open up the files in your favorite editor, delete all of the templates in index.html ( denoted with data-template-name ) and everything in app.js.

The first thing we are going to want to do is create our component template. For the sake of this tutorial we are going to use inline templates. You do this by writing the following in your index.html file. We also need to create a new Ember application in our JavaScript.

1
2
3
4
5
6
7
<script type="text/x-handlebars">
   {{my-name}}
</script>
<script type="text/x-handlebars" data-template-name="components/my-name">
// My component template will go here
</script>
1
var App = Ember.Application.create();

You’ll notice that the data-template-name has a path name instead of just a plain string. The reason why we prefix our component name with "components/" is to tell Ember we are dealing with a component template and not a regular application template. You’ll also notice that the component name has the hyphen in it. This is the namespacing that I had mentioned in the Web Components specification. Namespacing is done so that we do not have name collisions with existing tags.

If we open the browser we shouldn’t see anything different. The reason for this that we have yet to place anything in our my-name template. Let’s take care of that.

1
2
3
4
...
<script type="text/x-handlebars" data-template-name="components/my-name">
   Hi, my name is {{name}}.
</script>
Ember Name Component

Now in the browser you should see something like the image above. We still aren’t finished as you can see we actually aren’t printing out a name. As I mentioned in the first section, components should expose a well defined interface to the outside world. In this case we are concerned with the name. So let’s pass in the name by placing a name attribute on the my-name component.

1
2
3
4
...
<script type="text/x-handlebars">
   {{my-name name="Chad"}}
</script>

When you refresh the page you should see “Hi, my name is Chad”. All of this with writing one line of JavaScript. Now that we have a feel for writing a basic component, let’s talk about the difference between Ember components and Ember views.


Ember Components vs. Ember Views

Ember is an MVC, so some may be thinking, “Why not just use a view for this?” This is a legitimate question. Components actually are a subclass of Ember.View, the biggest difference here is that views are generally found in the context of a controller. Take the example below.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
App.IndexController = Ember.Controller.extend({
  myState: 'on'
});
App.IndexView = Ember.View.extend({
  click: function () {
    var controller = this.get( 'controller' ),
    myState = controller.get( 'mySate' );
    console.log( controller ) // The controller instance
    console.log( myState ) // The string "on"
  }
});
1
2
3
<script type="text/x-handlebars" data-template-name="index">
  {{myState}}
</script>

Views normally sit behind a template and turn raw input ( click, mouseEnter, mouseMove, etc ) into a semantic action ( openMenu, editName, hideModal, etc ) in a controller or route. Another thing to point out is that templates need a context as well. So what ends up happening is that Ember infers the context through naming conventions and the URL. See the diagram below.

Ember Hierarchy

As you can see, there is a level of hierarchy based on the URL and each level of that hierarchy has its own context which is derived through naming conventions.

Ember components do not have a context, they only know about the interface that they define. This allows a component to be rendered into any context, making it decoupled and reusable. If the component exposes an interface, it’s the job of the context to fulfill that interface. In other words, if you want the component to render properly you must supply it with data that it’s expecting. It’s important to note that these passed in values can be both strings or bound properties.

Ember Hierarchy With Components

When bound properties are manipulated inside of a component those changes are still propagated wherever they are referenced in your application. This makes components extremely powerful. Now that we have a good understanding of how components are different from views, let’s look at a more complex example that illustrates how a developer can compose multiple components.


Composition of Components

One really nice thing about Ember is that it’s built on concepts of UI hierarchy and this is very apparent with composition of components. Below is an example of what we are going to make. It’s a simple group chat UI. Obviously I’m not going to write a whole chat service to power the UI but we can look how we can break the UI down into re-usable and composeable components.

Ember Group Chat Component

Let’s first look how we are going to break up the UI into smaller and more digestible parts. Basically anything that we can draw a box around is a component, with the exception of a the text and button inputs at the bottom of the UI. Our goal is to be able to just configure the component at the outer layer and everything should just work.

Group Chat Breakdown

Let’s start by creating a new html file called chat.html and setting up all of the dependencies for Ember. Next create all of templates.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<script type="text/x-handlebars" data-template-name="application">
  {{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="index">
  {{ group-chat messages=model action="sendMessage" }}
</script>
<script type="text/x-handlebars" data-template-name="components/group-chat">
  <div class="chat-component">
    <ul class="conversation">
      {{#each message in messages}}
        <li class="txt">{{chat-message username=message.twitterUserName message=message.text time=message.timeStamp }}</li>
      {{/each}}
    </ul>
    <form class="new-message" {{action submit on="submit"}}>
      {{input type="text" placeholder="Send new message" value=message}}
      {{input type="submit" value="Send"}}
    </form>
  </div>
</script>
<script type="text/x-handlebars" data-template-name="components/chat-message">
  <div class="message media">
    <div class="img">
      {{user-avatar username=username service="twitter"}}
    </div>
    <div class="bd">
      {{user-message message=message}}
      {{time-stamp time=time}}
    </div>
  </div>
</script>
<script type="text/x-handlebars" data-template-name="components/user-avatar">
  <img {{bind-attr src=avatarUrl alt=username}} class="avatar">
</script>
<script type="text/x-handlebars" data-template-name="components/user-message">
  <div class="user-message">{{message}}</div>
</script>
<script type="text/x-handlebars" data-template-name="components/time-stamp">
  <div class="time-stamp">
    <span class="clock" role="presentation"></span>
    <span class="time">{{format-date time}}</span>
  </div>
</script>

You will see that components can be nested inside of other components. This makes components just like legos that we can assemble any way we want. We just need to write to the component’s interface.

If we now go look in the browser we shouldn’t see much because we don’t have any data flowing into the component. You will also notice that even though there is no data, the components do not throw an error. The only thing that actually gets rendered here is the input area and the send button. This is because they aren’t dependent on what is passed in.

Group Chat Without Data

Taking a little bit closer look at the templates you’ll notice that we assigned a couple things on the group-chat component.

1
2
3
<script type="text/x-handlebars" data-template-name="index">
  {{ group-chat messages=model action="sendMessage" }}
</script>

In this case, we are passing the model from the context of the IndexRoute as “messages” and we have set the string of “sendMessage” as the action on the component. The action will be used to broadcast out when the user wants to send a new message. We will cover this later in the tutorial. The other thing that you will notice is that we are setting up strict interfaces to the nested components all of which are using the data passed in from the group-chat interface.

1
2
3
4
5
6
7
...
<ul class="conversation">
  {{#each message in messages}}
    <li class="txt">{{chat-message username=message.twitterUserName message=message.text time=message.timeStamp }}</li>
  {{/each}}
</ul>
...

As mentioned before you can pass strings or bound properties into components. Rule of thumb being, use quotes when passing a string, don’t use quotes when passing a bound property. Now that we have our templates in place, lets throw some mock data at it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
App = Ember.Application.create();
App.IndexRoute = Ember.Route.extend({
  model: function() {
    return [
      {
        id: 1,
        firstName: 'Tom',
        lastName: 'Dale',
        twitterUserName: 'tomdale',
        text: 'I think we should back old Tomster. He was awesome.',
        timeStamp: Date.now() - 400000,
      },
      {
        id: 2,
        firstName: 'Yehuda',
        lastName: 'Katz',
        twitterUserName: 'wycats',
        text: 'That\'s a good idea.',
        timeStamp: Date.now() - 300000,
      }
    ];
  }
});

If we go look at this in the browser now, we should see a bit of progress. But there are still some work to be done, mainly getting the images to show up, formatting the date, and being able to send a new message. Let’s take care of that.

Group Chat Partially Filled With Data

So with our user-avatar component, we want to use a service called Avatars.io to fetch a user’s twitter avatar based on their twitter user name. Let’s look at how the user-image component is used in the template.

1
2
3
4
5
6
7
8
9
<script type="text/x-handlebars" data-template-name="components/chat-message">
...
{{ user-avatar username=username service="twitter" }}
...
</script>
<script type="text/x-handlebars" data-template-name="components/user-avatar">
  <img {{bind-attr src=avatarUrl alt=username}} class="avatar">
</script>

It’s a pretty simple component but you will notice that we have a bound property called avatarUrl. We are going to need to create this property within our JavaScript for this component. Another thing you will note is that we are specifying the service we want to fetch the avatar from. Avatars.io allows you fetch social avatars from Twitter, Facebook, and Instagram. So we can make this component extremely flexible. Let’s write the component.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
App.UserAvatarComponent = Ember.Component.extend({
  avatarUrl: function () {
    var username = this.get( 'username' ),
          service = this.get( 'service' ),
          availableServices = [ 'twitter', 'facebook', 'instagram' ];
    if (  availableServices.indexOf( service ) > -1 ) {
       return 'http://avatars.io/' + service + '/' + username;
    }
    return 'images/cat.png';
  }.property( 'username' , 'service' )
});

As you can see, to create a new component we just follow the naming convention of NAMEOFCOMPONENTComponent and extend Ember.Component. Now if we go back to the browser we should now see our avatars.

Group Chat Without Formatted Date

To take care of the date formatting let’s use moment.js and write a Handlebars helper to format the date for us.

1
2
3
Ember.Handlebars.helper('format-date', function( date ) {
  return moment( date ).fromNow();
});

Now all we need to do is apply the helper to our time stamp component.

1
2
3
4
5
6
<script type="text/x-handlebars" data-template-name="components/time-stamp">
  <div class="time-stamp">
    <span class="clock" role="presentation"></span>
    <span class="time">{{format-date time}}</span>
  </div>
</script>

We should now have a component that formats dates instead of the Unix epoch timestamps.

Group Chat With Dates

We can do one better though. These timestamps should automatically update over the coarse of time. So lets make our time-stamp component do just that.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
App.TimeStampComponent = Ember.Component.extend({
  startTimer: function () {
    var self = this, currentTime;
    this._timer = setInterval( function () {
      currentTime = self.get( 'time' );
      self.set( 'time', ( currentTime - 60000  ) );
    }, 60000 );
  }.on( 'didInsertElement' ),
  killTimer: function () {
    clearInterval( this._timer );
  }.on( 'willDestroyElement' )
});

A couple points to note here are the on() declarative event handler syntax. This was introduced in Ember prior to the 1.0 release. It does exactly what you think it does, when the time-stamp component is inserted into the DOM, startTimer is called. When the element is about to be destroyed and cleaned up the killTimer method will be called. The rest of component just tells the time to update every minute.

The next thing we need to do is setup the action so that when the user hits submit, a new message will be created. Our component shouldn’t care how the data is created it should just broadcast out that the user has tried to send a message. Our IndexRoute will be responsible for taking this action and turning into something meaningful.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
App.GroupChatComponent = Ember.Component.extend({
  message: '',
  actions: {
    submit: function () {
      var message = this.get( 'message' ).trim(),
          conversation = this.$( 'ul' )[ 0 ];
      // Fetches the value of 'action'
      // and sends the action with the message
      this.sendAction( 'action', message );
      // When the Ember run loop is done
      // scroll to the bottom
      Ember.run.next( function () {
        conversation.scrollTop = conversation.scrollHeight;
      });
      // Reset the text message field
      this.set( 'message', '' );
    }
  }
});
1
2
3
4
<form class="new-message" {{action submit on="submit"}}>
  {{input type="text" placeholder="Send new message" value=message}}
  {{input type="submit" value="Send"}}
</form>

Since the group-chat component owns the input and send button we need to react to the user clicking send at this level of abstraction. When the user clicks the submit button it is going to execute the submit action in our component implementation. Within the submit action handler we are going to get the value of message, which is set by by the text input. We will then send the action along with the message. Finally we will reset the message to a black string.

The other odd thing you see here is the Ember.run.next method being called. In Ember there is a queue, normally referred to as the run loop, that get’s flushed when data is changed. This is done to basically coalesce changes and make the change once. So in our case we are saying when the sending of the message is done making any manipulations, call our callback. We need to scroll our ul to the bottom so the user can see the new message after any manipulations. For more on the run loop I suggest reading Alex Matchneer’s article “Everything You Never Wanted to Know About the Ember Run Loop”.

If we go over to the browser and we click the send button, we get a really nice error from Ember saying “Uncaught Error: Nothing handled the event ‘sendMessage’. This is what we expect because we haven’t told our application on how to reaction to these types of events. Let’s fix that.

1
2
3
4
5
6
7
8
9
10
App.IndexRoute = Ember.Route.extend({
 /* … */
  actions: {
   sendMessage: function ( message ) {
      if ( message !== '') {
    console.log( message );
      }
   }
 }
});

Now if we go back to the browser type something into the message input and hit send, we should see the message in the console. So at this point our component is loosely coupled and talking to the rest our application. Let’s do something more interesting with this. First let’s create a new Ember.Object to work as a model for a new message.

1
2
3
4
5
6
7
8
App.Message = Ember.Object.extend({
  id: 3,
  firstName: 'Chad',
  lastName: 'Hietala',
  twitterUserName: 'chadhietala',
  text: null,
  timeStamp: null
});

So when the sendMessage action occurs we are going to want to populate the text and timeStamp field of our Message model, create a new instance of it, and then push that instance into the existing collection of messages.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
App.IndexRoute = Ember.Route.extend({
/* … */
  actions: {
    sendMessage: function ( message ) {
      var user, messages, newMessage;
      if ( message !== '' ) {
        messages = this.modelFor( 'index' ),
        newMessage = App.Message.create({
          text: message,
          timeStamp: Date.now()
        })
        messages.pushObject( newMessage );
      }
    }
  }
});

When we go back to the browser and we should now be able to create new messages.

Group Chat Creating Messages

We now have several different re-usable chucks of UI that we can just place anywhere. For instance if you needed to use an avatar somewhere else in your Ember application we can just reuse the user-avatar component.

1
2
3
4
5
6
<script type="text/x-handlebars" data-template-name="index">
...
{{user-avatar username="horse_js" service="twitter" }}
{{user-avatar username="detroitlionsnfl" service="instagram" }}
{{user-avatar username="KarlTheFog" service="twitter" }}
</script>
User Avatars From Twitter and Instagram

Wrapping jQuery Plugins

So at this point you’re probably wondering “What if I want to use some jQuery plugin in my component?” No problem. For brevity, lets modify our user-avatar component to show a tool tip when we hover over the avatar. I’ve chosen to use the jQuery plugin tooltipster to handle the tooltip. Let’s modify the existing code to utilize tooltipster.

First lets add correct files to our chat.html and modifiy the existing user avatar component.

1
2
3
4
5
6
7
...
<link href="css/tooltipster.css" rel="stylesheet" />
...
<script type="text/JavaScript" src="js/libs/jquery.tooltipster.min.js"></script>
<script type="text/JavaScript" src="js/app.js"></script>
...

And then our JavaScript:

1
2
3
4
5
6
7
8
9
10
11
12
13
App.UserAvatarComponent = Ember.Component.extend({
  /*…*/
  setupTooltip: function () {
    this.$( '.avatar' ).tooltipster({
      animation: 'fade'
    });
  }.on( 'didInsertElement' ),
  destroyTooltip: function () {
    this.$( '.avatar' ).tooltipster( 'destroy' );
  }.on( 'willDestroyElement' )
)};

So once again we see the declarative event listener syntax, but for the first time we see this.$. If you are familiar with jQuery you would expect that we would be querying all the elements with class of ‘avatar’. This isn’t the case in Ember because context is applied. So in our case we are only looking for elements with the class of ‘avatar’ in the user-avatar component. It’s comparable to jQuery’s find method e.g. $( ‘.user-avatar’ ).find( ‘.avatar’ ). On destruction of the element we should unbind the hover event on the avatar and clean up any functionality, this is done by passing ‘destroy’ to tooltipster. If we go to the browser, refresh and hover an image we should see the users username.

Avatar Tooltips

Conclusion

In this tutorial we took a deep dive into Ember components and showed how you can take re-usable chunks of UI to generate larger composites and integrate jQuery plugins. We looked at how components are different from views in Ember. We also covered the idea of interface-based programming when it comes to components. Hopefully I was able to shine some light on not only Ember Components but Web Components and where the Web is headed.