us

Diffusive transport of nanoscale objects through cell membranes: a computational perspective

Soft Matter, 2020, 16,3869-3881
DOI: 10.1039/C9SM02338K, Perspective
Ziyang Xu, Lijuan Gao, Pengyu Chen, Li-Tang Yan
Clarifying the diffusion dynamics of nanoscale objects with cell membrane is critical for revealing fundamental physics in biological systems. This perspective highlights the advances in computational and theoretical aspects of this emerging field.
The content of this RSS Feed (c) The Royal Society of Chemistry




us

Template-based fabrication of spatially organized 3D bioactive constructs using magnetic low-concentration gelation methacrylate (GelMA) microfibers

Soft Matter, 2020, 16,3902-3913
DOI: 10.1039/C9SM01945F, Paper
Tao Sun, Yibing Yao, Qing Shi, Huaping Wang, Paolo Dario, Junzhong Sun, Qiang Huang, Toshio Fukuda
A new template-based method to apply low-concentration GelMA microfibers as building blocks for higher-order cellular assembly.
The content of this RSS Feed (c) The Royal Society of Chemistry




us

How clay particulates affect flow cessation and the coiling stability of yield stress-matched cementing suspensions

Soft Matter, 2020, 16,3929-3940
DOI: 10.1039/C9SM02414J, Paper
Iman Mehdipour, Hakan Atahan, Narayanan Neithalath, Mathieu Bauchy, Edward Garboczi, Gaurav Sant
Transition from closely-packed to fractally-architected structures with clay addition improves homogeneity and prevents local dewatering, thus enhancing coiling stability of layer-wise extruded cementing suspensions during 3D-printing.
The content of this RSS Feed (c) The Royal Society of Chemistry




us

Normal and shear forces between boundary sphingomyelin layers under aqueous conditions

Soft Matter, 2020, 16,3973-3980
DOI: 10.1039/D0SM00215A, Paper
Yifeng Cao, Nir Kampf, Weifeng Lin, Jacob Klein
Sphingomyelin boundary layers can maintain extremely low friction under high pressures both in water and at high salt concentration.
The content of this RSS Feed (c) The Royal Society of Chemistry




us

Inverse leidenfrost drop manipulation using menisci

Soft Matter, 2020, 16,4043-4048
DOI: 10.1039/C9SM02363A, Paper
Anaïs Gauthier, Guillaume Lajoinie, Jacco H. Snoeijer, Devaraj van der Meer
The motion of droplets levitated above a liquid surface is controlled using the menisci rising against partially immersed walls.
The content of this RSS Feed (c) The Royal Society of Chemistry




us

Bi-continuous orthorhombic soft matter phase made of polycatenar molecules

Soft Matter, 2020, 16,3882-3885
DOI: 10.1039/D0SM00331J, Communication
Joanna Matraszek, Damian Pociecha, Nataša Vaupotič, Mirosław Salamończyk, Martin Vogrin, Ewa Gorecka
A slight deformation of a double gyroid structure of a cubic Iād phase results in the formation of a phase with an orthorhombic Pcab symmetry. The phase seems to be an intermediate state towards a columnar phase made of helical pillars.
The content of this RSS Feed (c) The Royal Society of Chemistry




us

Detachment work of prolate spheroidal particles from fluid droplets: role of viscous dissipation

Soft Matter, 2020, 16,4049-4056
DOI: 10.1039/C9SM02385B, Paper
Sergey V. Lishchuk, Rammile Ettelaie
The minimum possible work done upon removal of an elongated solid particle from the surface of a liquid droplet can be less than that for a sphere.
The content of this RSS Feed (c) The Royal Society of Chemistry




us

Using microprojectiles to study the ballistic limit of polymer thin films

Soft Matter, 2020, 16,3886-3890
DOI: 10.1039/D0SM00295J, Communication
Shawn H. Chen, Amanda J. Souna, Christopher L. Soles, Stephan J. Stranick, Edwin P. Chan
In this work, a microballistic impact test called laser induced projectile impact test (LIPIT) was used to study the perforation behavior of polycarbonate thin films to demonstrate the importance of film thickness on the film's ballistic limit.
The content of this RSS Feed (c) The Royal Society of Chemistry




us

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




us

