one

How Silverstone circuit could help F1

Silverstone managing director, Stuart Pringle made clear that everything had to be done so as not to put stress on policing or divert medical resources away from the fight against the coronavirus.




one

Water-resisting property and key technologies of grouting reconstruction of the Upper Ordovician limestone in North China's coalfields Hao Wang

Online Resource




one

The superior project manager: global competency standards and best practices / Frank Toney

Online Resource




one

Constitutive modelling and failure prediction for silicone adhesives in façade design Michael Drass

Online Resource




one

A telephone for the world: Iridium, Motorola, and the making of a global age / Martin Collins

Dewey Library - HE7797.I75 C65 2018




one

Morituris felicem vitae finem, Mortuis beatem sine fine vitam Silete, Confoederati Amici; quid emortuum Corniculum vestris auribus triste insonet, avidi auscultate, habet secreta ... Translatus est de vita ad mortem ... P. Tobias Herele ...

Autor: Herele, Tobias
Erschienen 1684
BSB-Signatur Res/2 Bavar. 980,2#Beibd.205

URN: urn:nbn:de:bvb:12-bsb11121330-5
URL: http://reader.digitale-sammlungen.de/de/fs1/object/display/bsb11121330_00001.html/




one

“I Am Someone Who Tends to Be Lazy”: The Importance of Soft Skills, and How Not to Measure Them in Schools

Guided by the recent Every Student Succeeds Act (ESSA), states are scrambling to incorporate nonacademic skills into school measurement systems, raising the question: “What measures should schools use and for which purpose?”




one

One world divisible : a global history since 1945 / David Reynolds

Reynolds, David, 1952-




one

The army and the Indonesian genocide [electronic resource] : mechanics of mass murder / Jess Melvin

Melvin, Jess, author




one

Oral histories of Wanneroo wetlands : recollections of Wanneroo pioneers : changes that occurred between European settlement and the 1950's / Shona Kennealy

Kennealy, Shona




one

Hashim Amla: One of South Africa's all-time greats

Here's a look at the South African run machine's brilliant record in international cricket, says Rajneesh Gupta.




one

[ASAP] One-Step Surface Modification to Graft DNA Codes on Paper: The Method, Mechanism, and Its Application

Analytical Chemistry
DOI: 10.1021/acs.analchem.0c00317




one

[ASAP] Temporal-Spatial-Color Multiresolved Chemiluminescence Imaging for Multiplex Immunoassays Using a Smartphone Coupled with Microfluidic Chip

Analytical Chemistry
DOI: 10.1021/acs.analchem.0c01405




one

Pause, rewind, play: Relive Ashes 2005 – one of the greatest Test series of all time

This documentary encapsulates the drama, the highs and lows, the animosity between the two teams, and England’s redemption as a cricketing power.




one

Coronavirus: Pune-based cricket museum buys Azhar Ali’s auctioned bat and jersey to raise funds

The Pakistan Test captain had put his bat used to score triple century in a day-night Test and Champions Trophy 2017 jersey up for auction.




one

Coronavirus: Players not wholly on board with proposal to resume NBA in giant quarantine zone

NBA Players Association executive director Michele Roberts told ESPN that the idea of setting up a bubble to guard against coronavirus was met with skepticism.




one

Hockey: President Narinder Batra’s term extended till May 2021 after FIH postpones annual congress

The annual meeting was originally scheduled for October 28, 2020 but had to be postponed due to uncertainty surrounding the coronavirus pandemic.




one

Lionel Messi and his Barcelona teammates return to training as La Liga eyes restart

The players arrived alone for individual sessions and took to the three pitches without passing through the changing rooms.




one

UFC to go ahead with it’s schedule despite one of the fighter testing positive for coronavirus

The organisers said Brazilian Ronaldo Souza, who was to fight Uriah Hall on the undercard, will not take part in the event.




one

Against all odds: Natalia Partyka, the one-armed TT player, who inspires the world

Too often, people only see the hurdles. But Partyka only saw the possibilities.




one

[ASAP] Characterization of Conjugation Effects in the Series of Quinoxaline-2-ones by Means of Vibrational Raman Spectroscopy

The Journal of Physical Chemistry A
DOI: 10.1021/acs.jpca.0c01838




one

[ASAP] Photochemical Generation of Benzoazetinone by UV Excitation of Matrix-Isolated Precursors: Isatin or Isatoic Anhydride

The Journal of Physical Chemistry A
DOI: 10.1021/acs.jpca.0c02562




one

Are You Honest When Patients Ask, 'What Would You Do?'

Dr David Kerr on when it might be the right decision to tell patients that you believe they're pursuing the wrong treatment.
Medscape Oncology




one

MCC Indonesia Nutrition Project Impact Evaluation Final Report

This report presents findings from a 5-year randomized control trial of a $120 million maternal and child health project in Indonesia funded by the Millennium Challenge Corporation. The project sought to improve stunting, along with a host of other pre-, postnatal, and early childhood health outcomes.




one

Octopus crowd: maritime history and the business of Australian pearling in its schooner age / Steve Mullins

Hayden Library - SH377.A8 M85 2019




one

Grinnell: America's environmental pioneer and his restless drive to save the West / John Taliaferro

Dewey Library - QH31.G74 T35 2019




one

Planning for the planet: environmental expertise and the international union for conservation of nature and natural resources, 1960-1980 / Simone Schleper

Hayden Library - QH75.S257 2019




one

Big Lonely Doug: the story of one of Canada's last great trees / Harley Rustad

Hayden Library - QH106.2.B7 R87 2018




one

Working with dynamic crop models: methods, tools and examples for agriculture and environment / Daniel Wallach, David Makowski, James W. Jones, Francois Brun

Hayden Library - SB112.5.W35x 2019




one

Tropical wetlands: proceedings of the International Workshop on Tropical Wetlands - Innovation in Mapping and Management, October 19-20, 2018, Banjarmasin, Indonesia / edited by Yiyi Sulaeman, Laura Poggio, Budiman Minasny, Dedi Nursyamsi

Online Resource




one

