Fixed bugs in the grid view js code (changes in the test_grid_view.html are for debugging purposes only), added class.egw_vfs_utils.inc.php which will contain high-level vfs functionality which was previously hidden inside etemplate and the filemanager, such as generating the thumbnail url for a file.

This commit is contained in:
Andreas Stöckel 2011-03-13 20:54:16 +00:00
parent 01fe133e60
commit 943f369cce
5 changed files with 3744 additions and 1662 deletions

View File

@ -0,0 +1,74 @@
<?php
/**
* eGroupWare API: VFS - static methods to use the new eGW virtual file system
*
* @link http://www.egroupware.org
* @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
* @package api
* @subpackage vfs
* @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
* @author Andreas Stöckel <as@stylite.de>
* @version $Id$
*/
class egw_vfs_utils
{
/**
* Returns the URL to the thumbnail of the given file. The thumbnail may simply
* be the mime-type icon, or - if activated - the preview with the given thsize.
*
* @param string $file name of the file
* @param int $thsize the size of the preview - false if the default should be used.
* @param string $mime if you already know the mime type of the file, you can supply
* it here. Otherwise supply "false".
*/
public static function thumbnail_url($file, $thsize = false, $mime = false)
{
// Retrive the mime-type of the file
if (!$mime)
{
$mime = egw_vfs::mime_content_type($file);
}
$image = "";
// Seperate the mime type into the primary and the secondary part
list($mime_main, $mime_sub) = explode('/', $mime);
if ($mime_main == 'egw')
{
$image = $mime_sub.'/navbar'; // egw-applications for link-widget
}
else if ($file && $mime_main == 'image' && in_array($mime_sub, array('png','jpeg','jpg','gif','bmp')) &&
(string)$GLOBALS['egw_info']['server']['link_list_thumbnail'] != '0' &&
(string)$GLOBALS['egw_info']['user']['preferences']['common']['link_list_thumbnail'] != '0' &&
(!is_array($value) && ($stat = egw_vfs::stat($file)) ? $stat['size'] : $value['size']) < 4000000)
{
if (substr($file, 0, 6) == '/apps/')
{
$file = parse_url(egw_vfs::resolve_url_symlinks($path), PHP_URL_PATH);
}
//Assemble the thumbnail parameters
$thparams = array();
$thparams['path'] = $file;
if ($thsize)
{
$thparams['thsize'] = $thsize;
}
$image = $GLOBALS['egw']->link('/etemplate/thumbnail.php', $thparams);
}
else
{
list($app, $name) = explode("/", egw_vfs::mime_icon($mime), 2);
$image = $GLOBALS['egw']->common->image($app, $name);
}
return $image;
}
}

View File

