Friday, 30 December 2016

The Quest For Mobile Knowledge (Part 2/2)

The second semester started off with a bit of a whimper. It wasn't so much that the coursework was difficult, because it wasn't. We were learning about web services - SOAP and REST. REST, in particular, seemed intuitive because I've been using a scaled-down version of it for years in my AJAX-driven applications.

No, it was because the lecturer in question was being paid by the hour, and on the first day alone he insisted on using the full three hours allotted to our lesson, to explain Client-server Architecture. I've had Client-server Architecture explained to me before, and I've even explained it while teaching. It has never, ever, taken more than ten minutes. This was to set the tone for all our lessons together.

On the other hand, the tutorials involved using a very scaled-down, very portable database known as HSQLDB, which I was pretty sure I'd get to apply in some interesting ways.

Term 1

As explained earlier, we were working on SOAP-based protocols, going through the ins and outs of XML. Nothing really ground-breaking there.

The other module was infinitely more interesting - we got to play with Android Studio. At long last, the very reason I had wanted to take this course in the first place. After having learned all that Java the previous semester, this shed new light on what I had been doing before starting this course. Now I knew what I had been missing - an understanding of Java, namespaces and all that jazz. It all started to look increasingly clearer.

Term 2

Here, we started delving into RESTful web services, and using them in the native Android applications we were developing. I began to make a native Android version of the hybrid app I had made earlier to keep track of my household chores. My web services and database were hosted on www.teochewthunder.com.



Yes, a lot of my coding was still done via copying and pasting, but this time I actually had some idea of what I was doing.

My Learning Methods

You'll probably have figured out by now that I learn mostly by doing. And making extensive use of other resources such as local libraries and the Internet.

That's why I did all those projects on my own time - to really drill in those lessons.

And also because I was - and still am - interested.

Sure, learning the coursework wasn't all that difficult. Even without the extra effort, I would probably have gotten by just doing the school projects and reading the material. Hell, I don't think anyone failed this course.

But I'm not in this just to get by. Getting by was never the point. Graduating and obtaining the certification was never the point. Even having good grades was never the point. Learning was the point of all this.

I had taken this course in order to help me along a path I had started traveling a year prior to this. And it all came to fruition in...

Graduation

… May of this year. That was when I graduated with my third Diploma.

But meh, it's just another piece of paper that may be obsolete in three years. In this business, what certifications you have aren't all that important. People are more interested in what you've done.

To the untrained eye, I had simply obtained certification. But my real harvest from all this was - Java, jQuery, jQuery Mobile, HSQLDB, Android development….

Quite a haul.

This is just the first step. This is just the beginning. One of many beginnings.
I did great! How about some app-lause?!
T___T

Wednesday, 28 December 2016

The Quest For Mobile Knowledge (Part 1/2)

Back in 2013, I started experimenting with mobile development after obtaining my first smartphone. I borrowed a copy of Android Application Development for Dummies from the library, downloaded a working version of Android Studio, and got to coding.


I met with mixed results, and my progress was slow. Sure, my code worked, but only because I typed everything from the example faithfully. I had no idea why it was working. All I really gained from the experience was the knowledge that XML supplied the user interface markup and Java did the rest. Self-learning wasn't cutting it. I needed guidance; being told when I was doing it wrong, and when I was doing it right.

It was around this time in 2014 when I finally decided to get off my arse and work towards a third Diploma. I had just turned 37, settled in a new job, and the time seemed ripe. Before that, I had a Bachelor's Degree and Diploma in Information Technology, and a Specialist Diploma in E-commerce Technology. Diversify or die, that had been the mantra since I left the desktop support job back in 2008. One area that really stood out for me was mobile technology. Having been in web development for years now, I knew mobile technology was here to stay. And learning this stuff could only improve my web dev cred in terms of responsive design, front-end work and cross-platform compatibility. So I looked back to my two alma maters in Temasek Polytechnic and Singapore Polytechnic, but for pragmatic purposes, I chose to take up night classes in the latter as it was a stone's throw from my place.

Meet my classmates 

The first day was a little bit of a culture shock. I know that globalization and Singapore's liberal labor laws had increased the percentage of foreign labor, but still I was in for a little surprise when I realized that less than a quarter of the class were local professionals. Roughly half were from India. Burmese, Filipinos and Singaporeans made up the rest. Were my fellow citizens that set against self-improvement? Was that why I was hearing so many complaints about their jobs being taken away by "invaders"?

