[Из песочницы] Десктопные приложения на JavaScript. Часть 1

Ни для кого не секрет, что в наше время JavaScript стал одним из самых популярных языков программирования. В далекие 90е годы, в момент зарождения языка, когда он был создан с единственной целью добавить интерактивность веб страницам и улучшить процесс взаимодействия с пользователем, кто бы мог подумать, что он достигнет столь небывалых высот. Ведь сейчас на нем можно делать практически все что угодно. Хотите написать сайт: и бэкэнд и фронтэнд на JavaScript? пожалуйста! Хотите написать мобильное приложение на JavaScript? нет проблем. Программируете микроконтроллер — и тут вам на помощь придет JavaScript.

Есть конечно небольшие минусы в подходе использования JavaScript везде, но если поразмыслить, то сколько времени и сил можно сэкономить, изучив всего лишь одни язык, особенно, если то же самое приложение должно работать на разных платформах. Разных платформах говорите? Хм… Точно — разных платформах — теперь JS может позволить себе десктопные приложения для Windows, Linux, Mac, как спросите вы? Ответ прост: встречайте — NW.js.

По первым буквам можно прочитать — Node.js + Webkit, если данные понятия вам пока не знакомы, то скоро вы поймете о чем идет речь.

Node.js — программная платформа, основанная на движке V8, который транслирует наш скрипт в машинный код. Данная платформа была создана в 2009 году преимущественно для работы с бэкэндом сайтов.

WebKit — свободный движок, разработанный компанией Apple. Впервые был анонсирован в составе Safari в 2003 году
Итак, коду, написанному на JS для данной технологии, будут доступны как Node.js модули, так и стандартный браузерный API (соответственно WebKit)

Быстрый старт


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

После того, как необходимое ПО скачано и установлено, вы написали свое приложение на любимом JS (как это сделать читайте далее) и локализовали все в одну папку. Полдела сделано, теперь остается самое сложное и долгое — упаковать все в один файл и подготовить для распространения. Для упрощения вы можете воспользоваться готовыми библиотеками, например nw-builder. Установка библиотеки не составит труда, если вы уже работали с node.js. Как известно, в состав node.js входит менеджер пакетов npm, с которым нужно работать из командной строки. Для того, чтобы поставить какую-либо библиотеку, необходимо выполнить команду:

> npm install  [имя_библиотеки] [опции]


Обратите внимание, что библиотеку можно ставить, как локально, так и глобально, для локальной установки используйте опцию --save-dev, для глобальной -g. Таким образом поставим наш сборщик для NW.js глобально, выполнив команду:

> npm install nw-builder -g


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

> nwbuild -p [имя_платформы] -o [путь_к_папке_для_собранной_версии] [путь_до_приложения]


В качестве имени платформы могут быть следующие значения: win32, win64, osx32, osx64, linux32, linux64.

Во время разработки нет нужды каждый раз собирать приложение, можно просто запустить его как есть и оно откроется в отдельном окне. Для этого нужно запустить приложение nw.exe из командной строки и передать в качестве параметров путь к папке с вашим приложением. Кроме того, если вы работаете под Windows, можно просто методом drag-n-drop перетащить папку с исходным кодом приложения на JS (обратите внимание, что именно папку целиком) в nw.exe.

Hello, world!


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

Для данного приложения, нам даже не понадобится JavaScript, только HTML. Создадим папку с названием HelloWorld. Поместим внутрь файл index.html со следующей разметкой:


  
     Hello, world 
  
  
    
Hello, world, from NW.js


Кроме того для каждого приложения под NW.js необходим файл, который обязательно должен называться package.json. Из него будет браться информация для построения приложения. Создадим простейший вариант файла и поместим в папку HelloWorld. Итак:

{
        "name": "hello-world",
        "version": "1.0.0",
        "description": "First application",
        "main": "index.html",
         "author": "Developer",
        "window": {
                 "toolbar": false,
                "width": 500,
                 "height": 200
         }
}


Содержимое файла понятно без пояснений (обратите внимание, что обязательные поля только main и name). В main необходимо записать файл с разметкой, который будет являться точкой входа в приложение. Секция window настраивает параметры окна (в данном случае мы отключаем панель инструментов и задаем размеры окна 500×200).

