Welcome

I'm Christian Cox, an Atlanta-based front-end web developer and occasional designer. Lately I'm focusing on web standards, mobile, and ActionScript development (if you can call that 'focus'). I get to work with PHP and some MySQL too, but not quite as often. Basically I am a problem solver.

I'm currently taking a break from web development freelance to focus on learning more mobile application development. Go go gadget iPhone!

Portfolio

Web Standards
MFY Monthly Newsletter & Gallery
MFY Facebook Welcome Page
EpiCity Facebook Welcome Page
EpiCity
Inside Izod
Tonalin CLA
Pro Football Hall of Fame
Montana Watch Company
Standard Press
Ventanas
Erica & Michael's Wedding
The Stacks
maybe.for.you.

Flash
Tronic Studio
FLASH Peril Map
FLASH Video Player
Capital Dateline Online
CDC Flu IQ Widget
Philips-Van Heusen Video Player
Philips-Van Heusen Map
Significant Federation Paparazzi Gallery
J&CO Creative
Firedog Jewelry Configurator

 

Sponsored Links

Basecamp

Web Hosting By ICDSoft.com

WebOS and WebSQL

Here’s a headache cure when dealing with WebOS (Palm Pre) and WebSQL:

GOOD
var db = window.openDatabase(“ext:my_db”,”0.1″,…)

BAD

var db = openDatabase(“my_db”,”0.1″,…)

Gotta reference window here, and if you want to store more than 1Mb of data, prepend “ext:” to the name of your database. It’s better than Tylenol.

BOTSEX

Villains Wallpaper

Starting a villains series, here’s round 1.

villains villains_1 villains

effoff wallpaper

Yay arts! Need to get back into creative endeavors.

Flash to HTML conversion

Montana Watch Company

Just launched Montana Watch Company’s site – built from the ground up by yours truly. This client needed a very customized yet easy-to-use CMS to drive their very customized front-end Flash site. I was glad to work with designing agency PrimaryTheory to provide both solutions earlier this year – a PHP/MySQL administration area driving a Flash site heavy on experience. Later this year, the site had to be converted into HTML for various reasons and I’m anxious to find out how we’ll improve sales and search engine rank with the new web-standards approach. Congrats to Montana Watch Company and PrimaryTheory, let’s sell some unique American timepieces!

An open letter to Comcast

Dear Comcast,
My name is Christian Cox and my phone number is 678-478-7531. It’s Saturday, August 21, 2010 at 12:45 PM Eastern time and I just got off the phone with one of your telemarketers. He was interested in promoting an upgrade to a package with High-Speed Internet and your Digital Starter Cable, a package I am actually interested in and on terms that sounded fairly reasonable! I can truly say that I was excited that I had answered a telemarketing call that may lead to something positive. Sadly, I will not be upgrading at this time because your customer service representative was so inept and so outright deceptive to me that I am disgusted, once again, with your company’s customer service. I try. I try again and again to give your company a chance to treat me with fairness and respect, but time and again you prove to me that you, as a company, cannot follow through on that basic service requirement.

I asked your customer service representative to tell me which HD channels were included in the package. He was unable to tell me. Instead of finding out for me, or telling me where to find the information on my own, he offered a money-back guarantee for the service if I was not satisfied. Trying to manipulate me into purchasing additional services that you will not define to me is insulting and rude. Furthermore, I was never able to pin him down on the actual final cost of everything after promotional rates expired. Rather than telling me actual numbers and final costs, he was more interested in telling me how much I would save (“Your internet cost will go down!”). I find that to be insulting and purposefully deceptive. When I asked him for a total number for all services after the promotional rate expires, he gave me a number that is lower than the price I am paying now for internet only. Wow, what a deal! When I pointed that out to him, he stated that the number he told me was only for part of the service, not the package. Again, PURPOSEFULLY DECEPTIVE. At this point I became frustrated and asked to speak to his supervisor, as I was confused about the terms of the promotion and I needed clarification that he could not provide to me. Rather than put me on hold and get a supervisor (apparently they were all busy), he continued arguing with me and denying that he had been deceptive. I chose to end the call after relating how disgusted I am with both him (the CSR) and your company as a whole.

Normally I would just let this slide but today I feel like sharing it with everyone I know, and anyone else who will listen. Thanks to your high-speed internet service and the beauty that is social networking, I am about to make that happen! I will continue to use your high-speed internet service because the product is actually quite good for my needs and I do not need to interact with your customer service on a regular basis to keep it turned on. On the other hand, I will not be expanding my utility use with your company at this time or in the near future because of your horrible customer service and the treatment I received today.

Sincerely,
Christian Cox

UPDATE
At 3:10 PM this same day I answered a call from a blocked number. It was the telemarketer – same man, same accent, same voice. He said “Fuck you,” then hung up. Classic.

Braves wallpaper

