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