Friday, 2 December 2011

Drupal 6: Enable/Disable the WYSIWYG Editor on Specific Forms

You will need your own custom module for this, in order to implement hook_form_FORM_ID_alter().

DISABLING
You can disable the WYSIWYG editor on any form by setting the FAPI (Forms API) setting #wysiwyg to FALSE e.g. for the Page node edit form, you can do this:
function MODULE_form_page_node_form_alter(&$form, &$form_state) {
    $form['body_field']['body']['#wysiwyg'] = FALSE;
}

ENABLING
  1. Some contrib modules (e.g. Ubercart) have completely disabled WYSIWYG editors on some of their textareas, and I haven't found a way around this.
  2. If you have checked the "Enable by default" option, the WYSIWYG editor should automatically be enabled for any form fields that have the "Input format" option below them.
  3. For other forms (with simple textareas that dont have the "Input format" option) you must manually enable the "Input format" option yourself. This can be done by again altering the $form object in your hook_form_FORM_ID_alter() e.g. for the Description field on the form to edit a content type:
function MODULE_form_node_type_form_alter(&$form, &$form_state) {
    $form['identity']['format'] = filter_form();
}


Update: if you're more into GUIs than fiddling in the code, you could just install the Better Formats module, which gives you loads of control on which Input formats are used for which forms. Then by having one plain-text input format, and another one associated with a WYSIWYG editor, you can easily control which forms use which.

Drupal 6: hook_form_node_form_alter() not working

I've long known about the versatile hook_form_alter() function, which allows you to alter any form before it gets displayed on the page, using your own custom module. Recently I discovered the wonderful hook_form_FORM_ID_alter() function, which is only fired for a specific form id, making it a better solution when you want to target only 1 form.