Liposomal adhesion via electrostatic interactions and osmotic deflation increase membrane tension and lipid diffusion coefficient

Soft Matter, 2020, Advance Article
DOI: 10.1039/D0SM00416B, Paper
Atsushi Oda, Chiho Watanabe, Natsumi Aoki, Miho Yanagisawa
Liposome–liposome adhesion by electrostatic interactions and osmotic contraction increase membrane tension and the lipid diffusion coefficient compared to isolated liposomes.
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




us

Color, Structure, and Rheology of a Diblock Bottlebrush Copolymer Solution

Soft Matter, 2020, Accepted Manuscript
DOI: 10.1039/D0SM00397B, Paper
Matthew A Wade, Dylan J Walsh, Ching-Wei Johnny Lee, Elizabeth G. Kelley, Katie Weigandt, Damien Guironnet, Simon A Rogers
A structure-property-process relation is established for a diblock bottlebrush copolymer solution, through a combination of rheo-neutron scattering, imaging, and rheological measurements. Polylactic acid-b-polystyrene diblock bottlebrush copolymers were dispersed in toluene...
The content of this RSS Feed (c) The Royal Society of Chemistry




us

Simultaneous determination of interfacial molarities of an alcohol, bromide ion, and water during an alcohol induced microstructural transition: The difference between medium and long chain alcohols.

Soft Matter, 2020, Accepted Manuscript
DOI: 10.1039/D0SM00665C, Paper
Kaixin Yao, Lijie Sun, Xiaoxuan Ding, Yuzhao Wang, Tianze Liu, Changyao Liu, Jiajing Tan, Li Zhao, Baocai Xu, Laurence S. Romsted
The transitions between surfactant aggregate structures are triggered by changes in chemical or physical stimulations, including addition of additives. Effects of added alcohols on aggregate morphologies correlate strongly with alcohol...
The content of this RSS Feed (c) The Royal Society of Chemistry




us

A Novel degradation mechanism of the elastic modulus of wet polymer substrates under nanoindentation

Soft Matter, 2020, Accepted Manuscript
DOI: 10.1039/D0SM00645A, Paper
Ruling Chen, Zhe Wang, Shaoxian Li, Hongwei Du
We demonstrated that the formation and solidification of the continuous confined water film played a very important role in changing the elastic modulus of the wet polymer substrate during nanoindentation...
The content of this RSS Feed (c) The Royal Society of Chemistry




us

Experimental observation of boundary-driven oscillations in a reaction–diffusion–advection system

Soft Matter, 2020, 16,4243-4255
DOI: 10.1039/C9SM02291K, Paper
Open Access
  This article is licensed under a Creative Commons Attribution 3.0 Unported Licence.
Torsten Eckstein, Estefania Vidal-Henriquez, Azam Gholami
Boundary-driven oscillations are observed experimentally in a reaction-diffusion-advection system, namely in the signaling population of Dictyostelium discoideum cells.
The content of this RSS Feed (c) The Royal Society of Chemistry




us

Lattice self-consistent field calculations of confined symmetric block copolymers of various chain architectures

Soft Matter, 2020, 16,4311-4323
DOI: 10.1039/D0SM00293C, Paper
Jingxue Zhang, Jiaping Wu, Run Jiang, Zheng Wang, Yuhua Yin, Baohui Li, Qiang Wang
The effects of chain architecture on the structural details and orientation of confined lamellae formed by symmetric AB-type block copolymer melts are studied.
The content of this RSS Feed (c) The Royal Society of Chemistry




us

A theory for the temperature effect on the chain length dependence of the diffusivity of oligomers

Soft Matter, 2020, 16,4283-4289
DOI: 10.1039/C9SM02505G, Paper
Chi Pui Jeremy Wong, Phillip Choi
Temperature effect on the size dependence of the diffusivity of oligomers is explained by free volume theory.
The content of this RSS Feed (c) The Royal Society of Chemistry




us

Effect of network homogeneity on mechanical, thermal and electrochemical properties of solid polymer electrolytes prepared by homogeneous 4-arm poly(ethylene glycols)

