PencilCoder

Teacher's Guide: Event Objects Notes

Overview

This lesson presents a straightforward yet powerful extension of the Keyboard Events! lesson. Event objects provide a range of additional, contextual information about their corresponding events. In the case of keyboard-related events, they also permit us to effectively bind events for all keys with a single event listener, thereby substantially reducing the amount of coding required for many applications. Additionally, this lesson formally introduces two additional Pencil Code keyboard-related event binding functions, keyup and keypress, which facilitate a more finessed response to computer keyboard input than can be accomplished with keydown alone.

More about the lesson

Pencil Code key-event-binding functions

The Pencil Code keypress and keyup functions are analogous to the previously-introduced keydown function. The sole difference between the functions is the event to which they bind. As the name suggests, keyup events fire when a key is released. The difference between keypress and keydown is more nuanced. For example, keydown events tend to fire for any key, including meta characters such as shift or arrow keys, whereas keypress events fire only for keys with visible output. The similarities and differences between these events will be discussed below. But first, we address issues of usage.

The Keyboard Events! lesson introduced keydown as a function that takes two arguments: a string identifying a key and a callback that the event listener will execute every time that key is pressed, i.e., the event handler. All three keyboard-event-binding functions can be called this way. For example, the following snippet creates a keypress event listener for the lower-case w key:

cbW = ()->
  jumpto random(position)
  label "w", fontSize:"50px", color:random(color)

keypress "w", cbW

This two-argument usage is useful when we only need to establish event bindings for only a few keys, such using W, A, S, and D to control sprite movement. However, adding listeners key by key is an inefficent and cumbersome approach for binding larger numbers of keys.

The current lesson introduces the Pencil Code keypress function as an event binding function that takes a single argument: just the event handler, with no reference to a specific key. Though not stated explicitly in the lesson, all three keyboard-event-binding functions (keydown, keypress, and keyup) can be called this way.

This alternative, single-argument usage of Pencil Code's keyboard-event-binding functions makes it possible to bind all occurances of each event type to a single event handler in one line of code. For example, in the following snippet, keypress cbAnyKey binds all keypress events to the cbAnyKey callback. Afterwards, pressing any key will print its character to a random location on the screen:

cbAnyKey = (e)->
  jumpto random(position)
  label e.key, fontSize:"50px", color:random(color)

keypress cbAnyKey

Rather than identify a specific key when setting up an event listener, this approach makes use of data about the event itself within the body of the event handler callback. This data is automatically passed to the callback by the event source as an argument in the form of a system-generated event object. Writing the event handler to explicitly accept the event object (the argument e in the example above) facilitates accessing it in the body of the handler.

Event objects provide a wealth of information about each event. In the case of keyboard events, this information includes not only the key that was pressed, but also a timestamp, a record of concurrently-pressed meta-keys (such as shift or control), and more.

Difference between keyboard events

As just noted, the syntax for the keydown, keypress, and keyup keybinding functions is identical. The differences between the functions owe to the differences between the underlying keyboard events.

The keyup event parallels the behavior of the keydown event. As the name suggests, the keyup event (generally) fires upon release of a key rather than when the key is engaged. One exception to this rule is for the caps lock key: the keyup event does not fire when caps lock is initially pressed and released, i.e., engaging the lock. Rather, it fires upon the subsequent press (not release) of caps lock, which releases the lock. Another important exception invovles the delete key. keyup is the only event that fires when the delete key is pressed and released.

keydown and keypress events differ in a variety of often nuanced, context-dependent ways. For the purpose of the activities in this lesson, the following general rules will typically suffice:

  • With a few exceptions (such as for the delete and caps lock keys), keydown events fire whenever a key is pressed. keypress events only fire when the key press produces a character value. Thus both will fire for the keystroke a but only keydown will fire when esc, or shift is pressed.
  • keypress and keydown event objects both have boolean properties that report the status of modifier keys, e.g., shiftKey, metaKey, and altKey. They differ, however, in that for keypress (but not keydown) the value of the event object's key and keyCode properties reflect the status of modifier keys such as shift or alt (a.k.a., option on Macs). In Pencil Code, this means that if shift is depressed while either event occurs, the key value for a keypress event will return an upper-case letter for keys A through Z and characters such as ! and @ rather than the number values 1 and 2. In general, keypress should be the preferred event when processing text.

Finally, there is the issue of timing: keypress and keydown fire prior to keyup.

