Forms. As web developers, we work with them a lot. And you have to deal with validating them client-side and server-side. You can write custom javascript to do the client-side validation and then separate code for server-side validation. But what if the server finds and error that was not found client side, such as trying to register a user, but that username is already taken? So now you have to be able to not only validate on both sides, but display errors from both sources.
It's simple really, but I've finally decided that it's just easier to submit ALL forms via AJAX. The validation can all be done server-side because with an AJAX call it's pretty darn fast. In the end it's really much more simple. Plus, on most sites, you have some forms that submit "normally" and some that submit via ajax, so you have two general philosophies to support. Let's make life more simple. Just do it all via AJAX.
Add a comment
Here are two simple scripts that will allow you to use mysql and mysqldump without having to constantly open up wp-config.php to copy the DB connection information.
Here's a quickie Wordpress backup script that I wrote. It gets the job done and may be useful to others. It assumes that it is being run as root and that backups are stored at /root/backups. Enjoy!
#!/bin/bash
#####################################################################################
# backup-blog
# Author: Dustin McQuay
#
# Simple script to backup a wordpress blog, including it's database.
#
# Usage: backup-blog [name] [source_directory]
# Example: backup-blog myblog /var/www/html/myblog
#
# You probably want to set it up to run daily using cron:
# 0 0 * * * backup-blog myblog /var/www/html/myblog
#####################################################################################
#set up file names and such
backup_name=$1
backup_source=$2
backup_root=/root/backups
backup_target_filename=$backup_name-`date +%F`.tar.gz
days_to_keep_backups=14
#ouptut this config
echo "backup_name=$backup_name"
echo "backup_source=$backup_source"
echo "backup_root=$backup_root"
echo "backup_target_filename=$backup_target_filename"
echo "days_to_keep_backups=$days_to_keep_backups"
echo
#acquire mysql creds
db_name=`grep DB_NAME $backup_source/wp-config.php | awk -F\' '{print $4}'`
db_user=`grep DB_USER $backup_source/wp-config.php | awk -F\' '{print $4}'`
db_pass=`grep DB_PASSWORD $backup_source/wp-config.php | awk -F\' '{print $4}'`
db_host=`grep DB_HOST $backup_source/wp-config.php | awk -F\' '{print $4}'`
#backup the database
echo -n "Creating database dump file: "
echo "mysqldump -u $db_user -h $db_host --password=$db_pass $db_name > $backup_source/dbdump.sql"
mysqldump -u $db_user -h $db_host --password=$db_pass $db_name > $backup_source/dbdump.sql
if [[ "$?" != "0" ]]; then exit; fi
#tar up the files, including db dump
echo -n "Archiving files to backup target: "
echo "tar -cz -f $backup_root/$backup_target_filename -C" `dirname $backup_source` `basename $backup_source`
tar -cz -f $backup_root/$backup_target_filename -C `dirname $backup_source` `basename $backup_source`
if [[ "$?" != "0" ]]; then exit; fi
#delete dbdump from backup_source because it is probably web accessible
echo -n "Removing dbdump: "
echo "rm $backup_source/dbdump.sql"
rm $backup_source/dbdump.sql
if [[ "$?" != "0" ]]; then exit; fi
#clean up? (delete backups older than x days???)
echo -n "Removing old backups: "
echo "rm -f \`ls $backup_root/$backup_name* -1 | head -n -$days_to_keep_backups\`"
rm -f `ls $backup_root/$backup_name* -1 | head -n \-$days_to_keep_backups`
if [[ "$?" != "0" ]]; then exit; fi
echo
echo "Backup completed successfully at "`date`
Working with JavaScript in the browser has a few pain points.
Keeping your JavaScript in many files is nice for organization, but loading all of those files can cause poor performance.
You can concatenate and minify your JavaScript into one file, but then you have to integrate this step into your build process
If you're concatenating & minifying yourself, you've got to have a way to test that both forms behave the same. The most common problem I've seen here is when you add a new JS file and forget to add it to the minified version.
Most important of all, you have to manage dependencies yourself. Let's say your file myapp.js requires jQuery to work. It would be very nice if you could just say require('jQuery') at the top of myapp.js instead of having to "just know" which files to put in your HTML and in what order.
Gracie fixes these problems. Gracie is a web service that delivers your JavaScript content. And it does some spiffy stuff in the process.
You can request multiple files in one request
You can specify if the output should be minified
You can put "require" statements at the top of your JS files and they will be resolved for you
You can have multiple JavaScript source directories
You can run the bundled Gracie server, or you can use it as a library to inject your JavaScript directly into your HTML documents
I just created a new JavaScript library that tracks the visibility of a set of elements. When the visibility of the element changes, an event is fired that contains detailed information about the visibility of that element (if it is fully visible or just partially, if it is the first or last visible element, etc. There are a few interesting things you can do with this:
Highlight content as it is being viewed in a forum or similar.
Delay loading content into an element until it becomes visible.
Track which parts of the page are viewed and send that information off to a web analytics service.
I recently needed to create a login modal that would allow a user to login without reloading the page. In addition, the login modal needed to be displayed on a non-secure page, but the form needed to be submitted over a secure connection. Here is how I accomplished it.
Create a login form that can be accessed via a non-secure URL and is on the same domain and port as the pages where login is ultimately needed
The login form must submit to a secure URL
The status of the submit (success or error) should be saved by the server within the session scope
The secure URL where the form is submitted to should always return a 302 redirect back to a non-secure URL
This form should be embedded in non-secure pages where login is desired using an iFrame
Create a function in the parent frame's window object called "handleLogin()" or whatever else you want
The child frame (the iFrame) can communicate success or error to the parent frame by calling parent.handleLogin()
That's the rough idea anyway. Of course I polished the solution quite a bit, but I want to keep this example simple. The only important addition I'd like to mention is that instead of putting custom code in handleLogin, I chose to create a custom event (I used YUI 2 for this) called "login" which I fire within this function. This way you can react to this event in custom ways on each page of your site as needed.
Anyone else know of a better way to handle this situation? I would love to hear your ideas.
Today I added Disqus Comments to the website. I found the setup process to be very painless and I like the functionality. So, enjoy being able to post comments! I hope to see some good discussion.
On my last post I talked about a one day project I worked on at Backcountry.com to integrate our community with Facebook and Twitter. It turns out everyone was pretty stoked about the idea. The general thought was that it was crazy that we weren't already doing this. Enough interest was generated to kick start an out-of-cycle project to clean up the implementation a bit and launch it. As of this morning at 6 am, you can use this feature on Backcountry.com.
Here's how it works. On your profile page, you can authenticate with Facebook by clicking a button that says "Connect to Facebook". When you return from authenticating, you are presented with a dialog that allows you to choose what you want to post to Facebook. Your options are reviews, photos and videos. We'll probably add more in the near future. After doing this, any time you write a review or post a photo or video (depending on the options you selected), your content will show up on your Facebook profile.
You might notice that Twitter integration is missing even though it was included in the prototype. We decided to focus on Facebook only for the initial launch for two reasons: 1) Net::Twitter required us to upgrade Moose, which was a reasonable task for me to complete in my development environment, but to upgrade all of our production servers is a larger task, mostly because of regression testing. 2) Facebook will likely have a larger impact and we'd like to keep things very simple for the first launch.
As I said in my last post, Facebook was pretty slick to integrate with and I didn't even use some of their super convenient libs/APIs such as FBML. Basically there is a very simple RESTful-ish service called the Facebook graph that you do very simple GET/POST/etc requests to. You can learn everything you want about the API at http://developers.facebook.com/docs/api. One thing that I couldn't find was a way to verify that your access token is still valid. The access token is what you get back from the OAuth authentication process and you need it for any subsequent calls to the graph API. So, in order to check this, we attempt to retrieve the user's profile data. There are two problems with this. First, it would be nice to have a more lightweight no-op call since I don't actually need to fetch any data. Second and more important is that I can't check what permissions the current access token grants me. For example, we need access to post to a user's wall. In Facebook, the user can revoke individual permissions such as this without disabling the entire app. So, when I retrieve the user's profile data to check that the token is valid, I don't actually know for sure that the token will still allow me to post to the user's wall. The only way I know of to check that is to try to post something to their wall, which obviously isn't an option. I don't expect that either of these problems will actually occur very often so I'm not too stressed about it.
It is debatable if working on a project like this out of cycle is the best thing to do. Perhaps there were other more important things to work on instead. However, this project proved that Backcountry.com is still agile enough to whip out a project, including testing and deployment, in a few days. This is great for the company's overall success. It's also great for developer satisfaction since fast moving projects are much more fun than slow moving projects caught up in company politics. +1 for Backcountry.com.
This Friday was was hack day at Backcountry.com. During hack day, all the engineers and a few other groups of people are given the freedom to work on any crazy idea they can think of. The result is fantastic innovations engineered at super-speed.
On Backcountry.com, we collect content from our users in the form of product reviews, questions, answers and more. For my team's project, we wanted to allow users to automatically post this content to social networks such as Facebook and Twitter. There are two parts to the project. First, provide users an interface to grant us access their networks (typically via OAuth) and to configure which content they're willing to spam their friends with. Second, when they post the content (reviews, etc.), send it to the social networks per the user's preferences.
Thanks to Josh Braegger and Jon Morrey, we send events to a message queue when users submit content. This allowed us to write a separate daemon that monitors the queue and posts content to social networks asynchronously. If there is a problem posting to Twitter or Facebook is being slow, it won't cause the website to lag at all.
The interface for authenticating with Facebook and Twitter is built into Backcountry.com, which was written in Perl, so I used Net::Twitter. Use of OAuth in this library is considered beta, but we didn't have any problems with it. The non-beta alternative is simple authentication, but Twitter is killing that method this month, so that really wasn't an option. Net::Twitter required us to upgrade Moose which caused a number of problems, but after an hour or so of hacking, things were working.
Authentication for Facebook was more simple than with Twitter due to a slightly diffierent version of OAuth which uses SSL to manage some of the security, making the handshake more simple. I was able to make the SSL requests using LWP without any fancy coding. There isn't any client library to use with Facebook and yet it still required less code to use their API. Props to the Facebook architects.
The second part of the project was to write a daemon that listens to the message queue for content posting events and to post corresponding content to the author's configured social websites. This was done using Java. All of this portion was done by Andres Arias so I can't explain it as well. But Apache MQ was very clean to integrate with and the tokens needed for posting to Facebook and Twitter were embedded in the events. So the Java daemon didn't have to connect to our database for any additional information and was therefore very simple, lightweight and fast.
In the true spirit of Hack Day, the interface wasn't perfect, but to be honest I think it turned out pretty good. Check out this video to see the final product. Thanks to my fantastic project team who made this project so fun and successful: Ben Preston, Kim Sullivan, Andres Arias and Mike Stevens. With luck, we'll see this feature on our production website soon.
Setting up a deployment process for small projects isn't a huge challenge. You just copy the files out and you're done, right? Well, time and time again I have found that it's actually really nice to have a consistent deployment process even for small projects so that you don't have to think when you are deploying. You just hit "go" and you can trust that it will work. However, since I'm talking about small, simple projects, it's not worth the time to develop anything elaborate. We need something really simple.
I have been using git for this purpose and have loved it. If you don't know what git is, you can learn more at the git website. This advice would probably apply just as well to Mercurial. I wouldn't suggest it as much for use with Subversion or CVS though. Deploying your code using git is dead simple. All you have to do is clone your git repository on your production server. Then, choose a branch that you will keep stable. You might use the standard master branch or you might create one called production. Whichever you choose, keep this branch very stable. When you're working on a feature, all you have to do is merge the code into this branch, login to your production server and do a git pull. You might also need to restart apache or something like that of course.
This setup requires that you don't have anything in your repository that is specific to a deployment environment. You need to be able to configure things like database passwords in a config file that is not tracked by git. This is something you should do anyway, so don't complain.