1
0
Fork 0
mirror of https://github.com/Oreolek/ifhub.club.git synced 2024-05-21 18:28:17 +03:00

Топики-фотосеты. Бета

This commit is contained in:
kirsan 2011-07-19 21:32:36 +00:00
parent d49c0eeb46
commit bcf815ea34
52 changed files with 4466 additions and 37 deletions

View file

@ -0,0 +1,611 @@
<?php
class ActionPhotoset extends Action {
/**
* Главное меню
*
* @var unknown_type
*/
protected $sMenuHeadItemSelect='blog';
/**
* Меню
*
* @var unknown_type
*/
protected $sMenuItemSelect='photoset';
/**
* СубМеню
*
* @var unknown_type
*/
protected $sMenuSubItemSelect='add';
/**
* Текущий юзер
*
* @var unknown_type
*/
protected $oUserCurrent=null;
/**
* Инициализация
*
* @return unknown
*/
public function Init() {
/**
* Проверяем авторизован ли юзер
*/
// if (!$this->User_IsAuthorization()) {
// $this->Message_AddErrorSingle($this->Lang_Get('not_access'),$this->Lang_Get('error'));
// return Router::Action('error');
// }
$this->oUserCurrent=$this->User_GetUserCurrent();
$this->SetDefaultEvent('add');
$this->Viewer_AddHtmlTitle($this->Lang_Get('topic_photoset_title'));
}
/**
* Регистрируем евенты
*
*/
protected function RegisterEvent() {
$this->AddEvent('add','EventAdd');
$this->AddEvent('edit','EventEdit');
$this->AddEvent('deleteimage','EventDeleteImage');
$this->AddEvent('upload','EventUpload');
$this->AddEvent('getMore','EventGetMore');
$this->AddEvent('setimagedescription','EventSetImageDescription');
}
/**********************************************************************************
************************ РЕАЛИЗАЦИЯ ЭКШЕНА ***************************************
**********************************************************************************
*/
protected function EventGetMore()
{
$this->Viewer_SetResponseAjax('json');
$iTopicid = getRequest('topic_id');
$oTopic = $this->Topic_getTopicById($iTopicid);
if (!$oTopic || !getRequest('last_id')) {
$this->Message_AddError($this->Lang_Get('system_error'), $this->Lang_Get('error'));
return false;
}
$aPhotos = $oTopic->getPhotos(getRequest('last_id'), Config::Get('module.topic.photoset.per_page'));
$aResult = array();
if (count ($aPhotos)) {
foreach($aPhotos as $oPhoto) {
$aResult[] = array('id' => $oPhoto->getId(), 'path_thumb' => $oPhoto->getWebPath('50crop'), 'path' => $oPhoto->getWebPath(), 'description' => $oPhoto->getDescription());
}
$this->Viewer_AssignAjax('photos', $aResult);
}
}
protected function EventDeleteImage()
{
$this->Viewer_SetResponseAjax('json');
$iId = getRequest('id');
$oPhoto = $this->Topic_getTopicPhotoById($iId);
if ($oPhoto) {
$this->Topic_deleteTopicPhoto($oPhoto);
$this->Message_AddNotice($this->Lang_Get('topic_photoset_photo_deleted'), $this->Lang_Get('attention'));
}
}
protected function EventSetImageDescription()
{
$this->Viewer_SetResponseAjax('json');
$iPhotoId = getRequest('id');
$oPhoto = $this->Topic_getTopicPhotoById($iPhotoId);
if ($oPhoto) {
$oPhoto->setDescription(getRequest('text'));
$this->Topic_updateTopicPhoto($oPhoto);
}
}
protected function EventUpload()
{
if (isset($_REQUEST['SSID'])) {
session_id($_REQUEST['SSID']);
}
if (getRequest('is_iframe')) {
$this->Viewer_SetResponseAjax('jsonIframe', false);
} else {
$this->Viewer_SetResponseAjax('json');
}
$iTopicId = getRequest('topic_id');
$sTargetId = null;
$iCountPhotos = 0;
if (!$iTopicId) {
$sTargetId = empty($_COOKIE['ls_photoset_target_tmp']) ? getRequest('ls_photoset_target_tmp') : $_COOKIE['ls_photoset_target_tmp'];
if (!$sTargetId) {
$this->Message_AddError($this->Lang_Get('system_error'), $this->Lang_Get('error'));
return false;
}
$iCountPhotos = $this->Topic_getCountPhotosByTargetTmp($sTargetId);
} else {
$oTopic = $this->Topic_getTopicById($iTopicId);
if (!$oTopic) {
$this->Message_AddError($this->Lang_Get('system_error'), $this->Lang_Get('error'));
return false;
}
$iCountPhotos = $this->Topic_getCountPhotosByTopicId($iTopicId);
}
if ($iCountPhotos >= Config::Get('module.topic.photoset.count_photos_max')) {
$this->Message_AddError($this->Lang_Get('topic_photoset_error_too_much_photos', array('%%MAX%%' => Config::Get('module.topic.photoset.count_photos_max'))), $this->Lang_Get('error'));
return false;
}
if (filesize($_FILES['Filedata']['tmp_name']) > Config::Get('module.topic.photoset.photo_max_size')*1024) {
$this->Message_AddError($this->Lang_Get('topic_photoset_error_bad_filesize', array('MAX' => Config::Get('module.topic.photoset.photo_max_size'))), $this->Lang_Get('error'));
return false;
}
$sFile = $this->Topic_uploadImage($_FILES['Filedata']);
if ($sFile) {
$oPhoto = Engine::GetEntity('Topic_TopicPhoto');
$oPhoto->setPath($sFile);
if ($iTopicId) {
$oPhoto->setTopicId($iTopicId);
} else {
$oPhoto->setTargetTmp($sTargetId);
}
$iId = $this->Topic_addTopicPhoto($oPhoto);
$oPhoto->setId($iId);
$this->Viewer_AssignAjax('file', $oPhoto->getWebPath(100));
$this->Viewer_AssignAjax('id', $oPhoto->getId());
$this->Message_AddNotice($this->Lang_Get('topic_photoset_photo_added'), $this->Lang_Get('attention'));
} else {
$this->Message_AddError($this->Lang_Get('system_error'), $this->Lang_Get('error'));
}
}
/**
* Редактирование ссылки
*
* @return unknown
*/
protected function EventEdit() {
/**
* Меню
*/
$this->sMenuSubItemSelect='';
$this->sMenuItemSelect='photoset';
/**
* Получаем номер топика из УРЛ и проверяем существует ли он
*/
$sTopicId=$this->GetParam(0);
if (!($oTopic=$this->Topic_GetTopicById($sTopicId))) {
return parent::EventNotFound();
}
/**
* Если права на редактирование
*/
if (!$this->ACL_IsAllowEditTopic($oTopic,$this->oUserCurrent)) {
return parent::EventNotFound();
}
/**
* Вызов хуков
*/
$this->Hook_Run('topic_edit_show',array('oTopic'=>$oTopic));
/**
* Загружаем переменные в шаблон
*/
$this->Viewer_Assign('aBlogsAllow',$this->Blog_GetBlogsAllowByUser($this->oUserCurrent));
$this->Viewer_AddHtmlTitle($this->Lang_Get('topic_photoset_title_edit'));
/**
* Устанавливаем шаблон вывода
*/
$this->SetTemplateAction('add');
/**
* Проверяем отправлена ли форма с данными(хотяб одна кнопка)
*/
if (isset($_REQUEST['submit_topic_publish']) or isset($_REQUEST['submit_topic_save'])) {
/**
* Обрабатываем отправку формы
*/
return $this->SubmitEdit($oTopic);
} else {
/**
* Заполняем поля формы для редактирования
* Только перед отправкой формы!
*/
$_REQUEST['topic_title']=$oTopic->getTitle();
$_REQUEST['topic_text']=$oTopic->getTextSource();
$_REQUEST['topic_tags']=$oTopic->getTags();
$_REQUEST['blog_id']=$oTopic->getBlogId();
$_REQUEST['topic_id']=$oTopic->getId();
$_REQUEST['topic_publish_index']=$oTopic->getPublishIndex();
$_REQUEST['topic_forbid_comment']=$oTopic->getForbidComment();
$_REQUEST['topic_main_photo']=$oTopic->getMainPhotoId();
$_REQUEST['topic_main_photo_description']=$oTopic->getMainPhotoDescription();
$_REQUEST['topic_forbid_comment']=$oTopic->getForbidComment();
}
$this->Viewer_Assign('aPhotos', $this->Topic_getPhotosByTopicId($oTopic->getId()));
}
/**
* Добавление ссылки
*
* @return unknown
*/
protected function EventAdd() {
/**
* Меню
*/
$this->sMenuSubItemSelect='add';
/**
* Загружаем переменные в шаблон
*/
$this->Viewer_Assign('aBlogsAllow',$this->Blog_GetBlogsAllowByUser($this->oUserCurrent));
$this->Viewer_AddHtmlTitle($this->Lang_Get('topic_photoset_title_create'));
if (empty($_COOKIE['ls_photoset_target_tmp'])) {
setcookie('ls_photoset_target_tmp', func_generator(), time()+24*3600);
} else {
setcookie('ls_photoset_target_tmp', $_COOKIE['ls_photoset_target_tmp'], time()+24*3600);
$this->Viewer_Assign('aPhotos', $this->Topic_getPhotosByTargetTmp($_COOKIE['ls_photoset_target_tmp']));
}
/**
* Обрабатываем отправку формы
*/
return $this->SubmitAdd();
}
/**
* Обработка добавлени топика
*
* @return unknown
*/
protected function SubmitAdd() {
/**
* Проверяем отправлена ли форма с данными(хотяб одна кнопка)
*/
if (!isPost('submit_topic_publish') and !isPost('submit_topic_save')) {
return false;
}
/**
* Проверка корректности полей формы
*/
if (!$this->checkTopicFields()) {
return false;
}
/**
* Определяем в какой блог делаем запись
*/
$iBlogId=getRequest('blog_id');
if ($iBlogId==0) {
$oBlog=$this->Blog_GetPersonalBlogByUserId($this->oUserCurrent->getId());
} else {
$oBlog=$this->Blog_GetBlogById($iBlogId);
}
/**
* Если блог не определен выдаем предупреждение
*/
if (!$oBlog) {
$this->Message_AddErrorSingle($this->Lang_Get('topic_create_blog_error_unknown'),$this->Lang_Get('error'));
return false;
}
/**
* Проверяем права на постинг в блог
*/
if (!$this->ACL_IsAllowBlog($oBlog,$this->oUserCurrent)) {
$this->Message_AddErrorSingle($this->Lang_Get('topic_create_blog_error_noallow'),$this->Lang_Get('error'));
return false;
}
/**
* Проверяем разрешено ли постить топик по времени
*/
if (isPost('submit_topic_publish') and !$this->ACL_CanPostTopicTime($this->oUserCurrent)) {
$this->Message_AddErrorSingle($this->Lang_Get('topic_time_limit'),$this->Lang_Get('error'));
return;
}
/**
* Теперь можно смело добавлять топик к блогу
*/
$oTopic=Engine::GetEntity('Topic');
$oTopic->setBlogId($oBlog->getId());
$oTopic->setUserId($this->oUserCurrent->getId());
$oTopic->setType('photoset');
$oTopic->setTitle(getRequest('topic_title'));
$oTopic->setText(htmlspecialchars(getRequest('topic_text')));
$oTopic->setTextShort(htmlspecialchars(getRequest('topic_text')));
$oTopic->setTextSource(getRequest('topic_text'));
$oTopic->setTags(getRequest('topic_tags'));
$oTopic->setDateAdd(date("Y-m-d H:i:s"));
$oTopic->setUserIp(func_getIp());
$oTopic->setCutText(null);
$oTopic->setTextHash(md5($oTopic->getType().$oTopic->getText().$oTopic->getTitle()));
$aPhotos = $this->Topic_getPhotosByTargetTmp($_COOKIE['ls_photoset_target_tmp']);
if (getRequest('topic_main_photo')) {
$oTopic->setMainPhoto(getRequest('topic_main_photo'));
} else {
$oFirstPhoto = $aPhotos[0];
$oTopic->setMainPhoto($oFirstPhoto->getId());
}
$oTopic->setMainPhotoDescription(getRequest('topic_main_photo_description'));
/**
* Проверяем топик на уникальность
*/
if ($oTopicEquivalent=$this->Topic_GetTopicUnique($this->oUserCurrent->getId(),$oTopic->getTextHash())) {
$this->Message_AddErrorSingle($this->Lang_Get('topic_create_text_error_unique'),$this->Lang_Get('error'));
return false;
}
/**
* Публикуем или сохраняем
*/
if (isset($_REQUEST['submit_topic_publish'])) {
$oTopic->setPublish(1);
$oTopic->setPublishDraft(1);
} else {
$oTopic->setPublish(0);
$oTopic->setPublishDraft(0);
}
/**
* Принудительный вывод на главную
*/
$oTopic->setPublishIndex(0);
if ($this->oUserCurrent->isAdministrator()) {
if (getRequest('topic_publish_index')) {
$oTopic->setPublishIndex(1);
}
}
/**
* Запрет на комментарии к топику
*/
$oTopic->setForbidComment(0);
if (getRequest('topic_forbid_comment')) {
$oTopic->setForbidComment(1);
}
/**
* Запускаем выполнение хуков
*/
$this->Hook_Run('topic_add_before', array('oTopic'=>$oTopic,'oBlog'=>$oBlog));
/**
* Добавляем топик
*/
if ($this->Topic_AddTopic($oTopic)) {
$this->Hook_Run('topic_add_after', array('oTopic'=>$oTopic,'oBlog'=>$oBlog));
/**
* Получаем топик, чтоб подцепить связанные данные
*/
$oTopic=$this->Topic_GetTopicById($oTopic->getId());
//Делаем рассылку спама всем, кто состоит в этом блоге
if ($oTopic->getPublish()==1 and $oBlog->getType()!='personal') {
$this->Topic_SendNotifyTopicNew($oBlog,$oTopic,$this->oUserCurrent);
}
if (count($aPhotos)) {
foreach($aPhotos as $oPhoto) {
$oPhoto->setTargetTmp(null);
$oPhoto->setTopicId($oTopic->getId());
$this->Topic_updateTopicPhoto($oPhoto);
}
}
setcookie('ls_photoset_target_tmp', null);
Router::Location($oTopic->getUrl());
} else {
$this->Message_AddErrorSingle($this->Lang_Get('system_error'));
return Router::Action('error');
}
}
/**
* Обработка редактирования топика
*
* @param unknown_type $oTopic
* @return unknown
*/
protected function SubmitEdit($oTopic) {
/**
* Проверка корректности полей формы
*/
if (!$this->checkTopicFields($oTopic)) {
return false;
}
/**
* Определяем в какой блог делаем запись
*/
$iBlogId=getRequest('blog_id');
if ($iBlogId==0) {
$oBlog=$this->Blog_GetPersonalBlogByUserId($oTopic->getUserId());
} else {
$oBlog=$this->Blog_GetBlogById($iBlogId);
}
/**
* Если блог не определен выдаем предупреждение
*/
if (!$oBlog) {
$this->Message_AddErrorSingle($this->Lang_Get('topic_create_blog_error_unknown'),$this->Lang_Get('error'));
return false;
}
/**
* Проверяем права на постинг в блог
*/
if (!$this->ACL_IsAllowBlog($oBlog,$this->oUserCurrent)) {
$this->Message_AddErrorSingle($this->Lang_Get('topic_create_blog_error_noallow'),$this->Lang_Get('error'));
return false;
}
/**
* Проверяем разрешено ли постить топик по времени
*/
if (isPost('submit_topic_publish') and !$oTopic->getPublishDraft() and !$this->ACL_CanPostTopicTime($this->oUserCurrent)) {
$this->Message_AddErrorSingle($this->Lang_Get('topic_time_limit'),$this->Lang_Get('error'));
return;
}
/**
* Теперь можно смело редактировать топик
*/
$oTopic->setBlogId($oBlog->getId());
$oTopic->setText(htmlspecialchars(getRequest('topic_text')));
$oTopic->setTextShort(htmlspecialchars(getRequest('topic_text')));
$oTopic->setTextSource(getRequest('topic_text'));
$oTopic->setTags(getRequest('topic_tags'));
$oTopic->setUserIp(func_getIp());
$oTopic->setMainPhoto(getRequest('topic_main_photo'));
$aPhotos = $oTopic->getPhotos();
if (getRequest('topic_main_photo')) {
$oTopic->setMainPhoto(getRequest('topic_main_photo'));
} else {
$oFirstPhoto = $aPhotos[0];
$oTopic->setMainPhoto($oFirstPhoto->getId());
}
$oTopic->setMainPhotoDescription(getRequest('topic_main_photo_description'));
$oTopic->setTextHash(md5($oTopic->getType().$oTopic->getText().$oTopic->getTitle()));
/**
* Проверяем топик на уникальность
*/
if ($oTopicEquivalent=$this->Topic_GetTopicUnique($this->oUserCurrent->getId(),$oTopic->getTextHash())) {
if ($oTopicEquivalent->getId()!=$oTopic->getId()) {
$this->Message_AddErrorSingle($this->Lang_Get('topic_create_text_error_unique'),$this->Lang_Get('error'));
return false;
}
}
/**
* Публикуем или сохраняем в черновиках
*/
$bSendNotify=false;
if (isset($_REQUEST['submit_topic_publish'])) {
$oTopic->setPublish(1);
if ($oTopic->getPublishDraft()==0) {
$oTopic->setPublishDraft(1);
$oTopic->setDateAdd(date("Y-m-d H:i:s"));
$bSendNotify=true;
}
} else {
$oTopic->setPublish(0);
}
/**
* Принудительный вывод на главную
*/
if ($this->oUserCurrent->isAdministrator()) {
if (getRequest('topic_publish_index')) {
$oTopic->setPublishIndex(1);
} else {
$oTopic->setPublishIndex(0);
}
}
/**
* Запрет на комментарии к топику
*/
$oTopic->setForbidComment(0);
if (getRequest('topic_forbid_comment')) {
$oTopic->setForbidComment(1);
}
$this->Hook_Run('topic_edit_before', array('oTopic'=>$oTopic,'oBlog'=>$oBlog));
/**
* Сохраняем топик
*/
if ($this->Topic_UpdateTopic($oTopic)) {
$this->Hook_Run('topic_edit_after', array('oTopic'=>$oTopic,'oBlog'=>$oBlog,'bSendNotify'=>&$bSendNotify));
/**
* Рассылаем о новом топике подписчикам блога
*/
if ($bSendNotify) {
$this->Topic_SendNotifyTopicNew($oBlog,$oTopic,$this->oUserCurrent);
}
if (!$oTopic->getPublish() and !$this->oUserCurrent->isAdministrator() and $this->oUserCurrent->getId()!=$oTopic->getUserId()) {
Router::Location($oBlog->getUrlFull());
}
Router::Location($oTopic->getUrl());
} else {
$this->Message_AddErrorSingle($this->Lang_Get('system_error'));
return Router::Action('error');
}
}
/**
* Проверка полей формы
*
* @return unknown
*/
protected function checkTopicFields($oTopic=null) {
$this->Security_ValidateSendForm();
$bOk=true;
/**
* Проверяем есть ли блог в кторый постим
*/
if (!func_check(getRequest('blog_id',null,'post'),'id')) {
$this->Message_AddError($this->Lang_Get('topic_create_blog_error_unknown'),$this->Lang_Get('error'));
$bOk=false;
}
if (!func_check(getRequest('topic_text',null,'post'),'text',0,500)) {
$this->Message_AddError($this->Lang_Get('topic_create_text_error'),$this->Lang_Get('error'));
$bOk=false;
}
/**
* проверяем заполнение вопроса/ответов только если еще никто не голосовал
*/
if (is_null($oTopic) ) {
/**
* Проверяем есть ли заголовок топика
*/
if (!func_check(getRequest('topic_title',null,'post'),'text',2,200)) {
$this->Message_AddError($this->Lang_Get('topic_create_title_error'),$this->Lang_Get('error'));
$bOk=false;
}
}
/**
* Проверяем есть ли теги(метки)
*/
if (!func_check(getRequest('topic_tags',null,'post'),'text',2,500)) {
$this->Message_AddError($this->Lang_Get('topic_create_tags_error'),$this->Lang_Get('error'));
$bOk=false;
}
/**
* проверяем ввод тегов
*/
$sTags=getRequest('topic_tags');
$aTags=explode(',',$sTags);
$aTagsNew=array();
foreach ($aTags as $sTag) {
$sTag=trim($sTag);
if (func_check($sTag,'text',2,50)) {
$aTagsNew[]=$sTag;
}
}
if (!count($aTagsNew)) {
$this->Message_AddError($this->Lang_Get('topic_create_tags_error_bad'),$this->Lang_Get('error'));
$bOk=false;
} else {
$_REQUEST['topic_tags']=join(',',$aTagsNew);
}
$iTopicId = getRequest('topic_id');
$sTargetId = null;
$iCountPhotos = 0;
if (!$oTopic) {
$sTargetId = $_COOKIE['ls_photoset_target_tmp'];
if (!$sTargetId) {
$this->Message_AddError($this->Lang_Get('system_error'), $this->Lang_Get('error'));
return false;
}
$iCountPhotos = $this->Topic_getCountPhotosByTargetTmp($sTargetId);
} else {
$iCountPhotos = $this->Topic_getCountPhotosByTopicId($oTopic->getId());
}
if ($iCountPhotos < Config::Get('module.topic.photoset.count_photos_min') || $iCountPhotos > Config::Get('module.topic.photoset.count_photos_max')) {
$this->Message_AddError($this->Lang_Get('topic_photoset_error_count_photos', array('%%MIN%%' => Config::Get('module.topic.photoset.count_photos_min'), '%%MAX%%' => Config::Get('module.topic.photoset.count_photos_max'))), $this->Lang_Get('error'));
return false;
}
/**
* Выполнение хуков
*/
$this->Hook_Run('check_photoset_fields', array('bOk'=>&$bOk));
return $bOk;
}
/**
* При завершении экшена загружаем необходимые переменные
*
*/
public function EventShutdown() {
$this->Viewer_Assign('sMenuHeadItemSelect',$this->sMenuHeadItemSelect);
$this->Viewer_Assign('sMenuItemSelect',$this->sMenuItemSelect);
$this->Viewer_Assign('sMenuSubItemSelect',$this->sMenuSubItemSelect);
}
}
?>

View file