Estuaries and coastal zones in times of global change: proceedings of ICEC-2018 / Kim Dan Nguyen, Sylvain Guillou, Philippe Gourbesville, Jérôme Thiébot, editors

Online Resource




one

Insect sex pheromone research and beyond: from molecules to robots / Yukio Ishikawa, editor

Online Resource




one

Structure and tensile properties of the forewing costal vein of the honeybee Apis mellifera

Soft Matter, 2020, 16,4057-4064
DOI: 10.1039/C9SM02364J, Paper
Yun Ma, Tianbao Ma, Jianguo Ning, Stanislav Gorb
Our paper reveals the functional morphology and tensile properties of the forewing costal vein of honeybees, reviews studies on wings and discusses outlooks for future research.
The content of this RSS Feed (c) The Royal Society of Chemistry




one

Uniform conductivity in stretchable silicones via multiphase inclusions

Soft Matter, 2020, Advance Article
DOI: 10.1039/D0SM00383B, Paper
R. Adam Bilodeau, Amir Mohammadi Nasab, Dylan S. Shah, Rebecca Kramer-Bottiglio
A thin, stretchable (200% linear strain), multiphase (solid–liquid) silicone composite with uniform electrical conductivity, for Joule heating and high-deformation sensing.
To cite this article before page numbers are assigned, use the DOI form of citation above.
The content of this RSS Feed (c) The Royal Society of Chemistry




one

On the pressure dependence of the thermodynamical scaling exponent γ

Soft Matter, 2020, Advance Article
DOI: 10.1039/D0SM00254B, Paper
R. Casalini, T. C. Ransom
In materials with a constant scaling parameter γS, the Isomorph γI is found to vary with pressure, demonstrating γSγI.
To cite this article before page numbers are assigned, use the DOI form of citation above.
The content of this RSS Feed (c) The Royal Society of Chemistry




one

Protonated state and synergistic role of Nd3+ doped barium cerate perovskite for the enhancement of ionic pathways in novel sulfonated polyethersulfone for H2/O2 fuel cells

Soft Matter, 2020, 16,4220-4233
DOI: 10.1039/D0SM00427H, Paper
R. Gayathri, M. Ramesh Prabhu
1.8 times higher current density and power density were obtained for a Nd3+ doped barium cerate membrane compared to pure SPES.
The content of this RSS Feed (c) The Royal Society of Chemistry




one

Peers and Politics, c. 1650 - 1850: Essays in Honour of Clyve Jones


 

A collection of essays in honour of Clyve Jones who has made an incomparable contribution to our understanding of the history of the Westminster house of lords – its politics, procedures and business – and to the history of the English and Scottish peerage more generally



Read More...





one

Design Tokens and Component Based Design

Stuart Robson rolls up his sleeves and begins to piece together the jigsaw puzzle that is design tokens and component based design. Starting with the corners, and working around the edges, Stu helps us to piece together a full picture of a modern design system.


If you stare at your twitter feed long enough, it can look like everyone is talking about Design Systems. In some cases you could be persuaded to think how shallow the term can go.

“Isn’t this what we called Style Guides?”, “Here’s my React Design System”, “I’ve just updated the Design System in Sketch”

To me, they are some and all of these things. Over the last 4 years of consulting with two clients on their Design System, my own view has changed a little.

If you dig a little deeper into Design Systems twitter you will probably see the term “Design Tokens” pop up at least once a day somewhere. Design Tokens came out of work that was being done at Salesforce with Jina and others who pioneered the creation of Design Tokens as we know them today – creating the first command line tool in Theo that had started the adoption of Design Tokens to the wider Design Systems Community.

A cool term but, what are they?

If you look at your client work, your companies site, the project you’re working on you should notice some parts of the page have a degree of consistency: the background colour of your form buttons is the same colour as your link text, or your text has the same margin, or your card elements have the same spacing as your media object.

These are design decisions, and they should be littered across the overall design of your project. These decisions might start off in a Sketch file and make their way into code from detailed investigation of a Sketch file, or you may find that the design evolves from your design application once it gets into code.

These design decisions can change, and to keep them synchronised across design and development in applications, as well as a larger documentation site in your Design System, is going to take some effort.

This is where Design Tokens come in, and I find the best way to succinctly reiterate what they are is via the two following quotes…

“Design Tokens are an abstraction for everything impacting the visual design of an app/platform.”
– Sönke Rohde

…and

“We use them in place of hard-coded values in order to maintain a scale-able and consistent visual system.”
– Jina

There are several global design decisions that we can abstract to create a top level design token – Sizing, Font Families, Font Styles, Font Weights, Font Sizes, Line Heights, Border Styles, Border Colours, Border Radius, Horizontal Rule Colours, Background Colours, Gradients, Background Gradients, Box Shadows, Filters, Text Colours, Text Shadow, Time, Media Queries, Z Index, Icons – these can all be abstracted as required.

So, spicy Sass variables?

We can look at Design Tokens as an abstraction of CSS, sort of like Sass variables, but spicier. Looking at them like this we can see that they are (in either .yaml or .json) a group of related key value pairs with more information that can be added as needed.

The great thing with abstracting design decisions outside of your CSS pre-processor is that you’re not tying those decisions to one platform or codebase.

As a crude example, we can see here that we are defining a name and a value that could then become our color, background-color, or border-color, and more.

# Colours
# -------
- name: color-red
  value: #FF0000
- name: color-green
  value: #00FF00
- name: color-blue
  value: #0000FF
- name: color-white
  value: #FFFFFF
- name: color-black
  value: #000000

These can then generate our Sass variables (as an example) for our projects.

$color-red: #FF0000 !default;
$color-green: #00FF00 !default;
$color-blue: #0000FF !default;
$color-white: #FFFFFF !default;
$color-black: #000000 !default;

Why are they so good

Ok, so we now know what Design Tokens are, but why do we need them? What makes them better than our existing solutions (css pre-processors) for defining these design decisions?

I think there are 5 really good reasons why we all should start abstracting these design decisions away from the CSS that they may live in. Some of these reasons are similar to reasons some developers use a pre-processor like Sass, but with added bonuses.

Consistency

