T.M. SoftStudio

feci quod potui, faciant meliora potentes

Купить полную версию книги "Среда разработки Eclipse 4: Руководство разработчика"

Создание GWT-приложений

Пример. Постраничное отображение HTML-контента

Рассмотрим создание GWT-приложения, которое отображает в виде электронной книги набор HTML-файлов с их автоматической разбивкой на страницы.

В среде Eclipse в меню File среды Eclipse выберем команду New | Other | Google | Web Application Project и нажмем кнопку Next. Введем имя проекта и имя пакета, отметим флажок Use Google Web Toolkit и уберем флажок Use Google App Engine, оставим отмеченным флажок Generate project sample code и нажмем кнопку Finish.

В папке src проекта оставим только пакет с файлом .gwt.xml и пакет .client с главным классом приложения.

В gwt.xml файл приложения для работы с HTTP-запросами и XML-контентом добавим наследование модулей:

<inherits name='com.google.gwt.xml.XML'/>

<inherits name="com.google.gwt.http.HTTP"/>

Изменим код главного класса приложения:

package com.tmsoftstudio.client;

import java.util.Iterator;

import com.google.gwt.core.client.EntryPoint;

import com.google.gwt.core.client.GWT;

import com.google.gwt.core.client.JsArrayString;

import com.google.gwt.dom.client.Style.Unit;

import com.google.gwt.event.dom.client.ClickEvent;

import com.google.gwt.event.dom.client.ClickHandler;

import com.google.gwt.event.logical.shared.ValueChangeEvent;

import com.google.gwt.event.logical.shared.ValueChangeHandler;

import com.google.gwt.http.client.Request;

import com.google.gwt.http.client.RequestBuilder;

import com.google.gwt.http.client.RequestCallback;

import com.google.gwt.http.client.RequestException;

import com.google.gwt.http.client.Response;

import com.google.gwt.http.client.URL;

import com.google.gwt.user.client.History;

import com.google.gwt.user.client.ui.Button;

import com.google.gwt.user.client.ui.HTML;

import com.google.gwt.user.client.ui.HorizontalPanel;

import com.google.gwt.user.client.ui.Hyperlink;

import com.google.gwt.user.client.ui.RootLayoutPanel;

import com.google.gwt.user.client.ui.ScrollPanel;

import com.google.gwt.user.client.ui.SplitLayoutPanel;

import com.google.gwt.user.client.ui.VerticalPanel;

import com.google.gwt.user.client.ui.Widget;

import com.google.gwt.xml.client.Document;

import com.google.gwt.xml.client.Element;

import com.google.gwt.xml.client.Node;

import com.google.gwt.xml.client.NodeList;

import com.google.gwt.xml.client.XMLParser;

/**

* Entry point classes define <code>onModuleLoad()</code>.

*/

