Friday, 18 September 2020

Day's until Xmas

Last night there was a question on Jay's Virtual Pub Quiz asking how many days there were until Xmas. I worked something up years ago but decided to revisit it today while waiting for Visual Studio to build my solution, this is the result:

const days2Xmas = Math.ceil(
  (
    new Date(
      new Date().getMonth() == 11 && new Date().getDate() > 25 ?
      new Date().getFullYear() + 1 :
      new Date().getFullYear(),
      11,
      25
    )
    .getTime() -
    new Date().getTime()
  ) /
  (1000 * 60 * 60 * 24)
)
console.log(days2Xmas)

Tuesday, 15 September 2020

Frontend vs backend developers (well, not really)

@backend1: @frontend1, @frontend2 - a bug here
@frontend1: @backend1 OMW
@frontend2: @backend1 Sure thing. @frontend1, let me know if you need a hand.

...

@frontend2: Not sure if this is a frontend or backend issue
@backend2: Frontend! Set the flux capacitor to true

...

@frontend2: Flux capacitor set to true, will look some more
@backend2: Are you sure?
@frontend2: @backend2, yep, just double-checked, shall I call you and show you what's happening?
@backend2: Sure

...

@backend2: @frontend2 backend issue.

Frontend and backend (or, for that matter, fullstack) developers are a funny lot, collectively. They're funny individually as well, but communication between them can be hilarious. I work with a brilliant team, and I've noticed a specific trend when it comes to the allocation of bugs to fix. I'm working with a backend technology I'm not overly familiar with, so I know I can be a pain when it comes to making requests or asking questions. I also acknowledge, wholeheartedly, that I'm guilty of making prototypes for the frontend with absolutely no regard to the information I'm likely to receive from the server - but I live in hope.

I have, however, noticed a specific trend with bugs that fall in the grey area between the responsibilities. Or those bugs where the cause is unclear. Generally speaking, it's obvious, but now and again much less so.

When a bug is a frontend issue, we (my fellow frontend developer and I) rush to take the issue and solve it just as soon as we can. Any delay is incurred only as a result of testing the solution in Chrome, Firefox, Edge and IE11. We make the PR and move along, avidly waiting for the next thing to fix, all the while searching for issues ourselves.

It's those grey area bugs that cause issues though. I'll take a look at something, clock that it's wrong and investigate. We're using Vue, so I'll open up the Developer Tools and check what we're sending back to the server using the Vue.js devtools and think about what I'm expecting back. If it's wrong, I'll tentatively suggest that the backend developers take a look and check to see if it's the responsibility of the frontend or backend developers to fix. The majority of the time the response will be that it's a frontend issue so I'll take another, more exhaustive, look and document the process. I'll perhaps prepare screenshots and videos to illustrate the process to go along with the documentation. Only then will I ask my teammates to check again and see if it's the responsibility of the frontend or backend developers to fix the bug. 9 out of 10 times I'll be right, and it will probably be a simple matter for them to fix. It's good for me to investigate though, I gain a far greater understanding of the working methods of my fellow developers, but it would be nice to be trusted now and again.

I wrote this the previous weekend, today I clocked that I'd argued with a backend developer over a very similar issue, which was eventually discovered to be a frontend issue!

Doh! I've also just clocked this is my 500th post!

Tuesday, 30 June 2020

The 10-Day JavaScript Challenge

Yay! There's another one started, such fun!

I'll add to this is I go along All done now - such fun.

Day 1

const add = (...a) => a.reduce((t, v) => t + v)

Day 2

const allLongestStrings = a => a.filter(i => i.length === Math.max(...(a.map(a => a.length))))

This is not overly efficient, but it works. Then I got to remembering about default values and altered it to this:

const allLongestStrings = (a, i = Math.max(...(a.map(a => a.length)))) => a.filter(e => e.length === i)

Longer, but we only check for the longest string the once, rather than over each iteration.

Day 3

const allLongestStrings = (a, i = Math.max(...(a.map(a => a.length)))) => a.filter(e => e.length === i)

Day 4

const arrayReplace = (arr, o, n) => arr.map(e => e === o ? n : e)

Day 5

