views:

257

answers:

4

tl;dr = "Anyone know how to apply chained classes for IE6 using jQuery or similar?"

Right,

perhaps I ask the impossible? I consider myself fairly new to Javscript and jQuery, but that being said, I have written some fairly complex code recently so I am definitely getting there... however I am now possed with a rather interesting issue at my current freelance contract.

The previous web coder has taken a Grid-960 approach to the HTML and as a result has used chained classes to style many of the elements. The example below is typical of what can be found in the code:

<div class='blocks four-col-1 orange highlight'>Some content</div>

And in the css there will be different declarations for: (not actual css... but close enough)

.blocks {margin-right:10px;}
.orange {background-image:url(someimage.jpg);}
.highlight {font-weight:bold;}
.four-col-1 {width:300px;}

and to make matters worse... this is in the CSS:

.blocks.orange.highlight {background-colour:#dd00ff;}

Anyone not familiar with this particular bug can read more on it here: http://www.ryanbrill.com/archives/multiple-classes-in-ie/ it is very real and very annoying.

Without wanting to go into the merrits of not chaining classes (I told them this, but it is no longer feasible to change their approach... 100 hand coded pages into a 150 page website, no CMS... sigh) and without the luxury of being able to change the way these blocks are styled... can anyone advise me on the complexity and benefits between any of my below proposed approaches or possible other options that would adequately solve this problem.

Potential Solution 1

Using conditional comments I am considering loading a jquery script only for IE6 that:

  1. Reads the class of all divs in a certain section of the page and pushes to an array
  2. creates empty boxes off screen with only one of the classes applied at a time
  3. Reads the applied CSS values for each box
  4. Re-applies these styles to the individual box, somehow bearing in mind the order in which they are called and overwriting conflicting instructions as required

Potential Solution 2

  1. read the class of all divs in a certain section of the page and push to an array
  2. Scan the document for links to style sheets
  3. Ajax grab the stylesheets and traverse looking for matching names to those in class array
  4. Apply styles as needed

Potential Solution 3

  1. Create an IE6 only stylesheet containing the exact style to be applied as a unique name (ie: class='blocks orange highlight' becomes class='blocks-orange-highlight')
  2. Traverse the document in IE6 and convert all spaces in class declarations to hyphens and reapply classes based on new style name

Summary:

Solution 1 allows the people at this company to apply any styles in the future and the script will adjust as needed. However it does not allow for the chained style to be added, only the individual style... it is also processor intensive and time consuming, but also the most likely to be converted into a plugin that could be used the world over

Solution 2 is a potential nightmare to code. But again will allow for an endless number of updates without breaking

Solution 3 will require someone at the companty to hardcode the new styles every time they make a change, and if they don't, IE6 will break.

Ironically the site, whilst needing to conform to IE6 in a limited manner, does not need to run wihtout javascript (they've made the call... have JS or go away), so consider all jQuery and JS solutions to be 'game on'.

Did I mention how much i hate IE6?

Anyway... any thoughts or comments would be appreciated.

I will continue to develop my own solution and if I discover one that can be turned into a jQuery plugin I will post it here in the comments.

Regards,

Mike.

edit: added tl;dr to the top.

+3  A: 

Here's a combination solution: http://code.google.com/p/ie7-js/

Fixes the multiple class bug and some other selector issues you may encounter.

Billiam
I'll try apllying this solution to the problem... it's one that I had originally considered (I've used an IE7.js previously on other projects, however due to the scale of the site and the amount of work that has already been completed on it, there have been a large number of IE6 hacks applied to the site previously that could break in a huge number of places if I simply upgrade IE6 to a working IE7 using this script). Oh the humanity. Will apply the js... and write back with results.Cheers.
Mike Baxter
OK... some feedback on this approach. Great idea, but unless this IE7 fix is implemented at the beginning of the project, it is a headache. Have just applied it and it conflicts with the 12 or so other JS on the page (I know, don't get me started - it's the reason they got me in... to fix these other coders' issues). Page hangs, then eventually loads looking like bollocks. Hacks have been applied at all previous stages to account for IE6 and now they are conflicting.
Mike Baxter
I would show you all an example page, however it is on a staging server at present. Sorry.
Mike Baxter
+1  A: 

I believe that if you look closely at how IE6 handles class chaining, and if the order of the class names are consistent, then you can avoid some of the IE6 issues with careful class coding.

First have a look at your provided HTML example:

<div class='blocks four-col-1 orange highlight'>Some content</div>

IE6 will apply the CSS in the order of the class names, starting with 'blocks' and continue through to 'highlight'.

Now look at your initial group of classes:

.blocks {margin-right:10px;}
.orange {background-image:url(someimage.jpg);}
.highlight {font-weight:bold;}
.four-col-1 {width:300px;}

These would be applied without any problems as each applies different properties. However, if you should, say, apply a different background with 'highlight' you should see that it will override the one set with 'orange'.

Using this same logic approach, let's have a look at the last class you defined:

.blocks.orange.highlight {background-colour:#dd00ff;}

This class should only apply to objects that have all three class names applied. What happens in IE6 is the first two class names are ignored and only the last class name is used to apply the styling. This means that any object that has the class 'highlight' will receive the new background property. (PS: the CSS property should be background-color, no 'u')

However, if you use other selector methods you can possibly avoid the limitations by applying nested ids/classes [#section .blocks] and/or object associations [form input.highlight]. This complicates the process I know, but at some point we simply need to stop trying to fully support out dated software.

Note: IE6 has not received any updates for two years and the browser itself is nine years old. The browser has two successors and a third is already in development. There should be some cutoff where an acceptable loss of presentation is allowed.

JoeFlash
A: 

OK... as there is some confusion about what I am asking:

I have been called in to work on a project that is almost completed.

There are no templates.

There are 100+ pages, hand coded and a looming deadline. Here is some actual code from the HTML/CSS all written by the last guy (not abreviated like above):

<div class="block four-col-1 gold black-bg">
  <h1>Self Managed Super</h1>
  <a class="highlight" href="#"><span class="left bottom">
  <strong><span class="text-white">Bolster your<br />
  portfolio</span><br /></strong>
  with unique<br />
  investment<br />
  options</span>
  <img src="/AU/individuals/_images/superannuation-2.png" alt="" /></a>
</div>

<div class="block four-col-1 grey-light black-bg">
  <h1>Self Managed Super</h1>
  <a class="highlight" href="#"><span class="left bottom">
  <strong><span class="text-white">Financial <br />
  flexibility,</span></strong> <br />
  into and <br />
  throughout <br />
  retirement
  </span> 
  <img src="/AU/individuals/_images/superannuation-3.png" alt="" /></a> 
</div>

and here is some of the relevant CSS:

.block .highlight {display:block;position:relative;height:auto;min-height:110px;-webkit-border-radius: 4px;-moz-border-radius: 4px;border-radius: 4px;}
.block .highlight:hover {border:1px solid #ddd;}
.block .bottom {position:absolute;font-size:11px;line-height:12px; bottom:10px;letter-spacing:-0.2px; }
.block .left {float:left;font-size:11px;margin-left:8px;width:75%;}
.block.black-bg p, .block.black-bg p * {color:#828282;}
.block.black-bg p * span.text-white {color:#fff;} 
.block img {position:absolute;bottom:0;right:1px;z-index:0}
.block .highlight img {position:absolute;bottom:0;right:0px;z-index:0}
.highlight:hover {opacity: .75; filter: alpha(opacity=75); -ms-filter: "alpha(opacity=75)";-khtml-opacity: .75;-moz-opacity: .75; overflow:visible;}
.content .block.black-light.highlight, .block.black-light .highlight, .block.black-light 
.block-inner {background:url(/AU/_images/system/block-black-light.gif) no-repeat top left;}
.content .block.grey-light.highlight, .block.grey-light .highlight, .block.grey-light 
.block-inner {background:url(/AU/_images/system/block-grey-light.gif) no-repeat top left;}

.content .block.orange.highlight, .block.orange .highlight, .block.orange .block-inner {background:url(/AU/_images/system/block-orange.gif) no-repeat top left;}
.content .block.gold.highlight, .block.gold .highlight, .block.gold .block-inner {background:url(/AU/_images/system/block-gold.gif) no-repeat top left;}
.content .block.blue-light.highlight, .block.blue-light .highlight, .block.blue-light .block-inner {background:url(/AU/_images/system/block-blue-light.gif) no-repeat top left;}
.content .block.blue-dark.highlight, .block.blue-dark .highlight, .block.blue-dark .block-inner {background:url(/AU/_images/system/block-blue-dark.gif) no-repeat top left;}
.content .block.black-light.black-bg.highlight, .block.black-light.black-bg .highlight, .block.black-light.black-bg .block-inner {background:url(/AU/_images/system/black-block-black-light.gif) no-repeat top left;}
.content .block.grey-light.black-bg.highlight, .block.grey-light.black-bg .highlight, .block.grey-light.black-bg .block-inner {background:url(/AU/_images/system/black-block-grey-light.gif) no-repeat top left;}
.content .block.orange.black-bg.highlight.block.orange.black-bg .highlight, .block.orange.black-bg .block-inner {background:url(/AU/_images/system/black-block-orange.gif) no-repeat top left;}
.content .block.gold.black-bg.highlight, .block.gold.black-bg .highlight, .block.gold.black-bg .block-inner {background:url(/AU/_images/system/black-block-gold.gif) no-repeat top left;}
.content .block.blue-light.black-bg.highlight, .block.blue-light.black-bg .highlight, .block.blue-light.black-bg .block-inner {background:url(/AU/_images/system/black-block-blue-light.gif) no-repeat top left;}
.content .block.blue-dark.black-bg.highlight, .block.blue-dark.black-bg .highlight, .block.blue-dark.black-bg .block-inner {background:url(/AU/_images/system/black-block-blue-dark.gif) no-repeat top left;}

(Code is essentially exactly as he wrote it, in all it's unformatted, hideous beauty.)

If you can be bothered to read all that (and most of you probably can't - hence my abbreviations above) you would see that whilst some classes are unique and do not conflict, some do. The result is that some blocks which are expected to be balck, in EI6 are blue, and the margins in EI6 are often wrong, and the absolutely positioned images also break particularly when combined with an IE PNGFix to make them appear transparent as expected.

Also, due to the nature of the deadlines, assume that going over each and every of the 100+ pages and editing the HTML is no longer an option. This was my recommendation from day one and whislt the client accepts that what they have is well and truly less than ideal, they are also working to a tight deadline.

This leaves only two options for edits. Change the CSS so it works across all browsers (as this is called on each page), or generate some Javascript (again, this can be called onto each page using an include) to do something with the HTML on every page on the site, or something else tricky. Changing code in the included pages is easy, changing the HTML in each of the blocks in question is out.

I completely understand what everyone is commenting on so far and thanks for those... they were my initial solutions in both cases, and I wouldn't be on here if they were an option.

Thanks to everyone who has read this, but I really am trying to find some super tricky solution to the entire problem of non-chaining classes in IE6. potentially for broader use than this project. However I now only have 5 working days to find the answer before my contract ends, so if we don't we will just hack an IE6 style sheet that makes all the blocks appear in one way on that browser and leave it at that. I would prefer to find a universal solution, but... meh. Hopefully 18 months from now the user base of IE6 will be so low that it's no longer an issue.

Thanks everyone.

Cheers,

Mike.

Mike Baxter
A: 

I think you may have missed the point of my earlier comment. I was not confused about your request but was trying to explain how you might approach the task should the coding of the site be consistent.

For a more detailed example, lets take a line from your last CSS example, minus the actual styling properties:

.content .block.orange.highlight, .block.orange .highlight, .block.orange .block-inner { }

Following the behavior of Internet Explorer 6 in regards to chained CSS classes, that line of code would be seen by IE6 as:

.content .highlight, .orange .highlight, .orange .block-inner { }

Notice that the chained class names are ignored for all except the last name in the chain. Since you had already rejected the JavaScript solutions that were proposed by others, the only solution I can see is to design your CSS class definitions with this IE6 limitation in mind as you code.

This does not make the task simple as the whole reason for chaining the classes is to be able to apply special conditional styling without increasing the DOM nodes of the document. However, in order to continue to support enhanced feature programming in IE6, without the help of some JavaScript solutions, you will simply have to put in more effort to find older conventional methods for the same result. I know this comment is likely a bit late for your project but I hope it helps with the planning process when dealing with IE6 styling.

JoeFlash