Saturday, 22 December 2012

Install pattern files into GIMP 2.8 in OS X

Problem:

How do I install patterns into GIMP 2.8 in OS X?

Solution:

One way to do this is to copy the .pat files directly into the GIMP folder that contains all of the default GIMP pattern files. To find this folder, follow the steps below:

  • open your Applications folder
  • secondary-click GIMP, and select "Show Package Contents" from the context menu
  • navigate to: Contents/Resources/share/gimp/2.0/patterns

Now that you've found the patterns folder, copy all the GIMP-compatible pattern files into this folder. Restart GIMP. You should now be able to see the new patterns in the patterns dialogue/selector of GIMP.

Notes:

Note that the above method will make the patterns you install available for every user of your system. There are other methods available which should only install it to your own user, but they may not be so straightforward for the typical user since they involve creating/opening hidden folders.

If you'd like to find out the alternative locations where GIMP is looking for pattern files, just follow these instructions:

In the main menu, click on (in OS X) GIMP->preferences, (or sometimes in another OS, file->preferences). The preferences dialogue should appear. Then in the left-hand menu of the new dialogue, expand the icon/item labelled 'folders' and look for the item named 'patterns'. Once you click on this, you should be able to find all of the folders GIMP is looking for patterns in, as shown in the following screenshot.

Tuesday, 11 December 2012

Access images in Symfony 2.1 CSS stylesheets with Twig and Assetic

Problem:

How can I access images from my Symfony 2.1 project's CSS stylesheets?

Solution -- intro:

The example in this blog post is only part of the picture and is meant to get the typical project started for the beginner. Please note that it's far from a complete explanation, but hopefully it'll be useful for some out there.

Accessing images in Symfony 2.1 stylesheets can be done by following a few steps. Before we list them out, let's establish some parameters for this blog post's example.

First, for illustration purposes, let's assume that your bundle is named DemoIllustrationBundle, its path is Demo/IllustrationBundle, and that your CSS and image files are located respectively in the following locations in src/Demo/IllustrationBundle/:

  • Resources/public/css
  • Resources/public/images

Let's also assume that our CSS file is named style.css, and that it needs to access the image 'repeat.png' to repeat as the background image.

In style.css, we'll access repeat.png via url('../images/repeat.png'), for example:

background-image: url('../images/repeat.png');

Now that we've established the parameters for this example, we can summarize the steps needed to be taken to properly access images in CSS styles:

  • whitelist the bundle in assetic
  • install web assets
  • use stylesheets tag in twig template with cssrewrite filter
  • compile assets for production (out of the scope of this blog post, but necessary to learn prior to switching to a production environment)

... whitelist bundle in assetic

This step allows you to use the stylesheets tag in your twig templates. You'll need this in order to use the rewrite filter to dynamically update the path of your images in the generated stylesheets of your app.

Open the file app/config.yml, it should have a section that looks like:

assetic:
  ...
  bundles:        []
  ...

Add your bundle to this whitelist. In the case of this blog post's example we'll add DemoIllustrationBundle:

bundles:        ['DemoIllustrationBundle']

Save this file and exit. Note that this assetic whitelist will now apply to all environments.

... install web assets

This step installs the images from your project's Resources/public folder to the web folder.

There are several ways to install assets. We'll be installing assets using the symlink method so we don't have to keep reinstalling them during development. In the command console / terminal, go to your project folder and use the command:

php app/console assets:install web --symlink

You should be able to access the CSS and image files in the web folder now. In the case of this example, they'd be located respectively in:

  • web/bundles/demoillustration/css
  • web/bundles/demoillustration/images

Note how these locations compare to your project's public folder.

... use the stylesheets tag with cssrewrite filter

When including the style.css file in this example, the twig template section should look like the following:

{% stylesheets 'bundles/demoillustration/css/style.css'
   filter="cssrewrite" %}
  <link href="{{ asset_url }}" rel="stylesheet" type="text/css" />
{% endstylesheets %}

This should rewrite the '../images/' in the stylesheet to the location of the installed images.

Debugging (incomplete):

There are a few things that can go wrong with the above example. This section will cover two of those bugs with potential approaches to debugging them.

Assetic not configured:

One error can be forgetting to whitelist your bundle. This is indicated by getting an exception such as the following:

An exception has been thrown during the compilation of a template ("You must add DemoIllustrationBundle to the assetic.bundle config to use the {% stylesheets %} tag in DemoIllustrationBundle::base.html.twig.") in "/path/to/Demo/IllustrationBundle/Resources/views/base.html.twig".

Images still aren't showing:

If the above steps were followed but images still aren't showing, there are a few things that should be looked at. We'll use the setup in the example of this blog post to illustrate a few steps that can be looked at when trying to debug this:

  • are there any typos?
  • are images located in the project's "Resources/public/images" folder?
  • does the CSS file look for images in "../images/"?
  • were web assets installed?

Unfortunately, since there is an exhaustive list of things that can potentially go wrong, you'll have to use your ingenuity or Google to search out any other scenarios besides the above ones if they don't seem to apply.

Further reading:

The example in this blog post is only part of the picture and is meant to get the typical project started for the beginner. There's a lot to learn, and several steps left to go in order to make your project suitable for production. The following links are either references that helped in figuring out the above steps in this post, in addition to other resources that may provide more useful information for either clarification or for how to proceed from where this post leaves off.

Thursday, 6 December 2012

Styling links and anchors with CSS by example

Problem:

How do I style anchors and links with CSS? Additionally, how do I override these styles?

Examples:

The examples below in this post will demonstrate how to use the most common pseudo-classes of website links: link, visited, hover, active.

Here's what the pseudo-classes mean:

SelectorInterpretation
:linkall unvisited links
:visitedall visited links
:activethe active link
:hoverthe link selected on mouseover

Link defaults (covers all links in the document):

:link { color:blue; text-decoration:underline; }
:visited { color:green; text-decoration:underline; }
:link:hover { color:blue; text-decoration:none; }
:link:active { color:blue; text-decoration:underline; }

Anchor defaults (covers all links embedded in anchors):

a:link { color:blue; text-decoration:underline; }
a:visited { color:green; text-decoration:underline; }
a:hover { color:blue; text-decoration:none; }
a:active { color:blue; text-decoration:underline; }

Override (covers all links embedded in anchors with the class 'overrideClass'):

a.overrideClass:link { color:red; text-decoration:none; }
a.overrideClass:visited { color:orange; text-decoration:none; }
a.overrideClass:hover { color:red; text-decoration:underline; }
a.overrideClass:active { color:red; text-decoration:underline; }

References:

Friday, 30 November 2012

Check if a javascript variable contains a function

Problem:

How do I check if a value stored in a javascript variable is a function?