Soft Matter, 2020, 16,4290-4298
DOI: 10.1039/D0SM00289E, Paper
Monami Tosa, Kei Hashimoto, Hisashi Kokubo, Kazuhide Ueno, Masayoshi Watanabe
The effect of network inhomogeneity in solid polymer electrolytes on its electrolyte properties was investigated by employing a model polymer network composed of a homogeneous 4-arm poly(ethylene glycol) (tetra-PEG) network and Li salt.
The content of this RSS Feed (c) The Royal Society of Chemistry




us

Filamentous and step-like behavior of gelling coarse fibrin networks revealed by high-frequency microrheology

Soft Matter, 2020, 16,4234-4242
DOI: 10.1039/C9SM02228G, Paper
Pablo Domínguez-García, Giovanni Dietler, László Forró, Sylvia Jeney
By a micro-experimental methodology, we study the ongoing molecular process inside coarse fibrin networks by means of microrheology.
The content of this RSS Feed (c) The Royal Society of Chemistry




us

Rapid analysis of cell-generated forces within a multicellular aggregate using microsphere-based traction force microscopy

Soft Matter, 2020, 16,4192-4199
DOI: 10.1039/C9SM02377A, Paper
Buğra Kaytanlı, Aimal H. Khankhel, Noy Cohen, Megan T. Valentine
We measure cell-generated forces from the deformations of elastic microspheres embedded within multicellular aggregates. Using a computationally efficient analytical model, we directly obtain the full 3D mapping of surface stresses within minutes.
The content of this RSS Feed (c) The Royal Society of Chemistry




us

Rapid characterization of neutral polymer brush with a conventional zetameter and a variable pinch of salt

Soft Matter, 2020, 16,4274-4282
DOI: 10.1039/C9SM01850F, Paper
Mena Youssef, Alexandre Morin, Antoine Aubret, Stefano Sacanna, Jérémie Palacci
We take advantage of the nanoscopic nature of the Debye length and used it as a probe to characterize polymer brushes on colloidal particles.
The content of this RSS Feed (c) The Royal Society of Chemistry




us

Systematic approach for wettability prediction using molecular dynamics simulations

Soft Matter, 2020, 16,4299-4310
DOI: 10.1039/D0SM00197J, Paper
Open Access
  This article is licensed under a Creative Commons Attribution 3.0 Unported Licence.
Ahmed Jarray, Herman Wijshoff, Jurriaan A. Luiken, Wouter K. den Otter
An efficient approach for fast screening of liquids in terms of their wetting properties.
The content of this RSS Feed (c) The Royal Society of Chemistry




us

Ionic effects on synthetic polymers: from solutions to brushes and gels

Soft Matter, 2020, 16,4087-4104
DOI: 10.1039/D0SM00199F, Review Article
Haiyang Yuan, Guangming Liu
In this review, the polymer solutions, brushes, and gels are employed to exemplify the ionic effects on synthetic polymers.
The content of this RSS Feed (c) The Royal Society of Chemistry




us

Structural characterization of fibrous synthetic hydrogels using fluorescence microscopy

Soft Matter, 2020, 16,4210-4219
DOI: 10.1039/C9SM01828J, Paper
Open Access
Johannes Vandaele, Boris Louis, Kaizheng Liu, Rafael Camacho, Paul H. J. Kouwer, Susana Rocha
The structural features of the matrix surrounding the cells play a crucial role in regulating their behavior.
The content of this RSS Feed (c) The Royal Society of Chemistry




us

Sustainable sorbitol-derived compounds for gelation of the full range of ethanol–water mixtures

Soft Matter, 2020, Advance Article
DOI: 10.1039/D0SM00343C, Paper
Glenieliz C. Dizon, George Atkinson, Stephen P. Argent, Lea T. Santu, David B. Amabilino
A combination of gelators prepared from sustainable sources combine in a synergic way to widen the scope for the compounds to immobilise liquids, as shown by imaging, diffraction and rheology measurements.
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




us

Mechanical robustness of monolayer nanoparticle-covered liquid marbles

Soft Matter, 2020, Advance Article
DOI: 10.1039/D0SM00496K, Paper
Junchao Huang, Ziheng Wang, Haixiao Shi, Xiaoguang Li
A particle shell as thin as ∼20 nm cannot protect internal liquid from wetting external solid.
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




us

Investigation of Thermal Conductivity for Liquid Metal Composites Using Micromechanics-Based Mean-Field Homogenization Theory