@ -1405,5 +1405,136 @@ class ModuleTopic extends Module {
@unlink($sFileTmp);
return ModuleImage::UPLOAD_IMAGE_ERROR;
}
public function getTopicPhotoById($iPhotoId)
{
return $this->oMapperTopic->getTopicPhotoById($iPhotoId);
}
public function getPhotosByTopicId($iTopicId, $iFromId = null, $iCount = null)
{
return $this->oMapperTopic->getPhotosByTopicId($iTopicId, $iFromId, $iCount);
}
public function getPhotosByTargetTmp($sTargetTmp)
{
return $this->oMapperTopic->getPhotosByTargetTmp($sTargetTmp);
}
public function getCountPhotosByTopicId($iTopicId)
{
return $this->oMapperTopic->getCountPhotosByTopicId($iTopicId);
}
public function getCountPhotosByTargetTmp($sTargetTmp)
{
return $this->oMapperTopic->getCountPhotosByTargetTmp($sTargetTmp);
}
public function getTopicMainPhoto($iTopicId)
{
return $this->oMapperTopic->getTopicMainPhoto($iTopicId);
}
public function addTopicPhoto($oPhoto)
{
return $this->oMapperTopic->addTopicPhoto($oPhoto);
}
public function updateTopicPhoto($oPhoto)
{
$this->oMapperTopic->updateTopicPhoto($oPhoto);
}
public function deleteTopicPhoto($oPhoto)
{
$this->oMapperTopic->deleteTopicPhoto($oPhoto->getId());
$sUploadsDir = Config::Get('path.root.server') . Config::Get('path.uploads.root') . '/';
unlink($sUploadsDir . $oPhoto->getPath());
list ($sFileBase, $sFileExt) = explode('.', $oPhoto->getPath());
$aSizes=Config::Get('topic.image.size');
// Удаляем все сгенерированные миниатюры основываясь на данных из конфига.
foreach ($aSizes as $aSize)
{
$sFileName = $sUploadsDir . $sFileBase.'_'.$aSize['w'];
if ($aSize['crop'])
{
$sFileName .= 'crop';
}
$sFileName .= '.' . $sFileExt;
unlink($sFileName);
}
return;
}
public function uploadImage($aFile)
{
if(!is_array($aFile) || !isset($aFile['tmp_name']))
{
return false;
}
$sFileName = func_generator(10);
$sIdDir = $this->getIdDir();
$sPath = Config::Get('path.root.server') . Config::Get('path.uploads.root') . '/' . $sIdDir;
if (!is_dir($sPath))
{
mkdir($sPath, 0755, true);
}
$sFile = $sPath . $sFileName;
if (!move_uploaded_file($aFile['tmp_name'],$sFile))
{
return false;
}
$aParams=$this->Image_BuildParams('topic');
$oImage = new LiveImage($sFile);
/**
* Если объект изображения не создан,
* возвращаем ошибку
*/
if($sError=$oImage->get_last_error()) {
// Вывод сообщения об ошибки, произошедшей при создании объекта изображения
$this->Message_AddError($sError,$this->Lang_Get('error'));
@unlink($sFile);
return false;
}
// Добавляем к загруженному файлу расширение
rename($sFile, $sFile . '.' . $oImage->get_image_params('format'));
$sFile = $sFile . '.' . $oImage->get_image_params('format');
$aSizes=Config::Get('topic.image.size');
// превращаем путь в относительный, т.к. графическая библиотека полные не понимает
$sPath= str_replace(Config::Get('path.root.server'), '', $sPath);
foreach ($aSizes as $aSize)
{
// Для каждого указанного в конфиге размера генерируем картинку
$sNewFileName = $sFileName.'_'.$aSize['w'];
$oImage = new LiveImage($sFile);
if ($aSize['crop'])
{
$this->Image_CropProportion($oImage, $aSize['w'], $aSize['h'], true);
$sNewFileName .= 'crop';
}
$this->Image_Resize($sFile,$sPath,$sNewFileName,Config::Get('view.img_max_width'),Config::Get('view.img_max_height'),$aSize['w'],$aSize['h'],true,$aParams,$oImage);
}
$sFile = $sIdDir . $sFileName . '.' . $oImage->get_image_params('format');
return $sFile;
}
/**
* Получение пути до каталога, куда загружаются изображения
* @param int $iTopicId
* @return string Путь вида 'images/topic/00/00/00/<id>/YYYY/mm/dd/
*/
private function getIdDir()
{
$sDateDir = date('Y/m/d');
return 'images/topic/' . $sDateDir . '/';
}
}
?>

View file

@ -287,7 +287,35 @@ class ModuleTopic_EntityTopic extends Entity
$this->setExtra($this->aExtra);
}
// Методы для фото-топика
public function getPhotos($iFromId = null, $iCount = null)
{
return $this->Topic_getPhotosByTopicId($this->getId(), $iFromId, $iCount);
}
public function getPhotosCount()
{
return $this->Topic_getCountPhotosByTopicId($this->getId());
}
public function getMainPhotoId()
{
$this->extractExtra();
return $this->aExtra['main_photo'];
}
public function getMainPhoto()
{
$this->extractExtra();
return $this->Topic_getTopicPhotoById($this->aExtra['main_photo']);
}
public function getMainPhotoDescription()
{
$this->extractExtra();
return $this->aExtra['main_photo_description'];
}
//*************************************************************************************************************************************************
public function setId($data) {
@ -381,5 +409,20 @@ class ModuleTopic_EntityTopic extends Entity
public function setIsFavourite($data) {
$this->_aData['topic_is_favourite']=$data;
}
// Методы для фото-топика
public function setMainPhoto($iPhotoId)
{
$this->extractExtra();
$this->aExtra['main_photo'] = $iPhotoId;
$this->setExtra($this->aExtra);
}
public function setMainPhotoDescription($sDescription)
{
$this->extractExtra();
$this->aExtra['main_photo_description'] = $sDescription;
$this->setExtra($this->aExtra);
}
}
?>

View file

@ -0,0 +1,57 @@
<?php
class ModuleTopic_EntityTopicPhoto extends Entity
{
public function getId()
{
return $this->_aData['id'];
}
public function getTopicId()
{
return ( isset($this->_aData['topic_id'])) ? $this->_aData['topic_id'] : null;
}
public function getTargetTmp()
{
return $this->_aData['target_tmp'];
}
public function getDescription()
{
return ( isset($this->_aData['description'])) ? $this->_aData['description'] : null;
}
public function getPath()
{
return $this->_aData['path'];
}
public function getWebPath($sWidth = null)
{
if (isset($this->_aData['path']) && $this->_aData['path']) {
if ($sWidth) {
$iDotPos = strrpos($this->_aData['path'], '.');
$sFileBase = substr($this->_aData['path'], 0, $iDotPos);
$sFileExt = substr($this->_aData['path'], $iDotPos);
$sFileName = $sFileBase.'_'.$sWidth.$sFileExt;
} else {
$sFileName = $this->_aData['path'];
}
return Config::Get('path.static.root').Config::Get('path.uploads.root').'/'.$sFileName;
} else {
return null;
}
}
public function setTopicId($iTopicId)
{
$this->_aData['topic_id'] = $iTopicId;
}
public function setTargetTmp($sTargetTmp)
{
$this->_aData['target_tmp'] = $sTargetTmp;
}
public function setDescription($sDescription)
{
$this->_aData['description'] = $sDescription;
}
}

View file

@ -671,6 +671,84 @@ class ModuleTopic_MapperTopic extends Mapper {
}
return false;
}
public function getPhotosByTopicId($iTopicId, $iFromId, $iCount)
{
$sql = 'SELECT * FROM ' . Config::Get('db.table.topic_photo') . ' WHERE topic_id = ?d {AND id > ?d LIMIT 0, ?d}';
$aPhotos = $this->oDb->select($sql, $iTopicId, ($iFromId !== null) ? $iFromId : DBSIMPLE_SKIP, $iCount);
$aReturn = array();
if (is_array($aPhotos) && count($aPhotos)) {
foreach($aPhotos as $aPhoto) {
$aReturn[] = Engine::GetEntity('Topic_TopicPhoto', $aPhoto);
}
}
return $aReturn;
}
public function getPhotosByTargetTmp($sTargetTmp)
{
$sql = 'SELECT * FROM ' . Config::Get('db.table.topic_photo') . ' WHERE target_tmp = ?';
$aPhotos = $this->oDb->select($sql, $sTargetTmp);
$aReturn = array();
if (is_array($aPhotos) && count($aPhotos)) {
foreach($aPhotos as $aPhoto) {
$aReturn[] = Engine::GetEntity('Topic_TopicPhoto', $aPhoto);
}
}
return $aReturn;
}
public function getTopicPhotoById($iPhotoId)
{
$sql = 'SELECT * FROM ' . Config::Get('db.table.topic_photo') . ' WHERE id = ?d';
$aPhoto = $this->oDb->selectRow($sql, $iPhotoId);
if ($aPhoto) {
return Engine::GetEntity('Topic_TopicPhoto', $aPhoto);
} else {
return null;
}
}
public function getCountPhotosByTopicId($iTopicId)
{
$sql = 'SELECT count(id) FROM ' . Config::Get('db.table.topic_photo') . ' WHERE topic_id = ?d';
$aPhotosCount = $this->oDb->selectCol($sql, $iTopicId);
return $aPhotosCount[0];
}
public function getCountPhotosByTargetTmp($sTargetTmp)
{
$sql = 'SELECT count(id) FROM ' . Config::Get('db.table.topic_photo') . ' WHERE target_tmp = ?';
$aPhotosCount = $this->oDb->selectCol($sql, $sTargetTmp);
return $aPhotosCount[0];
}
public function addTopicPhoto($oPhoto)
{
if (!$oPhoto->getTopicId() && !$oPhoto->getTargetTmp()) return false;
$sTargetType = ($oPhoto->getTopicId()) ? 'topic_id' : 'target_tmp';
$iTargetId = ($sTargetType == 'topic_id') ? $oPhoto->getTopicId() : $oPhoto->getTargetTmp();
$sql = 'INSERT INTO '. Config::Get('db.table.topic_photo') . ' SET
path = ?, description = ?, ?# = ?';
return $this->oDb->query($sql, $oPhoto->getPath(), $oPhoto->getDescription(), $sTargetType, $iTargetId);
}
public function updateTopicPhoto($oPhoto)
{
if (!$oPhoto->getTopicId() && !$oPhoto->getTargetTmp()) return false;
if ($oPhoto->getTopicId()) {
$oPhoto->setTargetTmp = null;
}
$sql = 'UPDATE '. Config::Get('db.table.topic_photo') . ' SET
path = ?, description = ?, topic_id = ?d, target_tmp=? WHERE id = ?d';
$this->oDb->query($sql, $oPhoto->getPath(), $oPhoto->getDescription(), $oPhoto->getTopicId(), $oPhoto->getTargetTmp(), $oPhoto->getId());
}
public function deleteTopicPhoto($iPhotoId)
{
$sql = 'DELETE FROM '. Config::Get('db.table.topic_photo') . ' WHERE
id= ?d';
$this->oDb->query($sql, $iPhotoId);
}
}
?>

View file

@ -275,6 +275,7 @@ $config['db']['table']['stream_event'] = '___db.table.prefix___stream_eve
$config['db']['table']['stream_config'] = '___db.table.prefix___stream_config';
$config['db']['table']['user_field'] = '___db.table.prefix___user_field';
$config['db']['table']['user_field_value'] = '___db.table.prefix___user_field_value';
$config['db']['table']['topic_photo'] = '___db.table.prefix___topic_photo';
$config['db']['tables']['engine'] = 'InnoDB'; // InnoDB или MyISAM
/**
@ -319,6 +320,7 @@ $config['router']['page']['admin'] = 'ActionAdmin';
$config['router']['page']['ajax'] = 'ActionAjax';
$config['router']['page']['feed'] = 'ActionUserfeed';
$config['router']['page']['stream'] = 'ActionStream';
$config['router']['page']['photoset'] = 'ActionPhotoset';
// Глобальные настройки роутинга
$config['router']['config']['action_default'] = 'index';
$config['router']['config']['action_not_found'] = 'error';
@ -433,6 +435,7 @@ $config['head']['default']['js'] = array(
"___path.root.engine_lib___/external/MooTools_1.2/plugs/vlaCal-v2.1/jslib/vlaCal-v2.1.js",
"___path.root.engine_lib___/external/MooTools_1.2/plugs/iFrameFormRequest/iFrameFormRequest.js",
"___path.root.engine_lib___/external/prettify/prettify.js",
"___path.static.skin___/js/ls.lang.ru.js",
"___path.static.skin___/js/vote.js",
"___path.static.skin___/js/favourites.js",
"___path.static.skin___/js/questions.js",
@ -474,7 +477,7 @@ $config['compress']['css']['template'] = "highest_compression";
/**
* Параметры компрессии js-файлов
*/
$config['compress']['js']['merge'] =true; // указывает на необходимость слияния файлов по указанным блокам.
$config['compress']['js']['merge'] = true; // указывает на необходимость слияния файлов по указанным блокам.
$config['compress']['js']['use'] = true; // указывает на необходимость компрессии файлов. Компрессия используется только в активированном режиме слияния файлов.
/**
@ -488,5 +491,37 @@ date_default_timezone_set('Europe/Moscow'); // See http://php.net/manual/en/time
*/
$config['jevix']=require(dirname(__FILE__).'/jevix.php');
/**
* Настройка топика-фотосета
*/
$config['module']['image']['topic']['jpg_quality'] = 100;
$config['module']['topic']['photoset']['photo_max_size'] = 1*1024; //kb
$config['module']['topic']['photoset']['count_photos_min'] = 2;
$config['module']['topic']['photoset']['count_photos_max'] = 30;
$config['module']['topic']['photoset']['per_page'] = 5;
$config['topic']['image']['width'] = 1000;
$config['topic']['image']['size'] = array(
array(
'w' => 1000,
'h' => null,
'crop' => false,
),
array(
'w' => 500,
'h' => null,
'crop' => false,
),
array(
'w' => 100,
'h' => null,
'crop' => false,
),
array(
'w' => 50,
'h' => 50,
'crop' => true,
)
);
return $config;
?>

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -0,0 +1,97 @@
/* MILKBOX */
#mbOverlay {
position: absolute;
left: 0;
width:100%;
background-color: #000; /* set the Milkbox overlay color // opacity: see the js options */
z-index:1000;
cursor: pointer;
}
#mbCenter {
/* for default width and height, see the js options */
position: absolute;
z-index:1001;
overflow:hidden;
left: 50%;
top:10%;/* overwritten in the js options to properly position the milkbox when activated in a scrolled window */
background-color: #fff;/* set the Milkbox background color */
border: 5px solid #fff;/* set the Milkbox border */
margin:0; padding:5px;/* set the Milkbox padding */
}
.mbLoading{ background: #fff url(loading.gif) no-repeat center; }/* IMAGE: loading gif */
#mbCanvas{ margin:0; padding:0; height:0; border:none; font-size:0; overflow:hidden; }
.mbClear{ clear:both; height:0; margin:0; padding:0; font-size:0; overflow:hidden; }
/* *** BOTTOM *** */
#mbBottom {
/* set text options */
font-family: Verdana, Arial, Geneva, Helvetica, sans-serif;
font-size: 10px;
color: #666;
line-height: 1.4em;
text-align: left;
padding-top:8px;
margin:0;
}
/* navigation */
/* be careful if you change buttons dimensions */
#mbNavigation{
float:right;
width:27px;
padding-top:3px;
border-left:1px solid #9c9c9c;/* set nav border */
}
#mbCount{
width:55px;
overflow:hidden;
padding-top:1px;
float:right;
text-align:right;
font-size:9px; /* count font size */
}
#mbCloseLink, #mbPrevLink, #mbNextLink, #mbPlayPause{
outline:none;
display:block;
float:right;
height:19px;
cursor: pointer;
}
#mbPrevLink, #mbNextLink{ width:15px; }
#mbPrevLink{ background: transparent url(prev.gif) no-repeat; }/* IMAGE: prev */
#mbNextLink{ background: transparent url(next.gif) no-repeat; }/* IMAGE: next */
#mbPlayPause{ width:13px; }
#mbPlayPause{ background: transparent url(play-pause.gif) no-repeat; }/* IMAGE: prev */
/* NOTE: doesn't work in ie6, so, just see the js options :) */
a#mbPrevLink:hover,a#mbNextLink:hover,a#mbCloseLink:hover,a#mbPlayPause:hover { background-position: 0 -22px; }
#mbCloseLink {
width:17px;
background: transparent url(close.gif) no-repeat;/* IMAGE: close */
}
/* description */
#mbDescription{
margin-right:27px;
padding:0px 10px 0 0;
font-weight: normal;
text-align:justify;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 187 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 B

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,262 @@
function fileQueueError(file, errorCode, message) {
try {
var imageName = "error.gif";
var errorName = "";
if (errorCode === SWFUpload.errorCode_QUEUE_LIMIT_EXCEEDED) {
errorName = "You have attempted to queue too many files.";
}
if (errorName !== "") {
alert(errorName);
return;
}
switch (errorCode) {
case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE:
imageName = "zerobyte.gif";
break;
case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT:
imageName = "toobig.gif";
break;
case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE:
case SWFUpload.QUEUE_ERROR.INVALID_FILETYPE:
default:
alert(message);
break;
}
addImage("images/" + imageName);
} catch (ex) {
this.debug(ex);
}
}
function fileDialogComplete(numFilesSelected, numFilesQueued) {
try {
photosetCloseForm();
if (numFilesQueued > 0) {
this.startUpload();
}
} catch (ex) {
this.debug(ex);
}
}
function uploadProgress(file, bytesLoaded) {
try {
var percent = Math.ceil((bytesLoaded / file.size) * 100);
var progress = new FileProgress(file, this.customSettings.upload_target);
progress.setProgress(percent);
if (percent === 100) {
progress.setStatus("Making thumbnail...");
progress.toggleCancel(false, this);
} else {
progress.setStatus("Uploading...");
progress.toggleCancel(true, this);
}
} catch (ex) {
this.debug(ex);
}
}
function uploadSuccess(file, serverData) {
try {
var progress = new FileProgress(file, this.customSettings.upload_target);
if (!window.jQuery) {
addTopicImage(JSON.decode(serverData, true));
} else {
addTopicImage(jQuery.parseJSON(serverData));
}
progress.setStatus("Image uploaded.");
progress.toggleCancel(false);
} catch (ex) {
this.debug(ex);
}
}
function uploadComplete(file) {
try {
/* I want the next upload to continue automatically so I'll call startUpload here */
if (this.getStats().files_queued > 0) {
this.startUpload();
} else {
var progress = new FileProgress(file, this.customSettings.upload_target);
progress.setComplete();
progress.setStatus("All images uploaded.");
progress.toggleCancel(false);
}
} catch (ex) {
this.debug(ex);
}
}
function uploadError(file, errorCode, message) {
var imageName = "error.gif";
var progress;
try {
switch (errorCode) {
case SWFUpload.UPLOAD_ERROR.FILE_CANCELLED:
try {
progress = new FileProgress(file, this.customSettings.upload_target);
progress.setCancelled();
progress.setStatus("Cancelled");
progress.toggleCancel(false);
}
catch (ex1) {
this.debug(ex1);
}
break;
case SWFUpload.UPLOAD_ERROR.UPLOAD_STOPPED:
try {
progress = new FileProgress(file, this.customSettings.upload_target);
progress.setCancelled();
progress.setStatus("Stopped");
progress.toggleCancel(true);
}
catch (ex2) {
this.debug(ex2);
}
case SWFUpload.UPLOAD_ERROR.UPLOAD_LIMIT_EXCEEDED:
imageName = "uploadlimit.gif";
break;
default:
alert(message);
break;
}
addImage("images/" + imageName);
} catch (ex3) {
this.debug(ex3);
}
}
function fadeIn(element, opacity) {
var reduceOpacityBy = 5;
var rate = 30; // 15 fps
if (opacity < 100) {
opacity += reduceOpacityBy;
if (opacity > 100) {
opacity = 100;
}
if (element.filters) {
try {
element.filters.item("DXImageTransform.Microsoft.Alpha").opacity = opacity;
} catch (e) {
// If it is not set initially, the browser will throw an error. This will set it if it is not set yet.
element.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(opacity=' + opacity + ')';
}
} else {
element.style.opacity = opacity / 100;
}
}
if (opacity < 100) {
setTimeout(function () {
fadeIn(element, opacity);
}, rate);
}
}
/* ******************************************
* FileProgress Object
* Control object for displaying file info
* ****************************************** */
function FileProgress(file, targetID) {
this.fileProgressID = "divFileProgress";
this.fileProgressWrapper = document.getElementById(this.fileProgressID);
if (!this.fileProgressWrapper) {
this.fileProgressWrapper = document.createElement("div");
this.fileProgressWrapper.className = "progressWrapper";
this.fileProgressWrapper.id = this.fileProgressID;
this.fileProgressElement = document.createElement("div");
this.fileProgressElement.className = "progressContainer";
var progressCancel = document.createElement("a");
progressCancel.className = "progressCancel";
progressCancel.href = "#";
progressCancel.style.visibility = "hidden";
progressCancel.appendChild(document.createTextNode(" "));
var progressText = document.createElement("div");
progressText.className = "progressName";
progressText.appendChild(document.createTextNode(file.name));
var progressBar = document.createElement("div");
progressBar.className = "progressBarInProgress";
var progressStatus = document.createElement("div");
progressStatus.className = "progressBarStatus";
progressStatus.innerHTML = "&nbsp;";
this.fileProgressElement.appendChild(progressCancel);
this.fileProgressElement.appendChild(progressText);
this.fileProgressElement.appendChild(progressStatus);
this.fileProgressElement.appendChild(progressBar);
this.fileProgressWrapper.appendChild(this.fileProgressElement);
document.getElementById(targetID).appendChild(this.fileProgressWrapper);
fadeIn(this.fileProgressWrapper, 0);
} else {
this.fileProgressElement = this.fileProgressWrapper.firstChild;
this.fileProgressElement.childNodes[1].firstChild.nodeValue = file.name;
}
this.height = this.fileProgressWrapper.offsetHeight;
}
FileProgress.prototype.setProgress = function (percentage) {
this.fileProgressElement.className = "progressContainer green";
this.fileProgressElement.childNodes[3].className = "progressBarInProgress";
this.fileProgressElement.childNodes[3].style.width = percentage + "%";
};
FileProgress.prototype.setComplete = function () {
this.fileProgressElement.className = "progressContainer blue";
this.fileProgressElement.childNodes[3].className = "progressBarComplete";
this.fileProgressElement.childNodes[3].style.width = "";
};
FileProgress.prototype.setError = function () {
this.fileProgressElement.className = "progressContainer red";
this.fileProgressElement.childNodes[3].className = "progressBarError";
this.fileProgressElement.childNodes[3].style.width = "";
};
FileProgress.prototype.setCancelled = function () {
this.fileProgressElement.className = "progressContainer";
this.fileProgressElement.childNodes[3].className = "progressBarError";
this.fileProgressElement.childNodes[3].style.width = "";
};
FileProgress.prototype.setStatus = function (status) {
this.fileProgressElement.childNodes[2].innerHTML = status;
};
FileProgress.prototype.toggleCancel = function (show, swfuploadInstance) {
this.fileProgressElement.childNodes[0].style.visibility = show ? "visible" : "hidden";
if (swfuploadInstance) {
var fileID = this.fileProgressID;
this.fileProgressElement.childNodes[0].onclick = function () {
swfuploadInstance.cancelUpload(fileID);
return false;
};
}
};

View file