Кроме того, можно настроить такие поля как (за полным списком опций обращайтесь в документацию):

  • icon — указываем путь до иконки (переопределить стандартную)
  • position — можно указать позицию окна при загрузке (null, center или mouse)
  • min_width, min_height, max_width, max_height — ограничение размеров окна
  • resizable — логическое значение, которое показывает можно ли пользователю изменять размеры окна
  • fullscreen — включить полноэкранный режим
  • kiosk — включить режим киоска
  • transparent — сделать окно прозрачным


Приложение создано и можно его запустить. После запуска (о том как это сделать, смотри раздел выше) вы должны получить следующее окно:

6f97dc9f05774021bad17f56fdbaefe5.png

Приложение написано, но в нем всего один div элемент и совсем нет логики, а что делать, если у нас богатая на элементы разметка и сложная логика? На помощь к нам приходит элемент конфигурационного файла toolbar, который мы установили в false. Для того, чтобы сделать доступными средства отладки, необходимо установить toolbar в true. Проделав это при запуске приложения мы получим следующее окно:

774d7da1c45a49bcabd323f8d3b163ba.png

После нажатия на кнопку в верхнем правом углу откроется еще одно окно, в котором будут отображены знакомые инструменты разработчика:

026c4352bc7c451dba0e31cbd8363b4d.png

Работа с нативными контролами


NW.js позволяет работать с нативными контролами. Рассмотрим работу на примере меню. Для работы с нативным UI контролами в nw.js необходимо использовать модуль nw.gui, который можно подключить следующим образом:

var gui = require('nw.gui');


Общий шаблон для использования контролов:

var element = new gui.ElementName(option);


Таким образом для создания элементов меню можно воспользоваться следующей конструкцией:

var menu = new gui.Menu();


Кроме того любые свойства созданного нами объекта можно легко изменить стандартными конструкциями JS, например так:

menu.title = 'New Title';


Меню создано, теперь нужно его заполнить, для манипуляциями дочерними элементами существуют методы:

menu.append(new gui.MenuItem({label: 'Label of menu item'}));
menu.removeAt(0);


Кроме того для более гибкого добавления элементов в menu можно воспользоваться методом insert, в параметрах которого необходимо передать MenuItem и номер позиции, куда его вставить (позиция перед первым элементом соответствует 0).

Для доступа к созданным элементам можно использовать свойство items:

menu.items[0].title = "New title"


Обратите внимание, что нельзя напрямую создавать элементы:

menu.items[2] = new gui.MenuItem(); // НЕПРАВИЛЬНО


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

control.remove();
control = null;


Для более удобной работы с контролами, они унаследованы от EventEmitter, поэтому хорошая новость в том, что мы можем легко работать с событиями, например так:

menuitem.on('click', function() {
   // сделать что-нибудь полезное
});


Меню было создано, но если запустить приложение, то никакого меню вы не увидите. Для отображения меню существует метод popup, в параметрах которого необходимо передать координаты для отображения меню.

Для демонстрации основных возможностей меню добавьте следующий скрипт к созданному ранее проекту Hello, world:

var gui = require('nw.gui');
var menu1 = new gui.Menu();
menu1.append(new gui.MenuItem({label: 'Item 1'}));
        
var subMenu1 = new gui.Menu();
subMenu1.append(new gui.MenuItem({label: 'Item 2'}));
menu1.append(new gui.MenuItem({
        label: "Submenu",
        submenu: subMenu1
}));
        
document.body.addEventListener('contextmenu', function(ev) { 
         ev.preventDefault();
         menu1.popup(ev.x, ev.y);
         return false;
});


После запуска приложения, мы можем увидеть созданное контекстное меню для body. Таким образом, мы можем определить контекстное меню для любого элемента.

9382bd56a6a6430a9c12aa831d565034.png

Итак, теперь кроссплатформенные приложения может создавать каждый, но за все нужно платить. В данном случае мы жертвуем как скоростью, так и занимаемым объемом памяти (собранное приложение получается достаточно большим, более 50 Мб). Список приложений, созданных, используя данную технологию можно найти на github.

Во второй части статьи мы рассмотрим технологию более подробно.

© Habrahabr.ru