jQuery Magnifier Loupe

Inspired by the loupe in Apple’s Aperture, I built a jQuery loupe to add a 100% zoom widget to a thumbnail. See the examples below to see how this works.

Images scaled with HTML

Images with the fullsize image set as a longdesc attribute

Usage

Import the jquery.jloupe.js script into your page Add the class “jLoupe” to an image to enable the loupe. To enable zoom you can add the URI of the fullsize image to the “longdesc” attribute. Your image tag should look something like this: <img src="thumbnail.jpg" longdesc="fullsize.jpg" class="jLoupe" /> An alternative way enable the zoom is to use HTML to scale a fullsize image with the width or height attribute.

Download

Download the source: jquery.jloupe.js

Learning CakePHP

At work I was tasked with building an internal application that is designed to closely mimic the popular Ffffound.com. Our designers have a lot to share but we are lacking a single robust channel for them to do so. Currenly they use email, but that method is disruptive and very difficult to have robust discussions for the whole community to see.

So with a basic set of objectives in hand I started to orgainze my thoughts on how I would build this. I decided to dig deep into CakePHP and start with nothing and see how far CakePHP could take me. I’ve learned a lot in the last week, and I plan on sharing much of it here on this blog. Ive found that the cake community is big on sharing, and the numerous blogs out there actually make up for a sometimes lacking manual and API.

I chose not to use codeignighter because it is so lightweight. If I was going to really learn MVC for PHP I wanted to learn it on the most robust framework available, that way any future work with a framework would either be status-quo or a step down in complexity.

So I started looking thru the Manual, the API and the Bakery for direction. To be frank, there wasn’t a whole lot of ‘getting started’ help. The manual has two application examples, one of them being the classic simple blog (using scaffolding). Although the examples were step-by-step I really found that they dont quite explain why things are happening, instead they sort of just tell you what to do to get things working. I could learn this way but it would take me forever to try to reverse engineer the process. I needed something else, another approach.

I set out looking on the interwebs for some help and I came across this article on Snook.ca where Jonathan explains his initial thoughts. He explains how he installed cakePHP and it literally told him what to do to get started. I thought this might be a good way to learn, actually get into the app and begin throwing around my own code, making it do what I wanted, poking here and there and seeing for myself what happens. Sure enough, when you install cake it starts telling you what you should do and the steps to do it.

Let’s say you want to show all your posts at the url /posts/. You plug that into your browser and cake will display a page telling you how to build out the code to make that page start handling code. It was not long before I was putting together the parts of this application, writing CakePHP code and exploring the manual for what I needed, instead of searching for explanations.

Some Discoveries

As with any large scale open source project, you will do yourself a huge favor to read through the source and see how the experts think. I am always amazed to see how people optimize functions, both for efficiency and for readability. One method I came across was the use of PHP compact() to set a named array as an option parameter.

To briefly explain compact(), it creates an array by combining variables supplied to it. The interesting thing is that the variables are named, not supplied. This means your arguments to compact are strings, not variables. As I’m using it i find it really cleans up the source code for functions that require nested arrays with named variables. This approach to array building has some hidden power, since now you could create the array by splitting strings and without even knowing the variables that will go into building it.

Inspiration From Wordpress Code

I was trolling through the wordpress code at PHPXRef.com because I wanted to really grasp how they implement their plugin system. I love the idea of setting up a base and then letting it be accessible by 3rd party scripters. I have a project that I’m working on that is totally great and useful on its own, but if I was to give developers a safe way to get into the code, im sure that they would be able to make it do all sorts of never-before imagined things. Besides wading through a monster of code and assembling a mental model of their approach, I was able to see their thought process during wordpress’s startup. Its very similar to my startup approach but they do a lot more and a few things I didnt expect, and a few things I will be doing in my own projects from now on. One thing to note is that their startup sequence takes place across about a dozen files, while also loading about 2 dozen class descriptions. They took “modular” to a new level, and I think they go a bit farther than is necissary. My opinion on that matter is mostlikely naieve because I dont have to manage an application with millions of user installs, as well as a fully hosted solution with millions more users. It all starts at wp-blog-header.php which then loads wp-load.php which then loads wp-config.php which finally loads wp-settings.php which is where the real work starts. From there it gets ugly and the stack goes from 4 files all the way to something like 30 files.