Solution:

While there are many ways to do this, the following code should work:

function isFunction(toCheck){
  return toCheck != null 
      && {}.toString.call(toCheck) == '[object Function]';
}

Notes:

Note that the first conditional, toCheck != null, may not be necessary. However, if null or nothing is passed to the function the result could be undefined otherwise (this was encountered, at least, in some older (or buggy?) implementations of javascript but might be a non-issue today -- feel free to test it out).

An alternative (and closely-related) method of checking is to directly call Object.prototype.toString.call() instead of instantiating an anonymous object.

References:

Thursday, 15 November 2012

Workaround for Symfony 2.1 composer.phar update timezone error

Problem:

Every time I run "php composer.phar update", I get an error similar to:

Warning: date_default_timezone_get(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'America/Los_Angeles' for 'PST/-8.0/no DST' instead in /path/to/symfony21/project/vendor/monolog/monolog/src/Monolog/Logger.php line 112

Script Sensio\Bundle\DistributionBundle\Composer\ScriptHandler::clearCache handling the post-update-cmd event terminated with an exception

[RuntimeException] An error occurred when executing the "'cache:clear --no-warmup'" command.

What's worse is that my php.ini file has a timezone already set. For instance, when I run the shell command "php -i | grep date.timezone", a timezone is produced, e.g. "date.timezone => America/Los_Angeles => America/Los_Angeles".

Workaround:

A quick workaround to this issue is to explicitly set a timezone in the app/console script. Open the app/console script in a text editor. In app/console, near the top (for instance, right before set_time_limit(0);), add the following line, replacing the example timezone from below with one of the valid PHP timezones found on the PHP docs page:

date_default_timezone_set('America/Los_Angeles');

When you save your changes to app/console and run "php composer.phar update" once more, it should now work.

Notes/Disclaimer:

This workaround isn't by any means an ideal fix, and it will affect the timezone of all Symfony2 commands run using the app/console script. (A fortunate side-effect, however, would be the workaround of timezone issues in other scripts using app/console.) This workaround may or may not also affect any scripts that try to upgrade app/console. To reverse this change, simply remove the "date_default_timezone_set" line you inserted into app/console. (Or even better, prior to modifying app/console, copy the old app/console script, rename the copy to app/console.old, and replace the script with the copy if you need to revert.) This workaround was tested with Symfony 2.1.3, PHP version 5.3.6 using MAMP 2.0.5 under OS X 10.7. Your mileage may vary with other versions.

Saturday, 10 November 2012

Batch resize images to a fixed width and add watermarks

Problem:

I've got a bunch of images that I want to make a resized version of to post online. Additionally, I want to add a watermark to each of these resized images. I already have ImageMagick installed in my OS X or Linux computer.

Solution:

This is quite a specific problem with a very specific solution. This post assumes that you have read and understood the previous post found here. If not, the solution in this blog post should still be somewhat clear, if not a little fast-paced.

For the sake of this post, let's assume that the source images are a bunch of .JPG images. Additionally, let's assume that we want to resize our images to a width of 320 pixels while maintaining the aspect ratio of the original image. Finally, let's assume that we want to give our images the semi-transparent watermark "grammarofdev.blogspot.com", using the font located at "/Library/Fonts/Arial.ttf". To prevent overriding our original images, we will also create a new sub-folder called 'results'. Below is an example Terminal command of how to do all of this (with line-breaks added for legibility):

$ mkdir ./results
$ mogrify -font /Library/Fonts/Arial.ttf -pointsize 88 -verbose
          -draw "fill rgba(255,255,255,0.5) text 24,75
                 'grammarofdev.blogspot.com'"
          -path ./results -resize 320 -quality 86 -format jpg *.JPG

Phew, what an ugly, long command. What does it all mean?

The "-font /Library/Fonts/Arial.ttf -pointsize 88" selects the Arial TrueType font with a point-size of 88pt. The "-verbose" flag outputs verbose information to the terminal while the conversion is being done. The "-draw "fill rgba(255,255,255,0.5) text 30,80 'grammarofdev.blogspot.com'"" portion tells ImageMagick to render the text "grammarofdev.blogspot.com" with a fill colour of white and an alpha of 0.5, starting at the (x,y) coordinate of (24,75) of the original image.

The "-path ./results" indicates that the resized images should be written to the "results" sub-folder. Note that all files in that sub-folder with the same name will be written over without warning! Additionally, omitting this flag will write over all of your original images!

Next, "-resize 320 -quality 86 -format jpg" indicates that the images should be resized to have a width of 320 pixels, maintaining the original aspect-ratio, and then converted to jpeg with a quality of 86. Finally "*.JPG" indicates that this command should convert all images with the suffix .JPG (case-sensitive).

Note that the text is drawn onto the original image prior to the image being scaled down to the final desired size.

Let's see how well this worked. The following two images will show an image before this command is run, and the resulting image afterwards. Note that the original image dimensions are 3264x2448 pixels, however this image is not included in this post. (A slightly-larger version can be found here!)

Original image (scaled to width 300px):

Watermarked image:

Where can this be useful:

Imagine that you had a hundred images you wanted to automatically watermark and resize, or imagine that you have created a web app that requires re-sizing and watermarking previews of images. Using ImageMagick to perform this task is a quick way to achieve the desired results without needing to program anything complex, or use programs such as Photoshop. This post only touched the surface of what ImageMagick can do. For more details on resizing, or details on drawing on images automatically with ImageMagick, check out the following references.


References:

OS X Terminal says 'you have mail'

Problem:

Whenever I open OS X Terminal, it says "you have mail". Why is this, and how can I get rid of this message?

Explanation:

OS X machines, just like Linux and Unix machines, have the capability to send emails to other machines, as well as receive emails from other machines directly to and from your local machine's user account. Long story short, if you are seeing the "you have mail" message in your Terminal window, your computer's local SMTP server has somehow received an email message to your account. (For far more details, look at the references below, or Google the terms "postfix", "sendmail", and "OS X").

Solution (using Terminal only):

This solution solely uses the Terminal. If you are not comfortable with this, please do not follow the rest of this how-to as you can cause some serious damage to your system if you don't know what you're doing. If you'd still like to poke around your system, try the "partially without Terminal" solution below.

The mail received in your account is saved in the file "/var/mail/$USER", where $USER is the name of your account. For instance, if your account was named "someone", and if your home folder shows up in the OS X filesystem as "/Users/someone", then the mail on your machine has been stored in "/var/mail/someone".

Because this is a regular text file, you can simply open it in a text editor to read the mail stored in this file, or you can view the file's contents directly in the Terminal with the command "more /var/mail/$USER", replacing "$USER" with your username (although typing in the command exactly will also suffice in this case, as Terminal will replace $USER with your username).

To get rid of the "you have mail" message, simply move or delete the email file from /var/mail. For instance, assuming again that your account name is "someone", you can type into the terminal "sudo rm -i /var/mail/someone", then confirm deletion when prompted. This command is permanent and possibly destructive if done wrong, so do not make any typos.

Finally, if you have reason to believe that something unusual is sending out emails from your machine after looking at your email file in /var/mail, you can check out the mail log on your machine with the command "more /var/log/mail.log" to see what email activity has occurred on your machine.

Solution (partially without Terminal):

To view the local mail folder on your OS X system in the Finder, type the following command into the Terminal window:

open /var/mail

Once open in the finder, to view the mail on your local machine, open the text file that matches your user in the "/var/mail" folder. For instance, if your username is "someone" and your home folder is "/Users/someone", then the email file to open is "/var/mail/someone".

With the OS X Finder still open to the "/var/mail" folder, in order to remove the "you have mail" message from the Terminal move the email text file from the "/var/mail" folder, or delete it altogether. For instance, if your user is "someone", you will want to either move or delete the file "/var/mail/someone".

After reading your email, if you suspect that there is unusual email activity happening on your local machine, you can confirm this by looking at the machine's email log with the following Terminal command:

open /var/log/mail.log

References:

Friday, 9 November 2012

Batch convert PNG images to 50% scaled jpg images with mogrify

Problem:

How do I convert a bunch of PNG images to jpeg images at 50% of their original dimensions? I'm on an OS X computer and have already installed ImageMagick.

Solution:

You can use the 'mogrify' command that comes with ImageMagick in the Terminal. Note however, that mogrify has the ability to silently overwrite images, so *be careful*! In the following example a destination folder is created to save images in order to preserve the original images.

$ mkdir ./results
$ mogrify -path ./results -resize 50x50% -quality 80 -format jpg *.PNG

So what did all of that mean?

The first part, "mkdir ./results" created a sub-folder named 'results' to save all of the converted images. You can make a different sub-folder if you already have a folder named 'results' to avoid overwriting contents in that existing sub-folder. Remember to change the folder in the -path portion of the mogrify command, too.

The next part batch converts all of the .PNG images to .jpg images of half the width and height. Note that the extensions are case-sensitive. The "-path ./results" flag indicates that results of the conversion are written to the "./results" folder. All destination images are overwritten if they already exist. The "-resize 50x50%" portion shrinks the final width and height to 50% of the original. The "-quality 80" indicates the compression level of the resulting jpeg images. The "-format jpg" indicates that the final image format should be jpeg. Finally, the "*.PNG" indicates that the input images will be every .PNG image in the current folder.

References:

Wednesday, 7 November 2012

PHP timezone error

Problem:

When trying to make a new DateTime object using PHP, or use any built-in time-related functions, I keep getting the following exception thrown: "DateTime::__construct(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'America/New_York' for 'EST/-5.0/no DST' instead"

Solution:

This error means that a PHP script should have some method of having its default timezone set besides the unsafe method of using the system's setting (making for more predictable and consistent behaviour of the script).

In the case of PHP, you can either use date_default_timezone_set() somewhere prior to calling any date or time functions. Alternatively, you can edit the /etc/php.ini file to add a valid timezone to the date.timezone parameter (e.g. date.timezone = "America/New_York") so that all scripts will use this timezone unless set otherwise by using date_default_timezone_set().

Reference:

Handle MySQL max_allowed_packet error

Problem:

My web application keeps giving the error "#1153 – Got a packet bigger than ‘max_allowed_packet’ bytes" and fails.

What's happening:

This error occurs when a statement to the MySQL server exceeds a certain size. For instance, if the max_allowed_packet is set to 2M but a statement attempts to INSERT a 5MB BLOB, the query will fail.

Solution:

There are two solutions around this problem, so long as you have sufficient privileges to access the configuration of your MySQL server, and are comfortable with either SSH or editing configuration files. Additionally, you should know how to safely restart your MySQL server.

  1. The first solution is to log into your server via SSH, then connect to your MySQL. Assuming you want the maximum packet size to be 16MB, when logged into MySQL type the following command into the prompt: mysqld --max_allowed_packet=16M
  2. The other solution is to find your MySQL configuration file, usually named my.cnf (though if not, you can easily Google how to find the location of this file on your current OS version). Assuming again that you want a max packet size of 16M, inside this file under the section [mysqld], add or change the following parameter to max_allowed_packet=16M

Once this is completed, you may have to restart your MySQL server to see the change. Note that this is a global change and every script that accesses the database on this server will now, by default, have a maximum allowed packet size to what you set it to.

Tuesday, 6 November 2012

Increase phpmyadmin import file size limit

Problem:

I'd like to increase the import file size limit for phpmyadmin.

Solution:

The import size limit of phpmyadmin is the file upload size limit of your php configuration, so the most direct method of increasing this limit is to increase the upload limit in your php.ini file.

If you have shell access with root privileges, (or high enough privileges,) you can follow these steps in the terminal to increase this limit:

  • find your php.ini file if you don't know its location, you can find it by the shell command "whereis php.ini"
  • open your php.ini file and search for the line that contains "upload_max_filesize". It may look something like "upload_max_filesize = 2M"
  • change this to the size that you need, e.g. "upload_max_filesize = 8M"
  • you may need to restart your apache server to see the change

Notes:

Note that by performing this change, the upload limit of all php scripts, not only phpmyadmin will be increased.

Monday, 5 November 2012

Restart a BlackBerry Bold 9900 (and earlier)

Problem:

For those of you still sporting your favourite BlackBerry handset, you may have noticed that on many models, such as the 9900, the only apparent way to restart your handset is to take out the battery and put it back in. Placing your phone in the "power off" mode from the menu only seems to suspend the handset rather than shut it off. For many, taking out the battery isn't a major problem. However, if you happen to keep your handset in a case the aforementioned procedure can become substantially more difficult.

Solution:

Luckily, there is another way to restart your BlackBerry handset, so long as it is equipped with a physical keyboard:

  • Press and hold down the Alt key. Continue holding this key through the next 2 steps.
  • Press and hold down the Right Shift key along with the Alt key. Continue holding these two keys through the next step.
  • While holding the other two keys, press the Backspace/Delete key. Your screen will turn off and the handset will restart.

Notes:

The restarting procedure in this post is called a "soft reset" and can be used to help troubleshoot problems with the phone. It will not erase data nor restore the phone to factory settings.

Additionally, the above procedure will not work on very old BlackBerry devices such as the RIM 850, 857, 950, nor 957.

Monday, 22 October 2012

Find the min and max value of a javascript array

Problem:

I'd like to quickly find the minimum and maximum values stored in a javascript array without having kept track of them in advance, and without using a loop.

Solution:

One of the easiest ways to do this is to use Function.prototype.apply with Math.min and Math.max, e.g.

var min = Math.min.apply(null, myArrOfNumbers);
var max = Math.max.apply(null, myArrOfNumbers);

Notes:

When expanded, note that the first of the above examples is roughly equivalent to Math.min(myArrOfNumbers[0], myArrOfNumbers[1], ...). With that in mind, it should be cautioned that the solution in this post should only be used with small arrays, as many javascript engines have a limit as to how many arguments a function can accept, leading to unpredictable behaviour when this limit is exceeded.

For those interested, see more details in the following linked reference for javascript's Function.prototype.apply.

Reference:

Friday, 12 October 2012

Icon missing when uploading PhoneGap app to Apple

Problem:

When I upload my Cordova app to Apple for review, I get the following error:
Invalid Image Path - No image found at the path referenced under key "CFBundleIcons": icon-72@2x.png

Solution:

This error seems to be caused because a reference to icon-72@2x.png is present in the icon list of your Cordova XCode project, however the icon has not been added to the project itself by the script that created the project.

To add this icon, simply open your project in XCode, find (or add) the icon to the Resources->icons folder of your project, then drag-and-drop this into the appropriate spot in your XCode project. Note that this icon needs to be 114x114 pixels.

Here are example screenshots of the icon-72@2x.png missing, and adding this icon to your Cordova XCode project. Hopefully someone out there finds these useful :)

