<object>, <embed> и валидный код
В детстве нас всех учили, что для встраивания флэша на страницу нужно пользоваться тегами object
и embed
. Объясняли это тем, что object
используется Internet Explorer'ом на винде, а браузеры, основанные на Netscape понимают только embed
.
Казалось бы, вставляй оба тега и будет счастье. Только вот счастья нет, потому что embed
— это нестандартный тег, которого нет в спецификации HTML4.01 / XHTML1.0. (однако, он включён в черновик HTML5).
Но это ещё не вся шокирующая правда. Дело в том, что все более-менее современные браузеры поддерживают стандартный тег object
.
В своём блоге я часто использую флэш, чтобы показывать видяшки и вставлять музыку. При этом я просто копирую под плеера с сайта и вставляю его в запись, либо использую oembed
(о котором я скоро напишу заметку). В большинстве случаев этот кусок кода содержит оба тега, а иногда и вовсе только embed
.
Все знают, что валидный HTML код — это мой пунктик. Поэтому я не стал терпеть этих невалидных корявок в своём собственном блоге и решил разобраться. Погуглив, я нашёл рецепт (написанный аж в 2002 году), описывающий, как вставлять объекты на страницу, используя при этом только валидный код. Вкратце суть его такова:
- Для тега
object
нужно указать атрибутtype
, напримерtype="application/x-shockwave-flash"
- Также для
object
нужно указать атрибутdata
. В нём указывается URL объекта, который вы хотите вставить - После этого нужно удалить тег
embed
нафиг
Чтобы не заниматься такой чисткой вручную, я написал простенькую функцию, которая автоматически исправляет HTML код перед отображением на странице. Вот она:
from BeautifulSoup import BeautifulSoup, Tag
def fix_embeds(value):
soup = BeautifulSoup(value)
for object in soup.findAll("object"):
movie = None
for param in object.findAll("param"):
if param["name"] == "movie":
movie = param["value"]
embeds = object.findAll("embed")
if embeds:
embed = embeds[0]
else:
embed = None
data = object.get("data")
if not data:
if movie:
object["data"] = movie
elif embed and embed.get("src"):
object["data"] = embed["src"]
else:
continue
if not object.get("type") and embed.get("type"):
object["type"] = embed["type"]
del object["classid"]
for embed in object.findAll("embed"):
embed.extract()
for embed in soup.findAll("embed"):
src = embed.get("src")
type = embed.get("type")
if not src or not type:
continue
width = embed.get("width")
height = embed.get("height")
object = Tag(soup, "object")
object["data"] = src
object["type"] = type
if width:
object["width"] = width
if height:
object["height"] = height
embed.replaceWith(object)
return unicode(soup)
На её основе можно, например, сделать фильтр для шаблонов Django.
Обратите внимание, что я принудительно удаляю атрибут classid
из тегов object
. Его назначение остаётся для меня загадкой, однако если он присутствует, то не отображается музыкальный проигрыватель с Jamendo.
Пользуйтесь на здоровье. Если обнаружите какие-то косяки — пишите.
P.S. Теперь у меня полностью валидный бложек.