Sunday 29 April 2012

Web script measuring sizes of images or divs breaks the first time, but not the rest with Javascript or JQuery

Problem:

A script that uses the width or height function to measure a loaded div or an image seems to break the first time the page is loaded, but not any subsequent times.

Possible diagnosis:

There are actually two problems in the above situation. The first problem is that the bug seemingly cannot be reproduced. The second problem is that the script will break for any users seeing the containing page for the first time.

One situation where this can occur is because the script is run by the browser prior to an image being loaded. For instance, the following example script can have this error occur:

$(document).ready(function(){
var divWidth = $("#mydivwithanimage").width();
doSomethingImportantWithWidth(divWidth);
});

The reason this script fails is because even though JQuery waits until the DOM is loaded prior to executing this script, this doesn't necessarily mean that other page components being loaded, such as images, have completed loading before this script is run. This leads to the funny problem that the script will only fail the first time it is run in an open browser, as the browser will cache all loaded images and other page components and often load them before the script is run when the page is reloaded.

Solution (for debugging):

The solution to reproducing this error while debugging is to clear all browser caches (javascript variables as well as loaded components) prior to re-running the script. In Firefox, you can simply clear your cache prior to completely quitting your browser. This should work with most other browsers, too. After re-launching the browser, the bug should appear once again.

Solution:

To correct the script, you need to ensure that it is run after all page components, such as images, are loaded, and not simply just the DOM. If you are using JQuery, rather than using $(document).ready(), use $(window).load(), e.g.

$(window).load(function(){
// ... your stuff here ...
});

For regular javascript, you can use the 'complete' property, e.g.

var myImage = new Image();
myImage.src = "img/myimage.png";

// ... later on ...
if(myImage.complete){
// ... do stuff ...
}

Thursday 26 April 2012

Optimize Netbeans 7.1 Memory and Configuration in OS X Manually

Reducing the memory footprint of Netbeans is often a good idea. Even on a system with plenty of RAM, a typical setup for development can quickly consume all free memory, leading to slowdowns and thrashing due to paging. Additionally, setting the initial memory usage high enough can avoid excessive memory allocations early on during the program's execution.

This post serves as a reminder of how to configure Netbeans and monitor its memory usage. It is not meant to be comprehensive, however I hope it turns out to be helpful for someone nonetheless.

Configuration:

The most direct way to configure memory usage in Netbeans 7.1 is by editing its configuration file. In OS X, the Netbeans configuration file is located directly within the application bundle. In finder, it can be found by the following:

  1. Go to your Applications folder
  2. Go into the Netbeans folder
  3. Secondary-click on the Netbeans 7.1 app, and view package contents
  4. Look for the file Contents/Resources/Netbeans/etc/netbeans.conf
  5. (optional) Backup the original in case you need to undo your changes
  6. Edit the netbeans.conf configuration file

If you would rather use terminal instead, the following string is the file's location (note that this is a single line, and any apparent line breaks are due to the blog format):

/Applications/Netbeans/Netbeans\ 7.1.app/Contents/Resources/Netbeans/etc/netbeans.conf

Note that this location is OS X specific, and in other platforms the location may vary. See the following site for details: http://wiki.netbeans.org/FaqNetbeansConf

In this file, flags to configure how the Java virtual machine runs Netbeans can be set. A good overview of these can be found here: http://performance.netbeans.org/howto/jvmswitches/

The following is an example of a tweaked configuration for netbeans_default_options:

-J-client -J-Xss2m -J-Xms256m -J-Xmx512m -J-XX:PermSize=32m -J-XX:MaxPermSize=160m -J-Dapple.laf.useScreenMenuBar=true -J-Dapple.awt.graphics.UseQuartz=true -J-Dsun.java2d.noddraw=true -J-Dsun.zip.disableMemoryMapping=true -J-XX:+UseConcMarkSweepGC -J-XX:+CMSClassUnloadingEnabled -J-XX:+CMSPermGenSweepingEnabled

Monitoring:

The easiest way to monitor the memory usage of Netbeans is to use the memory toolbar. To do this, in your menu select: View->Toolbars->Memory

In order to force garbage collection to free up some memory, simply click on the memory toolbar.

Sunday 22 April 2012

Time and time zones in PHP (and SQL)

Question:

How do I store, and then show the proper times at different time zones with php and SQL?

Solution:

Working with timestamps and time zones can be initially confusing with PHP. A common, but misguided solution when storing times in a database involves offseting a time by a number of hours, depending on what time zone you are in. This will lead to confusion later.
The best way to go about times and time zones is to use Unix time stamps. These are always measured in time passed since midnight, January 1, 1970 GMT, regardless of where you are in the world.
For instance, a time stamp of 1335092594 will be Sun, 22 Apr 2012 04:03:14 -0700 in PST (e.g. Seattle, WA), Sun, 22 Apr 2012 11:03:14 +0000 in UTC (e.g. Grenwich, United Kingdom), and Sun, 22 Apr 2012 21:03:14 +1000 in Sydney, Australia.