const caseInsensitivePalindrome = (s) => s.toLowerCase().replace(/[\W_]/g, '') === s.toLowerCase().replace(/[\W_]/g, '').split('').reverse().join('')

I like this way because it deals with "A man, a plan, a canal, Panama!". But I really like this one (not mine):

const caseInsensitivePalindrome = s => [...s = s.toLowerCase()].reverse().join`` === s;

Day 6

This was a fun one as we needed to produce three different approaches, here are mine:

const encloseInBrackets = s => `(${s})`
const encloseInBrackets = s => ['(', s, ')'].join('')
const encloseInBrackets = s => ['('].concat(s).concat(')').join('')

This can be improved to this though:

const encloseInBrackets = s => '('.concat(s, ')')
const encloseInBrackets = s => [...s.split('')].map((c, i, a) => i === 0 ? `(${c}` : i === a.length - 1 ? `${c})` : c).join('')

This isn't mine (it's from musa#0677), but I love it:

const encloseInBrackets = s => String.fromCharCode(40, ...s.split('').map((_, i) => s.charCodeAt(i)), 41);

Day 7

const factorialNumber = n => n ? n * factorialNumber(n - 1) : 1

Day 8

const firstDigit = s => s.match(/\d/)[0]

Day 9

const largestNumber = n => ~~[...Array(n)].fill(9).join``

Day 10

A few days late getting this uploaded but I was thinking... This is my attempt but, as was pointed out, it fails when the numbers get too large!

const maxMultiple = (d, b) => ~~(b/d) * d

After my ponder I clocked that this is much better:

const maxMultiple = (d, b) => b - (b % d)

I also played with some other methods:

const maxMultiple = (d, b) => Math.floor(b/d) * d // works
const maxMultiple = (d, b) => ((b/d) >> 0) * d // fails
const maxMultiple = (d, b) => parseInt(b/d, 10) * d // works

Every day really is a school day!

Tuesday, 23 June 2020

ISBN-10: 1780174764 & ASIN: B08BK5TGKS

I thought I'd spend a few minutes this morning trying to figure out what categories my book belongs to on Amazon. It was an interesting exploration.

  • Books
    • Business, Finance & Law
      • Careers
    • Computing & Internet
      • Computer Science
        • Programming
        • Software Design, Testing & Engineering
      • Professionals
        • Software Design, Testing & Engineering
      • Programming
        • Introduction to Programming
        • Software Design, Testing & Engineering
          • Functional Programming
          • Software Architecture
      • Software & Graphics
        • Software Design & Development
          • Software Design, Testing & Engineering
      • Web Development
        • E-commerce
          • Web Administration
          • Web Design
          • Web Scripting & Programming
        • Web Administration
          • Web Scripting & Programming
        • Web Design
          • Web Scripting & Programming
        • Web Scripting & Programming
    • Health, Family & Lifestyle
      • Self Help
    • Mind, Body & Spirit
      • Self Help
    • University Textbooks
      • Computer Science
        • Software Design, Testing & Engineering
          • Software Development
  • Kindle eBooks
    • Computing
      • Programming
        • Software Design, Testing & Engineering
    • Nonfiction
      • Computing

Red, Amber and Green progress bar

I've been doing some Moodle theming over the past few weeks and ended up discussing progress bars with the designer involved. Little progress is bad whereas finishing a Moodle course is good so I, of course, started waxing lyrical about colours. If red means bad and green means good, what about the middle ground? Then I remembered a traffic light visualisation I was working on ages ago and the joys of amber. Interestingly that post is ten years old! I must've been thinking about colours all these years - guess that's a good (green?) thing for a front-end developer!

Anyway, the project I'm working on, as I said, it based within Moodle and writing JS for that is something of a challenge. I can't get my head around the module system they use, and I don't want to learn it enough to get access to jQuery within a theme's script, so I wrote it in Vanilla JS.

I had CSS variables for the colours, so first I clocked I needed those within the script. Still, I also needed them in terms of the RGB values - as an array would work fine, after some research I came up with hexToRGB, which produces a simple collection with the RGB values as three distinct integer values in an array. One possible issue with using JS to get the computed style from a CSS variable is that it returns everything from the colon to the semi-colon as a string. That's good and all, but that left an extraneous space which needed trimming.

