PDA

View Full Version : Image gallery component with Ext.List



iSmartDevice
22 May 2012, 12:53 PM
Hi,
I just wanted to share the image gallery component with you. It might be useful for those who need.

http://www.appshowcase.net/apps/gallery/

35516
It is based on the image gallery in "airbnb.com" and still needs to be upgraded. If you have a better idea to implement the image gallery, do not hesitate to update it.


Ext.define("Gallery.view.Main", { extend: 'Ext.tab.Panel',
requires: [
'Ext.TitleBar',
'Gallery.view.ImageGallery'
],
config: {
tabBarPosition: 'bottom',


items: [
{
title: 'Gallery',
iconCls: 'action',


items: [
{
docked: 'top',
xtype: 'titlebar',
title: 'Gallery',
style: 'margin-bottom:10px',
},
{
xtype: 'imageGallery',
style: 'margin:10px',
scrollable: false,
store: {
data:[
{photo: 'http://2.bp.blogspot.com/-SwRvvHer_wQ/T6GhgnQoS0I/AAAAAAAHhkY/iyxaoyoC-2g/s800/Kia-K9-01.jpg'},
{photo: 'http://4.bp.blogspot.com/-8iGyCfFuLuU/T5QA-1t4QTI/AAAAAAAAAXg/izbeFI2PvC0/s1600/korea.jpg'},
{photo: 'http://www.dynamicdrive.com/cssexamples/media/ocean.jpg'},
{photo: 'http://media.lonelyplanet.com/lpi/24744/24744-14/469x264.jpg'},
{photo: 'http://3.bp.blogspot.com/-kyrXb2orUgA/Te9KO0AxR5I/AAAAAAAAErY/X_XkbgU107Q/s1600/Blue_Ocean_17723522_std.jpg'},
{photo: 'http://1.bp.blogspot.com/-iOPb28o8svc/TpvN-dWORKI/AAAAAAAAAuw/8pPLujrCSQ0/s1600/toronto.jpg'},
{photo: 'http://www.nyspsych.org/SiteCollectionImages/NYCSkylinelandingpage.jpg'},
{photo: 'http://www.ebaytemplate.info/wp-content/gallery/germany/elbe-river-dresden-germany.jpg'},
{photo: 'http://www.feratel.com/uploads/pics/Italien_1_01.jpg'},
{photo: 'http://blog.educationusa.or.kr/wp-content/uploads/2008/07/dokdo-islets.jpg'},
{photo: 'http://www.yarbridgeinn.co.uk/user/sites/yarbridgeinn.co.uk/files/UK%20Travel%20on%20a%20Shoestring%20Budget.jpg'},
{photo: 'http://villaluxe.com/wp-content/gallery/pamillaretreat/maxico-palmilla-04.jpg'},
{photo: 'http://www.cbrconnection.com/agent_files/Hawaii%20web9.jpg'},
],
},
},
]
}
]
}
});


.galleria-image-nav-right:hover, .galleria-image-nav-left:hover {
opacity: .8;
-ms-filter: "alpha(opacity=80)";
filter: alpha(opacity=80);
}


.galleria-image-nav-left, .galleria-image-nav-right {
cursor: pointer;
width: 23px;
height: 56px;
/*position: absolute;
z-index: 2;*/
background-position: 0 0;
background-image: url(../images/slideshow-arrows.png);
background-repeat: no-repeat;
}


.galleria-image-nav-left {
-moz-border-radius-topleft: 3px;
-moz-border-radius-bottomleft: 3px;
-webkit-border-radius: 3px 0 0 3px;
border-radius: 3px 0 0 3px;
}


.galleria-image-nav-right {
/*position: absolute;*/
-moz-border-radius-topright: 3px;
-moz-border-radius-bottomright: 3px;
-webkit-border-radius: 0 3px 3px 0;
border-radius: 0 3px 3px 0;
left: auto;
right: 0;
background-position: -23px 0;
z-index: 2;
}


