Jun 25

Quick fix for poor screen reader support of title attribute

As someone who remembers when ARIA was just an idea, I’ve spent a fair amount of time adding title="something descriptive" to many of the links, images, and possibly other elements on web pages I’ve authored and edited. But as developers began relying on authentic users of assistive technology to test their work, and those with differing abilities brought their knowledge and experience into the discussion and onto the Web, we learned we were wrong. Some of us knew that early on, or part of it anyway, and in the paralysis that may sometimes grip those unsure what to do, I stopped using title for anchor tags (i.e. links; <a>) altogether.

ARIA’s all grown up now

ARIA grew up and became the specification. The bulk of screen readers put their support there, and aria-label="making this meaningful" has supplanted the title attribute, freeing it to be what it is.

There’s enough explanation about this on the Internet already, so I’m going to keep this one very short. There are a lot of links in my pages that are in various states that reflected my limited understanding at the time, and maybe in yours too—live and learn! As I’m mostly working with WordPress sites these days, and WordPress has built-in jQuery, I’m sharing this snippet of code that takes text from existing “titles” and places it in an aria-label, or takes the linked text displayed to the visitor and makes it a bit more friendly and conversational than the typical screen reader default: “Link text. Link”

Most of my WordPress sites have a js folder in the theme I’ve chosen’s main folder at …wp-content/themes/theme-name/js, and in it a file called functions.js. Below is a standalone jQuery closure that should work in any site that has jQuery installed. In practice I took the indented part, between the first and last lines, and pasted it below the existing scripts in the existing closure. In Drupal you might put it in …/sites/all/themes/theme-name/js (and load it with a preprocess.inc). If you’re not using a CMS you probably need to wrap it in <script></script> tags, and make sure you place it below the prerequisite jQuery include.

For the blog you’re reading now, which didn’t already have a functions.js file in place, rather than stuff it into another I placed the following line below wp_head(); in header.php, found in the WordPress root folder.

wp_enqueue_script( 'my-custom-functions', get_template_directory_uri() .'/js/functions.js' );

This quick fix should probably be considered a temporary one, but it sure makes my pages sound better with ChromeVox, so I’ll carry on and wait for experts like Geoff Collis and others to tell me what to do next.

(function($) {
  // If there's a title attribute, make sure it's copied to aria-label (for screenreaders)
  // If there's no title, elaborate on the linked text.
      var
        links = $('a')
      ;
      links.each(function(i){
      	if (this.title){
      		$(this).attr({'aria-label':this.title});
      	} else {
      		this.title="Go to " + $(this).text() + ".";
      		$(this).attr({'aria-label':this.title});
      	}
      });


})(jQuery);


Nov 09

Who’s directing whom?

Photo. The cart is placed before the horse, who also looks confused.I’d like to tell you about the first time I taught children how to make webpages, which was in 1993, while a “teacher candidate” in the province of Ontario, Canada. There was an Education Resource Centre with a computer lab, an odd collection of Mac II, Mac Classics, and the last working Commodore 64s I saw for many years, and a few early Windows computers. I caught on quickly and soon landed 10-15 hours of gainful student employment each week. I was then, and remain today, an educator first and a technologist only so far as it supports the learners’ objectives.

Placed in a classroom within the (now defunct) Etobicoke Board, I needed the help of the school’s IT director to make sure each computer in the ambitious early 90s computer lab had access to the software they need during an in between my weekly lessons.

In their 2014 report, People for Education find that fewer than 1% of Ontario schools lack technology but it wasn’t the case in the early 90s.

Pause here to picture such a lab, and remember (as you can read on fact sheet 5 of the Census 2001 Highlights Immigration to Ontario Internet site) the Toronto census metropolitan area (CMA) had one of the highest proportions of foreign-born residents of all major urban centers in the world. Ontario’s public schools always reflect the faces of the immigration realities of the moment1.

My host school in 1993 had something else that was very new in those days—it had an IT Director. As it turned out, the relationship we developed revealed a conundrum that persists in organizations of many kinds to this day.

Naturally my lesson was being evaluated, and my course directors and adjunct professor expected the learning design to reflect my ideas and interpretations of such things as the anti-racist philosophy of education the Faculty espoused—and that I’d be the one directing the learning. So it was, in my very first adventures in electronically enhance learning design I quickly discovered that I wasn’t looking for an IT director — what I needed was a “facilitator,” and all the support and deference in executing my ideas the subtle distinction implies.

The third vision is a progressive one. The personal computer is used to amplify human potential. It is an intellectual laboratory and vehicle for self-expression that allows each child to not only learn what we’ve always taught, perhaps with greater efficacy, efficiency or comprehension. The computer makes it possible for students to learn and do in ways unimaginable just a few years ago. This vision of computing democratizes educational opportunity and supports what Papert and Turkle call epistemological pluralism. The learner is at the center of the educational experience and learns in their own way.
—Gary S. Stager, Ph.D.

Among his first questions to me was, why would I want to teach “these children” to write webpages? Maybe he mistook the early 90s fish-eye monitors for crystal balls, because he looked into the third graders’ future and told me they were mostly destined to be “end-users.”

As time passed, under further scrutiny he revealed that he considered his knowledge a territorial matter, requiring security, restricted access, and various other protections. So in my earliest attempt at widening the spread of code literacy I quickly learned that the control of information technology would become a powerful definer of access and privilege.

Quite clearly these attitudes are manifestations of deficit thinking. The relationship that unfolded and the conundrum were as follows: I could not accomplish my goals without him, yet I most emphatically could not let him direct.

More importantly, my grade 3 students could not afford to let him decide their computer science futures, or label them “end-users” with a derogatory connotation.

In the intervening years I’ve seen universities barter and leverage software, educational discounts and lab access in contexts ranging from educational to purely political, from departmental restructuring to instructional design. Technology is not neutral. Technology is political. It is a freedom issue, and an issue of democracy.

…leadership for equity needs to incorporate inclusive procedures such as discussion, transparency, and community involvement as well as an honest treatment of substantive issues that matter (e.g. racism and sexism) […] If we really believe in the ideal of leadership for equity in education, then we need to be aware of the nature of the deficit mentality, its pervasiveness and its dangers. (Portelli , Shields & Vibert, 2007; Portelli & Campbell-Stephens, 2009)

Educators do not need to be programmers to empower programmers. Just as technology support staff must facilitate and help implement the ideas of educational leaders, those leaders must discern and facilitate the educational aspirations of the learners in their charge.

§

    Notes:

  1. At 16%, China, including Hong Kong and Macau, was the leading country of birth among people who immigrated to Ontario in the 1990s. It was followed by India with 9%, the Philippines with 6%, Sri Lanka at 5.2% and Pakistan at 4.5%. At the time, European immigrants to Ontario were mostly from Poland, Yugoslavia and Russia. Jamaica was the leading country of birth among the Americas. Somalia was the leading birth country in Africa. (StatsCan)

References

Polgar, Jan Miller (2010), The Myth of Neutral Technology
in M.M.K. Oishi et al. (eds.), Design and Use of Assistive Technology: Social, 17 Technical, Ethical, and Economic Challenges [pdf]