Notice that the icon is missing ...

Drag-and-dropping the icon into the project.

Notes:

An alternative solution to this problem is to remove the reference to the image in the icon list. However, it may be useful to render this icon and add it to your project nonetheless. This bug was found and tested in PhoneGap/Cordova 2.0.0 using XCode 3.5. The original project itself was upgraded from an earlier PhoneGap 1.5.0 project.

Reference:

https://groups.google.com/forum/?fromgroups=#!topic/phonegap/51CYGyjj_pU
(Being relatively new to XCode, I wasn't exactly sure how to follow the brief instructions at the above link at first, which is why I created this how-to in order to help out others in a similar situation.)

Saturday, 6 October 2012

Replace every instance of a word in a string with a word stored in a variable using javascript

Problem:

In javascript, I'd like to replace every instance of a word (or substring) in a longer string, with a string stored in a variable.

For example, if I had the following string:

The red strawberries fell off the red table.

And I wanted to replace the word "red" with "dark red", the result should be:

The dark red strawberries fell off the dark red table.

However, I'd like to substitute "dark red" with any arbitrary string stored in a variable.

Solution:

One of the simplest ways to do this is to use the regular expression constructor combined with the 'replace' function. The easiest way to show this is by an example:

var replaceThis = "red";
var replaceWith = "dark red";
var theString = "The red strawberries fell off the red table.";

var theNewString =
  theString.replace(new RegExp(replaceThis, "g"), replaceWith);

More details:

Using the 'replace' function is a simple way to replace something in a string. Unfortunately, if you want to replace more than one instance of a substring in a string, passing two strings as parameters to the 'replace' function, such as in "str.replace('this', 'that')", will not work because the function will simply replace only the first match. In the highlighted example above, only the first instance of 'red' would have been replaced with 'dark red'. To get around this issue, the first parameter should be a regular expression, with the desired search string being 'red' and the modifier being 'g' for global matching. In javascript, this regular expression would look like: /red/g

However, regular expressions cannot be passed simply as strings, therefore passing "/red/g" or a variable containing that string as the first parameter of replace would have been interpreted as the string "/red/g" rather than the regular expression /red/g. This problem is worked around by converting the string of the regular expression to a valid regular expression via the regular expression constructor.

Additional details can be found at the following references:

Sunday, 30 September 2012

Blackberry Playbook clock problem fix

Problem:

My Blackberry Playbook's status bar clock no longer responds when clicked. However, it still shows the correct time. Additionally, when I go to the clock app, it takes awhile to load and the times do not match.

Solution:

A quick solution for this bug is to open the clock app and set the time zone to match your playbook's current time zone.

Thoughts:

This bug and its fix were both found in BB10 2.0.1.358 and earlier.

Normally the clock app and the playbook's time should not get out of sync. It seems as though when this happens, the built-in clock in the status bar no longer works as it should, also producing the problem of not being able to set an alarm. For me, this problem occurred due to an apparent bug (memory leak? buffer overrun?) when playing large mp3 files for a very long time (in my case, it was a 2-hour recording of the ocean overnight for a few days straight -- my neighbourhood is quite noisy).

If anyone at RIM is reading this post, many thanks in advance for finding and fixing this weird bug :) Note that the bug also sometimes seems to affect the ability to network to the playbook itself via wireless or USB, however I haven't found a fix for that.

