Category: компьютеры

Category was added automatically. Read all entries about "компьютеры".

Браузер: настройка загрузки файлов

Читаю сейчас подраздел 2.3 «Blob» третьей части учебника по JavaScript. Нахожу в нем очень много нового для себя. В частности, возник вопрос: как в браузере можно настраивать загрузку файлов?

Я пользуюсь браузером «Microsoft Edge» на движке «Chromium», поэтому далее буду излагать этот вопрос на примере именно этого браузера. (Для других браузеров, построенных на этом же движке [например, для того же «Google Chrome»], думаю, настройки должны быть примерно такими же.) Кроме этого, наверное, стоит отметить, что у меня на компьютере установлена операционная система «Windows 10 Pro».

Настройки браузера я могу открыть в открытом окне браузера с помощью комбинации клавиш «Alt+F» или с помощью кнопки с многоточием в правом верхнем углу окна браузера. В меню этих настроек можно найти и нажать пункт «Downloads» (по-русски «Загрузки»), а еще этот пункт можно вызывать с помощью комбинации клавиш «Ctrl+J». Еще этот пункт можно вызвать с помощью кнопки со стрелкой вниз на панели инструментов браузера, но ее там может и не быть (наличие или отсутствие этой кнопки на панели инструментов браузера тоже может быть настроено).

После открытия пункта «Downloads» появится небольшое окошко, основную часть которого занимает список загруженных (и загружаемых) файлов. Это окошко может открываться само при попытке загрузить файл (но может и не открываться, это тоже настраивается).

В верхней части этого окошка есть заголовок «Downloads», нажав на который можно открыть отдельную вкладку в браузере с тем же списком загруженных (и загружаемых) файлов, но в отдельной вкладке браузера с этим списком работать удобнее. Также эту отдельную вкладку можно открыть в браузере, написав в адресной строке следующее:
edge://downloads

Из окошка (или вкладки браузера) «Downloads» можно установить, какие файлы были загружены (загружаются в данный момент) и куда они были сохранены (сохраняются в данный момент).

Также из этого окошка можно открыть папку, в которую по умолчанию загружаются файлы (эту папку можно заменить на другую, это тоже настраивается). Причем можно открыть данную папку так, чтобы курсор уже стоял на указанном в списке загруженных (загружаемых) файле (если файлов в папке много, это очень полезно).

Список загруженных (загружаемых) файлов в любой момент можно очистить (это не удалит сами загруженные файлы). Это называется «Clear all download history» (по-русски «Стереть историю загрузок»).

Настройки загрузки файлов можно открыть из окошка «Downloads», нажав на кнопку с многоточием в этом окошке (эта кнопка называется «More options» или по-русски «Дополнительные опции»). Также эту кнопку можно нажать в описанной ранее вкладке «Downloads» браузера. В открывшемся меню следует выбрать пункт «Downloads settings» (по-русски «Настройки загрузок»). При выборе этого пункта меню откроется отдельная вкладка браузера с настройками. Еще эту вкладку браузера можно открыть в браузере, написав в адресной строке следующее:
edge://settings/downloads

Четвертый способ открыть вкладку браузера с этими настройками — открыть, собственно, настройки браузера (это тоже можно сделать несколькими способами). Откроется отдельная вкладка браузера с адресом:
edge://settings
И уже на этой вкладке выбрать в меню слева пункт «Downloads». Откроется та же самая вкладка браузера с настройками загрузок, описанная выше.

На вкладке браузера с настройкой загрузок файлов есть на сегодня (браузеры постоянно находятся в разработке, поэтому всё описанное здесь может в любой момент устареть) четыре пункта:

1) «Location» (по-русски «Папка по умолчанию, в которую загружаются файлы»). Тут можно изменить папку, в которую по умолчанию загружаются файлы;

2) «Ask me what to do with each download» (по-русски «Спрашивать меня, что делать с каждой загрузкой»). Если эта опция включена, при начале загрузки каждого файла браузер откроет окошко загрузок, а в нем выведет вопрос, что делать с данным файлом.

Тут можно отказаться от загрузки файла, нажав крестик в правом верхнем углу окна вопроса. Либо можно выбрать пункт «Open» (по-русски «Открыть»), в этом случае браузер загрузит файл, сохранит его в своей служебной папке и сразу же откроет этот файл соответствующей программой. Либо можно выбрать пункт «Save as» (по-русски «Сохранить как»), тогда браузер выведет окно, в котором можно будет выбрать папку для загрузки и хранения данного файла. Либо можно выбрать пункт «Save» (по-русски «Сохранить»), тогда браузер загрузит данный файл и сохранит его в папку по умолчанию из вышеописанного пункта «Location».

Если эта опция отключена, то браузер будет загружать файлы в папку по умолчанию из вышеописанного пункта «Location».

3) «Open Office files in the browser» (по-русски «Автоматически открывать офисные файлы в браузере, а не скачивать их в папку»). Под офисными файлами, как я понимаю, подразумеваются файлы, созданные для офисного пакета приложений «Microsoft Office» (таблицы, презентации, документы и так далее).

4) «Show downloads menu when a download starts» (по-русски «Открывать окошко «Downloads» при начале загрузки файла»). У меня эта опция включена, так как я хочу сразу знать, если браузер начнет загружать какой-либо файл на мой компьютер.

Выводы. Программист может на какой-либо HTML-странице с помощью скрипта на языке JavaScript (или с помощью конструкций на языке HTML) дать возможность пользователю запустить загрузку какого-либо файла к себе на компьютер, либо даже запустить загрузку какого-либо файла на компьютер пользователя без отмашки пользователя.

При этом браузер может либо вообще никак не показать пользователю, что началась загрузка некоего файла на его компьютер, либо браузер может сообщить об этом пользователю: всё зависит от настройки браузера.

Адаптация HTML-страницы для мобильника 2

Начало:
1. Инструмент разработчика Issues в браузере
2. Настройка веб-сервера из набора IIS, web.config, заголовки HTTP

Продолжаю разбирать замечания инструмента разработчика «Issues» браузера (у меня — «Microsoft Edge» на движке «Chromium») к моей тестовой HTML-странице.

Замечание, которое помечено как «ошибка» (по-английски «Error»):

A 'viewport' meta element was not specified.


Мне эта тема уже знакома, я три года назад писал пост по этому поводу, в котором разбирался, как говорится, «на пальцах»:

Адаптация HTML-страницы для мобильника

Там я подходил к этому вопросу, ориентируясь на руководства от компании «Google», касающиеся оптимизации сайта для мобильных устройств, онлайн-проверки оптимизации сайта под мобильник, адаптивного дизайна. Те ссылки и сейчас остаются актуальными.

Инструмент разработчика «Issues» браузера посылает читать несколько в другом направлении:

https://webhint.io/docs/user-guide/hints/hint-meta-viewport/
(Статья «Correct Viewport»)

https://developer.mozilla.org/en-US/docs/Web/HTML/Viewport_meta_tag
(Статья «Using the viewport meta tag to control layout on mobile browsers»)

Посмотреть, как HTML-страница будет выглядеть на мобильном устройстве, можно в любом браузере на движке «Chromium», открыв нужную HTML-страницу и вызвав для нее панель инструментов разработчика (F12). Там в левом верхнем углу есть кнопка (вторая слева), которая называется «Toggle device emulation». С ее помощью можно переключиться на эмуляцию мобильного устройства и обратно, в режим настольного компьютера.