Portelli, John P., Shields, Carolyn M. & Vibert, Ann B. (2007). Toward an Equitable Education: Poverty, Diversity, and Students at Risk. Toronto, ON: Centre for Leadership and Diversity, OISE, University of Toronto.

Portelli, John P. & Campbell-Stephens, R. (2009). Leading for Equity: The Investing in Diversity Approach. Toronto, ON: Edphil Books.

Stager, Gary (2013), Technology is not Neutral – educational computing requires a clear and consistent stance blog post

Aug 31

Case Method — classroom catalysts, from story to discourse and back again

Dis′ • course
1. spoken or written language, including literary works; the four traditionally classified modes of discourse are description, exposition, narration, and persuasion.
2. a form of discourse analysis, focusing on power relationships in society as expressed through language and practices.

One of the more interesting graduate courses I ever took, by way of both content and teaching style, was Current Policy Issues in Ontario Schooling. It was designed by the late R. Patrick Solomon but due to his tragic and untimely demise from cancer it was taught by his Brave New Teachers co-author John P. Portelli, at York University in the winter of 2010. Every class began using another of John’s books, What To Do? Case Studies for Educators 3d. Edition. It’s a collection of true stories from the classroom, either with an unknown outcome, or maybe a controversial but open ended one. Our job was to place ourselves in the classroom and reflect on what we might do in the same situation. Each “study” comes with 2 discussion questions at the end. We had no problem contributing additional ones of our own, and there are appendices containing further reading and resources for critical inquiry.

Case method

…curriculum reform focused on the effective negotiation of learning experiences between students and teachers and centred on the former’s concerns affords the opportunity for students to reengage in a creative, meaningful education where they are co-constructors of knowledge with their teachers in a genuine learning organisation.
O’Grady, O’ Reilly, Portelli, and Beal (2014)

Image of the book cover
Case method is the use of case studies as catalysts for conversation. The case poses a dilemma or problem, and the group must collaborate finding solutions. There’s ample evidence they work in many different areas, for many different age groups. With the right preparation and delivery they can “serve as springboards” that “engage students and faculty in collaborative problem posing, problem solving, and persuasion.” In other words, discourse.

“Case method teaching brings together three components: an appropriate case, students who are prepared to engage with the case material in a discussion, and an instructor who knows the case, has a plan for the discussion and is ready to deal with the unexpected.” (more). There are two well known approaches (Desiraju and Gopinath, 2001), the traditional Harvard Case Model (HCM) and an alternative proposed in the early 70s in response to criticism of HCM, the  McAleer Interactive Case Analysis (MICA) method (quoting McAleer, 1976; McAleer & Hale, 1992; Siciliano & McAleer, 1997). Desiraju and Gopinath conclude, “…students in the MICA method section reported better preparation and participation benefits as compared with students in the HCM method. In addition, students in the MICA class were better able to identify the main focus of the cases discussed, showing that they were able to better recall the content issues involved in the case discussion. Thus, on both counts of content and process, the MICA method appears superior” (2001, p. 406), influencing my current proposal, which follows.

I’ve written earlier about literal and extended meanings of discourse, and at how it can be at once a tool or model that describes, defines, and delineates narrative, and the narrative itself (see Foucault, or Derrida, for example). As we’ve heard, “…students develop skills, abilities, knowledge, and approaches, as well practice and discipline in becoming more reflective and creative. Most of the major theories of learning developed over the years all point toward effective learning being rooted in experience through the use of collaborative inquiry, discovery, reflection, and critique” (Booth, Bowie, Jordan & Rippin, 2000).

Children and Issues of Fairness

Our lives are “a series of unrelenting power struggles” (Buckmire, 2014, p. 0). Shaw, DeScioli, and Olson (2012) expose an “…inherent tension between favoritism and fairness” leading to “two related questions about children’s developing social behavior. First, how do children make allocation decisions when favoritism and fairness conflict? Second, how do children judge other people’s decisions about tradeoffs between favoritism and fairness” (p. 737)? I propose that cases relating to favoritism and fairness be used within a case method framing to instigate classroom discussion.

“There are few discussions of case teaching in the context of increasing student diversity or numbers, or of the use of the method on undergraduate programmes generally,” say Booth, Bowie, Jordan & Rippin (2000, p. 64), and probably fewer still that study its use with children and adolescents. This presents opportunities for field work and projects that blend other exciting developments, such as Maker Education (“…a unique combination of artistry, circuitry, and old-fashioned craftsmanship…”), to situate learners in collaborative inquiry and project-based settings that may develop and challenge their critical thinking in truly transformative ways. 

Where to obtain content

If your interest is fairness and you’re looking for stories to spark conversations there are undoubtedly many sources, and I hope you’ll add your own suggestions in the comments. In the meantime, I invite you to take a look at the Ontario Human Rights Commission’s Teaching Human Rights in Ontario: A Guide for Ontario Schools, and the case studies available within. As it’s a public document, provided by the Government of Ontario, you’re free to do with it as you please, as long as you credit the source and you don’t remove the Queen’s Printer’s copyright.

These are actual cases, that set the precedent, that made the laws, that inform the Ontario Human Rights Code. The Commission says “The case studies in the Students’ handouts section can be approached in two ways.” Really? …only two? It’s clear Ontario’s students can imagine at least 3 general categories of 21st Century multi-modal literacy students themselves identify as meaningful: games, apps, and video.

All of these can take many forms, and if we educators lack the imagination or experience to think in so many forms, students certainly don’t. Take a look at what students put together with Mozilla Webmaker and the Canada Privacy Commission last year.

I’m volunteering to help