I had used this successfully a few times, and then hit a wall when I tried using it for the main node edit form (the form's id is node-form, so I called the function hook_form_node_form_alter). Half an hour later, I stumbled upon the solution: it does not want the HTML ID attribute, it wants the internal Drupal ID for the form. So in my custom module, I used this code to get the ID:

function MODULE_form_alter(&$form, &$form_state, $form_id) {
 echo "formID=".$form_id;
}

Which turned out to be page_node_form, so the final function that worked was called MODULE_form_page_node_form_alter().

REFERENCES
http://www.hashbangcode.com/blog/drupal-hookformalter-node-form-501.html

Saturday, 12 November 2011

Problems cloning a GitHub repo using Egit on Eclipse 3.6.2 Helios


Eclipse 3.6.2 Helios
Egit 1.1.0
Ubuntu 11.10 Oneiric Ocelot

ERROR: when adding public repo (on github) to clone, does not accept SSH key password (just keeps asking for it again and again)

SOLUTION: https://bugs.eclipse.org/bugs/show_bug.cgi?id=326526
Then add to your .bashrc:
export GIT_SSH=/usr/bin/ssh
(and reload it with a "source .bashrc")
If it still doesn't work, try re-creating SSH keys through eclipse (Prefs>General>Network>SSH2) and use those keys for authentication (you have to add the public key to github again)


ERROR: on commit:
Unhandled event loop exception
No more handles [MOZILLA_FIVE_HOME='/usr/lib/xulrunner-addons'] (java.lang.UnsatisfiedLinkError: Could not load SWT library. Reasons:
/home/jack/programs/eclipse_v3.6.2/configuration/org.eclipse.osgi/bundles/203/1/.cp/libswt-mozilla-gtk-3659.so: libxpcom.so: cannot open shared object file: No such file or directory
no swt-mozilla-gtk in java.library.path
Can't load library: /tmp/swtlib-32/libswt-mozilla-gtk-3659.so
Can't load library: /tmp/swtlib-32/libswt-mozilla-gtk.so
/tmp/swtlib-32/libswt-mozilla-gtk-3659.so: libxpcom.so: cannot open shared object file: No such file or directory
)

SOLUTION: Ensure you have sun java installed: http://www.multimediaboom.com/how-to-install-java-in-ubuntu-11-04-natty-narwhal-ppa/
Then install xulrunner-1.9.2 (NOT v2.0) manually by downloading it from here (you will need to navigate to your version of ubuntu first, if it is not 11.10 Oneiric):
https://launchpad.net/ubuntu/oneiric/i386?text=xulrunner
Then install with this command:
sudo dpkg -i file.deb
Then add this line to your .bashrc:
export MOZILLA_FIVE_HOME=/usr/lib/xulrunner-1.9.2.17
(and reload it with a "source .bashrc")



ERROR: on push:
fatal: cannot exec '/home/jack/programs/eclipse_v3.6.2/plugins/com.aptana.git.core_3.0.0.1303919605/os/linux/askpass.tcl': Permission denied
SOLUTION: just change permissions to 777

NEXT ERROR:
exec: 3: wish: not found
SOLUTION: http://sysadmin.circularvale.com/desktop-config/getting-git-working-in-aptana-on-ubuntu/
Basically install these packages: tk and python-tk

Android 2.3 Gingerbread - Get your own profile picture in text message conversations

Phone: HTC Desire S
OS: Android 2.3.3 (HTC Sense 2.1)

If in text message conversations, your friend's profile pictures are showing up, but your own one isn't, you need to setup the "My Profile" contact. To do this, click People, then at the top, click My Profile (not the button to the right of it). Then either select a photo manually, or if you already have yourself as a regular contact with a picture, then hit Menu > Import and then select yourself.

REFERENCE: http://code.google.com/p/android/issues/detail?id=3898

Thursday, 27 October 2011

Using CSS rgba() values for background-color in IE6+

You can use rgba values for background colors in IE6-9 with a simple Microsoft filter in your CSS. You can even find an amazing interactive tool to help you generate all this code here: www.css3please.com

.black-semi-transparent {
  background-color: transparent;
  background-color: rgba(0, 0, 0, 0.5);  /* FF3+, Saf3+, Opera 10.10+, Chrome, IE9 */
            filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#7F000000,endColorstr=#7F000000); /* IE6–IE9 */
            zoom: 1;
}

Sunday, 16 October 2011

Ubuntu 11.10 - Show Desktop Keyboard Shortcut

I couldn't find the keyboard shortcut / hotkey for minimising all windows. Turns out it was renamed to "Hide all normal windows". This can be found in Keyboard settings, under the Shortcuts tab.

Wednesday, 28 September 2011

Ubuntu 10.04 Lucid - notify-send in crontab not working

Alternative title: How to harness Ubuntu's black notification bubbles to set yourself repeating reminders

I recently found the wonderful command notify-send, which you can use to create those black Ubuntu notifications in the top right of the screen e.g. notify-send "Message Title" "This is my message." (you may need to install libnotify-bin). I then tried to shove this in my crontab to remind me to do stuff (e.g. take a short break every hour) but it didn't work.

Turns out that from the crontab, you have to tell it which DISPLAY to use, and luckily this turned out to be quite simply. All you need to do is add this prefix: DISPLAY=:0.0. So my crontab now looks like this:
# m h dom mon dow command
0 * * * * DISPLAY=:0.0 notify-send "Have a break" "Have a Kit Kat"

Thursday, 8 September 2011

Ubuntu 10.04 Lucid - Keyboard Shortcut to move window to other monitor (output)

I have a dual-monitor setup, and have always wanted to be able to move a window to another screen using a keyboard shortcut / hotkey. Turns out it is really easy:

CCSM (Compiz Comfig Settings Manager) > Put > Put to next output

I set it to <Ctrl><Alt>Enter

Saturday, 3 September 2011

jQuery slideDown() doesn't work on elements with CSS min-height

jQuery v1.6.2

I have an empty div with min-height defined in the CSS. When I use jQuery's slideDown() on it, it doesn't work - the div just instantly appears. Here is the workaround:

var myMinHeight = myElement.css("minHeight");
myElement.css({minHeight: 0}).animate({height: myMinHeight}, "fast", function() {
   $(this).css({minHeight: "", height: ""});
});

First we grab the CSS min-height value. Then we overide it, setting it to 0, and animate our div to the given min-height. At this point, we have what we want, but our CSS is messed up (e.g. say our CSS min-height was originally 120px, now our div will have a fixed height of 120px). This means if we add more content to the div, it cannot grow like we want it to (the very reason we were using min-height in the first place). The solution is simply to reset jQuery's inline style values (see line 3), after which it seamlessly reverts to your original CSS values.


REFERENCES
http://docs.jquery.com/Tutorials:Getting_Around_The_Minimum_Height_Glitch
http://jsfiddle.net/jitter/mLHb9/1/

Thursday, 18 August 2011

Google Chrome on Ubuntu 11.04 Natty - Your profile could not be opened correctly

For me this was due to ghost chrome processes still running. Close chrome, and type:
ps aux | grep chrome
I had output like this:
16660 ?        00:00:15 chrome
16666 ?        00:00:00 chrome
16668 ?        00:00:00 chrome
18159 ?        00:00:11 chrome
18165 ?        00:00:00 chrome
18167 ?        00:00:00 chrome
Then kill em all!!! e.g. to kill the first one (process id 16660), type:
kill 16660
Then when you restart chrome, it should be able to load your profile properly again.

Tuesday, 16 August 2011

Load event for Google Maps Javascript API V3

Use this JavaScript event listener to know when your Google Map finishes initialising.

google.maps.event.addListener(map, 'idle', function() {
   ...
});

REFERENCES
http://code.google.com/p/gmaps-api-issues/issues/detail?id=1516

Saturday, 6 August 2011

Android 2.2 Froyo - Only Enable Auto-Sync when Connected to WiFi

I achieved this using an app called Tasker (currently £4).

1) New profile: on the Tasker homepage, click the plus icon to create a new profile, and don't bother entering a name.

