Monday, 1 September 2014

Save a zip file to a node.js server using node-webkit

It was so incredibly hard to do this. And it shouldn't be. So here's the code you need to do it.


nodeFileSystem = require('fs');
API.downloadItrData(newBook.isbn, newBook.version).then(function(response) {
    if (response.status === 200 && response.data.success) {

        var zipLocation = response.data.data.zipLocation;
        var zipSaveLocation = Constants.PATH_BASE + Constants.PATH_ITR_FOLDER + newBook.isbn + "/" + newBook.version + ".zip";

        $http.get(zipLocation,
            {
                responseType: "blob"
            }
        ).then(function(zipResult) {
                var reader = new FileReader();
                reader.addEventListener("loadend", function() {
                    nodeFileSystem.writeFile(zipSaveLocation, toBuffer(reader.result));
                });
                reader.readAsArrayBuffer(zipResult.data);
        });
    }
});

Ok, but what does the code do? Keep in mind this is just a stub, so this is more of a non-working example rather than code that can be copied and pasted into your work.

First, using an API, I check to see if my book (basically, an ebook) has an update. If it does, I take from the returned JSON to the location of the zip file (zipLocation), which I am going to save to the server (zipSaveLocation).

I then use the angular function $http.get() to download the zip. By setting the responseType in the config I can get the zip file as a "blob" instead of a string.

Once it has downloaded (the promise function .then fires) I use the HTML5 FileReader class to convert the JS Blob to a JS arrayBuffer so it can be converted to a Node.js Buffer so the node filesystem can save it.

I really hope this saves someone the 6 hours or so it took me to figure out :)


Tuesday, 27 May 2014

Giving Back

So, after a long time between drinks, I've contributed to an open source project again. OctoberCMS. Let me explain why.

The first time was years ago, when I created a Joomla plugin called Menu Module Clone, to help users copy module settings between pages. At least, that's what I think it did. It's been a long time.

Recently, I've been keeping an eye on the php based CMS market. At work we went through a fairly rigorous process to narrow down the best CMS for our clients. Very very sadly, WordPress ended up winning. I say sadly because the code that it runs on is terrible. Joomla didn't get a look in as too many people didn't want it, and Drupal was just at the wrong point of it's development cycle for us to consider. If we'd gone down the road, would we have wasted a lot of time learning Drupal 7 before Drupal 8 came out? Probably. Especially since most clients just want a small site with a blog, and WordPress fits that bill very well.

Anyway, I digress.

OctoberCMS. It is awesome. At this point it is still in beta, and is definitely not ready for use in production. The sheer potential though is enough to get me very excited. So excited I ended up writing a plugin for it fill a perceived gap.

Menu Manager does exactly what it says. If you're interested, go and read up about it.

But why am I so excited?

I've done quite a bit of research over the last few months into the current state of the market. According to all the surveys I've seen, there are 3 big php frameworks. Symfony, Laravel and Phalcon. All 3 are pretty awesome. From where I sit though, doing very simple websites, I need a CMS rather than a framework. But because I also do love doing things the right way, I want it based on a modern php framework. There are quite a few CMS's built on these, but most are either based on old versions or are just not viable. Red Kite looked very promising, but the inability to get it running on my local Vagrant machine ruled it out. And I tried a lot of things.

However, when I found out about OctoberCMS I got more excited about coding than I had in a long time. And you should have seen me when I first found out how much nicer the sql will be with nested sets! It's backend structure is awesome and it gives you the ability to edit pages either in code directly or in the CMS. There is even inline editing.

You can also use markdown. But seriously?

So what have I learned writing my plugin? That I don't know how to use it mainly. But after scanning all the documentation and copying other people's code I'm finally confident that I can do basic stuff.

The only thing missing is to make this CMS a WordPress killer. I would dearly love to never use it again. I've also always wanted to get involved in an open source project, and I've finally found something that intersects with both what I want to learn and where I think I need to be to further my career.

So that's what I'm excited about. The change to get in at the ground floor on a new project that I think has the ability to transform the way we as a web development industry work. At this point it's just a plugin, but hopefully I can continue contributing and help the industry move forward.



Saturday, 15 February 2014

Symfony Project on Ubuntu 13.10, using PhpStorm

This is far more complicated than it should be, and I've not found a reliable guide on it. But this is what we're going to end up with:

