Thursday 9 June 2016

Web Tutorial: The Scrooge Expense Tracker Mobile App (Part 1/4)

Mobile apps are becoming a way of life. They have the potential to help in so many little ways. And the fact that these apps can be opened from that tiny mobile phone we have on us almost all the time, sure doesn't hurt. Come to think of it, it's a definite part of the appeal.

But did you know they're fairly easy to make? Well, if you know your way around HTML5, CSS and JavaScript and don't worry too much about appealing to the mass market, you can create one, right off the bat. That's what we're going to do today - make a useful little web app and port it over to your mobile phone. This is what's known as a hybrid Android app.

So...

I have this thing I like to do with my money (other than spend it), and that's keeping track of my expenses. To that end, I will create an app that not only allows me to key in my daily expenses, but also tabulate the month's expenses handily.

Does that sound simple? That's because it is.

For this project, we'll be using a framework known as jQuery Mobile. Do some reading at this link if you're interested to know more. jQuery Mobile can be linked to your app either locally or remotely, through a Content Delivery Network (CDN). We'll be linking to the file locally, because this app is meant to be used offline. So download your copy of jQuery Mobile here (https://jquerymobile.com/download/). Also, we'll be previewing the output in Google Chrome, because Chrome has this nifty feature that lets us preview what the product will look like on various tablets and phones. If your browser of choice allows you to do the same, hey, y'know, go crazy.

Create a project folder and then put two subfolders in it, named css and js.


In the js folder, that's where your jQuery files will go.


In the css folder, place your CSS file and the images subfolder. The images subfolder will contain all the tiny icons that come with the CSS.



Finally, create a HTML file in the main folder, and name it index.html.


Now, it's time to get serious.

Open your index.html file. It's blank (duh) but you're going to fill it in with some basic HTML5 structure first.

<!DOCTYPE html>
<html>
    <head>
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <link rel="stylesheet" href="css/jquery.mobile-1.4.5.min.css">
        <script src="js/jquery-2.1.4.min.js"></script>
        <script src="js/jquery.mobile-1.4.5.min.js"></script>
    </head>

    <body>
        <script>

        </script>
    </body>
</html>


Note that this is strictly in HTML5. That's the standard for mobile apps these days. Deviate at your own risk.

The viewport needs to be specified because this is going to be a mobile app and mobile screen sizes vary greatly. Below the meta tag specification, we have links to the stylesheets and jQuery files. The script tag needs to be at the bottom of the body tag after everything else. That's because jQuery needs the DOM to be built before it can execute stuff on it.

Now, we're going to build what is called a "single-page application". There are multiple pages in this application, but instead of creating multiple HTML files, we're going to embed them all into one HTML file (index.html) and let jQuery Mobile handle the transitions. Here, we add the first "page", in the form of a div. The data-role attribute has to be set to "page" (so jQuery Mobile can recognize it as a page and render it accordingly) and here we set the id as well. It'll be in use later on. The data-theme attribute is relatively unimportant. I set it to "b" to make this page black, with white text.

