Fun Fact of the Day

So, let's say you're trying to catalog an object in a ZCatalog, and for important reasons irrelevant to the instant case you have code similar to the following:
    from Products.CMFCore.utils import getToolByName

def _getCatalog():
try:
return getToolByName(context, 'my_catalog')
except AttributeError:
return None

catalog = _getCatalog()
if catalog:
catalog.catalog_object(myobject)

I sure assumed that would work. Not so! If the catalog is empty, bool(catalog)==False. You have to do:

if catalog is not None:

And there's an hour I'll never get back.

Read More...

Portable Version of Archetypes' ReferenceEngine

Archetypes has a pretty good system for creating references between objects. I don't see, on a first glance through the code, why it couldn't be split out into a separate Zope product. It'd have quite a few dependencies, of course, including CMFCore, making it not the most plug-and-play package ever, but it'd be handy for Zenoss's purposes. Right now we're using our own relationships package, called ZenRelations, which works pretty well at the moment, but is slightly unwieldy and more than a little shaky. We're always a little afraid to mess with it; in fact, it's the primary reason we haven't moved to a more recent version of Zope. This could free us from the shackles of 2.8.

Anyway, I plan to mess with that this weekend.

Read More...

Accessing Zope variables with Javascript

ZPT totally ignores the contents of <script> tags, which makes it kind of a hassle to use values from the server in your Javascript. Short of writing a whole integration framework, the best way I've found to pull variables from page templates into Javascript is like this:

<tal:block tal:define="foo accessor/for/myvar">
<script tal:content="string:
var foo='${foo}';
"></script>
</tal:block>


I generally have one of these up at the top of the template, storing portal_url and whatever else I might need in a namespaced array. You can run into problems with nested quotes, but if you don't have the time to write more complex back-end methods, it's a handy quick-and-dirty hack.

Read More...

The unholy brilliance and universal utility of this CSS hack has made this the greatest day of my young life

Equal height columns with divs! My cup of happiness overflows. Although my support of <div>s over tables is constant and complete, nonetheless a single use case causes me grief: When laying out columns containing content blocks potentially of various heights (that is, always), one cannot set a background color on a column, because its height will be that of its content, not that of the longest column. OH NO.

Enter my favorite hack ever. All you do is set the bottom padding on each column to some enormous number of pixels (the maximum delta between any two column heights), then give each column a negative bottom margin of the same number. Now give the column container an overflow: hidden.

Unfortunately, there's an issue in Gecko browsers. I was doing this in a site template that wraps around some generated Docbook HTML; as you might imagine, linking to anchors inside the content happens a lot. And that's where the equal height hack fails;overflow:hidden doesn't react well to anchors inside--it scrolls the container to that point, instead of the page, leaving you stranded halfway through your content. Luckily, there's a fix: if you set position: absolute on those anchors, everything's okay. Not everyone can do that, of course. Thankfully, I could, and it's working like gangbusters.

For those who use YUI's Grids CSS, as I do on those rare occasions when I get to lay out some blocks on a nascent page, here's exactly what I did:

.yui-t1 #bd { overflow: hidden; }
.yui-t1 #bd .yui-b {
padding-bottom: 10000px;
margin-bottom: -10000px;
}
.yui-t1 #bd a[name] {
position: absolute
}

Naturally you can replace .yui-t1 with whatever layout template you're using.

This is old news to most. I don't know how it eluded me for so long. But now I can die.

Read More...