1
0
Fork 0
mirror of https://github.com/Oreolek/ifhub.club.git synced 2024-06-16 23:00:51 +03:00

Компонент photo

This commit is contained in:
Denis Shakhov 2014-11-19 19:02:48 +07:00
parent 5d21b3c2c4
commit 18bf206a55
9 changed files with 376 additions and 95 deletions

View file

@ -108,7 +108,7 @@ class ActionSettings extends Action
return $this->EventErrorDebug();
}
if (!$oUser = $this->User_GetUserById(getRequestStr('user_id'))) {
if (!$oUser = $this->User_GetUserById(getRequestStr('target_id'))) {
return $this->EventErrorDebug();
}
if (!$oUser->isAllowEdit()) {
@ -166,7 +166,7 @@ class ActionSettings extends Action
*/
$this->Viewer_SetResponseAjax('json');
if (!$oUser = $this->User_GetUserById(getRequestStr('user_id'))) {
if (!$oUser = $this->User_GetUserById(getRequestStr('target_id'))) {
return $this->EventErrorDebug();
}
if (!$oUser->isAllowEdit()) {
@ -245,7 +245,7 @@ class ActionSettings extends Action
*/
$this->Viewer_SetResponseAjax('json');
if (!$oUser = $this->User_GetUserById(getRequestStr('user_id'))) {
if (!$oUser = $this->User_GetUserById(getRequestStr('target_id'))) {
return $this->EventErrorDebug();
}
if (!$oUser->isAllowEdit()) {
@ -268,7 +268,7 @@ class ActionSettings extends Action
{
$this->Viewer_SetResponseAjax('json');
if (!$oUser = $this->User_GetUserById(getRequestStr('user_id'))) {
if (!$oUser = $this->User_GetUserById(getRequestStr('target_id'))) {
return $this->EventErrorDebug();
}
if (!$oUser->isAllowEdit()) {
@ -291,7 +291,7 @@ class ActionSettings extends Action
{
$this->Viewer_SetResponseAjax('json');
if (!$oUser = $this->User_GetUserById(getRequestStr('user_id'))) {
if (!$oUser = $this->User_GetUserById(getRequestStr('target_id'))) {
return $this->EventErrorDebug();
}
if (!$oUser->isAllowEdit()) {

View file

@ -546,6 +546,7 @@ $config['head']['default']['js'] = array(
"___path.skin.web___/components/editor/js/editor.js",
"___path.skin.web___/components/comment/js/comment.js",
"___path.skin.web___/components/comment/js/toolbar.comments.js",
"___path.skin.web___/components/photo/js/photo.js",
"___path.skin.web___/components/topic/js/topic.js",
"___path.skin.web___/components/topic/js/topic-add.js",
"___path.skin.web___/components/topic/js/topic-favourite.js",
@ -572,7 +573,6 @@ $config['head']['default']['js'] = array(
"___path.skin.web___/components/user/js/user-follow.js",
"___path.skin.web___/components/user/js/user-friend.js",
"___path.skin.web___/components/user/js/user-fields.js",
"___path.skin.web___/components/user/js/user-photo.js",
"___path.skin.web___/components/field/js/field.geo.js",
"___path.skin.web___/components/field/js/field.captcha.js",
"___path.skin.web___/components/uploader/js/uploader.js",
@ -633,6 +633,7 @@ $config['head']['default']['css'] = array(
"___path.skin.web___/components/comment/css/comment-form.css",
"___path.skin.web___/components/comment/css/comment.css",
"___path.skin.web___/components/comment/css/toolbar-comments.css",
"___path.skin.web___/components/photo/css/photo.css",
"___path.skin.web___/components/topic/css/topic.css",
"___path.skin.web___/components/wall/css/wall.css",
"___path.skin.web___/components/blog/css/blog.css",

View file

@ -292,7 +292,7 @@ jQuery(document).ready(function($){
$( '.js-user-fields' ).lsUserFields();
// Фото пользователя
$( '.js-user-photo' ).lsUserPhoto({
$( '.js-user-photo' ).lsPhoto({
urls: {
upload: aRouter.settings + 'ajax-upload-photo',
remove: aRouter.settings + 'ajax-remove-photo',

View file

@ -0,0 +1 @@
# Компонент photo

View file

@ -0,0 +1,61 @@
/**
* Фото
*
* @module ls/photo
*
* @license GNU General Public License, version 2
* @copyright 2013 OOO "ЛС-СОФТ" {@link http://livestreetcms.com}
* @author Denis Shakhov <denis.shakhov@gmail.com>
*/
.photo {
position: relative;
min-width: 100%;
min-height: 50px;
overflow: hidden;
}
/* Изображение */
.photo-image {
vertical-align: top;
max-width: 100%;
}
/* Действия */
.photo-actions {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
padding: 5px 0;
background: rgba( 0, 0, 0, .7 );
opacity: 0;
-webkit-transition: opacity .3s;
transition: opacity .3s;
}
.photo-actions li {
padding: 7px 15px;
color: #bbb;
font-size: 13px;
cursor: pointer;
-webkit-transition: color .2s;
transition: color .2s;
}
.photo-actions li:hover {
color: #eee;
}
.photo:hover .photo-actions {
opacity: 1;
}
/* @modifier nophoto */
.photo--nophoto .photo-image {
width: 100%;
}
.photo--nophoto .photo-actions {
opacity: 1;
}
.photo--nophoto .photo-actions-crop-avatar,
.photo--nophoto .photo-actions-remove {
display: none;
}

View file

@ -0,0 +1,223 @@
/**
* Photo
*
* @module ls/photo
*
* @license GNU General Public License, version 2
* @copyright 2013 OOO "ЛС-СОФТ" {@link http://livestreetcms.com}
* @author Denis Shakhov <denis.shakhov@gmail.com>
*
* TODO: Вынести опции кропа для фото и аватары в общие опции
* TODO: Сделать использование кропа аватара опциональным
*/
(function($) {
"use strict";
$.widget( "livestreet.lsPhoto", {
/**
* Дефолтные опции
*/
options: {
// Ссылки
urls: {
upload: null,
remove: null,
crop_photo: null,
crop_avatar: null,
save_photo: null,
save_avatar: null,
cancel_photo: null,
},
// Селекторы
selectors: {
image: '.js-photo-image',
actions: {
upload: '.js-photo-actions-upload',
upload_label: '.js-photo-actions-upload-label',
upload_input: '.js-photo-actions-upload-input',
crop_avatar: '.js-photo-actions-crop-avatar',
remove: '.js-photo-actions-remove',
},
},
// Классы
classes: {
nophoto: 'photo--nophoto'
},
// Параметры передаваемые в аякс запросах
params: {}
// Изменение аватара
// changeavatar: function() {}
},
/**
* Конструктор
*
* @constructor
* @private
*/
_create: function () {
var _this = this;
this.option( 'params.target_id', this.element.data( 'target-id' ) );
this.elements = {
image: this.element.find( this.option( 'selectors.image' ) ),
actions: {
upload: this.element.find( this.option( 'selectors.actions.upload' ) ),
upload_label: this.element.find( this.option( 'selectors.actions.upload_label' ) ),
upload_input: this.element.find( this.option( 'selectors.actions.upload_input' ) ),
crop_avatar: this.element.find( this.option( 'selectors.actions.crop_avatar' ) ),
remove: this.element.find( this.option( 'selectors.actions.remove' ) ),
}
};
this.elements.actions.upload_input.on( 'change' + this.eventNamespace, function () {
_this.upload( $( this ) );
});
this.elements.actions.crop_avatar.on( 'click' + this.eventNamespace, this.cropAvatar.bind( this ) );
this.elements.actions.remove.on( 'click' + this.eventNamespace, this.remove.bind( this ) );
},
/**
* Удаление фото
*/
remove: function() {
ls.ajax.load( this.option( 'urls.remove' ), this.option( 'params' ), function( response ) {
if ( response.bStateError ) {
ls.msg.error( null, response.sMsg );
} else {
this.element.addClass( this.option( 'classes.nophoto' ) );
this.elements.image.attr( 'src', response.photo );
this.elements.actions.upload_label.text( response.upload_text );
this._trigger( 'changeavatar', null, [ this, response.avatars ] );
}
}.bind( this ));
},
/**
* Загрузка фото
*/
upload: function( input ) {
var form = $( '<form method="post" enctype="multipart/form-data"></form>' ).hide().appendTo( 'body' );
input.clone( true ).insertAfter( input );
input.appendTo( form );
$( '<input type="hidden" name="target_id" value="' + this.option( 'params.target_id' ) + '" >').appendTo( form );
ls.ajax.submit( this.option( 'urls.upload' ), form, function ( response ) {
if ( response.bStateError ) {
ls.msg.error( response.sMsgTitle, response.sMsg );
} else {
this.cropPhoto( response );
}
form.remove();
}.bind( this ));
},
/**
* Показывает модальное кропа фото
*/
cropPhoto: function( image ) {
this.showModal( image, false, {
crop_params : {
minSize: [ 370, 370 ]
},
save_params : this.option( 'params' ),
crop_url : this.option( 'urls.crop_photo' ),
save_url : this.option( 'urls.save_photo' ),
save_callback : function( response, modal, image ) {
this.element.removeClass( this.option( 'classes.nophoto' ) );
this.elements.image.attr( 'src', response.photo );
this.elements.actions.upload_label.text( response.upload_text );
// TODO: Временный хак (модальное не показывается сразу после закрытия предыдущего окна)
setTimeout( this.cropAvatar.bind( this ), 300);
},
modal_close_callback : function( event, modal ) {
ls.ajax.load( this.option( 'urls.cancel_photo' ), this.option( 'params' ) );
}
});
},
/**
* Показывает модальное кропа аватара
*/
cropAvatar: function() {
var photo = this.elements.image;
var image = {
path: photo.attr( 'src' ),
// TODO: IE8 naturalWidth naturalHeight
original_width: photo[0].naturalWidth,
original_height: photo[0].naturalHeight,
width: photo[0].naturalWidth,
height: photo[0].naturalHeight
};
this.showModal( image, true, {
crop_params : {
minSize: [ 100, 100 ],
aspectRatio: 1
},
save_callback : function( response, modal, image ) {
this._trigger( 'changeavatar', null, [ this, response.avatars ] );
},
save_params : this.option( 'params' ),
crop_url : this.option( 'urls.crop_avatar' ),
save_url : this.option( 'urls.save_avatar' )
});
},
/**
* Показывает модальное кропа
*
* TODO: Перенести в компонент crop
*/
showModal: function( image, usePreview, params ) {
var _this = this;
ls.modal.load( params.crop_url, {
original_width: image.original_width,
original_height: image.original_height,
width: image.width,
height: image.height,
image_src: image.path,
use_preview: usePreview
}, {
aftershow: function( e, modal ) {
var crop = modal.element.find('.js-crop').lsCrop( params.crop_params );
var submit = modal.element.find('.js-crop-submit');
var image = crop.lsCrop( 'getImage' );
submit.on( 'click', function() {
var paramsRequest = $.extend({}, {
size: crop.lsCrop( 'getSelection' ),
canvas_width: image.innerWidth()
}, params.save_params || {});
ls.ajax.load( params.save_url, paramsRequest, function( response ) {
if ( response.bStateError ) {
ls.msg.error( null, response.sMsg );
} else {
modal.hide();
if ( $.isFunction( params.save_callback ) ) {
params.save_callback.call( _this, response, modal, image );
}
}
});
});
},
afterhide: function( event, modal ) {
if ( $.isFunction( params.modal_close_callback ) ) {
params.modal_close_callback.call( _this, event, modal );
}
},
center: false
});
}
});
})(jQuery);

View file

@ -0,0 +1,60 @@
{**
* Photo
*
* @param string $url
* @param integer $targetId
* @param boolean $hasPhoto
* @param boolean $photoPath
* @param boolean $photoAltText
* @param boolean $editable
*
* TODO: Вынести текстовки в photo
*}
{$component = 'photo'}
{$hasPhoto = $smarty.local.hasPhoto}
{$mods = $smarty.local.mods}
{if ! $hasPhoto}
{$mods = "$mods nophoto"}
{/if}
<div class="{$component} {mod name=$component mods=$mods} {$smarty.local.classes}"
data-target-id="{$smarty.local.targetId}"
{foreach $smarty.local.attributes as $attr}{$attr@key}="{$attr@value}" {/foreach}>
{* Фото *}
<a href="{$smarty.local.url}">
<img src="{$smarty.local.photoPath}" alt="{$smarty.local.photoAltText}" class="{$component}-image js-photo-image" />
</a>
{* Действия *}
{if $smarty.local.editable}
<ul class="{$component}-actions">
{* Загрузить *}
<li class="{$component}-actions-upload js-photo-actions-upload">
<label class="form-input-file">
<span class="js-photo-actions-upload-label">
{if $hasPhoto}
{lang 'user.photo.actions.change_photo'}
{else}
{lang 'user.photo.actions.upload_photo'}
{/if}
</span>
<input type="file" name="photo" class="js-photo-actions-upload-input">
</label>
</li>
{* Изменить аватар *}
<li class="{$component}-actions-crop-avatar js-photo-actions-crop-avatar">
{lang 'user.photo.actions.change_avatar'}
</li>
{* Удалить фото *}
<li class="{$component}-actions-remove js-photo-actions-remove">
{lang 'user.photo.actions.remove'}
</li>
</ul>
{/if}
</div>

View file

@ -10,51 +10,29 @@
{/block}
{block 'block_content'}
<div class="user-photo {if ! $oUserProfile->getProfileFoto()}user-photo--nophoto{/if} js-user-photo" data-user-id="{$oUserProfile->getId()}">
{* Статус онлайн\оффлайн *}
{if $oSession}
{if $oUserProfile->isOnline() && $smarty.now - strtotime($oSession->getDateLast()) < 60*5}
<div class="user-status user-status--online">{$aLang.user.status.online}</div>
{else}
<div class="user-status user-status--offline">
{$date = {date_format date=$oSession->getDateLast() hours_back="12" minutes_back="60" day_back="8" now="60*5" day="day H:i" format="j F в G:i"}}
{* Статус онлайн\оффлайн *}
{if $oSession}
{if $oUserProfile->isOnline() && $smarty.now - strtotime($oSession->getDateLast()) < 60*5}
<div class="user-status user-status--online">{$aLang.user.status.online}</div>
{else}
<div class="user-status user-status--offline">
{$date = {date_format date=$oSession->getDateLast() hours_back="12" minutes_back="60" day_back="8" now="60*5" day="day H:i" format="j F в G:i"}|lower}
{if $oUserProfile->getProfileSex() != 'woman'}
{lang 'user.status.was_online_male' date=$date}
{else}
{lang 'user.status.was_online_female' date=$date}
{/if}
</div>
{/if}
{if $oUserProfile->getProfileSex() != 'woman'}
{lang 'user.status.was_online_male' date=$date}
{else}
{lang 'user.status.was_online_female' date=$date}
{/if}
</div>
{/if}
{/if}
{* Фото *}
<a href="{$oUserProfile->getUserWebPath()}">
<img src="{$oUserProfile->getProfileFotoPath()}" alt="{$oUserProfile->getDisplayName()} photo" class="user-photo-image js-user-photo-image" />
</a>
{* Действия (редактировать/удалить) *}
{if $oUserProfile->isAllowEdit()}
<ul class="user-photo-actions">
<li class="js-user-photo-actions-upload">
<label class="form-input-file">
<span class="js-user-photo-actions-upload-label">
{if $oUserProfile->getProfileFoto()}
{lang 'user.photo.actions.change_photo'}
{else}
{lang 'user.photo.actions.upload_photo'}
{/if}
</span>
<input type="file" name="photo" class="js-user-photo-actions-upload-input">
</label>
</li>
<li class="js-user-photo-actions-crop-avatar" style="{if !$oUserProfile->getProfileFoto()}display:none;{/if}">
{lang 'user.photo.actions.change_avatar'}
</li>
<li class="js-user-photo-actions-remove" style="{if !$oUserProfile->getProfileFoto()}display:none;{/if}">
{lang 'user.photo.actions.remove'}
</li>
</ul>
{/if}
</div>
{include 'components/photo/photo.tpl'
classes = 'js-user-photo'
hasPhoto = $oUserProfile->getProfileFoto()
editable = $oUserProfile->isAllowEdit()
targetId = $oUserProfile->getId()
url = $oUserProfile->getUserWebPath()
photoPath = $oUserProfile->getProfileFotoPath()
photoAltText = $oUserProfile->getDisplayName()}
{/block}

View file

@ -6,16 +6,7 @@
*/
.block--user-photo .block-content {
padding: 0;
}
.user-photo {
position: relative;
min-width: 100%;
min-height: 50px;
overflow: hidden;
}
.user-photo-image {
vertical-align: top;
max-width: 100%;
}
/* Статус (онлайн/оффлайн) */
@ -23,6 +14,7 @@
position: absolute;
top: 20px;
left: 0;
z-index: 1;
padding: 12px 15px;
font: 300 13px/1em 'Open Sans';
}
@ -37,41 +29,6 @@
color: #fff;
}
/* Действия */
.user-photo-actions {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
padding: 5px 0;
background: rgba( 0, 0, 0, .7 );
opacity: 0;
-webkit-transition: opacity .3s;
transition: opacity .3s;
}
.user-photo-actions li {
padding: 7px 15px;
color: #bbb;
font-size: 13px;
cursor: pointer;
-webkit-transition: color .2s;
transition: color .2s;
}
.user-photo-actions li:hover {
color: #eee;
}
.user-photo:hover .user-photo-actions {
opacity: 1;
}
/* @modifier nophoto */
.user-photo--nophoto .user-photo-image {
width: 100%;
}
.user-photo--nophoto .user-photo-actions {
opacity: 1;
}
/**
* Блок управления на странице пользователя
*