Jamie Balfour

Welcome to my personal website.

Find out more about me, my personal projects, reviews, courses and much more here.

Jamie Balfour'sPersonal blog

I first introduced my tutorials back in 2012 when I began refurbishing my website. Since then they have become incredibly popular (I use a page visit counting algorithm that I have developed and I have noticed a huge spike in visitors to my reviews and tutorials over the last few months, with an average of around 500 visitors a day).

However, it struck me that in reality, my tutorials are not so much 'tutorials' but free online courses. I say this because when I look at say, my CSS tutorial, it doesn't focus on doing things in CSS like websites such as CSS Tricks does, but instead it focuses on giving a solid platform to build upon. For example, it teaches some of the core features like backgrounds and border-radii, but not more advanced things like the clearfix model or how to add gradient borders as I have been doing on my website.

From today on, these tutorials are now rebranded as my Courses and they will continue to be free, as with many of the resources I provide.

Not that I like reminding myself, but these are the last few hours of my twenties. In less than 10 hours (I was born at 10.31) I will turn 30 years old. I'm not sure I feel like I am thirty, I still feel a lot younger than that...

Today's date

I did a lot during my twenties - I got through and survived cancer, I got my first class degree, I got my first work experience, I got my PGDE, I got Charlie and I bought my own house (which I love). My twenties also had some bad things in them like losing Petro, Gismo, Henry and Sweep. I met some really great people like my pal Jonathan, Merlin, Mark etc at uni, and Beth and Campbell during my PGDE. I also got to meet some people with who I've become friends with (to name a few Grant, Daragh, Moira, Brian, Mel, Louise, Michael, Grant and Ann).

In terms of looking back at my twenties, I'm going to create an article as I did with the last decade. It might coincide with that one slightly since they are almost parallel.

Here is a video I found just today about the world's richest people. I found one a few years ago about the world's biggest brands, similar to this.

In the last few hours, I have been working on improving the information architecture and the URLs for my tutorials. For the last six or seven years the way the URLs to my tutorials have looked is like this:

/courses/web/css/1/2/

Now, with a bit of work, I've written a much more beautiful system, and that makes the URLs look like this:

/courses/web/css/using_css/

The new system uses URL rewrites alongside a clever automated (cron) generated JSON in which all of the titles are given friendly names:

