jqTOC 1.1 Release Notes

It's been a while since I did anything with jqTOC, a jQuery plugin I wrote 3 years ago that generates a table of contents for a page. Time seems to have treated it well. At some point though the ability to show multiple TOCs broke, and that meant the demo didn't work. Not a very good advertisement for potential users.

This latest revision fixes the problem, and so it's now possible to generate more than one TOC on a page. For instance, if you had separate containers within your page, that you want separate table of contents for. The fix involved a minor change to to the CSS, so if you happen to be upgrading from an earlier version, then you need to update your CSS to reference toc_header and toc_content as classes, not IDs.

Speeding up BlogIt by caching files with ExpiresByType

The recent 1.4.0 version of BlogIt adds a bunch of user-interface fancies, and Ajax goodies. The cost of doing this was the addition of jQuery, jQuery-UI, and a couple of jQuery libraries, all weighing in at over 100k. Unfortunately, depending on how your host is configured, this might make BlogIt driven sites load a little slower.

One way to minimize the effect of this is to force your visitors browser to cache javascript, css, and image files, by adding future expiry headers. This won't affect the load speed the first time visitors hit your site, but it will help for subsequent loads by that visitor. If you host uses Apache, and have the mod_expires module loaded, then you can use the ExpiresByType directive to set an expiration date relative to the current date.
Read more...

Redux: Set IFRAME height based on size of remotely loaded content

Shortly after writing a quick guide on how to set IFRAME height based on size of remotely loaded content an error came to light where Chrome and Firefox would either keep growing the iframe with after each load, or would set the iframe too large if subsequent content was shorter than the initial content.

I wasn't able to determine the exact cause of the problem, but I implemented a work around which cured the problem. I've extracted the core code as a template to resolve the problem. Basically we call a function periodically, and try to see if the IFRAME height remains constant. If it does, then assume it's stopped changing, and call the local resizing function with the hopefully correct height.

REMOTE.COM/REMOTE.HTML

var IFRAME={};
function isHeightStatic(h, x){
	IFRAME.resizeHeight[IFRAME.resizeHeight.length] = h;

	// Test to see if h has changed over last x iterations.
	for (var i=IFRAME.resizeHeight.length-1; i >= IFRAME.resizeHeight.length-x; i--)  // don't test last element, as we just added it
		if (i < 0 || IFRAME.resizeHeight[i]!=h) return false;  //value is or may still be changing
	return true;
}
function iframeResizePipe(){
	// noticable when subsequent content is shorter.
	//var height = jQuery(document.body).height();
	var height = document.body.parentNode.scrollHeight;
	var heightStatic = isHeightStatic(height,4);  //same height for 1 second? (4 * 250ms)
	if (IFRAME.resizeHeight.length>48 || heightStatic) //Iterate 50 times at 250ms delay = 12 seconds load time
		clearInterval(IFRAME.resizeTimer);

	if (!heightStatic){
		// Going to 'pipe' the data to the parent through the helpframe..
		var pipe = document.getElementById('helpframe');
		if ( pipe == undefined ) return;
		// Cachebuster a precaution here to stop browser caching interfering
		pipe.src = 'http://local.com/helper.html?height='+height+'&cacheb='+Math.random();
	}
}
jQuery(document.body).ready( function(){
	// Ready event seems to trigger before remote images are loaded. When images don't speficy height,
	// cause page height to be calculated wrongly (from Larger Images).
	// So ping every 250ms to see if the height has increase, and reset the iframe size.
	IFRAME.resizeTimer = setInterval('iframeResizePipe()', 250);
});

NOTE: Code extracted from working code, based around jQuery, which has been commented out, with the exception of the onload handler which is performed by jQuery above.

Hope this helps a little at least.

BlogIt Release 1.4.0

This is the start of improving the BlogIt user interface, and making the admin workflow smoother. Many of the typical admin functions now use Ajax, which allows an action to take place without having to reload the page. That means rather than clicking to approve a comment, and waiting a few seconds for the page to reload, the approval is 'immediate! So, approving, unapproving, and deleting comments now happens instantaneously. You click the delete comment link, and it will disappear before your very eyes.

Read more...

BlogIt progress, Ajax on the way

Just a quick note to let you know that progress on the next version of Blogit is going well. As promised we've got some Ajax goodies in this release. As an initial dive, many admin functions are now ajaxified:

  • Approving and unapproving comments is near immediate, as is deleting comments -- no waiting for the page to reload. Click and it's done.
  • Blocking commenter IP addresses is another tool in the fight against spam. Add commenter IP addresses to the BlockList with a direct link -- that's ajax as well.
  • Field validations are now done client-side, which means you get to see the error submitting the page. Much nicer.
  • Ever lost some work by clicking Cancel, or Back in error? Now you'll get a message verifying whether you want to loose your hard written work.

