Archive for July, 2006

IE7 css list element hack

There's been alot of talk lately about what's going to happen to current implementations of IE related CSS hacks when IE7 gets pushed to the mainstream. The past couple of years have been pretty stable with knowledgeable folks only having to employ a few basic tricks to keep things happy. Being a veteran of the version 4 browser wars, I've been pretty grateful about current CSS and DOM implementations to say the least.

Here's what happened to me

So I'm pretty good at writing clean W3C compliant CSS, I've been using CSS since about 1999 sometimes for good, sometimes for evil. With this new look and feel of my site I was running into an issue that I had never thought about before. How different browsers handle list item indentation.

As you can see over on the right (if you can't see over on the right because you subscribe via RSS, let me say thank you! I'm currently up to 20 subscribers or somthing woot!) anyway, as you can see over on the right, the nav elements for other posts, tags and whatever the hell i have over there are list elements, they sit in a div that floats right is 200px wide and everything is nice and happy and not going anywhere (unless of course you disable CSS). These list elements also have a little image that is being used as a bullet, it's set with css, and needs about (well exactly) 16px to display well, not be hidden, yadda yadda.

It's never just one thing right?

Of course it's not ever just one thing, at least for me it always seems like it's either two issues, bugs, what-have-you... or it's just straight up raining cats dogs and the kitchen sink and my hairline creeps a bit farther from my eyebrows. Well this time, I was only dealing with the two thing rule... however, I only knew what one of the things was. For some reason IE 6 wasn't displaying my little background image for each list element, not only that, it was actually displaying everything but the first few characters of each and every link. That's because Firefox likes to indent it's list items a bit and I had the margin-left property set to -2.5em, so in IE, it was REALLY making it -2.5em and pushing things over to the left and getting clipped.

One way of being able to exclude a property in CSS from being set in IE is to use the child selector method. Here's a exerpt from an article over at positioniseverything.net that explains it nicely.

The Child Selector
This selector uses a ">" symbol as a "combinator" that is placed between two parts of a CSS selector, and indicates that the target of the rule is the element on the right side of the ">" combinator, but only when that element is a direct child of the element to the left of the combinator. Thus, the selector table>td can never target any element, because TD's are never direct children of tables, only of TR's. On the other hand, the selector tr>td would select every TD on the page, since all TD's are direct children of TR's.
...
IEwin just ignores the entire rule because it cannot recognize that child combinator. Now that support is coming, IE7 will be able to view such hacked CSS. But since that browser will still have quite a few failings, letting it get a look at those hacks could be less than desirable, to say the least.

Not that big of a deal. Sofar there isn't any need for any conditional statements, or any of that jazz. I just simply moved my setting of the margin-left property down to a second style that will appear to redefine the style in Firefox and Opera and just be ignored by IE

CSS:
  1. #sidenav li, #casestudies li, #download li {
  2.         display: block;
  3.         width: 179px;
  4.         padding-left: 3px;
  5.         /*margin-left:-2.5em;*/
  6.         }
  7.  
  8. /* IE6 left margin fix */
  9. #sidenav>li, #casestudies>li, #download>li {
  10.         margin-left:-2.5em;
  11.         }
  12. /* end IE6 left margin fix */
  13.  
  14. #sidenav li a, #casestudies li a {
  15.     display: block;
  16.     width: 176px;
  17.     background: url(../images/li_small.gif) no-repeat 0.2em 0.4em;
  18.     padding-left: 1.1em;
  19.     }
  20.    
  21. #sidenav li a:hover, #casestudies li a:hover {
  22.     color: #a5965a !important;
  23.     width: 176px;
  24.     background: #f8faff url(../images/li_smallhover.gif) no-repeat 0.2em 0.4em;
  25.     padding-left: 1.1em;
  26.     border-right: 3px solid #a5965a;
  27.     }