In the coming weeks I’ll provide tentative lesson plans for a few of my own ideas. I’ll work with any teacher anywhere (via the comments section) to customize the plan(s) for your own learning situation. They include…

  1. #HourOfCode (or 2 or 3) building a web app, with teacher and class versions so you can learn together
  2. More web app stuff using online resources from THRiO (Human Rights Temperature and Glossary)
  3. Digital Storytelling using green screen and 3d techniques (this video goes with OHRC Case Study #9, “Tawney” the BC Firefighter… do you have a student that might be called “too short?” Do you think the person is invalid, or the standard?).
  4. More digital storytelling and games using such digital literacy supporting as Twine, Vine and ;

I’m ramping up to share these ideas and techniques in detail. Please watch this space!

§

Reference, further reading

Boehrer, John and Marty Linsky, “Teaching with Cases: Learning to Question,” in M.D. Svinicki (ed.), The Changing Face of College Teaching, New Directions for Teaching and Learning, no. 42 (San Francisco, CA: Jossey-Bass, 1990), p. 42.

Booth, Charles; Bowie, Stuart; Jordan, Judith; Rippin, Ann (2000), The Use of the Case Method in Large and Diverse Undergraduate Business Programmes: Problems and Issues, The International Journal of Management Education

Buckmire, Mark J. (2014), Human Fairness: An Evolutionary Approach,

Crone, E. A. (2013), Considerations of Fairness in the Adolescent Brain. Child Development Perspectives, 7: 97–103.

Desiraju, Ramarao and Gopinath, C. (2001), Encouraging Participation in Case Discussions: A Comparison of the Mica and the Harvard Case Methods, Journal of Management Education 2001 25: 394, pp. 394-408.

Foucault, M. (1990) The History of Sexuality Vol. 1: An Introduction New York: Vintage.

Minks, Larry C. (1998), The Comprehensive Case Study Method: Insights Into The Course Journey,

McAleer, G. (1976). Listening as away to teach marketing policy. In H. Nash & D. Robin, (Eds. ), Proceedings: Southern marketing association 1976 conference (pp. 106-108). Atlanta, GA: Southern Marketing Association and Mississippi State University.

McAleer, G. M. , & Hale, J. R. (1992, October). Want to increase student participation in marketing case courses? Try the MICA method. Paper presented at the American Marketing Association Annual Meeting, Chicago, IL.

O’Grady, Emmanuel; O’ Reilly, John; Portelli, John P.; Beal, Candy (2014) Putting the Learner into the Curriculum, not the Curriculum into the Learner: A Case for Negotiated Integrated Curriculum, International Journal of Pedagogical Innovations, 2, No. 2 (July 2014) [Read online]

Shaw, Alex; DeScioli, Peter; and Olson, Kristina R. (2012), Fairness versus favoritism in children, Evolution and Human Behavior 33 (2012) 736–745.

Siciliano, J. , & McAleer, G. M. (1997). Increasing student participation in case discussions: Using the MICA method in strategic management courses. Journal of Management Education, 21(2), 209-220.

Recommended

How the Maker Movement Is Moving Into Classrooms – Vicki Davis, July 18, 2014 [Blog post]

Government of Ontario, Ministry of Education (2007-2015), Capacity Building Series

Government of Ontario, Ontario Human Rights Commission (2013), Teaching Human Rights in Ontario: A Guide for Ontario Schools also available as PDF

Student Voice in Ontario Schools SpeakUp Video

  1. Full disclosure: I work there. Neither this idea, nor any activity that may result from it, has anything to do with my position or duties, and this is not sanctioned or promoted by the organization, and I do not stand to benefit financially as a result of outside interest. I will benefit in self satisfaction, and perhaps in other ways no one can predict.
Feb 26

The baby in the bath water?

I got my start as a “webmaster” in the Crocker-ian sense. I wrote jSyncWithMedia as a project for my master’s degree in education. With it you can synchronize a slide and caption show to your speech or video using the native <audio> and <video> tags. It contains some naïve and outright bad code, but it’s based on a thesis, and I got it to work. I noted that storytelling is in many ways central to teaching, and narration is at the center of storytelling. Teachers and storytellers highlight certain phrases, create mental images and metaphors, to emphasize the specifics of what they’re telling. I knew html css sql and was trying out JavaScript using only resources available on the Internet. I tried to synchronize events to an audio and or visual timeline. If nothing else, I proved that a tenacious person with strong but basic HTML/CSS/JavaScript background and access to a search engine could, in 2010, build a working jQuery plugin.

It’s nothing like Mozilla’s Popcorn.js in scalability, but If there’s one thing about it that’s still interesting it might be the CSS animation based on WAI-ARIA attributes aria-expanded aria-hidden and their values, which I manipulated with jQuery.

Selectors $(‘[aria-expanded=”false”]’) $(‘[aria-hidden=”true”]’)

/* CSS file
 * A fade in and out that can be controlled
 * by changing aria- attribute values
 * programmatically.
 */

[aria-expanded="false"] {
    display:none; 
} 

[aria-hidden="true"] {
    visibility:invisible; 
} 

[aria-expanded="false"] {
	opacity: 0;
	-webkit-transition: opacity 0.5s linear;
	-moz-transition: opacity 0.5s linear;
	-o-transition: opacity 0.5s linear;
	-ms-transition: opacity 0.5s linear;
	transition: opacity 0.5s linear;
}

[aria-expanded="true"] {
	opacity: 1;
	-webkit-transition: opacity 0.5s linear;
	-moz-transition: opacity 0.5s linear;
	-o-transition: opacity 0.5s linear;
	-ms-transition: opacity 0.5s linear;
	transition: opacity 0.5s linear;
}

In theory this can work with other CSS animations. The big challenge for practicality is the timeline interface. I created one that works, using Audacity .aup files, which are XML documents, and the timings extracted from its label track.

<!-- SNIPPET FROM .aup FILE CONTAINING LABELS -->
    <labeltrack name="Label Track" numlabels="11" height="253" minimized="0">
        <label t="1.69726544" t1="11.83946136" title="li:woodshed"/>
        <label t="11.92225480" t1="27.32183391" title="li:busting"/>
        <label t="20.79346939" t1="62.46764754" title="li:turntable"/>
        <label t="34.31787926" t1="43.54934739" title="li:changes the pitch"/>
        <label t="50.00723540" t1="62.46764754" title="a:audacity.soundforge.net"/>
        <label t="53.85713018" t1="62.50904425" title="img:audacity_logo.png"/>
        <label t="62.46764754" t1="62.55044097" title="off:ALL"/>
        <label t="76.70811855" t1="91.03138299" title="img:copy-paste.png"/>
        <label t="91.11417643" t1="109.90828642" title="li:copy menu item"/>
        <label t="110.15666673" t1="114.79309915" title="li:easily practice"/>
        <label t="114.79309915" t1="123.81758369"
               title="li:Choose File-&gt;Save Project As..."/>
    </labeltrack>

§

https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Using_HTML5_audio_and_video

http://www.w3.org/2010/05/video/mediaevents.html

Jan 28

WCAG 2.0 in a nutshell, and a problem that illustrates its use

The “Web Content Accessibility Guidelines” (WCAG) 2.0 are the accessibility standard most new websites in Ontario and many other places around the world have to meet nowadays. Here’s a front end accessibility lesson that can show us a few things about applying WCAG 2.0, at a couple different levels. I’ll demonstrate a JavaScript solution to a specific problem, I’ll sort of ‘reverse engineer’ from that problem to locate where it sits within the framework of the four principles—that content must be Perceivable, Operable, Understandable, and Robust—and I’ll show how I use the WCAG 2.0 site to understand any accessibility issue—whom it affects, how, how to fix it, and how to know that I’ve done so successfully. As a bonus, I’ll pop over to the jQuery API site and look at the selector reference. I think the WordPress “hack” I show for adding this to your blog is out of date—the “Admired” theme I’m using now has a way better built-in method—so you’ll need to adapt it. No clue at all what I’m talking about? I didn’t learn this in school either… sometimes you just have to dig in and figure it out.

Understanding WCAG 2.0

Understanding… WCAG 2.0 means understanding that the work began as a collaborative effort to define the 4 Principles of an accessible internet site, which after a decade of ongoing consultation with an ever-growing international community are now guidelines—not exactly the same as “rules”—and a list of criteria—things front-end developers must, should, and can do—to succeed at removing the barriers some groups will otherwise face when accessing and using the internet. [It…] is not prescriptive, but offers options…

Understanding how to use the huge body of work we call WCAG 2.0 means understanding that the work began as a collaborative effort to define the 4 Principles of an accessible internet site, which after a decade of ongoing consultation with an ever-growing international community are now guidelines—not exactly the same as “rules”—and a list of criteria—things front-end developers must, should, and can do—to succeed at removing the barriers some groups will otherwise face when accessing and using the internet. Because the list is not prescriptive, but offers options, it seems of the utmost importance to first know your audience, and next, to understand as the Web Consortium’s Accessibility Group sets out in WCAG 2.0, the best way your organization can guarantee your audience access to your content.

David Berman said in his workshop, and I think it makes perfect sense, that the differences between accessibility and usability are, for all intents and purposes, purely semantic. Providing access for people with varying abilities, simply makes things more usable for everyone.

The specific problems I’ll address are, ‘opening too many new windows’ and ‘changing things without telling me.’ In order to keep site visitors from leaving a site, Web developers often open links in new windows, usually by using the target attribute, and by assigning it a value of "_blank":


<a href="http://SOME_LINK" target="_blank">Linked text</a>

WCAG 2.0 in a nutshell

As I said earlier, there are 4 Principles. Websites must be 1) perceivable, 2) operable, 3) understandable, and 4) robust. If you like acronyms: POUR some accessibility sugar on me (use <abbr title="Spelled Out">SO</abbr> to create tool tips screen readers can use)! Each principal has “guidelines, “…which are further categorized into levels. Level A must be done, or some group will not be able to access the content. Level AA should be done, or some group will have difficulty accessing the content. Level AAA can be done to improve usability or enhance accessibility further. Too many windows causes problems in understanding, which is principle #3. This can be especially challenging for those with disabilities related to vision or cognition.

