Archive

Archive for September, 2011

Table-less Forms: A Partial Solition (Source Code)

September 20, 2011 Comments off

In my last two posts, I discussed what I want to see in a table-free form and the problems I had with creating one. To recap, here’s what I wanted:

  • Labels lined up in the same row as form fields
  • Label column that stretches/shrinks to the size of the longest label
  • As little extra HTML as possible

My solution was to enclose s in a

that stretches/shrinks to the width of its contents, and to use absolute positioning to push the s nested in those s outside the

. The limitations of that solution are:

  • The s’ height won’t stretch to fit form controls taller than a line of text, such as .
  • Since s are pushed to the right, you can’t put checkboxes and radio buttons before their label text unless they’re outside the wrapper

    .

  • Long labels stretch the wrapper

    .

  • Multiple wrapper

    s in a form won’t line up with each other.

So with that in mind, here’s my source code. First the CSS:

form { /* Add border to form as visualization aid */
border: 1px solid darkblue;
}
form * {
clear: left; /* don't let floated .formlineup break layout. */
}
.formlineup {
display: inline-block; /* shrink to fit content. */
float: left; /* Needed for backward-compatibility with IE6 and FF2. */
background-color: lightblue; /* Visualization aid */
}
.formlineup label {
display: block;
position: relative; /* allow absolute positioning of children */
padding-top: 2px;
margin-top: 2px;
padding-right: .5em;
background: #CEF; /* visualization aid */
}
.formlineup label input {
position: absolute;
top: 0px;
left: 100%; /* Push all the way outside the */
height: 1em;
}
/*
tags are used in case CSS breaks.
They create extra space when CSS is working, so hide them. */
.formlineup br {
display: none;
}

Next, the HTML. Note that nothing outside of div.formlineup is really important for this demo; I put the extra fields there to show some of the things that need to be outside of the wrapper div in order to work. See the screenshot in my previous post to see what happens when you put them inside.




Name:




Address:




Stuff:




Password:



Radio Buttons


Thing 1




Thing 2




VOOM!




This label is longer than the others.





Send Me Spam!




Addendum: Sorry about the ugliness of the source code; Blogger doesn’t feature syntax highlighting out of the box, and there’s some investment of effort required to add it. I’m still debating whether I want to add it or just stick to using my WordPress blog to post source code from now on.

Advertisements
Categories: Uncategorized

Nice, Clean HTML output at any length

September 17, 2011 Comments off

I have written previously about the rather spiffy SimplePie. For the record, I really like it so far.

But there’s one thing I want to do with feeds that SimplePie doesn’t support: Trimming output. It’s easy enough if you plan on stripping all markup from the output, but it gets trickier if you want to keep it. This feature is planned for the 2.0 release, which may or may not have to do with the “approximately 100 Jillion-Kabillion-Bazillion support questions” on the subject. (Now that’s a user base!)

Needing a solution that would work in the interim, I searched the Internet for a while and found an interesting function to truncate text and keep the HTML by Jonas Raoni Soares Silva. It worked well given good input, but it inserted extra end tags when the input contained improperly nested tags or missing end tags inside correctly paired tags.

Figuring that the last thing I need is a bunch of rogue </div> end tags breaking my layout, I decided to see if I could come up with something on my own. Here’s what I came up with:

function trim_html($string, $length = null, $suffix = '&hellip;'){

	// Trim the string to $length--if necessary (i.e. if a number given for $length).
	if (is_numeric($length)){
		$string = substr($string, 0, $length); // Get only first $length characters of $string
		$string .= $suffix; // If trimming, add the ellipsis or other specified suffix.
	} // endif 
	
	// Next, create a DOM document from the trimmed string.
	// The DOMDocument will correct any errors when loading the HTML.
	$dom = new DOMDocument();
	@$dom->loadHTML($string); // This can produce lots of warnings, so ignore errors.
	$string = $dom->saveHTML();
	
	// Remove the extra HTML added by saveHTML.
	$string = preg_replace('/^.*<body[^>]*>/is', '', $string);
	$string = preg_replace('/<\/body[^>]*>.*$/is', '', $string); 
	
	return($string);
} // end trim_html()

Of course, there are some issues. (Nothing’s ever easy.) For one thing, the DOMDocument::saveHTML method in recent versions of PHP (5.3.6 and up) lets you pass a DOMNode and get back only “a subset of the document.” I would have liked to try this, as the regular expressions seem hackish to me for some reason. However, my test environment is running 5.3.5, so I can’t test this.

