Made of Everything You're Not

Writing code... well, forever really. Sigh...
  • Home
  • Projects
  • Portfolio
  • Resume

Author Archive

The Commodity HTPC Dream is Finally Realized

Posted in Brain Dump on March 8th, 2011 by Eric Lamb – Be the first to comment

Ever since I first heard about home theater PCs (HTPC), way back in 2002, I’ve wanted one. Badly. To me, an HTPC is one of those killer products that offered what I would consider to be a perfect experience; the ability to have all my media centralized around a single interface and made for a more traditional entertainment experience. The problem though was that, until recently, setting up a system was a little outside my comfort zone when it came to the costs. It was fucking expensive to set up back then. But, that was then and the times they do a change. It’s not only ridiculously easy to build an HTPC but also quite reasonable in terms of the costs.

The HTPC Dream is Finally Realized

The HTPC Dream is Finally Realized

Back in 2002 I was a lowly intern level scrub with the pay to match and computers capable of running Windows Media Center were a little expensive and required a shit ton of upgrades hardware wise. You couldn’t just buy an inexpensive model off the show room floor and expect to have any cash left over. I don’t recall the specific prices involved for all the components but I do remember knowing with a complete and total certainty that getting an HTPC at that time just wasn’t going to happen. So, broken hearted, I moved on and focused on my career and drinking for the next 9 years.

Then, last August, I started looking into getting one put together again. I had some other, business, needs that required a dedicated desktop computer, to be placed in a closet, and I just figured, what the hell, why not kill two birds with one stone; have my utility computer and look into getting a Windows Media all at the same time. I mean, why not? The main purpose was for a backup machine which would only be ran on a slim time window and the rest of the time it’ll just be sitting there. Kind of a waste to just leave it sitting there doing nothing most of the day, right? Right?

Now, since I had done all the research into what it would take to build an HTPC back in the day I started looking up all the parts to build one. For my preferred system I was thinking about:

  1. ATX Media Center case $75
  2. An ATX Mother Board that can have a decent amount of RAM $299
  3. A decent amount of RAM $149
  4. A processor to match the motherboard $269
  5. HDMI Video Card $99
  6. 1 Blu Ray Disk Drive $90
  7. 500 Gig HDD (with a few extra external terabyte drives for the media) $60

I figured I’d get the parts and put it together myself; these things are like legos with how everything snaps together only where it belongs. Add a little MythTV (go FOSS) and I’d be good to go for a bit of time and around $1,100 (after shipping). But, the practical side of me couldn’t accept that like I assumed I would. $1,100 is still a lot of money regardless of how you look at it and, I couldn’t kid myself, it was going to take a bunch of effort to learn MythTV as a platform, not to mention how long it would take to put the thing together (I try to never underestimate my ability to procrastinate). So I decided to look up good old Dell and see what my options were. My mind blew.

Turns out that the lowest Dell desktop model available at the time had HDMI outputs native and is only $299. I don’t know when it started to be “standard” for commodity PCs to come with HDMI outputs but that was a good call. Plus, since the Dells come with Windows 7 Premium, and that it comes with Windows Media Center as a part of the OS, there’s no need to learn MythTV (something I just wasn’t motivated to do).

Still, the specs for the Dell wasn’t really all that great; only 2 Gigs of RAM and a Celeron processor (why do they still make these?) just wasn’t going to cut it. After upping the specs on the CPU and ordering 6 Gigs of RAM from Crucial the total cost ran around $450 and came with a year warranty which was something unexpected but nice.

It’s pretty cool that getting a home HTPC set up is now as easy as ordering any other computer.

Bookmark and Share

Practical PHP Reflection

Posted in Brain Dump, Code, Programming on March 1st, 2011 by Eric Lamb – 8 Comments

The Reflection API in PHP is one of those language features that can kind of creep up on you; it’s just not needed for a vast majority of projects. In fact, I’d wager there are a bunch of professional developers who have never had to make use of the Reflection API. Hell, I spent 8 years writing code professionally before I ever had to use it (though, because of some unrelated .NET research I was peripherally aware of it). It’s just not something that really comes up all that often in the day to day coding tasks.

Then, one day, out of nowhere, it comes up. The perfect problem where the Reflection API appears to be the perfect solution. For me this came up a couple months ago while I was working on a European zip code radius project that had to be built using one of those obfuscated and ill documented 3rd party commercial programs (nothing worse than when the platform is forced on you). So, I had to use this program that was intentionally encoded to prevent me from doing what I wanted to do. I couldn’t even look at the code; it was completely obfuscated.

Before getting into things it should be noted that the Reflection API is capable above and beyond what I’m outlining; usually for the kind of high level stuff like core Zend Framework components and anything you’d want way abstracted.

So, yeah, weird problem.

This is where reflection comes in for me. It was made for problems like the above; according to the manual:

PHP 5 comes with a complete reflection API that adds the ability to reverse-engineer classes, interfaces, functions, methods and extensions. Additionally, the reflection API offers ways to retrieve doc comments for functions, classes and methods.

