NanoUi: различия между версиями

Материал из Infinity Project
Перейти к навигации Перейти к поиску
Строка 149: Строка 149:
  
 
====Формат:====
 
====Формат:====
<pre>    { {:data.variable}}</pre>
+
<pre><nowiki>    {{:data.variable}}</nowiki></pre>
  
 
Тэг вывода выводит на окно значение переменной как сроку
 
Тэг вывода выводит на окно значение переменной как сроку
Строка 161: Строка 161:
 
</pre>
 
</pre>
 
И в womdinger.tmpl мы запрашиваем доступ к data с ключём:
 
И в womdinger.tmpl мы запрашиваем доступ к data с ключём:
<pre>
+
<pre><nowiki>
     { {:data.someString}}  
+
     {{:data.someString}}  
</pre>
+
</pre></nowiki>
 
Когда интерфейс прогрузится, тэг будет прогружен как:
 
Когда интерфейс прогрузится, тэг будет прогружен как:
 
<pre>
 
<pre>
Строка 179: Строка 179:
  
 
Вы можете получать доступ к элементам списка используя точку (.):
 
Вы можете получать доступ к элементам списка используя точку (.):
<pre>
+
<pre><nowiki>
 
{{:data.assocList.key1}} and {{:data.assocList.key2}}  
 
{{:data.assocList.key1}} and {{:data.assocList.key2}}  
</pre>
+
</pre></nowiki>
 
Когда интерфейс прогрузится, тэг будет заменён на:
 
Когда интерфейс прогрузится, тэг будет заменён на:
 
<pre>
 
<pre>
Строка 189: Строка 189:
  
 
====Формат:====
 
====Формат:====
<pre>
+
<pre><nowiki>
{ {if expression}} <expression true content> { {/if}} { {if expression}} <expression true content> { {else}} <expression false content> { {/if}} { {if expression1}} <expression1 true content> { {else expression2}} <expression2 true content> { {/if}}  
+
{{if expression}} <expression true content> {{/if}} {{if expression}} <expression true content> {{else}} <expression false content> {{/if}} {{if expression1}} <expression1 true content> {{else expression2}} <expression2 true content> {{/if}}  
</pre>
+
</pre></nowiki>
 
Тэг If отображает информацию в зависимости от правдивости данного выражения. Если вы видите { {if data.is_prog}}, то это проверка на присутствие переменной is_prog (если is_prog равен null или 0 или не обозначен, то действие не выполняется).
 
Тэг If отображает информацию в зависимости от правдивости данного выражения. Если вы видите { {if data.is_prog}}, то это проверка на присутствие переменной is_prog (если is_prog равен null или 0 или не обозначен, то действие не выполняется).
  
 
Комбинируя if и тэг else можно отображать другую информацию если выражение равно True.
 
Комбинируя if и тэг else можно отображать другую информацию если выражение равно True.
"{ {else expression2}}"), выдача выражения тэгу else даёт тэгу else функционал elseif
+
<nowiki>"{{else expression2}}"</nowiki>), выдача выражения тэгу else даёт тэгу else функционал elseif
 
====Пример 1:====
 
====Пример 1:====
  
 
Пример темплейта:
 