2) Choose the context: go State > Net > WiFi Connected and click the green tick icon to confirm.

3) Select task: you then have to create a task to run when this context is active. There should be a "Task Selection" popup, and you need to click New Task, and again you don't need to bother with a name. Then you should be on the Edit Task page. Click the plus icon to add an action > select Net > AutoSync > Select On and accept. Finally, finish the task by clicking the tick icon.

4) Repeat steps 1-3 for the AutoSync Off task i.e. set the context to be WiFi Connected, but then check Invert on the next page, and set the Task to be AutoSync Off.

That's it - your AutoSync should turn on when you connect to a WiFi network, and off again when you disconnect.


Alternative Apps
-Locale (with a plugin) - expensive at over £6
-AutoSync Account Activator - FREE, and looks good (though I haven't tested it), but too fine-grained controls (i.e. must set individual sync rules for each sync account rather than just overall enable/disable Auto-Sync, ALSO must select specific WiFi networks as triggers, rather than just overall "WiFi connected")
-Toggle Settings - FREE, but not very intuitive interface - I gave up quite quickly.

If anyone can figure out how to achieve this behaviour using a free app, then please let me know in the comments!

Wednesday, 20 July 2011

PHP Doctrine 2: Convert UK date string to datetime

You have a form with a date field, and on submit you want to save the value as a Doctrine Datetime. You may find PHP's strtotime() function, but this will only work for dates in the US format (e.g. mm/dd/yyyy) and not the UK format (e.g. dd/mm/yyyy). The solution is to use DateTime::createFromFormat() which lets you specify the way the date string is formatted.
$result = DateTime::createFromFormat("d/m/Y", $dateString);
This can then be set as your datetime property on your entity, and persisted in the database. You can see which letters to use to represent your date format here.

Wednesday, 13 July 2011

PHP autocomplete / code assist in Eclipse

I've been programming in PHP a lot recently, and the main issue I've been having is that Eclipse finds it difficult to auto-complete e.g. suggest methods that can be run on an instance of a class. This article shows you how to fix this using PHPDoc to give Eclipse more type information. Note: it assumes you have a User class on your include_path.

You can declare types for arguments to functions. Note: ignore the double spacing - it is a bug with the FogBugz wiki
function myFunction(User $user) {
$user-> // this will now autocomplete
}

You can declare return type of functions
/** @return User */
private function getUser() {
return new User();
}

public function run() {
$user = $this->getUser();
$user-> // this will now autocomplete
}

You can declare the type of class properties (AKA fields), accessed with $this->var. Note: you can also do this inline above the property itself, using @var instead of @property, BUT annoyingly the PHPdoc has to be in the 3 line form (doesn't work if you shorten it to 1 line e.g. /** @var User $user */)
/**
* @property User $user
*/
class myClass {
protected $user;
function myFunction() {
$this->user-> // this will now autocomplete
}
}

You can declare the type on variables in the code
/* @var $user User */
$user-> // this will now autocomplete

Zend Log: Log to a file, formatting output, logging request details, and all error info

Wham this in your Bootstrap.php (replacing YOUR_WEBSITE):
protected function _initLogger() {
$writer = new Zend_Log_Writer_Stream('/var/log/YOUR_WEBSITE/output.log');
$format = '%timestamp% %priorityName%: %message%' . PHP_EOL;
$formatter = new Zend_Log_Formatter_Simple($format);
$writer->setFormatter($formatter);
$logger = new Zend_Log($writer);
$logger->setTimestampFormat("d-M-Y H:i:s");
Zend_Registry::set('logger', $logger);
}
Functions starting with _init will automatically be run during the bootstrap. This will setup the logger to log to a file in your logs directory, with a slightly clearer format than the default one (inc. simplified date format). It then saves the logger instance in the Zend_Registry, which means we can access it from our controllers!

Now in your Controller:
class IndexController extends Zend_Controller_Action {
private $logger;
public function init() {$this->logger = Zend_Registry::get('logger');}
public function indexAction() {$this->logger->info("Hello");}
}

Next, lets setup our logger to log the details of all requests, as this is really useful for debugging. We do this with a Controller Plugin, by implementing the preDispatch function (create application/plugins/Logger.php):
class Application_Plugin_Logger extends Zend_Controller_Plugin_Abstract {
public function preDispatch(Zend_Controller_Request_Abstract $request) {
$uri = $_SERVER['REQUEST_URI'];
if ($uri != "/favicon.ico") {
$logger = Zend_Registry::get('logger');
$logger->info("* REQUESTED URI ".$_SERVER['REQUEST_URI']
    .", CONTROLLER ".$request->getControllerName()
    .", ACTION ".$request->getActionName());
}
}
}
Note: we don't bother logging browsers requests for favicon.ico, as they are not very interesting

Then we need to register the plugin, which we do back in our bootstrap, at the end of _initLogger():
$front = Zend_Controller_Front::getInstance();
$front->registerPlugin(new Application_Plugin_Logger());

Finally, we setup the ErrorController to log all error information by adding this code to errorAction():
$logger = Zend_Registry::get('logger');
$params = $errors->request->getParams();

$paramsString = "array (\n";
foreach($params as $key=>$value) {
$paramsString .= "'".$key."' => '".$value."'\n";
}
$paramsString .= ")";

$logger->crit("ERROR = ".$this->view->message."\n"
    ."MESSAGE = ".$errors->exception->getMessage()."\n"
    ."STACK TRACE = \n".$errors->exception->getTraceAsString()."\n"
    ."REQUEST PARAMS = ".$paramsString);

Monday, 27 June 2011

Gnome-do Suspend not working in Ubuntu Lucid 10.04

I love Gnome-do, but the version in the Lucid repo stopped at 0.8.3.1 (and 0.8.2.1 for gnome-do-plugins), which had a bug that meant Suspend didn't work (from the Session Management plugin). After noticing this had been fixed in a later version, I resorted to grabbing the latest version of the source code and compiling it myself. This was a surprisingly easy task.

1) Get the dependencies (including Bazaar which you need to download the source code)
sudo apt-get install bzr
sudo apt-get build-dep gnome-do
sudo apt-get build-dep gnome-do-plugins
2) Download the source code
bzr branch lp:do gnome-do
bzr branch lp:do-plugins
3) Install (do this for both of the new directories)
cd gnome-do
./autogen.sh
make
sudo make install
4) Restart gnome-do and enable GNOME Session Management plugin