JSON
[{
  "page_name": "What this tutorial is",
  "category": "web",
  "category_name": "Web",
  "topic": "css",
  "topic_name": "CSS",
  "route": "/courses/web/css/1/1",
  "area": "1",
  "page": "1",
  "title": "what_this_tutorial_is",
  "friendly_path": "web/css/what_this_tutorial_is"
}, {
  "page_name": "What CSS is",
  "category": "web",
  "category_name": "Web",
  "topic": "css",
  "topic_name": "CSS",
  "route": "/courses/web/css/2/1",
  "area": "2",
  "page": "1",
  "title": "what_css_is",
  "friendly_path": "web/css/what_css_is"
}, {
  "page_name": "Using CSS",
  "category": "web",
  "category_name": "Web",
  "topic": "css",
  "topic_name": "CSS",
  "route": "/courses/web/css/2/2",
  "area": "2",
  "page": "2",
  "title": "using_css",
  "friendly_path": "web/css/using_css"
}, {
  "page_name": "Why CSS is used",
  "category": "web",
  "category_name": "Web",
  "topic": "css",
  "topic_name": "CSS",
  "route": "/courses/web/css/2/3",
  "area": "2",
  "page": "3",
  "title": "why_css_is_used",
  "friendly_path": "web/css/why_css_is_used"
}, {
  "page_name": "Classes, IDs and tag selection",
  "category": "web",
  "category_name": "Web",
  "topic": "css",
  "topic_name": "CSS",
  "route": "/courses/web/css/2/4",
  "area": "2",
  "page": "4",
  "title": "classes_ids_and_tag_selection",
  "friendly_path": "web/css/classes_ids_and_tag_selection"
}, {
  "page_name": "Display, positioning, floating and visibility",
  "category": "web",
  "category_name": "Web",
  "topic": "css",
  "topic_name": "CSS",
  "route": "/courses/web/css/3/1",
  "area": "3",
  "page": "1",
  "title": "display_positioning_floating_and_visibility",
  "friendly_path": "web/css/display_positioning_floating_and_visibility"
}, {
  "page_name": "Width, height, padding, margins and overflow",
  "category": "web",
  "category_name": "Web",
  "topic": "css",
  "topic_name": "CSS",
  "route": "/courses/web/css/3/2",
  "area": "3",
  "page": "2",
  "title": "width_height_padding_margins_and_overflow",
  "friendly_path": "web/css/width_height_padding_margins_and_overflow"
}, {
  "page_name": "Borders, box shadows, border radius and box sizing",
  "category": "web",
  "category_name": "Web",
  "topic": "css",
  "topic_name": "CSS",
  "route": "/courses/web/css/3/3",
  "area": "3",
  "page": "3",
  "title": "borders_box_shadows_border_radius_and_box_sizing",
  "friendly_path": "web/css/borders_box_shadows_border_radius_and_box_sizing"
}, {
  "page_name": "Color, backgrounds, opacity and gradients",
  "category": "web",
  "category_name": "Web",
  "topic": "css",
  "topic_name": "CSS",
  "route": "/courses/web/css/3/4",
  "area": "3",
  "page": "4",
  "title": "color_backgrounds_opacity_and_gradients",
  "friendly_path": "web/css/color_backgrounds_opacity_and_gradients"
}, {
  "page_name": "Font families, sizes, weights, variants, styles and alignment",
  "category": "web",
  "category_name": "Web",
  "topic": "css",
  "topic_name": "CSS",
  "route": "/courses/web/css/3/5",
  "area": "3",
  "page": "5",
  "title": "font_families_sizes_weights_variants_styles_and_alignment",
  "friendly_path": "web/css/font_families_sizes_weights_variants_styles_and_alignment"
}, {
  "page_name": "Descendant selector",
  "category": "web",
  "category_name": "Web",
  "topic": "css",
  "topic_name": "CSS",
  "route": "/courses/web/css/4/1",
  "area": "4",
  "page": "1",
  "title": "descendant_selector",
  "friendly_path": "web/css/descendant_selector"
}, {
  "page_name": "Child selector",
  "category": "web",
  "category_name": "Web",
  "topic": "css",
  "topic_name": "CSS",
  "route": "/courses/web/css/4/2",
  "area": "4",
  "page": "2",
  "title": "child_selector",
  "friendly_path": "web/css/child_selector"
}, {
  "page_name": "Adjacenct sibling selector",
  "category": "web",
  "category_name": "Web",
  "topic": "css",
  "topic_name": "CSS",
  "route": "/courses/web/css/4/3",
  "area": "4",
  "page": "3",
  "title": "adjacenct_sibling_selector",
  "friendly_path": "web/css/adjacenct_sibling_selector"
}, {
  "page_name": "General sibling selector",
  "category": "web",
  "category_name": "Web",
  "topic": "css",
  "topic_name": "CSS",
  "route": "/courses/web/css/4/4",
  "area": "4",
  "page": "4",
  "title": "general_sibling_selector",
  "friendly_path": "web/css/general_sibling_selector"
}, {
  "page_name": "Universal selector",
  "category": "web",
  "category_name": "Web",
  "topic": "css",
  "topic_name": "CSS",
  "route": "/courses/web/css/4/5",
  "area": "4",
  "page": "5",
  "title": "universal_selector",
  "friendly_path": "web/css/universal_selector"
}, {
  "page_name": "Attribute selector",
  "category": "web",
  "category_name": "Web",
  "topic": "css",
  "topic_name": "CSS",
  "route": "/courses/web/css/4/6",
  "area": "4",
  "page": "6",
  "title": "attribute_selector",
  "friendly_path": "web/css/attribute_selector"
}, {
  "page_name": "An introduction to pseudo-selectors",
  "category": "web",
  "category_name": "Web",
  "topic": "css",
  "topic_name": "CSS",
  "route": "/courses/web/css/5/1",
  "area": "5",
  "page": "1",
  "title": "an_introduction_to_pseudo-selectors",
  "friendly_path": "web/css/an_introduction_to_pseudo-selectors"
}, {
  "page_name": "Advanced CSS pseudo selectors",
  "category": "web",
  "category_name": "Web",
  "topic": "css",
  "topic_name": "CSS",
  "route": "/courses/web/css/5/2",
  "area": "5",
  "page": "2",
  "title": "advanced_css_pseudo_selectors",
  "friendly_path": "web/css/advanced_css_pseudo_selectors"
}, {
  "page_name": "Shorthand CSS",
  "category": "web",
  "category_name": "Web",
  "topic": "css",
  "topic_name": "CSS",
  "route": "/courses/web/css/6/1",
  "area": "6",
  "page": "1",
  "title": "shorthand_css",
  "friendly_path": "web/css/shorthand_css"
}, {
  "page_name": "Precedence and specificity",
  "category": "web",
  "category_name": "Web",
  "topic": "css",
  "topic_name": "CSS",
  "route": "/courses/web/css/6/2",
  "area": "6",
  "page": "2",
  "title": "precedence_and_specificity",
  "friendly_path": "web/css/precedence_and_specificity"
}, {
  "page_name": "CSS rules",
  "category": "web",
  "category_name": "Web",
  "topic": "css",
  "topic_name": "CSS",
  "route": "/courses/web/css/6/3",
  "area": "6",
  "page": "3",
  "title": "css_rules",
  "friendly_path": "web/css/css_rules"
}, {
  "page_name": "Optimising CSS delivery",
  "category": "web",
  "category_name": "Web",
  "topic": "css",
  "topic_name": "CSS",
  "route": "/courses/web/css/6/4",
  "area": "6",
  "page": "4",
  "title": "optimising_css_delivery",
  "friendly_path": "web/css/optimising_css_delivery"
}, {
  "page_name": "Cross platform and browser compatibility",
  "category": "web",
  "category_name": "Web",
  "topic": "css",
  "topic_name": "CSS",
  "route": "/courses/web/css/6/5",
  "area": "6",
  "page": "5",
  "title": "cross_platform_and_browser_compatibility",
  "friendly_path": "web/css/cross_platform_and_browser_compatibility"
}, {
  "page_name": "Server-side generated CSS",
  "category": "web",
  "category_name": "Web",
  "topic": "css",
  "topic_name": "CSS",
  "route": "/courses/web/css/6/6",
  "area": "6",
  "page": "6",
  "title": "server-side_generated_css",
  "friendly_path": "web/css/server-side_generated_css"
}, {
  "page_name": "CSS and Sass",
  "category": "web",
  "category_name": "Web",
  "topic": "css",
  "topic_name": "CSS",
  "route": "/courses/web/css/6/7",
  "area": "6",
  "page": "7",
  "title": "css_and_sass",
  "friendly_path": "web/css/css_and_sass"
}, {
  "page_name": "An introduction to responsive web design",
  "category": "web",
  "category_name": "Web",
  "topic": "css",
  "topic_name": "CSS",
  "route": "/courses/web/css/7/1",
  "area": "7",
  "page": "1",
  "title": "an_introduction_to_responsive_web_design",
  "friendly_path": "web/css/an_introduction_to_responsive_web_design"
}, {
  "page_name": "Tablet and smartphone friendly CSS",
  "category": "web",
  "category_name": "Web",
  "topic": "css",
  "topic_name": "CSS",
  "route": "/courses/web/css/7/2",
  "area": "7",
  "page": "2",
  "title": "tablet_and_smartphone_friendly_css",
  "friendly_path": "web/css/tablet_and_smartphone_friendly_css"
}, {
  "page_name": "CSS transform",
  "category": "web",
  "category_name": "Web",
  "topic": "css",
  "topic_name": "CSS",
  "route": "/courses/web/css/8/1",
  "area": "8",
  "page": "1",
  "title": "css_transform",
  "friendly_path": "web/css/css_transform"
}, {
  "page_name": "CSS transitions",
  "category": "web",
  "category_name": "Web",
  "topic": "css",
  "topic_name": "CSS",
  "route": "/courses/web/css/8/2",
  "area": "8",
  "page": "2",
  "title": "css_transitions",
  "friendly_path": "web/css/css_transitions"
}, {
  "page_name": "CSS counters",
  "category": "web",
  "category_name": "Web",
  "topic": "css",
  "topic_name": "CSS",
  "route": "/courses/web/css/8/3",
  "area": "8",
  "page": "3",
  "title": "css_counters",
  "friendly_path": "web/css/css_counters"
}]