Another issue is that, since a text node can’t be a child of <body>, loadHTML wraps orphaned text nodes in paragraphs. So trim_html('test') would return <p>test</p>. I suppose I could add code to wrap input in a <div> and then tweak the regular expressions to strip those out, should the need arise. For now, the extra paragraphs don’t bother me, so I’ll leave them alone.

Here’s hoping that this is of some use to someone out there. If anyone has any suggestions for improvements, I’d love to hear them.

Categories: Programming Tags: , ,

RSS/Atom parsing: Easy as pie, but only after a simple fix.

September 13, 2011 Comments off

I recently discovered how much I love SimplePie, a PHP class that parses ATOM and RSS feeds. I’ve tried doing it manually in the past, and let me tell you that it’s a pain in the butt.

However, there’s one little issue that makes the pie less simple. This is one of those times when the error message doesn’t relate to the actual error. The message itself was:

This XML document is invalid, likely due to invalid characters. XML error: Mismatched tag at line 156, column 11

But that couldn’t possibly be the actual issue. For one thing, the XML file was only about 50 lines long, so there was no way the error could be on line 156. Besides, it worked perfectly on the W3C’s validator, Windows Live Mail, and even the online SimplePie demo. Weirdest of all, when I saved a local copy of the feed, SimplePie was able to open that just fine.

It turns out that the problem came from a bug in SimplePie: The equals sign (=) and ampersand (&) were being URL-encoded to %3D and %26, respectively. This bug was supposed to be fixed in the 1.2.1-dev version, which I’m using, but somehow the characters only got added to one of the two lines where they were needed.

The end result was that any feed that was automatically generated based on GET data in the URL wouldn’t work. I was testing with a feed from NASDAQ, and the URL was http://www.nasdaq.com/aspxcontent/NasdaqRSS.aspx?data=quotes&symbol=MSFT. When I changed the & and = characters in that url to their encoded values (http://www.nasdaq.com/aspxcontent/NasdaqRSS.aspx?data%3Dquotes%26symbol%3DMSFT), I got this nice custom HTTP 500 error page.

That explains everything: SimplePie messed up the URL, then tried to parse the error page as a feed. Adding the & and = to the appropriate line in simplepie.inc solved the problem.

If you’re working on a PHP script that parses RSS or ATOM feeds, I highly recommend giving SimplePie a try. This bug will probably be fixed soon, and in the mean time, adding two characters to one line of code is way easier than trying to write your own parser.

Categories: Programming Tags: ,

Table-less Forms: They Are Really That Hard.

September 7, 2011 Comments off

A couple weeks ago, I posted a list of criteria for what I’d like to see in a CSS-based form that emulated the nifty features that tables provided. To recap, I wanted:

  • Labels lined up in the same row as form fields
  • Label column that stretches/shrinks to the size of the longest label
  • As little extra HTML as possible

The good news: I quickly came up with a solution that met all my criteria. The bad news: It only works with simple forms. (“I quickly came up with a solution” should have been a tip-off!) First, I’ll explain what I did, and then I’ll explain why it can’t handle much complexity.
My solution was to nest the inputs I wanted to align inside a div, style the div so it would shrink to the width of its contents, and then use absolute positioning on the inputs (nested inside relative-positioned s) to push them to the left by 100% of the width of the div.

If it sounds too easy, that’s because it is. Here’s what doesn’t work:

  1. It only works with inputs that are the same height as the labels, which means it won’t work with s, multiple-row s, and probably others I’m forgetting.
  2. Checkboxes and radio buttons inside the wrapper div can’t be put before their labels because the positioning automatically puts the inputs on the right.
  3. Longer labels, such as you might need to ue for checkboxes and radio buttons, will stretch the wrapper
    ‘s width.
  4. Those last two aren’t problematic if you can group all your text inputs together and save everything else for the end. If you want to put anything between two groups of text inputs, though, you’ll need two separate wrapper
    s, which won’t line up with each other.

I will post the code as soon as I can get it cleaned up and looking nice. (My test code is embarrassingly messy.) I also plan to revisit this project and see what fixes I can make. The checkbox problem at number 2 shouldn’t be too hard to solve. Then again, that’s what I said about CSS forms in general.

Categories: HTML