I put together a list of the best take-away concepts for your own learning enjoyment:

  • Store the hard config data in constants with define()
  • Look for register_globals = true and disable it if it is (and force the auto globals to unset)
  • Set a php memory limit if you can (and if you need it to be higher)
  • Set the absolute path of the app to ABSPATH constant
  • Its OK to tweak $_SERVER if the webserver implements it wrong (IIS)
  • Check if the mysql extension is loaded before trying to use it
  • Make the DEBUG flag a constant
  • Get the config before the settings is loaded so that config supercedes settings
  • Append a unique site id to the cookie name
  • Search for the config file before including it
  • The config file is acceptably found in more than one place
  • Tables must have a prefix option
  • Check for the php version and die if its too old and unsupported
04.24.08

Recent Tastings

Last weekend Mark and Nancy visited and Mark brought the equivilant of a mini cellar with him. I think the total bottle count was 6, two of them French and the rest very posh Californian wines. This list includes a few of the wines we tried, but mostly just catching up with my tasting progress since my last posting.

  • 2004 Robert Mondavi Private Selection zinfandel (this wine was cooked probably due to poor shelf care)
  • 2005 Coppola Red Label zinfandel
  • 2004 Kendall-Jackson meritage
  • 2005 Santa Alicia malbec (better the second day after opening)
  • 1999 Louis Jadot Chambolle-musigny (Mark)
  • 2001 Chateneuf-du-Pape (Mark)
  • 2005 Coppola Blue Label merlot
  • 2003 Chateau Rocher Corbin bordeaux

We also made a visit to Vino 100 –a very keen little wine shop–which is just a couple of blocks outside of Downtown Chico. Let me make it clear that Chico is not a wine town. It is a town grown on alcoholic libations of every kind except wine. The philosophy is: as long as its cheap and available in a keg. The college town crowd brings everyone down a notch by increasing the demand for pee flavored water that makes it onto store shelves under the label Natural Ice or Keystone whatever.

Vino 100 is like a breath of fresh air in this town, with their shelves filled with unique and classy wines from the North State. They have $5 tastings every day they are open. Their slogan is “100 wines for under $25″ but you can find wine across the board. I picked up that Santa Alicia Malbec for $8 and it was quite good. Mark and I were able to taste four reds and we quite liked all of them. One stood out as a wine to remember for the winter holidays, yet Ive already forgotten the name.

The Web-Dev Dilema

I have been a “web” coder for nearly 10 years. Like many I find the web to be one of the most exciting places to be a builder and a creator. The web has a unique characteristic of providing instant gratification for your work. Where else can you click save on your computer and instantly thousands of people are seeing your work. 

I currently consider myself a PHP and Javascript coder. If you know either of these languages you would know that they both require a high proficiency in HTML and CSS and I’ve been doing that stuff even longer. Many projects I have completed in these web languages turn out to be quite laborious. Yet its remarkable they get completed at all when you consider the constraints that a web developer must live under. Some of these are problems of the platform and some are of the community.