On the front end, the page is found via its friendly_path value. To keep the order correct, the pages are not given a key. Although it would make it slightly faster to give them this key, it would mean that the order isn't correct any longer.

Changes to title names will actually break the system and any changes made will need to be followed by a running of the automated script (which happens every evening anyway).

I'm still testing this feature out, so if you find any bugs, let me know. 

ZPE 1.9.7 (Galashiels) is one of the most solid updates yet. Many major bug fixes have been introduced, new performance gains and a new typing system (TYPO v2). 

TYPO v2 is perhaps the biggest improvement to the whole ZPE Programming Environment in the last few months, and it changes the whole way that it works underneath. Instead of doing type checking at compile time and thus making starting and interpreting programs/scripts slower, it is now done at runtime. The impact here is actually slightly smaller and relies on the underlying implementation of variables to perform this check. 

TYPO v2 also removes the STRONG_TYPED property from the properties list and allows side by side strongly typed, statically typed and weakly, dynamically typed variables to be declared side by side in a single program or script. 

All ZPE/YASS documentation has been updated to reflect this new change, particularly the page on Assignment and variables.

ZPE 1.9.8 is looking to use more static hidden objects to improve both performance and lower memory usage. This might be another big update.

TYPO has been completely redesigned from the ground up to make it even better. Compared with the first version of TYPO, the new version uses late static type checking which is done during runtime rather than compilation time. This does add a slight performance penalty compared with untyped data, but it is far more stable than attempting it at compile time since so many functions may return multiple data types.