Notes to activities

The KeyEventNuances activity is designed to encourage students to explore the differences between the events associated with different keybinding functions along several dimensions. The primary issues to explore relate to "if" and "when" events fire. For example, keypress and keydown fire prior to keyup, and keypress will not fire at all when the arrow keys are pressed. The event object's timeStamp property can be helpful for documenting the sequencing of the different events for a given keyboard action and for exploring the timing of automatically re-firing events (as happens when keypress and keydown are pressed and held, rather than immediately released). Finally, students might also explore how modifier keys, such as shift or control, affect the values of event object properties.

The lesson provides this example solution to the KeyEventNuances activity. It's approach focuses on a narrow subset of event object properties (key, keyCode, and timeStamp). This alternative script provides another look, highlighting some other important differences between keypress and keydown events.

The String class's split method is a useful shortcut for TypingTest. split takes a single argument, which specifies the delimeter: abc.split(" ") breaks up a single string into an array of words; abc.split("") splits the string into its component letters.

The instructions for the Piano program recommend the use of tone, an alternative to the play function. Pencil Code provides this documentation:

A helpful alternative usage not mentioned in this documentation is the fact that tone's first argument, which specifies the note, can also be expressed a string (e.g., "A", specifying the note name) rather than a numeric value (e.g., 440, specifying the frequency).

Students have several options to map and bind keyboard keystrokes to individual musical notes. A common approach is to use nested if statements to test whether the event object's key value matches an appropriate string. However, such nested if statements can get rather cumbersome. switch statements (documented below) provide an alternative means to code the same conditional logic more succinctly. The use of switch is illustrated in the lesson's example solution. Yet another approach, illustrated in this script, makes use of a collection of objects that maps each keyboard key to the respective musical note, e.g., [{key:"a",note:"C"},{key:"w", note:"^C"}]. Each time a keyboard event fires, iterate over this array of key-and-note objects to determine which of one matches the event object's key property.

An additional solution to the Piano activity is provided in the Pencil Code Gym. This Interactive Keyboard script also uses keydown and keyup event binding functions, but it uses some advanced features not yet explored in this curriculum: anonymous functions, the delete function, and subscript notation.

Additional activities

  • Run this FourIsCOSMIC program a few times, until you figure out the riddle. Once you do, code your own version of the script. You might save your time by limiting the input options to the numbers 1 to 20.
  • FourIsCOSMIC
  • InputBox: The Pencil Code read function facilitates text entry in the Pencil Code environment. read accepts two arguments: (1) a string specifying a prompt and (2) a callback that defines what to do when data entry is complete.

    name = undefined
    
    updateName = (txt)->
      name = txt
        
    read "Please enter your name: ", updateName

    The foregoing snippet produces the following output on screen:

    read blocks

    After the user enters data and then either presses enter (on a PC) or return (on a Mac), or clicks the Submit button, this output changes to the following:

    read blocks

    read is useful for students who are new to coding, but for more advanced coders, it is rather restrictive. For example, the way that the text entry box disappears after you enter data, and then the text you entered appears as a label on the screen, is nice for some purposes, but more generally that behavior could be problematic. For example, we might want to keep the text entry box on the screen for continued use. Alternatively, you might want to interact with the user as they enter text into the box, such as for text validation purposes.

    Using the techniques described in this lesson, students should have little need for the read function. However, it does suggest an alternative means by which we may prompt users to enter data, i.e., using the same kind of text entry box. This is accomplished using an HTML <input> element. <input> is a familiar page element for end users and useful because it facilitates letting the user enter and or modify text prior to submitting it.

    For this activity, code your own InputBox program that makes use of an <input> element to gather information from the end user. In Pencil Code, you can easily add a specific type of HTML element using the Sprite constructor, e.g.,

    inputBox = new Sprite("<input>")

    To attach the event listener to the specific page element, rather than the entire document (which is the default), simply use dot notation

    inputBox.keypress(callback)

    Note that we bind the callback to keypress events so that the value of the event object's key property reflects modifier keys such as shift. You should use conditional logic in your callback to test for when the enter / return button is pressed (i.e., when e.keyCode==13), at which point your program should make use of the input in some fashion.

    InputBox

    Pro tip: you can manually keep track of each character the user types using the event object's key value. However, a much easier approach is to use the jQuery val method. When a jQuery object wraps an <input> element, val lets you access or modify the content of the text: e.g., box.val() returns the current value and box.val("x") replaces the content with the string "x".

  • RPN Calculator: Most calculators and computers base their computations on infix notation, in which operators are placed between operands. Two alternatives to infix notation are prefix notation, in which operators precede their operands, and postfix notation, in which operators follower their operands. Here is how you'd sum five and six, using each approach:

    • infix notation: 5 + 6 enter
    • prefix notation: + 5 6 enter
    • postfix notation: 5 enter 6 +

    Prefix and postfix notation have the advantage that they do not require parentheses. These latter two notations are known as Polish notation and Reverse Polish notation (RPN). The description "Polish" refers to the nationality of Jan Łukasiewicz, who invented Polish notation in 1924. RPN is used in scientific and financial calculators made by Hewlett Packard and the logic also undelies some programming languages, most notably LISP.

    For this task, code your own RPN Calculator. Rather than bind each key directly, make a single listener for all keys and evaluate the key event for the relevant inputs. Naturally, you will need to program the calculator-computation logic as well!

    To carry out a computation using RPN, type the first operand (i.e., value), press enter, type the second operand, and then the operator (e.g., "+" or "*"). A more complicated expression such as 7*(3+5) would be computed as 7, enter, 3, enter, 5, +, *.