@ -0,0 +1,980 @@
/**
* SWFUpload: http://www.swfupload.org, http://swfupload.googlecode.com
*
* mmSWFUpload 1.0: Flash upload dialog - http://profandesign.se/swfupload/, http://www.vinterwebb.se/
*
* SWFUpload is (c) 2006-2007 Lars Huring, Olov Nilzén and Mammon Media and is released under the MIT License:
* http://www.opensource.org/licenses/mit-license.php
*
* SWFUpload 2 is (c) 2007-2008 Jake Roberts and is released under the MIT License:
* http://www.opensource.org/licenses/mit-license.php
*
*/
/* ******************* */
/* Constructor & Init */
/* ******************* */
var SWFUpload;
if (SWFUpload == undefined) {
SWFUpload = function (settings) {
this.initSWFUpload(settings);
};
}
SWFUpload.prototype.initSWFUpload = function (settings) {
try {
this.customSettings = {}; // A container where developers can place their own settings associated with this instance.
this.settings = settings;
this.eventQueue = [];
this.movieName = "SWFUpload_" + SWFUpload.movieCount++;
this.movieElement = null;
// Setup global control tracking
SWFUpload.instances[this.movieName] = this;
// Load the settings. Load the Flash movie.
this.initSettings();
this.loadFlash();
this.displayDebugInfo();
} catch (ex) {
delete SWFUpload.instances[this.movieName];
throw ex;
}
};
/* *************** */
/* Static Members */
/* *************** */
SWFUpload.instances = {};
SWFUpload.movieCount = 0;
SWFUpload.version = "2.2.0 2009-03-25";
SWFUpload.QUEUE_ERROR = {
QUEUE_LIMIT_EXCEEDED : -100,
FILE_EXCEEDS_SIZE_LIMIT : -110,
ZERO_BYTE_FILE : -120,
INVALID_FILETYPE : -130
};
SWFUpload.UPLOAD_ERROR = {
HTTP_ERROR : -200,
MISSING_UPLOAD_URL : -210,
IO_ERROR : -220,
SECURITY_ERROR : -230,
UPLOAD_LIMIT_EXCEEDED : -240,
UPLOAD_FAILED : -250,
SPECIFIED_FILE_ID_NOT_FOUND : -260,
FILE_VALIDATION_FAILED : -270,
FILE_CANCELLED : -280,
UPLOAD_STOPPED : -290
};
SWFUpload.FILE_STATUS = {
QUEUED : -1,
IN_PROGRESS : -2,
ERROR : -3,
COMPLETE : -4,
CANCELLED : -5
};
SWFUpload.BUTTON_ACTION = {
SELECT_FILE : -100,
SELECT_FILES : -110,
START_UPLOAD : -120
};
SWFUpload.CURSOR = {
ARROW : -1,
HAND : -2
};
SWFUpload.WINDOW_MODE = {
WINDOW : "window",
TRANSPARENT : "transparent",
OPAQUE : "opaque"
};
// Private: takes a URL, determines if it is relative and converts to an absolute URL
// using the current site. Only processes the URL if it can, otherwise returns the URL untouched
SWFUpload.completeURL = function(url) {
if (typeof(url) !== "string" || url.match(/^https?:\/\//i) || url.match(/^\//)) {
return url;
}
var currentURL = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ":" + window.location.port : "");
var indexSlash = window.location.pathname.lastIndexOf("/");
if (indexSlash <= 0) {
path = "/";
} else {
path = window.location.pathname.substr(0, indexSlash) + "/";
}
return /*currentURL +*/ path + url;
};
/* ******************** */
/* Instance Members */
/* ******************** */
// Private: initSettings ensures that all the
// settings are set, getting a default value if one was not assigned.
SWFUpload.prototype.initSettings = function () {
this.ensureDefault = function (settingName, defaultValue) {
this.settings[settingName] = (this.settings[settingName] == undefined) ? defaultValue : this.settings[settingName];
};
// Upload backend settings
this.ensureDefault("upload_url", "");
this.ensureDefault("preserve_relative_urls", false);
this.ensureDefault("file_post_name", "Filedata");
this.ensureDefault("post_params", {});
this.ensureDefault("use_query_string", false);
this.ensureDefault("requeue_on_error", false);
this.ensureDefault("http_success", []);
this.ensureDefault("assume_success_timeout", 0);
// File Settings
this.ensureDefault("file_types", "*.*");
this.ensureDefault("file_types_description", "All Files");
this.ensureDefault("file_size_limit", 0); // Default zero means "unlimited"
this.ensureDefault("file_upload_limit", 0);
this.ensureDefault("file_queue_limit", 0);
// Flash Settings
this.ensureDefault("flash_url", "swfupload.swf");
this.ensureDefault("prevent_swf_caching", true);
// Button Settings
this.ensureDefault("button_image_url", "");
this.ensureDefault("button_width", 1);
this.ensureDefault("button_height", 1);
this.ensureDefault("button_text", "");
this.ensureDefault("button_text_style", "color: #000000; font-size: 16pt;");
this.ensureDefault("button_text_top_padding", 0);
this.ensureDefault("button_text_left_padding", 0);
this.ensureDefault("button_action", SWFUpload.BUTTON_ACTION.SELECT_FILES);
this.ensureDefault("button_disabled", false);
this.ensureDefault("button_placeholder_id", "");
this.ensureDefault("button_placeholder", null);
this.ensureDefault("button_cursor", SWFUpload.CURSOR.ARROW);
this.ensureDefault("button_window_mode", SWFUpload.WINDOW_MODE.WINDOW);
// Debug Settings
this.ensureDefault("debug", false);
this.settings.debug_enabled = this.settings.debug; // Here to maintain v2 API
// Event Handlers
this.settings.return_upload_start_handler = this.returnUploadStart;
this.ensureDefault("swfupload_loaded_handler", null);
this.ensureDefault("file_dialog_start_handler", null);
this.ensureDefault("file_queued_handler", null);
this.ensureDefault("file_queue_error_handler", null);
this.ensureDefault("file_dialog_complete_handler", null);
this.ensureDefault("upload_start_handler", null);
this.ensureDefault("upload_progress_handler", null);
this.ensureDefault("upload_error_handler", null);
this.ensureDefault("upload_success_handler", null);
this.ensureDefault("upload_complete_handler", null);
this.ensureDefault("debug_handler", this.debugMessage);
this.ensureDefault("custom_settings", {});
// Other settings
this.customSettings = this.settings.custom_settings;
// Update the flash url if needed
if (!!this.settings.prevent_swf_caching) {
this.settings.flash_url = this.settings.flash_url + (this.settings.flash_url.indexOf("?") < 0 ? "?" : "&") + "preventswfcaching=" + new Date().getTime();
}
if (!this.settings.preserve_relative_urls) {
//this.settings.flash_url = SWFUpload.completeURL(this.settings.flash_url); // Don't need to do this one since flash doesn't look at it
this.settings.upload_url = SWFUpload.completeURL(this.settings.upload_url);
this.settings.button_image_url = SWFUpload.completeURL(this.settings.button_image_url);
}
delete this.ensureDefault;
};
// Private: loadFlash replaces the button_placeholder element with the flash movie.
SWFUpload.prototype.loadFlash = function () {
var targetElement, tempParent;
// Make sure an element with the ID we are going to use doesn't already exist
if (document.getElementById(this.movieName) !== null) {
throw "ID " + this.movieName + " is already in use. The Flash Object could not be added";
}
// Get the element where we will be placing the flash movie
targetElement = document.getElementById(this.settings.button_placeholder_id) || this.settings.button_placeholder;
if (targetElement == undefined) {
throw "Could not find the placeholder element: " + this.settings.button_placeholder_id;
}
// Append the container and load the flash
tempParent = document.createElement("div");
tempParent.innerHTML = this.getFlashHTML(); // Using innerHTML is non-standard but the only sensible way to dynamically add Flash in IE (and maybe other browsers)
targetElement.parentNode.replaceChild(tempParent.firstChild, targetElement);
// Fix IE Flash/Form bug
if (window[this.movieName] == undefined) {
window[this.movieName] = this.getMovieElement();
}
};
// Private: getFlashHTML generates the object tag needed to embed the flash in to the document
SWFUpload.prototype.getFlashHTML = function () {
// Flash Satay object syntax: http://www.alistapart.com/articles/flashsatay
return ['<object id="', this.movieName, '" type="application/x-shockwave-flash" data="', this.settings.flash_url, '" width="', this.settings.button_width, '" height="', this.settings.button_height, '" class="swfupload">',
'<param name="wmode" value="', this.settings.button_window_mode, '" />',
'<param name="movie" value="', this.settings.flash_url, '" />',
'<param name="quality" value="high" />',
'<param name="menu" value="false" />',
'<param name="allowScriptAccess" value="always" />',
'<param name="flashvars" value="' + this.getFlashVars() + '" />',
'</object>'].join("");
};
// Private: getFlashVars builds the parameter string that will be passed
// to flash in the flashvars param.
SWFUpload.prototype.getFlashVars = function () {
// Build a string from the post param object
var paramString = this.buildParamString();
var httpSuccessString = this.settings.http_success.join(",");
// Build the parameter string
return ["movieName=", encodeURIComponent(this.movieName),
"&amp;uploadURL=", encodeURIComponent(this.settings.upload_url),
"&amp;useQueryString=", encodeURIComponent(this.settings.use_query_string),
"&amp;requeueOnError=", encodeURIComponent(this.settings.requeue_on_error),
"&amp;httpSuccess=", encodeURIComponent(httpSuccessString),
"&amp;assumeSuccessTimeout=", encodeURIComponent(this.settings.assume_success_timeout),
"&amp;params=", encodeURIComponent(paramString),
"&amp;filePostName=", encodeURIComponent(this.settings.file_post_name),
"&amp;fileTypes=", encodeURIComponent(this.settings.file_types),
"&amp;fileTypesDescription=", encodeURIComponent(this.settings.file_types_description),
"&amp;fileSizeLimit=", encodeURIComponent(this.settings.file_size_limit),
"&amp;fileUploadLimit=", encodeURIComponent(this.settings.file_upload_limit),
"&amp;fileQueueLimit=", encodeURIComponent(this.settings.file_queue_limit),
"&amp;debugEnabled=", encodeURIComponent(this.settings.debug_enabled),
"&amp;buttonImageURL=", encodeURIComponent(this.settings.button_image_url),
"&amp;buttonWidth=", encodeURIComponent(this.settings.button_width),
"&amp;buttonHeight=", encodeURIComponent(this.settings.button_height),
"&amp;buttonText=", encodeURIComponent(this.settings.button_text),
"&amp;buttonTextTopPadding=", encodeURIComponent(this.settings.button_text_top_padding),
"&amp;buttonTextLeftPadding=", encodeURIComponent(this.settings.button_text_left_padding),
"&amp;buttonTextStyle=", encodeURIComponent(this.settings.button_text_style),
"&amp;buttonAction=", encodeURIComponent(this.settings.button_action),
"&amp;buttonDisabled=", encodeURIComponent(this.settings.button_disabled),
"&amp;buttonCursor=", encodeURIComponent(this.settings.button_cursor)
].join("");
};
// Public: getMovieElement retrieves the DOM reference to the Flash element added by SWFUpload
// The element is cached after the first lookup
SWFUpload.prototype.getMovieElement = function () {
if (this.movieElement == undefined) {
this.movieElement = document.getElementById(this.movieName);
}
if (this.movieElement === null) {
throw "Could not find Flash element";
}
return this.movieElement;
};
// Private: buildParamString takes the name/value pairs in the post_params setting object
// and joins them up in to a string formatted "name=value&amp;name=value"
SWFUpload.prototype.buildParamString = function () {
var postParams = this.settings.post_params;
var paramStringPairs = [];
if (typeof(postParams) === "object") {
for (var name in postParams) {
if (postParams.hasOwnProperty(name)) {
paramStringPairs.push(encodeURIComponent(name.toString()) + "=" + encodeURIComponent(postParams[name].toString()));
}
}
}
return paramStringPairs.join("&amp;");
};
// Public: Used to remove a SWFUpload instance from the page. This method strives to remove
// all references to the SWF, and other objects so memory is properly freed.
// Returns true if everything was destroyed. Returns a false if a failure occurs leaving SWFUpload in an inconsistant state.
// Credits: Major improvements provided by steffen
SWFUpload.prototype.destroy = function () {
try {
// Make sure Flash is done before we try to remove it
this.cancelUpload(null, false);
// Remove the SWFUpload DOM nodes
var movieElement = null;
movieElement = this.getMovieElement();
if (movieElement && typeof(movieElement.CallFunction) === "unknown") { // We only want to do this in IE
// Loop through all the movie's properties and remove all function references (DOM/JS IE 6/7 memory leak workaround)
for (var i in movieElement) {
try {
if (typeof(movieElement[i]) === "function") {
movieElement[i] = null;
}
} catch (ex1) {}
}
// Remove the Movie Element from the page
try {
movieElement.parentNode.removeChild(movieElement);
} catch (ex) {}
}
// Remove IE form fix reference
window[this.movieName] = null;
// Destroy other references
SWFUpload.instances[this.movieName] = null;
delete SWFUpload.instances[this.movieName];
this.movieElement = null;
this.settings = null;
this.customSettings = null;
this.eventQueue = null;
this.movieName = null;
return true;
} catch (ex2) {
return false;
}
};
// Public: displayDebugInfo prints out settings and configuration
// information about this SWFUpload instance.
// This function (and any references to it) can be deleted when placing
// SWFUpload in production.
SWFUpload.prototype.displayDebugInfo = function () {
this.debug(
[
"---SWFUpload Instance Info---\n",
"Version: ", SWFUpload.version, "\n",
"Movie Name: ", this.movieName, "\n",
"Settings:\n",
"\t", "upload_url: ", this.settings.upload_url, "\n",
"\t", "flash_url: ", this.settings.flash_url, "\n",
"\t", "use_query_string: ", this.settings.use_query_string.toString(), "\n",
"\t", "requeue_on_error: ", this.settings.requeue_on_error.toString(), "\n",
"\t", "http_success: ", this.settings.http_success.join(", "), "\n",
"\t", "assume_success_timeout: ", this.settings.assume_success_timeout, "\n",
"\t", "file_post_name: ", this.settings.file_post_name, "\n",
"\t", "post_params: ", this.settings.post_params.toString(), "\n",
"\t", "file_types: ", this.settings.file_types, "\n",
"\t", "file_types_description: ", this.settings.file_types_description, "\n",
"\t", "file_size_limit: ", this.settings.file_size_limit, "\n",
"\t", "file_upload_limit: ", this.settings.file_upload_limit, "\n",
"\t", "file_queue_limit: ", this.settings.file_queue_limit, "\n",
"\t", "debug: ", this.settings.debug.toString(), "\n",
"\t", "prevent_swf_caching: ", this.settings.prevent_swf_caching.toString(), "\n",
"\t", "button_placeholder_id: ", this.settings.button_placeholder_id.toString(), "\n",
"\t", "button_placeholder: ", (this.settings.button_placeholder ? "Set" : "Not Set"), "\n",
"\t", "button_image_url: ", this.settings.button_image_url.toString(), "\n",
"\t", "button_width: ", this.settings.button_width.toString(), "\n",
"\t", "button_height: ", this.settings.button_height.toString(), "\n",
"\t", "button_text: ", this.settings.button_text.toString(), "\n",
"\t", "button_text_style: ", this.settings.button_text_style.toString(), "\n",
"\t", "button_text_top_padding: ", this.settings.button_text_top_padding.toString(), "\n",
"\t", "button_text_left_padding: ", this.settings.button_text_left_padding.toString(), "\n",
"\t", "button_action: ", this.settings.button_action.toString(), "\n",
"\t", "button_disabled: ", this.settings.button_disabled.toString(), "\n",
"\t", "custom_settings: ", this.settings.custom_settings.toString(), "\n",
"Event Handlers:\n",
"\t", "swfupload_loaded_handler assigned: ", (typeof this.settings.swfupload_loaded_handler === "function").toString(), "\n",
"\t", "file_dialog_start_handler assigned: ", (typeof this.settings.file_dialog_start_handler === "function").toString(), "\n",
"\t", "file_queued_handler assigned: ", (typeof this.settings.file_queued_handler === "function").toString(), "\n",
"\t", "file_queue_error_handler assigned: ", (typeof this.settings.file_queue_error_handler === "function").toString(), "\n",
"\t", "upload_start_handler assigned: ", (typeof this.settings.upload_start_handler === "function").toString(), "\n",
"\t", "upload_progress_handler assigned: ", (typeof this.settings.upload_progress_handler === "function").toString(), "\n",
"\t", "upload_error_handler assigned: ", (typeof this.settings.upload_error_handler === "function").toString(), "\n",
"\t", "upload_success_handler assigned: ", (typeof this.settings.upload_success_handler === "function").toString(), "\n",
"\t", "upload_complete_handler assigned: ", (typeof this.settings.upload_complete_handler === "function").toString(), "\n",
"\t", "debug_handler assigned: ", (typeof this.settings.debug_handler === "function").toString(), "\n"
].join("")
);
};
/* Note: addSetting and getSetting are no longer used by SWFUpload but are included
the maintain v2 API compatibility
*/
// Public: (Deprecated) addSetting adds a setting value. If the value given is undefined or null then the default_value is used.
SWFUpload.prototype.addSetting = function (name, value, default_value) {
if (value == undefined) {
return (this.settings[name] = default_value);
} else {
return (this.settings[name] = value);
}
};
// Public: (Deprecated) getSetting gets a setting. Returns an empty string if the setting was not found.
SWFUpload.prototype.getSetting = function (name) {
if (this.settings[name] != undefined) {
return this.settings[name];
}
return "";
};
// Private: callFlash handles function calls made to the Flash element.
// Calls are made with a setTimeout for some functions to work around
// bugs in the ExternalInterface library.
SWFUpload.prototype.callFlash = function (functionName, argumentArray) {
argumentArray = argumentArray || [];
var movieElement = this.getMovieElement();
var returnValue, returnString;
// Flash's method if calling ExternalInterface methods (code adapted from MooTools).
try {
returnString = movieElement.CallFunction('<invoke name="' + functionName + '" returntype="javascript">' + __flash__argumentsToXML(argumentArray, 0) + '</invoke>');
returnValue = eval(returnString);
} catch (ex) {
throw "Call to " + functionName + " failed";
}
// Unescape file post param values
if (returnValue != undefined && typeof returnValue.post === "object") {
returnValue = this.unescapeFilePostParams(returnValue);
}
return returnValue;
};
/* *****************************
-- Flash control methods --
Your UI should use these
to operate SWFUpload
***************************** */
// WARNING: this function does not work in Flash Player 10
// Public: selectFile causes a File Selection Dialog window to appear. This
// dialog only allows 1 file to be selected.
SWFUpload.prototype.selectFile = function () {
this.callFlash("SelectFile");
};
// WARNING: this function does not work in Flash Player 10
// Public: selectFiles causes a File Selection Dialog window to appear/ This
// dialog allows the user to select any number of files
// Flash Bug Warning: Flash limits the number of selectable files based on the combined length of the file names.
// If the selection name length is too long the dialog will fail in an unpredictable manner. There is no work-around
// for this bug.
SWFUpload.prototype.selectFiles = function () {
this.callFlash("SelectFiles");
};
// Public: startUpload starts uploading the first file in the queue unless
// the optional parameter 'fileID' specifies the ID
SWFUpload.prototype.startUpload = function (fileID) {
this.callFlash("StartUpload", [fileID]);
};
// Public: cancelUpload cancels any queued file. The fileID parameter may be the file ID or index.
// If you do not specify a fileID the current uploading file or first file in the queue is cancelled.
// If you do not want the uploadError event to trigger you can specify false for the triggerErrorEvent parameter.
SWFUpload.prototype.cancelUpload = function (fileID, triggerErrorEvent) {
if (triggerErrorEvent !== false) {
triggerErrorEvent = true;
}
this.callFlash("CancelUpload", [fileID, triggerErrorEvent]);
};
// Public: stopUpload stops the current upload and requeues the file at the beginning of the queue.
// If nothing is currently uploading then nothing happens.
SWFUpload.prototype.stopUpload = function () {
this.callFlash("StopUpload");
};
/* ************************
* Settings methods
* These methods change the SWFUpload settings.
* SWFUpload settings should not be changed directly on the settings object
* since many of the settings need to be passed to Flash in order to take
* effect.
* *********************** */
// Public: getStats gets the file statistics object.
SWFUpload.prototype.getStats = function () {
return this.callFlash("GetStats");
};
// Public: setStats changes the SWFUpload statistics. You shouldn't need to
// change the statistics but you can. Changing the statistics does not
// affect SWFUpload accept for the successful_uploads count which is used
// by the upload_limit setting to determine how many files the user may upload.
SWFUpload.prototype.setStats = function (statsObject) {
this.callFlash("SetStats", [statsObject]);
};
// Public: getFile retrieves a File object by ID or Index. If the file is
// not found then 'null' is returned.
SWFUpload.prototype.getFile = function (fileID) {
if (typeof(fileID) === "number") {
return this.callFlash("GetFileByIndex", [fileID]);
} else {
return this.callFlash("GetFile", [fileID]);
}
};
// Public: addFileParam sets a name/value pair that will be posted with the
// file specified by the Files ID. If the name already exists then the
// exiting value will be overwritten.
SWFUpload.prototype.addFileParam = function (fileID, name, value) {
return this.callFlash("AddFileParam", [fileID, name, value]);
};
// Public: removeFileParam removes a previously set (by addFileParam) name/value
// pair from the specified file.
SWFUpload.prototype.removeFileParam = function (fileID, name) {
this.callFlash("RemoveFileParam", [fileID, name]);
};
// Public: setUploadUrl changes the upload_url setting.
SWFUpload.prototype.setUploadURL = function (url) {
this.settings.upload_url = url.toString();
this.callFlash("SetUploadURL", [url]);
};
// Public: setPostParams changes the post_params setting
SWFUpload.prototype.setPostParams = function (paramsObject) {
this.settings.post_params = paramsObject;
this.callFlash("SetPostParams", [paramsObject]);
};
// Public: addPostParam adds post name/value pair. Each name can have only one value.
SWFUpload.prototype.addPostParam = function (name, value) {
this.settings.post_params[name] = value;
this.callFlash("SetPostParams", [this.settings.post_params]);
};
// Public: removePostParam deletes post name/value pair.
SWFUpload.prototype.removePostParam = function (name) {
delete this.settings.post_params[name];
this.callFlash("SetPostParams", [this.settings.post_params]);
};
// Public: setFileTypes changes the file_types setting and the file_types_description setting
SWFUpload.prototype.setFileTypes = function (types, description) {
this.settings.file_types = types;
this.settings.file_types_description = description;
this.callFlash("SetFileTypes", [types, description]);
};
// Public: setFileSizeLimit changes the file_size_limit setting
SWFUpload.prototype.setFileSizeLimit = function (fileSizeLimit) {
this.settings.file_size_limit = fileSizeLimit;
this.callFlash("SetFileSizeLimit", [fileSizeLimit]);
};
// Public: setFileUploadLimit changes the file_upload_limit setting
SWFUpload.prototype.setFileUploadLimit = function (fileUploadLimit) {
this.settings.file_upload_limit = fileUploadLimit;
this.callFlash("SetFileUploadLimit", [fileUploadLimit]);
};
// Public: setFileQueueLimit changes the file_queue_limit setting
SWFUpload.prototype.setFileQueueLimit = function (fileQueueLimit) {
this.settings.file_queue_limit = fileQueueLimit;
this.callFlash("SetFileQueueLimit", [fileQueueLimit]);
};
// Public: setFilePostName changes the file_post_name setting
SWFUpload.prototype.setFilePostName = function (filePostName) {
this.settings.file_post_name = filePostName;
this.callFlash("SetFilePostName", [filePostName]);
};
// Public: setUseQueryString changes the use_query_string setting
SWFUpload.prototype.setUseQueryString = function (useQueryString) {
this.settings.use_query_string = useQueryString;
this.callFlash("SetUseQueryString", [useQueryString]);
};
// Public: setRequeueOnError changes the requeue_on_error setting
SWFUpload.prototype.setRequeueOnError = function (requeueOnError) {
this.settings.requeue_on_error = requeueOnError;
this.callFlash("SetRequeueOnError", [requeueOnError]);
};
// Public: setHTTPSuccess changes the http_success setting
SWFUpload.prototype.setHTTPSuccess = function (http_status_codes) {
if (typeof http_status_codes === "string") {
http_status_codes = http_status_codes.replace(" ", "").split(",");
}
this.settings.http_success = http_status_codes;
this.callFlash("SetHTTPSuccess", [http_status_codes]);
};
// Public: setHTTPSuccess changes the http_success setting
SWFUpload.prototype.setAssumeSuccessTimeout = function (timeout_seconds) {
this.settings.assume_success_timeout = timeout_seconds;
this.callFlash("SetAssumeSuccessTimeout", [timeout_seconds]);
};
// Public: setDebugEnabled changes the debug_enabled setting
SWFUpload.prototype.setDebugEnabled = function (debugEnabled) {
this.settings.debug_enabled = debugEnabled;
this.callFlash("SetDebugEnabled", [debugEnabled]);
};
// Public: setButtonImageURL loads a button image sprite
SWFUpload.prototype.setButtonImageURL = function (buttonImageURL) {
if (buttonImageURL == undefined) {
buttonImageURL = "";
}
this.settings.button_image_url = buttonImageURL;
this.callFlash("SetButtonImageURL", [buttonImageURL]);
};
// Public: setButtonDimensions resizes the Flash Movie and button
SWFUpload.prototype.setButtonDimensions = function (width, height) {
this.settings.button_width = width;
this.settings.button_height = height;
var movie = this.getMovieElement();
if (movie != undefined) {
movie.style.width = width + "px";
movie.style.height = height + "px";
}
this.callFlash("SetButtonDimensions", [width, height]);
};
// Public: setButtonText Changes the text overlaid on the button
SWFUpload.prototype.setButtonText = function (html) {
this.settings.button_text = html;
this.callFlash("SetButtonText", [html]);
};
// Public: setButtonTextPadding changes the top and left padding of the text overlay
SWFUpload.prototype.setButtonTextPadding = function (left, top) {
this.settings.button_text_top_padding = top;
this.settings.button_text_left_padding = left;
this.callFlash("SetButtonTextPadding", [left, top]);
};
// Public: setButtonTextStyle changes the CSS used to style the HTML/Text overlaid on the button
SWFUpload.prototype.setButtonTextStyle = function (css) {
this.settings.button_text_style = css;
this.callFlash("SetButtonTextStyle", [css]);
};
// Public: setButtonDisabled disables/enables the button
SWFUpload.prototype.setButtonDisabled = function (isDisabled) {
this.settings.button_disabled = isDisabled;
this.callFlash("SetButtonDisabled", [isDisabled]);
};
// Public: setButtonAction sets the action that occurs when the button is clicked
SWFUpload.prototype.setButtonAction = function (buttonAction) {
this.settings.button_action = buttonAction;
this.callFlash("SetButtonAction", [buttonAction]);
};
// Public: setButtonCursor changes the mouse cursor displayed when hovering over the button
SWFUpload.prototype.setButtonCursor = function (cursor) {
this.settings.button_cursor = cursor;
this.callFlash("SetButtonCursor", [cursor]);
};
/* *******************************
Flash Event Interfaces
These functions are used by Flash to trigger the various
events.
All these functions a Private.
Because the ExternalInterface library is buggy the event calls
are added to a queue and the queue then executed by a setTimeout.
This ensures that events are executed in a determinate order and that
the ExternalInterface bugs are avoided.
******************************* */
SWFUpload.prototype.queueEvent = function (handlerName, argumentArray) {
// Warning: Don't call this.debug inside here or you'll create an infinite loop
if (argumentArray == undefined) {
argumentArray = [];
} else if (!(argumentArray instanceof Array)) {
argumentArray = [argumentArray];
}
var self = this;
if (typeof this.settings[handlerName] === "function") {
// Queue the event
this.eventQueue.push(function () {
this.settings[handlerName].apply(this, argumentArray);
});
// Execute the next queued event
setTimeout(function () {
self.executeNextEvent();
}, 0);
} else if (this.settings[handlerName] !== null) {
throw "Event handler " + handlerName + " is unknown or is not a function";
}
};
// Private: Causes the next event in the queue to be executed. Since events are queued using a setTimeout
// we must queue them in order to garentee that they are executed in order.
SWFUpload.prototype.executeNextEvent = function () {
// Warning: Don't call this.debug inside here or you'll create an infinite loop
var f = this.eventQueue ? this.eventQueue.shift() : null;
if (typeof(f) === "function") {
f.apply(this);
}
};
// Private: unescapeFileParams is part of a workaround for a flash bug where objects passed through ExternalInterface cannot have
// properties that contain characters that are not valid for JavaScript identifiers. To work around this
// the Flash Component escapes the parameter names and we must unescape again before passing them along.
SWFUpload.prototype.unescapeFilePostParams = function (file) {
var reg = /[$]([0-9a-f]{4})/i;
var unescapedPost = {};
var uk;
if (file != undefined) {
for (var k in file.post) {
if (file.post.hasOwnProperty(k)) {
uk = k;
var match;
while ((match = reg.exec(uk)) !== null) {
uk = uk.replace(match[0], String.fromCharCode(parseInt("0x" + match[1], 16)));
}
unescapedPost[uk] = file.post[k];
}
}
file.post = unescapedPost;
}
return file;
};
// Private: Called by Flash to see if JS can call in to Flash (test if External Interface is working)
SWFUpload.prototype.testExternalInterface = function () {
try {
return this.callFlash("TestExternalInterface");
} catch (ex) {
return false;
}
};
// Private: This event is called by Flash when it has finished loading. Don't modify this.
// Use the swfupload_loaded_handler event setting to execute custom code when SWFUpload has loaded.
SWFUpload.prototype.flashReady = function () {
// Check that the movie element is loaded correctly with its ExternalInterface methods defined
var movieElement = this.getMovieElement();
if (!movieElement) {
this.debug("Flash called back ready but the flash movie can't be found.");
return;
}
this.cleanUp(movieElement);
this.queueEvent("swfupload_loaded_handler");
};
// Private: removes Flash added fuctions to the DOM node to prevent memory leaks in IE.
// This function is called by Flash each time the ExternalInterface functions are created.
SWFUpload.prototype.cleanUp = function (movieElement) {
// Pro-actively unhook all the Flash functions
try {
if (this.movieElement && typeof(movieElement.CallFunction) === "unknown") { // We only want to do this in IE
this.debug("Removing Flash functions hooks (this should only run in IE and should prevent memory leaks)");
for (var key in movieElement) {
try {
if (typeof(movieElement[key]) === "function") {
movieElement[key] = null;
}
} catch (ex) {
}
}
}
} catch (ex1) {
}
// Fix Flashes own cleanup code so if the SWFMovie was removed from the page
// it doesn't display errors.
window["__flash__removeCallback"] = function (instance, name) {
try {
if (instance) {
instance[name] = null;
}
} catch (flashEx) {
}
};
};
/* This is a chance to do something before the browse window opens */
SWFUpload.prototype.fileDialogStart = function () {
this.queueEvent("file_dialog_start_handler");
};
/* Called when a file is successfully added to the queue. */
SWFUpload.prototype.fileQueued = function (file) {
file = this.unescapeFilePostParams(file);
this.queueEvent("file_queued_handler", file);
};
/* Handle errors that occur when an attempt to queue a file fails. */
SWFUpload.prototype.fileQueueError = function (file, errorCode, message) {
file = this.unescapeFilePostParams(file);
this.queueEvent("file_queue_error_handler", [file, errorCode, message]);
};
/* Called after the file dialog has closed and the selected files have been queued.
You could call startUpload here if you want the queued files to begin uploading immediately. */
SWFUpload.prototype.fileDialogComplete = function (numFilesSelected, numFilesQueued, numFilesInQueue) {
this.queueEvent("file_dialog_complete_handler", [numFilesSelected, numFilesQueued, numFilesInQueue]);
};
SWFUpload.prototype.uploadStart = function (file) {
file = this.unescapeFilePostParams(file);
this.queueEvent("return_upload_start_handler", file);
};
SWFUpload.prototype.returnUploadStart = function (file) {
var returnValue;
if (typeof this.settings.upload_start_handler === "function") {
file = this.unescapeFilePostParams(file);
returnValue = this.settings.upload_start_handler.call(this, file);
} else if (this.settings.upload_start_handler != undefined) {
throw "upload_start_handler must be a function";
}
// Convert undefined to true so if nothing is returned from the upload_start_handler it is
// interpretted as 'true'.
if (returnValue === undefined) {
returnValue = true;
}
returnValue = !!returnValue;
this.callFlash("ReturnUploadStart", [returnValue]);
};
SWFUpload.prototype.uploadProgress = function (file, bytesComplete, bytesTotal) {
file = this.unescapeFilePostParams(file);
this.queueEvent("upload_progress_handler", [file, bytesComplete, bytesTotal]);
};
SWFUpload.prototype.uploadError = function (file, errorCode, message) {
file = this.unescapeFilePostParams(file);
this.queueEvent("upload_error_handler", [file, errorCode, message]);
};
SWFUpload.prototype.uploadSuccess = function (file, serverData, responseReceived) {
file = this.unescapeFilePostParams(file);
this.queueEvent("upload_success_handler", [file, serverData, responseReceived]);
};
SWFUpload.prototype.uploadComplete = function (file) {
file = this.unescapeFilePostParams(file);
this.queueEvent("upload_complete_handler", file);
};
/* Called by SWFUpload JavaScript and Flash functions when debug is enabled. By default it writes messages to the
internal debug console. You can override this event and have messages written where you want. */
SWFUpload.prototype.debug = function (message) {
this.queueEvent("debug_handler", message);
};
/* **********************************
Debug Console
The debug console is a self contained, in page location
for debug message to be sent. The Debug Console adds
itself to the body if necessary.
The console is automatically scrolled as messages appear.
If you are using your own debug handler or when you deploy to production and
have debug disabled you can remove these functions to reduce the file size
and complexity.
********************************** */
// Private: debugMessage is the default debug_handler. If you want to print debug messages
// call the debug() function. When overriding the function your own function should
// check to see if the debug setting is true before outputting debug information.
SWFUpload.prototype.debugMessage = function (message) {
if (this.settings.debug) {
var exceptionMessage, exceptionValues = [];
// Check for an exception object and print it nicely
if (typeof message === "object" && typeof message.name === "string" && typeof message.message === "string") {
for (var key in message) {
if (message.hasOwnProperty(key)) {
exceptionValues.push(key + ": " + message[key]);
}
}
exceptionMessage = exceptionValues.join("\n") || "";
exceptionValues = exceptionMessage.split("\n");
exceptionMessage = "EXCEPTION: " + exceptionValues.join("\nEXCEPTION: ");
SWFUpload.Console.writeLine(exceptionMessage);
} else {
SWFUpload.Console.writeLine(message);
}
}
};
SWFUpload.Console = {};
SWFUpload.Console.writeLine = function (message) {
var console, documentForm;
try {
console = document.getElementById("SWFUpload_Console");
if (!console) {
documentForm = document.createElement("form");
document.getElementsByTagName("body")[0].appendChild(documentForm);
console = document.createElement("textarea");
console.id = "SWFUpload_Console";
console.style.fontFamily = "monospace";
console.setAttribute("wrap", "off");
console.wrap = "off";
console.style.overflow = "auto";
console.style.width = "700px";
console.style.height = "350px";
console.style.margin = "5px";
documentForm.appendChild(console);
}
console.value += message + "\n";
console.scrollTop = console.scrollHeight - console.clientHeight;
} catch (ex) {
alert("Exception: " + ex.name + " Message: " + ex.message);
}
};