Soft Matter, 2020, Accepted Manuscript
DOI: 10.1039/D0SM00279H, Paper
JiYoung Jung, Seunghee Jeong, Klas Hjort, Seunghwa Ryu
For the facile use of liquid metal composite (LMC) for soft, stretchable and thermal systems, it is crucial to understand and predict the thermal conductivity of the composite as a...
The content of this RSS Feed (c) The Royal Society of Chemistry




us

Wall entrapment of peritrichous bacteria: A mesoscale hydrodynamics simulation study

Soft Matter, 2020, Accepted Manuscript
DOI: 10.1039/D0SM00571A, Paper
S. Mahdiyeh Mousavi, Gerhard Gompper, Roland G. Winkler
Microswimmers such as E. Coli bacteria accumulate and exhibit an intriguing dynamics near walls, governed by hydrodynamic and steric interactions. Insight into the underlying mechanisms and predominant interactions demand a...
The content of this RSS Feed (c) The Royal Society of Chemistry




us

The Music Industry: Music in the Cloud


 
Since the first edition was published in 2009, Patrik Wikström's The Music Industry has become a go-to text for students and scholars. This thoroughly updated third edition provides an international overview of the music industry and its future prospects in the world of global entertainment.

The music industry has experienced two turbulent decades of immense change brought about in part by the digital revolution. How has the industry been transformed

Read More...




us

Sustainable Design Basics


 

An accessible, climate-diverse guide that transforms readers from sustainable design novices to whole-solution problem solvers.

Sustainable Design Basics is a student-friendly introduction to a holistic and integral view of sustainable design. Comprehensive in scope, this textbook presents basic technical information, sustainability strategies, and a practical, step-by-step approach for sustainable building projects. Clear and relatable chapters illustrate



Read More...




us

Museum Practice


 

MUSEUM PR ACTICE Edited by CONAL MCCARTHY

Museum Practice covers the professional work carried out in museums and art galleries of all types, including the core functions of management, collections, exhibitions, and programs. Some forms of museum practice are familiar to visitors, yet within these diverse and complex institutions many practices are hidden from view, such as creating marketing campaigns, curating and designing exhibitions, developing



Read More...




us

Museum Theory


 

MUSEUM THEORY EDITED BY ANDREA WITCOMB ANDKYLIE MESSAGE

Museum Theory offers critical perspectives drawn from a broad range of disciplinary and intellectual traditions. This volume describes and challenges previous ways of understanding museums and their relationship to society. Essays written by scholars from museology and other disciplines address theoretical reflexivity in the museum, exploring the contextual, theoretical, and pragmatic ways museums



Read More...




us

Museum Transformations: Decolonization and Democratization


 

MUSEUM TRANSFORMATIONS DECOLONIZATION AND DEMOCRATIZATION

Edited By ANNIE E. COOMBES ANDRUTH B. PHILLIPS

Museum Transformations: Decolonization and Democratization addresses contemporary approaches to decolonization, greater democratization, and revisionist narratives in museum exhibition and program development around the world. The text explores how museums of art, history, and ethnography responded to deconstructive critiques from activists and poststructuralist



Read More...




us

Museum Media


 

MUSEUM MEDIA Edited by Michelle Henning

Museum Media explores the contemporary uses of diverse media in museum contexts and discusses how technology is reinventing the museum. It considers how technological changes—from photography and television through to digital mobile media—have given rise to new habits, forms of attention and behaviors. It explores how research methods can be used to understand people's relationships with media technologies and



Read More...





us

Here's how business needs to change for a new decade


Running a good business carries a responsibility to think about the communities in which they operate.
More RSS Feed for Cisco: newsroom.cisco.com/rss-feeds ...





us

Cisco ushers in a bright new age of bridges


Our dependence on apps is reaching its technical limits. But don't worry: Cisco is solving the issue.
More RSS Feed for Cisco: newsroom.cisco.com/rss-feeds ...




us

Coronavirus | Chennai-based ayurvedic pharmacist dies after drinking concoction of his own preparation

Managing Director of the firm faints after tasting the chemical




us

Cine industry welcomes govt.’s decision allowing post-production work

The announcement by the Tamil Nadu government allowing post-production work on films and television projects to resume from May 11 was welcomed by the




us

Coronavirus | Tamil Nadu tally goes past 6,000 with 600 new cases

