Weekly Web Harvest for 2020-03-15

Weekly Web Harvest for 2020-03-08

  • Tone.js
    Tone.js is a framework for creating interactive music in the browser. It provides advanced scheduling capabilities, synths and effects, and intuitive musical abstractions built on top of the Web Audio API.
  • How to Create an Online Classroom | Stanford Online High School
    Stanford Online High School has been successfully educating students online through an innovative virtual classroom model since 2006. For schools exploring online learning in case of temporary closures, this webpage provides free resources and considerations for effective remote teaching and learning.

Weekly Web Harvest for 2020-03-01

  • Mapping coronavirus, responsibly
    The map is using totals (absolute values) as its raw data. There are very very few golden rules in cartography but this is one of them: you cannot map totals using a choropleth thematic mapping technique.
  • Oregon Engineer Makes History With New Traffic Light Timing Formula – Institute for Justice
    Mats’s work was generally met with interest, but when he e-mailed the Oregon State Board of Examiners for Engineering and Land Surveying, things took an abrupt illegal U-turn. The Board told Mats it had no interest in hearing about his ideas. Fair enough. But the Board didn’t stop there. After a two-year investigation, it fined him $500 for publicly criticizing the timing of traffic lights without having a Professional Engineer license. The Board also forbid him from continuing to discuss his research.
  • 1. – Castaways – Te Ara Encyclopedia of New Zealand
    ‘The curse of the widow and fatherless light upon the man that breaks open this box, whilst he has a ship at his back.’

WordPress Multisite Copy Users from One Site to Another

I made a little plugin that let me copy users from one blog to another in WordPress multisite.1

I thought I’d have to use switch_to or something but I didn’t. It’d be easy to expand this to do more tricks for you and have more shortcode parameters but I don’t need them so it is what it is.

