TheDrunkenEpic - Drunken Ramblings of a Code Monkey
Filed under

Code Monkey

 

A Testament to my Laziness

One of the biggest problems I've always had with maintaining a blog is the maintaining part. I often find myself too busy, too indifferent, too burned out or, more often than not, too brain dead to care. With the advent of Twitter, things have gotten even worse. I no longer have to sit and think about how to make a worth-while blog post based on a single, tiny string of thought.

Thanks to Twitter, blogging, for the most part, is pretty much dead. Want to share something cool? Well, you no longer have to write a few paragraphs about it, just post the damn thing to Twitter or even Facebook. Thanks to software like TweetDeck, and other push notification services, I can not only post to multiple twitter accounts, I can even update my Facebook status; all with a single click.

Publishing minutea is now easier than ever and you don't have to spend hours making 5 paragraphs from a simple 140 character message.

So, it is because of this small problem I threw together another Posterous integration script. This is basically a cron script I run once a week from the main site which pulls all of my tweets from the previous 7 days, compiles them into a digest and publishes them to my default Posterous blog.

As you can see from my previous entry it's already working. I figure this is a great stop-gap measure which keeps content flowing to the site in between real blog posts.

There are times when I just don't have the time or energy to spend on a decent blog post. As you can see from my archives, good and worthwhile entries are few and far between. Hopefully, this won't always be the case, but at the moment small measures such as this will have to do.

If anyone is interested, I threw this script up on my Github account as a public repository. Feel free to fork it and create something better. It isn't the prettiest block of code I've written, but I prefer the KISS method for something like this.

Here's to Twitter and micro-blogging!

Loading mentions Retweet
Filed under  //   Code Monkey   Development   Free Goodies   php  

Comments [0]

MyTopix is still out there ...

Yeah, yeah, I know it's been a while, but I've been working on a super-secret project for the past few months. After which, I'll find the time to finish Great British Walks. Speaking of which, I should probably shoot myself in the face because it's been in development in some form or another for the past few years. Not sure what my problem is as I usually finish my contracted projects post haste. Honestly, Pete is the most patient guy in the universe... and I suck.

ANYWAYS... A lot of people have been asking about MyTopix lately and where they can download a copy. I'm assuming the memo didn't go out to everyone, so I'll just say it again. MyTopix is no longer supported by me in any shape or form. It is an open source project now and can be forked by anyone who wants to keep the project alive.

For those of you who are interested, you can ALWAYS find the LATEST build tucked away in its Google Code repository.

Seriously, it's right there. Check it out, create a fork and publish your own distro. If you people like it so much, go ahead and keep it alive and you'll definitely have my full backing.

Loading mentions Retweet
Filed under  //   Code Monkey   Development   Free Goodies   MyTopix   Rants and Raves  

Comments [0]

MySQL: Sorting records by order they were requested ...

Ok, probably not the best title for this article, but it's Monday, so you'll just have to make due. Hopefully, it will make sense by the end of this entry and you will have walked away with a neat trick to hide up your sleeve.

When working with insert language here and MySQL, have you ever had a collected list of record ids that needed the rest of their corresponding record data? Probably. If you've been doing insert language here and MySQL development for more than a few months, it's likely you've done something like the following:

PHP:
$ids = array(33, 22, 545, 234, 6, 343, 99);