Как я и описывал три года назад, без определения соответствующего HTML-элемента meta с атрибутом name="viewport" HTML-страница, которая хорошо выглядит на дисплее настольного компьютера, на экране мобильника будет показана так, что текст HTML-страницы будет выглядеть очень мелко и его почти невозможно будет разобрать. Начинать решать эту проблему все известные мне источники предлагают с вставки следующего HTML-элемента в заголовочную часть HTML-страницы:
<meta name="viewport" content="width=device-width, initial-scale=1.0">

Этот метод подойдет для многих HTML-страниц. Для более сложных случаев нужно читать вышеупомянутые статьи и разбираться с адаптивным дизайном (википедия).

Вставка этого HTML-элемента избавляет от вышеупомянутого замечания инструмента разработчика «Issues» браузера.

Настройка веб-сервера из набора IIS, web.config, заголовки HTTP

Я уже писал несколько постов про то, как начал пользоваться (и пользуюсь до сих пор) локальным веб-сервером (как я понимаю, он может быть не только локальным) из набора серверов «IIS»:

1. JavaScript: локальный веб-сервер из набора IIS
2. JavaScript: локальный веб-сервер и кэш браузера
3. JavaScript: локальный веб-сервер и favicon.ico

Напомню, «IIS» (расшифровывается как «Internet Information Services») — это набор серверов для нескольких служб Интернета от компании «Microsoft». Набор серверов «IIS» включен в состав операционной системы «Windows 10 Pro», которая установлена на моём компьютере. Поэтому, собственно, я и стал пользоваться веб-сервером из этого набора. (Актуальная версия «IIS» — 10.0) Тут подробнее:

https://ru.wikipedia.org/wiki/Internet_Information_Services
https://docs.microsoft.com/en-gb/iis (документация на английском)

В предыдущем посте я писал, как начал пользоваться инструментом разработчика «Issues» в браузере «Microsoft Edge» на движке «Chromium».

И этот самый инструмент «Issues» выдал мне по поводу моей тестовой HTML-страницы следующее предупреждение (по-английски «Warning»):

'content-type' header charset value should be 'utf-8'


Вернее, он выдал мне три таких предупреждения — одно по поводу моей HTML-страницы index.html, а еще два — по поводу двух файлов, подключенных к моей HTML-странице — файла style.css с определениями стилей на языке CSS и файла myscript.js со скриптом на языке JavaScript.

О чем идет речь в предупреждении? Обратим внимание на слово «header» (по-русски «заголовок») в тексте предупреждения. Что это за заголовок? Как оказалось, речь тут идет про так называемые «заголовки HTTP»:

https://ru.wikipedia.org/wiki/Заголовки_HTTP
https://developer.mozilla.org/ru/docs/Web/HTTP/Headers

Казалось бы, для HTML-страницы заголовки HTTP можно настраивать с помощью HTML-элемента meta (об этом сказано на вышеуказанной странице википедии). Например, в данном случае на первый взгляд кажется, что нужно вставить в заголовочную часть HTML-страницы следующее:
<meta http-equiv="content-type" content="text/html; charset=utf-8">

Однако, это в моём браузере не работает (кодировку HTML-страницы указывает, но на заголовок HTTP, отсылаемый веб-сервером из набора «IIS», не влияет). Почему? Во-первых, значение "content-type" атрибута http-equiv HTML-элемента meta считается устаревшим (об этом сказано, например, тут), вместо этого для указания кодировки HTML-страницы рекомендуют использовать следующее:
<meta charset="utf-8">

У меня на тестовой HTML-странице уже указан этот короткий вариант, поэтому дополнительное указание HTML-элемента meta с атрибутом http-equiv="content-type" не требуется (будет считаться дублированием короткого варианта и об этом инструмент разработчика «Issues» браузера выдаст отдельное предупреждение).

Во-вторых (что более важно), как я понимаю (а я не специалист в этом вопросе, можно даже сказать, «чайник») веб-сервер из набора «IIS» вообще не учитывает, что там указано в коде HTML-страницы (возможно, веб-сервер можно как-то настроить, чтобы он учитывал HTML-элементы meta в коде отправляемой HTML-страницы, но я про такое не знаю).

Таким образом, очевидно, что для исправления вышеуказанного предупреждения от инструмента разработчика «Issues» браузера требуется настройка соответствующего заголовка HTTP, формируемого веб-сервером при отправке HTML-страницы (а также при отправке файлов, подключенных к этой HTML-странице).

* * *

Вообще, диалог между веб-сервером и браузером может служить удачной и достаточно простой иллюстрацией работы компьютерных сетей с архитектурой «клиент-сервер». В этом случае веб-сервер, соответственно, выполняет роль «сервера», а браузер выполняет роль «клиента». Оба конца этого диалога (сервер и клиент) являются компьютерными программами. Хотя часто сервером еще называют компьютер, на котором установлена программа (или несколько программ), выполняющая роль «сервера». Это создает некоторую путаницу в головах людей, изучающих компьютерные сети. Подробнее:

https://ru.wikipedia.org/wiki/Клиент_—_сервер

Если интересна эта тема, то, чтобы получить начальное представление о работе компьютерных сетей, я рекомендую прочесть первую главу знаменитой книги Эндрю Таненбаума, про которую у меня есть отдельный пост.

В рассматриваемом здесь случае веб-сервер из набора «IIS» и мой браузер (клиент) находятся на одном и том же моём компьютере, поэтому я здесь часто называю веб-сервер локальным веб-сервером. Это удобно для изучения, потому что оба участника сетевого диалога находятся под моим контролем, доступны для управления и экспериментов.

* * *

Итак, как произвести нужную мне настройку веб-сервера из набора «IIS»? Это можно сделать минимум двумя способами: 1) внести исправления напрямую в файл, в котором хранятся настройки веб-сервера; 2) открыть графический интерфейс веб-сервера и внести изменения в настройки веб-сервера через него, в результате чего эти настройки попадут в тот же файл, что при первом способе. Как я понимаю, результат при использовании любого из этих способов будет одинаковый.

Файлы настроек веб-сервера (как я понял) бывают разными: есть файлы настроек, которые действуют на все файлы, выдаваемые веб-сервером, а есть файлы настроек, которые действуют только на часть файлов, выдаваемых веб-сервером (например, только на файлы одного веб-сайта или на файлы, находящиеся в одном каталоге). Здесь я рассмотрю только последний случай, а именно я рассмотрю файл настроек веб-сервера, который называется web.config. Этот файл настроек действует только на файлы каталога, в котором он находится, в том числе на файлы, находящиеся во вложенных в текущий каталогах. Подробнее:

https://docs.microsoft.com/en-us/iis/manage/managing-your-configuration-settings/delegating-configuration-to-webconfig-files

Что из себя представляет этот файл? Это текстовый файл, в котором с помощью разметки на языке XML описаны настройки веб-сервера. Правила написания этой разметки можно узнать в соответствующем справочнике:

https://docs.microsoft.com/en-us/iis/configuration/

Файлы моего локального веб-сайта находятся в следующем каталоге (я про это рассказывал в отдельном посте):
C:\inetpub\wwwroot\

В этом каталоге изначально нет файла web.config, что значит, что на файлы в этом каталоге распространяются общие настройки веб-сервера.