Much like using a CSS pre-processor or using CSS custom properties, being able to define a background colour, breakpoint, or font-size in more than one place using the same key ensures that we are using the Sass values across the entire product suite we are developing for.

Using our Design Tokens in their generated formats, we can be sure to not end up with 261 shades of blue.

Maintainability

By using a pre-processor like Sass, or using native CSS custom properties, we can already have maintainable code in our projects. Design Tokens also do this at the abstracted level as well.

Scalability

“Design Tokens enable us to scale our Design across all the permutations.”
– Jina

At this point, we’re only talking about abstracting the design decisions for use in CSS. Having Design Tokens allows design to scale for multiple brands or multiple projects as needed.

The main benefit of Design Tokens in regards to scalability is the option that it gives us to offer the Design Tokens for other platforms and frameworks as needed. With some of the tools available, we can even have these Tokens shared between applications used by designers and developers.

Your marketing site and your iOS application can soon share the same design decisions codified, and you can move towards creating an Android app or web application as required.

Documentation

If we abstract the design decisions from one platform specific programming language it would be no good if it wasn’t made to be easily accessible.

The tools and applications available that are mentioned later in this article can now create their own documentation, or allow you to create your own. This documentation is either hosted within a web-based application or can be self-hosted with the rest of your Design Systems documentation.

Most of the command line tools go further and allow you do add more details that you wish to convey in the documentation, making it as unique as it is required for your project.

Empowerment

When you abstract your design decisions to Design Tokens, you can help empower other people on the project. With the tools available today, and the tools that are just around the corner, we can have these design decisions determined by anyone on the team.

No-one necessarily needs to understand how to set up the codebase to update the colour slightly. Some of the tools I mention later on allow you to update the Design Tokens in the browser.

Design Systems are already “bridging the gap” between design and development. With Design Tokens and the tooling available, we can create better team relationships by closing that gap instead.

Some of the benefits of creating and using Design Tokens are the same as using a pre-processor when it comes to authoring CSS. I feel the added bonuses of being able to empower other team members and document how you use them, as well as the fundamental reasoning in that they can be platform agnostic, are all great “selling points” to why you need to start using Design Tokens today.

Tools

There are several tools available to help you and your team to create the required files from your abstracted Design Tokens:

Command Line Tools

There are several tools available on the command line that can be used as part of, or separate to, your development process.

These tools allow you to define the Design Tokens in a .json or .yaml file format which can then be compiled into the formats you require.

Some have built in functions to turn the inputted values to something different when compiled – for example, turning hexadecimal code that is a Design Token into a RGB value in your .css file. These command line tools, written in JavaScript, allow you to create your own ways in which you want things transformed.

My current client has certain design decisions for typography in long form content (font size, weight, line height and margins) which need to be together to make sense. Being able to write JavaScript to compile these design decisions into an independent Sass map for each element allows us to develop with assurance that the long form content has the correct styling.

WYSIWYG Tools

WYSIWYG (What You See Is What You Get Tools) have been around for almost as long as we have been able to make websites. I can just about remember using Dreamweaver 2, before I knew what a <table> was.

When browsers started to employ vendor prefixes to new CSS for their browsers, a flurry of online WYSIWYG tools came with it built in. They’re still there, but the industry has moved on.

Design Tokens also have a few WYSIWYG tools available. From simpler online tools that allow you to generate the correct Sass variables needed for your design decisions to tools that store your decisions online and allow you to export them as npm packages.

These types of tools for creating Design Tokens can help empower the team as a whole, with some automatically creating documentation which can easily be shared with a url.

Retrofitting Tools

If you are starting from scratch on a new re-design or on a new project that requires a Design System and Tokens, the many of the tools mentioned above will help you along your way. But what if you’re in the middle of a project, or you have to maintain something and want to start to create the parts required for a Design System?

Luckily there are several tools and techniques to help you make a start.

One new tool that might be useful is Superposition. Currently in private beta with the public release set for Q1 of 2020 Superposition helps you “Extract design tokens from websites and use them in code and in your design tool.”

Entering your domain gives you a nice visual documentation of your sites styles as Design Tokens. These can then be exported as Sass Variables, CSS Custom Properties, JavaScript with the team working on exports to iOS and Android.

If you have an existing site, this could be a good first step before moving to one of the other tools mentioned above.

You could also make use of CSSStats or Project Wallace’s Analysis page that I mentioned earlier. This would give you an indication of what Design Tokens you would need to implement.

Component Based Design

So, we’ve created our Design Tokens by abstracting the design decisions of brand colours, typography, spacing and more. Is that as far as we can go?

Levels of Design Decisions

Once we have created our first set of Design Tokens for our project, we can take it that little bit deeper. With command line tools and some of the applications available, you can link these more global decisions to a more deeper level.

For example, you can take your chosen colours and make further design decisions on the themes of your project, such as what the primary, secondary, or tertiary colours are or what your general component and layout spacing will be.

With this, we can go one step further. We could also define some component specific design decisions that can then be compiled for the developer to use. Invest in time to check over the designs with a fine toothcomb and make sure you are using the correct Sass variable or CSS custom property for that component.

If you are going more than one or two levels of design decision making, you can compile each set of these Design Tokens to your Sass variables which can then be used as required. So you can provide: global, theme, component level Sass variables which can be used in the project. Or you could choose to only compile what you need for the components you are creating.

Variables, Maps, Custom Properties

Some of the tools available for creating and maintaining your Design Tokens allow you to compile to certain programming languages.

With my current client work, I am making use of Sass variables, Sass maps, and CSS custom properties. The Design Tokens are compiled into one or more of these options depending on how they will be used.

Colours are compiled as global Sass variables, inside of a couple of Sass maps and CSS custom properties. Our macro layout breakpoints are defined as a single Sass map.

If we know we are creating a component that has the ability to be themed, we can make use of CSS custom properties to reduce the amount of CSS we need to override, and also allow us to inline things that can be changed via a CMS as required. Which leaves us using Sass variables for parts of a component that won’t change. We are using Sass maps differently still. As mentioned, we generate a Sass map containing the design decisions for each element of text, and we can use long form text. This Sass map is then compiled into separate CSS declarations as needed using Sass mixins.