$result = $this->db->query
("
    SELECT
        `id`,
        `name`,
        `email`,
        `password`
    FROM `members`
    WHERE `id` IN (" . implode(',', $ids) . ")
    ORDER BY `id` DESC
");

In this example, the above should return the corresponding data assigned to each id provided, if the record exists, that is. The results are sorted by id in descending order.

Well, that's great, but what if you want the database to return the data in the exact order you requested it? Not possible by any normal means outside of using insert language here to manually sort the returned data for you.

Lucky for us, the big swiging dicks over at MySQL have added an indispensable tool to the massive list of the database server's intrinsic functions. Let me introduce to you a little secret; the FIELD() function. Using the FIELD() function in place of the column name within the ORDER BY clause, you can force MySQL to return the data in the order you requested.

Using a modified version of the example above:

PHP:
$ids = array(33, 22, 545, 234, 6, 343, 99);

$result = $this->db->query
("
    SELECT
        `id`,
        `name`,
        `email`,
        `password`
    FROM `members`
    WHERE `id` IN (" . implode(',', $ids) . ")
    ORDER BY FIELD(id, " . implode(',', $ids) . ")
");

Et viola! All the requested records are returned in the same order as the ids within the $ids array. How neat is that? I wish I knew about this a few years ago.

Well, that's it for this article. Enjoy.

Loading mentions Retweet
Filed under  //   Code Monkey   Development  

Comments [0]

jQuery: Plugin qTips

Hey guys! I've been trying to be a bit more active lately and provide you all with some decent articles. So, because of this, I took some time off my busy schedule last night to sit down and teach myself how to create jQuery plugins. I was trying to figure out what I could develop that would be useful when I was reminded of how many times I tried to implement a javascript-based tooltip solution.

There are plenty of these plugins out there that are dedicated to display tooltips, but I wanted a dirt-simple implementation that didn't require me to mull about CSS code and compatibility issues.

So, I wrote a little plugin that addresses all these inconvenient issues; qTips.

Why 'qTips'? Well, you can quickly add tooltips. So, it's actually quick tips, but qTips sounds catchier.

A Demonstration

Actions speak louder than words, so before I go into this plugin's details, I thought I'd show you all a proof-of-concept demonstration. Just hover your mouse pointer over the boxes and you'll see what happens. A pretty little tooltip will fade in and out with your mouse movements.

For more people, this is all they need.

Implementation

First, you might want to download the plugin package. You'll notice that it comes with the same demo page that I previously linked to.

This plugin is implemented like any other. After you link to your jQuery library's location, you place the following immediately after:

<script src="/path/to/plugin/jquery.qtips.js" type="text/javascript"></script>

Since we need to style the basic implementation of the tooltip, we should add the following CSS to one of your stylesheets:

div.qtip-wrapper {
    z-index: 999;
    text-align: center;
    position: absolute;
    font-size: .9em;
    width: 250px;
    background: transparent url(arrow.png) no-repeat scroll center bottom;
    color: #fff;
    padding-bottom: 5px;
    display: none
}    

    div.qtip-wrapper div {
        background: #333 none;
        padding: 5px;
        font: normal normal .9em/1em "Arial", verdana, sans-serif;
    }

You can substitute the above background image with anything you want, so long as the position information is still intact.

Next, you just implement the plugin and assign it to a selection of some kind. Take the following markup located within the <body> element of a document, for instance:

<body>
    

Simple enough, but you'd like to include a tooltip that displays some image meta data when someone hovers their mouse over the image. To do this, you just add the following within your document:

<script type="text/javascript">

    $(document).ready(function()
    {
        $('img#product-image-5').qtip({content:'Here is some image info...'});
    });

</script>

This tooltip is now applied to every element within your document that matches the specified selector. Of course, while using jQuery, you can apply a tooltip to just about anything within your page with a single line of code.

Configuration

While this plugin may be a simple tooltip implementation that doesn't mean it lacks functionality. There are several configuration options that you can choose from to fine-tune your tooltips so they display exactly how you want them to. Here is a quick breakdown of the current configuration items and their default values:

container

default: 'qtip'

usage: $(selector).qtip({container:'qtip'});

This allows you to specify a default prefix for the ids assigned to the tooltip elements themselves. Since there may be multiple tooltips displayed at any given time, an incrementor is used and suffixed to the end of the container name to prevent naming conflicts.

content

default: blank

usage: $(selector).qtip({content:'Why, good DAY to you, sir!'});

This is the content you want to display within your tooltip. It can be a string, html markup or even a DOM object.

position

default: 'center'

usage: $(selector).qtip({position:'center'});

choices: left, right, center, bottom

This setting defines the position of the tooltip relative to the matched element.

nudge_top

nudge_top: 10

usage: $(selector).qtip({nudge_top:5});

How many pixels above the matched element you'd like the tooltip to be displayed.

nudge_left

nudge_left: 0

usage: $(selector).qtip({nudge_left:5});

How many pixels to the left of the matched element you'd like the tooltip to be displayed.

Callback Functions

qTips comes with 4 built-in callback functions that are triggered during various phases of the tooltip display. All functions pass the object of the currently matched element as well as the object of the current tooltip.

preRender(e, tip)

usage: $(selector).qtip({preRender:function(e, tip){}});

This is triggered immediately after your mouse enters the boundaries of the matched element, but before anything is actually processed for display.

postRender(e, tip)

usage: $(selector).qtip({postRender:function(e, tip){}});

This is triggered last in the tooltip process; immediately after the tooltip fades away.

onShow(e, tip)

usage: $(selector).qtip({onShow:function(e, tip){}});

This is triggered when the tooltip is pushed out for display.

onHide(e, tip)

usage: $(selector).qtip({onHide:function(e, tip){}});

This is triggered when the tooltip disappears.

Conclusion

This is my very FIRST jQuery plugin, so please, be gentle. I could always use some suggestions and bug reports. I'd like this to be useful for everyone and not just me, so if you'd like to see something that can easily be implemented or you find an instance where it's not working properly, just send me an email or post a comment here.

This has actually been quite a pleasant experience. You don't fully realize the potential of jQuery until you actually take the time to build something off of the framework. Good stuff all around!

I hope you enjoy using it just as much as I did writing it!

qTips for all images:

Thanks to Nick for his lovely comment below, I have decided to post a quick snippet on how you can add a qTip to every image on a page. Just use the following code:

$('img').qtip(
{
    wrapper: 'body',
    position: 'right',
    onShow: function(e, tip)
    {
        $('div', tip).empty().append('

Download

In case you missed it, here is the download link!

You can also find the official qTips project page here on jQuery's plugin repository.

Loading mentions Retweet
Filed under  //   Code Monkey   Development   Free Goodies   jQuery  

Comments [0]

jQuery: Mirroring Selections

Ran into pretty interesting situation today while working on a client's administration interface. It made me realize that I'm probably not the first person to run into this.

In one of their sections they have a list of records. At the very top of the list is a select box element that allows you to pick an action and apply it to any chosen records.

Since the list of records is pretty long and requires a lot of scrolling, my client asked if it would be possible to have the same select box appear at the bottom of the list as well. Simple enough, but they also asked if it was possible to have one select box mirror the current selection to the other box at the bottom of the page.

So, to implement this feature, I decided to use a bit of jQuery magic.

The elements in question are both named 'action', so what I did was simply bind a 'change' even using 'select[name=action]' as the selector. Once this event is invoked, it just copies the value of the current box to all other boxes on the screen with the same name.

Take the following code:

$(document).ready(function()
{
    $('select[name=action]').bind('change', function()
    {
        $('select[name=action]').val($(this).val());
    });
});

This isn't anything special, but just shows how jQuery can rise to the challenge of any problem.

Loading mentions Retweet
Filed under  //   Code Monkey   jQuery   Tutorials and Such  

Comments [0]

Domain Redirects Using PHP for SEO Optimization!

Hello, everyone! It's been a while since I wrote a nice PHP tutorial, so here I am... doing just that! Today's article will deal with something I'm pretty sure you've all seen while on the web. How many times have you visited your favorite website by manually typing in the domain name in the address bar? Yeah. Lots. Sometimes you add the 'www.' and sometimes you just jump straight into the meaty part and type 2girls1... err... and the browser does the rest for you.

Ever wonder how this happens and, more importantly, why you should take this into consideration for your websites? Well, it's done using 301 header and canonical redirects. Let's get to the details and discuss the whys and hows.

But... Why?

While 'thedrunkenepic.com' and 'www.thedrunkenepic.com' might take you to the same place, from an SEO standpoint they're very different. Search engines may take those two urls and interpret them as different sites which could screw up your search engine ranking in some cases. Also, if you're using a web metrics service like Google Analytics, your reports, especially custom ones, might be spread across what appears to be two different sites as well. While this may not be a HUGE deal, it does add another layer of complexity to tracking visitors and other trends on your site, which is a chore in and of itself.

How Do I address problem?

Simple. By doing a '301 Permanent Redirect' from 'thedrunkenepic.com' to 'www.thedrunkenepic.com'. By doing this a visitor who clicks on or enters your site's link with no sub domain will be taken straight to the 'www.' version. Your analytics software will understand the '301' server response and act accordingly AND search engines will also make note of this next time they spider links to your site.

Simple? Surely you jest, good sir!

This isn't a standard header redirect, the 301 server response tells browser and search engines that the page you're accessing has been permanently moved to the following location. As far as metrics software and spiders are concerned 'thedrunkenepic.com' and 'www.thedrunkenepic.com' are now the same.

TEACH ME HOW!!!1one

Well, as the administrator of your website there are a few ways to take care of this issue. A solution is to use an .htaccess file with special mod_rewrite directives to redirect all requests that do not point to 'www.thedrunkenepic.com' to 'www.thedrunkenepic.com'. But, we're not going to get into this solution today as I prefer a lighter approach, one that makes use of my coding language of choice and isn't anywhere near as intensive as mod_rewrite; PHP.

Unlike .htaccess, this wouldn't be a global solution that works across your entire site, it sort of depends on your platform that serves your content. For the sake of of this article, we'll just assume all content for your site is filtered through a single landing page in the form of 'index.php' located in your public root directory.

Example: http://www.thedrunkenepic.com/index.php

Since the DirectoryIndex directive on most Apache servers, by default, contains 'index.php', this is your site's default landing page. But, you already knew that, didn't you?

This is beginning to sound a bit too complex for me...

Alright, now we're getting to the good stuff. We have all requests for our site starting at 'index.php'. Now we can determine what and what not to redirect.

First, we get the client requested host name by using $_SERVER['HTTP_HOST'] and break it down to manageable bits:

<?php

$host_bits = explode('.', $_SERVER['HTTP_HOST']);

Next, the script attempts to determine the current HTTP_HOST's sub domain(s) and then rebuild the domain's root:

<?php

$host_bits = explode('.', $_SERVER['HTTP_HOST']);

if(sizeof($host_bits) > 1)
{
    $tld = array_pop($host_bits);
    $domain = array_pop($host_bits) . ".{$tld}";
}
else
{
    $domain = array_pop($host_bits);
}

By using array_pop() we are iterating through the pieces of the domain, one by one. By this point, the bits of the host name that we have left, if any, are the actual sub domains. Since your site may actual make use of valid sub domains, we're only going to redirect if $host_bits is empty. In other words, if nothing is left in $host_bits and we have our actual root $domain, it's pretty safe to assume that the current user is attempting to access the site without the 'www.'.

If this is the case, we do a server-friendly redirect using the appropriate headers and exiting our script.

<?php

$host_bits = explode('.', $_SERVER['HTTP_HOST']);

if(sizeof($host_bits) > 1)
{
    $tld = array_pop($host_bits);
    $domain = array_pop($host_bits) . ".{$tld}";
}
else
{
    $domain = array_pop($host_bits);
}

if(false == implode('.', $host_bits))
{
    header("HTTP/1.1 301 Moved Permanently");
    header("Location: http://www.{$domain}{$_SERVER['REQUEST_URI']}");

    exit();
}

Note, that when we're invoking the Location header, we're adding $_SERVER['REQUEST_URI'] to the end of the domain name. This allows the script to preserve any extras at the end of the original URL. This prevents stuff like sub directory or file requests from being lost.

In Conclusion

Well, this article is a little longer than I wanted it to be, but I hope I explained this common problem well enough for you to understand its implications. Not only that, you now know how to tackle and resolve this issue. Naturally, if you have any questions about the article, don't hesitate to ask using the comment form below.

The above code should work on any server. To make it more efficient, though, you might want to wrap it up in a function and use it where ever it's needed in your site and other scripts. Also, just because it's in PHP doesn't mean you can't port it over to ASP or other languages. The code is simple enough to break down and translate and I'll always be more than happy to help you out if needed.

Also, if there is an interest, I'd be more than happy to post the Apache mod_rewrite solution. Although it'd work globally throughout your site and it wouldn't have to rely on PHP, it is a bit more server intensive.

I hope you enjoyed reading this article as much as I enjoyed writing it.

Cheers!

Note: This article as been republished after being accidentally wiped from my hosting provider. Hurray for cached RSS feeds!

Loading mentions Retweet
Filed under  //   Code Monkey   Development  

Comments [0]

The cause of Z2k ...

No doubt by now some of you have heard of the Z2K bug that's been affecting all 1st generation Zune 30 models the day before the new year; mine being one of them. Apparently, and the Microsoft Zune guys confirm this, there was a bug in the driver that controls the real time clock on that specific model. The problem was with how the Zune's firmware handled resetting it's internal clock for the last day of a leap year.

Bloops!

If anyone has this model of the Zune, what they saw when they tried using it was a hanging boot screen with a full progress bar.

Word from Microsoft was that the counter would reset itself exactly 24 hours after the day our Zune's failed. The fix was, basically, to do nothing but wait a day without our Zunes. Well, that day has come and gone and I can gladly say that mine is back up and running like a champ.

I was curious as to what the exact problem was with the firmware and why it would go tits up while doing something as mundane as a simple date check. Well, I wasn't the only curious coder as someone managed to post the offending source file on the internets.

Mulling about the code snippet we can traverse the library's path of execution to figure out where it all went wrong. At some point during the boot process, the kernel calls the OEMGetRealTime() function to grab the current date. This function invokes a helper function declared as GetTime() which calculates the time and day from a provided timestamp.

Everything seems fine until it calls yet another helper function named ConvertDays() which calculates the current day number of the provided year. Taking a very close look at this function reveals the problem. Here is the offending bit of code at around line 259:

while (days > 365)
{
    if (IsLeapYear(year))
    {
        if (days > 366)
        {
            days -= 366;
            year += 1;
        }
    }
    else
    {
        days -= 365;
        year += 1;
    }
}

This loop was written to execute only on the last day of the year. If we iterate through the days of a year using code, chances are we're using some sort of incrementor. So, by the time we hit 366 days, we know we're pretty close to the end of, at least, a standard year. But, what about leap years? 2008 was a leap year because it's divisible by 4. So, this means that 2008 had 366 days. If this is the case, our incrementor will stop at 367.

We can see the check for the leap year in line 3 of the code snippet above. What happens next is what killed the Zune. The code accounts for a day count of anything greater than 366, which would include 367. But, the zinger here is we're not checking if the day count IS EQUAL TO 366. Since we aren't resetting the day count to 1 and breaking the loop, the poor Zune is stuck in an infinite loop which causes the boot screen to hang.

What should have happened is something like the following:

while (days > 365)
{
    if (IsLeapYear(year))
    {
        if (days >= 366)
        {
            days -= 366;
            year += 1;
        }
    }
    else
    {
        days -= 365;
        year += 1;
    }
}

If the day counter reaches 367, we now this is the first day after the new year following a leap year, January 1st, 2009. We can now exit the loop and continue booting.

Microsoft told us to wait 24 hours because then we wouldn't be in a leap year, bypassing the troublesome block of code completely. We shouldn't see this happen again for another 4 years!

Could this have been prevented? Well, of course it could have. Code review doesn't always catch all the problems because it's being reviewed by human eyes. We tend to miss things in the code, especially if we've been staring at 1,000's of lines of it all day. What could have prevented this is simple and thorough unit testing.

But, hey, I'm gonna give Microsoft a break. They've made a great product and after going through 5 5th generation iPods in ONE year, I decided it was time for a change. I picked up the white brick the week it was released and haven't had a single issue until 2 days ago. Not bad, guys, not bad at all.

Besides, how many times have we caused self-inflicted facepalm moments? 'Duh' moments like will happen to any software engineer.

One last thing before I go, you gotta hand it to the guys at Redmond, their code is quite pleasant to look at. I don't care what your coding standard is as long as you use it consistently and these guys got it juuuust the way I like it. Kudos 2 u!

Till next time!

Note: This article as been republished after being accidentally wiped from my hosting provider. Hurray for cached RSS feeds!

Also Note: This article has been partially updated to reflect a great suggestion from Nick Shepherd

Loading mentions Retweet
Filed under  //   Code Monkey   Development   General Nonsense   The Funny  

Comments [0]

And a new framework is born!

Today marks the day I made my first commit to the new Cogsworth repository on Google Code. That's right, you can now, finally, check out Cogsworth and toy with it. It's still in its early, early Alpha stages, but this allows you all to test it as I go as well as make all sorts of requests and suggestions.

This is the first time I've publicly released my code in a very long time, so please, while I completely accept constructive criticism, be gentle. My over-inflated ego can only handle so much abuse.

There is also a Google Group set up for every one.

Since this is only the initial commit, there is a TON of incomplete documentation. It's all on my todo list, but as soon as I get the chance I'll be putting in a shit-ton of time into documentation, tutorials and everything else you might need to get started.

Unfortunately, I don't have the time right now to make a more detailed announcement, but that's gonna have to wait until later on this weekend. Until then, here's Cogsworth's description:

Cogsworth is a lightening fast open source framework with all the tools you need to rapidly create exceptionally awesome web applications. It was written with the belief that you shouldn't have to start from scratch every time you create a new project. Cogsworth not only does all the grunt work for you, but provides a system with security, stability and an unprecedented amount of flexibility out of > the box.

Booyah! We just made PHP fun again. Now go check it out and get to making some killer stuff!

Let the games begin!

Loading mentions Retweet
Filed under  //   Code Monkey   Cogsworth   Development  

Comments [0]

Hey, this can be fun!

Well, obviously, I've written a few quick tutorials to do some common tasks in jQuery. Which is great, because jQuery is an awesome set of JavaScript decorators. But, the thing is that not everybody uses jQuery. Chances are, if you're not using one of the 'Top 2', you're using the other. In this case I'm refering to Prototype.

So, in order to cater to a wider crowd and please more people, I have decided that all jQuery tutorials will have a Prototype version as well. I can't tell you how many times I got pissed when working with Prototype, hit a brick wall and then only found jQuery solutions to my problem and vice versa.

Why not post tutorials for both libraries that address the same problem and solution?

This decree is retroactive! I'll be adding Prototype versions for my last 2 jQuery articles this week.

This'll be fun!

Loading mentions Retweet
Filed under  //   Code Monkey   Development   Rants and Raves  

Comments [0]

jQuery: Add another row to a table ...

Here's another quick trick I just learned. We were attempting to allow a user to add more records to an existing form within our updated CRM. This form was represented as a row of a table. Rather than using JavaScript to manually build a new row to display, I did a bit of digging and found the clone() function of jQuery.

Say, we have a table with id of table#image-uploads that basically contains a minature upload form field (with other options) for images. In the last column of this upload form there is an 'add another' link:

add another

Clicking on the link invokes the following JavaScript function:

function addTableRow(table)
{
    $(table).append($(table + ' tr:last').clone());

    return true;
}

First, we pass the identifier to function addTableRow(table). The identifier, in this case, would be #image-uploads. You could also use classnames, ie .table-foo.

We then, using #image-uploads tr:last, take the last row of this table and clone(), or copy, it.

Finally, we just take the contents of the copied table row and then append() the data back onto the table.

There, now they can click that link and add as many extra form fields as they need for their images!

Neat trick, eh? I <3 jQuery. Really, I do!

Loading mentions Retweet
Filed under  //   Code Monkey   Development   jQuery   Tutorials and Such  

Comments [0]