The Understanding WCAG 2.0 site provides information by which to understand each guideline, and provides “success criteria” so you know when you’ve achieved each level, and examples of techniques you can use to get there. “Success criteria” are written as statements that are recognizably/measurably false until one meets the guidelines. The problems that prevent the statement from being true are your challenges to overcome.

Know your organization, your audience, and your content. Use valid HTML wherever you write code. If most of your site visitors are knowledgeable about technology it may not be necessary to open new windows, as they will use their familiar browsing setup to choose when and how to open them, and if your code is valid it will work as they expect. There’s no WCAG 2.0 guideline that says not to open new windows, but we must think more carefully about how doing so may create barriers to ease of access and use.

Guideline 3.2 says: make webpages appear and operate in predictable ways. Opening pop-up windows could be problematic for screen readers. If they don’t know the window is opening they can get lost. This guideline also covers many situations, such as focus or context changes, and page reloads—anything a user can potentially do that changes the content. WCAG 2.0 by no means prohibit pop-up windows, but we must prevent them from becoming barriers or annoyances. We should minimize the number of new windows, stop using target=”_blank”, and let users request a new window or otherwise inform them it’s about to open. If we look further in the Table of Contents we find a discussion about pop-ups under 3.2.5, with suggestions…

Situation C: If the Web page uses pop-up windows:

Including pop-up windows using one of the following techniques:

H83: Using the target attribute to open a new window on user request and indicating this in link text (HTML)

SCR24: Using progressive enhancement to open new windows on user request (Scripting)

3.2.5 also has an “Advisory” about additional techniques.

Additional Techniques (Advisory) for 3.2.5

Although not required for conformance, the following additional techniques should be considered in order to make content more accessible. Not all techniques can be used or would be effective in all situations.

Opening new windows by providing normal hyperlinks without the target attribute (future link), because many user agents allow users to open links in another window or tab.

G200: Opening new windows and tabs from a link only when necessary

Understanding the problem, we now make a plan

Objective

I don’t want folk leaving my pages abruptly or permanently, and I don’t think all my visitors know everything about their browser’s and other equipment’s context-sensitive help menus, access key options, etc., so I’ve elected to automatically open some content in new windows. I’ve decided I can sensibly limit the number of windows that open from any of my blog pages to a maximum of 2 by applying a simple self-enforced rule. I’ll still use the target attribute, but instead to create one “named window” for links to other areas of my site (rcfWin), and one “named window” for links to external sites (extWin). I’ll open all external links in their own window, which means I can easily design something that will apply retroactively to all such links. Go to the API selectors page and scroll down to Attribute Starts With Selector [name^="value"] to get the syntax. I want to select all the links (a) with an href attribute whose value begins with http:// (or https://). We can get away with [href^="http"].

I have to weigh all the advice to find the best way to handle my internal links. If you’ve linked text in the middle of one article to another article there’s a distinct chance the user will click it and start reading. If you don’t want that, the most sensible choice is usually to lose the link—link only at the end of the information and only to the next logical jump in a sequence. But if you feel you must have the option, to keep it as an available option you can create a CSS class name and tell jQuery to look for that. You’ll still have to add it manually to any links, past present or future, you want to behave that way. Or you could do it the other way around and use your class to prevent opening in another window or tab.


<a class="open-in-rcfWin" href="/MY_INTERNAL_LINK" target="rcfWin">Linked text</a>
<a href="http://SOME_EXTERNAL_LINK" target="extWin">Linked text</a>

* Aside: I’ve already manually removed the http://www.rcfouchaux.ca from internal links because of its effect on WordPress “pingback links,” which I’ve got going on here. I’ll have to explain those later, but it comes in handy that I’ve done this, as you’ll soon see.

Problem

This blog just turned 3, and I’ve got a lot of blog pages. I have to find some way to automate at least some of this. I might have used target="_blank" sometimes, and not others. I might have already used target="extWin".

jQuery to the rescue!

jQuery library—write less, do more

jQuery is a “library” of code that makes standard JavaScript easier to use by preparing commonly used patterns and tasks and giving them logical, easier-to-remember names. jQuery selectors let’s us find and select specific elements and groups of elements on a web page and then manipulate them in pretty astonishing ways. If your site is WordPress like this one you’ll have to find out if jQuery is already included in your theme, or if it can be added easily (or if you have admin access to your web root and know how you can add it to any web site). Due to historical reasons I combine methods. I let the Admired Theme supply the jQuery and I keep extras in my own file. To make it use the scripts in my file I need admin-level server access to edit my theme’s header.php, which is found in wp-content/themes/YOUR_THEME/. Find wp_head(); alone on its own line and add a line of code after it wp_enqueue_script( ALIAS, PATHTOFILENAME );. The path to the file has to be complete, should be a ‘relative’ path, and depends on your server. I always make the alias the first part of the filename.

<?php
	/* JavaScript for threaded comments.
	 ----------------------------------*/
	if ( is_singular() && get_option( 'thread_comments' ) )
		wp_enqueue_script( 'comment-reply' );

	/* wp_head() before closing </head> tag.
	---------------------------------------*/
	wp_head();
	
	/* Include own script(s) AFTER wp_head() tag.
	---------------------------------------*/
wp_enqueue_script( 'MY_CUSTOM_SCRIPT', '../[actual_path_to]/MY_CUSTOM_SCRIPT.js' );
 