Tuesday, 25 September 2012

Workaround for ios6 Phonegap 2.0.0 linker error

Problem:

After upgrading to ios6 and XCode 4.5, when trying to compile my old PhoneGap/Cordova project on an iOS device I get the following error:

"_OBJC_CLASS_$_CDVURLProtocol", referenced from:
Objc-class-ref in AppDelegate.o
"_OBJC_CLASS_$_CDVViewController", referenced from:
_OBJC_CLASS_$_MainViewController in MainViewController.o
"_OBJC_METACLASS_$_CDVViewController", referenced from:
_OBJC_METACLASS_$_MainViewController in MainViewController.o
Symbol(s) not found for architecture armv7s

This error may not necessarily show up when running the program in the simulator.

Temporary workaround:

To have your old PhoneGap project working again, you can try the following:

  • in XCode 4.5, click on your project and click "build settings"
  • change Architecture to "Standard (armv7, armv7s)"
  • change Valid Architectures to be only "armv7, armv7s"
  • change Build Active Architecture Only to "Yes"

You may also have to do this for the linked CordovaLib.xcodeproj. This temporary workaround assumes that you have been using a build configuration similar to the default configuration (e.g. things haven't been heavily customized).

Notes:

This workaround won't work for projects using older versions that import PhoneGap as a precompiled framework. It should work for versions that import CordovaLib.xcodeproj, but no guarantees.

Keep a lookout for updates with the Apache Cordova/PhoneGap project as this workaround is only a temporary fix for those looking to test their old projects after upgrading their devices to iOS6. Chances are that this bug will be fixed by the PhoneGap team, if it already hasn't been. This workaround will result in dropped support for older ios devices (as the armv7s instruction set isn't supported by devices older than the iPhone 3GS). This workaround was tested with XCode 4.5 and Apache Cordova 2.0.0 on devices with the old 3.5 inch retina screen, recently upgraded to ios6. This workaround has not been tested in a deployed/production setting.

