Creating a Web App From Scratch

Embed Size (px)

Citation preview

  • 8/6/2019 Creating a Web App From Scratch

    1/92

    CREATING A WEB APP fromSCRATCH

    H o m e

    [ T y p e t h e c o m p a n y a d d r e s s ]

    [ T y p e t h e p h o n e n u m b e r ]

    [ T y p e t h e f a x n u m b e r ]

    [ P i c k t h e d a t e ]

    SkullipsoToday we begin Part 1 of an 8-Part series onbuilding a web application from absolute scratch toa complete product. I am going to kick things off byintroducing the idea, and then I will be handling thedesign, UI, and general front-end stuff. We aregoing to be going back and forth from here over tomy friend Jason Lengstorfs blog Ennui Design.

    Jason will be handling the back-end stuff likeapplication planning and database stuff. At the endof the week, well unleash the actual workingapplication for you. Here is the plan:

  • 8/6/2019 Creating a Web App From Scratch

    2/92

    ContentsIt s Easy, Right? ................................ ......................... ........................... ............................ .................... 4

    The Big Idea ......................................................................................................................................... 4

    Sketch It Out ............................... ......................... ................................ ............................ .................... 4

    Early UI Planning .............................. ......................... ............................. .............................. ................ 5

    The Screens ......................................................................................................................................... 6

    Features ........................................................................................................................................... 7

    Moving On ........................................................................................................................................... 7

    Part II ........................... ........................ ................................ ....................... ................................ ............. 7

    Where We're At ............................. ........................... ............................... ............................ ................ 7

    Okay, So We Know How It Looks, but How Does It Work? ................................................. ................... 7

    Data Storage Planning and Database Structure .............................. ........................... ......................... 7Creating the Database ......................................................................................................................... 7

    Table 1: User Information ............................................................................................................ 8

    Table 2: List Information .............................................................................................................. 8

    Table 3: List Items ........................................................................................................................ 8

    Data Handling Planning and Script Organization ...................................................... ...................... .... 9

    Planning our PHP Classes .......................... ............................... ...................... ................................ .... 10

    Moving On ......................................................................................................................................... 10

    Part III ............................... ......................... ................................ ...................... ................................ ...... 11

    Developing a Workflow ............................. ............................... ...................... ................................ .... 11

    Bringing It to Life Photoshop ......................... ................................ ...................... ............................... 12

    Moving on ......................................................................................................................................... 15

    Part IV ................................................................................................................................................... 15

    Web Root Organization ............................. ............................... ...................... ................................ .... 15

    Header ............................... ........................ ................................ ...................... ................................ .. 16

    Footer ................................................................................................................................................ 17Sidebar .............................................................................................................................................. 17

    Main Page .............................. ......................... ................................ ...................... ............................. 17

    Logged in (The List) .............................. ............................... ....................... ................................ ........ 18

    Logged out (Public list) .......................... .............................. ...................... ................................ ......... 19

    Logged out (Sales) ............................ ......................... .............................. ............................. .............. 19

  • 8/6/2019 Creating a Web App From Scratch

    3/92

    Account Page .............................. ......................... ................................ ...................... ........................ 19

    Other Form Pages ............................. .......................... ............................ ............................... ......... 21

    The CSS .......................................................................................................................................... 21

    Moving Along..................................................................................................................................... 23

    Part V .................................................................................................................................................... 23

    Where Are We? ................................................................................................................................. 23

    Connecting to the Database .......................... ................................ ...................... ............................... 24

    Building the Class .............................. ........................ ............................. ............................... ............. 26

    Connecting the Class to the Database ............................... ................................ ...................... ........... 26

    Creating an Account ............................. .......................... ........................... ................................ ......... 27

    Creating the Sign-Up Form ......................... .............................. ...................... ................................ .... 28

    Saving the User's Email Address ......................... ................................ ...................... .......................... 29Generating and Sending a Verification Email .......................... ................................ ........................... . 31

    Verifying the User's Account ......................... ................................ ...................... ............................... 33

    Verifying the User's Email and Verification Code .............................. ....................... ........................... 34

    Updating the User's Password and Verified Status ........................................... ...................... ............ 35

    Logging In .......................................................................................................................................... 37

    Building the Login Method ......................... .............................. ...................... ................................ .... 39

    Logging Out ....................................................................................................................................... 40

    Modifying Account Information ................................................... ...................... ................................ 40

    Building the Interactions File .............................................................................................................. 44

    Updating the Email Address .......................... ................................ ...................... ............................... 45

    Updating the Password ............................. ............................... ...................... ................................ .... 46

    Deleting the Account ..................................... ................................ ...................... .............................. 47

    Resetting an Account Password ................................... ................................ ...................... ................ 49

    Returning the Account to "Unverified" Status .................................. ....................... ........................... 50

    Building the Reset Pending Page ........................ ................................ ...................... .......................... 51Generating a "Reset Password" Email .......................................... ........................ .............................. 51

    Resetting the Password...................................................................................................................... 52

    Moving On... ...................................................................................................................................... 54

    Part VI ................................................................................................................................................... 54

    The Big Thing: Saving the List ........................ ................................ ...................... ............................... 54

  • 8/6/2019 Creating a Web App From Scratch

    4/92

    Interface JavaScript .............................. ............................... ....................... ................................ ........ 55

    First things first: calling the JavaScript files......................... ............................. .............................. ..... 55

    Cleaning up the Markup with JavaScript ............................ ................................ ...................... ........... 56

    Making the list drag / sortable ...................................... ................................ ........................... .......... 58

    Marking items as done ................................... ................................ ...................... .......................... 58

    Color Cycling ................................ ........................ ................................ ............................ .................. 60

    Deleting list items ............................ ......................... ............................. .............................. .............. 61

    Click-to-edit list items ............................................... .............................. ............................. .............. 62

    Appending new list items .......................... ............................... ...................... ................................ .... 63

    Moving On ......................................................................................................................................... 64

    Part VII .................................................................................................................................................. 64

    Where We're At ............................. ........................... ............................... ............................ .............. 64Defining the Class .............................................................................................................................. 65

    Displaying List Items .......................................................................................................................... 66

    Saving New List Items ........................................................................................................................ 73

    Reordering List Items ............................. ............................. ...................... ................................ ......... 76

    Changing Item Colors .............................. ............................ ....................... ............................... ......... 79

    Editing Item Text .............................. ......................... ............................. .............................. .............. 81

    Marking Items as "Done" .............................................. ................................ ........................... .......... 82

    Deleting Items ................................................................................................................................... 84

    Moving On ......................................................................................................................................... 87

    Part VIII ................................................................................................................................................. 87

    Object-Oriented Programming ........................... ................................ ...................... .......................... 87

    Security ............................................................................................................................................. 87

    Security on the Server Side ...................................... ................................ ...................... .................... 88

    PDO ................................................................................................................................................... 88

    Data Escaping .................................................................................................................................... 88Security in the JavaScript .................................... ................................ ...................... ......................... 88

    POST vs GET ........................... ........................ ................................ ....................... ............................. 90

    2.0 Features ................................ ......................... ................................ ............................ .................. 90

  • 8/6/2019 Creating a Web App From Scratch

    5/92

    Today we begin Part 1 of an 8-Part series on building a web application from absolutescratch to a complete product. I am going to kick things off by introducing the idea, andthen I will be handling the design, UI, and general front-end stuff. We are going to be goingback and forth from here over to my friend Jason Lengstorfs blogEnnui Design. Jason willbe handling the back-end stuff like application planning and database stuff. At the end of the week, well unleash the actual working application for you. Here is the plan:

    I t s Easy, Right?What were going to create is a list app. The idea being focused on simplicity andusefulness. Sign up for an account, and get started making a list in just a few seconds.Sounds easy right? Even the PHP dabblers out there probably could throw something likethis together fairly quickly, right? Well the fact is, no, its not that easy.

    First of all, it needs to work and it needs to work well. That means good back end code thatdoes what its supposed to do and well. That means a good UI that is intuitive, helpful, and

    pleasurable to use. It means keeping the app secure and users data private. None of thesethings is trivial.

    Through this whole 8-part series, we are going to create an app that hopefully does allthese things pretty well. We arent out to tell you this is the greatest app ever made, butrather, we are going to use this app as a walk-through journey of the app creating processand hopefully do as many smart things as we can along the way.

    The Big Id eaThis list app is going to be called C olored Lists . Lists (in real life), can be for anything: ato-do list, a grocery list, things to bring camping list As you finish things, you cross them

    off. Things on a list may be of different relative importance as well. This makes paper listspotentially messy and inefficient. With a list on a computer, we can make crossing off items just a click and we can make rearranging them a matter of drag and drop. For dealing withrelative importance, we can use colorization, which could also be used for things likegrouping. Computers, and the web, are a perfect place for lists.

    Sk etch I t Out No need to get fancy right away. Here is a very rudimentary sketch of what the app mightlook like:

  • 8/6/2019 Creating a Web App From Scratch

    6/92

    Looks like a list to me. Each list item is a long rectangle, because the big idea here is tocolorize each list item, so putting them inside a colored box makes sense. There are someinteractive elements to the left and right of each list item. Those are going to be foraccomplishing the basic things we intent people to be able to do with their colored list. Letstake a closer look.

    Early U I PlanningWe dont necessarily want to be talking about specific technologies at this point, but weshould be thinking about how the UI will operate, so we can make choices about technologythat can accommodate our UI desires.

    y Click-to-edity Drag and dropy Two-click deletey Automatic saving (after any action)

  • 8/6/2019 Creating a Web App From Scratch

    7/92

    All this stuff basically adds up to a whole bunch of AJAX. We dont want to load special

    screens to do relatively trivial tasks like deleting a list item. That stuff should happenseamlessly, smoothly and with proper feedback in response to mouse clicks without pagerefreshes. In a sense, we are creating a one-page app, where the majority of interactionwith this app happens on a single page. This is certainly by design, and not trying to adhereto any particular fad. Lists are easy and quick, thats why are useful. If this app iscomplicated, its usefulness is diminished and nobody will use it.

    The S creensJust doing some quick brainstorming of the idea so far, we can come up with quite anumber of screens, or states the application can be in.

    y Homepagey Logged out = Intro/Sales Pagey Logged in = Your list

    y Log in pagey Settings pagey Lost password pagey Account activation page

  • 8/6/2019 Creating a Web App From Scratch

    8/92

    y Emails

    Yep, even emails should be considered a part of the screens, as they are a vital part of theprocess and interaction with an app.

    F eatures

    People love features. Things that your app has that other apps dont have, or that yoursdoes better. This is just as much for marketing as it is for your actual product. All the fancyAJAX this app will have is certainly a feature, but that stuff these days is getting more andmore expected rather than a feature. The one feature that we will focus on with this app is

    public sharing. Each list will have a unique URL that can be publicly shared. A visitorvisiting this URL can see the list in its exact current state, but not interact with it as far asediting/adding/deleting.

    Moving OnNow that we have the idea in place of what we want to build, in the next part well dive intolooking at what this is going to take in terms of server-side technology.

    Part II

    Where We're At Up to this point, we've planned the way our app is going to look, as well as given ourselves a basic idea of how the app is going to function. The next step is to figure out what's going to happen behind the scenesto allow our app to work the way we've planned.

    Ok ay, S o We Know How I t Loo k s, but How Does I t Wor k ?In order to keep a list available after a user logs out of our app, we'll need to store list information in adatabase. And, of course, to access that database we're going to need some kind of server-side scriptinglanguage. For this app, we made the choice to go with a combination of MySQL and PHP to handle all our behind-the-scenes data handling and storage.

    Data S torage Planning an d Database S tructureOur first step is to decide how we want to organize list data. Since this app is fairly simple, we'll onlyneed three tables in our database. The first table will store user information, and the second will store listinformation. The third table will keep track of list items.

    Creating the DatabaseOf course, before we can create our tables, we'll need a database to work with. For anyone working along athome, we'll be operating under the assumption that you're building and testing locally (we recommendXAMPP).

    Navigate to http://localhost/phpmyadmin and open the SQL tab. You can use the GUI if you want, but we're going to use raw SQL commands for learning purposes. The database will benamed cl_db , which is all the information that is required to build the database. However, we want tomake sure that our users can use characters from any language in their lists, so it's also a good idea to

  • 8/6/2019 Creating a Web App From Scratch

    9/92

    specify the collation and character set of the database. We'll be using the UTF-8 character set with generalcollation, which supports multilingual characters and is case-insensitive.

    The command to create this database is:

    CREATE DATABASE `cl_db`DEFAULT CHARACTER SET utf8COLLATE utf8_general_ci;

    Execute this command from the SQL tab in phpMyAdmin and the new database will become available. Nowthat we've got a database, we're ready to build our tables.

    Table 1: User Information

    Using our list app doesn't require a high security clearance; all we need to know is that you've got an emailaddress and that it's real. To determine that an email address is real, we'll be sending new users aconfirmation link in an email, which they need to follow before using our app. This means we need to havea unique confirmation link and a place to store whether or not an account has been verified.

    Of course, we also need to store the user's email address, and in the interest of keeping redundant datastorage to a minimum, we'll assign each user a unique numeric identifier.

    The MySQL command to build this table will look like this:

    CREATE TABLE cl_db.users( UserID INT PRIMARY KEY AUTO_INCREMENT, Username VARCHAR(150) NOT NULL , Password VARCHAR(150), ver_code VARCHAR(150), verified TINYINT DEFAULT 0)

    Table 2: List Information

    List information is fairly straightforward. Each list will have a unique identifier, a unique URL, and theidentifier of the user that owns the list. This helps us limit the amount of redundant information that needsto be stored.

    To build this table, execute the following MySQL command in phpMyAdmin's SQL tab:

    CREATE TABLE cl_db.lists( ListID INT PRIMARY KEY AUTO_INCREMENT, UserID INT NOT NULL , ListURL VARCHAR(150))

    Table 3: List Items

    Finally, we need a table that will store our list items. Each list item needs a unique identifier, the ID of thelist it belongs to, and the information the user enters as his or her list item. Also, to support features we'llbe adding later on, we also need to keep a record of the item's position and color.Execu te this command inthe SQL tab of phpMyAdmin:

    CREATE TABLE cl_db.list_items(

    ListItemID INT PRIMARY KEY AUTO_INCREMENT,

  • 8/6/2019 Creating a Web App From Scratch

    10/92

    ListID INT NOT NULL ,ListText VARCHAR(150),ListItemDone INT NOT NULL ,ListItemPosition INT NOT NULL ,ListItemColor INT NOT NULL

    )

    N OTE: The L istItemDone field was omitted in the original post of this article. It was added hereafter being pointed out in the comments by FuSi0 N .

    The database with our three tablesNow we ha ve our databas e and th e th re e tabl es we 'll nee d to build our app. Ne xt , we ' ll pla n how we 're going to create and access our database information using PHP.

    Data Han d ling Planning an d S cript OrganizationB efore we start coding, it's always a good idea to take a moment and map out everything that needs to be

    done. That way, we can group tasks into logical arrangements.

    B ecause great code starts with great organization, we'll be using an object-oriented approach.

  • 8/6/2019 Creating a Web App From Scratch

    11/92

    Planning our PHP ClassesObject-oriented programming provides an easy way to keep related functions grouped together.Afterlearni ng object-oriented programming, it becomes an incredibly powerful tool that increasesportability, readability , and usability of scripts. Our app is pretty simple, so we'll only need two classes.The first class is going to handle user interactions, such as registering, updating information, and logging

    in and out. The second class will handle list interactions, such as adding, deleting, and moving list items.

    User Actions Class

    Our first class, which we'll name C olored L ists Users , needs to handle all the actions our app willperform that are user account-related. Again, this is a pretty simple application, so when we map outeverything that users can do with their account, we end up with pretty short list:

    y Create an accounty Verify the accounty Update the account email addressy

    Update the account passwordy Retrieve a forgotten passwordy Delete the account

    In addition to those methods, we'll also need some support methods, such as one that will send averification email. We'll define these methods as we build the app in later installments of this series.

    List Actions Class

    The list actions class, which we'll call C olored L istsItems , also has a pretty short list of methods.This class will handle everything else our app does, which is anything a user can do with his or her listitems. The list of available actions ends up looking like this:

    y Create a list itemy Update a list itemy Delete a list itemy Change a list item's positiony Change a list item's color

    Action Hand ling Scripts

    Finally, we'll nee d a couple action-han d ling scripts. These will d etermine what the user's d esire d action is,create an instance of the proper object, an d call the correct metho d . As we build our app, we'll go into

    more d etail on how these scripts will work.

    Moving OnIn our next installment of this series, we'll create the application workflow. Make sure you're subscribe d to CSS -Tricks so you d on't miss out!

  • 8/6/2019 Creating a Web App From Scratch

    12/92

    Part III

    Developing a Wor kf lowWe have a great start going on our list application at this point. The "big idea" is in place, we know how wewant the lists to be displayed and interacted with, and we have some back-end structure in place to deal

    with users and all the data that goes along with these lists.

    It was a good idea to start with the "meat" of the app, but there is a little bit more that goes into a fullapplication. B ecause we have users, that means we need a sign up form and a log in area for returningusers. B ecause users can be forgetful, we need a 'Lost Password' feature. B ecause users should be justas concerned about securi ty as we are, users need to be able to change their passwords, change their login, and delete their accounts. Our one-page app has just turned into a four or five page app, so we'regoing to need to think about some workflow.

    There will be two different states for the homepage: logged in and logged out. While logged out, peopleneed a way to sign in and to register, and this will be essentially the "sales" page too, explaining the app.Logged in, the homepage will be the user's list itself. Logged in users will also need to do some ancillarystuff related to their account, like change their email, change their password, and delete their account, aswell as a way to log out. These ancillary options are probably best served on an account page. So now weare looking at at least two new pages: Account Settings and Registration. Here is some flow:

    Basic app workflow

    It's not pretty folks, but that's what sketching is. It's fast and it's just to help you think and plan for thethings you need.

  • 8/6/2019 Creating a Web App From Scratch

    13/92

    Bringing I t to Li f e PhotoshopOur developer is already ahead of us, thinking about the data they need and how this app is going toactually work. So we'd better get started actually designing here.

    Homepage (Logged In)

    This is the meat of our application so let's start here. The list is obviously the most important thing, solet's keep the header small and keep the list front and center. List items are big colored blocks withbuttons for their associated actions nearby. B elow the list a box for entering new list items.

    The home pageas it appears when logged in

    Homepage (Logged Out)

    When logged out, the homepage is going to act more like a "sales" page. Not that we plan to charge for it,but just to explain and get people interested in using it. There isn't much to say about a list app, so we'llkeep it simple.

  • 8/6/2019 Creating a Web App From Scratch

    14/92

    When logged out, we'll encourage the visitor to sign up

    S mall BitsWe've bee n designing long enough to know we might as well ma ke th e little buttons into a separate f il e and kee p th e m together as a sprite (a sprite is multiple i mages co mb ined into one to save HTTPre quests, in ou r case, also th e rollover states ). So we'll do that an d throw together a f avicon while we're at it .

    All the list ite m ta bs Favicon

    Registration

  • 8/6/2019 Creating a Web App From Scratch

    15/92

    Our intention with registration is going to be extremely simple. We're going to ask for a user's email andthat's it. They will be sent an email with a link in it to complete registration. The link in that email will"activate" their account and they can choose the password at that time. So, our registration page can bepretty darn simple.

    The registration form

    As small as this is, this registration page sets the stage for other forms. We have a label/input pair herethat can be used for any input/pair in any of our site's forms.

    Acc ount

    We'll use the same form design as the registration page here. It's not cheating or being lazy, it's gooddesign through consistency!

    Account controls

    Buttons

  • 8/6/2019 Creating a Web App From Scratch

    16/92

    Notice the change in buttons. They are now big, orange and rounded. Much more button-like don't youthink? Again for consistency, let's make this the default for all buttons across the site.

    Site buttons, looking button-like

    Moving onThe developer now has plenty to go on to start fleshing out the user interactions for the site. And we haveplenty to go on to start getting the HTML and CSS for all this ready, and ultimately to AJAX this puppy upand get it working.

    Part IV Its time to get our hands dirty with some markup!

    We know we have a couple different pages to deal with here. The main page of course,which acts as both our list page and sales page depending on login status. But then we havesign in and sign up pages and account pages. So lets be smart and work modularity. Thatmeans well make files like header.php and close.php that we can include on multiplepages so we dont have to repeat common code (e.g. the DOCTYPE, analytics code, andubiquitous things like that.

    Web Root OrganizationThis is what we have for files at the root of our web directory so far. All the major viewshave their own PHP files. We have subdirectories for images and common files. and wehave a few loose files like CSS and the favicon.

  • 8/6/2019 Creating a Web App From Scratch

    17/92

    Our developer will surely be adding more files. Hes going to need PHP files for interactingwith the database and doing all the list interactions.

    Hea d er

    Colored Lists |

    Colored Lists

    Log outYour Account

  • 8/6/2019 Creating a Web App From Scratch

    18/92

    Sign up Log in

    Right away in the header weve run across a few things where we need to be smart andleave notes for the developer, but give him the things he needs. In the page title, weve lefta note to do something smart there. Different pages need differnet page titles, so clearlysomething dynamic needs to happen there. Then with our control buttons (e.g. Account /Logout) those buttons will be different depending on the logged in state of the user. So well

    just let the developer jump in there and make those things function correctly.

    So at this point we have the top of a page. We are leaving the body, html, and #page-wrapelements open, as beyond that is the main content of the page. Before we get into thatmain content, lets toss in the sidebar and footer areas so we have a complete skin.

    F ooterOur design doesnt call for much of a footer, so well just close up those open elements andadd a note to put analytics here.

    S id ebarOur design calls for a bit of a sidebar. Right now, all well use it for is a few notes on usingthe application. But its nice to have some open room for content, as its extremely likelythat room will be needed for additional things as the app grows.

    Reminders

    Your list automatically savesDouble-click list items to edit them

    Main PageNow that we have our modules complete, lets dig into a real page. The template forbuilding any page will be like this:

  • 8/6/2019 Creating a Web App From Scratch

    19/92

    This site just doesn't work, period, without JavaScript

    Logge d in (The List)Walk the dog

    Pick up dry cleaning

    Milk

    The list itself will just be a regular ol unordered list. Well use CSS class names for thecolors. But then we need a bunch of controls for the list items. Thats what all those divs areinside the list items. There are empty divs for dragging, changing color, deleting, andchecking off list items. We need these for the CSS so we can target them and style them.

    Were smart designers though, we know this markup is merely temporary. These lists willbe dynamically generated by the application. Just looking at all those empty control divs;we know that those are probably automatically generated by the JavaScript. Thats fine, weneed the HTML in there now to set the stage and have everyone on the same page.

    Why the spans inside the list items? Just being smart. Because the list items wrap morethan just the text, its likely well need some kind of hook to target just the text later on.

    Now we need to get an input on this page for adding new list items. Our developer will beall over this, but well put the basics in so we can style them.

  • 8/6/2019 Creating a Web App From Scratch

    20/92

    Then one of our applications features is having sharable public URLs for our lists. Lets putthat in here too.

    Public list URL: URL GOES HERE(Nobody but YOU will be able to edit this list)

    Ahhh, more work for the developer! But hes ready for it. This public URL business leads usinto another possible scenario. We need this main page to be capable of displaying a listwithout showing the input form or all the list controls. Basically you can just look at the listbut not interact with it. (Like if you wanted to send your mom your Christmas list!)

    Logge d out (Public list)Walk the dog

    Pick up dry cleaning

    Milk

    This will be exactly the same as the list above, only no control tabs, no form to add newitems, and no public URL area (hey, they are already here, what do they need the URL for).We know this this probably will just be a change in how the backend code outputs the list.But whatever, if we create this, everybody is on the same page.

    Logge d out ( S ales)We might do something fancy someday for this, but for now, our big idea is just a coolgraphic showing that this area is potentially where your new list will be and a big ol arrowshowing people where they can sign up.

    Account PageAs a quick reminder, we us this structure for all pages, including this one.

  • 8/6/2019 Creating a Web App From Scratch

    21/92

    Thats the beauty of working modularly, all common content is included so updates downthe line are much easier.

    The account page is going to have several forms on it: one for updating email, one forupdating password, and a button for users to delete their accounts. Again, our developerwill be all over these forms filling them up with hidden inputs that pass along data andadding in action URLs and methods and all that. Well leave that to him, but this gives usenough to style.

    Your Account

    Change Email Address

    Change Password

    New Password

    Repeat New Password

  • 8/6/2019 Creating a Web App From Scratch

    22/92

    Other F orm PagesNow that weve done the account page, we have pretty much covered all the bases for theother form style pages. Sign up, sign in, forgot your password, they are all just simplerversions of the account page. Since well have styled the basic label/input format, theheader format, and the button format, the developer can easily create these pages himself copying the basic format and CSS classes from the account page.

    The CSS

    Reset /*

    RESET*/* { margin: 0; padding: 0; }body { font: 14px/1.1 Helvetica, Sans-Serif; background: url(images/stripe.png) repeat-x; }.clear { clear: both; }img, a img { border: none; }input { outline: none; } Just getting things cleaned up.

    S tru c ture

    /*STRUCTURE

    */body { font: 14px/1.1 Helvetica, Sans-Serif; background: url(images/stripe.png) repeat-x; }#page-wrap { width: 960px; margin: 6px auto 50px; position: relative; }hr { height: 1px; background: #ccc; clear: both; margin: 20px 0; border: none; display: block; } Not too much complicated formatting for our little one-page app.

    Ty pograph y

    /*TYPOGRAPHY

    */

    a { text-decoration: none; color: #900; border-bottom: 1px dotted #900; outline: none; }h1 { font: bold 36px Helvetica, Sans-Serif; margin: 0 0 8px 0; }h2 { margin: 0 0 10px 0; }p { margin: 0 0 6px 0; }.button { background: url(/images/button-bg.png) repeat-x; -moz-border-radius: 5px; padding: 6px 12px; border: none;color: white; cursor: pointer; text-shadow: 0 1px 1px #666; -webkit-border-radius: 5px; -webkit-box-shadow: 0 1px 3px#999; -moz-box-shadow: 0 1px 3px #999; font: bold 16px Helvetica; }.button:hover { background-position: bottom left; }.red { background: red; color: white; font-size: 12px; padding: 3px; }

  • 8/6/2019 Creating a Web App From Scratch

    23/92

    This isnt really a content-based app, so we dont have a whole heck of a lot of textformatting. However we do have page headers, links, and buttons, so well set those uphere.

    Header

    /*HEADER

    */#header { height: 68px; position: relative; }#header h1 { position: absolute; top: 0; left: 0; z-index: 2; text-indent: -9999px; overflow: hidden; }#header h1 a { display: block; text-indent: -9999px; width: 200px; height: 38px; border: none; background:url(/images/logo.png) no-repeat; }#control { width: 500px; float: right; padding: 10px 237px 0 0; text-align: right; }

    Our little stripe header doesnt take much. Just a little CSS image replacement for the logoand placement of our control buttons.

    Lists/*

    LISTS*/#list { list-style: none; }#list li { position: relative; margin: 0 0 8px 0; padding: 0 0 0 70px; width: 607px; }#list li span { padding: 8px; -moz-border-radius: 5px; -webkit-border-radius: 5px; width: 589px; display: block; position:relative; }.colorBlue span { background: rgb(115, 184, 191); }.colorYellow span { background: rgb(255, 255, 255); }.colorRed span { background: rgb(187, 49, 47); color: white; }.colorGreen span { background: rgb(145, 191, 75); }.tab { background: url(images/minibuttons.png) no-repeat; height: 21px; top: 4px; }.draggertab { position: absolute; left: 0px; width: 31px; cursor: move; }.draggertab:hover { background-position: 0 -21px; }.colortab { position: absolute; left: 34px; width: 34px; background-position: -31px 0; cursor: pointer; }.colortab:hover { background-position: -31px -21px; }.deletetab { position: absolute; right: -35px; width: 15px; background-position: -82px 0; cursor: pointer; }.deletetab:hover { background-position: -82px -21px; }.donetab { position: absolute; right: -17px; width: 16px; background-position: -65px 0; cursor: pointer; }.donetab:hover { background-position: -65px -21px; }.crossout { position: absolute; top: 50%; left: 0; height: 1px; }

    #share-area { margin: 20px 0 0 69px; width: 600px; }

    A lot more stuff needed here. Here well set up how the lists look: the colors, the spacing,the rounded corners, etc. Well also position all the little helper controls and give them

    appropriate backgrounds. Notice only a single image is used, minibuttons.png. A single CSSSprite for mad efficiency!

    F orms

    /*FORM STUFF

    */label { background: #999; color: white; padding: 3px; }

  • 8/6/2019 Creating a Web App From Scratch

    24/92

    input[type="text"], input[type="password"] { width: 324px; border: 3px solid #999; font-size: 18px; padding: 7px;display: block; }#add-new input[type="text"] { width: 532px; float: left; margin: 0 10px 0 69px; }#add-new input[type="text"]:focus { border-color: #73B8BF; }#add-new input[type="submit"] { padding: 10px 12px; }

    ul#list li span input[style] { width: 90% !important; }

    Forms across our whole site will be the same, so we set that up here. The one exception isthe Add New area on our lists, which is basically the same as any other input exceptbigger and is floated to the left to accommodate the Add button. Since we plan to useclick-to-edit, the list items temporarily turn into text inputs when doing that, so well planfor that by shortening the length of them to accommodate for a Save button.

    M essaging

    /*MESSAGING

    */.message { padding: 10px; margin: 0 0 10px 0; width: 607px; }.good { background: #9ff5b6; }.bad { color: #ef0040; } We havent talked too much about error messaging, but we can assume that because this isa web app, there will be some of it (for example, you enter in a wrong password, yourpasswords dont match, you have successfully done something, etc). Well set up one classfor messages in general and then classes for good and bad versions.

    S idebar

    /*SIDEBAR

    */#ribbon { position: absolute; right: 0; width: 125px; padding: 60px 30px 0 47px; height: 756px; top: -6px; background:url(/images/ribbon-bg.png) no-repeat; }#ribbon ul { list-style: none; }#ribbon ul li { background: rgba(0,0,0,0.8); color: white; padding: 5px; margin: 0 0 5px 0; font-size: 12px; } Just some simple stuff for our list of reminders.

    Moving AlongOur developer now has plenty to work with to make this app functional. Once hes gotten agood start on that, well tackle AJAX and making all those list interactions happen almostlike a desktop app.

    Part V

    Where Are We?Now that we have a workflow put together and the HTML and CSS to make it look good, we canactually start building the classes that will run this puppy.

  • 8/6/2019 Creating a Web App From Scratch

    25/92

    We'll focus this installment of the series on the user's account interactions. These include:

    y Creating an Accounty Modifying Account Informationy Resetting a Lost Passwordy

    Deleting an Account

    Connecting to the DatabaseB efore our class will be able to do much of anything, we need to connect to our database. To do this, we'llneed to create a couple of small files.

    D efining S ite-Wide Constants

    Our site won't require many constants, but in the interest of keeping them easy to maintain, we'llcreate aseparate file to contain any information that is site-wide. This will be called constants.inc.php ,and it will reside in a new folder called inc this folder will contain our PHP classes as well.

    Creating a constants file is a good idea for pieces of information that will be used often and in differentscopes throughout a site. That way, if your database changes, you're able to change every databaseconnection simply by swapping out the information in one file.

    Inside constants.inc.php , we want to define our database credentials. Since we're starting outby developing locally, constants.inc.php will look like this:

    As we develop, we'll add more to this file.

    Creating a P D O Objec t

    Next, we want to create a connection so that our application can communicate with our database.This filewill reside in the common folder along with the header, footer, and sidebar files. This file will create adatabase connection using PDO (PHP Data Objects), as well as setting up a couple other site-widefeatures: error reporting and opening a session.

    The file will look like this when all's said and done:

  • 8/6/2019 Creating a Web App From Scratch

    26/92

    // Start a PHP sessionsession_start();

    // Include site constants

    include_once"inc/constants.inc.php";

    // Create a database objecttry {

    $dsn = "mysql:host=".DB_HOST.";dbname=".DB_NAME;$db = new PDO( $dsn, DB_USER, DB_PASS);

    } catch (PDOException $e) {echo 'Connection failed: ' . $e->getMessage();exit ;

    }?>

    B ecause we're in the development stage, we want to see any and every error that occurs on the site. B ysetting error_reporting() to E_A LL and changing the display_errors directiveto 1 using ini_set() , we ensure that even notices will be displayed, which will keep our code cleaner and more secure.

    Next, we use session_start() to start a PHP session. This will allow our users to stay loggedin when we build that functionality later.

    Finally, we include config.inc.php and create a PDO object using the constants defined withinit. Note the use of the try-catch statementthis gives us the ability to use Exceptions, which helpimprove error handling. In this case, if the database connection fails, we're simply going to output the error message.

    Wh y P D O?

    The reason we're using PDO for this project is because of its support for prepared statements,whichvirtually eliminates the risk of SQL injection. There are other options that allow prepared statements, suchas the MySQLi extension. However, PDO is not database-specific, so migrating the app to Oracle or PostgreSQL wouldn't require a full rewrite of our code.

    Also, having used both MySQLi and PDO in projects, it's just my personal preference to use PDO. Feel freeto use whatever method of connecting to the database you prefer, but keep in mind that all databaseinteractions in this exerci se are assuming the use of PDO, and as such will probably require somereworking to accommodate your changes.

    F raming Out a User Intera c tions Class

    As we discussed in Part 2 of this series, we'll be taking the object-oriented approach with this app.All of these actions will be contained within our C olored L ists Users class. We'll also need to createseveral files that will display information to the user and interact with the class, which we'll cover as weget to them.

  • 8/6/2019 Creating a Web App From Scratch

    27/92

    Buil d ing the ClassTo get started, we need to create the file class.users.inc.php to contain the PHP class, whichwe'll place in the inc folder.

    With the file created, let's build the skeleton of the class:

    Connecting the Class to the DatabaseB efore our class can do much of anything, it needs to have access to the database object we createdin base.php . Our database connection within the object will be stored in a private propertycalled $_db , and this property will be set by the class constructor, which will accept the instance of PDOcreated in base.php as an argument. If no instance of PDO is passed, one will be created by theconstructor.

    This ends up looking like this:

    class ColoredListsUsers{/**

    * The database object** @var object*/

    private $_db;

  • 8/6/2019 Creating a Web App From Scratch

    28/92

    /**

    * Checks for a database object and creates one if none is found** @param object $db

    * @return void*/ public function __construct( $db= NULL ){

    if (is_object( $db)){

    $ this->_db = $db;}else {

    $dsn = "mysql:host=".DB_HOST.";dbname=".DB_NAME;$ this->_db = new PDO( $dsn, DB_USER, DB_PASS);

    }}

    } Now we are able to create an instance of our C olored L ists Users object and use it tocommunicate with our database. Next, let's start building user interactions!

    Creating an Account First and foremost, a user needs to be able to create an account. This will give them access to the rest of the site's functionality.

    As it stands, when a user visits our app, they're greeted with our "sales" page, which encourages them to

    click the "Sign Up" button in the top right of their screen:

  • 8/6/2019 Creating a Web App From Scratch

    29/92

    The home screen of our app

    Cl ic kin g tha t "Sign Up " bu tt on di rec ts the user to /signup.php ou r f irs t or der of bus iness shou ldpr o ba bly be to bu ild tha t pa ge .

    Creating the S ign-Up F ormIn our app's root directory, create a file called signup.php and place the following code inside:

    Sign up

    Email:

  • 8/6/2019 Creating a Web App From Scratch

    30/92

    To start, we include our common/base.php an d common/header.php files. Also, notice thatwe're declaring a variable called $pageTitle just before we include the header. Remember in Part4 when we built the header file and left that comment in the title tag?

    Colored Lists | We're going to replace that with a snippet of PHP that reads:

    Colored Lists | That gives us the opportunity to post a different title for each page of our app.

    With the proper files included, we can then create our sign-up form. The form will submitto signup.php itselfso we need to place an if-else check to see if the form has beensubmitted. If so, we create a new C olored L ists Users object and callth e createAccount() method (which we'll write in the next section).

    Finally, we close the if-else statement and include the footer. Our sign-up page should look like this:

    The sign-up page.

    Notice the use of alternative syntax for the if-else statement. Normally, I don't like to use thisformat, but in the case of outputting HTML, I prefer the way it ends with endif; instead of a closingcurly brace ( } ), which helps with readability in the script.

    Saving the User's Email A

    ddressWith our sign-up form ready, we need to write the createAccount() method that will be called

    when a user submits the form. This method will be public. Let's go backto inc/class.users.inc.php and declare this method:

    class ColoredListsUsers{

    // Class properties and other methods omitted to save space

  • 8/6/2019 Creating a Web App From Scratch

    31/92

    /**

    * Checks and inserts a new account email into the database** @return string a message indicating the action status

    */ public function createAccount(){

    $u = trim($_POST['username']);$v = sha1(time());

    $sql = "SELECT COUNT(Username) AS theCountFROM usersWHERE Username=:email";

    if ( $stmt = $ this->_db->prepare( $sql)) {$stmt->bindParam(":email", $u, PDO::PARAM_STR);$stmt->execute();$ row = $stmt->fetch();if ( $row['theCount']!=0) {

    return " Error ". "

    Sorry, that email is already in use. ". "Please try again.

    ";

    }if (! $ this->sendVerificationEmail( $u, $v)) {

    return " Error ". "

    There was an error sending your". " verification email. Please ". "conta

    ct ". "us for support. We apologize for the ". "inconvenience.

    ";

    }$stmt->closeCursor();

    }

    $sql = "INSERT INTO users(Username, ver_code)VALUES(:email, :ver)";

    if ( $stmt = $ this->_db->prepare( $sql)) {$stmt->bindParam(":email", $u, PDO::PARAM_STR);

    $stmt->bindParam(":ver", $v, PDO::PARAM_STR);$stmt->execute();$stmt->closeCursor();

    $userID = $ this->_db->lastInsertId();$url = dechex( $userID);

    /*

  • 8/6/2019 Creating a Web App From Scratch

    32/92

    * If the UserID was successfully* retrieved, create a default list.*/

    $sql = "INSERT INTO lists (UserID, ListURL)VALUES ($userID, $url)";

    if(!

    $this->_db->query(

    $sql)) {

    return " Error ". "

    Your account was created, but ". "creating your first list failed.

    ";

    } else {return " Success! "

    . "

    Your account was successfully "

    . "created with the username $u."

    . " Check your email!";}

    } else {return " Error

    Couldn't insert the "

    . "user information into the database.

    ";}

    }}

    This method follows several steps to create an account: first, it retriev es the posted email address fromthe form (stored in the $_POST superglobal ) and generates a hard-to-guess verification code (the SHA1hash of the current timestamp); second, it makes sure the supplied email address isn't already inuse; third, it generates and sends a verification email to the user with instructions on how to verify their account (we'll define the method that does this in the next section); fourth, it stores the email address andverificati on code in the database; and finally, it creates a list for the user.

    Each of these steps is monitored, and if any of them should fail, a specific error message is generated.Upon success, a message is generated to let the user know they should expect an email.

    G enerating an d S en d ing a V eri f ication EmailWhen the user creates an account, we need to send them an email with a link that will confirm their account. This is a precautionar y measure that proves the user provided a real email address that they haveaccess to and prevents a ton of spam accounts from being created easily.

    To send the email, we'll be using the built-in mail() function.In inc/class.users.inc.php , create theprivate

    sendVerificationEmail()method by inserting the following code:

    class ColoredListsUsers{

    // Class properties and other methods omitted to save space

    /*** Sends an email to a user with a link to verify their new accou

  • 8/6/2019 Creating a Web App From Scratch

    33/92

    nt** @param string $email The user's email address* @param string $ver The random verification code for the use

    r

    * @return boolean TRUE on successful send and FALSE on failure*/

    private function sendVerificationEmail( $email, $ver){

    $e = sha1( $email); // For verification purposes$ to = trim( $email);

    $subject = "[Colored Lists] Please Verify Your Account";

    $headers =

  • 8/6/2019 Creating a Web App From Scratch

    34/92

    user's hashed email address along with their verification code in the URI. This will allow us to identify andverify the user when they follow the link.

    V eri f ying the User's Account After our user follows the verification link in the email, we need to check that their email and verification

    code are valid, and then allow them to choose a password. After they choose a password, we needto update the datab ase to reflect the user's new password, as well as setting the account's status toverified.

    First, let's create a new file called accountverify.php in the root level of our app. Inside, placethe following code:

    Choose a Password

    Choose a Password:

  • 8/6/2019 Creating a Web App From Scratch

    35/92

    Re-Type Password:

  • 8/6/2019 Creating a Web App From Scratch

    36/92

    $stmt->execute();$ row = $stmt->fetch();if ( isset ( $row['Username'])){

    // Logs the user in if verification is successful$_SESSION['Username'] =

    $row['Username'];

    $_SESSION['LoggedIn'] = 1;}else {

    return array (4, "Verification Error\n". "

    This account has already been verified. ". "Did you forget ". "your password?");

    }$stmt->closeCursor();

    // No error message is required if verification is successful

    return array (0, NULL );}else {

    return array (2, "Error\n

    Database error.

    ");

    }}

    }

    This method executes a query that loads the user name stored in the database with the verification code,hashed user name, and a verified status of 0 . If a user name is returned, login credentials are stored. This

    method returns an array with an error code in the first index, and a message in the second. The error code 0 means nothing went wrong.

    Up d ating the User's Passwor d an d V eri f ie d S tatusOnce the user has selected a password and submitted the form, the if-else statement will catch theverification code sent using the POST method and execute the updatePassword() method. Thismethod needs to set the account status to verified and save the user's hashed password in the database.Let's build this method in C olored L ists Users :

    class ColoredListsUsers{// Class properties and other methods omitted to save space

    /*** Changes the user's password** @return boolean TRUE on success and FALSE on failure

  • 8/6/2019 Creating a Web App From Scratch

    37/92

    */ public function updatePassword(){

    if ( isset ($_POST['p'])&& isset ($_POST['r'])

    && $_POST['p']==$_POST['r']){$sql = "UPDATE users

    SET Password=MD5(:pass), verified=1WHERE ver_code=:verLIMIT 1";

    try {

    $stmt = $ this->_db->prepare( $sql);$stmt-

    >bindParam(":pass", $_POST['p'], PDO::PARAM_STR);$stmt-

    >bindParam(":ver", $_POST['v'], PDO::PARAM_STR);$stmt->execute();$stmt->closeCursor();

    return TR UE;}catch (PDOException $e){

    return FA LSE;}

    }

    else {

    return FA LSE;}

    }}

    Finally, since verifying an account logs a user in, we need toupdate common/header.php torecognize that a user is logged in and display differentoptions. In Part 4, common/header.php featured a code snippet that looked like this:

    Log out Your Account

    Sign up &

    nbsp; Log in

    To make those comments into functional code, we need to modify this snippet with an if-else block:

  • 8/6/2019 Creating a Web App From Scratch

    38/92

    Log out Your Account

    Sign up &

    nbsp; Log in

    Notice that we store in the session both the user name ( $_SESSIO N['U sername '] ) and a flag thattells us if the user is logged in ( $_SESSIO N['L oggedIn '] ).

    Logging I nNext, let's build the login form and allow our user to log in. To start, let's create a new filenamed login.php at the root level of our app. Like our other publicly displayed files, this will includethe base and header files. Then it checks if a user is already logged in, if the login form was submitted, or if the user needs to log in.

    If logged in, the user is notified of this fact and asked if he or she wishes to log out.

    If the form has been submitted, a new C olored L ists Users object is created andth e account L ogin() method is called. If the login succeeds, the user is directed to the home page,where his or her list will appear; otherwise, the login form is displayed again with an error.

    If neither of the previous conditions exists, the login form is displayed.

    Finally, the sidebar ads and footer are included to round out the file.

    When the file is all put together, it should look like this:

    You are currently logged in.

    Log out

  • 8/6/2019 Creating a Web App From Scratch

    39/92

    echo "";exit ;

    else :?>

    Login FailedTry Again?

    Email

    Password

    Did you forget your password?

    Your list awaits...

    Email

    Password



    Did you forget your password?

  • 8/6/2019 Creating a Web App From Scratch

    40/92

    Notice the "Did you forget your password?" links we'll be building this functionality a little later on inthe article.

    Buil d ing the Login Metho d Now we need to build the account L ogin() method. This method will compare the supplied user name and the MD5 hash of the supplied password to verify that there is a matching pair in the database. If a match is found, the user's name and a login flag are stored in the session and the methodreturns TR UE. If no match is found, the method returns FA L SE .

    B uild this method in C olored L ists Users by inserting the following code:

    class ColoredListsUsers{

    // Class properties and other methods omitted to save space

    /*** Checks credentials and logs in the user** @return boolean TRUE on success and FALSE on failure*/

    public function accountLogin()

    {$sql = "SELECT Username

    FROM usersWHERE Username=:userAND Password=MD5(:pass)LIMIT 1";

    try {

    $stmt = $ this->_db->prepare( $sql);$stmt-

    >bindParam(':user', $_POST['username'], PDO::PARAM_STR);

    $stmt->bindParam(':pass', $_POST['password'], PDO::PARAM_STR);$stmt->execute();if ( $stmt->rowCount()==1){

    $_SESSION['Username'] = htmlentities($_POST['username'], ENT_QUOTES);

    $_SESSION['LoggedIn'] = 1;

  • 8/6/2019 Creating a Web App From Scratch

    41/92

    return TR UE;}else {

    return FA LSE;

    }}catch (PDOException $e){

    return FA LSE;}

    }}

    Logging Out Next, our user needs to be able to log out. This is as easy as destroying the login data stored in thesession and sending the user back to the login page.

    Create a new file named logout.php at the root level of the app and place the following code inside:

    Mo d if ying Account I n f ormationNext, we need to allow our users to modify their account information. In order to do that, we need toprovide an "Account" page that will give them options to change their user name or password, as well asthe option to delete their account.

    Create a file named account.php at the root level of the app. There's a lot going on here becausewe're essentially combining three app functions within one file.

    First, we include the base file and check that the user is logged in. If not, he or she gets sent out to themain page.

    If the user is logged in, we check if any actions have already been attempted and assemble thecorresponding success or failure messages if any are found.

    Then we load the user's ID and verification code using the method retrieveAccountInfo() an dbuild three forms: one to update the user name (which is an email address, remember), one to change theaccount password, and one to delete the account.

  • 8/6/2019 Creating a Web App From Scratch

    42/92

  • 8/6/2019 Creating a Web App From Scratch

    43/92

    value="changeemail" /> Change Email Address



  • 8/6/2019 Creating a Web App From Scratch

    44/92

    C reating the Method to Retrieve Account Info

    In order to have th e u s er 's l ogin na me an d verification code avai la bl e to our account o p tion for ms, w e need to bui ld a ne w method that wi ll load th i s infor mation fr o m th e data ba s e .In inc/class.users.inc.php , create a ne w method in C olored L ists Users ca ll ed retrieveAccountInfo() an d ad d th e fo l lo wing code :

    class ColoredListsUsers{

    // Class properties and other methods omitted to save space

    /*** Retrieves the ID and verification code for a user

    ** @return mixed an array of info or FALSE on failure*/

    public function retrieveAccountInfo(){

    $sql = "SELECT UserID, ver_codeFROM usersWHERE Username=:user";

    try {

    $stmt = $ this->_db->prepare( $sql);

    $stmt->bindParam(':user', $_SESSION['Username'], PDO::PARAM_STR);$stmt->execute();$ row = $stmt->fetch();$stmt->closeCursor();return array ( $row['UserID'], $row['ver_code']);

    }catch (PDOException $e)

  • 8/6/2019 Creating a Web App From Scratch

    45/92

    {return FA LSE;

    }}

    }

    Building the Intera c tions F ile

    In account.php , all three forms direct to a file called db-interaction/users.php whensubmitted. This file helps relieve some of the clutter in account.php by determining form actions,creating a C olored L ists Users object, and calling the appropriate methods to handle the action.

    This file will be placed in a new folder called db-interaction , and it will be named users.php .Place the following code in the new file:

  • 8/6/2019 Creating a Web App From Scratch

    46/92

    elseif ($_POST['action']=="resetpassword"){

    if ( $resp= $userObj->resetPassword()=== TR UE){

    header("Location: /resetpending.php");

    }else {

    echo $resp;}exit ;

    }else {

    header("Location: /");exit ;

    }

    ?>

    Up d ating the Email A dd ressWhen a user submits a request to change their email address, the method updateEmail() is called.This function simply executes a query that changes the email address associated with an account. Itreturns TR UE if the email is successfully changed, and FA L SE otherwise.

    class ColoredListsUsers{

    // Class properties and other methods omitted to save space

    /*** Changes a user's email address** @return boolean TRUE on success and FALSE on failure*/

    public function updateEmail(){

    $sql = "UPDATE usersSET Username=:email

    WHERE UserID=:userLIMIT 1";try {

    $stmt = $ this->_db->prepare( $sql);$stmt-

    >bindParam(':email', $_POST['username'], PDO::PARAM_STR);$stmt-

  • 8/6/2019 Creating a Web App From Scratch

    47/92

    >bindParam(':user', $_POST['userid'], PDO::PARAM_INT);$stmt->execute();$stmt->closeCursor();

    // Updates the session variable

    $_SESSION['Username'] = htmlentities($_POST['username'],ENT_QUOTES);

    return TR UE;}catch (PDOException $e){

    return FA LSE;}

    }}

    Up d ating the Passwor d Quite similarly to updateEmail() , updatePassword() is called if the user submits a requestto change their password. The only difference in the methods is that this one will compare the passwordand the password confirmation to make sure they match before saving.

    class ColoredListsUsers{

    // Class properties and other methods omitted to save space

    /**

    * Changes the user's password** @return boolean TRUE on success and FALSE on failure*/

    public function updatePassword(){

    if ( isset ($_POST['p'])&& isset ($_POST['r'])&& $_POST['p']==$_POST['r']){

    $sql = "UPDATE users

    SET Password=MD5(:pass), verified=1WHERE ver_code=:verLIMIT 1";

    try {

    $stmt = $ this->_db->prepare( $sql);$stmt-

    >bindParam(":pass", $_POST['p'], PDO::PARAM_STR);

  • 8/6/2019 Creating a Web App From Scratch

    48/92

    $stmt->bindParam(":ver", $_POST['v'], PDO::PARAM_STR);

    $stmt->execute();$stmt->closeCursor();

    return

    TR U

    E;

    }catch (PDOException $e){

    return FA LSE;}

    }else {

    return FA LSE;}

    }}

    Deleting the Account If the user wants to delete their account, we need to go through several steps. First, we need todouble-check that the user is logged in, because we certainly don't want any accidental account deletions. If theuser is logged in, we then delete their list items. If the list items are successfully deleted, we move onto delete the user's lists. Finally, if the lists are successfully deleted, we delete the user from thedatabase, destroy their session information, and send them to a page called gone.php , which we'll buildin a minute.

    The method, when it's all written, will look like this:

    class ColoredListsUsers{

    // Class properties and other methods omitted to save space

    /*** Deletes an account and all associated lists and items** @return void*/

    public function deleteAccount(){

    if ( isset ($_SESSION['LoggedIn']) && $_SESSION['LoggedIn']==1){

    // Delete list items$sql = "DELETE FROM list_items

    WHERE ListID=(SELECT ListIDFROM lists

  • 8/6/2019 Creating a Web App From Scratch

    49/92

    WHERE UserID=:userLIMIT 1

    )";try {

    $stmt =

    $this->_db->prepare(

    $sql);

    $stmt->bindParam(":user", $_POST['user-id'], PDO::PARAM_INT);

    $stmt->execute();$stmt->closeCursor();

    }catch (PDOException $e){

    die ( $e->getMessage());}

    // Delete the user's list(s)$sql = "DELETE FROM lists

    WHERE UserID=:user";try {

    $stmt = $ this->_db->prepare( $sql);$stmt->bindParam(":user", $_POST['user-

    id'], PDO::PARAM_INT);$stmt->execute();$stmt->closeCursor();

    }catch (PDOException $e)

    {die ( $e->getMessage());

    }

    // Delete the user$sql = "DELETE FROM users

    WHERE UserID=:userAND Username=:email";

    try {

    $stmt = $ this->_db->prepare( $sql);

    $stmt->bindParam(":user", $_POST['user-id'], PDO::PARAM_INT);$stmt-

    >bindParam(":email", $_SESSION['Username'], PDO::PARAM_STR);$stmt->execute();$stmt->closeCursor();

    }catch (PDOException $e)

  • 8/6/2019 Creating a Web App From Scratch

    50/92

    {die ( $e->getMessage());

    }

    // Destroy the user's session and send to a confirmation

    page unset ($_SESSION['LoggedIn'], $_SESSION['Username']);header("Location: /gone.php");exit ;

    }else {

    header("Location: /account.php?delete=failed");exit ;

    }}

    }

    Resetting an Account Passwor d At this point, we're almost done. The last thing we need to do is allow a user to reset a forgottenpassword. To do this, we need to create the file password.php at the root level of our app and placethe following code inside:

    Reset Your Password

    Enter the email address you signed up with and we'll sendyou a link to reset your password.

    Email

  • 8/6/2019 Creating a Web App From Scratch

    51/92

    When a user visits this page, they'll be able to enter their email address. Submitting the form willreturn theaccount to unverified and send the user an email with a link to reset their password.

    Returning the Account to "Unveri f ie d " S tatusWhen the form in password.php is submitted, the information is sent to db-

    interaction/users.php and the resetPassword() method is called before sending theuser to resetpending.php .

    Th e resetPassword() method sets the verified field of our user's database entry to 0 , then callsth e sendResetEmail() method.

    class ColoredListsUsers{

    // Class properties and other methods omitted to save space

    /*** Resets a user's status to unverified and sends them an email** @return mixed TRUE on success and a message on failure*/

    public function resetPassword(){

    $sql = "UPDATE usersSET verified=0WHERE Username=:userLIMIT 1";

    try

    {$stmt = $ this->_db->prepare( $sql);$stmt-

    >bindParam(":user", $_POST['username'], PDO::PARAM_STR);$stmt->execute();$stmt->closeCursor();

    }catch (PDOException $e){

    return $e->getMessage();}

    // Send the reset emailif (! $ this->sendResetEmail($_POST['username'], $v)){

    return "Sending the email failed!";}return TR UE;

  • 8/6/2019 Creating a Web App From Scratch

    52/92

    }}

    Buil d ing the Reset Pen d ing PageAfter the user's account is back in an unverified state and the email has been sent with their password

    reset link, we send them to resetpending.php to let them know what their next steps are. Createthis file at the root level of the app and insert the following:

    Password Reset Requested

    Check your email to finish the reset process.

    G enerating a "Reset Passwor d " EmailTh e sendResetEmail() method is very similar toth e sendVerificationEmail() method. The main difference here is that the link sent to theuser directs them to a page called resetpassword.php where they're able to choose a newpassword.

    class ColoredListsUsers

    {// Class properties and other methods omitted to save space

    /*** Sends a link to a user that lets them reset their password** @param string $email the user's email address* @param string $ver the user's verification code* @return boolean TRUE on success and FALSE on failure*/

    private function sendResetEmail( $email, $ver){$e = sha1( $email); // For verification purposes$ to = trim( $email);

    $subject = "[Colored Lists] Request to Reset Your Password";

    $headers =

  • 8/6/2019 Creating a Web App From Scratch

    53/92

    From: Colored Lists Content-Type: text/plain;MESSAGE;

    $msg =

  • 8/6/2019 Creating a Web App From Scratch

    54/92

    elseif ( isset ($_POST['v'])){

    include_once "inc/class.users.inc.php";$users = new ColoredListsUsers( $db);$status = $users->updatePassword() ? "changed" : "failed";

    header("Location: /account.php?password=$status");exit ;}else {

    header("Location: /login.php");exit ;

    }

    $pageTitle = "Reset Your Password";include_once "common/header.php";

    if ( isset ( $ret[0])):echo isset ( $ret[1]) ? $ret[1] : NULL ;

    if ( $ret[0]

    Reset Your Password

    Choose a New Password:


    Re-Type Password:

  • 8/6/2019 Creating a Web App From Scratch

    55/92

    include_once 'common/close.php';?>

    Moving On...This article covered a whole lot of ground, and I went over some of it pretty quickly. Please don't hesitate

    to ask for clarification in the comments!

    In the next part of this series, our front-end designer will use some dummy lists to create AJAXeffects.After he's finished with the dummy lists, we'll explore how to combine those AJAX effects with our back-end and build the list interactions class in part 7.

    Part VI

    Our developer has already done a massive amount of work turning this idea into a realapplication. Now lets make some more for him! The most important part of this app iscreating and managing your list. We decided from the get-go that this was going to be anAJAX-y app. We didnt chose AJAX because its a popular buzzword, we chose it because weknow its the best path toward making a responsive, easy to use, natural feeling applicationon the web.

    The Big Thing: S aving the List AJAX allows for us to send requests and get responses from the server without a pagerefresh. In our app, that functionality is going to be used primarily for saving. Lets thinkthrough each of those times something needs to be saved:

    y When a new list items is added, it should be saved to the list.y When a list item is deleted, it should be deleted from the list.y When an items color is changed, the new color should be saved.y When a list item is marked as done, that status should be saved.y When the list is reordered, the new order should be saved.y When the text of a list item is altered, the new text should be saved.

  • 8/6/2019 Creating a Web App From Scratch

    56/92

    Thats a lot of saving going on. Our developer has his work cut out for him, because each of those little events needs to have a PHP file that is ready to receive that request and dealwith it. Fortunately he has some cool object oriented stuff gong on already and can certainlyextend that to deal with this.

    I nter f ace Java S cript Alongside all that AJAX saving is all the stuff that makes the interface do what visually itssaying it will do. That little drag tab is saying it can drag list items up and down. We are

    saying after that happens we are going to save the list. But how does that actually work?Dont worry, well get to it. For now lets think through all the interface JavaScript thingsthat we need:

    y Click and drag the drag tab, list items can be dragged around and reordered.y Click the color tab, the list items color is toggled between some predefined choices.y Click the checkmark, the list item crosses out and and fades down.y Click the X, a confirmation slides out. Click again, list item is whisked away.y Double-click the list item, text turns into a text-input for editing.y Type in the large box below and click add, new list item is appended to bottom of the

    list.And again, were going to get to all that. Just a little more setup to do!

    F irst things f irst: calling the Java S cript f ilesThere is really only one page on our site, the main list page, that needs JavaScript at all. Sowell be dropping the script files right into the index.php file. Youll often see JavaScript filelinked in the header of sites. This isnt the time for a lengthy discussion about that, butsuffice it to say that that isnt required as its generally considered a performance

  • 8/6/2019 Creating a Web App From Scratch

    57/92

    enhancement to list them at the end of pages instead. Thats just what well do here. In ourindex.php file, after weve output the list, well call the JavaScript we need.

    < script type='text/javascript'src='http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js?ver=1.3.2'> < /script>< script type="text/javascript" src="js/jquery-ui-1.7.2.custom.min.js"> < /script>< script type="text/javascript" src="js/jquery.jeditable.mini.js"> < /script>< script type="text/javascript" src="js/lists.js"> < /script>< script type="text/javascript">initialize();< /script> 1. Load jQuery (from Google for better speed)2. Load a customized jQuery UI library (for the draggable stuff)3. Load the jEditable plugin (for click-to-edit)4. Load our custom script

    5. Call the initialization function (our own kickstarter, kind of like a DOM ready statement)

    Cleaning up the Mar k up with Java S cript In our custom lists.js file, well be creating a number of different functions. The very firstone is the one that gets called directly in the index.php file after the lists have been output:

    function initialize() {

    }; The first thing we are going to do there is clean up the markup a bit by inserting commonelements with JavaScript rather than have them directly in the markup. Remember what themarkup for the list looked like when we mocked it up?

    • < li class="colorRed">

    < span>Walk the dog < /span>< div class="draggertab tab"> < /div>< div class="colortab tab"> < /div>< div class="deletetab tab"> < /div>< div class="donetab tab"> < /div>< /li>

    < /ul> Much of that is redundant across all the list items. What we want is more like this:

    < ul id="list">< li class="colorRed">

    Walk the dog< /li>

8/6/2019 Creating a Web App From Scratch

58/92

< /ul> All the divs and the span has been removed. The class name on the list item is fine, becausePHP will be spitting that out for us when it reads the database and outputs the list.

How do we append all that extra HTML? Easy with jQuery. Target the list items and wrapeach of the the innards using the wrapInner() function and append the extra divs with theappend() function.

function initialize() {

// WRAP LIST TEXT IN A SPAN, AND APPLY FUNCTIONALITY TABS$("#list li").wrapInner(" < span>").append(" < div class='draggertab tab'> < /div> < div class='colortab tab'> < /div> < /div> < div

class='deletetab tab'> < /div> < div class='donetab tab'> < /div>");

}; Bind events to the new functionality tabs, the smart wayBinding an event to an HTML element is pretty easy in JavaScript. Its like this:$("li").click(function() {

// do something}); There is nothing wrong with that, but we are in a bit of a unique situation with our list apphere. When you bind events like that 1) it creates a unique event handler for every singlelist item on the page, each one taking up browser memory and 2) it only does it once, forthe current state of the DOM. Dont worry about all that too much, the point is bindingevents this way isnt ideal for us because we will be inserting new list items dynamically.

When a user inserts a new list item, that gets plugged into the DOM right then and there.That new list item will not be bound as the others are, meaning all those fancy little tabswont work right. Boo hoo. What can we do to solve that? Well we can create a new functionthat will be called when the page loads and when new list items are appended that does allthat event binding work. That will definitely do the trick, but jQuery is smarter than that.

jQuery provides a function called live() that eliminates this problem entirely.

$("li").live("click", function() {// do something

}); Binding events with the live() function is fantastic for us because 1) it only creates one

event handler which is far more efficient and 2) new items appended to the page areautomatically bound by the same handler. Killer.

So for our little functionality tabs, well be using them like this:

$(".donetab").live("click", function() {// do stuff

});

8/6/2019 Creating a Web App From Scratch

59/92

$(".colortab").live("click", function(){// do stuff

});

$(".deletetab").live("click", function(){// do stuff

}); The drag tab doesnt have click event, its actually going to use jQuery UIs draggablefunctionality to do its thing. Lets check that out.

Ma k ing the list d rag / sortableMega thanks to jQuery UI for making such a useful set of functions. The draggable moduleis exactly perfect for making a list like our sortable. We target the parent , tell it the

handle we wish to use (which part of the list item you can click and drag to move them).We also use a parameter forcePlaceholderSize for some visual feedback when the list itemsare dragged around (a white block space pops in to indicate where the list item would land if released)

$("#list").sortable({handle : ".draggertab",update : function(event, ui){

// Developer, this function fires after a list sort, commence list saving !

},forcePlaceholderSize: true});

Mar k ing items as d oneWhen the user clicks the little checkmark tab, we have already decided to do two things.Draw a line through the list item and then fade that whole list item out. But then there isthe consideration of what to do if the item is already marked as done and that tab is clicked.

8/6/2019 Creating a Web App From Scratch

60/92

Well, well uncross it out and fade it back up. So when the click happens, well make sure tocheck which state we are in first.

$(".donetab").live("click", function() {

if(! $(this).siblings('span').children('img.crossout').length) {$(this)

.parent().find("span").append(" < img src='/images/crossout.png' class='crossout' />").find(".crossout").animate({

width: "100%"}).end()

.animate({opacity: "0.5"

},"slow","swing",

function() {

// DEVELOPER, the user has marked this item as done, commence saving !

})}

else{

$(this).siblings('span')

.find('img.crossout').remove().end()

.animate({opacity : 1

},"slow","swing",

function() {

// DEVELOPER, the user has UNmarked this item as done, commence saving !

})

}});

8/6/2019 Creating a Web App From Scratch

61/92

Color CyclingWed better get on this whole colored part of Colored Lists eh? CSS will be applying theactual color, so what well be doing with JavaScript is just cycling the class names applied tothose list items on clicks.

$(".colortab").live("click", function(){

$(this).parent().nextColor();

$.ajax({

// DEVELOPER, the user has toggled the color on this list item, commence saving !

});}); That nextColor() function isnt a built-in function, it will be custom written by us. Itsabstracted away here for code clarity. The way that weve used it here (as a part of the

chain) is such that well need to make a little jQuery plugin out of it. No problem.

jQuery.fn.nextColor = function() {

var curColor = $(this).attr("class");

if (curColor == "colorBlue") {$(this).removeClass("colorBlue").addClass("colorYellow").attr("color","2");

} else if (curColor == "colorYellow") {$(this).removeClass("colorYellow").addClass("colorRed").attr("color","3");

} else if (curColor == "colorRed") {$(this).removeClass("colorRed").addClass("colorGreen").attr("color","4");

} else {$(this).removeClass("colorGreen").addClass("colorBlue").attr("color","1");

};

}; Basically this check what color the list item already is and moves it to the next color. Noticehow we are altering an attribute on the list items too. Color isnt a valid attribute in XHMTL(its fine in HTML5), but oh well. Its not in the markup so it doesnt really matter. Why arewe using this? Well, its because we are about 50% of they way in doing this really

8/6/2019 Creating a Web App From Scratch

62/92

intelligently. When our developer goes to save the color information about this list item tothe database, he needs something to save. Back in Part 2 of this series, we can see that ourdeveloper already anticipated this and created a field for color called listItemColor, which hemade an INT (integer). He figured that would be the smartest way to do it as itslightweight, easy, and abstract. We can decide later what they key is, e.g., 1 = Blue, 2 =

Red, etc. The data itself doesnt need to know its red. So, if we have an integerrepresenting the color right in the DOM for him, that makes it really easy to snag out andpass along to save to the database.

Why is this only 50% smart? Well, because we should probably extend that smartness tothe class names themselves. We are using colorYellow for example, when color-1 mightmake more sense, if down the line we decide to drop yellow from the lineup and replace it.Or even perhaps let users declare their own colors.

Deleting list itemsOur little X tab is in charge of allowing users to delete list items. We want to have a littleextra insurance against accidentally fat-fingerings though. So we are going to require twoclicks to actually delete something. Some applications resort to a nasty ARE YOU SURE modal popup dialog box, well be a little more sly than that. As you click the X, a little noticewill pop out to the right asking about sureness. If they click again then deleting maycommence.

$(".deletetab").live("click", function(){

var thiscache = $(this);

if (thiscache.data("readyToDelete") == "go for it") {$.ajax({

// DEVELOPER, the user wants to delete this list item, commence deleting !

success: function(r){thiscache

.parent().hide("explode", 400, function(){$(this).remove()});

// Make sure to reorder list items after a delete !

}

});}

else{

thiscache.animate({width: "44px",right: "-64px"

}, 200)

8/6/2019 Creating a Web App From Scratch

63/92

.data("readyToDelete", "go for it");}

}); Because we were smart earlier and our little tab graphic is all a part of one sprite graphic,all we need to do is expand the width of that tab to display the message. After the firstclick, we append a little bit of data (jQuery