11 Jan 2011Today, I thought my current project was finished. But I had this bug report in my tracker from one of the beta-tester telling me that one of the page wasn't rendered properly.
It says that the code source was displayed on screen instead of being rendered as HTML. And only on Firefox.
And if that wasn't odd enough, even with the plethora of Firefox versions I got, I couldn't reproduce the bug on my side.
Turning off the debugger to debug
Then I had an idea. I turned off the debug mode, and was then able to reproduce the infamous bug.
As I initially supposed, there was something wrong with the Content-Type header. The Firebug Net Panel told me that it was set as text/plain while the developer toolbar insisted that it was text/html.
After some digging in my own code, I found the culprit. A requestAction() call I made as part of an update process. This requestActionwas targeted at a .txt file.
I played a little with the debug value and found that for any value above 2, everything was working correctly, but if I set my value below that threshold, my whole view will get displayed as text/plain.
I couldn't quite explain why a debug value will have anything to with the view rendering. I even disabled the Debug Kit component, just to be sure.
Digging into cake world
And then I decided to follow the dispatch trace to find where the debug value was being used. After a long journey, I got to the respondAsmethod of the RequestHandlercomponent.
And specifically, to that part :
if (Configure::read() < 2 && !defined('CAKEPHP_SHELL')) {
$this->_header($header);
}
Ok, so there was my debug value. Exactly the code reponsible for my symptoms. Well, I still don't understand WHY someone wanted to add an header based on the debug value, but I could easily understand HOW it made my view that ugly.
The requestActionwas being dispatched all along the way to its final action, firing the RequestHandlercomponent on its way. Its extension being .txt, RequestHandlerwill fire its respondAs method and set the appropriate header.
Unfortunatly, setting such an header in a requestActionwasn't useful for the request, and additionnaly, it was messing with the primary view dispatch path.
Solution
Ireported the bug hoping for a fix in a future version. For the time being, I manually set the debug to 2 before calling my requestAction, and set it back to its previous value after in my app.
And for why it was only buggy on Firefox, it was caused by a double header definition. A first header was telling text/plain and a second onetext/html. I guess Firefox uses the first one while other browsers the last. This is what made Firebug and the Developer Toolbar return different results too.
10 Jan 2011Did you know that when debugging RewriteRules, instead of commenting/uncommenting each line, you can simply make RewriteEngine On / RewriteEngine Off all along your code ?
I didn't, and now that I do it seems so obvious I don't believe I've never thought of that before...
07 Jan 2011IE8 has a strange bug (what bugs aren't strange in IE ?) when dealing with :after and :before pseudo-elements.
I was adding a nice looking arrow after one of my elements using :after. I wanted this arrow to only display when my element was hovered, so I wrote the following code :
a {
position:relative;
display:block;
height:30px;
}
a:after {
position:absolute;
content:"";
top:0px;
right:-15px;
width:15px;
height:30px;
background:url(arrow.gif) top left no-repeat;
display:none;
}
a:hover:after {
display:block;
}
As you can see, nothing too fancy. I positionned my arrow using an empty :after element and a backgroundimage. I defaulted the arrow to hidden, and only show it when hovering the element.
IE in action
It does work pretty well in moder browsers. It also seems to work on IE8. When you hover the element in IE8, the arrow gets displayed. But it does not gets hidden when you stop hovering it.
There's a kind of ghost element that keeps getting displayed. It gets removed if you directly mouse it, or scroll your page, or alt-tab, etc. This clearly is a display artefact.
To counter this I had to write it in an other fashion (less readable in my opinion). Removing the default a:after rule and adding all properties to a:hover:after :
a {
position:relative;
display:block;
height:30px;
}
a:hover:after {
position:absolute;
content:"";
top:0px;
right:-15px;
width:15px;
height:30px;
background:url(arrow.gif) top left no-repeat;
display:block;
}
Update
It should be noted that more generally, I gets confused and create ghost elements and styling when we try to update the :after/:before properties based on a rule selecting its parent.
There seems to have a little lag/delay before the properties gets applied, and most of the time they do not.
06 Jan 2011I often use $this->cakeError('error404') in my controllers to stop processing the request (and return a 404 error) when the supplied parameters are buggy or incomplete.
A strange side effect
I recently spotted a strange side effect on the latest site I was developping. It used a pretty large html footer filled with links dynamically fetched from my database.
As all pages (no matter what model/controller they were refering to) were using the same footer, I created a component with a simple startup method to fetch them all and return them to the view. I added this component to my AppController so that every controller will inherit it.
This worked nicely until I spotted that on error pages, the footer was left mostly empty. I was because my Component callback was never fired.
How's that ?
When detecting an error, cake starts using its ErrorHandlerand thus do not fire callbacks.
Fortunatly, you can create an AppErrorclass (in app/app_error.php) and overwrite the ErrorHandlermethod. Namely, the error404. I rewrote mine to explicitly fire the initialize and startup methods.
class AppError extends ErrorHandler {
function error404($params) {
$this->controller->Component->initialize($this->controller);
$this->controller->Component->startup($this->controller);
parent::error404($params);
}
}
I only fired two of the callbacks, but maybe beforeRenderand shutdownshould be fired too.
04 Jan 2011As you may have heard, Yahoo! is closing Delicious. I had started to use Delicious a lot lately, to work as a decentralised save of all my bookmarks and being able to search through them easily.
In my recent attempt to save as much of my work online, losing Delicious would meant losing a large part of collective wisdom. So I search for an alternative.
I finally registered for Pinboarda few days ago. It allows an easy way to import Delicious bookmarks in a matter of seconds and has all the features of Delicious I wanted.
It is not free however, but the one-time fee depends on the number of people using the service. I payed mine 9.12$.
The website itself is not as good looking as Delicious (ahem), but it does provide a cleaner search experience (in my point of view). I really don't care about other people bookmark, I only search through mine.