const hexToRGB = hex => hex.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i, (m, r, g, b) => '#' + r + r + g + g + b + b).substring(1).match(/.{2}/g).map(x => parseInt(x, 16))
const red = hexToRGB(getComputedStyle(document.documentElement).getPropertyValue('--under-third').trim())
const amber = hexToRGB(getComputedStyle(document.documentElement).getPropertyValue('--third-to-two-thirds').trim())
const green = hexToRGB(getComputedStyle(document.documentElement).getPropertyValue('--over-two-thirds').trim())

I also needed to mix the colours, which wasn't much of a bother. Though I did discover there were multiple ways of mixing colours, I chose to go the most straightforward route with mixColour (hey, what can I say? I know I'm supposed to use `color` when I code HTML and CSS, but I much prefer `colour`). mixColour uses a further function, imaginatively called mix, where the heavy lifting occurs and takes into account the percentage of each colour needing mixing, we pass this as a float between 0 and 1.

const mixColour = (c1, c2, pc) => RGBToHex(Math.round(mix(c1[0], c2[0], pc)), Math.round(mix(c1[1], c2[1], pc)), Math.round(mix(c1[2], c2[2], pc)))
const mix = (s, e, pc) => s + ((pc) * (e - s))

Once mixed, I needed to produce RGB values again, so I worked up RGBToHex which uses some smart bit-wise operators - I wish I knew what they did. Still, I use bit-wise operators so infrequently that I can't seem to work up the enthusiasm to learn them properly.

const RGBToHex = (r, g, b) => `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}`

We had values between 0 and 100 for the progress bar, so working out the float value was the only thing that caused me any head-scratching. If the amount was less than 50, then red and amber needed to be mixed by the value divided by 50; if the value was over 50 then we use amber and green: we need to subtract 50 from the value and then, again, divide the result by 50.

let value = 0;
const container = document.getElementById('bar');
const bar = container.querySelector('.progress-bar-filler');
const interval = setInterval(
  () => {
    value = value === 100 ? 0 : value + 1;
    container.setAttribute('data-value', value);
    bar.style.width = value + "%";
    bar.style.backgroundColor = value < 50
      ? mixColour(red, amber, (value / 50))
      : mixColour(amber, green, ((value - 50) / 50))
  }, 100);

Simples eh? Once it's all broken down, then it's just a collection of function, and it works a treat too. There are again some dodgy colours produced between amber and green - but that's only for a very little time, something like 5% I think.

All that was left was to work up a demo.

Wednesday, 3 June 2020

Free course: The 7-Day JavaScript Challenge

Scrimba are running a week-long JavaScript challenge, so I jumped in.

Day 1

Initial attempt:

function addBorder(array) {
    const l = Array.from({length: array[0].length + 2 }, () => '*').join('');
    array = array.map((x) => x.padStart(x.length + 1, '*').padEnd(x.length + 2, '*'))
    array.push(l)
    array.unshift(l)
    return array;
}

After I'd thought about it:

const addBorder = a => ['*'.repeat(a[0].length), ...a, '*'.repeat(a[0].length)].map(e => `*${e}*`)

Day 2

const addTwoDigits = n => (''+n).split('').reduce((a,c) => ~~a + ~~c)

Day 3

const firstDuplicate = ns => {
  const s = new Set();
  for(n of ns){
    if(s.size === s.add(n).size) return n
  }
  return -1
}

Day 4

const sumAllPrimes = n => Array.from({length: n-1}, (_, k) => k+2).reduce((a, c) => a += !'1'.repeat(c).match(/^1?$|^(11+?)\1+$/) ? c : 0)

Day 5

const evenDigitsOnly = n => (''+n).split('').every(n => !(~~n % 2))

Day 6

const makeArrayConsecutive = n => Math.max(...n) - Math.min(...n) - [...new Set(n)].sort().reduce((a, c) => c > Math.min(...n) && c < Math.max(...n) ? a + 1 : a, 0) - 1

Alternatively:

const makeArrayConsecutive = n => ([...new Set(n)].sort()[[...new Set(n)].length - 1] - [...new Set(n)].sort()[0] + 1) - [...new Set(n)].length

