Saturday, 23 April 2016

Recover images Snippet

As a side project for the archery club I'm a member of I've been looking at saving some stuff to Google Drive as a backup so I've been trawling the interweb for examples of how to upload backups weekly. I did find an old but interesting article but the images were broken :-(.

Then I got to thinking about how to recover them and clocked that the full size images which they linked to still existed so I cracked open Chrome's snippet pane and entered this as a new snippet:

Array.prototype.forEach.call(document.querySelectorAll(".no-line"), function(el, i){
    var img = el.querySelector("img");
    img.setAttribute("src", el.getAttribute("href"));
    img.setAttribute("width","100%");
});

This way of sorting stuff is just so unbelievably powerful and is probably why my codeivate score is as low as it is... Why bother with a full on IDE when you can do most, if not all, of your work in the browser - all without worrying that your changes will affect anyone else?

Sunday, 17 April 2016

It's been an odd couple of days

I was working from home Friday afternoon when the phone rang. It was a teacher from #3’s school who I’d met once or twice and who had read a lovely poem at his funeral. It would’ve been the year he left school after doing his GCSEs this year so she wanted my permission to put something in this years Year Book; a photo and a poem or something. I said that was fine and forwarded her email to his Mum so she could also give permission.


That school has been lovely! I think that there’s some sort of memorial to him in the grounds somewhere but I’ve not been to see it. ‘Er indoors has and said it’s lovely, I think she might’ve even taken a picture and tried to show it to me but I turned away before I could see it so I can’t really remember.


Then Google showed me some pictures from 7 years ago that I’d taken whilst on we’d been on holiday in Tenby. We’d spent the day going to Caldey Island where we’d wandered around and I think I’ve got some aftershave from there - the number of times I shave it’ll probably outlast me!


That was odd as I was on the verge of slinging out a mug with World’s Greatest Dad on it that the boys had bought me while we were there. Seeing the utter failure I’ve been as a Dad meant it simply had to go, thankfully ‘er indoors persuaded me not to. There was a picture on the fridge that I also moved. It was of #2, #3, ‘er indoors and me at our wedding and I remember the photo being taken as I’d just had a go at #3 for carrying on alarming as he was tired. I’m not trying to remember him with rose-tinted glasses or anything, I just don’t want to remember telling him off.


He was a love but could also be a bugger! Goodness me, I miss him so much!


In the meantime I’ve got things growing in the car…


The picture above is from when I was leaving work on Friday afternoon, I thought I’d run into a bush but upon opening the door I looked into the gap and saw this:


I’m guessing it’s fine though. Life always find a way and it’s not down to me to remove it.

Thursday, 24 March 2016

JavaScript: split sentence and add line breaks

I've been using Semantic UIs form validation nigh on constantly over the past few months and apart from the ability to write my own validation rules (which is a brilliant thing by the way) I'm also impressed with the messages that get slung into the UI. The on ly problem I've had though is if the message is particularly long then it can often mess up the layout of the form. After some experimentation I discovered that adding <br/> tags added line breaks within the message. I'm using this an awful lot so I decided to write a simple function which takes a string and splits it on words. It's a wee bit fuzzy so perhaps could do with a wee bit of tidying, but it works for my purposes:

function addBr(sentence, letters, seperator){
    letters = letters || 25;
    seperator = seperator || "<br/>"
    words = sentence.trim().split(" ");
    var returnString = "";
    var line = "";
    while(words.length > 0){
        if(line.length < letters){
            if(~~line.length){
                line += " " + words.shift();
            }else{
                line += words.shift();
            }
        }else{
            returnString += line + seperator;
            line = "";
        }
    }
    if(line !== ""){
        returnString += line;
    }    
    return returnString;
}

Here's a working JSFiddle.

Friday, 18 March 2016

Moving data between pages using DataTables and the Query string

I recently got a tweet from someone I previously helped with a DataTable question:

And, seeing as I was playing with the really rather marvelous MDB framework, I thought I'd give it a try.

I knew I'd be able to get the data from the selected rows and also indicate their state as being selected but what was I to do with that data? If I could create a global data JSON object within the script I could use the unique ID of each row as the key to the full data of the representation of the row within the JSON object. The ID was for my benefit and could have been anything unique about the row... I guess I could've used a hash of the rows values as well, but why make things difficult?

So I needed a global data object, something to hide the the ID row within the table and some way of manipulating the data object when the user interacted with the table:

var data = {};
$(function(){
    var example = $("#example").DataTable({
        "columnDefs": [
            { 
                targets: [0], 
                visible: false
            }
        ]
    });
    $('#example tbody').on("click", "tr", function () {
        var temp = example.row(this).data()
        var obj = { 
            "ID": temp[0],
            "Name": temp[1],
            "Position": temp[2],
            "Office": temp[3],
            "Age": temp[4],
            "Start date": temp[5],
            "Salary": temp[6],
        }
        if($(this).hasClass("info")){
            $(this).removeClass("info");
            delete data[temp[0]];
        }else{
            $(this).addClass("info");
            data[temp[0]] = obj;
        }
        console.log(data);
    });
});

In case you're wondering, this is what the data looks like:

{
    "4": {
        "ID": "4",
        "Name": "Cedric Kelly",
        "Position": "Senior Javascript Developer",
        "Office": "Edinburgh",
        "Age": "22",
        "Start date": "2012/03/29",
        "Salary": "$433,060"
    },
    "5": {
        "ID": "5",
        "Name": "Airi Satou",
        "Position": "Accountant",
        "Office": "Tokyo",
        "Age": "33",
        "Start date": "2008/11/28",
        "Salary": "$162,700"
    },
    "6": {
        "ID": "6",
        "Name": "Brielle Williamson",
        "Position": "Integration Specialist",
        "Office": "New York",
        "Age": "61",
        "Start date": "2012/12/02",
        "Salary": "$372,000"
    }
}

So far so good, but how to move the data between the pages?

$("#move").on("click", function(){
    var encodedData = window.btoa(JSON.stringify(data));;
    var href = window.location.href.split("/");
    href.pop();
    href.push("catch.html");
    var newURL = href.join("/");
    document.location.href = newURL + "?data=" + encodedData;
});

When the button with an id of move is clicked I encode the stringed data object, take the uri of the current page, strip off the original page and add a new one (catch.html, in this case) and add the Base64 encoded data to the data query string. I then change the document.location.href to the catching page.

Simple ehh?

Within catch.html I needed to decode the Base64 encoded data and put it back into an object, I also needed to tell the catching DataTable how to read the caught data.

$(function(){
    var example = $("#example").DataTable({
        "columns": [
            { 
                "data": "ID",
                "visible": false
            },
            { 
                "data": "Name",
                "title": "Name"
            },
            { 
                "data": "Position",
                "title": "Position"
            },
            { 
                "data": "Office",
                "title": "Office"
            },
            { 
                "data": "Age",
                "title": "Age"
            },
            { 
                "data": "Start date",
                "title": "Start date"
            },
            { 
                "data": "Salary",
                "title": "Salary"
            }
        ]
    });
    var data = JSON.parse(window.atob(GetURLParameter("data")));
    if(Object.keys(data).length){
        $.each(data, function(k,v){
            example.row.add(v);
        });
        example.draw();
    }
});
function GetURLParameter(sParam){
    var sPageURL = window.location.search.substring(1);
    var sURLVariables = sPageURL.split('&');
    for (var i = 0; i < sURLVariables.length; i++){
        var sParameterName = sURLVariables[i].split('=');
        if (sParameterName[0] == sParam){
            return sParameterName[1];
        }
    }
}

Also simple ehh?

This was a nice little challenge and allowed me to slot wee bits of logic together to get something that just works, it was just what I needed to relax now I've picked all the low-hanging fruit from Empire of Code.

Wednesday, 9 March 2016

Ajax Chatter File Attachment

Putting here so I don't forget how to do it:

public string imageData {get;set;}
public string imageName {get;set;}
public string imageDescription {get;set;}
public string recordId {get;set;}
/*
 * imageData:        base64 encoded file starting with something like this - data:image/png;base64,iVBORw0KGgoAAAA...
 * imageName:        name of the file being uploaded
 * imageDescription: description of the file being uploaded
 * recordId:         ID of the record the uplaod is assocaited with
 */
public void submitImage(){
    String base64 = imageData.substring(imageData.indexOf(',')+1);
    Blob actualdata = EncodingUtil.base64Decode(base64);        
    /* Regular attachment */ 
    //Attachment a = new Attachment(
    //    parentId = recordId,
    //    name = imageName,
    //    body = actualdata,
    //    description = imageDescription
    //);
    //insert a;
    /* Chatter attachment */ 
    ContentVersion doc = new ContentVersion();
    doc.Title = imageName;
    doc.Description = imageDescription;
    doc.PathOnClient = imageName;
    doc.VersionData = actualdata;
    insert doc;
    FeedItem post = new FeedItem();
    post.Visibility = 'AllUsers';
    post.ParentId = recordId;
    post.CreatedById = UserInfo.getUserId();
    post.RelatedRecordId = doc.Id;
    post.Type = 'ContentPost';
    post.Title = 'File upload for ' + imageDescription;
    insert post;
    imageData = ''; // so it doesn't blow my page up!
}

Monday, 7 March 2016

Sublime Text ASCII Art

Splitting your content into separate files for HTML, CSS and JS is a brilliant idea but sometimes you simply need to smudge it all together - even huge quantities of JS - and that can make navigating through lines and lines of script a pain.

If you use Sublime Text (and if you're not, why not?) then you can install this plugin or you can do what I do and use the excellent Text to ASCII Art Generator (TAAG) to generate lovely comments like this:

/*
 .d8888b.                    888 
d88P  Y88b                   888 
888    888                   888 
888         .d88b.   .d88b.  888 
888        d88""88b d88""88b 888 
888    888 888  888 888  888 888 
Y88b  d88P Y88..88P Y88..88P 888 
 "Y8888P"   "Y88P"   "Y88P"  888 
 */

Quite apart from making things easier, it's also readable in the minimap so you can scroll to just where you need to be!

This is mainly up for my own reference but if it helps all good!

Monday, 25 January 2016

19/01/2016 Portsmouth Scoring

I've been shooting at least once a week for about 18 months so I thought I should record my score at least weekly (598)
Date
Round Score Round Score
1 24 11 26
2 25 12 26
3 24 13 25
4 25 14 22
5 27 15 26
6 20 16 25
7 26 17 24
8 26 18 25
9 27 19 26
10 25 20 24