* Filemanager/Expose view: enhancements

-Fullscreen feature
-Loading on thumbnail scrolling
-Fix thumbnail not being loaded for the first time
This commit is contained in:
Hadi Nategh 2015-01-30 15:50:57 +00:00
parent ec13220449
commit e9ebd97e78
7 changed files with 104 additions and 30 deletions

View File

@ -327,15 +327,14 @@ var et2_vfsMime = expose(et2_valueWidget.extend([et2_IDetachedDOM],
{ {
var base_url = egw.webserverUrl.match(/^\//,'ig')?egw(window).window.location.origin + egw.webserverUrl:egw.webserverUrl; var base_url = egw.webserverUrl.match(/^\//,'ig')?egw(window).window.location.origin + egw.webserverUrl:egw.webserverUrl;
var mediaContent = []; var mediaContent = [];
if (_value && _value.mime && _value.mime.match(/video|audio/,'ig')) if (_value && _value.mime && _value.mime.match(/video\/|audio\//,'ig'))
{ {
mediaContent = [{ mediaContent = [{
title: _value.name, title: _value.name,
type: 'video/*', type: _value.mime,
sources:[{ poster:'', // TODO: Should be changed by correct video thumbnail later
href: base_url + _value.download_url, thumbnail:this.egw().mime_icon(_value['mime'], _value['path']) ,
type: _value.mime href: base_url + _value.download_url,
}]
}]; }];
} }
else else

View File

@ -12,7 +12,7 @@
/*egw:uses /*egw:uses
jquery.jquery; jquery.jquery;
/phpgwapi/js/jquery/blueimp/js/jquery.blueimp-gallery.min.js; /phpgwapi/js/jquery/blueimp/js/blueimp-gallery.min.js;
*/ */
/** /**
@ -48,7 +48,7 @@ function expose (widget)
}; };
// For filtering to only show things we can handle // For filtering to only show things we can handle
var mime_regex = new RegExp(/video\/|image|audio\//); var mime_regex = new RegExp(/video\/|image\/|audio\//);
// Only one gallery // Only one gallery
var gallery = null; var gallery = null;
@ -89,6 +89,7 @@ function expose (widget)
var read_from_nextmatch = function(nm, images, start_at) var read_from_nextmatch = function(nm, images, start_at)
{ {
if(!start_at) start_at = 0; if(!start_at) start_at = 0;
var image_index = start_at;
var stop = Math.max.apply(null,Object.keys(nm.controller._indexMap)); var stop = Math.max.apply(null,Object.keys(nm.controller._indexMap));
for(var i = start_at; i <= stop; i++) for(var i = start_at; i <= stop; i++)
@ -98,7 +99,7 @@ function expose (widget)
// Returning instead of using IMAGE_DEFAULT means we stop as // Returning instead of using IMAGE_DEFAULT means we stop as
// soon as a hole is found, instead of getting everything that is // soon as a hole is found, instead of getting everything that is
// available. The gallery can't fill in the holes. // available. The gallery can't fill in the holes.
images[i] = IMAGE_DEFAULT; images[image_index++] = IMAGE_DEFAULT;
continue; continue;
} }
var uid = nm.controller._indexMap[i].uid; var uid = nm.controller._indexMap[i].uid;
@ -107,7 +108,7 @@ function expose (widget)
if(data && data.data && data.data.mime && mime_regex.test(data.data.mime)) if(data && data.data && data.data.mime && mime_regex.test(data.data.mime))
{ {
var media = this.getMedia(data.data); var media = this.getMedia(data.data);
images.push(jQuery.extend({}, data.data, media[0])); images[image_index++] = jQuery.extend({}, data.data, media[0]);
} }
} }
}; };
@ -133,9 +134,11 @@ function expose (widget)
// Don't bother with adding a default, we just did that // Don't bother with adding a default, we just did that
if(image.loading) if(image.loading)
{ {
$j(gallery.slides[index]) //Add load class if it's really a slide with error
.addClass(gallery.options.slideLoadingClass) if (gallery.slidesContainer.find('[data-index="'+index+'"]').hasClass(gallery.options.slideErrorClass))
.removeClass(gallery.options.slideErrorClass); $j(gallery.slides[index])
.addClass(gallery.options.slideLoadingClass)
.removeClass(gallery.options.slideErrorClass);
return; return;
} }
@ -234,6 +237,8 @@ function expose (widget)
closeClass: 'close', closeClass: 'close',
// The class for the "play-pause" toggle control: // The class for the "play-pause" toggle control:
playPauseClass: 'play-pause', playPauseClass: 'play-pause',
// The class to add for fullscreen button option
fullscreenClass:'fullscreen',
// The list object property (or data attribute) with the object type: // The list object property (or data attribute) with the object type:
typeProperty: 'type', typeProperty: 'type',
// The list object property (or data attribute) with the object title: // The list object property (or data attribute) with the object title:
@ -305,6 +310,8 @@ function expose (widget)
thumbnailProperty: 'thumbnail', thumbnailProperty: 'thumbnail',
// Defines if the gallery indicators should display a thumbnail: // Defines if the gallery indicators should display a thumbnail:
thumbnailIndicators: true, thumbnailIndicators: true,
//thumbnail with image tag
thumbnailWithImgTag: true,
// Callback function executed when the Gallery is initialized. // Callback function executed when the Gallery is initialized.
// Is called with the gallery instance as "this" object: // Is called with the gallery instance as "this" object:
onopen: jQuery.proxy(this.expose_onopen,this), onopen: jQuery.proxy(this.expose_onopen,this),
@ -347,7 +354,7 @@ function expose (widget)
// Gallery Main DIV container // Gallery Main DIV container
var $expose_node = jQuery(document.createElement('div')).attr({id:"blueimp-gallery", class:"blueimp-gallery"}); var $expose_node = jQuery(document.createElement('div')).attr({id:"blueimp-gallery", class:"blueimp-gallery"});
// Create Gallery DOM NODE // Create Gallery DOM NODE
$expose_node.append('<div class="slides"></div><h3 class="title"></h3><a class="prev"></a><a class="next"></a><a class="close">×</a><a class="play-pause"></a><ol class="indicator"></ol>'); $expose_node.append('<div class="slides"></div><h3 class="title"></h3><a class="prev"></a><a class="next"></a><a class="close">×</a><a class="play-pause"></a><a class="fullscreen"></a><ol class="indicator"></ol>');
// Append the gallery Node to DOM // Append the gallery Node to DOM
$body.append($expose_node); $body.append($expose_node);
} }
@ -419,6 +426,7 @@ function expose (widget)
expose_onopened: function (event){ expose_onopened: function (event){
// Check to see if we're in a nextmatch, do magic // Check to see if we're in a nextmatch, do magic
var nm = find_nextmatch(this); var nm = find_nextmatch(this);
var self=this;
if(nm) if(nm)
{ {
// Add scrolling to the indicator list // Add scrolling to the indicator list
@ -428,9 +436,18 @@ function expose (widget)
gallery.container.find('.indicator').off() gallery.container.find('.indicator').off()
.addClass('paginating') .addClass('paginating')
.mousewheel(function(event, delta) { .mousewheel(function(event, delta) {
if(delta > 0 && parseInt($j(this).css('left')) > gallery.container.width() / 2) return; if(delta > 0 && parseInt($j(this).css('left')) > gallery.container.width() / 2) return;
//Reload next pictures into the gallery by scrolling on thumbnails
if (delta<0 && $j(this).width() + parseInt($j(this).css('left')) < gallery.container.width())
{
var nextIndex = gallery.indicatorContainer.find('[title="loading"]')[0];
if (nextIndex) self.expose_onslideend(gallery,nextIndex.dataset.index -1);
return;
}
// Move it about 5 indicators // Move it about 5 indicators
$j(this).css('left',parseInt($j(this).css('left'))-(-delta*gallery.activeIndicator.width()*5)+'px'); $j(this).css('left',parseInt($j(this).css('left'))-(-delta*gallery.activeIndicator.width()*5)+'px');
event.preventDefault(); event.preventDefault();
}) })
.swipe(function(event, direction, distance) { .swipe(function(event, direction, distance) {
@ -460,14 +477,20 @@ function expose (widget)
expose_onslide: function (gallery, index, slide){ expose_onslide: function (gallery, index, slide){
// First let parent try // First let parent try
this._super.apply(this, arguments); this._super.apply(this, arguments);
// Check to see if we're in a nextmatch, do magic
var nm = find_nextmatch(this); var nm = find_nextmatch(this);
if(nm) if(nm)
{ {
// See if we need to move the indicator // See if we need to move the indicator
var indicator = gallery.container.find('.indicator'); var indicator = gallery.container.find('.indicator');
var current = $j('.active',indicator).position(); var current = $j('.active',indicator).position();
if (current.left == 0)
{
//As controlsClass activates indicators,
//we use it to make indicators available for the first time
//which helps to re-calculate the correct position of it, if it's not loaded yet
gallery.container.addClass(this.expose_options.controlsClass);
current = $j('.active',indicator).position();
}
if(current) if(current)
{ {
indicator.animate({left: (gallery.container.width() / 2)-current.left}); indicator.animate({left: (gallery.container.width() / 2)-current.left});
@ -484,7 +507,7 @@ function expose (widget)
var total_count = nm.controller._grid.getTotalCount(); var total_count = nm.controller._grid.getTotalCount();
// Already at the end, don't bother // Already at the end, don't bother
if(index == total_count) return; if(index == total_count -1 || index == 0) return;
// Try to determine direction from state of next & previous slides // Try to determine direction from state of next & previous slides
var direction = 1; var direction = 1;

View File

@ -163,11 +163,23 @@
.blueimp-gallery-playing > .play-pause { .blueimp-gallery-playing > .play-pause {
background-position: -15px 0; background-position: -15px 0;
} }
.blueimp-gallery > .fullscreen {
position: absolute;
right: 15px;
bottom: 30px;
width: 15px;
height: 15px;
background: url(../img/fullscreen.png) 0 0 no-repeat;
cursor: pointer;
opacity: 0.5;
display:none;
}
.blueimp-gallery > .prev:hover, .blueimp-gallery > .prev:hover,
.blueimp-gallery > .next:hover, .blueimp-gallery > .next:hover,
.blueimp-gallery > .close:hover, .blueimp-gallery > .close:hover,
.blueimp-gallery > .title:hover, .blueimp-gallery > .title:hover,
.blueimp-gallery > .play-pause:hover { .blueimp-gallery > .play-pause:hover,
.blueimp-gallery > .fullscreen:hover{
color: #fff; color: #fff;
opacity: 1; opacity: 1;
} }
@ -175,7 +187,8 @@
.blueimp-gallery-controls > .next, .blueimp-gallery-controls > .next,
.blueimp-gallery-controls > .close, .blueimp-gallery-controls > .close,
.blueimp-gallery-controls > .title, .blueimp-gallery-controls > .title,
.blueimp-gallery-controls > .play-pause { .blueimp-gallery-controls > .play-pause,
.blueimp-gallery-controls > .fullscreen{
display: block; display: block;
/* Fix z-index issues (controls behind slide element) on Android: */ /* Fix z-index issues (controls behind slide element) on Android: */
-webkit-transform: translateZ(0); -webkit-transform: translateZ(0);
@ -195,7 +208,8 @@
.blueimp-gallery > .prev, .blueimp-gallery > .prev,
.blueimp-gallery > .next, .blueimp-gallery > .next,
.blueimp-gallery > .close, .blueimp-gallery > .close,
.blueimp-gallery > .play-pause { .blueimp-gallery > .play-pause,
.blueimp-gallery > .fullscreen{
-webkit-user-select: none; -webkit-user-select: none;
-khtml-user-select: none; -khtml-user-select: none;
-moz-user-select: none; -moz-user-select: none;

File diff suppressed because one or more lines are too long

View File

@ -38,7 +38,11 @@
// used as alternative to a thumbnail child element: // used as alternative to a thumbnail child element:
thumbnailProperty: 'thumbnail', thumbnailProperty: 'thumbnail',
// Defines if the gallery indicators should display a thumbnail: // Defines if the gallery indicators should display a thumbnail:
thumbnailIndicators: true thumbnailIndicators: true,
// The tag name of thumbnails indicators
thumbnailsTagIndicators: 'li',
//thumbnail with image tag
thumbnailWithImgTag: false
}); });
var initSlides = Gallery.prototype.initSlides, var initSlides = Gallery.prototype.initSlides,
@ -51,7 +55,7 @@
$.extend(Gallery.prototype, { $.extend(Gallery.prototype, {
createIndicator: function (obj) { createIndicator: function (obj) {
var indicator = this.indicatorPrototype.cloneNode(false), var indicator = this.indicatorPrototype.cloneNode(this.options.thumbnailWithImgTag),
title = this.getItemProperty(obj, this.options.titleProperty), title = this.getItemProperty(obj, this.options.titleProperty),
thumbnailProperty = this.options.thumbnailProperty, thumbnailProperty = this.options.thumbnailProperty,
thumbnailUrl, thumbnailUrl,
@ -64,7 +68,18 @@
thumbnailUrl = this.getItemProperty(obj, thumbnailProperty); thumbnailUrl = this.getItemProperty(obj, thumbnailProperty);
} }
if (thumbnailUrl) { if (thumbnailUrl) {
indicator.style.backgroundImage = 'url("' + thumbnailUrl + '")'; if (this.options.thumbnailsTagIndicators == 'img')
{
indicator.src = thumbnailUrl;
}
else if (this.options.thumbnailWithImgTag)
{
indicator.children[0].src = thumbnailUrl;
}
else
{
indicator.style.backgroundImage = 'url("' + thumbnailUrl + '")';
}
} }
} }
if (title) { if (title) {
@ -100,8 +115,9 @@
this.options.indicatorContainer this.options.indicatorContainer
); );
if (this.indicatorContainer.length) { if (this.indicatorContainer.length) {
this.indicatorPrototype = document.createElement('li'); this.indicatorPrototype = document.createElement(this.options.thumbnailsTagIndicators);
this.indicators = this.indicatorContainer[0].children; if (this.options.thumbnailWithImgTag) this.indicatorPrototype.appendChild(document.createElement('img'));
this.indicators = this.indicatorContainer[0].children;
} }
} }
initSlides.call(this, reload); initSlides.call(this, reload);

View File

@ -91,6 +91,8 @@
closeClass: 'close', closeClass: 'close',
// The class for the "play-pause" toggle control: // The class for the "play-pause" toggle control:
playPauseClass: 'play-pause', playPauseClass: 'play-pause',
// The class fullscreen button control
fullscreenClass:'fullscreen',
// The list object property (or data attribute) with the object type: // The list object property (or data attribute) with the object type:
typeProperty: 'type', typeProperty: 'type',
// The list object property (or data attribute) with the object title: // The list object property (or data attribute) with the object title:
@ -113,6 +115,8 @@
toggleControlsOnReturn: true, toggleControlsOnReturn: true,
// Toggle the automatic slideshow interval on pressing the Space key: // Toggle the automatic slideshow interval on pressing the Space key:
toggleSlideshowOnSpace: true, toggleSlideshowOnSpace: true,
// Toggle fullscreen mode when slideshow is running
toggleFullscreenOnSlideShow: true,
// Navigate the gallery by pressing left and right on the keyboard: // Navigate the gallery by pressing left and right on the keyboard:
enableKeyboardNavigation: true, enableKeyboardNavigation: true,
// Close the gallery on pressing the Esc key: // Close the gallery on pressing the Esc key:
@ -865,6 +869,10 @@
// Click on "play-pause" control // Click on "play-pause" control
this.preventDefault(event); this.preventDefault(event);
this.toggleSlideshow(); this.toggleSlideshow();
}else if (isTarget(options.fullscreenClass)) {
// Click on "fullscreen" control
this.preventDefault(event);
this.toggleFullscreen();
} else if (parent === this.slidesContainer[0]) { } else if (parent === this.slidesContainer[0]) {
// Click on slide background // Click on slide background
this.preventDefault(event); this.preventDefault(event);
@ -1128,11 +1136,25 @@
toggleSlideshow: function () { toggleSlideshow: function () {
if (!this.interval) { if (!this.interval) {
this.play(); this.play();
if (this.options.toggleFullscreenOnSlideShow) this.requestFullScreen(this.container[0]);
} else { } else {
this.pause(); this.pause();
if (this.options.toggleFullscreenOnSlideShow) this.exitFullScreen();
} }
}, },
toggleFullscreen: function ()
{
if (!this.getFullScreenElement())
{
this.requestFullScreen(this.container[0]);
}
else
{
this.exitFullScreen();
}
},
getNodeIndex: function (element) { getNodeIndex: function (element) {
return parseInt(element.getAttribute('data-index'), 10); return parseInt(element.getAttribute('data-index'), 10);
}, },

File diff suppressed because one or more lines are too long