28 Jun 2010Gradients are one of the new cool stuff CSS3 brought with it. Like the others cool things, it still suffer from a partial implementation and vendor-specific properties.
It also isn't correctly parsed by CSSTidy. Here I'll show you how to patch your CSSTidy to make it eat gradients correctly.
Quick and dirty patch
First, you'll need to edit the huge parse() method in csstidy.php. You'll have to add a condition to explictly tell CSSTidy not to discard -webkit- gradient and -moz-linear-gradient.
Just open your csstidy.php file, find the parse() method and locate the case 'instr' in the huge switchstatement.
if (!($this->str_char === ')' && in_array($string{$i}, $GLOBALS['csstidy']['whitespace']) && !$this->str_in_str)) {
$this->cur_string .= $temp_add;
} **else {**
** if ($this->sub_value=="-webkit-gradient" || $this->sub_value=="-moz-linear-gradient") {**
** $this->cur_string.=' ';**
** }**
**}**
In bold, the elsepart to add. This will make sure your webkit and firefox gradient rules will get processed correctly.
I don't really understand WHY it work, but it does. The parse()method is a huge uncommented mess, it is quite difficult to understand it. There must be a better way, a more generic one than specifying some properties, but I didn't manage to come with anything better than that.
Fortunatly, the next part is cleaner.
Telling CSSTidy which properties not to merge
If you write a css like the following, only the latest (color:white) rule will get through CSSTidy.
body {
color:red;
color:white;
}
That's logical, because CSSTidy will remove any unused CSS declaration. Unfortunatly, this is not what we want, because we need to declare several background: rules, one for Webkit, and one for Firefox.
By looking at CSSTidy source code, we can find that it contain a quick fix to allow the cursor: property to be defined several time (to cope with the old cursor:pointer / cursor:hand issue).
I just extended this quick fix to work for other properties as well, and even managed to allow them to be passed as a config value.
Defining the config value
First, open the csstidy.php file, and around line 310 you should find a list of default config values. Just add the following :
$this->settings['multiple_properties'] = array('cursor', 'background');
This will define the default list of properties that are allowed to be defined several times in a css rule.
Next, we'll edit the set_cfg() method to allow the passing of array values. Just replace the else statement with this one :
else if(isset($this->settings[$setting]) && $value !== '') {
// Merging array settings
if (is_array($value) && is_array($this->settings[$setting])) {
$this->settings[$setting] = array_merge($this->settings[$setting], $value);
} else {
// Setting classic setting
$this->settings[$setting] = $value;
}
if ($setting === 'template') {
$this->_load_template($this->settings['template']);
}
return true;
}
You can now pass a list of properties to be added to the existing list by calling ->set_cfg('multiple_properties', array('property1', 'property2'));
Now, find the css_add_property() method, and around line 1066, change theif (strtolower($property) == 'cursor')if statement to this more generic one :
if (in_array($property, $this->get_cfg('multiple_properties')))
And now, in csstidy_print.php, find the_print() method, and replace the case PROPERTY block with this (more concise) one :
case PROPERTY:
// Converting back multiple properties
$multipleProperties = $this->parser->get_cfg('multiple_properties');
foreach($multipleProperties as $property) {
$propertyLength = strlen($property);
if (substr($token[1], 0, $propertyLength)==$property) $token[1] = $property;
}
// Applying correct casing
$caseProperties = $this->parser->get_cfg('case_properties');
if ($caseProperties==2) $token[1] = strtoupper($token[1]);
if ($caseProperties==1) $token[1] = strtolower($token[1]);
$out .= $template[4] . $this->_htmlsp($token[1], $plain) . ':' . $template[5];
break;
And that's it
You now can have gradients compressed with CSSTidy. Well sort of, because this is just a quick and dirty patch, as I'm not the creator of CSSTidy.
This could surely be improved in a less hacky way, for example by compressing the color code used in the gradients...
25 Jun 2010On July 21st will be held an informal meeting in Paris for all the web developers that have an interest in web performance.
Eric Daspet and Stoyan Stefanov will be there and host a talk about performance impact on sales and some more technical less known facts.
The first part will be in French while Stoyan's will be in English. If you have the chance to be in Paris in July, do not miss this event.
I will, of course, be there. Eric Daspet is the french "gourou" on web performances, and Stoyan Stefanov is one of the main author of the Smushit plugin/websit.
Web performance is a really interesting subject where there is so much to learn and so much to try.
14 Jun 2010My spam protection is really simple. Most spam bots will fill all input fields they'll find in a form. If one is named website or email, they will most certainly want to fill them first.
So I've added to every form a fake input field with a name="email"that have to stay empty. I also labeled it "Spam bait" and displayed a little sentence to tell my human readers to keep this field empty.
I also hide the whole field using Javascript because most of the bots don't have Javascript enabled, but legitimate users do.
Does it work ?
To say the truth I don't know. In the previous version of this website I haven't any kind of spam protection and was receinving almost a dozen spam mails a day.
Now that I've added this protection, I don't receive spam anymore. But that doesn't mean my protection is working, it may just mean that the spam bots needs a little time to adjust to the new website.
Improving the existing
One week ago, two spam comments managed to get past my protection. I have currently no way to judge my protection efficiency. Maybe that was the only two spam comments aimed at my website and I let them both slip in. Maybe I was under a mass attack and managed to block thousand of spam and those two were the only two to beat me.
I don't know, I have absolutly no numbers on that.
Getting some stats
So today, I decided to add some extra measures. I'm keeping count of every spam I block (this number will be displayed below the comment list if at least one spam was blocked).
I'll also log some informations when someone is posting a comment : headers sent, if javascript is enabled and the delay between displaying the form and submitting it.
It is useless to build protection if you don't know what you want to be protected against. So I'll let the actual protection in place and will come back to check the numbers in a couple of weeks.
I'll then know exactly how performs my existing spam protection and will be able to extract spam patterns from the information I'll gather.
I think I'll add a timing system, to block comments that were posted too fast. If nothing works I'll use Akismet, but I want to try to defeat them on my own first.
10 Jun 2010Recently, when connecting to my MySQL databases on Dreamhost through Navicat, I was greeted with a "1577 - Cannot proceed because system tables used by Event Scheduler were found damaged at server start" error message.
It didn't stop me from accessing the tables actually, so I didn't bother. But today it prevent me from copying tables from one server to another, so I decided to have a deeper look into it.
It seems that it has to do with a mysql upgrade issue. I contacted Dreamhost about that and they told me that they just upgraded their servers to 5.1, and that they needed to be restarted. Which they do for me.
So if you ever run into the same problem, just contact Dreamhost support and they'll fix it for you.
10 Jun 2010I recently bought an HTC Legend. My old phone was broken and I have plans to develop an Android app. I've been using the phone for 3 weeks now, and I'm not exactly as thrilled about it as I think I would.
Open source from Big Brother
I was hoping to have a little piece of open source software in my pocket. In fact, it turns out that Google has a little more piece of me when I'm using the phone.
The software is not that open. Maybe it's because of my phone carrier, SFR, but there are a lot of pre-installed and useless apps that I can't get rid of.
Some settings can't even be changed because I'm only a user of my own phone and don't have a root access by default. The "Accessibility" setting panel is a joke (I'll post a picture of it later)
When I first switched the phone on, I was asked for my Google credentials. Once entered, all my Google life was downloaded to the phone : mail address book, google maps location and google calendar meetings. Asking first if I wanted that would have been great.
Because loading 500+ mails address book into a phone memory is not the kind of "smart" I was expecting from a smart phone. I had to manually remove all the contacts I needed not from my phone.
And then the phone was complaining again, when it tried to synchronize back with Gmail, when it tried to remove the mails from my online address book.
I didn't want them downloaded in the first place and once I removed them I didn't want them to be deleted from my online address book !
Disabling sync
So I tried to remove the google account from my phone, but that is clearly impossible and is NEEDED to make the phone work. What ? This is stupid.
I'm not confortable with having a device from which I can't even remove my credentials... At least I disabled the auto-sync feeature.
An other thing to note is that if you want to fine-tune what kind of data your phone syncs, you first have to enable the auto-sync feature and quickly disable the data you don't want, because they all are checked by default.
Other settings
Even changing the default ringtone is a chore. There's no way to easily select a music file saved on the SD card. There isn't even a native file explorer, you have to download one from the Market.
The camera quality isn't very good and the auto-focus makes pictures more blurry with it than without. Even my old Nokia XpressMusic was taking better shots.
Conclusion
I really am disapointed by this phone actually, and by the Android platform as a whole. Maybe the underlying app is great but as an end-user we are blocked from it.
I'll try to root my device and remove the SFR rom to get what I want and need.