All with a nice shiny look. Of course all existing bugs have been quelled, squashed, and removed. Check out the BlogIt Known Issues list for a full account of what's changing.

A little more testing and we should be done. In the meantime take a look over on the BlogIt test blog for a feel of what's coming.

Blix: PmWiki skin conversion

Blix is one of the more popular skins I've ported over from other systems. It's pretty flexible, and gets used as a foundation for some adaptions. That, and it's pretty colorful by default, but can be muted down pretty easily.


Check for a valid date in PHP, redux

Update 31-Jul-2010: Check out the updated version for a slightly more concise function.

This is an updated PHP based date validator, correcting some issues with the original version. An additional parameter has been added specifying the expected format of the date, using PHP date expressions.

function bi_IsDate($d, $f='%d-%m-%Y %H:%M'){
	if (empty($d))  return true;

	#Convert Unix timestamp to a std format (must not include regular expressions)
	if (preg_match('!\d{5,}!',$d))
		$d=strftime($f,$d);

	$re_day='%d|%e';
	$re_month='%m';
	$re_year='%g|%G|%y|%Y';
	$re_sep='[\/\-\.]';
	$re = array(
		'/'.$re_day.'/' => '(0?[1-9]|[12][0-9]|3[01])',
		'/'.$re_month.'/' => '(0?[1-9]|1[012])',
		'/'.$re_year.'/' => '(19\d\d|20\d\d)',
		'/%H|%I|%l/' => '([0-1]?\d|2[0-3])',
		'/%M/' => '([0-5]\d)'
	);

	$re_date = preg_replace(
		array_keys($re), 
		array_values($re), 
		$f);  #convert $f into a regular expression

	#does %d match the regular expression version of $f?
	if (preg_match('!^'.$re_date.'$!',$d,$x)  
		#determine expected date order based on $f and checkdate
		&& ((preg_match(
				'!^('.$re_day.')' .$re_sep .'('.$re_month.')' .$re_sep .'('.$re_year.')!',$f) 
				&& checkdate($x[2], $x[1], $x[3]))
			|| (preg_match(
				'!^('.$re_month.')' .$re_sep .'('.$re_day.')' .$re_sep .'('.$re_year.')!',$f) 
				&& checkdate($x[1], $x[2], $x[3]))
			|| (preg_match(
				'!^('.$re_year.')' .$re_sep .'('.$re_month.')' .$re_sep. '('.$re_day.')!',$f) 
				&& checkdate($x[3], $x[1], $x[2]))
	))  return true;
	return false;
}

BlogIt Release 1.3.0

The main new user feature in this release is the new UI for comment editing. The UI basically re-uses the exiting comment entry form, but exposes fields that would normally be hidden to the average user; as such it required very few lines of code. This is a good thing. As a general goal I'm trying to keep the size of BlogIt small, primarily to keep the entry barrier low for new contributors, and partly to keep maintenance overheads low.

Most other changes were developer oriented, aimed at grouping similar variables together into arrays, which hopefully makes things a little easier to read. One change I did make was to update the date validation routine. This has been flaky for a while, and I finally broke down and took a different approach to the validation. This version should allow for a little more variation in the date formats, as well as handling international formats a little better.

Next release will be a little more user oriented, and should see some Ajax goodness.

BlogIt RSS Feeds

Adding an RSS feed to my blogs has been on my todo list for a while now, but I just haven't made the time. Thankfully others have had the time, and managed to provide some good guidance on how how to set up an RSS feed for BlogIt, and in using BlogIt in general. Before the next BlogIt? release I'll give this a go. Thanks Trevor.

BlogIt Maintenance Release 1.2.2

Maintenance release 1.2.2 of BlogIt many of the day to day bugs found over the past 8 weeks or so since the last release. None of the bugs are critical, but it's worth upgrading, particularly if you tend to use apostrophes in your titles.

In addition to the help from prior contributor SteP who provided some code fixes, we also saw some additional participation from Peter Kay who as a first time BlogIt user managed to find some pretty interesting bugs, including the apostrophe issue, and a problem where non-BlogIt links in the sidebar were incorrectly rendered with hyphens. Thanks Peter.

Hopefully as BlogIt matures we'll start to see increasingly broader involvement from the PmWiki community. One day we might even get us a code review.