Fix blinking text issue in Firefox

I wish there was only one browser, which may make Web Developer’s life easier. But I know without compteting, we may be still using IE6 (A Terrible Browser.)

Anyway, the problem I had this time is a CSS issue in Firefox. The same code works fine in Chrome and IE (although, IE is a different in this case. I will explain this at the end.)

Issue

We have a hoveover dropdown div on the top of big carousel banners div. The transition of carousel is set to fade-in and fade-out by changing wrapper div’s opacity. We found that the text on the dropdown div is blinking as the background carousel is rotating, which is happened in Firefox 13.0.1 (probably the lower version, too.) But it works fine in Chrome and IE.

Why

The css settings of wrapping div was like the following,

.wrapper {
    display: inline-block;
    height: 270px;
    left: 0;
    margin: 0 auto;
    overflow: hidden;
    position: absolute;
    top: 0;
    width: 984px;
}

And there is a jQuery function to perform an animation on wrapper div during the transistion of carousel, like the following,

 $('.wrapper').animate(
	{ opacity: '0.2'}, 
        1500, 
       "swing", 
        function () {
	//some functions;
        }
 );

As you see, in the CSS settings of wrapper div, we did not set z-index. Although the z-index of dropdown div was already set to 12, somehow, the texts in the dropdown div is still affected when the background’s opacity changes.

Solution

The solution is actually very simple. We just need to implicitly set z-index of wrapper div to whatever number that is lower than 12 (in our case, 12 is the value of z-index of the dropdown div.) So the dropdown div and the text on it, are implicitly sitting on the top of carousel div. This fixs the text blinking issue in Firefox when the opacity of background div changes.

Final Note

As I said in the beginning of this article, IE is different in this case. That’s because, IE8 and below does not support “opacity” navtively. jQuery’s animation function must handle opacity differently, which does not cause the issue we had.

I set a cookie but cannot retrieve it

This may be another stupid question, it bugged me a long time ago. I have not seen anyone mentioning this anywhere, perhaps it’s too obviously, but I think it’s worth to mention, especially for a newbie.

When you set a cookie in PHP, you cannot retrieve it right away, for example,

setcookie("user", "John Doe", time()+3600);
if (isset($_COOKIE["user"]))
  echo "Welcome " . $_COOKIE["user"] . "!
"; else echo "Welcome guest!
";

When you run this code in your browser at the first time, you will see “Welcome guest!”. You may think that we already set cookie before checking cookie, and cookie should be ready. But note that cookie is something saved in user’s computer, setcookie() function just sends the command, but cookie will not be created until the page loaded. So you can only retrieve the cookie in next PHP process (or the second page load.)

Easy? Good just skip this. Hopefully, I will bring some hard questions next time.

Get mangled content from jQuery .html()

jQery .html() can be used to get the contents of any element in html document. I just found that .html() does not return the exactly same content of selected element. The following are two examples,

& is replaced with &

& is replaced with & in URLs. This is not a bad thing, actually, I just learned that to avoid problems with both validators and browsers, we should always use & in place of & when writing URLs in HTML, so then if you have parameter named copy,  for example, &copy=3, then it will not be translated to ©=3 in some browsers. (Read this article for details)

URL is encoded in Firefox

I found jQuery .html() returns URL encoded contents in Firefox (By this time, I only test this in Firefox 13.0.1.) For example, if the content contains

<a href="http://www.caiapps.com/?abc=!^{}<>">special</a>

in Firefox, .html() will return the following result,

<a href="http://www.caiapps.com/?abc=%21%5E%7B%7D%3C%3E">special</a>

Not sure this is a bug of Firefox, or something need to be fixed in jQuery library, .html() doesn’t encode URL in Chrome and IE. This may not cause issue in most case, but in my case, I use html() to generate some dynamic content, which including some tags like, {$abc}, if it’s mangled, then it will be replaced with correct content. So I have to decode url in the content got from .html() using unescape() function as the following,

var escaped_html = unescape($(this).html())

If you also want to keep & untouched, then you will have to use regexp, because unescape() does not replace &amp to &. It will be like the following,