Beyond the lesson

jQuery event objects and properties

The Notes to the Keyboard Events! lesson described in some detail the structures that faciliate working with events in JavaScript. In summary, GUI-related system events (such as keyboard and mouse events) originate in the underlying operating system. The OS passes information about each event to the system's currently-active program. When that program is a web browser, the browser uses the HTML Document Object Model (DOM) to identify which page element the event affects. If the system event matches an event listener registered for that page element, JavaScript will invoke the corresponding event handler, passing along to that callback, upon execution, a JavaScript event object containing information about the event.

Pencil Code relies heavily on the jQuery library, not only for animations, but for it's event-handling features as well. As a result, students using the Pencil Code event binding functions typically won't interact directly with native JavaScript event objects, but rather with jQuery "wrapper objects" of the underlying JavaScript objects. The benefit of using jQuery is that it provides additional functionality and cross-browser consistency compared to plain JavaScript. Conceptually, the role of JavaScript and jQuery event objects is exactly the same. On a practical level, the difference is that the event object properties mentioned in these notes are all jQuery event object properties. This become important when students want to look up information about specific events.

When working on keyboard events, students will likely focus primarily on the key, timeStamp properties and a few others that were mentioned in the lesson. For a complete listing, refer to the jQuery API for Event Objects. Alternatively, one can explore the event object by iterating over it, as illustrated for keydown events in this script.

Technical note: jQuery objects are termed "wrapper" obects because they retain a reference to the native JavaScript object as one of their properties. In the case of event objects, this reference is provided by the jQuery originalEvent property. Though not common, it can be useful to access the original event. See the Technicalities section of this document for an example.

As noted above, explicitly naming the argument in the callback function's definition—such as e in the example above—facilitates accessing the event object in the body of the callback. The alternative is to rely on JavaScript function's built-in arguments argument, as described in the Technicalities section of the Notes to the Custom Functions! lesson.

switch statements

As noted briefly in the Notes to the Conditional Logic! lesson, a switch statement provides a convenient alternative to nested if/else statements. There are some variations in usage; the basic CoffeeScript switch statement syntax is straightforward:

switch 
  when condition1 
    statement(s)
  when condition2
    statement(s)
  else
    statement(s)

The CoffeeScript then operator allow us to combine conditions and single-line statementse, anologous to how then can be use with if statements:

switch 
  when condition1 then statement
  when condition2 then statement
  else then statement

switch statements are particularly useful in the context of keyboard events because they facilitate evaluating event object properties, such as key or keyCode, that can take on a wide range of potential values. The following snippet illustrates one way we might evaluate the event object for a keyboard event handler with parameter e:

switch 
  when e.key=="up"
    fd 100
    dot blue, 10
  when e.key=="down"
    dot erase, 10
    bk 100
  when e.key==right" then rt 90
  when e.key=="left" then lt 90
  else
    see "Invalid input: #{e.key}"

An alternative switch-statement syntax is useful for cases, like the one above, where there is a lot of redundancy in the conditional statements testing for equality. As the following example illustrates, CoffeeScript permits splitting the test for equality into two expressions, and these are implicity compared for equality:

switch e.key
  when "up" 
    fd 100
    dot blue, 10
  when "down"
    dot erase, 10
    bk 100
  when "right" then rt 90
  when "left" then lt 90
  else
    see "Invalid input: #{e.key}"

This next and final example illustrates yet another variation of the CoffeeScript switch statement, which takes advantage of the CoffeeScript feature that "everything that can be an expression is structured to be one". CoffeeScript permits replacing multiple redundant assignments, i.e., one in each when clause, with a single assignment to the switch statement itself.

result = switch
  when e.keyCode>=97 and e.keyCode<=122
    "an uppercase letter"
  when e.keyCode>=65 and e.keyCode<=90
    "a lowercase letter"
  when e.keyCode>=48 and e.keyCode<=57
    "a number"
  else
    "neither a letter or a number"  

For more details about switch, please refer to other CoffeeScript resources, such as this one by TutorialsPoint.

Keyboard event sources: tabable HTML elements

As described in the notes to the Keyboard Events! lesson, each call to a Pencil Code keyboard event binding function effectively binds a callback to the web page's <body> element. As a result, the event listener fires the event handler whenever a key associated with that event is pressed.

Binding keyboard events to <body> is a convenient setup for beginners, but it will be limiting in time. For example, students may wish to explore using the HTML <input> element to gather text input, as suggested in one of the additional exercises. Moreover, the ability to bind callbacks to different event sources becomes indispensible when working with mouse events, the topic of the next lesson.

Using dot-notation, we can use event binding functions to register event listeners with page elements other than the the whole page. For example, the following example uses the Sprite constructor to create a <textarea> element in the middle of the screen. It then attaches the event handler cb using textarea.keypress:

  textarea = new Sprite("""<textarea rows=5 cols=50></textarea>""")
  
    cb =  (e)->
      jumpto random(position)
      dot random(color), 50
      label e.key
  
    textarea.keypress cb  

Note, however, that when working with keyboard input, associated events will only fire for page elements that are tabable. "Tabable" means that the element is reachable via sequential keyboard navigation, i.e., with the tab key. (Tabable elements can also be selected using a mouse click.) The <body> element is by default tabable, but most other page elements are not. The exceptions include text-related elements such as <input>, <textinput>, <form>, and <textarea>.

Technical note: Most non-tabable elements can be made tabable by adding a tabindex attribute with an integer value. The easiest choice is to choose 0, which simply adds them in order of appearance in the document source. An illustration is provided in this script.

Be aware, however, that adding listeners to different page elements can lead to confusing results if listeners for the same event type are also attached to containing elements, such as <body>. Owing to an events feature called propagation, events will fire for both the contained (a.k.a., child or descendant) element as well as for the containing (parent or ancestor) element. Propagation, and ways to control it, will be discussed in the notes to the Mouse Events! lesson.

What can go wrong

key events are not firing!

The preceding sections of these notes have described in detail many of the nuances of working with keyboard-related events. Perhaps the issue most likely to cause confusion is the fact that the different types of events—keydown, keyup, and keypress—do not all fire in response to all keys.

The first, rather straightforward example involves keypress events. These only fire for character keys, i.e., letters, numbers, and punctuation. Notably, this leaves out the arrow keys.

A second, and much more nuanced example involves the behavior of deletion-related keys. The delete key on the Mac behaves the same as backspace← on the PC. PCs typically also have a delete key, with its own behavior. For the keys delete (on the Mac) or backspace← (on the PC), only keyup fires, though this occurs upon releasing the key rather than when pressing it. The associated event object's key property (also discussed in the next lesson) has value "backspace". On the PC, pressing delete does result in keydown and keyup events. The associated event object's key property has value "delete". (See this script for an illustration.)

Variable scope complications

It is common to reference global variables in event handlers. When doing so, note that the variable must be declared prior to calling the event binding function. If not, the variable referenced in the event handler function will be a new variable with function scope. This short script provides a simple illustration.

Event Polling

When learning about keyboard events, students may attempt to create programs that allow them to control sprites using keys. However, such efforts may end in frustration. As described in the instructions to the Additional Activity TurtleWarperGame in the Notes to the Keyboard Events lesson, the use of keyevent-binding functions to control sprite motion is fine for programs that involve simple motions, but it is a suboptimal means by which to control sprite movement more generally. The underlying issue relates to lags associate with key events, a topic explored in these notes in a section on long presses. A superior solution is to rely on frame-based animation using timers and to harness a concept known as event polling, rather than to make use of the event binding fuctions directly. Timers and event polling are the focus of subsequent lessons in this curriculum, Timers (forever)! and Event Polling!.