@ -499,19 +499,16 @@ egwGridDataElement.prototype.callGridViewObjectUpdate = function(_immediate)
}
}
/**
* Returns the absolute index of this element
*/
egwGridDataElement.prototype.getTotalIndex = function()
egwGridDataElement.prototype.getDeepestOpened = function()
{
var idx = this.index;
if (this.parent && this.parent.opened)
if (this.opened && this.children.length > 0)
{
idx += this.parent.getTotalIndex();
return this.children[this.children.length - 1].getDeepestOpened();
}
else
{
return this;
}
return idx;
}
/**
@ -519,7 +516,7 @@ egwGridDataElement.prototype.getTotalIndex = function()
*/
egwGridDataElement.prototype.isOdd = function()
{
return (this.getTotalIndex() % 2) == 0;
return (this.index % 2) == 0; // Improve - old exact version needed way too much performance
}
/**

View File

@ -9,8 +9,6 @@
* @version $Id$
*/
//TODO: Spacer itemHeight should automatically be set to the average item height in the
// grid to solve the "stutters" when scrolling up.
//TODO (minor): Do auto cleanup - remove elements from the view again after they
// haven't been viewed for a certain time.
@ -336,11 +334,10 @@ egwGridViewContainer.prototype.setVisible = function(_visible, _force)
{
$(this.parentNode).toggleClass("hidden", !_visible);
// While the element has been invisible, the viewarea might have changed,
// so check it now
if (this.visible)
if (_visible)
{
this.checkViewArea();
this.assumedHeight = 0;
this.height = false;
}
// As the element is now (in)visible, its height has changed. Inform the
@ -400,6 +397,11 @@ egwGridViewContainer.prototype.setViewArea = function(_area, _force)
this.viewArea = relArea;
if (this.containerClass == "grid" && this.grid != null)
{
// console.log(this, _area, this.viewArea);
}
this.checkViewArea(_force);
}
@ -549,9 +551,12 @@ function egwGridViewGrid(_grid, _heightChangeProc, _scrollable, _outer)
container.beginUpdate = egwGridViewGrid_beginUpdate;
container.endUpdate = egwGridViewGrid_endUpdate;
container.triggerUpdateAssumedHeights = egwGridViewGrid_triggerUpdateAssumedHeights;
container.addIconHeightToAvg = egwGridViewGrid_addIconHeightToAvg;
container.children = [];
container.outer = _outer;
container.containerClass = "grid";
container.avgIconHeight = 16;
container.avgIconCnt = 1;
// Overwrite the abstract container interface functions
container.invalidateHeightCache = egwGridViewGrid_invalidateHeightCache;
@ -582,13 +587,14 @@ function egwGridViewGrid_triggerUpdateAssumedHeights()
var self = this;
var id = this.triggerID;
window.setTimeout(function() {
if (id = self.triggerID)
{
self.triggerID = 0;
self.updateAssumedHeights(20);
}
},
EGW_GRID_UPDATE_HEIGHTS_TIMEOUT);
if (id == self.triggerID)
{
self.triggerID = 0;
self.updateAssumedHeights(20);
}
},
EGW_GRID_UPDATE_HEIGHTS_TIMEOUT
);
}
function egwGridViewGrid_endUpdate(_recPrev)
@ -617,10 +623,10 @@ function egwGridViewGrid_endUpdate(_recPrev)
{
this.triggerUpdateAssumedHeights();
}
this.didUpdate = false;
}
}
this.didUpdate = false;
}
function egwGridViewGrid_getOuter()
@ -756,6 +762,12 @@ function egwGridViewGrid_updateAssumedHeights(_maxCount)
// Offset the position of all following elements by the delta.
var delta = newHeight - oldHeight;
if (this.grid != null)
{
// console.log(child, delta, newHeight, oldHeight);
}
if (Math.abs(delta) > 0.001)
{
for (var j = this.updateIndex + 1; j < this.children.length; j++)
@ -779,8 +791,6 @@ function egwGridViewGrid_updateAssumedHeights(_maxCount)
this.endUpdate(true);
}
var self = this;
if (cnt == 0)
{
// If the maximum-update-count has been exhausted, retrigger this function
@ -790,6 +800,7 @@ function egwGridViewGrid_updateAssumedHeights(_maxCount)
{
// Otherwise, all elements have been checked - we'll now call "setViewArea"
// which may check whether new objects are now in the currently visible range
var self = this;
window.setTimeout(function() {
self.setViewArea(self.viewArea);
}, EGW_GRID_UPDATE_HEIGHTS_TIMEOUT);
@ -919,8 +930,8 @@ function egwGridViewGrid_invalidateHeightCache(_children)
_children = true;
}
this.height = false;
this.assumedHeight = false;
// Call the inherited function
egwGridViewContainer.prototype.invalidateHeightCache.call(this);
if (_children)
{
@ -951,6 +962,11 @@ function egwGridViewGrid_heightChangeHandler(_elem)
{
this.didUpdate = true;
if (this.grid != null)
{
// console.log("HCH for", _elem);
}
// The old height of the element is now only an assumed height - the next
// time the "updateAssumedHeights" functions is triggered, this will be
// updated.
@ -959,7 +975,7 @@ function egwGridViewGrid_heightChangeHandler(_elem)
_elem.invalidateHeightCache(false);
_elem.assumedHeight = oldHeight;
if (_elem.containerClass == "grid" && !this.inUpdate)
if ((_elem.containerClass == "grid" || _elem.containerClass == "spacer") && !this.inUpdate)
{
this.triggerUpdateAssumedHeights();
}
@ -1065,6 +1081,14 @@ function egwGridViewGrid_doSetviewArea(_area, _recPrev)
}
}
function egwGridViewGrid_addIconHeightToAvg(_value)
{
this.avgIconCnt++;
var frac = 1.0 / this.avgIconCnt;
this.avgIconHeight = this.avgIconHeight * (1 - frac) + _value * frac;
}
/** -- egwGridViewRow Class -- **/
function egwGridViewRow(_grid, _heightChangeProc, _item)
@ -1259,9 +1283,19 @@ function egwGridViewRow_doUpdateData(_immediate)
{
// Build the icon element
var icon = $(document.createElement("img"));
// Default the image height to the average height - this attribute
// is removed from the row as soon as the icon is loaded
icon.attr("height", Math.round(this.grid.avgIconHeight));
icon.attr("src", data[col.id].iconUrl);
icon.load(this, function(e) {
e.data.callHeightChangeProc();
icon.load({"item": this, "col": td}, function(e) {
var icon = $(this);
icon.removeAttr("height");
window.setTimeout(function() {
e.data.item.grid.addIconHeightToAvg(icon.height());
}, 100);
e.data.item.callHeightChangeProc();
});
icon.addClass("icon");
td.append(icon);
@ -1322,6 +1356,8 @@ function egwGridViewRow_setOpen(_open)
{
if (_open != this.opened)
{
var inserted = false;
if (_open)
{
if (!this.childGrid)
@ -1332,8 +1368,10 @@ function egwGridViewRow_setOpen(_open)
arrow.addClass("loading");
// Create the "child grid"
this.childGrid = this.grid.insertContainer(this.index, egwGridViewGrid,
var childGrid = null;
this.childGrid = childGrid = this.grid.insertContainer(this.index, egwGridViewGrid,
false);
inserted = true;
this.childGrid.setVisible(false);
var spacer = this.childGrid.insertContainer(-1, egwGridViewSpacer,
this.grid.getOuter().avgRowHeight);
@ -1342,11 +1380,12 @@ function egwGridViewRow_setOpen(_open)
arrow.removeClass("closed");
arrow.addClass("opened");
spacer.setItemList(_children);
childGrid.setVisible(true);
});
}
}
if (this.childGrid)
if (this.childGrid && !inserted)
{
this.childGrid.setVisible(_open);
}
@ -1354,6 +1393,7 @@ function egwGridViewRow_setOpen(_open)
this.opened = _open;
this.item.opend = _open;
}
}
@ -1373,6 +1413,7 @@ function egwGridViewSpacer(_grid, _heightChangeProc, _itemHeight)
container.domNode = null;
container.items = [];
container.setItemList = egwGridViewSpacer_setItemList;
container.containerClass = "spacer";
// Overwrite the inherited functions
container.doInsertIntoDOM = egwGridViewSpacer_doInsertIntoDOM;
@ -1437,13 +1478,17 @@ function egwGridViewSpacer_doSetViewArea()
// created elements.
if (it_top.length > 0)
{
var spacer = this.grid.insertContainer(idx - 1, egwGridViewSpacer, avgHeight);
spacer.setItemList(it_top)
// this.itemHeight has to be passed to the new top spacer - otherwise the
// scroll position might change and we'll go into a nasty setViewArea
// loop.
var spacer = this.grid.insertContainer(idx - 1, egwGridViewSpacer, this.itemHeight);
spacer.setItemList(it_top);
}
// If there are items left at the bottom of the spacer, set theese as items of this spacer
if (it_bot.length > 0)
{
// The height of this (the bottom) spacer can be set to the average height
this.itemHeight = avgHeight;
this.setItemList(it_bot);
}

View File

@ -30,7 +30,7 @@
{
"id": "name",
"caption": "Name",
"width": "20%",
"width": "75%",
"type": EGW_COL_TYPE_NAME_ICON_FIXED
},
{
@ -39,36 +39,43 @@
},
{
"id": "rights",
"caption": "UNIX Filerights"
"caption": "UNIX Filerights",
"visibility": EGW_COL_VISIBILITY_INVISIBLE
},
{
"id": "mime",
"caption": "File-Type/MIME"
"caption": "File-Type/MIME",
"visibility": EGW_COL_VISIBILITY_INVISIBLE
},
{
"id": "atime",
"caption": "atime",
"width": "15%"
"width": "15%",
"visibility": EGW_COL_VISIBILITY_INVISIBLE
},
{
"id": "ctime",
"caption": "ctime",
"width": "15%"
"width": "15%",
"visibility": EGW_COL_VISIBILITY_INVISIBLE
},
{
"id": "mtime",
"caption": "mtime",
"width": "15%"
"width": "15%",
"visibility": EGW_COL_VISIBILITY_INVISIBLE
},
{
"id": "owner",
"caption": "owner",
"width": "10%"
"width": "10%",
"visibility": EGW_COL_VISIBILITY_INVISIBLE
},
{
"id": "group",
"caption": "group",
"width": "10%"
"width": "10%",
"visibility": EGW_COL_VISIBILITY_INVISIBLE
}
];
@ -136,23 +143,46 @@
"entryType": EGW_DATA_TYPE_RANGE,
"prefix": "root_elem_",
"canHaveChildren": true,
"count": 10000
"count": 1000
}
]
);
grid.resize(1500, 500);
});
function check_positions()
function check_positions(_grid, _delta)
{
var g = grid.gridOuter.grid;
var delta = - g.scrollarea.offset().top;
var outer = grid.gridOuter.grid;
if (typeof _grid == "undefined")
{
_grid = outer;
}
if (typeof _delta == "undefined")
{
_delta = 0;
}
var g = _grid;
var delta = outer.scrollarea.scrollTop() - outer.scrollarea.offset().top;
for (var i = 0; i < g.children.length; i++)
{
var rtop = g.children[i].parentNode.offset().top + g.scrollarea.scrollTop() - g.scrollarea.offset().top;
var itop = g.children[i].position;
var rtop = g.children[i].parentNode.offset().top + delta;
var itop = g.children[i].position + _delta;
console.log(Math.round(itop - rtop));
var rheight = g.children[i].parentNode.outerHeight();
var iheight = g.children[i].getHeight();
console.log(Math.round(itop - rtop), Math.round(iheight - rheight), g.children[i].visible);
if (g.children[i].containerClass == "grid" && g.children[i].visible)
{
console.log("-->");
check_positions(g.children[i], itop);
console.log("<--");
}
}
}
</script>

File diff suppressed because it is too large Load Diff