Я поместил в этот каталог файл web.config со следующим содержанием:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <staticContent>
            <mimeMap fileExtension=".html" mimeType="text/html; charset=utf-8" />
            <mimeMap fileExtension=".css" mimeType="text/css; charset=utf-8" />
            <mimeMap fileExtension=".js" mimeType="application/javascript; charset=utf-8" />
        </staticContent>
    </system.webServer>
</configuration>

Затем открыл в своём браузере адрес, который соответствует указанному выше каталогу:
http://localhost/index.html
и неожиданно получил сообщение об ошибке «HTTP 500.19 — Internal Server Error».

Почему произошла эта ошибка? Дело в том, что в настройках веб-сервера уже есть определения для трех указанных типов файлов (с расширениями .html, .css, .js), а мой файл настроек web.config пытается добавить определения для этих же расширений файлов. Правила описания настроек веб-сервера запрещают определения mimeMap с одинаковыми атрибутами fileExtension.

Я этого не знал, поэтому решил попытаться внести нужные мне настройки через графический интерфейс веб-сервера из набора «IIS». Как открыть этот графический интерфейс? Как обычно, в операционной системе «Windows 10 Pro» это можно сделать кучей способов. Я открываю поиск (либо кликнув по иконке с увеличительным стеклом справа от кнопки «Пуск», либо нажав комбинацию клавиш Win+S) и набираю там «Диспетчер служб IIS», а затем открываю этот самый диспетчер.

В открывшемся окне «Диспетчера служб IIS» слева будет часть окна, озаглавленная «Подключения», и в ней будет отображено дерево подключений. В корне этого дерева у меня находится название моего компьютера. Если корень «развернуть», то там у меня открывается два пункта: «Пулы приложений» и «сайты». Я «развернул» пункт «сайты» и в нем оказался единственный сайт с названием «Default Web Site» (этот сайт, как я понимаю, был создан при включении набора «IIS», которое я описывал в отдельном посте). Это и есть сайт, который соответствует каталогу C:\inetpub\wwwroot\ (по умолчанию).

Я выбрал этот сайт, кликнув на него мышкой. После этого в центральной части окна и в правой части окна доступны возможные действия и настройки.

В центральной части окна диспетчера я кликнул мышкой на пункт «Типы MIME». Центральная часть окна диспетчера сменилась на окно выбранной функции. Но возникла ошибка из-за ошибки в написанном мной (см. выше) файле web.config. Я удалил этот файл и снова открыл пункт «Типы MIME». Теперь в центральной части окна диспетчера (теперь уже без ошибки) открылся большой список разнообразных расширений файлов.

Я нашел в этом списке три нужных мне расширения (.html, .css, .js) и добавил к определению каждого из этих расширений в графе «Тип MIME» текст ; charset=utf-8.

После этого я заглянул в каталог моего сайта C:\inetpub\wwwroot\ и увидел, что там появился файл web.config, по-видимому, созданный диспетчером служб «IIS» в ответ на мои вышеописанные действия. Вот содержимое этого файла (я пометил красным цветом отличия от файла, написанного мной ранее):
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <staticContent>
            <remove fileExtension=".js" />
            <remove fileExtension=".css" />
            <remove fileExtension=".html" />
            <mimeMap fileExtension=".html" mimeType="text/html; charset=utf-8" />
            <mimeMap fileExtension=".css" mimeType="text/css; charset=utf-8" />
            <mimeMap fileExtension=".js" mimeType="application/javascript; charset=utf-8" />
        </staticContent>
    </system.webServer>
</configuration>

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

После этого я снова открыл в браузере адрес http://localhost/index.html и теперь HTML-страница загрузилась без ошибок сервера.

Обсуждаемое предупреждение инструмента разработчика «Issues» исчезло.

Кстати, полученные браузером от веб-сервера заголовки HTTP можно просмотреть в инструменте разработчика «Network», кликнув мышкой на название конкретного полученного от веб-сервера файла в списке полученных файлов. Я там посмотрел и увидел, что в полученных от веб-сервера заголовках HTTP присутствуют изменения, которые я настроил вышеописанным файлом web.config.

В принципе, мой локальный сайт работал корректно и без этих настроек. Поэтому не уверен, что я оставлю эти настройки. Впрочем, я всегда могу их легко откатить, удалив вышеописанный файл web.config из каталога своего веб-сайта. Необходимость этих настроек описана по следующей ссылке:

https://webhint.io/docs/user-guide/hints/hint-content-type/

JavaScript: двигаем элемент стрелками клавиатуры

Решил задачу «Мышь, управляемая клавиатурой» к подразделу 4.2 «Фокусировка: focus/blur» второй части учебника по JavaScript.

Название задачи сначала кажется странным (но вообще задача получилась веселая). Что значит «мышь, управляемая клавиатурой»? Тут путаница: речь идет не о компьютерной мыши (устройстве для взаимодействия с компьютером), а о мыши (мелком животном, грызуне), нарисованной на тестовой HTML-странице. Вот как эта HTML-страница выглядит в моём браузере (картинка):



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

«Мышь» на тестовой HTML-странице представлена HTML-элементом pre с идентификатором mouse, внутри которого средствами ASCII-графики (вики) нарисована мышь.

Задача состоит в том, чтобы написать скрипт на языке JavaScript, который позволит пользователю двигать HTML-элемент (в данном случае — HTML-элемент pre) по экрану компьютера с помощью клавиш со стрелками (вправо, влево, вверх и вниз) на клавиатуре.

На тестовой HTML-странице описаны два стиля на языке CSS для целевого HTML-элемента pre, представляющего мышь:
#mouse {
  display: inline-block;
  cursor: pointer;
  margin: 0;
}

#mouse:focus {
  outline: 1px dashed black;
}

При наведении указателя мыши на «мышь» на тестовой HTML-странице указатель мыши сменит свой вид со стрелки на руку с указующим перстом (указание cursor: pointer;). Это общепринятый способ показать пользователю, что в этом месте HTML-страницы он (пользователь) может воспользоваться дополнительным функционалом (в данном случае — двигать «мышь» клавишами-стрелками с клавиатуры).

«Мышь» на тестовой HTML-странице можно будет (по условиям задачи) двигать клавишами с клавиатуры только после установки фокуса на HTML-элемент pre, представляющий «мышь». При установке на него фокуса этот HTML-элемент будет обведен рамкой (черная прерывистая линия толщиной в 1 пиксель). Это описано с помощью указания outline: 1px dashed black; в соответствующем стиле, приведенном выше.

Код тестовой HTML-страницы можно посмотреть в песочнице. Также есть демонстрационный пример на отдельной странице.

* * *

Приступим к решению задачи. Я открыл тестовую HTML-страницу в своем браузере и попробовал установить фокус на HTML-элемент pre, представляющий мышь. Это у меня не получилось. По умолчанию пользователь не может установить фокус на данный HTML-элемент. Однако, эту возможность можно включить.

По условиям задачи запрещено вносить изменения в код тестовой HTML-страницы на языке HTML или с помощью стилей CSS. Сделаем это в скрипте на языке JavaScript с помощью свойства tabIndex:
let elem = document.getElementById("mouse");
elem.tabIndex = 0;