Pedagogy

Explicitly defined callback functions

As mentioned in the notes to the previous lesson, the coding snippet provided in the Pencil Code block coding palette makes use of anonymous functions, and students and teachers alike may be tempted to adopt this convenience at this point. However, doing so risks diminishing student awareness of the role that callbacks play here. It also blurs the role of arguments used in the keybinding function context.

For example, the following code is the first line of a call to the keydown function with two arguments:

keydown 'x', (e) ->

An inexperienced coder can easily confuse e as an argument to keydown, though it is not. Rather, (e) ->, together with the subsequent lines of indented code which define an anonymous function, are the second argument to keydown

The upshot is that there continues to be good reason to hold off on anonymous functions. The topic will be addressed directly in the Anonymous Functions! lesson.

Technicalities

Keyboard event nuances

While the concepts and activities in the lesson are straightforward enough, keyboard event objects can be notoriously difficult to process in practice. Many of the nuances of working with events trace to historical cross-browser (and cross-platform) differences between browsers. Admittedly, these differences have become less pronounced over time, but it is still an issue. A primary reason for adopting jQuery is that it frees up coders from having to worry about the many cross-browser differences which would otherwise significanly complicate code. However, when it comes to keyboard events, jQuery is not a panacea.

Over the years, the HTML specifications and the JavaScript langauge have continued to evolve, with some significant changes to keyboard events. A not-to-be-overlooked consequence of this evolution is that different sources for documentation on events will provide divergent and even conflicting approaches to working with events. Quite a few of the properties in event objects have been deprecated over time.

A more far-reaching change is that the JavaScript keypress event itself is now deprecated. The upshot is that, while event bindings with the Pencil Code keydown and keyup functions (which internally use calls to jQuery event-event binding methods) can be counted on to provide consistent results across systems, the same may not continue to be true for keypress: per the the JQuery API, "as the keypress event isn't covered by any official specification, the actual behavior encountered when using it may differ across browsers, browser versions, and platforms."

Details on the deprecation of keypress are provided on the mdn docs page for keypress. The preferred modern alternatives to using keypress involve use of the beforeinput, keydown, or input (this last one new in 2023). However, given that access to the keypress event continues to be facilitated by jQuery, and also that the newer alternatives exceed most student needs while increasing the complexity of use, this curriculum recommends continued reliance on keypress events.

Yet another complicating factor to working with events in the Pencil Code environment is that the Pencil Code key event binding functions are modifications of the underlying jQuery. Some of these modifications were added to simplify the use of event-binding functions, such as adding the two-argument variants (e.g., keydown "x", eventHandler). Also, as noted above, the default codes from keydown are lowercase letters, whereas the standard mappings are to uppercase letters. Additional modifications, unseen to the user, include keybinding changes written with the intent to eliminate some persistent cross-browser differences in jQuery.

The upshot of the foregoing conversation is that, for the level of work that students will use at this point in their coding careers, most of the nuances listed in this section are unlikely to surface, but be aware that problems can arise, and also that documentation listed on other sites (MDN web docs for JavaScript, W3schools, jQuery API documentation) will at times give explanations that don't sync with functionality enountered on the Pencil Code platform.

jQuery event-binding methods

As discussed in the notes to the Keyboard Events! lesson, the jQuery keydown method is a shortcut for a call to the more general and versatile jQuery method on. The statement keydown eHandler is synonymous with $(window).on("keydown", eHandler). The on method works analogously for other browser events, including keypress and keyup.

As with the Pencil Code keybinding methods, on can be called on any jQuery object that references an HTML page element (or collection of page elements). Note that we have to explicitly reference $(window) (or some other page element wrapped in jQuery) because in CoffeeScript on is an alias for true, rather than for the jQuery event-binding method.

The primary benefit to using the on method rather than keydown is that you can subsequently use the corresponding off method to detach the event handler. off uses a similar syntax. For example,

window.off("keydown", eHandler)

removes the eHandler callback from the keydown event listener that was established using on. window.off("keydown") will remove all keydown event handlers set up using on. However, off has no effect on handlers set up with the Pencil Code keydown function, as illustrated in this script

