crowley code!

Posts tagged “jquery”

10/22 HTML layout the XUL way (0)

css, firefox, html, ie, jquery, xhtml, xul

Layout with HTML and CSS sucks. I was one of the people that clung to tables longer than the average bear (if bears could write PHP) because they actually work. My designerish friends guilted me into diving full-on into semantic HTML served with a hack-fest of CSS.

There’s got to be a better way.

I started this evening looking into using a XUL-style layout on a regular website. To my surprise, 35% of my visitors are on IE. WTF, really? So my first solution (follows) won’t work too well. If IE was something like 10%, I wouldn’t hesitate to screw them and go Firefox-only. 37Signals mention something about not trying to be everything to everyone to promote simplicity and I think catering to that 90% would certainly promote simple code. And since I know how a lot of JavaScript nerds feel about using non-standard HTML attributes, I had jQuery add the necessary bits after the fact.

<style type="text/css">
.hbox, .vbox {
    display: -moz-box;
}
.foo {
    width: 200px;
    margin: 0 10px 10px 0;
    padding: 10px;
    background: black;
    color: white;
}
hr {
    margin: 0 0 10px 0;
}
</style>
<script type="text/javascript" src="jquery-1.2.1.pack.js"></script>
<script type="text/javascript">
$(document).ready(function() {
    $('.vbox').attr('orient', 'vertical');
});
</script>

But as I said, I don’t want to screw all of those IE users. So onward to a better solution, using the same nice markup:

<div class="hbox">
    <div class="foo">foo</div>
    <div class="vbox">
        <div class="foo">asdf</div>
        <div class="foo">qwerty</div>
        <div class="foo">hooah</div>
    </div>
    <div class="foo">bar</div>
</div>
<hr />
<div class="vbox">
    <div class="foo">foo</div>
    <div class="hbox">
        <div class="foo">asdf</div>
        <div class="foo">qwerty</div>
        <div class="foo">hooah</div>
    </div>
    <div class="foo">bar</div>
</div>

This time, a bit more must be left to JavaScript to keep the older browsers up to date. Because nesting a bunch of boxes in boxes in boxes is just going to happen (otherwise what’s the point?), I had to resort to the > CSS selector, which has less than stellar support. So jQuery to the rescue again. Here’s my current CSS/JS. Don’t have IE, so this only theoretically works there. Anyone want to verify?

<style type="text/css">
.hbox {
    border: 1px solid blue;
}
.hbox > div {
    float: left;
}
.hbox br {
    clear: both;
}
.vbox {
    border: 1px solid red;
}
.vbox > div {
    float: none;
}
.foo {
    width: 200px;
    margin: 0 10px 10px 0;
    padding: 10px;
    background: black;
    color: white;
}
hr {
    margin: 0 0 10px 0;
}
</style>
<script type="text/javascript" src="jquery-1.2.1.pack.js"></script>
<script type="text/javascript">
$(document).ready(function() {
    $('.hbox').append('<br />');
    $('.hbox > div').css({
        float: 'left'
    });
    $('.vbox > div').css({
        float: 'none'
    });
});
</script>

Demo: http://rcrowley.org/work/xul.html

Update: I’m experimenting with ways to duplicate the flex="1" attribute of XUL boxes. Will post soon.

8/22 jQuery conditionals plugin (2)

javascript, jquery

jQuery provides a ton of ways to select sets of elements but pretty much no way to pare down a selection in an arbitrary way. Fortunately for me it’s easy to extend jQuery, so I wrote a plugin that allows you to apply a function to your set of elements to pare the set down before applying an action. Source first, talk later:

jQuery.fn.if = function(arg) {
    var elems = [];
    var all = this.get();
    var ii = all.length;
    for (var i = 0; i < ii; ++i) {
        if (arg.apply(all[i])) {
            elems.push(all[i]);
        }
    }
    return jQuery(elems);
};

jquery.if.js (version 0.1)

The plugin takes as its argument a function that must return a boolean value. This function will be applied to every argument in the current set. Those that the function finds true will be returned in the final subset.

The use-case that inspired this quickie plugin is this: I wanted an action to happen to form fields that were empty, which previously required a bit of work. If I had more work to do with each match or a more complex matching requirement, this could get ugly.

$('input.promptable').focus(function() {
    var to = $(this);
    if ('' == to.val()) {
        to.val(this.id);
        to.addClass('prompt');
    }
});

With this plugin, the chaining action jQuery is known for is not interrupted. I can select all input elements with the promptable class and pare down that selection to only those whose value is empty. On the set returned there I can set values and add classes without breaking the chain.

$('input.promptable').focus(function() {
    $(this).if(function() {
        return '' == $(this).val();
    }).val(this.id).addClass('prompt');
});

jquery.if.js (version 0.1)