Встраивание Flash С Помощью Swfobject 2

Вопрос о реализации Flash с использованием разметки, соответствующей стандартам, возникает довольно часто, но у этой проблемы есть достаточно известное решение — SWFObject. SWFObject 2 позволяет встраивать Flash не только динамически, с помощью JavaScript, но и статически, когда для встраивания используется стандартная разметка, а JavaScript исправляет только проблемы, которые невозможно решить с помощью разметки, и даже если JavaScript отключен, пользователи все равно будут видеть Flash. .

Вы можете скачать библиотеку и получить дополнительную информацию по адресу Страница проекта SWFObject в Google Коде.



Что такое SWFObject?

SWF-объект 2:
  • Предоставляет два оптимизированных метода встраивания Flash, основанных на разметке и использующих JavaScript.
  • Предоставляет API JavaScript со всеми возможностями, необходимыми для внедрения SWF-файлов и получения информации о проигрывателе Flash. [ http://code.google.com/p/swfobject/wiki/api ]
  • Использует один небольшой файл JavaScript (размер SWFObject 2.0: 8,7 КБ / в формате GZIP: 3,4 КБ, размер SWFObject 2.1: 9,5 КБ / в формате GZIP: 3,8 КБ)
  • Преемник SWFObject 1.5 [ http://blog.deconcept.com/swfobject/ ] и НЛО [ http://www.bobbyvandersluis.com/ufo/ ]
  • В конечном итоге должен заменить Adobe Flash Player Detection Kit [ http://www.adobe.com/products/flashplayer/download/detection_kit/ ]
  • Объединяет все существующие методы встраивания Flash и претендует на звание нового стандарта встраивания Flash.
  • Проект с открытым исходным кодом Джеффа Стернса, Майкла Уильямса и Бобби ван дер Слейса, ранее известный как SWFFix. http://code.google.com/p/swffix/ ]


Почему вам следует использовать SWFObject?

  • Он более оптимизирован и гибок, чем любой другой способ реализации Flash-плеера.

  • Это универсальное решение для всех: независимо от того, являетесь ли вы разработчиком HTML, Flash или JavaScript, это решение подойдет каждому.

  • Прекращается многолетнее использование разметки, специфичной для браузера, что позволяет использовать стандартную разметку и альтернативный контент.
  • Использует ненавязчивый JavaScript и лучшие практики JavaScript.
  • Легко использовать
Подробное обоснование необходимости использования SWFObject 2 можно найти в статье Flash Embedding Cage Match, опубликованной на сайте A List Apart [ http://www.alistapart.com/articles/flashembedcagematch/ ].



Почему SWFObject использует JavaScript?

SWFObject 2 использует JavaScript в первую очередь для решения проблем, которые не может решить разметка:
  • Определяет версию Flash плеера и в зависимости от результата отображает Flash или альтернативный контент, что предотвращает искажение Flash в плеерах старых версий.

  • Позволяет вернуться к альтернативному контенту с помощью манипуляций с DOM в случае использования Flash-плагина неправильной версии (Примечание: если Flash-плагин не установлен, вместо элемента объекта автоматически отображается вложенный альтернативный контент).

  • Позволяет использовать Adobe Express Install для установки последней версии Flash player.
  • Устранена проблема, из-за которой более старые версии движка Webkit игнорировали вложенные элементы параметров в объекте с помощью собственного элемента внедрения.

    (Это единственный случай, когда используется проприетарная разметка, в будущих версиях она будет удалена)

  • Позволяет публиковать Flash-контент с помощью JavaScript, тем самым устраняя механизмы активации.

  • Предоставляет сложный API JavaScript для выполнения общих действий с проигрывателем Flash и содержимым Flash.


Какой метод публикации предпочтительнее: статический или динамический?

SWFObject 2 позволяет встраивать Flash двумя разными способами:
  1. В статический метод публикации Flash и альтернативный контент реализуются с использованием стандартной разметки, а JavaScript используется для решения проблем, которые невозможно решить с помощью разметки.

  2. Метод динамической публикации основан на замене альтернативного контента на Flash-контент при наличии достаточно новой версии Flash-плеера и поддержке JavaScript.
Преимущества статический метод публикации :
  1. Используется стандартная разметка
  2. Механизм встраивания Flash-контента не зависит от JavaScript, что делает Flash доступным гораздо более широкой аудитории:
Преимущества метод динамической публикации :
  1. Позволяет обходить механизмы активации активного контента в Internet Explorer 6/7 и Opera 9+.

    Обратите внимание, что Microsoft выпустила обновления, устраняющие механизм активации в браузерах Internet Explorer [ http://www.swffix.org/devblog/Эp=19 ]

  2. Прекрасно интегрируется в приложения JavaScript.


Статический метод публикации Flash с использованием SWFObject



Шаг 1. Встраивайте Flash и альтернативный контент с помощью стандартной разметки

SWFObject использует метод вложенных объектов (с условными комментариями для Internet Explorer) [ http://www.alistapart.com/articles/flashembedcagematch/ ] это самая оптимальная кроссбраузерная разметка, соответствующая стандартам и позволяющая задавать альтернативный контент [ http://www.swffix.org/testsuite/ ]:
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" " http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd ">
 
 <html xmlns=" http://www.w3.org/1999/xhtml " lang="en"  xml:lang="en ">
   <head>
     <title>SWFObject - step 1</title>
 
     <meta http-equiv="Content-Type" content="текст/html; кодировка = iso-8859-1" />
   </head>
   <body>
     <div>
 
       <object classid=" clsid:D27CDB6E-AE6D-11cf-96B8-444553540000 " width="780" height="420">
         <param name="movie" value="myContent.swf" />
 
         <!--[if !IE]>-->
         <object type="application/x-shockwave-flash" data="myContent.swf" width="780" height="420">
 
         <!--<![endif]-->
           <p>Alternative content</p>
         <!--[if !IE]>-->
         </object>
         <!--<![endif]-->
 
       </object>
 
     </div>
   </body>
 </html>
Примечание: Метод вложенного объекта требует дублирования объявления объекта (внешний объект предназначен для Internet Explorer, а внутренний объект для других браузеров), поэтому, если вам нужно определить атрибуты или параметры для объекта, их необходимо продублировать для внешнего и внутреннего объектов.

.

Обязательные атрибуты:

  • classid (только для внешнего объекта, значение всегда clsid:D27CDB6E-AE6D-11cf-96B8-444553540000)
  • тип (только для внутреннего объекта, значение всегда равно application/x-shockwave-flash)
  • данные (только для внутреннего объекта, указывает URL-адрес SWF-файла)
  • ширина (для обоих элементов объекта указывает ширину SWF)
  • высота (для обоих элементов объекта определяет высоту SWF)
Обязательные элементы параметров:
  • фильм (только для элемента внешнего объекта, указывает URL-адрес SWF-файла)
Примечание: Мы рекомендуем не использовать атрибут codebase для указания URL-адреса для установки Flash с серверов Adobe, поскольку это противоречит спецификации, ограничивающей доступ к домену текущего документа.

Вместо этого используйте альтернативный контент с сообщением о том, что пользователь может получить полную версию, установив плагин Flash.

Как использовать HTML для настройки Flash-контента?

Вы можете использовать необязательные атрибуты объекта [ element http://www.w3schools.com/tags/tag_object.asp ]:
  • идентификатор
  • имя
  • сорт
  • выровнять
Вы можете использовать специфичные для Flash элементы param[ http://www.adobe.com/cfusion/knowledgebase/index.cfmЭid=tn_12701 ]:

Зачем нам альтернативный контент?

Элемент объекта может содержать альтернативный контент, который будет отображаться, если проигрыватель Flash не установлен или не поддерживается.

Альтернативный контент доступен поисковым системам, поэтому он может стать хорошим инструментом при оптимизации сайта для поисковых систем.

Альтернативный контент нужен, если вы хотите сделать сайт доступным для пользователей, не использующих плагины [ http://www.adobe.com/devnet/flash/articles/progressive_enhancement_03.html ], хорошо индексируется поисковыми системами [ http://www.adobe.com/devnet/flash/articles/progressive_enhancement_04.html ] и ненавязчиво показывая пользователям, что они смогут увидеть его во всей красе, если установят плагин Flash.

Шаг 2. Подключение библиотеки SWFObject

Библиотека SWFObject состоит из одного внешнего файла JavaScript. Код SWFObject выполняется сразу после загрузки его файла, манипуляции с DOM выполняются после загрузки DOM, в поддерживающих это браузерах, таких как IE, Firefox, Safari и Opera 9+, или при загрузке в других случаях:
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" " http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd ">
 
 <html xmlns=" http://www.w3.org/1999/xhtml " lang="en"  xml:lang="en ">
   <head>
     <title>SWFObject - step 2</title>
 
     <meta http-equiv="Content-Type" content="текст/html; кодировка = iso-8859-1" />
 
     <script type="text/javascript" src="swfobject.js"></script>
 
   </head>
   <body>
     <div>
       <object classid=" clsid:D27CDB6E-AE6D-11cf-96B8-444553540000 " width="780" height="420">
 
         <param name="movie" value="myContent.swf" />
         <!--[if !IE]>-->
         <object type="application/x-shockwave-flash" data="myContent.swf" width="780" height="420">
 
         <!--<![endif]-->
           <p>Alternative content</p>
         <!--[if !IE]>-->
         </object>
         <!--<![endif]-->
 
       </object>
     </div>
   </body>
 </html>


Шаг 3. Зарегистрируйте свой Flash-контент и установите параметры.

Сначала добавьте уникальный идентификатор к элементу внешнего объекта, который определяет содержимое Flash, затем вам нужно вызвать метод swfobject.registerObject со следующими аргументами:
  1. Первый аргумент (обязательный String) — это идентификатор, используемый в разметке.

  2. Второй аргумент (обязательный String) — это необходимая версия Flash player. Если установлена более старая версия Flash player, SWFObject вынужден отображать альтернативное содержимое (выполняются манипуляции с DOM).

    Номер версии проигрывателя Flash обычно содержит четыре элемента major.minor.release.build, SWFObject работает только с первыми тремя цифрами, следовательно, «WIN 9,0,18,0» (IE) и «Shockwave Flash 9 r18» (все остальные браузеры) будут преобразованы в «9.0.18».

  3. Третий аргумент (строка, необязательный) используется для активации экспресс-установки Adobe [ http://www.adobe.com/cfusion/knowledgebase/index.cfmЭid=6a253b75 ] и должен быть равен URL-адресу SWF-файла экспресс-установки.

    Экспресс-установка отображает стандартное диалоговое окно загрузки плагина Flash вместо содержимого Flash, если необходимая версия плагина не установлена.

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

    Обратите внимание, что экспресс-установка работает только один раз (при первом запуске), требуется Flash player версии 6.0.65 или выше на платформах Win или Mac, минимально возможный размер SWF для работы — 310x137px.

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" " http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd ">
 
 <html xmlns=" http://www.w3.org/1999/xhtml " lang="en"  xml:lang="en ">
   <head>
     <title>SWFObject - step 3</title>
 
     <meta http-equiv="Content-Type" content="текст/html; кодировка = iso-8859-1" />
     <script type="text/javascript" src="swfobject.js"></script>
 
     <script type="text/javascript">
     swfobject.registerObject("myId", "9.0.0", "expressInstall.swf");
     </script>
 
   </head>
 
   <body>
     <div>
 
       <object id="myId" classid=" clsid:D27CDB6E-AE6D-11cf-96B8-444553540000 " width="780" height="420">
 
         <param name="movie" value="myContent.swf" />
         <!--[if !IE]>-->
         <object type="application/x-shockwave-flash" data="myContent.swf" width="780" height="420">
 
         <!--<![endif]-->
           <p>Alternative content</p>
         <!--[if !IE]>-->
         </object>
         <!--<![endif]-->
 
       </object>
     </div>
   </body>
 </html>


Совет

  • Используйте генератор HTML и JavaScript SWFObject для автоматического создания кода [ http://code.google.com/p/swfobject/wiki/generator ]
  • Чтобы вставить несколько SWF-файлов, просто повторите шаги 1 и 3.
  • Самый простой способ получить объект активного элемента — использовать API JavaScript: swfobject.getObjectById(objectIdStr) [ http://code.google.com/p/swfobject/wiki/api ]


Метод динамической публикации с использованием SWFObject



Шаг 1. Создайте альтернативный контент, используя стандартную разметку

Метод динамической публикации следует принципам постепенного улучшения [ http://www.adobe.com/devnet/flash/articles/progressive_enhancement.html ] и заменяет альтернативное содержимое HTML содержимым Flash, если имеется достаточная поддержка JavaScript и Flash. При использовании метода динамической публикации необходимо создать HTML-контейнер с альтернативным контентом и задать для него идентификатор:
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" " http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd ">
 
 <html xmlns=" http://www.w3.org/1999/xhtml " lang="en"  xml:lang="en ">
   <head>
     <title>SWFObject dynamic embed - step 1</title>
 
     <meta http-equiv="Content-Type" content="текст/html; кодировка = iso-8859-1" />
   </head>
   <body>
 
     <div id="myContent">
 
       <p>Alternative content</p>
     </div>
 
   </body>
 </html>


Шаг 2. Подключение библиотеки SWFObject

Библиотека SWFObject состоит из одного внешнего файла JavaScript. Код SWFObject выполняется сразу после загрузки его файла, манипуляции с DOM выполняются после загрузки DOM, в поддерживающих это браузерах, таких как IE, Firefox, Safari и Opera 9+, или при загрузке в других случаях:
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" " http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd ">
 
 <html xmlns=" http://www.w3.org/1999/xhtml " lang="en"  xml:lang="en ">
   <head>
     <title>SWFObject dynamic embed - step 2</title>
 
     <meta http-equiv="Content-Type" content="текст/html; кодировка = iso-8859-1" />
 
     <script type="text/javascript" src="swfobject.js"></script>
 
   </head>
   <body>
     <div id="myContent">
       <p>Alternative content</p>
     </div>
 
   </body>
 </html>


Шаг 3. Встраивание SWF с помощью JavaScript

swfobject.embedSWF(swfUrl, id, width, height, version, expressInstallSwfurl, flashvars, params, Attributes) этот метод имеет пять обязательных и четыре дополнительных параметра:
  1. wfUrl (обязательное поле — строка) URL-адрес SWF-файла.

  2. id (строка, обязательная) идентификатор элемента HTML (содержащего альтернативный контент), который следует заменить содержимым Flash.
  3. ширина (строка, обязательная) Ширина SWF
  4. height (строка, обязательная) Высота SWF
  5. version (строка, обязательная) версия Flash player, необходимая для этого SWF (формат: «major.minor.release»)
  6. expressInstallSwfurl (строка, необязательно) указывает URL-адрес SWF-файла экспресс-установки и активирует экспресс-установку Adobe [ http://www.adobe.com/cfusion/knowledgebase/index.cfmЭid=6a253b75 ].

    Обратите внимание, что экспресс-установка работает только один раз (при первом запуске), требуется Flash player версии 6.0.65 или выше на платформах Win или Mac, минимально возможный размер SWF для ее работы — 310x137 пикселей.

  7. flashvars (строка, необязательно) переменные, передаваемые во Flash как пары «имя: значение».

  8. params (строка, необязательно) — элементы params, вложенные в объект как пары «имя: значение».

  9. атрибуты (строка, необязательно) атрибуты элемента объекта в виде пары имя: значение.

Примечание: Вы можете опустить необязательные параметры при условии, что это не изменит порядок параметров.

Если вы не хотите использовать необязательный параметр, но хотите использовать параметр, следующий за ним, просто установите для него значение false. Параметры flashvars, params и атрибуты являются объектами JavaScript, их можно пропустить не только с помощью описанного выше метода, но и передав пустой объект: {}.

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" " http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd ">
 
 <html xmlns=" http://www.w3.org/1999/xhtml " lang="en"  xml:lang="en ">
   <head>
     <title>SWFObject dynamic embed - step 3</title>
 
     <meta http-equiv="Content-Type" content="текст/html; кодировка = iso-8859-1" />
     <script type="text/javascript" src="swfobject.js"></script>
 
 
     <script type="text/javascript">
     swfobject.embedSWF("myContent.swf", "myContent", "300", "120", "9.0.0");
     </script>
 
   </head>
   <body>
     <div id="myContent">
       <p>Alternative content</p>
     </div>
 
   </body>
 </html>


Настройка Flash-контента

Вы можете использовать необязательные атрибуты объекта [ element http://www.w3schools.com/tags/tag_object.asp ]:
  • id (если id не определен, элемент объекта автоматически наследует идентификатор альтернативного контейнера содержимого)
  • имя
  • styleclass (используется вместо class, поскольку это ключевое слово в ECMA4)
  • выровнять
Вы можете использовать специфичные для Flash элементы param[ http://www.adobe.com/cfusion/knowledgebase/index.cfmЭid=tn_12701 ]:

Как установить переменные, параметры и атрибуты с помощью объектов JavaScript?

Вы можете создавать объекты JavaScript, используя литерал объекта:
 <script type="text/javascript">
 
 var flashvars = {};
 var params = {};
 var attributes = {};
 
 swfobject.embedSWF("myContent.swf", "myContent", "300", "120", "9.0.0",
                    "expressInstall.swf", flashvars, params, attributes);
 
 </script>
Пары имя:значение можно добавлять при создании объекта (примечание: не ставьте запятую после пары фамилия:значение):
 <script type="text/javascript">
 
 var flashvars = {
   name1: "hello",
   name2: "world",
   name3: "foobar"
 };
 var params = {
   menu: "false"
 };
 var attributes = {
   id: "myDynamicContent",
   name: "myDynamicContent"
 };
 
 swfobject.embedSWF("myContent.swf", "myContent", "300", "120", "9.0.0",
                    "expressInstall.swf", flashvars, params, attributes);
 
 
 </script>
Или после него:
 <script type="text/javascript">
 
 var flashvars = {};
 flashvars.name1 = "hello";
 flashvars.name2 = "world";
 flashvars.name3 = "foobar";
 
 var params = {};
 params.menu = "false";
 
 var attributes = {};
 attributes.id = "myDynamicContent";
 attributes.name = "myDynamicContent";
 
 swfobject.embedSWF("myContent.swf", "myContent", "300", "120", "9.0.0",
                    "expressInstall.swf", flashvars, params, attributes);
 
 
 </script>
Это можно записать в одну строку так:
 <script type="text/javascript">
 
 swfobject.embedSWF("myContent.swf", "myContent", "300", "120", "9.0.0",
                    "expressInstall.swf", {name1:"hello",name2:"world",name3:"foobar"},
                    {menu:"false"}, {id:"myDynamicContent",name:"myDynamicContent"});
 
 
 </script>
Если вы не хотите использовать необязательный аргумент, вы можете передать false или пустой объект (Примечание: для SWF-объект 2.1 Вы также можете использовать ноль или 0):
 <script type="text/javascript">
 
 var flashvars = false;
 var params = {};
 var attributes = {
   id: "myDynamicContent",
   name: "myDynamicContent"
 };
 
 swfobject.embedSWF("myContent.swf", "myContent", "300", "120", "9.0.0",
                    "expressInstall.swf", flashvars, params, attributes);
 
 
 </script>
Объект flashvars предназначен для упрощения работы с переменными, передаваемыми во Flash; если хотите, вы можете игнорировать это и передавать flashvars через объект params:
 <script type="text/javascript">
 
 var flashvars = false;
 var params = {
   menu: "false",
   flashvars: "name1=hello&name2=world&name3=foobar"
 };
 var attributes = {
   id: "myDynamicContent",
   name: "myDynamicContent"
 
 };
 
 swfobject.embedSWF("myContent.swf", "myContent", "300", "120", "9.0.0",
                    "expressInstall.swf", flashvars, params, attributes);
 
 </script>


Совет

  • Используйте генератор HTML и JavaScript SWFObject для автоматического создания [ http://code.google.com/p/swfobject/wiki/generator ]
  • Чтобы вставить несколько SWF-файлов, просто повторите шаги 1 и 3.


Переход с SWFObject 1.5 на SWFObject 2

  1. SWFObject 2 НЕ имеет обратной совместимости с SWFObject 1.5.
  2. Предпочтительно весь код JavaScript должен находиться в разделе head.
  3. Имя библиотеки теперь написано строчными буквами: swfobject вместо SWFObject.
  4. Методы доступны только через библиотеку (вместо экземпляра SWFObject в SWFObject 1.5).

  5. API совершенно новый: [ http://code.google.com/p/swfobject/wiki/api ]
  6. SWFObject 2 полностью заменяет указанный блок HTML альтернативным содержимым, включая элемент контейнера, если имеется достаточная поддержка Flash и JavaScript, а SWFObject 1.5 заменяет только содержимое указанного контейнера.

    Если вы не укажете атрибут id явно, элемент объекта автоматически наследует идентификатор указанного контейнера альтернативного содержимого HTML.



Переход от НЛО к SWFObject 2

  1. SWFObject 2 заменяет указанный блок HTML альтернативным содержимым полностью, включая элемент контейнера, если имеется достаточная поддержка Flash и JavaScript, тогда как UFO заменяет только содержимое указанного контейнера.

    Если вы не укажете атрибут id явно, элемент объекта автоматически наследует идентификатор указанного контейнера альтернативного содержимого HTML.

  2. setcontainercss отсутствует в SWFObject 2, аналогичная функциональность обеспечивается SWFObject JavaScript API: swfobject.createCSS(selStr, declStr) [ http://code.google.com/p/swfobject/wiki/api ]


Поддерживает ли SWFObject 2 тип MIME application/xhtml+xml?

SWFObject 2 НЕ поддерживает типы XML MIME, это осознанное решение.

Есть несколько причин, по которым мы их не поддерживаем:

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

    Internet Explorer не поддерживает его, и все остальные крупные производители браузеров больше склоняются к новому стандартному способу анализа HTML (в HTML 5), отходя от анализа HTML как XML, как его видит W3C.

  • Устранив поддержку типов XML MIME, мы уменьшили размер файла и упростили тестирование и поддержку.

Дополнения, предложенные в комментариях:

Инструменты для реализации Flash в популярных JS-фреймворках

jQuery — Плагин jQuery Flash мутулы - Свифф

WMODE

Параметр, заслуживающий особого упоминания.

wmode может принимать следующие значения: окно, непрозрачный, прозрачный и определяет режим отображения Flash на веб-странице.

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

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

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

К сожалению, wmode не решает проблему с перекрытием флэш-видео других элементов в Linux, по крайней мере в FF3 он ее точно не решает. Еще раз ссылка на описание всех параметров http://kb.adobe.com/selfservice/viewContent.doЭexternalId=tn_12701&sliceId=1 Источник перевода: Дизайн для мастеров Теги: #flash #JavaScript #HTML #swfobject #разработка сайтов

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.