Friday, 23 November 2018

Finding the index of an array of objects by one of the object's properties

I've been doing a shed load of work with lodash of late and, seeing as I've not posted in an age, I thought I'd illustrate an issue I was working on today.

I needed to pass an element of an array to a Vue component but needed a specific one identified by another object. We use lodash so thought I'd make use of findIndex and isEqual and came up with this:

const obj = {
    id: 1,
    name: "fred"
};

const arr = [{
    a: "B",
    s: {
        id: 1,
        name: "fred"
    }
}, {
    a: "A",
    s: {
        id: 2,
        name: "fred"
    }
}];

alert(arr[_.findIndex(arr, (a) => _.isEqual(a.s, obj))].a);

Heat eh?

Saturday, 14 July 2018

Getting Unstuck: Day 10

As a result of signing up for Scratch Getting Unstuck I got a little carried away building a binary clock like this one in Scratch, but got really, really annoyed about not being able to place the elements just where I wanted. I remembered reading something a little while ago about the sb2 file format being an archive so I unzipped it and clocked that sprites have a scratchX and scratchY coordinate within the project.json file. That and figuring out that it uses SVG as the Vector format (why wouldn't you?) meant that I could replace the dodgy path with a circle element. This is the result and I'm quite pleased with it. Now, if only I could automagically use dynamic variable names I wouldn't have to have so many functions. Ah well.

Wednesday, 11 July 2018

Getting IE11 to play nicely with grid-area

I've been playing with CSS Grid layout lately within a Vue Component and I'm needing to place specific blocks within a grid, they are of an arbitrary position width and height and that all worked a treat within FireFox and Chrome... just not in, you guessed it, IE11.

So after banging my head against the issue for a few hours and trying everything I could think of I went to StackOverflow and asked. It seems I was being too helpful and adding the browser prefix rather than letting Vue do it for me. So far so good and StackOverflow provided the answer (thanks zero298), but it only went so far.

After looking at the issue some more I came up with the following script:

getStyle: function(x, y, a, b, c, d){
    var style = [];
    style.push("grid-row: " + x + ";");
    style.push("grid-row-span: " + d + ";");
    style.push("grid-column: " + y + ";");
    style.push("grid-column-span: " + c + ";");
    style.push("grid-area: " + x + " / " + y + " / " + a + " / " + b + ";");
    style.push("border: 1px solid white;");
    return style.join(" ");
}

I know that I'm using CSS for the border on the elements but IE11 doesn't support the grid-gap property for some reason, and rather than use browser detection, I figured it would be better to just do it this way for all elements. It's an interesting way of doing things as some of the properties are incompatible, which is why the decent bits of grid-area are left to the end and the IE11 specific bits get added first. IE11 doesn't support grid-area anyway so we're golden.

A little bit of extra work but should you examine the result in the bound style of an element you only see the appropriate CSS for the appropriate browser, which is nice. As I replied added in my original question on SO I just needed to trust Vue!

EDIT

I got to thinking about the variables I was passing to the function above and realised that the c and d variables could be derived from subtracting the width from the x coordinate and the depth of the block from the y coordinate. Not only does this meant that the number of variables I was passing was reduced (something of an issue as the functions I was calling this from were making the calculations on the fly) but it also makes it much clearer. This is the new function:

getStyle: function(x, y, width, depth){
    /***
     * X=Row , Y=Column
     * https://answers.yahoo.com/question/index?qid=20090609205915AASR51m&guccounter=1
     * IE11 has issues with grid-area as well as the syntax of grid-row and grid-column.
     * As such we need a polyfill for that that uses "-span" to indicate the "length" of the element
     * @param {number} x The "line" where the element should start on the horizontal grid (column) from the top
     * @param {number} y The "line" where the element should start on the vertical grid (row) from the left
     * @param {number} width The "line" where the element should end on the horizontal grid (column) from the top
     * @param {number} depth The "line" where the element should end on the vertical grid (row) from the left
     */
    var style = [];
    style.push("grid-row: " + x);
    style.push("grid-row-span: " + (width - x));
    style.push("grid-column: " + y);
    style.push("grid-column-span: " + (depth - y));
    style.push("grid-area: " + x + " / " + y + " / " + width + " / " + depth);
    return style.join("; ");
}

Thursday, 28 June 2018

Colour shading with JavaScript

Shading a colour can be an utter pain but when I came across this script from CSS-TRICKS I was happy as a pig in muck. At least I was until I had to change the colour received via a call to getComputedStyle. getComputedStyle returns the colour in this format rgb(RedDecimalNumber, GreenDecimalNumber, BlueDecimalNumber) (red is rgb(255,0,0)) rather than the #RedHexadecimalNumberGreenHexadecimalNumberBlueHexadecimalNumber (red is #ff0000). The original script I was using was the one linked above so I had to convert the colour from getComputedStyle to hexadecimal, alter its shade and return it back to the original element's style as hexadecimal again.

This method seemed overly complicated, and I clocked that I didn't need to return it to the element as hexadecimal but could use it just as an RGB string in the inline CSS. Then I got to looking at the original script and realised that as getComputedStyle returns an RGB string, I could rewrite the original function to use a regex function and return that to the inline CSS instead. The following is the function:

o.replace(/\d+/g,c=>~~c+s>=255?255:~~c+s<=0?0:~~c+s)

I always forget that replace can take a function as the second argument but in this instance, it's cool that it does. The following is a less ES6y version:

o.replace(/\d+/g, function(c){
  if((parseInt(c, 10) + s) >= 255){
    return 255
  }else{
    if((parseInt(c, 10) + s) <= 0){
      return 0
    }else{
      return parseInt(c, 10) + s
    }
  }
})

Fun eh?

Monday, 25 June 2018

Vue simple-webpack on c9

I've lost track of how many times I've had to re-research this issue so I thought I'd best document it here. When playing through tutorials on Vue I often use c9 but had problems figuring out how to get the simple-webpack versions running. This, then, is how to get it up and running with a the vue-cli.

Open webpack.config.js and turn off the host check by adding this to the devServer object:

devServer: {
    historyApiFallback: true,
    noInfo: true,
    overlay: true,
    disableHostCheck: true
}

Then open package.json and alter the dev scripts object so it looks like this:

"cross-env NODE_ENV=development webpack-dev-server --host $IP --port $PORT --open --hot"

Of course, this works for me but YMMV.

Sunday, 22 April 2018

A new outdoor venue for Witchford Archers

One of the things that always impresses me about Witchford Archers is just how well we work together! Last year when we had to move venue, we worked like crazy to move all of our kit. While it might seem that all we do is shoot, and drink afterwards, in the background, there's so much activity it makes me positive about humanity!
We prepared our new outdoor venue yesterday. Nick has moved heaven and earth to secure the playing fields at Sutton C of E (VC) Primary School as a lovely place to shoot when the sun's out. Yesterday we made significant progress with building a... shed doesn't do it justice, to be honest as it's a work of art!
Designed and architected by Alan and Chris loads of work went into sourcing and preparing materials as cheaply as possible.
Aided my Derek, Nick, Oliwia and Dominic it was erected in a lovely shady spot in the playing fields over the course of Saturday the 21st of April 2018. The following show just what was accomplished!

Wednesday, 4 April 2018

Detect IE11

I'm old enough to remember why we needed jQuery: IE6.

Now I'm less used to using it and prefer vanilla JS but still wish for its universal levelling of the playing field because now I have to deal with the peculiarities of IE11 on a near daily basis so, thanks to this answer on StackOverflow, you'll often see this peppering my code:

if(!!navigator.userAgent.match(/Trident.*rv\:11\./)){
    // Do something peculiar...
}