So, the theory was that I could use the Reflection API to look into the obfuscated code and get some insight into what was going on and what I had to work with. I figured that, at the least, if I could see what methods, properties and comments the code had; maybe I’d get some clue about what the code was about. Using, for example, the internal PHP class “SimpleXMLElement” it’s real simple to get a nice map of the class by calling the class ReflectionClass and passing the name of the class you want to get details on as a parameter like the below:

1
2
3
4
<?php
$reflector = new ReflectionClass("SimpleXMLElement"); 
echo $reflector;
?>

The above outputs an eye gouging but verbose class map:

Class [ <internal:SimpleXML> <iterateable> class SimpleXMLElement implements Traversable ] {
 
  - Constants [0] {
  }
 
  - Static properties [0] {
  }
 
  - Static methods [0] {
  }
 
  - Properties [0] {
  }
 
  - Methods [14] {
    Method [ <internal:SimpleXML, ctor> final public method __construct ] {
    }
 
    Method [ <internal:SimpleXML> public method asXML ] {
    }
 
    Method [ <internal:SimpleXML> public method saveXML ] {
    }
 
    Method [ <internal:SimpleXML> public method xpath ] {
    }
 
    Method [ <internal:SimpleXML> public method registerXPathNamespace ] {
    }
 
    Method [ <internal:SimpleXML> public method attributes ] {
    }
 
    Method [ <internal:SimpleXML> public method children ] {
    }
 
    Method [ <internal:SimpleXML> public method getNamespaces ] {
    }
 
    Method [ <internal:SimpleXML> public method getDocNamespaces ] {
    }
 
    Method [ <internal:SimpleXML> public method getName ] {
    }
 
    Method [ <internal:SimpleXML> public method addChild ] {
    }
 
    Method [ <internal:SimpleXML> public method addAttribute ] {
    }
 
    Method [ <internal:SimpleXML> public method __toString ] {
    }
 
    Method [ <internal:SimpleXML> public method count ] {
    }
  }
}

As you can see, the above lists every property, method and constant about a class along with any parent classes and interfaces. If there were any variables the methods accepted it would also list those as well but SimpleXMLElement doesn’t have any.

It’s also possible to get the individual elements on a one by one basis while using the ReflectionClass object; for example the below methods returns the class name, any comments (if they’re in docblock format), the constants, parent class, constructor and default properties for the class DateTime.

<?php
$reflector = new ReflectionClass("DateTime");
echo "Class name: ".$reflector->getName()."\n";
echo "Doc Comment:".var_dump($reflector->getDocComment())."\n";
echo "Contants: ".var_dump($reflector->getConstants())."\n";
echo "Parent Class: ".var_dump($reflector->getParentClass())."\n";
echo "Constructor: ".var_dump($reflector->getConstructor())."\n";
echo "Default Properties: ".var_dump($reflector->getDefaultProperties())."\n";
?>

Outputs

Class name: DateTime
Doc Comment: bool(false)
Contants: array(11) {
  ["ATOM"]=>
  string(13) "Y-m-d\TH:i:sP"
  ["COOKIE"]=>
  string(16) "l, d-M-y H:i:s T"
  ["ISO8601"]=>
  string(13) "Y-m-d\TH:i:sO"
  ["RFC822"]=>
  string(16) "D, d M y H:i:s O"
  ["RFC850"]=>
  string(16) "l, d-M-y H:i:s T"
  ["RFC1036"]=>
  string(16) "D, d M y H:i:s O"
  ["RFC1123"]=>
  string(16) "D, d M Y H:i:s O"
  ["RFC2822"]=>
  string(16) "D, d M Y H:i:s O"
  ["RFC3339"]=>
  string(13) "Y-m-d\TH:i:sP"
  ["RSS"]=>
  string(16) "D, d M Y H:i:s O"
  ["W3C"]=>
  string(13) "Y-m-d\TH:i:sP"
}
 
Parent Class: bool(false)
Constructor: object(ReflectionMethod)#2 (2) {
  ["name"]=>
  string(11) "__construct"
  ["class"]=>
  string(8) "DateTime"
}
Default Properties: array(0) {
}

Check out the documentation; there are a bunch of other details you can get from other methods.

This is really just the tip of the iceberg though. There are other classes that allow even deeper insight into functions, methods, extensions and much more. Definitely worth checking out.

Bookmark and Share

The Lesson of Adobe Reader

Posted in Programming, Rant on February 25th, 2011 by Eric Lamb – Be the first to comment

One of my favorite parts about programming is the design part of a project. No, not the pretty sparkly pretty design; I know I suck ass at that and it’s just a bad idea for me to even attempt. Instead, I like the part where the program itself gets designed; the part where the order of things gets worked out and you, the programmer, gets to be creative and connect A to B to C on all the parts that were left out of the scope.  Sure, you know you need to add, for example, a form to a webpage but unless anyone told you how it should be written it’s entirely up to you how to do it; that’s the good stuff.

There are all sorts of places people go to sharpen their program design skills, which, and let’s not kid ourselves here,  is a way subjective but difficult specialty; personal favorites of mine are sites like Gamasutra, which has a great postmortem section, and The Daily WTF, books about projects like Dreaming in Code and Showstopper! and, to look at how other programs function and what other people like or dislike about that program, Reddit (of all places).

