diff --git a/expobanner/admin.py b/expobanner/admin.py index 5bb709d7..311c83f8 100644 --- a/expobanner/admin.py +++ b/expobanner/admin.py @@ -3,9 +3,9 @@ from django.views.generic import TemplateView, CreateView, ListView, UpdateView, from django.conf import settings from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404 -from expobanner.models import URL, BannerGroup, Banner, Paid +from expobanner.models import URL, BannerGroup, Banner, Paid, MainPage, Top from expobanner.forms import UrlCreateForm, BannerCreateGroupForm, BannerCreateForm, BannerGroupUpdateForm,\ - PaidCreateForm, PaidUpdateForm, TopCreateForm + PaidCreateForm, PaidUpdateForm, TopCreateForm, BannerLinkCreateForm, MainCreateForm, MainUpdateForm, TopUpdateForm from exposition.models import Exposition @@ -32,6 +32,10 @@ class CreateBanner(AbstractCreate): model = Banner form_class = BannerCreateForm +class CreateLink(AbstractCreate): + model = Banner + form_class = BannerLinkCreateForm + # LISTS VIEWS class AbstractList(ListView): @@ -63,6 +67,16 @@ class BannerList(AbstractList): qs = qs.filter(group__isnull=False) return qs +class LinkList(AbstractList): + model = Banner + verbose = u'Список ссылок' + template_name = 'admin/expobanner/link_list.html' + + def get_queryset(self): + qs = super(LinkList, self).get_queryset() + qs = qs.filter(link=True) + return qs + # UPDATE VIEWS class AbstractUpdate(UpdateView): template_name = 'admin/expobanner/default_form.html' @@ -84,10 +98,16 @@ class BannerUpdate(AbstractUpdate): form_class = BannerCreateForm +class LinkUpdate(AbstractUpdate): + model = Banner + form_class = BannerLinkCreateForm + + class BannerStat(DetailView): model = Banner template_name = 'admin/expobanner/banner_stat.html' + class PaidList(ListView): model = Exposition template_name = 'admin/expobanner/paid_list.html' @@ -96,11 +116,13 @@ class PaidList(ListView): def get_queryset(self): return self.model.objects.language().filter(paid_new__isnull=False) + class PaidCreate(CreateView): form_class = PaidCreateForm template_name = 'admin/expobanner/paid_create.html' success_url = '/admin/expobanners/paid/list/' + class PaidUpdate(UpdateView): model = Paid form_class = PaidUpdateForm @@ -140,6 +162,58 @@ class PaidStat(DetailView): model = Paid template_name = 'admin/expobanner/paid_stat.html' +# ---------------------------------- +class MainList(ListView): + model = Exposition + template_name = 'admin/expobanner/main_list.html' + paginate_by = settings.ADMIN_PAGINATION + + def get_queryset(self): + return self.model.objects.language().filter(main__isnull=False) + + +class MainCreate(CreateView): + form_class = MainCreateForm + template_name = 'admin/expobanner/paid_create.html' + success_url = '/admin/expobanners/main/list/' + + +class MainUpdate(UpdateView): + model = MainPage + form_class = MainUpdateForm + template_name = 'admin/expobanner/default_form.html' + success_url = '/admin/expobanners/main/list/' + + + def get_context_data(self, **kwargs): + context = super(MainUpdate, self).get_context_data(**kwargs) + obj = self.object + context['exposition'] = obj.get_event() + return context + + +def main_turn(request, pk, status): + main = get_object_or_404(MainPage, pk=pk) + if status == 'on': + main.public = True + else: + main.public = False + main.save() + return HttpResponseRedirect('/admin/expobanners/main/list/') + + +class MainStat(DetailView): + model = MainPage + template_name = 'admin/expobanner/main_stat.html' + + def get_context_data(self, **kwargs): + context = super(MainStat, self).get_context_data(**kwargs) + obj = self.object + context['stats'] = obj.link.banner_stat.all() + return context + +# ------------------------------------ + class TopList(ListView): model = Exposition @@ -154,3 +228,17 @@ class TopCreate(CreateView): form_class = TopCreateForm template_name = 'admin/expobanner/top_create.html' success_url = '/admin/expobanners/top/list/' + + +class TopUpdate(UpdateView): + model = Top + form_class = TopUpdateForm + template_name = 'admin/expobanner/top_create.html' + success_url = '/admin/expobanners/top/list/' + + + def get_context_data(self, **kwargs): + context = super(TopUpdate, self).get_context_data(**kwargs) + obj = self.object + context['exposition'] = obj.get_event() + return context diff --git a/expobanner/admin_urls.py b/expobanner/admin_urls.py index 5497da30..d91abfca 100644 --- a/expobanner/admin_urls.py +++ b/expobanner/admin_urls.py @@ -8,13 +8,17 @@ urlpatterns = patterns('expobanner.admin', url(r'^banners/url/$', CreateUrl.as_view(), name='expobanner-create_url'), url(r'^banners/group/$', CreateBannerGroup.as_view(), name='expobanner-create_group'), url(r'^banners/banner/$', CreateBanner.as_view(), name='expobanner-create_banner'), + url(r'^banners/link/$', CreateLink.as_view(), name='expobanner-create_link'), url(r'^banners/url/list/$', UrlList.as_view(), name='expobanner-list_url'), url(r'^banners/group/list/$', BannerGroupList.as_view(), name='expobanner-list_group'), url(r'^banners/banner/list/$', BannerList.as_view(), name='expobanner-list_banner'), + url(r'^banners/link/list/$', LinkList.as_view(), name='expobanner-list_link'), url(r'^banners/url/(?P\d+)/edit/$', UrlUpdate.as_view(), name='expobanner-update_url'), url(r'^banners/group/(?P\d+)/edit/$', BannerGroupUpdate.as_view(), name='expobanner-update_group'), url(r'^banners/banner/(?P\d+)/edit/$', BannerUpdate.as_view(), name='expobanner-update_banner'), + url(r'^banners/link/(?P\d+)/edit/$', LinkUpdate.as_view(), name='expobanner-update_link'), url(r'^banners/banner/(?P\d+)/stat/$', BannerStat.as_view(), name='expobanner_stat_banner'), + url(r'^banners/banner/(?P\d+)/stat/$', BannerStat.as_view(), name='expobanner_stat_link'), # paid url(r'^paid/list/$', PaidList.as_view(), name='expobanner-list_paid'), url(r'^paid/(?P\d+)/edit/$', PaidUpdate.as_view(), name='expobanner-update_paid'), @@ -23,7 +27,13 @@ urlpatterns = patterns('expobanner.admin', url(r'^paid/(?P\d+)/stat/$', PaidStat.as_view(), name='expobanner_stat_paid'), # top url(r'^top/list/$', TopList.as_view(), name='expobanner-list_top'), - url(r'^top/(?P\d+)/edit/$', PaidUpdate.as_view(), name='expobanner-update_top'), + url(r'^top/(?P\d+)/edit/$', TopUpdate.as_view(), name='expobanner-update_top'), url(r'^top/$', TopCreate.as_view(), name='expobanner-create_top'), url(r'^top/(?P\d+)/stat/$', PaidStat.as_view(), name='expobanner_stat_top'), + # main page + url(r'^main/list/$', MainList.as_view(), name='expobanner-list_main'), + url(r'^main/(?P\d+)/edit/$', MainUpdate.as_view(), name='expobanner-update_main'), + url(r'^main/$', MainCreate.as_view(), name='expobanner-create_main'), + url(r'^main/turn/(?P\d+)/(?P.*)/$', main_turn, name='expobanner-main-turn'), + url(r'^main/(?P\d+)/stat/$', MainStat.as_view(), name='expobanner_stat_main'), ) \ No newline at end of file diff --git a/expobanner/forms.py b/expobanner/forms.py index 5c3b6473..85f479ea 100644 --- a/expobanner/forms.py +++ b/expobanner/forms.py @@ -1,14 +1,15 @@ # -*- coding: utf-8 -*- from django import forms -from expobanner.models import URL, BannerGroup, Banner, Paid, Top +from expobanner.models import URL, BannerGroup, Banner, Paid, Top, MainPage from exposition.models import Exposition from country.models import Country -from city.models import City +from ckeditor.widgets import CKEditorWidget from theme.models import Theme, Tag class UrlCreateForm(forms.ModelForm): verbose = u'Создать урл' + class Meta: model = URL exclude = ['created_at', 'updated_at', 'sites'] @@ -16,12 +17,14 @@ class UrlCreateForm(forms.ModelForm): class BannerCreateGroupForm(forms.ModelForm): verbose = u'Создать групу' + class Meta: model = BannerGroup exclude = ['created_at', 'updated_at', 'speed'] class BannerGroupUpdateForm(BannerCreateGroupForm): verbose = u'Изменить групу' + class Meta: model = BannerGroup exclude = ['created_at', 'updated_at', 'slug', 'speed'] @@ -29,15 +32,28 @@ class BannerGroupUpdateForm(BannerCreateGroupForm): class BannerCreateForm(forms.ModelForm): verbose = u'Создать банер' - #country = forms.ChoiceField(label=u'Страна', choices=[('', ' ')] + [(c.id, c.name) for c in Country.objects.all()], required=False) - #theme = forms.ChoiceField(label=u'Тематика', required=False, - # choices=[('', ' ')] + [(item.id, item.name) for item in Theme.objects.language().all()]) - #city = forms.CharField(label=u'Город', widget=forms.HiddenInput(), required=False) - #tag = forms.CharField(label=u'Тег', widget=forms.HiddenInput(), required=False) + text = forms.CharField(label=u'Текст', required=False, widget=CKEditorWidget) + class Meta: + model = Banner + exclude = ['created_at', 'updated_at', 'often', 'paid', 'stat_pswd', 'cookie', 'link'] + + +class BannerLinkCreateForm(forms.ModelForm): + verbose = u'Отслеживаемую ссылку' class Meta: model = Banner - exclude = ['created_at', 'updated_at', 'often', 'paid', 'stat_pswd'] + fields = ['public', 'alt', 'url'] + exclude = ['created_at', 'updated_at', 'often', 'paid', 'stat_pswd', 'cookie', 'link'] + + def save(self, commit=True): + banner = super(BannerLinkCreateForm, self).save(commit=False) + if commit: + banner.link =True + banner.save() + + return banner + class ClientStatForm(forms.Form): @@ -91,6 +107,36 @@ class PaidCreateForm(forms.ModelForm): raise forms.ValidationError(u'Такой выставки не существует') return expo +class MainCreateForm(forms.ModelForm): + verbose = u'Добавить выставку на главную' + exposition = forms.CharField(label=u'Выставка', widget=forms.HiddenInput()) + + class Meta: + model = MainPage + fields = ['position', 'public'] + + def save(self, commit=True): + main = super(MainCreateForm, self).save(commit=False) + if commit: + expo = self.cleaned_data['exposition'] + link = expo.get_permanent_url() + link_b = Banner.objects.create_for_paid(expo, link, 'main_page_link') + main.link = link_b + main.save() + + expo.main = main + expo.save() + return main + + def clean_exposition(self): + expo_id = self.cleaned_data['exposition'] + try: + expo = Exposition.objects.get(id=expo_id) + except Exposition.DoesNotExist: + raise forms.ValidationError(u'Такой выставки не существует') + return expo + + class PaidUpdateForm(forms.ModelForm): tickets = forms.URLField(label=u'Линк на билеты') participation = forms.URLField(label=u'Линк на участие') @@ -126,17 +172,23 @@ class PaidUpdateForm(forms.ModelForm): return paid +class MainUpdateForm(forms.ModelForm): + class Meta: + model = MainPage + fields = ['position', 'public'] + + class TopCreateForm(forms.ModelForm): verbose = u'Создать выставку в топе' exposition = forms.CharField(label=u'Выставка', widget=forms.HiddenInput()) country = forms.MultipleChoiceField(label=u'Страна', choices=[('', ' ')] + [(c.id, c.name) for c in Country.objects.all()], required=False) theme = forms.MultipleChoiceField(label=u'Тематика', required=False, choices=[('', ' ')] + [(item.id, item.name) for item in Theme.objects.language().all()]) - excluded_cities = forms.CharField(label=u'Город', widget=forms.HiddenInput(), required=False) - excluded_tags = forms.CharField(label=u'Тег', widget=forms.HiddenInput(), required=False) + #excluded_cities = forms.CharField(label=u'Город', widget=forms.HiddenInput(), required=False) + #excluded_tags = forms.CharField(label=u'Тег', widget=forms.HiddenInput(), required=False) class Meta: model = Top - fields = ['catalog', 'position', 'theme', 'excluded_tags', 'country', 'excluded_cities', 'fr', 'to'] + fields = ['catalog', 'position', 'theme', 'country', 'fr', 'to'] def save(self, commit=True): top = super(TopCreateForm, self).save(commit=False) @@ -149,15 +201,22 @@ class TopCreateForm(forms.ModelForm): top.theme.clear() for theme in self.cleaned_data['theme']: top.theme.add(theme) + top.country.clear() + for country in self.cleaned_data['country']: + top.country.add(country) self.save_m2m = save_m2m if commit: expo = self.cleaned_data['exposition'] + link = expo.get_permanent_url() + link_b = Banner.objects.create_for_paid(expo, link, 'top_link') + top.link = link_b top.save() self.save_m2m() expo.top = top expo.save() + return top def clean_theme(self): @@ -178,4 +237,34 @@ class TopCreateForm(forms.ModelForm): expo = Exposition.objects.get(id=expo_id) except Exposition.DoesNotExist: raise forms.ValidationError(u'Такой выставки не существует') - return expo \ No newline at end of file + return expo + + +class TopUpdateForm(forms.ModelForm): + verbose = u'Изменить выставку' + class Meta: + model = Top + fields = ['catalog', 'position', 'theme', 'country', 'fr', 'to'] + + def save(self, commit=True): + top = super(TopUpdateForm, self).save(commit=False) + # Prepare a 'save_m2m' method for the form, + old_save_m2m = self.save_m2m + + def save_m2m(): + old_save_m2m() + # This is where we actually link the pizza with toppings + top.theme.clear() + for theme in self.cleaned_data['theme']: + top.theme.add(theme) + top.country.clear() + for country in self.cleaned_data['country']: + top.country.add(country) + + self.save_m2m = save_m2m + + if commit: + + top.save() + self.save_m2m() + return top diff --git a/expobanner/management/commands/banner_log_update.py b/expobanner/management/commands/banner_log_update.py index 86cfb920..9b795176 100644 --- a/expobanner/management/commands/banner_log_update.py +++ b/expobanner/management/commands/banner_log_update.py @@ -9,7 +9,7 @@ class Command(BaseCommand): def handle(self, *args, **options): today = date.today() # banners - for banner in Banner.objects.select_related('group').filter(public=True, group__isnull=False): + for banner in Banner.objects.select_related('group').filter(public=True): try: logstat = LogStat.objects.get(banner=banner, group=banner.group, date=today) except LogStat.DoesNotExist: diff --git a/expobanner/managers.py b/expobanner/managers.py index 42e82670..51f988af 100644 --- a/expobanner/managers.py +++ b/expobanner/managers.py @@ -51,7 +51,7 @@ class BannerGroupCached(models.Manager): for group in groups: result[group.slug] = list(group.banners.prefetch_related('urls', 'theme', 'country')\ .filter(public=True, fr__lte=today)\ - .filter(Q(to__gte=today) | Q(to__isnull=True)).extra({})) + .filter(Q(to__gte=today) | Q(to__isnull=True))) cache.set(key, result, 70) return result @@ -71,7 +71,9 @@ class TopCached(models.Manager): key = 'expo_b_top_all' result = cache.get(key) if not result: - result = list(self.prefetch_related('theme', 'country', 'excluded_tags', 'excluded_cities').all()) + today = date.today() + result = list(self.prefetch_related('theme', 'country', 'excluded_tags', 'excluded_cities'). + filter(fr__lte=today).filter(Q(to__gte=today) | Q(to__isnull=True))) cache.set(key, result, 80) return result \ No newline at end of file diff --git a/expobanner/models.py b/expobanner/models.py index b49c914f..7091af0e 100644 --- a/expobanner/models.py +++ b/expobanner/models.py @@ -95,8 +95,11 @@ class Banner(models.Model, StatMixin): html = models.BooleanField(verbose_name=_('HTML?'), default=False) flash = models.BooleanField(verbose_name=_('Flash?'), default=False) - js = models.BooleanField(verbose_name=_('Javascript?'), default=False) + popup = models.BooleanField(verbose_name=_('Popup?'), default=False) paid = models.BooleanField(verbose_name=_('Is Paid event link?'), default=False) + link = models.BooleanField(verbose_name=_('Is simple link?'), default=False) + # for detecting popups + cookie = models.CharField(max_length=30, blank=True, null=True, default=settings.DEFAULT_POPUP_COOKIE) public = models.BooleanField(verbose_name=u'Активный', default=True) created_at = models.DateTimeField(verbose_name=_('Created At'), auto_now_add=True) @@ -221,9 +224,10 @@ class Paid(models.Model, StatMixin): ordering = ['-public'] def get_event(self): - if self.exposition_set.all().exists(): + try: return self.exposition_set.all()[0] - return None + except IndexError: + return None class PaidStat(models.Model): @@ -239,6 +243,7 @@ class PaidStat(models.Model): class Top(models.Model, StatMixin): + link = models.ForeignKey(Banner) catalog = models.CharField(max_length=16, verbose_name=u'Каталог для топа') position = models.PositiveIntegerField(blank=True, default=2, null=True, verbose_name=u'Позиция') theme = models.ManyToManyField('theme.Theme', blank=True, null=True, verbose_name=u'Тематики') @@ -270,6 +275,25 @@ class TopStat(models.Model): views = models.PositiveIntegerField(default=0) clicks = models.PositiveIntegerField(default=0) + +class MainPage(models.Model, StatMixin): + link = models.ForeignKey(Banner) + position = models.PositiveIntegerField(blank=True, default=2, null=True, verbose_name=u'Позиция') + public = models.BooleanField(default=True, verbose_name=u'Активная') + stat_pswd = models.CharField(max_length=16) + created = models.DateTimeField(auto_now_add=True) + modified = models.DateTimeField(auto_now=True) + + class Meta: + ordering = ['-public'] + + def get_event(self): + try: + return self.exposition_set.all()[0] + except IndexError: + return None + + def generatePassword(length=5): """ generate random password diff --git a/expobanner/utils.py b/expobanner/utils.py index 9c4222a2..f3e457cf 100644 --- a/expobanner/utils.py +++ b/expobanner/utils.py @@ -1,5 +1,7 @@ # -*- coding: utf-8 -*- +import re import random +import datetime from django.db import connection def get_client_ip(request): @@ -10,6 +12,32 @@ def get_client_ip(request): ip = request.META.get('REMOTE_ADDR') return ip +def get_referer_view(request, default=None): + ''' + Return the referer view of the current request + + Example: + + def some_view(request): + ... + referer_view = get_referer_view(request) + return HttpResponseRedirect(referer_view, '/accounts/login/') + ''' + + # if the user typed the url directly in the browser's address bar + referer = request.META.get('HTTP_REFERER') + if not referer: + return default + + # remove the protocol and split the url at the slashes + referer = re.sub('^https?:\/\/', '', referer).split('/') + if referer[0] != request.META.get('SERVER_NAME'): + return default + + # add the slash at the relative path's view and finished + referer = u'/' + u'/'.join(referer[1:]) + return referer + def get_by_sort(banner_list): max_sort = 0 for banner in banner_list: @@ -19,12 +47,26 @@ def get_by_sort(banner_list): result = [banner for banner in banner_list if banner.sort == max_sort] return result +def set_cookie(response, key, value, days_expire = 7): + if days_expire is None: + max_age = 365 * 24 * 60 * 60 #one year + else: + max_age = days_expire * 24 * 60 * 60 + expires = datetime.datetime.strftime(datetime.datetime.utcnow() + datetime.timedelta(seconds=max_age), "%a, %d-%b-%Y %H:%M:%S GMT") + response.set_cookie(key, value, max_age=max_age, expires=expires) + return response + -def get_banner_by_params(banners_list, urls, params): +def get_banner_by_params(banners_list, urls, params, request): thematic_banners = [] url_banners = [] for banner in banners_list: + # check popups + if banner.popup: + cookie = request.COOKIES.get(banner.cookie) + if cookie: + continue # check by theme banner_theme_ids = [str(theme.id) for theme in banner.theme.all()] if banner_theme_ids: @@ -64,14 +106,18 @@ def get_banner_by_params(banners_list, urls, params): continue if thematic_banners: - return random.choice(thematic_banners) - if url_banners: - return random.choice(url_banners) - return None - - #print('END. NUMBER of queries = %d'%len(connection.queries)) + result = thematic_banners + elif url_banners: + result = url_banners + else: + result = [] + if result: + sort_result = get_by_sort(result) + return random.choice(sort_result) + else: + return None -def get_top_events(tops, params): +def get_top_events(tops, params, request): catalog = params.get('catalog') country = params.get('country', '') theme = params.get('theme', []) @@ -108,5 +154,6 @@ def get_top_events(tops, params): for top in sorted_top: event = top.get_event() if event: + top.link.log(request, 1) events.append(event) return events \ No newline at end of file diff --git a/expobanner/views.py b/expobanner/views.py index 96540cdc..0c5a0438 100644 --- a/expobanner/views.py +++ b/expobanner/views.py @@ -6,7 +6,7 @@ from django.shortcuts import redirect, get_object_or_404 from django.shortcuts import render_to_response from django.template import RequestContext from .models import Banner, BannerGroup, URL, Top -from expobanner.utils import get_by_sort, get_banner_by_params, get_client_ip, get_top_events +from expobanner.utils import get_banner_by_params, get_client_ip, get_top_events, get_referer_view, set_cookie def click(request, banner_id): @@ -21,8 +21,7 @@ def view(request, banner_id): return redirect(banner.img.url) def get_banners(request): - #url = request.GET.get('url', '/') - url = request.META.get('HTTP_REFERER', '/') + url = get_referer_view(request, default='/') # get urls by current url urls = URL.cached.all() good_urls = [] @@ -42,18 +41,27 @@ def get_banners(request): group_banners = BannerGroup.cached.group_banners() result = [] + cookie = None # get banners for all groups + places = request.GET.getlist('places', []) + for group, banners in group_banners.iteritems(): - banner = get_banner_by_params(banners, good_urls, params) + if group not in places: + # on this page there is no such group + continue + banner = get_banner_by_params(banners, good_urls, params, request) if banner: - if banner.js or banner.html: + if banner.html: text = banner.text img = '' alt = '' is_img = False else: text = '' - img = banner.img.url + try: + img = banner.img.url + except ValueError: + continue alt = banner.alt is_img = True result.append({'id': group, @@ -61,15 +69,20 @@ def get_banners(request): 'is_html': banner.html, 'is_flash': banner.flash, 'is_img': is_img, - 'is_js': banner.js, + 'is_popup': banner.popup, 'img': img, 'alt': alt, 'text': text }) + if banner.popup: + cookie = banner.cookie # add view log banner.log(request, 1) + response = HttpResponse(json.dumps(result, indent=4), content_type='application/json') + if cookie: + response = set_cookie(response, cookie, '1') - return HttpResponse(json.dumps(result, indent=4), content_type='application/json') + return response def get_top(request): params = {'theme': request.GET.getlist('theme', []), @@ -79,6 +92,6 @@ def get_top(request): 'catalog': request.GET.get('catalog')} tops = Top.cached.all() - events = get_top_events(tops, params) + events = get_top_events(tops, params, request) context = {'objects': events} return render_to_response('client/includes/exposition/expo_top.html', context, context_instance=RequestContext(request)) \ No newline at end of file diff --git a/exposition/forms.py b/exposition/forms.py index 990fc457..5cb1380e 100644 --- a/exposition/forms.py +++ b/exposition/forms.py @@ -2,8 +2,6 @@ from django import forms from django.conf import settings from ckeditor.widgets import CKEditorWidget -from tinymce.widgets import TinyMCE -from django.core.exceptions import ValidationError from django.forms.util import ErrorList from django.core.validators import validate_email, URLValidator from django.utils.translation import ugettext as _ @@ -13,15 +11,11 @@ from theme.models import Tag from country.models import Country from theme.models import Theme from organiser.models import Organiser -from accounts.models import User -from company.models import Company from city.models import City -from service.models import Service from place_exposition.models import PlaceExposition #functions -from functions.translate import populate_all, fill_trans_fields_all, fill_with_signal +from functions.translate import fill_with_signal from functions.form_check import is_positive_integer -from functions.files import check_tmp_files from functions.form_check import translit_with_separator from settings.settings import date_formats from functions.admin_forms import AdminFilterForm diff --git a/exposition/manager.py b/exposition/manager.py index 1c9deec7..bf08f166 100644 --- a/exposition/manager.py +++ b/exposition/manager.py @@ -10,6 +10,7 @@ class ClientManager(TranslationManager): def upcoming(self): return self.filter(data_begin__gte=datetime.datetime.now().date()) + """ from exposition.models import Exposition diff --git a/exposition/models.py b/exposition/models.py index 76b7177f..fbae6343 100644 --- a/exposition/models.py +++ b/exposition/models.py @@ -158,6 +158,7 @@ class Exposition(TranslatableModel, EventMixin, ExpoMixin): paid_new = models.ForeignKey('expobanner.Paid', blank=True, null=True, on_delete=models.SET_NULL) top = models.ForeignKey('expobanner.Top', blank=True, null=True, on_delete=models.SET_NULL) + main = models.ForeignKey('expobanner.MainPage', blank=True, null=True, on_delete=models.SET_NULL) #set manager of this model(fisrt manager is default) objects = ExpoManager() enable = ClientManager() @@ -306,6 +307,18 @@ class Exposition(TranslatableModel, EventMixin, ExpoMixin): def theme_ids(self): return [item['id'] for item in self.theme.all().values('id')] + def get_main_link(self): + if self.main: + return self.main.link.get_click_link() + else: + return self.get_permanent_url() + + def get_top_link(self): + if self.top: + return self.top.link.get_click_link() + else: + return self.get_permanent_url() + class Statistic(TranslatableModel): exposition = models.ForeignKey(Exposition, related_name='statistic') diff --git a/exposition/views.py b/exposition/views.py index 43f5fb8f..fa7eff6a 100644 --- a/exposition/views.py +++ b/exposition/views.py @@ -433,7 +433,9 @@ class ExpoCityCatalog(ExpoCatalog): return qs def get_context_data(self, **kwargs): context = super(ExpoCityCatalog, self).get_context_data(**kwargs) - context['city'] = str(self.kwargs['city'].id) + city = self.kwargs['city'] + context['country'] = str(city.country_id) + context['city'] = str(city.id) return context diff --git a/functions/models_methods.py b/functions/models_methods.py index 35121ea9..064667ac 100644 --- a/functions/models_methods.py +++ b/functions/models_methods.py @@ -25,6 +25,17 @@ class ExpoManager(TranslationManager): except: return None + def expo_main(self): + lang = translation.get_language() + key = 'expo_main_page_key_%s'%lang + result = cache.get(key) + if not result: + result = list(self.language(lang).select_related('country', 'city', 'place', 'main').prefetch_related('tag').filter(main__isnull=False)) + cache.set(key, result, 45) + + return result + + class CityManager(TranslationManager): cache_time = 600 diff --git a/proj/settings.py b/proj/settings.py index c2828869..14caba29 100644 --- a/proj/settings.py +++ b/proj/settings.py @@ -449,6 +449,8 @@ CLIENT_DATE_FORMAT = ["%d.%m.%Y"] # cache pages in random seconds. random in this range CACHE_RANGE = [60, 120] +DEFAULT_POPUP_COOKIE = 'expo_b_default_popup' + try: from local import * except ImportError, e: diff --git a/proj/urls.py b/proj/urls.py index 03c2a385..085e5bf1 100644 --- a/proj/urls.py +++ b/proj/urls.py @@ -78,7 +78,6 @@ urlpatterns = patterns('', # ajax urls urlpatterns += patterns('', - url(r'^ajax/get_popover/$', 'settings.views.get_popover_info'), url(r'^registration/reply/$', 'registration.backends.default.views.RegisterReply'), url(r'^register/', 'registration.backends.default.views.RegisterAjaxView'), url(r'^register-complete/', 'registration.backends.default.views.complete_registration'), diff --git a/proj/views.py b/proj/views.py index 0db0e5bd..cfb06577 100644 --- a/proj/views.py +++ b/proj/views.py @@ -77,8 +77,11 @@ class MainPageView(JitterCacheMixin, TemplateView): def get_context_data(self, **kwargs): context = super(MainPageView, self).get_context_data(**kwargs) - - events = Exposition.objects.language().select_related('country', 'city', 'place').filter(main_page__gte=1).order_by('-main_page') + ev = Exposition.objects.expo_main() + events = sorted(ev, key=lambda x: x.main.position) + # update main_page counter + for event in events: + event.main.link.log(self.request, 1) exposition_themes = Theme.objects.language().order_by('-main_page').filter(types=Theme.types.exposition)[:6] conference_themes = Theme.objects.language().order_by('-main_page').filter(types=Theme.types.conference)[:6] diff --git a/settings/views.py b/settings/views.py index 0655f9c3..80875d27 100644 --- a/settings/views.py +++ b/settings/views.py @@ -159,24 +159,4 @@ def get_popover(request): html = render_to_string(popover) response['html'] = html - return HttpResponse(json.dumps(response), content_type='application/json') - -from banners.models import Redirect -from django.db.models import F -import datetime - -def set_cookie(response, key, value, days_expire = 7): - if days_expire is None: - max_age = 365 * 24 * 60 * 60 #one year - else: - max_age = days_expire * 24 * 60 * 60 - expires = datetime.datetime.strftime(datetime.datetime.utcnow() + datetime.timedelta(seconds=max_age), "%a, %d-%b-%Y %H:%M:%S GMT") - response.set_cookie(key, value, max_age=max_age, expires=expires) - -def get_popover_info(request): - id = request.GET.get('rdr') - if id: - Redirect.objects.filter(id=id).update(views = F('views') + 1) - response = HttpResponse('success') - set_cookie(response, 'popover_test1', '1') - return response \ No newline at end of file + return HttpResponse(json.dumps(response), content_type='application/json') \ No newline at end of file diff --git a/templates/admin/expobanner/banners_control.html b/templates/admin/expobanner/banners_control.html index e307cecd..5d4214fb 100644 --- a/templates/admin/expobanner/banners_control.html +++ b/templates/admin/expobanner/banners_control.html @@ -13,6 +13,9 @@ + @@ -27,6 +30,9 @@ + diff --git a/templates/admin/expobanner/default_form.html b/templates/admin/expobanner/default_form.html index 50d696c0..3322088e 100644 --- a/templates/admin/expobanner/default_form.html +++ b/templates/admin/expobanner/default_form.html @@ -2,6 +2,7 @@ {% load static %} {% block scripts %} + +{% endblock %} + + +{% block body %} +
+
+
+