I find the beauty of being able to make use of the global, themed, and component level design decisions by compiling them into various formats (that essentially become CSS) and that gives us more power in authoring components.

Creating Consistent Utility Classes

As you have created your more global generic design decisions, you can create your own small set of utility classes.

Using a pre-processor like Sass you can define a set of mixins and functions that can take your Design Tokens that have been compiled down into variables and maps and generate separate classes for each design decision.

By making tokens available to all digital teams, we can enable them to create custom experiences that are aligned to current visual standards when a component does not (or will not) exist in the design system. Maya King

In creating utility classes with Design Tokens (using something like Sass) you have consistency with the overall Design System for times when you or a team need to create a one-off component for a project.

These exceptions tend to be something that won’t make it as part of the overall Design System, but it still needs that look and feel.

Having classes available that we can guarantee use the generic, global design decisions from the Design Tokens means these one-off components should be well on their way to have the overall look and feel of the project, and will get any updates with little to no additional overhead.

Wrapping Up

I think we are starting to see the potential of using Design Tokens as Design Systems become even more popular. I think that, from this overview, we can see how they can help us close the gap that still exists in places between the designers and developers on the team. They can help empower people who do not code to make changes that can be automatically updating live work.

I think you can start now. You may not have or need what you could term “a fully-fledged Design System” but this small step will help move towards one in the future and give you instant benefits of consistency and maintainability now. If you want more Design Tokens, as well as the links that are dotted around this article I also maintain a GitHub repo of Awesome Design Tokens which I try to keep updated with links to tools, articles, examples, videos, and anything else that’s related to Design Tokens.


About the author

Stuart Robson is a freelance front-end developer and design systems advocate who curates the design systems newsletter - news.design.systems

More articles by Stuart




one

Building a Dictaphone Using Media Recorder and getUserMedia

Chris Mills brushes up his shorthand and shows how the MediaStream Recording API in modern browsers can be used to capture audio directly from the user’s device. Inching ever closer to the capabilities of native software, it truly is an exciting time to be a web developer.


The MediaStream Recording API makes it easy to record audio and/or video streams. When used with MediaDevices.getUserMedia(), it provides an easy way to record media from the user’s input devices and instantly use the result in web apps. This article shows how to use these technologies to create a fun dictaphone app.

A sample application: Web Dictaphone

To demonstrate basic usage of the MediaRecorder API, we have built a web-based dictaphone. It allows you to record snippets of audio and then play them back. It even gives you a visualisation of your device’s sound input, using the Web Audio API. We’ll just concentrate on the recording and playback functionality in this article, for brevity’s sake.

You can see this demo running live, or grab the source code on GitHub. This has pretty good support on modern desktop browsers, but pretty patchy support on mobile browsers currently.

Basic app setup

To grab the media stream we want to capture, we use getUserMedia(). We then use the MediaRecorder API to record the stream, and output each recorded snippet into the source of a generated <audio> element so it can be played back.

We’ll first declare some variables for the record and stop buttons, and the <article> that will contain the generated audio players:

const record = document.querySelector('.record');
const stop = document.querySelector('.stop');
const soundClips = document.querySelector('.sound-clips');

Next, we set up the basic getUserMedia structure:

if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
   console.log('getUserMedia supported.');
   navigator.mediaDevices.getUserMedia (
      // constraints - only audio needed for this app
      {
         audio: true
      })

      // Success callback
      .then(function(stream) {

      })

      // Error callback
      .catch(function(err) {
         console.log('The following `getUserMedia` error occured: ' + err);
      }
   );
} else {
   console.log('getUserMedia not supported on your browser!');
}

The whole thing is wrapped in a test that checks whether getUserMedia is supported before running anything else. Next, we call getUserMedia() and inside it define:

  • The constraints: Only audio is to be captured for our dictaphone.
  • The success callback: This code is run once the getUserMedia call has been completed successfully.
  • The error/failure callback: The code is run if the getUserMedia call fails for whatever reason.

Note: All of the code below is found inside the getUserMedia success callback in the finished version.

Capturing the media stream

Once getUserMedia has created a media stream successfully, you create a new Media Recorder instance with the MediaRecorder() constructor and pass it the stream directly. This is your entry point into using the MediaRecorder API — the stream is now ready to be captured into a <Blob>, in the default encoding format of your browser.

const mediaRecorder = new MediaRecorder(stream);

There are a series of methods available in the MediaRecorder interface that allow you to control recording of the media stream; in Web Dictaphone we just make use of two, and listen to some events. First of all, MediaRecorder.start() is used to start recording the stream once the record button is pressed:

record.onclick = function() {
  mediaRecorder.start();
  console.log(mediaRecorder.state);
  console.log("recorder started");
  record.style.background = "red";
  record.style.color = "black";
}

When the MediaRecorder is recording, the MediaRecorder.state property will return a value of “recording”.

As recording progresses, we need to collect the audio data. We register an event handler to do this using mediaRecorder.ondataavailable:

let chunks = [];

mediaRecorder.ondataavailable = function(e) {
  chunks.push(e.data);
}

Last, we use the MediaRecorder.stop() method to stop the recording when the stop button is pressed, and finalize the Blob ready for use somewhere else in our application.

stop.onclick = function() {
  mediaRecorder.stop();
  console.log(mediaRecorder.state);
  console.log("recorder stopped");
  record.style.background = "";
  record.style.color = "";
}

Note that the recording may also stop naturally if the media stream ends (e.g. if you were grabbing a song track and the track ended, or the user stopped sharing their microphone).

Grabbing and using the blob

When recording has stopped, the state property returns a value of “inactive”, and a stop event is fired. We register an event handler for this using mediaRecorder.onstop, and construct our blob there from all the chunks we have received:

mediaRecorder.onstop = function(e) {
  console.log("recorder stopped");

  const clipName = prompt('Enter a name for your sound clip');

  const clipContainer = document.createElement('article');
  const clipLabel = document.createElement('p');
  const audio = document.createElement('audio');
  const deleteButton = document.createElement('button');

  clipContainer.classList.add('clip');
  audio.setAttribute('controls', '');
  deleteButton.innerHTML = "Delete";
  clipLabel.innerHTML = clipName;

  clipContainer.appendChild(audio);
  clipContainer.appendChild(clipLabel);
  clipContainer.appendChild(deleteButton);
  soundClips.appendChild(clipContainer);

  const blob = new Blob(chunks, { 'type' : 'audio/ogg; codecs=opus' });
  chunks = [];
  const audioURL = window.URL.createObjectURL(blob);
  audio.src = audioURL;

  deleteButton.onclick = function(e) {
    let evtTgt = e.target;
    evtTgt.parentNode.parentNode.removeChild(evtTgt.parentNode);
  }
}

Let’s go through the above code and look at what’s happening.

First, we display a prompt asking the user to name their clip.

Next, we create an HTML structure like the following, inserting it into our clip container, which is an <article> element.

<article class="clip">
  <audio controls></audio>
  <p>_your clip name_</p>
  <button>Delete</button>
</article>

After that, we create a combined Blob out of the recorded audio chunks, and create an object URL pointing to it, using window.URL.createObjectURL(blob). We then set the value of the <audio> element’s src attribute to the object URL, so that when the play button is pressed on the audio player, it will play the Blob.

Finally, we set an onclick handler on the delete button to be a function that deletes the whole clip HTML structure.

So that’s basically it — we have a rough and ready dictaphone. Have fun recording those Christmas jingles! As a reminder, you can find the source code, and see it running live, on the MDN GitHub.


This article is based on Using the MediaStream Recording API by Mozilla Contributors, and is licensed under CC-BY-SA 2.5.


About the author

Chris Mills manages the MDN web docs writers’ team at Mozilla, which involves spreadsheets, meetings, writing docs and demos about open web technologies, and occasional tech talks at conferences and universities. He used to work for Opera and W3C, and enjoys playing heavy metal drums and drinking good beer.

More articles by Chris




one

Five Interesting Ways to Use Array.reduce() (And One Boring Way)

Chris Ferdinandi turns the heat down low and lets the sauce reduce while we take a look at how to add spice to our source with a sprinkling of Array.reduce(). Just a little ingenuity with the humblest of functions.


Of all the modern array methods, the one I had the hardest time wrapping my head around was Array.reduce().

On the surface, it seems like a simple, boring method that doesn’t do much. But below its humble exterior, Array.reduce() is actually a powerful, flexible addition to your developer toolkit.

Today, we’re going to look at some cool things you can do with Array.reduce().

How Array.reduce() works

Most of the modern array methods return a new array. The Array.reduce() method is a bit more flexible. It can return anything. Its purpose is to take an array and condense its content into a single value.

That value can be a number, a string, or even an object or new array. That’s the part that’s always tripped me up – I didn’t realize just how flexible it is!

The syntax

The Array.reduce() accepts two arguments: a callback method to run against each item in the array, and a starting value.

The callback also accepts two arguments: the accumulator, which is the current combined value, and the current item in the loop. Whatever you return is used as the accumulator for the next item in the loop. On the very first loop, that starting value is used instead.

var myNewArray = [].reduce(function (accumulator, current) {
  return accumulator;
}, starting);

Let’s look at some examples to make this all tangible.

1. Adding numbers together

Let’s say you had an array of numbers that you wanted to add together. Using Array.forEach(), you might do something like this:

var total = 0;

[1, 2, 3].forEach(function (num) {
  total += num;
});

This is the cliche example for using Array.reduce(). I find the word accumulator confusing, so in this example, I’m calling it sum, because that’s what it is.

var total = [1, 2, 3].reduce(function (sum, current) {
  return sum + current;
}, 0);

Here, we pass in 0 as our starting value.

In the callback, we add the current value to the sum, which has our starting value of 0 on the first loop, then 1 (the starting value of 0 plus the item value of 1), then 3 (the sum value of 1 plus the item value of 2), and so on.

Here’s a demo.

2. Combining multiple array methods into Array.map() and Array.filter() into a single step

Imagine you had an array of wizards at Hogwarts.

var wizards = [
  {
    name: 'Harry Potter',
    house: 'Gryfindor'
  },
  {
    name: 'Cedric Diggory',
    house: 'Hufflepuff'
  },
  {
    name: 'Tonks',
    house: 'Hufflepuff'
  },
  {
    name: 'Ronald Weasley',
    house: 'Gryfindor'
  },
  {
    name: 'Hermione Granger',
    house: 'Gryfindor'
  }
];

You want to create a new array that contains just the names of wizards who are in Hufflepuff. One way you could do that is by using the Array.filter() method to get back just wizards whose house property is Hufflepuff. Then, you’d use the Array.map() method to create a new array containing just the name property for the remaining wizards.

// Get the names of the wizards in Hufflepuff
var hufflepuff = wizards.filter(function (wizard) {
  return wizard.house === 'Hufflepuff';
}).map(function (wizard) {
  return wizard.name;
});

With the Array.reduce() method, we can get the same array in a single pass, improving our performance. You pass in an empty array ([]) as the starting value. On each pass, you check to see if the wizard.house is Hufflepuff. If it is, you push it to the newArr (our accumulator in this example). If not, you do nothing.

Either way, you return the newArr to become the accumulator on the next pass.

// Get the names of the wizards in Hufflepuff
var hufflepuff = wizards.reduce(function (newArr, wizard) {
  if (wizard.house === 'Hufflepuff') {
    newArr.push(wizard.name);
  }
  return newArr;
}, []);

Here’s another demo.

3. Creating markup from an array

What if, instead of creating an array of names, we wanted to create an unordered list of wizards in Hufflepuff? Instead of passing an empty array into Array.reduce() as our starting value, we’ll pass in an empty string ('') and call it html.

If the wizard.house equals Hufflepuff, we’ll concatenate our html string with the wizard.name wrapped in an opening and closing list item (li). Then, we’ll return the html to become the accumulator on the next loop.

// Create a list of wizards in Hufflepuff
var hufflepuffList = wizards.reduce(function (html, wizard) {
  if (wizard.house === 'Hufflepuff') {
    html += '<li>' + wizard.name + '</li>';
  }
  return html;
}, '');