One of the better posts I’ve seen on Reddit, in regards to insight, was for Adobe Reader. On Reddit the question of why Adobe Reader is constantly updated is often asked but, what with the hive mind and all coming to the proper conclusions, is almost always linked to the “correct” answer:

Ok.. here is a comment from somebory who knows his shit:

the adobe reader you have isnt a simple PDF reader.

TL;DR: Adobe Reader is a huge system and reading PDFs is one of its many functions. If all you care is reading PFDs only then you should ditch it and get Sumatra or Foxit.

Long version:

lets follow the rabbit..

There is a reason its not called “Adobe PDF reader” but “Acrobat reader” or “Adobe reader”. It is a monster of a system.
reading PDFs is one of many functions.
For a project i had to read into adobe acrobat and heck its a real monster: it has

a complete mail server, document lifecycle [sic] management system, DRM client, full fledged document tracking system, form capabilities, statistics for your docs (imagine sending a survey and tracking the collected data), video AND audio playing capabilities (yes you can embed audio and video in pdf) as well as capabilites [sic] for other formats (such as displaying CAD(!) data in its own 3Dviewer).

all in all the full acrobat SDK is like 500 MB and its manual a couple tousand [sic] pages long.

merely displaying PDFs is one function out of like 100.
To you as the consumer its the bait… but the full fledged system behind it is what Adobe sells to its corporate consumers.

they basically say: “You want a full fledged content tracking system? we got it… and the best part is all your customers have the clients already installed! in form of the acrobat reader”.

Its like a monster sleeping in every computer.

see this link. Its the function comparisson [sic] of the acrobat family..

and here comes the scoop: all functions you see are supported by acrobat reader… but you cant use them. They are there so you can provide them to the guys who paid for “pro extended”.

Basically the pro extended package can create all that shit and all drones using acrobat reader will support the functionality. wheter [sic] they want it or not.

And here is the screamer: being a normal guy you will most likely never need all that crap. You know what does it mean when i say ” document tracking system”? its just a fancy word for the dream of every adverstiser [sic]: Corporate customers can track how succesful [sic] their
newsletter, advertising and customer Polls are.

Yup.. they can track how efficient their spam is. And all you sheeples who over the years keep complaining “omg i just want to read pdfs why is the install file soo big” never cared to actually read what is included.

My advice: if all you care for is reading PDFs (and im sure 99% of Acrobat reader users are in this group) install Foxit or Sumatra.

That’s just poor design right there; forcing a large percentage of your users to suffer a poor experience for the benefit of a smaller portion of users is just flat out dumb and one of those decisions I’m fairly certain couldn’t be made by a team that’s dogfooding their project. It’s just basic math; make life easier on the majority.

Bookmark and Share

Truth In Hard Drive Space Marketing

Posted in IT, Rant on February 16th, 2011 by Eric Lamb – 2 Comments

One question I get asked from time to time by, well, pretty much anyone I’ve ever worked for or with, is why their hard drive was marketed at one size yet the available size is far smaller. For example, they may buy a hard drive that’s marketed at 320 Gigabytes but when they get it installed there are only 286 Gigabytes of space available. On the surface this can be pretty frustrating in the “Bait and Switch” kind of way; you buy one thing and get another, lesser, thing but like most things about computers, the reality is actually pretty rational if not simple.

Truth in Hard Drive Marketing

Truth in Hard Drive Marketing

Traditionally, when confronted with the question I had always just gone with the tried and true line that I cribbed from Tom’s Hardware:

Hard Disk Drive (HDD) makers define “GB” or “Gigabyte” as 1,000,000,000 bytes. Microsoft (in Windows) defines it as 1,024 x 1,024 x 1,024 bytes, or 1,073,741,824 bytes.

Thanks to Stack Overflow I now know that the real, thorough, answer is:

There are 3 reasons why the amount of space you can actually use is different from that listed for the drive, all of which work against you:

  1. Hard drive manufactures treat 1GB as one billion bytes, while the operating system calls it 1,073,741,824 bytes (1000 * 1000 * 1000 vs 1024 * 1024 * 1024).
  2. You lose some space for file tables when formatting.
  3. Disk space is divided into chunks larger than 1 byte (typically 4K). Using typical Windows defaults, a 1 byte file takes up 4K of space on disk.

Of these, the first two can influence the amount of space reported by the drive (though IIRC the 2nd one was more of an issue with FAT32 than NTFS). The last one only influences the amount of free space remaining, but will still prevent you from using the full capacity of your 80GB drive.

It’s almost reminiscent of the Mars rover debacle about metric vs standard measurements; HDD makers use a decimal metric while the operating system uses binary. Anywho, this means that if you have a 320 Gigabyte HDD Windows will recognize it as 286 Gigabyte HDD. Pretty straightforward really and aside from having to dodge the occasional rant about how illogical that is and how come I just don’t know more about the ins and outs of HDD business practices it’s not really been that big of a concern for me professionally. Well, now as my client’s needs for storage are increasing well, it’s, in a sorta kinda way, becoming a bit of an annoyance.

