Knockout css binding - IT Справочник
Llscompany.ru

IT Справочник
3 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Knockout css binding

Байндинги в KnockOut: управление видимостью и содержимым

KO построен по принципам MVVM паттерна, т.е. предоставляет возможность изменять View посредством изменения ViewModel. А делает он это при помощи байндингов. Рассмотрим какие из них отвечают за управление видимостью и содержимым элементов.

visible

Отвечает за отображение DOM элемента, т.е. делает его скрытым или видимым, в зависимости от переданного значения свойства ViewModel.

Принимает всего один параметр:

  • если равен false (в том числе , null и undefined), то css свойство display элемента (DomElement.style.display) установится в none
  • если равен true (все что угодно кроме false подобных значений), свойство display будет удалено с элемента

Если параметр наблюдаемый, то элемент будет показываться/прятаться при каждом изменении последнего. Если он не наблюдаемый, то видимость будет установлено только один раз, при вызове ko.applyBindings .

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

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

Принимает один параметр, который устанавливается в свойство DOM элемента innerText (для IE) или textContent (FireFox и другие). Если передать что-либо другое кроме строки или числа, то параметр приведется к строковому типу посредством вызова его метода toString.

Байндинг заескейпит любой переданный ему html код, например

приведет к такому результату

Это достаточно удобно, так как предотвращает XSS атаки.

Полностью аналогичен предыдущему с той разницей, что он изменяет свойство innerHTML у элемента.

Этот байндинг удаляет или добавляет CSS класс элементу. Это полезно, например, для подсветки элемента, когда он выбран.

В таком случае элементу установится класс profitWarning при условии, что свойство currentProfit станет меньше 0 и удалит этот класс, когда значение станет больше 0.

Принимает один параметр в виде хэша, ключи которого являются названиями классов, а значения — свойствами/выражениями/функциями связанными с ViewModel. Если нужно добавлять/удалять класс вида my-class , то его нужно взять в апострофы.

Это связано с ограничениями в JavaScript на имена ключей.

style

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

Так как ключи являются свойствами JavaScript объекта style, то чтобы привязать background-color нужно писать backgroundColor .

Полный список JavaScript эквивалентов названий css свойств можно найти здесь.

Байндинг также по синтаксису похож на 2 предыдущих и изменяет значения атрибутов элемента. Это часто используется, когда нужно поменять атрибут src у картинки или href у ссылки.

Все остальное аналогично, как в двух предыдущих байндингах.

Knockstrap

Knockout bindings library

Overview

Knockstrap is binding library for Knockout.js, which provides binding to Twitter Bootstrap widgets

Features

  • Using Bootstrap widgets via data-bind attribute
  • Supports dynamicaly changing parameters and data of widgets via observables
  • Supports Knockout templates for such widgets, as modal or popover
  • Supports using of third party template engines
  • Provides default templates for such widgets, as modal , for typical using
  • Provides string template engine, which allows to use javascript strings as templates

Using

If you have all dependencies, you only need to include knockstrap.min.js or knockstrap.js to your pages:

Dependencies

Tooltip

Binding to Bootstrap tooltip

Examples

Html markup

View model

Options

tooltipOptions

Type: object, can be observable

Uses Bootstrap 3 options. If any option is not specified, uses default value. See Bootstrap documentation. All of the options can be observables. Also option’s object can be observable too.

Popover

Binding to Bootstrap popover. Supports custom templates with observables for popover content

Examples

Html markup

View model

Options

All of the options can be observables, also option’s object can be observable too

options

Type: object, can be observable

Bootstrap options for popover. If any option is not specified, uses default value. Please, see Bootstrap documentation

templateName

Type: string, can be observable

Name of template for popover content. If template is not specified, uses content property from options object

templateData

Type: object, can be observable

Data for template

templateOptions

Contains options for template.

They are: templateEngine , afterRender , beforeRender and afterAdd . Please, see Knockout documentation for details.

Short notation

If you don’t need use template, you can use short notation of binding, which uses only option object.

popoverOptions

Type: object, can be observable