Example:

  1. To get the current time with PHP, you can use the time() function
  2. To get the date of your server, use date()
  3. To get the date at UTC, use gmdate()
  4. To change timezones in order to render that zone's local time, use date_default_timezone_set() followed by date()
e.g.:
$timestamp_now = time();
echo ' My Server Time: ' . date('r', $timestamp_now) . PHP_EOL;
echo ' UTC: ' . gmdate('r', $timestamp_now) . PHP_EOL;
date_default_timezone_set('Australia/Sydney');
echo 'Sydney, Australia: ' . date('r', $timestamp_now) . PHP_EOL;

This should yield (at a time stamp of 1335092594):
My Server Time: Sun, 22 Apr 2012 04:03:14 -0700
UTC: Sun, 22 Apr 2012 11:03:14 +0000
Sydney, Australia: Sun, 22 Apr 2012 21:03:14 +1000

Using SQL, you'll want to simply save this time stamp whenever you want to record a time, regardless of where in the world you are. A caveat is that you will want to make sure that your server is set to the correct time zone so it records the proper time stamp to begin with.

Update:

Just found a really good blog post related to this topic (PHP time and SQL). Enjoy :)
http://www.richardlord.net/blog/dates-in-php-and-mysql

Saturday 14 April 2012

Native SQL with Doctrine2 Fixtures in Symfony2

Sometimes the use of native SQL queries is desired over using Doctrine2 when programming fixtures in Symfony2, whether this be for performance reasons, etc. While it's recommended to use Doctrine2 in most cases, here's how to execute a SQL query:

$manager->exec($yoursql);

Note that this assumes that $manager is an ObjectManager type (hint: it should already be if you're creating your own fixture that extends Doctrine\Common\DataFixtures\AbstractFixture).

Doctrine fixtures is still changing, so I'll note that this works as of April 14, 2012 but it might not if they change their public interface in the future.

Saturday 7 April 2012

DYLD_LIBRARY_PATH error when running gedit in OS X

Problem:

When running gedit once, I got the following error:

dyld: Library not loaded: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libLAPACK.dylib
Referenced from: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/vecLib
Reason: Incompatible library version: vecLib requires version 1.0.0 or later, but libLAPACK.dylib provides version 0.0.0

Solution:

It turns out that something I had been working on earlier had set the environment variable DYLD_LIBRARY_PATH. To verify this, in Terminal the command printenv was used (specifically, printenv | grep DYLD*). This command yielded 'DYLD_LIBRARY_PATH=/opt/local/lib', which pointed to some libraries installed by macports.

In order to unset this environment variable, in the terminal just type:

unset DYLD_LIBRARY_PATH

After this variable is unset, try to run your program again and see if it works.

Thoughts:

The reason why having this environment variable set broke programs like gedit was probably because the programs being run would normally use the native libraries that come with OSX (in this case, the Accelerate framework), but because DYLD_LIBRARY_PATH was set, the programs were looking at that path instead for the dynamically linked libraries it needs to run, and unfortunately in my case actually finding some dynamically linked libraries that weren't compatible with the Accelerate framework (see Apple docs) and linking to them.

Friday 6 April 2012

Get MAMP to only serve localhost (i.e. only your own computer)

Problem:

Although MAMP is already configured to be ideal for local development, anything you're working on can still be viewed over the network you're on, since it is a web server after all.

To test this, using another computer on the same network, try to access your web server by typing in your computer's IP address and port into a web browser. For instance, if your computer's IP address is 192.168.3.121 and the port MAMP is set to listen to is 120, type in: http://192.168.3.121:120

Note that this test will not work on networks that block servers, but it should work on open networks such as most home wireless networks.

Solution:

The best way to avoid casual snooping would be to use your firewall. The next lazy thing you can do is to configure the MAMP Apache server to only listen to programs on your local computer. One way to do this is by editing the right option in your Apache httpd.conf file:

  1. In a text editor, open the file /Applications/MAMP/conf/apache/httpd.conf
  2. Locate the line that contains the word Listen. For this example, we're going to assume it is: Listen 80
  3. Comment this out and replace with: Listen 127.0.0.1:80
    • Note that the 80 in this example is the port number your apache server is listening to. You'll want to use the actual port number you set MAMP to listen to.

To test that this worked, use another computer try to access the computer with your started MAMP apache server by typing your computer's IP address into a browser (if you're unsure of how to find your computer's IP address, look up the Terminal command ifconfig in Google/Bing/etc.).

Note that the port configuration in your MAMP preferences pane will most likely report the incorrect port now (mine says 127). In addition, changing your port using the preferences pane could possibly undo this httpd.conf tweak (I haven't tested this).

This tweak was tested on MAMP 2.0.5.