Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion

Participants: Derya Akbaba * Ben Allen * Natalia-Rozalia Avlona * Kirill Azernyi * Erin Kathleen Bahl * Natasha Bajc * Lucas Bang * Tully Barnett * Ivette Bayo * Eamonn Bell * John Bell * kiki benzon * Liat Berdugo * Kathi Berens * David Berry * Jeffrey Binder * Philip Borenstein * Gregory Bringman * Sophia Brueckner * Iris Bull * Zara Burton * Evan Buswell * Ashleigh Cassemere-Stanfield * Brooke Cheng* Alm Chung * Jordan Clapper * Lia Coleman * Imani Cooper * David Cuartielles * Edward de Jong * Pierre Depaz * James Dobson * Quinn Dombrowski * Amanda Du Preez * Tristan Espinoza * Emily Esten * Meredith Finkelstein * Caitlin Fisher * Luke Fischbeck * Leonardo Flores * Laura Foster * Federica Frabetti * Jorge Franco * Dargan Frierson * Arianna Gass * Marshall Gillson * Jan Grant * Rosi Grillmair * Ben Grosser * E.L. (Eloisa) Guerrero * Yan Guo * Saksham Gupta * Juan Gutierrez * Gottfried Haider * Nabil Hassein * Chengbo He * Brian Heim * Alexis Herrera * Paul Hertz * shawné michaelain holloway * Stefka Hristova * Simon Hutchinson * Mai Ibrahim * Bryce Jackson * Matt James * Joey Jones * Masood Kamandy * Steve Klabnik * Goda Klumbyte * Rebecca Koeser * achim koh * Julia Kott * James Larkby-Lahet * Milton Laufer * Ryan Leach * Clarissa Lee * Zizi Li * Lilian Liang * Keara Lightning * Chris Lindgren * Xiao Liu * Paloma Lopez * Tina Lumbis * Ana Malagon * Allie Martin * Angelica Martinez * Alex McLean * Chandler McWilliams * Sedaghat Payam Mehdy * Chelsea Miya * Uttamasha Monjoree * Nick Montfort * Stephanie Morillo * Ronald Morrison * Anna Nacher * Maxwell Neely-Cohen * Gutierrez Nicholaus * David Nunez * Jooyoung Oh * Mace Ojala * Alexi Orchard * Steven Oscherwitz * Bomani Oseni McClendon * Kirsten Ostherr * Julia Polyck-O'Neill * Andrew Plotkin * Preeti Raghunath * Nupoor Ranade * Neha Ravella * Amit Ray * David Rieder * Omar Rizwan * Barry Rountree * Jamal Russell * Andy Rutkowski * samara sallam * Mark Sample * Zehra Sayed * Kalila Shapiro * Renee Shelby * Po-Jen Shih * Nick Silcox * Patricia Silva * Lyle Skains * Winnie Soon * Claire Stanford * Samara Hayley Steele * Morillo Stephanie * Brasanac Tea * Denise Thwaites * Yiyu Tian * Lesia Tkacz * Fereshteh Toosi * Alejandra Trejo Rodriguez * Álvaro Triana * Job van der Zwan * Frances Van Scoy * Dan Verständig * Roshan Vid * Yohanna Waliya * Sam Walkow * Kuan Wang * Laurie Waxman * Jacque Wernimont * Jessica Westbrook * Zach Whalen * Shelby Wilson * Avery J. Wiscomb * Grant Wythoff * Cy X * Hamed Yaghoobian * Katherine Ye * Jia Yu * Nikoleta Zampaki * Bret Zawilski * Jared Zeiders * Kevin Zhang * Jessica Zhou * Shuxuan Zhou

Guests: Kayla Adams * Sophia Beall * Daisy Bell * Hope Carpenter * Dimitrios Chavouzis * Esha Chekuri * Tucker Craig * Alec Fisher * Abigail Floyd * Thomas Forman * Emily Fuesler * Luke Greenwood * Jose Guaraco * Angelina Gurrola * Chandler Guzman * Max Li * Dede Louis * Caroline Macaulay * Natasha Mandi * Joseph Masters * Madeleine Page * Mahira Raihan * Emily Redler * Samuel Slattery * Lucy Smith * Tim Smith * Danielle Takahashi * Jarman Taylor * Alto Tutar * Savanna Vest * Ariana Wasret * Kristin Wong * Helen Yang * Katherine Yang * Renee Ye * Kris Yuan * Mei Zhang
Coordinated by Mark Marino (USC), Jeremy Douglass (UCSB), and Zach Mann (USC). Sponsored by the Humanities and Critical Code Studies Lab (USC), and the Digital Arts and Humanities Commons (UCSB).

Code Critique: JS Accessibility Hack

Programming language:

HTML + JavaScript

Code snippet (excerpt of code):

Examples below; you can find the entire script on my github.


I'm presenting a bit of simple HTML/JS. Essentially, it carries out the following sequence of steps:

  1. presents a clickable link for the user to generate an accessible <table> containing the data in an otherwise non-accessible media object embedded on the page. On click, the JavaScript...
  2. generates the URI of the JSON data which underlie the media;
  3. assigns the JSON data to a variable;
  4. uses a series of 'replace' operations to edit the content of the variable;
  5. displays the variable content as an accessible <table> element on the original webpage. (the code for this last bit is courtesy of Afshin Mehrabani via GitHub.)