Пример темплейта:
<pre>
+
<pre><nowiki>
{ {if data.aNumber}} data.aNumber is set (not null) and is positive { {/if}  
+
{{if data.aNumber}} data.aNumber is set (not null) and is positive {{/if}  
</pre>
+
</pre></nowiki>
 
Когда интерфейс прогрузится тэг будет заменён на:
 
Когда интерфейс прогрузится тэг будет заменён на:
 
<pre>
 
<pre>
Строка 212: Строка 212:
 
Пример темплейта:
 
Пример темплейта:
  
<pre>{ {if data.someString == "Who goes there?"}} Some string is "Who goes there?" { {else}} Some string is not "Who goes there?" { {/if}</pre>
+
<pre>{{if data.someString == "Who goes there?"}} Some string is "Who goes there?" { {else}} Some string is not "Who goes there?" { {/if}</pre>
  
 
Когда интерфейс прогрузится тэг будет заменён на:
 
Когда интерфейс прогрузится тэг будет заменён на:
Строка 223: Строка 223:
  
 
Пример темплейта:
 
Пример темплейта:
<pre>
+
<pre><nowiki>
{ {if data.aNumber < 50}} data.aNumber is less than 50 { {else data.aNumber < 100}} data.aNumber is less than 100 { {else data.aNumber < 150}} data.aNumber is less than 150 { {else}} None of the expressions above are true. { {/if}  
+
{{if data.aNumber < 50}} data.aNumber is less than 50 {{else data.aNumber < 100}} data.aNumber is less than 100 {{else data.aNumber < 150}} data.aNumber is less than 150 {{else}} None of the expressions above are true. {{/if}  
</pre>
+
</pre></nowiki>
 
Когда интерфейс прогрузится тэг будет заменён на:
 
Когда интерфейс прогрузится тэг будет заменён на:
 
<pre>
 
<pre>
Строка 234: Строка 234:
 
===Тэг for===
 
===Тэг for===
 
====Формат:====
 
====Формат:====
<pre>
+
<pre><nowiki>
   { {for array}} <list entry content> { {/for}}  
+
   {{for array}} <list entry content> {{/for}}  
   { {for array}} <list entry content> { {empty}} <empty list content> { {/for}}
+
   {{for array}} <list entry content> {{empty}} <empty list content> {{/for}}
</pre>
+
</pre></nowiki>
 
Цикл по элементам массива (массив - список с нумерацией элементов начинающейся с 0 (it does not use strings as keys).
 
Цикл по элементам массива (массив - список с нумерацией элементов начинающейся с 0 (it does not use strings as keys).
  
Строка 249: Строка 249:
  
 
Пример темплейта:
 
Пример темплейта:
 
+
<nowiki>
     { {for data.arrayOfAssocLists}}
+
     {{for data.arrayOfAssocLists}}
 
         { {:index}} -> { {:value.key1}} and { {:value.key2}}<br>
 
         { {:index}} -> { {:value.key1}} and { {:value.key2}}<br>
     { {/for}     
+
     {{/for}     
 +
</nowiki>
 
Когда интерфейс прогрузится, тэги будут заменены на:
 
Когда интерфейс прогрузится, тэги будут заменены на:
  
Строка 261: Строка 262:
  
 
Пример темплейта:
 
Пример темплейта:
 
+
<nowiki>
 
     { {for data.emptyArray}}
 
     { {for data.emptyArray}}
 
         { {:value.key}}
 
         { {:value.key}}
 
     { {empty}}
 
     { {empty}}
 
         This list is empty.
 
         This list is empty.
     { {/for}  
+
     { {/for}  
 +
</nowiki>
 
Когда интерфейс прогрузится, тэги будут заменены на:
 
Когда интерфейс прогрузится, тэги будут заменены на:
 
<pre>
 
<pre>

Версия 14:20, 30 мая 2019

Тихо! Идёт работа!
Статья или раздел находится в процессе написания и использовать её на сервере необходимо с осторожностью, информация может быть неточной. Вы можете помочь с её заполнением.

Код Dream Maker

Мы начнём с создания простейшего NanoUi. Чтобы понять как писать индусский код оно работает.
Для начала создадим простейший интерфейс для объекта "womdinger".

Вот файл нашего объекта:

/obj/item/device/wombdinger
       name = "womdinger"
       desc = "It's some kind of crude alien device."
       icon = 'icons/obj/wombdinger.dmi'
       icon_state = "0"

Создадим для него прок attack_self куда мы будем передавать, как mob, того кто использовал предмет.

Файл теперь выглядит так:

/obj/item/device/wombdinger
       name = "womdinger"
       desc = "It's some kind of crude alien device."
       icon = 'icons/obj/wombdinger.dmi'
       icon_state = "0"
/obj/item/device/wombdinger/attack_self(mob/user as mob)

Теперь чтобы открыть NanoUi нужно поместить в attack_self прок вызова Ui, то есть ui_interact, которому нужно передать пользователя.

Файл теперь выглядит так:

/obj/item/device/wombdinger
       name = "womdinger"
       desc = "It's some kind of crude alien device."
       icon = 'icons/obj/wombdinger.dmi'
       icon_state = "0"
/obj/item/device/wombdinger/attack_self(mob/user as mob)
       ui_interact(user)

Теперь нужно создать сам прок ui_interact, создадим его в этом же файле:

/obj/item/device/wombdinger/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)

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

Массив data передаёт значения в нужный темплейт. О темплейтах позже.

/obj/item/device/wombdinger/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
       var/list/data = list()
       // Добавим простые данные в массив
       data["myName"] = name
       data["myDesc"] = desc
       data["someString"] = "I am a string."
       data["aNumber"] = 123
       
       data["assocList"] = list("key1" = "Value1", "key2" = "Value2")
       
       // Обратный слэш говорит компилятору игнорировать перенос строки, полезно для улучшения читабельности кода.
       data["arrayOfAssocLists"] = list(\ 
           list("key1" = "ValueA1", "key2" = "ValueA2"),\
           list("key1" = "ValueB1", "key2" = "ValueB2"),\
           list("key1" = "ValueC1", "key2" = "ValueC2")
       )
       
       data["emptyArray"] = list()
       
       // обновляет ui с данными переданными данными если они переданы, возврашает null если ui не найдено, или ui не передаётся, или если force_open == 1 или true
       ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)	
       //Если ui не открыт то мы открываем его:
       if (!ui)
           // Список параметров ui можно найти в \code\modules\nano\nanoui.dm
           ui = new(user, src, ui_key, "womdinger.tmpl", "Womdinger UI", 520, 410)
           // Если ui открыт первый раз то мы используем эти данные:
           ui.set_initial_data(data)		
           // Открываем новое окно ui
           ui.open()

Две важные вещи в коде выше это data, а точнее список ассоциаций и создание NanoUi: ("ui = new(user, src, ui_key, "womdinger.tmpl", "Womdinger UI", 520, 410)")

Первые три параметра nanoui никогда не меняются user(пользователь), src(цель пользователя), ui_key(ui ключ(уточнить)).

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

Темплейт должен именоваться именем файла в \nano\templates\

Ширина - это ширина как ни странно окна ui в пикселях.

Высота - высота окна ui в пикселях

Это всё что нам нужно в DM файле, прейдём к темплейтам.

Создаём темплейт и учим HTML

NanoUI разделяет разметку отображения и код логики (файлы DM) и помещает его в файлы шаблонов (.tmpl). Файлы шаблонов - это в основном HTML-документы с разметкой, добавленной для динамических элементов, такие как кнопки.

В предыдущем разделе мы настроили наш файл womdinger.dm. В этом файле, в рамках процедуры ui_interact, имеется ссылка на файл «womdinger.tmpl». Нам нужно создать этот файл в папке \nano\templates\

Примечание: начиная с последнего обновления библиотеки NanoUI больше нет необходимости добавлять файлы шаблонов в клиентский процесс send_resources, поскольку это обрабатывается автоматически.

Теперь создадим темплейт кода для womdinger.tmpl:

   <div class="item">
        <div class="itemLabel">
            <b>Object Name</b>:
        </div>
        <div class="itemContent">
            {{:data.myName}}
        </div>
    </div>
    <div class="item">
        <div class="itemLabel">
            <b>Object Description</b>:
        </div>
        <div class="itemContent">
            {{:data.myDesc}}
        </div>
    </div>
    <div class="item">
        <div class="itemLabel">
            <b>Some String</b>:
        </div>
        <div class="itemContent">
            {{:data.someString}}
        </div>
    </div>
    <div class="item">
        <div class="itemLabel">
            <b>A Number</b>:
        </div>
        <div class="itemContent">
            {{:data.aNumber}}
        </div>
    </div>
    <div class="item">
        <div class="itemLabel">
            <b>Associated list values</b>:
        </div>
        <div class="itemContent">
            {{:data.assocList.key1}} and {{:data.assocList.key2}}
        </div>
    </div>

Шаблон представляет собой стандартный HTML4 с дополнительными тегами разметки (заключенными в фигурные скобки { {...} }(Без пробелов в скобках, из-за вики тут они превращаются в шаблоны так что должно выглядеть как {{}}, а между ними содержимое)) для динамического содержимого (печать, условные операторы { {if} }, циклы { {for} } { {while} } и т. Д.).

Стиль по умолчанию для шаблона предоставляется файлом shared.css в папке /nano/css

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

Спец тэги разметки темплейтов

Специальный тэги разметки используются для добавления в темплейт динамических элементов зависящих от .dm части кода.

Тэг вывода

Формат:

    {{:data.variable}}

Тэг вывода выводит на окно значение переменной как сроку

Пример 1:

В womdinger.dm, в ui_interact, мв ставим значение для "someString" ключа массива Data:

    data["someString"] = "I am a string" 

И в womdinger.tmpl мы запрашиваем доступ к data с ключём:

<nowiki>
    {{:data.someString}} 

</nowiki>

Когда интерфейс прогрузится, тэг будет прогружен как:

    I am a string.

I am a string.

Пример 2:

В womdinger.dm, в ui_interact, мы делаем список асоциаций:

data["assocList"] = list("key1" = "Value1", "key2" = "Value2") 

Вы можете получать доступ к элементам списка используя точку (.):

<nowiki>
{{:data.assocList.key1}} and {{:data.assocList.key2}} 

</nowiki>

Когда интерфейс прогрузится, тэг будет заменён на:

Value1 and Value2

Тэг If

Формат:

<nowiki>
{{if expression}} <expression true content> {{/if}} {{if expression}} <expression true content> {{else}} <expression false content> {{/if}} {{if expression1}} <expression1 true content> {{else expression2}} <expression2 true content> {{/if}} 

</nowiki>

Тэг If отображает информацию в зависимости от правдивости данного выражения. Если вы видите { {if data.is_prog}}, то это проверка на присутствие переменной is_prog (если is_prog равен null или 0 или не обозначен, то действие не выполняется).

Комбинируя if и тэг else можно отображать другую информацию если выражение равно True. "{{else expression2}}"), выдача выражения тэгу else даёт тэгу else функционал elseif

Пример 1:

Пример темплейта:

<nowiki>
{{if data.aNumber}} data.aNumber is set (not null) and is positive {{/if} 

</nowiki>

Когда интерфейс прогрузится тэг будет заменён на:

data.aNumber is set (not null) and is positive 

Потому что data.aNumber обозначен (не null) и положителен (it's value is 123).

Пример 2:

Пример темплейта:

{{if data.someString == "Who goes there?"}} Some string is "Who goes there?" { {else}} Some string is not "Who goes there?" { {/if}

Когда интерфейс прогрузится тэг будет заменён на:

Some string is not "Who goes there?" 

Потому что выражение (someString == "Who goes there?") не истинно.

Пример 3:

Пример темплейта:

<nowiki>
{{if data.aNumber < 50}} data.aNumber is less than 50 {{else data.aNumber < 100}} data.aNumber is less than 100 {{else data.aNumber < 150}} data.aNumber is less than 150 {{else}} None of the expressions above are true. {{/if} 

</nowiki>

Когда интерфейс прогрузится тэг будет заменён на:

data.aNumber is less than 150 

Потому что выражение подходит под второй else тэг (data.aNumber < 150).

Тэг for

Формат:

<nowiki>
   {{for array}} <list entry content> {{/for}} 
   {{for array}} <list entry content> {{empty}} <empty list content> {{/for}}

</nowiki>

Цикл по элементам массива (массив - список с нумерацией элементов начинающейся с 0 (it does not use strings as keys).

Каждый раз, когда тег for выполняет проходит по массиву, он устанавливает переменную ("value" по умолчанию) для данных текущей записи (другая переменная, значение по умолчанию «index», содержит индекс (номер элемента в массиве)).

И примером этого является использование тега вывода для печати содержимого (например, { {: value.key1}} и { {: value.key2}}).

В сочетании с empty тегом тег for может отображать содержимое, когда массив пуст.

Пример 1

Пример темплейта: {{for data.arrayOfAssocLists}} { {:index}} -> { {:value.key1}} and { {:value.key2}}<br> {{/for} Когда интерфейс прогрузится, тэги будут заменены на:

  0 -> ValueA1 and ValueA2
  1 -> ValueB1 and ValueB2
  2 -> ValueC1 and ValueC2

Пример 2

Пример темплейта: { {for data.emptyArray}} { {:value.key}} { {empty}} This list is empty. { {/for} Когда интерфейс прогрузится, тэги будут заменены на:

This list is empty.

Template Helpers

Helpers are functions written in JavaScript which can be called within templates. They are used within the above markup tags, most commonly the print tag.

Helpers are accessed via the "helper" object.

Link Helper

Format:

   {{:helper.link(text, icon, parameters, status, elementClass, elementId)}}

The link helper generates a link (which by default is styled as a button). When clicked the button will send the supplied parameters to the server.

Parameters:

  • text - string - The text which appears on the link.
  • icon - string - An icon to show on the link. Icon names can be found at http://fontawesome.io/icons/. Examples: 'refresh', 'shuffle', 'radiation', 'power'. * parameters - JSON - Parameters to send to the server when the link is clicked. The "src" parameter is added automatically, do not add it here.
  • status - optional null/string - Optional status of the link. Can be null for active, 'disabled' for disabled or 'selected' for selected. Defaults to active if nothing is passed.
  • elementClass - optional string - If provided this string will be added to the link as a class (used for custom styling in CSS or as a JavaScript selector).
  • elementId - optional string - If provided this string will be added to the link as an id (used for custom styling in CSS or as a JavaScript selector).

Example 1: Basic usage

   {{:helper.link('Toggle Power', 'power', { 'option' : 'togglePower' })}}

If clicked the receiving object's Topic proc's href_list will have the following entries (src is added automatically and should not be changed):

   list("src" = "\ref[src]", "option" = "togglePower")

Example 2: Multiple parameters

   {{:helper.link('Cut Red Wire', 'scissors', { 'wireColor' : 'red', 'action' : 'cut' })}}

If clicked the receiving object's Topic proc's href_list will have the following entries (src is added automatically and should not be changed):

   list("src" = "\ref[src]", "wireColor" = "red", "action" = "cut")

Bar Helper

Format:

   {{:helper.displayBar(value, rangeMin, rangeMax, styleClass, styleClass, showText)}}

This helper creates a bar.

Parameters:

  • value - number - Current value of progress bar
  • rangeMin - number - Lower bound of value
  • rangeMax - number - Upper bound of value
  • styleClass - optional string - List of styles to apply, seperated by spaces. Acceptable styles include alignRight, good, notgood, average, bad, and highlight.
  • showText - optional string - The text that is shown. Do not include the number itself.

Example 1: Health

    {{if data.occupant.health >= 0}}
        {{:helper.displayBar(data.occupant.health, 0, data.occupant.maxHealth, 'good')}}
    {{else}}
        {{:helper.displayBar(data.occupant.health, 0, data.occupant.minHealth, 'average alignRight')}}
    {{/if}}