.galleria-image-nav-left:active
{
background-position:-46px top;
}


.galleria-image-nav-right:active
{
background-position:-69px top;
}


.galleria .x-list-normal .x-list-item:first-child .x-list-item-label {
border-top: 0;
}


.galleria .x-list-normal .x-list-item .x-list-item-label {
border-top: 0;
}


.galleria .x-list-normal .x-list-item:last-child .x-list-item-label {
border-bottom: 0;
}


.galleria .x-list-item
{
background: white;
padding: 2px;
border: 1px solid #BABABA;
height: 46px;
width: 46px;
margin: 5px 0 5px 5px;
float: left;
cursor: pointer;
/*z-index: 2;*/
}


.galleria .x-list-item img
{
display: block;
width: 40px;
height: 40px;
top: 0px;
left: 0px;
position:absolute;
top: 2px!important;
left: 2px!important;
}


.galleria .gallery-image-selected {
background: #EE2A96;
border-color: #AE0061;
-moz-box-shadow: 0 0 4px 3px rgba(255,94,188,0.6);
-webkit-box-shadow: 0 0 4px 3px rgba(255,94,188,0.6);
box-shadow: 0 0 4px 3px rgba(255,94,188,0.6);
}


.galleria .x-img {
background-repeat: no-repeat;
background-size: auto 100%;
background-position: center;
border:solid 1px #d0d0d0;
}


Ext.define('Gallery.view.ImageGallery', { extend: 'Ext.Container',
xtype: 'imageGallery',
requires: [
'Ext.Img',
],

config:{
cls: 'galleria',
listeners:{
painted: 'onPainted',
},

items:[
{
xtype: 'image',
which: 'galleria_image',
height: Ext.os.is.Phone ? '10em' : '20em',
},
{
xtype:'panel',
layout: 'hbox',
style: 'border: 1px solid #D0D0D0;margin-top:5px',

items: [
{
xtype:'button',
which: 'nav_left',
nav_direction: 1,
cls: 'galleria-image-nav-left',
style: 'border:0',
pressedCls: '',
},
{
//give it an xtype of list for the list component
xtype: 'list',
which: 'thumnail_list',
flex: 1,
padding: '0 0 0 0',
scrollable: {
direction: 'horizontal',
directionLock: true
},
selectedCls : 'gallery-image-selected',
pressedCls: '',
inline: {
wrap: false
},
//set the itemtpl to show the fields for the store
/*itemTpl: '<img src="{photo}" style="display: block; width: 40px; height: 40px; top: 0px; left: 0px; opacity: 0.6;">',*/
itemTpl: '<img src="{photo}">',
},
{
xtype:'button',
which: 'nav_right',
nav_direction: 2,
cls: 'galleria-image-nav-right',
pressedCls: '',
style: 'border:0',
}
]
}
],

store: null
},

galleria_image: null,
thumnail_list: null,
nav_left: null,
nav_right: null,
current_image_index: 0,

initialize: function () {
// Initialize parent.
this.callParent(arguments);

this.galleria_image = this.down('image[which=galleria_image]');
this.thumnail_list = this.down('list[which=thumnail_list]');

this.nav_left = this.down('button[which=nav_left]');
this.nav_right = this.down('button[which=nav_right]');

this.thumnail_list.on('itemtap', this.onChangeImage, this);
this.nav_left.on('tap', this.onNavLeft, this);
this.nav_right.on('tap', this.onNavRight, this);
},

onNavLeft: function(btn, e, eOpts){
this.current_image_index--;
if(this.current_image_index < 0)
this.current_image_index = this.getStore().data.length-1;

this.moveSelection(btn,e,eOpts);
},

onNavRight: function(btn, e, eOpts){
this.current_image_index++;
if(this.current_image_index > this.getStore().data.length-1)
this.current_image_index = 0;

this.moveSelection(btn,e,eOpts);
},

moveSelection: function(btn, e, eOpts) {
var buttonRight = this.nav_right.element;
var buttonLeft = this.nav_left.element;

var currentImageItem = this.thumnail_list.getInnerItems()[0].element.dom.childNodes[this.current_image_index];
var scrollPosition = this.thumnail_list.getScrollable().getScroller().position;
var currentImageItemStartX = currentImageItem.offsetLeft-currentImageItem.offsetTop;
var currentImageItemEndX = currentImageItemStartX+currentImageItem.offsetTop+currentImageItem.offsetWidth;

var offsetLeftX_Left = buttonLeft.dom.offsetLeft+buttonLeft.dom.offsetWidth;
var offsetLeftX_Right = buttonRight.dom.offsetLeft-buttonRight.dom.offsetWidth;

if( currentImageItemEndX-scrollPosition.x > offsetLeftX_Right ){
this.thumnail_list.getScrollable().getScroller().scrollTo((currentImageItemEndX-offsetLeftX_Right), scrollPosition.y, true);
}
else if(scrollPosition.x > currentImageItemStartX){
this.thumnail_list.getScrollable().getScroller().scrollTo(scrollPosition.x-(scrollPosition.x - currentImageItemStartX),scrollPosition.y,true);
}
else if(scrollPosition.x > currentImageItemStartX){
this.thumnail_list.getScrollable().getScroller().scrollTo(0,scrollPosition.y,true);
}


this.thumnail_list.select(this.current_image_index);
this.galleria_image.setSrc(this.getStore().data[this.current_image_index].photo);
},

onChangeImage: function( view, index, target, record, e, eOpts ) {
this.current_image_index = index;
this.galleria_image.setSrc(record.data.photo);
},

onPainted: function( cmp, eOpts ){
if(this.getStore() && this.thumnail_list && this.galleria_image){
this.thumnail_list.setStore(this.getStore());

if(this.getStore().data.length > 0){
this.thumnail_list.select(0);
this.galleria_image.setSrc(this.getStore().data[0].photo);
}
}
}
});