A recent project I had was to design a system for obscene storage space; the client is a civil engineering firm so they deal in those HUGE CAD files for city planning and architectural plans and they want to do version control on them. So, lots and lots of space was needed and while investigating a possible solution that involved a dedicated RAID array it dawned on me that the specs were a little more complicated than they aught to be. Math was going to be required above the normal RAID calculations you have to do for setting up a RAID array.  I mean, God forbid I say they’ll have one amount of space when the reality is they’ll get a lesser amount; I don’t need that kind of attention.

On the surface setting up a RAID 5 device with 8 2 terabyte HDDs would yield a total of 16 terabytes before the RAID and, according to the RAID calculator, around 13 terabytes of usable space after the RAID setup. The reality though is that each 2 terabyte HDD is only going to yield 1.8 terabytes each and once the RAID is configured the total size is going to be 11.7 terabytes. A little over a full terabyte is missing; a non trivial amount to be sure.

So it’s a knowable problem and it just requires a little math but the more I think about it the more I’m starting to empathize with the reactions of previous clients. Put simply; wtf man? Why don’t the HDD makers put on the box the amount of space most people will experience; at least as a sub text on the box? For example, putting both the decimal and the binary amounts side by side or maybe listing the amount of space available for the big 3 operating systems (Windows, Mac and *nix) would be way more helpful and truthful than just listing the binary amount and leaving customers feeling ripped off.

canThere are 3 reasons why the amount of space you can actually use is different from that listed for the drive, <em>all</em> of which work against you:</p>

<ol>
<li>Hard drive manufactures treat 1GB as one billion bytes, while the operating system calls it 1,073,741,824 bytes (1000 * 1000 * 1000 vs 1024 * 1024 * 1024).</li>
<li>You lose some space for file tables when formatting.</li>
<li>Disk space is divided into chunks larger than 1 byte (typically 4K).  Using typical Windows defaults, a 1 byte file takes up 4K of space on disk.</li>
</ol>

<p>Of these, the first two can influence the amount of space reported by the drive (though IIRC the 2nd one was more of an issue with FAT32 than NTFS).  The last one only influences the amount of <em>free space</em> remaining, but will still prevent you from using the full capacity of your 80GB drive.
Bookmark and Share

My Xbox Live Fraud Experience

Posted in Brain Dump, Rant on February 14th, 2011 by Eric Lamb – 26 Comments

This Sunday I had one of those moments I’ve heard about but never experienced: my Xbox Live account was compromised and someone had purchased a crap load of points and transferred them to someone else. Since I default to the outlook that corporations don’t give a crap anymore (have they ever?) I was thinking I was screwed and was out of the money unless I contact my bank. Not the case though; turns out Micro$soft actually seemed to care and everything turned out better than expected.

On Sunday, I woke up to a series of 4 emails confirming the purchase of 10,000 points from Xbox Live Marketplace, a renewal of my Xbox Live Family account (dude actually changed my plan to include his account) and an email confirming the transfer of those points to another Xbox Live account. Now, my first thought was that I had really tied one on the night before and had just blacked out while doing some shopping on Xbox Live.  Then I remembered that I didn’t drink (just smoked) and, after checking the email timestamps, the purchases were made while I was sleeping. Fuck me.

Now, I’m not a stranger to the odd charge on my credit cards and know exactly what to do; call the bank and contest the charges. Because I actually use my Xbox though, and I do purchase a lot of content through Zune and Xbox both, I thought it would be a good idea to contact Microsoft and let them know about what was going on. God forbid I contest the charges and Microsoft thinks I’m the one ripping them off, right? So, I call them up and, after waiting on hold for a good 10 minutes, I get on the phone with Regina.

Regina was very pleasant and, after she confirmed I was who I said I was, she was actually pretty sympathetic and understanding as well. I honestly didn’t expect actual sympathy though and was pretty taken back by it; going through the motions and patronizing wouldn’t have surprised me in the least but Regina was very accommodating, knowledgeable and helpful. Regina explained that while this isn’t what she would call a common issue it does happen from time to time and, to me at least, she came across as having dealt with similar issues in the past personally. This really put me at ease when dealing with her which was good because I was in fight mode, expecting to be screwed at any moment.

One key part that struck me about this whole thing was the paper trail; because the system emailed me confirmations about each transaction it was obvious who was responsible and Regina made it clear that this a good thing. I had the username of the person the points were transferred to so, apparently, it’s pretty trivial for them to respond though I find the idea that the account wasn’t temporary ridiculous. I don’t want to underestimate the stupidity of criminals but surely the jackass who ripped me off must know the username they sent the points to would be flagged and investigated. Right?

Anyway, Regina gave me some details about what Microsoft were going to do on their side (which I’ll post once the investigation is completed lest I tip someone off in the event I know the asshole) and what my expectations should be as far as resolution (pretty good since it was caught within hours of the purchases). She also made sure to make a point of contacting my bank and letting them know as well which, while I was going to do regardless, I definitely appreciated.

It should be about a week until I hear something about the investigation and, hopefully, the resolution. All told the process took only 34 minutes and left me feeling a lot better about Xbox and Microsoft as companies to, if not completely respect, not worry about screwing me given half a chance.

That said, I’m not an idiot (well, about this stuff anyway); I still contacted my bank and contested the charges so my money is back safely where it should be. The bank, as a matter of policy, invalidated my credit card and is going to send me a new one but it’s a small price to pay I think. Well, that and now there’s no way I’m ever going to let a service keep my credit card on file ever again.