Saturday, 15 September 2012

Increase memory for PHP scripts in MAMP

Problem:

I'd like to increase the amount of memory allocated to PHP scripts because my optimized script still keeps running out of memory when using MAMP.

Solution:

If you find that a local PHP script is not executing because it is running out of memory, you can give more memory to PHP scripts by editing the php.ini file(s) in MAMP by the following steps:

  • Stop MAMP servers
  • Open the file /Applications/MAMP/bin/php/php[version]/conf/php.ini (where [version] is the PHP version you're using, e.g. php5.3.6)
  • Search for "memory_limit" (without the quotes). You should end up with something like "memory_limit = 8M"
  • increase the number to however much you will be allocating to your scripts. For example, a 128MB maximum script would need a setting "memory_limit = 128M"
  • restart MAMP servers

Notes:

This trick is useful for locally-run scripts. For scripts that will be hosted on an external server, you should be careful to match the memory limit of your remote host machine as scripts that will execute in the higher local memory limit may break when deployed online. Not to mention that it is also a useful exercise to think up ways to execute scripts more efficiently.

This was tested on MAMP 2.0.5. Other versions may keep php.ini in a different location.

Friday, 14 September 2012

Count the number of lines in a file using terminal

Problem:

I would like to count the number of lines in a file.

Solution:

An easy way to count the number of lines in a file in Linux or OS X is to use the 'wc' command in terminal. For instance:

cat myfile.txt | wc -l 

Reference:

The 'wc' command can also do a bunch of other useful things. You can find out more by googling, looking at the command's man page, or clicking the following reference: http://linux.about.com/library/cmd/blcmdl1_wc.htm

Replace spaces with newlines using terminal

problem:

Using Linux or OS X, I would like to replace spaces with newline characters in a file and output the result to a new file.

For instance, if my file's contents look like the following:
Monday Tuesday Wednesday Thursday Friday

The output should look like:
Monday
Tuesday
Wednesday
Thursday
Friday

solution:

In the terminal, a simple solution would be to use the 'tr' command, for instance:
cat infile.txt | xargs | tr -s ' ' '\n' > outfile.txt

reference:

http://www.linfo.org/tr.html

Friday, 29 June 2012

Reminder of my netbeans.conf file

This post is just meant to be an online reminder of my current OS X Netbeans 7.1 configuration so I can remember when I switch machines or upgrade my Netbeans version. It probably won't be too useful to others out there, but you're welcome to take a look at it nonetheless.

Also note that tuning JVM flags to work well on one machine or system configuration does not necessarily mean that it will work well on another. In fact, in some cases it can even make things worse when compared to the default settings. So if you decide to use some of the configuration below, you'll definitely want to tweak it to work well for your own machine.


Current netbeans.conf setup:

netbeans_default_options="-J-client -J-Xss2m -J-Xms1280m -J-Xmx1280m
-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:+UseParNewGC
-J-XX:+UseConcMarkSweepGC -J-XX:+CMSParallelRemarkEnabled
-J-XX:ParallelGCThreads=3 -J-XX:+CMSClassUnloadingEnabled
-J-XX:+CMSPermGenSweepingEnabled -J-Xverify:none
-J-XX:CompileThreshold=100"

(For 7.1.2, using 768m instead seems to work better as the major garbage collection cycles are much faster, and there seems to be a severe memory leak with larger amounts on the rig I'm using; the heap fills up significantly faster forcing more frequent major garbage collection cycles.)

What this is trying to do:

  • Provide enough memory to the JVM so Java doesn't frequently 'stop the world' in order to allocate more memory
  • Provide enough memory at the beginning so things don't grind to a halt in order to change the VM size early on
  • Use parallel garbage collection so Netbeans doesn't freeze for a long time when doing a major garbage collection cycle
  • Use several (but not all) cores for more efficient garbage collection
  • Make Netbeans more responsive at a slight cost of startup time
  • Provide a large enough amount of heap in order to delay time between major garbage collection cycles, also making Netbeans more responsive on average in the long run

Also note that some of the (default) flags in the configuration are there to make sure that Netbeans actually works in OS X.


Problems this is trying to solve:

The current system Netbeans is running on has ample physical memory available so a GB+ memory footprint is not an issue. However, other large programs are often used at the same time to create other resources for the same projects being developed using Netbeans. Garbage collection and memory allocations plague the system with a small VM size since opened projects can sometimes take up hundreds of MB. This creates the need to often wait for Netbeans to become responsive again after having it pause for a bit. In addition, when the system is idle for long enough, Netbeans is often paged to disk by OS X to make other programs more responsive (the current JVM flags will not be able to fix this, only more RAM will). Netbeans is often left running without restarting for weeks on end to work on parts of projects every day. The system is currently running OS X 10.7 Lion.


How well has this worked compared to the default:

The default configuration would often cause Netbeans to frequently halt when working on projects. The current configuration appears to be significantly better, without too much pausing. However, notable pauses do occur when forcing garbage collection (which doesn't appear to be necessary with the current configuration, but is still possible to do), and when loading paged memory back into RAM.


References:

Tuesday, 26 June 2012

Navigate or redirect to a url using javascript

Problem:

How do I use javascript to navigate to another url?

Solution:

The follow are two ways that can redirect a user to another page:

// redirect without updating browser history
window.location.replace("my-next-page.html");

In the above and below example "my-next-page.html" should be replaced with your own URL. The above example shouldn't update the change of pages in the browser history, whereas the next example will.

// redirect and update in browser history
window.location.href = "my-next-page.html";

Notes:

This was tested on the iOS 5.1 browser, Firefox 12, and with PhoneGap 1.5.0 on iOS 5.1. This should also work with most other browsers.

Saturday, 16 June 2012

Get the current route and url in a Symfony 2 controller

Problem:

How do I get the current page's URL and current route in a Symfony 2 controller?

Solution:

There are several ways to get the current page's route and url. One way is demonstrated here.

Current route

public function someAction(Request $request){
  // ... some code here

  $currentRoute = $request->attributes->get('_route');

  // more code ...
}
Current URL

public function someAction(Request $request){
  // ... some code here
  
  $currentRoute = $request->attributes->get('_route');
  $currentUrl = $this->get('router')
                     ->generate($currentRoute, array(), true);
  
  // more code ...
}
Updated:

Alternatively, you can also generate the current URL directly without using the current route (thanks COil for the comment!)


$currentUrl = $this->getRequest()->getUri();

$currentUrl = $request->getUri();
//(see comments below, thanks Marcos for the comment!)


Notes:

This was tested to work using Symfony2 version 2.0.4.

Reference:

http://symfony.com/doc/current/book/routing.html#generating-urls

Include custom PHP-generated html code using Twig and Symfony 2

Problem:

How do I embed custom HTML code (or scripts, etc.) into a page generated from a Twig template?

This is useful because:

For instance, if a page controller in Symfony 2 is used to generate a fancy widget, such as a calendar, you may want to have a way for the twig template to render this custom server-side generated code.

Solution:

Pass the customized html string into a parameter in the twig template (customcodeparam, in the example below), and use the raw filter when rendering, e.g.

{{ customcodeparam | raw }}

Detailed example:

This example is not 100% complete, but it should include enough code to convey the idea of how to embed custom code into a twig template. This example assumes that you're already familiar with PHP and Symfony 2, and are learning Twig.

Imagine that you have a twig template named 'something.twig':


{# MyBundle:Page:something.twig #}
{% extends 'MyBundle:Page:index.html.twig' %}

{% block body %}
<h1>My awesome custom server-side-generated widget</h1>
{{ customcodeparam | raw }}
{% endblock %}

And also imagine that there was a page controller that rendered the template:


public function renderSomethingAction(){

  // replace the code below with your own
  $widgetcode = "<a href='http://www.google.ca'>Go Google!</a>";

  try {
         return $this->render('MyBundle:Page:something.html.twig',
                    array(
                        'customcodeparam' => $widgetcode
                    ));
  } catch (\Doctrine\ORM\NoResultException $e) {
         return null;
  }
}

The resulting rendered html in the body block would look similar to the following:


<h1>My awesome custom server-side-generated widget</h1>
<a href='http://www.google.ca'>Go Google!</a>

(Note that the above code snippet does not include the html generated by MyBundle:Page:index.html.twig)

Important

This probably goes without saying, but just a reminder that when including un-sanitized code that is generated by your server-side script on your web app, you should ensure that this code is safe. This is especially important to consider if the inserted code includes user-generated content (in case a user decides to sneak in a script, etc.). In other words, when using the trick in this post, the sanitization of the page is now up to you and not up to Twig. Pretty basic, I know, but I thought I should mention it anyway.

Saturday, 2 June 2012

Stop and complete all jQuery animations immediately

Problem:

I'd like to stop and complete all jQuery animations immediately. At one point my web app needs to progress to another stage and the smooth completion of several pending, long animations isn't needed.

Solution:

Edit: have a look at the comment below by Navigator regarding .finish() (see jQuery doc for the .finish() function). It's valid for jQuery 1.9 and above =) The points written in this post were tested for the jQuery version that was used when this post was originally written June 2012.

There are several ways to immediately stop and complete all animations that are currently running or pending in jQuery. Two of those methods will be outlined here.

One way to do this is by setting the jQuery.fx.off parameter to true, e.g.

jQuery.fx.off = true;

This will cause all queued animations to skip immediately to the final frame and complete. Note that while this parameter is set to true all animations will skip to their final states. To allow jQuery animations later on, set this parameter back to false.

The second way is more of a shotgun approach and probably isn't a good way to skip over animations in the general case. However, if you haven't been keeping track of all the selected elements that have a pending animation and thereby can't use the stop() method on them individually, you can try selecting all elements and calling the stop() function, e.g.

$("*").stop(true, true);

Note that the latter is extremely inefficient since it selects all elements on the page!

Notes:

These methods were tested on jQuery version 1.7.2 on Firefox 12.0 and the iOS 5.1 browser.

It isn't quite clear whether the jQuery.fx.off method will skip currently running animations to the final frame.

References:

Friday, 25 May 2012

Be motivated to live life

Problem:

I want to be motivated to do things.

Solution:

Just remember, everyone has a 100% chance of dying, so you may as well live while you are alive.

For those who say that they do not have enough time, time is the only thing we are all given the same amount of, (when compared to other things such as opportunity or resources).

For those who say that they have never done something before, everyone who has ever lived did everything they're good at for the very first time at one point in their life. Even the world's best. We were all born knowing nothing.

So with this in mind, just ask yourself, "when can I get started", and always keep moving forward.

Dedication:

I wanted to dedicate this post to a friend of mine who passed away in a plane crash a few months ago near Mt. Everest. I just came back from his memorial unveiling earlier today. Although young, this friend experienced, and accomplished a lot in a very short amount of time, and made many friends along the way. I wish everyone who reads this post the very best in your future :)

Saturday, 19 May 2012

JQuery animation: execute callback only once when all completed

Problem:

When using the animate function after selecting more than one item, my callback function is executed as many times as there are items. How do I get the callback function to execute only once when the entire animation is done?

Problem Example:

If, for example, you have five items with the class 'do-something', and you try the following code:

var ctr = 0;
var selected = $(".do-something");

var mycallback = function(){
  ctr++;
  alert(ctr);
}

selected.animate({
  // ... your animation stuff ...
}, 200, mycallback);

Rather than the hoped for single alert with the number 1, you'll receive five alerts with the numbers 1 through 5.

Solution:

As of JQuery version 1.6 you can use the promise() and done() functions to fire off your callback once after all the animations are completed.

For example, again if you have five items with the class 'do-something' the following code should now produce a single alert with the number 1:

var ctr = 0;
var selected = $(".do-something");

var mycallback = function(){
  ctr++;
  alert(ctr);
}

selected.animate({
  // ... your animation stuff ...
}, 200);

selected.promise().done(mycallback);

Other notes:

This was tested to work using JQuery 1.7.2 and Firefox 12.0.

References:

Sunday, 13 May 2012

Copy files in order using Linux or OS X

Problem:

How do I copy files in sorted order using the Linux or OS X Terminal?

Solution:

In the terminal, you can use a combination of the "find", "sort", "xargs", and "cp" commands to copy files in sorted order.

For instance, first switch to the directory that has the files you would like to copy:

cd /path/to/media/directory

Then copy the files in sorted order:

find . -print0 | sort -z | xargs -0 cp --parents
  --target-directory=/path/to/destination -v

Note that the above command is a single line, (but it appears split into two in order to fit into this page.)

In the cp command, the -v flag will help you see if files are being copied in the desired order. This can be omitted if you do not wish to monitor the files being copied. To customize the order of your sort, simply customize the flags used with the 'sort' command (see the manual pages for 'sort' using the command 'man sort', if you're unsure of how to do this).

Why copying files in sorted order can be useful:

Some MP3 players, digital media players, and other devices play back media in the order that files were copied to it. With some file managers, files can be copied out of order, in reverse-sorted order, or in other ways that copy files out of the order that is desired (such as copying multiple files in parallel). There are also other situations where copying files in a particular sorted order would be useful. For instance, copying files in some required order to a custom-built robot's flash memory, etc.

Other thoughts:

Although the command 'cp -R' can also recursively copy things in order, the method mentioned above in this post should give a bit more flexibility customizing the sorted order of the copied files.

Friday, 11 May 2012

Fullscreen PhoneGap app with XCode

Problem:

How can I get rid of the status bar on top of my PhoneGap application on my iOS device?

Solution:

There are several ways to do this, and although I won't go into all of the ones I found, one of the easiest ways to do this is to just edit your project's Info.plist file. This is generally named in the form of "YourAppName-Info.plist".

In your plist file, secondary-click and add a row. Name this row UIStatusBarHidden, and change its type to Boolean. Note that if a drop-down menu appears and gives you the option to select "Status bar is initially hidden", pick that. In both cases, set the value to YES.

The next screenshot is an example where the choice is given to initially hide the status bar:

The next time you run your PhoneGap application, you'll now notice that it is fullscreen. This will continue to be the case until your application code does anything to change this, (for instance, if you try to send the user to a different page).


Other thoughts:

This was tested with PhoneGap version 1.5.0 (codename Cordova) on iOS 5.1, using XCode 4.3.2. Your mileage might vary with different versions. Also note that these instructions can be used to initially hide the status bar in any iOS application, not necessarily just PhoneGap applications.

Wednesday, 9 May 2012

String character whitelist

Problem:

How do I determine if a string contains only allowed characters?

Solution (code snippet):

The following PHP example code will check if a string contains only characters in a white-list. It should be pretty easy to convert this to other languages.

function containsOnly($string, $whiteliststring){
    $char_arr = str_split($string);
    $whitelist_arr = str_split($whiteliststring);
    
    foreach($char_arr as $char){
        if(in_array($char, $whitelist_arr)==false) return false;
    }
    return true;
}

Example usage of this would be, for instance, checking for numbers only:

$numbers = "0123456789";
$not_only_numbers = "abcd123";
$only_numbers = "123";

echo containsOnly($not_only_numbers, $numbers)?"yes":"no"; // no
echo containsOnly($only_numbers, $numbers)?"yes":"no";     // yes

Code explained:

The containsOnly function uses str_split to convert strings into arrays containing their characters. The loop checks to see if any of the test string characters is absent from the white-list.

This code can generally be sped up by using an implementation of a set rather than arrays.

Tuesday, 8 May 2012

Clearing an array in Javascript

There are a few ways to clear an array in Javascript. Two particularly useful ways are as follows:
  1. Assigning a new array:
    myArray = [];
  2. Refactoring the current array:
    myArray.length = 0;

The first method will assign a new array to the myArray variable. If there are any other pointers to the previous array, these will still point to the old array.

The second method changes the array itself. If there are any other pointers to the previous array, they will all be updated to the cleared array.

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.

Thursday, 29 March 2012

Workaround for copy & paste with Inkscape in OS X

There is a bug in OS X with X11 that affects copy and paste between X11 windows when using Inkscape. Basically, vector snippets that are copied in one window paste in another as bitmap rather than vector.

Solution (workaround):

Go into the X11 preferences (click on X11 icon in your dock, then in the menu bar X11->preferences...), and go to the tab that says pasteboard and uncheck: Update Pasteboard when CLIPBOARD changes.

Thursday, 15 March 2012

Bash shell script confirmation prompt

To prompt for user confirmation before performing a dangerous action in a bash shell script, you can use the following code:

read -p "Confirm (y/n)? " -n 1 -r
if [[ $REPLY =~ ^[Yy]$ ]]
then
  # get cursor on next line (optional)
  echo
  # do dangerous stuff here
fi

Wednesday, 14 March 2012

Ignore all .svn folders with .gitignore

If you find yourself looking to use both Subversion and Git together for any reason, in order to ignore all .svn folders in a project directory tree using your .gitignore file, add the following to your .gitignore file:

.svn

This assumes that no .svn directories or files inside of them have been committed yet. Also, note that there aren't any wildcard characters, (e.g. "*"). If you are using GitX, refresh your 'commit' view to see the changes after making this change to your .gitignore file.

Tuesday, 13 March 2012

Random Symfony2 reminders

This post is basically a crib sheet of Symfony 2 reminders for myself, but you're welcomed to use it if it helps. It's a short list right now, but I'll be periodically adding to it.

List available app/console commands

$ php app/console list

Useful DQL examples


Install web assets

$ php app/console assets:install web

The optional parameter --symlink will use symbolic links instead.


Force schema update

$ php app/console doctrine:schema:update --force

Note: consider using Doctrine Migrations instead


Create tables

$ php app/console doctrine:schema:create

Note: don't run this in a production setting


Create database

$ php app/console doctrine:database:create

Generate setters and getters

$ php app/console doctrine:generate:entities Package

Generates setters and getters for all entities in Package.

ORM annotation Column() options

  • type (optional, default 'string')
  • name (optional, default to field name)
  • length (optional, default 255)
  • unique (optional, default FALSE)
  • nullable (optional, default FALSE)
  • precision (optional, default 0) The precision for a decimal column.
  • scale (optional, default 0) The scale for a decimal column.
References:

Install doctrine fixtures in Symfony 2.1

Step 1 (only if necessary): install Composer

$ curl -s http://getcomposer.org/installer | php

Step 2: Update composer.json

{
    "require": {
        "doctrine/doctrine-fixtures-bundle": "dev-master"
    }
}

Step 3 (optional): allow only stable updates in composer.json

Look for the key "minimum-stability", and change its value from "dev" to "stable", e.g.

"minimum-stability": "stable",

Step 4: update vendors library

$ php composer.phar update
Step 5: register in AppKernal.php
// ...
public function registerBundles()
{
    $bundles = array(
        // ...
        new Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle(),
        // ...
    );
    // ...
}
References:

Generate a new bundle

$ php app/console generate:bundle --namespace=Package/YourBundle --format=yml

Generates a new bundle named PackageYourBundle in the namespace named Package/YourBundle.

Friday, 9 March 2012

Full Google Calendar in Playbook (or mobile browser)

Back Story:
During the price drop of last year I got a Blackberry Playbook prior to the version 2 update (before it had a decent calendar app). When trying to use Google Calendar in its place, one of the things I ran into was that Google Calendar would default to the mobile site in a browser, whereas some friends and I really liked using the full site at the time. We ran into this issue with some other mobile devices, too.

Solution:
One way to get the full Google Calendar to display in the browser is to use the following URL:
https://www.google.com/calendar/render?gsessionid=ok 

Additional Notes:
Bookmarking this URL allows for easy access to this web app, and this workaround solution still worked as of March 2012.

Thursday, 8 March 2012

Install PHPUnit in MAMP

To install PHPUnit in MAMP 2.0.5, run the following commands in Terminal, noting that the pear.conf file needs to be deleted first. Also, ignore the premature word-wrapping in the commands as they should be one line each.

rm /Applications/MAMP/bin/php/php5.3.6/conf/pear.conf

/Applications/MAMP/bin/php/php5.3.6/bin/pear channel-update pear.php.net

/Applications/MAMP/bin/php/php5.3.6/bin/pear upgrade pear

/Applications/MAMP/bin/php/php5.3.6/bin/pear channel-discover pear.phpunit.de

/Applications/MAMP/bin/php/php5.3.6/bin/pear channel-discover pear.symfony-project.com

/Applications/MAMP/bin/php/php5.3.6/bin/pear install phpunit/PHPUnit 

To test this, you can run the following in Terminal:
/Applications/MAMP/bin/php/php5.3.6/bin/phpunit --version

Caution: before performing the next step, make sure that you won't be conflicting with another installation of PHPUnit!

To run php unit with the command "phpunit", you can make a symlink to the phpunit binary in a directory that is defined in your PATH, such as /usr/local/bin, e.g.:

sudo ln -s /Applications/MAMP/bin/php/php5.3.6/bin/phpunit /usr/local/bin/phpunit

Sunday, 4 March 2012

Change GTK themes in OS X

There are several great, cross-platform programs out there that use GTK to handle their UI elements. Inkscape, and JPilot (for those still rocking their Palm handhelds!), are two examples. In Linux it is possible to customize the themes of these applications to make them look better, and in OS X it turns out this is also true.

While I'll summarize below, a great tutorial on how to do this can be found here:
http://blog.e-shell.org/60

This solution was tested to work in OS X 10.7.3 using MacPorts version 2.0.3.

Summary of Solution:


1) install MacPorts
the project can be found at: http://www.macports.org/

2) install gtk-theme-switch in Terminal
sudo port -v install gtk-theme-switch

3) run the theme switcher app from Terminal, and use it to change themes
switch2

Optional:
4) Install themes 
  • Some great ones can be found at http://gnome-look.org/
  • You can also search MacPorts for themes (try: port search gnome-themes)
