Final tweaks to initial sticky machine demo

This commit is contained in:
Jeff Parsons 2017-01-03 17:28:35 -08:00 • committed by Jeff Parsons
commit 43bec5fd03
7 changed files with 99 additions and 43 deletions

View file

@ -16,7 +16,7 @@ machines:
sticky: top
---
Introducing PDP-11 tutorials. For more information, keep scrolling.
Introducing PDP-11 tutorials. For more details, keep scrolling, and keep your eye on the VT100 below.
{% include machine.html id="vt100" %}
@ -26,8 +26,8 @@ like [bitsavers.org](http://bitsavers.org), I suspect most people don't have a l
reading old manuals.
In an effort to remedy that situation, I'm adding some new features to PCjs. The first feature is what I call
"Sticky Machines", and it's more a website feature than a machine feature. At the top of any PCjs webpage, in the
*machines* section, a machine can now have a *sticky* property. For now, the only supported value is "top"; e.g.:
"Sticky Machines", and it's really just a new feature of the PCjs website. At the top of any PCjs webpage, in the
*machines* section, a machine can now define a *sticky* property. For now, the only supported value is "top"; e.g.:
machines:
- id: vt100
@ -37,23 +37,31 @@ In an effort to remedy that situation, I'm adding some new features to PCjs. Th
sticky: top
A sticky machine makes it easier to construct a tutorial page for a single machine, by preventing that machine from
scrolling off the top of the page; it "sticks" to the top instead. The rest of the page scrolls normally, allowing the
user to progress at their own pace through the text and/or images of an accompanying tutorial.
scrolling off the top; it "sticks" to the top instead. The rest of the page scrolls normally, allowing the user to
progress at their own pace through the text and/or images of an accompanying tutorial.
The second feature is a generalized method for sending commands to components within a machine. For example, if we
want to send some keyboard commands to machine:
want to send some serial data to a machine:
{% raw %}
{% include machine-command.html type='button' label='Try It!' machine='vt100' component='Keyboard' command='sendString' value='Hello World' %}
{% include machine-command.html type='button' label='Try It!' machine='vt100' component='SerialPort' command='receiveData' value='Hello World' %}
{% endraw %}
which should translate into a control that looks like:
<button type="button" onclick="commandMachine('vt100','Keyboard','sendString','Hello World')">Try It!</button>
<button type="button" onclick="commandMachine('vt100','SerialPort','receiveData','Hello World')">Try It!</button>
In fact, let's try it now. {% include machine-command.html type='button' label='Try It!' machine='vt100' component='Keyboard' command='sendString' value='Hello World' %}
In fact, let's try it now. {% include machine-command.html type='button' label='Try It!' machine='vt100' component='SerialPort' command='receiveData' value='Hello World' %}
Obviously, every component we want to control will need to be updated to export the necessary functions.
Obviously, every component we want to control will need to be updated to export the necessary "command" functions.
So expect some PDPjs tutorials in the near future, featuring sticky machines and built-in command demos. Some
commands will be very simple, like the data injection command shown above. Others will perform more sophisticated
operations, such as loading and booting a particular disk, running a particular application, automatically flipping
selected Front Panel switches, and so on.
Finally, in case you're wondering why there's another machine below, well, what did you think the VT100 was talking to?
This PDP-11/70, of course.
{% include machine.html id="test1170" %}

View file

@ -594,6 +594,18 @@ function embedPDP11(idMachine, sXMLFile, sXSLFile, sParms)
return embedMachine("PDPjs", "pdp11", APPVERSION, idMachine, sXMLFile, sXSLFile, sParms);
}
/**
* findMachineComponent(idMachine, sType)
*
* @param {string} idMachine
* @param {string} sType
* @return {Component|null}
*/
function findMachineComponent(idMachine, sType)
{
return Component.getComponentByType(sType, idMachine + ".machine");
}
/**
* Prevent the Closure Compiler from renaming functions we want to export, by adding them as global properties.
*/
@ -611,5 +623,7 @@ if (APPNAME == "PDPjs") {
window['embedPDP11'] = embedPDP11;
}
window['findMachineComponent'] = findMachineComponent;
window['enableEvents'] = Web.enablePageEvents;
window['sendEvent'] = Web.sendPageEvent;

View file

@ -1,5 +1,5 @@
/**
* @fileoverview Support for "sticky" machines
* @fileoverview Support for "sticky" machines and commands that drive them.
* @author <a href="mailto:Jeff@pcjs.org">Jeff Parsons</a> (@jeffpar)
* @copyright © Jeff Parsons 2012-2017
*
@ -29,11 +29,19 @@
"use strict";
/**
* addStickyMachine(idMachine)
* addStickyMachine(idMachine, sPosition)
*
* If a machine is defined with a 'sticky' property, then the page containing that machine should
* also contain a call this function. Technically, the 'sticky' property's value should also be passed
* via sPosition, but since the only page position we currently support is "top", callers are currently
* omitting it, and "top" is simply assumed.
*
* TODO: Do something intelligent if sPosition is NOT omitted and is NOT "top".
*
* @param {string} idMachine
* @param {string} [sPosition] (if omitted, "top" is assumed)
*/
function addStickyMachine(idMachine)
function addStickyMachine(idMachine, sPosition)
{
var topMachine = -1;
var prevOnScroll = window.onscroll;
@ -68,16 +76,42 @@ function addStickyMachine(idMachine)
}
/**
* commandMachine(idMachine, typeComponent, sCommand, sValue)
* commandMachine(idMachine, sType, sCommand, sValue)
*
* Note that this script is not compiled into any of the machines, since "sticky machines" are feature of the PCjs
* website rather than of the machines. And since the machines are compiled, all their code and data is completely
* opaque to us, except for those functions explicitly exported by embed.js.
*
* So now, in addition to the functions for embedding machines on a webpage, embed.js includes a new function:
*
* findMachineComponent()
*
* which uses existing Component methods to find the requested component type for a specific machine, and if a
* component is found, then its 'exports' table is checked for an entry matching the specified command string, and if
* an entry is found, then the corresponding function is called with the specified data.
*
* @param {string} idMachine
* @param {string} typeComponent
* @param {string} sType
* @param {string} sCommand
* @param {string} [sValue]
*/
function commandMachine(idMachine, typeComponent, sCommand, sValue)
function commandMachine(idMachine, sType, sCommand, sValue)
{
console.log("commandMachine('" + idMachine + "','" + typeComponent + "','" + sCommand + "','" + sValue + "')");
if (window.findMachineComponent) {
var component = window.findMachineComponent(idMachine, sType);
if (component) {
var exports = component['exports'];
if (exports) {
var fnCommand = exports[sCommand];
if (fnCommand) {
//noinspection JSUnresolvedFunction
fnCommand.call(component, sValue);
return;
}
}
}
}
console.log("unimplemented: commandMachine('" + idMachine + "','" + typeComponent + "','" + sCommand + "','" + sValue + "')");
}
/**

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long