Note: I actually left the old repo versions installed, in the hope that there may be some dependencies fulfilled. Hopefully this wont cause any headaches in the future (it hasn't so far).

Sunday, 5 June 2011

Ubuntu 11.04 Natty - Slow Alt+Tab Window Switcher

If you regularly use the Alt+Tab window switcher, and find it is annoyingly slow to launch, simply go into the Compiz Config Settings Manager (you will need to install this if you havent already - it's in the repos), and look under Window Management > Static Application Switcher and then click the Behaviour tab, and set the Popup Window Delay to 0.

Rather odd that it would be set to anything else if you ask me...

Friday, 3 June 2011

Minify JavaScript in Eclipse with Google Closure Compiler

Recently I decided it was time to start minifying my jQuery scripts before deploying them to decrease download time. After lots of research, I found Google Closure Compiler, which not only minifies, it also obfuscates and even optimises your scripts (dead code removal etc)! The best place to get this done is within Eclipse, and you can do it using a plugin by Rock Star Apps. Details here: http://update.rockstarapps.com/index.html.

Basically, add this URL to your Eclipse Software Sites: http://update.rockstarapps.com, and install Rockstar Web Optimizer. You should then be able to right click a Javascript file and go Rockstarapps > Compress and you get loads of options like Google Closure Compiler, YUI Compressor etc.

You can even tell it to auto-build. When you are on the options screen, select "Automatically recreate file when one of it's dependencies changes", and then it will rebuild every time you save the source file.

UPDATE: sadly it appears rockstarapps are no more. If anyone knows of another way to achieve this, I would be very grateful!

Wednesday, 1 June 2011

CentOS php-config: command not found

If you try using php-config, and you get the error: "command not found", you just need to install php-devel.
sudo yum install php-devel

Friday, 20 May 2011

Ubuntu 11.04 Natty - Changing the Number of Workspaces

OS: Ubuntu 10.04 Natty Narwhal

By default, Natty comes with 4 workspaces, which you can view by clicking the Workspace Switcher icon in the Unity Launcher. I personally don't like using multiple workspaces, so I wanted to change this to 1, so I didn't accidentally move windows to hidden workspaces (with hotkeys etc.) never to find them again. Others of you may want to reduce the number to 2, or even increase the number. An easy way to do this is with the Compiz Config Settings Manager, but if you don't have this installed, you can do it with gconf-editor.
  1. Hit F2 and type gconf-editor
  2. Navigate to apps > compiz-1 > general > screen0 > options
  3. Update the number of workspaces by changing the values of the variables hsize and vsize, which represent the horizontal and vertical number of workspaces respectively (I set both of mine to 1)
Note: if like me you only want to have 1 workspace, you probably will also want to get rid of the Workspace Switcher icon in the Unity Launcher. Once you have followed the above instructions, all you have to do is log out and back in again and the icon will be gone!

Wednesday, 18 May 2011

Banshee Notification Area Icon in Ubuntu 11.04 Natty

My favourite extension for Banshee is called Notification Area Icon, which lets you control Banshee from an icon in the panel (left click will restore / minimise to tray, and right click will give you music controls). Unfortunately this stopped working after I upgraded to Ubuntu Natty.

To get it working again, you need to put Banshee in the Unity panel whitelist, which you can check with the following command.
gsettings get com.canonical.Unity.Panel systray-whitelist
Mine read as follows:
['JavaEmbeddedFrame', 'Mumble', 'Wine', 'Skype', 'hp-systray', 'scp-dbus-service']
To update this, you must append 'banshee' to the end of the list, and set it like so:
gsettings set com.canonical.Unity.Panel systray-whitelist "['JavaEmbeddedFrame', 'Mumble', 'Wine', 'Skype', 'hp-systray', 'scp-dbus-service', 'banshee']"
And then you will need to do a restart.


REFERENCES
http://fossplanet.com/f10/%5Bbug-777112%5D-%5Bnew%5D-notification-area-icon-not-working-ubuntu-11-04-banshee-2-0-0-a-154634

Adding a Custom App to the Unity Launcher

OS: Ubuntu 11.04 Natty Narwhal

I use a custom version of Eclipse, which I simply download from their website, extract to somewhere in my home directory, and then I can run the executable. If you want to integrate something like this with the new Unity launcher in Natty, you can do so by following the instructions below:
  1. Open the dash and run "Main Menu".
  2. Create a "New Item" in a suitable location (e.g. Applications > Programming).
  3. Leave the Type set to Application. Give it a nice readable Name, and then for the Command, simply type the path to your executable. You can also add an icon by clicking the springboard button.
  4. You should then be able to invoke the Dash, and type the Name you entered before, and your app should appear. You can then drag it into the Launcher.

Wednesday, 4 May 2011

Problems with jQuery fades using semi-transparent PNG images in IE8

I had some PNG images containing some semi-transparency (there were parts that were not completely transparent i.e. a shadow). I then used jQuery to fade between these images, as shown in the code below. This worked in all browsers except for IE, which showed a dark grey ring around each image while it was fading (it looked fine before and after each animation). I think IE was replacing each semi-transparent pixel with a fully opaque dark grey one. The solution was to apply Microsoft's AlphaImageLoader filter to each image, as shown in the CSS at the bottom.

HTML

JQUERY
setInterval(function() {
   var $active = $("#header-splats .active");
   var $next = $active.next().length ? $active.next() :
                                $("#header-splats div:first");
        
   $active.fadeOut("slow", function() {
      $active.removeClass('active');
   });
   $next.fadeIn("slow").addClass('active');
  
}, 3000);

CSS
#header-splats, #header-splats div {
   width: 106px;
   height: 106px;
}
/* overlap each other */
#header-splats div {
   position: absolute;
   top: 0;
   left: 0;
   display: none;
}
#header-splats div.active {display: block;}