/* etc... */

Thereafter you make changes to that file and then replace it on the server. Keep in mind that header.php will be over-written if and when you update your theme, so keep backups of any code you add.

Adding the behaviors we want to the elements we want

The jQuery magic starts when you wrap the selector in $('SELECTOR');. I’ll be creating a set of extWinLinks $('[href^="http"]'); and rcfWinLinks $('.open-in-rcfWin');

There are nearly always more than one way to solve a problem with jQuery. My general approach will be to create a function as the page loads, and call it when the page is ready. I’ll supply more details in the code comments!

To recap: we’ll take all http links and assign target=”extWin” regardless if they’ve got a target attribute set or what it might be set to. We’ll also create a class name to apply to internal links we think should open their own window, but never the same window an external link may already be open in. Bonus: We’ll add the sentence ” … Opens in a new tab or window.” to every link that does that. Because this last bit of code will be repeated in both the previous functions we’ll write it as a standalone function in its own right, and call it from the other two when needed (those jQuery.each(); loops that repeat in each function are good candidates for the same treatment, but I left it so you can better compare what’s happening in each case).


        /*
         * Window openers
         * Require jQuery
         *
         */
          
          // Declare variables in a single statement at the top of the script.
          // Select external links and store in a variable named extWinLinks
          // Select internal links and store in a variable named rcfWinLinks
          // Create two functions to set the targets on the two sets of elements. 
          var
             extWinLinks = $('a[href^="http"]').not( 'a[href~=".rcfouchaux.ca/"]' ), // use a comma if you have more
             rcfWinLinks = $('.open-in-rcfWin'),
             do_extWinLinks = function() {
                 // Set the target attribute to 'extWin'
                 extWinLinks.attr({ target:'extWin' });
                 
                 // Go through each item and get its title if it has one, or set it to an empty string.
                 extWinLinks.each( function( el,i ) {
                     var my = $(this), myTitle = my.attr('title') || '' ;
                         my.attr({ title : appendNotice( myTitle ) });
                 });
             },
             do_rcfWinLinks = function() {          
                 // Set the target attribute to 'extWin'
                 rcfWinLinks.attr({ target:'rcfWin' });
                 
                 // Go through each item and get its title if it has one, or set it to an empty string.
                 rcfWinLinks.each( function( el,i ) {
                     var my = $(this), myTitle = my.attr('title') || '' ;
                         my.attr({ title : appendNotice( myTitle ) });
                 });
             },
             appendNotice = function( title ) {
                 // Store the notice as a variable
                 var
                     notice = ' … Opens in a new tab or window.'
                 ;
                 
                 // return the appended notice (but don't add a leading space)
                 // This syntax, if what's left of ? is true returns left of :, otherwise right of :
                 return ( title.length > 0 ) ? title + ' ' + notice : notice ;
             }
          ; // I make the final semicolon obvious so I can find it later
          
          // Call the functions. 
          do_extWinLinks(); 
          do_rcfWinLinks();  
  

To summarize

Know your organization, your audience, and your content. Use valid HTML wherever you write code. If most of your site visitors are knowledgeable about technology it may not be necessary to open new windows, as they will use their familiar browsing setup to choose when and how to open them, and if your code is valid it will work as they expect. There’s no WCAG 2.0 guideline that says not to open new windows, but we must think more carefully about how doing so may create barriers to ease of access and use. We might consider limiting their number—by using a named window, not the well-known keyword _blank—and warn our users it will open in a way that screen readers will discover and convey to any users who may be using one. This discussion follows a line of thinking you can adapt to meeting other WCAG 2.0 success criteria. This JavaScript shows only one way to reduce the number of windows your site opens, and to inform users in advance in a way their technology can understand.

I’ve coded all the external links in this post differently, but they should all open in the same tab or window. Hover your mouse over any links on this page to see if the ” … Opens in a new tab or window” notice worked. Here’s a class="open-in-rcfWin" internal link and here’s another one. The next one has no class set, so it will replace the content of this page with the home page: ciao for now!

§

Understanding WCAG 2.0 Latest version: www.w3.org/TR/UNDERSTANDING-WCAG20/

How to Meet WCAG 2.0 – Quick Reference: www.w3.org/WAI/WCAG20/quickref/

Jan 23

There’s still time to get edreform right in Canada, and there’s still interest in doing so

Canada’s campaign finance laws, relatively stronger unions, a slight majority of conservatives who understand the role of revenues, tradition of compassion and peace-making—I think these are some of the characteristics of a precariously perched public pride that keep, for now, an all-out US-style free-market frenzy from taking root. “Publick Spirit,” as they spelled it when the call was for 19th Century Competencies, was a virtue touted by Republicans, Federalists, Tories and Whigs throughout the shrinking Empire. @symphily, while being perhaps exceptionally articulate in his questioning, and meticulous in the quality and expression of his supporting arguments, asks immensely important questions that in my experience aren’t exceptionally uncommon amongst Canadian teacher candidates today. They are coining, learning and understanding terms such as “glocalization,” “cyber-colonialism,” “metamodal mastery.”

Just as musicianship is known to support mathematical learning, perhaps entrepreneurship might be responsibly and ethically understood in ways that support social capital, that enrich and nourish the public sphere. Practical action research, connecting theory and discourse in praxis, participatory research… these are respected techniques known for decades in Canadian faculties of education, whether or not they are associated with names like Freire, or Gramsci. Is that why Ontario teachers were able to resist and eventually overcome a neoliberal assault in ’97, to demand some semblance of evidence based assessment be included in the EQAO?

But universities will be given free SharePoint systems, corporate-stocked libraries on wheels will replace education resource centres with their specialist-enhanced collections, and venture capitalists will actively seek out in education what free-marketists call “areas of nonconsumption.” That is a turn of phrase First Nations peoples targeted by the anti-teacher, anti-public spin-off of the American for-profit venture “Teach for America” might want to critique—and might well question!
—moi

But universities will be given free SharePoint systems, corporate-stocked libraries on wheels will replace education resource centres with their specialist-enhanced collections, and venture capitalists will actively seek out what free-marketists might call “areas of nonconsumption in education” (see Christensen, Horn, and other Harvard Business School’s blogs and cookbooks). That is a turn of phrase First Nations peoples targeted by the anti-teacher, anti-public spin-off of the American for-profit venture “Teach for America” might want to critique—and might well question!

What Canada has to fear most is her tradition of complacency. What good is eschewing corporate and union capital in elections if you don’t get up and go to the polls yourselves?

I do agree with a great deal of what C21 has to say about 21st Century competencies and literacies. The SMART board is a truly engaging and open-ended tool, the kind that allows pedagogy to take wings. I think there are genuine educators at all levels of this organization, and I’ve seen them genuinely engaged. In my master’s research I was able to differentiate C21 from its American cousin P21, where a free-market feeding frenzy suggests the “p” might stand for “piranha.” But the line is all too thin and we may remind the enthusiastic Canadian publishers and education technology innovators here—you swim with sharks.