var full_escaped_html = unescape($(this).html()).replace(/\&/g, "&");

Hope this helps.

MySql index is very important

In a project, we need to import data from a plain file into database and the file has about 55,000 rows.
What the script does is looping throught 55,000 rows, for each row, check the search term that is in the database table or not, if yes, update it, if not, insert it.

The script was running fine for a while, but some day we found that the script took more than 10 hours to run. So we check the script. It uses php json_decode(), serialize() when processing the data, but without connecting to the database, it loops quickly. So obviousely, the issue lies in the database part.

We checked the table, which has been growing into about 200,000 rows. As I mentioned, before inserting data, the script queries the search term, the “search_term” column was not indexed, so for 200,000 rows table, the query does not run as fast as you may think. Although for single query, it’s not notiable, but for about 55,000 loops, the different is significant. We added index to the column.

ALTER TABLE `io_search_recs` ADD INDEX ( `search_term` ) 

The perfomance is dramatically changed, See the benchmark below,

55029 loops total run? 89.491609096527 secs
55186 loops total run? 43986.108026981 secs

Some article mentions, “Indexes have some downsides. When you create a new index MySQL builds a separate block of information that needs to be updated every time there are changes made to the table. This means that if you are constantly updating, inserting and removing entries in your table this could have a negative impact on performance.”, but based on our testing, we do not see the downside.

Form is double submitted in IE

Not sure if this is common or stupid. I found that the <button> may cause form being double submitted in IE, if the button type is not set.

For exmaple,

<form id="target" action="edit.php">
    <input type="text" name="w" maxlength="20" placeholder="Enter something ..." />
    <button class="send">Double Submit In IE</button>
</form>

In the above html code, the button’s type is not set, and it defaults to “submit”, so when you click the button, it will submit the form, which is fine. But if you want to bind the click event to this button (may be do something,) and then trigger the form submission, then it may causes the form bening doubled submited in IE. See the Javascript code below.

$(document).ready(function(){
	$('.send').click(function() {
	    //do something ...
            $("#target").submit();
        });
});

Basically, the jQuery can bind multiple envents to a single action, so in this case, jQuery adds additional submit action to the button, it seems works fine in Firefox and Chrome (I think they ignore the second one), but in IE, the form is actually submitted twice, and if the backend action is writing the submitted data into database, then it may cause duplicated entries. In order to prevent this from happening in IE, you have to implicitly set button type to be “button”, like below (It’s wired that <button>’s default type is “submit” not “button”, isn’t it?)

<form id="target" action="edit.php">
    <input type="text" name="w" maxlength="20" placeholder="Enter something ..." />
    <button class="send" type="button">Submit</button>
</form>

Auto generate report for previous month

I was asked to write the script to auto generate monthly report about previous month’s data. Because the script will be ran by cron job, the last month is arbitrary. I have to figure out what the time period of the last month is based on the time the script runs. There are two methods,

Method 1: PHP to get previous month

$m =  date("m", strtotime("-1 month") ) ;
$y =  date("Y", strtotime("-1 month") ) ;
$lastmonth = $y . "/" . $m;

And use the following query,

$sql = "select * from testimonials
         where year(insert_date) = '" . $y . "' and month(insert_date) = '" . $m . "'";

Method 2: Use MySQL function to get previous month

$sql = "select * from testimonials
         where `date` BETWEEN date_format(NOW() - INTERVAL $int MONTH, '%Y-%m-01')
         AND last_day(NOW() - INTERVAL $int MONTH)";

After that, I would need to set up the cron job to run every first Monday in a month. Someone suggested the following cron settings, but it actually runs from day 1st to day 7th in every month regardless it’s monday or not.

0 7 1-7 * * 1 /user/bin/php /var/user/task/sometask.php

So the real solution is,

0 7 1-7 * * [ "$(date '+\%a')" = "Mon" ] && /user/bin/php /var/user/task/sometask.php

How to download file from Github

Github probably the most popular project hosting site in the world. A lot of open source projects are hosted on Github. You may like me often to download open source code from Github. If you are GUI user, then there is no problem to download the source code, but if you are command line user, then you may have a little trouble. Because the download link on Github is not obvious. You can can use wget to download it. Fortunately, there is another handy tool you can use, curl.