Bookmark and Share

The ExpressionEngine Caching Solution

Posted in Code, Programming on January 3rd, 2011 by Eric Lamb – Be the first to comment

I’ve been hard at work on a dynamic navigation system for an ExpressionEngine project this last week. The project has been a lot of fun in all the right ways; complicated, technical and way outside my comfort zone. Basically, the project was to build a suckerfish style navigation bar using jQuery, superfish (a jQuery implementation of suckerfist) and ExpressionEngine. And therein lies the issue…

I had anticipated making the nav all efficient-like with a single query to pull out all the items and build the nav using unordered lists. I started doubting this as a good idea though when I came to learn how complicated the data model was for this particular project. Now, don’t get me wrong, ExpressionEngine by itself is a blank slate when it comes to the data model for a project and, technically, they have a good and normalized structure for everything. Which was the problem.

An ExpressionEngine site is traditionally (at least as far as the sites I’ve seen and learned from) broken up like the below:

Weblogs
    Categories
        Entries
            Sub-Entries...

So, weblogs have categories which have entries attached to them which, in turn, can have sub-entries. Pretty straightforward I think but when you consider that this all represents around 6 tables that would require some pretty complex joins it’s one of those cases where the “right” way isn’t the ideal way. On the other hand, breaking the SQL up into multiple queries done in a loop is usually a pretty bad idea especially when you don’t know how many times the loop is going to occur.

So, I was fucked with 2 crappy choices and needed to pick the least evil; I settled on looping queries with the caveat of caching. This was ideal because the cache could be set to a pretty large interval so the nasty SQL wouldn’t execute but once a week or so. Having never worked with the native caching mechanism within ExpressionEngine learning about it became the new problem.

To be honest, I’m a little embarrassed that I didn’t delve into learning about this sooner; it turns out ExpressionEngine has a few different caching options available built right in. I’m pretty new to ExpressionEngine, having only been developing with it for a few months, but it was pretty lame that I didn’t immediately look into this option. There are so many problems the built in caching would have solved :/

Query Caching in ExpressionEngine stores the output of certain database queries to a flat file (in fact, all the caching mechanisms store the cache as a flat file). It has to be manually turned on in the administration panel but once it is turned on you’re good; all the queries that can be cached will be cached in (what else?) the cache directory. It should be noted that EllisLab doesn’t recommend using Query Caching because it’s much more effective to just turn on the native caching in MySQL itself.

Tag Caching is useful for storing the output of ExpressionEngine tags on a tag by tag basis. Tag Caching allows for very granular caching so you can have certain portions of a page cached while leaving others completely dynamic. It should noted that Tag Caching only works on ExpressionEngine tags and, unless it’s coded for caching, won’t have any effect on plugins or extensions.

To enable Tag Caching all you have to do is add “caching=’true’ refresh=’60′” to any ExpressionEngine tag like the below:

{exp:channel:entries cache="yes" refresh="30"}

The first parameter just tells ExpressionEngine to turn caching on for the tag; the second is the amount of time, in minutes, to keep the cache active before it is refreshed. Pretty simple really though depending on how many tags you’re trying to cache it could be a bitch to implement I think.

Template Caching is what I think of as the most effective caching mechanism ExpressionEngine has to offer. Essentially, ExpressionEngine saves the entire output of a template to a flat file. The really cool thing is that ExpressionEngine caches not only most of the output for most EE Tags used (like the above) but also any php you may have added as well.

It’s a little misleading to say that it’s perfect though; there are a quirk to how it works. The entire, processed, template doesn’t get cached just the heavy database or PHP stuff does; any EE Tag for conditional logic and URLs are still processed after the fact. Not a thing that’s initially worrisome though that may depend on the circumstances of the project.

Bookmark and Share

jQuery HoverIntent

Posted in Code, Programming on December 6th, 2010 by Eric Lamb – Be the first to comment

I had a project recently to build a custom tooltip for a client site. The spec called for something the opposite of out of the box so it would have to be done as a custom job; no single off the shelf plugin would work here. There was one in particular that I was really stoked I could use to make development a lot easier; hoverIntent.

When I started thinking about how to approach this project an immediate worry I had was how to bypass the snappiness of the default jquery hover behavior. As you’d probably expect it’s perfect, which sums up my problem; the project requirements called for an ajax tooltip which means every time it was activated a call to the server would happen. This would SUCK if it happened too much for basic performance reasons so it was important that there wasn’t any unnecessary server calls. Using the default behavior a user just dragging their mouse over the links would make a server call. This was no good.

Off the top of my head the best way to handle this situation was to write in some timers to delay the server call and add in some checks. Frankly though, I’m much too lazy for all that so I hit up my goto source for all code related head scratchers: StackOverflow. There I heard about hoverIntent; a great plugin which handles all of the above and then some.

In a nutshell, hoverIntent works by replacing the normal calls to “hover” with “hoverIntent” with the same parameters as “hover”. A basic example of both techniques would be:

//default jquery hover usage
$("#demo1 li").hover( overCallBack, outCallBack );
 
//default jquery hover usage
$("#demo1 li").hoverIntent( overCallBack, outCallBack );