public class GWT_BookReader implements EntryPoint {

/**

* This is the entry point method.

*/

private String href[];

private VerticalPanel content[];

private int lengthContent;

private int indexContent;

public static native String ajax(String url) /*-{

AJAX=new XMLHttpRequest();

if (AJAX) {

AJAX.open("GET", url, false);

AJAX.send();

return AJAX.responseText;

} else {

return "";

}

}-*/;

public static native JsArrayString parseHTML(String html) /*-{

var PageSize=2000;

html=html.substring(html.indexOf('<body')+5);

html=html.substring(html.indexOf('>')+1,html.indexOf('</body>'));

var listHTML=new Array();

var text=html.replace(/<.*?>/g, '');

var posStart=0;

var posEnd=PageSize;

var posHTML=0;

var posReal=0;

while(posEnd>text.length){

posEnd=posEnd-1;

}

while(posEnd<=text.length){

var i=0;

var target="";

while((target=="")||(html.indexOf(target)==-1)||(target.length==1)||(target.indexOf("\r")!= -1)){

if(posEnd>=text.length) {

posEnd=posEnd-i;

}else{

posEnd=posEnd+i;

}

page=text.substring(posStart,posEnd);

var split = page.split(" ");

target=split[split.length-1];

i++;

}

var j = -1;

var tmpHTML;

var tmpText;

var tmppos;

while ( (j = html.indexOf(target, j+1)) != -1) {

tmpHTML=html.substring(0, j)+target;

tmpText=tmpHTML.replace(/<.*?>/g, '');

tmppos=j;

if(tmpText.length>=page.length){

break;

}

}

tmpHTML=html.substring(0, tmppos);

posReal=posReal+tmpText.lastIndexOf(target);

posStart=posReal;

posEnd=posStart+PageSize;

if(posEnd>text.length){

tmpHTML=html;

listHTML.push(tmpHTML);

break;

}

listHTML.push(tmpHTML);

posHTML=tmppos;

html=html.substring(posHTML);

}

return listHTML;

}-*/;

public void onModuleLoad() {

SplitLayoutPanel panelSp = new SplitLayoutPanel();

ScrollPanel scrollPanelContents = new ScrollPanel();

final VerticalPanel verticalPanelContents = new VerticalPanel();

verticalPanelContents.setSpacing(10);

scrollPanelContents.setWidget(verticalPanelContents);

panelSp.addWest(scrollPanelContents, 200);

final ScrollPanel scrollPanelHTML = new ScrollPanel();

panelSp.add(scrollPanelHTML);

panelSp.getElement().addClassName("border");

RootLayoutPanel rp = RootLayoutPanel.get();

rp.add(panelSp);

rp.setWidgetLeftWidth(panelSp, 2, Unit.PCT, 96, Unit.PCT);

rp.setWidgetTopHeight(panelSp, 2, Unit.PCT, 96, Unit.PCT);

RequestBuilder builderContents = new RequestBuilder(RequestBuilder.GET, URL.encode(GWT.getHostPageBaseURL()+"content/index.html"));

try {

builderContents.sendRequest(null, new RequestCallback() {

public void onError(Request request, Throwable exception) {

}

public void onResponseReceived(Request request, Response response) {

String xml="<?xml version='1.0' encoding='UTF-8'?>"+response.getText();

Document docxml = XMLParser.parse(xml);

NodeList linkList = docxml.getElementsByTagName("a");

lengthContent=linkList.getLength();

href=new String[lengthContent];

for(int i=0; i<lengthContent;i++){

Node link=linkList.item(i);

href[i]=((Element)link).getAttribute("href");

String title=link.getFirstChild().getNodeValue();

Hyperlink hLink = new Hyperlink(title, false, href[i]);

verticalPanelContents.add(hLink);

}

content=new VerticalPanel[lengthContent];

for(indexContent=0;indexContent<lengthContent;indexContent++){

String url=URL.encode(GWT.getHostPageBaseURL()+"content/"+href[indexContent]);

String html=ajax(url);

JsArrayString listHTML=parseHTML(html);

content[indexContent]=new VerticalPanel();

content[indexContent].setSpacing(10);

final HorizontalPanel btnPanel=new HorizontalPanel();

btnPanel.setSpacing(10);

if(listHTML.length()!=1){

content[indexContent].add(btnPanel);

}

final HTML[] wHTML=new HTML[listHTML.length()];

for (int indexPage = 0; indexPage < listHTML.length(); indexPage++) {

String str=listHTML.get(indexPage);

wHTML[indexPage] =new HTML();

wHTML[indexPage].setHTML(str);

if(indexPage==0){

content[indexContent].add(wHTML[indexPage]);

}

Button btnPage = new Button("<b>"+indexPage+"</b>", new ClickHandler() {

public void onClick(ClickEvent event) {

Button btn=(Button) event.getSource();

HorizontalPanel parentH=(HorizontalPanel)btn.getParent();

VerticalPanel parentV=(VerticalPanel) btn.getParent().getParent();

parentV.clear();

parentV.add(parentH);

parentV.add(wHTML[new Integer(btn.getText())]);

Iterator<Widget> arrayOfWidgets = parentH.iterator();

while (arrayOfWidgets.hasNext()){

Widget ch = arrayOfWidgets .next();

if (ch instanceof Button) {

ch.getElement().getStyle().setProperty("color", "black");

}

}

btn.getElement().getStyle().setProperty("color", "blue");

}

});

btnPanel.add(btnPage);

}

if(indexContent==0){

scrollPanelHTML.setWidget(content[0]);

}

}

History.addValueChangeHandler(new ValueChangeHandler<String>() {

public void onValueChange(ValueChangeEvent<String> event) {

String historyToken = event.getValue();

for(indexContent=0;indexContent<lengthContent;indexContent++){

if (historyToken.equals(href[indexContent])) {

scrollPanelHTML.clear();

scrollPanelHTML.setWidget(content[indexContent]);

}

}

}});

String initToken = History.getToken();

if (initToken.length() == 0) {

History.newItem(href[0]);

}

}

});

} catch (RequestException e) {

}

}}

В коде класса GWT_BookReader в методе onModuleLoad() создается SplitLayout-панель, содержащая левую и правую части.

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

Содержимое каждой части SplitLayout-панели упаковывается в Scroll-панель.

Предполагается, что набор HTML-файлов расположен в папке content каталога WAR приложения. При этом папка content содержит файл содержания index.html с гиперссылками <a href=""></a> на HTML-файлы.

Для разбора файла index.html в методе onModuleLoad() с помощью класса RequestBuilder создается HTTP-запрос, загружающий файл index.html, после чего в начало файла index.html добавляется XML-объявление и производится XML-парсинг файла.

В результате XML-парсинга из документа index.html выбираются узлы гиперссылок, которые конвертируются в объекты Hyperlink с их добавлением в левую часть SplitLayout-панели.

После нахождения гиперссылок по каждой из них производится загрузка соответствующего HTML-файла с помощью синхронного Ajax-запроса GWT JSNI-интерфейса, так как если использовать асинхронные запросы, тогда будут трудности с сопоставлением гиперссылки и соответствующего ей HTML-файла.

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

Метод parseHTML() возвращает массив строк HTML-кода, каждая из которых представляет страницу.

Если количество страниц больше одной, тогда в правую часть SplitLayout-панели добавляется панель кнопок для постраничного перехода.

Навигация между Hyperlink-ссылками производится с помощью обработчика событий объекта History.

Код главной HTML-страницы приложения:

<!doctype html>

<html>

<head>

<meta http-equiv="content-type" content="text/html; charset=UTF-8">

<link type="text/css" rel="stylesheet" href="GWT_BookReader.css">

<title>GWT BookReader</title>

<script type="text/javascript" language="javascript" src="gwt_bookreader/gwt_bookreader.nocache.js"></script>

</head>

<body>

<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>

<noscript>

<div style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">

Your web browser must have JavaScript enabled

in order for this application to display correctly.

</div>

</noscript>

</body>

</html>

Код CSS-файла:

h1 {

font-size: 2em;

font-weight: bold;

color: #777777;

margin: 40px 0px 70px;

text-align: center;

}

.border{

border: 2px double silver;

}



GWT и SEO