diff --git a/apps/contacts/css/styles.css b/apps/contacts/css/styles.css index f961767a0d6..b6709c5a791 100644 --- a/apps/contacts/css/styles.css +++ b/apps/contacts/css/styles.css @@ -1,3 +1,4 @@ +#contacts li { padding-left:25px;background:url('../img/person.svg') no-repeat; } #chooseaddressbook {margin-right: 170px; float: right;} #contacts_details_name { font-weight:bold;font-size:1.1em;margin-left:25%;} #contacts_details_photo { margin:.5em 0em .5em 25%; } diff --git a/apps/contacts/img/person.png b/apps/contacts/img/person.png new file mode 100644 index 00000000000..17e79196540 Binary files /dev/null and b/apps/contacts/img/person.png differ diff --git a/apps/contacts/img/person.svg b/apps/contacts/img/person.svg new file mode 100644 index 00000000000..c4842c5916b --- /dev/null +++ b/apps/contacts/img/person.svg @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/contacts/js/interface.js b/apps/contacts/js/interface.js index 02470d5a767..3190efae3cc 100644 --- a/apps/contacts/js/interface.js +++ b/apps/contacts/js/interface.js @@ -108,6 +108,18 @@ Contacts={ }) $.each(contacts, function(idx, itm) { contactlist.append(itm); }); */ + setTimeout(Contacts.UI.Contacts.lazyupdate(), 500); + }, + lazyupdate:function(){ + //alert('lazyupdate'); + $('#contacts li').live('inview', function(){ + if (!$(this).attr('style')) { + //alert($(this).data('id') + ' has background: ' + $(this).attr('style')); + $(this).css('background','url(thumbnail.php?id='+$(this).data('id')+') no-repeat'); + }/* else { + alert($(this).data('id') + ' has style ' + $(this).attr('style').match('url')); + }*/ + }); } } } @@ -279,4 +291,25 @@ $(document).ready(function(){ }); $('#contacts_addcardform select').chosen(); + + $('#contacts li').bind('inview', function(event, isInView, visiblePartX, visiblePartY) { + if (isInView) { //NOTE: I've kept all conditions for future reference ;-) + // element is now visible in the viewport + if (visiblePartY == 'top') { + // top part of element is visible + } else if (visiblePartY == 'bottom') { + // bottom part of element is visible + } else { + // whole part of element is visible + if (!$(this).attr('style')) { + //alert($(this).data('id') + ' has background: ' + $(this).attr('style')); + $(this).css('background','url(thumbnail.php?id='+$(this).data('id')+') no-repeat'); + }/* else { + alert($(this).data('id') + ' has style ' + $(this).attr('style').match('url')); + }*/ + } + } else { + // element has gone out of viewport + } + }); }); diff --git a/apps/contacts/js/jquery.inview.js b/apps/contacts/js/jquery.inview.js new file mode 100644 index 00000000000..a38ab164977 --- /dev/null +++ b/apps/contacts/js/jquery.inview.js @@ -0,0 +1,118 @@ +/** + * author Christopher Blum + * - based on the idea of Remy Sharp, http://remysharp.com/2009/01/26/element-in-view-event-plugin/ + * - forked from http://github.com/zuk/jquery.inview/ + */ +(function ($) { + var inviewObjects = {}, viewportSize, viewportOffset, + d = document, w = window, documentElement = d.documentElement, expando = $.expando; + + $.event.special.inview = { + add: function(data) { + inviewObjects[data.guid + "-" + this[expando]] = { data: data, $element: $(this) }; + }, + + remove: function(data) { + try { delete inviewObjects[data.guid + "-" + this[expando]]; } catch(e) {} + } + }; + + function getViewportSize() { + var mode, domObject, size = { height: w.innerHeight, width: w.innerWidth }; + + // if this is correct then return it. iPad has compat Mode, so will + // go into check clientHeight/clientWidth (which has the wrong value). + if (!size.height) { + mode = d.compatMode; + if (mode || !$.support.boxModel) { // IE, Gecko + domObject = mode === 'CSS1Compat' ? + documentElement : // Standards + d.body; // Quirks + size = { + height: domObject.clientHeight, + width: domObject.clientWidth + }; + } + } + + return size; + } + + function getViewportOffset() { + return { + top: w.pageYOffset || documentElement.scrollTop || d.body.scrollTop, + left: w.pageXOffset || documentElement.scrollLeft || d.body.scrollLeft + }; + } + + function checkInView() { + var $elements = $(), elementsLength, i = 0; + + $.each(inviewObjects, function(i, inviewObject) { + var selector = inviewObject.data.selector, + $element = inviewObject.$element; + $elements = $elements.add(selector ? $element.find(selector) : $element); + }); + + elementsLength = $elements.length; + if (elementsLength) { + viewportSize = viewportSize || getViewportSize(); + viewportOffset = viewportOffset || getViewportOffset(); + + for (; i viewportOffset.top && + elementOffset.top < viewportOffset.top + viewportSize.height && + elementOffset.left + elementSize.width > viewportOffset.left && + elementOffset.left < viewportOffset.left + viewportSize.width) { + visiblePartX = (viewportOffset.left > elementOffset.left ? + 'right' : (viewportOffset.left + viewportSize.width) < (elementOffset.left + elementSize.width) ? + 'left' : 'both'); + visiblePartY = (viewportOffset.top > elementOffset.top ? + 'bottom' : (viewportOffset.top + viewportSize.height) < (elementOffset.top + elementSize.height) ? + 'top' : 'both'); + visiblePartsMerged = visiblePartX + "-" + visiblePartY; + if (!inView || inView !== visiblePartsMerged) { + $element.data('inview', visiblePartsMerged).trigger('inview', [true, visiblePartX, visiblePartY]); + } + } else if (inView) { + $element.data('inview', false).trigger('inview', [false]); + } + } + } + } + + $(w).bind("scroll resize", function() { + viewportSize = viewportOffset = null; + }); + + // Use setInterval in order to also make sure this captures elements within + // "overflow:scroll" elements or elements that appeared in the dom tree due to + // dom manipulation and reflow + // old: $(window).scroll(checkInView); + // + // By the way, iOS (iPad, iPhone, ...) seems to not execute, or at least delays + // intervals while the user scrolls. Therefore the inview event might fire a bit late there + setInterval(checkInView, 250); +})(jQuery); \ No newline at end of file diff --git a/apps/contacts/templates/index.php b/apps/contacts/templates/index.php index 8592ffe1c4c..9e63b201987 100644 --- a/apps/contacts/templates/index.php +++ b/apps/contacts/templates/index.php @@ -1,3 +1,10 @@ + + diff --git a/apps/contacts/thumbnail.php b/apps/contacts/thumbnail.php new file mode 100644 index 00000000000..bf0a6e96a5d --- /dev/null +++ b/apps/contacts/thumbnail.php @@ -0,0 +1,150 @@ +. + * + */ + +// Init owncloud +require_once('../../lib/base.php'); +OC_Util::checkLoggedIn(); +OC_Util::checkAppEnabled('contacts'); + +if(!function_exists('imagecreatefromjpeg')) { + OC_Log::write('contacts','GD module not installed',OC_Log::ERROR); + header('Content-Type: image/png'); + // TODO: Check if it works to read the file and echo the content. + return 'img/person.png'; +} + +function getStandardImage(){ + $src_img = imagecreatefrompng('img/person.png'); + header('Content-Type: image/png'); + imagepng($src_img); + imagedestroy($src_img); +} + + +$id = $_GET['id']; + +$l10n = new OC_L10N('contacts'); + +$card = OC_Contacts_VCard::find( $id ); +if( $card === false ){ + echo $l10n->t('Contact could not be found.'); + exit(); +} + +$addressbook = OC_Contacts_Addressbook::find( $card['addressbookid'] ); +if( $addressbook === false || $addressbook['userid'] != OC_USER::getUser()){ + echo $l10n->t('This is not your contact.'); // This is a weird error, why would it come up? (Better feedback for users?) + exit(); +} + +$content = OC_VObject::parse($card['carddata']); + +// invalid vcard +if( is_null($content)){ + echo $l10n->t('This card is not RFC compatible.'); + exit(); +} + +// define the width and height for the thumbnail +// note that theese dimmensions are considered the maximum dimmension and are not fixed, +// because we have to keep the image ratio intact or it will be deformed +$thumbnail_width = 23; +$thumbnail_height = 23; + +// Photo :-) +foreach($content->children as $child){ + if($child->name == 'PHOTO'){ + foreach($child->parameters as $parameter){ + if( $parameter->name == 'TYPE' ){ + $mime = $parameter->value; + } + } + $data = base64_decode($child->value); + $src_img = imagecreatefromstring($data); + if ($src_img !== false) { + //gets the dimmensions of the image + $width_orig=imageSX($src_img); + $height_orig=imageSY($src_img); + $ratio_orig = $width_orig/$height_orig; + + if ($thumbnail_width/$thumbnail_height > $ratio_orig) { + $new_height = $thumbnail_width/$ratio_orig; + $new_width = $thumbnail_width; + } else { + $new_width = $thumbnail_height*$ratio_orig; + $new_height = $thumbnail_height; + } + + $x_mid = $new_width/2; //horizontal middle + $y_mid = $new_height/2; //vertical middle + + $process = imagecreatetruecolor(round($new_width), round($new_height)); + if ($process == false) { + getStandardImage(); + //echo 'Error creating process image: '.$new_width.'x'.$new_height; + OC_Log::write('contacts','Error creating process image for '.$id.' '.$new_width.'x'.$new_height,OC_Log::ERROR); + imagedestroy($process); + imagedestroy($src_img); + exit(); + } + + imagecopyresampled($process, $src_img, 0, 0, 0, 0, $new_width, $new_height, $width_orig, $height_orig); + if ($process == false) { + getStandardImage(); + //echo 'Error resampling process image: '.$new_width.'x'.$new_height; + OC_Log::write('contacts','Error resampling process image for '.$id.' '.$new_width.'x'.$new_height,OC_Log::ERROR); + imagedestroy($process); + imagedestroy($src_img); + exit(); + } + $thumb = imagecreatetruecolor($thumbnail_width, $thumbnail_height); + if ($process == false) { + getStandardImage(); + //echo 'Error creating thumb image: '.$thumbnail_width.'x'.$thumbnail_height; + OC_Log::write('contacts','Error creating thumb image for '.$id.' '.$thumbnail_width.'x'.$thumbnail_height,OC_Log::ERROR); + imagedestroy($process); + imagedestroy($src_img); + exit(); + } + imagecopyresampled($thumb, $process, 0, 0, ($x_mid-($thumbnail_width/2)), ($y_mid-($thumbnail_height/2)), $thumbnail_width, $thumbnail_height, $thumbnail_width, $thumbnail_height); + if ($thumb !== false) { + header('Content-Type: image/png'); + imagepng($thumb); + } else { + getStandardImage(); + OC_Log::write('contacts','Error resampling thumb image for '.$id.' '.$thumbnail_width.'x'.$thumbnail_height,OC_Log::ERROR); + //echo 'An error occurred resampling thumb.'; + } + imagedestroy($thumb); + imagedestroy($process); + imagedestroy($src_img); + } + else { + getStandardImage(); + } + exit(); + } +} +getStandardImage(); + +// Not found :-( +//echo $l10n->t('This card does not contain a photo.');