Статьи

Добавьте веб-консоль на панель инструментов, часть 1

Консоль — это программный артефакт, предназначенный для считывания строкового текстового ввода с клавиатуры и вывода строкового текстового вывода на экран. Консоли часто используются для реализации интерфейсов командной строки операционной системы, но также удобны в текстовых приключенческих играх и других контекстах.

Хотя текстовые ориентированные консоли не так популярны, как раньше, из-за распространения графических пользовательских интерфейсов, они могут быть полезны для опытных пользователей , которых не пугает этот стиль интерфейса. Кроме того, консоли могут открыть новый класс веб-приложений, таких как встроенная оболочка браузера.

Эта статья начинает серию из двух частей, в которой представлена ​​консольная библиотека на основе 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 типа DOM double .
                                  • report_error(error) вызывается (при сбое) с аргументом PositionError который хранит причину сбоя через своего члена message типа DOM DOMString и его члена code типа DOM unsigned 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 .