This looks great in all browsers except IE, as you can see in these images:


THE SOLUTION: apply the following Microsoft filter in the CSS to each image (make sure you update the image path for each one).

CSS
#splat-1 img {filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled='true',sizingMethod='crop',src='/images/splats/splat1.png');}
#splat-2 img {filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled='true',sizingMethod='crop',src='/images/splats/splat2.png');}
#splat-3 img {filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled='true',sizingMethod='crop',src='/images/splats/splat3.png');}

Friday, 22 April 2011

Wireless Sync Music between Ubuntu PC and Android Phone

PC: Linux - Ubuntu 10.10 Maverick
Phone: HTC Wildfire with HTC Sense for Android 2.2 Froyo

I have been looking for a good way to wirelessly sync music to my phone for ages. I tried various android apps that failed to meet my needs in one way or another:

-Winamp - need winamp client on PC - no version for linux
-DoubleTwist (AirSync) - only for iTunes
-Android Sync Manager WiFi - PC client requires winXP or above
-Dropbox - must upload all music to internet first (when dropbox syncs on PC), which takes AGES, AND cannot auto-download anything - have to select each song and long press>download (BUT could work with additional app "Sync Folder with Dropbox")
-SugarSync - no Linux client
-ZumoDrive - same as dropbox in that have to upload everything to the cloud first, and cannot auto sync a particular folder on android, so would have to manually download all songs