Even among the local professionals, there weren't many like me - a code monkey looking to expand his skill-set. They were mostly at managerial level trying to gain an understanding of mobile technology, probably so that they wouldn't get gypped by vendors. There were even a couple of network technicians. Now, I'm not disparaging network techs at all; in fact networking was one of the toughest subjects for me back in school and I have nothing but respect for those who are good enough at it to ply it as a trade. However, the fact remains that these guys not only had never done any kind of software development (much less web development), they had never written a single line of code in their careers. It leads me to think that they hadn't really thought this through and all they were doing was trying to cash in on the Government grants for professional development. And that whoever was vetting suitable applicants for the course, had either been snoozing that day, or taken a very liberal view as to what constituted "experience in web or software development".

All in all, my foreign classmates seemed more my kind of people. And so the first semester began...

Term 1

It all started out mostly with basic Java. Having my roots in C++, PHP and JavaScript made this a breeze. Having spent a year using almost exclusively C# back in 2012, sure didn't hurt. I got through the basics fairly quickly; in fact the real value of these lessons lay in using an IDE such as Eclipse for the first time. I gave myself a little test, implementing what I had done for this web tutorial, in Java. It was completed within minutes. I supplemented all this by reading Java SE 7 Programming Essentials by Michael Ernest. It's a good reference and I hope to review it sometime on this blog.


Concurrently, we were learning the theory behind mobile technology, what constituted web applications, native applications and hybrid applications. To further cement what I was learning, I blogged about it. This phase was more about drawing wireframes and mocking up mobile applications. I took special note of the tools used, such as Pencil. They would come in handy during my day job.

Term 2 

Now we were having fun in Java. We learned the basics of Object-oriented Programming in Java, and I began applying those concepts to my work in PHP and JavaScript as well. I'm not sure this actually improved the robustness of my work, but it definitely made it more extensible. And then we started making GUIs in Java, using the Swing library. This turned out to be interesting, and after handing in my project, I decided to embark on my own project - a memory game written in Java. To that end, I needed to use some stuff that wasn't covered by the lessons, such as timer functions for animations. Frequent reference to Oracle's documentation did the trick.



I'd be remiss here if I didn't give a little shout-out to my tenant Zhao from Guangdong, China. He'd been renting my guest bedroom for the past couple years. Sure, he had his little eccentricities that drove me nuts, such as this habit of singing cheesy pop songs in the middle of the night over and over, leaving the bathroom lights on the entire day… but he was also experienced in Java and a great help whenever I hit a wall. We had also begun learning JQuery Mobile, and this meant I was picking up jQuery as well. I practised what I could with jQuery, the results of which you can see in this web tutorial during Easter.


Again, to further drill in the process of creating a Single-page hybrid app in jQuery Mobile and porting it over to mobile using Cordova, I created a few apps in my own time - an expense tracker (which I’m still using to this day), a household chores tracker, and a mobile compass. During an annual medical checkup, my doctor gave me a valuable piece of advice: if I wanted to succeed at something, I had to make it part of my daily routine. In fact, I had to make it a part of me as much as possible. (She was actually referring to the task of lowering my cholesterol levels, but that’s another tale for another day.) That got me thinking. I wanted to manage my expenses better, right? And my household chores. And I wanted to learn how to make mobile apps.

The obvious solution? Make mobile apps to track my expenses and manage my household chores! I had learned all this really cool stuff, now I simply needed to apply it.

Next

A look at Semester 2

Friday, 23 December 2016

Web Tutorial: Scroll-down Christmas Carol

Christmas Day is looming!

For that, I traditionally write a web tutorial to commemorate the occasion. This year, it will be sinfully simple - a scroll-down card. Y'know, one of those things where content changes on the screen when you scroll.

In order to do that, however, we'll need to start off with a standard HTML layout.
<!DOCTYPE html>
<html>
    <head>
        <title>Xmas Carol</title>

        <style>

        </style>

        <script>

        </script>
    </head>

    <body>

    </body>
</html>


Because we'll be screwing around with div layouts, let's add this to the CSS. It turns all divs a translucent green.
        <style>
            div{background-color:rgba(0,255,0,0.2);}
        </style>


Add a div to the body. The id will be container.
    <body>
        <div id="container">

        </div>
    </body>