Add an opening and closing unordered list element before and after Array.reduce(), and you’re ready to inject your markup string into the DOM.

// Create a list of wizards in Hufflepuff
var hufflepuffList = '<ul>' + wizards.reduce(function (html, wizard) {
  if (wizard.house === 'Hufflepuff') {
    html += '<li>' + wizard.name + '</li>';
  }
  return html;
}, '') + '</ul>';

See it in action here.

4. Grouping similar items in an array together

The lodash library has a groupBy() method takes a collection of items as an array and groups them together into an object based on some criteria.

Let’s say you want an array of numbers.

If you wanted to group all of the items in numbers together based on their integer value, you would do this with lodash.

var numbers = [6.1, 4.2, 6.3];

// returns {'4': [4.2], '6': [6.1, 6.3]}
_.groupBy(numbers, Math.floor);

If you had an array of words, and you wanted to group the items in words by their length, you would do this.

var words = ['one', 'two', 'three'];

// returns {'3': ['one', 'two'], '5': ['three']}
_.groupBy(words, 'length');

Creating a groupBy() function with Array.reduce()

You can recreate that same functionality using the Array.reduce() method.

We’ll create a helper function, groupBy(), that accepts the array and criteria to sort by as arguments. Inside groupBy(), we’ll run Array.reduce() on our array, passing in an empty object ({}) as our starting point, and return the result.

var groupBy = function (arr, criteria) {
  return arr.reduce(function (obj, item) {
    // Some code will go here...
  }, {});
};

Inside the Array.reduce() callback function, we’ll check to see if the criteria is a function, or a property of the item. Then we’ll get its value from the current item.

If there’s no property in the obj with that value yet, we’ll create it and assign an empty array as its value. Finally, we’ll push the item to that key, and return the object as the accumulator for the next loop.

var groupBy = function (arr, criteria) {
  return arr.reduce(function (obj, item) {

    // Check if the criteria is a function to run on the item or a property of it
    var key = typeof criteria === 'function' ? criteria(item) : item[criteria];

    // If the key doesn't exist yet, create it
    if (!obj.hasOwnProperty(key)) {
      obj[key] = [];
    }

    // Push the value to the object
    obj[key].push(item);

    // Return the object to the next item in the loop
    return obj;

  }, {});
};

Here’s a demo of the completed helper function.

Special thanks to Tom Bremer for helping me make some improvements to this one. You can find this helper function and more like it on the Vanilla JS Toolkit.

5. Combining data from two sources into an array

Remember our array of wizards?

var wizards = [
  {
    name: 'Harry Potter',
    house: 'Gryfindor'
  },
  {
    name: 'Cedric Diggory',
    house: 'Hufflepuff'
  },
  {
    name: 'Tonks',
    house: 'Hufflepuff'
  },
  {
    name: 'Ronald Weasley',
    house: 'Gryfindor'
  },
  {
    name: 'Hermione Granger',
    house: 'Gryfindor'
  }
];

What if you had another data set, an object of house points each wizard has earned.

var points = {
  HarryPotter: 500,
  CedricDiggory: 750,
  RonaldWeasley: 100,
  HermioneGranger: 1270
};

Imagine you wanted to combine both sets of data into a single array, with the number of points added to each wizard’s data in the wizards array. How would you do it?

The Array.reduce() method is perfect for this!

var wizardsWithPoints = wizards.reduce(function (arr, wizard) {

  // Get the key for the points object by removing spaces from the wizard's name
  var key = wizard.name.replace(' ', '');

  // If the wizard has points, add them
  // Otherwise, set them to 0
  if (points[key]) {
    wizard.points = points[key];
  } else {
    wizard.points = 0;
  }

  // Push the wizard object to the new array
  arr.push(wizard);

  // Return the array
  return arr;

}, []);

Here’s a demo combining data from two sources into an array.

6. Combining data from two sources into an object

What if you instead wanted to combine the two data sources into an object, where each wizard’s name was the key, and their house and points were properties? Again, the Array.reduce() method is perfect for this.

var wizardsAsAnObject = wizards.reduce(function (obj, wizard) {

  // Get the key for the points object by removing spaces from the wizard's name
  var key = wizard.name.replace(' ', '');

  // If the wizard has points, add them
  // Otherwise, set them to 0
  if (points[key]) {
    wizard.points = points[key];
  } else {
    wizard.points = 0;
  }

  // Remove the name property
  delete wizard.name;

  // Add wizard data to the new object
  obj[key] = wizard;

  // Return the array
  return obj;

}, {});

Here’s a demo combining two data sets into an object.

Should you use Array.reduce() more?

The Array.reduce() method has gone from being something I thought was pointless to my favorite JavaScript method. So, should you use it? And when?

The Array.reduce() method has fantastic browser support. It works in all modern browsers, and IE9 and above. It’s been supported in mobile browsers for a long time, too. If you need to go back even further than that, you can add a polyfill to push support back to IE6.

The biggest complaint you can make about Array.reduce() is that it’s confusing for people who have never encountered it before. Combining Array.filter() with Array.map() is slower to run and involves extra steps, but it’s easier to read. It’s obvious from the names of the methods what they’re supposed to be doing.

That said, there are times where Array.reduce() makes things that would be complicated more simple rather than more complicated. The groupBy() helper function is a good example.

Ultimately, this is another tool to add to your toolkit. A tool that, if used right, can give you super powers.


About the author

Chris Ferdinandi helps people learn vanilla JavaScript. He believes there’s a simpler, more resilient way to make things for the web.

Chris is the author of the Vanilla JS Pocket Guide series, creator of the Vanilla JS Academy training program, and host of the Vanilla JS Podcast. His developer tips newsletter is read by thousands of developers each weekday.

He’s taught developers at organizations like Chobani and the Boston Globe, and his JavaScript plugins have been used used by Apple and Harvard Business School. Chris Coyier, the founder of CSS-Tricks and CodePen, has described his writing as “infinitely quote-worthy.”

Chris loves pirates, puppies, and Pixar movies, and lives near horse farms in rural Massachusetts. He runs Go Make Things with Bailey Puppy, a lab-mix from Tennessee.

