From 61be09d54ada3e6438a86485ec08aeb3cef220ca Mon Sep 17 00:00:00 2001 From: Jeff Parsons Date: Mon, 2 Jan 2017 22:17:12 -0800 Subject: [PATCH 1/4] Minimal support for "sticky" machines (ie, machines that can't be scrolled off the top of the page) --- modules/shared/es6/sticky.js | 84 ++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 modules/shared/es6/sticky.js diff --git a/modules/shared/es6/sticky.js b/modules/shared/es6/sticky.js new file mode 100644 index 000000000..a4e0615dc --- /dev/null +++ b/modules/shared/es6/sticky.js @@ -0,0 +1,84 @@ +/** + * @fileoverview Support for "sticky" machines + * @author Jeff Parsons (@jeffpar) + * @copyright © Jeff Parsons 2012-2017 + * + * This file is part of PCjs, a computer emulation software project at . + * + * PCjs is free software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * PCjs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without + * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with PCjs. If not, + * see . + * + * You are required to include the above copyright notice in every modified copy of this work + * and to display that copyright notice when the software starts running; see COPYRIGHT in + * . + * + * Some PCjs files also attempt to load external resource files, such as character-image files, + * ROM files, and disk image files. Those external resource files are not considered part of PCjs + * for purposes of the GNU General Public License, and the author does not claim any copyright + * as to their contents. + */ + +"use strict"; + +/** + * addStickYMachine(idMachine) + * + * @param {string} idMachine + */ +function addStickyMachine(idMachine) +{ + var machine = document.getElementById(idMachine); + if (machine) { + var machineFooter = document.getElementById(idMachine + '.footer'); + if (machineFooter) { + var topMachine = findTop(machine); + var prevOnScroll = window.onscroll; + window.onscroll = function() { + if (window.pageYOffset <= topMachine) { + machine.style.position = 'relative'; + machine.style.zIndex = 'auto'; + machine.style.backgroundColor = ''; + machine.style.paddingRight = 0; + if (machineFooter) machineFooter.style.paddingTop = 0; + } else { + machine.style.position = 'fixed'; + machine.style.zIndex = 1; + machine.style.backgroundColor = 'white'; + machine.style.paddingRight = '30px'; + machine.style.top = 0; + if (machineFooter) machineFooter.style.paddingTop = machine.offsetHeight + 'px'; + } + }; + if (prevOnScroll) prevOnScroll(); + } + } +} + +/** + * findTop(obj) + * + * @param {Object} obj + */ +function findTop(obj) +{ + var curTop = 0; + if (typeof obj.offsetParent != 'undefined' && obj.offsetParent) { + while (obj.offsetParent) { + curTop += obj.offsetTop; + obj = obj.offsetParent; + } + curTop += obj.offsetTop; + } + else if (obj.y) { + curTop += obj.y; + } + return curTop; +} From 0eccf30d3cb82b3df4c1c690ad74fcb6bdf2c7a5 Mon Sep 17 00:00:00 2001 From: Jeff Parsons Date: Mon, 2 Jan 2017 23:21:16 -0800 Subject: [PATCH 2/4] Support for sticky machines when using the Node web server (so that we have parity between the Node and Jekyll web environments) --- _posts/2017-01-03-pdp-11-tutorials.md | 56 +++++++++++++++++++++++++++ modules/htmlout/lib/htmlout.js | 7 ++++ modules/markout/lib/markout.js | 5 ++- modules/shared/{es6 => lib}/sticky.js | 36 ++++++++++------- 4 files changed, 89 insertions(+), 15 deletions(-) create mode 100644 _posts/2017-01-03-pdp-11-tutorials.md rename modules/shared/{es6 => lib}/sticky.js (69%) diff --git a/_posts/2017-01-03-pdp-11-tutorials.md b/_posts/2017-01-03-pdp-11-tutorials.md new file mode 100644 index 000000000..b33803e06 --- /dev/null +++ b/_posts/2017-01-03-pdp-11-tutorials.md @@ -0,0 +1,56 @@ +--- +layout: post +title: PDP-11 Tutorials +date: 2017-01-03 15:00:00 +permalink: /blog/2017/01/03/ +machines: + - id: test1170 + type: pdp11 + debugger: true + config: /devices/pdp11/machine/1170/vt100/debugger/machine.xml + connection: dl11->vt100.serialPort + - id: vt100 + type: pc8080 + config: /devices/pc8080/machine/vt100/machine.xml + connection: serialPort->test1170.dl11 + sticky: top +--- + +Introducing PDP-11 tutorials! + +{% include machine.html id="vt100" %} + +[PDPjs](/devices/pdp11/machine/) is the newest addition to the PCjs family of emulators, joining PCx86, PC8080, and C1Pjs. + +While PDPjs may eventually support a range of DEC PDP machines, my current focus is on the PDP-11, starting with the +PDP-11/70. From there, I'll work backwards to support other PDP-11 models, such as the PDP-11/45, until I reach the +beginning of the PDP-11 line: the PDP-11/20. + +I'm starting with the top-of-the-line PDP-11/70 largely because the core of the emulator is being adapted from the +JavaScript [PDP-11/70 Emulator (v1.3)](http://skn.noip.me/pdp11/pdp11.html) written by +Paul Nankervis, who has generously given permission to use his code in PCjs. Since his emulator is a fully functional +11/70, it made sense to start there and work backwards, factoring out features as needed. + +The code has already undergone a lot of refactoring. Opcodes are now decoded by function tables rather than a single +switch statement, and every opcode is implemented with a discrete function. Other refactoring includes flag management, +interrupt management, and device management. + +Most of the work remaining is in device management. Like other PCjs emulators, PDPjs has a Bus component, +[bus.js](/modules/pdp11/lib/bus.js), that allows separate device components to register I/O handlers for specific +UNIBUS addresses. During the initial port, I moved all of Paul's original device management code into one "catch-all" +component, [device.js](/modules/pdp11/lib/device.js), which has now been converted to the new I/O registration model. + +The first new device component is [serial.js](/modules/pdp11/lib/serial.js), which is currently the +only means PDPjs has of communicating with the outside world. So you can try +[PDPjs connected to a VT100 Terminal](/devices/pdp11/machine/1170/vt100/), by clicking the **Run** button on the test machine. +The test machine is running [custom boot code](/apps/pdp11/boot/test/), adapted from boot code written by Paul, but due to the +lack of other device support, nothing can be booted yet. + +Obviously PDPjs is very much a work-in-progress. Before I proceed much farther, I really want to put the CPU through +some rigorous testing, so I'll be on the lookout for some comprehensive PDP-11 instruction tests. Or I'll write my own, +and compare results across 1 or 2 other PDP-11 emulators. + +{% include machine.html id="test1170" %} + +*[@jeffpar](http://twitter.com/jeffpar)* +*Jan 3, 2017* diff --git a/modules/htmlout/lib/htmlout.js b/modules/htmlout/lib/htmlout.js index 56cef16af..353e2a5bc 100644 --- a/modules/htmlout/lib/htmlout.js +++ b/modules/htmlout/lib/htmlout.js @@ -879,6 +879,7 @@ HTMLOut.prototype.findTokens = function(reTokens) aParms.push(aMatch[1]); } } + //noinspection JSUnresolvedFunction fnToken.call(this, sToken, sIndent, aParms); } } @@ -1968,6 +1969,12 @@ HTMLOut.prototype.processMachines = function(aMachines, buildOptions, done) } } this.addFilesToHTML(asFiles, sScriptEmbed); + if (infoMachine['sticky']) { + asFiles = []; + asFiles.push("/modules/shared/lib/sticky.js"); + sScriptEmbed = ''; + this.addFilesToHTML(asFiles, sScriptEmbed); + } if (buildOptions.id) { asFiles = []; asFiles.push("/modules/build/lib/build.js"); diff --git a/modules/markout/lib/markout.js b/modules/markout/lib/markout.js index ad64d8524..027cbeced 100644 --- a/modules/markout/lib/markout.js +++ b/modules/markout/lib/markout.js @@ -367,7 +367,7 @@ MarkOut.aFMBooleanMachineProps = { 'autopower': "autoPower", 'autostart': "autoStart" }; -MarkOut.aFMReservedMachineProps = ['id', 'name', 'type', 'debugger', 'config', 'template', 'uncompiled', 'autoMount', 'drives', 'parms']; +MarkOut.aFMReservedMachineProps = ['id', 'name', 'type', 'debugger', 'config', 'template', 'uncompiled', 'autoMount', 'drives', 'parms', 'sticky']; /** * convertMD() @@ -1167,6 +1167,7 @@ MarkOut.prototype.convertMDMachineLinks = function(sBlock) var machine = this.aMachineDefs[sMachineID]; sMachineType = machine['type'] || "PCx86"; sMachineOptions = ((sMachineType.indexOf("-dbg") > 0 || machine['debugger'] == "true")? "debugger" : ""); + if (machine['sticky']) sMachineOptions += (sMachineOptions? "," : "") + "sticky"; sMachineType = sMachineType.replace("-dbg", ""); sMachineXMLFile = machine['config'] || this.sMachineFile || "machine.xml"; sMachineXSLFile = machine['template'] || ""; @@ -1204,6 +1205,7 @@ MarkOut.prototype.convertMDMachineLinks = function(sBlock) sMachineParms = aMachineParms[4] || ""; var aMachineOptions = sMachineOptions.split(','); var fDebugger = (aMachineOptions.indexOf("debugger") >= 0); + var fSticky = (aMachineOptions.indexOf("sticky") >= 0); /* * TODO: Consider validating the existence of this XML file and generating a more meaningful error if not found @@ -1247,6 +1249,7 @@ MarkOut.prototype.convertMDMachineLinks = function(sBlock) 'xsl': sMachineXSLFile, 'version': sMachineVersion,// eg, "1.10", "*" to select the current version, or "uncompiled"; "*" is the default 'debugger': fDebugger, // eg, true or false; false is the default + 'sticky': fSticky, // eg, true or false; false is the default 'parms': sMachineParms} ); } diff --git a/modules/shared/es6/sticky.js b/modules/shared/lib/sticky.js similarity index 69% rename from modules/shared/es6/sticky.js rename to modules/shared/lib/sticky.js index a4e0615dc..2b5c39ecb 100644 --- a/modules/shared/es6/sticky.js +++ b/modules/shared/lib/sticky.js @@ -35,31 +35,39 @@ */ function addStickyMachine(idMachine) { - var machine = document.getElementById(idMachine); - if (machine) { - var machineFooter = document.getElementById(idMachine + '.footer'); - if (machineFooter) { - var topMachine = findTop(machine); - var prevOnScroll = window.onscroll; - window.onscroll = function() { + var topMachine = -1; + var prevOnScroll = window.onscroll; + window.onscroll = function() { + /* + * TODO: Determine if/when we can cache the machine and machineSibling elements; we already + * know we can't cache them when addStickyMachine() is first called, because that currently + * happens *before* embed.js replaces the placeholder machine DIV with the *real* machine DIV. + */ + var machine = document.getElementById(idMachine); + if (machine) { + var machineSibling = machine.nextElementSibling; + if (machineSibling) { + if (topMachine < 0) { + topMachine = findTop(machine); + } if (window.pageYOffset <= topMachine) { machine.style.position = 'relative'; machine.style.zIndex = 'auto'; machine.style.backgroundColor = ''; machine.style.paddingRight = 0; - if (machineFooter) machineFooter.style.paddingTop = 0; + if (machineSibling) machineSibling.style.paddingTop = 0; } else { machine.style.position = 'fixed'; machine.style.zIndex = 1; - machine.style.backgroundColor = 'white'; - machine.style.paddingRight = '30px'; + machine.style.backgroundColor = '#404040'; + machine.style.paddingRight = '16px'; machine.style.top = 0; - if (machineFooter) machineFooter.style.paddingTop = machine.offsetHeight + 'px'; + if (machineSibling) machineSibling.style.paddingTop = machine.offsetHeight + 'px'; } - }; - if (prevOnScroll) prevOnScroll(); + if (prevOnScroll) prevOnScroll(); + } } - } + }; } /** From 6f3658370486ffd6f24999a4f2bf621da2f5e774 Mon Sep 17 00:00:00 2001 From: Jeff Parsons Date: Tue, 3 Jan 2017 10:58:25 -0800 Subject: [PATCH 3/4] Added support for machine command links to assist in the creation of online tutorials; however, the commandMachine() function isn't wired to anything yet, and this only works with the Node web server (updating the Jekyll environment is next) --- ...cting-an-ibm-pc-to-a-dec-vt100-terminal.md | 4 +- ...-06-introducing-pdpjs-a-pdp-11-emulator.md | 10 +-- _posts/2017-01-03-pdp-11-tutorials.md | 53 +++++++++------- modules/markout/lib/markout.js | 62 ++++++++++++++++--- modules/shared/lib/sticky.js | 20 +++++- 5 files changed, 106 insertions(+), 43 deletions(-) diff --git a/_posts/2016-08-19-connecting-an-ibm-pc-to-a-dec-vt100-terminal.md b/_posts/2016-08-19-connecting-an-ibm-pc-to-a-dec-vt100-terminal.md index a804fdf7f..8d1f7c7e2 100644 --- a/_posts/2016-08-19-connecting-an-ibm-pc-to-a-dec-vt100-terminal.md +++ b/_posts/2016-08-19-connecting-an-ibm-pc-to-a-dec-vt100-terminal.md @@ -64,10 +64,10 @@ was add the following Front Matter to the top of the Markdown file: and then embed the machines in the post, each with a single line: - {% raw %} +{% raw %} {% include machine.html id="ibm5170" %} {% include machine.html id="vt100" %} - {% endraw %} +{% endraw %} For people rolling their own web pages, [the basics](/docs/pcx86/) haven't changed, and adding a serial connection merely requires adding a *connection* property (eg, `connection:"com2->vt100.serialPort"`) to the *parms* parameter passed to the diff --git a/_posts/2016-10-06-introducing-pdpjs-a-pdp-11-emulator.md b/_posts/2016-10-06-introducing-pdpjs-a-pdp-11-emulator.md index 7581e1506..9ae85d022 100644 --- a/_posts/2016-10-06-introducing-pdpjs-a-pdp-11-emulator.md +++ b/_posts/2016-10-06-introducing-pdpjs-a-pdp-11-emulator.md @@ -24,9 +24,9 @@ beginning of the PDP-11 line: the PDP-11/20. I'm starting with the top-of-the-line PDP-11/70 largely because the core of the emulator is being adapted from the JavaScript [PDP-11/70 Emulator (v1.3)](http://skn.noip.me/pdp11/pdp11.html) written by Paul Nankervis, who has generously given permission to use his code in PCjs. Since his emulator is a fully functional -11/70, it made sense to start there and work backwards, factoring out features as needed. +11/70, it made sense to start there and work backwards, disabling features according to the model. -The code has already undergone a lot of refactoring. Opcodes are now decoded by function tables rather than a single +The code has already undergone a lot of refactoring. Opcodes are now decoded by function tables rather than a single switch statement, and every opcode is implemented with a discrete function. Other refactoring includes flag management, interrupt management, and device management. @@ -37,9 +37,9 @@ component, [device.js](/modules/pdp11/lib/device.js), which has now been convert The first new device component is [serial.js](/modules/pdp11/lib/serial.js), which is currently the only means PDPjs has of communicating with the outside world. So you can try -[PDPjs connected to a VT100 Terminal](/devices/pdp11/machine/1170/vt100/), by clicking the **Run** button on the test machine. -The test machine is running [custom boot code](/apps/pdp11/boot/test/), adapted from boot code written by Paul, but due to the -lack of other device support, nothing can be booted yet. +[PDPjs connected to a VT100 Terminal](/devices/pdp11/machine/1170/vt100/), by clicking the **Run** button on the +test machine. The test machine is running a custom [Boot Monitor](/apps/pdp11/boot/monitor/) included with +[Paul's emulator](http://skn.noip.me/pdp11/), but due to the lack of other device support, nothing can be booted yet. Obviously PDPjs is very much a work-in-progress. Before I proceed much farther, I really want to put the CPU through some rigorous testing, so I'll be on the lookout for some comprehensive PDP-11 instruction tests. Or I'll write my own, diff --git a/_posts/2017-01-03-pdp-11-tutorials.md b/_posts/2017-01-03-pdp-11-tutorials.md index b33803e06..b2a5097e5 100644 --- a/_posts/2017-01-03-pdp-11-tutorials.md +++ b/_posts/2017-01-03-pdp-11-tutorials.md @@ -16,39 +16,44 @@ machines: sticky: top --- -Introducing PDP-11 tutorials! +Introducing PDP-11 tutorials. For more information, keep scrolling. {% include machine.html id="vt100" %} -[PDPjs](/devices/pdp11/machine/) is the newest addition to the PCjs family of emulators, joining PCx86, PC8080, and C1Pjs. +[PDPjs](/devices/pdp11/machine/) is able to run a variety of old DEC operating systems, such as RT-11 and RSTS/E, +and while there are manuals available online, thanks to the efforts of those who operate and contribute to websites +like [bitsavers.org](http://bitsavers.org), I suspect most people don't have a lot of interest or time to spend +reading old manuals. -While PDPjs may eventually support a range of DEC PDP machines, my current focus is on the PDP-11, starting with the -PDP-11/70. From there, I'll work backwards to support other PDP-11 models, such as the PDP-11/45, until I reach the -beginning of the PDP-11 line: the PDP-11/20. +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.: -I'm starting with the top-of-the-line PDP-11/70 largely because the core of the emulator is being adapted from the -JavaScript [PDP-11/70 Emulator (v1.3)](http://skn.noip.me/pdp11/pdp11.html) written by -Paul Nankervis, who has generously given permission to use his code in PCjs. Since his emulator is a fully functional -11/70, it made sense to start there and work backwards, factoring out features as needed. + machines: + - id: vt100 + type: pc8080 + config: /devices/pc8080/machine/vt100/machine.xml + connection: serialPort->test1170.dl11 + sticky: top -The code has already undergone a lot of refactoring. Opcodes are now decoded by function tables rather than a single -switch statement, and every opcode is implemented with a discrete function. Other refactoring includes flag management, -interrupt management, and device management. +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. -Most of the work remaining is in device management. Like other PCjs emulators, PDPjs has a Bus component, -[bus.js](/modules/pdp11/lib/bus.js), that allows separate device components to register I/O handlers for specific -UNIBUS addresses. During the initial port, I moved all of Paul's original device management code into one "catch-all" -component, [device.js](/modules/pdp11/lib/device.js), which has now been converted to the new I/O registration model. +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: -The first new device component is [serial.js](/modules/pdp11/lib/serial.js), which is currently the -only means PDPjs has of communicating with the outside world. So you can try -[PDPjs connected to a VT100 Terminal](/devices/pdp11/machine/1170/vt100/), by clicking the **Run** button on the test machine. -The test machine is running [custom boot code](/apps/pdp11/boot/test/), adapted from boot code written by Paul, but due to the -lack of other device support, nothing can be booted yet. +{% raw %} + {% include machine-command.html type='button' label='Try It!' machine='vt100' component='Keyboard' command='sendString' value='Hello World' %} +{% endraw %} -Obviously PDPjs is very much a work-in-progress. Before I proceed much farther, I really want to put the CPU through -some rigorous testing, so I'll be on the lookout for some comprehensive PDP-11 instruction tests. Or I'll write my own, -and compare results across 1 or 2 other PDP-11 emulators. +which should translate into a control that looks like: + + + +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' %} + +Obviously, every component we want to control will need to be updated to export the necessary functions. {% include machine.html id="test1170" %} diff --git a/modules/markout/lib/markout.js b/modules/markout/lib/markout.js index 027cbeced..998e9c794 100644 --- a/modules/markout/lib/markout.js +++ b/modules/markout/lib/markout.js @@ -942,10 +942,12 @@ MarkOut.prototype.convertMDLinks = function(sBlock) * Before we start replacing Markdown links, see if there are any Liquid-style replacements * (in case this Markdown file is part of a Jekyll installation) and remove them. * - * TODO: These replacements should use appropriate values from _config.yml; however, unless/until - * we start using Node again to host the public site, that's low priority. + * TODO: Any double-brace replacements should use appropriate values from _config.yml or the + * page's Front Matter; however, unless/until we start using Node again to host the public site, + * that's low priority. */ - sBlock = sBlock.replace(/\{([\{%]).*?\1}/g, ""); + sBlock = sBlock.replace(/([^\t])\{([\{%]).*?\2}/g, "$1"); + sBlock = sBlock.replace(/(\{)([\{%])(.*?\2})/g, "
$1$2$3
"); var aMatch; var re = /\[([^\[\]]*)]\((.*?)(?:\s*"(.*?)"\)|\))/g; @@ -1150,21 +1152,21 @@ MarkOut.prototype.convertMDImageLinks = function(sBlock, sIndent) */ MarkOut.prototype.convertMDMachineLinks = function(sBlock) { - var aMatch, sReplacement; + var aMatch, sReplacement, machine; var sMachineType, sMachineID, sMachineXMLFile, sMachineXSLFile, sMachineVersion, sMachineOptions, sMachineParms; /* * Before we start looking for Markdown-style machine links, see if there are any Liquid-style machines, * (in case this Markdown file is part of a Jekyll installation) and convert them to Markdown-style links. */ - - var reIncludes = /\{%\s*include\s+machine\.html\s+id=(["'])(.*?)\1\s*%}/g; + var reIncludes = /(.){%\s*include\s+machine\.html\s+id=(["'])(.*?)\2\s*%}/g; while ((aMatch = reIncludes.exec(sBlock))) { + if (aMatch[1] == '\t') continue; sReplacement = ""; - sMachineID = aMatch[2]; + sMachineID = aMatch[3]; if (this.aMachineDefs[sMachineID]) { - var machine = this.aMachineDefs[sMachineID]; + machine = this.aMachineDefs[sMachineID]; sMachineType = machine['type'] || "PCx86"; sMachineOptions = ((sMachineType.indexOf("-dbg") > 0 || machine['debugger'] == "true")? "debugger" : ""); if (machine['sticky']) sMachineOptions += (sMachineOptions? "," : "") + "sticky"; @@ -1176,11 +1178,14 @@ MarkOut.prototype.convertMDMachineLinks = function(sBlock) sReplacement = machine['name'] || "Embedded PC"; sReplacement = "[" + sReplacement + "](" + sMachineXMLFile + ' "' + sMachineType + '!' + sMachineID + '!' + sMachineXSLFile + '!!' + sMachineOptions + '!' + sMachineParms + '")'; } - sBlock = sBlock.replace(aMatch[0], sReplacement); + sBlock = sBlock.replace(aMatch[0].substr(1), sReplacement); reIncludes.lastIndex = 0; // reset lastIndex, since we just modified the string that reIncludes is iterating over } - sBlock = sBlock.replace(/\{%\s*include\s+build\.html\s+id=(["'])(.*?)\1\s*%}/g, '
'); + /* + * Ditto for any Liquid-style machine build links. + */ + sBlock = sBlock.replace(/\{%\s*include\s+machine-build\.html\s+id=(["'])(.*?)\1\s*%}/g, '
'); /* * Start looking for Markdown-style machine links now... @@ -1254,6 +1259,43 @@ MarkOut.prototype.convertMDMachineLinks = function(sBlock) ); } + /* + * Last but not least, see if there are any Liquid-style machine command links that need to be converted. + */ + reIncludes = /([ \t]*)\{%\s*include\s+machine-command\.html\s+(.*?)\s*%}/g; + + var findParm = function(aParms, sParm) { + sParm += '='; + for (var i = 0; i < aParms.length; i++) { + if (aParms[i].indexOf(sParm) == 0) { + return aParms[i].slice(sParm.length+1, -1); + } + } + return ""; + }; + + while ((aMatch = reIncludes.exec(sBlock))) { + if (aMatch[1] == '\t') continue; + var aParms = aMatch[2].match(/[a-z]+=(["']).*?\1/g); + if (!aParms) continue; + sReplacement = ""; + sMachineID = findParm(aParms, 'machine'); + var sControl = findParm(aParms, 'type') || 'button'; + var sControlType = sControl == 'button'? ' type="button"' : ''; + if (this.aMachineDefs[sMachineID]) { + sReplacement = '<' + sControl + sControlType + ' onclick="commandMachine('; + sReplacement += "'" + sMachineID + "',"; + sReplacement += "'" + findParm(aParms, 'component') + "',"; + sReplacement += "'" + findParm(aParms, 'command') + "',"; + sReplacement += "'" + findParm(aParms, 'value') + "')"; + sReplacement += '">' + (findParm(aParms, 'label') || 'Try It!') + ''; + } else { + sReplacement = ""; + } + sBlock = sBlock.replace(aMatch[0], sReplacement); + reIncludes.lastIndex = 0; // reset lastIndex, since we just modified the string that reIncludes is iterating over + } + if (cMatches) { sBlock = sBlock.replace(/^

