Last week I tried some of the extjs dataview example, it really great, just my thought, why not creating simple image gallery with dataview? All that we need is provided in the example (the panel, fileinputfield, the xtemplate) and this is the page wire frame that I created using Pencil Firefox Plugins.

1. Div Continer (HTML)
<div id="container">
<div id="left"></div>
<div id="right">
<div id="right-top"></div>
<div id="right-bottom"></div>
</div>
<div class="clear"></div>
</div>
I will not explain the CSS code in here you can see on the code I provided below, just playing with float properties, the div element inside the body tag have to be rendered by the Ext Panel that we will create on the next step, div with “left” id for displaying the Ext Panel that have a DataView Component, div with “right-top” id for displaying the Ext FormPanel (to upload the image) and div with “right-bottom” id is for displaying simple image detail when one of the image in DataView clicked.
2. Div Left (HTML)
Now for the left, we need to create Ext Panel that has the DataView inside it, before start you need to add the file from the Ext example files, it located on “examples\view\data-view.css” and “examples\ux\DataView-more.js”, they used to styling the XTemplate in DataView and to add multiple selection using mouse drag, here the code for the left div
var store = new Ext.data.JsonStore({
url: 'get-images.php',
root: 'images',
fields: [
'name', 'url',
{ name: 'size', type: 'float' },
{ name: 'lastmod', type: 'date', dateFormat: 'timestamp' },
'thumb_url'
]
});
store.load();
var tpl = new Ext.XTemplate(
'<tpl for=".">',
'<div class="thumb-wrap" id="{name}">',
'<div class="thumb"><img src="{thumb_url}" title="{name}"></div>',
'<span class="x-editable">{shortName}</span></div>',
'</tpl>',
'<div class="x-clear"></div>'
);
var tbar = new Ext.Toolbar({
style: 'border:1px solid #99BBE8;'
});
tbar.add('->', {
text: 'Delete',
icon: 'img/delete.png',
handler: function() {
var records = datav.getSelectedRecords();
if (records.length != 0) {
var imgName = '';
for (var i = 0; i < records.length; i++) {
imgName = imgName + records[i].data.name + ';';
}
Ext.Ajax.request({
url: 'delete.php',
method: 'post',
params: { images: imgName},
success: function() {
store.load();
}
});
}
}
});
var datav = new Ext.DataView({
autoScroll: true,
store: store,
tpl: tpl,
autoHeight: false,
height: 400,
multiSelect: true,
overClass: 'x-view-over',
itemSelector: 'div.thumb-wrap',
emptyText: 'No images to display',
style: 'border:1px solid #99BBE8; border-top-width: 0',
plugins: [
new Ext.DataView.DragSelector(),
],
prepareData: function(data){
data.shortName = Ext.util.Format.ellipsis(data.name, 15);
data.sizeString = Ext.util.Format.fileSize(data.size);
data.dateString = data.lastmod.format("m/d/Y g:i a");
return data;
},
listeners: {
selectionchange: {
fn: function(dv,nodes){
var l = nodes.length;
var s = l != 1 ? 's' : '';
panelLeft.setTitle('Simple DataView Gallery ('+l+' image'+s+' selected)');
}
},
click: {
fn: function() {
var selNode = datav.getSelectedRecords();
tplDetail.overwrite(panelRightBottom.body, selNode[0].data);
}
}
}
})
var panelLeft = new Ext.Panel({
id: 'images-view',
frame: true,
width: 520,
height: 200,
autoHeight: true,
layout: 'auto',
title: 'Simple DataView Gallery (0 images selected)',
items: [tbar, datav]
});
panelLeft.render('left');
Mostly I imitate the DataView Example, so the code almost the same the official example. First the store component is to getting the image data from the server by calling the get-image.php script, I modified a bit cause I want to separate the original image and the thumbnail image, here the code.
<?php
$dir = "img/ori/";
$dir_thumbs = "img/thumbs/";
$images = array();
$d = dir($dir);
while($name = $d->read()){
if(!preg_match('/\.(jpg|gif|png)$/', $name)) continue;
$size = filesize($dir.$name);
$lastmod = filemtime($dir.$name)*1000;
$thumb = "thumb_".$name;
$images[] = array('name' => $name, 'size' => $size,
'lastmod' => $lastmod, 'url' => $dir.$name,
'thumb_url' => $dir_thumbs.$thumb);
}
$d->close();
$o = array('images'=>$images);
echo json_encode($o);
There is a toolbar inside the panel just add one function that is deleting the selected images, and the handler function calling the delete.php script, the variable that sent from the client is the multiple images name with “;” (semicolon) separator, so in the PHP it has to be exploded as an array, it something like this code below.
<?php
$dir = 'img/ori/';
$dir_thumbs = 'img/thumbs/';
$arrayImg = explode(";", $_POST['images']);
foreach($arrayImg as $imgname) {
if ($imgname != "") {
unlink($dir.$imgname);
unlink($dir_thumbs.'thumb_'.$imgname);
}
}
echo '{success: true}';
3. Div Top Right (HTML)
The div top right is the place for Ext FormPanel to uploading images, (similar to my previous post about multiple file upload in Extjs) this code use the Ext ux that you can find on the source “examples\ux\fileuploadfield\FileUploadField.js” and the css file in folder “examples\ux\fileuploadfield\css\fileuploadfield.css”, in showed code below the maximum number file to upload is two images but in the provided code I make it 5 images to upload at a time.
var panelRightTop = new Ext.FormPanel({
title: 'Upload Images',
width: 270,
renderTo: 'right-top',
buttonAlign: 'center',
labelWidth: 50,
fileUpload: true,
frame: true,
items: [{
xtype: 'fileuploadfield',
emptyText: '',
fieldLabel: 'Image 1',
buttonText: 'Select a File',
width: 200,
name: 'img[]'
}, {
xtype: 'fileuploadfield',
emptyText: '',
fieldLabel: 'Image 2',
buttonText: 'Select a File',
width: 200,
name: 'img[]'
}],
buttons: [{
text: 'Upload',
handler: function() {
panelRightTop.getForm().submit({
url: 'upload.php',
waitMsg: 'Uploading ....',
success: function(form, o) {
obj = Ext.util.JSON.decode(o.response.responseText);
if (obj.failed == '0' && obj.uploaded != '0') {
Ext.Msg.alert('Success', 'All files uploaded');
} else if (obj.uploaded == '0') {
Ext.Msg.alert('Success', 'Nothing Uploaded');
} else {
Ext.Msg.alert('Success',
obj.uploaded + ' files uploaded <br/>' +
obj.failed + ' files failed to upload');
}
panelRightTop.getForm().reset();
store.load();
}
});
}
}, {
text: 'Reset',
handler: function() {
panelRightTop.getForm().reset();
}
}]
});
The upload.php have the code to uploading image and checking whether the image can be uploaded, I limit max file size is 500 KB and the thumbnail is created to the image that pass the validation, the code for creating thumbnail is almost like my previous post, just modified to be a function and last there are two counter to counting the failed upload and the success upload, here the code.
<?php
function createThumb($img_file, $ori_path, $thumb_path, $img_type) {
// get the image source
$path = $ori_path;
$img = $path.$img_file;
switch ($img_type) {
case "image/jpeg":
$img_src = @imagecreatefromjpeg($img);
break;
case "image/png":
$img_src = @imagecreatefrompng($img);
break;
case "image/x-png":
$img_src = @imagecreatefrompng($img);
break;
case "image/gif":
$img_src = @imagecreatefromgif($img);
break;
}
$img_width = imagesx($img_src);
$img_height = imagesy($img_src);
$square_size = 100;
// check width, height, or square
if ($img_width == $img_height) {
// square
$tmp_width = $square_size;
$tmp_height = $square_size;
} else if ($img_height < $img_width) {
// wide
$tmp_height = $square_size;
$tmp_width = intval(($img_width / $img_height) * $square_size);
if ($tmp_width % 2 != 0) {
$tmp_width++;
}
} else if ($img_height > $img_width) {
$tmp_width = $square_size;
$tmp_height = intval(($img_height / $img_width) * $square_size);
if ($tmp_height % 2 != 0) {
$tmp_height++;
}
}
$img_new = imagecreatetruecolor($tmp_width, $tmp_height);
imagecopyresampled($img_new, $img_src, 0, 0, 0, 0,
$tmp_width, $tmp_height, $img_width, $img_height);
// create temporary thumbnail and locate on the server
$thumb = $thumb_path."thumb_".$img_file;
switch ($img_type) {
case "image/jpeg":
imagejpeg($img_new, $thumb);
break;
case "image/png":
imagepng($img_new, $thumb);
break;
case "image/x-png":
imagepng($img_new, $thumb);
break;
case "image/gif":
imagegif($img_new, $thumb);
break;
}
// get tmp_image
switch ($img_type) {
case "image/jpeg":
$img_thumb_square = imagecreatefromjpeg($thumb);
break;
case "image/png":
$img_thumb_square = imagecreatefrompng($thumb);
break;
case "image/x-png":
$img_thumb_square = imagecreatefrompng($thumb);
break;
case "image/gif":
$img_thumb_square = imagecreatefromgif($thumb);
break;
}
$thumb_width = imagesx($img_thumb_square);
$thumb_height = imagesy($img_thumb_square);
if ($thumb_height < $thumb_width) {
// wide
$x_src = ($thumb_width - $square_size) / 2;
$y_src = 0;
$img_final = imagecreatetruecolor($square_size, $square_size);
imagecopy($img_final, $img_thumb_square, 0, 0,
$x_src, $y_src, $square_size, $square_size);
} else if ($thumb_height > $thumb_width) {
// landscape
$x_src = 0;
$y_src = ($thumb_height - $square_size) / 2;
$img_final = imagecreatetruecolor($square_size, $square_size);
imagecopy($img_final, $img_thumb_square, 0, 0,
$x_src, $y_src, $square_size, $square_size);
} else {
$img_final = imagecreatetruecolor($square_size, $square_size);
imagecopy($img_final, $img_thumb_square, 0, 0,
0, 0, $square_size, $square_size);
}
switch ($img_type) {
case "image/jpeg":
@imagejpeg($img_final, $thumb);
break;
case "image/png":
@imagepng($img_final, $thumb);
break;
case "image/x-png":
@imagepng($img_final, $thumb);
break;
case "image/gif":
@imagegif($img_final, $thumb);
break;
}
}
$ori_dir = 'img/ori/';
$thumb_dir = 'img/thumbs/';
$allowedType = array(
'image/jpeg', 'image/png', 'image/gif', 'image/x-png'
);
$uploaded = 0;
$failed = 0;
foreach($_FILES['img']['name'] as $key => $img) {
if (in_array($_FILES['img']['type'][$key], $allowedType)) {
// max upload file is 500 KB
if ($_FILES['img']['size'][$key] <= 500000) {
// upload file
move_uploaded_file($_FILES['img']['tmp_name'][$key],
$ori_dir.$_FILES['img']['name'][$key]);
// create thumbnail
createThumb($_FILES['img']['name'][$key],
$ori_dir, $thumb_dir,
$_FILES['img']['type'][$key]);
// count how many files uploaded
$uploaded++;
} else {
$failed++;
}
} else if ($_FILES['img']['type'][$key] != '') {
$failed++;
}
}
echo '{success: true, failed: '.$failed.', uploaded: '.$uploaded.'}';
?>
4. Div Top Bottom (HTML)
The last part is the Ext Panel to displaying the image detail, it use the Ext XTemplate and put inside the panel, this dynamic value of the panel is triggered by the DataView click event, that declared before.
var tplDetail = new Ext.XTemplate(
'<div class="details">',
'<tpl for=".">',
'<img src="{thumb_url}"><div class="details-info">',
'<b>Image Name:</b>',
'<span>{name}</span>',
'<b>Size:</b>',
'<span>{sizeString}</span>',
'<b>Last Modified:</b>',
'<span>{dateString}</span>',
'<span><a href="{url}" target="_blank">view original</a></span></div>',
'</tpl>',
'</div>'
);
var panelRightBottom = new Ext.Panel({
title: 'Image Detail',
frame: true,
width: 270,
height: 255,
id: 'panelDetail',
renderTo: 'right-bottom',
tpl: tplDetail
});
Below you can see the sample screen shot of this post, and you can download the source or see online demo, but sorry I disabled the upload and delete feature for online demo.