(End Summary)

5) Additional notes
Updating themes might break some GTK-based programs. For instance, if Inkscape looks ugly rather than looking like the theme you set, it is because Inkscape only supports variants of the "Clearlooks" theme in OS X (at least for version 0.48). A solution to this would be to launch applications using their own themes, but for now this is out of the scope of this how-to.

To find out a little more on how this theme switch works, (and how to possibly do it manually), you can google up on the configuration file in your home folder named ".gtkrc-2.0".

Incorrect time on received text messages

Ever since Feb 29 (coincidentally), my smartphone had suddenly begun showing weird behavior for received text messages. For instance, if I sent a message at 8pm and immediately got a reply, it would show up as 3pm. Aside from the inconvenience factor, for some phones this can be a problem if "conversation" views are used as replies and sent messages do not appear one after another.

Diagnosis:
It turns out that recently, my service provider had a cell that had its time zone programmed wrong and because my phone was set to automatically update date, time, and time zone from the cell phone company, it updated my phone's time zone to the wrong zone.

Solution:
A quick fix was to manually set my phone's time zone and stop it from automatically updating. This seemed to fix the problem.

Final Thoughts:
This post is not really a definitive solution for all causes of this problem. Rather, it is meant to talk about one possible cause of this problem (and a solution for that cause), just in case someone out there hadn't thought of this cause while trying to debug their own phone or debugging an app for texts.