This is the style for container. Yep, you didn't read it wrong. The width is set to 100%, and the height is 10 times the height of the screen. Which puts it at a whopping 1000%. This forces the page to be scrollable. However, if you run the code now, you might not see a damn thing even though ideally, you're supposed to see a translucent green overlay.
        <style>
            div{background-color:rgba(0,255,0,0.2);}

            #container
            {
                width:100%;
                height:1000%;
            }
        </style>


You may not see anything until you do this. This ensures that the html and body elements are set at 100% of screen height. This is supposed to be the default, but you know how it is with different browsers...
        <style>
            div{background-color:rgba(0,255,0,0.2);}

            html, body
            {
                height:100%;
                padding:0px;
            }

            #container
            {
                width:100%;
                height:1000%;
            }
        </style>


Now here you go. This is what you should see. padding:0px ensures that there are no ugly spaces at the top.

OK, now let's add another div, id view_wrapper.
    <body>
        <div id="container">
            <div id="view_wrapper">

            </div>
        </div>
    </body>


We style it like so. Width is set to full, height is at 80%, and there's a 5% margin at the top. Most importantly, the position property has been set to fixed so it will remain in the middle of your screen no matter where you scroll.
        <style>
            div{background-color:rgba(0,255,0,0.2);}

            html, body
            {
                height:100%;
                padding:0px;
            }

            #container
            {
                width:100%;
                height:1000%;
            }

            #view_wrapper
            {
                width:100%;
                height:80%;
                position:fixed;
                margin-top:5%;
            }
        </style>


Try it!

One more div nested. Set the id to view.
    <body>
        <div id="container">
            <div id="view_wrapper">
                <div id="view">

                </div>
            </div>
        </div>
    </body>


Style it like this. It occupies 80% of view_wrapper's width, all of its height, and the margin property is set to center it. Properties such as text-align, font-size, font-family and font-weight are optional. Do what you want with those - unless you get really extreme, it won't change the functionality much.
        <style>
            div{background-color:rgba(0,255,0,0.2);}

            html, body
            {
                height:100%;
                padding:0px;
            }

            #container
            {
                width:100%;
                height:1000%;
            }

            #view_wrapper
            {
                width:100%;
                height:80%;
                position:fixed;
                margin-top:5%;
            }

            #view
            {
                width:80%;
                height:100%;
                margin: 0 auto 0 auto;
                text-align:center;
                font-size:5em;
                font-family:verdana;
                font-weight:bold;
            }
        </style>


That's what it should look like now. The view div is meant to contain the content of your text!

Now we're going to write some JavaScript to populate the view div. We start off by declaring a variable lyrics, and populate it with lines from a standard Christmas song. Note that each line is denoted with a "|" symbol.
        <script>
            var lyrics="We wish you a Merry Christmas|We wish you a Merry Christmas|We wish you a Merry Christmas|And a Happy New Year!";
        </script>


Next, we create an array named lines, and set it to contain each line of the lyrics, using the "|" symbol.
        <script>
            var lyrics="We wish you a Merry Christmas|We wish you a Merry Christmas|We wish you a Merry Christmas|And a Happy New Year!";

            var lines=lyrics.split("|");
        </script>


Next, we write a function getScrollPercentage(). It will return the percentage of how much you've scrolled from the top. window.innerHeight has to be multiplied by 10 in this case because you're measuring it against the entire scrollable content, which is 10 times your screen height. The height of container was set at 1000% percent, remember?

So when you reach the bottom, it should be 100%, right? Wrong! And I'll prove it.
        <script>
            var lyrics="We wish you a Merry Christmas|We wish you a Merry Christmas|We wish you a Merry Christmas|And a Happy New Year!";

            var lines=lyrics.split("|");

            function getScrollPercentage()
            {
                return (document.documentElement.scrollTop/(window.innerHeight*10))*100;
            }
        </script>


Add this to your code, and run it.
    <body onscroll="console.log(getScrollPercentage())">


Check your console (Ctrl+Shift+i should do it) and you'll see when you scroll all the way to the bottom, the readout is 90% at most.

So add this line. This is to help decide what percentage of scrollable content to be dedicated to each line, ie. each item in the lines array. Instead of 100%, we only have 90% to work with, so it's (90/lines.length). Since we want to err on the side of caution, we'll round it down using Math.floor().
            var lines=lyrics.split("|");

            var segment_per_line=Math.floor(90/lines.length);

            function getScrollPercentage()
            {
                return (document.documentElement.scrollTop/(window.innerHeight*10))*100;
            }