Теперь на тестовой HTML-странице я могу установить фокус на «мышь» либо кликнув по ней компьютерной мышью, либо с помощью клавиши Tab на клавиатуре. Установка фокуса отображается визуально появлением рамки из черной прерывистой линии толщиной в 1 пиксель, о которой я уже писал выше.

Отмечу два момента. Во-первых, нужно обратить внимание на заглавную букву I в названии свойства tabIndex. Именно так и следует писать в коде, иначе данная инструкция не сработает. А в коде HTML названия свойств можно писать по-разному, как захочется: хоть tabIndex, хоть tabindex и так далее. Названия свойств в HTML регистронезависимы.

Во-вторых, я создал переменную elem, чтобы сделать код более универсальным. Ведь вместо «мыши» нам может понадобиться передвинуть таким же образом любой HTML-элемент с любым рисунком в нем. То есть там может оказаться, скажем, не «мышь», а «кошка» или еще кто-то другой.

Дальше я стал думать, как отловить нажатия клавиш на целевом HTML-элементе. Сначала я подумал, что нужно как-то использовать событие focus или событие click, но потом понял, что можно просто использовать событие keydown на нужном HTML-элементе. Нажатия клавиш по умолчанию будут отлавливаться на HTML-элементе, только если на нем установлен фокус.

Дополним код:
let elem = document.getElementById("mouse");
elem.tabIndex = 0;

elem.addEventListener("keydown", function (event) {
    //...
});

В данном случае функция-обработчик события keydown отлавливает нажатие на любую клавишу клавиатуры. Нам же нужно отловить только нажатия на клавиши-стрелки. Исправим это, дополнив код:
let elem = document.getElementById("mouse");
elem.tabIndex = 0;

elem.addEventListener("keydown", function (event) {
    if (event.code != "ArrowRight" && event.code != "ArrowLeft" &&
        event.code != "ArrowUp" && event.code != "ArrowDown") return;

    //...
});

Такой фильтр пройдут только нажатия на четыре нужные клавиши-стрелки. Теперь осталось лишь реализовать движение целевого HTML-элемента, представляющего «мышь». Я решил включить для данного HTML-элемента абсолютное позиционирование. Движение HTML-элемента будет реализовано изменением координат этого HTML-элемента. HTML-элемент будет двигаться в указанную сторону не попиксельно (это слишком медленно), а сразу на свою ширину (влево или вправо) или на свою высоту (вверх или вниз). Дополним код:
let elem = document.getElementById("mouse");
elem.tabIndex = 0;

elem.addEventListener("keydown", function (event) {
    if (event.code != "ArrowRight" && event.code != "ArrowLeft" &&
        event.code != "ArrowUp" && event.code != "ArrowDown") return;

    let rectElem = elem.getBoundingClientRect();
    let x = rectElem.x + pageXOffset,
        y = rectElem.y + pageYOffset;

    if (event.code == "ArrowRight") x += elem.offsetWidth;
    if (event.code == "ArrowLeft")  x -= elem.offsetWidth;
    if (event.code == "ArrowUp")    y -= elem.offsetHeight;
    if (event.code == "ArrowDown")  y += elem.offsetHeight;
    
    elem.style.position = "absolute";
    elem.style.left = x + "px";
    elem.style.top = y + "px";
});

Этот код уже работает так, как требуется в задаче. Установив на «мышь» фокус, можно двигать ее клавишами-стрелками с клавиатуры. Если фокус с «мыши» убрать, ее нельзя будет двигать клавишами-стрелками с клавиатуры.

Однако, у этого кода есть один недостаток: когда «мышь» добегает до правой границы области просмотра браузера и заходит за нее, появляется горизонтальная полоса прокрутки. Если «мышь» добегает до нижней границы области просмотра браузера и заходит за нее, появляется вертикальная полоса прокрутки. На демонстрационной странице от авторов задачи такого не происходит.

Чтобы избавиться от этого эффекта, я решил запретить прокрутку на тестовой HTML-странице. Дополним код (я отметил изменение красным цветом):
let elem = document.getElementById("mouse");
elem.tabIndex = 0;
document.body.style.overflow = "hidden";

elem.addEventListener("keydown", function (event) {
    if (event.code != "ArrowRight" && event.code != "ArrowLeft" &&
        event.code != "ArrowUp" && event.code != "ArrowDown") return;

    let rectElem = elem.getBoundingClientRect();
    let x = rectElem.x + pageXOffset,
        y = rectElem.y + pageYOffset;

    if (event.code == "ArrowRight") x += elem.offsetWidth;
    if (event.code == "ArrowLeft")  x -= elem.offsetWidth;
    if (event.code == "ArrowUp")    y -= elem.offsetHeight;
    if (event.code == "ArrowDown")  y += elem.offsetHeight;
    
    elem.style.position = "absolute";
    elem.style.left = x + "px";
    elem.style.top = y + "px";
});

Это окончательный вариант скрипта. Теперь «мышь» просто забегает за границу области просмотра и исчезает из области видимости. Но ее можно вернуть обратно.

В прошлом веке, кстати, такими простыми методами и делали игры.