problems

  1. All web languages have dozens of “right ways” to do things, but hundreds of wrong ways
  2. Required to support multiple–often incompatible–browsers
  3. Constantly changing technology on top of never changing browsers
  4. Countless XSS and hacking vulnerabilities require you to be an über hacker defend
  5. No single source of definitive information
  6. No single company to hold responsible for platform bugs
  7. Microsoft
  8. Raging and fruitless debates over Javascript libraries and ROR
  9. The pandering to the beginning developers in the libraries
    (Lightbox in only one line of code!!!! OMG LOLZ!!!1)
  10. Invention of poor UI elements to make up for the browser retardations
    (lightboxes, mega ajax usage, faked js windows, simulated drag and drop. etc…)
  11. Your success as a web app developer depends on your ability to seed the blogosphere with your sales pitch
  12. Popularity of sites like Facebook and Twitter that prove that the web is all about FREE which means
  13. All revenue must be garnered by disgusting Google ADS
  14. Users are less likely to pay your monthly service plan when they understand that someone else will come along soon and provide that service for free
  15. The “heroes” or “celebrities” of the web are just ego maniacs and should be punched in the mouth
  16. The really smart guys “under the hood” are ignored and most of the time the credit is sorely misplaced on the front man. (kevin and the digg)

crux

Ive hit a crux in my career development. I have to decide where I want to be in 5 years and Im getting this terrible feeling that the developing web is not the place. You know that feeling when you thought you were the cool kid at school because you had the –insert trend here– before everyone else? Then when everyone joins and it becomes “trendy” and you sorta give up on the idea. Then people started to –insert derivative trend– with your trend and angry nausea ensued? Thats where I am at with the web. I feel absolutely terrible knowing that the highlight of my career as a web developer would be to work for Google, Microsoft/Facebook, or Yahoo. I dont want to work for any of them! They are the suck, for me to poop on.

change of plans

So from this conclusion, I opened a new path. The last few weeks ive been teaching myself Cocoa. Most of the problems above are either irrelevant or there are discrete choices. For example there are only two or three Mac OSX systems currently in use. You can choose to support all of them, or only two, or only one. All of these choices are valid ones in the Mac community. AND most of the bugs and deficiencies are known and help is provided to get around them. This simply has no analogue in the web browser environment. Most importantly: Apple is paving the way in easy mobile platform development, and I want to get in on that trend before its too cool for school.

Here’s to a new adventure and a new business model. Lets ride this one and see where it takes me.

04.11.08

2008 - The Year of Wine

My new year’s resolution for 2008 was to gain an interest in wine. I was fumbling around with wine like I had always done until a few weeks in when I discovered the BBC show “Oz and James’ Big Wine Adventure.” Across two seasons and about 14 episodes, they impart great wine wisdom. I love it because its infotainment and because it’s got James May in it.

Its a shame that great British shows like this aren’t readily available to the US viewers (I had to download all the episodes from motorworld.net) After watching the series I had this strange feeling that I actually knew something about wine. It led me to instantly make better decisions about what I was buying. Most importantly it helped me to be more critical and buy wine that I liked. That led me to pretty much stop buying white wine after I realized that I just didn’t like it.

Ive been keeping a small log on the wines that I’ve had to this point. Im definitely in the early “crazy in love” phase of a new hobby and Ive been tasting wine like my life depends on it. My favorites are in bold and the bad ones are struck out.

  • 2004 Prima Voce merlot
  • 2007 Yellow Tail shiraz-cab
  • 2006 XYZin zinfandel
  • 2005 Block 50 shiraz
  • 2006 Yellow Tail merlot
  • 2005 Kendall-Jackson zinfandel
  • 2005 LaRocca cabernet
  • 2000 Berengario cabernet merlot
  • 2006 Wild Horse pinot noir
  • 2006 Fetzer gewurtztraminer
  • 2005 Robert Mondavi PS zinfandel
  • 2006 Gallo sonoma reserve pinot noir
  • 2005 Bogle zinfandel
  • 2006 Baroncini Messere chianti
  • 2005 Gallo sonoma reserve cabernet
  • 2006 Coppola silver label pinot noir
  • 2005 Coppola Rubicon cab franc
  • 2005 Coppola rubicon zinfandel
  • 2006 Alfaro Family ”A” Estate pinot noir santa cruz
  • 200x Rex Goliath pinot noir
  • 1999 Alexander Cellars zinfandel
  • 2005 Irony pinot noir
  • 2006 Directors Cut coppola zinfandel
  • 2004 Toasted Head shiraz
  • 2004 Picchetti pinot noir
  • 2005 Sebastiani cab
  • 2003 Pacific Estates cab
  • 2005 Woodside Vineyard kingsmtn cab
  • 2003 Havens syrah
  • 2004 LaRocca pinot noir
  • 200x Coppola black label claret
  • 2005 Berryessa Gap zinfandel
  • 2006 Charles merlot
  • 2006 Charlse Shaw rose zinfandel
  • 2006 Charles Shaw syrah