For example:

YASS
declare $i as number = 50
declare j as number = 32
$i = "Test"

This would crash when it gets to setting $i from a number to a string. Previously this check was carried out by the compiler but it wasn't effective in comparison, whereas defining it this way ensures 100% efficiency in comparisons and although late typing often has performance penalties, in comparison to the previous iteration of TYPO so much has been improved that these penalties are actually minuscule. 

Another major change to TYPO is that is now always enabled and doesn't need to be set in the ZPE Properties file, and can be used in parallel with untyped YASS code for the first time.

The formalised specification of the language has yet to be updated with this new information but will be sorted at some point over the next few days.

With ZPE and YASS featuring more and more unit testing capabilities, I thought it was time for me to look into adding proper testing methods.

ZPE unit testing will broaden and expand the current situation with unit testing to the point where specific unit testing scripts can be produced separately from any code.

Unit testing, known as zUnit, will feature its own language parser, also built upon the Zenith Parsing Engine, of course. It will use a language different from YASS entirely and will also allow multiple tests to be carried out on code very quickly.

Like when ZPE started out, it will likely begin as a very basic tool for testing but will expand to provide more and more features as time goes on.

As a result of the sweeping new changes brought to unit testing so far, ZPE 1.9.6 is now available much earlier than I had originally planned for. Please also note that this version removes the new record structure as this is under redevelopment.

Over the last few years, the landscape for our business has been heavily changed by the outbreak of COVID-19. Jambour Digital has had to adapt quite a bit to both continue to grow and to retain existing clients. We've supported our existing clients by offering them both financial support and extra features. But as we move back to something a bit like normality, how do we plan to expand Jambour Digital?

Challenges faced

Over the last year or so, we've faced a tremendous amount of challenges within the business, ranging from not being able to see new clients, to not being able to meet with our existing clients. All of this makes development much trickier. Further to this, we've encountered that a lot of our clients themselves are so busy that things like updating a website or even simply checking out a new feature on a website is becoming a difficult task to fit into their schedules.

Leading us back to normal

As the leading managing director of Jambour Digital, I have overseen all plans to support the business out of this difficult time and to support our clients in doing so. 

We have adopted a new member of the company on contract, Kyle, who works with us when we need him. This will help me focus on the business side of the company alongside my brother and my mother who are the other managing directors of the company. 

We plan to take things one step at a time to minimise risk and to ensure a safe return to normal. 

We understand our clients who hopefully understand that the most important thing here is safety. 

I'm really happy to announce BalfSlider V2 as of today. It is now fitted out with the generator and the samples as well as being used on my own website without any issues.

V2 breaks compatibility with V1 but offers much smaller file sizes and easier to maintain code. Packaged as always with the slideshow is the BalfSliderAnimations package. This has changed too, albeit, very marginally. Effects are still the same but the structure of the code differs.

Why did I bother?

The old version was, at the very least, difficult to maintain. I needed to streamline this version and move away from passing objects. The new version offers more functionalities that will allow future animations to be created with ease. 

You can download the latest version from my website from today.

Over the next few weeks, I'm moving all of my teaching resources from PowerPoint and Google Slides to my own website which will bring them to HTML and CSS and bring them alive.

By bringing them to the web, I can use what I know best to make these slides highly interactive and useful. I have in the past done this with some of the slide decks I have used at talks I have carried out (such as my talk at Amazon on a small business using AWS to promote growth) and also as an introduction to ZPE but things haven't been as smooth as they will be this time.

This project stems from my hatred for both Google Slides and PowerPoint due to the lack of something that mirrors CSS - I have been developing my own PowerPoint theme over the last few years and every time I think of something new, I need to update all of my slides. CSS fixes this and it's something I've wanted for a very long time.

It's now found at https://www.jamiebalfour.scot/teaching/slides/.  

Powered by DASH 2.0