bravos wallpaper!Braves wallpaper (1920×1200, 1.8MB) fo tha kidzz!

 

bravos wallpaper!Braves wallpaper (960×800, 850Kb) android!

 

How to get rid of a ghost or demon

  1. Turn on some lights. Ghosts/demons are not comfortable unless it’s dark. Need nightvision or microphones to observe the curious phenomena? Consider saving your money and investing in a hot tub instead. Also, invite me over to enjoy said hot tub.
  2. Learn how to do something useful. Only motherfucking idiots see ghosts, so protect yourself by being smart or at least productive.
  3. Stop being a woman. I don’t know if it’s the periods, verginias or what, but ghosts are all about attaching to some women so buck up and kick that ghost in the damn face (or facial area if said entity happens to be of the faceless variety).
  4. Laugh out loud while watching “Paranormal Activity.” They bought a townhouse without inspecting the attic/crawlspace. Dumbasses (see #2). I know San Diego has good weather year round and all, but insulation is non-negotiable.
  5. Ignore it. Ghosts are needy motherfuckers, and if you refuse to acknowledge one’s existence, it will most likely just give up after a few door closings.
  6. Get a television that’s not ancient. Ghosts like to turn televisions to static channels, but modern televisions just show a blank or blue screen. Ghosts are totally frustrated because that’s a tried and true method for scaring fucking idiots (again, see #2).

Quicksand that doesn’t suck

I am using this awesome Quicksand plugin for jQuery that makes filtering and reordering a list both beautiful and simple. I love this thing – it’s snappy, looks great, and put some polish on a regular old unordered list. But I was having trouble getting it to work locally in IE. I have an unordered list of items that I want to sort by type. Some items are one type, some items fall into multiple type categories. I’m organizing those types by class name as seen here:


<ul class="filter-list">
<li class="stores">Lorem</li>
<li class="brands">Ipsum</li>
<li class="products">Dolor</li>
<li class="stores brands">Sit</li>
<li class="brands products">Amet</li>
<li class="stores brands products">Quandis</li>
</ul>

To filter the list, I was using links as my triggers instead of inputs. Each link had an href attribute that either triggered ALL items, or corresponded to a particular class of items in the list, as seen here:

WRONG


<p class="trigger"><a href="all">All</a> | <a href="brands">Brands</a> | <a href="stores">Stores</a> | <a href="online">Online</a></p>

So I was stripping out the href attribute and using that to filter the list. But hold up a minute. In IE 7 when I test locally, that href translates to finding a class of “/user/Christian/Documents/Clients/blahblahblah/classname” or something ridiculous like that – IE appends the entire path when it passes that information to my jQuery script. So I ended up stripping out the href and using another attribute – rel – to drive the filters. Here’s the updated HTML:


<p class="trigger"><a href="#" rel="all">All</a> | <a href="#" rel="brands">Brands</a> | <a href="#" rel="stores">Stores</a> | <a href="#" rel="online">Online</a></p>

Here’s the final jQuery:


// get the initial (full) list
var $filterList = $('ul.filter-list');
// add unique id's
// i don't like having to write these all in the code
// so i wrote a script to id these for me
for(var i=0; i<$('ul.filter-list li').length; i++){
$('ul.filter-list li:eq(' + i + ')').attr('id','flitem' + i);
}
// clone first collection to get a second collection
var $data = $filterList.clone();
// handle trigger clicks
$('p.trigger a').click(function(e) {
if($(this).attr('rel') == 'all') {
// get a group of all items
var $filteredData = $data.find('li');
} else {
// get a group of items of a particular class
var $filteredData = $data.find('li.' + $(this).attr('rel'));
}
// call quicksand
$('ul.filter-list').quicksand($filteredData, {
duration: 500,
attribute: function(v) {
// this is the unique id attribute we created above
return $(v).attr('id');
}
});
e.preventDefault();
});

So if you're having trouble getting Quicksand to work in IE, and you're using a link's href attribute as a trigger, consider moving that trigger to the rel attribute or a class name instead. Hope this helps!

Subscribe list users to a MailChimp mailing list using Flash

 

UPDATES:
1. On March 16 2011, it was brought to my attention that MailChimp had removed the publicly accessible crossdomain.xml file from their server. As of March 18 2011, this file has been reinstated. There may have been some downtime related to this problem, but that should now be resolved.

2. The MailChimp API has been updated! Several people have noticed that they are receiving an error that says something like “You are accessing the wrong datacenter.” If you are getting this error, you will need to change this:

var send_url:String = "http://api.mailchimp.com/1.1/?output=xml";

to this:

var send_url:String = "http://[YOUR DATA CENTER].api.mailchimp.com/1.2/?output=xml";

…obviously you’ll need to change [YOUR DATA CENTER] to your data center. Your data center key can be found at the end of your API Key, the last 3 characters. For instance if your api key ends in -us2, then your data center is us2 and your send_url would look like this:

var send_url:String = "http://us2.api.mailchimp.com/1.2/?output=xml";

If your api key ends in -us1, then your data center is us1 and your send_url would look like this:

var send_url:String = "http://us1.api.mailchimp.com/1.2/?output=xml";

Also, an updated MailChimp AS 3.0 sample is now available from kohactive!

Original post follows.

 

Here’s some sample code you can use to connect your Flash signup form to the MailChimp API. I recently had a client with an existing MailChimp account ask to allow users to sign up for their newsletter through their website, which has a full Flash interface. Unfortunately I was not able to find much documentation out there about how to make this work, and it took me some hair pulling to get it sorted out. Finally, with the help of Jesse Peterson and the API team at MailChimp, we were able to get a working version that doesn’t require any additional PHP or other backend scripting. Here’s the AS:


// Edit your MailChimp specifics here.
// You shouldn't have to edit anything but these two variables
// unless you are collecting additional data.
_global.apiKey = "YOUR_MAILCHIMP_API_KEY";
_global.listID = "YOUR_MAILCHIMP_LIST_ID";

// set tab order for form usability
firstName_txt.tabIndex = 1;
lastName_txt.tabIndex = 2;
email_txt.tabIndex = 3;
submit_mc.tabIndex = 4;

// submission
submit_mc.onRelease = function()
{
   // show a loading message in case transmission is slow
   response_txt.text = "Sending…";

   // gather form data
   var firstName:String = firstName_txt.text;
   var lastName:String = lastName_txt.text;
   var email:String = email_txt.text;

   // check the email address
   // if it's valid…
   if(validEmail(email)){

      // disable the submit button while loading data
      submit_mc.enabled = false;

      // set up result xml
      var result_xml:XML = new XML();
      result_xml.ignoreWhite = true;
      result_xml.onLoad = function(success){

         // if the user is subscribed successfully, the result set
         // will look something like
         // <MCAPI type="boolean">1</MCAPI>
         // so you can reset the form and display
         // the confirmation message.
         if(result_xml.firstChild.firstChild.toString() == "1"){
            resetForm("Please check your email to confirm your subscription.");
         }

         // or else there was a data error,
         // so you need to parse the error code.
         else{

            // Convert the error string from XML data to a string,
            // then display it in the response text field.
            var resultCode = result_xml.firstChild.childNodes[0].childNodes[0].toString();
            _root.resetForm(resultCode);
         }
      }

      // Set up a send XML object, even though we're not
      // really sending anything in XML.
      // All your data will be encoded in the send_url variable.
      var send_xml:XML = new XML();
      send_xml.ignoreWhite = true;
      // Here's where your data is added.
      // For additional text fields, add additional merge_vars
      // array elements and append at the end.
      var send_url:String = "http://api.mailchimp.com/1.1/?output=xml";
      send_url += "&method=listSubscribe&apikey=" + apiKey;
      send_url += "&id=" + listID + "&email_address=" + email;
      send_url += "&merge_vars[FNAME]=" + firstName;
      send_url += "&merge_vars[LNAME]=" + lastName;
      // And here's how you send/load:
      send_xml.sendAndLoad(send_url, result_xml);

   }
   // or else there's an issue with the email address
   else{
      // show the email error.
      showErrors();
   }
}

// validate an email address
function validEmail(inputEmail:String):Boolean
{
   if (inputEmail.indexOf(" ")>0) {
   return false;
}
var emailArray:Array=inputEmail.split("@");
if (emailArray.length != 2 || emailArray[0].length == 0 || emailArray[1].length ==0) {
   return false;
}
var postArray:Array=emailArray[1].split(".");
if (postArray.length < 2) {
   return false;
}
for (var i:Number=0; i<postArray.length; i++){

   if (postArray[i].length < 1) {
      return false;
   }
}
var suffix=postArray[postArray.length-1];
if (suffix.length < 2 || suffix.length > 3) {
   return false;
}
   return true;
}

// delete all form elements and display a response message
function resetForm(pResponse){
   submit_mc.enabled = true;
   firstName_txt.text = "";
   lastName_txt.text = "";
   email_txt.text = "";
   response_txt.text = pResponse;
   Selection.setFocus("firstName_txt");
}

// select the email address and display an error message
function showErrors(){
   Selection.setFocus("email_txt");
   Selection.setSelection(0, email_txt.length);
   response_txt.text = "Invalid email address.";
   submit_mc.enabled = true;
}

Want to try it out? All you need to do to get it working is set up your MailChimp account and lists, then edit these variables:


_global.apiKey = "YOUR_MAILCHIMP_API_KEY";
_global.listID = "YOUR_MAILCHIMP_LIST_ID";

Then push your files online or test your SWF directly in the Flash Player (testing in a browser from your desktop may throw a Flash security error). You should be subscribing users in no time. Thanks again to the API team for working with me on this!