Мяу:
                   /)
          /\___/\ ((
          \`@_@'/  ))
          {_:Y:.}_//
----------{_}^-'{_}----------

Источник ASCII-картинки: https://www.asciiart.eu/animals/cats

JavaScript: одновременное нажатие клавиш

Разбираю своё решение задачи «Отследить одновременное нажатие» к подразделу 3.4 «Клавиатура: keydown и keyup» второй части учебника по JavaScript.

Требуется написать функцию с названием runOnKeys. В постановке задачи сказано, что она должна запускать другую функцию (переданную ей в первом параметре func) при одновременном нажатии на клавиатуре нескольких клавиш (предполагается, что их количество может быть любым) с кодами, переданными ей в параметрах, начиная со второго. Приведен пример вызова этой функции:
runOnKeys(
  () => alert("Привет!"),
  "KeyQ",
  "KeyW"
);

Видимо, авторы задачи запутались в формулировке постановки задачи. На самом деле, функция runOnKeys будет запускаться на HTML-странице, но она не будет запускать переданную ей в первом параметре функцию func. Я это понял, когда обдумывал способы решения этой задачи.

Запуск функции runOnKeys должен придавать HTML-странице способность выполнять функцию func при одновременном нажатии заданных клавиш на клавиатуре. Собственно, запуск функции func будет производить пользователь, одновременно нажав на заданные клавиши на клавиатуре.

Как функция runOnKeys придаст HTML-странице (document) эту способность? Она должна повесить соответствующую функцию-обработчик на какие-то события, которые произойдут на HTML-странице. Так как одновременное нажатие на несколько клавиш на клавиатуре вызовет событие keydown, значит, функцию-обработчик следует вешать именно на это событие. Пишем код:
function runOnKeys() {

    // вешаем функцию-обработчик на событие "keydown" на HTML-странице
    document.addEventListener("keydown", function (event) {
        //...
    });

}

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

Когда мы сможем понять, что последовательность одновременного нажатия клавиш окончилась? Когда пользователь начнет отпускать клавиши, то есть при генерации первого события keyup после одновременного нажатия клавиш. Значит, нам нужно отслеживать и отпускание клавиш, то есть повесить функцию-обработчик на событие keyup. Дополним код:
function runOnKeys() {

    // вешаем функцию-обработчик на событие "keydown" на HTML-странице
    document.addEventListener("keydown", function (event) {
        //...
    });

    // вешаем функцию-обработчик на событие "keyup" на HTML-странице
    document.addEventListener("keyup", function (event) {
        //...
    });

}

Мы можем при событии keydown запоминать нажатые клавиши, а при событии keyup обработать их. Для запоминания одновременно нажатых клавиш я решил использовать массив. Дополним код:
function runOnKeys() {

    let arrChars = [];                    // массив одновременно нажатых клавиш

    document.addEventListener("keydown", function (event) {
        arrChars.push(event.code);        // запоминаем код нажатой и пока еще не отпущенной клавиши
    });

    document.addEventListener("keyup", function (event) {
        if (arrChars.length == 0) return; // нечего обрабатывать, завершаем функцию

        // ...

        arrChars.length = 0;              // очистим массив одновременно нажатых клавиш
    });

}

Событий keyup после отпускания одновременно нажатых клавиш будет сгенерировано столько же, сколько было отпущенных клавиш. Обработку одновременного нажатия клавиш мы запустим при первом событии keyup, после чего очистим массив одновременно нажатых клавиш. Последующие события keyup после первого проигнорируем с помощью инструкции if (arrChars.length == 0) return;.

Я потестировал полученный код в браузере, отслеживая состояние массива одновременно нажатых клавиш с помощью инструкции console.log(arrChars);, и заметил, что при достаточно продолжительном нажатии клавиш генерируется повторное событие keydown, из-за чего в массиве одновременно нажатых клавиш некоторые клавиши многократно дублируются (этот момент был отмечен и в обсуждаемом учебнике). Эти повторы можно отбросить. Дополним код (я отметил изменения красным цветом):
function runOnKeys() {

    let arrChars = [];                    // массив одновременно нажатых клавиш

    document.addEventListener("keydown", function (event) {
        if (event.repeat) return;         // повторы не обрабатываем
        arrChars.push(event.code);        // запоминаем код нажатой и пока еще не отпущенной клавиши
    });

    document.addEventListener("keyup", function (event) {
        if (arrChars.length == 0) return; // нечего обрабатывать, завершаем функцию

        // ...

        arrChars.length = 0;              // очистим массив одновременно нажатых клавиш
    });

}

Осталось написать обработку одновременного нажатия клавиш. От нас требуется при одновременном нажатии заданных клавиш запустить заданный код. До сих пор я не рассматривал параметры нашей функции runOnKeys. Первым параметром с названием func, очевидно, будет заданный код. Чтобы прописать для функции runOnKeys множество параметров, начиная со второго, задающих определенную последовательность одновременно нажатых клавиш, мне пришлось вернуться к первой части обсуждаемого учебника и повторить подраздел 6.2 «Остаточные параметры и оператор расширения». Множество параметров с точно не определенным их количеством можно задать с помощью так называемых «остаточных параметров», используя многоточие. Дополним код (я отметил изменения красным цветом):
function runOnKeys(func, ...args) {

    let arrChars = [];                    // массив одновременно нажатых клавиш

    document.addEventListener("keydown", function (event) {
        if (event.repeat) return;         // повторы не обрабатываем
        arrChars.push(event.code);        // запоминаем код нажатой и пока еще не отпущенной клавиши
    });

    document.addEventListener("keyup", function (event) {
        if (arrChars.length == 0) return; // нечего обрабатывать, завершаем функцию

        // ...

        arrChars.length = 0;              // очистим массив одновременно нажатых клавиш
    });

}

Теперь нам нужно проверить, есть ли заданные клавиши среди одновременно нажатых. И, если заданные клавиши есть среди одновременно нажатых, запустим заданный код func. Дополним код (я отметил изменения красным цветом):
function runOnKeys(func, ...args) {

    let arrChars = [];                    // массив одновременно нажатых клавиш

    document.addEventListener("keydown", function (event) {
        if (event.repeat) return;         // повторы не обрабатываем
        arrChars.push(event.code);        // запоминаем код нажатой и пока еще не отпущенной клавиши
    });

    document.addEventListener("keyup", function (event) {
        if (arrChars.length == 0) return; // нечего обрабатывать, завершаем функцию

        let runFunc = true;
        for (let arg of args) {           // нажаты ли одновременно отслеживаемые клавиши
            if (!arrChars.includes(arg)) {
                runFunc = false;
                break;
            }
        }
        if (runFunc) func();              // если нажаты, запускаем заданный код

        arrChars.length = 0;              // очистим массив одновременно нажатых клавиш
    });

}

args — это массив кодов отслеживаемых клавиш. Я перебираю их в цикле и проверяю, есть ли эти коды в массиве одновременно нажатых клавиш arrChars с помощью метода includes. Если установлено, что какая-либо из отслеживаемых клавиш отсутствует в массиве одновременно нажатых клавиш, цикл прерывается, а этот факт запоминается в переменной runFunc. Заданный код func запускается (или не запускается) в зависимости от значения переменной runFunc.

Вот, собственно, и всё. Я протестировал этот код у себя в браузере, он работает. Авторы задачи решили ее несколько по-другому, хотя общие принципы те же. Вместо массива они используют множество значений Set, а обработку заданного кода умудрились вставить в функцию-обработчик события keydown. Очень интересное решение.

GIMP, формат PNG, утилита pngcrush

В одном из предыдущих постов я разбирал постановку задачи в учебнике по JavaScript. Авторы задачи создали тестовую HTML-страницу, на которой использовалась картинка в формате PNG размером 380 × 260 пикселей. Я описал несколько недостатков и ошибок, допущенных художником. После решения той задачи я решил почистить картинку, избавить ее от некоторых из перечисленных ошибок и недостатков. Вот эта картинка:



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

Уже довольно давно для обработки изображений я пользуюсь растровым графическим редактором «GIMP»:

https://ru.wikipedia.org/wiki/GIMP
https://www.gimp.org

Сначала (с 1995 года) эта программа разрабатывалась для операционной системы «Linux», но потом появилась и версия для «Microsoft Windows», которая так и называется: «GIMP for Windows». Я использую именно ее. Программа бесплатная, у нее имеется перевод интерфейса на русский язык. По возможностям, конечно, уступает флагману жанра, программе «Adobe Photoshop». Скачать программу можно с ее официального сайта, ссылка указана выше.

У меня на компьютере стояла версия 2.8.10 программы «GIMP for Windows». Это довольно старая версия, вышедшая где-то в 2013 году (то есть 8 лет назад). Но она меня полностью устраивала, и я не испытывал потребности в ее обновлении.

Изображение, которое я решил исправить, оказалось непохожим на те, с которыми я обычно имею дело. В этом изображении оказались области с прозрачностью, а кроме этого тени для фигур героев были нарисованы пикселями с частичной прозрачностью. Для своих постов я вообще не пользуюсь прозрачностью или частичной прозрачностью, поэтому вообще не умею с ними работать.

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

С этими задачами я более-менее справился и сохранил итоговое изображение в формате PNG. И тут оказалось, что на выходе у меня получился файл примерно раза в полтора больше исходного. Исходный файл имеет размер в 55,3 килобайт, а у меня получился файл около 86 килобайт.

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

* * *

Я решил немного поэкспериментировать с графическим редактором. И в первую очередь просто открыл исходную картинку, а потом сохранил ее в другом файле, никак не изменяя. И вот оно: размер файла картинки увеличился в полтора раза. Значит, виновником увеличения был не я (не мои действия, изменяющие картинку), а сам графический редактор.

Тут, наверное, следует немного пояснить, как в графическом редакторе происходит работа с картинкой. Картинка хранится в файле в формате PNG. В первую очередь это значит, что картинка хранится в файле в упакованном (сжатом) виде. Формат PNG предназначен для использования на веб-сайтах, для уменьшения размера файла картинка упаковывается по определенным алгоритмам так, чтобы размер файла был как можно меньше. Для отображения картинки браузер распаковывает ее из файла.

Точно так же графический редактор, когда открывает картинку в формате PNG из файла, распаковывает ее. Затем картинка импортируется во внутренний формат графического редактора. В этом формате картинку удобнее обрабатывать: в нем можно сохранять свои действия над картинкой, чтобы их можно было «откатить». Также у внутреннего формата есть еще множество других возможностей. Внутренний формат графического редактора «GIMP» называется «XCF», в нем можно сохранять картинку на промежуточных этапах работы над нею. Вот статья об этом формате в википедии:

https://ru.wikipedia.org/wiki/XCF

Чтобы сохранить окончательный результат обработки обратно в файл формата PNG, картинку следует не «сохранять», а «экспортировать» (в меню редактора «GIMP» это разные пункты).

* * *

Сначала я решил обновить графический редактор, надеясь, что это решит мою проблему с увеличением размера итогового файла картинки по сравнению с исходным файлом картинки. Обновление прошло гладко: нужно скачать с официального сайта файл соответствующего дистрибутива к себе на компьютер, запустить его и он установит новую версию графического редактора (затерев старую версию).

Текущая версия программы «GIMP for Windows» — 2.10.54 от 28.03.2021 года.

Но обновление не помогло. Несколько увеличились возможности импорта и экспорта картинок.

Например, при импорте картинки из файла формата PNG графический редактор выдает вопрос о преобразовании цветового пространства (цветового профиля) картинки (этот вопрос может и не выдаваться, его можно отключить в настройках редактора). В связи с этим в википедии есть несколько подходящих статей:

https://ru.wikipedia.org/wiki/Цветовое_пространство
https://ru.wikipedia.org/wiki/Цветовая_модель
https://ru.wikipedia.org/wiki/ICC-профиль

В оригинальной картинке содержится цветовой профиль «sRGB IEC61966-2.1», на который, как там написано, есть авторские права у американской компании «Hewlett-Packard». Редактор «GIMP» предлагает преобразовать указанный цифровой профиль в цифровой профиль «GIMP built-in sRGB», который передан в общественное достояние (по-английски «Public Domain»). Однако, всё это мало влияет на итоговый размер файла картинки в формате PNG (я пробовал использовать оба этих цифровых профиля).

В новой версии графического редактора обновлен диалог экспорта картинки в файл формата PNG.

Например, добавился раскрывающийся список, в котором по умолчанию выбрано значение «Автовыбор формата пикселей», а если этот список раскрыть, то в нем есть 8 пунктов, например «8 бит на канал RGB», «8 бит на канал GRAY» и так далее. Да, с помощью этого списка можно регулировать размер итогового файла формата PNG, но эти пункты (я их проверил) меняют изображение так, что разница становится видна невооруженным глазом, а мне этого не нужно (я хотел, чтобы качество картинки осталось примерно таким же, как и на исходной картинке). Например, если из этих пунктов выбрать вариант без буквы «A» на конце, то с картинки исчезнет прозрачность в нужных местах (будет удален так называемый «альфа-канал», как я понимаю). Ни один из этих пунктов так и не дал уменьшения файла картинки до нужного размера с одновременным сохранением нужного качества.

Еще в новой версии редактора в этом диалоге внизу добавилось пять флагов: «Сохранить данные Exif», «Сохранить данные XMP» и так далее. Это дополнительные данные к картинке формата PNG и они, как я понимаю, не влияют на само изображение. Я отключил все эти пять флагов, но в моем случае это не дало уменьшения итогового файла картинки.

* * *

Еще я пробовал уменьшить размер итогового файла картинки, переведя ее в так называемый «индексированный режим» (пункт меню «Изображение – Режим – Индексированный...»). Да, таким образом можно очень сильно уменьшить размер итогового файла, но у меня, например, при этом исчезли полупрозрачные тени героев. Полная прозрачность, где она была, осталась, а частично прозрачные пиксели полностью исчезли.

Как я понимаю, при переводе в индексированный режим уменьшается количество используемых цветов в изображении, таким образом и достигается уменьшение размера итогового файла. В оригинальном изображении в моем случае содержится 498 разных цветов (количество цветов в изображении можно определить с помощью пункта меню «Цвет – Инфо – Анализ изображения»). По умолчанию при переходе в индексированный режим количество цветов сокращается до максимум 256. Понятно, что качество картинки при этом ухудшится. Мне такое не подходит. Не знаю, можно ли в индексированном режиме использовать палитру из 498 цветов? Я не смог такого добиться.

* * *

В конце концов, мне помогла серия из 4 статьей от 2007-2008 годов автора, имя которого в именительном падеже звучит как «Сергей Чикуенок» (не знаю, как склонять его фамилию):

https://www.artlebedev.ru/technogrette/img/png-1/
https://www.artlebedev.ru/technogrette/img/png-2/
https://www.artlebedev.ru/technogrette/img/png-3/
https://www.artlebedev.ru/technogrette/img/png-4/

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

Путей, по которым может пойти работа алгоритма сжатия, настолько много, что проверить их все не представляется возможным. Например, в статье Сергея утверждается, что таких способов 5 в степени числа пикселей, содержащихся по высоте картинки. То есть, к примеру, для нашей картинки их 5 в степени 260. Это очень большое число.

Я не знаю, как с этим справляется редактор «GIMP», но по моему случаю видно, что не очень хорошо. Сергей рекомендует пользоваться оптимизирующими утилитами, которые перебирают несколько путей сжатия, выбранных эвристически. (Тут мне в голову пришли шахматные движки, которые уже давно играют лучше шахматистов-людей. Эти движки, ведь, тоже не могут рассчитать все возможные пути развития шахматной партии, потому что их очень много. И эти движки тоже пользуются различными эвристическими уловками, чтобы оценить перспективность путей развития партии и выбрать лучший, не просчитывая пути до конца.)

Я попробовал использовать одну из таких утилит, указанную в списке Сергея первой. Это оказалась утилита с названием «pngcrush» из набора утилит «PNG and MNG tools». Статья в википедии:

https://ru.wikipedia.org/wiki/Pngcrush
https://pmt.sourceforge.io/pngcrush/index.html (страница утилиты)

Утилита бесплатная. Скомпилированные версии утилиты можно скачать отсюда:

https://sourceforge.net/projects/pmt/files/pngcrush-executables/

Я скачал версию 1.8.11 от 16.01.2017 года.

Утилита запускается из командной строки операционной системы «Microsoft Windows» или из программы «Windows PowerShell» той же операционной системы. Я запускал из «Windows PowerShell».

Как сказано на странице утилиты и на странице википедии, посвященной этой утилите, главная цель этой утилиты — уменьшение размера данных секции IDAT в файле формата PNG. Как я понимаю, в этой секции и хранятся, собственно, сжатые данные об изображении (по-английски «image data», сокращенно «IDAT»). Возможные секции (по-английски «chunk») формата PNG описаны в спецификации формата PNG:

https://www.w3.org/TR/PNG/

Команда для запуска утилиты в программе «Windows PowerShell» у меня в компьютере:
PS C:\Илья\PNG crush> .\pngcrush_1_8_11_w64 heroes_gimp.png heroes_pngcrush.png

Здесь PS C:\Илья\PNG crush> — это так называемое «приглашение ко вводу команды», оно содержит адрес местоположения, в котором сейчас находится пользователь (название каталога, в который я поместил утилиту). Символы .\ требуются, чтобы запустить исполняемый файл из текущего каталога (в командной строке они не были нужны). pngcrush_1_8_11_w64 — это название исполняемого файла утилиты «pngcrush».

Я передал утилите два параметра: название входящего файла heroes_gimp.png (этот файл утилита будет анализировать, он должен присутствовать в каталоге) и название исходящего файла heroes_pngcrush.png (утилита создаст файл с таким именем и поместит в него файл в формате PNG уменьшенного размера).

Что у меня получилось? Итоги:

heroes.png — исходный файл, размер: 56 699 байт (55,3 килобайта);
heroes_gimp.png — файл heroes.png после импорта в GIMP и экспорта обратно в файл, размер: 86 404 байта (84,3 килобайта);
heroes_pngcrush.png — результат обработки файла heroes_gimp.png утилитой «pngcrush», размер: 43 697 байт (42,6 килобайта).

Утилита «pngcrush» почти в два раза уменьшила размер переданного ей файла. Естественно, без потери качества изображения, так как меняется только способ сжатия в пределах одного и того же алгоритма сжатия (а формат PNG — это изначально формат сохранения изображения со сжатием без потери качества изображения).

JavaScript: локальный веб-сервер из набора IIS

Начало:
1. JavaScript: модули, зачем нужен экспорт и импорт
2. JavaScript: Политика одинакового источника и CORS

Зачем мне понадобился локальный веб-сервер?

Ранее я тестировал свои HTML-страницы со своими скриптами на языке JavaScript, открывая их в браузере. Тестируемые файлы находились на рабочем столе (на моем компьютере установлена операционная система «Windows 10 Pro»). При этом адрес в адресной строке браузера (я использую «Microsoft Edge» на движке «Chromium») выглядел так:
C:/Users/Илья/Desktop/test.html

То же самое с приставкой из названия схемы URI:
file:///C:/Users/Илья/Desktop/test.html

То же самое с кодированием русских букв в URL:
file:///C:/Users/%D0%98%D0%BB%D1%8C%D1%8F/Desktop/test.html

В прошлом посте я рассказал, как выяснил, что при работе с модулями в языке JavaScript механизм CORS браузера блокирует доступ к отдельным модулям, если скрипт пытается получить доступ через схему URI file:///. Поэтому я решил установить на свой компьютер локальный веб-сервер, что позволит мне обращаться к моей тестовой HTML-страничке с моими тестовыми скриптами через браузер по протоколу HTTP (я рассчитывал, что доступ к отдельным модулям по этому протоколу не будет заблокирован механизмом CORS браузера). Например, вот с таким адресом в адресной строке браузера:
localhost/test.html

То же самое с приставкой из названия схемы URI (протокол HTTP):
http://localhost/test.html

В данном случае localhost — это мой компьютер.

В интернете можно найти десятки вариантов разных локальных веб-серверов. Их прямо-таки слишком агрессивно пропихивают при любых запросах в поисковых системах. Но я решил, что раз уж у меня на компьютере установлена операционная система «Windows 10 Pro», то сначала следует поискать в ней.

Оказалось, что операционная система «Windows 10 Pro» включает целый набор серверов для нескольких служб интернета. Этот набор называется «Internet Information Services», сокращенно «IIS»:
https://ru.wikipedia.org/wiki/Internet_Information_Services

По умолчанию IIS в операционной системе «Windows 10 Pro» обычно отключен. В этом можно убедиться, введя в адресной строке браузера адрес:
localhost

Если локальный веб-сервер из набора IIS отключен, то браузер на введение этого адреса выдаст ошибку. Если локальный веб-сервер работает, то должна открыться умолчательная HTML-страничка. У меня она выглядит так:



Как включить набор серверов IIS в операционной системе «Windows 10 Pro»?

Набор серверов IIS является одним из компонентов операционной системы «Windows 10 Pro». В этой операционной системе есть специальный механизм для включения и отключения отдельных компонентов операционной системы. Добраться до него можно через «Панель управления» (по-английски «Control Panel»).

Так как у операционной системы «Windows 10 Pro» очень много разных настроек и меню, то обычно я для поиска нужного пункта пользуюсь кнопкой поиска с увеличительным стеклом, которая находится на экране компьютера возле кнопки «Пуск» операционной системы. После нажатия на эту кнопку откроется окно, снизу которого будет присутствовать строка поиска, в которой можно ввести фразу «Панель управления» и нажать клавишу Enter на клавиатуре.

После этого должно открыться окно панели управления. В этом окне могут быть включены разные режимы просмотра, при некоторых из которых будут видны не все возможные пункты. Следует выбрать режим просмотра, к примеру, «Крупные значки». После этого станут доступны все возможные пункты панели управления. Далее следует выбрать пункт «Программы и компоненты».

После этого откроется окно «Программы и компоненты». В меню слева следует выбрать пункт «Включение или отключение компонентов Windows». Для доступа к этому пункту может потребоваться административный доступ. После этого откроется окно «Компоненты Windows». У меня оно выглядит вот так:



В списке компонентов нужно найти пункт «Службы IIS». У меня квадратик (флажок) слева от названия этого пункта был пустым, что означает, что все серверы и службы из набора IIS полностью отключены. Я один раз щелкнул по этому флажку левой кнопкой мыши, после чего в квадратике (флажке) появился черный квадрат (как на картинке выше). После этого я нажал кнопку «OK» внизу окна и некоторое время (5-10 минут) подождал, пока происходило включение этой компоненты (окно «Компоненты Windows» закрылось).

После этого уже можно пользоваться локальным веб-сервером из набора IIS. Я набрал в адресной строке браузера адрес localhost и браузер открыл вышеупомянутую умолчательную HTML-страничку.

Стоит отметить, что в окне «Компоненты Windows» пункт «Службы IIS» можно открыть с помощью плюсика слева от флажка этого пункта (его можно увидеть на картинке выше). Там откроются три пункта («FTP-сервер», «Службы Интернета», «Средства управления веб-сайтом»), которые, в свою очередь, тоже можно открыть с помощью плюсиков слева от их флажков и так далее. Всего там около 40-50 пунктов, каждый из которых можно либо включить, либо отключить.

То есть возможна очень гибкая настройка набора IIS, которую я на данный момент не потяну, потому что плохо в этом разбираюсь. Как я понимаю, мой выбор самого верхнего пункта в этой настройке — это настройка по умолчанию. При этом внутри описанной иерархии набора IIS выбрались не все пункты (я проверил)! Буду надеяться, что этой умолчательной настройки мне на первое время хватит.

Работа с включенным локальным веб-сервером из набора IIS.

Еще до включения набора серверов IIS в операционной системе «Windows 10 Pro» на основном диске компьютера есть каталог C:\inetpub\. После включения набора IIS в этом каталоге появляется подкаталог C:\inetpub\wwwroot\. В этом каталоге и расположена та самая умолчательная HTML-страница, которая открывается в браузере по адресу localhost, введенному в адресной строке браузера:
C:\inetpub\wwwroot\iisstart.htm

Копируем файлы test.html, script1.js и script2.js из прошлого поста в эту папку C:\inetpub\wwwroot\ и запускаем нашу HTML-страничку из браузера через протокол HTTP:
localhost/test.html

Теперь всё работает без ошибки! Механизм CORS браузера теперь наши скрипты не блокирует.

Мои инструменты

Под «инструментами» я подразумеваю различные программы и сайты, которые использую (практически все из них — бесплатные). Некоторые из этих инструментов я использую ежедневно, другие — периодически, через большие промежутки времени. Не всегда удается быстро вспомнить, как выполнил какую-то задачу пару лет назад, какой инструмент для этого использовал, не удается быстро найти нужный инструмент, если используешь его нечасто. Этот список я создаю, чтобы не рыть каждый раз сотни ссылок и постов в поисках забытого. Предполагается, что время от времени я буду его обновлять. (Инструменты, которые я в данный момент использую чаще, будут в списке «всплывать» вверх.)

Если вы знаете аналоги этих инструментов, которые по вашему мнению лучше, сошлитесь на них в комментариях (не забудьте написать, почему они лучше).

Веб-технологии (HTML, CSS, JavaScript и другие) (5)

https://learn.javascript.ru – учебник по JavaScript (на русском)
https://javascript.info – учебник по JavaScript (на английском)

https://developer.mozilla.org/en-US/docs/Web – на английском
https://developer.mozilla.org/ru/docs/Web – на русском

https://validator.w3.org – проверка правильности разметки на HTML (и не только)

Программы для настольного компьютера (5)

https://www.gimp.org — «GIMP» (для «Windows»), графический редактор
https://pmt.sourceforge.io/pngcrush/ — утилита «pngcrush» для уменьшения файлов PNG
https://notepad-plus-plus.org — «Notepad++», текстовый редактор
https://www.videolan.org/vlc/ — медиапроигрыватель «VLC»

https://visualstudio.microsoft.com/ru/vs/community/
«Visual Studio Community» — среда разработки программ

Сайт вопросов и ответов для программистов (и не только)

https://stackoverflow.com

Таблица символов Юникода

https://unicode-table.com/ru/

Поясняющие рисунки и схемы

https://app.diagrams.net

Создание онлайн разных поясняющих рисунков к постам. Рисунки можно сохранять в разных форматах, из которых мне больше всего нравится формат PNG. В начале работы над рисунком я сохраняю рабочий вариант в файле PNG на рабочий стол своего компьютера. Для работы над рисунком нужен только браузер. Созданный когда-то в этом сервисе рисунок в формате PNG всегда можно открыть и изменить (структура объектов будет восстановлена). Мои поясняющие рисунки — это не картины, а наборы объектов, в том числе геометрических фигур (прямоугольники, квадратики, круги, эллипсы и так далее) с текстом или без. Там есть инструменты для рисования прямых линий, в том числе разного типа (непрерывных, пунктирных с разным пунктиром), разной толщины, со стрелками или без, разного цвета и так далее. На сайте есть множество библиотек с разнообразными объектами из разных систем (блок-схемы, электрические схемы и так далее).

Построение графиков функций онлайн (2)

1. https://www.desmos.com/calculator
2. http://www.yotx.ru

Оба эти сервиса имеют недостатки. Но оба можно использовать. Первый кажется перспективнее. Он развивается, там больше пользователей и больше возможностей. Но второй — проще в использовании.

Построение математических формул онлайн

https://www.hostmath.com

В одном окошке вводишь текстом разметку системы вёрстки «TeX», в другом окошке получаешь математическую формулу нужного вида. Например:

разметка:

\sum_{k=1}^\infty p^{k-1}(1-p)=1

результат:



Высшая математика (2)

http://www.mathprofi.ru
https://textpub.neocities.org/e/emelin/mathmap.html (карта сайта)

Мои посты по 1-й главе учебника Таненбаума и 37 заданиям к ней

Посты разбиты по году опубликования.

2020 год

По тексту книги:

1. Компьютерные сети, книга, Таненбаум и Уэзеролл
2. Общественная музыка домена
3. Юмористический монолог Дика Трэйси
4. Применение компьютерных сетей: Таненбаум, 1.1
5. Сетевое оборудование: Таненбаум, 1.2
6. Дейтаграмма VS датаграмма
7. Перевод терминов в технической литературе
8. Timing
9. Сетевое ПО: Таненбаум, 1.3
10. Эталонные модели сетей: Таненбаум, 1.4
11. Создание интернета: государство VS бизнес
12. Переводчик-антигосударственник
13. Примеры сетей: Таненбаум, 1.5
14. Стандартизация сетей: Таненбаум, 1.6
15. Таненбаум, окончание введения: 1.7, 1.8, 1.9

По вопросам-задачам (в оригинале они называются «problems»). Подводящие посты сдвинуты вправо относительно основных и не пронумерованы:

1. Сенбернар и скорость передачи данных
2. Система с разделением времени VS современная ЛВС
3. Пропускная способность и время ожидания
4. Характеристики качества обслуживания
5. Задержка в сети Нью-Йорк-Калифорния
6. Задержка в спутниковой сети
7. Прямая демократия с помощью компьютерных сетей
8. Топология сети, алгебра и комбинаторика


9. Широковещательная подсеть и вероятности
10. Преимущества и недостатки многоуровневой организации сетей
11. Нарушение принципа многоуровневой иерархии протоколов
12. Надежный поток байтов VS надежный поток сообщений
13. Переговоры в сетевых протоколах
14. Связь между службой и протоколом
15. Ошибки передачи, вероятности, среднее
16. Многоуровневая система, сообщения, заголовки
17. Различие между протоколами TCP и UDP
18. Бомбим подсеть
19. Число хостов в интернете
20. Стратегии подтверждений при передаче файла
21. Тайна местоположения мобильника
22. Какова длина бита
23. Передача картинки по сети
24. Сравнение Ethernet и Wi-Fi
25. Международная стандартизация сетевых протоколов
26. Стандарты в системах с постоянной и съемной частями
27, 28. Влияние изменений в службе уровня на другие уровни
29. Время отклика клиента и задержка сети

2021 год

Последовательная и параллельная передача данных
Почему аналоговый сигнал так называется (на примере звука)
Непрерывность аналогового сигнала
Что такое цифровой сигнал
Прерывность цифрового сигнала
Синхронизация при передаче цифрового сигнала
Анализ цифрового сигнала в получателе сигнала (пример)
Сериализация происходит от последовательности
Синхронный и асинхронный режимы передачи цифрового сигнала
Мультиплексирование с разделением по времени

30. Что такое ATM и недостатки его ячеек
31. Компьютерные сети ежедневно, что если они исчезнут?
32. Компьютерная сеть дома и в офисе
33. Программа ping и зависимость задержки от расстояния
34. Чем занимается организация IETF и проект WebRTC
35. Топология интернета
36. Точки обмена интернет-трафиком, пиринг
37. Программа, моделирующая сетевую архитектуру (разбор задания, реализация)