Chennai adds 399 patients to its total




us

[ASAP] Describing Meta-Atoms Using the Exact Higher-Order Polarizability Tensors

ACS Photonics
DOI: 10.1021/acsphotonics.9b01776




us

[ASAP] Goodbye Juan José Sáenz (1960–2020): A Bright Scientific Mind, an Unusually Prolific Friend, and a Family Man

ACS Photonics
DOI: 10.1021/acsphotonics.0c00526




us

Making a Better Custom Select Element

Julie Grundy kicks off this, our fifteenth year, by diving headlong into the snowy issue of customising form inputs. Nothing makes a more special gift at Christmas that something you’ve designed and customised yourself. But can it be done while staying accessible to every user?


In my work as an accessibility consultant, there are some frequent problems I find on people’s websites. One that’s come up a lot recently is that people are making custom select inputs for their forms. I can tell that people are trying to make them accessible, because they’ve added ARIA attributes or visually-hidden instructions for screen reader users. Sometimes they use a plugin which claims to be accessible. And this is great, I love that folks want to do the right thing! But so far I’ve never come across a custom select input which actually meets all of the WCAG AA criteria.

Often I recommend to people that they use the native HTML select element instead. Yes, they’re super ugly, but as Scott Jehl shows us in his article Styling a Select Like It’s 2019 they are a lot easier to style than they used to be. They come with a lot of accessibility for free – they’re recognised and announced clearly by all screen reader software, they work reliably and predictably with keyboards and touch, and they look good in high contrast themes.

But sometimes, I can’t recommend the select input as a replacement. We want a way for someone to choose an item from a list of options, but it’s more complicated than just that. We want autocomplete options. We want to put images in there, not just text. The optgroup element is ugly, hard to style, and not announced by screen readers. The focus styles are low contrast. I had high hopes for the datalist element, but although it works well with screen readers, it’s no good for people with low vision who zoom or use high contrast themes.

Figure 1: a datalist zoomed in by 300%

Select inputs are limited in a lot of ways. They’re frustrating to work with when you have something which looks almost like what you want, but is too restricted to be useful. We know we can do better, so we make our own.

Let’s work out how to do that while keeping all the accessibility features of the original.

Semantic HTML

We’ll start with a solid, semantic HTML base. A select input is essentially a text input which restricts the possible answers, so let’s make a standard input.

<label for="custom-select">User Type</label>
<input type="text" id="custom-select">

Then we need to show everyone who can see that there are options available, so let’s add an image with an arrow, like the native element.

<label for="custom-select">User Type</label>
<input type="text" id="custom-select">
<img src="arrow-down.svg" alt="">

For this input, we’re going to use ARIA attributes to represent the information in the icon, so we’ll give it an empty alt attribute so screen readers don’t announce its filename.

Finally, we want a list of options. An unordered list element is a sensible choice here. It also lets screen reader software understand that these bits of text are related to each other as part of a group.

<ul class="custom-select-options">
  <li>User</li>
  <li>Author</li>
  <li>Editor</li>
  <li>Manager</li>
  <li>Administrator</li>
</ul>

You can dynamically add or remove options from this list whenever you need to. And, unlike our <option> element inside a <select>, we can add whatever we like inside the list item. So if you need images to distinguish between lots of very similar-named objects, or to add supplementary details, you can go right ahead. I’m going to add some extra text to mine, to help explain the differences between the choices.

This is a good base to begin with. But it looks nothing like a select input! We want to make sure our sighted users get something they’re familiar with and know how to use already.

Styling with CSS

I’ll add some basic styles similar to what’s in Scott Jehl’s article above.

We also need to make sure that people who customise their colours in high contrast modes can still tell what they’re looking at. After checking it in the default Windows high contrast theme, I’ve decided to add a left-hand border to the focus and hover styles, to make sure it’s clear which item is about to be chosen.

This would be a good time to add any dark-mode styles if that’s your jam. People who get migraines from bright screens will thank you!

JavaScript for behaviour

Of course, our custom select doesn’t actually do anything yet. We have a few tasks for it: to toggle the options list open and closed when we click the input, to filter the options when people type in the input, and for selecting an option to add it to the input and close the list. I’m going to tackle toggling first because it’s the easiest.

Toggling