Check out the data-theme specification for jQuery Mobile. (http://demos.jquerymobile.com/1.1.2/docs/api/themes.html)
    <head>
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <link rel="stylesheet" href="css/jquery.mobile-1.4.5.min.css">
        <script src="js/jquery-2.1.4.min.js"></script>
        <script src="js/jquery.mobile-1.4.5.min.js"></script>
    </head>

    <body>
        <div data-role="page" id="selectdate" data-theme="b">

        </div>

        <script>

        </script>
    </body>


More stuff to add to the page - a header, body and footer. The header and footer have data-position attributes set to "fixed", which means they'll stay at the top and bottom of your screen irrespective of how long your page gets.
        <div data-role="page" id="selectdate" data-theme="b">
            <div data-role="header" data-position="fixed">

            </div>

            <div data-role="main" class="ui-content">

            </div>

            <div data-role="footer" data-position="fixed">

            </div>
        </div>


Now we're going to add some content to your header and footer. For the header, obviously this is cosmetic and you can do whatever you please. I call this app "Scrooge" for obvious reasons.
            <div data-role="header" data-position="fixed">
            THE SCROOGE DIRECTIVE<br />A project by T___T
            </div>


For the footer, we add some navigational buttons. Placing links in the footer will cause them to be rendered as buttons. The data-icon attribute determines the icon that jQuery Mobile will render for that button.

Check out the full listing of the icons!

The href attribute sends the user to the specified page when clicked (or tapped). You'll notice that they're coded like anchor tags, which in a sense, they are. Each "page" is a div within the index.html file, remember? This particular page has the id selectdate. The other two pages will be entries and settings respectively.
            <div data-role="footer" data-position="fixed">
                <a href="#selectdate" data-icon="info">Select Month</a>
                <a href="#entries" data-icon="grid">Entries</a>
                <a href="#settings" data-icon="gear">Settings</a>
            </div>


This is what you should have right now.


Let's add the rest of the pages. Even after you re-run your code, the only page visible should be the first one you created. That's because the first page in the document body is always the default initial page unless otherwise specified. But you should be able to navigate from page to page successfully!
        <div data-role="page" id="selectdate" data-theme="b">
            <div data-role="header" data-position="fixed">
            THE SCROOGE DIRECTIVE<br />A project by T___T
            </div>

            <div data-role="main" class="ui-content">

            </div>

            <div data-role="footer" data-position="fixed">
                <a href="#selectdate" data-icon="info">Select Month</a>
                <a href="#entries" data-icon="grid">Entries</a>
                <a href="#settings" data-icon="gear">Settings</a>
            </div>
        </div>

        <div data-role="page" id="entries" data-theme="b">
            <div data-role="header" data-position="fixed">
            ENTRIES
            </div>

            <div data-role="main" class="ui-content">

            </div>

            <div data-role="footer" data-position="fixed">
                <a href="#selectdate" data-icon="info">Select Month</a>
                <a href="#entries" data-icon="grid">Entries</a>
                <a href="#settings" data-icon="gear">Settings</a>
            </div>
        </div>

        <div data-role="page" id="settings" data-theme="b">
            <div data-role="header" data-position="fixed">
            SETTINGS
            </div>

            <div data-role="main" class="ui-content">

            </div>

            <div data-role="footer" data-position="fixed">
                <a href="#selectdate" data-icon="info">Select Month</a>
                <a href="#entries" data-icon="grid">Entries</a>
                <a href="#settings" data-icon="gear">Settings</a>
            </div>
        </div>


Local Storage

Now that the layout is out of the way, let's concentrate on the data storage and retrieval for this app. We'll be using HTML5's localStorage object. Add this within your script tag. glb_settings is a global variable in your app, because all most of the pages are going to be using it. It's an object meant to store user settings for the app. Then, using jQuery's ready() method, we start a procedure that will begin every time the app is started up.
        <script>
                var glb_settings;

                $(document).ready(function()
                {

                });
        </script>


If there is nothing named "scrooge_settings" in your localStorage, ie an attempt to retrieve it using the getItem() method is null, we create one in the localStorage. It's in JSON format and here we initialize an array of categories named "A", "B", "C" and "D", a budget value of 1000.00 and an interval of 5 days. This will become clearer as we progress; for now, these are the settings that a user should be able to change.
        <script>
                var glb_settings;

                $(document).ready(function()
                {
                    if (localStorage.getItem("scrooge_settings") == null)
                    {
                            localStorage.setItem("scrooge_settings","[{\"category\":\"A\",\"name\":\"A\"},{\"category\":\"B\",\"name\":\"B\"},{\"category\":\"C\",\"name\":\"C\"},{\"category\":\"D\",\"name\":\"D\"},{\"budget\":\"1000.00\"},{\"interval\":\"5\"}]");
                    }
                });
        </script>


After that, you will have an item in your localStorage called "scrooge_settings", so set the global object glb_settings to the parsed JSON value of the retrieved text string.
        <script>
                var glb_settings;

                $(document).ready(function()
                {
                    if (localStorage.getItem("scrooge_settings") == null)
                    {
                            localStorage.setItem("scrooge_settings","[{\"category\":\"A\",\"name\":\"A\"},{\"category\":\"B\",\"name\":\"B\"},{\"category\":\"C\",\"name\":\"C\"},{\"category\":\"D\",\"name\":\"D\"},{\"budget\":\"1000.00\"},{\"interval\":\"5\"}]");
                    }

                        glb_settings = JSON.parse(localStorage.getItem("scrooge_settings"));
                });
        </script>


We can test this using Google Chrome. Press Ctrl+Shift+i, then view items in Resources > Local Storage. You should see "scrooge_settings" because it was created when your app was run. $(document).ready() method, remember?


Delete it.


Now refresh your code. The "scrooge_settings" item should come back.

Next

Enough of setup - it's serious business from this point on.

No comments:

Post a Comment