May 13, 2010 | How-To: Hack LightboxThumbs Extension for MediaWiki
Topics: Battlestar Galactica,How-To,Programming,g33k | Tags: CSS, hacks, JS, Lightbox, MediaWiki, PHP
As with most everything that is released for MediaWiki or WordPress, I invariably have to modify it to suit the needs of the projects I work on. I find that nothing works quite right “out of the box.” In the interests of people who run into this same issues, I’ve decided on a new track for my website (in addition to just being a general place to vent, sorry!) where I tell you how I frakking fix things. Hopefully, this will help some hapless bloke who faces similar problems with extensions and programs that I run into as well—and who knows, I may just need your help someday. Scared yet?
The extension I had to hack is called LightboxThumbs, and it adds the “lightbox” effect to images that are thumbnailed or added to a gallery on a MediaWiki-run website. In this case, this was for Battlestar Wiki. Typically, whenever you clicked on an image on a Wiki, it would simply lead you to another page called an “image description page,” which contains information about the image in question, in addition to the image itself. For most end-users, that sucks as they want to see a larger version of the image. Ergo, this extension satisfies that need.
In any event, there are two issues I ran into when running this program.
- Any links defined in the caption text of any image in a gallery would not parse correctly.
- Images that have dimensions that are larger than your screen resolution (say, 1200 x 800) would not resize.
So I had to whip up a few dirty hacks to address these issues. Let’s start with issue number 1—and the following assumptions:
- That you’ve already installed the extension per the instructions on that page.
- That you’re running MediaWiki 1.15.
1. The Gallery Caption Text Issue (and the Want of Trying to Call it Something Better)
If you have galleries on the articles in your wiki (like this article here on William Adama at the Battlestar Wiki), then when you install the extension you may run into this problem.
Yeah, I think you see that problem. You’re not able to click on the images that have this problem—except, as you’ll see, the one on the middle is clickable—and logic does suggest that it has something to do with the links. (That’s indeed the case.)
So I decide to click on the center image image, and then use the “next” and “previous” arrows to navigate the gallery. Doing so, I see this in the first image of the gallery:
… and, indeed, this is the case with other captions that have links!
So I decide to check out the source code that the browser reads. Here’s the snippet of the offending markup:
Now the way this Lightbox extension works is that it reads the “title” attribute of <a> tag. As you can see, the syntax is broken and it’s because of the use of the quotation mark (“) and the fact that it’s trying to insert the hyperlink code again. So we have an issue where the browser is trying to parse the tags, but fail to realize that it should stay within that “title” attribute. You see, browsers aren’t that smart, and so we have to nip this in the bud.
Come to find out that the code generating this syntax is located in LightboxThumbs.php, and the offending code is on line 67, as seen below:
function efRewriteGalleryImage($matches)
{
## see comments in second $pattern in efBeforePageDisplay() for what the pieces of $matches are
global $wgOut, $lightboxThumbsDebug;
$titleObj = Title::newFromText(rawurldecode($matches[2]));
$image = wfFindFile($titleObj,false,false,true);
return $matches[1].' href="'.$image->getURL().'" class="image" rel="lightbox[gallery]" title="'
.$matches[4]
.'" '.$matches[3].$matches[4]."</div>"
.($lightboxThumbsDebug?efDebugVar('$matches',$matches).efDebugVar('$titleObj',$titleObj).efDebugVar('$image',$image):'');
}
After some research, it’s “matches[4]” that gives us the problem; the fourth array of the variable “matches” contains the caption of the image. The issue is that none of the HTML tags are stripped, nor are the offending quotation marks, so we need to fix that by adding the htmlspecialchars and strip_tags functions (built into PHP, so we don’t need to define them) to that variable, as you see below.
function efRewriteGalleryImage($matches)
{
## see comments in second $pattern in efBeforePageDisplay() for what the pieces of $matches are
global $wgOut, $lightboxThumbsDebug;
$titleObj = Title::newFromText(rawurldecode($matches[2]));
$image = wfFindFile($titleObj,false,false,true);
return $matches[1].' href="'.$image->getURL().'" class="image" rel="lightbox[gallery]" title="'
.htmlspecialchars(strip_tags($matches[4]))
.'" '.$matches[3].$matches[4]."</div>"
.($lightboxThumbsDebug?efDebugVar('$matches',$matches).efDebugVar('$titleObj',$titleObj).efDebugVar('$image',$image):'');
}
So that fixes that problem! It’s the easiest problem I came across, once I found the variable and fixed it accordingly.
Images that Won’t Fit to Screen…
This deals with resizing the dimensions of images that simply go beyond the size of your screen, forcing you to vertically and horizontally scroll to see the image. (And really, who wants that?)
This is the trickier one, and it took some doing. I’m vaguely satisfied with it, but it has its flaws. I know that, and now that I’ve told you that it does, you’ll proceed at your own risk. (And I hope that someone will be able to provide solutions. Hint frakking hint.)
In the lightbox.js file under the lightbox/js folder, you’ll find the following starting at line 261:
imgPreloader.onload = (function(){
this.lightboxImage.src = this.imageArray[this.activeImage][0];
this.resizeImageContainer(imgPreloader.width, imgPreloader.height);
}).bind(this);
imgPreloader.src = this.imageArray[this.activeImage][0];
This deals with resizing the image container, which is the div box that contains the image… not the image itself, which we’ll get to later. Basically, this fancy piece of code dynamically resizes the container depending on the size of the picture, and to do that it grabs the size of the image… Which we don’t want to do in the case of larger images, since it creates a box that is the same size as the large image; and after we resize the image itself, we want the box to fit snugly around that. Ok?
So we have to add these three lines of code.
imgPreloader.onload = (function(){
this.lightboxImage.src = this.imageArray[this.activeImage][0];
if (imgPreloader.width > 1000) { var imgW = 1000; } else { var imgW = imgPreloader.width; } ;
if (imgPreloader.height > 600) { var imgH = 600; } else { var imgH = imgPreloader.height; } ;
this.resizeImageContainer(imgW, imgH);
}).bind(this);
imgPreloader.src = this.imageArray[this.activeImage][0];
As you can surmise, I operated on the concept that most people are sensible and use a screen resolution of 1200 x 800. Therefore, if the image is more than 1000 pixels in width, I define the container width attribute to a solid “1000.” The same goes for the height: if it’s over 600 pixels high, I force the container height to “600.” (Also, the browser screen real estate will be affected by the presence of toolbars and the all important “URL” bar, in addition to a status bar at the bottom, so the usable space available for the webpage itself is far less.) As you can see, if the image is smaller than those dimensions, I simply keep the height and width the same.
Now that we have that out of the way, we need to tackle the actual image itself. Fortunately, this is a simple CSS hack.
You’ll need to change the following lines in the lightbox.css file under lightbox/css:
#lightbox{ position: absolute; left: 0; width: 100%; z-index: 100; text-align: center; line-height: 0;}
#lightbox img{ width: auto; height: auto; max-width: 1000px; max-height: 600px;}
#lightbox a img{ border: none; }
This forces any larger image to be resized at 1000px in width (should it be wider than 1000px), or 600px in width (should it be wider than that). Aspect ratios will be kept, so there should be no distortion of the image. It will not touch images that are smaller than those dimensions, which is why I used the max-width and max-height attributes.
#imageDataContainer{ font: 10px Verdana, Helvetica, sans-serif; background-color: #471919; margin: 0 auto; line-height: 1.4em; overflow: auto; width: auto;}
The downsides to this method are:
- It doesn’t deal with images that have a large file size. It’s just going to resize the image dimensions so they fit. If this is an issue, and if you have no programming skills to speak of, then the best way would be to resize the offending images in Photoshop or a image manipulation program to reduce their file size.
- On images that are disproportionally wider than taller, you’ll have whitespace between the image and the caption.
That should do it! Any suggestions you can make to this code are more than welcome! Be seeing you!



TwitRSS