Day 7

const properNounCorrection = s => s === s + '' && s.length ? String.fromCharCode(...[...s].map((_, i) => !i ? s.charCodeAt(i) - (s.charCodeAt(i) >= 97 && s.charCodeAt(i) <= 122 ? 32 : 0) : s.charCodeAt(i) + (s.charCodeAt(i) >= 65 && s.charCodeAt(i) <= 90 ? 32 : 0))) : ''

Think that's all of them now.

Thursday, 21 May 2020

SVG background image workflow

I've done a fair bit of work recently using SVGs as background images, so I thought I'd better document the sites I use (thanks again Daniel). I put the original SVG image through SVGOMG! I then paste the resulting, clean, markup into URL-encoder for SVG. Quite a nice and simple process:

  1. SVGOMG!
  2. URL-encoder for SVG

Sunday, 10 May 2020

Layout techniques

You're all lucky bleeders! You are! These are the days of miracle and wonder (And don't cry baby, don't cry). When I started, I was using tables for layouts and thinking they were the best thing since sliced bread - how could they ever be beat? I even, and this shames me significantly, spent a fair amount of time figuring out how to do rounded corners using tables. That's from 2005, don't you know! Don't blame me for the errors in my youth; even then I had to code things for IE.

I did make a foray into float-based layouts, but since that time I stopped worrying and offloaded the heavy lifting to frameworks for a few years. Until, that is, that last few years when CSS frameworks started to feel a little constraining.

So, in my first book, I took a wander through the different ways of creating a layout. And let me tell you, there are ever-so-many options now!

These are the methods I discuss:

Table based

Float based

Float based with wrapper

Position based

CSS table based

Flexbox based

Grid based

The examples above are different from those in the book because... reasons. I guess that after spending hours and hours staring at them, I've clocked that they could be better, and I've refactored them as a result. The same happened yesterday when I spent hours looking at an experiment from the book.

I've been doing this professionally for something like a decade now, so if I'm not allowed to go back and look at old code and scream like a little girl then Yah, boo, hiss! Of course, the opposite is true, and rarely I'll come across some old code and be blown away at its elegance.

I guess the point of this post though is to remind older, fusty developers (hands-up!) that they don't need to deal with the vagueries of IE6 anymore and can start to embrace some of this new-fangled CSS that's, actually, been around for quite a while! That's not to say that the above will work out-of-the-box on IE11. It's got a dodgy implementation of CSS Grid - but there are ways around that.

Saturday, 9 May 2020

User test, updated

In my forthcoming book, I make significant use of a piece of research I carried out some years back on how users could enter data about their family. The example was contrived, but it served its purpose. I talk about how I could've used a SPA but that at that time I wasn't comfortable building them. I also wax lyrical about Native JavaScript Modules along with various other technologies, so last weekend and this I spent some time putting my money where my mouth is.

I set out to replicate the original statically hosted application using Vue, Vuex and Vue-Router, and I'm quite pleased with the result. Then I got a little carried away and updated Bootstrap from v3 to v4. I also dusted out my old Font-awesome account and threw taht into the mix, along with some SCSS, just for fun!

It's nigh on where I want it to be TBH, except I can't get the router to work correctly; going to any page other than the home page throws an error. Scratch that: I'm hosting on repl.it so I need to use the "hash" mode for the router rather than "history". Simples, eh?

I also ran the text through Grammarly.

Friday, 1 May 2020

Animated curves in SVG

The animation is triggered on hover over the path above.

A mate asked about animating an SVG yesterday and it got me thinking about how to do it using CSS.

The original is here, but I like this version as the points also move. After reading a lot from the MBN web docs I figured out that the S stole a control point from the preceding C.

Then I got to playing with quadratic curves. The result is above.

Thursday, 30 April 2020

Triangles are the strongest shape

After spending the best part of a year and a half of Sunday's writing and editing a book on the subject of front-end development, you can only imagine the angst I felt when I read "The title 'Front-End Developer' is obsolete." on an RSS feed.