Note that there are 2 parameters that can be passed and they’re the same regardless of whether you’re using “hover” or “hoverIntent”; both are functions with the first being the over state (when the user mouses over the item) and the second being the out state (when the user moves their mouse off the item).

The above is the easiest and fastest way to use hoverIntent but there’s another, better, method that allows for much more customization. By passing hoverIntent and single object you can customize how the plugin behaves. hoverIntent allows for customization of the sensitivity and the interval, which according to the official site means:

timeout:
A simple delay, in milliseconds, before the “out” function is called. If the user mouses back over the element before the timeout has expired the “out” function will not be called (nor will the “over” function be called). This is primarily to protect against sloppy/human mousing trajectories that temporarily (and unintentionally) take

sensitivity:
If the mouse travels fewer than this number of pixels between polling intervals, then the “over” function will be called. With the minimum sensitivity threshold of 1, the mouse must not move between polling intervals. With higher sensitivity thresholds you are more likely to receive a false positive. Default sensitivity: 7

interval:
The number of milliseconds hoverIntent waits between reading/comparing mouse coordinates. When the user’s mouse first enters the element its coordinates are recorded. The soonest the “over” function can be called is after a single polling interval. Setting the polling interval higher will increase the delay before the first possible “over” call, but also increases the time to the next point of comparison. Default interval: 100

The below example illustrates how the object should be created and passed.

var settings = {
    sensitivity: 4,
    interval: 75,
    over: overCallBack,
    out: outCallBack
}; 
$("#demo1 li").hoverIntent( settings );

And there you go; a better way to handle hovering over elements with jquery.

Bookmark and Share

Buh Bye Blackberry

Posted in Brain Dump, IT on November 28th, 2010 by Eric Lamb – Be the first to comment

It’s a strange day when an opinion piece condemning a device for not a few inadequacies actually sells someone else on the supposedly flawed device; but that’s exactly what happened while reading Omar Shahine’s recent rant against the iPhone. In a nutshell, he’s been using the iPhone for the last couple years and, while he initially loved the iPhone, he’s grown tired of all the problems he has (which are mostly due to his work situation because of Windows tech).

However, I have grown tired of you. As an enterprise device, you have completely failed. Each update of iOS brings more problems with Exchange support. You fundamentally don’t understand what it means to talk to an Exchange server since your programmers don’t use Exchange for their jobs. I put up with months of email hangs, years of poorly formated emails, calendar appointments went missing from my calendar, and you still don’t understand that it’s important when you look someone up in the corporate directory that you show their office location. After 2 years of this, I’m convinced you’ll never figure this out. I put up with it though because you were the best lifestyle phone around.

All good points and the above is almost picture perfect for why I’ve been sticking with the Blackberry for the last 4 years. I always looked at the iPhone (and I hate to say it but pretty much anything Apple) as just a toy used by amateurs. Yeah, I’m a snob about computers (Surprise!). But it was true; once upon a time Blackberry had the better reputation for email and, with email being as important to me as it is, Blackberry wins. It was really that simple.

Blackberry really took care of me and most of my needs for a LONG time. I’ve used the Blackberry Enterprise Server (BES), IMAP and POP with the Blackberry for email and it’s always been pretty cool (POP less so but what do you expect from POP?). There’s a pretty nice App ecosystem too, not as good as the iPhone (obviously), but I never really felt like I was missing anything. I had Google Maps, a great RSS reader with Viigo, a couple cool games, an SSH client and a pretty nice phone to boot. Along with the email, which, seriously, I thought couldn’t be beat, I was a pretty happy man.

And then, about a year and a half ago things started to get a little… crappy with the Blackberry. I’ve been using a Blackberry Bold, once a really good device, but there was a constant issue with the trackball not working. For days at a time I couldn’t scroll down. That probably doesn’t sound so bad at first glance but when you consider that the Blackberry doesn’t have keyboard shortcuts for navigation and moving the trackball to the extreme of any direction doesn’t loop to the opposite side the device in the interface this made my Blackberry pretty much useless for anything except email (painful, but usable anyway) because of a keyboard shortcut for opening that application.

I couldn’t use Google Maps and I couldn’t read any articles. I couldn’t use the web browser (unless I clicked a link in an email). Hell, a couple times I couldn’t even turn the ringer back on once I’d turned it off. Oddly though, the trackball would miraculously start working after about a week though I could never figure out what happened.

And that’s where I found myself last week as I was reading Omar’s post; I’d been ham fisting my way through using my Blackberry for basic, email only, stuff and I was fucking sick of it. Hearing all of Omar’s reasons for dropping the iPhone were reasons that don’t apply to me anymore. I don’t work in a corporate job so no more Exchange or IT policies to comply with that aren’t of my making. This was a revelation; I don’t need a Blackberry just a good smart phone that does email alright. Enter the iPhone.

So I took the plunge. I dropped a couple hundred, signed a 2 year contract with AT&T (sigh…) and after playing with the iPhone for the last 24 hours I really think I made the right choice. The whole tapping thing is pretty nice though typing is challenging right now (makes me feel like I have fat fingers…) but I’m told it gets easier.

