I'm not a JavaScript programmer. I have next to no idea about "what's out there" of libraries and so on. Therefore it's not unlikely that the referred to Windows HTML Application (HTA) code here, which is a mix of HTML5, CSS3 and JScript 5.6, may be incompatible with such libraries, common naming conventions, whatever, and I would like to rectify the issues that the more JavaScript-experienced reader can spot.
Compatibility is important because this is intended as a host environment for simple JavaScript scripts, which may likely use common libraries etc.
This code consists of a number of logical modules encapsulated in a single .HTA file by design*.
Therefore, even though it's only about half-finished it's too large to present inline here, I think, at about 750 lines. And since I have no idea what the issues could be, I'm reluctant to pare it down to what I think can be relevant. I think would be bound to err there.
Code at http://pastebin.com/FW88DLS1.
Oh, in order to make sense of the code it might help to see how the app looks:
As per request in comments I tried to post the full code inline here, but there was a limitation of 30.000 characters, while the code is some 36.000 characters.
Here's the CSS part (first part of the code):
<html>
<!-- Windows HTA application "Text Stream Host". Copyright (©) 2014 Alf P. Steinbach -->
<head id="head-element">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta http-equiv="MSThemeCompatible" content="yes">
<title id="title-element"></title>
<style>
* { font: 10pt 'MS Shell Dlg 2'; }
code { font: 10pt 'Courier new'; }
body {
padding: 0; margin: 0; overflow: hidden;
background-color: #F0F0F0;
}
#text-stream-display p { margin: 0; padding: 0; color: #000080; }
#control-area {
padding-top: 0; padding-left: 0; padding-right: 0.5em; padding-bottom: 0;
overflow: none;
margin: 0;
position: absolute;
left: 0; top: 0;
/*background-color: #FF0000;*/
width: 30em; height: 2em; left: -14em; top: +14em;
transform: rotate(-90deg);
}
#info-area {
background-color: white;
overflow: none;
position: absolute;
left: 2.5em; top: 0; right: 0; bottom: 0px;
}
#commandline-display {
color: gray;
overflow: auto;
white-space: nowrap;
padding: 0.5em;
border-bottom: 1px solid gray;
margin-bottom: 0.5em;
position: absolute; left: 0; top: 0; right: 0;
height: 7em;
}
.command-line { background-color: #F0FFF0; }
#text-stream-display {
overflow: auto;
white-space: nowrap;
padding: 0.5em;
position: absolute;
left: 0; top: 0px; right: 0; bottom: 0px;
}
.checkbox-div {
border: 1px black solid;
border-radius: 5px;
padding-bottom: 0.2em; margin-bottom: 0.1em;
padding-right: 0.5em;
display: inline-block;
cursor: pointer;
}
.checkbox-div:hover {
background: #D0E0FF;
}
</style>
Here's the first logical JavaScript module (following right after the above in the full code):
<!-- Namespace js_util
JavaScript utilities -->
<script type="text/javascript">
js_util = new function()
{
this.is_whitespace_character = function( ch )
{
return (ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t');
};
this.is_whitespace = function( s )
{
with( this )
{
var n = s.length;
for( var i = 0; i < n; ++i )
{
if( !is_whitespace_character( s.substr( i, 1 ) ) )
{
return false;
}
}
}
return true;
};
this.hex_digits = '0123456789ABCDEF';
this.hex_from_int = function( number, n_digits )
{
if( n_digits == undefined ) { n_digits = 8; }
var digits = new Array();
for( var i = 1; i <= n_digits; ++i )
{
digits.push( number & 0xF );
number >>>= 4;
}
var result = '';
for( var i = n_digits - 1; i >= 0; --i )
{
result += this.hex_digits.substr( digits[i], 1 );
}
return result;
}
this.add_class = function( html_elem, classname )
{
var classname_set = html_elem.classList;
if( !classname_set.contains( classname ) )
{
classname_set.toggle( classname );
return true;
}
return false;
}
this.unquoted = function( s )
{
var quote = '"';
var n = s.length;
if( n <= 1 )
{
return s;
}
if( s.substr( 0, 1 ) == quote && s.substr( n - 1, 1 ) == quote )
{
return s.substring( 1, n - 1 );
}
return s;
}
this.local_file_url = function( filespec )
{
with( this )
{
var url = 'file:///' + unquoted( filespec ).replace( /\\/g, '/' );
return url;
}
}
};
</script>
Here's the second JavaScript module:
<!-- Namespace windows.wsh
Windows Script Host (shell functionality only). -->
<script type="text/javascript">
var windows = windows || {};
windows.wsh = new function()
{
this.shell = new ActiveXObject( 'WScript.Shell' );
this.sleep = function( millisecs )
{
with( this )
{
var nowindow = 0;
var wait = true;
shell.Run( 'ping 1.1.1.1 -n 1 -w ' + millisecs, nowindow, wait );
}
};
this.is_running = function( wsh_execution )
{
return (wsh_execution.Status == 0);
};
this.run_hidden = function( command )
{
var hidden_window = 0;
var wait_for_completion = true;
with( this )
{
return shell.Run( command, hidden_window, wait_for_completion );
}
}
};
</script>
Here's the third JavaScript module:
<!-- Namespace windows.fs
File System Object (part of Window's script support). -->
<script type="text/javascript">
var windows = windows || {};
windows.fs = new function()
{
this.fso = new ActiveXObject( "Scripting.FileSystemObject" );
this.tempfolder = this.fso.GetSpecialFolder( 2 );
this.tempfolder_path = this.tempfolder.Path;
this.open_for_reading = function( textfile_spec )
{
var for_reading = 1;
var do_not_create = false;
var ascii_encoding = 0;
var utf16_encoding = -1;
var default_encoding = -2;
with( this )
{
return fso.OpenTextFile(
textfile_spec,
for_reading, do_not_create, default_encoding
);
}
}
this.joined_paths = function( folder_path, filename )
{
with( this ) return fso.BuildPath( folder_path, filename );
}
this.temp_filename = function()
{
with( this ) return fso.GetTempName();
}
this.temp_filepath = function()
{
with( this ) return joined_paths( tempfolder_path, temp_filename() );
}
this.quoted = function( path )
{
var quote = '"';
var is_quoted = (path.length > 0 && path.substr( 0, 1 ) == quote);
return (is_quoted? path : quote + path + quote);
}
};
</script>
Here's the fourth JavaScript module:
<!-- Namespace windows.process_info
Windows process information. -->
<script type="text/javascript">
var windows = windows || {};
windows.process_info = new function()
{
var pg = {}; // "private globals" namespace, to make that explicit.
pg.Record = function()
{
this._add_item = function( spec )
{
i_delimiter = spec.indexOf( '=' );
if( i_delimiter != -1 )
{
var property_name = spec.substring( 0, i_delimiter );
var value = spec.substr( i_delimiter + 1 );
this[property_name] = value;
}
}
};
this.new_records = function()
{
var filepath = windows.fs.temp_filepath();
var exitcode = windows.wsh.run_hidden(
'cmd /c wmic process list full >' + windows.fs.quoted( filepath )
);
if( exitcode != 0 )
{
return null; // TODO: exception
}
var records = new Array();
var current_record = null;
var f = windows.fs.open_for_reading( filepath );
while( !f.AtEndOfStream )
{
var line = f.ReadLine();
var i_end = line.length - 1;
while( i_end >= 0 && line.substr( i_end, 1 ) < ' ' )
{
--i_end;
}
if( 0 <= i_end && i_end < line.length - 1 )
{
line = line.substr( 0, i_end + 1 );
}
if( js_util.is_whitespace( line ) )
{
if( current_record != null )
{
records.push( current_record );
current_record = null;
}
}
else // line.length > 0
{
if( current_record == null )
{
current_record = new pg.Record();
}
current_record._add_item( line );
}
}
// Complete a possible last record.
if( current_record != null )
{
records.push( current_record );
}
f.Close();
windows.fs.fso.DeleteFile( filepath );
return records;
};
};
</script>
When I try to post the fifth and main JavaScript module, I get an error about exceeding the max length. So that module plus the main HTML body is missing here. Consult the PasteBin posting for a complete version that can be tried out – which I believe is a practical necessity for gaining a good understanding of code.
*Single file: the idea is to provide a simple text only i/o host environment for learning programming, where one simply drags the javascript source onto the HTA file. And for beginners I think it's decidedly an advantage to have the host environment as a single file, with no special installation issues etc.