Clicking through to the article I was a little mollified that Chris Coyier (who I ended up referencing extensively) wasn't in agreement with the original Tweet. Still, he notes that the profession has changed significantly over the years, if not months/weeks/days/hours (it is sometimes hard to keep up). Even the author of the Tweet seemed to be railing at the focus on JavaScript rather HTML and CSS. Back when I discovered that the front-end trinity of HTML, CSS and JavaScript now sheltered under the umbrella term of Web Fundamentals, I didn't realise quite how much room JavaScript would end taking up, sometimes even pushing HTML and CSS into the rain.

I guess that's because JavaScript isn't just a simple technology anymore. Frameworks have moved in, sometimes whole new languages like TypeScript have barged in like they own the place! HTML is even being nudged out of the way by JSX and don't get me started on CSS-in-JS (though I do sort of like it TBH). JavaScript's getting all greedy like some crazed Abzorbalovian (go on, Google it). Except it's not all charming like Peter Key, but perhaps I'm being disingenuous with this analogy: JavaScript itself isn't at fault; instead, it's developers.

I think that some frameworks, with their use of static typing (yeah, I'm looking at you Angular), do so to ease the movement of "proper" developers into the front-end. Instead of having to dirty their hands with markup and fuzzy and oft-times ill-supported CSS, developers can instead code up beautiful, statically typed, TypeScript. TypeScript which their transpilers gob out as ugly old JavaScript that they never have to look at in its raw state, all shivering and misshapen. Then some others (yeah, you React, you with your JSX (which I sort of quite like too TBH)) shuck the whole HTML shebang altogether and instead use an extension of JavaScript that looks like but isn't HTML. I guess this situation is only going to get worse as developers start casting their eyes over the charms of WebAssembly.

But what a shame, I can understand why it happened though, JavaScript has come ever such a long way of late and some of us just didn't notice. This evolution started with ES6, and the standard is only improving; native modules is a revelation (just a shame I don't code for ever-green browsers). Frameworks are fun but do we still need them all that much? And CSS, oh goodness me, CSS! I'm working with such a skilled CSS maestro (yes, you Daniel Martínez) that I sometimes look at the things he has crafted, and that I was just about to implement in JavaScript, and boggle. It almost feels like, just as CSS was starting to give us just what we wanted, we decided to throw it away in preference for - not even JavaScript - TypeScript.

TypeScript eh? Static Typing, eh? What if I like playing all fast and loose with variables and embracing the whole truthy/falsy nature of the language? Sure it can catch out young 'uns (and old 'uns too sometimes, but that's why we have ===), but that's fun as well as it can sometimes lead them to moments of delight!

And don't get me started on developers re-inventing the wheel with Web Components! Don't get me wrong, Web Components rock, and a better melding of HTML, CSS and JavaScript you couldn't hope to find, but they sometimes go well overboard, and they're not quite there yet either as they rely on other things. I read an article today about select inputs and their alternatives, except that the alternatives were mentioned far before the native implementations were, and it was only in the closing paragraph that the reader was encouraged to use native selects. Browsers and HTML are smart! Embrace that smartness and don't spend ages importing something (and it's related dependencies) when you've got the tools to hand already.

But this isn't a rant about frameworks; this is more a gentle reminder to those developers who get lost in the joys of pure code (something I'm also guilty of (that link is 10 years old!)). Look up every once-in-a-while and check what's going on around you. Ever-green browsers are very nearly the norm (March 2020 sees IE11 making up just 2.39% of the Web Browser Market Share), and you don't need to worry quite so much about supporting it. Enjoy modern CSS, read a couple of articles about CSS animation, play with some SVGs and read the MDN on HTML5!

Bring HTML and CSS back under the umbrella! Triangles are the strongest shape, after all. Walk like an Egyptian (cue The Bangles)!

Sunday, 19 April 2020

More Inkscape Hexagon stuff

That was lots of fun and I got a chance to use the picture element for the first time!

Here it is with black and white backgrounds:

And here is the SVG on a Gist.

Friday, 17 April 2020

Playing with Inscape - Hexagonal Binary(ish)

Last night I was playing with Inscape and came up with the above, I'm quite pleased with it. Then I had half an hour over lunch so updated it a smidge:

I'm not sure which I prefer, but I think I'll get the grey background one printed large and check it out.

I've put the source SVG online here.