And then I found Syncness. It doesn't require a PC client as it connects straight to network shares over your WiFi. Requires minimal setup (see below), and then you can have a directory of music on your PC automatically syncing to your phone every night (or just manually whenever you want). It costs about £1, but is well worth it.


SETUP

Put some music in a dir on your PC, and share it: R click > Sharing Options (then it might ask you for permissions to install some sharing libs). Now open Syncness on your phone and create a new profile and give it a name e.g. Music. Click the "Share" folder icon, and let it scan your network for shares, and then select your share from the list. Next click the "Local" folder icon and select your Music dir (if you don't already have one, you may need to connect your phone to your PC and create it first). Set "Sync Type" to "Push To / Pull From Remote", check "Active" (so it appears in your "Active profiles" list), and also check "Allow file deletions", so it can wipe old music you don't want any more. Then enter your Ubuntu name/pass (I left Domain blank), and do Menu > Save. Then you can setup a sync schedule if you want, but I don't change my music that often, so I just do it manually by pressing the big blue SYNCHRONIZE button on the home-screen.

Android 2.2 Froyo - Moving contacts from Phone to Google

Phone: HTC Wildfire
OS: HTC Sense for Android v2.2 Froyo

Confusing contacts system: you can store your contacts in 3 different "accounts" on your phone: in your SIM card account, on your phone's native account, or in your Google account. Only contacts stored in the third list will be synced to your Google Contacts list (used in Gmail), and so really this is where you wanna store all of them.

So what if you already have some contacts in your "phone account"? Maybe you got sent a vCard in a text message and when you clicked it, it automatically got added there without asking (how annoying), or maybe when you first got your phone, you just imported all your old contacts to your phone account without thinking, and now want to move them to your Google account, so they sync.

The best way I have found of moving ALL contacts from your phone account to your Google account is as follows:

1) Save your "phone account" contacts to a file: go into your contacts list (called HTC People on the Wildfire), and do Menu > Import/Export > Export to SD, and select phone account.

Maybe you wanna connect your phone to your PC and backup this file and check it worked properly, as next we will be deleting the contacts from your phone! You can read more about this later in the article.

2) Delete all your phone account contacts: do Menu > View and only select "Phone", then do Menu > Delete, and then Menu > Select All...

3) Import your contacts to your Google account: Menu > Import/Export > Import from SD, then select Google account. If you did step 2, you will need to update your View preferences again to see contacts in your Google account.

Note: If you decided you wanted to backup your contacts file and check it was working, here is some advice:  The file will be stored in your SD card's root directory, with a name like "pcsc_pcsc_00001.vcf". One way to check the file works is to skip step 2, and just import them to your Google account. BUT then each contact is automatically "linked" to the corresponding one on the phone account, and so if you then delete all your phone account contacts, both of them will get deleted, and you will be left with nothing! Of course you then know you are safe to import them again.

Thursday, 31 March 2011

Drush - Backup and Migrate command documentation

Drush is an amazing command line tool for administrating Drupal. Backup and Migrate is a Drupal module which simplifies the process of backing up and restoring your Drupal database(s). When I found out that Backup and Migrate now includes Drush support, I was really excited, but then I could not find any documentation for it anywhere (at the time of writing, the documentation link on the module page was broken). Eventually I thought to try the command line, and found everything I needed in the drush help output, so thought I would post it here in case it helps others.

Commands
bam-backup - Backup the site's database with Backup and Migrate.
bam-backups - Get a list of previously created backup files.
bam-destinations - Get a list of available destinations.
bam-profiles - Get a list of available settings profiles.
bam-restore - Restore the site's database with Backup and Migrate.
bam-sources - Get a list of available sources.



bam-backup
Backup the site's database using default settings.

Examples:
drush bam-backup - Backup the default databse to the manual backup directory using the default settings.
drush bam-backup db scheduled mysettings - Backup the database to the scheduled directory using a settings profile called "mysettings"
drush bam-backup files - Backup the files directory to the manual directory using the default settings. The Backup and Migrate Files module is required for files backups.

Arguments:
source - Optional. The id of the source (usually a database) to backup. Use 'drush bam-sources' to get a list of sources. Defaults to 'db'
destination - Optional. The id of destination to send the backup file to. Use 'drush bam-destinations' to get a list of destinations. Defaults to 'manual'
profile - Optional. The id of a settings profile to use. Use 'drush bam-profiles' to get a list of available profiles. Defaults to 'default'