Saturday, 3 March 2012

jquery .val() after key pressed

When entering data into a text input (for purposes such as auto-suggest), the following example code seems to always be one step behind, in other words .val() is called too early, i.e. seemingly before the keystroke is done:

$("#some-form-text-input").live("keypress", function(e){
  alert($("#some-form-text-input").val());
});


An example of why this is undesirable is: if the text field already contained the string "somethin" and "g" is typed next, the alert in the callback would only display "somethin" versus the desired "something".

Solution: use the "keyup" rather than the "keypress" event

E.g.

$("#some-form-text-input").live("keyup", function(e){
  alert($("#some-form-text-input").val());
});


This waits until the latest pressed key is lifted before firing the callback.

Handling the doctrine-fixtures interface update error

Got the following error after updating doctrine-fixtures:
Fatal error: Declaration of Translator\GFBundle\DataFixtures\ORM\StatementTranslationFixtures::load() must be compatible with that of Doctrine\Common\DataFixtures\FixtureInterface::load()

It turns out that doctrine-fixtures changed their interface for the load function from:
 interface FixtureInterface
    {
        load($manager);
    }


To:
use Doctrine\Common\Persistence\ObjectManager;

    interface FixtureInterface
    {
        load(ObjectManager $manager);
    }



... as seen in the included text file named "UPGRADE".