([\s\S]*)<\/p>$/g, "$1"); } diff --git a/modules/shared/lib/sticky.js b/modules/shared/lib/sticky.js index 2b5c39ecb..270523448 100644 --- a/modules/shared/lib/sticky.js +++ b/modules/shared/lib/sticky.js @@ -29,7 +29,7 @@ "use strict"; /** - * addStickYMachine(idMachine) + * addStickyMachine(idMachine) * * @param {string} idMachine */ @@ -41,7 +41,10 @@ function addStickyMachine(idMachine) /* * TODO: Determine if/when we can cache the machine and machineSibling elements; we already * know we can't cache them when addStickyMachine() is first called, because that currently - * happens *before* embed.js replaces the placeholder machine DIV with the *real* machine DIV. + * happens before embed.js replaces the placeholder machine

with the real machine
. + * + * Placement of the addStickyMachine() call is irrelevant, because embed.js asynchronously + * reads all the XML files that define the machine *before* replacing the
. */ var machine = document.getElementById(idMachine); if (machine) { @@ -70,6 +73,19 @@ function addStickyMachine(idMachine) }; } +/** + * commandMachine(idMachine, typeComponent, sCommand, sValue) + * + * @param {string} idMachine + * @param {string} typeComponent + * @param {string} sCommand + * @param {string} [sValue] + */ +function commandMachine(idMachine, typeComponent, sCommand, sValue) +{ + +} + /** * findTop(obj) * From 82506638f804deadecea823437a69cc5bdde07c1 Mon Sep 17 00:00:00 2001 From: Jeff Parsons Date: Tue, 3 Jan 2017 15:39:14 -0800 Subject: [PATCH 4/4] Made sticky machine support adjustable through CSS instead of hard-coded --- modules/shared/lib/sticky.js | 14 ++++---------- modules/shared/templates/components.css | 14 +++++++++++++- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/modules/shared/lib/sticky.js b/modules/shared/lib/sticky.js index 270523448..baf393d2b 100644 --- a/modules/shared/lib/sticky.js +++ b/modules/shared/lib/sticky.js @@ -53,18 +53,12 @@ function addStickyMachine(idMachine) if (topMachine < 0) { topMachine = findTop(machine); } + machine.className = machine.className.replace(/pcjs-machine-(floating|sticky) /g, ''); if (window.pageYOffset <= topMachine) { - machine.style.position = 'relative'; - machine.style.zIndex = 'auto'; - machine.style.backgroundColor = ''; - machine.style.paddingRight = 0; + machine.className = 'pcjs-machine-floating ' + machine.className; if (machineSibling) machineSibling.style.paddingTop = 0; } else { - machine.style.position = 'fixed'; - machine.style.zIndex = 1; - machine.style.backgroundColor = '#404040'; - machine.style.paddingRight = '16px'; - machine.style.top = 0; + machine.className = 'pcjs-machine-sticky ' + machine.className; if (machineSibling) machineSibling.style.paddingTop = machine.offsetHeight + 'px'; } if (prevOnScroll) prevOnScroll(); @@ -83,7 +77,7 @@ function addStickyMachine(idMachine) */ function commandMachine(idMachine, typeComponent, sCommand, sValue) { - + console.log("commandMachine('" + idMachine + "','" + typeComponent + "','" + sCommand + "','" + sValue + "')"); } /** diff --git a/modules/shared/templates/components.css b/modules/shared/templates/components.css index 409d32848..ec888e4c9 100644 --- a/modules/shared/templates/components.css +++ b/modules/shared/templates/components.css @@ -228,7 +228,19 @@ .pcjs-copyright a { text-decoration: none; } - +.pcjs-machine-floating { + position: relative; + z-index: auto; + background-color: transparent; + padding-right: 0; +} +.pcjs-machine-sticky { + position: fixed !important; + z-index: 1 !important; + background-color: #404040 !important; + padding-right: 16px !important; + top: 0 !important; +} @media screen and (max-width: 800px) { .pcjs-textarea { width: 100% !important;