--- /dev/null
+# -*- encoding: utf-8 -*-
+__author__ = u'Marek Stępniowski, <marek@stepniowski.com>'
+__version__ = '0.1'
--- /dev/null
+from django.db import models
+from django.contrib import admin
+
+from sponsors.models import Sponsor, SponsorGroup
+from sponsors.widgets import OrderedSelectMultiple
+
+class SponsorGroupAdmin(admin.ModelAdmin):
+ formfield_overrides = {
+ models.CommaSeparatedIntegerField: {'widget': OrderedSelectMultiple},
+ }
+ list_display = ('name',)
+ search_fields = ('name',)
+ ordering = ('name',)
+
+class SponsorAdmin(admin.ModelAdmin):
+ list_display = ('name',)
+ search_fields = ('name',)
+ ordering = ('name',)
+
+admin.site.register(SponsorGroup, SponsorGroupAdmin)
+admin.site.register(Sponsor, SponsorAdmin)
--- /dev/null
+from django.db import models
+from django.utils.translation import ugettext_lazy as _
+
+
+class Sponsor(models.Model):
+ name = models.CharField(_('name'), max_length=120)
+ _description = models.CharField(_('description'), blank=True, max_length=255)
+ logo = models.ImageField(_('logo'), upload_to='sponsors/sponsor/logo')
+ url = models.URLField(_('url'), blank=True, verify_exists=False)
+
+ def __unicode__(self):
+ return self.name
+
+ def description(self):
+ if len(self._description):
+ return self._description
+ else:
+ return self.name
+
+
+class SponsorGroup(models.Model):
+ name = models.CharField(_('name'), max_length=120)
+ order = models.IntegerField(_('order'), default=0)
+ column_width = models.PositiveIntegerField(_('column width'))
+ sponsor_ids = models.CommaSeparatedIntegerField(_('sponsors'), max_length=255)
+
+ def sponsors(self):
+ ids = [int(pk) for pk in self.sponsor_ids.split(',')]
+ result = Sponsor.objects.in_bulk(ids)
+ return [result[pk] for pk in ids]
+ sponsors.changes_data = False
+
+ def __unicode__(self):
+ return self.name
+
--- /dev/null
+.sponsor-group {
+ float: left;
+ overflow: hidden;
+}
--- /dev/null
+(function($) {
+ $.fn.orderedSelectMultiple = function(options) {
+ var settings = {
+ choices: []
+ };
+ $.extend(settings, options);
+
+ var input = $(this).hide();
+ var values = input.val().split(',');
+
+ var container = $('<div></div>').insertAfter($(this));
+ var choicesList = $('<ol class="choices connectedSortable"></ol>').appendTo(container).css({
+ width: 200, float: 'left', minHeight: 200, backgroundColor: '#eee', margin: 0, padding: 0
+ });
+ var valuesList = $('<ol class="values connectedSortable"></ol>').appendTo(container).css({
+ width: 200, float: 'left', minHeight: 200, backgroundColor: '#eee', margin: 0, padding: 0
+ });
+ var choiceIds = [];
+ $.each(settings.choices, function() {
+ choiceIds.push('' + this.id);
+ });
+
+ function createItem(hash) {
+ return $('<li>' + hash.name + '</li>').css({
+ backgroundColor: '#cff',
+ display: 'block',
+ border: '1px solid #cdd',
+ padding: 2,
+ margin: 0
+ }).data('obj-id', hash.id);
+ }
+
+ $.each(settings.choices, function() {
+ if ($.inArray('' + this.id, values) == -1) {
+ choicesList.append(createItem(this));
+ }
+ });
+
+ $.each(values, function() {
+ var index = $.inArray('' + this, choiceIds); // Why this[0]?
+ if (index != -1) {
+ valuesList.append(createItem(settings.choices[index]));
+ }
+ });
+
+ choicesList.sortable({
+ connectWith: '.connectedSortable'
+ }).disableSelection();
+
+ valuesList.sortable({
+ connectWith: '.connectedSortable',
+ update: function() {
+ values = [];
+ $('li', valuesList).each(function(index) {
+ values.push($(this).data('obj-id'));
+ console.log($(this).data('obj-id'));
+ });
+ console.log('update', values.join(','), input);
+ input.val(values.join(','));
+ }
+ }).disableSelection();
+ };
+})(jQuery);
--- /dev/null
+<div class="sponsors">
+{% for group in sponsor_groups %}
+ <div class="sponsor-group" style="width: {{ group.column_width }}px">
+ <p class="sponsor-group-name">{{ group.name }}</p>
+ {% for sponsor in group.sponsors %}
+ <div class="sponsor">{% if sponsor.url %}<a style="sponsor-link" href="{{ sponsor.url }}" >{% endif %}<img class="sponsor-logo" src="{{ sponsor.logo.url }}" alt="{{ sponsor.description }}"/>{% if sponsor.url %}</a>{% endif %}</div>
+ {% endfor %}
+ </div>
+{% endfor %}
+<div style="clear: both" />
+</div>
--- /dev/null
+from django import template
+
+from sponsors import models
+
+
+register = template.Library()
+
+
+def sponsors():
+ return {'sponsor_groups': models.SponsorGroup.objects.all()}
+
+compressed_js = register.inclusion_tag('sponsors/sponsors.html')(sponsors)
--- /dev/null
+from django import forms
+from django.conf import settings
+from django.utils.safestring import mark_safe
+from django.utils.translation import ugettext_lazy as _
+
+from sponsors import models
+
+
+class OrderedSelectMultiple(forms.TextInput):
+ """
+ A SelectMultiple with a JavaScript interface.
+ """
+ class Media:
+ js = (
+ 'http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js',
+ 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.1/jquery-ui.min.js',
+ settings.MEDIA_URL + 'js/ordered_select_multiple.js',
+ )
+
+ def render(self, name, value, attrs=None, choices=()):
+ output = [super(OrderedSelectMultiple, self).render(name, value, attrs)]
+ choices = [(unicode(obj), obj.pk) for obj in models.Sponsor.objects.all()]
+ choices_js = ', '.join('{name: "%s", id: %d}' % choice for choice in choices)
+ output.append(u'<script type="text/javascript">addEvent(window, "load", function(e) {')
+ # TODO: "id_" is hard-coded here. This should instead use the correct
+ # API to determine the ID dynamically.
+ output.append(u'$("#id_%s").orderedSelectMultiple({choices: [%s]}); });</script>\n' %
+ (name, choices_js))
+ return mark_safe(u''.join(output))
+
--- /dev/null
+.sponsor-group {
+ float: left;
+ overflow: hidden;
+}
+
+.sponsor-logo {
+ float: left;
+}
\ No newline at end of file
--- /dev/null
+(function($) {
+ $.fn.orderedSelectMultiple = function(options) {
+ var settings = {
+ choices: []
+ };
+ $.extend(settings, options);
+
+ var input = $(this).hide();
+ var values = input.val().split(',');
+
+ var container = $('<div></div>').insertAfter($(this));
+ var choicesList = $('<ol class="choices connectedSortable"></ol>').appendTo(container).css({
+ width: 200, float: 'left', minHeight: 200, backgroundColor: '#eee', margin: 0, padding: 0
+ });
+ var valuesList = $('<ol class="values connectedSortable"></ol>').appendTo(container).css({
+ width: 200, float: 'left', minHeight: 200, backgroundColor: '#eee', margin: 0, padding: 0
+ });
+ var choiceIds = [];
+ $.each(settings.choices, function() {
+ choiceIds.push('' + this.id);
+ });
+
+ function createItem(hash) {
+ return $('<li>' + hash.name + '</li>').css({
+ backgroundColor: '#cff',
+ display: 'block',
+ border: '1px solid #cdd',
+ padding: 2,
+ margin: 0
+ }).data('obj-id', hash.id);
+ }
+
+ $.each(settings.choices, function() {
+ if ($.inArray('' + this.id, values) == -1) {
+ choicesList.append(createItem(this));
+ }
+ });
+
+ $.each(values, function() {
+ var index = $.inArray('' + this, choiceIds); // Why this[0]?
+ if (index != -1) {
+ valuesList.append(createItem(settings.choices[index]));
+ }
+ });
+
+ choicesList.sortable({
+ connectWith: '.connectedSortable'
+ }).disableSelection();
+
+ valuesList.sortable({
+ connectWith: '.connectedSortable',
+ update: function() {
+ values = [];
+ $('li', valuesList).each(function(index) {
+ values.push($(this).data('obj-id'));
+ console.log($(this).data('obj-id'));
+ });
+ console.log('update', values.join(','), input);
+ input.val(values.join(','));
+ }
+ }).disableSelection();
+ };
+})(jQuery);
# external
'south',
+ 'sponsors',
'newtagging',
'pagination',
'chunks',
# CSS and JavaScript file groups
COMPRESS_CSS = {
'all': {
- 'source_filenames': ('css/master.css', 'css/jquery.autocomplete.css', 'css/master.plain.css',),
+ 'source_filenames': ('css/master.css', 'css/jquery.autocomplete.css', 'css/master.plain.css', 'css/sponsors.css',),
'output_filename': 'css/all.min.css',
},
'book': {
-{% load chunks compressed catalogue_tags %}
+{% load chunks compressed catalogue_tags sponsor_tags %}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
Fundacja Nowoczesna Polska, 00-514 Warszawa, ul. Marszałkowska 84/92 lok. 125, tel/fax: (22) 621-30-17,
e-mail: <a href="mailto:fundacja@nowoczesnapolska.org.pl">fundacja@nowoczesnapolska.org.pl</a>
</p>
-<p>
- <img src="{% attachment 'footer-img' %}" usemap="#footermap" alt="Partnerzy serwisu" />
-<MAP NAME="footermap">{% chunk 'footer-map' %}</MAP>
-</p>
+ {% sponsors %}
</div>
<div id="login-register-window">
<div class="header"><a href="#" class="jqmClose">Zamknij</a></div>