Solution:


To update your fixture files, simply add the "use" line in your fixtures file, and change all of your load() functions to include the ObjectManager bit.


Example:


... (other use statements) ...
load($manager){
  ... (code to load stuff ) ...
}


To:
... (other use statements) ...
use Doctrine\Common\Persistence\ObjectManager;

load(ObjectManager $manager){
  ... (code to load stuff) ...
}

Symfony 2 Doctrine Fixtures TRUNCATE (rather than DELETE) hack

Symfony2 fixtures clears database tables prior to populating them with fixture data. In the (earlier) version of doctrine-fixtures we tried, tables would refuse to be cleared if there were foreign keys, or indexes would not reset due to using SQL DELETE versus TRUNCATE.

This behavior might be fixed by now, but just in case you have an older version, here's a quick hack around this problem.

Warning: don't do this hack if you're not sure what you're doing! These instructions aren't comprehensive. They're only complete enough for someone to figure out why the changes should work.

1) locate your ORM Purger
it should be in:
vendors/doctrine-fixtures/lib/Doctrine/Common/DataFixtures/Purger/ORMPurger.php

2) make the purge() function truncate
There should be some loop in purge() that looks like:
foreach($orderedTables as $tbl) {
            ... (old code for deleting tables) ...
}


update this to be something like the following, commenting out old code so you can undo if you messed up:
foreach($orderedTables as $tbl) {
  // stupid hack
  $this->em->getConnection()->executeUpdate("SET foreign_key_checks = 0;");
  $this->em->getConnection()->executeUpdate($platform->getTruncateTableSQL($tbl, true));
  $this->em->getConnection()->executeUpdate("SET foreign_key_checks = 1;");
}


The disabling of the foreign key checks is done so the tables can be truncated, otherwise SQL will not allow the truncate operation if your database have foreign key constraints set.


3) how to undo
Un-comment the old code if you commented it out, or reinstall doctrine-fixtures.


4) final thoughts
This isn't the best way around this doctrine-fixtures behavior, and it's only meant as a hack for the impatient.