Binary file not shown.

File diff suppressed because one or more lines are too long

View file

@ -299,7 +299,30 @@ return array(
'topic_vote_ok' => 'Ваш голос учтен',
'topic_vote_ok_abstain' => 'Вы воздержались для просмотра рейтинга топика',
'topic_vote_count' => 'всего проголосовало',
/**
* Фотосет
*/
'topic_photoset_create' => 'Создание фотосета',
'topic_photoset_edit' => 'Редактирование фотосета',
'topic_photoset_upload_title' => 'Загрузка изображений',
'topic_photoset_upload_rules' => 'Доступна загрузка изображений в формат JPG, PNG, GIF<br />Размер изображений не должен превышать %%SIZE%% Kб<br />Максимальное число загружаемых изображений: %%COUNT%%',
'topic_photoset_choose_image' => 'Выберите изображение для загрузки',
'topic_photoset_is_preview' => 'Отмечено как превью к топику',
'topic_photoset_mark_as_preview' => 'Отметить как превью',
'topic_photoset_show_all' => 'Показать все %%COUNT%% фото',
'topic_photoset_count_images' => ' изображений',
'topic_photoset_show_more' => 'Показать ещё фото',
'topic_photoset_error_count_photos' => 'В топике может быть от %%MIN%% до %%MAX%% фото',
'topic_photoset_title' => 'Фотосет',
'topic_photoset_photo_deleted' => 'Фото удалено',
'topic_photoset_photo_added' => 'Фото добавлено',
'topic_photoset_error_too_much_photos' => 'Топик может содержать не более %%MAX%% фото',
'topic_photoset_title_edit' => 'Редактирование фотосета',
'topic_photoset_title_create' => 'Создание фотосета',
'topic_photoset_error_bad_filesize' => 'Размер фото должен быть не более %%MAX%% Кб',
'topic_photoset_photos' => 'фото',
/**
* Комментарии
*/
@ -748,6 +771,7 @@ return array(
'userfeed_no_subscribed_users' => 'Вы ещё не подписались на пользователей, чьи топики хотите видеть',
'userfeed_no_blogs' => 'Вы не вступили ни в один блог',
'userfeed_error_subscribe_to_yourself' => 'Вы не можете подписаться на себя',
/**
* Stream
@ -775,7 +799,7 @@ return array(
'stream_list_event_add_topic' => 'добавил новый топик',
'stream_list_event_add_blog' => 'добавил новый блог',
'stream_list_event_add_comment' => 'прокомментировал топик',
'stream_list_event_vote_topic' => 'оцнил топик',
'stream_list_event_vote_topic' => 'оценил топик',
'stream_list_event_vote_blog' => 'оценил блог',
'stream_list_event_vote_user' => 'оценил пользователя',
'stream_list_event_vote_comment' => 'оценил комментарий к топику',

View file

@ -0,0 +1,244 @@
{include file='header.tpl' menu='topic_action' showWhiteBack=true}
{if $oConfig->GetValue('view.tinymce')}
<script type="text/javascript" src="{cfg name='path.root.engine_lib'}/external/tinymce/tiny_mce.js"></script>
<script type="text/javascript">
{literal}
tinyMCE.init({
mode : "specific_textareas",
editor_selector : "mceEditor",
theme : "advanced",
theme_advanced_toolbar_location : "top",
theme_advanced_toolbar_align : "left",
theme_advanced_buttons1 : "lshselect,bold,italic,underline,strikethrough,|,bullist,numlist,|,undo,redo,|,lslink,unlink,lsvideo,lsimage,pagebreak,code",
theme_advanced_buttons2 : "",
theme_advanced_buttons3 : "",
theme_advanced_statusbar_location : "bottom",
theme_advanced_resizing : true,
theme_advanced_resize_horizontal : 0,
theme_advanced_resizing_use_cookie : 0,
theme_advanced_path : false,
object_resizing : true,
force_br_newlines : true,
forced_root_block : '', // Needed for 3.x
force_p_newlines : false,
plugins : "lseditor,safari,inlinepopups,media,pagebreak",
inline_styles:false,
formats : {
underline : {inline : 'u', exact : true},
strikethrough : {inline : 's', exact : true}
},
convert_urls : false,
extended_valid_elements : "embed[src|type|allowscriptaccess|allowfullscreen|width|height]",
pagebreak_separator :"<cut>",
media_strict : false,
language : TINYMCE_LANG
});
{/literal}
</script>
{else}
{include file='window_load_img.tpl' sToLoad='topic_text'}
{/if}
<script type="text/javascript" src="{cfg name='path.root.engine_lib'}/external/swfupload/swfupload.swfobject.js"></script>
<script type="text/javascript" src="{cfg name='path.root.engine_lib'}/external/swfupload/swfupload.js"></script>
<script type="text/javascript" src="{cfg name='path.root.engine_lib'}/external/swfupload/swfupload.handlers.js"></script>
<script type="text/javascript">
{literal}
if (jQuery.browser.flash) {
{/literal}
var path_root_engine_lib = '{cfg name='path.root.engine_lib'}';
var topic_id = '{$_aRequest.topic_id}';
var SSID='{$_sPhpSessionId}'
{literal}
var target_tmp = ($.cookie('ls_photoset_target_tmp')) ? $.cookie('ls_photoset_target_tmp') : 0;
$(document).ready(function() {
swfu = new SWFUpload({
// Backend Settings
upload_url: aRouter['photoset']+"upload",
post_params: {'ls_photoset_target_tmp':target_tmp,'topic_id':topic_id, 'SSID':SSID, 'security_ls_key': LIVESTREET_SECURITY_KEY},
// File Upload Settings
file_types : "*.jpg; *.JPG;*.png;*.gif",
file_types_description : "Images",
file_upload_limit : "0",
// Event Handler Settings - these functions as defined in Handlers.js
// The handlers are not part of SWFUpload but are part of my website and control how
// my website reacts to the SWFUpload events.
file_queue_error_handler : fileQueueError,
file_dialog_complete_handler : fileDialogComplete,
upload_progress_handler : uploadProgress,
upload_error_handler : uploadError,
upload_success_handler : uploadSuccess,
upload_complete_handler : uploadComplete,
// Button Settings
button_placeholder_id : "topic-photo-upload-input",
button_width: 122,
button_height: 30,
button_text : '<span class="button">Загрузить фото</span>',
button_text_style : '.button { font-family: Helvetica, Arial, sans-serif; font-size: 14pt; } .buttonSmall { font-size: 10pt; }',
button_window_mode: SWFUpload.WINDOW_MODE.TRANSPARENT,
button_text_left_padding: 6,
button_text_top_padding: 3,
button_cursor: SWFUpload.CURSOR.HAND,
// Flash Settings
flash_url : path_root_engine_lib+'/external/swfupload/swfupload.swf',
custom_settings : {
upload_target : "notice_wrap"
},
// Debug Settings
debug: true
});
});
}
{/literal}
</script>
<div class="topic" style="display: none;">
<div class="content" id="text_preview"></div>
</div>
<div class="profile-user">
{if $sEvent=='add'}
<h1>{$aLang.topic_photoset_create}</h1>
{else}
<h1>{$aLang.topic_photoset_edit}</h1>
{/if}
<form id="photoset-upload-form" method="POST" enctype="multipart/form-data">
<p id="topic-photo-upload-input" class="topic-photo-upload-input">
<label for="">{$aLang.topic_photoset_choose_image}:</label><br />
<input type="file" id="photoset-upload-file" name="Filedata" />
<a href="javascript:photosetUploadPhoto()" >upload</a>
<input type="hidden" name="is_iframe" value="true" />
<input type="hidden" name="topic_id" value="{$_aRequest.topic_id}" />
</p>
</form>
<form action="" method="POST" enctype="multipart/form-data">
{hook run='form_add_topic_topic_begin'}
<input type="hidden" name="security_ls_key" value="{$LIVESTREET_SECURITY_KEY}" />
<p><label for="blog_id">{$aLang.topic_create_blog}</label>
<select name="blog_id" id="blog_id" onChange="ajaxBlogInfo(this.value);">
<option value="0">{$aLang.topic_create_blog_personal}</option>
{foreach from=$aBlogsAllow item=oBlog}
<option value="{$oBlog->getId()}" {if $_aRequest.blog_id==$oBlog->getId()}selected{/if}>{$oBlog->getTitle()}</option>
{/foreach}
</select></p>
<script language="JavaScript" type="text/javascript">
jQuery(document).ready(function($){
ls.blog.loadInfo($('#blog_id').val());
});
</script>
<p><label for="topic_title">{$aLang.topic_create_title}:</label><br />
<input type="text" id="topic_title" name="topic_title" value="{$_aRequest.topic_title}" class="w100p" /><br />
<span class="form_note">{$aLang.topic_create_title_notice}</span>
</p>
<p>{if !$oConfig->GetValue('view.tinymce')}<div class="note">{$aLang.topic_create_text_notice}</div>{/if}<label for="topic_text">{$aLang.topic_create_text}:</label>
{if !$oConfig->GetValue('view.tinymce')}
<div class="panel_form">
{hook run='form_add_topic_panel_begin'}
<select onchange="lsPanel.putTagAround('topic_text',this.value); this.selectedIndex=0; return false;">
<option value="">{$aLang.panel_title}</option>
<option value="h4">{$aLang.panel_title_h4}</option>
<option value="h5">{$aLang.panel_title_h5}</option>
<option value="h6">{$aLang.panel_title_h6}</option>
</select>
<select onchange="lsPanel.putList('topic_text',this); return false;">
<option value="">{$aLang.panel_list}</option>
<option value="ul">{$aLang.panel_list_ul}</option>
<option value="ol">{$aLang.panel_list_ol}</option>
</select>
<a href="#" onclick="lsPanel.putTagAround('topic_text','b'); return false;" class="button"><img src="{cfg name='path.static.skin'}/images/panel/bold.png" title="{$aLang.panel_b}"></a>
<a href="#" onclick="lsPanel.putTagAround('topic_text','i'); return false;" class="button"><img src="{cfg name='path.static.skin'}/images/panel/italic.png" title="{$aLang.panel_i}"></a>
<a href="#" onclick="lsPanel.putTagAround('topic_text','u'); return false;" class="button"><img src="{cfg name='path.static.skin'}/images/panel/underline.png" title="{$aLang.panel_u}"></a>
<a href="#" onclick="lsPanel.putTagAround('topic_text','s'); return false;" class="button"><img src="{cfg name='path.static.skin'}/images/panel/strikethrough.png" title="{$aLang.panel_s}"></a>
&nbsp;
<a href="#" onclick="lsPanel.putTagUrl('topic_text','{$aLang.panel_url_promt}'); return false;" class="button"><img src="{cfg name='path.static.skin'}/images/panel/link.png" title="{$aLang.panel_url}"></a>
<a href="#" onclick="lsPanel.putQuote('topic_text'); return false;" class="button"><img src="{cfg name='path.static.skin'}/images/panel/quote.png" title="{$aLang.panel_quote}"></a>
<a href="#" onclick="lsPanel.putTagAround('topic_text','code'); return false;" class="button"><img src="{cfg name='path.static.skin'}/images/panel/code.png" title="{$aLang.panel_code}"></a>
<a href="#" onclick="lsPanel.putTagAround('topic_text','video'); return false;" class="button"><img src="{cfg name='path.static.skin'}/images/panel/video.png" title="{$aLang.panel_video}"></a>
<a href="#" onclick="showImgUploadForm(); return false;" class="button"><img src="{cfg name='path.static.skin'}/images/panel/img.png" title="{$aLang.panel_image}"></a>
<a href="#" onclick="lsPanel.putText('topic_text','<cut>'); return false;" class="button"><img src="{cfg name='path.static.skin'}/images/panel/cut.png" title="{$aLang.panel_cut}"></a>
{hook run='form_add_topic_panel_end'}
</div>
{/if}
<textarea name="topic_text" class="mceEditor" id="topic_text" rows="20">{$_aRequest.topic_text}</textarea></p>
<!-- Topic Photo Add -->
<div class="topic-photo-upload">
<h2>{$aLang.topic_photoset_upload_title}</h2>
<div class="topic-photo-upload-rules">
{$aLang.topic_photoset_upload_rules|ls_lang:"SIZE%%`$oConfig->get('module.topic.photoset.photo_max_size')`":"COUNT%%`$oConfig->get('module.topic.photoset.count_photos_max')`"}
</div>
<a href="javascript:photosetShowUploadForm()">Загрузить фото</a>
<input type="hidden" name="topic_main_photo" id="topic_main_photo" />
<ul id="swfu_images">
{if count($aPhotos)}
{foreach from=$aPhotos item=oPhoto}
{if $_aRequest.topic_main_photo && $_aRequest.topic_main_photo == $oPhoto->getId()}
{assign var=bIsMainPhoto value=true}
{/if}
<li id="photo_{$oPhoto->getId()}" {if $bIsMainPhoto}class="marked-as-preview"{/if}>
<img src="{$oPhoto->getWebPath(100)}" alt="image" />
<textarea onBlur="topicImageSetDescription({$oPhoto->getId()}, this.value)">{$oPhoto->getDescription()}</textarea><br />
<a href="javascript:deleteTopicImage({$oPhoto->getId()})" class="image-delete">Удалить</a>
<span class="photo-preview-state">
{if $bIsMainPhoto}
{$aLang.topic_photoset_is_preview}
{else}
<a href="javascript:setTopicMainPhoto({$oPhoto->getId()})" class="mark-as-preview">{$aLang.topic_photoset_mark_as_preview}</a>
{/if}
</span>
</li>
{assign var=bIsMainPhoto value=false}
{/foreach}
{/if}
</ul>
<div id="notice_wrap"></div>
</div>
<textarea name="topic_main_photo_description" id="topic_main_photo_description" rows="20">{$_aRequest.topic_main_photo_description}</textarea></p>
<!-- /Topic Photo Add -->
<p><label for="topic_tags">{$aLang.topic_create_tags}:</label><br />
<input type="text" id="topic_tags" name="topic_tags" value="{$_aRequest.topic_tags}" class="w100p" /><br />
<span class="form_note">{$aLang.topic_create_tags_notice}</span></p>
<p><label for="topic_forbid_comment"><input type="checkbox" id="topic_forbid_comment" name="topic_forbid_comment" class="checkbox" value="1" {if $_aRequest.topic_forbid_comment==1}checked{/if}/>
&mdash; {$aLang.topic_create_forbid_comment}</label><br />
<span class="form_note">{$aLang.topic_create_forbid_comment_notice}</span></p>
{if $oUserCurrent->isAdministrator()}
<p><label for="topic_publish_index"><input type="checkbox" id="topic_publish_index" name="topic_publish_index" class="checkbox" value="1" {if $_aRequest.topic_publish_index==1}checked{/if}/>
&mdash; {$aLang.topic_create_publish_index}</label><br />
<span class="form_note">{$aLang.topic_create_publish_index_notice}</span></p>
{/if}
{hook run='form_add_topic_topic_end'}
<p class="buttons">
<input type="submit" name="submit_topic_publish" value="{$aLang.topic_create_submit_publish}" class="right" />
<input type="submit" name="submit_preview" value="{$aLang.topic_create_submit_preview}" onclick="$('text_preview').getParent('div').setStyle('display','block'); ajaxTextPreview('topic_text',false); return false;" />&nbsp;
<input type="submit" name="submit_topic_save" value="{$aLang.topic_create_submit_save}" />
</p>
</form>
</div>
{include file='footer.tpl'}

View file

@ -52,4 +52,150 @@
.topic .poll .poll-result li dl dd div { height: 5px; margin-top: 5px; background: #ccc; overflow: hidden; }
.topic .poll .poll-result li.most dl dd div { background: #555; }
.topic .poll .poll-total { color: #aaa; }
.topic .poll .poll-total { color: #aaa; }
/* Topic Photo */
.topic.photo { }
.topic.photo .topic-photo-preview { position: relative; margin-bottom: 15px; cursor: pointer; }
.topic.photo .topic-photo-preview img { vertical-align: top; }
.topic.photo .topic-photo-preview .topic-photo-count { position: absolute; top: 5px; right: 5px; background: #000; color: #6bd24b; padding: 4px 7px; background: rgba(0,0,0,.6); }
.topic.photo .topic-photo-preview .topic-photo-desc { width: 96%; padding: 7px 2%; position: absolute; bottom: 0; left: 0; background: #000; color: #6bd24b; color: #fff; line-height: 16px; background: rgba(0,0,0,.7); }
.topic.photo .topic-photo-images { padding-top: 10px; }
.topic.photo .topic-photo-images h2 { border-bottom: 1px solid #ddd; padding-bottom: 4px; margin-bottom: 15px; }
.topic.photo .topic-photo-images ul { overflow: hidden; zoom: 1; }
.topic.photo .topic-photo-images ul li { float: left; margin: 0 10px 10px 0; position: relative; }
.topic.photo .topic-photo-images ul li .image-number { display: none; position: absolute; top: 5px; right: 5px; background: #000; color: #6bd24b; padding: 1px 6px; font-size: 11px; background: rgba(0,0,0,.6); }
.topic.photo .topic-photo-images ul li:hover .image-number { display: block; }
.topic.photo .topic-photo-images ul li img { vertical-align: top; }
.topic.photo .topic-photo-images .topic-photo-more { display: block; border-top: 1px solid #dbe6f0; text-align: center; padding: 10px 0; margin-bottom: 15px; text-decoration: none; background: #f3f7fa; color: #7b90a5; }
.topic.photo .topic-photo-images .topic-photo-more:hover { background: #eaf2f8; }
.topic-photo-upload { background: #fafafa; padding: 15px 15px 15px; margin-bottom: 20px; }
.topic-photo-upload h2 { margin-bottom: 15px; }
.topic-photo-upload ul { overflow: hidden; zoom: 1; }
.topic-photo-upload ul li { min-height: 100px; _height: 100px; margin-bottom: 10px; padding-left: 110px; position: relative; }
.topic-photo-upload ul li img { position: absolute; top: 0; left: 0; }
.topic-photo-upload ul li label { color: #aaa; }
.topic-photo-upload ul li textarea { border: 1px solid #ddd; width: 350px; height: 60px; padding: 3px; font-size: 12px; font-family: Arial, sans-serif; color: #333; }
.topic-photo-upload ul li .image-delete { text-decoration: none; margin-right: 15px; }
.topic-photo-upload ul li .image-delete:hover { color: #f00; }
.topic-photo-upload ul li.marked-as-preview .mark-as-preview { display: inline; color: #43c70f; font-weight: bold; }
.topic-photo-upload ul li .mark-as-preview { display: none; text-decoration: none; }
.topic-photo-upload ul li:hover .mark-as-preview { display: inline; }
.topic-photo-upload .topic-photo-upload-rules { color: #888; margin-bottom: 15px; }
.topic-photo-upload .topic-photo-upload-input { margin-bottom: 20px; }
.topic-photo-upload .topic-photo-upload-input input { margin-top: 3px; }
#photoset-upload-form {
width: 270px;
padding: 15px;
margin-left: -120px;
position: absolute;
left: -300px;
top:70%;
background-color: #fff;
border: 1px solid #ccc;
-moz-box-shadow: 0 0 10px #ddd;
-webkit-box-shadow: 0 0 10px #ddd;
box-shadow: 0 0 10px #ddd;
}
#photoset-upload-form p { margin-bottom: 10px; }
#photoset-upload-form .input-text { width: 262px; border: 1px solid #ccc; margin: 0; padding: 3px; font-family: Arial, sans-serif; font-size: 12px; }
.progressWrapper {
width: 357px;
overflow: hidden;
}
.progressContainer {
margin: 5px;
padding: 4px;
border: solid 1px #E8E8E8;
background-color: #F7F7F7;
overflow: hidden;
}
/* Message */
.message {
margin: 1em 0;
padding: 10px 20px;
border: solid 1px #FFDD99;
background-color: #FFFFCC;
overflow: hidden;
}
/* Error */
.red {
border: solid 1px #B50000;
background-color: #FFEBEB;
}
/* Current */
.green {
border: solid 1px #DDF0DD;
background-color: #EBFFEB;
}
/* Complete */
.blue {
border: solid 1px #CEE2F2;
background-color: #F0F5FF;
}
.progressName {
font-size: 8pt;
font-weight: 700;
color: #555;
width: 323px;
height: 14px;
text-align: left;
white-space: nowrap;
overflow: hidden;
}
.progressBarInProgress,
.progressBarComplete,
.progressBarError {
font-size: 0;
width: 0%;
height: 2px;
background-color: blue;
margin-top: 2px;
}
.progressBarComplete {
width: 100%;
background-color: green;
visibility: hidden;
}
.progressBarError {
width: 100%;
background-color: red;
visibility: hidden;
}
.progressBarStatus {
margin-top: 2px;
width: 337px;
font-size: 7pt;
font-family: Arial;
text-align: left;
white-space: nowrap;
}
a.progressCancel {
font-size: 0;
display: block;
height: 14px;
width: 14px;
background-image: url(../images/cancelbutton.gif);
background-repeat: no-repeat;
background-position: -14px 0px;
float: right;
}
a.progressCancel:hover {
background-position: 0px 0px;
}

View file

@ -0,0 +1,41 @@
/**
* jQuery Cookie plugin
*
* Copyright (c) 2010 Klaus Hartl (stilbuero.de)
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
*
*/
jQuery.cookie = function (key, value, options) {
// key and at least value given, set cookie...
if (arguments.length > 1 && String(value) !== "[object Object]") {
options = jQuery.extend({}, options);
if (value === null || value === undefined) {
options.expires = -1;
}
if (typeof options.expires === 'number') {
var days = options.expires, t = options.expires = new Date();
t.setDate(t.getDate() + days);
}
value = String(value);
return (document.cookie = [
encodeURIComponent(key), '=',
options.raw ? value : encodeURIComponent(value),
options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
options.path ? '; path=' + options.path : '',
options.domain ? '; domain=' + options.domain : '',
options.secure ? '; secure' : ''
].join(''));
}
// key and possibly options given, get cookie...
options = value || {};
var result, decode = options.raw ? function (s) { return s; } : decodeURIComponent;
return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? decode(result[1]) : null;
};

View file

@ -0,0 +1,16 @@
/*
*jQuery browser plugin detection 1.0.2
* http://plugins.jquery.com/project/jqplugin
* Checks for plugins / mimetypes supported in the browser extending the jQuery.browser object
* Copyright (c) 2008 Leonardo Rossetti motw.leo@gmail.com
* MIT License: http://www.opensource.org/licenses/mit-license.php
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
(function($){if(typeof $.browser==="undefined"||!$.browser){var browser={};$.extend(browser);}var pluginList={flash:{activex:"ShockwaveFlash.ShockwaveFlash",plugin:/flash/gim},sl:{activex:["AgControl.AgControl"],plugin:/silverlight/gim},pdf:{activex:"PDF.PdfCtrl",plugin:/adobe\s?acrobat/gim},qtime:{activex:"QuickTime.QuickTime",plugin:/quicktime/gim},wmp:{activex:"WMPlayer.OCX",plugin:/(windows\smedia)|(Microsoft)/gim},shk:{activex:"SWCtl.SWCtl",plugin:/shockwave/gim},rp:{activex:"RealPlayer",plugin:/realplayer/gim},java:{activex:navigator.javaEnabled(),plugin:/java/gim}};var isSupported=function(p){if(window.ActiveXObject){try{new ActiveXObject(pluginList[p].activex);$.browser[p]=true;}catch(e){$.browser[p]=false;}}else{$.each(navigator.plugins,function(){if(this.name.match(pluginList[p].plugin)){$.browser[p]=true;return false;}else{$.browser[p]=false;}});}};$.each(pluginList,function(i,n){isSupported(i);});})(jQuery);

View file

@ -0,0 +1,4 @@
var lsLang = new Array();
lsLang['mark_as_preview'] = 'Отметить как превью';
lsLang['preview'] = 'Превью';
lsLang['delete'] = 'Удалить';

View file

@ -0,0 +1,103 @@
function addTopicImage(response)
{
if (!response.bStateError) {
template = '<li id="photo_'+response.id+'"><a href="#"><img src="'+response.file+'" alt="image" /></a>'
+'<textarea onBlur="topicImageSetDescription('+response.id+', this.value)"></textarea><br />'
+'<a href="javascript:deleteTopicImage('+response.id+')" class="image-delete">'+lsLang['delete']+'</a>'
+'<span class="photo-preview-state"><a href="javascript:setTopicMainPhoto('+response.id+')" class="mark-as-preview">'+lsLang['mark_as_preview']+'</a></span></li>';
$('#swfu_images').append(template);
ls.msg.notice(response.sMsgTitle,response.sMsg);
} else {
ls.msg.error(response.sMsgTitle,response.sMsg);
}
photosetCloseForm();
}
function deleteTopicImage(id)
{
ls.ajax(aRouter['photoset']+'deleteimage', {'id':id, 'security_ls_key': LIVESTREET_SECURITY_KEY }, function(response){
if (!response.bStateError) {
$('#photo_'+id).remove();
ls.msg.notice(response.sMsgTitle,response.sMsg);
} else {
ls.msg.error('Error','Please try again later');
}
});
}
function setTopicMainPhoto(id)
{
$('#topic_main_photo').val(id);
$('.marked-as-preview').each(function (index, el) {
$(el).removeClass('marked-as-preview');
$(el).children('span').html('<a href="javascript:setTopicMainPhoto('+$(el).attr('id').slice($(el).attr('id').lastIndexOf('_')+1)+')" class="mark-as-preview">'+lsLang['mark_as_preview']+'</a>');
});
$('#photo_'+id).addClass('marked-as-preview');
$('#photo_'+id).children('span').html(lsLang['preview']);
}
function topicImageSetDescription(id, text)
{
ls.ajax(aRouter['photoset']+'setimagedescription', {'id':id, 'text':text, 'security_ls_key': LIVESTREET_SECURITY_KEY }, function(result){
if (!bStateError) {
} else {
msgErrorBox.alert('Error','Please try again later');
}
}
)
}
function getMorePhotos(topic_id)
{
var last_id = $('#last_photo_id').val();
ls.ajax(aRouter['photoset']+'getmore', {'topic_id':topic_id, 'last_id':last_id, 'security_ls_key': LIVESTREET_SECURITY_KEY }, function(result){
if (!result.bStateError) {
if (result.photos) {
var photoNumber = $('#photo_number').val();
$.each(result.photos, function(index, photo) {
var image = '<li><div class="image-number">'+(photoNumber++)+'</div><a class="photoset-image" href="'+photo.path+'" rel="[photoset]" title="'+photo.description+'"><img src="'+photo.path_thumb+'" alt="'+photo.description+'" /></a></li>';
$('#topic-photo-images').append(image);
$('#photo_number').val(photoNumber);
$('#last_photo_id').val(photo.id);
$('.photoset-image').unbind('click');
$('.photoset-image').prettyPhoto({
social_tools:'',
show_title: false,
slideshow:false,
deeplinking: false
});
});
} else {
$('#topic-photo-more').remove();
}
} else {
msgErrorBox.alert('Error','Please try again later');
}
});
}
function photosetUploadPhoto()
{
ls.ajaxSubmit(aRouter['photoset']+'upload/',$('#photoset-upload-form'),function(data){
if (data.bStateError) {
ls.msg.error(data.sMsgTitle,data.sMsg);
} else {
addTopicImage(data);
}
});
photosetCloseForm();
}
function photosetCloseForm() {
$('#photoset-upload-form').css('left', '-300px');
}
function photosetShowUploadForm()
{
if ($('#photoset-upload-file').length) {
$('#photoset-upload-file').val( '');
}
$('#photoset-upload-form').css('left', '50%');
}

View file

@ -3,21 +3,24 @@ var ls = ls || {};
ls.stream =( function ($) {
this.isBusy = false;
this.subscribe = function (iTargetUserId) {
ls.ajax(aRouter['stream']+'subscribe', {'id':iTargetUserId}, function(data) {
ls.ajax(aRouter['stream']+'subscribe/', {'id':iTargetUserId}, function(data) {
if (!data.bStateError) {
ls.msg.notice(data.sMsgTitle,data.sMsg);
} else {
ls.msg.notice(data.sMsgTitle,data.sMsg);
}
});
}
this.unsubscribe = function (iId) {
ls.ajax(aRouter['stream']+'unsubscribe', {'id':iId}, function(data) {
ls.ajax(aRouter['stream']+'unsubscribe/', {'id':iId}, function(data) {
if (!data.bStateError) {
ls.msg.notice(data.sMsgTitle,data.sMsg);
}
});
}
this.switchEventType = function (iType) {
ls.ajax(aRouter['stream']+'switchEventType', { 'type':iType}, function(data) {
ls.ajax(aRouter['stream']+'switchEventType/', { 'type':iType}, function(data) {
if (!data.bStateError) {
ls.msg.notice(data.sMsgTitle,data.sMsg);
}
@ -26,7 +29,7 @@ ls.stream =( function ($) {
this.appendUser = function() {
var sLogin = $('#stream_users_complete').val();
if (!sLogin) return;
ls.ajax(aRouter['stream']+'subscribeByLogin', {'login':sLogin}, function(data) {
ls.ajax(aRouter['stream']+'subscribeByLogin/', {'login':sLogin}, function(data) {
if (!data.bStateError) {
$('#stream_no_subscribed_users').remove();
var checkbox = $('#strm_u_'+data.uid);
@ -42,6 +45,8 @@ ls.stream =( function ($) {
$('#stream_block_users_list').append(liElement);
ls.msg.notice(data.sMsgTitle,data.sMsg);
}
} else {
ls.msg.notice(data.sMsgTitle,data.sMsg);
}
});
}
@ -53,7 +58,7 @@ ls.stream =( function ($) {
if (!lastId) return;
$('#stream_get_more').addClass('stream_loading');
this.isBusy = true;
ls.ajax(aRouter['stream']+'get_more', {'last_id':lastId}, function(data) {
ls.ajax(aRouter['stream']+'get_more/', {'last_id':lastId}, function(data) {
if (!data.bStateError && data.topics_count) {
$('#stream_loaded_topics').append(data.result);
$('#stream_last_id').attr('value', data.iStreamLastId);

View file

@ -3,14 +3,14 @@ var ls = ls || {};
ls.userfeed =( function ($) {
this.isBusy = false;
this.subscribe = function (sType, iId) {
ls.ajax(aRouter['feed']+'subscribe', {'type':sType, 'id':iId}, function(data) {
ls.ajax(aRouter['feed']+'subscribe/', {'type':sType, 'id':iId}, function(data) {
if (!data.bStateError) {
ls.msg.notice(data.sMsgTitle,data.sMsg);
}
});
}
this.unsubscribe = function (sType, iId) {
ls.ajax(aRouter['feed']+'unsubscribe', {'type':sType, 'id':iId}, function(data) {
ls.ajax(aRouter['feed']+'unsubscribe/', {'type':sType, 'id':iId}, function(data) {
if (!data.bStateError) {
ls.msg.notice(data.sMsgTitle,data.sMsg);
}
@ -19,7 +19,7 @@ ls.userfeed =( function ($) {
this.appendUser = function() {
var sLogin = $('#userfeed_users_complete').val();
if (!sLogin) return;
ls.ajax(aRouter['feed']+'subscribeByLogin', {'login':sLogin}, function(data) {
ls.ajax(aRouter['feed']+'subscribeByLogin/', {'login':sLogin}, function(data) {
if (!data.bStateError) {
$('#stream_no_subscribed_users').remove();
var checkbox = $('#usf_u_'+data.uid);
@ -46,7 +46,7 @@ ls.userfeed =( function ($) {
if (!lastId) return;
$('#userfeed_get_more').addClass('userfeed_loading');
this.isBusy = true;
ls.ajax(aRouter['feed']+'get_more', {'last_id':lastId}, function(data) {
ls.ajax(aRouter['feed']+'get_more/', {'last_id':lastId}, function(data) {
if (!data.bStateError && data.topics_count) {
$('#userfeed_loaded_topics').append(data.result);
$('#userfeed_last_id').attr('value', data.iUserfeedLastId);

View file

@ -11,6 +11,9 @@ $config['head']['default']['js'] = array(
"___path.static.skin___/js/libs/markitup/jquery.markitup.js",
"___path.static.skin___/js/libs/markitup/sets/default/set.js",
"___path.static.skin___/js/libs/jquery.form.js",
"___path.static.skin___/js/libs/jquery.jqplugin.1.0.2.min.js",
"___path.static.skin___/js/libs/jquery.cookie.js",
"___path.static.skin___/js/ls.lang.ru.js",
"___path.static.skin___/js/main.js",
"___path.static.skin___/js/favourite.js",
"___path.static.skin___/js/blocks.js",
@ -22,6 +25,7 @@ $config['head']['default']['js'] = array(
"___path.static.skin___/js/friend.js",
"___path.static.skin___/js/userfeed.js",
"___path.static.skin___/js/stream.js",
"___path.static.skin___/js/other.js",
);
$config['head']['default']['css'] = array(
"___path.static.skin___/css/reset.css",

View file

@ -0,0 +1,130 @@
{assign var="oBlog" value=$oTopic->getBlog()}
{assign var="oUser" value=$oTopic->getUser()}
{assign var="oVote" value=$oTopic->getVote()}
<script type="text/javascript" src="{cfg name='path.root.engine_lib'}/external/prettyPhoto/js/prettyPhoto.js"></script>
<link rel='stylesheet' type='text/css' href="{cfg name='path.root.engine_lib'}/external/prettyPhoto/css/prettyPhoto.css" />
<script type="text/javascript">
{literal}
$(document).ready(function() {
$('.photoset-image').prettyPhoto({
social_tools:'',
show_title: false,
slideshow:false,
deeplinking: false
});
});
{/literal}
</script>
<div class="topic photo">
<div class="favorite {if $oUserCurrent}{if $oTopic->getIsFavourite()}active{/if}{else}fav-guest{/if}"><a href="#" onclick="lsFavourite.toggle({$oTopic->getId()},this,'topic'); return false;"></a></div>
<h1 class="title">
{if $oTopic->getPublish()==0}
<img src="{cfg name='path.static.skin'}/images/topic_unpublish.gif" border="0" title="{$aLang.topic_unpublish}" width="16" height="16" alt="{$aLang.topic_unpublish}">
{/if}
{if $bTopicList}
<a href="{$oTopic->getUrl()}">{$oTopic->getTitle()|escape:'html'}</a>
{else}
{$oTopic->getTitle()|escape:'html'}
{/if}
</h1>
<ul class="action">
<li><a href="{$oBlog->getUrlFull()}">{$oBlog->getTitle()|escape:'html'}</a>&nbsp;&nbsp;</li>
{if $oUserCurrent and ($oUserCurrent->getId()==$oTopic->getUserId() or $oUserCurrent->isAdministrator() or $oBlog->getUserIsAdministrator() or $oBlog->getUserIsModerator() or $oBlog->getOwnerId()==$oUserCurrent->getId())}
<li class="edit"><a href="{cfg name='path.root.web'}/{$oTopic->getType()}/edit/{$oTopic->getId()}/" title="{$aLang.topic_edit}">{$aLang.topic_edit}</a></li>
{/if}
{if $oUserCurrent and ($oUserCurrent->isAdministrator() or $oBlog->getUserIsAdministrator() or $oBlog->getOwnerId()==$oUserCurrent->getId())}
<li class="delete"><a href="{router page='topic'}delete/{$oTopic->getId()}/?security_ls_key={$LIVESTREET_SECURITY_KEY}" title="{$aLang.topic_delete}" onclick="return confirm('{$aLang.topic_delete_confirm}');">{$aLang.topic_delete}</a></li>
{/if}
</ul>
{assign var=iPhotosCount value=$oTopic->getPhotosCount()}
<!-- Topic Photo Preview -->
<div class="topic-photo-preview" style="width: 500px">
{assign var=oMainPhoto value=$oTopic->getMainPhoto()}
<div class="topic-photo-count">{$iPhotosCount} {$aLang.topic_photoset_photos}</div>
<div class="topic-photo-desc">{$oTopic->getMainPhotoDescription()}</div>
<img src="{$oMainPhoto->getWebPath(500)}" alt="image" />
</div>
<!-- /Topic Photo Preview -->
<div class="content">
{if $bTopicList}
{$oTopic->getTextShort()}
<!-- Cut link -->
<br /><br /><a href="{$oTopic->getUrl()}">{$aLang.topic_photoset_show_all|ls_lang:"COUNT%%`$iPhotosCount`"} &rarr;</a>
<!-- /Cut link -->
{if $oTopic->getTextShort()!=$oTopic->getText()}
<br><br>( <a href="{$oTopic->getUrl()}#cut" title="{$aLang.topic_read_more}">
{if $oTopic->getCutText()}
{$oTopic->getCutText()}
{else}
{$aLang.topic_read_more}
{/if}
</a> )
{/if}
{else}
{$oTopic->getText()}
{/if}
</div>
<!-- Topic Photo Image List -->
{if !$bTopicList}
<div class="topic-photo-images">
<h2>{$iPhotosCount} {$aLang.topic_photoset_count_images}</h2>
<ul id="topic-photo-images" >
{assign var=aPhotos value=$oTopic->getPhotos(0, $oConfig->get('module.topic.photoset.per_page'))}
{if count($aPhotos)}
{assign var=iPhotoNumber value=1}
{foreach from=$aPhotos item=oPhoto}
<li><div class="image-number">{$iPhotoNumber}</div><a class="photoset-image" href="{$oPhoto->getWebPath()}" rel="[photoset]" title="{$oPhoto->getDescription()}"><img src="{$oPhoto->getWebPath('50crop')}" alt="{$oPhoto->getDescription()}" /></a></li>
{assign var=iPhotoNumber value=$iPhotoNumber+1}
{assign var=iLastPhotoId value=$oPhoto->getId()}
{/foreach}
{/if}
</ul>
<input type="hidden" id="photo_number" value="{$iPhotoNumber}" />
<input type="hidden" id="last_photo_id" value="{$iLastPhotoId}" />
<a href="javascript:getMorePhotos({$oTopic->getId()})" id="topic-photo-more" class="topic-photo-more">{$aLang.topic_photoset_show_more} &darr;</a>
</div>
{/if}
<!-- /Topic Photo Image List -->
<ul class="tags">
{foreach from=$oTopic->getTagsArray() item=sTag name=tags_list}
<li><a href="{router page='tag'}{$sTag|escape:'url'}/">{$sTag|escape:'html'}</a>{if !$smarty.foreach.tags_list.last}, {/if}</li>
{/foreach}
</ul>
<ul class="voting {if $oVote || ($oUserCurrent && $oTopic->getUserId()==$oUserCurrent->getId())|| strtotime($oTopic->getDateAdd())<$smarty.now-$oConfig->GetValue('acl.vote.topic.limit_time')}{if $oTopic->getRating()>0}positive{elseif $oTopic->getRating()<0}negative{/if}{/if} {if !$oUserCurrent || $oTopic->getUserId()==$oUserCurrent->getId() || strtotime($oTopic->getDateAdd())<$smarty.now-$oConfig->GetValue('acl.vote.topic.limit_time')}guest{/if} {if $oVote} voted {if $oVote->getDirection()>0}plus{elseif $oVote->getDirection()<0}minus{/if}{/if}">
<li class="plus"><a href="#" onclick="lsVote.vote({$oTopic->getId()},this,1,'topic'); return false;"></a></li>
<li class="total" title="{$aLang.topic_vote_count}: {$oTopic->getCountVote()}">{if $oVote || ($oUserCurrent && $oTopic->getUserId()==$oUserCurrent->getId()) || strtotime($oTopic->getDateAdd())<$smarty.now-$oConfig->GetValue('acl.vote.topic.limit_time')} {if $oTopic->getRating()>0}+{/if}{$oTopic->getRating()} {else} <a href="#" onclick="lsVote.vote({$oTopic->getId()},this,0,'topic'); return false;">&mdash;</a> {/if}</li>
<li class="minus"><a href="#" onclick="lsVote.vote({$oTopic->getId()},this,-1,'topic'); return false;"></a></li>
<li class="date">{date_format date=$oTopic->getDateAdd()}</li>
<li class="author"><a href="{$oUser->getUserWebPath()}">{$oUser->getLogin()}</a></li>
{if $bTopicList}
<li class="comments-total">
{if $oTopic->getCountComment()>0}
<a href="{$oTopic->getUrl()}#comments" title="{$aLang.topic_comment_read}"><span class="red">{$oTopic->getCountComment()}</span>{if $oTopic->getCountCommentNew()}<span class="green">+{$oTopic->getCountCommentNew()}</span>{/if}</a>
{else}
<a href="{$oTopic->getUrl()}#comments" title="{$aLang.topic_comment_add}"><span class="red">{$aLang.topic_comment_add}</span></a>
{/if}
</li>
{/if}
{hook run='topic_show_info' topic=$oTopic}
</ul>
{hook run='topic_show_end' topic=$oTopic}
</div>

View file

@ -0,0 +1,256 @@
{include file='header.tpl' menu='topic_action' showWhiteBack=true}
{literal}
<script language="JavaScript" type="text/javascript">
document.addEvent('domready', function() {
new Autocompleter.Request.LS.JSON($('topic_tags'), aRouter['ajax']+'autocompleter/tag/?security_ls_key='+LIVESTREET_SECURITY_KEY, {
'indicatorClass': 'autocompleter-loading', // class added to the input during request
'minLength': 2, // We need at least 1 character
'selectMode': 'pick', // Instant completion
'multiple': true // Tag support, by default comma separated
});
});
</script>
{/literal}
{if $oConfig->GetValue('view.tinymce')}
<script type="text/javascript" src="{cfg name='path.root.engine_lib'}/external/tinymce/tiny_mce.js"></script>
<script type="text/javascript">
{literal}
tinyMCE.init({
mode : "specific_textareas",
editor_selector : "mceEditor",
theme : "advanced",
theme_advanced_toolbar_location : "top",
theme_advanced_toolbar_align : "left",
theme_advanced_buttons1 : "lshselect,bold,italic,underline,strikethrough,|,bullist,numlist,|,undo,redo,|,lslink,unlink,lsvideo,lsimage,pagebreak,code",
theme_advanced_buttons2 : "",
theme_advanced_buttons3 : "",
theme_advanced_statusbar_location : "bottom",
theme_advanced_resizing : true,
theme_advanced_resize_horizontal : 0,
theme_advanced_resizing_use_cookie : 0,
theme_advanced_path : false,
object_resizing : true,
force_br_newlines : true,
forced_root_block : '', // Needed for 3.x
force_p_newlines : false,
plugins : "lseditor,safari,inlinepopups,media,pagebreak",
inline_styles:false,
formats : {
underline : {inline : 'u', exact : true},
strikethrough : {inline : 's', exact : true}
},
convert_urls : false,
extended_valid_elements : "embed[src|type|allowscriptaccess|allowfullscreen|width|height]",
pagebreak_separator :"<cut>",
media_strict : false,
language : TINYMCE_LANG
});
{/literal}
</script>
{else}
{include file='window_load_img.tpl' sToLoad='topic_text'}
{/if}
<script type="text/javascript" src="{cfg name='path.root.engine_lib'}/external/swfupload/swfupload.swfobject.js"></script>
<script type="text/javascript" src="{cfg name='path.root.engine_lib'}/external/swfupload/swfupload.js"></script>
<script type="text/javascript" src="{cfg name='path.root.engine_lib'}/external/swfupload/swfupload.handlers.js"></script>
<script type="text/javascript">
{literal}
if (Browser.Plugins.Flash.version) {
{/literal}
var path_root_engine_lib = '{cfg name='path.root.engine_lib'}';
var topic_id = '{$_aRequest.topic_id}';
var SSID='{$_sPhpSessionId}'
{literal}
var target_tmp = (Cookie.read('ls_photoset_target_tmp')) ? Cookie.read('ls_photoset_target_tmp') : 0;
document.addEvent('domready', function() {
swfu = new SWFUpload({
// Backend Settings
upload_url: aRouter['photoset']+"upload",
post_params: {'ls_photoset_target_tmp':target_tmp,'topic_id':topic_id, 'SSID':SSID, 'security_ls_key': LIVESTREET_SECURITY_KEY},
// File Upload Settings
file_types : "*.jpg; *.JPG;*.png;*.gif",
file_types_description : "Images",
file_upload_limit : "0",
// Event Handler Settings - these functions as defined in Handlers.js
// The handlers are not part of SWFUpload but are part of my website and control how
// my website reacts to the SWFUpload events.
file_queue_error_handler : fileQueueError,
file_dialog_complete_handler : fileDialogComplete,
upload_progress_handler : uploadProgress,
upload_error_handler : uploadError,
upload_success_handler : uploadSuccess,
upload_complete_handler : uploadComplete,
// Button Settings
button_placeholder_id : "topic-photo-upload-input",
button_width: 122,
button_height: 30,
button_text : '<span class="button">Загрузить фото</span>',
button_text_style : '.button { font-family: Helvetica, Arial, sans-serif; font-size: 14pt; } .buttonSmall { font-size: 10pt; }',
button_window_mode: SWFUpload.WINDOW_MODE.TRANSPARENT,
button_text_left_padding: 6,
button_text_top_padding: 3,
button_cursor: SWFUpload.CURSOR.HAND,
// Flash Settings
flash_url : path_root_engine_lib+'/external/swfupload/swfupload.swf',
custom_settings : {
upload_target : "notice_wrap"
},
// Debug Settings
debug: true
});
});
}
{/literal}
</script>
<div class="topic" style="display: none;">
<div class="content" id="text_preview"></div>
</div>
<div class="profile-user">
{if $sEvent=='add'}
<h1>{$aLang.topic_photoset_create}</h1>
{else}
<h1>{$aLang.topic_photoset_edit}</h1>
{/if}
<form id="photoset-upload-form" method="POST" enctype="multipart/form-data">
<p id="topic-photo-upload-input" class="topic-photo-upload-input">
<label for="">{$aLang.topic_photoset_choose_image}:</label><br />
<input type="file" id="photoset-upload-file" name="Filedata" />
<a href="javascript:photosetUploadPhoto()" >upload</a>
<input type="hidden" name="is_iframe" value="true" />
<input type="hidden" name="topic_id" value="{$_aRequest.topic_id}" />
</p>
</form>
<form action="" method="POST" enctype="multipart/form-data">
{hook run='form_add_topic_topic_begin'}
<input type="hidden" name="security_ls_key" value="{$LIVESTREET_SECURITY_KEY}" />
<p><label for="blog_id">{$aLang.topic_create_blog}</label>
<select name="blog_id" id="blog_id" onChange="ajaxBlogInfo(this.value);">
<option value="0">{$aLang.topic_create_blog_personal}</option>
{foreach from=$aBlogsAllow item=oBlog}
<option value="{$oBlog->getId()}" {if $_aRequest.blog_id==$oBlog->getId()}selected{/if}>{$oBlog->getTitle()}</option>
{/foreach}
</select></p>
<script language="JavaScript" type="text/javascript">
ajaxBlogInfo($('blog_id').value);
</script>
<p><label for="topic_title">{$aLang.topic_create_title}:</label><br />
<input type="text" id="topic_title" name="topic_title" value="{$_aRequest.topic_title}" class="w100p" /><br />
<span class="form_note">{$aLang.topic_create_title_notice}</span>
</p>
<p>{if !$oConfig->GetValue('view.tinymce')}<div class="note">{$aLang.topic_create_text_notice}</div>{/if}<label for="topic_text">{$aLang.topic_create_text}:</label>
{if !$oConfig->GetValue('view.tinymce')}
<div class="panel_form">
{hook run='form_add_topic_panel_begin'}
<select onchange="lsPanel.putTagAround('topic_text',this.value); this.selectedIndex=0; return false;">
<option value="">{$aLang.panel_title}</option>
<option value="h4">{$aLang.panel_title_h4}</option>
<option value="h5">{$aLang.panel_title_h5}</option>
<option value="h6">{$aLang.panel_title_h6}</option>
</select>
<select onchange="lsPanel.putList('topic_text',this); return false;">
<option value="">{$aLang.panel_list}</option>
<option value="ul">{$aLang.panel_list_ul}</option>
<option value="ol">{$aLang.panel_list_ol}</option>
</select>
<a href="#" onclick="lsPanel.putTagAround('topic_text','b'); return false;" class="button"><img src="{cfg name='path.static.skin'}/images/panel/bold.png" title="{$aLang.panel_b}"></a>
<a href="#" onclick="lsPanel.putTagAround('topic_text','i'); return false;" class="button"><img src="{cfg name='path.static.skin'}/images/panel/italic.png" title="{$aLang.panel_i}"></a>
<a href="#" onclick="lsPanel.putTagAround('topic_text','u'); return false;" class="button"><img src="{cfg name='path.static.skin'}/images/panel/underline.png" title="{$aLang.panel_u}"></a>
<a href="#" onclick="lsPanel.putTagAround('topic_text','s'); return false;" class="button"><img src="{cfg name='path.static.skin'}/images/panel/strikethrough.png" title="{$aLang.panel_s}"></a>
&nbsp;
<a href="#" onclick="lsPanel.putTagUrl('topic_text','{$aLang.panel_url_promt}'); return false;" class="button"><img src="{cfg name='path.static.skin'}/images/panel/link.png" title="{$aLang.panel_url}"></a>
<a href="#" onclick="lsPanel.putQuote('topic_text'); return false;" class="button"><img src="{cfg name='path.static.skin'}/images/panel/quote.png" title="{$aLang.panel_quote}"></a>
<a href="#" onclick="lsPanel.putTagAround('topic_text','code'); return false;" class="button"><img src="{cfg name='path.static.skin'}/images/panel/code.png" title="{$aLang.panel_code}"></a>
<a href="#" onclick="lsPanel.putTagAround('topic_text','video'); return false;" class="button"><img src="{cfg name='path.static.skin'}/images/panel/video.png" title="{$aLang.panel_video}"></a>
<a href="#" onclick="showImgUploadForm(); return false;" class="button"><img src="{cfg name='path.static.skin'}/images/panel/img.png" title="{$aLang.panel_image}"></a>
<a href="#" onclick="lsPanel.putText('topic_text','<cut>'); return false;" class="button"><img src="{cfg name='path.static.skin'}/images/panel/cut.png" title="{$aLang.panel_cut}"></a>
{hook run='form_add_topic_panel_end'}
</div>
{/if}
<textarea name="topic_text" class="mceEditor" id="topic_text" rows="20">{$_aRequest.topic_text}</textarea></p>
<!-- Topic Photo Add -->
<div class="topic-photo-upload">
<h2>{$aLang.topic_photoset_upload_title}</h2>
<div class="topic-photo-upload-rules">
{$aLang.topic_photoset_upload_rules|ls_lang:"SIZE%%`$oConfig->get('module.topic.photoset.photo_max_size')`":"COUNT%%`$oConfig->get('module.topic.photoset.count_photos_max')`"}
</div>
<a href="javascript:photosetShowUploadForm()">Загрузить фото</a>
<input type="hidden" name="topic_main_photo" id="topic_main_photo" />
<ul id="swfu_images">
{if count($aPhotos)}
{foreach from=$aPhotos item=oPhoto}
{if $_aRequest.topic_main_photo && $_aRequest.topic_main_photo == $oPhoto->getId()}
{assign var=bIsMainPhoto value=true}
{/if}
<li id="photo_{$oPhoto->getId()}" {if $bIsMainPhoto}class="marked-as-preview"{/if}>
<img src="{$oPhoto->getWebPath(100)}" alt="image" />
<textarea onBlur="topicImageSetDescription({$oPhoto->getId()}, this.value)">{$oPhoto->getDescription()}</textarea><br />
<a href="javascript:deleteTopicImage({$oPhoto->getId()})" class="image-delete">Удалить</a>
<span class="photo-preview-state">
{if $bIsMainPhoto}
{$aLang.topic_photoset_is_preview}
{else}
<a href="javascript:setTopicMainPhoto({$oPhoto->getId()})" class="mark-as-preview">{$aLang.topic_photoset_mark_as_preview}</a>
{/if}
</span>
</li>
{assign var=bIsMainPhoto value=false}
{/foreach}
{/if}
</ul>
<div id="notice_wrap"></div>
</div>
<textarea name="topic_main_photo_description" id="topic_main_photo_description" rows="20">{$_aRequest.topic_main_photo_description}</textarea></p>
<!-- /Topic Photo Add -->
<p><label for="topic_tags">{$aLang.topic_create_tags}:</label><br />
<input type="text" id="topic_tags" name="topic_tags" value="{$_aRequest.topic_tags}" class="w100p" /><br />
<span class="form_note">{$aLang.topic_create_tags_notice}</span></p>
<p><label for="topic_forbid_comment"><input type="checkbox" id="topic_forbid_comment" name="topic_forbid_comment" class="checkbox" value="1" {if $_aRequest.topic_forbid_comment==1}checked{/if}/>
&mdash; {$aLang.topic_create_forbid_comment}</label><br />
<span class="form_note">{$aLang.topic_create_forbid_comment_notice}</span></p>
{if $oUserCurrent->isAdministrator()}
<p><label for="topic_publish_index"><input type="checkbox" id="topic_publish_index" name="topic_publish_index" class="checkbox" value="1" {if $_aRequest.topic_publish_index==1}checked{/if}/>
&mdash; {$aLang.topic_create_publish_index}</label><br />
<span class="form_note">{$aLang.topic_create_publish_index_notice}</span></p>
{/if}
{hook run='form_add_topic_topic_end'}
<p class="buttons">
<input type="submit" name="submit_topic_publish" value="{$aLang.topic_create_submit_publish}" class="right" />
<input type="submit" name="submit_preview" value="{$aLang.topic_create_submit_preview}" onclick="$('text_preview').getParent('div').setStyle('display','block'); ajaxTextPreview('topic_text',false); return false;" />&nbsp;
<input type="submit" name="submit_topic_save" value="{$aLang.topic_create_submit_save}" />
</p>
</form>
</div>
{include file='footer.tpl'}

View file

@ -448,8 +448,148 @@ p { margin-bottom: 18px; }
.userfield-form p { margin-bottom: 10px; }
.userfield-form .input-text { width: 262px; border: 1px solid #ccc; margin: 0; padding: 3px; font-family: Arial, sans-serif; font-size: 12px; }
/* Topic Photo */
.topic.photo { }
.topic.photo .topic-photo-preview { position: relative; margin-bottom: 15px; cursor: pointer; }
.topic.photo .topic-photo-preview img { vertical-align: top; }
.topic.photo .topic-photo-preview .topic-photo-count { position: absolute; top: 5px; right: 5px; background: #000; color: #6bd24b; padding: 4px 7px; background: rgba(0,0,0,.6); }
.topic.photo .topic-photo-preview .topic-photo-desc { width: 96%; padding: 7px 2%; position: absolute; bottom: 0; left: 0; background: #000; color: #6bd24b; color: #fff; line-height: 16px; background: rgba(0,0,0,.7); }
.topic.photo .topic-photo-images { padding-top: 10px; }
.topic.photo .topic-photo-images h2 { border-bottom: 1px solid #ddd; padding-bottom: 4px; margin-bottom: 15px; }
.topic.photo .topic-photo-images ul { overflow: hidden; zoom: 1; }
.topic.photo .topic-photo-images ul li { float: left; margin: 0 10px 10px 0; position: relative; }
.topic.photo .topic-photo-images ul li .image-number { display: none; position: absolute; top: 5px; right: 5px; background: #000; color: #6bd24b; padding: 1px 6px; font-size: 11px; background: rgba(0,0,0,.6); }
.topic.photo .topic-photo-images ul li:hover .image-number { display: block; }
.topic.photo .topic-photo-images ul li img { vertical-align: top; }
.topic.photo .topic-photo-images .topic-photo-more { display: block; border-top: 1px solid #dbe6f0; text-align: center; padding: 10px 0; margin-bottom: 15px; text-decoration: none; background: #f3f7fa; color: #7b90a5; }
.topic.photo .topic-photo-images .topic-photo-more:hover { background: #eaf2f8; }
.topic-photo-upload { background: #fafafa; padding: 15px 15px 15px; margin-bottom: 20px; }
.topic-photo-upload h2 { margin-bottom: 15px; }
.topic-photo-upload ul { overflow: hidden; zoom: 1; }
.topic-photo-upload ul li { min-height: 100px; _height: 100px; margin-bottom: 10px; padding-left: 110px; position: relative; }
.topic-photo-upload ul li img { position: absolute; top: 0; left: 0; }
.topic-photo-upload ul li label { color: #aaa; }
.topic-photo-upload ul li textarea { border: 1px solid #ddd; width: 350px; height: 60px; padding: 3px; font-size: 12px; font-family: Arial, sans-serif; color: #333; }
.topic-photo-upload ul li .image-delete { text-decoration: none; margin-right: 15px; }
.topic-photo-upload ul li .image-delete:hover { color: #f00; }
.topic-photo-upload ul li.marked-as-preview .mark-as-preview { display: inline; color: #43c70f; font-weight: bold; }
.topic-photo-upload ul li .mark-as-preview { display: none; text-decoration: none; }
.topic-photo-upload ul li:hover .mark-as-preview { display: inline; }
.topic-photo-upload .topic-photo-upload-rules { color: #888; margin-bottom: 15px; }
.topic-photo-upload .topic-photo-upload-input { margin-bottom: 20px; }
.topic-photo-upload .topic-photo-upload-input input { margin-top: 3px; }
#photoset-upload-form {
width: 270px;
padding: 15px;
margin-left: -120px;
position: absolute;
left: -300px;
top:70%;
background-color: #fff;
border: 1px solid #ccc;
-moz-box-shadow: 0 0 10px #ddd;
-webkit-box-shadow: 0 0 10px #ddd;
box-shadow: 0 0 10px #ddd;
}
#photoset-upload-form p { margin-bottom: 10px; }
#photoset-upload-form .input-text { width: 262px; border: 1px solid #ccc; margin: 0; padding: 3px; font-family: Arial, sans-serif; font-size: 12px; }
.progressWrapper {
width: 357px;
overflow: hidden;
}
.progressContainer {
margin: 5px;
padding: 4px;
border: solid 1px #E8E8E8;
background-color: #F7F7F7;
overflow: hidden;
}
/* Message */
.message {
margin: 1em 0;
padding: 10px 20px;
border: solid 1px #FFDD99;
background-color: #FFFFCC;
overflow: hidden;
}
/* Error */
.red {
border: solid 1px #B50000;
background-color: #FFEBEB;
}
/* Current */
.green {
border: solid 1px #DDF0DD;
background-color: #EBFFEB;
}
/* Complete */
.blue {
border: solid 1px #CEE2F2;
background-color: #F0F5FF;
}
.progressName {
font-size: 8pt;
font-weight: 700;
color: #555;
width: 323px;
height: 14px;
text-align: left;
white-space: nowrap;
overflow: hidden;
}
.progressBarInProgress,
.progressBarComplete,
.progressBarError {
font-size: 0;
width: 0%;
height: 2px;
background-color: blue;
margin-top: 2px;
}
.progressBarComplete {
width: 100%;
background-color: green;
visibility: hidden;
}
.progressBarError {
width: 100%;
background-color: red;
visibility: hidden;
}
.progressBarStatus {
margin-top: 2px;
width: 337px;
font-size: 7pt;
font-family: Arial;
text-align: left;
white-space: nowrap;
}
a.progressCancel {
font-size: 0;
display: block;
height: 14px;
width: 14px;
background-image: url(../images/cancelbutton.gif);
background-repeat: no-repeat;
background-position: -14px 0px;
float: right;
}
a.progressCancel:hover {
background-position: 0px 0px;
}

View file

@ -0,0 +1,4 @@
var lsLang = new Array();
lsLang['mark_as_preview'] = 'Отметить как превью';
lsLang['preview'] = 'Превью';
lsLang['delete'] = 'Удалить';

View file

@ -117,4 +117,121 @@ function ajaxUploadImg(form,sToLoad) {
}
});
iFrame.send();
}
function addTopicImage(response)
{
if (!response.bStateError) {
template = '<a href="#"><img src="'+response.file+'" alt="image" /></a>'
+'<textarea onBlur="topicImageSetDescription('+response.id+', this.value)"></textarea><br />'
+'<a href="javascript:deleteTopicImage('+response.id+')" class="image-delete">'+lsLang['delete']+'</a>'
+'<span class="photo-preview-state"><a href="javascript:setTopicMainPhoto('+response.id+')" class="mark-as-preview">'+lsLang['mark_as_preview']+'</a></span>';
liElement= new Element('li', {'id':'photo_'+response.id,'html':template})
liElement.inject('swfu_images');
msgNoticeBox.alert(response.sMsgTitle,response.sMsg);
} else {
msgErrorBox.alert(response.sMsgTitle,response.sMsg);
}
photosetCloseForm();
}
function deleteTopicImage(id)
{
new Request.JSON({
url: aRouter['photoset']+'deleteimage',
data: {'id':id, 'security_ls_key': LIVESTREET_SECURITY_KEY },
onSuccess: function(response){
if (!response.bStateError) {
$('photo_'+id).dispose();
msgNoticeBox.alert(response.sMsgTitle,response.sMsg);
} else {
msgErrorBox.alert('Error','Please try again later');
}
}
}).send();
}
function setTopicMainPhoto(id)
{
$('topic_main_photo').set('value', id);
$$('..marked-as-preview').each(function (el) {
el.removeClass('marked-as-preview');
el.getElement('span').set('html','<a href="javascript:setTopicMainPhoto('+el.get('id').slice(el.get('id').lastIndexOf('_')+1)+')" class="mark-as-preview">'+lsLang['mark_as_preview']+'</a>')
});
$('photo_'+id).addClass('marked-as-preview');
$('photo_'+id).getElement('span').set('html', lsLang['preview']);
}
function topicImageSetDescription(id, text)
{
new Request.JSON({
url: aRouter['photoset']+'setimagedescription',
data: {'id':id, 'text':text, 'security_ls_key': LIVESTREET_SECURITY_KEY },
onSuccess: function(result){
if (!bStateError) {
} else {
msgErrorBox.alert('Error','Please try again later');
}
}
}).send();
}
function getMorePhotos(topic_id)
{
var last_id = $('last_photo_id').get('value');
new Request.JSON({
url: aRouter['photoset']+'getmore',
data: {'topic_id':topic_id, 'last_id':last_id, 'security_ls_key': LIVESTREET_SECURITY_KEY },
onSuccess: function(result){
if (!result.bStateError) {
if (result.photos) {
var photoNumber = $('photo_number').get('value');
result.photos.each(function(photo) {
var image = '<div class="image-number">'+(photoNumber++)+'</div><a class="photoset-image" href="'+photo.path+'" rel="milkbox[photoset]" title="'+photo.description+'"><img src="'+photo.path_thumb+'" alt="'+photo.description+'" /></a>';
var liElement = new Element('li', {'html':image});
liElement.inject($('topic-photo-images'));
$('photo_number').set('value', photoNumber);
$('last_photo_id').set('value', photo.id);
$$('.photoset-image').each(function(el) {console.log(el);el.removeEvents('click')});
milkbox = new Milkbox();
});
} else {
$('topic-photo-more').dispose();
}
} else {
msgErrorBox.alert('Error','Please try again later');
}
}
}).send();
}
function photosetUploadPhoto()
{
var iFrame = new iFrameFormRequest($('photoset-upload-form').getProperty('id'),{
url: aRouter['photoset']+'upload/',
dataType: 'json',
params: {security_ls_key: LIVESTREET_SECURITY_KEY},
onComplete: function(response){
if (response.bStateError) {
msgErrorBox.alert(response.sMsgTitle,response.sMsg);
} else {
addTopicImage(response);
}
}
});
iFrame.send();
photosetCloseForm();
}
function photosetCloseForm() {
if ($('photoset-upload-file')) {
$('photoset-upload-file').set('value', '');
}
$('photoset-upload-form').setStyle('left', '-300px');
}
function photosetShowUploadForm()
{
$('photoset-upload-form').setStyle('left', '50%');
}

View file

@ -2,18 +2,20 @@ function lsStreamClass() {
this.isBusy = false;
this.subscribe = function (iTargetUserId) {
new Request.JSON({
url: aRouter['stream']+'subscribe',
url: aRouter['stream']+'subscribe/',
data: {'id':iTargetUserId, 'security_ls_key':LIVESTREET_SECURITY_KEY},
onSuccess: function(data) { // запрос выполнен уcпешно
if (!data.bStateError) {
msgNoticeBox.alert(data.sMsgTitle,data.sMsg);
}else {
msgErrorBox.alert(data.sMsgTitle,data.sMsg);
}
}
}
}).send();
}
this.unsubscribe = function (iId) {
new Request.JSON({
url: aRouter['stream']+'unsubscribe',
url: aRouter['stream']+'unsubscribe/',
data: { 'id':iId, 'security_ls_key':LIVESTREET_SECURITY_KEY},
onSuccess: function(data) { // запрос выполнен уcпешно
if (!data.bStateError) {
@ -24,7 +26,7 @@ function lsStreamClass() {
}
this.switchEventType = function (iType) {
new Request.JSON({
url: aRouter['stream']+'switchEventType',
url: aRouter['stream']+'switchEventType/',
data: { 'type':iType, 'security_ls_key':LIVESTREET_SECURITY_KEY},
onSuccess: function(data) { // запрос выполнен уcпешно
if (!data.bStateError) {
@ -37,7 +39,7 @@ function lsStreamClass() {
sLogin = $('stream_users_complete').get('value');
if (!sLogin) return;
new Request.JSON({
url: aRouter['stream']+'subscribeByLogin',
url: aRouter['stream']+'subscribeByLogin/',
data: {'login':sLogin, 'security_ls_key':LIVESTREET_SECURITY_KEY},
onSuccess: function(data) { // запрос выполнен уcпешно
if (!data.bStateError) {
@ -68,6 +70,8 @@ function lsStreamClass() {
liElement.inject($('stream_block_users_list'));
msgNoticeBox.alert(data.sMsgTitle,data.sMsg);
}
} else {
msgErrorBox.alert(data.sMsgTitle,data.sMsg);
}
}
}).send();
@ -81,7 +85,7 @@ function lsStreamClass() {
$('stream_get_more').addClass('stream_loading');
this.isBusy = true;
new Request.JSON({
url: aRouter['stream']+'get_more',
url: aRouter['stream']+'get_more/',
data: {'last_id':lastId, 'security_ls_key':LIVESTREET_SECURITY_KEY},
onSuccess: function(data) { // запрос выполнен уcпешно
if (!data.bStateErro && data.events_count) {

View file

@ -2,18 +2,20 @@ function lsUserfeedClass() {
this.isBusy = false;
this.subscribe = function (sType, iId) {
new Request.JSON({
url: aRouter['feed']+'subscribe',
url: aRouter['feed']+'subscribe/',
data: {'type':sType, 'id':iId, 'security_ls_key':LIVESTREET_SECURITY_KEY},
onSuccess: function(data) { // запрос выполнен уcпешно
if (!data.bStateError) {
msgNoticeBox.alert(data.sMsgTitle,data.sMsg);
} else {
msgErrorBox.alert(data.sMsgTitle,data.sMsg);
}
}
}).send();
}
this.unsubscribe = function (sType, iId) {
new Request.JSON({
url: aRouter['feed']+'unsubscribe',
url: aRouter['feed']+'unsubscribe/',
data: {'type':sType, 'id':iId, 'security_ls_key':LIVESTREET_SECURITY_KEY},
onSuccess: function(data) { // запрос выполнен уcпешно
if (!data.bStateError) {
@ -26,7 +28,7 @@ function lsUserfeedClass() {
sLogin = $('userfeed_users_complete').get('value');
if (!sLogin) return;
new Request.JSON({
url: aRouter['feed']+'subscribeByLogin',
url: aRouter['feed']+'subscribeByLogin/',
data: {'login':sLogin, 'security_ls_key':LIVESTREET_SECURITY_KEY},
onSuccess: function(data) { // запрос выполнен уcпешно
$('userfeed_no_subscribed_users').dispose();
@ -57,6 +59,8 @@ function lsUserfeedClass() {
liElement.inject($('userfeed_block_users_list'));
msgNoticeBox.alert(data.sMsgTitle,data.sMsg);
}
} else {
msgErrorBox.alert(data.sMsgTitle,data.sMsg);
}
}
}).send();
@ -70,7 +74,7 @@ function lsUserfeedClass() {
$('userfeed_get_more').addClass('userfeed_loading');
this.isBusy = true;
new Request.JSON({
url: aRouter['feed']+'get_more',
url: aRouter['feed']+'get_more/',
data: {'last_id':lastId, 'security_ls_key':LIVESTREET_SECURITY_KEY},
onSuccess: function(data) { // запрос выполнен уcпешно
if (!data.bStateError && data.topics_count) {

View file

@ -9,6 +9,7 @@ $config['head']['default']['js'] = array(
"___path.root.engine_lib___/external/MooTools_1.2/plugs/Autocompleter/Autocompleter.Request.js",
"___path.root.engine_lib___/external/MooTools_1.2/plugs/vlaCal-v2.1/jslib/vlaCal-v2.1.js",
"___path.root.engine_lib___/external/MooTools_1.2/plugs/iFrameFormRequest/iFrameFormRequest.js",
"___path.static.skin___/js/ls.lang.ru.js",
"___path.static.skin___/js/vote.js",
"___path.static.skin___/js/favourites.js",
"___path.static.skin___/js/questions.js",

View file

@ -0,0 +1,118 @@
{assign var="oBlog" value=$oTopic->getBlog()}
{assign var="oUser" value=$oTopic->getUser()}
{assign var="oVote" value=$oTopic->getVote()}
<script type="text/javascript" src="{cfg name='path.root.engine_lib'}/external/milkbox-3.0.1/js/milkbox.js"></script>
<link rel='stylesheet' type='text/css' href="{cfg name='path.root.engine_lib'}/external/milkbox-3.0.1/css/milkbox.css" />
<div class="topic photo">
<div class="favorite {if $oUserCurrent}{if $oTopic->getIsFavourite()}active{/if}{else}fav-guest{/if}"><a href="#" onclick="lsFavourite.toggle({$oTopic->getId()},this,'topic'); return false;"></a></div>
<h1 class="title">
{if $oTopic->getPublish()==0}
<img src="{cfg name='path.static.skin'}/images/topic_unpublish.gif" border="0" title="{$aLang.topic_unpublish}" width="16" height="16" alt="{$aLang.topic_unpublish}">
{/if}
{if $bTopicList}
<a href="{$oTopic->getUrl()}">{$oTopic->getTitle()|escape:'html'}</a>
{else}
{$oTopic->getTitle()|escape:'html'}
{/if}
</h1>
<ul class="action">
<li><a href="{$oBlog->getUrlFull()}">{$oBlog->getTitle()|escape:'html'}</a>&nbsp;&nbsp;</li>
{if $oUserCurrent and ($oUserCurrent->getId()==$oTopic->getUserId() or $oUserCurrent->isAdministrator() or $oBlog->getUserIsAdministrator() or $oBlog->getUserIsModerator() or $oBlog->getOwnerId()==$oUserCurrent->getId())}
<li class="edit"><a href="{cfg name='path.root.web'}/{$oTopic->getType()}/edit/{$oTopic->getId()}/" title="{$aLang.topic_edit}">{$aLang.topic_edit}</a></li>
{/if}
{if $oUserCurrent and ($oUserCurrent->isAdministrator() or $oBlog->getUserIsAdministrator() or $oBlog->getOwnerId()==$oUserCurrent->getId())}
<li class="delete"><a href="{router page='topic'}delete/{$oTopic->getId()}/?security_ls_key={$LIVESTREET_SECURITY_KEY}" title="{$aLang.topic_delete}" onclick="return confirm('{$aLang.topic_delete_confirm}');">{$aLang.topic_delete}</a></li>
{/if}
</ul>
{assign var=iPhotosCount value=$oTopic->getPhotosCount()}
<!-- Topic Photo Preview -->
<div class="topic-photo-preview" style="width: 500px">
{assign var=oMainPhoto value=$oTopic->getMainPhoto()}
<div class="topic-photo-count">{$iPhotosCount} {$aLang.topic_photoset_photos}</div>
<div class="topic-photo-desc">{$oTopic->getMainPhotoDescription()}</div>
<img src="{$oMainPhoto->getWebPath(500)}" alt="image" />
</div>
<!-- /Topic Photo Preview -->
<div class="content">
{if $bTopicList}
{$oTopic->getTextShort()}
<!-- Cut link -->
<br /><br /><a href="{$oTopic->getUrl()}">{$aLang.topic_photoset_show_all|ls_lang:"COUNT%%`$iPhotosCount`"} &rarr;</a>
<!-- /Cut link -->
{if $oTopic->getTextShort()!=$oTopic->getText()}
<br><br>( <a href="{$oTopic->getUrl()}#cut" title="{$aLang.topic_read_more}">
{if $oTopic->getCutText()}
{$oTopic->getCutText()}
{else}
{$aLang.topic_read_more}
{/if}
</a> )
{/if}
{else}
{$oTopic->getText()}
{/if}
</div>
<!-- Topic Photo Image List -->
{if !$bTopicList}
<div class="topic-photo-images">
<h2>{$iPhotosCount} {$aLang.topic_photoset_count_images}</h2>
<ul id="topic-photo-images" >
{assign var=aPhotos value=$oTopic->getPhotos(0, $oConfig->get('module.topic.photoset.per_page'))}
{if count($aPhotos)}
{assign var=iPhotoNumber value=1}
{foreach from=$aPhotos item=oPhoto}
<li><div class="image-number">{$iPhotoNumber}</div><a class="photoset-image" href="{$oPhoto->getWebPath(1000)}" rel="milkbox[photoset]" title="{$oPhoto->getDescription()}"><img src="{$oPhoto->getWebPath('50crop')}" alt="{$oPhoto->getDescription()}" /></a></li>
{assign var=iPhotoNumber value=$iPhotoNumber+1}
{assign var=iLastPhotoId value=$oPhoto->getId()}
{/foreach}
{/if}
</ul>
<input type="hidden" id="photo_number" value="{$iPhotoNumber}" />
<input type="hidden" id="last_photo_id" value="{$iLastPhotoId}" />
<a href="javascript:getMorePhotos({$oTopic->getId()})" id="topic-photo-more" class="topic-photo-more">{$aLang.topic_photoset_show_more} &darr;</a>
</div>
{/if}
<!-- /Topic Photo Image List -->
<ul class="tags">
{foreach from=$oTopic->getTagsArray() item=sTag name=tags_list}
<li><a href="{router page='tag'}{$sTag|escape:'url'}/">{$sTag|escape:'html'}</a>{if !$smarty.foreach.tags_list.last}, {/if}</li>
{/foreach}
</ul>
<ul class="voting {if $oVote || ($oUserCurrent && $oTopic->getUserId()==$oUserCurrent->getId())|| strtotime($oTopic->getDateAdd())<$smarty.now-$oConfig->GetValue('acl.vote.topic.limit_time')}{if $oTopic->getRating()>0}positive{elseif $oTopic->getRating()<0}negative{/if}{/if} {if !$oUserCurrent || $oTopic->getUserId()==$oUserCurrent->getId() || strtotime($oTopic->getDateAdd())<$smarty.now-$oConfig->GetValue('acl.vote.topic.limit_time')}guest{/if} {if $oVote} voted {if $oVote->getDirection()>0}plus{elseif $oVote->getDirection()<0}minus{/if}{/if}">
<li class="plus"><a href="#" onclick="lsVote.vote({$oTopic->getId()},this,1,'topic'); return false;"></a></li>
<li class="total" title="{$aLang.topic_vote_count}: {$oTopic->getCountVote()}">{if $oVote || ($oUserCurrent && $oTopic->getUserId()==$oUserCurrent->getId()) || strtotime($oTopic->getDateAdd())<$smarty.now-$oConfig->GetValue('acl.vote.topic.limit_time')} {if $oTopic->getRating()>0}+{/if}{$oTopic->getRating()} {else} <a href="#" onclick="lsVote.vote({$oTopic->getId()},this,0,'topic'); return false;">&mdash;</a> {/if}</li>
<li class="minus"><a href="#" onclick="lsVote.vote({$oTopic->getId()},this,-1,'topic'); return false;"></a></li>
<li class="date">{date_format date=$oTopic->getDateAdd()}</li>
<li class="author"><a href="{$oUser->getUserWebPath()}">{$oUser->getLogin()}</a></li>
{if $bTopicList}
<li class="comments-total">
{if $oTopic->getCountComment()>0}
<a href="{$oTopic->getUrl()}#comments" title="{$aLang.topic_comment_read}"><span class="red">{$oTopic->getCountComment()}</span>{if $oTopic->getCountCommentNew()}<span class="green">+{$oTopic->getCountCommentNew()}</span>{/if}</a>
{else}
<a href="{$oTopic->getUrl()}#comments" title="{$aLang.topic_comment_add}"><span class="red">{$aLang.topic_comment_add}</span></a>
{/if}
</li>
{/if}
{hook run='topic_show_info' topic=$oTopic}
</ul>
{hook run='topic_show_end' topic=$oTopic}
</div>

View file

@ -0,0 +1,256 @@
{include file='header.tpl' menu='topic_action' showWhiteBack=true}
{literal}
<script language="JavaScript" type="text/javascript">
document.addEvent('domready', function() {
new Autocompleter.Request.LS.JSON($('topic_tags'), aRouter['ajax']+'autocompleter/tag/?security_ls_key='+LIVESTREET_SECURITY_KEY, {
'indicatorClass': 'autocompleter-loading', // class added to the input during request
'minLength': 2, // We need at least 1 character
'selectMode': 'pick', // Instant completion
'multiple': true // Tag support, by default comma separated
});
});
</script>
{/literal}
{if $oConfig->GetValue('view.tinymce')}
<script type="text/javascript" src="{cfg name='path.root.engine_lib'}/external/tinymce/tiny_mce.js"></script>
<script type="text/javascript">
{literal}
tinyMCE.init({
mode : "specific_textareas",
editor_selector : "mceEditor",
theme : "advanced",
theme_advanced_toolbar_location : "top",
theme_advanced_toolbar_align : "left",
theme_advanced_buttons1 : "lshselect,bold,italic,underline,strikethrough,|,bullist,numlist,|,undo,redo,|,lslink,unlink,lsvideo,lsimage,pagebreak,code",
theme_advanced_buttons2 : "",
theme_advanced_buttons3 : "",
theme_advanced_statusbar_location : "bottom",
theme_advanced_resizing : true,
theme_advanced_resize_horizontal : 0,
theme_advanced_resizing_use_cookie : 0,
theme_advanced_path : false,
object_resizing : true,
force_br_newlines : true,
forced_root_block : '', // Needed for 3.x
force_p_newlines : false,
plugins : "lseditor,safari,inlinepopups,media,pagebreak",
inline_styles:false,
formats : {
underline : {inline : 'u', exact : true},
strikethrough : {inline : 's', exact : true}
},
convert_urls : false,
extended_valid_elements : "embed[src|type|allowscriptaccess|allowfullscreen|width|height]",
pagebreak_separator :"<cut>",
media_strict : false,
language : TINYMCE_LANG
});
{/literal}
</script>
{else}
{include file='window_load_img.tpl' sToLoad='topic_text'}
{/if}
<script type="text/javascript" src="{cfg name='path.root.engine_lib'}/external/swfupload/swfupload.swfobject.js"></script>
<script type="text/javascript" src="{cfg name='path.root.engine_lib'}/external/swfupload/swfupload.js"></script>
<script type="text/javascript" src="{cfg name='path.root.engine_lib'}/external/swfupload/swfupload.handlers.js"></script>
<script type="text/javascript">
{literal}
if (Browser.Plugins.Flash.version) {
{/literal}
var path_root_engine_lib = '{cfg name='path.root.engine_lib'}';
var topic_id = '{$_aRequest.topic_id}';
var SSID='{$_sPhpSessionId}'
{literal}
var target_tmp = (Cookie.read('ls_photoset_target_tmp')) ? Cookie.read('ls_photoset_target_tmp') : 0;
document.addEvent('domready', function() {
swfu = new SWFUpload({
// Backend Settings
upload_url: aRouter['photoset']+"upload",
post_params: {'ls_photoset_target_tmp':target_tmp,'topic_id':topic_id, 'SSID':SSID, 'security_ls_key': LIVESTREET_SECURITY_KEY},
// File Upload Settings
file_types : "*.jpg; *.JPG;*.png;*.gif",
file_types_description : "Images",
file_upload_limit : "0",
// Event Handler Settings - these functions as defined in Handlers.js
// The handlers are not part of SWFUpload but are part of my website and control how
// my website reacts to the SWFUpload events.
file_queue_error_handler : fileQueueError,
file_dialog_complete_handler : fileDialogComplete,
upload_progress_handler : uploadProgress,
upload_error_handler : uploadError,
upload_success_handler : uploadSuccess,
upload_complete_handler : uploadComplete,
// Button Settings
button_placeholder_id : "topic-photo-upload-input",
button_width: 122,
button_height: 30,
button_text : '<span class="button">Загрузить фото</span>',
button_text_style : '.button { font-family: Helvetica, Arial, sans-serif; font-size: 14pt; } .buttonSmall { font-size: 10pt; }',
button_window_mode: SWFUpload.WINDOW_MODE.TRANSPARENT,
button_text_left_padding: 6,
button_text_top_padding: 3,
button_cursor: SWFUpload.CURSOR.HAND,
// Flash Settings
flash_url : path_root_engine_lib+'/external/swfupload/swfupload.swf',
custom_settings : {
upload_target : "notice_wrap"
},
// Debug Settings
debug: true
});
});
}
{/literal}
</script>
<div class="topic" style="display: none;">
<div class="content" id="text_preview"></div>
</div>
<div class="profile-user">
{if $sEvent=='add'}
<h1>{$aLang.topic_photoset_create}</h1>
{else}
<h1>{$aLang.topic_photoset_edit}</h1>
{/if}
<form id="photoset-upload-form" method="POST" enctype="multipart/form-data">
<p id="topic-photo-upload-input" class="topic-photo-upload-input">
<label for="">{$aLang.topic_photoset_choose_image}:</label><br />
<input type="file" id="photoset-upload-file" name="Filedata" />
<a href="javascript:photosetUploadPhoto()" >upload</a>
<input type="hidden" name="is_iframe" value="true" />
<input type="hidden" name="topic_id" value="{$_aRequest.topic_id}" />
</p>
</form>
<form action="" method="POST" enctype="multipart/form-data">
{hook run='form_add_topic_topic_begin'}
<input type="hidden" name="security_ls_key" value="{$LIVESTREET_SECURITY_KEY}" />
<p><label for="blog_id">{$aLang.topic_create_blog}</label>
<select name="blog_id" id="blog_id" onChange="ajaxBlogInfo(this.value);">
<option value="0">{$aLang.topic_create_blog_personal}</option>
{foreach from=$aBlogsAllow item=oBlog}
<option value="{$oBlog->getId()}" {if $_aRequest.blog_id==$oBlog->getId()}selected{/if}>{$oBlog->getTitle()}</option>
{/foreach}
</select></p>
<script language="JavaScript" type="text/javascript">
ajaxBlogInfo($('blog_id').value);
</script>
<p><label for="topic_title">{$aLang.topic_create_title}:</label><br />
<input type="text" id="topic_title" name="topic_title" value="{$_aRequest.topic_title}" class="w100p" /><br />
<span class="form_note">{$aLang.topic_create_title_notice}</span>
</p>
<p>{if !$oConfig->GetValue('view.tinymce')}<div class="note">{$aLang.topic_create_text_notice}</div>{/if}<label for="topic_text">{$aLang.topic_create_text}:</label>
{if !$oConfig->GetValue('view.tinymce')}
<div class="panel_form">
{hook run='form_add_topic_panel_begin'}
<select onchange="lsPanel.putTagAround('topic_text',this.value); this.selectedIndex=0; return false;">
<option value="">{$aLang.panel_title}</option>
<option value="h4">{$aLang.panel_title_h4}</option>
<option value="h5">{$aLang.panel_title_h5}</option>
<option value="h6">{$aLang.panel_title_h6}</option>
</select>
<select onchange="lsPanel.putList('topic_text',this); return false;">
<option value="">{$aLang.panel_list}</option>
<option value="ul">{$aLang.panel_list_ul}</option>
<option value="ol">{$aLang.panel_list_ol}</option>
</select>
<a href="#" onclick="lsPanel.putTagAround('topic_text','b'); return false;" class="button"><img src="{cfg name='path.static.skin'}/images/panel/bold.png" title="{$aLang.panel_b}"></a>
<a href="#" onclick="lsPanel.putTagAround('topic_text','i'); return false;" class="button"><img src="{cfg name='path.static.skin'}/images/panel/italic.png" title="{$aLang.panel_i}"></a>
<a href="#" onclick="lsPanel.putTagAround('topic_text','u'); return false;" class="button"><img src="{cfg name='path.static.skin'}/images/panel/underline.png" title="{$aLang.panel_u}"></a>
<a href="#" onclick="lsPanel.putTagAround('topic_text','s'); return false;" class="button"><img src="{cfg name='path.static.skin'}/images/panel/strikethrough.png" title="{$aLang.panel_s}"></a>
&nbsp;
<a href="#" onclick="lsPanel.putTagUrl('topic_text','{$aLang.panel_url_promt}'); return false;" class="button"><img src="{cfg name='path.static.skin'}/images/panel/link.png" title="{$aLang.panel_url}"></a>
<a href="#" onclick="lsPanel.putQuote('topic_text'); return false;" class="button"><img src="{cfg name='path.static.skin'}/images/panel/quote.png" title="{$aLang.panel_quote}"></a>
<a href="#" onclick="lsPanel.putTagAround('topic_text','code'); return false;" class="button"><img src="{cfg name='path.static.skin'}/images/panel/code.png" title="{$aLang.panel_code}"></a>
<a href="#" onclick="lsPanel.putTagAround('topic_text','video'); return false;" class="button"><img src="{cfg name='path.static.skin'}/images/panel/video.png" title="{$aLang.panel_video}"></a>
<a href="#" onclick="showImgUploadForm(); return false;" class="button"><img src="{cfg name='path.static.skin'}/images/panel/img.png" title="{$aLang.panel_image}"></a>
<a href="#" onclick="lsPanel.putText('topic_text','<cut>'); return false;" class="button"><img src="{cfg name='path.static.skin'}/images/panel/cut.png" title="{$aLang.panel_cut}"></a>
{hook run='form_add_topic_panel_end'}
</div>
{/if}
<textarea name="topic_text" class="mceEditor" id="topic_text" rows="20">{$_aRequest.topic_text}</textarea></p>
<!-- Topic Photo Add -->
<div class="topic-photo-upload">
<h2>{$aLang.topic_photoset_upload_title}</h2>
<div class="topic-photo-upload-rules">
{$aLang.topic_photoset_upload_rules|ls_lang:"SIZE%%`$oConfig->get('module.topic.photoset.photo_max_size')`":"COUNT%%`$oConfig->get('module.topic.photoset.count_photos_max')`"}
</div>
<a href="javascript:photosetShowUploadForm()">Загрузить фото</a>
<input type="hidden" name="topic_main_photo" id="topic_main_photo" />
<ul id="swfu_images">
{if count($aPhotos)}
{foreach from=$aPhotos item=oPhoto}
{if $_aRequest.topic_main_photo && $_aRequest.topic_main_photo == $oPhoto->getId()}
{assign var=bIsMainPhoto value=true}
{/if}
<li id="photo_{$oPhoto->getId()}" {if $bIsMainPhoto}class="marked-as-preview"{/if}>
<img src="{$oPhoto->getWebPath(100)}" alt="image" />
<textarea onBlur="topicImageSetDescription({$oPhoto->getId()}, this.value)">{$oPhoto->getDescription()}</textarea><br />
<a href="javascript:deleteTopicImage({$oPhoto->getId()})" class="image-delete">Удалить</a>
<span class="photo-preview-state">
{if $bIsMainPhoto}
{$aLang.topic_photoset_is_preview}
{else}
<a href="javascript:setTopicMainPhoto({$oPhoto->getId()})" class="mark-as-preview">{$aLang.topic_photoset_mark_as_preview}</a>
{/if}
</span>
</li>
{assign var=bIsMainPhoto value=false}
{/foreach}
{/if}
</ul>
<div id="notice_wrap"></div>
</div>
<textarea name="topic_main_photo_description" id="topic_main_photo_description" rows="20">{$_aRequest.topic_main_photo_description}</textarea></p>
<!-- /Topic Photo Add -->
<p><label for="topic_tags">{$aLang.topic_create_tags}:</label><br />
<input type="text" id="topic_tags" name="topic_tags" value="{$_aRequest.topic_tags}" class="w100p" /><br />
<span class="form_note">{$aLang.topic_create_tags_notice}</span></p>
<p><label for="topic_forbid_comment"><input type="checkbox" id="topic_forbid_comment" name="topic_forbid_comment" class="checkbox" value="1" {if $_aRequest.topic_forbid_comment==1}checked{/if}/>
&mdash; {$aLang.topic_create_forbid_comment}</label><br />
<span class="form_note">{$aLang.topic_create_forbid_comment_notice}</span></p>
{if $oUserCurrent->isAdministrator()}
<p><label for="topic_publish_index"><input type="checkbox" id="topic_publish_index" name="topic_publish_index" class="checkbox" value="1" {if $_aRequest.topic_publish_index==1}checked{/if}/>
&mdash; {$aLang.topic_create_publish_index}</label><br />
<span class="form_note">{$aLang.topic_create_publish_index_notice}</span></p>
{/if}
{hook run='form_add_topic_topic_end'}
<p class="buttons">
<input type="submit" name="submit_topic_publish" value="{$aLang.topic_create_submit_publish}" class="right" />
<input type="submit" name="submit_preview" value="{$aLang.topic_create_submit_preview}" onclick="$('text_preview').getParent('div').setStyle('display','block'); ajaxTextPreview('topic_text',false); return false;" />&nbsp;
<input type="submit" name="submit_topic_save" value="{$aLang.topic_create_submit_save}" />
</p>
</form>
</div>
{include file='footer.tpl'}

View file

@ -896,19 +896,150 @@ table.admin_page td { /* IE: */ border-left: expression(previousSibling == nul
.userfield-form p { margin-bottom: 10px; }
.userfield-form .input-text { width: 262px; border: 1px solid #ccc; margin: 0; padding: 3px; font-family: Arial, sans-serif; font-size: 12px; }
/* Topic Photo */
.topic.photo { }
.topic.photo .topic-photo-preview { position: relative; margin-bottom: 15px; cursor: pointer; }
.topic.photo .topic-photo-preview img { vertical-align: top; }
.topic.photo .topic-photo-preview .topic-photo-count { position: absolute; top: 5px; right: 5px; background: #000; color: #6bd24b; padding: 4px 7px; background: rgba(0,0,0,.6); }
.topic.photo .topic-photo-preview .topic-photo-desc { width: 96%; padding: 7px 2%; position: absolute; bottom: 0; left: 0; background: #000; color: #6bd24b; color: #fff; line-height: 16px; background: rgba(0,0,0,.7); }
.topic.photo .topic-photo-images { padding-top: 10px; }
.topic.photo .topic-photo-images h2 { border-bottom: 1px solid #ddd; padding-bottom: 4px; margin-bottom: 15px; }
.topic.photo .topic-photo-images ul { overflow: hidden; zoom: 1; }
.topic.photo .topic-photo-images ul li { float: left; margin: 0 10px 10px 0; position: relative; }
.topic.photo .topic-photo-images ul li .image-number { display: none; position: absolute; top: 5px; right: 5px; background: #000; color: #6bd24b; padding: 1px 6px; font-size: 11px; background: rgba(0,0,0,.6); }
.topic.photo .topic-photo-images ul li:hover .image-number { display: block; }
.topic.photo .topic-photo-images ul li img { vertical-align: top; }
.topic.photo .topic-photo-images .topic-photo-more { display: block; border-top: 1px solid #dbe6f0; text-align: center; padding: 10px 0; margin-bottom: 15px; text-decoration: none; background: #f3f7fa; color: #7b90a5; }
.topic.photo .topic-photo-images .topic-photo-more:hover { background: #eaf2f8; }
.topic-photo-upload { background: #fafafa; padding: 15px 15px 15px; margin-bottom: 20px; }
.topic-photo-upload h2 { margin-bottom: 15px; }
.topic-photo-upload ul { overflow: hidden; zoom: 1; }
.topic-photo-upload ul li { min-height: 100px; _height: 100px; margin-bottom: 10px; padding-left: 110px; position: relative; }
.topic-photo-upload ul li img { position: absolute; top: 0; left: 0; }
.topic-photo-upload ul li label { color: #aaa; }
.topic-photo-upload ul li textarea { border: 1px solid #ddd; width: 350px; height: 60px; padding: 3px; font-size: 12px; font-family: Arial, sans-serif; color: #333; }
.topic-photo-upload ul li .image-delete { text-decoration: none; margin-right: 15px; }
.topic-photo-upload ul li .image-delete:hover { color: #f00; }
.topic-photo-upload ul li.marked-as-preview .mark-as-preview { display: inline; color: #43c70f; font-weight: bold; }
.topic-photo-upload ul li .mark-as-preview { display: none; text-decoration: none; }
.topic-photo-upload ul li:hover .mark-as-preview { display: inline; }
.topic-photo-upload .topic-photo-upload-rules { color: #888; margin-bottom: 15px; }
.topic-photo-upload .topic-photo-upload-input { margin-bottom: 20px; }
.topic-photo-upload .topic-photo-upload-input input { margin-top: 3px; }
#photoset-upload-form {
width: 270px;
padding: 15px;
margin-left: -120px;
position: absolute;
left: -300px;
top:50%;
background-color: #fff;
border: 1px solid #ccc;
-moz-box-shadow: 0 0 10px #ddd;
-webkit-box-shadow: 0 0 10px #ddd;
box-shadow: 0 0 10px #ddd;
}
#photoset-upload-form p { margin-bottom: 10px; }
#photoset-upload-form .input-text { width: 262px; border: 1px solid #ccc; margin: 0; padding: 3px; font-family: Arial, sans-serif; font-size: 12px; }
.progressWrapper {
width: 357px;
overflow: hidden;
}
.progressContainer {
margin: 5px;
padding: 4px;
border: solid 1px #E8E8E8;
background-color: #F7F7F7;
overflow: hidden;
}
/* Message */
.message {
margin: 1em 0;
padding: 10px 20px;
border: solid 1px #FFDD99;
background-color: #FFFFCC;
overflow: hidden;
}
/* Error */
.red {
border: solid 1px #B50000;
background-color: #FFEBEB;
}
/* Current */
.green {
border: solid 1px #DDF0DD;
background-color: #EBFFEB;
}
/* Complete */
.blue {
border: solid 1px #CEE2F2;
background-color: #F0F5FF;
}
.progressName {
font-size: 8pt;
font-weight: 700;
color: #555;
width: 323px;
height: 14px;
text-align: left;
white-space: nowrap;
overflow: hidden;
}
.progressBarInProgress,
.progressBarComplete,
.progressBarError {
font-size: 0;
width: 0%;
height: 2px;
background-color: blue;
margin-top: 2px;
}
.progressBarComplete {
width: 100%;
background-color: green;
visibility: hidden;
}
.progressBarError {
width: 100%;
background-color: red;
visibility: hidden;
}
.progressBarStatus {
margin-top: 2px;
width: 337px;
font-size: 7pt;
font-family: Arial;
text-align: left;
white-space: nowrap;
}
a.progressCancel {
font-size: 0;
display: block;
height: 14px;
width: 14px;
background-image: url(../images/cancelbutton.gif);
background-repeat: no-repeat;
background-position: -14px 0px;
float: right;
}
a.progressCancel:hover {
background-position: 0px 0px;
}

View file

@ -0,0 +1,4 @@
var lsLang = new Array();
lsLang['mark_as_preview'] = 'Отметить как превью';
lsLang['preview'] = 'Превью';
lsLang['delete'] = 'Удалить';

View file

@ -128,4 +128,121 @@ function ajaxUploadImg(form,sToLoad) {
}
});
iFrame.send();
}
function addTopicImage(response)
{
if (!response.bStateError) {
template = '<a href="#"><img src="'+response.file+'" alt="image" /></a>'
+'<textarea onBlur="topicImageSetDescription('+response.id+', this.value)"></textarea><br />'
+'<a href="javascript:deleteTopicImage('+response.id+')" class="image-delete">Удалить</a>'
+'<span class="photo-preview-state"><a href="javascript:setTopicMainPhoto('+response.id+')" class="mark-as-preview">Отметить как превью</a></span>';
liElement= new Element('li', {'id':'photo_'+response.id,'html':template})
liElement.inject('swfu_images');
msgNoticeBox.alert(response.sMsgTitle,response.sMsg);
} else {
msgErrorBox.alert(response.sMsgTitle,response.sMsg);
}
photosetCloseForm();
}
function deleteTopicImage(id)
{
new Request.JSON({
url: aRouter['photoset']+'deleteimage',
data: {'id':id, 'security_ls_key': LIVESTREET_SECURITY_KEY },
onSuccess: function(response){
if (!response.bStateError) {
$('photo_'+id).dispose();
msgNoticeBox.alert(response.sMsgTitle,response.sMsg);
} else {
msgErrorBox.alert('Error','Please try again later');
}
}
}).send();
}
function setTopicMainPhoto(id)
{
$('topic_main_photo').set('value', id);
$$('..marked-as-preview').each(function (el) {
el.removeClass('marked-as-preview');
el.getElement('span').set('html','<a href="javascript:setTopicMainPhoto('+el.get('id').slice(el.get('id').lastIndexOf('_')+1)+')" class="mark-as-preview">Отметить как превью</a>')
});
$('photo_'+id).addClass('marked-as-preview');
$('photo_'+id).getElement('span').set('html', 'Превью');
}
function topicImageSetDescription(id, text)
{
new Request.JSON({
url: aRouter['photoset']+'setimagedescription',
data: {'id':id, 'text':text, 'security_ls_key': LIVESTREET_SECURITY_KEY },
onSuccess: function(result){
if (!bStateError) {
} else {
msgErrorBox.alert('Error','Please try again later');
}
}
}).send();
}
function getMorePhotos(topic_id)
{
var last_id = $('last_photo_id').get('value');
new Request.JSON({
url: aRouter['photoset']+'getmore',
data: {'topic_id':topic_id, 'last_id':last_id, 'security_ls_key': LIVESTREET_SECURITY_KEY },
onSuccess: function(result){
if (!result.bStateError) {
if (result.photos) {
var photoNumber = $('photo_number').get('value');
result.photos.each(function(photo) {
var image = '<div class="image-number">'+(photoNumber++)+'</div><a class="photoset-image" href="'+photo.path+'" rel="milkbox[photoset]" title="'+photo.description+'"><img src="'+photo.path_thumb+'" alt="'+photo.description+'" /></a>';
var liElement = new Element('li', {'html':image});
liElement.inject($('topic-photo-images'));
$('photo_number').set('value', photoNumber);
$('last_photo_id').set('value', photo.id);
$$('.photoset-image').each(function(el) {console.log(el);el.removeEvents('click')});
milkbox = new Milkbox();
});
} else {
$('topic-photo-more').dispose();
}
} else {
msgErrorBox.alert('Error','Please try again later');
}
}
}).send();
}
function photosetUploadPhoto()
{
var iFrame = new iFrameFormRequest($('photoset-upload-form').getProperty('id'),{
url: aRouter['photoset']+'upload/',
dataType: 'json',
params: {security_ls_key: LIVESTREET_SECURITY_KEY},
onComplete: function(response){
if (response.bStateError) {
msgErrorBox.alert(response.sMsgTitle,response.sMsg);
} else {
addTopicImage(response);
}
}
});
iFrame.send();
photosetCloseForm();
}
function photosetCloseForm() {
if ($('photoset-upload-file')) {
$('photoset-upload-file').set('value', '');
}
$('photoset-upload-form').setStyle('left', '-300px');
}
function photosetShowUploadForm()
{
$('photoset-upload-form').setStyle('left', '50%');
}

View file

@ -2,7 +2,7 @@ function lsStreamClass() {
this.isBusy = false;
this.subscribe = function (iTargetUserId) {
new Request.JSON({
url: aRouter['stream']+'subscribe',
url: aRouter['stream']+'subscribe/',
data: {'id':iTargetUserId, 'security_ls_key':LIVESTREET_SECURITY_KEY},
onSuccess: function(data) { // запрос выполнен уcпешно
if (!data.bStateError) {
@ -13,7 +13,7 @@ function lsStreamClass() {
}
this.unsubscribe = function (iId) {
new Request.JSON({
url: aRouter['stream']+'unsubscribe',
url: aRouter['stream']+'unsubscribe/',
data: { 'id':iId, 'security_ls_key':LIVESTREET_SECURITY_KEY},
onSuccess: function(data) { // запрос выполнен уcпешно
if (!data.bStateError) {
@ -24,7 +24,7 @@ function lsStreamClass() {
}
this.switchEventType = function (iType) {
new Request.JSON({
url: aRouter['stream']+'switchEventType',
url: aRouter['stream']+'switchEventType/',
data: { 'type':iType, 'security_ls_key':LIVESTREET_SECURITY_KEY},
onSuccess: function(data) { // запрос выполнен уcпешно
if (!data.bStateError) {
@ -37,7 +37,7 @@ function lsStreamClass() {
sLogin = $('stream_users_complete').get('value');
if (!sLogin) return;
new Request.JSON({
url: aRouter['stream']+'subscribeByLogin',
url: aRouter['stream']+'subscribeByLogin/',
data: {'login':sLogin, 'security_ls_key':LIVESTREET_SECURITY_KEY},
onSuccess: function(data) { // запрос выполнен уcпешно
if (!data.bStateError) {
@ -81,7 +81,7 @@ function lsStreamClass() {
$('stream_get_more').addClass('stream_loading');
this.isBusy = true;
new Request.JSON({
url: aRouter['stream']+'get_more',
url: aRouter['stream']+'get_more/',
data: {'last_id':lastId, 'security_ls_key':LIVESTREET_SECURITY_KEY},
onSuccess: function(data) { // запрос выполнен уcпешно
if (!data.bStateErro && data.events_count) {

View file

@ -2,18 +2,20 @@ function lsUserfeedClass() {
this.isBusy = false;
this.subscribe = function (sType, iId) {
new Request.JSON({
url: aRouter['feed']+'subscribe',
url: aRouter['feed']+'subscribe/',
data: {'type':sType, 'id':iId, 'security_ls_key':LIVESTREET_SECURITY_KEY},
onSuccess: function(data) { // запрос выполнен уcпешно
if (!data.bStateError) {
msgNoticeBox.alert(data.sMsgTitle,data.sMsg);
} else {
msgErrorBox.alert(data.sMsgTitle,data.sMsg);
}
}
}).send();
}
this.unsubscribe = function (sType, iId) {
new Request.JSON({
url: aRouter['feed']+'unsubscribe',
url: aRouter['feed']+'unsubscribe/',
data: {'type':sType, 'id':iId, 'security_ls_key':LIVESTREET_SECURITY_KEY},
onSuccess: function(data) { // запрос выполнен уcпешно
if (!data.bStateError) {
@ -26,11 +28,11 @@ function lsUserfeedClass() {
sLogin = $('userfeed_users_complete').get('value');
if (!sLogin) return;
new Request.JSON({
url: aRouter['feed']+'subscribeByLogin',
url: aRouter['feed']+'subscribeByLogin/',
data: {'login':sLogin, 'security_ls_key':LIVESTREET_SECURITY_KEY},
onSuccess: function(data) { // запрос выполнен уcпешно
$('userfeed_no_subscribed_users').dispose();
if (!data.bStateError) {
$('userfeed_no_subscribed_users').dispose();
checkbox = $('usf_u_'+data.uid);
if (checkbox) {
if ($(checkbox).get('checked')) {
@ -57,6 +59,8 @@ function lsUserfeedClass() {
liElement.inject($('userfeed_block_users_list'));
msgNoticeBox.alert(data.sMsgTitle,data.sMsg);
}
} else {
msgErrorBox.alert(data.sMsgTitle,data.sMsg);
}
}
}).send();
@ -70,7 +74,7 @@ function lsUserfeedClass() {
$('userfeed_get_more').addClass('userfeed_loading');
this.isBusy = true;
new Request.JSON({
url: aRouter['feed']+'get_more',
url: aRouter['feed']+'get_more/',
data: {'last_id':lastId, 'security_ls_key':LIVESTREET_SECURITY_KEY},
onSuccess: function(data) { // запрос выполнен уcпешно
if (!data.bStateError && data.topics_count) {

View file

@ -0,0 +1,118 @@
{assign var="oBlog" value=$oTopic->getBlog()}
{assign var="oUser" value=$oTopic->getUser()}
{assign var="oVote" value=$oTopic->getVote()}
<script type="text/javascript" src="{cfg name='path.root.engine_lib'}/external/milkbox-3.0.1/js/milkbox.js"></script>
<link rel='stylesheet' type='text/css' href="{cfg name='path.root.engine_lib'}/external/milkbox-3.0.1/css/milkbox.css" />
<div class="topic photo">
<div class="favorite {if $oUserCurrent}{if $oTopic->getIsFavourite()}active{/if}{else}fav-guest{/if}"><a href="#" onclick="lsFavourite.toggle({$oTopic->getId()},this,'topic'); return false;"></a></div>
<h1 class="title">
{if $oTopic->getPublish()==0}
<img src="{cfg name='path.static.skin'}/images/topic_unpublish.gif" border="0" title="{$aLang.topic_unpublish}" width="16" height="16" alt="{$aLang.topic_unpublish}">
{/if}
{if $bTopicList}
<a href="{$oTopic->getUrl()}">{$oTopic->getTitle()|escape:'html'}</a>
{else}
{$oTopic->getTitle()|escape:'html'}
{/if}
</h1>
<ul class="action">
<li><a href="{$oBlog->getUrlFull()}">{$oBlog->getTitle()|escape:'html'}</a>&nbsp;&nbsp;</li>
{if $oUserCurrent and ($oUserCurrent->getId()==$oTopic->getUserId() or $oUserCurrent->isAdministrator() or $oBlog->getUserIsAdministrator() or $oBlog->getUserIsModerator() or $oBlog->getOwnerId()==$oUserCurrent->getId())}
<li class="edit"><a href="{cfg name='path.root.web'}/{$oTopic->getType()}/edit/{$oTopic->getId()}/" title="{$aLang.topic_edit}">{$aLang.topic_edit}</a></li>
{/if}
{if $oUserCurrent and ($oUserCurrent->isAdministrator() or $oBlog->getUserIsAdministrator() or $oBlog->getOwnerId()==$oUserCurrent->getId())}
<li class="delete"><a href="{router page='topic'}delete/{$oTopic->getId()}/?security_ls_key={$LIVESTREET_SECURITY_KEY}" title="{$aLang.topic_delete}" onclick="return confirm('{$aLang.topic_delete_confirm}');">{$aLang.topic_delete}</a></li>
{/if}
</ul>
{assign var=iPhotosCount value=$oTopic->getPhotosCount()}
<!-- Topic Photo Preview -->
<div class="topic-photo-preview" style="width: 500px">
{assign var=oMainPhoto value=$oTopic->getMainPhoto()}
<div class="topic-photo-count">{$iPhotosCount} {$aLang.topic_photoset_photos}</div>
<div class="topic-photo-desc">{$oTopic->getMainPhotoDescription()}</div>
<img src="{$oMainPhoto->getWebPath(500)}" alt="image" />
</div>
<!-- /Topic Photo Preview -->
<div class="content">
{if $bTopicList}
{$oTopic->getTextShort()}
<!-- Cut link -->
<br /><br /><a href="{$oTopic->getUrl()}">{$aLang.topic_photoset_show_all|ls_lang:"COUNT%%`$iPhotosCount`"} &rarr;</a>
<!-- /Cut link -->
{if $oTopic->getTextShort()!=$oTopic->getText()}
<br><br>( <a href="{$oTopic->getUrl()}#cut" title="{$aLang.topic_read_more}">
{if $oTopic->getCutText()}
{$oTopic->getCutText()}
{else}
{$aLang.topic_read_more}
{/if}
</a> )
{/if}
{else}
{$oTopic->getText()}
{/if}
</div>
<!-- Topic Photo Image List -->
{if !$bTopicList}
<div class="topic-photo-images">
<h2>{$iPhotosCount} {$aLang.topic_photoset_count_images}</h2>
<ul id="topic-photo-images" >
{assign var=aPhotos value=$oTopic->getPhotos(0, $oConfig->get('module.topic.photoset.per_page'))}
{if count($aPhotos)}
{assign var=iPhotoNumber value=1}
{foreach from=$aPhotos item=oPhoto}
<li><div class="image-number">{$iPhotoNumber}</div><a class="photoset-image" href="{$oPhoto->getWebPath(1000)}" rel="milkbox[photoset]" title="{$oPhoto->getDescription()}"><img src="{$oPhoto->getWebPath('50crop')}" alt="{$oPhoto->getDescription()}" /></a></li>
{assign var=iPhotoNumber value=$iPhotoNumber+1}
{assign var=iLastPhotoId value=$oPhoto->getId()}
{/foreach}
{/if}
</ul>
<input type="hidden" id="photo_number" value="{$iPhotoNumber}" />
<input type="hidden" id="last_photo_id" value="{$iLastPhotoId}" />
<a href="javascript:getMorePhotos({$oTopic->getId()})" id="topic-photo-more" class="topic-photo-more">{$aLang.topic_photoset_show_more} &darr;</a>
</div>
{/if}
<!-- /Topic Photo Image List -->
<ul class="tags">
{foreach from=$oTopic->getTagsArray() item=sTag name=tags_list}
<li><a href="{router page='tag'}{$sTag|escape:'url'}/">{$sTag|escape:'html'}</a>{if !$smarty.foreach.tags_list.last}, {/if}</li>
{/foreach}
</ul>
<ul class="voting {if $oVote || ($oUserCurrent && $oTopic->getUserId()==$oUserCurrent->getId())|| strtotime($oTopic->getDateAdd())<$smarty.now-$oConfig->GetValue('acl.vote.topic.limit_time')}{if $oTopic->getRating()>0}positive{elseif $oTopic->getRating()<0}negative{/if}{/if} {if !$oUserCurrent || $oTopic->getUserId()==$oUserCurrent->getId() || strtotime($oTopic->getDateAdd())<$smarty.now-$oConfig->GetValue('acl.vote.topic.limit_time')}guest{/if} {if $oVote} voted {if $oVote->getDirection()>0}plus{elseif $oVote->getDirection()<0}minus{/if}{/if}">
<li class="plus"><a href="#" onclick="lsVote.vote({$oTopic->getId()},this,1,'topic'); return false;"></a></li>
<li class="total" title="{$aLang.topic_vote_count}: {$oTopic->getCountVote()}">{if $oVote || ($oUserCurrent && $oTopic->getUserId()==$oUserCurrent->getId()) || strtotime($oTopic->getDateAdd())<$smarty.now-$oConfig->GetValue('acl.vote.topic.limit_time')} {if $oTopic->getRating()>0}+{/if}{$oTopic->getRating()} {else} <a href="#" onclick="lsVote.vote({$oTopic->getId()},this,0,'topic'); return false;">&mdash;</a> {/if}</li>
<li class="minus"><a href="#" onclick="lsVote.vote({$oTopic->getId()},this,-1,'topic'); return false;"></a></li>
<li class="date">{date_format date=$oTopic->getDateAdd()}</li>
<li class="author"><a href="{$oUser->getUserWebPath()}">{$oUser->getLogin()}</a></li>
{if $bTopicList}
<li class="comments-total">
{if $oTopic->getCountComment()>0}
<a href="{$oTopic->getUrl()}#comments" title="{$aLang.topic_comment_read}"><span class="red">{$oTopic->getCountComment()}</span>{if $oTopic->getCountCommentNew()}<span class="green">+{$oTopic->getCountCommentNew()}</span>{/if}</a>
{else}
<a href="{$oTopic->getUrl()}#comments" title="{$aLang.topic_comment_add}"><span class="red">{$aLang.topic_comment_add}</span></a>
{/if}
</li>
{/if}
{hook run='topic_show_info' topic=$oTopic}
</ul>
{hook run='topic_show_end' topic=$oTopic}
</div>