Friday 29 August 2014

gMusic on Opera

Some little time ago I created a wee little thing that allowed me to control the playback of music within Google Music from the top bar of my Chrome browser. After a near disaster upgrading Chrome to 37 I ended up having to use Opera again to stop me swearing at the computer too much. I really missed my little tool so I re-wrote it to work on Opera and submitted it for publication. I have to say that their moderation process is HARD. I was initially annoyed with this but after thinking about it I guess it makes sense. There have been criticisms of Google for allowing all sorts of malicious extensions to be installed on Chrome but from what I can gather the folks at Opera are much more critical - I had to remove an extraneous folder and use Opera specific screen shots for the posting. The folder removal resulted in a much slimmer extension so that can't be bad and the screen shots show the extension in action on Opera rather than Chrome so I guess that that makes a lot of sense. Anyway, it's finally been published. If you use Opera give it a go

Wednesday 27 August 2014

For no reason what-so-ever

Wednesday 20 August 2014

Install SeedDMS 4.0.0 on Ubuntu 14.04 (AWS hosted)

This took quite a wee while to figure out TBH but I got there in the end, with lots of thanks to Sergio and his post as well as other sources (linked to when I use them).

Logging in via MobaXterm from my windows box this is the process I followed:

sudo apt-get update

sudo apt-get upgrade

sudo shutdown -h now

Rebooted the machine, there’s usually a lot of guff about GRUB bootloader but that stuff is too scary so I just accepted the defaults…

Be aware that your machines IP address will change so you might need to edit your session in ModaXterm!

sudo apt-get install lamp-server^

Altered the root user password for MySQL to <your-password>.

sudo aptitude install php-pear

sudo aptitude install php-http-webdav-server

wget http://sourceforge.net/projects/seeddms/files/seeddms-4.0.0-pre5/SeedDMS_Lucene-1.1.1.tgz

wget http://sourceforge.net/projects/seeddms/files/seeddms-4.0.0-pre5/SeedDMS_Core-4.0.0pre5.tgz

wget http://sourceforge.net/projects/seeddms/files/seeddms-4.0.0-pre5/SeedDMS_Preview-1.0.0.tgz

sudo pear install SeedDMS_Core-4.0.0pre5.tgz

sudo pear install SeedDMS_Lucene-1.1.1.tgz

sudo pear install SeedDMS_Preview-1.0.0.tgz

wget http://download.pear.php.net/package/Log-1.12.7.tgz

sudo pear install Log-1.12.7.tgz

Then came the fun stuff:

cd /var/www/html/

sudo cp index.html index.html.old

sudo rm index.html

sudo wget http://sourceforge.net/projects/seeddms/files/seeddms-4.0.0-pre5/seeddms-4.0.0-pre5.tar.gz

sudo tar -xvzf seeddms-4.0.0-pre5.tar.gz

mysql -u root -p<your-password>

Within the MySQL shell entered this (after thinking of <mysql-password>):

create database seeddms;

grant all privileges on seeddms.* to seeddms@localhost identified by '<mysql-password>';

exit

Copy everything into our main directory and enable install:

sudo cp -a /var/www/html/seeddms-4.0.0-pre5/. /var/www/html/

cd conf/

touch ENABLE_INSTALL_TOOL

cd ..

sudo chown -R www-data /var/www/html/

sudo a2enmod rewrite

sudo apt-get install php5-gd

sudo service apache2 restart

Make the correct directories

sudo mkdir data

sudo mkdir data/staging

sudo mkdir data/lucene

Go home and install Zend (version 1 not 2):

cd ~

wget https://packages.zendframework.com/releases/ZendFramework-1.12.3/ZendFramework-1.12.3.tar.gz

tar -xvzf ZendFramework-1.12.3.tar.gz

Tell PHP where everything is:

sudo nano /etc/php5/apache2/php.ini Yeah… I know… but I like nano!

This bit is interesting as I needed to include the previously installed pear packages as well. I replaced the line:

;include_path = ".:/usr/share/php"

with (adapting the instructions from BGO):

include_path = ".:/usr/share/php:/home/ubuntu/ZendFramework-1.12.3/library"

Then:

sudo service apache2 restart

And hitting (in the browser):

<my-ip>/install/install.php

Once all that was done I simply cleaned up:

sudo rm /var/www/html/conf/ENABLE_INSTALL_TOOL