bam-backups
Get a list of previously created backup files.

Examples:
drush bam-backups manual - List of backup files currently in the destination called "manual"

Arguments:
destination - Required. The id of destination to list backups from. Use 'drush bam-destinations' to get a list of destinations.



bam-destinations
Get a list of available destinations.



bam-profiles
Get a list of available settings profiles.



bam-restore
Restore the site's database with Backup and Migrate.

Examples:
drush bam-restore db manual "LCC-31.03.2011-14.01.59.mysql.gz" - restore the default database using the given dump file, which can be found in the destination called "manual"

Arguments:
source - Required. The id of the source (usually a database) to restore the backup to. Use 'drush bam-sources' to get a list of sources. Defaults to 'db'
destination - Required. The id of destination to send the backup file to. Use 'drush bam-destinations' to get a list of destinations. Defaults to 'manual'
backup id - Required. The id of a backup file restore. Use 'drush bam-backups' to get a list of available backup files.



bam-sources
Get a list of available sources.



Closing Notes
I'm not sure if this is out of date or something, but in my experience you provide the name and not the id for all of the arguments.

Drupal 6 - Drush warning about orphaned actions

When I was executing drush commands, I got a warning similar to this:
WD actions: 2 orphaned actions (comment_unpublish_action, comment_publish_action) exist in the actions table. Remove orphaned actions
Solution is to use a badly-documented Drupal feature which automatically removes all orphaned actions. Simply visit the following hidden URL on your drupal site: yoursite.com/admin/settings/actions/orphan, and it will remove any orphaned actions and forward you to the Manage Actions page, where you will see they are no longer listed!


REFERENCES
https://drupal.org/node/445922#comment-2977526

Thursday, 24 February 2011

Drupal 6 - Webforms: Loading GIF on Submit

If you have a slow mail server, then submitting webforms can sometimes appear to do nothing for a while. For me, this is anywhere between 2 and 8 seconds, but I have read about a lot of other people in similar situations. While the problem is with the mail server, sometimes there's nothing that can be done about this, and a simple solution to keep the user calm is to add a little loading animation. No Ajax involved: the GIF is simply shown when the user clicks submit, and then after the wait, they will be taken to the success page.

1) Grab the right GIF animation from this amazing site: http://ajaxload.info/ and put it here: /sites/all/images/loading.gif

2) The CSS: make it so that the GIF is used when a certain class is applied to an input element
input.form-submit.loading-gif {
 background: url('/sites/all/images/loading.gif') 50% 1px no-repeat;
}

3) The jQuery script: in your theme dir, create js/submit-loading.js which will apply the CSS class to the submit button when it is clicked
$(document).ready(function()
{
    // preload image
    (new Image()).src = "/sites/all/images/loading.gif";
    
    $(".webform-client-form").submit(function() {
        // select the button
        var $button = $(this).find("#edit-submit");
        // remove the text, but persist the width of the button
        var $buttonWidth = $button.outerWidth();
        $button.attr('value', '').width($buttonWidth);
        // display the loading gif and disable the button
        $button.addClass("loading-gif").attr('disabled','disabled');
    });
});

4) Add the script only to the right page with a bit of PHP in your theme's template.php. See #2 in my article: Different ways of adding JavaScript to a page

Tuesday, 22 February 2011

PHP Logging on Ubuntu 10.04 Lucid

PHP CONFIGURATION
Enable PHP logging by setting up the appropriate variables in your php.ini. If you don't know where your php.ini file is, try the command: locate php.ini, mine was here: /etc/php5/apache2/php.ini:
error_reporting = E_ALL & ~E_DEPRECATED
log_errors = On
error_log = /var/log/apache2/php_errors.log
EXTRA: if you want to show PHP errors on screen, set:
display_errors = On
To finish, we restart apache: sudo /etc/init.d/apache2 restart


PERMISSIONS
Then find out what your apache user is called: ps aux | grep apache (mine was www-data), and ensure that user has full permissions on the log file directory (/var/log/apache2/). The best way to do this is ensure the user has group access i.e. either add the user the group currently assigned to the directory, or change the directory's group to one that the user is in! On my system, the directory had the group: adm, and so I added www-data to that group (see /etc/group). You then need to give the directory full permissions for group access: sudo chmod 770 /var/log/apache2/

To register these changes, we need to log out and back in again.


TESTING
An easy way to generate a PHP error is to call an undefined function i.e. put this PHP code into one of your pages:
a_function_that_doesnt_exist();
Now when you visit that page, you will either get a PHP error on screen (if you enabled that), or your browser will just display a 403 error, but importantly, your new log file php_errors.log should have been created and had it's first error logged.


