В данной статье рассматривается создание на JSP-странице GAE-приложения галереи фотографий, наполняемой с помощью Entity-сущностей, хранящихся в Datastore-хранилище, а также самих изображений, хранящихся в Blobstore-хранилище платформы Google App Engine.

На JSP-странице приложения создадим блок кода:
 
<%@ page import="com.google.appengine.api.datastore.*" %>
<%@ page import="com.google.appengine.api.datastore.Query.*" %>
<%@ page import="com.google.appengine.api.blobstore.*" %>
<%@ page import="com.google.appengine.api.images.*" %>
<%@page import="java.util.*"%>
<div id="all_img">
<div id="all_img_count"></div>
 
 
<div id="btn_all_img_list_prev" >&#60;&#60;</div>
 
 
<div id="all_img_content" >
<%
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
ImagesService imagesService = ImagesServiceFactory.getImagesService();
Query qUsersImage = new Query("UsersImage");
PreparedQuery pq = datastore.prepare(qUsersImage);
List<Entity> list = pq.asList(FetchOptions.Builder.withDefaults());
if(!list.isEmpty()){
for (Entity result : list) {
String album = (String)result.getProperty("album");
BlobKey blobkey=(BlobKey) result.getProperty("blobKey");
String blobkeyToString=blobkey.getKeyString();
String url = imagesService.getServingUrl(ServingUrlOptions.Builder.withBlobKey(blobkey).imageSize(400));
String name=(String)result.getProperty("name");
%>
<figure class="all_img" >
<label class="all_img_label"><%=album %></label>
<div><img src="<%=url %>" alt=""/></div>
<figcaption class="all_img_label"><%=name %></figcaption>
<label class="blobkeyToString" style="display:none;"><%=blobkeyToString %></label>
</figure>
 
 
<%
}
%>
</div>
 
 
<div id="btn_all_img_list_next">&#62;&#62;</div>
</div>
<%
}
%>
В вышеприведенном коде блок «all_img_content» окружен справа и слева стрелками «<<» и «>>», при клике на которые изображения будут перелистываться.
 
В блоке «all_img_content» динамически с помощью запроса к Datastore-хранилищу GAE-платформы формируются блоки «figure», содержащие название альбома изображения, само изображение и название изображения.
 
Entity-сущности типа «UsersImage», хранящиеся в Datastore-хранилище, содержат BlobKey-ключ изображения, в свою очередь хранящегося в Blobstore-хранилище GAE-платформы, название альбома изображения и название самого изображения.
 
После извлечения BlobKey-ключа изображения из UsersImage-сущности, с помощью GAE-сервиса Images создается URL-адрес изображения, размер которого уменьшается до 400 пикселей.
 
CSS-стиль созданного блока «all_img»:
 
figure {
display: none;
float: left;
margin: 0px 10px 10px 0px;
text-align: center;
}
 
 
figcaption {
color: #8B0000;
font-weight:bold;
width:150px;
}
 
 
#all_img{
text-align:right;
border-color:#972509;
border-width:2px;
border-style:solid;
background-color:#000;
width:500px;
height:500px;
margin-left:75px;
padding-bottom:20px;
}
 
 
#all_img_count {
color:#fff;
font-size:16px;
margin-left:20px;
text-align: left;
padding-top:10px;
}
#all_img_content{
float:left;
}
#btn_all_img_list_prev{
color:#fff;
float:left;
cursor:pointer;
font-size:20px;
height:50px;
}
#btn_all_img_list_next{
color:#fff;
cursor:pointer;
font-size:20px;
height:50px;
}
.all_img{
margin-left:26px;
cursor:pointer;
}
.all_img_label{
color:#fff;
width:400px;
overflow: hidden;
text-align: center;
}
CSS-стиль определяет наличие рамки вокруг всего блока «all_img», а также расположение блоков «btn_all_img_list_prev», «all_img_content» и «btn_all_img_list_next» в один ряд с помощью свойства float:left.
 
Первоначально все блоки «figure» скрыты.
 
При отображении блока «all_img» запускается JQuery-код:
 
var length=$('.all_img').length;
$('#all_img_count').html('1/'+length);
$('.all_img').hide();
$('.all_img').first().show();
var heightFoto=[];
$('.all_img').each(function(index) {
var height=$(this).height();
heightFoto[index]=height;
});
var j=0;
for(var i=0;i<heightFoto.length;i++)
{
if(heightFoto[i]>heightFoto[j])
j=i;
}
var height=heightFoto[j];
var heightContent=$('#content').height();
if(heightContent<500){
$('#content').css('height','500px');
}
$('#all_img').css('height',height+20+'px');
$('#btn_all_img_list_prev').css('padding-top',(height-50)/2+'px');
$('#btn_all_img_list_next').css('padding-top',(height-50)/2+'px');
 
 
В вышеприведенном коде вычисляется количество блоков «figure», затем полученная цифра передается в блок «all_img_count» для отображения.
 
Первый блок «figure» отображается и вычисляется максимальная высота всех блоков «figure», чтобы затем подогнать высоту блока «all_img» и высоту его родительского блока «content» под полученную максимальную высоту.
 
Стрелки «<<» и «>>» выравниваются на середину блока «all_img».
 
Перелистывание изображений обеспечивает следующий JQuery-код:
 
$("#btn_all_img_list_prev").click(function() {
var i='';
var j='';
var el=[];
$('.all_img').each(function(index) {
el[index]=$(this);
if($(this).css('display')!='none'){
i=index;
}
});
if(i!=0){
el[i].hide('slow');
j=i-1;
$('#btn_all_img_list_prev').hide('slow');
el[j].show('slow');
$('#btn_all_img_list_prev').show('slow');
var length=$('.all_img').length;
$('#all_img_count').html((j+1)+'/'+length);
}
});
 
 
$("#btn_all_img_list_next").click(function() {
var i='';
var j='';
var el=[];
$('.all_img').each(function(index) {
el[index]=$(this);
if($(this).css('display')!='none'){
i=index;
}
});
if(i!=(el.length-1)){
el[i].hide('slow');
j=i+1;
$('#btn_all_img_list_next').hide('slow');
el[i+1].show('slow');
$('#btn_all_img_list_next').show('slow');
var length=$('.all_img').length;
$('#all_img_count').html((j+1)+'/'+length);
}
});
 
 
В вышеприведенном коде вычисляется индекс отображаемого блока «figure», затем данный блок «figure» скрывается, а отображается блок «figure» с предыдущим или следующим индексом.