In addition to the on method, jQuery also provides its own keydown, keypress, and keyup methods. These are jQuery shortcuts to pure jQuery event binding calls using on; they are not directly related to the Pencil Code keybinding functions of the same name. For additional details about using jQuery event-binding methods, refer to the jQuery events documentation.

jQuery event object's originalEvent property

The jQuery library's popularity owes in no small part to how it simplifies writing code that will work in all the different major browsers on all common operating systems. This is no mean feat, as the differences are not only myriad but often highly nuanced, and hence often tedious and time consuming to address.

In the case of events, jQuery creates its own event object that adjusts any system specific features so that they all adhere to these W3C standards. As with objects more generally, jQuery does not simply replace the orginal event, but creates a wrapper object. This jQuery event object normalizes and provides values for "common event properties", which include altKey, bubbles, button, buttons, cancelable, char, charCode, clientX, clientY, ctrlKey, currentTarget, data, detail, eventPhase, key, keyCode, metaKey, offsetX, offsetY, originalTarget, pageX, pageY, relatedTarget, screenX, screenY, shiftKey, target, toElement, view, and which.

The foregoing list may seem extensive, but it is not complete. It does not include properties for which the W3C does not provide a standard. The jQuery originalEvent property provides access to the event object that the browser itself created, and thus to the properties not included in the jQuery object directly.

Long presses / auto-repeat

An example of a property not included in the jQuery event object relates to "long presses". When a key is pressed and held, keydown and/or keypress events will fire repeatedly until the key is released. (In the case of keydown events, this holds only for keys that produce output, such as letters, and for arrow keys, but not for modifier keys such as shift or alt). .

Though the jQuery event object does not have a property to track whether a keyboard event fires as the result of an initial key press or from a repeat, the JavaScript event objects of each of the major browsers do. originalEvent.repeat records a boolean value indicating whether the event was a repeat fire from a single key press. The following example provides an illustration of how one might access this wrapped object property:

The timing of the auto-repeated events is determined by the underlying operating system. On a MacBook Pro running Chrome, the lag before the first keydown event and the first repeat is about 400ms. Subseqent refirings occur about every 80ms.

These lags between events can produce suboptimal behavior in interactive games when key events are used to control movement. A superior alternative is to use event polling, which is enabled by using timers (facilitate with the foreover function in Pencil Code), as discussed in the Event Polling! lesson.

JavaScript key event bindings

The "best-practice" approach to adding event bindings using pure JavaScript involves using a page element's addEventListener method. The following script illustrates this approach by adding a keydown event listener to the <html> element. (The JavaScript document variable provides access to the <html> element; see above for more details.) JavaScript listeners can be subsequently removed using the removeEventListener method.

document.addEventListener('keydown', writeText);
function writeText(e) {
write(`${e.key} ${e.keyCode}`);
}

Compared to JavaScript, the jQuery event binding alternatives have the obvious advantage of simpler syntax. Another advantage to jQuery event binding functions is that they can be used to add event listeners to multiple objects using one function call. Students will explore this functionality in the Mouse Events! lesson.

Legacy approaches to event binding

An alternative approach to adding listeners is to directly assign an event handler to an event property of an HTML page element. However, this approach to event binding is antiquated and considered poor form, and therefore it's use is strongly discouraged. This section is provided solely as a reference—for example, to help a student understand code that he or she may happen across when looking through other JavaScript resources.

To create a keypress event listener, assign a callback to the HTML element's onkeydown property. One approach for doing this is to use jQuery to identify and manipulate page elements, including assigning the callback, as illustrated here:

$("body").attr('onkeypress', 
"""
  cs();
  label("You entered " + event.key, 50);
  $("body").css({backgroundColor:random(color)}); 
"""
)

Note the following nuances to the foregoing example: the argument that defines the callback is passed as a string; the function definition itself must be coded in JavaScript (not CoffeeScript); and the event object is automatically passed to the callback as the variable event.

Using native JavaScript to identify and manipulate page elements, the previous code can be written as follows:

  document.body.onkeypress = function(){
        cs();
        label("You pressed " + event.key, 50);
        document.body.style.background=random(color);
      }

Direct use of the page-element properties to bind events often appears for simple callbacks as inline JavaScript (i.e., defined within the HTML definition of a web page), such as illustrated here :

<html>
<body onkeypress = "cs();label("You pressed " + event.key, 50); document.body.style.background=random(color);" >
  <p>Press a key to change the color.</p>
</body>
</html>