I plan on keeping this list growing throughout the year. I just recently purchased 3 additional bottles of the Alfaro Family Pinot Noir–which remains my favorite wine by far. 

Firefox, Flash and the Dissapearing Trick(ster)

If you are using Flash with Scriptaculous and Firefox you might be seeing your flash movies embed, but then dissappear immediately. Dont worry, its not a problem that you cant fix.

Let me just explain the problem and its simple solution. Evidently Firefox does not like Flash movies to be inside anything with even a hint of opacity. I want to underscore hint. The reason for that is the object inside which my flash movie resided had an opacity of 0.999999999. By most standard thats not technically one but depending on who you ask it (mathematically) is. The reason for this opacity being set to such a bizzare number is that as far as Scriptaculous’ Effect.Opacity will take you. Even if you specify that you want to fade from 0.0 opacity to 1.0 it wont ever get you to that ideal 1.0 only infintely close. Its bringing back uncomfortable memories of Calculus.

So the problem isnt really with Flash or Firefox but Scriptaculous and its wonky effects.

The solution is almost too simple, I set Effect.Opacity to fade to 1.1 opacity. It does that with no complaint and simply sets the css appropriately to 1.1. Firefox doesnt seem to mind nor Safari and my flash movie show up correctly. Im dreading what IE 6 might think, but then again if it were a physical object it would have been incinerated by angry developers a few minutes after it was created.

Safari and location.hash

One of the more annoying problems with Safari 2 and lower is the fact that it fully breaks the common pattern of applying a page anchor to the history via location.hash. The most frusturating part about this was that it acutally does submit the hash to the URL but Safari goes into a sort of perma-loading state with the spinner perpetually spinning. After reading around I didnt find anything that particularly fixed this problem. I did get some ideas however and came up with this solution.

Some things to note, while safari doesnt play nice when you apply the hash through javascript, it does behave correctly if you set a link with the href="#hash". I figured that if you could create a link with the hash you want to set, you could simulate a click, and Safari might get it right. It appears that there arent any good reliable ways to trigger a click on an A element. BUT there is a reliable way to trigger such an event on more (or less) ovbious elements like SUBMIT and BUTTON, also RESET and RADIO. Why they chose not to include A is a mystery to me.

So discovering that I realized that there might be a third way to do this. A form element has an action attribute which is ususally used to send data to a form processor. Well I cheated and set the action to be my hash instead. Javascript can build the form element, set the attribute, build the submit button, simulate the click and then wipe it all clean. This actually works! Its such a filthy hack it sorta makes me feel sick but its better to have it work than not at all.

Here is a bit of code to show how this works: In it I attempt to set the location.hash to #1.0.0

if(navigator.appVersion.indexOf('AppleWebKit') >0)
{
   var form = document.createElement('form');
   Element.hide(form);
    // here we set our desired hash
   form.action = '#1.0.0'; 

var link = document.createElement('input');
   link.type = 'submit';
   form.appendChild(link);

document.body.appendChild(form);
   link.click();

// requires prototype.js
   Element.remove(form);
}
else {
    // so easy for everyone else
   location.hash = '1.0.0';
}

Notice that it checks for Safari, thus saving everyone else from this convoluted series of steps. If you have any further suggestions on how to improve this method please feel free to contact me.

PAGES
CATEGORIES
MY DEL.ICIO.US
OLD POSTS