More articles by Chris




one

Flexible Captioned Slanted Images

Eric Meyer gift wraps the most awkwardly shaped of boxes using nothing but CSS, HTML and a little curl of ribbon. No matter how well you plan and how much paper you have at your disposal, sometimes you just need to slant the gift to the side.


We have a lot of new layout tools at our disposal these days—flexbox is finally stable and interoperable, and Grid very much the same, with both technologies having well over 90% support coverage. In that light, we might think there’s no place for old tricks like negative margins, but I recently discovered otherwise.

Over at An Event Apart, we’ve been updating some of our landing pages, and our designer thought it would be interesting to have slanted images of speakers at the tops of pages. The end result looks like this.

The interesting part is the images. I wanted to set up a structure like the following, so that it will be easy to change speakers from time to time while preserving accessible content structures:

<div id="page-top">
  <ul class="monoliths">
    <li>
      <a href="https://aneventapart.com/speakers/rachel-andrew"> 
        <img src="/img/rachel-andrew.jpg" alt=""> 
        <div> 
          <strong>Rachel Andrew</strong> CSS Grid 
        </div> 
      </a>
    </li>
    <li>
      <a href="https://aneventapart.com/speakers/derek-featherstone"> 
        <img src="/img/derek-featherstone.jpg" alt=""> 
        <div> 
          <strong>Derek Featherstone</strong> Accessibility 
        </div> 
      </a>
    </li>
    <li>
      …
    </li>
    <li>
      …
    </li>
  </ul>
</div>

The id value for the div is straightforward enough, and I called the ul element monoliths because it reminded me of the memorial monoliths at the entrance to EPCOT in Florida. I’m also taking advantage of the now-ubiquitous ability to wrap multiple elements, including block elements, in a hyperlink. That way I can shove the image and text structures in there, and make the entire image and text below it one link.

Structure is easy, though. Can we make that layout fully responsive? I wondered. Yes we can. Here’s the target layout, stripped of the navbar and promo copy.

So let’s start from the beginning. The div gets some color and text styling, and the monoliths list is set to flex. The images are in a single line, after all, and I want them to be flexible for responsive reasons, so flexbox is 100% the right tool for this particular job.

#page-top { 
  background: #000; 
  color: #FFF; 
  line-height: 1; 
} 
#page-top .monoliths { 
  display: flex; 
  padding-bottom: 1em; 
  overflow: hidden; 
}

I also figured, let’s give the images a simple basis for sizing, and set up the hyperlink while we’re at it.

#page-top .monoliths li { 
  width: 25%; 
} 
#page-top .monoliths a { 
  color: inherit; 
  text-decoration: inherit; 
  display: block; 
  padding: 1px; 
}

So now the list items are 25% wide—I can say that because I know there will be four of them—and the links pick up the foreground color from their parent element. They’re also set to generate a block box.

At this point, I could concentrate on the images. They need to be as wide as their parent element, but no wider, and also match height. While I was at it, I figured I’d create a little bit of space above and below the captioning text, and make the strong elements containing speakers’ names generate a block box.

#page-top .monoliths img { 
  display: block; 
  height: 33rem; 
  width: 100%; 
} 
#page-top .monoliths div { 
  padding: 0.5em 0; 
} 
#page-top .monoliths strong { 
  display: block; 
  font-weight: 900; 
}

It looks like the speakers were all cast into the Phantom Zone or something, so that needs to be fixed. I can’t physically crop the images to be the “correct” size, because there is no correct size: this needs to work across all screen widths. So rather than try to swap carefully-sized images in and out at various breakpoints, or complicate the structure with a wrapper element set to suppress overflow of resized images, I turned to object-fit.

#page-top .monoliths img { 
  display: block; 
  height: 33rem; 
  width: 100%; 
  object-fit: cover; 
  object-position: 50% 20%; 
}

If you’ve never used object-fit, it’s a bit like background-size. You can use it to resize image content within the image’s element box without creating distortions. Here, I set the fit sizing to cover, which means all of the img element’s element box will be covered by image content. In this case, it’s like zooming in on the image content. I also set a zooming origin with object-position, figuring that 50% across and 20% down would be in the vicinity of a speaker’s face, given the way pictures of people are usually taken.

This is fairly presentable as-is—a little basic, perhaps, but it would be fine to layer the navbar and promo copy back over it with Grid or whatever, and call it a day. But it’s too square and boxy. We must go further!

To make that happen, I’m going to take out the third and fourth images temporarily, so we can see more clearly how the next part works. That will leave us with Rachel and Derek.

The idea here is to clip the images to be slanted, and then pull them close to each other so they have just a little space between them. The first part is managed with clip-path, but we don’t want to pull the images together unless their shapes are being clipped. So we set up a feature query.

@supports (clip-path: polygon(0 0)) or (-webkit-clip-path: polygon(0 0)) { 
  #page-top .monoliths li { 
    width: 37.5%; 
  } 
}

I decided to test for both the un-prefixed and WebKit-prefixed versions of clip-path because Safari still requires the prefix, and I couldn’t think of a good reason to penalize Safari’s users for the slowness of its standards advancement. Then I made the images wider, taking them from 25% to 37.5%, which makes them half again as wide.

Thanks to object fitting, the images don’t distort when I change their parent’s width; they just get wider and scale up the contents to fit. And now, it is time for clipping!

@supports (clip-path: polygon(0 0)) or (-webkit-clip-path: polygon(0 0)) { 
  #page-top .monoliths li { 
    width: 37.5%; 
    -webkit-clip-path: polygon(25% 0, 100% 0, 75% 100%, 0 100%); 
    clip-path: polygon(25% 0, 100% 0, 75% 100%, 0 100%); 
  } 
}

Each coordinate pair in the polygon() is like the position pairs in background-position or object-position: the horizontal distance first, followed by the vertical distance. So the first point in the polygon is 25% 0, which is 25% of the way across the element box, and no distance down, so right at the top edge. 100% 0 is the top right corner. 75% 100% is on the bottom edge, three-quarters of the way across the element, and 0 100% is the bottom left corner. That creates a polygon that’s a strip three-quarters the full width of the element box, and runs from bottom left to top right.