function copy_users_home($atts){
 $a = shortcode_atts( array(
    'id' => '',   //copy from this site
  ), $atts );

  $copy_site_id = $a['id'];
  $the_users = get_users( 'blog_id='.$copy_site_id );
  foreach ( $the_users as $user ) {
    echo  $user->ID . '<br>';// I just like to see stuff happen sometimes
    add_user_to_blog(1, $user->ID, 'subscriber');

  //add_user_to_blog($blog_id, $user_id, $role);


add_shortcode( 'copy', 'copy_users_home' );

1 But you already knew that from the title.

Weekly Web Harvest for 2020-02-23

  • Wildcard: Spreadsheet-Driven Customization of Web Applications
    In this paper, we present spreadsheet-driven customization, a technique that enables end users to customize software without doing any traditional programming. The idea is to augment an application’s UI with a spreadsheet that is synchronized with the application’s data. When the user manipulates the spreadsheet, the underlying data is modified and the changes are propagated to the UI, and vice versa.
  • Concordia University’s online vision hid grim reality – oregonlive.com
    In a draft version of Ries’ speech to trustees, he spelled out the “pronounced challenges” of Concordia’s 20-year deal with HotChalk, a California firm the school had paid hundreds of millions of dollars to jumpstart its online programs. The financial success of the deal depended on “overly aggressive enrollment targets,” Ries planned to say. Declining enrollment devastated the university’s finances.
  • Home of “Louie” & “Gyp” (LOC) | Bain News Service,, publishe… | Flickr
    thanks to @cogdog I got another beautiful flickr comments example
  • How a Web Design Company Crowdfunded Millions and Completely Disappeared – VICE
    “The problem space we tackled, we had the kind of hopeful naivety that would actually give us the balls to do it, but it’s much more difficult than any of us realized,” Toucchi told Motherboard. “I can imagine there’s a few people who are pissed off.”

    Toucchi went on to portray those his company has “pissed off” as being a vocal minority, and disputed that it has run off with everyone’s cash for the very simple reason that his company is bad at making money and good at spending it. It is not clear how much money The Grid raised in total; news articles suggest it raised at least $7 million from VC funders and another $5.2 million from users via crowdfunding and the sale of memberships.

    “It’s funny ’cause there’s this narrative from a small group of angry people on Twitter about ‘oh millions of dollars, blah blah blah,’” said Toucchi. “We made less than $6 million on a crowdfunding campaign and a lot of that was ad-driven. We had to spend to get there, we made a 20 percent profit on that, so it’s not like we’re awash in cash and pulling a Fyre Festival and partying like crazy.”

    It’s worth noting, though, that The Grid’s own marketing material hyped it, and also suggested that, during its early phases, the entire team took a trip to Hawaii to work on the product there.

  • Musicians Algorithmically Generate Every Possible Melody, Release Them to Public Domain – VICE
    Two programmer-musicians wrote every possible MIDI melody in existence to a hard drive, copyrighted the whole thing, and then released it all to the public in an attempt to stop musicians from getting sued.

    Programmer, musician, and copyright attorney Damien Riehl, along with fellow musician/programmer Noah Rubin, sought to stop copyright lawsuits that they believe stifle the creative freedom of artists.

  • Yes, You Can Pronounce GIF With A Soft-G Or Hard-G
    — Exactly. No need to die on random hills, relax and realize nothing makes sense and less stuff really matters.


    That’s right, let’s talk about another graphical file format. The JPEG, like the GIF, is a pretty popular file format in the graphic/photographic space. And I’m gonna go ahead and make a brave, bold guess that you pronounce it JAY-PEG, right? And here you, imagined verbal sparring partner, will snarkily note that the G in JAY-PEG is that hard, turgid, erect ‘g’ because the G in JPEG stands for Group.

    But what about the other letters?

    JPEG = Joint Photographic Experts Group.

    So, the P in JPEG is a soft Ph-sound, meaning, an F-sound.

  • Smithsonian Open Access | Smithsonian Institution
    download, share, and reuse millions of the Smithsonian’s images
  • Petrichor Geoviz Studio – a geo-dataviz collaboration
  • Depression researchers rethink popular mouse swim tests
    It is not clear whether mice stop swimming because they are despondent or because they have learnt that a lab technician will scoop them out of the tank when they stop moving. Factors such as water temperature also seem to affect the results.
  • Crossbow killer exposed by car telematics / Boing Boing
    so much data

Clean the WordPress Dashboard & Add Your Own Content

This little plugin is meant for WordPress multisite. When network activated, it closes all the default dashboard widgets and adds your own. It populates your widget with the title and excerpt of any posts on your root blog that are in the category ‘support.’ It’s meant to make it easy for you to add tutorial links across the site to a place that most users go frequently.

It’s comment up a bit below but there’s not much too it. I remember struggling with something like this a number of years ago. So there is some evidence that I am getting better over time.

Plugin Name: SOLA custom Dashboard
Plugin URI:  https://github.com/
Description: For adding directions to the dashboard
Version:     1.0
Author:      Tom Woodward
Author URI:  http://bionicteaching.com
License:     GPL2
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Domain Path: /languages
Text Domain: sola-custom

defined( 'ABSPATH' ) or die( 'No script kiddies please!' );

add_action('wp_dashboard_setup', 'sola_custom_dashboard_widgets');
function sola_custom_dashboard_widgets() {
  global $wp_meta_boxes;
  wp_add_dashboard_widget('custom_sola_widget', '<img style="width:100px; display:block; margin:0 auto;" src="'.plugin_dir_url( __FILE__ ).'/imgs/logo.png"><h1>Guidance</h1>', 'sola_custom_dashboard_posts');

function sola_custom_dashboard_posts() {
    echo '<p>Use the links below to learn more about Sola.</p>';
    //echo network_home_url();
    // WP_Query arguments
    switch_to_blog(1);//switch to the home blog but you could put another source URL here
    $args = array(
      'post_type'              => array( 'post' ),
      'post_status'            => array( 'public' ),
      'order'                  => 'ASC',
      'orderby'                => 'date',
      'category_name'          => 'support',// using the category support slug here

// The Query
$query = new WP_Query( $args );

// The Loop
if ( $query->have_posts() ) {
  while ( $query->have_posts() ) {
    $post = $query->the_post();

    // do something
    echo '<hr/><h2><a href="' . get_the_permalink() .'">'. get_the_title() . '</a></h2>';
    echo '<p>' . get_the_excerpt() . '</p>';

  } else {
    // no posts found

  // Restore original Post Data
  Disable Default Dashboard Widgets
  @ https://digwp.com/2014/02/disable-default-dashboard-widgets/
function disable_default_dashboard_widgets() {
  global $wp_meta_boxes;
  // wp..
  // bbpress
  // yoast seo
  // gravity forms
add_action('wp_dashboard_setup', 'disable_default_dashboard_widgets', 999);

//LOGGER -- like frogger but more useful

if ( ! function_exists('write_log')) {
   function write_log ( $log )  {
      if ( is_array( $log ) || is_object( $log ) ) {
         error_log( print_r( $log, true ) );
      } else {
         error_log( $log );


All the TAGS Twitter Avatars

I have someone who gathered a bunch of tweets for their research using Martin’s TAGS aggregator. She wanted to show all the avatars.

Once I published the spreadsheet, here’s all the javascript needed to make that happen. It’s lightly annotated for your reading pleasure and the functioning codepen example is included below.

var spreadsheetID = "11Dhxbt5YbrKJN9IUxop-kQ73oqI6oefF8KTDcLuAl04"; // Make sure it is published to the web and that this your ss ID

var dataURL =
  "https://spreadsheets.google.com/feeds/list/" +
  spreadsheetID +
  "/2/public/values?alt=json";//our data is on page two

//set some variables
var faces = "";

//get the data
fetch(dataURL).then(function(response) {
  var contentType = response.headers.get("content-type");
  if (contentType && contentType.indexOf("application/json") !== -1) {
    return response.json().then(function(json) {
      // now that you've got the data let's do something with it per item
      if (json.feed.entry) {
        var data = json.feed.entry;
          faces = faces +makeFace(element);//make the faces . . . so much humor
      document.getElementById('face-holder').innerHTML = faces;

function makeFace(element){
        return '<img src="' +element.gsx$profileimageurl.$t + '">'

See the Pen
Sheets avatar display – ALL
by Tom (@twwoodward)
on CodePen.

Monthly Reporting, A Gravity Forms to Google Forms Love Story

Well not really but I’ll explain it anyway.

Gravity to Google

There are a number of plugins that tie Gravity Forms to Google Sheets but most (all?) of them rely on the ability to create an application to get authentication tokens. Many institutional accounts turn off that capability. VCU has turned that off.

As a result, I ended up going the more manual route with this Google Script integration. Note the Martin Hawksey mention! I won’t re-write their documentation here but it does work and it’s relatively easy to set up.

Counting Unique Things

Now that we had our data showing up, I wrote some stuff to summarize it. Nothing too fancy, but I do find myself using =sort(UNIQUE(Sheet1!E2:E)) which gets the unique values in column E and sorts them and then doing a =COUNTIF(Sheet1!E:E,”=”&A2) to count how many times those unique values show up.

That all works pretty well for a summary look but there was also a desire for monthly data. That’s complicated by the data being added live on a continuous basis and the date field coming in with a full date/time stamp. I considered, and attempted, a variety of paths and ended up using =query. It works well and I thought some of the details were kind of neat. I also knew that I would forget them if I didn’t write it down.

Getting just this month’s data

=query(Sheet1!A1:H,”select * WHERE H>=date'”&to_text($A$2)&”‘ AND H<=date'"&to_text($B$2)&"'")

This is the query that gets me the current month’s data no matter what month it is. As cleaner version of the query looks like this select * WHERE H>=date’2020-2-1′ AND H<=date'2020-2-29'"). It’s going to get all (that’s the * symbol) rows where column H’s date is equal to or between Feb. 1 and Feb. 29.1 To get the first and last day of the month and year without having to change it, I used the following functions. Start of the month =EOMONTH(today(),-1)+1 and the end of the month is =eomonth(today(),0). Note that when I use them as variables in the upper example, I’m using to_text to keep them from being treated as Google Sheets date variable.

This saves the manager of one of our programs a chunk of time every month. It frees her up to do more important work and, probably more importantly, doing it let her know someone wanted to make her life easier. Digital workflow creation can be an act of caring.

1 You can chant some bizarre thing about 30-days-hath-something-or-another at me all you want. I will never know nor care what months have what number of days.

Justify Your Year – 1 Page Front and Back

We’re getting a new supervisor in the near future so we were asked to write up a success/challenges<footnote>See how I made them opportunities? ABC baby. ABC. Or ABC if you’d prefer. I’m good with either.</footnote> sheet to give them an idea of what’s working for our various groups and what’s giving us problems. I thought it might interest some people to see how I lined up some of our work.  I toned down examples and hyperlinks as I’m not sure whether it’ll end up printed out or not. I sacrificed a chunk of space to use headers under the belief that these things are often scanned. It’ll be interesting to see how it all goes.

Ram Pages

Success: A key tool in VCU’s SACSCOC accreditation goals for integrating digital fluency into the curriculum, Ram Pages has over 35,000 sites and nearly 33,000 users. This flexible platform supports student portfolios, courses, projects, and more. Use continues to expand with increases in innovative and powerful uses across disciplines.

Opportunities: Building confidence that the service will continue will increase usage rates. We’ve had confusion between our service and IT’s version of WordPress (now closed) have negatively impacted this perception.

Student & Faculty Portfolios

Success: We support 12+ VCU departments in their use of student portfolios for assessment, accreditation, and workforce engagement. Roughly comparable scale and capability using third-party services would cost over $300,000 for portfolios alone.

Opportunities: We could expand this and make it far more powerful with centralized-goals and enterprise considerations. Portfolios could also be tied into accreditation at the institutional level much more effectively.


Success: Part of our role is engaging with departments that have been hesitant to engage in online or blended learning in ways that open their eyes to new opportunities.  Selected examples include:

  • Virtual Geriatrics Case Study – online course for the MCV Center for Interprofessional Education and Collaborative Care
  • Photography 391 – blended Arts course which led to three online Arts courses
  • Online Digital Sociology Masters Program – program site and course sites

We support a significant number of courses and programs that align with major VCU initiatives including the Common Book, the REAL initiative, community engaged learning, large course redesign, and service learning. Selected examples include:

Opportunities: With particular metrics or enterprise-goal-alignment we could target particular departments or faculty more specifically. There is the potential to feature some of the more public faculty members in MOOCs to drive interest in VCU and particular programs.

Open Education Resources/Grants

Success: In partnership with the library, we have supported VCU Open and Affordable Course Content Faculty Awards for the last 3 years: 18 awards, 9 schools/colleges, 31 sections, 3,726 student seats, $620,000 savings (2017-2019).

We currently support two VIVA grants for course redesigns (Sociology, Social Work) and have written letters of support for three additional VIVA grants that are in process.

Select grant support examples:

  • The College of Emotional and Behavioral Health (COBE) – multiple grants
  • The Collaborative Studies on the Genetics of Alcoholism (COGA) – multiple grants
  • World Language Digital Curriculum – multiple grants
  • Environmental Studies RIVER Field Studies Network Incubator Grant

Select OER support examples:

  • Digital Histology – Replaced histology text for medical campus students
  • VCU Writes – Replaced an $80 textbook for all first-year students for over $350,000 a year in student savings.
  • VCU Arts Qatar – Part of a grant from the Queen of Qatar to create educational resources unique to Qatar and the Middle East.

Opportunities: With program alignment and support we could target high DFW courses for alignment of supplementary OER material. This could be tied into larger curricular and assessment patterns. We are supporting an increasing number of grants but need to determine our financial model.

Faculty & Program Support

Success: We help programs think through how technology can help them do what they need to do in the best way possible. This includes workflow, data dashboards, and project evaluation.

We provide complete support for faculty members engaging in digital learning endeavors. This support ranges from supporting a variety of platforms to providing workshops and individual consultations on a wide variety of topics.

Opportunities: There is a real need for digital workflow and data consultations for many major VCU initiatives.