INLINE PHP CONFIGURATION
One other method worth noting is inline configuration. During development, you may decide you want to temporarily enable showing errors on the screen for a particular page. The easiest way to do this, is simply to add this line of PHP to the top of your PHP file:
ini_set('display_errors', TRUE);

Wednesday, 2 February 2011

Drupal 6: Different ways of adding JavaScript to a page

REMEMBER
  • Always use drupal_add_js() as this lets Drupal handle it i.e. preprocess/cache it.
  • All of the examples assume your JS is in a script file, but you can also include an "inline" script by sending it as a string for the first argument, and setting the second to "inline" e.g. drupal_add_js('alert("Hello!")', 'inline');
  • If your script is in your theme directory, you can use path_to_theme() and then the relative path from there (with a preceding slash) e.g. path_to_theme().'/js/myscript.js'

1) Add a script to all pages
a) using template.php
drupal_add_js('sites/all/scripts/tweaks.js');
b) using your theme's .info file (the script needs to be somewhere within your theme directory)
scripts[] = script.js

2) Add a script to page(s) with a specific URL / URL pattern using template.php (the following will only add the script on site.com/my/page)
NOTE: if you are using URL aliases, you need to know the un-aliased version for this (see site.com/admin/build/path)
function mytheme_preprocess_page(&$vars) {
  if (arg(0) == 'my' && arg(1) == 'page' && arg(2) == null) {
    drupal_add_js(path_to_theme().'/js/myscript.js');
    $vars['scripts'] = drupal_get_js();
  }
}
OR use the following condition to add it to any pages that start with the URL site.com/my/page e.g. /my/page/1, /my/page/2, /my/page/2/edit etc.
if (arg(0) == 'my' && arg(1) == 'page') {...}
OR use the node ID
if (isset($vars['node']) && $vars['node']->nid == 23) {...}
OR apply to all nodes of a specific content type
if (isset($vars['node']) && $vars['node']->type == 'book') {...}

3) Add a script to a specific page by editing the page in Drupal, and setting the input format to "PHP code"
drupal_add_js('sites/all/scripts/tweaks.js');

4) Add a script to a block, which you can then setup to be included in a specific page or set of pages
drupal_add_js('sites/all/scripts/tweaks.js');


Also note that it is very similar to add stylesheets to pages. The function is drupal_get_css().


REFERENCES
http://drupal.org/node/304178
http://api.drupal.org/api/drupal/includes--common.inc/function/drupal_add_js/6
http://stackoverflow.com/questions/61735/include-css-or-javascript-file-for-specific-node-in-drupal-6

Wednesday, 26 January 2011

Installing Sass on Ubuntu 10.04 Lucid

Sass is a CSS extension that enables you to use variables, nested rules etc. To install it, see their website. If like me, you just try the first command they give you before installing ruby, you will get this:
The program 'sass' is currently not installed. You can install it by typing:
sudo apt-get install libhaml-ruby1.8
Don't do as it says and install libhaml-ruby1.8, as you end up with an old version of Haml/Sass: 2.2.17. Instead, you first need to install Ruby and RubyGems, which is simple:
sudo apt-get install rubygems
Next, we install Sass using RubyGems (thanks for tip from Boyd Hemphill):
sudo gem install sass
You should now have Sass installed, but if you try to use it, you may still get the original "not installed" message. This is because annoyingly the RubyGems binaries directory is not automatically added to your PATH. To do this, I simply added the following to the end of my ~/.bashrc file:
export PATH=$PATH:/var/lib/gems/1.8/bin
Then restart your terminal and that should be it. You can check that it installed successfully, and that you have the latest version with the following command:
sass -v
I get the following output: Sass 3.1.15 (Brainy Betty). You can then follow the rest of the tutorial on their website to start compiling .sass files into .css files.

Additionally, see this blog post for a great walk-through in refactoring existing CSS to Sass.

Monday, 24 January 2011

Android Calendar - Duplicate Facebook Birthdays

Device: HTC Legend
OS: Android 2.2 Froyo (with HTC Sense)

In my calendar, I had 2 entries for every birthday on my Facebook calendar. If I went into the calendar options and hid the Facebook calendar, both entries disappeared. I've learnt that this calendar is populated by the Facebook for HTC Sense app.

The solution was to remove the account in my sync settings (Settings>Accounts & sync>Facebook for HTC Sense), do a full sync, and then re-add it the account. My contacts remembered all the facebook link information too, so after re-adding the account and doing a full sync, everything was back just the way it was (inc Facebook pictures in my contact list) except no more duplicate birthday events in my calendar!


REFERENCES
http://www.htcforums.com/android-applications-games/6762-duplicate-facebook-birthday-calendar.html