Sometimes folks use opacity or height to hide content on screen, but that’s like using Harry Potter’s invisibility cloak. No-one can see what’s under there, but Harry doesn’t cease to exist and you can still poke him with a wand. In our case, screen reader and keyboard users can still reach an invisible list.

Instead of making the content see-through or smaller, I’m going to use display: none to hide the list. display: none removes the content from the accessibility tree, so it can’t be accessed by any user, not just people who can see. I always have a pair of utility classes for hiding things, as follows:

.hidden-all {
  display: none;
}

.hidden-visually {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0,0,0,0);
    white-space: nowrap;
    -webkit-clip-path: inset(50%);
    clip-path: inset(50%);
    border: 0;
} 

So now I can just toggle the CSS class .hidden-all on my list whenever I like.

Browsing the options

Opening up our list works well for our mouse and touch-screen users. Our styles give a nice big tap target for touch, and mouse users can click wherever they like.

We need to make sure our keyboard users are taken care of though. Some of our sighted users will be relying on the keyboard if they have mobility or dexterity issues. Usually our screen reader users are in Browse mode, which lets them click the arrow keys to navigate through content. However, custom selects are usually inside form elements. which pushes screen reader software to Forms Mode. In Forms mode, the screen reader software can only reach focusable items when the user clicks the Tab key, unless we provide an alternative. Our list items are not focusable by default, so let’s work on that alternative.

To do this, I’m adding a tabindex of -1 to each list item. This way I can send focus to them with JavaScript, but they won’t be part of the normal keyboard focus path of the page.