I see the words “student centred” often, and I trust that they’re written with sincere esteem. I yearn only for shared understanding of what student centred actually might look like. I think it says they get to be the ones to decide what kind of world they live in or, for a practical example, that if code is a 21st century literacy we teach kids to read and write code—not simply to buy other people’s code. The discourse and theory of disruptive innovation too can be disrupted — students and teachers adept at technology, collaboration and critical thinking will be quite capable of creating rich learning situations with or without their own choice of self-authored, open source and/or commercial products, chosen because they support the lesson—never because the lesson was designed to sell a product. Students assessed to identify strengths and weaknesses, to improve their next performance—not because there’s a contract with a far-away testing company whose CEO may expect an obscene bonus for creating numbers that will be used against them and their support systems.

With awareness, involvement and due vigilance—“jealousy” as they said when public had the extra “k”—and an understanding that democracy is a way of life, not the vote you cast every few years—genuine ITC *facilitators* of deep, thick learning, teaching excellence, and student achievement will gain favour and remain important contributors, while ITC *directors* who say they have all the answers, who employ the “power tools” of coercive disruption to push those they label “resistant to change” aside in the interest of profits and stockholder achievement, will fail and fade away.

Thank you Mr. Kierstead for your work in transforming education. Thank you Mr. Steeves for your vigilance and this essential restoration and re-framing of the critical underlying issues. Thank you also Mr. Cantor for your supporting evidence and the astute simile that inspired me to think back yet another hundred years.

Let’s protect Canadian schools and children from blind, uncritical, ideology-driven trust in innovation, and put into practice policy that rewards the genuine thickening of learning situation—differentiating informed ongoing assessment from deficit thinking and prejudice, critically evaluating whether a perceived anaemia is due to poverty, language acquisition, a learning disability, or something else—student-centred investment in students, actively learning. Investing in the supply chain that monetizes a child’s learning environment for quick gain is something that costs so very much more, and yields so very much less.

 

† Comment on C21Canada.org awaiting moderation. The post is a year old; I may eventually revise or elaborate the above as a new and independent post, if after some time approval is not forthcoming. -RCF

§

Further thought and reflection

Morbey and class (2014) EDUC 3610: Morbey, Franklin, and Friedman. Professor Mary Leigh Morbey’s Teacher Candidates at York University consider cyberethics, comparing Morbey, Ursula Franklin and Thomas Friedman and asking, “…in light of all three writers how do we begin to think about ethics, technology, and education?” [Prezi]

Nov 24

JavaScript the least of (my) hurdles with MIDI.js

On #musedchat Monday Nov 18 I saw an opportunity to mention an open source Scoring/Engraving tool and was soon encouraged to send more links to open source resources. I’ve been collecting such links in the bookmarks of various browsers for years, and I’ve followed through on my initial interest to various degrees, so in some cases I found myself checking links along with my memory. In one case—MIDI.js—I said a big “Oh yeah! I was gonna try installing that, wasn’t I?”

How easy it is to try out any of the hundreds of thousands of interesting and potentially useful JavaScript offerings one can find on the Internet depends a lot on how much documentation the developer and interested community have provided and good examples of the code in (ahem) “authentic situations.” No matter how good it is, if you want it you’ll soon have to view source and dig in. The code behind MIDI.js looked to me daunting, but on closer inspection it turned out the biggest hurdle was recognizing the playlist of MIDI files is an array of Base64-encoded strings hard-coded in the file. If you know what that is, and if you can encode your MIDI file as a Base-64 string then copy/paste it over the ones in the original example—and if you set up the folder structure identically to the original (clone the Git repository straight into /xampp/htdocs if you work with a LAMP setup like mine)—it just works! But it looks just like the author’s.

The design is not responsive1 and doesn’t fit my blog or mobile device. The colours are very cool but I don’t need them. The note display has so many pedagogical applications my brain is exploding—but it doesn’t fit on my pages, same goes for the player and buttons. The JavaScript knowledge I need is “just enough” to identify where to safely slice and dice the code and recognize the very few places I might change something. It was more important I knew Base-64 encoding is something I’d likely find a web site to do. The highest-level skill needed here is actually CSS. I need to restyle the player so it fits my pages in the contexts I expect it to be viewed. And I want those notes to play along exactly as they do now, just in a completely different layout.

Here’s what it looks like today. (It’s not worth listening to in anything but Chrome).

An undefined error originally came from this line, but I haven’t found where MIDI.lang is supposed to be defined, and the sentence really doesn’t tell me anything I care to know if I define it as “English.” I made sure the page has a title and I even gave it a language attribute but no luck only by hard-coding it as shown below could I stop it so far. Will dig in [to the MIDI object, its properties and methods] later.

// I added...
// Quick suppression of undefined
MIDI.lang = MIDI.lang || 'en-ca';
/// above...
// this is the language we are running in
var title = document.getElementById("title");
title.innerHTML = "Sound being generated with &quot; + MIDI.lang + ".";
// I also added at line 108
pausePlayStop(true);  // Sorry Gasman. Autoplay is just wrong!
// Just above that I see <code>song[songid++%3]</code>, the '%3' implies something hard-coded that applied to the fact there used to be 3 midi files. To be continued... 

Some site JavaScript tweaks

Aside

HTML, CSS and JavaScript iconsI noticed the previous article, in which I begin to elaborate on what I mean by “thick” learning “situations,” was jumping to the iFrame that contains an audio clip. I knew why right away—the JavaScript plugin that syncs the audio and images is the first jQuery plugin I ever wrote (2011), I was trying to make sure the user could press the space bar after the page loaded, and the audio would play. It works until you load it in an “inline frame,” the < iframe > tag you may have noticed if you’ve ever copy/pasted YouTube “embed” code anywhere. I’d like to rewrite the entire routine “knowing what I know now,” but the jumping was annoying me and likely confusing others, if not turning them away. So I opened the plugin source file I haven’t opened in over a year. Then I remembered another problem, so I “fixed” that too.

The plugin itself is an example of what can happen when someone who had never taken a formal computer science course or even a programming class, but is reasonably good at finding the right documentation and making some sense of it, gets an idea and digs in, for better or worse. I came up with an approach that’s, well, completely different than Mozilla’s Popcorn, for example. The fact it works as well as it does must have at least as much to do with the power of computers and browser javascript engines as with anything I did (intentionally), but I’ll talk about that another day.

When good code goes bad

I think, but haven’t tested it, that I got away with this where the iframe is on another site because scripts don’t normally run if they’re on separate domains. It seems the “focus()” command was “bubbling up the DOM,” which is a bit like SCTV doing a 3D movie skit in your browser window, if that means anything to you. [I didn’t “embed” that in an iframe because it’s more entertaining than this post, you’d watch it and I’d probably lose you. Don’t click it now… oh shoot, that probably won’t work either.] I just meant to post news of the two tweaks and get back to the next instalment on making learning situations “thicker” using mind mapping tools.