digeridoo
22 May 2012, 1:23 PM
Great work, thanks for sharing. It looks nice, is there a live example?

:-)

iSmartDevice
22 May 2012, 3:13 PM
No problem.
http://www.appshowcase.net/apps/gallery/

armode
22 May 2012, 11:50 PM
Nice work!
Do you know, that it doesn't render right on a smartphone (iPhone 4), because there is not enough space for the panel and the bottom navigation bar?
Maybe you could use a carousel, instead of the panel to display the photos. On a small device you could hide the bottom navigation bar and navigate via swiping.
Maybe you can use the ImageViewer (http://www.sencha.com/forum/showthread.php?197903-Pinch-Image-with-carousel-and-working-fine) component from Chris, that allows pinching and viewing more then one photo in a carousel!
Hope this helps ;-)

iSmartDevice
23 May 2012, 6:11 AM
I fixed the size issue in the component by adding "height: Ext.os.is.Phone ? '10em' : '20em'".

I like your idea. Thanks for letting me know!! :)

mitchellsimoens
24 May 2012, 4:18 AM
Nice little app!

abdullah.hafidh
4 Jun 2012, 10:12 PM
It's actually really nice, but there are few bugs when I tried on Chrome browser, here is the screen shot

35944

iSmartDevice
5 Jun 2012, 11:07 AM
It might seem CSS is not applied to the web page. Could you please tell me which version of Chrome you use? My browser is 19.0.1084.53.

Thanks!

abdullah.hafidh
5 Jun 2012, 11:13 AM
It might seem CSS is not applied to the web page. Could you please tell me which version of Chrome you use? My browser is 19.0.1084.53.

Thanks!

I'm using Chrome version 19.0.1084.52 m

Thanks

Salomonsan
5 Jul 2013, 12:33 AM
Hey everyone,

i try to start the Gallery by tab a button, but it don work (show screenshot)
can anyone help me please ?

thx an greats