# HG changeset patch # User neko259 # Date 2015-04-21 18:16:11 # Node ID 2ec94187ed35e7de84fb828844e5a452144fda31 # Parent 423cb733942209d15a04603dd920fad70c5ce238 Setting for image view mode: in post (simple) or in popup diff --git a/boards/abstracts/settingsmanager.py b/boards/abstracts/settingsmanager.py --- a/boards/abstracts/settingsmanager.py +++ b/boards/abstracts/settingsmanager.py @@ -14,6 +14,7 @@ SETTING_HIDDEN_TAGS = 'hidden_tags' SETTING_PERMISSIONS = 'permissions' SETTING_USERNAME = 'username' SETTING_LAST_NOTIFICATION_ID = 'last_notification' +SETTING_IMAGE_VIEWER = 'image_viewer' DEFAULT_THEME = 'md' @@ -44,7 +45,7 @@ class SettingsManager: else: return False - def get_setting(self, setting): + def get_setting(self, setting, default=None): pass def set_setting(self, setting, value): @@ -127,11 +128,11 @@ class SessionSettingsManager(SettingsMan SettingsManager.__init__(self) self.session = session - def get_setting(self, setting): + def get_setting(self, setting, default=None): if setting in self.session: return self.session[setting] else: - return None + return default def set_setting(self, setting, value): self.session[setting] = value diff --git a/boards/context_processors.py b/boards/context_processors.py --- a/boards/context_processors.py +++ b/boards/context_processors.py @@ -1,5 +1,5 @@ from boards.abstracts.settingsmanager import get_settings_manager, \ - SETTING_USERNAME, SETTING_LAST_NOTIFICATION_ID + SETTING_USERNAME, SETTING_LAST_NOTIFICATION_ID, SETTING_IMAGE_VIEWER from boards.models.user import Notification __author__ = 'neko259' @@ -18,7 +18,7 @@ CONTEXT_USER = 'user' CONTEXT_NEW_NOTIFICATIONS_COUNT = 'new_notifications_count' CONTEXT_USERNAME = 'username' CONTEXT_TAGS_STR = 'tags_str' - +CONTEXT_IMAGE_VIEWER = 'image_viewer' def get_notifications(context, request): @@ -54,6 +54,9 @@ def user_and_ui_processor(request): context[CONTEXT_VERSION] = settings.VERSION context[CONTEXT_SITE_NAME] = settings.SITE_NAME + context[CONTEXT_IMAGE_VIEWER] = settings_manager.get_setting( + SETTING_IMAGE_VIEWER, default=settings.DEFAULT_IMAGE_VIEWER) + get_notifications(context, request) return context diff --git a/boards/default_settings.py b/boards/default_settings.py --- a/boards/default_settings.py +++ b/boards/default_settings.py @@ -12,6 +12,7 @@ MAX_POSTS_PER_THREAD = 10 MAX_THREAD_COUNT = 5 THREADS_PER_PAGE = 3 DEFAULT_THEME = 'md' +DEFAULT_IMAGE_VIEWER = 'simple' LAST_REPLIES_COUNT = 3 # Enable archiving threads instead of deletion when the thread limit is reached diff --git a/boards/forms.py b/boards/forms.py --- a/boards/forms.py +++ b/boards/forms.py @@ -365,6 +365,7 @@ class ThreadForm(PostForm): class SettingsForm(NeboardForm): theme = forms.ChoiceField(choices=settings.THEMES, label=_('Theme')) + image_viewer = forms.ChoiceField(choices=settings.IMAGE_VIEWERS, label=_('Image view mode')) username = forms.CharField(label=_('User name'), required=False) timezone = forms.ChoiceField(choices=get_timezones(), label=_('Time zone')) diff --git a/boards/locale/ru/LC_MESSAGES/django.mo b/boards/locale/ru/LC_MESSAGES/django.mo index 57a50f9290977c5d4ac6289f21397e36bb63bbe8..7f24f7b27a59e34ca85c68c7d85ab6f78fed9ea5 GIT binary patch literal 7188 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 MGB?E}<~NV}KTjsG\n" "Language-Team: LANGUAGE \n" @@ -59,7 +59,7 @@ msgstr "Текст" msgid "Tag" msgstr "Метка" -#: forms.py:41 templates/boards/base.html:40 templates/search/search.html:7 +#: forms.py:41 templates/boards/base.html:41 templates/search/search.html:7 msgid "Search" msgstr "Поиск" @@ -129,14 +129,18 @@ msgid "Theme" msgstr "Тема" #: forms.py:368 +msgid "Image view mode" +msgstr "Режим просмотра изображений" + +#: forms.py:369 msgid "User name" msgstr "Имя пользователя" -#: forms.py:369 +#: forms.py:370 msgid "Time zone" msgstr "Часовой пояс" -#: forms.py:375 +#: forms.py:376 msgid "Inappropriate characters." msgstr "Недопустимые символы." @@ -164,41 +168,41 @@ msgstr "лицензией" msgid "Repository" msgstr "Репозиторий" -#: templates/boards/base.html:13 +#: templates/boards/base.html:14 msgid "Feed" msgstr "Лента" -#: templates/boards/base.html:30 +#: templates/boards/base.html:31 msgid "All threads" msgstr "Все темы" -#: templates/boards/base.html:36 +#: templates/boards/base.html:37 msgid "Add tags" msgstr "Добавить метки" -#: templates/boards/base.html:38 +#: templates/boards/base.html:39 msgid "Tag management" msgstr "Управление метками" -#: templates/boards/base.html:43 templates/boards/base.html.py:44 +#: templates/boards/base.html:44 templates/boards/base.html.py:45 #: templates/boards/notifications.html:8 msgid "Notifications" msgstr "Уведомления" -#: templates/boards/base.html:51 templates/boards/settings.html:9 +#: templates/boards/base.html:52 templates/boards/settings.html:9 msgid "Settings" msgstr "Настройки" -#: templates/boards/base.html:64 +#: templates/boards/base.html:65 msgid "Admin" msgstr "Администрирование" -#: templates/boards/base.html:66 +#: templates/boards/base.html:67 #, python-format msgid "Speed: %(ppd)s posts per day" msgstr "Скорость: %(ppd)s сообщений в день" -#: templates/boards/base.html:68 +#: templates/boards/base.html:69 msgid "Up" msgstr "Вверх" @@ -232,11 +236,11 @@ msgstr "Изменить тему" msgid "Replies" msgstr "Ответы" -#: templates/boards/post.html:81 templates/boards/thread.html:31 +#: templates/boards/post.html:81 templates/boards/thread.html:26 msgid "messages" msgstr "сообщений" -#: templates/boards/post.html:82 templates/boards/thread.html:32 +#: templates/boards/post.html:82 templates/boards/thread.html:27 msgid "images" msgstr "изображений" @@ -277,7 +281,7 @@ msgstr "" msgid "Text syntax" msgstr "Синтаксис текста" -#: templates/boards/posting_general.html:158 +#: templates/boards/posting_general.html:159 msgid "Pages:" msgstr "Страницы: " @@ -359,7 +363,7 @@ msgstr "Метки не найдены." msgid "All tags" msgstr "Все метки" -#: templates/boards/thread.html:33 +#: templates/boards/thread.html:28 msgid "Last update: " msgstr "Последнее обновление: " diff --git a/boards/models/image.py b/boards/models/image.py --- a/boards/models/image.py +++ b/boards/models/image.py @@ -89,17 +89,19 @@ class PostImage(models.Model, Viewable): def get_view(self): return ''\ - .format(CSS_CLASS_IMAGE, CSS_CLASS_THUMB, self.image.url, + .format(CSS_CLASS_IMAGE, CSS_CLASS_THUMB, self.image.url_200x150, str(self.hash), str(self.pre_width), - str(self.pre_height), str(self.width), str(self.height)) + str(self.pre_height), str(self.width), str(self.height), full=self.image.url) diff --git a/boards/static/css/base.css b/boards/static/css/base.css --- a/boards/static/css/base.css +++ b/boards/static/css/base.css @@ -95,3 +95,8 @@ textarea, input { #form-close-button { display: none; } + +.post-image-full { + display: none; + width: 100%; +} diff --git a/boards/static/js/image.js b/boards/static/js/image.js --- a/boards/static/js/image.js +++ b/boards/static/js/image.js @@ -23,8 +23,100 @@ for the JavaScript code in this page. */ + +var IMAGE_VIEWERS = [ + ['simple', new SimpleImageViewer()], + ['popup', new PopupImageViewer()] +]; + + +function ImageViewer() {} +ImageViewer.prototype.view = function (post) {}; + +function SimpleImageViewer() {} +SimpleImageViewer.prototype.view = function (post) { + post.find('img').toggle(); +}; + +function PopupImageViewer() {} +PopupImageViewer.prototype.view = function (post) { + var margin = 20; //..change + + var el = post; + var thumb_id = 'full' + el.find('img').attr('alt'); + + var existingPopups = $('#' + thumb_id); + if(!existingPopups.length) { + var imgElement= el.find('img'); + + var img_w = imgElement.attr('data-width'); + var img_h = imgElement.attr('data-height'); + + var win = $(window); + + var win_w = win.width(); + var win_h = win.height(); + //new image size + if (img_w > win_w) { + img_h = img_h * (win_w/img_w) - margin; + img_w = win_w - margin; + } + if (img_h > win_h) { + img_w = img_w * (win_h/img_h) - margin; + img_h = win_h - margin; + } + + var img_pv = new Image(); + var newImage = $(img_pv); + newImage.addClass('img-full') + .attr('id', thumb_id) + .attr('src', $(el).attr('href')) + .appendTo($(el)) + .css({ + 'width': img_w, + 'height': img_h, + 'left': (win_w - img_w) / 2, + 'top': ((win_h - img_h) / 2) + }) + //scaling preview + .mousewheel(function(event, delta) { + var cx = event.originalEvent.clientX, + cy = event.originalEvent.clientY, + i_w = parseFloat(newImage.width()), + i_h = parseFloat(newImage.height()), + newIW = i_w * (delta > 0 ? 1.25 : 0.8), + newIH = i_h * (delta > 0 ? 1.25 : 0.8); + + newImage.width(newIW); + newImage.height(newIH); + //set position + newImage.css({ + left: parseInt(cx - (newIW/i_w) * (cx - parseInt($(img_pv).position().left, 10)), 10), + top: parseInt(cy - (newIH/i_h) * (cy - parseInt($(img_pv).position().top, 10)), 10) + }); + + return false; + } + ) + .draggable({ + addClasses: false, + stack: '.img-full' + }); + } else { + existingPopups.remove(); + } +}; + function addImgPreview() { - var margin = 20; //..change + var viewerName = $('body').attr('data-image-viewer'); + var viewer = ImageViewer(); + for (var i = 0; i < IMAGE_VIEWERS.length; i++) { + var item = IMAGE_VIEWERS[i]; + if (item[0] === viewerName) { + viewer = item[1]; + break; + } + } //keybind $(document).on('keyup.removepic', function(e) { @@ -34,70 +126,8 @@ function addImgPreview() { }); $('body').on('click', '.thumb', function() { - var el = $(this); - var thumb_id = 'full' + el.find('img').attr('alt'); - - var existingPopups = $('#' + thumb_id); - if(!existingPopups.length) { - var imgElement= el.find('img'); - - var img_w = imgElement.attr('data-width'); - var img_h = imgElement.attr('data-height'); - - var win = $(window); - - var win_w = win.width(); - var win_h = win.height(); - //new image size - if (img_w > win_w) { - img_h = img_h * (win_w/img_w) - margin; - img_w = win_w - margin; - } - if (img_h > win_h) { - img_w = img_w * (win_h/img_h) - margin; - img_h = win_h - margin; - } + viewer.view($(this)); - var img_pv = new Image(); - var newImage = $(img_pv); - newImage.addClass('img-full') - .attr('id', thumb_id) - .attr('src', $(el).attr('href')) - .appendTo($(el)) - .css({ - 'width': img_w, - 'height': img_h, - 'left': (win_w - img_w) / 2, - 'top': ((win_h - img_h) / 2) - }) - //scaling preview - .mousewheel(function(event, delta) { - var cx = event.originalEvent.clientX, - cy = event.originalEvent.clientY, - i_w = parseFloat(newImage.width()), - i_h = parseFloat(newImage.height()), - newIW = i_w * (delta > 0 ? 1.25 : 0.8), - newIH = i_h * (delta > 0 ? 1.25 : 0.8); - - newImage.width(newIW); - newImage.height(newIH); - //set position - newImage.css({ - left: parseInt(cx - (newIW/i_w) * (cx - parseInt($(img_pv).position().left, 10)), 10), - top: parseInt(cy - (newIH/i_h) * (cy - parseInt($(img_pv).position().top, 10)), 10) - }); - - return false; - } - ) - .draggable({ - addClasses: false, - stack: '.img-full' - }); - } else { - existingPopups.remove(); - } - //prevent default return false; }); } diff --git a/boards/templates/boards/base.html b/boards/templates/boards/base.html --- a/boards/templates/boards/base.html +++ b/boards/templates/boards/base.html @@ -21,7 +21,7 @@ {% block head %}{% endblock %} - + diff --git a/boards/views/settings.py b/boards/views/settings.py --- a/boards/views/settings.py +++ b/boards/views/settings.py @@ -3,15 +3,17 @@ from django.shortcuts import render, red from django.utils import timezone from boards.abstracts.settingsmanager import get_settings_manager, \ - SETTING_USERNAME, SETTING_LAST_NOTIFICATION_ID + SETTING_USERNAME, SETTING_LAST_NOTIFICATION_ID, SETTING_IMAGE_VIEWER from boards.middlewares import SESSION_TIMEZONE from boards.views.base import BaseBoardView, CONTEXT_FORM from boards.forms import SettingsForm, PlainErrorList +from boards import settings FORM_THEME = 'theme' FORM_USERNAME = 'username' FORM_TIMEZONE = 'timezone' +FORM_IMAGE_VIEWER = 'image_viewer' CONTEXT_HIDDEN_TAGS = 'hidden_tags' @@ -29,6 +31,8 @@ class SettingsView(BaseBoardView): form = SettingsForm( initial={ FORM_THEME: selected_theme, + FORM_IMAGE_VIEWER: settings_manager.get_setting( + SETTING_IMAGE_VIEWER, default=settings.DEFAULT_IMAGE_VIEWER), FORM_USERNAME: settings_manager.get_setting(SETTING_USERNAME), FORM_TIMEZONE: request.session.get( SESSION_TIMEZONE, timezone.get_current_timezone()), @@ -51,6 +55,8 @@ class SettingsView(BaseBoardView): username = form.cleaned_data[FORM_USERNAME].lower() settings_manager.set_theme(selected_theme) + settings_manager.set_setting(SETTING_IMAGE_VIEWER, + form.cleaned_data[FORM_IMAGE_VIEWER]) old_username = settings_manager.get_setting(SETTING_USERNAME) if username != old_username: diff --git a/neboard/settings.py b/neboard/settings.py --- a/neboard/settings.py +++ b/neboard/settings.py @@ -202,6 +202,11 @@ THEMES = [ ('pg', 'Photon Gray'), ] +IMAGE_VIEWERS = [ + ('simple', 'Simple'), + ('popup', 'Popup'), +] + POSTING_DELAY = 20 # seconds # Websocket settins