Статьи

Интеграция HTML5 и Wicket

После обсуждения некоторых дебатов о новом iPad от Apple и о будущем Adobe Flash , дискуссия обычно переходила на будущее HTML5 .

Увидев, что мы любим Apache Wicket в Mystic , я подумал, что поиграюсь, чтобы увидеть, насколько сложно начать добавлять поддержку новых тегов HTML5. Есть немало примеров, демонстрирующих холст, геолокацию, хранение и, конечно, видео и аудио.

Первым делом я решил определить тег видео. Он принимает необязательный атрибут src среди других или несколько тегов источника для предоставления различных видеопотоков для выбора браузером. Firefox использует Ogg Vorbis, а Safari использует H.264, поэтому, конечно, производители браузеров все еще не согласны. Вот некоторый код, чтобы использовать то, что я хотел бы видеть из видео компонента:

		final List<MediaSource> mm = new ArrayList<MediaSource>();
mm.add(new MediaSource("/dizzy.mp4", "video/mp4"));
mm.add(new MediaSource("/dizzy.ogv", "video/ogg"));
IModel<List<MediaSource>> mediaSourceList = new AbstractReadOnlyModel<List<MediaSource>>() {
public List<MediaSource> getObject() {
return mm;
}
};
add(new Html5Video("dizzy", mediaSourceList) {
@Override
protected boolean isControls() {
return true;
}
@Override
protected boolean isAutoPlay() {
return true;
}
});


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

public class Html5Video extends Html5Media {
public Html5Video(String id, IModel<List<MediaSource>> model) {
super(id, model);
}
protected int getWidth() { return 0; }
protected int getHeight() { return 0; }
@Override
protected void onComponentTag(final ComponentTag tag) {
if(getWidth()>0) {
tag.put("width", getWidth());
}
if(getHeight()>0) {
tag.put("height", getHeight());
}
super.onComponentTag(tag);
}
protected String getTagName() {
return "video";
}
}

Итак, вы можете видеть, что мы абстрагировали это еще дальше в объект Html5Media, который мы вскоре рассмотрим. На данный момент у нас есть ширина и высота, которые относятся только к видео тегу. И мы также переопределяем onComponentTag, чтобы добавить эти атрибуты в тег видео, если они не равны нулю. Мы также опираемся на некоторые идеи в ядре калитки и реализуем метод в Html5Media для checkComponentTag на основе результатов метода, который может быть переопределен getTagName.

Давайте посмотрим на Html5Media, где мы найдем большую часть мяса:

public class Html5Media extends WebMarkupContainer {
private IModel<List<MediaSource>> sources;
public Html5Media(String id, final IModel<List<MediaSource>> model) {
super(id, model);
this.sources = wrap(model);
add(new Html5UtilsBehavior());
}

Первое, что мы видим, это то, что мы расширяем WebMarkupContainer, в основном потому, что наш компонент может иметь основной текст (полезный для поддержки отступления). Далее вы увидите, что мы добавляем поведение Html5UtilsBehavior. Основная цель — добавить полезный файл javascript в заголовок при работе с браузерами, которые еще не поддерживают HTML5 (Internet Explorer, я смотрю на вас!). Еще немного кода

	@Override
protected void onComponentTag(final ComponentTag tag) {
String tagName = getTagName();
if (tagName != null) {
checkComponentTag(tag, tagName);
}
List<MediaSource> sources = getSources();
if (sources != null && sources.size() == 1) {
MediaSource source = sources.get(0);
tag.put("src", source.getSrc());
}
if (isAutoBuffer()) {
tag.put("autobuffer", true);
}
if (isAutoPlay()) {
tag.put("autoplay", true);
}
if (isLoop()) {
tag.put("loop", true);
}
if (isControls()) {
tag.put("controls", true);
}
// Default handling for component tag
super.onComponentTag(tag);
}
protected String getTagName() {
return null;
}

Здесь мы проверяем тег компонента, чтобы убедиться, что это допустимое имя. Тогда, если у нас есть только один источник, мы добавляем это к тегу video вместо отдельных элементов в теле. Следующая группа операторов извлекает из методов и добавляет к тегу логические атрибуты, если они истинны. И мы предоставляем реализацию getTagName, которая возвращает значение null в качестве разумного значения по умолчанию.

onComponentTagBody — это место, где мы необязательно будем определять теги источника и необязательные атрибуты, которые сопровождают его

	@Override
protected void onComponentTagBody(final MarkupStream markupStream, final ComponentTag openTag) {
List<MediaSource> sources = getSources();
if (sources != null && sources.size() > 1) {
final AppendingStringBuffer buffer = new AppendingStringBuffer();
for (int index = 0; index < sources.size(); index++) {
final MediaSource source = sources.get(index);
buffer.append("\n<source ");
buffer.append("src='");
buffer.append(source.getSrc());
buffer.append("'");
if (source.getType() != null) {
buffer.append(" type='");
buffer.append(source.getType());
buffer.append("'");
}
if (source.getMedia() != null) {
buffer.append(" media='");
buffer.append(source.getMedia());
buffer.append("'");
}
buffer.append(" />");
}
buffer.append("\n");
getResponse().write(buffer.toString());
}
super.onComponentTagBody(markupStream, openTag);
}

 

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

Мы также столкнулись с проблемой добавления реализации Html5Audio, которая состояла из переопределения метода getTagName и возврата аудио. Довольно простые вещи.

Когда мы поместим наш пример на место, мы получим видео с такими элементами управления:

Так что же дальше? Если вы скачали проект, доступный и связанный ниже, он также содержит пример использования аудио компонента. Html5UtilsBehavior дает нам возможность стилизовать CSS новые теги HTML5 даже с помощью Internet Explorer, поэтому наш код может быть более семантическим, вместо того, чтобы засорять его элементами div из-за отсутствия альтернативы. Существует множество дополнительных взаимодействий и поведений, которые можно добавить для поддержки видео и аудио, поддержки canvas, postMessage, хранилища, веб-базы данных. Веб-работники, геолокация, редактирование контента и т. Д. У меня нет причин полагать, что что-либо из этого было бы невозможно интегрировать в разумный компонент с Wicket.

Если вы хотите загрузить пример и запустить его локально или взглянуть на написанные компоненты, я начал проект в Google Code, который называется wicket-html5 . Свяжитесь со мной, если хотите внести свой вклад и начать взламывать некоторые из этих компонентов.

Бесконечность не предел!

С http://wicketbyexample.com