This all probably sounds dead simple but I got stuck any number of times and made lots of use of tail -f /var/log/apache2/error.log to check what I was doing wrong as things kept hanging while it was running. Hey ho. I’m not 100% sure that Zend is required TBH but better safe than sorry. This worked for me but do please bear in mind that YMMV.

Tuesday 19 August 2014

Archery Scorer

I wrote about being lazy and pants at maths before but I've been playing with Firebase as well as having my many, many faults. I decided to turn my faults into positives though, and carried on with my lazy endeavour; the result is now up on github: https://github.com/annoyingmouse/archery-scorer. It's dead easy to run!

I've a list of Todos which I'll get around to as and when I've got time but in the meantime it works well enough for me and seems a better solution than paying for one of the dedicated mobile apps available for Android or though the Apple App Store. See: not only lazy but tight as well ;-)

Thursday 14 August 2014

Vanilla JavaScript Dynamic SVG Geo Map (UK region population)

I love the articles on sitepoint and this one on creating Dynamic geo-maps using SVG and jQuery looked lovely and it has been on my to-read list for a while now... pretty much since it was written.

But I've recently started looking at the need for jQuery. Don't get me wrong - I love jQuery, but with modern browsers it's needed less and less. So I decided to use Inkscape instead of Illustrator (because one is free and the other really isn't), and vanilla JavaScript rather than jQuery. As an exercise it was fun and reminded me of the time when I was first starting out and reading about DOM manipulation.

The result is up on my site http://drmsite.co.uk/geo-map/.

The source image is from Wikimedia - an the population numbers are from Wikipedia (think they're from the 2011 Census).

Tuesday 12 August 2014

Archery Scorer (mental arithmetic isn't my strong suit)

I've taken up Archery at The Witchford Archers and I love it. I've only been doing it for a wee while but I'm already twitched about calculating my score after each round... I did try really hard to work on my mental arithmetic but clocked I was doing really quite badly (just check my Luminosity score for evidence of that ;-)). Anyway, I got to thinking and wrote http://drmsite.co.uk/score/, it's dead simple but I'm gonna improve it and use Firebase as a backend for persistent storage so I can grab the results later on a datacard type of thing... because why wouldn't you?

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8"/>
        <title>Score</title>
        <link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.2.0/css/bootstrap.css" rel="stylesheet"/>
        <style>
            container {
                width: 100%;
                display: inline-block;
            }
            block {
                display: inline-block;
                width: calc(32% - 10px);
                height: 200px;
                margin: 10px;
                background: #eee;
                float: right;
                text-align: center;
                font-size: 10em;
                cursor: pointer;
            }
            block.score:hover {
                background-color: #9e9e9e;
                color: #fff;
                transition-property: background-color .2s linear 0s;
                    -moz-transition: background-color .2s linear 0s;
                 -webkit-transition: background-color .2s linear 0s;
                      -o-transition: background-color .2s linear 0s;
            }
            block#roundTotal{
                background-color: #fff;
                width: calc(100% - 30px);
                cursor: default;
            }
            .glyphicon{
                margin-top: 0.2em;
            }
            #content{margin: 0 auto;}
            </style>

    </head>
    <body>
        <container>
            <block id="roundTotal">0</block>
            <block class="num score" data-num="9">9</block>
            <block class="num score" data-num="8">8</block>
            <block class="num score" data-num="7">7</block>
            <block class="num score" data-num="6">6</block>
            <block class="num score" data-num="5">5</block>
            <block class="num score" data-num="4">4</block>
            <block class="num score" data-num="3">3</block>
            <block class="num score" data-num="2">2</block>
            <block class="num score" data-num="1">1</block>
            <block class=" score" id="btnClr"><span class="glyphicon glyphicon-refresh"></span></block>
            <block class="num score" data-num="0">M</block>
            <block class="num score" data-num="10">10</block>
        </container>
        <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
        <script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.2.0/js/bootstrap.js"></script>
        <script>
            var total = 0;
            var clicks = 0;
            $(function(){
                $(".num").on("click", function(){
                    var $this = $(this);
                    if($this.hasClass("score")){
                        clicks++;
                        total += parseInt($(this).data("num"), 10);
                        $("#roundTotal").text(total)
                        if(clicks === 6){
                            $(".num").removeClass("score");
                        }
                    }
                });
                $("#btnClr").on("click", function(){
                    total = 0;
                    clicks = 0;
                    $("#roundTotal").text("0")
                    $(".num").addClass("score");
                });
            });
        </script>
    </body>
</html>

It's hosted on Google Drive but doesn't have to be - if you want to use it either copy and paste it into your own hosting or just use it as is - the backend version will be written elsewhere and I'll leave this as is for a wee while.

Monday 4 August 2014

Holding pattern (playlist)

He's right!

Nicer JavaScript inArray

so I'm presently using the fantastic Stormpath for user management for some work I'm doing for the equally fantastic HopeUK... I'm getting to play with nodejs and as such I'm rediscovering all those lovely things about JavaScript I've missed having to develop for IE6 and so resort to jQuery - don't get me wrong: I love jQuery... but after a couple of years developing for old and busted browsers it's nice to get back to bleeding-edge vanilla JavaScript. One of the joys of jQuery is it's $.inArray() function as it just works!

I needed to a method to discover whether or not a user had access to a specific route within the application... let's call it the "/Educators" route. Stormpath lets me query the user's Groups so I so that and get an object back from their API which has an array of "items" (not the actual result):

{
    "user": "User Name",
    "something": "else",
    "items": [
        {
            "name": "Educators",
            "something": "else"
        },
        {
            "name": "Administrators",
            "something": "else"
        },
        {
            "name": "Funders",
            "something": "else"
        }
    ]
}

Initially I wrote a lovely function taking two variables (the groups array and the group name I was interested in) it initialized a return value to false then iterated over the items array and if the array item name equaled the group name set the return value to true - at the end of the loop the return value was returned. Dead simple, ehh? You can imagine how it looks even I'll bet?

Then I got to thinking about the map() function available in JavaScript and thought that that must be a better approach so I took the original array and fed it to map to produce and array like this (all within the console of Chrome as it seems like the best place to test JavaScript sometimes):

var d = {
    "user": "User Name",
    "something": "else",
    "items": [
        {
            "name": "Educators",
            "something": "else"
        },
        {
            "name": "Administrators",
            "something": "else"
        },
        {
            "name": "Funders",
            "something": "else"
        }
    ]
};
var e = d.items.map(function(item){return item.name});
console.log(e);
["Educators", "Administrators", "Funders"]

So to test I simply did something like this if(e.indexOf("Educators")) !== -1)