Ok, looks good, everything's peachy. I'm seeing the list elements in the same place now in Firefox, Opera and also IE6. At this point I had remembered reading somthing about the Child Selector being supported in IE7, so now I had to see for myself what was going on and then decide what I was going to do about it.

It's true, IE7 doesn't ignore the Child Selector and went ahead and rendered the style, this time, it's not clipped, and way off to the left.

The first thing that I thought to do is try to make sure that I set the margin-left property for everyone BUT IE. I couldn't seem to find anthing out there that would to specifically exclude IE, only ways to directly express IE. I wasn't interested in having to do the inline VBscript method (that doesn't appear to work within linked CSS files anyway, tell me if I'm wrong)

HTML:
  1. <style type="text/css" media="screen">
  2.     ...some default css....
  3. </style>
  4. <!--[if IE]>
  5.     <style type="text/css" media="screen">
  6.         ...some IE only CSS...
  7.     </style>
  8. <![endif]-->

Additionally I didn't want to require a second file that's just for IE because when it comes down to it, it's Firefox and Opera that aren't displaying how I'd like and not IE, hence the need to set the property in the first place.

Ok so it's looking like this more of a Firefox / Opera hack

It all comes down to the lowest common denominator, the List Element itself. The chain of events sofar are this

  1. the core attributes are set
  2. the margin-left attribute is set for everything but IE6
  3. now we need to reset margin-left for IE7 only

This is where I had to use that client-side VBScript, it's quite simple. since each and every List Element on my site I indend to operate in the same way, I didn't have to do any more than this.

HTML:
  1. <style type="text/css" media="screen">
  2.     @import "includes/naterkane.css";
  3. </style>
  4. <!--[if IE 7]>
  5.     <style type="text/css" media="screen">
  6.         li { margin-left: 0 !important; }
  7.     </style>
  8. <![endif]-->

ajax boot camp

Earlier today Ajaxian mentioned Eric Pascarello's proposal for an Ajax Boot Camp. A two day adventure filled with lectures and hands-on coding. Some of questions Eric plans to answer with this workshop are:

  • what is the consequences of not using caching on the client?
  • what happens with session?
  • what causes that memory leak?

Current plans are to host the camp in the Baltimore/DC area (my old stomping grounds) sometime in september. You can read the original post and keep yourself updated here.

Now drop and give me twenty.

monster’s new instant job search beta

Since I'm currently job hunting, a few times a week I bounce around between the different job sites out there to see if there are any decent opportunities close to where I live, or if I do actually have to commute to NYC to find good work. Today I was checking out monster after persuing a lead that made it's way to my Inbox early this morning to discover Monster's new Instant Job Search.

