Commit 538c4781 authored by Mike Street's avatar Mike Street
Browse files

Task: Content audit and style updates

parent a343dc3c
......@@ -24,3 +24,6 @@ sitemapIgnore: true
/blog/p16 /blog/15/
/blog/p17 /blog/16/
/blog/p18 /blog/17/
# Blog posts
/blog/reminder-git-analytics-tina-and-js blog/notes-0/
......@@ -4,6 +4,5 @@ sitemapIgnore: true
---
User-agent: *
Allow: /
Disallow: /drafts/
Sitemap: {{ meta.site.url }}/sitemap.xml
---
title: Dahon Vitesse Speed D7
date: 2012-02-26
updated: 2016-04-08
updated: 2021-03-28
intro: Whenever I am thinking about making a significant purchase, I always hunt around for reviews, check out blogs and generally search the web for word, be it good or bad.
permalink: "blog/dahon-vitesse-speed-d7/"
tags:
- General
- Thoughts
......
---
title: How do I update to Gulp 4?
date: 2016-03-22
updated: 2021-03-28
intro: Gulp is a task runner used for compiling SCSS to CSS, minifying JS and creating SVG sprites. Version 4 is about to be released and this blog post runs you through how to update and use the new features of gulp.
canonical: https://www.liquidlight.co.uk/blog/how-do-i-update-to-gulp-4/
publication: Liquid Light
permalink: "blog/how-do-i-update-to-gulp-4/"
tags:
- Web
- Gulp
---
Gulp is a fantastic build tool for compiling your SCSS, Less and [SVG sprites](https://www.liquidlight.co.uk/blog/article/creating-svg-sprites-using-gulp-and-sass/) that we use at Liquid Light.
For a while now, the gulpJS team have been working on [Version 4](https://github.com/gulpjs/gulp). This version features some nice additions to the build tool but does also feature some substantial breaking changes. Upgrading is simple, but does require a few tweaks.
## Upgrading gulp to v4
_**Note:** The `$` shows the command is to be run on the command line and shouldn’t be typed_
```bash
$ npm install -g gulp
```
```bash
$ gulp -v
CLI version 2.0.1
```
If you are in a gulp project, a local version will be listed below the `CLI version`
### Install gulp 4 locally
Once globally installed, gulp v4 will then need to be installed on a per-project basis.
```bash
$ npm install gulp --save-dev
```
If in your `package.json` file gulp is listed under `dependencies`, then replace the `--save-dev` with just `--save`.
You should now have gulp v4 installed and ready to go. This can be verified by running the version command above
Running `gulp -v` once again should now give you
```bash
$ gulp -v
CLI version 2.0.1
Local version 4.0.0
```
## Updating your gulpfile
Now you have v4 successfully installed, you’ll need to do a few updates to your gulpfile.js. The best thing to do is run `gulp` and follow the errors that you get.
When you get an error, you will be faced with several lines of what appears to be jargon.
The first thing you need to look for is the error message. This will be something like
```bash
Error: Error message here
```
Make a note of that. The second line to look for is the one that includes the path to your gulpfile with some numbers afterwards. This is what mine looks like:
```bash
at Object.<anonymous> /Sites/gulp-v4/gulpfile.js:418:6
```
This tells you the error was generated in your gulpfile at line **418**, character **6**.
I’ve tested below some errors I came across during the update and how to fix them.
### AssertionError: Task function must be specified
This error for me was thrown because of:
```js
gulp.task('default', ['del'], function() {
// default task code here
});
```
Where the `del` task is being run before the `default` task.
To resolve this, you need to specify that the `del` and following function are to be run in a `series`.
To resolve this, change the code to:
```js
gulp.task('default', gulp.series('del', function() {
// default task code here
}));
```
_**Note:** because you are opening a parenthesis for `gulp.series`, don’t forget to add an extra closing one after the function._
Make sure you update the rest of your gulpfile to follow suit.
The gulp has updated this syntax for running tasks in series to add the functionality of running tasks in parallel with `gulp.parallel`. More can be read about it [in the gulp docs](https://github.com/gulpjs/gulp/tree/master/docs/api#gulpparalleltasks).
### Did you forget to signal async completion?
```bash
The following tasks did not complete: default, del
Did you forget to signal async completion?
```
This error occurred on an anonymous function (the one occurring after `del` in the example above).
Gulp v4 requires a stream, promise, event emitter, child process or observable to be returned from a function or task. This was resolved in the simplest case of passing a parameter into the function and firing it after the task is completed.
E.g.
```js
gulp.task('default', gulp.series(function(done) {
// task code here
done();
}));
```
(Note the `done` in-between the parenthesis when the function opens and then it firing at the end).
I specifically got this error when trying to run the `del` [npm package](https://www.npmjs.com/package/del).
My `del` package was set to call `del.sync` which returns an array, Gulp requires one of the stream, promise, event emitter, child process or observable to be returned, which `del` does by default.
```js
return del(dirs);
```
### Gulp watcher with change event and paths
With gulp v3, the watcher would return the path of the modified file within the function it called.
For example, the output for the below would be an object with the location of the file modified and event (e.g. `changed`).
```js
gulp.task('watch', function(){
gulp.watch('path/to/css/*.css').on('change', function(event) {
console.log(event.path);
console.log(event.type);
// code to execute
});
});
```
With gulp 4, this doesn't seem to be the case. Instead, the watcher can fire some standard functions, but if you need filename based operations, these need to be moved to the `changed` function.
```js
gulp.task('watch', function(){
gulp.watch('path/to/css/*.css')
.on('change', function(path, stats) {
console.log(path);
// code to execute on change
})
.on('unlink', , function(path, stats) {
console.log(path);
// code to execute on delete
});
});
```
If you did need to fire a generic function when a file is changed while being watched, the [gulp tutorials](https://github.com/gulpjs/gulp/blob/v4.0.0/docs/API.md#gulpwatchglobs-opts-fn) have an example of this.
- - -
Just a small reminder, if you are upgrading to Gulp 4 and have a shared project, the other developers will need to upgrade also.
If you have encountered any other errors, then feel free to drop a comment below or [tweet us](https://twitter.com/liquidlightuk) - we'd be more than happy to help and include the solution above for others!
- - -
**Update 13/08/2018:** Two years later and Gulp 4 still hasn't been released!
---
title: How can I score 100 on Google PageSpeed Insights?
date: 2017-03-13
updated: 2021-03-28
intro: PageSpeed Insights (PSI) is a tool developed by Google to rank the speed of your website. There are a few things it doesn’t look out for, such as code validation or usability but it’s a good starting point at getting your site up to scratch.
canonical: https://www.liquidlight.co.uk/blog/how-can-i-score-100-on-google-pagespeed-insights/
publication: Liquid Light
permalink: "blog/how-can-i-score-100-on-google-pagespeed-insights/"
tags:
- Web
- Google
- Lighthouse
- Performance
---
PageSpeed Insights (PSI) is a tool developed by Google to rank the speed of your website. There are a few things it doesn’t look out for, such as code validation or usability but it’s a good starting point at getting your site up to scratch.
The first step is to head to the [insight tool](https://developers.google.com/speed/pagespeed/insights/) and put your URL in the box. Unless you have already worked your way through the results, you will no doubt be faced with a series of errors and warnings for you to fix. Even the most popular sites could make some improvements (at the time of writing `theguardian.com` receives a 16/100 rating).
PageSpeed Insights is split into two sections - Mobile and Desktop. When measuring your site Google will access it using two different ways; a mobile-user agent and desktop-user agent. When accessing via the mobile-user agent, PSI tries to replicate mobile characteristics, such as screen size, network speed and device processing power. The desktop analysis does not take these factors into consideration and will generally produce a higher score, as page speed will not be restricted.
**So how do you go about getting the elusive 100?**
![The Guardian Website only scores 16 on PSI](/assets/img/content/how-can-i-score-100-on-google-pagespeed-insights/csm_guardian-psi_7cabe9cbe0.webp)
## Minify JavaScript, HTML and CSS
In order to make PSI happy, all your images, CSS, JavaScript and HTML need to be optimised and minified. To minify your CSS and JavaScript, you can use a build tool such as Gulp or Grunt, or there are several online tools which can do this for you. As for minifying HTML, most CMS’s provide this as a plugin (if you are using one), if not services such as Cloudflare act as a CDN and asset compressor. Alternatively desktop applications such as [ImageOptim](https://imageoptim.com/mac) exist to allow you to “preprocess” your images before being uploaded.
If there are any optimisations to be made, PSI will generate a zip file containing all the new assets for you. If you are just running this tool on a static site, download the new assets and upload them to your site.
However, chances are you are going to want to know what optimisations have been made to the assets, so you can update and re-optimise any new assets you create.
## Optimise Images
Having un-optimised images on your site can really hinder your Google PageSpeed score. The messages from Google are very unhelpful, as to what is required to “optimise” your images. We’ve spent the last few weeks ticking all the boxes and working out what is needed:
**JPEG Quality - no higher than 85%**
The compression quality of your jpeg should be no higher than 85% (for example, when saving in Photoshop). In most cases, there is no need to have it this high anyway, but make sure it does not go past this number. Our designers often mention the magic number of “51” for jpeg compression, but use your judgement as to how low you can go.
**JPEG Subsampling - use 4:2:0 (aka 2x2,1x1,1x1 or 2:1:1)**
JPEG subsampling is a topic which is not widely talked about and required a substantial amount of research before we fully understood it. This article on [Chroma-Subsampling](https://calendar.perfplanet.com/2015/why-arent-your-images-using-chroma-subsampling/) explains it better than we ever could. A tool similar to [IMGOnline](http://www.imgonline.com.ua/eng/compress-image.php) can be used to change this. Alternatively we use ImageMagick on the command line.
**Greyscale PNGs - use the right colorspace**
This one caught us out but now seems obvious. If your PNG image only uses black & white colours (e.g. is a shade of grey and features no colour) you can set it to use the  “Gray” PNG colorspace when saving.
**PNG-8 over PNG-32**
Using PNG-8 over PNG-32 is down to personal judgement. Most of the time, PNG-8 will be sufficient for what you need and the file size is normally significantly smaller. This thread on [Stack Overflow](http://stackoverflow.com/questions/22707130/what-is-difference-between-png8-and-png24) explains more. IDUX also have a [great article](http://www.idux.com/2011/02/27/what-are-index-and-alpha-transparency/) explaining alpha transparency
**Image size**
PSI won’t generally pull you up on this, but it is good practice to ensure your images are not oversized for what is required. If your image is only every used as a thumbnail, the user shouldn’t need to download a 4000px image for it.
**Image meta data**
Every image created stores several bits of meta information about itself. Storing this data increases the file size, which isn’t needed on the web. Use an image optimiser or minifier to strip out this meta data, reducing the file size of the image.
## Eliminate render-blocking JavaScript and CSS in above-the-fold content
Google PageSpeed Insights requires any render blocking assets to be located in the footer of the page (just before your closing body tag). These render blocking assets include CSS and Javascript. Be careful - there may be some inline JavaScript on your page which relies on a library (such as jQuery) to be loaded before it can be executed. If this occurs and you are unable to move the inline script, you may wish to consider implementing a “javascript [handler](http://writing.colin-gourlay.com/safely-using-ready-before-including-jquery/)” to prevent your page from failing to execute.
It may seem counter-intuitive to move your CSS to the bottom of the page as the page would have rendered the content before applying styles and the user would see a FOUC (flash of unstyled content). However, this is where critical CSS comes in. The idea behind critical CSS is to include any layout and base styling in the head of your document so the page can render a basic wireframe-esque layout before applying the full styling. The CSS in the head should be inlined (e.g. in between style tags). For example:
```html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style media="screen">
/**
* Critical CSS goes here
*/
</style>
</head>
<body>
<div class="container">
<!-- Web page content -->
<link rel="stylesheet" href="/path/to/your/style.css">
<script src="/path/to/your/script.js"></script>
</div>
</body>
</html>
```
There will still be a small FOUC, but it should be barely visible as long as your page is not too big. Once the site has been visited, the CSS will be cached and the FOUC will then reduce.
The thought of creating and implementing critical CSS could seem quite a task, however many tools exist these days to allow automation. There are many gulp, grunt and webpack plugins if you are using a preprocessor/build tool. Alternatively, there is a [Critical CSS Generator](https://jonassebastianohlsson.com/criticalpathcssgenerator/) website which helps you extract your critical CSS.
## Leverage browser caching and enable compression
Both browser caching and compression require a bit more technical knowledge as they need to be done on the server side. Several CMS’s have this functionality built in if you are using one, if not, then you may need to get your hands dirty. The chances are your website/server already has this set up, so you only need to worry about this if it gets flagged up.
#### Leverage browser caching
PSI requires (we believe) the caching expiry to be set to at least 2 hours. Ironically, Google Analytics get’s flagged up in this section, which you can do nothing about.
#### Enable compression
You will need to enable “gzip” compression. This serves assets up compressed (think like a zip file) which makes them smaller and quicker to download.
## Other PSI Issues to note
### Avoid landing page redirects
Ensure your page doesn’t make any immediate HTTP redirects before any content is visible. For example if your “desktop” site redirects to a “mobile”, or if your users get automatically redirected to another page when landing on the homepage.
### Prioritize visible content needs more detail
Any content “above the fold” should be able to be rendered without any additional requests.  This can be achieved by removing any render blocking CSS and JavaScript plugins at the top of the page. A classic example of this is the homepage slider - as it would need the library and images to be rendered and loaded before being initialised. This is one of the most common issues websites fall foul of.
### Reduce server response time
Resolving this is beyond the scope of the article, but essentially requires your server to have a quick TTFB (time to first byte) and able to serve the HTML for your website quicker than 200ms.
## Conclusion
If you have corrected the issues listed above, you should be somewhere closer to that perfect 100. Google class anything above 85 as a good website, so don’t fret too much if you are not quite there.
However, it’s not all as perfect as it seems: Google do seem to keep moving the goalposts with these rules, already over the last couple of months we’ve seen our scores dramatically drop as they alter some algorithms.
Getting 100 on Google Page Speed Insights is not the golden bullet. You can score top marks and still have a really slow website. If you have a JPG which is still 15mb but optimised correctly, PSI will not penalise you for it. Your CSS and JS could be several megabytes in size, but as long as it is not render blocking and minified, your overall score will be high.
Web development also moves at such a pace, that nothing seems right for long. Today's optimisations often turn into tomorrow's “hacks” (remember when it was best practice to have all your CSS in one file served at the top of your page?!). With the progression of the internet and serving up assets ever evolving (HTTP/2 for example) if you don’t keep on top of it you can soon fall behind.
At the end of the day, as long as your website is fast for the user, accessible to everyone and works consistently and doesn’t eat up data, who cares what a machine on the internet says‽
All the information mentioned in this blog in more detail can be found on the Rules page - it’s well worth having a read over to get a better understanding of what they are after.
---
title: How can I verify my Google Event Tracking is working?
date: 2017-09-18
updated: 2021-03-28
intro: Validating your Google Event tracking is working can be a tricky business. This blog post walks you through checking the data being sent to Google Analytics, so you can verify the information is correct.
canonical: https://www.liquidlight.co.uk/blog/how-can-i-verify-my-google-event-tracking-is-working/
publication: Liquid Light
permalink: "blog/how-can-i-verify-my-google-event-tracking-is-working/"
tags:
- Web
- Google
- Analytics
---
_This blog post does go slightly technical - you should hopefully be familiar with seeing Chrome Developer Web Tools open - or know someone that does._
Google Analytics (GA) is great. It gives you data on your most popular content and informs you on where users are coming from. Along with this, GA enables you to add and track [specific events](https://developers.google.com/analytics/devguides/collection/analyticsjs/events). Event tracking can include any interaction on your page - for example you may wish to know if an FAQ has been opened, a button clicked or a modal dialog closed.
By using event tracking you can get a better understanding of user behaviour on your website especially if those actions don’t generate traditional page view analytic events.
Alongside GA you can also use plugins such as the [jQuery scroll depth plugin](http://scrolldepth.parsnip.io/) which will tell you, as an event, how far people scroll down your website (e.g. 30 people scrolled 75% of the way down). This is particularly useful if you are assessing your page structure and content layout.
Validating the event data being sent is potentially a tricky one. If your website is low on visitors then you can trigger the event yourself and hopefully see it in the “**Real Time > Events**” panel in Google Analytics. However, if you are unsure if your event is setup correctly or if your website is busy, it can be hard to identify if your changes are having any effect. Checking if your event is working when it should is almost as essential as knowing when it doesn’t work when it shouldn’t - especially as you don’t want to be send false data and building false reports.
Fortunately Google themselves have developed an analytics debugger which can be installed as a Chrome extension. This lets you drill-down into what data is being sent, so you can check that it is valid and what you expect.
## Setup instructions
### Install the plugin
The first step is to install the [Chrome extension](https://chrome.google.com/webstore/detail/google-analytics-debugger/jnkmfdileelhofjcijamephohjechhna). This just takes a few clicks and should add a new icon to your browser.
<figure>
<img loading="lazy" class="image-embed-item" alt="Installing chrome extension" src="/assets/img/content/how-can-i-verify-my-google-event-tracking-is-working/csm_ga_tracking_install_36dadcde2c.webp" width="1200" height="900">
</figure>
### Visit your website
Go to the jpegage where you have set up the Google events. The console now needs to be opened. You can _right click -> inspect element_ and then click the console tab. The [Google website](https://developers.google.com/web/tools/chrome-devtools/console/) has more details on opening the console.
<figure class="csc-textpic-image">
<a href="/assets/img/content/how-can-i-verify-my-google-event-tracking-is-working/ga_tracking_open_console.gif">
<img loading="lazy" class="image-embed-item" alt="Opening the JavaScript console" src="/assets/img/content/how-can-i-verify-my-google-event-tracking-is-working/ga_tracking_open_console.jpeg" width="960" height="721">
</a>
</figure>
_Note: If your event involves navigating to a different page (for example; a button click) you will want to enable “Preserve log upon navigation” - this stops your event tracking info being removed from the console before you’ve had time to view it. To do this, click the 3 dots in the top right and click settings. Scroll down to the “Console” section and enable the checkbox \[[Watch a gif on how to do this]/assets/img/content/how-can-i-verify-my-google-event-tracking-is-working/ga_tracking_preserve_log.gif)\]._
### Enable the plugin
When you’re ready, enable the plugin by clicking the icon in the taskbar. The page will refresh and the developer console will be filled with lots of data (including a Google Analytics header). If you see this, it means it’s working. Click the “clear console” button (located in the top left of the console) to give yourself a clean slate and then perform the event.
In the gif below, the plugin is activated and then I begin to scroll down the page. We are using the aforementioned jQuery scroll plugin, so at 25% an event is triggered. Looking at the data in the console, the two important bits get highlighted - category and label. These reference the fields required to pass data through to Google Analytics.
<figure class="csc-textpic-image">
<a href="/assets/img/content/how-can-i-verify-my-google-event-tracking-is-working/ga_tracking_scroll_event.gif">
<img loading="lazy" class="image-embed-item" alt="Tracking a scroll event" src="/assets/img/content/how-can-i-verify-my-google-event-tracking-is-working/ga_tracking_scroll_event.jpeg" width="960" height="719">
</a>
</figure>
It is worth taking time to understand the output in the console as it can help you understand what is being sent to Google Analytics. Be careful to check that your data is only being sent once as intended and that a single click or scroll doesn’t trigger many events. The big “google analytics” text in the console (seen in the gif below at the bottom) represents a new page navigation - button click events to go to a new page are sent before this, so make sure you scroll up to the correct part. I find regularly clearing the console helps me understand when events start and stop.
<figure class="csc-textpic-image">
<a href="/assets/img/content/how-can-i-verify-my-google-event-tracking-is-working/ga_tracking_button_click.gif">
<img loading="lazy" class="image-embed-item" alt="Tracking a button click " src="/assets/img/content/how-can-i-verify-my-google-event-tracking-is-working/ga_tracking_button_click.jpeg" width="960" height="717">
</a>
</figure>
Tracking what your users are doing on your website gives you great insights into what parts of your site are being used, utilised and viewed. This in turn will help you focus your efforts on either getting the less interacted-with more noticed, or improving the more popular parts of your website further. Let us know in the comments below what you think and, as ever, if you have any issues!
---
title: How I wrote a book; the writing process from one of our Developers
date: 2018-03-08
updated: 2019-03-27
intro: Over the second half of 2017, I spent my spare time writing a book on Vue.js and it’s official plugins; [Vue.js 2.x by Example](https&#58;//www.packtpub.com/...
updated: 2021-03-28
intro: In 2017, one of our front-end developers wrote and released a book about the JavaScript library; Vue.js. This blog post explains the process he went through to get the book from his mind to print.
canonical: https://www.liquidlight.co.uk/blog/how-i-wrote-a-book-the-writing-process-from-one-of-our-developers/
publication: Liquid Light
permalink: "blog/how-i-wrote-a-book-the-writing-process-from-one-of-our-developers/"
tags:
- General
- Thoughts
---
Over the second half of 2017, I spent my spare time writing a book on Vue.js and it’s official plugins; [Vue.js 2.x by Example](https://www.packtpub.com/application-development/vuejs-2x-example). The book was then published at the end of December.
{% raw %}
Over the second half of 2017, I spent my spare time writing a book on Vue.js and its official plugins; [Vue.js 2.x by Example](https://www.packtpub.com/application-development/vuejs-2x-example). The book was then published at the end of December.
Writing a book can seem like a daunting process and was certainly something I had never considered before. I’ve outlined the writing process below and how I approached the “mammoth” task.
If you wish the write a book yourself, the first piece of advice I have is to start a blog for yourself. Don’t write the posts for other people, but instead explain things for yourself - nothing cements an idea better than having to re-write and explain an idea or a method. Don’t be put off writing about “easy” or “simple” topics either if you didn't know it, neither do other people.
It was through blog post writing that I was approached by the published PacktPub to write the Vue.js book. They found me through my blog post about [Building a Vue v2 JS app using Vue-router](https://www.liquidlight.co.uk/blog/article/building-a-vue-v2-js-app-using-vue-router/), along with other [Vue.js posts](/category/vuejs) on my personal website.
It was through blog post writing that I was approached by the publisher PacktPub to write the Vue.js book. They found me through my blog post about Building a Vue v2 JS app using Vue-router, along with other [Vue.js posts](https://www.mikestreety.co.uk/category/web/vuejs) on my personal website.
If you have the desire to write a book, you don't have to wait for the publishers to find you. Each publisher has a link on their website allowing potential authors to submit proposals. Go out there, find a publisher you like the look of and submit an idea.
The Writing Process
- - -- - -- - -- - -- - -- - --
## The Writing Process
Initially, the idea of writing a 400 page book from scratch is daunting, however Packt helped me break it down into manageable chunks and make the process a lot smoother.
### Planning
Before starting to write, the publishers got me to flesh out details about the book. This included who the book was for and what the reader expected to learn. Filling out the details gave me flashbacks to secondary school where we had to replicate a similar passage for a a project.
Before starting to write, the publishers got me to flesh out details about the book. This included who the book was for and what the reader expected to learn. Filling out the details gave me flashbacks to secondary school where we had to replicate a similar passage for a project.
The sections included **Audience**, **Mission**, **Objectives and achievements** and **General structure**.
......@@ -41,33 +43,32 @@ This was mentally draining but the assistance it gave me while actually writing
For each chapter, I had to fill out the following:
* **Description** \- a short description of what the chapter will be about
* **Level** \- is it Basic, Medium or Advanced?
* **Topics covered** \- what topics will be covered
* **Skills learned** \- what skills will the reader have at the end of the chapter?
* **Description** - a short description of what the chapter will be about
* **Level** - is it Basic, Medium or Advanced?
* **Topics covered** - what topics will be covered
* **Skills learned** - what skills will the reader have at the end of the chapter?
With the outline completed and signed off by the publishers, I was sent a schedule which included deadlines for each draft and chapter.
### Writing
Sitting down and writing a book is an odd feeling. You’ve spent weeks planning and finally you’re going to start typing word which will, one day, end up on paper in front of you. You are stating facts and techniques that people are going to pay to learn. It’s not like a blog post which can be edited, or disregarded because it’s free. That part of book writing is scary.
Sitting down and writing a book is an odd feeling. You’ve spent weeks planning and finally you’re going to start typing words which will, one day, end up on paper in front of you. You are stating facts and techniques that people are going to pay to learn. It’s not like a blog post which can be edited, or disregarded because it’s free. That part of book writing is scary.
However, the rigid book and chapter structure which I had “forced” to create and the list of deadlines in my calendar, I was able to focus on each part without worrying about writing a book.
However, the rigid book and chapter structure which I had been “forced” to create and the list of deadlines in my calendar meant that I was able to focus on each part without worrying about writing a book.
I decided to write the code for the book as I wrote the words. This helped me create a more organic and natural flow to the book, without having the code pre-written and a programmatic approach to explaining each line.
The other advantage to writing code as the book is written is allowing the user to learn how a project would be developed. Which steps are taken in which order. There a times in the book I encourage the reader to delete code they’ve written a chapter before, or replace functions and methods with more effective code. This allows an organic understanding of the code.
The other advantage to writing code as the book is written is allowing the user to learn how a project would be developed. Which steps are taken in which order. There are a times in the book I encourage the reader to delete code they’ve written a chapter before, or replace functions and methods with more effective code. This allows an organic understanding of the code.
A book snippet
- - -- - -- - -- - ---
## A book snippet
I’ve included an excerpt from the book below, to give you a taste of the contents. If you are interested in buying a copy, you can do so from [the publisher's website](https://www.packtpub.com/application-development/vuejs-2x-example) or from [Amazon](https://www.amazon.co.uk/Vue-js-2-x-Example-Example-driven-beginners/dp/1788293460). A bigger sample of the book can be found on [Google Books](https://books.google.co.uk/books?id=OPNFDwAAQBAJ&pg=PP1&lpg=PP1&dq=vue.js+2.x+by+example&source=bl&ots=-zybyFHveX&sig=K_mO-b_7yUXsRJiREorMcYb99T4&hl=en&sa=X&ved=0ahUKEwjD_qr6mYXZAhXLCMAKHWeUCkAQ6AEIXDAI).
As mentioned above, the book covers the development process of building three web apps. The apps developed during the book are:
* A people listing directory; with filtering and search
* A Dropbox web app; allowing the user to navigate through their Dropbox and download files and
* A shop interface; which allows the user the browse through products and “checkout”
- A people listing directory; with filtering and search
- A Dropbox web app; allowing the user to navigate through their Dropbox and download files and
- A shop interface; which allows the user the browse through products and “checkout”
The Dropbox app introduces Vuex, a plugin allowing you to create a central store/cache for your application while the shop takes this one step further by also introducing Vue-router, a second plugin which handles URLs and routing in the app.
......@@ -83,37 +84,47 @@ Binding a CSS class is similar to other attributes. The value takes an object th
First, let's add a class to the cell containing the `isActive` variable if the user is active:
<pre class="language-html"><code>&lt;td v-bind:class="{ active: person.isActive }"&gt;
```html
<td v-bind:class="{ active: person.isActive }">
{{ activeStatus(person) }}
&lt;/td&gt;</code></pre>
</td>
```
The class HTML attribute is first prepended by `v-bind:` to let Vue know it needs to process the attribute. The value is then an object, with the CSS class as the key and the condition as the value. This code toggles the active class on the table cell if the `person.isActive` variable equates to `true`. If we wanted to add an inactive class if the user was not active, we could add it to the object:
<pre class="language-html"><code>&lt;td v-bind:class="{ active: person.isActive, inactive: !person.isActive }"&gt;
```html
<td v-bind:class="{ active: person.isActive, inactive: !person.isActive }">
{{ activeStatus(person) }}
&lt;/td&gt;</code></pre>
</td>
```
Here's we've used the exclamation point again to reverse the status. If you run this app, you should find the CSS classes applied as expected.
If we're just applying two classes based on one condition, a ternary if statement can be used inside of the class attribute:
<pre class="language-html"><code>&lt;td v-bind:class="person.isActive ? 'active' : 'inactive'"&gt;
```html
<td v-bind:class="person.isActive ? 'active' : 'inactive'">
{{ activeStatus(person) }}
&lt;/td&gt;</code></pre>
</td>
```
Note the single quotes around the class names. Once again, however, logic has started to creep into our View and, should we wish to also use this class elsewhere, is not very scalable.
Create a new method on our Vue instance called activeClass and abstract the logic into that — not forgetting to pass the `person` object in:
<pre class="language-js"><code>activeClass(person) {
```js
activeClass(person) {
return person.isActive ? 'active' : 'inactive';
}</code></pre>
}
```
We can now call that method in our view:
<pre class="language-html"><code>&lt;td v-bind:class="activeClass(person)"&gt;
```html
<td v-bind:class="activeClass(person)">
{{ activeStatus(person) }}
&lt;/td&gt;</code></pre>
</td>
```
I appreciate this is quite a simple execution; let's try a slightly more complex one. We want to add a conditional class to the balance cell depending on the value. If their balance is under $2000, we will add an `error` class. If it is between $2000 and $3000, a `warning` class will be applied and if it is over $3000 a `success` class will be added.
......@@ -121,19 +132,24 @@ Along with the error, warning and success classes, a class of `increasing` will
As this contains several bits of logic, we will create a use a method in our instance. Create a `balanceClass` method and bind it to the class HTML attribute of the cell containing the balance. To begin with, we'll add the error, warning and success classes.
<pre class="language-html"><code>&lt;td v-bind:class="balanceClass(person)"&gt;
```html
<td v-bind:class="balanceClass(person)">
{{ formatBalance(person.balance) }}
&lt;/td&gt;</code></pre>
</td>
```
In the method, we need to access the balance property of the person passed in and return the name of the class we wish to add. For now, we'll return a fixed result to verify that it's working:
<pre class="language-js"><code>balanceClass(person) {
```js
balanceClass(person) {
return 'warning';
}</code></pre>
}
```
We now need to evaluate our `balance`. As it's already a number, comparing it against our criteria won't involve any conversions:
<pre class="language-js"><code>balanceClass(person) {