Now we write the function scrolling(). We set a variable, scrolled, to the current scrolled percentage defined in getScrollPercentage(). Then we get the line number, another variable called line_no, by dividing scrolled with segment_per_line. Erring on the side of caution, again, we use Math.floor() to round it down. Then we set the innerHTML property of the view div to the appropriate item of the lines array.
            function getScrollPercentage()
            {
                return (document.documentElement.scrollTop/(window.innerHeight*10))*100;
            }

            function scrolling()
            {
                var scrolled=getScrollPercentage();
                var line_no=Math.floor(scrolled/segment_per_line);

                document.getElementById("view").innerHTML=lines[line_no];
            }


Change this line, and run your code.
    <body onscroll="scrolling()">


So you should get different lines at different scroll heights! Try scrolling all the way down from the top.

The problem with this...

...is that it's not terribly friendly. You scroll, an entire line appears, then as you scroll, it's replaced by a whole new line just like that. In the case of our chosen stanza, the first three lines are identical! How you you even tell when one line changes to the next?!

The answer: Make each word appear individually, by line.

For that to happen, add this to your code. It runs through each item in the lines array and turns it into an array too. So instead of an array of lines, you have an array of arrays, and each of these sub arrays will contain the words to the lines, in sequence!
            var lines=lyrics.split("|");

            var segment_per_line=Math.floor(90/lines.length);

            for (var i=0;i<lines.length;i++)
            {
                lines[i]=lines[i].split(" ");
            }

            function getScrollPercentage()
            {
                return (document.documentElement.scrollTop/(window.innerHeight*10))*100;
            }


In other words, instead of this...
lines[0] "We wish you a Merry Christmas"
lines[1] "We wish you a Merry Christmas"
lines[2] "We wish you a Merry Christmas"
lines[3] "And a Happy New Year!"

...you get this!
lines[0] ["We","wish","you","a","Merry","Christmas"]
lines[1] ["We","wish","you","a","Merry","Christmas"]
lines[2] ["We","wish","you","a","Merry","Christmas"]
lines[3] ["And","a","Happy","New","Year!"]

Now modify your scrolling() function. The variable segment_completion gives you how many total segments has been completed already. So, for example, if you're at line number 3 and each line is 5% of scroll completion, you have scrolled at least 15%! The next line would be at 20%, so how many words of the current line you display will be the progress you've made from 15% to 20%.
            function scrolling()
            {
                var scrolled=getScrollPercentage();
                var line_no=Math.floor(scrolled/segment_per_line);
                var segment_completion=line_no*segment_per_line;

                document.getElementById("view").innerHTML=lines[line_no];
            }


For that, we'll create a few function, getWordsFromLine(). We'll use this function to determine how many words from the current line (which is now an array, remember?) to display, and display those words instead of the entire line. For that, we pass in the entire sub-array from the lines array which will be defined as lines[line_no], and a value which gives you the percentage scrolled since the last completed segment.
            function getWordsFromLine(line,completion)
            {

            }

            function scrolling()
            {
                var scrolled=getScrollPercentage();
                var line_no=Math.floor(scrolled/segment_per_line);
                var segment_completion=line_no*segment_per_line;

                var words=getWordsFromLine(lines[line_no], scrolled-segment_completion));
                document.getElementById("view").innerHTML=words;
            }


Here, we calculate the completion percentage of the current segment, and assign it to the completion_ratio variable. Then we use this ratio to determine how many words out of the entire line will be displayed, using the number of words (line.length) and completion_ratio.
            function getWordsFromLine(line,completion)
            {
                var completion_ratio=(completion/segment_per_line);
                var words_displayed=Math.ceil(line.length*completion_ratio);
                var words="";
            }


After that, we iterate through the line array using a For loop, adding the necessary number of words, and return the string generated.
            function getWordsFromLine(line,completion)
            {
                var completion_ratio=(completion/segment_per_line);
                var words_displayed=Math.ceil(line.length*completion_ratio);
                var words="";

                for (var i=0;i<words_displayed;i++)
                {
                    words+=line[i]+" ";
                }

                return words;
            }


Run your code! What happens? Bet it worked, didn't it? But you may run into a small problem near the end because lines[line_no] may be undefined due to line_no being larger than the total number of items in lines. So just do this...
            function scrolling()
            {
                var scrolled=getScrollPercentage();
                var line_no=Math.floor(scrolled/segment_per_line);
                var segment_completion=line_no*segment_per_line;

                var words=(lines[line_no]==undefined?"":getWordsFromLine(lines[line_no],scrolled-segment_completion));
                document.getElementById("view").innerHTML=words;
            }