The weird thing is just how much I love the email management. It. Is. Slick!! The iPhone really makes the Blackberry look like shit; it’s like comparing Windows 3 to Windows 7. It’s that good. Animations, smooth interface, decent search and really thorough Google Apps integration; wow was I impressed. It’s that good.

Still, the juries out on whether or not this is a good move; it’s entirely possible I’m going to regret moving to the iPhone but for now at least everything’s nice. I still have my old Blackberry Bold, ready to use at a moments notice (sans trackball moving down of course), so I should be cool but as of right now I’m happy.

Bookmark and Share

Care About What Matters

Posted in Code, Programming on October 22nd, 2010 by Eric Lamb – Be the first to comment

It’d been a while since I’ve had the free time to write something and I really didn’t think it’d be a bitch post but it is and here we are. But, as I sit here at midnight browsing Reddit, and, yes, a little drunk, I find myself raging about the idea of the dumb stuff we care about and why we probably shouldn’t.

Case in point, an article called “PHP require vs. include vs. require_once vs. include_once Performance Test” written by Arin Sarkissian way back in 2007. Forgiving the obscenely long and verbose title, Arin goes over the process and code he created to test which of 4 statements (require, include, require_once, includes_once) was the most efficient in terms of performance. It’s definitely a good read if for no other reason than the insight into how to test and benchmark code but I think there’s more to the article than that.

That said, the article left me unsettled for a couple reasons. First, with the amazement and appreciation that someone had taken the initiative to test a theory instead of just drawing conclusions (something that’s pretty rare in my experience). Second though, well the second thing bothered me because of the other more applicable and meaningful question I couldn’t shake. Why do we care about this nonsense?

For years I’ve read articles about how best to handle certain circumstances to improve performance. Some are good. Things like how to use the dir() function to iterate over directories or how to properly write SQL are great and definitely worthwhile reads. On the other hand though, there are tons of articles talking about the advantages of using single quotes over double quotes or, as Arin wrote, which function is better suited for file inclusion; scenarios that matter so minimally that the effort in thinking about the issue is far greater than the gains of switching techniques.

As my friend Caroline would say, “Rubbish; all of it.” (she’s British).

Care about your SQL. Care about your file system interaction, your loops and your math. Care about your logic. And, because it’s so important it demands repeating, care about your SQL.

I promise you, there are zero circumstances where whether you used include_once over require_once is going to be the bottleneck. It will never matter one bit if you concatenate with single quotes rather than use double quotes with nested variables. Hand to fucking god; it will not matter nearly enough to spend any time debating which approach is better.

So before you start spending all your time wondering what is the best technique or method for a specific scenario as yourself how much does it matter.

SQL
Bookmark and Share

Developing ExpressionEngine 1.6x Extensions

Posted in Code, Programming on September 30th, 2010 by Eric Lamb – Be the first to comment

I recently had a project come up that could have gone one of two ways from a  strategic design stand point; either as a straight up script custom built for the occasion or, time warranting, I could build an extension for ExpressionEngine. As I’d already looked into writing an ExpressionEngine plugin the idea of writing an extension was pretty enticing regardless of the added time costs I would have to swallow (can’t bill the client for my fun now can I?).

Developing ExpressionEngine 1.6x Extensions

Developing ExpressionEngine 1.6x Extensions

The only problem is that the project in question was built on ExpressionEngine 1.6.7 and ExpressionEngine, having recently released 2.0 with all new bells and whistles and ways of doing things, updated their documentation as well. I couldn’t find any documentation for writing extensions for 1.6x though there’s a really nice help center for 2.0. A little advice third party developers; don’t just remove documentation and replace it with the new stuff because, as shocking as this may sound, people still use the old stuff.

To ExpressionEngine an extension is a script built to modify how ExpressionEngine works as opposed to adding additional functionality like a plugin would do. For example, a plugin would be good for adding a drop in template tag while an extension would be good for changing how ExpressionEngine parses all template tags. If you’re used to the WordPress development paradigm think of extensions as hook filters in WordPress plugins.

Those aren’t the only distinction though; extensions can also have a settings section, language files and database tables too so you’re really going  to need at least an extension for any deep functionality or customizations (there are also ExpressionEngine modules and expansions but that’s for another day).

Codewise, ExpressionEngine extensions are pretty similar to plugins insofar as structure and elements. At the core an extension is a PHP class that follows the same naming structure for both the class and the file as a plugin except the prefix changes and where you store the file. ExpressionEngine extensions should be named with a prefix of “ext.” and the class name, include a couple class variables for information about the extension, a couple methods to activate, deactivate and remove the extension and, ideally, a method to be called when the “hook” is executed.

As an example let’s put together an extension stub for a demonstration of how things should be setup

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
<?php
class Pissoff_client
{
	/**
	 * Name of the extension
	 * @var string
	 */
	public $name = 'Enrage The Client';
 
	/**
	 * Version of the extension
	 * @var string
	 */
	public $version = '1.0';
 
	/**
	 * The description of the extension
	 * @var string
	 */
	public $description = 'Replaces every instance of one word with another from all entries';
 
	/**
	 * Flag for whether this extension has settings 
	 * @var string
	 */
	public $settings_exist = 'n';
 
	/**
	 * URL to the documentation for the extension
	 * @var stirng
	 */
	public $docs_url = 'http://url_to_documentation.com';
 