can you write a simple use of extjs..
It’s hard to learn without guidance…
thanks
you can found on the default examples, I think it really great resource to start, sorry for late reply
Hi.
I am trying to create form for image uploading according to your example.
But I have one problem:
when I click to “Upload” button – all page reloads. I mean it is not ajax submitting. Does it work the same way in your example?
it have to be ajax uploading, but the browser show the loading notification on the title when uploading
this is how it looks on my localhost
http://i35.tinypic.com/10517c7.jpg
your sample doesn’t work ie. browser.
when ı click to file error…
owh sorry I have same problem too on ie,
update:
i have tried it on IE sometimes when you upload the jpg image the type will be ‘image/pjpeg’
so in upload php script should add the condition,
and the plugins property in dataview component seems like causing an error to in ie
I’ll fix it soon, thanks
Your script doesn’t works with IE8 at all. On load displays only gray panel.
IE error:
Webpage error details
User Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)
Timestamp: Wed, 22 Sep 2010 08:33:02 UTC
Message: ‘ptype’ is null or not an object
Line: 7
Char: 122774
Code: 0
URI: http://demo.superdit.com/ext_gallery/ext/ext-all.js
ok thanks for the your test I will try to fix it soon
update: I have fixed the error and updated the code to download, well not perfect but now it working on IE8, if you found another just let me know …. thanks again
Now can’t upload images with IE8, with FF still OK.
ok I try to fixing it again
:: I have updated the code, it is because in IE8 the jpeg format detected as “image/pjpeg” in PHP
thank for your attention, I’ll be more careful next time
thank very much
very interesting but I am having trouble creating the environment…
Thanks a lot for the tutorial..
But.., why when I tried your code in my browser, the vertical scroll bar in the dataview didn’t appear?
hmm strange …
do you get all the image?? if users add more image it should be automatically add the scroll bar on data view, ….
or maybe because the browser issue?? what browser are you using?
Respect!!!! I’m trying to write a small user-profile, editing by Ext js Grid, and now the photo field is a problem for me. It must be changeble and if user has no avatar – there must be a default picture…And for a big pity i don’t know how to do it. Can you tell me, where i can read about this? Thank you very much.
How would I paginate this?
you could try this http://superdit.com/2011/01/11/extjs-dataview-with-pagination/
He has been very useful for the procedure prepareData:
thank you very much