What it basically does is check if lines[line_no] is undefined, and returns an empty string if so. If not, run the getWordsFromLine() function as per normal.

Further improvements?

Well, now your lines appear word by word, but they skip onwards to the next line without pause. That's really unnatural.

So just modify your code like so. Instead of a single "|" symbol, we use a double "||". This ensures that the lines array has more items, specifically an empty item between each line of the song.
            var lyrics="We wish you a Merry Christmas||We wish you a Merry Christmas||We wish you a Merry Christmas||And a Happy New Year!||Good tidings to you||To you and your kin||Good tidings for Christmas||And a Happy New Year!";


Run your code. Is there a nice pause between each line? But let's add an If conditional to this. As in, the content only changes if there are actually words to display. Re-run your code. Now there won't be any blank pauses between each line!
            function scrolling()
            {
                var scrolled=getScrollPercentage();
                var line_no=Math.floor(scrolled/segment_per_line);
                var segment_completion=line_no*segment_per_line;

                var words=(lines[line_no]==undefined?"":getWordsFromLine(lines[line_no],scrolled-segment_completion));

                if (words.length>0)
                {
                    document.getElementById("view").innerHTML=words;
                }
            }


So now you have a nice scrolling card. Let's change the background a bit to remove the placeholder green.
            div{background-color:rgba(0,255,0,0.0);}


Then we'll add this tile to spruce things up.

xmas2016_bg.jpg

            body
            {
                background:url(xmas2016_bg.jpg);
            }


Nice, right?!


Little extras - a mini caroller

Now, for all intents and purposes, your scrolling card is done. But here's a little something to complement the look. I've added the HTML and CSS for a little South Park type caroller. I'm not going to show you how it's done because that's totally not the point of this tutorial at all, but here's the code anyway.
            <div id="view_wrapper">
                <div id="view">

                </div>
                <div id="caroller">
                    <div class="head" id="head">
                        <div class="hair">

                        </div>
                        <div class="mouth" id="mouth">

                        </div>
                    </div>
                    <div class="body">
                        <div class="sheet">

                        </div>
                    </div>
                    <div class="feet">

                    </div>
                </div>
            </div>


Here's the CSS. Change the colors if you like.
            #view
            {
                width:80%;
                height:100%;
                margin: 0 auto 0 auto;
                text-align:center;
                font-size:5em;
                font-family:verdana;
                font-weight:bold;
            }

            #caroller
            {
                width:200px;
                height:300px;
                margin: -20% auto 0 auto;
            }

            #caroller .head
            {
                width:100px;
                height:100px;
                background-color:#AA4400;
                border-radius:50%;
                margin: 0 auto 0 auto;
            }

            #caroller .head .hair
            {
                width:100%;
                height:50%;
            }

            #caroller .head .hair::before,#caroller .head .hair::after
            {
                content:"";
                display:block;
                width:60%;
                height:100%;
                background-color:#000000;
            }

            #caroller .head .hair::before
            {
                border-radius:70% 0%;
                float:left;
                margin-left:-10%;
            }

            #caroller .head .hair::after
            {
                border-radius:0% 70%;
                float:right;
                margin-right:-10%;
            }

            #caroller .head .mouth
            {
                width:0px;
                height:0px;
                background-color:#000000;
                border-radius:50%;
                margin: 10% auto 0 auto;
            }

            #caroller .body
            {
                width:180px;
                height:150px;
                background-color:#AA0000;
                border-radius:40% 40% 0% 0%;
                margin: -5px auto 0 auto;
                padding-top:10px;
            }

            #caroller .body::before,#caroller .body::after
            {
                content:"";
                display:block;
                width:50px;
                height:50px;
                border-radius:50%;
                background-color:#FFFFFF;   
            }

            #caroller .body::before
            {
                float:left;
                margin-left:-10%;
                margin-top:50px;
            }

            #caroller .body::after
            {
                float:right;
                margin-right:-10%;
                margin-top:-30px;
            }

            #caroller .sheet
            {
                width:80%;
                height:50%;
                background-color:#FFFF00;
                margin: 0 auto 0 auto;
            }

            #caroller .feet
            {
                width:150px;
                height:50px;
                background-color:#440000;
                margin: 0 auto 0 auto;
            }

            #caroller .feet::before,#caroller .feet::after
            {
                content:"";
                display:block;
                width:60%;
                height:80%;
                border-radius:50% 50% 0% 0%;
                background-color:#220000;
                margin-top:10px;
            }

            #caroller .feet::before
            {
                float:left;
                margin-left:-10%;
            }

            #caroller .feet::after
            {
                float:right;
                margin-right:-10%;
            }