	/**
	 * The available settings for the extension
	 * @var array
	 */
	public $settings = array();
 
	/**
	 * Constructor
	 *
	 * @param 	mixed	Settings array or empty string if none exist.
	 */
	function Pissoff_client($settings = '')
	{
		$this->settings = $settings;
	}
 
	/**
	 * Activate Extension
	 *
	 * This function enters the extension into the exp_extensions table
	 *
	 * @see http://codeigniter.com/user_guide/database/index.html for
	 * more information on the db class.
	 *
	 * @return void
	 */
	function activate_extension()
	{
		global $DB;
 
		// default settings
		$settings =	array();
		$hook = array(
				'extension_id'	=> '',
				'class'			=> __CLASS__,
				'method'		=> 'run',
				'hook'			=> 'hook_to_process_extension_on',
				'settings'		=> serialize($settings),
				'priority'		=> 1,
				'version'		=> $this->version,
				'enabled'		=> 'y'
		);
 
		$DB->query($DB->insert_string('exp_extensions',	$hook));
	}
 
	/**
	 * Update Extension
	 *
	 * This function performs any necessary db updates when the extension
	 * page is visited
	 *
	 * @return 	mixed	void on update / false if none
	 */
	function update_extension($current = '')
	{
		global $DB, $EXT;
 
		if ($current < $this->version)
		{
			$query = $DB->query("SELECT settings FROM exp_extensions WHERE class = '".$DB->escape_str(__CLASS__)."'");
 
			$this->settings = unserialize($query->row['settings']);
			$DB->query($DB->update_string('exp_extensions', array('settings' => serialize($this->settings), 'version' => $this->version), array('class' => __CLASS__)));
		}
 
		return TRUE;
	}
 
	/**
	 * Disable Extension
	 *
	 * This method removes information from the exp_extensions table
	 *
	 * @return void
	 */
	function disable_extension()
	{
		global $DB;
		$DB->query("DELETE FROM exp_extensions WHERE class = '".__CLASS__."'");
	}
 
	/**
	 * Method to execute when hook is called
	 * @param mixed $data
	 */
	public function run($data)
	{
 
		//process
	}
}

Most of the above should be self explanatory but just in case what’s going on is that most of the class variables are used for extension details and there are 3 methods for activating, deactivating and removing the extension. The methods for activation management are important, especially the activation method “activate_extension” which contains the details about the extension including the hook to execute on along with the method name to execute when the hook is called. In the above example, the extension will execute the method “run” when the hook “hook_to_process_extension_on” is called. Thankfully, ExpressionEngine hasn’t done away with the list of hooks available in the 1.x branch.

Obviously, the above extension is pretty useless, what with not doing anything, but that’s all you’re gonna need to have the extension listed in the Extension Manager. To further personalize and customize (huh… I’m a poet) the details of your extension you can add settings and, if you want people to have the ability to change those settings, you can add a settings page by.

To add a settings page to your extension things get a little complicated at first but it’s not so bad. All you have to do is set the class variable $settings_exist to “y”, create a new method called “settings()” that EE uses and modify your extension language file (should be created inside the “lang” directory using the convention of “lang.extension_name”). The settings() function should contain an associative array with the key being the name of the setting and any default value for that setting like the below:

<?php
function settings()
{
	$settings = array();
	$settings['pissoff_find']		= '';
	$settings['pissoff_replace']	= 'this is the default value';
	return $settings;
}

Using the above will simply display a form with 2 text boxes for input. If no value is provided for the second item then there’ll be a default used. Simple. But, if you want to use, say, radio buttons or select boxes you have to make a couple modifications like the below:

<?php
function settings()
{
	$settings = array();
 
	$settings['pissoff_find'] = array('t', 'Default!!');
	$settings['pissoff_replace'] = array('r', array('nothing' => "Nothing", 'something' => "Something"), 'something');
	return $settings;
}

The above will create a new setting form with a textarea for the first option and a radio fieldgroup for the second. Make sure you add the radio option text to your language file though; it won’t do that automatically. Also, you’re not locked into just radio and textareas; you can also have select boxes (s) and multi-select boxes (ms) by updating the relevant array key.

Bookmark and Share
« Older Entries
Newer Entries »
  • Subscribe: Entries | Comments
  • About Me

    Email Email
    Twitter Twitter
    310.739.3322
  • Categories

    • Brain Dump
    • Business
    • Code
    • IT
    • Programming
    • Rant
    • Servers
  • Archives

    • February 2012
    • October 2011
    • August 2011
    • July 2011
    • June 2011
    • May 2011
    • April 2011
    • March 2011
    • February 2011
    • January 2011
    • December 2010
    • November 2010
    • October 2010
    • September 2010
    • August 2010
    • July 2010
    • June 2010
    • May 2010
    • April 2010
    • March 2010
    • February 2010
    • January 2010
    • December 2009
    • November 2009
    • October 2009
    • September 2009
    • August 2009
    • July 2009
    • June 2009
    • May 2009
    • April 2009
    • March 2009
    • February 2009
    • January 2009
    • December 2008
    • November 2008
    • October 2008

Copyright © 2008 - 2012 Eric Lamb - All rights reserved