The Instant Job Search is a simple ajax app that lets job seekers do basic keyword searches of available jobs on the fly, without the use of a submit button. You specify your zip code, and search radius, and get results sort of quickly (avg. search time for me was between 2-5 seconds, not blazingly fast by any means, but quicker than a page refresh of course. I quickly typed in "Ajax" to get two listings of the same job for a .NET Developer in Connecticut. Well I'm not a .NET guy, so I expanded the radius from 35 to 70 miles (which includes NYC of course) and got 12 returned results, most of which I can work with.

Some interesting findings

This new little app works like an auto-complete and begins searching once you type in two characters in the Keywords field. As I said before there isn't a submit button, so it seems like every time you add a letter, it sends a request. And when you enter another character, it cancels that request and replaces it with a new one. So this is my quesiton. What's the point of this app? By sending requests with each keystroke and trying to return any data any chance it gets, theoretically if a user types slowly and is a hunt and peck type, they could actually using more bandwidth than if they had a page refresh since the server is returning more than the typical auto-complete string array.

Json meets AHAH

Ok, I'm sure you're saying "what's the big deal?" It's just lightweight data and folks who hunt and peck will never notice. And I'll agree with you. The WTF is what's returned by the server when you run your query, a line of JSON then some AHAH style HTML. Huh? Here's my query.

HTML:
  1. http://my.monster.com/JobSearch/InstantFeeder.aspx?_location=12528&_keywords=ajax&_radius=70&_sort=rank&_pagenum=1&_pagesize=1

And here's the JSON / AHAH hybrid that was returned

HTML:
  1. {"jobs":{"returned":12,"found":22,"pagenum":1}}
  2. <table class="ijsResult" id="ijsresult_1" xmlns:fo="http://www.w3.org/1999/XSL/Format">
  3.   <tr>
  4.     <td style="vertical-align:top;">
  5.       <span style="display:none;" id="ijsmeta_1">{'jobid':46098442 , 'positionid':36388017, 'displayoptions':}</span>
  6.       <div class="colItemNumber">1.
  7.         <br /></div>
  8.     </td>
  9.     <td style="vertical-align:top;">
  10.       <div class="colDetailedDateActive">
  11.         <span style="display:none;" class="colApplied" id="ijsapplied_1">A</span>
  12.         <span style="display:none;" class="colFiled" id="ijsfiled_1" onclick="IjsEvent({etype:'delfromfile',value:1});return false;">F</span>7/25/2006</div>
  13.       <div class="colDetailedJobTitle">
  14.         <span style="display:none;" id="ijsstar_1">
  15.           <img src="http://media.monster.com/mm/usen/icons/10x10_arrow.gif" border="0" alt="" />
  16.         </span>
  17.         <a href="http://jobsearch.monster.com/getjob.asp?JobID=46098442&amp;WT.mns_pth=1001" target="_blank">Java Developer with XML and Web Services exp</a>
  18.       </div>
  19.       <div>
  20.         <span class="colDetailedCompanyName">CyberCoders</span>  <span class="colDetailedLocation">Harrison, New York</span></div>
  21.       <div class="colDetailedSummary">Java developer for exciting Software Company This position is open as of 7/26/2006. Not a fit for this position? Java Developer with XML and Web Services exp   Location    ...<a href="http://jobsearch.monster.com/getjob.asp?JobID=46098442&amp;WT.mns_pth=1001" target="_blank">[more]</a>  <span class="colSaveToFile" id="ijssavetofile_1"><a href="javascript:return false;" onclick="IjsEvent({etype:'savetofile',value:1});return false;">[save to file]</a></span></div>
  22.     </td>
  23.   </tr>
  24. </table>

Pretty weird eh? Every time results are returned there is a parsing error due to syntax issues with the JSON string. And then other errors related to various DOM issues ie. "uncaught exception: Permission denied to set property Window.status" and "Error in parsing value for property 'right'. Declaration dropped."

What I don't understand is why the use of a hybrid return data set in the first place? All of the XHTML is formatted in the same way so why bloat things up with the redundant code? That same data could be in XML or JSON and be totally trimmed down. Below is an example of a JSON version of the same data. The JSON string equates to 592 bytes as opposed to the HTML version that is a much heftier 1,749 bytes. You get the point.

JavaScript:
  1. {"jobs": {
  2.     "meta": {
  3.         "returned": 1,
  4.         "found": 22,
  5.         "pagenum": 1},
  6.     "result": [
  7.         {"jobid": 46098442,
  8.         "positionid": 36388017,
  9.         "displayoptions":,
  10.         "itemNumber":1,
  11.         "ijsapplied": "A",
  12.         "ijsfiled": "7/25/2006",
  13.         "detailedJobTitle": "Java Developer with XML and Web Services exp",
  14.         "detailedCompanyName": "CyberCoders",
  15.         "detailedLocation": "Harrison, New York",
  16.         "detailedSummary": "Java developer for exciting Software Company This position is open as of 7/26/2006. Not a fit for this position? Java Developer with XML and Web Services exp   Location    ..."}]}

How to make a beta annoying to debug

Three words, lousy code formatting. The javascript errors took me to this line

JavaScript:
  1. return"";},SafeEval:function(s){return eval("["+s+"]")[0];},CookieGet:function(ckey){var carr=document.cookie.split(/\s*;\s*/);for(var nvk in carr){var nvsplit=carr[nvk].split(/=/);if(nvsplit[0]==ckey){return nvsplit[1];}}

Coding grammar

I can't stress enough the importance of well formatted code. When you are writing in any language, english included, poor formatting equals improper grammar. Thissentence,isinenglishandcanberead!eventhoughitisnotnaturalYadig? If a highschool student wrote a paper that was difficult to read, they'd get a lousy grade even if it was the most most amazing piece of work in the entire history of literature. The same applies to coding. Yes, when I typed in my query the app returned the results I was expecting. But from such a large company as monster.com, I was hoping for more.

unconscious vs. conscious interface design

I just recently discovered Justin Palmer's blog Encytemedia. About a month or so ago he wrote an article about Unconscious Interface Design as defined by Marco Dorante.

Basically, unconscious design is design where there is no “conversation with the situation�. Sometimes we make design decisions based out of habit; we are simply following the norm; or we just never asked ourselves “Why?�. Every design decision we make should involve us having a “conversation with the situation� if we wish to break free of unconscious design.

He goes on to talk about examples of unconscious design in the Wordpress admin interface which got me thinking about all of the bulk information that I don't really need to see every time I login in to add a post or do whatever. Has anyone else been interested in revamping the wordpress admin? I'm not concentrating on look and feel, but actually putting together an "admin admin" that lets the user decide what information they want to see on each page as they manage their blog. If so let please let me know by either leaving a comment or emailing me directly.

some new css, and some new glasses.

Since I'm the kind of guy, that's always busy but somehow usually bored, I decided to give naterkane.com a new look and feel this past weekend.
It's based on the Fauxed wordpress template, and over the next week, will continue to get a few more changes as well as I work out some browser degradation issues, and finish implementing back button and bookmarking functionality in the portfolio.

Also I finally got around to reillustrating my glasses for the first time in 6 years. I've had this pair for more than half that time now and I figured the logo illustration needed an upgrade as well. New NaterKane™ logo typography is in the works since I have now just realized that the font I designed for the original NaterKane brand was completely and hopelessly lost when my computer gave up the ghost last year. With that, I'm taking typeface suggestions from anyone who cares, if you have a favorite font that you'd like to see my name in, email it to me at nater at naterkane.

If you have any feedback, I'd love to hear from you, so please leave a comment.

developing the navigation for an.tidote.us

Following up to my previous post about what's been going on with the development of an.tidote.us

Getting Started

an.tidote.us is the first full flash site I've developed in over a year, and working outside of the infrastructure that Evolving Media previously provided for me, our hosting account with Daily Razor has created a few issues that I've had to take into consideration. Namely the last of Flash Remoting Support.

The site uses a basic two level navigation component that's setup like this.

  • Work
    • Print
    • Web
    • Identity
  • About
    • Mission
    • History
    • Staff
  • Contact

There is a third level that only exists for the Staff section, and we're going to let that section have it's own iteration of the nav component, instead of relying on extending the main navigational component further. Doing so lets me create an xml object with one very simple SQL statement.

No Remoting? Now What?

Looking into alternatives to remoting, I came across AMFPHP. Which would be a great solution if I wasn't hell bent on developing this site in ColdFusion. The last few projects that I've done, including my own site and this blog have been in PHP, and I really wanted to use the simplicity,flexibility and power of CFCs for this site instead of layers of mangled crap that would have come from a mixed Flash/ColdFusion/PHP implementation.

Ok, so there's this little thing that I remembered about it being pretty simple to connect to a webservice in flash and retrieve whatever data, in whatever format it sends. So this is where we get to our CFC.

The World's Simplest Web Service, WSWS...

I wrote a CFC that does two simple things, runs a query against the Sections table, and parses the results to XML.

CODE:
  1. <cfcomponent>
  2. <cffunction name="getNavXML"
  3.     access="remote"
  4.     returntype="xml"
  5.     output="false"
  6.     hint="gets an xml object that is used to build main and subnavigation components">
  7.     <cfquery name="GetNavItems" datasource="antidoteus">
  8.         SELECT *
  9.         FROM Sections
  10.         ORDER BY ParentID ASC
  11.     </cfquery>
  12.     <cfscript>
  13.     // create xml object
  14.     navXML = XmlNew();
  15.     navXML.XmlRoot = XmlElemNew(navXML, "navigation");
  16.     </cfscript>
  17.     <cfoutput query="GetNavItems">
  18.     <cfscript>
  19.     if (parentid eq "0"){
  20.         // create menu node and attach it to the root node
  21.         xnNavItem = XmlElemNew(navXML, "menu");
  22.         xnNavItem.xmlAttributes["name"] = "#name#";
  23.         ArrayAppend(navXML.XmlRoot.XmlChildren, xnNavItem);
  24.     } else {
  25.         // create menu node and attach it to it's parent node
  26.         xnNavItem = XmlElemNew(navXML, "submenu");
  27.         xnNavItem.xmlAttributes["name"] = "#name#";
  28.         ArrayAppend(navXML.XmlRoot["menu"][parentid].XmlChildren, xnNavItem);
  29.     }
  30.     </cfscript>
  31.     </cfoutput>
  32.     <cfreturn navXML />
  33. </cffunction>
  34. </cfcomponent>

This is what is returned, or you can check it out for yourself here.

XML:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <navigation>
  3.     <menu name="Work">
  4.         <submenu name="Print"/>
  5.         <submenu name="Web"/>
  6.         <submenu name="Identity"/>
  7.     </menu>
  8.     <menu name="About">
  9.         <submenu name="Mission"/>
  10.         <submenu name="History"/>
  11.         <submenu name="Staff"/>
  12.     </menu>
  13.     <menu name="Contact"/>
  14. </navigation>

Ok, So Now What?

So I now have my XML to build the nav from, now I need a quick way to build the nav itself, and of course keep to the specs outlined in the site's final comping design. That's where extending flash components, themes and styles comes in. I'll save that for my next post once I finish the nav in a day or two.

an.tidote.us progress report

There are quite a few things that need to get done with an.tidote.us. But first some history...

For those who have no idea what an.tidote.us is...

an.tidote.us is the home of the Antidote Branding Consortium.
So you ask, what the hell is the Antidote Branding Consortium? Well, the ABC is an organization, design collective and identity that has been put together by yours truely and Jim Maximowicz. What we're most excited about at the ABC is The Antidote Project, a web-based initiative inspired by Jim Maximowicz's thesis project at SUNY New Paltz of the same name. But more on that later.

Ok, so onto the progress.

We have an identity

an.tidote.us logo We put this together using Coolvetica by Ray Larabie. The logo uses a 1:1.2 ratio for lineheight to textheight. so if the font size is 24px, the line height is 20px.

We have a finalized color pallete

To keep things simple, we chose to go with a clean CMY based pallete, with C, M, and Y representing the three main categories of the site. One thing i noticed when putting it together is that the luminocity of true CMY vary to a great degree. This was before I began selecting additional color values in for each section to represent various states, actions, relationships, visual effects, etc. I asked myself if there was a color pallete or color theme that i was familiar with, that had good ratios and good luminocity out there. The answer was simple, Adobe's Halo Theme, which is what's used to set the color and feel to Adobe's Exchange. an.tidote.us color pallete

Appying the luminocity and color value relationships used in Halo to our true CMY base pallete, this is what we ended up with.

Navigation Components

The development of the site's navigation will be in a soon-to-be-written post. So check back soon components can be found here.

doing simple things without a code library

So I just was reading this article written by David Talbot on Devx.com about Yahoo's UI libraries aiming to make crossbrowser development a bit easier for some folks.

The only notable feature that I could seem to find, was the simplification of setting the opacity of a DOM element in an elegant way. An entire library for that? I got a little curious and took a further look.

Here's an exerpt from the artile:

The DOM and Event Libraries
YUI's capabilities in regard to core DOM and event handling are incredibly rock-solid, perform as expected, and cover a broad range of capabilities. Most surprisingly, this API gives you simple cross-browser transparency control. Most developers aren't even aware that magic tricks even exist (via DirectX calls) to make semi-transparency work in IE, much less the Mozilla-based equivalents, but YUI enables access to most, if not all, of the CSS properties you'd ever want. Here's an example:

YAHOO.util.Dom.setStyle('MyDivID', 'opacity', .5);

Suprizingly? Are you kidding me? Maybe I just don't get what the big deal is. I've been developing crossbrowser DHTML in one way or another since the beginnings of the last browser wars. And back in 99-2000 when everyone was bitching about the diversity in W3C support between the version 4 browsers, I was just doing what needed to be done to make everything work the way it needed to.

So despite Mr. Talbot's enthusiasm for what I considered to be not much of a big deal at all I headed over to Yahoo's Developer Center poked around their lousy documentation and downloaded the most recent build here on Sourceforge. I took a peek at the source, and it turns out that Yahoo and I have almost the same exact approach, thing is, running their entire library is pretty needless.

Here's what I came up with to put together a fade in effect for the items being loaded into my portfolio via xmlHttpRequest.

here's the very simple browser check:

JavaScript:
  1. var ua = navigator.userAgent.toLowerCase();
  2. var isOpera = (ua.indexOf('opera') != -1);
  3. var isIE = (ua.indexOf('msie') != -1 && !isOpera);

and here's an exerpt from my getPortfolioDetail function:

JavaScript:
  1. xhrPortfolioDetail.onreadystatechange = function() {
  2.     if (xhrPortfolioDetail.readyState == 4 && xhrPortfolioDetail.status == 200) {
  3.         portfolioDetail.innerHTML = xhrPortfolioDetail.responseText;
  4.         var fader;
  5.         for(count = 1;count <= 10; count++){
  6.             fader = setTimeout(function(){
  7.                 val = count*0.1;
  8.                 if (isIE && typeof portfolioDetail.style.filter == 'string'){
  9.                     portfolioDetail.style.filter = 'alpha(opacity=' + val * 100 + ')';
  10.                     if (!portfolioDetail.currentStyle || !portfolioDetail.currentStyle.hasLayout) {
  11.                     portfolioDetail.style.zoom = 'normal'; // if you use '1' it distorts things
  12.                 }
  13.             } else {
  14.                 portfolioDetail.style.opacity = val;
  15.                 portfolioDetail.style['-moz-opacity'] = val;
  16.                 portfolioDetail.style['-khtml-opacity'] = val;
  17.             }
  18.         },100*count);
  19.     }
  20.     xhrPortfolioDetail = null;
  21. }

Pretty simple eh? One thing that you can't see is where I use the same approach to lower the opacity to 0.1 while loading, so there isn't any flashing of the loaded content before it fades in.

I know that there are tons of AJAX Frameworks out there that provide fade in type effects, but I'm not quite there on implementing one. Noteables include Dojo, MochiKit, and of course the ever popular script.aculo.us.

I'm still working on making it work a little more smoothly and efficient as the delay in setting the opacity while i'm doing the xmlHttpRequest is inconsistant at best.


Nater Kane naterkane personal http://www.naterkane.com LinkedIn Profile Web Technologist personal nater@naterkane.com 1978-09-12 voice 845.234.6698 | fax 707.922.0593
964 Flushing Ave. Brooklyn, NY 11206