Cute little bugger, isn't he?!


Now do this to your JavaScript. This ensures that the head and mouth move in random directions when there are words to "sing", and stays still otherwise.
            function generaterandomno(varmin,varmax)
            {
                return Math.floor((Math.random() * (varmax-varmin+1)) + varmin);
            }

            function scrolling()
            {
                var scrolled=getScrollPercentage();
                var line_no=Math.floor(scrolled/segment_per_line);
                var segment_completion=line_no*segment_per_line;

                var words=(lines[line_no]==undefined?"":getWordsFromLine(lines[line_no],scrolled-segment_completion));

                if (words.length>0)
                {
                    document.getElementById("view").innerHTML=words;
                    document.getElementById("mouth").style.height=generaterandomno(10,30)+"px";
                    document.getElementById("mouth").style.width=generaterandomno(10,50)+"px";
                    document.getElementById("head").style.transform="rotate("+generaterandomno(-5,5)+"deg)";
                    document.getElementById("head").style.webkitTransform="rotate("+generaterandomno(-5,5)+"deg)";
                }
                else
                {
                    document.getElementById("mouth").style.height="0px";
                    document.getElementById("mouth").style.width="0px";   
                }
            }


Merry Christmas!

You can vary things by changing the lyrics. It should still work unless you substitute the lyrics with something long and rambling (like one of Roy Ngerng's speeches) going over 100 lines or so.

That's how I (sc)roll, baby.
T___T

Sunday, 18 December 2016

Five User Interface Wins

Last year, I wrote a listicle about five user interface fails. In the interest of balance, I'm going to bring you five user interface wins.

Groovy!

These are five little things that while not groundbreaking, do make life easier for the user above and beyond the call of duty. Things not just done right, but done excellently. This, incidentally, is in accordance to the second Great Virtue of a Developer - Impatience.

1. The Nationalistic List

You know those pesky drop-down lists of countries you have to use whenever you fill out a form that asks for your address? This drop-down does one better. It anticipates what country you are hailing from (based on guesswork, IP address or somesuch) and puts that country at the top of the list. How excellent is that?! Sure, it's a small touch... but in user experience, the small things do matter.
Country:


2. Preemptive Login screen

You're probably familiar with the standard login screen where you have to fill in your id and password. This can be a major pain in the ass if you're confronted with a "invalid login/password" message after typing in both fields.

This login screen does it better. First, you enter an id, and if the id doesn't match any id in the database, you simply don't proceed. Go on, try it. Enter any value. The "Next" button doesn't become clickable until you enter "teochewthunder". And then it asks you for the password. This saves you a bit of typing if you enter an incorrect id.

3. Overlaid Operation

Want to save screen space? Don't want to dedicate an entire page to what amounts to a simple operation? Use an overlay for, in this example, registration. The main advantage is that you don't get taken away from whatever you were doing. You're still on the same page. The other advantage is that in an age where screens are getting smaller, this saves you some valuable real estate.
x close

Registration

Name
Email
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.



4. Explanatory Rollover Buttons 

The button is obviously clickable and self-explanatory, but when you mouse over, there's more information. Sure, this probably won't work on a touch-screen information, but on a conventional interface, it adds value. The win here is that absence of the additional value will not take away from the usefulness of the original button. It's just the icing on top of an already very edible cake.

50% off
selected products!
BUY NOW

5. Searchable Lists 

Frameworks such as jQuery Mobile already have APIs for this cool little feature. Say you have a long-ass list of stuff and don't want to scroll through all of it. I don't blame you - who would? You type in whatever you're searching for, and the list gets truncated down to your search results! Pretty neat, eh?

The example below reuses the list of countries in the first example.


So much win.

There's so much more I could add to this list, but the sheer awesomeness might just cause your skull to implode. As technology improves, UI and UX have become increasingly sophisticated. These aren't even the most impressive things you'll find out there.

Sadly, simply because stuff like this is so commonplace, the ingenuity of these little things often goes unlauded. Well, no longer.


Cool button signoff!
T___T