I recently got an odd bug report for the ModalBox project: Modalbox used to appear with the wrong positioning. The modal window was sliding down not in the center, but from the left or right side of the window (depending on browser used). So I started investigating the issue.
The Problem
Since ModalBox has unit-tests now I asked the person who reported the issue to run them first to be sure he’s using compatible prototype and script.aculo.us libraries. The tests passed successfully. Weird!
I looked into the HTML source where the issue appeared and noticed there was also a lightbox.js — another JavaScript library for creating neat popups. After excluding Lightbox from the HTML source ModalBox started to work perfectly. The issue was localized at last. Cool!
Digging the latest Lightbox (2.03.3) sources I found these lines of code:
Object.extend(Element, {
getWidth: function(element) {
element = $(element);
return element.offsetWidth;
},
...
To feel the difference here is the original getWidth and getDimensions methods from prototype 1.5.1:
getWidth: function(element) {
return $(element).getDimensions().width;
},
getDimensions: function(element) {
element = $(element);
var display = $(element).getStyle('display');
if (display != 'none' && display != null) // Safari bug
return {width: element.offsetWidth, height: element.offsetHeight};
// All *Width and *Height properties give 0 on elements with display none,
// so enable the element temporarily
var els = element.style;
var originalVisibility = els.visibility;
var originalPosition = els.position;
var originalDisplay = els.display;
els.visibility = 'hidden';
els.position = 'absolute';
els.display = 'block';
var originalWidth = element.clientWidth;
var originalHeight = element.clientHeight;
els.display = originalDisplay;
els.position = originalPosition;
els.visibility = originalVisibility;
return {width: originalWidth, height: originalHeight};
}
As you can see, the original method handles the case when the element is not visible at the time of calling the getWidth method. It’s very useful when you need to calculate the dimensions of the element before showing it. ModalBox relies on this technique as well.
Bad design
For sure, Object.extend is a very useful way to override existing methods with your own ones. But shouldn’t it be used with care? To me it’s a good example of bad design as well. Thinking that developers will use only one (and only your own) JavaScript component seems stupid to me these days. Overriding some basic methods is very dangerous practice. This particular example just demonstrated why.
Conclusion
Be aware of using prototype’s Object.extend method without keeping in mind the rest of the world. Mostly, people rely on how each particular framework is working. Silently overriding a framework’s core functionality isn't a good programming practice.