csOptions.forEach(function(option) {
    option.setAttribute('tabindex, '-1')
}) 

Now I can move the focus using the Up and Down arrow keys, as well as with a mouse or tapping the screen. The activeElement property of the document is a way of finding where the keyboard focus is at the moment. I can use that to loop through the elements in the list and move the focus point forward or back, depending on which key is pressed.

function doKeyAction(whichKey) {
  const focusPoint = document.activeElement
  switch(whichKey) {
    case: 'ArrowDown':
      toggleList('Open')
      moveFocus(focusPoint, 'forward')
      break
    case: 'ArrowUp':
      toggleList('Open')
      moveFocus(focusPoint, 'back')
      break
  }
}

Selecting

The Enter key is traditional for activating an element, and we want to match the original select input.

We add another case to the keypress detector…

case 'Enter':
  makeChoice(focusPoint)
  toggleList('Shut')
  setState('closed')
  break 

… then make a function which grabs the currently focused item and puts it in our text input. Then we can close the list and move focus up to the input as well.

function makeChoice(whichOption) {
    const optionText = whichOption.documentQuerySelector('strong')
    csInput.value = optionText
}

Filtering

Standard select inputs have keyboard shortcuts – typing a letter will send focus to the first item in the option which begins with that letter. If you type the letter again, focus will move to the next option beginning with that letter.

This is useful, but there’s no clue to tell users how many options might be in this category, so they have to experiment to find out. We can make an improvement for our users by filtering to just the set of options which matches that letter or sequence of letters. Then sighted users can see exactly how many options they’ve got, and continue filtering by typing more if they like. (Our screen reader users can’t see the remaining options while they’re typing, but don’t worry – we’ll have a solution for them in the next section).

I’m going to use the .filter method to make a new array which only has the items which match the text value of the input. There are different ways you could do this part – my goal was to avoid having to use regex, but you should choose whatever method works best for your content.

function doFilter() {
  const terms = csInput.value
  const aFilteredOptions = aOptions.filter(option => {
    if (option.innerText.toUpperCase().startsWith(terms.toUpperCase())) {
    return true
    }
  })
  // hide all options
  csOptions.forEach(option => option.style.display = "none")
  // re-show the options which match our terms
  aFilteredOptions.forEach(function(option) {
    option.style.display = ""
  })
} 

Nice! This is now looking and behaving really well. We’ve got one more problem though – for a screen reader user, this is a jumble of information. What’s being reported to the browser’s accessibility API is that there’s an input followed by some clickable text. Are they related? Who knows! What happens if we start typing, or click one of the clicky text things? It’s a mystery when you can’t see what’s happening. But we can fix that.

ARIA

ARIA attributes don’t provide much in the way of additional features. Adding an aria-expanded='true' attribute doesn’t actually make anything expand. What ARIA does is provide information about what’s happening to the accessibility API, which can then pass it on to any assistive technology which asks for it.

The WCAG requirements tell us that when we’re making custom elements, we need to make sure that as a whole, the widget tells us its name, its role, and its current value. Both Chrome and Firefox reveal the accessibility tree in their dev tools, so you can check how any of your widgets will be reported.

We already have a name for our input – it comes from the label we associated to the text input right at the start. We don’t need to name every other part of the field, as that makes it seem like more than one input is present. We also don’t need to add a value, because when we select an item from the list, it’s added to the text input and therefore is exposed to the API.

Figure 2: How Firefox reports our custom select to assistive technology.

But our screen readers are going to announce this custom select widget as a text entry field, with some images and a list nearby.

The ARIA Authoring Practices site has a pattern for comboboxes with listboxes attached. It tells you all the ARIA you need to make screen reader software give a useful description of our custom widget.

I’m going to add all this ARIA via JavaScript, instead of putting it in the HTML. If my JavaScript doesn’t work for any reason, the input can still be a plain text field, and we don’t want screen readers to announce it as anything fancier than that.

csSelector.setAttribute('role', 'combobox') 
csSelector.setAttribute('aria-haspopup', 'listbox')
csSelector.setAttribute('aria-owns', '#list') 
csInput.setAttribute('aria-autocomplete', 'both')
csInput.setAttribute('aria-controls', 'list')

The next thing to do is let blind users know if the list is opened or closed. For that task I’m going to add an aria-expanded attribute to the group, and update it from false to true whenever the list changes state in our toggling function.

The final touch is to add a secret status message to the widget. We can use it to update the number of options available after we’ve filtered them by typing into the input. When there are a lot of options to choose from, this helps people who can’t see the list reducing know if they’re on the right track or not.

To do that we first have to give the status message a home in our HTML.

<div id='custom-select-status' class='hidden-visually' aria-live='polite'></div>

I’m using our visually-hidden style so that only screen readers will find it. I’m using aria-live so that it will be announced as often as it updates, not just when a screen reader user navigates past it. Live regions need to be present at page load, but we won’t have anything to say about the custom select then so we can leave it empty for now.

Next we add one line to our filtering function, to find the length of our current list.

updateStatus(aFilteredOptions.length)

Then we send that to a function which will update our live region.

function updateStatus(howMany) {
    console.log('updating status')
    csStatus.textContent = howMany + " options available."
}

Conclusion

Let’s review what we’ve done to make an awesome custom select input:

  • Used semantic HTML so that it’s easily interpreted by assistive technology while expanding the types of content we can include in it
  • Added CSS styles which are robust enough to survive different visual environments while also fitting into our branding needs
  • Used JavaScript to provide the basic functionality that the native element has
  • Added more JavaScript to get useful functionality that the native element lacks
  • Carefully added ARIA attributes to make sure that the purpose and results of using the element are available to assistive technology and are updated as the user interacts with it.

You can check out my custom select pattern on GitHub – I’ll be making additions as I test it on more assistive technology, and I welcome suggestions for improvements.

The ARIA pattern linked above has a variety of examples and customisations. I hope stepping through this example shows you why each of the requirements exists, and how you can make them fit your own needs.

I think the volume of custom select inputs out there shows the ways in which the native select input is insufficient for modern websites. You’ll be pleased to know that Greg Whitworth and Simon Pieters are working on improving several input types! You can let them know what features you’d like selects to have. But until that work pays off, let’s make our custom selects as accessible and robust as they can possibly be.


About the author

Julie Grundy is an accessibility expert who works for Intopia, a digital accessibility consultancy. She has over 15 years experience as a front-end web developer in the health and education sectors. She believes in the democratic web and aims to unlock digital worlds for as many people as possible. In her spare time, she knits very slowly and chases very quickly after her two whippets.

More articles by Julie




us

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




us

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




us

Usability and Security; Better Together

Divya Sasidharan calls into question the trade-offs often made between security and usability. Does a secure interface by necessity need to be hard to use? Or is it the choice we make based on years of habit? Snow has fallen, snow on snow.


Security is often synonymous with poor usability. We assume that in order for something to be secure, it needs to by default appear impenetrable to disincentivize potential bad actors. While this premise is true in many instances like in the security of a bank, it relies on a fundamental assumption: that there is no room for choice.

With the option to choose, a user almost inevitably picks a more usable system or adapts how they interact with it regardless of how insecure it may be. In the context of the web, passwords are a prime example of such behavior. Though passwords were implemented as a way to drastically reduce the risk of attack, they proved to be marginally effective. In the name of convenience, complex, more secure passwords were shirked in favor of easy to remember ones, and passwords were liberally reused across accounts. This example clearly illustrates that usability and security are not mutually exclusive. Rather, security depends on usability, and it is imperative to get user buy-in in order to properly secure our applications.

Security and Usability; a tale of broken trust

At its core, security is about fostering trust. In addition to protecting user accounts from malicious attacks, security protocols provide users with the peace of mind that their accounts and personal information is safe. Ironically, that peace of mind is incumbent on users using the security protocols in the first place, which further relies on them accepting that security is needed. With the increased frequency of cyber security threats and data breaches over the last couple of years, users have grown to be less trusting of security experts and their measures. Security experts have equally become less trusting of users, and see them as the “the weakest link in the chain”. This has led to more cumbersome security practices such as mandatory 2FA and constant re-login flows which bottlenecks users from accomplishing essential tasks. Because of this break down in trust, there is a natural inclination to shortcut security altogether.

Build a culture of trust not fear

Building trust among users requires empowering them to believe that their individual actions have a larger impact on the security of the overall organization. If a user understands that their behavior can put critical resources of an organization at risk, they will more likely behave with security in mind. For this to work, nuance is key. Deeming that every resource needs a similarly high number of checks and balances diminishes how users perceive security and adds unnecessary bottlenecks to user workflows.

In order to lay the foundation for good security, it’s worth noting that risk analysis is the bedrock of security design. Instead of blindly implementing standard security measures recommended by the experts, a better approach is to tailor security protocols to meet specific use cases and adapt as much as possible to user workflows. Here are some examples of how to do just that:

Risk based authentication

Risk based authentication is a powerful way to perform a holistic assessment of the threats facing an organization. Risks occur at the intersection of vulnerability and threat. A high risk account is vulnerable and faces the very real threat of a potential breach. Generally, risk based authentication is about calculating a risk score associated with accounts and determining the proper approach to securing it. It takes into account a combination of the likelihood that that risk will materialize and the impact on the organization should the risk come to pass. With this system, an organization can easily adapt access to resources depending on how critical they are to the business; for instance, internal documentation may not warrant 2FA, while accessing business and financial records may.

Dynamically adaptive auth

Similar to risk based auth, dynamically adaptive auth adjusts to the current situation. Security can be strengthened and slackened as warranted, depending on how risky the access point is. A user accessing an account from a trusted device in a known location may be deemed low risk and therefore not in need of extra security layers. Likewise, a user exhibiting predictive patterns of use should be granted quick and easy access to resources. The ability to adapt authentication based on the most recent security profile of a user significantly improves the experience by reducing unnecessary friction.

Conclusion

Historically, security failed to take the user experience into account, putting the onus of securing accounts solely on users. Considering the fate of password security, we can neither rely on users nor stringent security mechanisms to keep our accounts safe. Instead, we should aim for security measures that give users the freedom to bypass them as needed while still protecting our accounts from attack. The fate of secure systems lies in the understanding that security is a process that must constantly adapt to face the shifting landscape of user behavior and potential threats.


About the author

Divya is a web developer who is passionate about open source and the web. She is currently a developer experience engineer at Netlify, and believes that there is a better workflow for building and deploying sites that doesn’t require a server—ask her about the JAMstack. You will most likely find her in the sunniest spot in the room with a cup of tea in hand.

More articles by Divya




us

Cigarette taxes and teen marijuana use [electronic resource] / D. Mark Anderson, Kyutaro Matsuzawa, Joseph J. Sabia

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




us

Vicious games [electronic resource] : capitalism and gambling / Rebecca Cassidy.

London : Pluto Press, 2020.




us

VA HOUSE OF DELEGATES v. BETHUNE-HILL. Decided 06/17/2019




us

NORTH CAROLINA DEPT. OF REVENUE v. KAESTNER FAMILY TRUST. Decided 06/21/2019