The code was born out of creative tension. StoryMapJS is a project of Knight Lab at Northwestern University, which develops open-source tools for storytelling. Their tools provide engaging and interactive ways to understand data visually in narrative context. As with many media-centric tools, though, StoryMapsJS is optimized for sighted users; navigating a StoryMapJS object using NVDA is an exercise in confusion. I wanted to create a lightweight user-side bit of code that would programmatically offer the user access to the same data used in the visual map, but in a standard HTML table, providing structural context which screen readers can parse effectively for the listener.

As I developed and deployed the code, I began realizing that there were some curious ways the requirements of the code structure and syntax expressed values relevant to the presumed audience. One significant context was in step 4 above, i.e., the 'replace' operations for content editing. The raw JSON data, if presented in a table, would be hardly more intelligible, aurally, than the original media. Thus, as code author, I was immediately making choices of exclusion, based on the aural clarity of how the data would be presented. For example, here's one line:

var obj = obj.replace(/zoomify|location|head|storymap|media|text|attribution|call_to_action|true|false|slides|date|caption|credit|type|overview|line|osm|zoom|map_as_image|map_subdomains|map_|,|url|::|\/\/|[{\[\]}_\"]/gim , "");

As you'll probably intuit, most of these terms to be 'replaced' (with nothing) are headers. Rather than just leaving them alone, or formatting them to be more readable as needed (e.g converting "call_to_action" to "call to action"), I made the choice that these category signifiers were both extraneous - the data themselves were intelligible - and obscurantist - the value of any meaning they conveyed would be outweighed by their "cluttering up" the aural space of the information. The last several terms to be replaced represent the special and escape characters which, if left alone, would obscure meaning and/or produce oddities in formatting once the string is converted to an HTML <table> element.

A second example of how the actual writing of the code was shaped by authorial consideration of the audience: the line below formats the string as a colon-separated array. This is not the most typical choice; but I made it responding to my perception of the most likely ways the typical creators of StoryMapJS items would enter readable text. A StoryMapJS object is based on a Google Sheet, and includes fields for narrative descriptions, captions, etc. The script needed to take into account the fact that the string it's meant to format will include characters, including punctuation with special meaning in code, which have different meaning in context of human-read content, and so which must be in a sense "escaped." The second line, below, is an illustrative example of a consequence of this choice: adding a colon into a string for the sole purpose of signalling a table break.

var jsonarray = obj.split(":");

obj = obj.replace(/image url/gim , "New Slide:image url");

A final, and rather significant, consideration arose at the testing stage. The script relies upon the XMLHttpRequest object to get access to the original JSON data underlying the media object. Security protections against malicious code restrict the remote use of XMLHttpRequest. Interestingly, the relevant policy is implemented in slightly different ways by the different major browsers; and so, while the script works as intended in Firefox and Edge, Chrome and Safari block its execution on security grounds. It can be enabled if the admin of the target server enables a certain header (see below); but of course this is often not a realistic option, and essentially places the agency for "allowing" the implementation of an accessibility solution in the control of the server admin, rather than the end user.

Chrome console error message blocking data access: "Failed to load No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin '' is therefore not allowed access."

Discussion questions:

  1. How much of code writing rests on a model of constraint, either presumed or explicit? Particularly in conversations of user experience and design, how often does the end user perceive "all" the information contained in the source database, and how do those choices get made for the "generic" end user? for specific end users?

  2. How does such a constraint model influence a code author's perception of power imbalances in relation to the end user, particularly in context of the idealism of "open"?

  3. The nexus of accessibility, agency, and security seems a powerful convergence of considerations for a code writer. Given that the rhetoric of security tends to set safety and agency as mutually constraining elements, are there parameters of code work which tacitly weigh against accessible coding?


  • One thing your critique and the questions has me thinking about is this talk by Jacob Thornton (who co-created the extremely popular CSS framework Bootstrap about some of the problems associated with CSS as a concept.

    The thing that I think is especially relevant to your second question is the early discussion of Richard Stallman and the different early models for what was "open" on the web. To save anyone who's interested from watching a 42-minute video, the point is that in the early days of HTML, when it was first becoming apparent that people might want to change the font on their websites (gasp), there was a discussion at the W3C about who should have control: the content provider, the browser provider, or the user.

    As the talk kind of lays out, all three ideas conform to the idea of an open web. The W3C, with the release of the CSS spec, eventually sided with content providers, figuring that the ability to style one's content in any fashion embodied the open web. But Stallman was, and still is, an advocate for the user having final authority, with the idea that each of us could have our particular and particularly detailed stylesheet that styles the web how we want it. This is another definition of "open."

    So, all of that is to say, with regards to CORS and XMLHttpRequest, the onus of being "open" is on the content provider (again) and not on the user, so while we have an "open web" of accessible APIs (which is why StoryMapJS is so cool), it's only "open" at the behest of a particular segment of web users, as you draw out.

    All of this is to say that there's an interesting way to think about a constraint on application design emerging from human language itself, a particular definition of "open" (that was chosen and baked into the web's architecture) that out-competed other, different definitions of "open."

Sign In or Register to comment.