Now we just have to pull them together, and this is where old tricks come back into play: all we need is a negative right margin to bring them closer together.

#page-top .monoliths li { 
  width: 37.5%; 
  margin-right: -7.5%; 
  -webkit-clip-path: polygon(25% 0, 100% 0, 75% 100%, 0 100%); 
  clip-path: polygon(25% 0, 100% 0, 75% 100%, 0 100%); 
}

The separation between them is a little wider than we were originally aiming for, but let’s see what happens when we add the other two images back in and let flexbox do its resizing magic.

Notice how the slants actually change shape as the screen gets narrower or wider. This is because they’re still three-quarters the width of the image element’s box, but the width of that box is changing as the screen width changes. That means at narrow widths, the slant is much steeper, whereas at wide widths, the slant is more shallow. But since the clipping path’s coordinates were all set with percentage distances, they all stay parallel to each other while being completely responsive to changes in screen size. An absolute measure like pixels would have failed.

But how did the images get closer together just by adding in two more? Because the list items’ basic sizing added up to more than 100%, and they’re all set to flex-shrink: 1. No, you didn’t miss a line in the CSS: 1 is the default value for flex-shrink. Flex items will shrink by default, which after all is what we should expect from a flexible element. If you want to know how much they shrunk, and why, here’s what Firefox’s flex inspector reports.

When there were only two list items, there was space enough for both to be at their base size, with no shrinkage. Once we went to four list items, there wasn’t enough space, so they all shrank down. At that point, having a negative right margin of -7.5% was just right to pull them together to act as a unit.

So, now they’re all nicely nestled together, and fully responsive! The captions need a little work, though. Notice how they’re clipped off a bit on the left edge, and can be very much clipped off on the right side at narrower screen widths? This happens because the li elements are being clipped, and that clipping applies to all their contents, images and text alike. And we can’t use overflow to alter this: clipped is clipped, not overflowed.

Fortunately, all we really need to do is push the text over a small amount. Inside the feature query, I added:

#page-top .monoliths div { 
  padding-left: 2%;
  padding-right: 26%; 
}

This shifts the text just a bit rightward, enough to clear the clip path. On the right side, I padded the div boxes so their contents wouldn’t fall outside the clipped area and appear to slide under the next caption. We could also use margins here, but I didn’t for reasons I’ll make clear at the end.

At the last minute, I decided to make the text at least appear to follow the slants of the images. For that, I just needed to shift the first line over a bit, which I did with a bit more padding.

#page-top .monoliths strong { 
  padding-left: 1%; 
}

That’s all to the good, but you may have noticed the captions still overlap at really narrow screen widths. There are a lot of options here, from stacking the images atop one another to reverting to normal flow, but I decided to just hide the captions if things got too narrow. It reduces clutter without sacrificing too much in the way of content, and by leaving them still technically visible, they seem to remain accessible.

@media (max-width: 35rem) { 
  #page-top .monoliths div { 
    opacity: 0.01 
  } 
}

And that, as they say, is that! Fully responsive slanted images with text, in an accessible markup structure. I dig it.

I did fiddle around with the separations a bit, and found that a nice thin separator occurred around margin-right: -8%, whereas beefier ones could be found above -7%. And if you crank the negative margin value to something beyond -8%, you’ll make the images overlap entirely, no visible separation—which can be a useful effect in its own right.

I promised to say why I used padding for the caption text div rather than margins. Here’s why.

#page-top .monoliths div { 
  padding-left: 3%; 
  padding-right: 26%; 
  border-top: 2px solid transparent; 
  background: linear-gradient(100deg,hsl(292deg,50%,50%) 50%, transparent 85%); 
  background-clip: padding-box; 
}

It required a wee bit more padding on the left to look decent, and an alteration to the background clipping box in order to keep the purple from filling the transparent border area, but the end result is pretty nifty, if I do say so myself. Alternatively, we could drop the background gradient on the captions and put one in the background, with a result like this.

I have no doubt this technique could be extended, made more powerful, and generally improved upon. I really wished for subgrid support in Chrome, so that I could put everything on a grid without having to tear the markup structure apart, and there are doubtless even more interesting clipping paths and layout patterns to try out.

I hope these few ideas spark some much better ideas in you, and that you’ll share them with us!


About the author

Eric A. Meyer (@meyerweb) has been a burger flipper, a college webmaster, an early blogger, one of the original CSS Samurai, a member of the CSS Working Group, a consultant and trainer, and a Standards Evangelist for Netscape. Among other things, Eric co-wrote Design For Real Life with Sara Wachter-Boettcher for A Book Apart and CSS: The Definitive Guide with Estelle Weyl for O’Reilly, created the first official W3C test suite, assisted in the creation of microformats, and co-founded An Event Apart with Jeffrey Zeldman. Eric lives with his family in Cleveland, Ohio, which is a much nicer city than you’ve probably heard. He enjoys a good meal whenever he can and considers almost every form of music to be worthwhile.

More articles by Eric




one

Cigarette taxes and smoking among sexual minority adults [electronic resource] / Christopher Carpenter, Dario Sansone

Cambridge, Mass. : National Bureau of Economic Research, 2020




one

European socialism: a concise history with documents / William Smaldone

Dewey Library - HX236.5.S6293 2020




one

Prisoners of politics: breaking the cycle of mass incarceration / Rachel Elise Barkow

Online Resource




one

Learning one's native tongue: citizenship, contestation, and conflict in America / Tracy B. Strong

Dewey Library - JK1759.S87 2019




one

Citizenship: what everyone needs to know / Peter J. Spiro

Dewey Library - JF801.S694 2020




one

Money rock: a family's story of cocaine, race, and ambition in the new South / Pam Kelley

Dewey Library - HV5831.N8 K45 2018




one

Wartime sexual violence against men: masculinities and power in conflict zones / Élise Féron

Dewey Library - HV6558.F47 2018




one

Yolqui, a warrior summoned from the spirit world: testimonios on violence / Roberto Cintli Rodríguez ; foreword by Patrisia Gonzales

Dewey Library - HV8141.R63 2019