But I got to thinking more, especially about truthy falsy, and I clocked the bitwise NOT operator. Now I could do some simple tests like this:

if(~d.items.map(function(item){return item.name}).indexOf("Educators")){
    console.log("true");
}else{
    console.log("false");
}
if(~d.items.map(function(item){return item.name}).indexOf("Fred")){
    console.log("true");
}else{
    console.log("false");
}
if(~d.items.map(function(item){return item.name}).indexOf("Funders")){
    console.log("true");
}else{
    console.log("false");
}
true
false
true

So from a clunky function we get a nice one-liner! I'm really rather pleased with it.

Of course, all that there playing within the console doesn't help with my Codeivate score does it?

Friday 1 August 2014

I want a SodaStream

I've always wanted a SodaStream! Ever since I were wee I've wanted a SodaStream but when I were wee we couldn't afford one - now, when I might be able to afford one for my birthday, I can't justify buying one... and can I find an alternative? I dare say there are alternatives from the US but the postage would double the price whereas Cutlacks in Ely have them there... right on the shelf!

I've seen the posts on FaceBook complaining about the actions of Israel in Palestine and I'm left feeling a wee bit helpless... a little like how I feel driving past an accident... I don't want to rubber-neck or I might see something 'orrible and I then might throw-up. I've seen the posts shared by my conspiracy-theorist son and grinned at the fruit not falling that far from the tree... but still felt like I want to look away. What's my outrage going to do to stop innocent people dying in Palestine - or anywhere else for that matter? All I can do is refuse to upgrade Mellel... and not buy a SodaStream. I love Mellel, I wrote my dissertation on it and fell in love with it then, but it's written in Israel so I can't upgrade (hey, I don't have a Mac anymore but I'd think about installing a virtual machine with OSX on it if Israel would stop taking the hands of innocent people and smacking them in the face with them, all the while saying: "Stop slapping yourself"). So while I love Mellel and would, hands-down, recommend it for people who write on Macs... I can't suggest you buy it :-(.

So I'm saddened - or at least I would be if I could bear to look at the reality of the situation long enough - but I'm not gonna do anything apart from not upgrade Mellel or buy a SodaStream... Yay for middle-class angst!

I'm even starting to go off Scarlett Johansson and I'm wondering if I should boycott Lucy...? That might be a step too far though.