Problem 1 was the jumping focus. I searched for the function I used, which was ‘.focus()’ and thought of two ways to approach it. The good programmers at jQuery have created a function named “stopPropagation()” but that’s not as much fun for me because I don’t really know how it works, I know when to type it in non-iframe-embeded code to make specific types of problems stop happening, then I go do something else. That’s always tempting, but the deciding factor was I wanted to turn it on and off. Plugins are supposed to make that easy. It was. I added a new variable ‘jswmAutoFocus‘ set it true by default (so it doesn’t break my old stuff all over the blog) and then wrapped focus() in an IF statement, so it only happens “if jswmAutoFocus is true.” The only trick is you have to look for it as settings.jswmAutoFocus once you set it false, which you now do in the blog post, not the plugin code. (I’ll go back and experiment with stopPropagation() too, it’s probably called for here and these aren’t mutually exclusive solutions.)

 // snipped code that preceded this...
		methods = {
		init : function(options) {
			/*
			 * These styles enable you to change nearly 
			 * anything about the appearance. You can 
			 * also quite easily add your own. 
			 *  *  *  *  *  *  *  *  *  *  *  *  *  *  */
			var /* The first group need to be declared before the 
			     * "defaults" object, because we use them inside it
			     */
				jswmAutoFocus = true, // New line
				jswmTitleId = "jswmTitle",  /* etc... */

The IF statement looks like this. ‘===’ means “deeply equals,” (not just the word ‘true,’ but boolean type true) (setTimeout(code_delayed_by_number_of,milliseconds) is a function that delays whatever code on the left of the comma by the number of milliseconds on the right:

if (settings.jswmAutoFocus === true)
{
        setTimeout("$('.jswm audio:first').focus();",250);
}

Problem 2 was that I used old fashioned User Agent detection, not recommended feature detection using modernizr. The thing is I wanted the old method because I knew how to “spoof” it and pretend to be something I wasn’t, and that let me test some things more quickly. Not recommended for “robust” “scalable” applications, but the only harm for me in using it was that I knew all along it was deprecated and would one day produce an error. I saw the error a few weeks ago when I updated the jQuery on my site to 1.9, I’ve since installed 1.10 so it was time to deal with it.

jQuery released a “migration” plugin that returns this feature and others. I don’t need the others right now, only this one. It’s very likely I could download the “debug” version and extract just the right bits, but this seemed like a challenge within my grasp. I know the original was a property of the global jQuery object and was itself an object. I knew from jQuery dicumentation it had 4 “keys.” I knew it returned only true, false or undefined, and the latter would be written in red text in the error console of Firebug. I know that in JavaScript you can return an object from a function, and you can assign a function to a variable name. So I knew if I could write a function, that produces an object, that returns value of true or false (and is more discreet about advertising its errors) and assign it the same name I gave the old one ($brwsr), it should work and the error should go away. With Firebug open as my scratch pad I wrote the function shown below. The dot in the old code, $brwsr = $.browser, means ‘browser’ is a property of ‘$’ (which is jQuery itself), I gave it my own name so it will come when I call it and not sneak away and pick up other properties somehow when my back is turned, and so it wouldn’t have to travel through the entire jQuery object every time I call. It just happens to begin with a ‘$’ because in 2011 that’s how I reminded myself it’s a nickname for a piece of the jQuery object.

I used this list of User Agent strings (and I don’t care about versions tonight). You make a “regular expression” in JavaScript by using ‘/‘ where you would have used “'” or ‘"‘ and you have to know the secret code. Then you can call a “method” (a function that’s already built into an object straight “out of the box”) of regular expressions, called test(), on the User Agent, which you called ‘ua’ like so: /myRegularExpressionPattern/.test(ua). I used a couple different regExp abilities just for variety and to demo, see the comments beside them.

var getBrowser = function(){
 var ua = navigator.userAgent,
     brwsrObj = {browser:"unknown"}
 if (/firefox|konqueror/i.test(ua)) // the 'i' means case-insensitive
 {
    brwsrObj = {mozilla:true}; // key : value
 }
 else if (/ MSIE /.test(ua)) // the MSIE is upper case between spaces
 {
    brwsrObj = {msie:true};
 }
 else if (/AppleWebKit/.test(ua)) // case sensitive
 {
    brwsrObj = {webkit:true};
 }
 else if (/Opera[\/ ]/.test(ua)) // the backslash \ prevents JS from thinking this / is the end of the regExp
 {
    brwsrObj = {opera:true};
 }
 return brwsrObj;
},
$brwsr = getBrowser(); // The old name now stores the function, which returns a similar object. 

I don’t think for a minute this is as comprehensive as what I’ll find in the migrate.js source when I eventually open it. It is what it is: a quick fix to overcome a deprecated property in an alpha version of a script I wrote 2 years ago. It just needs to hold up until I install the beta… which I just need to write first.

§

Sep 30

LilyPond with Frescobaldi: open source music engraving

LilyPond is open source music engraving software. LilyPond “…was designed to solve the problems we found in existing software and to create beautiful music that mimics the finest hand-engraved scores.” It produces some of the finest looking scores you can imagine, and almost any style of note or notation you can imagine. But it’s a scripting language—which for many people makes it very difficult to learn, and much too tedious to use. Enter Frescobaldi.

Frescobaldi is an open source editing tool for LilyPond. I won’t pretend there’s no learning curve, but if you want to print absolutely stunning music scores and enjoy learning technology it’s worth it, and I’ll help you get started. And if you’re a music educator I’ll make some suggestions about how I might use this in teaching, albeit at a high school level or higher, with students who have already learned the basics of reading. Thanks to Frescobaldi’s built-in MIDI player I see applications to ear training, as well as more obvious help with general notation problems. I’ve also screen-recorded some of my first explorations, and I intend to edit them down and add audio, and continue with a video tutorial, hopefully in just a few days.

Both programs run on Windows, Mac or Linux, but there’s no Mac or Linux installer for Frescobaldi, so if you’re not running Windows you may need some extra skills there. First, download and install both programs using the links below. You will not need to launch LilyPond. You’ll launch Frescobaldi, tell it where to find LilyPond and Frescobaldi will take it from there.

Software links

LilyPond is a music engraving program, devoted to producing the highest-quality sheet music possible. Download

Frescobaldi is a LilyPond sheet music text editor. It aims to be powerful, yet lightweight and easy to use. Download

  1. On first launch Frescobaldi opens an empty document. You type and insert LilyPond code in the left Editor panel and then press the LilyPond icon ion the toolbar to render a gorgeous PDF in the right, or Music View panel. hide image Screen shot
  2. Choose EditPreferences… show image
  3. Set path to LilyPond show image
    Windows default: C:/Program Files (x86)/LilyPond/usr/bin/lilypond-windows.exe
  4. Choose ToolsPreferencesSetup New Score… (Ctrl+Shift+N) to open the Score Setup Wizard show image
     Other items on this list will be of great interest soon… I used the Quick Insert tool and the MIDI Player early in my very first score.

    The Score Setup Wizard lets you set the following up front—especially recommended your first time, as once you create the file you’ll need to get code snippets from the documentation, the other tools in the Tools menu, another file, or know what to type.
     You might even want to fill in all the fields and save a MasterSnippet.ly file for later reference. Frescobaldi also has its own built-in Snippets manager.

    1. Titles and Headers show
    2. Parts show
    3. Score Settings show
       Be sure to try the Preview button!

To get started I just picked 8 bars of a Stevie Wonder tune I happened to have loaded in iTunes. You can see the first 2 bars of the lick on the right of the screen shot below. The script on the left side, which you’d have to write from scratch without an editor, demonstrates rather aptly I think, why a tool like Frescobaldi can likely make LilyPond more useful to a much larger community. What will be much easier to demonstrate in a video tutorial is how I copy/pasted a snippet of code from the documentation into the editor and then tweaked it until I got what I wanted. The notes you see on the right are formed entirely by this part of the script on the left. 'is' as a sharp is not intuitive (unless you speak Dutch), but now that I’ve told you perhaps you can see the 4, 8 and 16 that sets note values, ‘r’ for rest, and the lower case note names, key of B Major. The tildes (~) create the ties, and I entered staccato and accents using the Quick Insert tool shown in the left panel of the final screen shot below.
 All your music goes immediately after the % Music follows here. and before the closing curly brace (}) that lines up flush left with the instrument name above it and the code \score below it (see both screen shots beneath the following code snippet).

// You can group and nest notes in curly braces for readability.
// Here I've grouped each beat within each measure on its own line.
{
{b4-.} {r16 b16 dis cis-&amp;gt;~}  {cis-. cis16 gis' fis-&amp;gt;~} {fis8-. fis,16 gis}
}
{
{b8-&amp;gt;-. cis16 cisis16} {dis16 fis gis b-&amp;gt;~}  {b16 cis16 cisis dis-&amp;gt;~} {dis4-.}
}

Screen shot

By the time I’d finished I’d opened the MIDI Player to check my work. You need to press the Engrave button to refresh the output on the right (there are further options under the LilyPond menu). Frescobaldi supplies the bar lines based on the time signature in the score settings, and plays audio—I feel those two facts have pedagogical implications. I slowed down my 8-bar passage using Audacity, played them side by side, and by refreshing the output was able to see and hear what I had right and wrong along the way.
Screen shot
I hope this is enough to pique your interest. There’s another LilyPond editor I plan to try soon too, Denemo, highlighted with even more on the LilyPond site. It looks quite sophisticated, but I can tell I’ve barely scratched the surface of Frescobaldi, which was intuitive enough out of the box to keep me intrigued and progressing—getting this far was fun! Please use the comments section and stay tuned for some video tutorials as I get in further.

§

Richard studied as a teenager with Trevor Payne at John Abbott College and attended Berklee College of Music in Boston. He has performed across Canada with full-time rock bands since the early 80s. He’s been a teacher of rock, jazz & classical guitar at the now defunct Toronto Percussion Centre, and at The Arts Music Store for many years. He holds the degrees of Bachelor of Fine Arts Music (Special Honours), Bachelor of Education, and Master of Education from York University, plays guitar and trombone, and taught grade 6-8 band at the Toronto District School Board and North York School Board.

Bookmarklets update

Aside

Last June I explored “bookmarklets,” which I’ve found to be an engaging way to explore JavaScript, primarily by leveraging the power of pet peeves—enticing novice learners to change something they don’t like about a web page to be more the way they’d like it to be. As an example I offered a simple script that toggles the visibility of the ads on a Facebook home page.

javascript:(function()
{
  var 
  rCol=document.getElementById('rightCol'),
  isHidden=rCol.style.visibility==='hidden'?true:false;
if(isHidden)
  {
    rCol.style.visibility='visible'
  }
else
  {
    rCol.style.visibility='hidden'
  }
})();
To actually use this as a bookmarklet, first remove all the line breaks and optimize spaces.

Such a snippet can lead to a discussion of the differences between CSS display and visibility or more advanced ideas like native functions and how and when to import external libraries. My bookmarklet soon evolved into the next snippet, which uses an updated id and display:none;

javascript:(function(){var%20adsDiv=document.getElementById('pagelet_side_ads'),isHidden=adsDiv.style.display==='none';if(isHidden){adsDiv.style.display='inline-block';}else{adsDiv.style.display='none';}})();

This worked fine on the Home page, but not elsewhere. Looking into it with Firebug you quickly see the id is different—on a Messages page, for example, it’s pagelet_ego_pane. You might try simply adding a conditional, if it’s not 'pagelet_side_ads' try ‘pagelet_ego_pane’. But this will fail in JavaScript when the document.getElementById method can’t find the id it’s looking for. While there are elegant advanced ways to do this, and we don’t know how many different ids there might be, I followed the learner’s first suggestion and let it turn into an introduction of try/catch blocks and error handling. These work as follows:

try
  { /*something. If it fails...*/ }
catch(errorObjectName)
  {/*report the error and/or try something else*/}

The errorObjectName is usually error and you can retrieve error.message from it, amongst other things.

If at first you don’t succeed, try/catch again

Here’s the expanded code that tries to find an element with id="pagelet_side_ads" and if that returns and error, it catches that and “tries” again with id="pagelet_ego_pane". If that fails it attempts to log that information to the console. Notice I didn’t say “tries” as there’s no additional try/catch block and I want to avoid using the same word with two meanings. What do you think would happen if the browser has no console object containing a log() method? Below the expanded version is a single line version of the same code (except generic console.log() has been refined to console.error() see this link) to use, as expanded code doesn’t work in this context.

javascript:
(function() 
{
  try
    {
      var adsDiv=document.getElementById('pagelet_side_ads'),
          isHidden=adsDiv.style.display==='none';
      if (isHidden) 
      {
        adsDiv.style.display='inline-block';
      }
      else
      {
        adsDiv.style.display='none';
      }
     }
  catch(e) 
  {
    try 
    {
      var adsDiv=document.getElementById('pagelet_ego_pane'),
          isHidden=adsDiv.style.display==='none';
      if (isHidden) 
      {
        adsDiv.style.display='inline-block';
      }
      else 
      {
        adsDiv.style.display='none';
      }
    }
    catch(e)
    {
      console.log('Failed. Message: ',e.message)
    }
   }
})();

Single line version for general use:

javascript:(function(){try{var adsDiv=document.getElementById('pagelet_side_ads'),isHidden=adsDiv.style.display==='none';if(isHidden){adsDiv.style.display='inline-block';}else{adsDiv.style.display='none';}}catch(e){ try{var adsDiv=document.getElementById('pagelet_ego_pane'),isHidden=adsDiv.style.display==='none';if(isHidden){adsDiv.style.display='inline-block';}else{adsDiv.style.display='none';}}catch(e){console.warn('toggleFBAds failed. Message:',e.message,'. This can mean the id was not found.')}}})();

Drag it to your Bookmarks toolbar: Toggle FB ads

You wouldn’t want to nest try/catch blocks in catch statements endlessly, so you might extend this into lessons on arrays, loops, recursion… that depends on you and your learners’ situation.

§

Further reading

console on the Mozilla Developer Network

try…catch on the Mozilla Developer Network