Консоль — это программный артефакт, предназначенный для считывания строкового текстового ввода с клавиатуры и вывода строкового текстового вывода на экран. Консоли часто используются для реализации интерфейсов командной строки операционной системы, но также удобны в текстовых приключенческих играх и других контекстах.
Хотя текстовые ориентированные консоли не так популярны, как раньше, из-за распространения графических пользовательских интерфейсов, они могут быть полезны для опытных пользователей , которых не пугает этот стиль интерфейса. Кроме того, консоли могут открыть новый класс веб-приложений, таких как встроенная оболочка браузера.
Эта статья начинает серию из двух частей, в которой представлена консольная библиотека на основе JavaScript для использования с веб-приложениями, которые могут извлечь выгоду из этого стиля пользовательского интерфейса. Часть 1 знакомит вас с простым API библиотеки, а также с приложением оболочки браузера, которое служит полезной демонстрацией этого API. Во второй части показано, как реализована библиотека, чтобы вы могли изменить ее в соответствии с дополнительными требованиями.
Исследуйте консольную библиотеку
Библиотека консоли состоит из глобального объекта Console
с несколькими свойствами. Такое расположение минимизирует загрязнение глобального пространства имен. Кроме того, это отражает мое желание избежать поддержки нескольких консолей, так как мне проще реализовать одноканальную консоль.
Console
предоставляет следующие функции:
- простая инициализация на основе количества нужных строк и столбцов (
<canvas>
требует только атрибутаid
)
- холст размещается в порядке табуляции и сразу получает фокус клавиатуры для браузеров, таких как Firefox
- очистить консоль
- зеленый на черном тексте с моноширинным шрифтом
- видимый курсор, который отмечает текущую позицию ввода
- возможность отображения текста
- вертикальная прокрутка, когда текст перемещается за нижнюю правую позицию символа
- упрощенное редактирование с точки зрения клавиши возврата
- автоматически вызывать функцию, когда вход недоступен
- поддерживает FireFox, Internet Explorer, Chrome, Opera и Safari
Хотя Console
инкапсулирует несколько доступных свойств, я считаю, что только четыре из них являются членами «открытого» API. Другие свойства не должны быть доступны; они существуют для поддержки следующих четырех свойств и могут измениться в следующей версии библиотеки:
-
init(canvasName, numCols, numRows)
инициализирует консоль. Строка, передаваемая вcanvasName
должна соответствовать значению атрибутаid
существующего элемента<canvas>
. Целое число, переданное вnumCols
определяет желаемое количество столбцов (например, 80), а целое число, переданное вnumRows
определяет желаемое количество строк (например, 25). Консоль очищается и позиция курсора устанавливается (0, 0). Полученная консоль отображает зеленый текст на черном фоне. Эта функция не возвращает значение.
-
clear()
очищает консоль и устанавливает позицию курсора в (0, 0). Эта функция не возвращает значение.
-
getLine(callback)
возвращает строку ввода иgetLine(callback)
ее на консоль. Сначала он проверяет, была ли введена строка, отмечая, присутствует ли во вводе символ новой строки (указанный пользователем, нажав клавишу с надписью Enter или Return). Если это так, строка возвращается без символа новой строки. Если нет новой строки или нет ввода, эта функция возвращает ноль. Когда функция передается вcallback
, эта функция вызывается, когда ничего не было введено.
-
echo(msg)
выводит строку, переданную вmsg
на консоль, начиная с позиции курсора, которая обновляется. Консоль прокручивается вертикально, когда сообщение проходит через правый нижний угол. Эта функция распознает специальные символыb
(backspace) иn
(перевод строки). Кроме того, он не возвращает значение.
Функция getLine(callback)
не блокирует текущий поток, ожидая, когда пользователь getLine(callback)
Enter / Return. Вместо этого он возвращается немедленно. Это происходит потому, что код JavaScript выполняется в одном потоке. (Веб-работники HTML5 являются исключением и выходят за рамки этой статьи.) Если блокировать этот поток дольше, чем то, что браузер считает приемлемым, браузер отображает диалоговое окно с сообщением о не отвечающем скрипте.
Библиотека консоли проста в использовании. После определения элемента <canvas>
и после инициализации и вывода любого предварительного текста в консоль, повторно выполняйте функцию с помощью функции JavaScript setInterval()
. Каждое выполнение должно вызывать getLine(callback)
(с необязательной функцией обратного вызова), а затем предпринимать соответствующие действия на основе возвращаемого значения getLine()
. В листинге 1 представлен HTML-код для простой демонстрации этой библиотеки.
<HTML> <Голова> <Название> Консоль Демо </ Title> <meta http-эквивалент = "X-UA-совместимый" контент = "IE = Edge" /> <script src = "../ Console / Console.js"> </ Скрипт> </ HEAD> <body style = "text-align: center"> <Р> <H2> Консоль Демо </ H2> <canvas id = "mycanvas"> Элемент HTML5 canvas не поддерживается этим браузером. </ Холст> <Р> Возможно, вам придется нажать клавишу Tab или щелкнуть на холсте, чтобы сфокусировать его на клавиатуре. </ Р> <Скрипт> Console.init ("mycanvas", 64, 16); Console.echo ( ">"); функция галочка () { var line = Console.getLine (); если (строка! = ноль) { if (line! = "") Console.echo (линия + "п"); Console.echo ( ">"); } } setInterval ("tick ()", 50); // Вызывать tick () каждые 50 миллисекунд. </ Скрипт> </ Body> </ Html>
Листинг 1: Вывод введенного текста в консоль
В листинге 1 описывается ConsoleDemo.html
. Этот список довольно прост, за исключением, возможно, элемента <meta>
. Этот элемент обеспечивает режим совместимости — используйте режим отображения последних стандартов — так, чтобы консоль работала в Internet Explorer 9 (и, возможно, более поздних версиях этого браузера). В противном случае Explorer выводит сообщение об ошибке о том, что функция getContext()
API Canvas не определена.
В листинге 1 продолжается элемент <script>
который включает в себя содержимое исходного файла JavaScript с именем Console.js
. Этот файл определяет библиотеку консоли и находится в каталоге Console
, к которому осуществляется доступ относительно ConsoleDemo.html
. Файл кода, прилагаемый к этой статье, содержит ConsoleDemo.html
и Console.js
в соответствующих каталогах относительно друг друга, поэтому вы сможете без проблем запустить ConsoleDemo
.
В теле этого HTML-файла указан элемент <canvas>
, атрибуту id
которого назначен mycanvas
. Никаких других атрибутов не требуется, потому что консольная библиотека заботится о них. Тело также содержит элемент <script>
который представляет демонстрационный код консоли.
Сначала код инициализирует холст областью рисования 64 на 16 строк — я выбрал эти значения, потому что они были размерами текстового экрана на моем старом микрокомпьютере TRS-80 Model III. Затем код выводит символ >
на консоль в качестве подсказки начальной строки ввода.
На этом этапе функция с именем tick()
определена для повторного выполнения. Эта функция будет выполняться каждые 50 миллисекунд благодаря вызову функции setInterval("tick()", 50)
. Каждый вызов пытается получить и вывести обратно на консоль строку ввода.
tick()
сначала вызывает getLine()
без передачи функции обратного вызова, потому что в этом примере ничего не нужно. Если эта функция возвращает ноль, потому что ничего не было введено, или пользователь вводит какой-то ввод (и еще не нажал Enter / Return), больше ничего не происходит. В противном случае, если возвращаемая строка не равна пустой строке (была нажата только Enter / Return), введенный текст, за которым следует новая строка, выводится на консоль. На этом этапе появляется запрос >
чтобы сообщить пользователю, что ожидается другая строка ввода.
На рисунке 1 показана полученная консоль в контексте Firefox.
Рисунок 1: Вам не нужно нажимать клавишу Tab, чтобы начать использовать консоль в Firefox.
Обнаружить оболочку браузера
Оболочка обеспечивает пользовательский интерфейс операционной системы, и ее основное назначение — запуск программ. Современные операционные системы имеют графические оболочки, но многие также имеют традиционные оболочки, ориентированные на командную строку (например, оболочки Unix Korn и Bourne). Подобная оболочка может быть встроена в веб-страницу через консольную библиотеку, и эта оболочка браузера может использоваться для выполнения ориентированных на браузер команд. Я создал приложение оболочки браузера в качестве полезной демонстрации консольной библиотеки. На рисунке 2 показана консоль этого приложения в контексте браузера Internet Explorer 9.
Рисунок 2: Оболочка браузера в настоящее время поддерживает четыре команды.
На рисунке 2 показана интересная аномалия: информация о геолокации отображается не сразу. Вместо этого данные о широте и долготе часто отображаются несколькими строками позже в браузере. Вы узнаете причину, изучая листинг 2.
<HTML> <Голова> <Название> Оболочка браузера </ Title> <meta http-эквивалент = "X-UA-совместимый" контент = "IE = Edge" /> <script src = "../ Console / Console.js"> </ Скрипт> </ HEAD> <body style = "text-align: center"> <Р> <H2> Оболочка браузера </ H2> <canvas id = "mycanvas"> Элемент HTML5 canvas не поддерживается этим браузером. </ Холст> <Р> Возможно, вам придется нажать клавишу Tab или щелкнуть на холсте, чтобы сфокусировать его на клавиатуре. </ Р> <Скрипт> Console.init ("mycanvas", 64, 22); Console.echo ("Оболочка браузера 1.0nn"); Console.echo («Введите help (без кавычек) для получения helpnn»); Console.echo ( ">"); var geo = ""; функция обратного вызова () { if (geo == "") возвращение; Console.echo (гео + "п"); Console.echo ( ">"); geo = ""; } функция галочка () { var line = Console.getLine (callback); если (строка! = ноль) { line = line.trim (); if (line == "browser") Console.echo (навигатор. UserAgent + "nn"); иначе if (line == "cls") Console.clear (); else if (line == "geo") {Console.echo ("запрос информации о местоположении ... может занять несколько мгновенийnn"); function report_error (error) {geo = error.message; if (geo == "") // geo is "" в Safari geo = "неизвестная ошибка"; } function report_geolocation_query ( position) {geo = "Lat:" + position.coords.latitude + ", Lon:" + position.coords.latitude; } navigator.geolocation. getCurrentPosition (Отчет_ geolocation_query, report_error); } else if (line == "help") {Console.echo ("Доступные команды ... n"); Console.echo («браузер - отображать текущую информацию браузера»); Console.echo ("cls - clear screenn"); Console.echo («гео - получить информацию о геолокации»); Console.echo ("help - показать эту справку textnn"); } else if (line! = "") Console.echo ("плохая командаn"); Console.echo ( ">"); }} setInterval ("tick ()", 50); // Вызывать tick () каждые 50 миллисекунд. </ script> </ body> </ html>
Листинг 2: Интерпретация и выполнение команд
В листинге 2 представлен BrowserShell.html
. Этот листинг похож на листинг 1 и должен быть довольно простым для понимания. После инициализации и вывода предварительного текста на консоль, функция tick()
многократно выполняется, чтобы получить следующую строку ввода, обрезать пробелы с обоих концов, проверить одну из четырех возможных команд и выполнить команду. Если введена bad command
, bad command
отображается на консоли. В любом случае, пользователю предлагается ввести следующую команду.
Команда geo
является наиболее сложной для реализации. Он получает информацию о геолокации о пользователе через API геолокации , который является асинхронным, чтобы избежать блокировки потока JavaScript. navigator.geolocation. getCurrentPosition(report_ geolocation_query, report_error)
navigator.geolocation. getCurrentPosition(report_ geolocation_query, report_error)
запрашивает у пользователя разрешение на получение информации о геолокации, переходит к получению этой информации, когда пользователь принимает, а затем вызывает одну из двух функций обратного вызова:
-
report_geolocation_query( position)
вызывается (в случае успеха) с аргументомPosition
который хранит данные геолокации через свой элементCoordinates
типаCoordinates
объектной модели документа. Этот интерфейс DOM включает в себя поляlatitude
иlongitude
типа DOMdouble
.
-
report_error(error)
вызывается (при сбое) с аргументомPositionError
который хранит причину сбоя через своего членаmessage
типа DOMDOMString
и его членаcode
типа DOMunsigned short
.
Каждый из этих обратных вызовов извлекает информацию из своего переданного аргумента и создает строку, которую он присваивает geo
переменной. Во время тестирования в Safari я обнаружил, что этот браузер не позволяет мне получать информацию о геолокации. Кроме того, он назначил пустую строку message
. Чтобы report_error(error)
эту ситуацию, я кодировал report_error(error)
чтобы присвоить сообщению "unknown error"
. (Я мог бы вывести сообщение на основе error.code
, значение которого было 2 — позиция недоступна. Я оставляю это изменение с вами в качестве упражнения.)
В листинге 2 объявляется функция callback()
которую она передает в качестве аргумента getLine(callback)
. Эта функция вызывается каждый раз, когда getLine(callback)
обнаруживает отсутствие ввода. После проверки того, что что-то назначено для geo
, callback()
отображает значение этой переменной, после чего в консоли выводится приглашение >
, а затем присваивает этой переменной пустую строку (чтобы избежать повторного вывода значения geo
).
Почему я не report_geolocation_query( position)
значение report_geolocation_query( position)
в report_geolocation_query( position)
и report_error(error)
(и тогда мне не понадобится geo
но я мог бы использовать локальную переменную) вместо того, чтобы идти к проблеме передачи функции обратного вызова в getLine(callback)
? Если бы я это сделал, эти навигационные данные могли быть выведены в процессе ввода команды, что приводило к путанице. Например, при вводе help
я мог бы получить следующий смешанный вывод:
> helLat: 49,88, Lon: 49,88 > р
Вывод
Консоль — полезный инструмент для встраивания простой консоли в веб-страницы. Предыдущее приложение оболочки браузера дает вам представление о том, что возможно. Возможно, вы захотите расширить это приложение дополнительными командами, такими как команда dir
для получения списка каталогов веб-хранилища . Однако сначала вы должны понять, как работает эта библиотека, и это тема части 2.
Заметка |
---|
Все файлы, относящиеся к этой статье, находятся в code.zip . |