A Symfony 2 project running under a puphpet controlled virtual machine using Vagrant. We're going to be able to edit the project and run all the commands via PhpStorm.

Technically you probably don't need the Ubuntu bit ... but there are some specific gotchas in here. I've included the version numbers I've used in parentheses where applicable.


  1. Install Vagrant (1.4.2
  2. Install Virtual Box  (4.3)
  3. Use PuPHPet to create your manifest file. 
    1. Create 2 virtual hosts. One just for flat files to make sure editing our host works fine, and one for Symfony. I call them flathtml.vagrant and symfony.vagrant, so I know what they're referring to. 
    2. The document root for these is /var/www/flathtml/ and /var/www/symfony/ respectively.
    3. These map to the folders /var/www/vagrant/flathtml/ and /var/www/vagrant/symfony/ respectively. 
    4. At least, they will if I run Vagrant from /var/www/vagrant/.
    5. The mapping is taken care of automatically in the PuPHPet manifest, in the "Box Sync" section.
  4. Download those files to wherever it is you want the virtual server to be. I chose /var/www/vagrant/ 
  5. In the Vagrantfile, fine the line that starts with "config.vm.synced_folder" and add ":mount_options => ["dmode=777,fmode=777"]" to the end. Otherwise Symfony will not run.
  6. Using terminal, in /var/www/vagrant/, run "Vagrant Up"
  7. That should work after a while.
  8. Edit your hosts file "sudo gedit /etc/hosts/" and add your two virtual hosts to the file. 
  9. The ip address is your Local VM IP Address. Most likely you left it as 192.168.56.101
  10. Get a test site with flat html working within Vagrant. This ensures that your Virtual server works.
    1. I ran into a problem here once of not being able to get the flat html site working, because the IP address I was being assigned came from DHCP, or similar. The trick is to change the Vagrantfile networking section. I can't remember the exact details of that fix sorry.
  11. Once that is working, then we can start with Symfony
  12. In Terminal, type "cd /var/www/vagrant/symfony"
  13. Install composer by "curl -s https://getcomposer.org/installer | php"
    1. Personally, I like to install it in a central location, such as /var/www/includes/. 
  14. Now install Symfony by "php composer.phar create-project symfony/framework-standard-edition /var/www/vagrant/symfony/ 2.4.*"
  15. You may have to apt-get install php5-json as well.
  16. Now we can initialise the project in PhpStorm. We couldn't earlier as the create-project command will fail if anything is in the folder.
    1. Set up all your version control stuff now.
    2. I found this guy has some very good tips on setting up as well. In particular, steps 3-8.
  17. In app_dev.php and config.php, remove the lines that stop people on none localhost accessing. This will allow you to get to the configurator and make sure everything is working.
There are a lot more things you should be doing, but this is enough to get you up and running at least. I hope this helps someone.

Sunday, 2 February 2014

PHPStorm, grunt.js and File Watchers

I had a pickle of a time getting grunt.js to work on my Mac. So eventually I gave up and decided to use PhpStorm's built in watchers to do my tasks.

I highly recommend you get this all working in Grunt first. Once things work as expected there, then you can set up PhpStorm.

Tested with PhpStorm 7.1.1, node 0.10.25, grunt-cli 0.1.13 and grunt 0.4.2.

Project Structure

In this project, we have a bunch of HTML sections that are baked together. For example, the header, nav, and footer are html files that are "baked" into a final file in the build directory. In a css subfolder we have all our css (/css/styles.less and /css/custom/, /css/vendor/ for Bootstrap) which are combined via Less into one final /build/css/styles.css file. And the JS files are also copied to the build folder.

LESS

This was by far the easiest. If you've already got this to work then you don't need any help. I simply had to change the default "Output paths to refresh" from "$FileNameWithoutExtension$.css" to be "$ProjectFileDir$/build/css/$FileNameWithoutExtension$.css" and it worked.

Grunt Tasks

This was the tricky bit, as I wasn't methodical enough. Assuming that you have installed grunt globally then the following settings will work. 
  • Name: Grunt Bake
  • Description: Builds HTML (obviously change these two to what you want them to be)
  • Turn off immediate file synchronization
  • File type: HTML files
  • Scope: Changed files. This is under VCS, probably at the bottom of the drop down. This stops the watcher being triggered when the file is created in the final build folder.
  • Program: On a mac, with grunt installed globally, it is /usr/local/bin/grunt. Run "which grunt" in your terminal to figure it out (sorry Window's users, I don't know the command for you).
  • Arguments: This is the name of the task. For me, I added this line to the Gruntfile.js. "grunt.registerTask('phpstorm-bake', ['bake'] );" Which means my argument is phpstorm-bake
  • Working directory: $ProjectFileDir$
That's it. 

It's beyond the scope of this article how to get grunt and it's associated tasks up and running. There are plenty of handy tutorials and documentation on the web for that already. 

Wednesday, 11 December 2013

Bootstrap Dropdown Mega Menu

Update: Just use this plugin https://github.com/CWSpear/bootstrap-hover-dropdown. It's most likely better tested than this hastily put together script.

I would just like to point out that I agree with the Twitter Bootstrap dev's, in that you should not be having the megamenu display on hover. That's paraphrasing their words but seems to be their general intent.

Now that that's out of the way, if you do want a Mega Menu that works on desktop and tablets, here is some code that may be of assistance. I'm pretty curious about it's behaviour on touch screen PCs, but as we don't have any to test with I can't check it :(

var topLevelLinks = jQuery('.dropdown-toggle');  // We're using bootstrap for the dropdown, but we need it to display on hover
    if (!Modernizr.touch) {
        // pseudo hover stuff
        topLevelLinks.on('mouseover', function(event) {
            topLevelLinks.removeClass('disabled');
            jQuery(this).dropdown('toggle').addClass('disabled');
        });
        // pseduo off hover
        jQuery('#menu-main-menu').on('mouseout', function() {
            jQuery('.dropdown-toggle.disabled').removeClass('disabled').dropdown('toggle');
        });
    }
    topLevelLinks.on('click', function(event) {
        if (jQuery(this).parent().hasClass('open')) {
            // stop the dropdown stuff and let the normal link stuff happen
            event.stopPropagation();
        }
    });

Wednesday, 27 February 2013

Installing Drupal (7.20) on Fortrabbit

Want to install Drupal on Fortrabbit? Here's how. Bear in mind these settings may change as Drupal get's newer or Fortrabbit matures/changes. Also, I've made some assumptions on how you want to do things. Your use case may be different, so have a read over things before following the steps.

I've assumed you have already installed git on your local machine. You're going to need it.

Login and create an App

We're going to login and create an app. Then we're going to set up git access for later.
  • Login in to Fortrabbit (or create an account)
  • Create the app in Fortrabbit
  • Give the app a name
  • Give the app a description (in the notes section)
  • Leave this window open for later.
  • Open the .ssh folder with "gitbash"
    • Open windows explorer
    • Right click on the folder that matches your username (you'll find in under Desktop)
    • Select the "gitbash" option.
  • If you haven't yet created all the ssh stuff, google "github generating ssh keys"
  • In git bash, run this command "clip < ~/.ssh/id_rsa.pub"
  • Move the cursor into "Your public SSH Key"
  • Paste the previously copied key info into this field (ctrl + v)
  • If you want to have login details emailed to you, enter the email address into the field
  • Click Save App Settings
  • Wait. This takes a little while.

SSH Access to the server (via a key-pair)

SSH access is gold. Unfortunately, for Windows Users it is a pain to set up. Follow this step by step guide, and make sure you have installed Putty and PuttyGen. You don't need PuttyGen if you like to try and remember your password every login. That works for some people.

Or you could set up a key value pair so you never have to remember the username/password combination again.
  • This may not work straight away, as the account needs to be verified. Come back in 5 minutes if it didn't.
  • Open Putty
  • In Saved Sessions, write a memorable name
  • Click Save
    • I do these two steps first so I always remember about it. You don't have to.
  • Put in the hostname (ssh1.eu1.frbit.com)
  • In category, expand "Connection" and click on "Data"
  • Put your username in the Auto-login username field
  • Go back to Session and click save
  • Click open
  • Type in your password
  • You're now connected. If you don't want to use a keygen pair, you're done. If you do, follow these steps
  • As we're using Putty, we need to create a keygen there
  • Open PuttyGen
  • Click Generate
  • Move the mouse cursor like a good developer
  • When it's generated, save the key
  • Right clock on the generated key
  • Select "select all" 
  • Right click and select copy
  • Go back to your connected shell
  • Type "cd ~/.ssh"
  • Then type "vim authorized_keys"
  • Press "i" to insert
  • Assuming your public key is still in your clipboard, right click and it will be copied into the file
  • Press "esc"
  • Type ":wq!"
  • This is now saved.
  • Exit the shell.
  • In putty, either create a new session or load the existing one
  • Expand "Connection", then "SSH" and click on "Auth".
  • Click on browse to select Private Key File
  • Select the previously saved file.
  • Go back to the session menu and save it
  • Open
  • You now have ssh access using a key (no more remembering passwords)

Installing Drupal

  • http://drupal.org/documentation/install/download has all the instructions you need to install Drupal. 
  • On Fortrabbit, you need to change the .htaccess file after you have moved and untarred everything.
    • Comment out line 14 of the .htaccess (Options +FollowSymLinks)'
    • This isn't allowed by the server settings, as it's already set.
  • Go to your apps URL and follow the prompts to install Drupal.

Getting mysql to work

  • Use MySQL workbench. Download it from Oracle. 
  • Create a new connection.
  • Set the conenction method to "Standard over SSH"
  • Use the SSH and MySQL details that FortRabbit supplied to connect. 
  • If you want to create/edit users, use the Model view. That's not intuitive.
Alright then. 

Enjoy the steps and let me know any steps I've missed.

Sunday, 9 December 2012

PhpStorm, Symfony 2 and GIT

I've recently started a new job, and after 2 years of using Ubuntu I'd had enough and wanted to try out Windows 7. Basically, I got sick of running two operating systems, and as my macbook is getting a bit long in the tooth I decided to try and get everything working under Windows 7. These instructions worked for me.
  • Install wampserver2
  • Download and install Composer using the Windows Installer option.
  • Download and install GIT (only if you're using it, but at some point in your development life you will be, so you may as well install it now
  • When installing GIT, make sure to select the middle option, that allows GIT to be run from the command line (the cli in some documentation)
  • Download and install the trial version of PhpStorm. You may not like it so no point paying until you have trialled it.
At this point you should have a working version of everything you need. Here's how to test it, to make sure everything actually works. 
  1. Use Composer to install the Symfony 2 framework. I'd highly recommend that you do this in the wamp/www folder to save yourself time.
    • On the Symfony website, they say to use composer.phar . It should be updated to read "composer". Composer installed a .bat file that will do all the hard work for you.
    • The "path/" in the command is the folder to install it into. If you're in the www folder, use "symfony" or something similar.
    • The full command to run from the c:\wamp\www\ folder is now "php compose create-project symfony/framework-standard-edition symfony/ 2.1.4"
  2. If you have yet to install GIT, you won't be able to install Ascetic. If GIT is installed correctly, then we also know that GIT is installed and working correctly!
    • If it failed at this point, then go back and install GIT. Then from the command line, run "composer update" in the c:\wamp\www\symfony\ folder.
    • This will read the composer.json file and download/update components. Most importantly, it will add in the missing components such as Ascetic as the git command is now available.
    • If for some reason that didn't work, close the command prompt window and try this again in a new one.
  3. Open PhpStorm
  4. Create a project, from existing sources, where we just installed Symfony 2 to. Select the bottom option, as the files are local and we don't yet have a server set up. 
  5. You should get a few "error" messages, as this is the first time you've worked with PhpStorm. It'll prompt you to say you're using the Symfony 2 framework. Follow the prompts to fix this.
  6. It will probably also say GIT is not installed. It's wrong, but click fix button.
  7. In the dialog, you'll see it's looking for "git.cmd". Change that to "git". Click the test button to prove it worked.
  8. Now, open the .gitignore file in PhpStorm
  9. At the bottom, add the lines ".idea/*". This folder is where PhpStorm keeps a record of stuff about the project, and we do not want this committed.
  10. Right click the name of the project in the left hand panel, and select GIT -> Add. This should add our entire directory to GIT. I like to do this so I can always tell what files I have played around with whenever I'm doing anything.
  11. Next, right click again, GIT -> Commit Directory. Now that we've added the files to the list of files to be indexed by GIT, we need to commit the files to the repository. (note, that is a very simple explanation of what a VCS does)
  12. Double check the .idea folder is ignored (i.e. There are no files to be committed from that directory)
  13. Mouseover the commit button, and select commit.
  14. I tend to ignore the review option but you may want to have a look to see what errors/todo's have been left in the code.
One last thing that you may find useful. Run a "composer update" from the root directory of the project. Changes are the version of Symfony 2 you've downloaded is slightly out of date, and this will go through and check everything.

That's it. I've assumed you're comfortable with the command line. If you're not, well, there's no time like the present to learn!

Leave a comment if I've missed a step or something isn't clear :)

Wednesday, 17 October 2012

LessCSS Auto-compile in PHP

I don't have the attributions for where this comes from but it works perfectly for me.

Include this code in your main template file, so it gets run every time.

PseudoCode: If we're on a development server, re-compile the css.


// Auto versioning using PHP, only when on localhost and debugging
if ($this->debug) {
    include($_SERVER['DOCUMENT_ROOT'].'/includes/autoCompileLess.php');  
    auto_compile_less($_SERVER['DOCUMENT_ROOT'].'/css/less/style.less', $_SERVER['DOCUMENT_ROOT'].'/css/styleCompiled.css');
}

This is the code for the autoCompileLess.php. It checks a cache file, and if that file is newer than my main LessCSS file it'll use the cache rather than re-compiling.

PseudoCode: Check the modified times of the cached compiled css, and if that is newer than the main less css file use the cache. Otherwise recompile all the less.


require 'lessc.inc.php';

function auto_compile_less($less_fname, $css_fname) {  
    $cache = $less_fname;
   
    // We may want to load from the cache
    $cache_fname = $less_fname.".cache";
    if (file_exists($cache_fname)) {      
        // Use the cache if the filetime is newer
        $cacheTime = filemtime($cache_fname);
        $fileTime = filemtime($less_fname);
        // If I managed to read both and the cache is still relevant, use it
        if ($cacheTime && $fileTime && $fileTime < $cacheTime) {
            $cache = unserialize(file_get_contents($cache_fname));
        }
    }

    $new_cache = lessc::cexecute($cache);
    if (!is_array($cache) || $new_cache['updated'] > $cache['updated']) {      
        file_put_contents($css_fname, $new_cache['compiled']);
        file_put_contents($cache_fname, serialize($new_cache));
    }
}

A bit of googling should get you all the necessary files you need. Perhaps this site, http://leafo.net/lessphp/, would be a good place to start.

Happy coding!

Friday, 20 July 2012

Code Readability

Or why I use ternary operations but never single line if statements.

This is a massive issue on collaborative projects. And since virtually every single piece of code you use will need to be modified / understood by someone else in the future, in my opinion everything you write should emphasise the readability rather than functionality.

Of course there will always be projects where speed is important, and you want to use the data structure that is fastest / most efficient.

As a professional software engineer (even if it is "just" websites) I am constantly working with other people's code. And it frustrates the hell out of me that people write code that is just so hard to understand.

A ternary operation is fairly trivial for any professional to understand. Even there though, the use of a variable name that explains where it comes from would be so handy!

One thing that annoys me though is single line if statements. Most IDE's allow you to format everything properly according to your conventions (we use Zend), and if everyone follows those it makes it much easier to follow the code when you have to fix a bug. But scanning code by eye for a line (I'm lazy like that) is made so much harder with single line if statements. Especially when you're checking for a value like: $_SESSION['carhire.search.dropoff_location'] .

The number of studies that have been done on the width of columns for readability is astonishing. Made your code more readable by using the following format always:

if (statement) {
    then do this
}

And comment your bloody code or I will curse you forever.

Saturday, 14 July 2012

Zend Form, and auto height of a textarea

Zend framework has it's uses. But gee it can be a pain at times.

If you don't have access to the decorators of the form, and you want to style your text areas better, this snippet should come in handy. Stupid scroll bars.

var textArea = "";
jQuery('textarea.info').each(function() {
                    textArea = jQuery(this);
                    textArea.removeAttr('rows');
                    textArea.removeAttr('cols');
                    textArea.css('height', this.scrollHeight + 'px');
                });

Pimcore, Helpers and Forms

It's taken me a while to get around to this, but I'm finally getting somewhere with this. Here's the code I've got. Underneath is an explanation of everything.

I've assumed you're using the formbuilder plugin for Pimcore with this code.
    
        
    public function init()
    {        
        parent::init();
        $this->_helper->addPath(PIMCORE_WEBSITE_PATH . '/views/helpers/cru', 'Website_Helper_Cru');
    }
    
    public function formpageAction()
    {
        // Make sure I want to display the form
        // the useForm property is a checkbox, so I always get true/false
        if ($this->document->getProperty('useForm') && !empty($this->document->getProperty('formName'))) {
            // Put everything in a try/catch statement, as there is some buggy code here
            try {
                $this->formHelper = $this->_helper->getHelper('Forms');
                $form = $this->formHelper->getForm($this->document->getProperty('formName'));  

                // Do I have a submitted form to worry about?
                if ($this->getRequest()->isPost()) {
                    if (!$form->isValid($_POST)) {
                    }
                }
                // We are going to display the form
                $this->formHelper->setDecorators($form, 'default');
                $this->view->form = $form;
            } catch (Exception $e) {
                // Log the error if I had one
                Logger::error($e->getMessage());
            }
        }
        $this->enableLayout();
    }


Ok. This is (hopefully) obviously all inside your controller.

When the controller is initialised, add an extra path to the helpers paths. Now, instead of just looking inside Zend, my controller will now look for helpers in the /website/views/helpers/cru/ folder.

Now, in my document that is using the formpage action, I look for 2 properties. A checkbox called useForm (ticked on) and a formName (I have to know which form to load!).

If both of those properties exist and have a value, add on a formHelper to the action so it can do things.

This class is called Website_Helper_Cru_Forms and the filename is Forms.php. I'm sure you can figure out which folder it's in.

I haven't fleshed out the validation of the form. I imagine I'll end up adding something in the formHelper class to do this.

I add on the decorators using my helper. I haven't yet got a good way of doing this, I plan on using .ini files but I'll get around to this later.

And finally, add the form to the view. In the view you simply call echo $this->form to print it out. If you've set up the decorators and validators correctly everything displays in a nice pretty format :)

I've also wrapped the whole thing in a try/catch statement. There are quite a few ways this could break at present as I don't do much error checking yet. That's another thing on the to do list.

Let me know of any obvious errors you can see with this code in the comments below. I hope this helps somebody!

Wednesday, 21 March 2012

Beware easy shortcuts

If you need to replace a character, make sure you replace it with the correct character!

I recently made the mistake of replacing a comma (,) with &comma; That isn't the correct ascii character. &#44; is.

And because I do my IE testing last, I didn't pick it up. Just thought it'd be a good heads up for anyone who didn't realise it either.

Tuesday, 6 March 2012

Validating an email address in PHP

Just a little post, because most of the top Google results point to old pages that aren't correct.

Basically, I wanted to validate some input to see if it was a valid email address. Rather than rely on a regular expression, I knew there was a better way of doing it. In PHP at least.

So, the function you're looking for is filter_var(). If you're doing it with $_POST or $_GET you can instead use filter_input().

In my case, it's verifying that an API is providing me with a valid email, as somebody at the other end likes to chuck in "unsubscribed" to the email field. So the code looks similar to this.

if (false === filter_var($valueToCheck, FILTER_VALIDATE_EMAIL) ) {
    // This is *not* an email address
} else {
   // This *is* an email address
}

Tuesday, 29 November 2011

Amazon cloud servers

They may sound like the silver bullet to kill all silver bullets.

But judging from the swearing coming from the Systems Administrator from the other side of the desk lately, I think I may steer clear of them for a little while yet.

Monday, 28 November 2011

Pimcore and it's Jekyll and Hyde-ness

I am playing with Pimcore to try and learn what it can do, as well as for a friends website. I was having all sorts of issues with getting it to work, however, mainly because some PHP extensions weren't installed locally. Or it wasn't the up to date version. I'm not really sure which.

So after installing php5-imagick (sudo apt-get install php5-imagick) I seem to have fixed the issues with the image uploader and viewing images while editing content.

So that got me to playing with thumbnails to constrain an image to the size I wanted it to be. And that's when I discovered you can automatically make images have rounded corners. How cool is that??

So many options hidden in this CMS that I don't think I'll ever fully understand it.

Thursday, 22 September 2011

jQuery mouseleave and Flash wmode

I ran into an odd isuue today while trying to get some sliding content to hide/show. I'm using the .animate() method and .mouseleave() to get my desired effects.

That worked fairly easily, but then when I added a flickr slideshow to one page the mouseleave() for the container the flash was in, the event was being triggered when the mouse entered the flash object.
Luckily at work there is a very experienced Flash Dev* who helped with this one. I thought it would be the wmode parameter, I just had no idea what it should be or where to put it.

In the end it was wmode='opaque'. It defaults to window, but it can also be transparent. In this case, as there were no flash parameters to set I simply added it as an attribute of the embed tag and the mouseleave() event is now being fired correctly.

For most problems there is Google, but gee it's great to be able to ask someone.

* Yes, he is very excited about Flash 11

Tuesday, 20 September 2011

HTML5 Placeholder in all browsers

One of my favourite features of HTML5 (and yes, I have several!) is the placeholder attribute. It's fantastic for useability and reduces the amount of space used by forms on the page.

And of course, it's not supported by Internet Explorer.

Because I was building a form that requires placeholder text,and validation (what forms don't these days) I decided to finally do something about it.

So here is a little jQuery snippet I wrote to add in support for browsers that don't natively work with the placeholder attribute. It also works in both input and textarea fields.

I've used Modernizr to check for placeholder support. Why re-write the wheel?

// Add pseudo placeholder to bad browsers
    var noPlaceSupport = !Modernizr.input.placeholder;
 
    if(noPlaceSupport) {
        var myInputs = $('input[placeholder], textarea[placeholder]');
        myInputs.each(function() {          
            // Set a value now!
            $(this).val($(this).attr('placeholder'));
            // Set up my focus in, to remove text if it is the placeholder
            $(this).focusin(function() {
                if($(this).val() == $(this).attr('placeholder')) {
                    $(this).val('');
                }
            });
            // On focus out, if empty set it back to the placeholder
            $(this).focusout(function() {
                if ($(this).val() == '') {
                    $(this).val($(this).attr('placeholder'));
                }
            });
        });
    }
There is one little gotcha with this; I had originally written the check as $(this).placeholder, as I figured jQuery was smart enough to work with that in IE. Sadly I was mistaken, but $(this).attr('placeholder') is cross browser compatible.

And now you can extend your validation plugin to check for the default value!

Of course, there is no great fallback here for no JS browsers. Personally, if I had more time I would be using jQuery to dynamically make the placeholder text the label value for this field, and then hiding the label.

I hope this snippet is of use to someone out there!

Tuesday, 24 November 2009

Handy MooTools script for phpBB3 inside a wrapper

For reasons that are too long to go into, a change between phpBB2 and phpBB3 was to make all links not include a target attribute to make the output meet relevant requirements.

On one site I manage (http://www.connectage.com) we have a forum inside a Joomla! wrapper. I'm sure you can see where this is going.

So to stop this happening, I wrote a MooTools script. This script ensures that links to our site open in the parent window (i.e. not the iframe) and other links open in a new window / tab.


<script src="../media/system/js/mootools.js" type="text/javascript"></script>
<script type="text/javascript">
window.addEvent('load', function() {
// send links to a new window, unless it is on our site
var postLinks = $$("div#pagecontent div.postbody a.postlink");

postLinks.each(function(link) {
var sendTo = '_blank';
if(link.getProperty('href').contains(window.location.hostname)) {
sendTo = '_parent';
}
link.setProperties({
target: sendTo,
rel: 'nofollow'
});
});
});
</script>


Simple as that.

There are two scripts there. 1 brings in the default Joomla! MooTools script, which is needed so the rest works.

The second bit, creates an array of links within posts only, checks the domain they're going to and sends them to the parent window (target='_parent') or a new window (target='_blank').

And because it's Javascript, I believe it's still standards compliant. It will also not stop your site working if someone has Javascript turned off in their browser.

This may not work on your template, but it should be easily adaptable if you need it for your own site.

Validated XML for Joomla!

http://docs.joomla.org/Official_DTDs

And better yet, if you're using Eclipse and put the information in (correctly), it will validate it for you. Might solve my current problem with a component not installing correctly.

Tuesday, 17 November 2009

Menu Module Clone

I've written a Joomla! component. Here's a demo of it.




Here's the full listing.