You can do the following, it works for both tarball and zipball.

curl -L https://nodeload.github.com/blueimp/jQuery-File-Upload/tarball/master > jquery-file-upload.tar
curl -L https://nodeload.github.com/blueimp/jQuery-File-Upload/zipball/master > jquery-file-upload.zip

If the file is in tar format (tarball), you can even extract the tar file on fly by the following command,

curl -L https://nodeload.github.com/blueimp/jQuery-File-Upload/tarball/master | tar xz

Web user and group settings in nginx+php-fpm env.

I have a VPS box with Nginx and php-fpm installed. It seems to be more stable than another box with Nginx and FastCgi-php installed. Noted that php-fpm is just a FastCGI Process Manager for PHP, so it still uses FastCgi-php.

What Happened

I had one issue, I set Web (nginx process) user/group as “nginx nginx”, and set the web folder’s owner/group as “nginx nginx”.

drwxr-xr-x. 10 nginx nginx      4096  03:18 caiweb

And the mod of sub folders has the same settings. However, when I tried to upload the file to the web folders via web interface, for example, install WordPress Plugin, I got permission denied. Again, my another box with Nginx and FastCgi-php installed with the same settings has no issue at all.

Why

What could that be? Finally, I figured out that there is another web user/group settings at /etc/php-fpm.d/www.conf, both of them were set to “php”. And it overrides the settings in nginx.conf.

Solution

The solution is simple, just need to change user/group settings in “/etc/php-fpm.d/www.conf” to be “nginx” in my case, and restart the php-fpm.

Vanilla Forum “Statistics Permission denied” Error

Recently, I installed Vanilla Forum on one of my sites. Overall, Vanilla Forum is a clean and fast community type forum platform. But there was one issue bugging me for a while. That is the error message of “Analytics: Permission denied – Verification is required, but failed.” pops up on the lower left hand side of the page from time to time. I Googled it, and did find some threads talking about this issues from Vanilla Forum Community. But it seems no one had given a clear answer.

I spent some time to look into the source code, and finally figured out the solution. In short, just need to disable Vanilla Statistics by adding the following line into your installation’s configuration file (conf/config.php):

$Configuration['Garden']['Analytics']['Enabled'] = FALSE;

Is it just that easy? Yes it is. The following are why make it so hard to me,

First, I could not find error string “Permission denied – Verification is required, but failed.” anywhere in the source code, so I did not know where to start to debug this. Finally I found they are using the stand way to show information message on the left lower corner, by which I found this,

 "Gdn::Controller()->InformMessage("Analytics: {$Reason}"); 

in library/core/class.statistics.php. From there, I figured out the error because the registration of Vanilla Forum Statistics failed. The message is from Json Response, that’s why I could not find it in the source code.

Secondly, someone actually mentioned the Vanilla Statistics, but I thought I did not enable it. There are actually two Statistics, one is in the Core (Garden), and the other one is in the Plugins. Not sure if they are the same thing, but one thing for sure is that disabling the plugin one does not turn off the Vanilla Statistics. You have to manually add the above line into your installation’s configuration file. (Looks like they really want us to use this feature.)

Furthermore, someone mentioned that the curl-exec is not enabled. I think this is a misleading. Because, based on source code (library/core/functions.general.php), if it’s curl issue, you will not see “Permission denied – Verification is required, but failed.”, instead see “Encountered an error while making a request to the remote server: Your PHP configuration does not allow curl or fsock requests.”

Finally, I still have not figured out why I cannot register Vanilla API. Is Key wrong? Anyway, I can use Google Analytics instead if I really want.

No gcc on ec2 instance

What I picked is Basic 32-bit Amazon Linux AMI 2011.02.1 Beta (AMI Id: ami-6af08e38)
Try to install mysql-python using easy_install, but get the following error,

unable to execute gcc: No such file or directory
error: command ‘gcc’ failed with exit status 1

Finally figure out there is not gcc on the instance I picked. The solution is easy,
yum install gcc

Cheers!