Bootstrap options for popover. If any option is not specified, uses default value. Please, see Bootstrap documentation

Alert

Binding to Bootstrap alert widget. This binding can be used with virtual elements. Supports custom templates with observables

Examples

Html markup

View model

Options

All of the options can be observables.

message

Type: string, can be observable

Text of alert message. Doesn’t used if data property is specified.

type

Type: string, can be observable (default: ‘info’ )

Type of alert message. Possible values are ‘info’ , ‘warning’ , ‘danger’ , ‘success’ . To specify your own type you should define css-styles for this type. For exmaple, for type ‘my-custom-type’ , you shoud provide css class ‘alert-my-custom-type’ .

template

Type: string, can be observable (default: ‘alertTemplate’ )

Name of template for alert content. Default template:

data

Type: object, can be observable

Data for template. If this option is specified, message option will be ignored.

For default template, you should provide message property (or, if it will not provided via data , message option of binding will be used).

templateOptions

Contains options for template.

They are: templateEngine , afterRender , beforeRender and afterAdd . Please, see Knockout documentation for details.

Modal

Binding to Bootstrap modal widget.

Examples

Html markup

View model

Options

All of the options can be observables.

options

Type: object, can be observable

Bootstrap options for modal. If any option is not specified, it uses default values (except show , it default value is false in comparing with Bootstrap). Also, can be specified via data-attributes. Please, see Bootstrap documentation for details.

visible

Type: boolean, can be observable (default: false )

Shows modal, if true, otherwise hides modal. By default is false.

Can be omitted in order to use Bootstrap’s attributes for showing or closing modal.

dialogCss

Type: string, can be observable (default: undefined )

Used to add classes to modal-dialog element. For example, it can accept modal-lg value for large modal or modal-sm for small.

Please, see Bootstrap documentation for more details.

header

Type: object, can be observable

Template binding for modal header, uses options from Knockout template binding. Please, see Knockout documentation for details.

Default values of header object:

name

Type: string, can be observable (default: ‘modalHeader’ )

Name of template for modal header. Default template:

data

Data for header template. For default template, you should provide label property

body

Type: object, can be observable

Template binding for modal body, uses options from Knockout template binding. Please, see Knockout documentation for details.

Default values of body object:

name

Type: string, can be observable (default: ‘modalBody’ )

Name of template for modal body. Default template:

data

Data for body template. For default template, you should provide content property, which can contain html.

footer

Type: object, can be observable

Template binding for modal footer, uses options from Knockout template binding. Please, see Knockout documentation for details.

If omitted, no footer will be rendered.

Default values of footer object:

name

Type: string, can be observable (default: ‘modalFooter’ )

Name of template for modal footer. Default template:

data

Data for footer template. For default template, data object contains:

action

Function, which will be called, when user clicks on primary button. If this property is omitted for default template, primary button wouldn’t render.

primaryLabel

Type: string, can be observable (default: ‘Ok’ )

Text for primary button in default template.

closeLabel

Type: string, can be observable (default: ‘Close’ )

Text for closing button in default template.

events

Type: object, can be observable

Names of Bootstrap events, which are used by binding. Some bootstrap plugins change them, so you can pass new events to binding.

Default values of events object:

shown

Type: string, can be observable (default: ‘shown.bs.modal’ )

Name of Bootstrap event, which fired when the modal has been made visible to the user

hidden

Type: string, can be observable (default: ‘hidden.bs.modal’ )

Name of Bootstrap event, which fired when the modal has finished being hidden from the user

Технология Клиент-Сервер 2011’1

Knockout