{{ object.get_event }}

+
+
+
+
Линк на статистику: {{ request.get_host }}/expo-b/banner/{{ object.link.id }}/stat/
+
Пароль: {{ object.link.stat_pswd }}
+
+ + + + + + + + + + + + {% with stats=stats %} + {% for stat in stats %} + + + + + + + + + {% endfor %} + {% endwith %} + +
ДатаПоказыКликиУникальные показыУникальные клики
{{ stat.date|date:"Y-m-d" }}{{ stat.view }}{{ stat.click }}{{ stat.unique_view }}{{ stat.unique_click }}
+
+
+
+ +{% endblock %} \ No newline at end of file diff --git a/templates/admin/expobanner/paid_stat.html b/templates/admin/expobanner/paid_stat.html index b935251c..b47791c5 100644 --- a/templates/admin/expobanner/paid_stat.html +++ b/templates/admin/expobanner/paid_stat.html @@ -12,6 +12,10 @@

{{ object.get_event }} (Пароль: {{ object.stat_pswd }})

+
+
Линк на статистику: {{ request.get_host }}/expo-b/paid/{{ object.id }}/stat/
+
Пароль: {{ object.stat_pswd }}
+
diff --git a/templates/admin/expobanner/top_create.html b/templates/admin/expobanner/top_create.html index 4479d055..648ea992 100644 --- a/templates/admin/expobanner/top_create.html +++ b/templates/admin/expobanner/top_create.html @@ -61,7 +61,7 @@ $(function(){
-

{{ form.verbose }}

+

{{ form.verbose }} {% if object %}{{ object.get_event }}{% endif %}

{% for field in form %} diff --git a/templates/admin/includes/admin_nav.html b/templates/admin/includes/admin_nav.html index 59a41ebf..068e0067 100644 --- a/templates/admin/includes/admin_nav.html +++ b/templates/admin/includes/admin_nav.html @@ -111,6 +111,7 @@
  • Управление банерами
  • Платные выставки
  • Выставки в топе
  • +
  • Выставки на главной
  • diff --git a/templates/client/base_catalog.html b/templates/client/base_catalog.html index 46746b57..6582dc3e 100644 --- a/templates/client/base_catalog.html +++ b/templates/client/base_catalog.html @@ -1,4 +1,4 @@ -{% extends 'blank.html' %} +{% extends 'client/blank.html' %} {% load static %} {% load i18n %} diff --git a/templates/client/blank.html b/templates/client/blank.html index 526f8aec..04a4d77e 100644 --- a/templates/client/blank.html +++ b/templates/client/blank.html @@ -87,16 +87,7 @@ This template include basic anf main styles and js files, })(window,document,'script','dataLayer','GTM-P5C6GR'); - - - + @@ -145,76 +136,8 @@ This template include basic anf main styles and js files, {% endif %} {% include 'client/popups/callback.html' %} + {% include 'client/includes/banners/popup.html' %} {% block popup_banner %} - {% if not request.COOKIES.popover_test1 %} - {% if theme_for_filter %} - - {% if theme_for_filter.id == 54 or theme_for_filter.id == 26 or theme_for_filter.id == 22 or theme_for_filter.id == 15 or theme_for_filter.id == 44 or theme_for_filter.id == 30 %} - {% with r=False|random3 %} - {% if r == 1 %} - {% include 'client/popups/cemat_modal.html' %} - {% else %} - {% if r == 2 %} - {% include 'client/popups/cemat_banner1.html' %} - {% else %} - {% include 'client/popups/cemat_banner2.html' %} - {% endif %} - {% endif %} - {% endwith %} - {% endif %} - - {% if theme_for_filter.id == 32 %} - {% with r=False|random3 %} - {% if r == 1 %} - {% include 'client/popups/cemat_modal.html' %} - {% endif %} - {% if r == 2 %} - {% include 'client/popups/cemat_banner1.html' %} - {% endif %} - {% if r == 0 %} - {% include 'client/popups/cemat_banner2.html' %} - {% endif %} - {% endwith %} - {% endif %} - - - - - {% endif %} - {% endif %} {% endblock %} {# if user doesnt have url- show form #} {% if 'partial_pipeline' not in request.session %} @@ -245,5 +168,16 @@ This template include basic anf main styles and js files, {% endif %} + + + + diff --git a/templates/client/expobanners/banner_stat.html b/templates/client/expobanners/banner_stat.html index da8af1c1..924617ca 100644 --- a/templates/client/expobanners/banner_stat.html +++ b/templates/client/expobanners/banner_stat.html @@ -1,5 +1,33 @@ {% extends 'base_catalog.html' %} +{% block styles %} + +{% endblock %} + {% block page_title %}

    {{ object }}. Статистика

    diff --git a/templates/client/expobanners/paid_stat.html b/templates/client/expobanners/paid_stat.html index ba695d71..a7e54012 100644 --- a/templates/client/expobanners/paid_stat.html +++ b/templates/client/expobanners/paid_stat.html @@ -1,4 +1,32 @@ -{% extends 'base_catalog.html' %} +{% extends 'client/base_catalog.html' %} + +{% block styles %} + +{% endblock %} {% block page_title %}
    diff --git a/templates/client/exposition/exposition_detail.html b/templates/client/exposition/exposition_detail.html index 3910dd18..f95b6dc3 100644 --- a/templates/client/exposition/exposition_detail.html +++ b/templates/client/exposition/exposition_detail.html @@ -26,73 +26,4 @@ {% block paginator %} -{% endblock %} - -{% block popup%} - -{% if not request.COOKIES.popover_test1 %} - - {% with theme_ids=object.theme_ids %} - {% if 32 in theme_ids %} - {% with r=False|random3 %} - {% if r == 0 %} - {% include 'client/popups/cemat_modal.html' %} - {% endif %} - {% if r == 1 %} - {% include 'client/popups/cemat_banner1.html' %} - {% endif %} - {% if r == 2 %} - {% include 'client/popups/cemat_banner2.html' %} - {% endif %} - {% endwith %} - {% else %} - {% if 54 in theme_ids or 26 in theme_ids or 22 in theme_ids or 15 in theme_ids or 44 in theme_ids or 30 in theme_ids %} - {% with r=False|random3 %} - {% if r == 1 %} - {% include 'client/popups/cemat_modal.html' %} - {% else %} - {% if r == 2 %} - {% include 'client/popups/cemat_banner1.html' %} - {% else %} - {% include 'client/popups/cemat_banner2.html' %} - {% endif %} - {% endif %} - {% endwith %} - - {% endif %} - {% endif %} - {% endwith %} - -{% endif %} - -{% endblock %} +{% endblock %} \ No newline at end of file diff --git a/templates/client/includes/banners/popup.html b/templates/client/includes/banners/popup.html new file mode 100644 index 00000000..6152147d --- /dev/null +++ b/templates/client/includes/banners/popup.html @@ -0,0 +1,2 @@ + \ No newline at end of file diff --git a/templates/client/includes/banners/tops.html b/templates/client/includes/banners/tops.html index 142e63a4..f1678855 100644 --- a/templates/client/includes/banners/tops.html +++ b/templates/client/includes/banners/tops.html @@ -1,13 +1,7 @@ +{% load static %} +
    - \ No newline at end of file + + \ No newline at end of file diff --git a/templates/client/includes/exposition/expo_top.html b/templates/client/includes/exposition/expo_top.html index 639c0425..dbe0056e 100644 --- a/templates/client/includes/exposition/expo_top.html +++ b/templates/client/includes/exposition/expo_top.html @@ -5,10 +5,10 @@
      {% for obj in objects %} -
    • +
    • {% endif %}
      - +
      {{ obj.main_title|safe }} diff --git a/templates/client/includes/index/main_events.html b/templates/client/includes/index/main_events.html index f39da5c8..17368ba8 100644 --- a/templates/client/includes/index/main_events.html +++ b/templates/client/includes/index/main_events.html @@ -12,7 +12,7 @@
    • diff --git a/templates/client/static_client/js/_modules/block.common.js b/templates/client/static_client/js/_modules/block.common.js index c61cda55..9dad6235 100644 --- a/templates/client/static_client/js/_modules/block.common.js +++ b/templates/client/static_client/js/_modules/block.common.js @@ -354,7 +354,7 @@ if (EXPO.common){ $staticFields = $('.'+validErrorClass); $waiter = $('#wait-ajax:not(.absolute)').css({'z-index': '8031'}); - $('.'+addClass+', .'+remClass).on('click', function(event){ + $('body').on('click', '.' + addClass + ', .' + remClass, function(event) { addText = self.opt.addCalendarText; remText = self.opt.removeCalendarText; event.preventDefault(); diff --git a/templates/client/static_client/js/rejs/banners.js b/templates/client/static_client/js/rejs/banners.js new file mode 100644 index 00000000..70e4998b --- /dev/null +++ b/templates/client/static_client/js/rejs/banners.js @@ -0,0 +1,113 @@ +(function () { + "use strict"; + + var API_URL_ROOT = "/expo-b/get-banners/"; + + var getUrl = function () { + var search = []; + + var parts = /^\/([^\/]+)(?:\/|$)/i.exec(location.pathname); + if (parts) { + search.push("catalog=" + encodeURIComponent(parts[1])); + } else { + search.push("catalog="); + } + + var elements = $("[id^=\"expo_b_\"]"); + for (var j = 0; j < elements.length; j++) { + search.push("places=" + encodeURIComponent($(elements[j]).attr("id"))); + } + + var data = window.sendData; + if (data instanceof Object) { + for (var key in data) { + if (data.hasOwnProperty(key)) { + var value = data[key]; + + if (value instanceof Array) { + for (var i = 0, l = value.length; i < l; i++) { + search.push(encodeURIComponent(key) + "=" + encodeURIComponent(value[i])); + } + } else { + search.push(encodeURIComponent(key) + "=" + encodeURIComponent(value)); + } + } + } + } + + return API_URL_ROOT + "?" + search.join("&"); + }; + + var getBanners = function (url, callback) { + var xhr = new XMLHttpRequest(); + xhr.open("GET", url, true); + + xhr.onreadystatechange = function (event) { + if (event.target.readyState === 4) { + if (event.target.status === 200) { + try { + callback(JSON.parse(event.target.responseText)); + } catch (error) { + // do nothing + } + } + } + }; + + xhr.send(); + }; + + var addBanner = function (banner) { + var parent = document.getElementById(banner.id); + + if (parent) { + if (banner.is_popup) { + if (banner.is_img) { + parent.innerHTML = + "
      " + + "\""
      "; + } else if (banner.is_html) { + parent.innerHTML = banner.text; + } + + $("#expo-form-popup").on("submit", function(e) { + e.preventDefault(); + window.location = $("#expo-form-popup").attr("action"); + }); + + setTimeout(function(){ + $.fancybox.open([{"href": "#" + banner.id}], {}); + }, 5000); + } else { + if (banner.is_img) { + var a = document.createElement("a"); + a.href = banner.url; + + var img = document.createElement("img"); + img.src = banner.img; + img.alt = banner.alt; + + a.appendChild(img); + parent.appendChild(a); + } else if (banner.is_html) { + parent.innerHTML = banner.text; + } + } + } + + }; + + var insertBanners = function (data) { + if (data instanceof Array) { + for (var i = 0, l = data.length; i < l; i++) { + addBanner(data[i]); + } + } + }; + + var main = function () { + getBanners(getUrl(), insertBanners); + }; + + window.addEventListener("load", main); +})(); diff --git a/templates/client/static_client/js/banners.js b/templates/client/static_client/js/rejs/tops.js similarity index 53% rename from templates/client/static_client/js/banners.js rename to templates/client/static_client/js/rejs/tops.js index 1f6126ca..31bee27b 100644 --- a/templates/client/static_client/js/banners.js +++ b/templates/client/static_client/js/rejs/tops.js @@ -1,14 +1,21 @@ (function () { "use strict"; - var API_URL_ROOT = "/expo-b/get-banners/"; + var API_URL_ROOT = "/expo-b/get-tops/"; + var PARENT_ID = "expo_top_events"; var getUrl = function () { - var data = window.sendData; + var search = []; - if (data instanceof Object) { - var search = []; + var parts = /^\/([^\/]+)(?:\/|$)/i.exec(location.pathname); + if (parts) { + search.push("catalog=" + encodeURIComponent(parts[1])); + } else { + search.push("catalog="); + } + var data = window.sendData; + if (data instanceof Object) { for (var key in data) { if (data.hasOwnProperty(key)) { var value = data[key]; @@ -22,16 +29,12 @@ } } } - - if (search.length) { - return API_URL_ROOT + "?" + search.join("&"); - } } - return API_URL_ROOT; + return API_URL_ROOT + "?" + search.join("&"); }; - var getBanners = function (url, callback) { + var getTops = function (url, callback) { var xhr = new XMLHttpRequest(); xhr.open("GET", url, true); @@ -39,7 +42,7 @@ if (event.target.readyState === 4) { if (event.target.status === 200) { try { - callback(JSON.parse(event.target.responseText)); + callback(event.target.responseText); } catch (error) { // do nothing } @@ -50,37 +53,16 @@ xhr.send(); }; - var addBanner = function (banner) { - var parent = document.getElementById(banner.id); + var insertTops = function (text) { + var parent = document.getElementById(PARENT_ID); if (parent) { - if (banner.is_img) { - var a = document.createElement("a"); - a.href = banner.url; - - var img = document.createElement("img"); - img.src = banner.img; - img.alt = banner.alt; - - a.appendChild(img); - parent.appendChild(a); - } else if (banner.is_html) { - parent.innerHTML = banner.text; - } - } - - }; - - var insertBanners = function (data) { - if (data instanceof Array) { - for (var i = 0, l = data.length; i < l; i++) { - addBanner(data[i]); - } + parent.innerHTML = text; } }; var main = function () { - getBanners(getUrl(), insertBanners); + getTops(getUrl(), insertTops); }; window.addEventListener("load", main); diff --git a/templates/client/static_client/js_min/_modules/block.common.min.js b/templates/client/static_client/js_min/_modules/block.common.min.js index bbe0ad18..ec08a27c 100644 --- a/templates/client/static_client/js_min/_modules/block.common.min.js +++ b/templates/client/static_client/js_min/_modules/block.common.min.js @@ -1 +1 @@ -var EXPO=EXPO||{};EXPO.common?console.warn("WARNING: EXPO.common is already defined!"):EXPO.common=function(){var e,t={},s=function(e,t){return(e.matches||e.matchesSelector||e.msMatchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.oMatchesSelector).call(e,t)};t.opt={};var r=function(e){this.fields=[],this.allIsClear=!1,this.ajaxUrl=e.getAttribute("action"),this.DOM=e,this._initFields(),this._eventController()};return r.prototype={_eventController:function(){var e=this;this.DOM.addEventListener?this.DOM.addEventListener("submit",function(t){return e.validate(),t.preventDefault(),!1},!1):this.DOM.attachEvent&&this.DOM.attachEvent("onsubmit",function(t){return e.validate(),t.preventDefault(),!1})},_initFields:function(){},validate:function(){var t,s=this,r=$(s.DOM).serialize(),o={},a="err-message-box",i=s.DOM.querySelector("."+a),n=i.innerHTML,l=function(r){var a,l;if(t=r,s.unHighlightFields(),t.success)i&&EXPO.common.removeClass(i,"active"),$(s.DOM).attr("id")==EXPO.common.opt.registerFormId?(a=$("#"+EXPO.common.opt.successRegisterId),l=$.trim($("#id_email",s.DOM).val()),$("."+EXPO.common.opt.resendLetterClass,a).attr("data-email",l),$.fancybox.close(!0),$.fancybox("#"+EXPO.common.opt.successRegisterId)):window.location.reload();else{EXPO.common.removeClass(i,"active"),o={},s.fields=[];for(var c in t.errors)t.errors.hasOwnProperty(c)&&("__all__"!=c?(o={name:c,id:"id_"+c,errorText:t.errors[c]},s.fields.push(o)):i&&(EXPO.common.addClass(i,"active"),n.indexOf(t.errors[c])<0&&i.insertAdjacentHTML("beforeend",t.errors[c]+" ")));s.highliteFields()}e.hide()};s.unHighlightFields(),e.show(),EXPO.common.postRequest(r,s.ajaxUrl,l)},highliteFields:function(){for(var e,t,s=0;s").attr("class","error").append(s);r.parent().addClass("required err").prepend(o)}))};"post"==o?$.post(s,r,a):$.get(s,r,a)}),$("form.simple-validate-register").on("submit",function(e){e.preventDefault();var t=$(this),s=t.attr("action"),r=$(this).serialize(),o=t.attr("method"),a=$("#pw-reg-complete"),i=$(".resend-letter",a),n=$.trim($("#id_email",t).val()),l=function(e){e.success?($(".error",t).remove(),$(".required.err",t).removeClass("required err"),$("input:text",t).val(""),$(".pwf-line .msg-help",t).each(function(){var e=$(this),t=e.attr("data-default");""!=$.trim(t)&&e.html("").text(t)}),i.attr("data-email",n),$.fancybox.close(!0),$.fancybox("#pw-reg-complete")):($(".error",t).remove(),$(".required.err",t).removeClass("required err"),$(".pwf-line .msg-help",t).each(function(){var e=$(this),t=e.attr("data-default");""!=$.trim(t)&&e.html("").text(t)}),$.each(e.errors,function(e,s){var r=$("#id_"+e,t),o=$("
      ").attr("class","error").append(s),a=r.closest(".pwf-line").find(".msg-help");r.parent().addClass("required err"),a.attr("data-default",a.text()),a.text("").prepend(o)}))};"post"==o?$.post(s,r,l):$.get(s,r,l)})}),$(function(){$.fancybox.helpers.overlay.overlay=$('
      ').appendTo("body"),$.fn.customRadioCheck=function(){return $(this).each(function(){function e(){if("radio"==s){var e=t.attr("name"),r=$('input[type="radio"]').filter('[name="'+e+'"]');r.each(function(){var e=$(this).closest(".custom-radio");e.removeClass("checked"),$(this).is(":checked")&&e.addClass("checked")})}else t.prop("checked")?o.addClass("checked"):o.removeClass("checked");t.trigger("blur")}var t=$(this),s=t.attr("type"),r=t.closest("label"),o=t.wrap("").parent();r.addClass("custom-radio-check"),e(),t.on("change",e)})},$("input[type='checkbox'], input[type='radio']").customRadioCheck()}),function(e){e.fn.inlineStyle=function(t){var s,r=this.attr("style");return r&&r.split(";").forEach(function(r){var o=r.split(":");e.trim(o[0])===t&&(s=o[1])}),s}}(jQuery),t.init=function(t){$.extend(this.opt,t);{var s,r=this,o=this.opt.addCalendarClass,a=this.opt.removeCalendarClass,i=this.opt.addCalendarText,n=this.opt.removeCalendarText,l=r.opt.staticValidation.errorClass,c=r.opt.staticValidation.containerClass;r.opt.staticValidation.blobClass}$(function(){s=$("."+l),e=$("#wait-ajax:not(.absolute)").css({"z-index":"8031"}),$("."+o+", ."+a).on("click",function(e){i=r.opt.addCalendarText,n=r.opt.removeCalendarText,e.preventDefault();var t=$(this),s=t.attr("href");$.get(s,function(e){e.not_authorized?$.fancybox.open("#"+r.opt.loginModalId):e.success&&(e.in?t.removeClass(o).addClass(a).text(n):t.removeClass(a).addClass(o).text(i))})}),s.length&&s.find("input:text").on("keyup",function(){""!=$.trim($(this).val())?$(this).closest("."+l).removeClass(l):$(this).closest("."+c).addClass(l)});for(var t=0;t=0;)r=r.replace(" "+s+" "," ");e.className=r.replace(/^\s+|\s+$/g," ")}return e},t.closest=function(e,s){for(var r=function(s){return t.hasClass(e,s)};e;){if(r(s))return e;e=e.parentNode}},t.children=function(e,t){for(var r,o=[],r=0,a=e.childNodes.length;a>r;++r)s(e.childNodes[r],t)&&o.push(e.childNodes[r]);return o},t.postRequest=function(e,t,s){e||(e=""),$.ajax({type:"POST",url:t,data:e,success:function(e){return"function"!=typeof s?e:(console.log("data recieved:"),console.log(e),console.log(JSON.stringify(e)),s(e),void 0)}})},t.getRequest=function(e,t,s){e||(e=""),$.ajax({type:"GET",url:t,data:e,success:function(e){return"function"!=typeof s?e:(console.log("data recieved:"),console.log(e),console.log(JSON.stringify(e)),s(e),void 0)}})},t.Modal=function(e){var t=this;this.id,this.opt=e,this.DOMwrap=document.getElementById(e.id),this.DOM=this.DOMwrap.querySelector("."+e.wrapClass),$(".modal-close",this.DOM).on("click",function(){t.close()}),$(".modals > *").on("click",function(e){$(e.target.parentNode).find(t.DOMwrap).length&&t.close()})},t.Modal.prototype={pullData:function(e){this.id=e.substr(1),$(e).show().siblings().hide(),this.refresh()},open:function(){$(this.DOMwrap).fadeIn(),t.addClass(document.body,"ov-hidden")},close:function(){$(this.DOMwrap).fadeOut(),t.removeClass(document.body,"ov-hidden")},refresh:function(){var e=this;e.DOM.style.width=e.opt.size[e.id].width+"px",e.DOM.style.minHeight=e.opt.size[e.id].height+"px",e.DOM.style.marginLeft=-(e.opt.size[e.id].width/2)+"px",e.DOM.style.marginTop=-(e.opt.size[e.id].height/2)+"px"}},t.SEOhide={seoContent:{},seoHrefs:{},decode:function(e){for(var t=$("["+e+"]"),s=0,r=t.length;r>s;s++){var o=t.eq(s),a=o.attr("data-hash");switch(o.data("type")){case"href":o.attr("href",Base64.decode(this.seoHrefs[a]));break;case"content":o.replaceWith(Base64.decode(this.seoContent[a]))}}}},t.nl2br=function(e,t){var s=t||"undefined"==typeof t?"
      ":"
      ";return(e+"").replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g,"$1"+s+"$2")},t}(); \ No newline at end of file +var EXPO=EXPO||{};EXPO.common?console.warn("WARNING: EXPO.common is already defined!"):EXPO.common=function(){var e,t={},s=function(e,t){return(e.matches||e.matchesSelector||e.msMatchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.oMatchesSelector).call(e,t)};t.opt={};var r=function(e){this.fields=[],this.allIsClear=!1,this.ajaxUrl=e.getAttribute("action"),this.DOM=e,this._initFields(),this._eventController()};return r.prototype={_eventController:function(){var e=this;this.DOM.addEventListener?this.DOM.addEventListener("submit",function(t){return e.validate(),t.preventDefault(),!1},!1):this.DOM.attachEvent&&this.DOM.attachEvent("onsubmit",function(t){return e.validate(),t.preventDefault(),!1})},_initFields:function(){},validate:function(){var t,s=this,r=$(s.DOM).serialize(),o={},a="err-message-box",i=s.DOM.querySelector("."+a),n=i.innerHTML,l=function(r){var a,l;if(t=r,s.unHighlightFields(),t.success)i&&EXPO.common.removeClass(i,"active"),$(s.DOM).attr("id")==EXPO.common.opt.registerFormId?(a=$("#"+EXPO.common.opt.successRegisterId),l=$.trim($("#id_email",s.DOM).val()),$("."+EXPO.common.opt.resendLetterClass,a).attr("data-email",l),$.fancybox.close(!0),$.fancybox("#"+EXPO.common.opt.successRegisterId)):window.location.reload();else{EXPO.common.removeClass(i,"active"),o={},s.fields=[];for(var c in t.errors)t.errors.hasOwnProperty(c)&&("__all__"!=c?(o={name:c,id:"id_"+c,errorText:t.errors[c]},s.fields.push(o)):i&&(EXPO.common.addClass(i,"active"),n.indexOf(t.errors[c])<0&&i.insertAdjacentHTML("beforeend",t.errors[c]+" ")));s.highliteFields()}e.hide()};s.unHighlightFields(),e.show(),EXPO.common.postRequest(r,s.ajaxUrl,l)},highliteFields:function(){for(var e,t,s=0;s").attr("class","error").append(s);r.parent().addClass("required err").prepend(o)}))};"post"==o?$.post(s,r,a):$.get(s,r,a)}),$("form.simple-validate-register").on("submit",function(e){e.preventDefault();var t=$(this),s=t.attr("action"),r=$(this).serialize(),o=t.attr("method"),a=$("#pw-reg-complete"),i=$(".resend-letter",a),n=$.trim($("#id_email",t).val()),l=function(e){e.success?($(".error",t).remove(),$(".required.err",t).removeClass("required err"),$("input:text",t).val(""),$(".pwf-line .msg-help",t).each(function(){var e=$(this),t=e.attr("data-default");""!=$.trim(t)&&e.html("").text(t)}),i.attr("data-email",n),$.fancybox.close(!0),$.fancybox("#pw-reg-complete")):($(".error",t).remove(),$(".required.err",t).removeClass("required err"),$(".pwf-line .msg-help",t).each(function(){var e=$(this),t=e.attr("data-default");""!=$.trim(t)&&e.html("").text(t)}),$.each(e.errors,function(e,s){var r=$("#id_"+e,t),o=$("
      ").attr("class","error").append(s),a=r.closest(".pwf-line").find(".msg-help");r.parent().addClass("required err"),a.attr("data-default",a.text()),a.text("").prepend(o)}))};"post"==o?$.post(s,r,l):$.get(s,r,l)})}),$(function(){$.fancybox.helpers.overlay.overlay=$('
      ').appendTo("body"),$.fn.customRadioCheck=function(){return $(this).each(function(){function e(){if("radio"==s){var e=t.attr("name"),r=$('input[type="radio"]').filter('[name="'+e+'"]');r.each(function(){var e=$(this).closest(".custom-radio");e.removeClass("checked"),$(this).is(":checked")&&e.addClass("checked")})}else t.prop("checked")?o.addClass("checked"):o.removeClass("checked");t.trigger("blur")}var t=$(this),s=t.attr("type"),r=t.closest("label"),o=t.wrap("").parent();r.addClass("custom-radio-check"),e(),t.on("change",e)})},$("input[type='checkbox'], input[type='radio']").customRadioCheck()}),function(e){e.fn.inlineStyle=function(t){var s,r=this.attr("style");return r&&r.split(";").forEach(function(r){var o=r.split(":");e.trim(o[0])===t&&(s=o[1])}),s}}(jQuery),t.init=function(t){$.extend(this.opt,t);{var s,r=this,o=this.opt.addCalendarClass,a=this.opt.removeCalendarClass,i=this.opt.addCalendarText,n=this.opt.removeCalendarText,l=r.opt.staticValidation.errorClass,c=r.opt.staticValidation.containerClass;r.opt.staticValidation.blobClass}$(function(){s=$("."+l),e=$("#wait-ajax:not(.absolute)").css({"z-index":"8031"}),$("body").on("click","."+o+", ."+a,function(e){i=r.opt.addCalendarText,n=r.opt.removeCalendarText,e.preventDefault();var t=$(this),s=t.attr("href");$.get(s,function(e){e.not_authorized?$.fancybox.open("#"+r.opt.loginModalId):e.success&&(e.in?t.removeClass(o).addClass(a).text(n):t.removeClass(a).addClass(o).text(i))})}),s.length&&s.find("input:text").on("keyup",function(){""!=$.trim($(this).val())?$(this).closest("."+l).removeClass(l):$(this).closest("."+c).addClass(l)});for(var t=0;t=0;)r=r.replace(" "+s+" "," ");e.className=r.replace(/^\s+|\s+$/g," ")}return e},t.closest=function(e,s){for(var r=function(s){return t.hasClass(e,s)};e;){if(r(s))return e;e=e.parentNode}},t.children=function(e,t){for(var r,o=[],r=0,a=e.childNodes.length;a>r;++r)s(e.childNodes[r],t)&&o.push(e.childNodes[r]);return o},t.postRequest=function(e,t,s){e||(e=""),$.ajax({type:"POST",url:t,data:e,success:function(e){return"function"!=typeof s?e:(console.log("data recieved:"),console.log(e),console.log(JSON.stringify(e)),s(e),void 0)}})},t.getRequest=function(e,t,s){e||(e=""),$.ajax({type:"GET",url:t,data:e,success:function(e){return"function"!=typeof s?e:(console.log("data recieved:"),console.log(e),console.log(JSON.stringify(e)),s(e),void 0)}})},t.Modal=function(e){var t=this;this.id,this.opt=e,this.DOMwrap=document.getElementById(e.id),this.DOM=this.DOMwrap.querySelector("."+e.wrapClass),$(".modal-close",this.DOM).on("click",function(){t.close()}),$(".modals > *").on("click",function(e){$(e.target.parentNode).find(t.DOMwrap).length&&t.close()})},t.Modal.prototype={pullData:function(e){this.id=e.substr(1),$(e).show().siblings().hide(),this.refresh()},open:function(){$(this.DOMwrap).fadeIn(),t.addClass(document.body,"ov-hidden")},close:function(){$(this.DOMwrap).fadeOut(),t.removeClass(document.body,"ov-hidden")},refresh:function(){var e=this;e.DOM.style.width=e.opt.size[e.id].width+"px",e.DOM.style.minHeight=e.opt.size[e.id].height+"px",e.DOM.style.marginLeft=-(e.opt.size[e.id].width/2)+"px",e.DOM.style.marginTop=-(e.opt.size[e.id].height/2)+"px"}},t.SEOhide={seoContent:{},seoHrefs:{},decode:function(e){for(var t=$("["+e+"]"),s=0,r=t.length;r>s;s++){var o=t.eq(s),a=o.attr("data-hash");switch(o.data("type")){case"href":o.attr("href",Base64.decode(this.seoHrefs[a]));break;case"content":o.replaceWith(Base64.decode(this.seoContent[a]))}}}},t.nl2br=function(e,t){var s=t||"undefined"==typeof t?"
      ":"
      ";return(e+"").replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g,"$1"+s+"$2")},t}(); \ No newline at end of file