Вступление

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

  • Отслеживание зависимостей – автоматическое обновление нужных частей UI при изменении модели данных;
  • Декларативные связывания – простой и очевидный путь соединения частей UI с моделью данных.
  • Гибкие и сложные шаблоны – конструирование сложного динамического UI упрощается благодаря произвольной вложенности шаблонов.
  • Расширяемость – пользовательское поведение реализуется как новые декларативные связывания, которые легко использовать с помощью всего нескольких строк кода.
  • Дополнительные преимущества:
  • Чистая JavaScript-библиотека – работает с любой серверной или клиентской технологией;
  • Может быть использована поверх существующих Web-приложений, не требуя больших архитектурных изменений.
  • Компактная – около 25kb до архивирования gzip.
  • Работает в любом распространенном браузере (IE 6+, Firefox 2+, Chrome, Safari и т.д.)
  • Широкий набор спецификаций (в BDD-стиле) означает, что корректность функционирования на новых браузерах и платформах можно легко проверить.

Разработчики, использовавшие Silverlight или WPF, могут узнать в КО пример паттерна MVVM; разработчики, более знакомые с Ruby on Rails или другой технологией, использующей MVC, могут рассматривать КО как realtime-форму MVC с декларативным синтаксисом. В другом смысле КО можно рассматривать как общий способ создания UI для редактирования JSON-данных… в общем, как вам удобнее, так и рассматривайте. 🙂

OK, как это использовать?

Коротко: определите ваши данные как объект модели JavaScript, и затем привяжите к ним DOM-элементы и/или шаблоны.

Посмотрим на пример

Возьмем экран, на котором авиапассажиры выбирают дополнения к полетному меню. Мы хотим позволить им выбрать блюдо, а затем динамически отобразить его описание и цену. Сперва давайте объявим доступные блюда:

Если мы хотим отобразить эти опции в UI, мы можем привязать к ним выпадающий список (т.е. HTML-элемент

Чтобы активировать Knockout и оживить созданные связи, добавим следующие строки сразу после объявления availableMeals:

Подробнее о моделях представления данных и MVVM можно прочитать здесь: http://knockoutjs.com/docu­men­tation/observables.html. Пока же страница будет выглядеть так:

Отклик на выбор элемента

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

Что за ko.observable, спросите вы? Это фундаментальная концепция в Knockout. Это значение, за которым UI может «следить» и откликаться на его изменения. В данном случае мы говорим, что UI может видеть значение, представляющее выбранное блюдо, и что исходно оно равно первому вхождению availableMeal (т.е. «стандартному» блюду).

Давайте свяжем chosenMeal с выпадающим списком. Нужно просто обновить атрибут data-bind элемента

Технически теперь оно читает и записывает свойство chosenMeal, но мы не увидим, что хоть что-то происходит, пока не дополним UI. Давайте отобразим описание и цену выбранного блюда:

Эта часть UI будет динамически обновляться при выборе различных элементов выпадающего списка:

Еще раз об отслеживании зависимостей

Еще одно: лучше бы показывать цену в формате денежных единиц. Определим для этого JavaScript-функцию:

…и обновим связывание для его использования…

…после чего UI будет выглядеть несколько лучше:

Форматирование цены показывает, что в связываниях можно использовать произвольный JavaScript, и КО все-таки сможет определить, от каких наблюдаемых элементов зависят связывания. Именно так он узнает, какие части UI надо обновлять при изменениях модели. Он не перерисовывает UI полностью и постоянно – только те части, в которых изменились наблюдаемые элементы.

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

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

Конкурирует ли КО с jQuery (или Prototype и т.п.), или работает совместно с ними?

Все любят jQuery! Это выдающаяся замена неуклюжему и нелогичному DOM API, который мы вынуждены были использовать раньше. jQuery – это прекрасный низкоуровневый способ манипулировать элементами и обработчиками событий на Web-странице. Я, разумеется, использую jQuery для низкоуровневых DOM-мани­пу­ляций. КО решает другую проблему.

Как только UI становится нетривиальным, и обзаводится несколькими пересекающимися поведениями, при использовании одного лишь jQuery все становится запутанным и дорогим в поддержке. Рассмотрим пример: нужно выводить список элементов, указывая число элементов списка, и делать доступной кнопку «Add», только если элементов меньше пяти. В jQuery нет концепции нижележащей модели данных, так что получать число элементов придется, выводя его из количества элементов TR в таблице или числа DIV в соответствующем CSS-классе. Возможно, число элементов выводится в каком-то SPAN, и вам нужно помнить о том, что текст этого SPAN нужно обновить, когда пользователь добавит элемент. Нужно также не забыть отключить кнопку «Add», когда количество TR достигнет 5. Позже, если вас попросят реализовать также кнопку «Delete», вам придется выяснять, какие DOM-элементы изменять по нажатию на нее.

В чем отличия Knockout?

КО все серьезно упрощает. Он позволяет масштабировать сложность, не опасаясь несоответствий. Просто представьте элементы как JavaScript-массив, и затем используйте шаблон для трансформации этого массива в таблицу или набор элементов DIV. При изменениях массива UI также обновится (вам не придется выяснять, как и куда вставлять новые TR). Остальной UI останется без изменений. Например, можно декларативно связать SPAN, выводящий число элементов (и использовать где угодно на странице, не только в шаблоне):

Вот оно! Вам не нужно писать код для его обновления; он обновится сам, когда изменится массив myItems. Аналогично, чтобы сделать доступной или недоступной кнопку «Add» в зависимости от числа элементов, достаточно написать:

Позже, когда вас попросят реализовать функциональность кнопки «Delete», вам не придется выяснять, с какими частями UI она должна взаимодействовать; вы просто заставите ее изменить нижележащую модель данных.

Суммируя: КО не соревнуется с jQuery или аналогичными DOM API. КО дает альтернативный, высокоуровневый способ связать модель данных с UI. Сам КО не зависит от jQuery, но вы, конечно, можете использовать jQuery вместе с ним, и это зачастую полезно, если вы хотите делать такие вещи, как анимированные переходы.

Отслеживаемые значения (Observables)

Knockout строится на трех основных концепциях:

  1. Observables (отслеживаемые значения) и отслеживание зависимостей
  2. Декларативные связывания
  3. Шаблоны

На этой странице рассказывается о первой из трех. Но, прежде чем приступить, разрешите мне рассказать о паттерне MVVM и концепции модели представления (view model).

MVVM и View Model

Model-View-View Model (MVVM) – это паттерн проектирования, применяемый при создании пользовательских интерфейсов. Он описывает, как можно сохранить простоту потенциально сложного UI, разделив его на три части:

  • Модель: данные, хранящиеся приложением. Эти данные представляют объекты и операции предметной области (например, банковские счета, которые могут выполнять перечисление денег), которые не зависимы от любого UI. При использовании КО вы обычно будете выполнять AJAX-вызовы какого-то серверного кода для чтения и записи данных этой сохраненной модели.
  • Модель представления: представление данных и операций в коде. Например, если вы реализуете редактор списка, ваша модель представления будет объектом, содержащим список элементов, и предоставляющим методы для добавления и удаления элементов.

Заметьте, что это не сам UI: здесь нет никаких кнопок или стилей отображения. Это также и не модель с сохранением данных – она содержит несохраненные данные, с которыми работает пользователь. При использовании КО модели представления – это чистые JavaScript-объекты, которые не содержат никаких сведений об HTML. Поддержание абстрактности модели представления – это способ сохранения ее простоты, позволяющий управлять сложным поведением без риска заблудиться.

  • Представление: видимый интерактивный UI, отображающий состояние модели представления. Он отображает информацию из модели представления, отправляет команды модели представления (т.е. нажатия кнопок), и обновляется по мере изменения состояния модели представления.

При использовании КО представление – это просто HTML-документ с декларативной привязкой к модели представления. Альтернативой является использование шаблонов, генерирующих HTML, который использует данные из модели представления.

Чтобы создать модель представления с помощью КО, просто объявите JavaScript-объект, например:

Затем вы можете создать очень простое представление этой модели представления, используя декларативное связывание. Например, следующая разметка выводит значение personName:

Активация Knockout

Атрибут data-bind не является родным для HTML, но это не страшно (он напрямую совместим с HTML 5, и не вызывает проблем в HTML 4, хотя валидатор укажет, что это неопознанный атрибут). Но, поскольку браузер не знает, что он значит, вам нужно активировать Knockout, чтобы этот атрибут заработал.

Чтобы активировать Knockout, добавьте следующую строку в блок

Параметры


  • Основной параметр

Когда значение этого параметр похоже на false (т.е. булево значение false, или числовое значение 0, или null, или undefined), связывание устанавливает yourElement.style.display в none, что приводит к его скрытию. Это имеет приоритет перед любым другим стилем, определенным в CSS.

Когда значение этого параметр похоже на true (т.е. булево значение true, или не равный null объект, или массив), связывание удаляет значение yourElement.style.display, и элемент становится видимым.

При этом будет применен стиль отображения, определенный в CSS (так что правила CSS наподобие display:table-row прекрасно работают с этим связыванием).

  • Если этот параметр – отлеживаемое значение, связывание будет изменять видимость элемента при изменениях этого значения. Если значение параметра не является отслеживаемым значением, видимость элемента будет задана один раз и не будет изменяться в дальнейшем.
  • Дополнительные параметры отсутствуют.

Примечание: используйте функции и выражения для управления видимостью элемента

В качестве значения параметра можно использовать также JavaScript-функции или произвольные JavaScript-выражения. В этом случае КО исполнит функцию или вычислит значение выражения и использует результат для определения видимости элемента.

combine dynamic and static classes through css binding, knockout.js

Posted by: admin February 6, 2018 Leave a comment

In knockout.js we can use css binding for static classes

I’ve tried http://jsfiddle.net/tT9PK/1/ to combine it in something like

to get dynamic class color and static translucent at the same time, but I get an error. Is there a way to do that?

You can add dynamic class by css property and then add static class by attr property

Be sure to add any predefined classes to this binding
attr:

I solved this problem a while back by just cloning the css binding as css2 .

Normally you can’t use the same binding handler twice in a data-bind attribute, so this allowed me to do the following:

I can’t quite decide whether I still prefer this, or @Aleksey’s answer, but this may be the only choice if you have multiple dynamic classes to add.

Correct…and to launch you even further, check out this modification.

Here, you’ll see that not only are we combining the options, but we’re creating our own binding entirely…which results in a much more portable extension of not just this view model, but any view model you may have in your project…so you’ll only need to write this one once!

To invoke this, you just use it as a new data-bind property and can include as many (or as few) options as possible. Under this specific condition, I might have just provided $data, however if you’re wanting a reusable option you need to be more specific as to what data types you need as parameters and not all view models may have the same properties.

Hope this does more than answer your question!

Whereas color is a property with a string value.

If the value of color is an observable then we need to clear the classname before that observable updates. If we do not do this then each change will add another class and not remove the previous one. This can easily be accomplished manually but I wrote an extender for those who are interested.

With this extender, your JavaScript code would look like this:

And your markup would be this simple:

I have a code pen demonstrating this technique:
http://codepen.io/USIUX/pen/WryGZQ

I have also submitted an issue with knockout in hopes that one day the custom extender will not be necessary: https://github.com/knockout/knockout/issues/1990

Nice question, the problem seems to be the binding css isn’t thought to mix the two kinds, color(): color() != » doesn’t work (would be nice).

I like @Simon_waver’s answer approach, simple and practical.

Maybe at the time of the question wasn’t supported (Idk) but with current knockout also combining the classes works: data-bind=»css: computed»

Related Posts

in A-Frame for WebXR? – Stack Overflow» rel=»bookmark»> javascript – Can you adjust the size of in A-Frame for WebXR? – Stack Overflow

Questions: I’m trying to shrink the size of a-scene in A-Frame without having to change the sizes of what is inside of a-scene. In this particular example, i’m displaying code on Magic Lea.

javascript – React-Native Accumulate results from a loop to a single string – Stack Overflow

Questions: I want to extract the data in between the tag and, based on the content, return This is a Text or This is a Picture.

javascript – Nest JS Cannot read property of undefined – Stack Overflow

Questions: My application was working fine, and it stopped after trying to get the documentation with swagger, i think it may be a dependency issue, but can’t find it anywhere. I keep getting th.

Understanding Knockout Binding Context Variable

Basically, binding context is an object that holds data, which is referenced from your view-model bindings. While applying bindings, Knockout automatically creates and manages a hierarchy of binding contexts. Let’s have a look on different types of binding context with example.

The $root Property

The $root context always refers to the top-level ViewModel, regardless of loops or other changes in scope. This allow us to access top-level methods for manipulating the ViewModel.

For example, inside the foreach: shoppingCart loop, $root refers to top-level methods removeProduct of ViewModel as shown below:

The $data Property

The $data binding context refers to the ViewModel object in the current context. It is much more like the this keyword in a JavaScript object.

For example, inside the foreach: shoppingCart loop, $data refers to the current list item as shown below:

The $index Property

Inside of a foreach loop, the $index property contains the current item’s index in the array. Unlike the other binding context properties, $index is an observable and is updated automatically whenever you add or delete an item from the associated observable array.

The $parent Property

The $parent property context refers to the parent ViewModel object. Typically, you will require this prroperty when you will work with nested loops and with in the nested loop, you need to access properties of the outer loop.

For example, if you need to access the Product instance from the inside of the foreach: types loop, you could use the $parent property as shown below:

$parentContext

This refers to the binding context object at the parent level. This is different from $parent, which refers to the data (not binding context) at the parent level.

For example, if you need to access the index value of the outer foreach item with in inner foreach context you could use the $parentContext as shown below:

$parents

This is an array that represent all of the parent view models. This is useful when you need to access the parents with in inner most loops that may nested upto n-level.

$parents[0] is the view model from the parent context (i.e., it’s the same as $parent)

$parents[1] is the view model from the grandparent context

$parents[2] is the view model from the great-grandparent context

All the binding context properties are only available in the view, not in the ViewModel.

Example of Knockout Binding Context ($root,$data,$parent,$index)

Output

Adding Product to Order List

Remove Product from Order List

Checkout Order List

What do you think?

I hope you will enjoy the tips while working with Knockout. I would like to have feedback from my blog readers. Your valuable feedback, question, or comments about this article are always welcome.

Take our free skill tests to evaluate your skill!

In less than 5 minutes, with our skill test, you can identify your knowledge gaps and strengths.

ASP.NET MVC Questions and Answers

ASP.NET MVC is an open source and lightweight web application development framework from Microsoft. This book has been written to prepare yourself for ASP.NET MVC Interview. This book is equally helpful to sharpen their programming skills and understanding ASP.NET MVC in a short time. This book also helps you to get an in-depth knowledge of ASP.NET MVC with a simple and elegant way.

LINQ Questions and Answers

LINQ or Language Integrated Query is a part of the Microsoft Dot Net framework which provides easily understandable data querying facilities to .Net languages such as C#, VB.NET, etc. LINQ is a readable code that can be used as a standard way to extract data from XML documents, arrays, relational databases, and other third-party data sources. LINQ allows us to write queries over local collection objects and remote data sources like SQL, XML documents, etc.

AngularJS Questions and Answers

AngularJS is an open-source JavaScript framework which is developed by Google. This structural framework is developed on model view controller MVC design pattern which helps to create dynamic Web apps and single page application using HTML, CSS and JavaScript. AngularJS creates extended HTML tags that can be used as normal HTML tags and this tag will help you to write efficient code as AngularJS Dependency Injection and Data binding capabilities helps you to eliminate much of the code that you have to write using normal JavaScript.

TypeScript Questions and Answers

TypeScript is a superset of JavaScript developed by Microsoft. This book aims to help you to prepare yourself for Typescript interview questions and answers in a short time and easy way.

JS and ES6 Questions and Answers

JavaScript is the most popular language to create a web application with HTML and CSS, today JavaScript can execute not only in the browser but also on the server. In this book, we are going to learn about the fundamentals of JavaScript like DOM, String, Array, Objects, Events. Error handling and many more.

Читать еще:  Макросы в ассемблере
Ссылка на основную публикацию
ВсеИнструменты 220 Вольт
Adblock
detector