- Added librarian as a submodule.
authorŁukasz Rekucki <lrekucki@gmail.com>
Tue, 15 Jun 2010 23:50:00 +0000 (01:50 +0200)
committerŁukasz Rekucki <lrekucki@gmail.com>
Tue, 15 Jun 2010 23:50:00 +0000 (01:50 +0200)
- Split tests in catalouge into a package.
- Don't write to actual MEDIA_ROOT during tests.
- Fixed trailing whitespace.

118 files changed:
.gitmodules [new file with mode: 0644]
apps/api/handlers.py
apps/catalogue/admin.py
apps/catalogue/fields.py
apps/catalogue/forms.py
apps/catalogue/management/commands/importbooks.py
apps/catalogue/migrations/0001_initial.py
apps/catalogue/migrations/0002_auto__add_bookstub__add_field_tag_death.py
apps/catalogue/migrations/0003_fix_book_count_on_shelves.py
apps/catalogue/migrations/0004_book_html_shorts_translations.py
apps/catalogue/migrations/0005_fragment_html_shorts_translations.py
apps/catalogue/migrations/0006_epub_tag_counters_and_ltags_descendants.py
apps/catalogue/migrations/0007_remove_empty_html.py
apps/catalogue/migrations/0008_unique_tag_category_slug.py
apps/catalogue/models.py
apps/catalogue/templatetags/catalogue_tags.py
apps/catalogue/templatetags/switch_tag.py
apps/catalogue/test_utils.py [new file with mode: 0644]
apps/catalogue/tests.py [deleted file]
apps/catalogue/tests/__init__.py [new file with mode: 0644]
apps/catalogue/tests/book_import.py [new file with mode: 0644]
apps/catalogue/tests/search.py [new file with mode: 0644]
apps/catalogue/tests/tags.py [new file with mode: 0644]
apps/catalogue/urls.py
apps/catalogue/utils.py
apps/catalogue/views.py
apps/chunks/models.py
apps/chunks/templatetags/chunks.py
apps/compress/filter_base.py
apps/compress/filters/csstidy/__init__.py
apps/compress/filters/csstidy_python/__init__.py
apps/compress/management/commands/synccompress.py
apps/compress/utils.py
apps/infopages/migrations/0001_initial.py
apps/infopages/models.py
apps/lessons/models.py
apps/lessons/urls.py
apps/lessons/views.py
apps/newtagging/admin.py
apps/newtagging/managers.py
apps/newtagging/models.py
apps/piston/authentication.py
apps/piston/decorator.py
apps/piston/doc.py
apps/piston/emitters.py
apps/piston/forms.py
apps/piston/handler.py
apps/piston/managers.py
apps/piston/models.py
apps/piston/oauth.py
apps/piston/resource.py
apps/piston/signals.py
apps/piston/store.py
apps/piston/templates/documentation.html
apps/piston/templates/piston/authorize_token.html
apps/piston/test.py
apps/piston/tests.py
apps/piston/utils.py
apps/sponsors/admin.py
apps/sponsors/fields.py
apps/sponsors/migrations/0001_initial.py
apps/sponsors/models.py
apps/sponsors/static/sponsors/js/footer_admin.js
apps/sponsors/templatetags/sponsor_tags.py
apps/sponsors/widgets.py
apps/suggest/migrations/0001_initial.py
apps/suggest/models.py
apps/suggest/urls.py
apps/suggest/views.py
fabfile.py
lib/librarian [new submodule]
lib/markupstring.py
lib/slughifi.py
requirements.txt
scripts/conv_genre_families.py
scripts/irename.py
scripts/setmainpage.py
wolnelektury/manage.py
wolnelektury/middleware.py
wolnelektury/settings.py
wolnelektury/static/js/book.js
wolnelektury/static/js/catalogue.js
wolnelektury/static/js/jquery.autocomplete.js
wolnelektury/static/js/jquery.countdown-de.js
wolnelektury/static/js/jquery.countdown-es.js
wolnelektury/static/js/jquery.countdown-fr.js
wolnelektury/static/js/jquery.countdown-pl.js
wolnelektury/static/js/jquery.countdown-ru.js
wolnelektury/static/js/jquery.countdown-uk.js
wolnelektury/static/js/jquery.countdown.js
wolnelektury/static/js/jquery.eventdelegation.js
wolnelektury/static/js/jquery.form.js
wolnelektury/static/js/jquery.highlightfade.js
wolnelektury/static/js/jquery.jqmodal.js
wolnelektury/static/js/jquery.labelify.js
wolnelektury/static/js/jquery.scrollto.js
wolnelektury/static/js/ordered_select_multiple.js
wolnelektury/static/sponsors/js/footer_admin.js
wolnelektury/templates/1percent.html
wolnelektury/templates/404.html
wolnelektury/templates/500.html
wolnelektury/templates/503.html
wolnelektury/templates/auth/login.html
wolnelektury/templates/base.html
wolnelektury/templates/catalogue/book_detail.html
wolnelektury/templates/catalogue/book_list.html
wolnelektury/templates/catalogue/book_stub_detail.html
wolnelektury/templates/catalogue/differentiate_tags.html
wolnelektury/templates/catalogue/folded_tag_list.html
wolnelektury/templates/catalogue/main_page.html
wolnelektury/templates/catalogue/pd_counter.html
wolnelektury/templates/catalogue/search_multiple_hits.html
wolnelektury/templates/catalogue/search_no_hits.html
wolnelektury/templates/catalogue/search_too_short.html
wolnelektury/templates/catalogue/tagged_object_list.html
wolnelektury/templates/lessons/document_detail.html
wolnelektury/templates/lessons/document_list.html
wolnelektury/urls.py

diff --git a/.gitmodules b/.gitmodules
new file mode 100644 (file)
index 0000000..56b9c42
--- /dev/null
@@ -0,0 +1,3 @@
+[submodule "lib/librarian"]
+       path = lib/librarian
+       url = git://github.com/fnp/librarian.git
index 799b608..40121d6 100644 (file)
@@ -16,14 +16,14 @@ staff_required = user_passes_test(lambda user: user.is_staff)
 class BookHandler(BaseHandler):
     model = Book
     fields = ('slug', 'title')
 class BookHandler(BaseHandler):
     model = Book
     fields = ('slug', 'title')
-    
+
     @staff_required
     def read(self, request, slug=None):
         if slug:
             return get_object_or_404(Book, slug=slug)
         else:
             return Book.objects.all()
     @staff_required
     def read(self, request, slug=None):
         if slug:
             return get_object_or_404(Book, slug=slug)
         else:
             return Book.objects.all()
-    
+
     @staff_required
     def create(self, request):
         form = BookImportForm(request.POST, request.FILES)
     @staff_required
     def create(self, request):
         form = BookImportForm(request.POST, request.FILES)
index b2744ee..0275094 100644 (file)
@@ -20,7 +20,7 @@ class TagAdmin(admin.ModelAdmin):
 
 class BookAdmin(TaggableModelAdmin):
     tag_model = Tag
 
 class BookAdmin(TaggableModelAdmin):
     tag_model = Tag
-    
+
     list_display = ('title', 'slug', 'has_pdf_file', 'has_epub_file', 'has_odt_file', 'has_html_file', 'has_description',)
     search_fields = ('title',)
     ordering = ('title',)
     list_display = ('title', 'slug', 'has_pdf_file', 'has_epub_file', 'has_odt_file', 'has_html_file', 'has_description',)
     search_fields = ('title',)
     ordering = ('title',)
@@ -30,14 +30,14 @@ class BookAdmin(TaggableModelAdmin):
 
 class FragmentAdmin(TaggableModelAdmin):
     tag_model = Tag
 
 class FragmentAdmin(TaggableModelAdmin):
     tag_model = Tag
-    
+
     list_display = ('book', 'anchor',)
     ordering = ('book', 'anchor',)
 
 
 class BookStubAdmin(admin.ModelAdmin):
     # tag_model = Tag
     list_display = ('book', 'anchor',)
     ordering = ('book', 'anchor',)
 
 
 class BookStubAdmin(admin.ModelAdmin):
     # tag_model = Tag
-    
+
     list_display = ('title', 'author', 'slug','pd')
     search_fields = ('title','author')
     ordering = ('title',)
     list_display = ('title', 'author', 'slug','pd')
     search_fields = ('title','author')
     ordering = ('title',)
index ded6f0e..62ca29c 100644 (file)
@@ -123,7 +123,7 @@ try:
     (
         [JSONField], # Class(es) these apply to
         [], # Positional arguments (not used)
     (
         [JSONField], # Class(es) these apply to
         [], # Positional arguments (not used)
-        {}, # Keyword argument           
+        {}, # Keyword argument
     ), ], ["^catalogue\.fields\.JSONField"])
 except ImportError:
     pass
     ), ], ["^catalogue\.fields\.JSONField"])
 except ImportError:
     pass
index 60a99cd..d217824 100644 (file)
@@ -21,7 +21,7 @@ class BookImportForm(forms.Form):
 class SearchForm(forms.Form):
     q = JQueryAutoCompleteField('/katalog/tags/', {'minChars': 2, 'selectFirst': True, 'cacheLength': 50, 'matchContains': "word"})
     tags = forms.CharField(widget=forms.HiddenInput, required=False)
 class SearchForm(forms.Form):
     q = JQueryAutoCompleteField('/katalog/tags/', {'minChars': 2, 'selectFirst': True, 'cacheLength': 50, 'matchContains': "word"})
     tags = forms.CharField(widget=forms.HiddenInput, required=False)
-    
+
     def __init__(self, *args, **kwargs):
         tags = kwargs.pop('tags', [])
         super(SearchForm, self).__init__(*args, **kwargs)
     def __init__(self, *args, **kwargs):
         tags = kwargs.pop('tags', [])
         super(SearchForm, self).__init__(*args, **kwargs)
@@ -39,7 +39,7 @@ class UserSetsForm(forms.Form):
 
 
 class ObjectSetsForm(forms.Form):
 
 
 class ObjectSetsForm(forms.Form):
-    def __init__(self, obj, user, *args, **kwargs):        
+    def __init__(self, obj, user, *args, **kwargs):
         super(ObjectSetsForm, self).__init__(*args, **kwargs)
         self.fields['set_ids'] = forms.MultipleChoiceField(
             label=_('Shelves'),
         super(ObjectSetsForm, self).__init__(*args, **kwargs)
         self.fields['set_ids'] = forms.MultipleChoiceField(
             label=_('Shelves'),
@@ -48,20 +48,20 @@ class ObjectSetsForm(forms.Form):
             initial=[tag.id for tag in obj.tags.filter(category='set', user=user)],
             widget=forms.CheckboxSelectMultiple
         )
             initial=[tag.id for tag in obj.tags.filter(category='set', user=user)],
             widget=forms.CheckboxSelectMultiple
         )
-        
+
 
 class NewSetForm(forms.Form):
     name = forms.CharField(max_length=50, required=True)
 
 class NewSetForm(forms.Form):
     name = forms.CharField(max_length=50, required=True)
-    
+
     def __init__(self, *args, **kwargs):
         super(NewSetForm, self).__init__(*args, **kwargs)
         self.fields['name'].widget.attrs['title'] = _('Name of the new shelf')
     def __init__(self, *args, **kwargs):
         super(NewSetForm, self).__init__(*args, **kwargs)
         self.fields['name'].widget.attrs['title'] = _('Name of the new shelf')
-        
+
     def save(self, user, commit=True):
         name = self.cleaned_data['name']
         new_set = Tag(name=name, slug=utils.get_random_hash(name), sort_key=slughifi(name),
             category='set', user=user)
     def save(self, user, commit=True):
         name = self.cleaned_data['name']
         new_set = Tag(name=name, slug=utils.get_random_hash(name), sort_key=slughifi(name),
             category='set', user=user)
-        
+
         new_set.save()
         return new_set
 
         new_set.save()
         return new_set
 
@@ -78,7 +78,7 @@ FORMATS = (
 
 class DownloadFormatsForm(forms.Form):
     formats = forms.MultipleChoiceField(required=False, choices=FORMATS, widget=forms.CheckboxSelectMultiple)
 
 class DownloadFormatsForm(forms.Form):
     formats = forms.MultipleChoiceField(required=False, choices=FORMATS, widget=forms.CheckboxSelectMultiple)
-    
+
     def __init__(self, *args, **kwargs):
          super(DownloadFormatsForm, self).__init__(*args, **kwargs)
 
     def __init__(self, *args, **kwargs):
          super(DownloadFormatsForm, self).__init__(*args, **kwargs)
 
index c5fbb2e..cead75f 100644 (file)
@@ -39,7 +39,7 @@ class Command(BaseCommand):
 
         files_imported = 0
         files_skipped = 0
 
         files_imported = 0
         files_skipped = 0
-        
+
         for dir_name in directories:
             if not os.path.isdir(dir_name):
                 print self.style.ERROR("%s: Not a directory. Skipping." % dir_name)
         for dir_name in directories:
             if not os.path.isdir(dir_name):
                 print self.style.ERROR("%s: Not a directory. Skipping." % dir_name)
@@ -47,30 +47,30 @@ class Command(BaseCommand):
                 for file_name in os.listdir(dir_name):
                     file_path = os.path.join(dir_name, file_name)
                     file_base, ext = os.path.splitext(file_path)
                 for file_name in os.listdir(dir_name):
                     file_path = os.path.join(dir_name, file_name)
                     file_base, ext = os.path.splitext(file_path)
-                    
+
                     # Skip files that are not XML files
                     if not ext == '.xml':
                         continue
                     # Skip files that are not XML files
                     if not ext == '.xml':
                         continue
-                    
+
                     if verbose > 0:
                         print "Parsing '%s'" % file_path
                     else:
                         sys.stdout.write('.')
                         sys.stdout.flush()
                     if verbose > 0:
                         print "Parsing '%s'" % file_path
                     else:
                         sys.stdout.write('.')
                         sys.stdout.flush()
-                    
+
                     # Import book files
                     try:
                         book = Book.from_xml_file(file_path, overwrite=force)
                         files_imported += 1
                     # Import book files
                     try:
                         book = Book.from_xml_file(file_path, overwrite=force)
                         files_imported += 1
-                        
+
                         if os.path.isfile(file_base + '.pdf'):
                             book.pdf_file.save('%s.pdf' % book.slug, File(file(file_base + '.pdf')))
                             if verbose:
                         if os.path.isfile(file_base + '.pdf'):
                             book.pdf_file.save('%s.pdf' % book.slug, File(file(file_base + '.pdf')))
                             if verbose:
-                                print "Importing %s.pdf" % file_base 
+                                print "Importing %s.pdf" % file_base
                         if os.path.isfile(file_base + '.epub'):
                             book.epub_file.save('%s.epub' % book.slug, File(file(file_base + '.epub')))
                             if verbose:
                         if os.path.isfile(file_base + '.epub'):
                             book.epub_file.save('%s.epub' % book.slug, File(file(file_base + '.epub')))
                             if verbose:
-                                print "Importing %s.epub" % file_base 
+                                print "Importing %s.epub" % file_base
                         if os.path.isfile(file_base + '.odt'):
                             book.odt_file.save('%s.odt' % book.slug, File(file(file_base + '.odt')))
                             if verbose:
                         if os.path.isfile(file_base + '.odt'):
                             book.odt_file.save('%s.odt' % book.slug, File(file(file_base + '.odt')))
                             if verbose:
@@ -87,20 +87,20 @@ class Command(BaseCommand):
                             book.ogg_file.save('%s.ogg' % book.slug, File(file(os.path.join(dir_name, book.slug + '.ogg'))))
                             if verbose:
                                 print "Importing %s.ogg" % book.slug
                             book.ogg_file.save('%s.ogg' % book.slug, File(file(os.path.join(dir_name, book.slug + '.ogg'))))
                             if verbose:
                                 print "Importing %s.ogg" % book.slug
-                            
+
                         book.save()
                         book.save()
-                    
+
                     except Book.AlreadyExists, msg:
                         print self.style.ERROR('%s: Book already imported. Skipping. To overwrite use --force.' %
                             file_path)
                         files_skipped += 1
                     except Book.AlreadyExists, msg:
                         print self.style.ERROR('%s: Book already imported. Skipping. To overwrite use --force.' %
                             file_path)
                         files_skipped += 1
-                        
+
         # Print results
         print
         print "Results: %d files imported, %d skipped, %d total." % (
             files_imported, files_skipped, files_imported + files_skipped)
         print
         # Print results
         print
         print "Results: %d files imported, %d skipped, %d total." % (
             files_imported, files_skipped, files_imported + files_skipped)
         print
-                        
+
         transaction.commit()
         transaction.leave_transaction_management()
 
         transaction.commit()
         transaction.leave_transaction_management()
 
index 05ba18d..2aabb82 100644 (file)
@@ -5,9 +5,9 @@ from south.v2 import SchemaMigration
 from django.db import models
 
 class Migration(SchemaMigration):
 from django.db import models
 
 class Migration(SchemaMigration):
-    
+
     def forwards(self, orm):
     def forwards(self, orm):
-        
+
         # Adding model 'Tag'
         db.create_table('catalogue_tag', (
             ('category', self.gf('django.db.models.fields.CharField')(max_length=50, db_index=True)),
         # Adding model 'Tag'
         db.create_table('catalogue_tag', (
             ('category', self.gf('django.db.models.fields.CharField')(max_length=50, db_index=True)),
@@ -69,10 +69,10 @@ class Migration(SchemaMigration):
             ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
         ))
         db.send_create_signal('catalogue', ['Fragment'])
             ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
         ))
         db.send_create_signal('catalogue', ['Fragment'])
-    
-    
+
+
     def backwards(self, orm):
     def backwards(self, orm):
-        
+
         # Deleting model 'Tag'
         db.delete_table('catalogue_tag')
 
         # Deleting model 'Tag'
         db.delete_table('catalogue_tag')
 
@@ -87,8 +87,8 @@ class Migration(SchemaMigration):
 
         # Deleting model 'Fragment'
         db.delete_table('catalogue_fragment')
 
         # Deleting model 'Fragment'
         db.delete_table('catalogue_fragment')
-    
-    
+
+
     models = {
         'auth.group': {
             'Meta': {'object_name': 'Group'},
     models = {
         'auth.group': {
             'Meta': {'object_name': 'Group'},
@@ -178,5 +178,5 @@ class Migration(SchemaMigration):
             'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
         }
     }
             'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
         }
     }
-    
+
     complete_apps = ['catalogue']
     complete_apps = ['catalogue']
index 508f957..c278a83 100644 (file)
@@ -5,9 +5,9 @@ from south.v2 import SchemaMigration
 from django.db import models
 
 class Migration(SchemaMigration):
 from django.db import models
 
 class Migration(SchemaMigration):
-    
+
     def forwards(self, orm):
     def forwards(self, orm):
-        
+
         # Adding model 'BookStub'
         db.create_table('catalogue_bookstub', (
             ('author', self.gf('django.db.models.fields.CharField')(max_length=120)),
         # Adding model 'BookStub'
         db.create_table('catalogue_bookstub', (
             ('author', self.gf('django.db.models.fields.CharField')(max_length=120)),
@@ -22,17 +22,17 @@ class Migration(SchemaMigration):
 
         # Adding field 'Tag.death'
         db.add_column('catalogue_tag', 'death', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True), keep_default=False)
 
         # Adding field 'Tag.death'
         db.add_column('catalogue_tag', 'death', self.gf('django.db.models.fields.IntegerField')(null=True, blank=True), keep_default=False)
-    
-    
+
+
     def backwards(self, orm):
     def backwards(self, orm):
-        
+
         # Deleting model 'BookStub'
         db.delete_table('catalogue_bookstub')
 
         # Deleting field 'Tag.death'
         db.delete_column('catalogue_tag', 'death')
         # Deleting model 'BookStub'
         db.delete_table('catalogue_bookstub')
 
         # Deleting field 'Tag.death'
         db.delete_column('catalogue_tag', 'death')
-    
-    
+
+
     models = {
         'auth.group': {
             'Meta': {'object_name': 'Group'},
     models = {
         'auth.group': {
             'Meta': {'object_name': 'Group'},
@@ -133,5 +133,5 @@ class Migration(SchemaMigration):
             'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
         }
     }
             'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
         }
     }
-    
+
     complete_apps = ['catalogue']
     complete_apps = ['catalogue']
index a161e27..8180311 100644 (file)
@@ -23,11 +23,11 @@ class Migration(DataMigration):
                 'tagged_item': qn(orm.TagRelation._meta.db_table),
                 'tag_id': tag.pk,
             }
                 'tagged_item': qn(orm.TagRelation._meta.db_table),
                 'tag_id': tag.pk,
             }
-    
+
             cursor = connection.cursor()
             cursor.execute(query)
             book_count = (cursor.fetchone() or (0,))[0]
             cursor = connection.cursor()
             cursor.execute(query)
             book_count = (cursor.fetchone() or (0,))[0]
-            
+
             tag.book_count = book_count
             tag.save()
 
             tag.book_count = book_count
             tag.save()
 
index 8d8e06a..d9e7b53 100644 (file)
@@ -5,9 +5,9 @@ from south.v2 import SchemaMigration
 from django.db import models
 
 class Migration(SchemaMigration):
 from django.db import models
 
 class Migration(SchemaMigration):
-    
+
     def forwards(self, orm):
     def forwards(self, orm):
-        
+
         # Adding field 'Book._short_html_en'
         db.add_column('catalogue_book', '_short_html_en', self.gf('django.db.models.fields.TextField')(null=True, blank=True), keep_default=False)
 
         # Adding field 'Book._short_html_en'
         db.add_column('catalogue_book', '_short_html_en', self.gf('django.db.models.fields.TextField')(null=True, blank=True), keep_default=False)
 
@@ -31,10 +31,10 @@ class Migration(SchemaMigration):
 
         # Adding field 'Book._short_html_lt'
         db.add_column('catalogue_book', '_short_html_lt', self.gf('django.db.models.fields.TextField')(null=True, blank=True), keep_default=False)
 
         # Adding field 'Book._short_html_lt'
         db.add_column('catalogue_book', '_short_html_lt', self.gf('django.db.models.fields.TextField')(null=True, blank=True), keep_default=False)
-    
-    
+
+
     def backwards(self, orm):
     def backwards(self, orm):
-        
+
         # Deleting field 'Book._short_html_en'
         db.delete_column('catalogue_book', '_short_html_en')
 
         # Deleting field 'Book._short_html_en'
         db.delete_column('catalogue_book', '_short_html_en')
 
@@ -58,8 +58,8 @@ class Migration(SchemaMigration):
 
         # Deleting field 'Book._short_html_lt'
         db.delete_column('catalogue_book', '_short_html_lt')
 
         # Deleting field 'Book._short_html_lt'
         db.delete_column('catalogue_book', '_short_html_lt')
-    
-    
+
+
     models = {
         'auth.group': {
             'Meta': {'object_name': 'Group'},
     models = {
         'auth.group': {
             'Meta': {'object_name': 'Group'},
@@ -168,5 +168,5 @@ class Migration(SchemaMigration):
             'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
         }
     }
             'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
         }
     }
-    
+
     complete_apps = ['catalogue']
     complete_apps = ['catalogue']
index 4828d6f..8322b4c 100644 (file)
@@ -5,9 +5,9 @@ from south.v2 import SchemaMigration
 from django.db import models
 
 class Migration(SchemaMigration):
 from django.db import models
 
 class Migration(SchemaMigration):
-    
+
     def forwards(self, orm):
     def forwards(self, orm):
-        
+
         # Adding field 'Fragment._short_html_de'
         db.add_column('catalogue_fragment', '_short_html_de', self.gf('django.db.models.fields.TextField')(null=True, blank=True), keep_default=False)
 
         # Adding field 'Fragment._short_html_de'
         db.add_column('catalogue_fragment', '_short_html_de', self.gf('django.db.models.fields.TextField')(null=True, blank=True), keep_default=False)
 
@@ -31,10 +31,10 @@ class Migration(SchemaMigration):
 
         # Adding field 'Fragment._short_html_uk'
         db.add_column('catalogue_fragment', '_short_html_uk', self.gf('django.db.models.fields.TextField')(null=True, blank=True), keep_default=False)
 
         # Adding field 'Fragment._short_html_uk'
         db.add_column('catalogue_fragment', '_short_html_uk', self.gf('django.db.models.fields.TextField')(null=True, blank=True), keep_default=False)
-    
-    
+
+
     def backwards(self, orm):
     def backwards(self, orm):
-        
+
         # Deleting field 'Fragment._short_html_de'
         db.delete_column('catalogue_fragment', '_short_html_de')
 
         # Deleting field 'Fragment._short_html_de'
         db.delete_column('catalogue_fragment', '_short_html_de')
 
@@ -58,8 +58,8 @@ class Migration(SchemaMigration):
 
         # Deleting field 'Fragment._short_html_uk'
         db.delete_column('catalogue_fragment', '_short_html_uk')
 
         # Deleting field 'Fragment._short_html_uk'
         db.delete_column('catalogue_fragment', '_short_html_uk')
-    
-    
+
+
     models = {
         'auth.group': {
             'Meta': {'object_name': 'Group'},
     models = {
         'auth.group': {
             'Meta': {'object_name': 'Group'},
@@ -176,5 +176,5 @@ class Migration(SchemaMigration):
             'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
         }
     }
             'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
         }
     }
-    
+
     complete_apps = ['catalogue']
     complete_apps = ['catalogue']
index 7b2f2c5..b990fc3 100644 (file)
@@ -14,7 +14,7 @@ def get_ltag(book, orm):
 
 
 class Migration(SchemaMigration):
 
 
 class Migration(SchemaMigration):
-    
+
     def forwards(self, orm):
         """ Add _tag_counter and make sure all books carry their ancestors' l-tags """
 
     def forwards(self, orm):
         """ Add _tag_counter and make sure all books carry their ancestors' l-tags """
 
@@ -32,7 +32,7 @@ class Migration(SchemaMigration):
             ltag = get_ltag(book, orm)
             for child in book.children.all():
                 ltag_descendants(child, ltags + [ltag])
             ltag = get_ltag(book, orm)
             for child in book.children.all():
                 ltag_descendants(child, ltags + [ltag])
-        
+
         if not db.dry_run:
             try:
                 book_ct = orm['contenttypes.contenttype'].objects.get(app_label='catalogue', model='book')
         if not db.dry_run:
             try:
                 book_ct = orm['contenttypes.contenttype'].objects.get(app_label='catalogue', model='book')
@@ -42,8 +42,8 @@ class Migration(SchemaMigration):
             orm.TagRelation.objects.filter(content_type=book_ct, tag__category='book').delete()
             for book in orm.Book.objects.filter(parent=None):
                 ltag_descendants(book)
             orm.TagRelation.objects.filter(content_type=book_ct, tag__category='book').delete()
             for book in orm.Book.objects.filter(parent=None):
                 ltag_descendants(book)
-    
-    
+
+
     def backwards(self, orm):
         """ Delete _tag_counter and make sure books carry own l-tag. """
 
     def backwards(self, orm):
         """ Delete _tag_counter and make sure books carry own l-tag. """
 
@@ -61,8 +61,8 @@ class Migration(SchemaMigration):
             orm.TagRelation.objects.filter(content_type=book_ct, tag__category='book').delete()
             for book in orm.Book.objects.filter(parent=None):
                 orm.TagRelation(object_id=book.pk, tag=get_ltag(book, orm), content_type=book_ct).save()
             orm.TagRelation.objects.filter(content_type=book_ct, tag__category='book').delete()
             for book in orm.Book.objects.filter(parent=None):
                 orm.TagRelation(object_id=book.pk, tag=get_ltag(book, orm), content_type=book_ct).save()
-    
-    
+
+
     models = {
         'auth.group': {
             'Meta': {'object_name': 'Group'},
     models = {
         'auth.group': {
             'Meta': {'object_name': 'Group'},
@@ -182,5 +182,5 @@ class Migration(SchemaMigration):
             'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
         }
     }
             'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
         }
     }
-    
+
     complete_apps = ['catalogue']
     complete_apps = ['catalogue']
index ca87ccb..5b6f453 100644 (file)
@@ -5,12 +5,12 @@ from south.v2 import DataMigration
 from django.db import models
 
 class Migration(DataMigration):
 from django.db import models
 
 class Migration(DataMigration):
-    
+
     def forwards(self, orm):
         """ Look for HTML files without any real content and delete them """
         from lxml import etree
         from librarian.html import html_has_content
     def forwards(self, orm):
         """ Look for HTML files without any real content and delete them """
         from lxml import etree
         from librarian.html import html_has_content
-        
+
         for book in orm.Book.objects.exclude(html_file=''):
             if not html_has_content(etree.parse(book.html_file)):
                 book.html_file.delete()
         for book in orm.Book.objects.exclude(html_file=''):
             if not html_has_content(etree.parse(book.html_file)):
                 book.html_file.delete()
@@ -18,11 +18,11 @@ class Migration(DataMigration):
                 for key in filter(lambda x: x.startswith('_short_html'), book.__dict__):
                     book.__setattr__(key, '')
                 book.save()
                 for key in filter(lambda x: x.startswith('_short_html'), book.__dict__):
                     book.__setattr__(key, '')
                 book.save()
-    
+
     def backwards(self, orm):
         """ Do nothing. We don't want empty HTML files anyway. """
         pass
     def backwards(self, orm):
         """ Do nothing. We don't want empty HTML files anyway. """
         pass
-    
+
     models = {
         'auth.group': {
             'Meta': {'object_name': 'Group'},
     models = {
         'auth.group': {
             'Meta': {'object_name': 'Group'},
@@ -142,5 +142,5 @@ class Migration(DataMigration):
             'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
         }
     }
             'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
         }
     }
-    
+
     complete_apps = ['catalogue']
     complete_apps = ['catalogue']
index 876d0fd..d130819 100644 (file)
@@ -5,25 +5,25 @@ from south.v2 import SchemaMigration
 from django.db import models
 
 class Migration(SchemaMigration):
 from django.db import models
 
 class Migration(SchemaMigration):
-    
+
     def forwards(self, orm):
     def forwards(self, orm):
-        
+
         # Removing unique constraint on 'Tag', fields ['slug']
         db.delete_unique('catalogue_tag', ['slug'])
 
         # Adding unique constraint on 'Tag', fields ['category', 'slug']
         db.create_unique('catalogue_tag', ['category', 'slug'])
         # Removing unique constraint on 'Tag', fields ['slug']
         db.delete_unique('catalogue_tag', ['slug'])
 
         # Adding unique constraint on 'Tag', fields ['category', 'slug']
         db.create_unique('catalogue_tag', ['category', 'slug'])
-    
-    
+
+
     def backwards(self, orm):
     def backwards(self, orm):
-        
+
         # Adding unique constraint on 'Tag', fields ['slug']
         db.create_unique('catalogue_tag', ['slug'])
 
         # Removing unique constraint on 'Tag', fields ['category', 'slug']
         db.delete_unique('catalogue_tag', ['category', 'slug'])
         # Adding unique constraint on 'Tag', fields ['slug']
         db.create_unique('catalogue_tag', ['slug'])
 
         # Removing unique constraint on 'Tag', fields ['category', 'slug']
         db.delete_unique('catalogue_tag', ['category', 'slug'])
-    
-    
+
+
     models = {
         'auth.group': {
             'Meta': {'object_name': 'Group'},
     models = {
         'auth.group': {
             'Meta': {'object_name': 'Group'},
@@ -143,5 +143,5 @@ class Migration(SchemaMigration):
             'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
         }
     }
             'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
         }
     }
-    
+
     complete_apps = ['catalogue']
     complete_apps = ['catalogue']
index 2008f09..367f382 100644 (file)
@@ -55,7 +55,7 @@ class Tag(TagBase):
     death = models.IntegerField(_(u'year of death'), blank=True, null=True)
     gazeta_link = models.CharField(blank=True, max_length=240)
     wiki_link = models.CharField(blank=True, max_length=240)
     death = models.IntegerField(_(u'year of death'), blank=True, null=True)
     gazeta_link = models.CharField(blank=True, max_length=240)
     wiki_link = models.CharField(blank=True, max_length=240)
-    
+
     categories_rev = {
         'autor': 'author',
         'epoka': 'epoch',
     categories_rev = {
         'autor': 'author',
         'epoka': 'epoch',
@@ -117,7 +117,7 @@ class Tag(TagBase):
                             real_tags.append(Tag.objects.exclude(category='book').get(slug=name))
                         except Tag.MultipleObjectsReturned, e:
                             ambiguous_slugs.append(name)
                             real_tags.append(Tag.objects.exclude(category='book').get(slug=name))
                         except Tag.MultipleObjectsReturned, e:
                             ambiguous_slugs.append(name)
-                            
+
             if category:
                 # something strange left off
                 raise Tag.DoesNotExist()
             if category:
                 # something strange left off
                 raise Tag.DoesNotExist()
@@ -131,13 +131,13 @@ class Tag(TagBase):
                 return real_tags
         else:
             return TagBase.get_tag_list(tags)
                 return real_tags
         else:
             return TagBase.get_tag_list(tags)
-    
+
     @property
     def url_chunk(self):
         return '/'.join((Tag.categories_dict[self.category], self.slug))
 
 
     @property
     def url_chunk(self):
         return '/'.join((Tag.categories_dict[self.category], self.slug))
 
 
-# TODO: why is this hard-coded ? 
+# TODO: why is this hard-coded ?
 def book_upload_path(ext):
     def get_dynamic_path(book, filename):
         return 'lektura/%s.%s' % (book.slug, ext)
 def book_upload_path(ext):
     def get_dynamic_path(book, filename):
         return 'lektura/%s.%s' % (book.slug, ext)
@@ -171,7 +171,7 @@ class Book(models.Model):
     objects = models.Manager()
     tagged = managers.ModelTaggedItemManager(Tag)
     tags = managers.TagDescriptor(Tag)
     objects = models.Manager()
     tagged = managers.ModelTaggedItemManager(Tag)
     tags = managers.TagDescriptor(Tag)
-    
+
     _tag_counter = JSONField(null=True, editable=False)
     _theme_counter = JSONField(null=True, editable=False)
 
     _tag_counter = JSONField(null=True, editable=False)
     _theme_counter = JSONField(null=True, editable=False)
 
@@ -210,7 +210,7 @@ class Book(models.Model):
     @property
     def name(self):
         return self.title
     @property
     def name(self):
         return self.title
-    
+
     def book_tag(self):
         slug = ('l-' + self.slug)[:120]
         book_tag, created = Tag.objects.get_or_create(slug=slug, category='book')
     def book_tag(self):
         slug = ('l-' + self.slug)[:120]
         book_tag, created = Tag.objects.get_or_create(slug=slug, category='book')
@@ -399,8 +399,8 @@ class Book(models.Model):
 
         book.save()
         return book
 
         book.save()
         return book
-    
-    
+
+
     def refresh_tag_counter(self):
         tags = {}
         for child in self.children.all().order_by():
     def refresh_tag_counter(self):
         tags = {}
         for child in self.children.all().order_by():
@@ -411,7 +411,7 @@ class Book(models.Model):
         self.set__tag_counter_value(tags)
         self.save(reset_short_html=False, refresh_mp3=False)
         return tags
         self.set__tag_counter_value(tags)
         self.save(reset_short_html=False, refresh_mp3=False)
         return tags
-    
+
     @property
     def tag_counter(self):
         if self._tag_counter is None:
     @property
     def tag_counter(self):
         if self._tag_counter is None:
@@ -426,13 +426,13 @@ class Book(models.Model):
         self.set__theme_counter_value(tags)
         self.save(reset_short_html=False, refresh_mp3=False)
         return tags
         self.set__theme_counter_value(tags)
         self.save(reset_short_html=False, refresh_mp3=False)
         return tags
-    
+
     @property
     def theme_counter(self):
         if self._theme_counter is None:
             return self.refresh_theme_counter()
         return dict((int(k), v) for k, v in self.get__theme_counter_value().iteritems())
     @property
     def theme_counter(self):
         if self._theme_counter is None:
             return self.refresh_theme_counter()
         return dict((int(k), v) for k, v in self.get__theme_counter_value().iteritems())
-    
+
 
 
 class Fragment(models.Model):
 
 
 class Fragment(models.Model):
index 504ee69..7f2bf29 100644 (file)
@@ -54,7 +54,7 @@ def simple_title(tags):
         'kind': u'rodzaj',
         'set': u'półka',
     }
         'kind': u'rodzaj',
         'set': u'półka',
     }
-    
+
     title = []
     for tag in tags:
         title.append("%s: %s" % (mapping[tag.category], tag.name))
     title = []
     for tag in tags:
         title.append("%s: %s" % (mapping[tag.category], tag.name))
@@ -68,46 +68,46 @@ def title_from_tags(tags):
         for tag in tags:
             result[tag.category] = tag
         return result
         for tag in tags:
             result[tag.category] = tag
         return result
-    
+
     # TODO: Remove this after adding flection mechanism
     return simple_title(tags)
     # TODO: Remove this after adding flection mechanism
     return simple_title(tags)
-    
+
     class Flection(object):
         def get_case(self, name, flection):
             return name
     flection = Flection()
     class Flection(object):
         def get_case(self, name, flection):
             return name
     flection = Flection()
-    
+
     self = split_tags(tags)
     self = split_tags(tags)
-    
+
     title = u''
     title = u''
-    
+
     # Specjalny przypadek oglądania wszystkich lektur na danej półce
     if len(self) == 1 and 'set' in self:
         return u'Półka %s' % self['set']
     # Specjalny przypadek oglądania wszystkich lektur na danej półce
     if len(self) == 1 and 'set' in self:
         return u'Półka %s' % self['set']
-    
+
     # Specjalny przypadek "Twórczość w pozytywizmie", wtedy gdy tylko epoka
     # jest wybrana przez użytkownika
     if 'epoch' in self and len(self) == 1:
         text = u'Twórczość w %s' % flection.get_case(unicode(self['epoch']), u'miejscownik')
         return capfirst(text)
     # Specjalny przypadek "Twórczość w pozytywizmie", wtedy gdy tylko epoka
     # jest wybrana przez użytkownika
     if 'epoch' in self and len(self) == 1:
         text = u'Twórczość w %s' % flection.get_case(unicode(self['epoch']), u'miejscownik')
         return capfirst(text)
-    
+
     # Specjalny przypadek "Dramat w twórczości Sofoklesa", wtedy gdy podane
     # są tylko rodzaj literacki i autor
     if 'kind' in self and 'author' in self and len(self) == 2:
     # Specjalny przypadek "Dramat w twórczości Sofoklesa", wtedy gdy podane
     # są tylko rodzaj literacki i autor
     if 'kind' in self and 'author' in self and len(self) == 2:
-        text = u'%s w twórczości %s' % (unicode(self['kind']), 
+        text = u'%s w twórczości %s' % (unicode(self['kind']),
             flection.get_case(unicode(self['author']), u'dopełniacz'))
         return capfirst(text)
             flection.get_case(unicode(self['author']), u'dopełniacz'))
         return capfirst(text)
-    
+
     # Przypadki ogólniejsze
     if 'theme' in self:
         title += u'Motyw %s' % unicode(self['theme'])
     # Przypadki ogólniejsze
     if 'theme' in self:
         title += u'Motyw %s' % unicode(self['theme'])
-    
+
     if 'genre' in self:
         if 'theme' in self:
             title += u' w %s' % flection.get_case(unicode(self['genre']), u'miejscownik')
         else:
             title += unicode(self['genre'])
     if 'genre' in self:
         if 'theme' in self:
             title += u' w %s' % flection.get_case(unicode(self['genre']), u'miejscownik')
         else:
             title += unicode(self['genre'])
-            
+
     if 'kind' in self or 'author' in self or 'epoch' in self:
         if 'genre' in self or 'theme' in self:
             if 'kind' in self:
     if 'kind' in self or 'author' in self or 'epoch' in self:
         if 'genre' in self or 'theme' in self:
             if 'kind' in self:
@@ -116,12 +116,12 @@ def title_from_tags(tags):
                 title += u' w twórczości '
         else:
             title += u'%s ' % unicode(self.get('kind', u'twórczość'))
                 title += u' w twórczości '
         else:
             title += u'%s ' % unicode(self.get('kind', u'twórczość'))
-            
+
     if 'author' in self:
         title += flection.get_case(unicode(self['author']), u'dopełniacz')
     elif 'epoch' in self:
         title += flection.get_case(unicode(self['epoch']), u'dopełniacz')
     if 'author' in self:
         title += flection.get_case(unicode(self['author']), u'dopełniacz')
     elif 'epoch' in self:
         title += flection.get_case(unicode(self['epoch']), u'dopełniacz')
-    
+
     return capfirst(title)
 
 
     return capfirst(title)
 
 
@@ -152,7 +152,7 @@ def breadcrumbs(tags, search_form=True):
 def catalogue_url(parser, token):
     bits = token.split_contents()
     tag_name = bits[0]
 def catalogue_url(parser, token):
     bits = token.split_contents()
     tag_name = bits[0]
-    
+
     tags_to_add = []
     tags_to_remove = []
     for bit in bits[1:]:
     tags_to_add = []
     tags_to_remove = []
     for bit in bits[1:]:
@@ -160,7 +160,7 @@ def catalogue_url(parser, token):
             tags_to_remove.append(bit[1:])
         else:
             tags_to_add.append(bit)
             tags_to_remove.append(bit[1:])
         else:
             tags_to_add.append(bit)
-    
+
     return CatalogueURLNode(tags_to_add, tags_to_remove)
 
 
     return CatalogueURLNode(tags_to_add, tags_to_remove)
 
 
@@ -168,7 +168,7 @@ class CatalogueURLNode(Node):
     def __init__(self, tags_to_add, tags_to_remove):
         self.tags_to_add = [Variable(tag) for tag in tags_to_add]
         self.tags_to_remove = [Variable(tag) for tag in tags_to_remove]
     def __init__(self, tags_to_add, tags_to_remove):
         self.tags_to_add = [Variable(tag) for tag in tags_to_add]
         self.tags_to_remove = [Variable(tag) for tag in tags_to_remove]
-    
+
     def render(self, context):
         tags_to_add = []
         tags_to_remove = []
     def render(self, context):
         tags_to_add = []
         tags_to_remove = []
@@ -186,14 +186,14 @@ class CatalogueURLNode(Node):
                 tags_to_remove += [t for t in tag]
             else:
                 tags_to_remove.append(tag)
                 tags_to_remove += [t for t in tag]
             else:
                 tags_to_remove.append(tag)
-            
+
         tag_slugs = [tag.url_chunk for tag in tags_to_add]
         for tag in tags_to_remove:
             try:
                 tag_slugs.remove(tag.url_chunk)
             except KeyError:
                 pass
         tag_slugs = [tag.url_chunk for tag in tags_to_add]
         for tag in tags_to_remove:
             try:
                 tag_slugs.remove(tag.url_chunk)
             except KeyError:
                 pass
-        
+
         if len(tag_slugs) > 0:
             return reverse('tagged_object_list', kwargs={'tags': '/'.join(tag_slugs)})
         else:
         if len(tag_slugs) > 0:
             return reverse('tagged_object_list', kwargs={'tags': '/'.join(tag_slugs)})
         else:
@@ -201,7 +201,7 @@ class CatalogueURLNode(Node):
 
 
 @register.inclusion_tag('catalogue/latest_blog_posts.html')
 
 
 @register.inclusion_tag('catalogue/latest_blog_posts.html')
-def latest_blog_posts(feed_url, posts_to_show=5):    
+def latest_blog_posts(feed_url, posts_to_show=5):
     try:
         feed = feedparser.parse(str(feed_url))
         posts = []
     try:
         feed = feedparser.parse(str(feed_url))
         posts = []
@@ -234,7 +234,7 @@ def folded_tag_list(tags, choices=None):
         choices = []
     some_tags_hidden = False
     tag_count = len(tags)
         choices = []
     some_tags_hidden = False
     tag_count = len(tags)
-    
+
     if tag_count == 1:
         one_tag = tags[0]
     else:
     if tag_count == 1:
         one_tag = tags[0]
     else:
index b91f872..72476be 100644 (file)
@@ -1,11 +1,11 @@
 # Source: http://djangosnippets.org/snippets/967/
 # Author: adurdin
 # Posted: August 13, 2008
 # Source: http://djangosnippets.org/snippets/967/
 # Author: adurdin
 # Posted: August 13, 2008
-# 
-# 
+#
+#
 # We can use it based on djangosnippets Terms of Service:
 # (http://djangosnippets.org/about/tos/)
 # We can use it based on djangosnippets Terms of Service:
 # (http://djangosnippets.org/about/tos/)
-# 
+#
 # 2. That you grant any third party who sees the code you post
 # a royalty-free, non-exclusive license to copy and distribute that code
 # and to make and distribute derivative works based on that code. You may
 # 2. That you grant any third party who sees the code you post
 # a royalty-free, non-exclusive license to copy and distribute that code
 # and to make and distribute derivative works based on that code. You may
@@ -71,13 +71,13 @@ def do_switch(parser, token):
     got_else = False
     while token.contents != 'endswitch':
         nodelist = parser.parse(BlockTagList('case', 'else', 'endswitch'))
     got_else = False
     while token.contents != 'endswitch':
         nodelist = parser.parse(BlockTagList('case', 'else', 'endswitch'))
-        
+
         if got_else:
             raise template.TemplateSyntaxError("'else' must be last tag in '%s'." % tag_name)
 
         contents = token.contents.split()
         token_name, token_args = contents[0], contents[1:]
         if got_else:
             raise template.TemplateSyntaxError("'else' must be last tag in '%s'." % tag_name)
 
         contents = token.contents.split()
         token_name, token_args = contents[0], contents[1:]
-        
+
         if token_name == 'case':
             tests = map(parser.compile_filter, token_args)
             case = (tests, nodelist)
         if token_name == 'case':
             tests = map(parser.compile_filter, token_args)
             case = (tests, nodelist)
@@ -122,7 +122,7 @@ class SwitchNode(Node):
         except VariableDoesNotExist:
             no_value = True
             value_missing = None
         except VariableDoesNotExist:
             no_value = True
             value_missing = None
-        
+
         for tests, nodelist in self.cases:
             if tests is None:
                 return nodelist.render(context)
         for tests, nodelist in self.cases:
             if tests is None:
                 return nodelist.render(context)
diff --git a/apps/catalogue/test_utils.py b/apps/catalogue/test_utils.py
new file mode 100644 (file)
index 0000000..3a8af57
--- /dev/null
@@ -0,0 +1,38 @@
+from django.conf import settings
+from django.test import TestCase
+import shutil
+import tempfile
+
+class WLTestCase(TestCase):
+    """
+        Generic base class for tests. Adds settings freeze and clears MEDIA_ROOT.
+    """
+    def setUp(self):
+        self._MEDIA_ROOT, settings.MEDIA_ROOT = settings.MEDIA_ROOT, tempfile.mkdtemp(prefix='djangotest_')
+
+    def tearDown(self):
+        shutil.rmtree(settings.MEDIA_ROOT, True)
+        settings.MEDIA_ROOT = self._MEDIA_ROOT
+
+class PersonStub(object):
+
+    def __init__(self, first_names, last_name):
+        self.first_names = first_names
+        self.last_name = last_name
+
+
+class BookInfoStub(object):
+
+    def __init__(self, **kwargs):
+        self.__dict = kwargs
+
+    def __setattr__(self, key, value):
+        if not key.startswith('_'):
+            self.__dict[key] = value
+        return object.__setattr__(self, key, value)
+
+    def __getattr__(self, key):
+        return self.__dict[key]
+
+    def to_dict(self):
+        return dict((key, unicode(value)) for key, value in self.__dict.items())
diff --git a/apps/catalogue/tests.py b/apps/catalogue/tests.py
deleted file mode 100644 (file)
index 829f8dc..0000000
+++ /dev/null
@@ -1,476 +0,0 @@
-# -*- coding: utf-8 -*-
-from django.test import TestCase
-from catalogue import models, views
-from django.core.files.base import ContentFile
-from django.contrib.auth.models import User, AnonymousUser
-from django.test.client import Client
-
-from nose.tools import raises
-from StringIO import StringIO
-
-class BasicSearchLogicTests(TestCase):
-
-    def setUp(self):
-        self.author_tag = models.Tag.objects.create(
-                                name=u'Adam Mickiewicz [SubWord]',
-                                category=u'author', slug="one")
-
-        self.unicode_tag = models.Tag.objects.create(
-                                name=u'Tadeusz Żeleński (Boy)',
-                                category=u'author', slug="two")
-
-        self.polish_tag = models.Tag.objects.create(
-                                name=u'ĘÓĄŚŁŻŹĆŃęóąśłżźćń',
-                                category=u'author', slug="three")
-
-    @raises(ValueError)
-    def test_empty_query(self):
-        """ Check that empty queries raise an error. """
-        views.find_best_matches(u'')
-
-    @raises(ValueError)
-    def test_one_letter_query(self):
-        """ Check that one letter queries aren't permitted. """
-        views.find_best_matches(u't')
-
-    def test_match_by_prefix(self):
-        """ Tags should be matched by prefix of words within it's name. """
-        self.assertEqual(views.find_best_matches(u'Ada'), (self.author_tag,))
-        self.assertEqual(views.find_best_matches(u'Mic'), (self.author_tag,))
-        self.assertEqual(views.find_best_matches(u'Mickiewicz'), (self.author_tag,))
-
-    def test_match_case_insensitive(self):
-        """ Tag names should match case insensitive. """
-        self.assertEqual(views.find_best_matches(u'adam mickiewicz'), (self.author_tag,))
-
-    def test_match_case_insensitive_unicode(self):
-        """ Tag names should match case insensitive (unicode). """
-        self.assertEqual(views.find_best_matches(u'tadeusz żeleński (boy)'), (self.unicode_tag,))
-
-    def test_word_boundary(self):
-        self.assertEqual(views.find_best_matches(u'SubWord'), (self.author_tag,))
-        self.assertEqual(views.find_best_matches(u'[SubWord'), (self.author_tag,))
-
-    def test_unrelated_search(self):
-        self.assertEqual(views.find_best_matches(u'alamakota'), tuple())
-        self.assertEqual(views.find_best_matches(u'Adama'), ())
-
-    def test_infix_doesnt_match(self):
-        """ Searching for middle of a word shouldn't match. """
-        self.assertEqual(views.find_best_matches(u'deusz'), tuple())
-
-    def test_diactricts_removal_pl(self):
-        """ Tags should match both with and without national characters. """
-        self.assertEqual(views.find_best_matches(u'ĘÓĄŚŁŻŹĆŃęóąśłżźćń'), (self.polish_tag,))
-        self.assertEqual(views.find_best_matches(u'EOASLZZCNeoaslzzcn'), (self.polish_tag,))
-        self.assertEqual(views.find_best_matches(u'eoaslzzcneoaslzzcn'), (self.polish_tag,))
-
-    def test_diactricts_query_removal_pl(self):
-        """ Tags without national characters shouldn't be matched by queries with them. """
-        self.assertEqual(views.find_best_matches(u'Adąm'), ())
-
-    def test_sloppy(self):
-        self.assertEqual(views.find_best_matches(u'Żelenski'), (self.unicode_tag,))
-        self.assertEqual(views.find_best_matches(u'zelenski'), (self.unicode_tag,))
-
-
-class PersonStub(object):
-
-    def __init__(self, first_names, last_name):
-        self.first_names = first_names
-        self.last_name = last_name
-
-from slughifi import slughifi
-
-class BookInfoStub(object):
-
-    def __init__(self, **kwargs):            
-        self.__dict = kwargs
-
-    def __setattr__(self, key, value):
-        if not key.startswith('_'):
-            self.__dict[key] = value
-        return object.__setattr__(self, key, value)
-
-    def __getattr__(self, key):
-        return self.__dict[key]
-
-    def to_dict(self):
-        return dict((key, unicode(value)) for key, value in self.__dict.items())
-
-def info_args(title):
-    """ generate some keywords for comfortable BookInfoCreation  """
-    slug = unicode(slughifi(title))
-    return {'title': unicode(title),
-            'slug': slug,
-            'url': u"http://wolnelektury.pl/example/%s" % slug,
-            'about': u"http://wolnelektury.pl/example/URI/%s" % slug,
-            }
-
-class BookImportLogicTests(TestCase):
-
-    def setUp(self):
-        self.book_info = BookInfoStub(
-            url=u"http://wolnelektury.pl/example/default_book",
-            about=u"http://wolnelektury.pl/example/URI/default_book",
-            title=u"Default Book",
-            author=PersonStub(("Jim",), "Lazy"),
-            kind="X-Kind",
-            genre="X-Genre",
-            epoch="X-Epoch",
-        )
-
-        self.expected_tags = [
-           ('author', 'jim-lazy'),
-           ('genre', 'x-genre'),
-           ('epoch', 'x-epoch'),
-           ('kind', 'x-kind'),
-        ]
-        self.expected_tags.sort()
-
-    def tearDown(self):
-        models.Book.objects.all().delete()
-
-    def test_empty_book(self):
-        BOOK_TEXT = "<utwor />"
-        book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
-
-        self.assertEqual(book.title, "Default Book")
-        self.assertEqual(book.slug, "default_book")
-        self.assert_(book.parent is None)
-        self.assertFalse(book.has_html_file())
-
-        # no fragments generated
-        self.assertEqual(book.fragments.count(), 0)
-
-        # TODO: this should be filled out probably...
-        self.assertEqual(book.wiki_link, '')
-        self.assertEqual(book.gazeta_link, '')
-        self.assertEqual(book._short_html, '')
-        self.assertEqual(book.description, '')
-
-        tags = [ (tag.category, tag.slug) for tag in book.tags ]
-        tags.sort()
-
-        self.assertEqual(tags, self.expected_tags)
-    
-    def test_not_quite_empty_book(self):
-        """ Not empty, but without any real text.
-        
-        Should work like any other non-empty book.
-        """
-        
-        BOOK_TEXT = """<utwor>
-        <liryka_l>
-            <nazwa_utworu>Nic</nazwa_utworu>
-        </liryka_l></utwor>
-        """
-        
-        book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
-        self.assertTrue(book.has_html_file())
-
-    def test_book_with_fragment(self):
-        BOOK_TEXT = """<utwor>
-        <opowiadanie>
-            <akap><begin id="m01" /><motyw id="m01">Love</motyw>Ala ma kota<end id="m01" /></akap>
-        </opowiadanie></utwor>
-        """
-
-        book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
-        self.assertTrue(book.has_html_file())
-
-        self.assertEqual(book.fragments.count(), 1)
-        self.assertEqual(book.fragments.all()[0].text, u'<p class="paragraph">Ala ma kota</p>\n')
-
-        self.assert_(('theme', 'love') in [ (tag.category, tag.slug) for tag in book.tags ])
-
-    def test_book_replace_title(self):
-        BOOK_TEXT = """<utwor />"""
-        self.book_info.title = u"Extraordinary"
-        book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
-
-        tags = [ (tag.category, tag.slug) for tag in book.tags ]
-        tags.sort()
-
-        self.assertEqual(tags, self.expected_tags)
-
-    def test_book_replace_author(self):
-        BOOK_TEXT = """<utwor />"""
-        self.book_info.author = PersonStub(("Hans", "Christian"), "Andersen")
-        book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
-
-        tags = [ (tag.category, tag.slug) for tag in book.tags ]
-        tags.sort()
-
-        self.expected_tags.remove(('author', 'jim-lazy'))
-        self.expected_tags.append(('author', 'hans-christian-andersen'))
-        self.expected_tags.sort()
-
-        self.assertEqual(tags, self.expected_tags)
-
-        # the old tag should disappear 
-        self.assertRaises(models.Tag.DoesNotExist, models.Tag.objects.get,
-                    slug="jim-lazy", category="author")
-
-
-    
-class BooksByTagTests(TestCase):
-    """ tests the /katalog/tag page for found books """
-    
-    def setUp(self):
-        author = PersonStub(("Common",), "Man")
-        tags = dict(genre='G', epoch='E', author=author, kind="K")
-
-        # grandchild
-        kwargs = info_args(u"GChild")
-        kwargs.update(tags)
-        gchild_info = BookInfoStub(**kwargs)
-        # child
-        kwargs = info_args(u"Child")
-        kwargs.update(tags)
-        child_info = BookInfoStub(parts=[gchild_info.url], **kwargs)
-        # other grandchild
-        kwargs = info_args(u"Different GChild")
-        kwargs.update(tags)
-        diffgchild_info = BookInfoStub(**kwargs)
-        # other child
-        kwargs = info_args(u"Different Child")
-        kwargs.update(tags)
-        kwargs['kind'] = 'K2'
-        diffchild_info = BookInfoStub(parts=[diffgchild_info.url], **kwargs)
-        # parent
-        kwargs = info_args(u"Parent")
-        kwargs.update(tags)
-        parent_info = BookInfoStub(parts=[child_info.url, diffchild_info.url], **kwargs)
-
-        # create the books
-        book_file = ContentFile('<utwor />')
-        for info in gchild_info, child_info, diffgchild_info, diffchild_info, parent_info:
-            book = models.Book.from_text_and_meta(book_file, info)
-
-        # useful tags
-        self.author = models.Tag.objects.get(name='Common Man', category='author')
-        tag_empty = models.Tag(name='Empty tag', slug='empty', category='author')
-        tag_empty.save()
-        
-        self.client = Client()
-    
-    
-    def tearDown(self):
-        models.Book.objects.all().delete()
-
-    
-    def test_nonexistent_tag(self):
-        """ Looking for a non-existent tag should yield 404 """
-        self.assertEqual(404, self.client.get('/katalog/czeslaw_milosz/').status_code)
-        
-    def test_book_tag(self):
-        """ Looking for a book tag isn't permitted """
-        self.assertEqual(404, self.client.get('/katalog/parent/').status_code)
-    
-    def test_tag_empty(self):
-        """ Tag with no books should return no books """
-        context = self.client.get('/katalog/empty/').context
-        self.assertEqual(0, len(context['object_list']))
-    
-    def test_tag_common(self):
-        """ Filtering by tag should only yield top-level books. """
-        context = self.client.get('/katalog/%s/' % self.author.slug).context
-        self.assertEqual([book.title for book in context['object_list']],
-                         ['Parent'])
-
-    def test_tag_child(self):
-        """ Filtering by child's tag should yield the child """
-        context = self.client.get('/katalog/k2/').context
-        self.assertEqual([book.title for book in context['object_list']],
-                         ['Different Child'])
-
-    def test_tag_child_jump(self):
-        """ Of parent and grandchild, only parent should be returned. """
-        context = self.client.get('/katalog/k/').context
-        self.assertEqual([book.title for book in context['object_list']],
-                         ['Parent'])
-        
-
-class TagRelatedTagsTests(TestCase):
-    """ tests the /katalog/tag/ page for related tags """
-    
-    def setUp(self):
-        author = PersonStub(("Common",), "Man")
-
-        gchild_info = BookInfoStub(author=author, genre="GchildGenre", epoch='Epoch', kind="Kind", 
-                                   **info_args(u"GChild"))
-        child1_info = BookInfoStub(author=author, genre="ChildGenre", epoch='Epoch', kind="ChildKind",
-                                   parts=[gchild_info.url],
-                                   **info_args(u"Child1"))
-        child2_info = BookInfoStub(author=author, genre="ChildGenre", epoch='Epoch', kind="ChildKind",
-                                   **info_args(u"Child2"))
-        parent_info = BookInfoStub(author=author, genre="Genre", epoch='Epoch', kind="Kind", 
-                                   parts=[child1_info.url, child2_info.url],
-                                   **info_args(u"Parent"))
-        
-        for info in gchild_info, child1_info, child2_info, parent_info:
-            book_text = """<utwor><opowiadanie><akap>
-                <begin id="m01" />
-                    <motyw id="m01">Theme, %sTheme</motyw>
-                    Ala ma kota
-                <end id="m01" />
-                </akap></opowiadanie></utwor>
-                """ % info.title.encode('utf-8')
-            book = models.Book.from_text_and_meta(ContentFile(book_text), info)
-            book.save()
-        
-        tag_empty = models.Tag(name='Empty tag', slug='empty', category='author')
-        tag_empty.save()
-
-        self.client = Client()
-    
-    
-    def tearDown(self):
-        models.Book.objects.all().delete()
-    
-    
-    def test_empty(self):
-        """ empty tag should have no related tags """
-        
-        cats = self.client.get('/katalog/empty/').context['categories']
-        self.assertEqual(cats, {}, 'tags related to empty tag')
-    
-    
-    def test_has_related(self):
-        """ related own and descendants' tags should be generated """
-        
-        cats = self.client.get('/katalog/kind/').context['categories']
-        self.assertTrue('Common Man' in [tag.name for tag in cats['author']],
-                        'missing `author` related tag')
-        self.assertTrue('Epoch' in [tag.name for tag in cats['epoch']],
-                        'missing `epoch` related tag')
-        self.assertTrue("ChildKind" in [tag.name for tag in cats['kind']],
-                        "missing `kind` related tag")
-        self.assertTrue("Genre" in [tag.name for tag in cats['genre']],
-                        'missing `genre` related tag')
-        self.assertTrue("ChildGenre" in [tag.name for tag in cats['genre']],
-                        "missing child's related tag")
-        self.assertTrue("GchildGenre" in [tag.name for tag in cats['genre']],
-                        "missing grandchild's related tag")
-        self.assertTrue('Theme' in [tag.name for tag in cats['theme']],
-                        "missing related theme")
-        self.assertTrue('Child1Theme' in [tag.name for tag in cats['theme']],
-                        "missing child's related theme")
-        self.assertTrue('GChildTheme' in [tag.name for tag in cats['theme']],
-                        "missing grandchild's related theme")
-    
-    
-    def test_related_differ(self):
-        """ related tags shouldn't include filtering tags """
-        
-        cats = self.client.get('/katalog/kind/').context['categories']
-        self.assertFalse('Kind' in [tag.name for tag in cats['kind']],
-                         'filtering tag wrongly included in related')
-        cats = self.client.get('/katalog/theme/').context['categories']
-        self.assertFalse('Theme' in [tag.name for tag in cats['theme']],
-                         'filtering theme wrongly included in related')
-    
-    
-    def test_parent_tag_once(self):
-        """ if parent and descendants have a common tag, count it only once """
-
-        cats = self.client.get('/katalog/kind/').context['categories']
-        self.assertEqual([(tag.name, tag.count) for tag in cats['epoch']],
-                         [('Epoch', 1)],
-                         'wrong related tag epoch tag on tag page')
-    
-    
-    def test_siblings_tags_add(self):
-        """ if children have tags and parent hasn't, count the children """
-        
-        cats = self.client.get('/katalog/epoch/').context['categories']
-        self.assertTrue(('ChildKind', 2) in [(tag.name, tag.count) for tag in cats['kind']],
-                    'wrong related kind tags on tag page')
-    
-    def test_themes_add(self):
-        """ all occurencies of theme should be counted """
-
-        cats = self.client.get('/katalog/epoch/').context['categories']
-        self.assertTrue(('Theme', 4) in [(tag.name, tag.count) for tag in cats['theme']],
-                    'wrong related theme count')
-    
-
-
-class CleanTagRelationTests(TestCase):
-    """ tests for tag relations cleaning after deleting things """
-    
-    def setUp(self):
-        author = PersonStub(("Common",), "Man")
-
-        book_info = BookInfoStub(author=author, genre="G", epoch='E', kind="K", 
-                                   **info_args(u"Book"))
-        book_text = """<utwor><opowiadanie><akap>
-            <begin id="m01" /><motyw id="m01">Theme</motyw>Ala ma kota
-            <end id="m01" />
-            </akap></opowiadanie></utwor>
-            """
-        book = models.Book.from_text_and_meta(ContentFile(book_text), book_info)
-        book.save()
-        
-        self.client = Client()
-    
-    
-    def tearDown(self):
-        models.Book.objects.all().delete()
-    
-    
-    def test_delete_objects(self):
-        """ there should be no related tags left after deleting some objects """
-        
-        models.Book.objects.all().delete()
-        cats = self.client.get('/katalog/k/').context['categories']
-        self.assertEqual({}, cats)
-
-
-    def test_deleted_tag(self):
-        """ there should be no tag relations left after deleting tags """
-        
-        models.Tag.objects.all().delete()
-        cats = self.client.get('/katalog/lektura/book/').context['categories']
-        self.assertEqual(cats, {})
-
-
-class TestIdenticalTag(TestCase):
-    
-    def setUp(self):
-        author = PersonStub(("A",), "B")
-
-        book_info = BookInfoStub(author=author, genre="A B", epoch='A B', kind="A B", 
-                                   **info_args(u"A B"))
-        book_text = """<utwor><opowiadanie><akap>
-            <begin id="m01" /><motyw id="m01">A B</motyw>Ala ma kota
-            <end id="m01" />
-            </akap></opowiadanie></utwor>
-            """
-        book = models.Book.from_text_and_meta(ContentFile(book_text), book_info)
-        book.save()
-        
-        self.client = Client()
-    
-    
-    def tearDown(self):
-        models.Book.objects.all().delete()
-    
-    
-    def test_book_tags(self):
-        """ there should be all related tags in relevant categories """
-        
-        cats = self.client.get('/katalog/lektura/a-b/').context['categories']
-        for category in 'author', 'kind', 'genre', 'epoch', 'theme':
-            self.assertTrue('A B' in [tag.name for tag in cats[category]],
-                            'missing related tag for %s' % category)
-
-    def test_qualified_url(self):
-        categories = {'author': 'autor', 'theme': 'motyw', 'epoch': 'epoka', 'kind':'rodzaj', 'genre':'gatunek'}
-        for cat, localcat in categories.iteritems():
-            context = self.client.get('/katalog/%s/a-b/' % localcat).context
-            self.assertEqual(1, len(context['object_list']))
-            self.assertNotEqual({}, context['categories'])
-            self.assertFalse(cat in context['categories'])
-
diff --git a/apps/catalogue/tests/__init__.py b/apps/catalogue/tests/__init__.py
new file mode 100644 (file)
index 0000000..d656d45
--- /dev/null
@@ -0,0 +1,3 @@
+from catalogue.tests.book_import import *
+from catalogue.tests.tags import *
+from catalogue.tests.search import *
diff --git a/apps/catalogue/tests/book_import.py b/apps/catalogue/tests/book_import.py
new file mode 100644 (file)
index 0000000..fed9922
--- /dev/null
@@ -0,0 +1,109 @@
+# -*- coding: utf-8 -*-
+from django.core.files.base import ContentFile
+from catalogue.test_utils import *
+from catalogue import models
+
+class BookImportLogicTests(WLTestCase):
+
+    def setUp(self):
+        WLTestCase.setUp(self)
+        self.book_info = BookInfoStub(
+            url=u"http://wolnelektury.pl/example/default_book",
+            about=u"http://wolnelektury.pl/example/URI/default_book",
+            title=u"Default Book",
+            author=PersonStub(("Jim",), "Lazy"),
+            kind="X-Kind",
+            genre="X-Genre",
+            epoch="X-Epoch",
+        )
+
+        self.expected_tags = [
+           ('author', 'jim-lazy'),
+           ('genre', 'x-genre'),
+           ('epoch', 'x-epoch'),
+           ('kind', 'x-kind'),
+        ]
+        self.expected_tags.sort()
+
+    def test_empty_book(self):
+        BOOK_TEXT = "<utwor />"
+        book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
+
+        self.assertEqual(book.title, "Default Book")
+        self.assertEqual(book.slug, "default_book")
+        self.assert_(book.parent is None)
+        self.assertFalse(book.has_html_file())
+
+        # no fragments generated
+        self.assertEqual(book.fragments.count(), 0)
+
+        # TODO: this should be filled out probably...
+        self.assertEqual(book.wiki_link, '')
+        self.assertEqual(book.gazeta_link, '')
+        self.assertEqual(book._short_html, '')
+        self.assertEqual(book.description, '')
+
+        tags = [ (tag.category, tag.slug) for tag in book.tags ]
+        tags.sort()
+
+        self.assertEqual(tags, self.expected_tags)
+
+    def test_not_quite_empty_book(self):
+        """ Not empty, but without any real text.
+
+        Should work like any other non-empty book.
+        """
+
+        BOOK_TEXT = """<utwor>
+        <liryka_l>
+            <nazwa_utworu>Nic</nazwa_utworu>
+        </liryka_l></utwor>
+        """
+
+        book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
+        self.assertTrue(book.has_html_file())
+
+    def test_book_with_fragment(self):
+        BOOK_TEXT = """<utwor>
+        <opowiadanie>
+            <akap><begin id="m01" /><motyw id="m01">Love</motyw>Ala ma kota<end id="m01" /></akap>
+        </opowiadanie></utwor>
+        """
+
+        book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
+        self.assertTrue(book.has_html_file())
+
+        self.assertEqual(book.fragments.count(), 1)
+        self.assertEqual(book.fragments.all()[0].text, u'<p class="paragraph">Ala ma kota</p>\n')
+
+        self.assert_(('theme', 'love') in [ (tag.category, tag.slug) for tag in book.tags ])
+
+    def test_book_replace_title(self):
+        BOOK_TEXT = """<utwor />"""
+        book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
+        self.book_info.title = u"Extraordinary"
+        book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
+
+        tags = [ (tag.category, tag.slug) for tag in book.tags ]
+        tags.sort()
+
+        self.assertEqual(tags, self.expected_tags)
+
+    def test_book_replace_author(self):
+        BOOK_TEXT = """<utwor />"""
+        book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
+        self.book_info.author = PersonStub(("Hans", "Christian"), "Andersen")
+        book = models.Book.from_text_and_meta(ContentFile(BOOK_TEXT), self.book_info)
+
+        tags = [ (tag.category, tag.slug) for tag in book.tags ]
+        tags.sort()
+
+        self.expected_tags.remove(('author', 'jim-lazy'))
+        self.expected_tags.append(('author', 'hans-christian-andersen'))
+        self.expected_tags.sort()
+
+        self.assertEqual(tags, self.expected_tags)
+
+        # the old tag should disappear
+        self.assertRaises(models.Tag.DoesNotExist, models.Tag.objects.get,
+                    slug="jim-lazy", category="author")
diff --git a/apps/catalogue/tests/search.py b/apps/catalogue/tests/search.py
new file mode 100644 (file)
index 0000000..93bec87
--- /dev/null
@@ -0,0 +1,71 @@
+# -*- coding: utf-8 -*-
+from catalogue import models, views
+from catalogue.test_utils import *
+
+from nose.tools import raises
+
+class BasicSearchLogicTests(WLTestCase):
+
+    def setUp(self):
+        WLTestCase.setUp(self)
+        self.author_tag = models.Tag.objects.create(
+                                name=u'Adam Mickiewicz [SubWord]',
+                                category=u'author', slug="one")
+
+        self.unicode_tag = models.Tag.objects.create(
+                                name=u'Tadeusz Żeleński (Boy)',
+                                category=u'author', slug="two")
+
+        self.polish_tag = models.Tag.objects.create(
+                                name=u'ĘÓĄŚŁŻŹĆŃęóąśłżźćń',
+                                category=u'author', slug="three")
+
+    @raises(ValueError)
+    def test_empty_query(self):
+        """ Check that empty queries raise an error. """
+        views.find_best_matches(u'')
+
+    @raises(ValueError)
+    def test_one_letter_query(self):
+        """ Check that one letter queries aren't permitted. """
+        views.find_best_matches(u't')
+
+    def test_match_by_prefix(self):
+        """ Tags should be matched by prefix of words within it's name. """
+        self.assertEqual(views.find_best_matches(u'Ada'), (self.author_tag,))
+        self.assertEqual(views.find_best_matches(u'Mic'), (self.author_tag,))
+        self.assertEqual(views.find_best_matches(u'Mickiewicz'), (self.author_tag,))
+
+    def test_match_case_insensitive(self):
+        """ Tag names should match case insensitive. """
+        self.assertEqual(views.find_best_matches(u'adam mickiewicz'), (self.author_tag,))
+
+    def test_match_case_insensitive_unicode(self):
+        """ Tag names should match case insensitive (unicode). """
+        self.assertEqual(views.find_best_matches(u'tadeusz żeleński (boy)'), (self.unicode_tag,))
+
+    def test_word_boundary(self):
+        self.assertEqual(views.find_best_matches(u'SubWord'), (self.author_tag,))
+        self.assertEqual(views.find_best_matches(u'[SubWord'), (self.author_tag,))
+
+    def test_unrelated_search(self):
+        self.assertEqual(views.find_best_matches(u'alamakota'), tuple())
+        self.assertEqual(views.find_best_matches(u'Adama'), ())
+
+    def test_infix_doesnt_match(self):
+        """ Searching for middle of a word shouldn't match. """
+        self.assertEqual(views.find_best_matches(u'deusz'), tuple())
+
+    def test_diactricts_removal_pl(self):
+        """ Tags should match both with and without national characters. """
+        self.assertEqual(views.find_best_matches(u'ĘÓĄŚŁŻŹĆŃęóąśłżźćń'), (self.polish_tag,))
+        self.assertEqual(views.find_best_matches(u'EOASLZZCNeoaslzzcn'), (self.polish_tag,))
+        self.assertEqual(views.find_best_matches(u'eoaslzzcneoaslzzcn'), (self.polish_tag,))
+
+    def test_diactricts_query_removal_pl(self):
+        """ Tags without national characters shouldn't be matched by queries with them. """
+        self.assertEqual(views.find_best_matches(u'Adąm'), ())
+
+    def test_sloppy(self):
+        self.assertEqual(views.find_best_matches(u'Żelenski'), (self.unicode_tag,))
+        self.assertEqual(views.find_best_matches(u'zelenski'), (self.unicode_tag,))
diff --git a/apps/catalogue/tests/tags.py b/apps/catalogue/tests/tags.py
new file mode 100644 (file)
index 0000000..f9102a7
--- /dev/null
@@ -0,0 +1,257 @@
+# -*- coding: utf-8 -*-
+from catalogue import models
+from catalogue.test_utils import *
+from django.core.files.base import ContentFile
+from slughifi import slughifi
+
+from nose.tools import raises
+
+def info_args(title):
+    """ generate some keywords for comfortable BookInfoCreation  """
+    slug = unicode(slughifi(title))
+    return {
+        'title': unicode(title),
+        'slug': slug,
+        'url': u"http://wolnelektury.pl/example/%s" % slug,
+        'about': u"http://wolnelektury.pl/example/URI/%s" % slug,
+    }
+
+
+class BooksByTagTests(WLTestCase):
+    """ tests the /katalog/tag page for found books """
+
+    def setUp(self):
+        WLTestCase.setUp(self)
+        author = PersonStub(("Common",), "Man")
+        tags = dict(genre='G', epoch='E', author=author, kind="K")
+
+        # grandchild
+        kwargs = info_args(u"GChild")
+        kwargs.update(tags)
+        gchild_info = BookInfoStub(**kwargs)
+        # child
+        kwargs = info_args(u"Child")
+        kwargs.update(tags)
+        child_info = BookInfoStub(parts=[gchild_info.url], **kwargs)
+        # other grandchild
+        kwargs = info_args(u"Different GChild")
+        kwargs.update(tags)
+        diffgchild_info = BookInfoStub(**kwargs)
+        # other child
+        kwargs = info_args(u"Different Child")
+        kwargs.update(tags)
+        kwargs['kind'] = 'K2'
+        diffchild_info = BookInfoStub(parts=[diffgchild_info.url], **kwargs)
+        # parent
+        kwargs = info_args(u"Parent")
+        kwargs.update(tags)
+        parent_info = BookInfoStub(parts=[child_info.url, diffchild_info.url], **kwargs)
+
+        # create the books
+        book_file = ContentFile('<utwor />')
+        for info in gchild_info, child_info, diffgchild_info, diffchild_info, parent_info:
+            book = models.Book.from_text_and_meta(book_file, info)
+
+        # useful tags
+        self.author = models.Tag.objects.get(name='Common Man', category='author')
+        models.Tag.objects.create(name='Empty tag', slug='empty', category='author')
+
+    def test_nonexistent_tag(self):
+        """ Looking for a non-existent tag should yield 404 """
+        # NOTE: this yields a false positive, 'cause of URL change
+        self.assertEqual(404, self.client.get('/katalog/czeslaw_milosz/').status_code)
+
+    def test_book_tag(self):
+        """ Looking for a book tag isn't permitted """
+        self.assertEqual(404, self.client.get('/katalog/parent/').status_code)
+
+    def test_tag_empty(self):
+        """ Tag with no books should return no books """
+        context = self.client.get('/katalog/empty/').context
+        self.assertEqual(0, len(context['object_list']))
+
+    def test_tag_common(self):
+        """ Filtering by tag should only yield top-level books. """
+        context = self.client.get('/katalog/%s/' % self.author.slug).context
+        self.assertEqual([book.title for book in context['object_list']],
+                         ['Parent'])
+
+    def test_tag_child(self):
+        """ Filtering by child's tag should yield the child """
+        context = self.client.get('/katalog/k2/').context
+        self.assertEqual([book.title for book in context['object_list']],
+                         ['Different Child'])
+
+    def test_tag_child_jump(self):
+        """ Of parent and grandchild, only parent should be returned. """
+        context = self.client.get('/katalog/k/').context
+        self.assertEqual([book.title for book in context['object_list']],
+                         ['Parent'])
+
+
+class TagRelatedTagsTests(WLTestCase):
+    """ tests the /katalog/tag/ page for related tags """
+
+    def setUp(self):
+        WLTestCase.setUp(self)
+        author = PersonStub(("Common",), "Man")
+
+        gchild_info = BookInfoStub(author=author, genre="GchildGenre", epoch='Epoch', kind="Kind",
+                                   **info_args(u"GChild"))
+        child1_info = BookInfoStub(author=author, genre="ChildGenre", epoch='Epoch', kind="ChildKind",
+                                   parts=[gchild_info.url],
+                                   **info_args(u"Child1"))
+        child2_info = BookInfoStub(author=author, genre="ChildGenre", epoch='Epoch', kind="ChildKind",
+                                   **info_args(u"Child2"))
+        parent_info = BookInfoStub(author=author, genre="Genre", epoch='Epoch', kind="Kind",
+                                   parts=[child1_info.url, child2_info.url],
+                                   **info_args(u"Parent"))
+
+        for info in gchild_info, child1_info, child2_info, parent_info:
+            book_text = """<utwor><opowiadanie><akap>
+                <begin id="m01" />
+                    <motyw id="m01">Theme, %sTheme</motyw>
+                    Ala ma kota
+                <end id="m01" />
+                </akap></opowiadanie></utwor>
+                """ % info.title.encode('utf-8')
+            book = models.Book.from_text_and_meta(ContentFile(book_text), info)
+            book.save()
+
+        tag_empty = models.Tag(name='Empty tag', slug='empty', category='author')
+        tag_empty.save()
+
+    def test_empty(self):
+        """ empty tag should have no related tags """
+
+        cats = self.client.get('/katalog/empty/').context['categories']
+        self.assertEqual(cats, {}, 'tags related to empty tag')
+
+    def test_has_related(self):
+        """ related own and descendants' tags should be generated """
+
+        cats = self.client.get('/katalog/kind/').context['categories']
+        self.assertTrue('Common Man' in [tag.name for tag in cats['author']],
+                        'missing `author` related tag')
+        self.assertTrue('Epoch' in [tag.name for tag in cats['epoch']],
+                        'missing `epoch` related tag')
+        self.assertTrue("ChildKind" in [tag.name for tag in cats['kind']],
+                        "missing `kind` related tag")
+        self.assertTrue("Genre" in [tag.name for tag in cats['genre']],
+                        'missing `genre` related tag')
+        self.assertTrue("ChildGenre" in [tag.name for tag in cats['genre']],
+                        "missing child's related tag")
+        self.assertTrue("GchildGenre" in [tag.name for tag in cats['genre']],
+                        "missing grandchild's related tag")
+        self.assertTrue('Theme' in [tag.name for tag in cats['theme']],
+                        "missing related theme")
+        self.assertTrue('Child1Theme' in [tag.name for tag in cats['theme']],
+                        "missing child's related theme")
+        self.assertTrue('GChildTheme' in [tag.name for tag in cats['theme']],
+                        "missing grandchild's related theme")
+
+
+    def test_related_differ(self):
+        """ related tags shouldn't include filtering tags """
+
+        cats = self.client.get('/katalog/kind/').context['categories']
+        self.assertFalse('Kind' in [tag.name for tag in cats['kind']],
+                         'filtering tag wrongly included in related')
+        cats = self.client.get('/katalog/theme/').context['categories']
+        self.assertFalse('Theme' in [tag.name for tag in cats['theme']],
+                         'filtering theme wrongly included in related')
+
+
+    def test_parent_tag_once(self):
+        """ if parent and descendants have a common tag, count it only once """
+
+        cats = self.client.get('/katalog/kind/').context['categories']
+        self.assertEqual([(tag.name, tag.count) for tag in cats['epoch']],
+                         [('Epoch', 1)],
+                         'wrong related tag epoch tag on tag page')
+
+
+    def test_siblings_tags_add(self):
+        """ if children have tags and parent hasn't, count the children """
+
+        cats = self.client.get('/katalog/epoch/').context['categories']
+        self.assertTrue(('ChildKind', 2) in [(tag.name, tag.count) for tag in cats['kind']],
+                    'wrong related kind tags on tag page')
+
+    def test_themes_add(self):
+        """ all occurencies of theme should be counted """
+
+        cats = self.client.get('/katalog/epoch/').context['categories']
+        self.assertTrue(('Theme', 4) in [(tag.name, tag.count) for tag in cats['theme']],
+                    'wrong related theme count')
+
+
+class CleanTagRelationTests(WLTestCase):
+    """ tests for tag relations cleaning after deleting things """
+
+    def setUp(self):
+        WLTestCase.setUp(self)
+        author = PersonStub(("Common",), "Man")
+
+        book_info = BookInfoStub(author=author, genre="G", epoch='E', kind="K",
+                                   **info_args(u"Book"))
+        book_text = """<utwor><opowiadanie><akap>
+            <begin id="m01" /><motyw id="m01">Theme</motyw>Ala ma kota
+            <end id="m01" />
+            </akap></opowiadanie></utwor>
+            """
+        book = models.Book.from_text_and_meta(ContentFile(book_text), book_info)
+
+    def test_delete_objects(self):
+        """ there should be no related tags left after deleting some objects """
+
+        models.Book.objects.all().delete()
+        cats = self.client.get('/katalog/k/').context['categories']
+        self.assertEqual(cats, {})
+
+    def test_deleted_tag(self):
+        """ there should be no tag relations left after deleting tags """
+
+        models.Tag.objects.all().delete()
+        cats = self.client.get('/katalog/lektura/book/').context['categories']
+        self.assertEqual(cats, {})
+
+
+class TestIdenticalTag(WLTestCase):
+
+    def setUp(self):
+        WLTestCase.setUp(self)
+        author = PersonStub((), "Tag")
+
+        self.book_info = BookInfoStub(author=author,
+                                 genre="tag",
+                                 epoch='tag',
+                                 kind="tag",
+                                   **info_args(u"tag"))
+        self.book_text = """<utwor>
+            <opowiadanie>
+            <akap>
+                <begin id="m01" /><motyw id="m01">tag</motyw>Ala ma kota<end id="m01" />
+            </akap>
+            </opowiadanie>
+            </utwor>
+        """
+
+
+    def test_book_tags(self):
+        """ there should be all related tags in relevant categories """
+        models.Book.from_text_and_meta(ContentFile(self.book_text), self.book_info)
+
+        cats = self.client.get('/katalog/lektura/tag/').context['categories']
+        for category in 'author', 'kind', 'genre', 'epoch', 'theme':
+            self.assertTrue('tag' in [tag.name for tag in cats[category]],
+                            'missing related tag for %s' % category)
+
+    def test_qualified_url(self):
+        models.Book.from_text_and_meta(ContentFile(self.book_text), self.book_info)
+        categories = {'author': 'autor', 'theme': 'motyw', 'epoch': 'epoka', 'kind':'rodzaj', 'genre':'gatunek'}
+        for cat, localcat in categories.iteritems():
+            context = self.client.get('/katalog/%s/tag/' % localcat).context
+            self.assertEqual(1, len(context['object_list']))
+            self.assertNotEqual({}, context['categories'])
+            self.assertFalse(cat in context['categories'])
index 25389f4..4d44dc6 100644 (file)
@@ -20,7 +20,7 @@ urlpatterns = patterns('catalogue.views',
 
     # tools
     url(r'^zegar', 'clock', name='clock'),
 
     # tools
     url(r'^zegar', 'clock', name='clock'),
-    
+
     # Public interface. Do not change this URLs.
     url(r'^lektura/(?P<slug>[a-zA-Z0-9-]+)\.html$', 'book_text', name='book_text'),
     url(r'^lektura/(?P<slug>[a-zA-Z0-9-]+)/$', 'book_detail', name='book_detail'),
     # Public interface. Do not change this URLs.
     url(r'^lektura/(?P<slug>[a-zA-Z0-9-]+)\.html$', 'book_text', name='book_text'),
     url(r'^lektura/(?P<slug>[a-zA-Z0-9-]+)/$', 'book_detail', name='book_detail'),
index 36bd9e7..e44b379 100644 (file)
@@ -19,7 +19,7 @@ MAX_SESSION_KEY = 18446744073709551616L     # 2 << 63
 
 
 def get_random_hash(seed):
 
 
 def get_random_hash(seed):
-    sha_digest = sha_constructor('%s%s%s%s' % 
+    sha_digest = sha_constructor('%s%s%s%s' %
         (randrange(0, MAX_SESSION_KEY), time.time(), unicode(seed).encode('utf-8', 'replace'),
         settings.SECRET_KEY)).digest()
     return urlsafe_b64encode(sha_digest).replace('=', '').replace('_', '-').lower()
         (randrange(0, MAX_SESSION_KEY), time.time(), unicode(seed).encode('utf-8', 'replace'),
         settings.SECRET_KEY)).digest()
     return urlsafe_b64encode(sha_digest).replace('=', '').replace('_', '-').lower()
index 4476fd2..47abe63 100644 (file)
@@ -9,7 +9,7 @@ import pprint
 import traceback
 import re
 import itertools
 import traceback
 import re
 import itertools
-from operator import itemgetter 
+from operator import itemgetter
 
 from django.conf import settings
 from django.template import RequestContext
 
 from django.conf import settings
 from django.template import RequestContext
@@ -83,7 +83,7 @@ def differentiate_tags(request, tags, ambiguous_slugs):
             'tags': [tag]
         })
     return render_to_response('catalogue/differentiate_tags.html',
             'tags': [tag]
         })
     return render_to_response('catalogue/differentiate_tags.html',
-                {'tags': tags, 'options': options, 'unparsed': ambiguous_slugs[1:]}, 
+                {'tags': tags, 'options': options, 'unparsed': ambiguous_slugs[1:]},
                 context_instance=RequestContext(request))
 
 
                 context_instance=RequestContext(request))
 
 
@@ -122,7 +122,7 @@ def tagged_object_list(request, tags=''):
             fragments = models.Fragment.tagged.with_any(l_tags, fragments)
 
         # newtagging goes crazy if we just try:
             fragments = models.Fragment.tagged.with_any(l_tags, fragments)
 
         # newtagging goes crazy if we just try:
-        #related_tags = models.Tag.objects.usage_for_queryset(fragments, counts=True, 
+        #related_tags = models.Tag.objects.usage_for_queryset(fragments, counts=True,
         #                    extra={'where': ["catalogue_tag.category != 'book'"]})
         fragment_keys = [fragment.pk for fragment in fragments]
         if fragment_keys:
         #                    extra={'where': ["catalogue_tag.category != 'book'"]})
         fragment_keys = [fragment.pk for fragment in fragments]
         if fragment_keys:
@@ -141,7 +141,7 @@ def tagged_object_list(request, tags=''):
         descendants_keys = [book.pk for book in models.Book.tagged.with_any(l_tags)]
         if descendants_keys:
             objects = objects.exclude(pk__in=descendants_keys)
         descendants_keys = [book.pk for book in models.Book.tagged.with_any(l_tags)]
         if descendants_keys:
             objects = objects.exclude(pk__in=descendants_keys)
-        
+
         # get related tags from `tag_counter` and `theme_counter`
         related_counts = {}
         tags_pks = [tag.pk for tag in tags]
         # get related tags from `tag_counter` and `theme_counter`
         related_counts = {}
         tags_pks = [tag.pk for tag in tags]
@@ -154,7 +154,7 @@ def tagged_object_list(request, tags=''):
         related_tags = [tag for tag in related_tags if tag not in tags]
         for tag in related_tags:
             tag.count = related_counts[tag.pk]
         related_tags = [tag for tag in related_tags if tag not in tags]
         for tag in related_tags:
             tag.count = related_counts[tag.pk]
-        
+
         categories = split_tags(related_tags)
         del related_tags
 
         categories = split_tags(related_tags)
         del related_tags
 
@@ -238,7 +238,7 @@ def book_text(request, slug):
 
 def _no_diacritics_regexp(query):
     """ returns a regexp for searching for a query without diacritics
 
 def _no_diacritics_regexp(query):
     """ returns a regexp for searching for a query without diacritics
-    
+
     should be locale-aware """
     names = {
         u'a':u'aąĄ', u'c':u'cćĆ', u'e':u'eęĘ', u'l': u'lłŁ', u'n':u'nńŃ', u'o':u'oóÓ', u's':u'sśŚ', u'z':u'zźżŹŻ',
     should be locale-aware """
     names = {
         u'a':u'aąĄ', u'c':u'cćĆ', u'e':u'eęĘ', u'l': u'lłŁ', u'n':u'nńŃ', u'o':u'oóÓ', u's':u'sśŚ', u'z':u'zźżŹŻ',
@@ -256,16 +256,16 @@ def unicode_re_escape(query):
 def _word_starts_with(name, prefix):
     """returns a Q object getting models having `name` contain a word
     starting with `prefix`
 def _word_starts_with(name, prefix):
     """returns a Q object getting models having `name` contain a word
     starting with `prefix`
-    
+
     We define word characters as alphanumeric and underscore, like in JS.
     We define word characters as alphanumeric and underscore, like in JS.
-    
+
     Works for MySQL, PostgreSQL, Oracle.
     For SQLite, _sqlite* version is substituted for this.
     """
     kwargs = {}
 
     prefix = _no_diacritics_regexp(unicode_re_escape(prefix))
     Works for MySQL, PostgreSQL, Oracle.
     For SQLite, _sqlite* version is substituted for this.
     """
     kwargs = {}
 
     prefix = _no_diacritics_regexp(unicode_re_escape(prefix))
-    # can't use [[:<:]] (word start), 
+    # can't use [[:<:]] (word start),
     # but we want both `xy` and `(xy` to catch `(xyz)`
     kwargs['%s__iregex' % name] = u"(^|[^[:alnum:]_])%s" % prefix
 
     # but we want both `xy` and `(xy` to catch `(xyz)`
     kwargs['%s__iregex' % name] = u"(^|[^[:alnum:]_])%s" % prefix
 
@@ -273,8 +273,8 @@ def _word_starts_with(name, prefix):
 
 
 def _sqlite_word_starts_with(name, prefix):
 
 
 def _sqlite_word_starts_with(name, prefix):
-    """ version of _word_starts_with for SQLite 
-    
+    """ version of _word_starts_with for SQLite
+
     SQLite in Django uses Python re module
     """
     kwargs = {}
     SQLite in Django uses Python re module
     """
     kwargs = {}
@@ -320,12 +320,12 @@ def _get_result_type(match):
 
 def find_best_matches(query, user=None):
     """ Finds a Book, Tag or Bookstub best matching a query.
 
 def find_best_matches(query, user=None):
     """ Finds a Book, Tag or Bookstub best matching a query.
-    
+
     Returns a with:
       - zero elements when nothing is found,
       - one element when a best result is found,
       - more then one element on multiple exact matches
     Returns a with:
       - zero elements when nothing is found,
       - one element when a best result is found,
       - more then one element on multiple exact matches
-    
+
     Raises a ValueError on too short a query.
     """
 
     Raises a ValueError on too short a query.
     """
 
@@ -458,7 +458,7 @@ def download_shelf(request, slug):
     """"
     Create a ZIP archive on disk and transmit it in chunks of 8KB,
     without loading the whole file into memory. A similar approach can
     """"
     Create a ZIP archive on disk and transmit it in chunks of 8KB,
     without loading the whole file into memory. A similar approach can
-    be used for large dynamic PDF files.                                        
+    be used for large dynamic PDF files.
     """
     shelf = get_object_or_404(models.Tag, slug=slug, category='set')
 
     """
     shelf = get_object_or_404(models.Tag, slug=slug, category='set')
 
index 86f0466..cd9cf4e 100644 (file)
@@ -15,7 +15,7 @@ class Chunk(models.Model):
         ordering = ('key',)
         verbose_name = _('chunk')
         verbose_name_plural = _('chunks')
         ordering = ('key',)
         verbose_name = _('chunk')
         verbose_name_plural = _('chunks')
-    
+
     def __unicode__(self):
         return self.key
 
     def __unicode__(self):
         return self.key
 
@@ -23,7 +23,7 @@ class Chunk(models.Model):
 class Attachment(models.Model):
     key = models.CharField(_('key'), help_text=_('A unique name for this attachment'), primary_key=True, max_length=255)
     attachment = models.FileField(upload_to='chunks/attachment')
 class Attachment(models.Model):
     key = models.CharField(_('key'), help_text=_('A unique name for this attachment'), primary_key=True, max_length=255)
     attachment = models.FileField(upload_to='chunks/attachment')
-    
+
     class Meta:
         ordering = ('key',)
         verbose_name, verbose_name_plural = _('attachment'), _('attachments')
     class Meta:
         ordering = ('key',)
         verbose_name, verbose_name_plural = _('attachment'), _('attachments')
index 595482f..083c48a 100644 (file)
@@ -30,7 +30,7 @@ class ChunkNode(template.Node):
     def __init__(self, key, cache_time=0):
        self.key = key
        self.cache_time = cache_time
     def __init__(self, key, cache_time=0):
        self.key = key
        self.cache_time = cache_time
-    
+
     def render(self, context):
         try:
             cache_key = 'chunk_' + self.key
     def render(self, context):
         try:
             cache_key = 'chunk_' + self.key
@@ -44,7 +44,7 @@ class ChunkNode(template.Node):
             n.save()
             return ''
         return content
             n.save()
             return ''
         return content
-        
+
 register.tag('chunk', do_get_chunk)
 
 
 register.tag('chunk', do_get_chunk)
 
 
@@ -58,6 +58,6 @@ def attachment(key, cache_time=0):
         return c.attachment.url
     except Attachment.DoesNotExist:
         return ''
         return c.attachment.url
     except Attachment.DoesNotExist:
         return ''
-    
+
 register.simple_tag(attachment)
 
 register.simple_tag(attachment)
 
index 9b98531..9bb23b2 100644 (file)
@@ -6,7 +6,7 @@ class FilterBase:
         raise NotImplementedError
     def filter_js(self, js):
         raise NotImplementedError
         raise NotImplementedError
     def filter_js(self, js):
         raise NotImplementedError
-        
+
 class FilterError(Exception):
     """
     This exception is raised when a filter fails
 class FilterError(Exception):
     """
     This exception is raised when a filter fails
index d40e8ee..ae7c103 100644 (file)
@@ -18,16 +18,16 @@ class CSSTidyFilter(FilterBase):
         tmp_file.flush()
 
         output_file = tempfile.NamedTemporaryFile(mode='w+b')
         tmp_file.flush()
 
         output_file = tempfile.NamedTemporaryFile(mode='w+b')
-        
+
         command = '%s %s %s %s' % (BINARY, tmp_file.name, ARGUMENTS, output_file.name)
         command = '%s %s %s %s' % (BINARY, tmp_file.name, ARGUMENTS, output_file.name)
-        
+
         command_output = os.popen(command).read()
         command_output = os.popen(command).read()
-        
+
         filtered_css = output_file.read()
         output_file.close()
         tmp_file.close()
         filtered_css = output_file.read()
         output_file.close()
         tmp_file.close()
-        
+
         if self.verbose:
             print command_output
         if self.verbose:
             print command_output
-        
+
         return filtered_css
         return filtered_css
index 7d581ed..03a4ac0 100644 (file)
@@ -8,12 +8,12 @@ COMPRESS_CSSTIDY_SETTINGS = getattr(settings, 'COMPRESS_CSSTIDY_SETTINGS', {})
 class CSSTidyFilter(FilterBase):
     def filter_css(self, css):
         tidy = CSSTidy()
 class CSSTidyFilter(FilterBase):
     def filter_css(self, css):
         tidy = CSSTidy()
-        
+
         for k, v in COMPRESS_CSSTIDY_SETTINGS.items():
             tidy.setSetting(k, v)
 
         tidy.parse(css)
 
         r = tidy.Output('string')
         for k, v in COMPRESS_CSSTIDY_SETTINGS.items():
             tidy.setSetting(k, v)
 
         tidy.parse(css)
 
         r = tidy.Output('string')
-        
+
         return r
         return r
index 6e31d25..f5624f5 100644 (file)
@@ -14,7 +14,7 @@ class Command(NoArgsCommand):
     args = ''
 
     def handle_noargs(self, **options):
     args = ''
 
     def handle_noargs(self, **options):
-        
+
         force = options.get('force', False)
         verbosity = int(options.get('verbosity', 1))
 
         force = options.get('force', False)
         verbosity = int(options.get('verbosity', 1))
 
index 3c59728..89b04a5 100644 (file)
@@ -97,7 +97,7 @@ def get_version(version):
     except ValueError:
         return str(version)
 
     except ValueError:
         return str(version)
 
-def remove_files(path, filename, verbosity=0):    
+def remove_files(path, filename, verbosity=0):
     regex = re.compile(r'^%s$' % (os.path.basename(get_output_filename(settings.COMPRESS_VERSION_PLACEHOLDER.join([re.escape(part) for part in filename.split(settings.COMPRESS_VERSION_PLACEHOLDER)]), r'\d+'))))
 
     for f in os.listdir(path):
     regex = re.compile(r'^%s$' % (os.path.basename(get_output_filename(settings.COMPRESS_VERSION_PLACEHOLDER.join([re.escape(part) for part in filename.split(settings.COMPRESS_VERSION_PLACEHOLDER)]), r'\d+'))))
 
     for f in os.listdir(path):
index a1289a2..a28ce3a 100644 (file)
@@ -5,9 +5,9 @@ from south.v2 import SchemaMigration
 from django.db import models
 
 class Migration(SchemaMigration):
 from django.db import models
 
 class Migration(SchemaMigration):
-    
+
     def forwards(self, orm):
     def forwards(self, orm):
-        
+
         # Adding model 'InfoPage'
         db.create_table('infopages_infopage', (
             ('title_de', self.gf('django.db.models.fields.CharField')(max_length=120, null=True, blank=True)),
         # Adding model 'InfoPage'
         db.create_table('infopages_infopage', (
             ('title_de', self.gf('django.db.models.fields.CharField')(max_length=120, null=True, blank=True)),
@@ -55,14 +55,14 @@ class Migration(SchemaMigration):
             call_command("loaddata", "wl_data")
 
         db.send_create_signal('infopages', ['InfoPage'])
             call_command("loaddata", "wl_data")
 
         db.send_create_signal('infopages', ['InfoPage'])
-    
-    
+
+
     def backwards(self, orm):
     def backwards(self, orm):
-        
+
         # Deleting model 'InfoPage'
         db.delete_table('infopages_infopage')
         # Deleting model 'InfoPage'
         db.delete_table('infopages_infopage')
-    
-    
+
+
     models = {
         'infopages.infopage': {
             'Meta': {'object_name': 'InfoPage'},
     models = {
         'infopages.infopage': {
             'Meta': {'object_name': 'InfoPage'},
@@ -106,5 +106,5 @@ class Migration(SchemaMigration):
             'title_uk': ('django.db.models.fields.CharField', [], {'max_length': '120', 'null': True, 'blank': True})
         }
     }
             'title_uk': ('django.db.models.fields.CharField', [], {'max_length': '120', 'null': True, 'blank': True})
         }
     }
-    
+
     complete_apps = ['infopages']
     complete_apps = ['infopages']
index 5026da2..9fe7b32 100644 (file)
@@ -9,7 +9,7 @@ class InfoPage(models.Model):
     """
     An InfoPage is used to display a two-column flatpage
     """
     """
     An InfoPage is used to display a two-column flatpage
     """
-    
+
     page_title = models.CharField(_('page title'), max_length=120, blank=True)
     slug = models.SlugField(_('slug'), max_length=120, unique=True, db_index=True)
     title = models.CharField(_('title'), max_length=120, blank=True)
     page_title = models.CharField(_('page title'), max_length=120, blank=True)
     slug = models.SlugField(_('slug'), max_length=120, unique=True, db_index=True)
     title = models.CharField(_('title'), max_length=120, blank=True)
@@ -20,7 +20,7 @@ class InfoPage(models.Model):
         ordering = ('slug',)
         verbose_name = _('info page')
         verbose_name_plural = _('info pages')
         ordering = ('slug',)
         verbose_name = _('info page')
         verbose_name_plural = _('info pages')
-    
+
     def __unicode__(self):
         return self.title
 
     def __unicode__(self):
         return self.title
 
index dc113ed..ffb2b6c 100644 (file)
@@ -16,14 +16,14 @@ class Document(models.Model):
     slideshare_id = models.CharField(_('slideshare ID'), blank=True, max_length=120)
     description = models.TextField(_('description'), blank=True)
     created_at = models.DateTimeField(auto_now_add=True)
     slideshare_id = models.CharField(_('slideshare ID'), blank=True, max_length=120)
     description = models.TextField(_('description'), blank=True)
     created_at = models.DateTimeField(auto_now_add=True)
-    
+
     def slideshare_player(self):
         base, ext = path.splitext(self.file.name)
         if ext in ('.ppt', '.pps', '.pot', '.pptx', '.potx', '.ppsx', '.odp', '.key', '.zip', '.pdf',):
             return 'ssplayer2.swf'
         else:
             return 'ssplayerd.swf'
     def slideshare_player(self):
         base, ext = path.splitext(self.file.name)
         if ext in ('.ppt', '.pps', '.pot', '.pptx', '.potx', '.ppsx', '.odp', '.key', '.zip', '.pdf',):
             return 'ssplayer2.swf'
         else:
             return 'ssplayerd.swf'
-    
+
     class Meta:
         ordering = ['slug']
         verbose_name, verbose_name_plural = _("document"), _("documents")
     class Meta:
         ordering = ['slug']
         verbose_name, verbose_name_plural = _("document"), _("documents")
index 69a47e3..6c89e5f 100644 (file)
@@ -15,7 +15,7 @@ urlpatterns = patterns('',
             'form': forms.SearchForm(),
         },
     }, name='lessons_document_list'),
             'form': forms.SearchForm(),
         },
     }, name='lessons_document_list'),
-    
+
     url(r'^(?P<slug>[a-zA-Z0-9_-]+)/$', 'lessons.views.document_detail', name='lessons_document_detail'),
 )
 
     url(r'^(?P<slug>[a-zA-Z0-9_-]+)/$', 'lessons.views.document_detail', name='lessons_document_detail'),
 )
 
index 69380d6..242526d 100644 (file)
@@ -11,7 +11,7 @@ def document_detail(request, slug):
     template_name = 'lessons/document_detail.html'
     if request.is_ajax():
         template_name = 'lessons/ajax_document_detail.html'
     template_name = 'lessons/document_detail.html'
     if request.is_ajax():
         template_name = 'lessons/ajax_document_detail.html'
-    
+
     return object_detail(request,
         slug=slug,
         slug_field='slug',
     return object_detail(request,
         slug=slug,
         slug_field='slug',
index 956d2cf..a8f5110 100644 (file)
@@ -17,7 +17,7 @@ class FilteredSelectMultiple(forms.SelectMultiple):
         js = ['js/SelectBox.js' , 'js/SelectFilter2.js']
         return forms.Media(js=['%s%s' % (settings.ADMIN_MEDIA_PREFIX, url) for url in js])
     media = property(_media)
         js = ['js/SelectBox.js' , 'js/SelectFilter2.js']
         return forms.Media(js=['%s%s' % (settings.ADMIN_MEDIA_PREFIX, url) for url in js])
     media = property(_media)
-    
+
     def __init__(self, verbose_name, is_stacked, attrs=None, choices=()):
         self.verbose_name = verbose_name
         self.is_stacked = is_stacked
     def __init__(self, verbose_name, is_stacked, attrs=None, choices=()):
         self.verbose_name = verbose_name
         self.is_stacked = is_stacked
@@ -44,7 +44,7 @@ class TaggableModelForm(forms.ModelForm):
             kwargs['initial']['tags'] = [tag.id for tag in self.tag_model.objects.get_for_object(kwargs['instance'])]
         super(TaggableModelForm, self).__init__(*args, **kwargs)
         self.fields['tags'].choices = [(tag.id, tag.name) for tag in self.tag_model.objects.all()]
             kwargs['initial']['tags'] = [tag.id for tag in self.tag_model.objects.get_for_object(kwargs['instance'])]
         super(TaggableModelForm, self).__init__(*args, **kwargs)
         self.fields['tags'].choices = [(tag.id, tag.name) for tag in self.tag_model.objects.all()]
-    
+
     def save(self, commit):
         obj = super(TaggableModelForm, self).save()
         tag_ids = self.cleaned_data['tags']
     def save(self, commit):
         obj = super(TaggableModelForm, self).save()
         tag_ids = self.cleaned_data['tags']
@@ -59,7 +59,7 @@ class TaggableModelForm(forms.ModelForm):
 
 class TaggableModelAdmin(admin.ModelAdmin):
     form = TaggableModelForm
 
 class TaggableModelAdmin(admin.ModelAdmin):
     form = TaggableModelForm
-    
+
     def get_form(self, request, obj=None):
         form = super(TaggableModelAdmin, self).get_form(request, obj)
         form.tag_model = self.tag_model
     def get_form(self, request, obj=None):
         form = super(TaggableModelAdmin, self).get_form(request, obj)
         form.tag_model = self.tag_model
index 7870092..3107070 100644 (file)
@@ -14,15 +14,15 @@ class ModelTagManager(models.Manager):
     def __init__(self, tag_model):
         super(ModelTagManager, self).__init__()
         self.tag_model = tag_model
     def __init__(self, tag_model):
         super(ModelTagManager, self).__init__()
         self.tag_model = tag_model
-    
+
     def get_query_set(self):
         content_type = ContentType.objects.get_for_model(self.model)
         return self.tag_model.objects.filter(
             items__content_type__pk=content_type.pk).distinct()
     def get_query_set(self):
         content_type = ContentType.objects.get_for_model(self.model)
         return self.tag_model.objects.filter(
             items__content_type__pk=content_type.pk).distinct()
-    
+
     def related(self, tags, *args, **kwargs):
         return self.tag_model.objects.related_for_model(tags, self.model, *args, **kwargs)
     def related(self, tags, *args, **kwargs):
         return self.tag_model.objects.related_for_model(tags, self.model, *args, **kwargs)
-    
+
     def usage(self, *args, **kwargs):
         return self.tag_model.objects.usage_for_model(self.model, *args, **kwargs)
 
     def usage(self, *args, **kwargs):
         return self.tag_model.objects.usage_for_model(self.model, *args, **kwargs)
 
@@ -62,7 +62,7 @@ class TagDescriptor(object):
     """
     def __init__(self, tag_model):
         self.tag_model = tag_model
     """
     def __init__(self, tag_model):
         self.tag_model = tag_model
-    
+
     def __get__(self, instance, owner):
         if not instance:
             tag_manager = ModelTagManager(self.tag_model)
     def __get__(self, instance, owner):
         if not instance:
             tag_manager = ModelTagManager(self.tag_model)
index 2055ec3..1c35254 100644 (file)
@@ -6,7 +6,7 @@ Models and managers for generic tagging.
 # Python 2.3 compatibility
 try:
     set
 # Python 2.3 compatibility
 try:
     set
-except NameError: 
+except NameError:
     from sets import Set as set
 
 from django.contrib.contenttypes import generic
     from sets import Set as set
 
 from django.contrib.contenttypes import generic
@@ -45,7 +45,7 @@ class TagManager(models.Manager):
     def __init__(self, intermediary_table_model):
         super(TagManager, self).__init__()
         self.intermediary_table_model = intermediary_table_model
     def __init__(self, intermediary_table_model):
         super(TagManager, self).__init__()
         self.intermediary_table_model = intermediary_table_model
-    
+
     def update_tags(self, obj, tags):
         """
         Update tags associated with an object.
     def update_tags(self, obj, tags):
         """
         Update tags associated with an object.
@@ -54,7 +54,7 @@ class TagManager(models.Manager):
         current_tags = list(self.filter(items__content_type__pk=content_type.pk,
                                         items__object_id=obj.pk))
         updated_tags = self.model.get_tag_list(tags)
         current_tags = list(self.filter(items__content_type__pk=content_type.pk,
                                         items__object_id=obj.pk))
         updated_tags = self.model.get_tag_list(tags)
-    
+
         # Remove tags which no longer apply
         tags_for_removal = [tag for tag in current_tags \
                             if tag not in updated_tags]
         # Remove tags which no longer apply
         tags_for_removal = [tag for tag in current_tags \
                             if tag not in updated_tags]
@@ -66,7 +66,7 @@ class TagManager(models.Manager):
         for tag in updated_tags:
             if tag not in current_tags:
                 self.intermediary_table_model._default_manager.create(tag=tag, content_object=obj)
         for tag in updated_tags:
             if tag not in current_tags:
                 self.intermediary_table_model._default_manager.create(tag=tag, content_object=obj)
-    
+
     def remove_tag(self, obj, tag):
         """
         Remove tag from an object.
     def remove_tag(self, obj, tag):
         """
         Remove tag from an object.
@@ -83,7 +83,7 @@ class TagManager(models.Manager):
         ctype = ContentType.objects.get_for_model(obj)
         return self.filter(items__content_type__pk=ctype.pk,
                            items__object_id=obj.pk)
         ctype = ContentType.objects.get_for_model(obj)
         return self.filter(items__content_type__pk=ctype.pk,
                            items__object_id=obj.pk)
-    
+
     def _get_usage(self, model, counts=False, min_count=None, extra_joins=None, extra_criteria=None, params=None, extra=None):
         """
         Perform the custom SQL query for ``usage_for_model`` and
     def _get_usage(self, model, counts=False, min_count=None, extra_joins=None, extra_criteria=None, params=None, extra=None):
         """
         Perform the custom SQL query for ``usage_for_model`` and
@@ -94,12 +94,12 @@ class TagManager(models.Manager):
         model_table = qn(model._meta.db_table)
         model_pk = '%s.%s' % (model_table, qn(model._meta.pk.column))
         tag_columns = self._get_tag_columns()
         model_table = qn(model._meta.db_table)
         model_pk = '%s.%s' % (model_table, qn(model._meta.pk.column))
         tag_columns = self._get_tag_columns()
-        
+
         if extra is None: extra = {}
         extra_where = ''
         if 'where' in extra:
             extra_where = 'AND ' + ' AND '.join(extra['where'])
         if extra is None: extra = {}
         extra_where = ''
         if 'where' in extra:
             extra_where = 'AND ' + ' AND '.join(extra['where'])
-        
+
         query = """
         SELECT DISTINCT %(tag_columns)s%(count_sql)s
         FROM
         query = """
         SELECT DISTINCT %(tag_columns)s%(count_sql)s
         FROM
@@ -224,12 +224,12 @@ class TagManager(models.Manager):
         tag_count = len(tags)
         tagged_item_table = qn(self.intermediary_table_model._meta.db_table)
         tag_columns = self._get_tag_columns()
         tag_count = len(tags)
         tagged_item_table = qn(self.intermediary_table_model._meta.db_table)
         tag_columns = self._get_tag_columns()
-        
+
         if extra is None: extra = {}
         extra_where = ''
         if 'where' in extra:
             extra_where = 'AND ' + ' AND '.join(extra['where'])
         if extra is None: extra = {}
         extra_where = ''
         if 'where' in extra:
             extra_where = 'AND ' + ' AND '.join(extra['where'])
-        
+
         # Temporary table in this query is a hack to prevent MySQL from executing
         # inner query as dependant query (which could result in severe performance loss)
         query = """
         # Temporary table in this query is a hack to prevent MySQL from executing
         # inner query as dependant query (which could result in severe performance loss)
         query = """
@@ -301,7 +301,7 @@ class TaggedItemManager(models.Manager):
     def __init__(self, tag_model):
         super(TaggedItemManager, self).__init__()
         self.tag_model = tag_model
     def __init__(self, tag_model):
         super(TaggedItemManager, self).__init__()
         self.tag_model = tag_model
-    
+
     def get_by_model(self, queryset_or_model, tags):
         """
         Create a ``QuerySet`` containing instances of the specified
     def get_by_model(self, queryset_or_model, tags):
         """
         Create a ``QuerySet`` containing instances of the specified
@@ -473,7 +473,7 @@ class TaggedItemManager(models.Manager):
 def create_intermediary_table_model(model):
     """Create an intermediary table model for the specific tag model"""
     name = model.__name__ + 'Relation'
 def create_intermediary_table_model(model):
     """Create an intermediary table model for the specific tag model"""
     name = model.__name__ + 'Relation'
-     
+
     class Meta:
         db_table = '%s_relation' % model._meta.db_table
         unique_together = (('tag', 'content_type', 'object_id'),)
     class Meta:
         db_table = '%s_relation' % model._meta.db_table
         unique_together = (('tag', 'content_type', 'object_id'),)
@@ -483,8 +483,8 @@ def create_intermediary_table_model(model):
             return u'%s [%s]' % (self.content_type.get_object_for_this_type(pk=self.object_id), self.tag)
         except ObjectDoesNotExist:
             return u'<deleted> [%s]' % self.tag
             return u'%s [%s]' % (self.content_type.get_object_for_this_type(pk=self.object_id), self.tag)
         except ObjectDoesNotExist:
             return u'<deleted> [%s]' % self.tag
-            
-    # Set up a dictionary to simulate declarations within a class    
+
+    # Set up a dictionary to simulate declarations within a class
     attrs = {
         '__module__': model.__module__,
         'Meta': Meta,
     attrs = {
         '__module__': model.__module__,
         'Meta': Meta,
@@ -513,15 +513,15 @@ class TagMeta(ModelBase):
 class TagBase(models.Model):
     """Abstract class to be inherited by model classes."""
     __metaclass__ = TagMeta
 class TagBase(models.Model):
     """Abstract class to be inherited by model classes."""
     __metaclass__ = TagMeta
-    
+
     class Meta:
         abstract = True
     class Meta:
         abstract = True
-    
+
     @staticmethod
     def get_tag_list(tag_list):
         """
         Utility function for accepting tag input in a flexible manner.
     @staticmethod
     def get_tag_list(tag_list):
         """
         Utility function for accepting tag input in a flexible manner.
-        
+
         You should probably override this method in your subclass.
         """
         if isinstance(tag_list, TagBase):
         You should probably override this method in your subclass.
         """
         if isinstance(tag_list, TagBase):
index 7d09707..19b8e82 100644 (file)
@@ -26,7 +26,7 @@ class NoAuthentication(object):
 class HttpBasicAuthentication(object):
     """
     Basic HTTP authenticater. Synopsis:
 class HttpBasicAuthentication(object):
     """
     Basic HTTP authenticater. Synopsis:
-    
+
     Authentication handlers must implement two methods:
      - `is_authenticated`: Will be called when checking for
         authentication. Receives a `request` object, please
     Authentication handlers must implement two methods:
      - `is_authenticated`: Will be called when checking for
         authentication. Receives a `request` object, please
@@ -46,7 +46,7 @@ class HttpBasicAuthentication(object):
 
         if not auth_string:
             return False
 
         if not auth_string:
             return False
-            
+
         try:
             (authmeth, auth) = auth_string.split(" ", 1)
 
         try:
             (authmeth, auth) = auth_string.split(" ", 1)
 
@@ -57,12 +57,12 @@ class HttpBasicAuthentication(object):
             (username, password) = auth.split(':', 1)
         except (ValueError, binascii.Error):
             return False
             (username, password) = auth.split(':', 1)
         except (ValueError, binascii.Error):
             return False
-        
+
         request.user = self.auth_func(username=username, password=password) \
             or AnonymousUser()
         request.user = self.auth_func(username=username, password=password) \
             or AnonymousUser()
-                
+
         return not request.user in (False, None, AnonymousUser())
         return not request.user in (False, None, AnonymousUser())
-        
+
     def challenge(self):
         resp = HttpResponse("Authorization Required")
         resp['WWW-Authenticate'] = 'Basic realm="%s"' % self.realm
     def challenge(self):
         resp = HttpResponse("Authorization Required")
         resp['WWW-Authenticate'] = 'Basic realm="%s"' % self.realm
@@ -78,7 +78,7 @@ class HttpBasicSimple(HttpBasicAuthentication):
         self.password = password
 
         super(HttpBasicSimple, self).__init__(auth_func=self.hash, realm=realm)
         self.password = password
 
         super(HttpBasicSimple, self).__init__(auth_func=self.hash, realm=realm)
-    
+
     def hash(self, username, password):
         if username == self.user.username and password == self.password:
             return self.user
     def hash(self, username, password):
         if username == self.user.username and password == self.password:
             return self.user
@@ -122,17 +122,17 @@ def initialize_server_request(request):
     request.META['Authorization'] = request.META.get('HTTP_AUTHORIZATION', '')
 
     oauth_request = oauth.OAuthRequest.from_request(
     request.META['Authorization'] = request.META.get('HTTP_AUTHORIZATION', '')
 
     oauth_request = oauth.OAuthRequest.from_request(
-        request.method, request.build_absolute_uri(), 
+        request.method, request.build_absolute_uri(),
         headers=request.META, parameters=params,
         query_string=request.environ.get('QUERY_STRING', ''))
         headers=request.META, parameters=params,
         query_string=request.environ.get('QUERY_STRING', ''))
-        
+
     if oauth_request:
         oauth_server = oauth.OAuthServer(oauth_datastore(oauth_request))
         oauth_server.add_signature_method(oauth.OAuthSignatureMethod_PLAINTEXT())
         oauth_server.add_signature_method(oauth.OAuthSignatureMethod_HMAC_SHA1())
     else:
         oauth_server = None
     if oauth_request:
         oauth_server = oauth.OAuthServer(oauth_datastore(oauth_request))
         oauth_server.add_signature_method(oauth.OAuthSignatureMethod_PLAINTEXT())
         oauth_server.add_signature_method(oauth.OAuthSignatureMethod_HMAC_SHA1())
     else:
         oauth_server = None
-        
+
     return oauth_server, oauth_request
 
 def send_oauth_error(err=None):
     return oauth_server, oauth_request
 
 def send_oauth_error(err=None):
@@ -152,7 +152,7 @@ def send_oauth_error(err=None):
 
 def oauth_request_token(request):
     oauth_server, oauth_request = initialize_server_request(request)
 
 def oauth_request_token(request):
     oauth_server, oauth_request = initialize_server_request(request)
-    
+
     if oauth_server is None:
         return INVALID_PARAMS_RESPONSE
     try:
     if oauth_server is None:
         return INVALID_PARAMS_RESPONSE
     try:
@@ -176,20 +176,20 @@ def oauth_auth_view(request, token, callback, params):
 @login_required
 def oauth_user_auth(request):
     oauth_server, oauth_request = initialize_server_request(request)
 @login_required
 def oauth_user_auth(request):
     oauth_server, oauth_request = initialize_server_request(request)
-    
+
     if oauth_request is None:
         return INVALID_PARAMS_RESPONSE
     if oauth_request is None:
         return INVALID_PARAMS_RESPONSE
-        
+
     try:
         token = oauth_server.fetch_request_token(oauth_request)
     except oauth.OAuthError, err:
         return send_oauth_error(err)
     try:
         token = oauth_server.fetch_request_token(oauth_request)
     except oauth.OAuthError, err:
         return send_oauth_error(err)
-        
+
     try:
         callback = oauth_server.get_callback(oauth_request)
     except:
         callback = None
     try:
         callback = oauth_server.get_callback(oauth_request)
     except:
         callback = None
-    
+
     if request.method == "GET":
         params = oauth_request.get_normalized_parameters()
 
     if request.method == "GET":
         params = oauth_request.get_normalized_parameters()
 
@@ -207,26 +207,26 @@ def oauth_user_auth(request):
             else:
                 args = '?error=%s' % 'Access not granted by user.'
                 print "FORM ERROR", form.errors
             else:
                 args = '?error=%s' % 'Access not granted by user.'
                 print "FORM ERROR", form.errors
-            
+
             if not callback:
                 callback = getattr(settings, 'OAUTH_CALLBACK_VIEW')
                 return get_callable(callback)(request, token)
             if not callback:
                 callback = getattr(settings, 'OAUTH_CALLBACK_VIEW')
                 return get_callable(callback)(request, token)
-                
+
             response = HttpResponseRedirect(callback+args)
             response = HttpResponseRedirect(callback+args)
-                
+
         except oauth.OAuthError, err:
             response = send_oauth_error(err)
     else:
         response = HttpResponse('Action not allowed.')
         except oauth.OAuthError, err:
             response = send_oauth_error(err)
     else:
         response = HttpResponse('Action not allowed.')
-            
+
     return response
 
 def oauth_access_token(request):
     oauth_server, oauth_request = initialize_server_request(request)
     return response
 
 def oauth_access_token(request):
     oauth_server, oauth_request = initialize_server_request(request)
-    
+
     if oauth_request is None:
         return INVALID_PARAMS_RESPONSE
     if oauth_request is None:
         return INVALID_PARAMS_RESPONSE
-        
+
     try:
         token = oauth_server.fetch_access_token(oauth_request)
         return HttpResponse(token.to_string())
     try:
         token = oauth_server.fetch_access_token(oauth_request)
         return HttpResponse(token.to_string())
@@ -234,7 +234,7 @@ def oauth_access_token(request):
         return send_oauth_error(err)
 
 INVALID_PARAMS_RESPONSE = send_oauth_error(oauth.OAuthError('Invalid request parameters.'))
         return send_oauth_error(err)
 
 INVALID_PARAMS_RESPONSE = send_oauth_error(oauth.OAuthError('Invalid request parameters.'))
-                
+
 class OAuthAuthentication(object):
     """
     OAuth authentication. Based on work by Leah Culver.
 class OAuthAuthentication(object):
     """
     OAuth authentication. Based on work by Leah Culver.
@@ -242,12 +242,12 @@ class OAuthAuthentication(object):
     def __init__(self, realm='API'):
         self.realm = realm
         self.builder = oauth.build_authenticate_header
     def __init__(self, realm='API'):
         self.realm = realm
         self.builder = oauth.build_authenticate_header
-    
+
     def is_authenticated(self, request):
         """
         Checks whether a means of specifying authentication
         is provided, and if so, if it is a valid token.
     def is_authenticated(self, request):
         """
         Checks whether a means of specifying authentication
         is provided, and if so, if it is a valid token.
-        
+
         Read the documentation on `HttpBasicAuthentication`
         for more information about what goes on here.
         """
         Read the documentation on `HttpBasicAuthentication`
         for more information about what goes on here.
         """
@@ -263,14 +263,14 @@ class OAuthAuthentication(object):
                 request.consumer = consumer
                 request.throttle_extra = token.consumer.id
                 return True
                 request.consumer = consumer
                 request.throttle_extra = token.consumer.id
                 return True
-            
+
         return False
         return False
-        
+
     def challenge(self):
         """
         Returns a 401 response with a small bit on
         what OAuth is, and where to learn more about it.
     def challenge(self):
         """
         Returns a 401 response with a small bit on
         what OAuth is, and where to learn more about it.
-        
+
         When this was written, browsers did not understand
         OAuth authentication on the browser side, and hence
         the helpful template we render. Maybe some day in the
         When this was written, browsers did not understand
         OAuth authentication on the browser side, and hence
         the helpful template we render. Maybe some day in the
@@ -290,7 +290,7 @@ class OAuthAuthentication(object):
         response.content = tmpl
 
         return response
         response.content = tmpl
 
         return response
-        
+
     @staticmethod
     def is_valid_request(request):
         """
     @staticmethod
     def is_valid_request(request):
         """
@@ -302,14 +302,14 @@ class OAuthAuthentication(object):
         must_have = [ 'oauth_'+s for s in [
             'consumer_key', 'token', 'signature',
             'signature_method', 'timestamp', 'nonce' ] ]
         must_have = [ 'oauth_'+s for s in [
             'consumer_key', 'token', 'signature',
             'signature_method', 'timestamp', 'nonce' ] ]
-        
+
         is_in = lambda l: all([ (p in l) for p in must_have ])
 
         auth_params = request.META.get("HTTP_AUTHORIZATION", "")
         req_params = request.REQUEST
         is_in = lambda l: all([ (p in l) for p in must_have ])
 
         auth_params = request.META.get("HTTP_AUTHORIZATION", "")
         req_params = request.REQUEST
-             
+
         return is_in(auth_params) or is_in(req_params)
         return is_in(auth_params) or is_in(req_params)
-        
+
     @staticmethod
     def validate_token(request, check_timestamp=True, check_nonce=True):
         oauth_server, oauth_request = initialize_server_request(request)
     @staticmethod
     def validate_token(request, check_timestamp=True, check_nonce=True):
         oauth_server, oauth_request = initialize_server_request(request)
index f8dc3b8..e173d01 100755 (executable)
@@ -28,7 +28,7 @@ def getinfo(func):
     - doc (the docstring : str)
     - module (the module name : str)
     - dict (the function __dict__ : str)
     - doc (the docstring : str)
     - module (the module name : str)
     - dict (the function __dict__ : str)
-    
+
     >>> def f(self, x=1, y=2, *args, **kw): pass
 
     >>> info = getinfo(f)
     >>> def f(self, x=1, y=2, *args, **kw): pass
 
     >>> info = getinfo(f)
@@ -37,7 +37,7 @@ def getinfo(func):
     'f'
     >>> info["argnames"]
     ['self', 'x', 'y', 'args', 'kw']
     'f'
     >>> info["argnames"]
     ['self', 'x', 'y', 'args', 'kw']
-    
+
     >>> info["defaults"]
     (1, 2)
 
     >>> info["defaults"]
     (1, 2)
 
@@ -75,7 +75,7 @@ def update_wrapper(wrapper, model, infodict=None):
 def new_wrapper(wrapper, model):
     """
     An improvement over functools.update_wrapper. The wrapper is a generic
 def new_wrapper(wrapper, model):
     """
     An improvement over functools.update_wrapper. The wrapper is a generic
-    callable object. It works by generating a copy of the wrapper with the 
+    callable object. It works by generating a copy of the wrapper with the
     right signature and by updating the copy, not the original.
     Moreovoer, 'model' can be a dictionary with keys 'name', 'doc', 'module',
     'dict', 'defaults'.
     right signature and by updating the copy, not the original.
     Moreovoer, 'model' can be a dictionary with keys 'name', 'doc', 'module',
     'dict', 'defaults'.
@@ -126,7 +126,7 @@ def decorator(caller):
      def caller(func, *args, **kw):
          # do something
          return func(*args, **kw)
      def caller(func, *args, **kw):
          # do something
          return func(*args, **kw)
-    
+
     Here is an example of usage:
 
     >>> @decorator
     Here is an example of usage:
 
     >>> @decorator
@@ -136,7 +136,7 @@ def decorator(caller):
 
     >>> chatty.__name__
     'chatty'
 
     >>> chatty.__name__
     'chatty'
-    
+
     >>> @chatty
     ... def f(): pass
     ...
     >>> @chatty
     ... def f(): pass
     ...
@@ -164,13 +164,13 @@ if __name__ == "__main__":
     import doctest; doctest.testmod()
 
 ##########################     LEGALESE    ###############################
     import doctest; doctest.testmod()
 
 ##########################     LEGALESE    ###############################
-      
-##   Redistributions of source code must retain the above copyright 
+
+##   Redistributions of source code must retain the above copyright
 ##   notice, this list of conditions and the following disclaimer.
 ##   Redistributions in bytecode form must reproduce the above copyright
 ##   notice, this list of conditions and the following disclaimer in
 ##   the documentation and/or other materials provided with the
 ##   notice, this list of conditions and the following disclaimer.
 ##   Redistributions in bytecode form must reproduce the above copyright
 ##   notice, this list of conditions and the following disclaimer in
 ##   the documentation and/or other materials provided with the
-##   distribution. 
+##   distribution.
 
 ##   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 ##   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
 ##   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 ##   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
index 63f89ec..fc14add 100644 (file)
@@ -15,14 +15,14 @@ def generate_doc(handler_cls):
     """
     if not type(handler_cls) is handler.HandlerMetaClass:
         raise ValueError("Give me handler, not %s" % type(handler_cls))
     """
     if not type(handler_cls) is handler.HandlerMetaClass:
         raise ValueError("Give me handler, not %s" % type(handler_cls))
-        
+
     return HandlerDocumentation(handler_cls)
     return HandlerDocumentation(handler_cls)
-    
+
 class HandlerMethod(object):
     def __init__(self, method, stale=False):
         self.method = method
         self.stale = stale
 class HandlerMethod(object):
     def __init__(self, method, stale=False):
         self.method = method
         self.stale = stale
-        
+
     def iter_args(self):
         args, _, _, defaults = inspect.getargspec(self.method)
 
     def iter_args(self):
         args, _, _, defaults = inspect.getargspec(self.method)
 
@@ -36,34 +36,34 @@ class HandlerMethod(object):
                 yield (arg, str(defaults[-didx]))
             else:
                 yield (arg, None)
                 yield (arg, str(defaults[-didx]))
             else:
                 yield (arg, None)
-        
+
     @property
     def signature(self, parse_optional=True):
         spec = ""
 
         for argn, argdef in self.iter_args():
             spec += argn
     @property
     def signature(self, parse_optional=True):
         spec = ""
 
         for argn, argdef in self.iter_args():
             spec += argn
-            
+
             if argdef:
                 spec += '=%s' % argdef
             if argdef:
                 spec += '=%s' % argdef
-            
+
             spec += ', '
             spec += ', '
-            
+
         spec = spec.rstrip(", ")
         spec = spec.rstrip(", ")
-        
+
         if parse_optional:
             return spec.replace("=None", "=<optional>")
         if parse_optional:
             return spec.replace("=None", "=<optional>")
-            
+
         return spec
         return spec
-        
+
     @property
     def doc(self):
         return inspect.getdoc(self.method)
     @property
     def doc(self):
         return inspect.getdoc(self.method)
-    
+
     @property
     def name(self):
         return self.method.__name__
     @property
     def name(self):
         return self.method.__name__
-    
+
     @property
     def http_name(self):
         if self.name == 'read':
     @property
     def http_name(self):
         if self.name == 'read':
@@ -74,21 +74,21 @@ class HandlerMethod(object):
             return 'DELETE'
         elif self.name == 'update':
             return 'PUT'
             return 'DELETE'
         elif self.name == 'update':
             return 'PUT'
-    
+
     def __repr__(self):
         return "<Method: %s>" % self.name
     def __repr__(self):
         return "<Method: %s>" % self.name
-    
+
 class HandlerDocumentation(object):
     def __init__(self, handler):
         self.handler = handler
 class HandlerDocumentation(object):
     def __init__(self, handler):
         self.handler = handler
-        
+
     def get_methods(self, include_default=False):
         for method in "read create update delete".split():
             met = getattr(self.handler, method, None)
 
             if not met:
                 continue
     def get_methods(self, include_default=False):
         for method in "read create update delete".split():
             met = getattr(self.handler, method, None)
 
             if not met:
                 continue
-                
+
             stale = inspect.getmodule(met) is handler
 
             if not self.handler.is_anonymous:
             stale = inspect.getmodule(met) is handler
 
             if not self.handler.is_anonymous:
@@ -97,64 +97,64 @@ class HandlerDocumentation(object):
             else:
                 if not stale or met.__name__ == "read" \
                     and 'GET' in self.allowed_methods:
             else:
                 if not stale or met.__name__ == "read" \
                     and 'GET' in self.allowed_methods:
-                    
+
                     yield HandlerMethod(met, stale)
                     yield HandlerMethod(met, stale)
-        
+
     def get_all_methods(self):
         return self.get_methods(include_default=True)
     def get_all_methods(self):
         return self.get_methods(include_default=True)
-        
+
     @property
     def is_anonymous(self):
         return handler.is_anonymous
 
     def get_model(self):
         return getattr(self, 'model', None)
     @property
     def is_anonymous(self):
         return handler.is_anonymous
 
     def get_model(self):
         return getattr(self, 'model', None)
-            
+
     @property
     def has_anonymous(self):
         return self.handler.anonymous
     @property
     def has_anonymous(self):
         return self.handler.anonymous
-            
+
     @property
     def anonymous(self):
         if self.has_anonymous:
             return HandlerDocumentation(self.handler.anonymous)
     @property
     def anonymous(self):
         if self.has_anonymous:
             return HandlerDocumentation(self.handler.anonymous)
-            
+
     @property
     def doc(self):
         return self.handler.__doc__
     @property
     def doc(self):
         return self.handler.__doc__
-    
+
     @property
     def name(self):
         return self.handler.__name__
     @property
     def name(self):
         return self.handler.__name__
-    
+
     @property
     def allowed_methods(self):
         return self.handler.allowed_methods
     @property
     def allowed_methods(self):
         return self.handler.allowed_methods
-    
+
     def get_resource_uri_template(self):
         """
         URI template processor.
     def get_resource_uri_template(self):
         """
         URI template processor.
-        
+
         See http://bitworking.org/projects/URI-Templates/
         """
         def _convert(template, params=[]):
             """URI template converter"""
             paths = template % dict([p, "{%s}" % p] for p in params)
             return u'%s%s' % (get_script_prefix(), paths)
         See http://bitworking.org/projects/URI-Templates/
         """
         def _convert(template, params=[]):
             """URI template converter"""
             paths = template % dict([p, "{%s}" % p] for p in params)
             return u'%s%s' % (get_script_prefix(), paths)
-        
+
         try:
             resource_uri = self.handler.resource_uri()
         try:
             resource_uri = self.handler.resource_uri()
-            
+
             components = [None, [], {}]
 
             for i, value in enumerate(resource_uri):
                 components[i] = value
             components = [None, [], {}]
 
             for i, value in enumerate(resource_uri):
                 components[i] = value
-        
+
             lookup_view, args, kwargs = components
             lookup_view = get_callable(lookup_view, True)
 
             possibilities = get_resolver(None).reverse_dict.getlist(lookup_view)
             lookup_view, args, kwargs = components
             lookup_view = get_callable(lookup_view, True)
 
             possibilities = get_resolver(None).reverse_dict.getlist(lookup_view)
-            
+
             for possibility, pattern in possibilities:
                 for result, params in possibility:
                     if args:
             for possibility, pattern in possibilities:
                 for result, params in possibility:
                     if args:
@@ -167,9 +167,9 @@ class HandlerDocumentation(object):
                         return _convert(result, params)
         except:
             return None
                         return _convert(result, params)
         except:
             return None
-        
+
     resource_uri_template = property(get_resource_uri_template)
     resource_uri_template = property(get_resource_uri_template)
-    
+
     def __repr__(self):
         return u'<Documentation for "%s">' % self.name
 
     def __repr__(self):
         return u'<Documentation for "%s">' % self.name
 
@@ -180,16 +180,16 @@ def documentation_view(request):
     """
     docs = [ ]
 
     """
     docs = [ ]
 
-    for handler in handler_tracker: 
+    for handler in handler_tracker:
         docs.append(generate_doc(handler))
 
         docs.append(generate_doc(handler))
 
-    def _compare(doc1, doc2): 
+    def _compare(doc1, doc2):
        #handlers and their anonymous counterparts are put next to each other.
        name1 = doc1.name.replace("Anonymous", "")
        name2 = doc2.name.replace("Anonymous", "")
        #handlers and their anonymous counterparts are put next to each other.
        name1 = doc1.name.replace("Anonymous", "")
        name2 = doc2.name.replace("Anonymous", "")
-       return cmp(name1, name2)    
+       return cmp(name1, name2)
+
     docs.sort(_compare)
     docs.sort(_compare)
-       
-    return render_to_response('documentation.html', 
+
+    return render_to_response('documentation.html',
         { 'docs': docs }, RequestContext(request))
         { 'docs': docs }, RequestContext(request))
index 1ff0a52..c2116d2 100644 (file)
@@ -58,7 +58,7 @@ class Emitter(object):
     as the methods on the handler. Issue58 says that's no good.
     """
     EMITTERS = { }
     as the methods on the handler. Issue58 says that's no good.
     """
     EMITTERS = { }
-    RESERVED_FIELDS = set([ 'read', 'update', 'create', 
+    RESERVED_FIELDS = set([ 'read', 'update', 'create',
                             'delete', 'model', 'anonymous',
                             'allowed_methods', 'fields', 'exclude' ])
 
                             'delete', 'model', 'anonymous',
                             'allowed_methods', 'fields', 'exclude' ])
 
@@ -68,16 +68,16 @@ class Emitter(object):
         self.handler = handler
         self.fields = fields
         self.anonymous = anonymous
         self.handler = handler
         self.fields = fields
         self.anonymous = anonymous
-        
+
         if isinstance(self.data, Exception):
             raise
         if isinstance(self.data, Exception):
             raise
-    
+
     def method_fields(self, handler, fields):
         if not handler:
             return { }
 
         ret = dict()
     def method_fields(self, handler, fields):
         if not handler:
             return { }
 
         ret = dict()
-            
+
         for field in fields - Emitter.RESERVED_FIELDS:
             t = getattr(handler, str(field), None)
 
         for field in fields - Emitter.RESERVED_FIELDS:
             t = getattr(handler, str(field), None)
 
@@ -85,13 +85,13 @@ class Emitter(object):
                 ret[field] = t
 
         return ret
                 ret[field] = t
 
         return ret
-    
+
     def construct(self):
         """
         Recursively serialize a lot of types, and
         in cases where it doesn't recognize the type,
         it will fall back to Django's `smart_unicode`.
     def construct(self):
         """
         Recursively serialize a lot of types, and
         in cases where it doesn't recognize the type,
         it will fall back to Django's `smart_unicode`.
-        
+
         Returns `dict`.
         """
         def _any(thing, fields=()):
         Returns `dict`.
         """
         def _any(thing, fields=()):
@@ -99,7 +99,7 @@ class Emitter(object):
             Dispatch, all types are routed through here.
             """
             ret = None
             Dispatch, all types are routed through here.
             """
             ret = None
-            
+
             if isinstance(thing, QuerySet):
                 ret = _qs(thing, fields=fields)
             elif isinstance(thing, (tuple, list)):
             if isinstance(thing, QuerySet):
                 ret = _qs(thing, fields=fields)
             elif isinstance(thing, (tuple, list)):
@@ -131,19 +131,19 @@ class Emitter(object):
             Foreign keys.
             """
             return _any(getattr(data, field.name))
             Foreign keys.
             """
             return _any(getattr(data, field.name))
-        
+
         def _related(data, fields=()):
             """
             Foreign keys.
             """
             return [ _model(m, fields) for m in data.iterator() ]
         def _related(data, fields=()):
             """
             Foreign keys.
             """
             return [ _model(m, fields) for m in data.iterator() ]
-        
+
         def _m2m(data, field, fields=()):
             """
             Many to many (re-route to `_model`.)
             """
             return [ _model(m, fields) for m in getattr(data, field.name).iterator() ]
         def _m2m(data, field, fields=()):
             """
             Many to many (re-route to `_model`.)
             """
             return [ _model(m, fields) for m in getattr(data, field.name).iterator() ]
-        
+
         def _model(data, fields=()):
             """
             Models. Will respect the `fields` and/or
         def _model(data, fields=()):
             """
             Models. Will respect the `fields` and/or
@@ -152,7 +152,7 @@ class Emitter(object):
             ret = { }
             handler = self.in_typemapper(type(data), self.anonymous)
             get_absolute_uri = False
             ret = { }
             handler = self.in_typemapper(type(data), self.anonymous)
             get_absolute_uri = False
-            
+
             if handler or fields:
                 v = lambda f: getattr(data, f.attname)
 
             if handler or fields:
                 v = lambda f: getattr(data, f.attname)
 
@@ -167,26 +167,26 @@ class Emitter(object):
 
                     if 'absolute_uri' in get_fields:
                         get_absolute_uri = True
 
                     if 'absolute_uri' in get_fields:
                         get_absolute_uri = True
-                
+
                     if not get_fields:
                         get_fields = set([ f.attname.replace("_id", "", 1)
                             for f in data._meta.fields ])
                     if not get_fields:
                         get_fields = set([ f.attname.replace("_id", "", 1)
                             for f in data._meta.fields ])
-                
+
                     # sets can be negated.
                     for exclude in exclude_fields:
                         if isinstance(exclude, basestring):
                             get_fields.discard(exclude)
                     # sets can be negated.
                     for exclude in exclude_fields:
                         if isinstance(exclude, basestring):
                             get_fields.discard(exclude)
-                            
+
                         elif isinstance(exclude, re._pattern_type):
                             for field in get_fields.copy():
                                 if exclude.match(field):
                                     get_fields.discard(field)
                         elif isinstance(exclude, re._pattern_type):
                             for field in get_fields.copy():
                                 if exclude.match(field):
                                     get_fields.discard(field)
-                                    
+
                 else:
                     get_fields = set(fields)
 
                 met_fields = self.method_fields(handler, get_fields)
                 else:
                     get_fields = set(fields)
 
                 met_fields = self.method_fields(handler, get_fields)
-                           
+
                 for f in data._meta.local_fields:
                     if f.serialize and not any([ p in met_fields for p in [ f.attname, f.name ]]):
                         if not f.rel:
                 for f in data._meta.local_fields:
                     if f.serialize and not any([ p in met_fields for p in [ f.attname, f.name ]]):
                         if not f.rel:
@@ -197,13 +197,13 @@ class Emitter(object):
                             if f.attname[:-3] in get_fields:
                                 ret[f.name] = _fk(data, f)
                                 get_fields.remove(f.name)
                             if f.attname[:-3] in get_fields:
                                 ret[f.name] = _fk(data, f)
                                 get_fields.remove(f.name)
-                
+
                 for mf in data._meta.many_to_many:
                     if mf.serialize and mf.attname not in met_fields:
                         if mf.attname in get_fields:
                             ret[mf.name] = _m2m(data, mf)
                             get_fields.remove(mf.name)
                 for mf in data._meta.many_to_many:
                     if mf.serialize and mf.attname not in met_fields:
                         if mf.attname in get_fields:
                             ret[mf.name] = _m2m(data, mf)
                             get_fields.remove(mf.name)
-                
+
                 # try to get the remainder of fields
                 for maybe_field in get_fields:
                     if isinstance(maybe_field, (list, tuple)):
                 # try to get the remainder of fields
                 for maybe_field in get_fields:
                     if isinstance(maybe_field, (list, tuple)):
@@ -225,7 +225,7 @@ class Emitter(object):
                         # using different names.
                         ret[maybe_field] = _any(met_fields[maybe_field](data))
 
                         # using different names.
                         ret[maybe_field] = _any(met_fields[maybe_field](data))
 
-                    else:                    
+                    else:
                         maybe = getattr(data, maybe_field, None)
                         if maybe:
                             if callable(maybe):
                         maybe = getattr(data, maybe_field, None)
                         if maybe:
                             if callable(maybe):
@@ -242,13 +242,13 @@ class Emitter(object):
             else:
                 for f in data._meta.fields:
                     ret[f.attname] = _any(getattr(data, f.attname))
             else:
                 for f in data._meta.fields:
                     ret[f.attname] = _any(getattr(data, f.attname))
-                
+
                 fields = dir(data.__class__) + ret.keys()
                 add_ons = [k for k in dir(data) if k not in fields]
                 fields = dir(data.__class__) + ret.keys()
                 add_ons = [k for k in dir(data) if k not in fields]
-                
+
                 for k in add_ons:
                     ret[k] = _any(getattr(data, k))
                 for k in add_ons:
                     ret[k] = _any(getattr(data, k))
-            
+
             # resouce uri
             if self.in_typemapper(type(data), self.anonymous):
                 handler = self.in_typemapper(type(data), self.anonymous)
             # resouce uri
             if self.in_typemapper(type(data), self.anonymous):
                 handler = self.in_typemapper(type(data), self.anonymous)
@@ -259,51 +259,51 @@ class Emitter(object):
                         ret['resource_uri'] = reverser( lambda: (url_id, fields) )()
                     except NoReverseMatch, e:
                         pass
                         ret['resource_uri'] = reverser( lambda: (url_id, fields) )()
                     except NoReverseMatch, e:
                         pass
-            
+
             if hasattr(data, 'get_api_url') and 'resource_uri' not in ret:
                 try: ret['resource_uri'] = data.get_api_url()
                 except: pass
             if hasattr(data, 'get_api_url') and 'resource_uri' not in ret:
                 try: ret['resource_uri'] = data.get_api_url()
                 except: pass
-            
+
             # absolute uri
             if hasattr(data, 'get_absolute_url') and get_absolute_uri:
                 try: ret['absolute_uri'] = data.get_absolute_url()
                 except: pass
             # absolute uri
             if hasattr(data, 'get_absolute_url') and get_absolute_uri:
                 try: ret['absolute_uri'] = data.get_absolute_url()
                 except: pass
-            
+
             return ret
             return ret
-        
+
         def _qs(data, fields=()):
             """
             Querysets.
             """
             return [ _any(v, fields) for v in data ]
         def _qs(data, fields=()):
             """
             Querysets.
             """
             return [ _any(v, fields) for v in data ]
-                
+
         def _list(data):
             """
             Lists.
             """
             return [ _any(v) for v in data ]
         def _list(data):
             """
             Lists.
             """
             return [ _any(v) for v in data ]
-            
+
         def _dict(data):
             """
             Dictionaries.
             """
             return dict([ (k, _any(v)) for k, v in data.iteritems() ])
         def _dict(data):
             """
             Dictionaries.
             """
             return dict([ (k, _any(v)) for k, v in data.iteritems() ])
-            
+
         # Kickstart the seralizin'.
         return _any(self.data, self.fields)
         # Kickstart the seralizin'.
         return _any(self.data, self.fields)
-    
+
     def in_typemapper(self, model, anonymous):
         for klass, (km, is_anon) in self.typemapper.iteritems():
             if model is km and is_anon is anonymous:
                 return klass
     def in_typemapper(self, model, anonymous):
         for klass, (km, is_anon) in self.typemapper.iteritems():
             if model is km and is_anon is anonymous:
                 return klass
-        
+
     def render(self):
         """
         This super emitter does not implement `render`,
         this is a job for the specific emitter below.
         """
         raise NotImplementedError("Please implement render.")
     def render(self):
         """
         This super emitter does not implement `render`,
         this is a job for the specific emitter below.
         """
         raise NotImplementedError("Please implement render.")
-        
+
     def stream_render(self, request, stream=True):
         """
         Tells our patched middleware not to look
     def stream_render(self, request, stream=True):
         """
         Tells our patched middleware not to look
@@ -312,7 +312,7 @@ class Emitter(object):
         more memory friendly for large datasets.
         """
         yield self.render(request)
         more memory friendly for large datasets.
         """
         yield self.render(request)
-        
+
     @classmethod
     def get(cls, format):
         """
     @classmethod
     def get(cls, format):
         """
@@ -322,19 +322,19 @@ class Emitter(object):
             return cls.EMITTERS.get(format)
 
         raise ValueError("No emitters found for type %s" % format)
             return cls.EMITTERS.get(format)
 
         raise ValueError("No emitters found for type %s" % format)
-    
+
     @classmethod
     def register(cls, name, klass, content_type='text/plain'):
         """
         Register an emitter.
     @classmethod
     def register(cls, name, klass, content_type='text/plain'):
         """
         Register an emitter.
-        
+
         Parameters::
          - `name`: The name of the emitter ('json', 'xml', 'yaml', ...)
          - `klass`: The emitter class.
          - `content_type`: The content type to serve response as.
         """
         cls.EMITTERS[name] = (klass, content_type)
         Parameters::
          - `name`: The name of the emitter ('json', 'xml', 'yaml', ...)
          - `klass`: The emitter class.
          - `content_type`: The content type to serve response as.
         """
         cls.EMITTERS[name] = (klass, content_type)
-        
+
     @classmethod
     def unregister(cls, name):
         """
     @classmethod
     def unregister(cls, name):
         """
@@ -342,7 +342,7 @@ class Emitter(object):
         want to provide output in one of the built-in emitters.
         """
         return cls.EMITTERS.pop(name, None)
         want to provide output in one of the built-in emitters.
         """
         return cls.EMITTERS.pop(name, None)
-    
+
 class XMLEmitter(Emitter):
     def _to_xml(self, xml, data):
         if isinstance(data, (list, tuple)):
 class XMLEmitter(Emitter):
     def _to_xml(self, xml, data):
         if isinstance(data, (list, tuple)):
@@ -360,16 +360,16 @@ class XMLEmitter(Emitter):
 
     def render(self, request):
         stream = StringIO.StringIO()
 
     def render(self, request):
         stream = StringIO.StringIO()
-        
+
         xml = SimplerXMLGenerator(stream, "utf-8")
         xml.startDocument()
         xml.startElement("response", {})
         xml = SimplerXMLGenerator(stream, "utf-8")
         xml.startDocument()
         xml.startElement("response", {})
-        
+
         self._to_xml(xml, self.construct())
         self._to_xml(xml, self.construct())
-        
+
         xml.endElement("response")
         xml.endDocument()
         xml.endElement("response")
         xml.endDocument()
-        
+
         return stream.getvalue()
 
 Emitter.register('xml', XMLEmitter, 'text/xml; charset=utf-8')
         return stream.getvalue()
 
 Emitter.register('xml', XMLEmitter, 'text/xml; charset=utf-8')
@@ -388,10 +388,10 @@ class JSONEmitter(Emitter):
             return '%s(%s)' % (cb, seria)
 
         return seria
             return '%s(%s)' % (cb, seria)
 
         return seria
-    
+
 Emitter.register('json', JSONEmitter, 'application/json; charset=utf-8')
 Mimer.register(simplejson.loads, ('application/json',))
 Emitter.register('json', JSONEmitter, 'application/json; charset=utf-8')
 Mimer.register(simplejson.loads, ('application/json',))
-    
+
 class YAMLEmitter(Emitter):
     """
     YAML emitter, uses `safe_dump` to omit the
 class YAMLEmitter(Emitter):
     """
     YAML emitter, uses `safe_dump` to omit the
@@ -410,7 +410,7 @@ class PickleEmitter(Emitter):
     """
     def render(self, request):
         return pickle.dumps(self.construct())
     """
     def render(self, request):
         return pickle.dumps(self.construct())
-        
+
 Emitter.register('pickle', PickleEmitter, 'application/python-pickle')
 
 """
 Emitter.register('pickle', PickleEmitter, 'application/python-pickle')
 
 """
@@ -437,5 +437,5 @@ class DjangoEmitter(Emitter):
             response = serializers.serialize(format, self.data, indent=True)
 
         return response
             response = serializers.serialize(format, self.data, indent=True)
 
         return response
-        
+
 Emitter.register('django', DjangoEmitter, 'text/xml; charset=utf-8')
 Emitter.register('django', DjangoEmitter, 'text/xml; charset=utf-8')
index 351df7c..36bd6ff 100644 (file)
@@ -5,7 +5,7 @@ from django.conf import settings
 
 class Form(forms.Form):
     pass
 
 class Form(forms.Form):
     pass
-    
+
 class ModelForm(forms.ModelForm):
     """
     Subclass of `forms.ModelForm` which makes sure
 class ModelForm(forms.ModelForm):
     """
     Subclass of `forms.ModelForm` which makes sure
index 2d28bb3..a128d7a 100644 (file)
@@ -19,17 +19,17 @@ class HandlerMetaClass(type):
             for k, (m, a) in typemapper.iteritems():
                 if model == m and anon == a:
                     return k
             for k, (m, a) in typemapper.iteritems():
                 if model == m and anon == a:
                     return k
-        
+
         if hasattr(new_cls, 'model'):
             if already_registered(new_cls.model, new_cls.is_anonymous):
                 if not getattr(settings, 'PISTON_IGNORE_DUPE_MODELS', False):
                     warnings.warn("Handler already registered for model %s, "
                         "you may experience inconsistent results." % new_cls.model.__name__)
         if hasattr(new_cls, 'model'):
             if already_registered(new_cls.model, new_cls.is_anonymous):
                 if not getattr(settings, 'PISTON_IGNORE_DUPE_MODELS', False):
                     warnings.warn("Handler already registered for model %s, "
                         "you may experience inconsistent results." % new_cls.model.__name__)
-                
+
             typemapper[new_cls] = (new_cls.model, new_cls.is_anonymous)
         else:
             typemapper[new_cls] = (None, new_cls.is_anonymous)
             typemapper[new_cls] = (new_cls.model, new_cls.is_anonymous)
         else:
             typemapper[new_cls] = (None, new_cls.is_anonymous)
-        
+
         if name not in ('BaseHandler', 'AnonymousBaseHandler'):
             handler_tracker.append(new_cls)
 
         if name not in ('BaseHandler', 'AnonymousBaseHandler'):
             handler_tracker.append(new_cls)
 
@@ -40,43 +40,43 @@ class BaseHandler(object):
     Basehandler that gives you CRUD for free.
     You are supposed to subclass this for specific
     functionality.
     Basehandler that gives you CRUD for free.
     You are supposed to subclass this for specific
     functionality.
-    
+
     All CRUD methods (`read`/`update`/`create`/`delete`)
     receive a request as the first argument from the
     resource. Use this for checking `request.user`, etc.
     """
     __metaclass__ = HandlerMetaClass
     All CRUD methods (`read`/`update`/`create`/`delete`)
     receive a request as the first argument from the
     resource. Use this for checking `request.user`, etc.
     """
     __metaclass__ = HandlerMetaClass
-    
+
     allowed_methods = ('GET', 'POST', 'PUT', 'DELETE')
     anonymous = is_anonymous = False
     exclude = ( 'id', )
     fields =  ( )
     allowed_methods = ('GET', 'POST', 'PUT', 'DELETE')
     anonymous = is_anonymous = False
     exclude = ( 'id', )
     fields =  ( )
-    
+
     def flatten_dict(self, dct):
         return dict([ (str(k), dct.get(k)) for k in dct.keys() ])
     def flatten_dict(self, dct):
         return dict([ (str(k), dct.get(k)) for k in dct.keys() ])
-    
+
     def has_model(self):
         return hasattr(self, 'model') or hasattr(self, 'queryset')
 
     def queryset(self, request):
         return self.model.objects.all()
     def has_model(self):
         return hasattr(self, 'model') or hasattr(self, 'queryset')
 
     def queryset(self, request):
         return self.model.objects.all()
-    
+
     def value_from_tuple(tu, name):
         for int_, n in tu:
             if n == name:
                 return int_
         return None
     def value_from_tuple(tu, name):
         for int_, n in tu:
             if n == name:
                 return int_
         return None
-    
+
     def exists(self, **kwargs):
         if not self.has_model():
             raise NotImplementedError
     def exists(self, **kwargs):
         if not self.has_model():
             raise NotImplementedError
-        
+
         try:
             self.model.objects.get(**kwargs)
             return True
         except self.model.DoesNotExist:
             return False
         try:
             self.model.objects.get(**kwargs)
             return True
         except self.model.DoesNotExist:
             return False
-    
+
     def read(self, request, *args, **kwargs):
         if not self.has_model():
             return rc.NOT_IMPLEMENTED
     def read(self, request, *args, **kwargs):
         if not self.has_model():
             return rc.NOT_IMPLEMENTED
@@ -92,13 +92,13 @@ class BaseHandler(object):
                 return rc.BAD_REQUEST
         else:
             return self.queryset(request).filter(*args, **kwargs)
                 return rc.BAD_REQUEST
         else:
             return self.queryset(request).filter(*args, **kwargs)
-    
+
     def create(self, request, *args, **kwargs):
         if not self.has_model():
             return rc.NOT_IMPLEMENTED
     def create(self, request, *args, **kwargs):
         if not self.has_model():
             return rc.NOT_IMPLEMENTED
-        
+
         attrs = self.flatten_dict(request.POST)
         attrs = self.flatten_dict(request.POST)
-        
+
         try:
             inst = self.queryset(request).get(**attrs)
             return rc.DUPLICATE_ENTRY
         try:
             inst = self.queryset(request).get(**attrs)
             return rc.DUPLICATE_ENTRY
@@ -108,7 +108,7 @@ class BaseHandler(object):
             return inst
         except self.model.MultipleObjectsReturned:
             return rc.DUPLICATE_ENTRY
             return inst
         except self.model.MultipleObjectsReturned:
             return rc.DUPLICATE_ENTRY
-    
+
     def update(self, request, *args, **kwargs):
         if not self.has_model():
             return rc.NOT_IMPLEMENTED
     def update(self, request, *args, **kwargs):
         if not self.has_model():
             return rc.NOT_IMPLEMENTED
@@ -132,7 +132,7 @@ class BaseHandler(object):
 
         inst.save()
         return rc.ALL_OK
 
         inst.save()
         return rc.ALL_OK
-    
+
     def delete(self, request, *args, **kwargs):
         if not self.has_model():
             raise NotImplementedError
     def delete(self, request, *args, **kwargs):
         if not self.has_model():
             raise NotImplementedError
@@ -147,7 +147,7 @@ class BaseHandler(object):
             return rc.DUPLICATE_ENTRY
         except self.model.DoesNotExist:
             return rc.NOT_HERE
             return rc.DUPLICATE_ENTRY
         except self.model.DoesNotExist:
             return rc.NOT_HERE
-        
+
 class AnonymousBaseHandler(BaseHandler):
     """
     Anonymous handler.
 class AnonymousBaseHandler(BaseHandler):
     """
     Anonymous handler.
index 5694d0e..a1c9d49 100644 (file)
@@ -48,15 +48,15 @@ class ResourceManager(models.Manager):
         if not self._default_resource:
             self._default_resource = self.get(name=name)
 
         if not self._default_resource:
             self._default_resource = self.get(name=name)
 
-        return self._default_resource        
+        return self._default_resource
 
 class TokenManager(KeyManager):
     def create_token(self, consumer, token_type, timestamp, user=None):
         """
         Shortcut to create a token with random key/secret.
         """
 
 class TokenManager(KeyManager):
     def create_token(self, consumer, token_type, timestamp, user=None):
         """
         Shortcut to create a token with random key/secret.
         """
-        token, created = self.get_or_create(consumer=consumer, 
-                                            token_type=token_type, 
+        token, created = self.get_or_create(consumer=consumer,
+                                            token_type=token_type,
                                             timestamp=timestamp,
                                             user=user)
 
                                             timestamp=timestamp,
                                             user=user)
 
@@ -65,4 +65,4 @@ class TokenManager(KeyManager):
             token.save()
 
         return token
             token.save()
 
         return token
-        
+
index 9c93af8..d205930 100644 (file)
@@ -29,7 +29,7 @@ class Nonce(models.Model):
     token_key = models.CharField(max_length=KEY_SIZE)
     consumer_key = models.CharField(max_length=KEY_SIZE)
     key = models.CharField(max_length=255)
     token_key = models.CharField(max_length=KEY_SIZE)
     consumer_key = models.CharField(max_length=KEY_SIZE)
     key = models.CharField(max_length=255)
-    
+
     def __unicode__(self):
         return u"Nonce %s for %s" % (self.key, self.consumer_key)
 
     def __unicode__(self):
         return u"Nonce %s for %s" % (self.key, self.consumer_key)
 
@@ -46,17 +46,17 @@ class Consumer(models.Model):
     user = models.ForeignKey(User, null=True, blank=True, related_name='consumers')
 
     objects = ConsumerManager()
     user = models.ForeignKey(User, null=True, blank=True, related_name='consumers')
 
     objects = ConsumerManager()
-        
+
     def __unicode__(self):
         return u"Consumer %s with key %s" % (self.name, self.key)
 
     def generate_random_codes(self):
         """
         Used to generate random key/secret pairings. Use this after you've
     def __unicode__(self):
         return u"Consumer %s with key %s" % (self.name, self.key)
 
     def generate_random_codes(self):
         """
         Used to generate random key/secret pairings. Use this after you've
-        added the other data in place of save(). 
+        added the other data in place of save().
 
         c = Consumer()
 
         c = Consumer()
-        c.name = "My consumer" 
+        c.name = "My consumer"
         c.description = "An app that makes ponies from the API."
         c.user = some_user_object
         c.generate_random_codes()
         c.description = "An app that makes ponies from the API."
         c.user = some_user_object
         c.generate_random_codes()
@@ -77,28 +77,28 @@ class Token(models.Model):
     REQUEST = 1
     ACCESS = 2
     TOKEN_TYPES = ((REQUEST, u'Request'), (ACCESS, u'Access'))
     REQUEST = 1
     ACCESS = 2
     TOKEN_TYPES = ((REQUEST, u'Request'), (ACCESS, u'Access'))
-    
+
     key = models.CharField(max_length=KEY_SIZE)
     secret = models.CharField(max_length=SECRET_SIZE)
     verifier = models.CharField(max_length=VERIFIER_SIZE)
     token_type = models.IntegerField(choices=TOKEN_TYPES)
     timestamp = models.IntegerField(default=long(time.time()))
     is_approved = models.BooleanField(default=False)
     key = models.CharField(max_length=KEY_SIZE)
     secret = models.CharField(max_length=SECRET_SIZE)
     verifier = models.CharField(max_length=VERIFIER_SIZE)
     token_type = models.IntegerField(choices=TOKEN_TYPES)
     timestamp = models.IntegerField(default=long(time.time()))
     is_approved = models.BooleanField(default=False)
-    
+
     user = models.ForeignKey(User, null=True, blank=True, related_name='tokens')
     consumer = models.ForeignKey(Consumer)
     user = models.ForeignKey(User, null=True, blank=True, related_name='tokens')
     consumer = models.ForeignKey(Consumer)
-    
+
     callback = models.CharField(max_length=255, null=True, blank=True)
     callback_confirmed = models.BooleanField(default=False)
     callback = models.CharField(max_length=255, null=True, blank=True)
     callback_confirmed = models.BooleanField(default=False)
-    
+
     objects = TokenManager()
     objects = TokenManager()
-    
+
     def __unicode__(self):
         return u"%s Token %s for %s" % (self.get_token_type_display(), self.key, self.consumer)
 
     def to_string(self, only_key=False):
         token_dict = {
     def __unicode__(self):
         return u"%s Token %s for %s" % (self.get_token_type_display(), self.key, self.consumer)
 
     def to_string(self, only_key=False):
         token_dict = {
-            'oauth_token': self.key, 
+            'oauth_token': self.key,
             'oauth_token_secret': self.secret,
             'oauth_callback_confirmed': 'true',
         }
             'oauth_token_secret': self.secret,
             'oauth_callback_confirmed': 'true',
         }
@@ -121,7 +121,7 @@ class Token(models.Model):
         self.key = key
         self.secret = secret
         self.save()
         self.key = key
         self.secret = secret
         self.save()
-        
+
     # -- OAuth 1.0a stuff
 
     def get_callback_url(self):
     # -- OAuth 1.0a stuff
 
     def get_callback_url(self):
@@ -136,13 +136,13 @@ class Token(models.Model):
             return urlparse.urlunparse((scheme, netloc, path, params,
                 query, fragment))
         return self.callback
             return urlparse.urlunparse((scheme, netloc, path, params,
                 query, fragment))
         return self.callback
-    
+
     def set_callback(self, callback):
         if callback != "oob": # out of band, says "we can't do this!"
             self.callback = callback
             self.callback_confirmed = True
             self.save()
     def set_callback(self, callback):
         if callback != "oob": # out of band, says "we can't do this!"
             self.callback = callback
             self.callback_confirmed = True
             self.save()
-        
+
 admin.site.register(Token)
 
 # Attach our signals
 admin.site.register(Token)
 
 # Attach our signals
index 3a42e20..8c430ea 100644 (file)
@@ -87,7 +87,7 @@ class OAuthConsumer(object):
 class OAuthToken(object):
     """OAuthToken is a data type that represents an End User via either an access
     or request token.
 class OAuthToken(object):
     """OAuthToken is a data type that represents an End User via either an access
     or request token.
-    
+
     key -- the token
     secret -- the token secret
 
     key -- the token
     secret -- the token secret
 
@@ -133,7 +133,7 @@ class OAuthToken(object):
         if self.callback_confirmed is not None:
             data['oauth_callback_confirmed'] = self.callback_confirmed
         return urllib.urlencode(data)
         if self.callback_confirmed is not None:
             data['oauth_callback_confirmed'] = self.callback_confirmed
         return urllib.urlencode(data)
+
     def from_string(s):
         """ Returns a token from something like:
         oauth_token_secret=xxx&oauth_token=xxx
     def from_string(s):
         """ Returns a token from something like:
         oauth_token_secret=xxx&oauth_token=xxx
@@ -157,11 +157,11 @@ class OAuthRequest(object):
     """OAuthRequest represents the request and can be serialized.
 
     OAuth parameters:
     """OAuthRequest represents the request and can be serialized.
 
     OAuth parameters:
-        - oauth_consumer_key 
+        - oauth_consumer_key
         - oauth_token
         - oauth_signature_method
         - oauth_token
         - oauth_signature_method
-        - oauth_signature 
-        - oauth_timestamp 
+        - oauth_signature
+        - oauth_timestamp
         - oauth_nonce
         - oauth_version
         - oauth_verifier
         - oauth_nonce
         - oauth_version
         - oauth_verifier
@@ -436,7 +436,7 @@ class OAuthServer(object):
     def get_callback(self, oauth_request):
         """Get the callback URL."""
         return oauth_request.get_parameter('oauth_callback')
     def get_callback(self, oauth_request):
         """Get the callback URL."""
         return oauth_request.get_parameter('oauth_callback')
+
     def build_authenticate_header(self, realm=''):
         """Optional support for the authenticate header."""
         return {'WWW-Authenticate': 'OAuth realm="%s"' % realm}
     def build_authenticate_header(self, realm=''):
         """Optional support for the authenticate header."""
         return {'WWW-Authenticate': 'OAuth realm="%s"' % realm}
@@ -482,7 +482,7 @@ class OAuthServer(object):
         if not token:
             raise OAuthError('Invalid %s token: %s' % (token_type, token_field))
         return token
         if not token:
             raise OAuthError('Invalid %s token: %s' % (token_type, token_field))
         return token
-    
+
     def _get_verifier(self, oauth_request):
         return oauth_request.get_parameter('oauth_verifier')
 
     def _get_verifier(self, oauth_request):
         return oauth_request.get_parameter('oauth_verifier')
 
@@ -601,7 +601,7 @@ class OAuthSignatureMethod_HMAC_SHA1(OAuthSignatureMethod):
 
     def get_name(self):
         return 'HMAC-SHA1'
 
     def get_name(self):
         return 'HMAC-SHA1'
-        
+
     def build_signature_base_string(self, oauth_request, consumer, token):
         sig = (
             escape(oauth_request.get_normalized_http_method()),
     def build_signature_base_string(self, oauth_request, consumer, token):
         sig = (
             escape(oauth_request.get_normalized_http_method()),
index 40f065d..ee78b0e 100644 (file)
@@ -26,22 +26,22 @@ class Resource(object):
     is an authentication handler. If not specified,
     `NoAuthentication` will be used by default.
     """
     is an authentication handler. If not specified,
     `NoAuthentication` will be used by default.
     """
-    callmap = { 'GET': 'read', 'POST': 'create', 
+    callmap = { 'GET': 'read', 'POST': 'create',
                 'PUT': 'update', 'DELETE': 'delete' }
                 'PUT': 'update', 'DELETE': 'delete' }
-    
+
     def __init__(self, handler, authentication=None):
         if not callable(handler):
             raise AttributeError, "Handler not callable."
     def __init__(self, handler, authentication=None):
         if not callable(handler):
             raise AttributeError, "Handler not callable."
-        
+
         self.handler = handler()
         self.handler = handler()
-        
+
         if not authentication:
             self.authentication = (NoAuthentication(),)
         elif isinstance(authentication, (list, tuple)):
             self.authentication = authentication
         else:
             self.authentication = (authentication,)
         if not authentication:
             self.authentication = (NoAuthentication(),)
         elif isinstance(authentication, (list, tuple)):
             self.authentication = authentication
         else:
             self.authentication = (authentication,)
-            
+
         # Erroring
         self.email_errors = getattr(settings, 'PISTON_EMAIL_ERRORS', True)
         self.display_errors = getattr(settings, 'PISTON_DISPLAY_ERRORS', True)
         # Erroring
         self.email_errors = getattr(settings, 'PISTON_EMAIL_ERRORS', True)
         self.display_errors = getattr(settings, 'PISTON_DISPLAY_ERRORS', True)
@@ -58,12 +58,12 @@ class Resource(object):
         that as well.
         """
         em = kwargs.pop('emitter_format', None)
         that as well.
         """
         em = kwargs.pop('emitter_format', None)
-        
+
         if not em:
             em = request.GET.get('format', 'json')
 
         return em
         if not em:
             em = request.GET.get('format', 'json')
 
         return em
-    
+
     @property
     def anonymous(self):
         """
     @property
     def anonymous(self):
         """
@@ -74,16 +74,16 @@ class Resource(object):
         """
         if hasattr(self.handler, 'anonymous'):
             anon = self.handler.anonymous
         """
         if hasattr(self.handler, 'anonymous'):
             anon = self.handler.anonymous
-            
+
             if callable(anon):
                 return anon
 
             for klass in typemapper.keys():
                 if anon == klass.__name__:
                     return klass
             if callable(anon):
                 return anon
 
             for klass in typemapper.keys():
                 if anon == klass.__name__:
                     return klass
-            
+
         return None
         return None
-    
+
     def authenticate(self, request, rm):
         actor, anonymous = False, True
 
     def authenticate(self, request, rm):
         actor, anonymous = False, True
 
@@ -97,9 +97,9 @@ class Resource(object):
                     actor, anonymous = authenticator.challenge, CHALLENGE
             else:
                 return self.handler, self.handler.is_anonymous
                     actor, anonymous = authenticator.challenge, CHALLENGE
             else:
                 return self.handler, self.handler.is_anonymous
-        
+
         return actor, anonymous
         return actor, anonymous
-    
+
     @vary_on_headers('Authorization')
     def __call__(self, request, *args, **kwargs):
         """
     @vary_on_headers('Authorization')
     def __call__(self, request, *args, **kwargs):
         """
@@ -119,19 +119,19 @@ class Resource(object):
             return actor()
         else:
             handler = actor
             return actor()
         else:
             handler = actor
-        
+
         # Translate nested datastructs into `request.data` here.
         if rm in ('POST', 'PUT'):
             try:
                 translate_mime(request)
             except MimerDataException:
                 return rc.BAD_REQUEST
         # Translate nested datastructs into `request.data` here.
         if rm in ('POST', 'PUT'):
             try:
                 translate_mime(request)
             except MimerDataException:
                 return rc.BAD_REQUEST
-        
+
         if not rm in handler.allowed_methods:
             return HttpResponseNotAllowed(handler.allowed_methods)
         if not rm in handler.allowed_methods:
             return HttpResponseNotAllowed(handler.allowed_methods)
-        
+
         meth = getattr(handler, self.callmap.get(rm), None)
         meth = getattr(handler, self.callmap.get(rm), None)
-        
+
         if not meth:
             raise Http404
 
         if not meth:
             raise Http404
 
@@ -139,18 +139,18 @@ class Resource(object):
         em_format = self.determine_emitter(request, *args, **kwargs)
 
         kwargs.pop('emitter_format', None)
         em_format = self.determine_emitter(request, *args, **kwargs)
 
         kwargs.pop('emitter_format', None)
-        
+
         # Clean up the request object a bit, since we might
         # very well have `oauth_`-headers in there, and we
         # don't want to pass these along to the handler.
         request = self.cleanup_request(request)
         # Clean up the request object a bit, since we might
         # very well have `oauth_`-headers in there, and we
         # don't want to pass these along to the handler.
         request = self.cleanup_request(request)
-        
+
         try:
             result = meth(request, *args, **kwargs)
         except FormValidationError, e:
             resp = rc.BAD_REQUEST
             resp.write(' '+str(e.form.errors))
         try:
             result = meth(request, *args, **kwargs)
         except FormValidationError, e:
             resp = rc.BAD_REQUEST
             resp.write(' '+str(e.form.errors))
-            
+
             return resp
         except TypeError, e:
             result = rc.BAD_REQUEST
             return resp
         except TypeError, e:
             result = rc.BAD_REQUEST
@@ -158,15 +158,15 @@ class Resource(object):
             sig = hm.signature
 
             msg = 'Method signature does not match.\n\n'
             sig = hm.signature
 
             msg = 'Method signature does not match.\n\n'
-            
+
             if sig:
                 msg += 'Signature should be: %s' % sig
             else:
                 msg += 'Resource does not expect any parameters.'
 
             if sig:
                 msg += 'Signature should be: %s' % sig
             else:
                 msg += 'Resource does not expect any parameters.'
 
-            if self.display_errors:                
+            if self.display_errors:
                 msg += '\n\nException was: %s' % str(e)
                 msg += '\n\nException was: %s' % str(e)
-                
+
             result.content = format_error(msg)
         except Http404:
             return rc.NOT_FOUND
             result.content = format_error(msg)
         except Http404:
             return rc.NOT_FOUND
@@ -177,13 +177,13 @@ class Resource(object):
             On errors (like code errors), we'd like to be able to
             give crash reports to both admins and also the calling
             user. There's two setting parameters for this:
             On errors (like code errors), we'd like to be able to
             give crash reports to both admins and also the calling
             user. There's two setting parameters for this:
-            
+
             Parameters::
              - `PISTON_EMAIL_ERRORS`: Will send a Django formatted
                error email to people in `settings.ADMINS`.
              - `PISTON_DISPLAY_ERRORS`: Will return a simple traceback
                to the caller, so he can tell you what error they got.
             Parameters::
              - `PISTON_EMAIL_ERRORS`: Will send a Django formatted
                error email to people in `settings.ADMINS`.
              - `PISTON_DISPLAY_ERRORS`: Will return a simple traceback
                to the caller, so he can tell you what error they got.
-               
+
             If `PISTON_DISPLAY_ERRORS` is not enabled, the caller will
             receive a basic "500 Internal Server Error" message.
             """
             If `PISTON_DISPLAY_ERRORS` is not enabled, the caller will
             receive a basic "500 Internal Server Error" message.
             """
@@ -237,17 +237,17 @@ class Resource(object):
 
             if True in [ k.startswith("oauth_") for k in block.keys() ]:
                 sanitized = block.copy()
 
             if True in [ k.startswith("oauth_") for k in block.keys() ]:
                 sanitized = block.copy()
-                
+
                 for k in sanitized.keys():
                     if k.startswith("oauth_"):
                         sanitized.pop(k)
                 for k in sanitized.keys():
                     if k.startswith("oauth_"):
                         sanitized.pop(k)
-                        
+
                 setattr(request, method_type, sanitized)
 
         return request
                 setattr(request, method_type, sanitized)
 
         return request
-        
-    # -- 
-    
+
+    # --
+
     def email_exception(self, reporter):
         subject = "Piston crash report"
         html = reporter.get_traceback_html()
     def email_exception(self, reporter):
         subject = "Piston crash report"
         html = reporter.get_traceback_html()
@@ -255,6 +255,6 @@ class Resource(object):
         message = EmailMessage(settings.EMAIL_SUBJECT_PREFIX+subject,
                                 html, settings.SERVER_EMAIL,
                                 [ admin[1] for admin in settings.ADMINS ])
         message = EmailMessage(settings.EMAIL_SUBJECT_PREFIX+subject,
                                 html, settings.SERVER_EMAIL,
                                 [ admin[1] for admin in settings.ADMINS ])
-        
+
         message.content_subtype = 'html'
         message.send(fail_silently=True)
         message.content_subtype = 'html'
         message.send(fail_silently=True)
index 133be13..a302d1b 100644 (file)
@@ -1,5 +1,5 @@
 # Django imports
 # Django imports
-import django.dispatch 
+import django.dispatch
 
 # Piston imports
 from utils import send_consumer_mail
 
 # Piston imports
 from utils import send_consumer_mail
index 787791a..13377d6 100644 (file)
@@ -23,7 +23,7 @@ class DataStore(oauth.OAuthDataStore):
         elif token_type == 'access':
             token_type = Token.ACCESS
         try:
         elif token_type == 'access':
             token_type = Token.ACCESS
         try:
-            self.request_token = Token.objects.get(key=token, 
+            self.request_token = Token.objects.get(key=token,
                                                    token_type=token_type)
             return self.request_token
         except Token.DoesNotExist:
                                                    token_type=token_type)
             return self.request_token
         except Token.DoesNotExist:
@@ -32,7 +32,7 @@ class DataStore(oauth.OAuthDataStore):
     def lookup_nonce(self, oauth_consumer, oauth_token, nonce):
         if oauth_token is None:
             return None
     def lookup_nonce(self, oauth_consumer, oauth_token, nonce):
         if oauth_token is None:
             return None
-        nonce, created = Nonce.objects.get_or_create(consumer_key=oauth_consumer.key, 
+        nonce, created = Nonce.objects.get_or_create(consumer_key=oauth_consumer.key,
                                                      token_key=oauth_token.key,
                                                      key=nonce)
         if created:
                                                      token_key=oauth_token.key,
                                                      key=nonce)
         if created:
@@ -45,10 +45,10 @@ class DataStore(oauth.OAuthDataStore):
             self.request_token = Token.objects.create_token(consumer=self.consumer,
                                                             token_type=Token.REQUEST,
                                                             timestamp=self.timestamp)
             self.request_token = Token.objects.create_token(consumer=self.consumer,
                                                             token_type=Token.REQUEST,
                                                             timestamp=self.timestamp)
-            
+
             if oauth_callback:
                 self.request_token.set_callback(oauth_callback)
             if oauth_callback:
                 self.request_token.set_callback(oauth_callback)
-            
+
             return self.request_token
         return None
 
             return self.request_token
         return None
 
index d7b1830..8fdfb8f 100644 (file)
        </head>
        <body>
                <h1>API Documentation</h1>
        </head>
        <body>
                <h1>API Documentation</h1>
-               
+
                {% for doc in docs %}
                {% for doc in docs %}
-               
+
                        <h3>{{ doc.name|cut:"Handler" }}:</h3>
 
                        <p>
                                {{ doc.get_doc|default:""|restructuredtext }}
                        </p>
                        <h3>{{ doc.name|cut:"Handler" }}:</h3>
 
                        <p>
                                {{ doc.get_doc|default:""|restructuredtext }}
                        </p>
-                       
+
                        <p>
                                URL: <b>{{ doc.get_resource_uri_template }}</b>
                        </p>
                        <p>
                                URL: <b>{{ doc.get_resource_uri_template }}</b>
                        </p>
-                       
+
                        <p>
                                Accepted methods: {% for meth in doc.allowed_methods %}<b>{{ meth }}</b>{% if not forloop.last %}, {% endif %}{% endfor %}
                        </p>
                        <p>
                                Accepted methods: {% for meth in doc.allowed_methods %}<b>{{ meth }}</b>{% if not forloop.last %}, {% endif %}{% endfor %}
                        </p>
-                                       
+
                        <dl>
                                {% for method in doc.get_all_methods %}
                        <dl>
                                {% for method in doc.get_all_methods %}
-                               
+
                                        <dt>
                                                method <i>{{ method.name }}</i>({{ method.signature }}){% if method.stale %} <i>- inherited</i>{% else %}:{% endif %}
                                        <dt>
                                                method <i>{{ method.name }}</i>({{ method.signature }}){% if method.stale %} <i>- inherited</i>{% else %}:{% endif %}
-                                               
-                                       </dt>                           
-                                                                               
+
+                                       </dt>
+
                                        {% if method.get_doc %}
                                                <dd>
                                                        {{ method.get_doc|default:""|restructuredtext }}
                                                <dd>
                                        {% endif %}
                                        {% if method.get_doc %}
                                                <dd>
                                                        {{ method.get_doc|default:""|restructuredtext }}
                                                <dd>
                                        {% endif %}
-                               
+
                                {% endfor %}
                        </dl>
                                {% endfor %}
                        </dl>
-               
+
                {% endfor %}
        </body>
 </html>
                {% endfor %}
        </body>
 </html>
index dae840e..59c09e3 100644 (file)
@@ -6,7 +6,7 @@
        </head>
        <body>
                <h1>Authorize Token</h1>
        </head>
        <body>
                <h1>Authorize Token</h1>
-               
+
         <form action="{% url piston.authentication.oauth_user_auth %}" method="POST">
             {{ form.as_table }}
         </form>
         <form action="{% url piston.authentication.oauth_user_auth %}" method="POST">
             {{ form.as_table }}
         </form>
index 57eda72..f19fb21 100644 (file)
@@ -32,8 +32,8 @@ class OAuthClient(client.Client):
         url = "http://testserver" + request['PATH_INFO']
 
         req = oauth.OAuthRequest.from_consumer_and_token(
         url = "http://testserver" + request['PATH_INFO']
 
         req = oauth.OAuthRequest.from_consumer_and_token(
-            self.consumer, token=self.token, 
-            http_method=request['REQUEST_METHOD'], http_url=url, 
+            self.consumer, token=self.token,
+            http_method=request['REQUEST_METHOD'], http_url=url,
             parameters=params
         )
 
             parameters=params
         )
 
@@ -49,7 +49,7 @@ class OAuthClient(client.Client):
 
         if isinstance(data, dict):
             data = urlencode(data)
 
         if isinstance(data, dict):
             data = urlencode(data)
-        
+
         return super(OAuthClient, self).post(path, data, content_type, follow, **extra)
 
 class TestCase(test.TestCase):
         return super(OAuthClient, self).post(path, data, content_type, follow, **extra)
 
 class TestCase(test.TestCase):
index 92d14ee..99f7028 100644 (file)
@@ -19,7 +19,7 @@ class ConsumerTest(TestCase):
 
     def test_create_pending(self):
         """ Ensure creating a pending Consumer sends proper emails """
 
     def test_create_pending(self):
         """ Ensure creating a pending Consumer sends proper emails """
-        # If it's pending we should have two messages in the outbox; one 
+        # If it's pending we should have two messages in the outbox; one
         # to the consumer and one to the site admins.
         if len(settings.ADMINS):
             self.assertEquals(len(mail.outbox), 2)
         # to the consumer and one to the site admins.
         if len(settings.ADMINS):
             self.assertEquals(len(mail.outbox), 2)
@@ -36,8 +36,8 @@ class ConsumerTest(TestCase):
         mail.outbox = []
 
         # Delete the consumer, which should fire off the cancel email.
         mail.outbox = []
 
         # Delete the consumer, which should fire off the cancel email.
-        self.consumer.delete() 
-        
+        self.consumer.delete()
+
         self.assertEquals(len(mail.outbox), 1)
         expected = "Your API Consumer for example.com has been canceled."
         self.assertEquals(mail.outbox[0].subject, expected)
         self.assertEquals(len(mail.outbox), 1)
         expected = "Your API Consumer for example.com has been canceled."
         self.assertEquals(mail.outbox[0].subject, expected)
index 8d0cce8..9128cbc 100644 (file)
@@ -39,7 +39,7 @@ class rc_factory(object):
 
     def __getattr__(self, attr):
         """
 
     def __getattr__(self, attr):
         """
-        Returns a fresh `HttpResponse` when getting 
+        Returns a fresh `HttpResponse` when getting
         an "attribute". This is backwards compatible
         with 0.2, which is important.
         """
         an "attribute". This is backwards compatible
         with 0.2, which is important.
         """
@@ -49,9 +49,9 @@ class rc_factory(object):
             raise AttributeError(attr)
 
         return HttpResponse(r, content_type='text/plain', status=c)
             raise AttributeError(attr)
 
         return HttpResponse(r, content_type='text/plain', status=c)
-    
+
 rc = rc_factory()
 rc = rc_factory()
-    
+
 class FormValidationError(Exception):
     def __init__(self, form):
         self.form = form
 class FormValidationError(Exception):
     def __init__(self, form):
         self.form = form
@@ -64,7 +64,7 @@ def validate(v_form, operation='POST'):
     @decorator
     def wrap(f, self, request, *a, **kwa):
         form = v_form(getattr(request, operation))
     @decorator
     def wrap(f, self, request, *a, **kwa):
         form = v_form(getattr(request, operation))
-    
+
         if form.is_valid():
             return f(self, request, *a, **kwa)
         else:
         if form.is_valid():
             return f(self, request, *a, **kwa)
         else:
@@ -75,11 +75,11 @@ def throttle(max_requests, timeout=60*60, extra=''):
     """
     Simple throttling decorator, caches
     the amount of requests made in cache.
     """
     Simple throttling decorator, caches
     the amount of requests made in cache.
-    
+
     If used on a view where users are required to
     log in, the username is used, otherwise the
     IP address of the originating request is used.
     If used on a view where users are required to
     log in, the username is used, otherwise the
     IP address of the originating request is used.
-    
+
     Parameters::
      - `max_requests`: The maximum number of requests
      - `timeout`: The timeout for the cache entry (default: 1 hour)
     Parameters::
      - `max_requests`: The maximum number of requests
      - `timeout`: The timeout for the cache entry (default: 1 hour)
@@ -90,7 +90,7 @@ def throttle(max_requests, timeout=60*60, extra=''):
             ident = request.user.username
         else:
             ident = request.META.get('REMOTE_ADDR', None)
             ident = request.user.username
         else:
             ident = request.META.get('REMOTE_ADDR', None)
-    
+
         if hasattr(request, 'throttle_extra'):
             """
             Since we want to be able to throttle on a per-
         if hasattr(request, 'throttle_extra'):
             """
             Since we want to be able to throttle on a per-
@@ -99,7 +99,7 @@ def throttle(max_requests, timeout=60*60, extra=''):
             object. If so, append the identifier name with it.
             """
             ident += ':%s' % str(request.throttle_extra)
             object. If so, append the identifier name with it.
             """
             ident += ':%s' % str(request.throttle_extra)
-        
+
         if ident:
             """
             Preferrably we'd use incr/decr here, since they're
         if ident:
             """
             Preferrably we'd use incr/decr here, since they're
@@ -108,7 +108,7 @@ def throttle(max_requests, timeout=60*60, extra=''):
             stable, you can change it here.
             """
             ident += ':%s' % extra
             stable, you can change it here.
             """
             ident += ':%s' % extra
-    
+
             now = time.time()
             count, expiration = cache.get(ident, (1, None))
 
             now = time.time()
             count, expiration = cache.get(ident, (1, None))
 
@@ -123,7 +123,7 @@ def throttle(max_requests, timeout=60*60, extra=''):
                 return t
 
             cache.set(ident, (count+1, expiration), (expiration - now))
                 return t
 
             cache.set(ident, (count+1, expiration), (expiration - now))
-    
+
         return f(self, request, *args, **kwargs)
     return wrap
 
         return f(self, request, *args, **kwargs)
     return wrap
 
@@ -133,7 +133,7 @@ def coerce_put_post(request):
     In case we send data over PUT, Django won't
     actually look at the data and load it. We need
     to twist its arm here.
     In case we send data over PUT, Django won't
     actually look at the data and load it. We need
     to twist its arm here.
-    
+
     The try/except abominiation here is due to a bug
     in mod_python. This should fix it.
     """
     The try/except abominiation here is due to a bug
     in mod_python. This should fix it.
     """
@@ -146,7 +146,7 @@ def coerce_put_post(request):
             request.META['REQUEST_METHOD'] = 'POST'
             request._load_post_and_files()
             request.META['REQUEST_METHOD'] = 'PUT'
             request.META['REQUEST_METHOD'] = 'POST'
             request._load_post_and_files()
             request.META['REQUEST_METHOD'] = 'PUT'
-            
+
         request.PUT = request.POST
 
 
         request.PUT = request.POST
 
 
@@ -158,10 +158,10 @@ class MimerDataException(Exception):
 
 class Mimer(object):
     TYPES = dict()
 
 class Mimer(object):
     TYPES = dict()
-    
+
     def __init__(self, request):
         self.request = request
     def __init__(self, request):
         self.request = request
-        
+
     def is_multipart(self):
         content_type = self.content_type()
 
     def is_multipart(self):
         content_type = self.content_type()
 
@@ -179,7 +179,7 @@ class Mimer(object):
             for mime in mimes:
                 if ctype.startswith(mime):
                     return loadee
             for mime in mimes:
                 if ctype.startswith(mime):
                     return loadee
-                    
+
     def content_type(self):
         """
         Returns the content type of the request in all cases where it is
     def content_type(self):
         """
         Returns the content type of the request in all cases where it is
@@ -188,10 +188,10 @@ class Mimer(object):
         type_formencoded = "application/x-www-form-urlencoded"
 
         ctype = self.request.META.get('CONTENT_TYPE', type_formencoded)
         type_formencoded = "application/x-www-form-urlencoded"
 
         ctype = self.request.META.get('CONTENT_TYPE', type_formencoded)
-        
+
         if type_formencoded in ctype:
             return None
         if type_formencoded in ctype:
             return None
-        
+
         return ctype
 
     def translate(self):
         return ctype
 
     def translate(self):
@@ -202,21 +202,21 @@ class Mimer(object):
         key-value (and maybe just a list), the data will be placed on
         `request.data` instead, and the handler will have to read from
         there.
         key-value (and maybe just a list), the data will be placed on
         `request.data` instead, and the handler will have to read from
         there.
-        
+
         It will also set `request.content_type` so the handler has an easy
         way to tell what's going on. `request.content_type` will always be
         None for form-encoded and/or multipart form data (what your browser sends.)
         It will also set `request.content_type` so the handler has an easy
         way to tell what's going on. `request.content_type` will always be
         None for form-encoded and/or multipart form data (what your browser sends.)
-        """    
+        """
         ctype = self.content_type()
         self.request.content_type = ctype
         ctype = self.content_type()
         self.request.content_type = ctype
-        
+
         if not self.is_multipart() and ctype:
             loadee = self.loader_for_type(ctype)
         if not self.is_multipart() and ctype:
             loadee = self.loader_for_type(ctype)
-            
+
             if loadee:
                 try:
                     self.request.data = loadee(self.request.raw_post_data)
             if loadee:
                 try:
                     self.request.data = loadee(self.request.raw_post_data)
-                        
+
                     # Reset both POST and PUT from request, as its
                     # misleading having their presence around.
                     self.request.POST = self.request.PUT = dict()
                     # Reset both POST and PUT from request, as its
                     # misleading having their presence around.
                     self.request.POST = self.request.PUT = dict()
@@ -227,18 +227,18 @@ class Mimer(object):
                 self.request.data = None
 
         return self.request
                 self.request.data = None
 
         return self.request
-                
+
     @classmethod
     def register(cls, loadee, types):
         cls.TYPES[loadee] = types
     @classmethod
     def register(cls, loadee, types):
         cls.TYPES[loadee] = types
-        
+
     @classmethod
     def unregister(cls, loadee):
         return cls.TYPES.pop(loadee)
 
 def translate_mime(request):
     request = Mimer(request).translate()
     @classmethod
     def unregister(cls, loadee):
         return cls.TYPES.pop(loadee)
 
 def translate_mime(request):
     request = Mimer(request).translate()
-    
+
 def require_mime(*mimes):
     """
     Decorator requiring a certain mimetype. There's a nifty
 def require_mime(*mimes):
     """
     Decorator requiring a certain mimetype. There's a nifty
@@ -265,7 +265,7 @@ def require_mime(*mimes):
     return wrap
 
 require_extended = require_mime('json', 'yaml', 'xml', 'pickle')
     return wrap
 
 require_extended = require_mime('json', 'yaml', 'xml', 'pickle')
-    
+
 def send_consumer_mail(consumer):
     """
     Send a consumer an email depending on what their status is.
 def send_consumer_mail(consumer):
     """
     Send a consumer an email depending on what their status is.
@@ -280,20 +280,20 @@ def send_consumer_mail(consumer):
             subject += "has been canceled."
         elif consumer.status == "rejected":
             subject += "has been rejected."
             subject += "has been canceled."
         elif consumer.status == "rejected":
             subject += "has been rejected."
-        else: 
+        else:
             subject += "is awaiting approval."
 
             subject += "is awaiting approval."
 
-    template = "piston/mails/consumer_%s.txt" % consumer.status    
-    
+    template = "piston/mails/consumer_%s.txt" % consumer.status
+
     try:
     try:
-        body = loader.render_to_string(template, 
+        body = loader.render_to_string(template,
             { 'consumer' : consumer, 'user' : consumer.user })
     except TemplateDoesNotExist:
             { 'consumer' : consumer, 'user' : consumer.user })
     except TemplateDoesNotExist:
-        """ 
+        """
         They haven't set up the templates, which means they might not want
         these emails sent.
         """
         They haven't set up the templates, which means they might not want
         these emails sent.
         """
-        return 
+        return
 
     try:
         sender = settings.PISTON_FROM_EMAIL
 
     try:
         sender = settings.PISTON_FROM_EMAIL
index f8e2801..897c221 100644 (file)
@@ -19,7 +19,7 @@ class SponsorAdmin(admin.ModelAdmin):
 class SponsorPageAdmin(admin.ModelAdmin):
     formfield_overrides = {
         fields.JSONField: {'widget': widgets.SponsorPageWidget},
 class SponsorPageAdmin(admin.ModelAdmin):
     formfield_overrides = {
         fields.JSONField: {'widget': widgets.SponsorPageWidget},
-    }   
+    }
     list_display = ('name',)
     search_fields = ('name',)
     ordering = ('name',)
     list_display = ('name',)
     search_fields = ('name',)
     ordering = ('name',)
index b3fa361..c2098ec 100644 (file)
@@ -32,7 +32,7 @@ def loads(str):
 
 class JSONFormField(forms.CharField):
     widget = forms.Textarea
 
 class JSONFormField(forms.CharField):
     widget = forms.Textarea
-    
+
     def clean(self, value):
         try:
             loads(value)
     def clean(self, value):
         try:
             loads(value)
@@ -55,7 +55,7 @@ class JSONField(models.TextField):
 
     def contribute_to_class(self, cls, name):
         super(JSONField, self).contribute_to_class(cls, name)
 
     def contribute_to_class(self, cls, name):
         super(JSONField, self).contribute_to_class(cls, name)
-        
+
         def get_value(model_instance):
             return loads(getattr(model_instance, self.attname, None))
         setattr(cls, 'get_%s_value' % self.name, get_value)
         def get_value(model_instance):
             return loads(getattr(model_instance, self.attname, None))
         setattr(cls, 'get_%s_value' % self.name, get_value)
index 5721bcc..daccec5 100644 (file)
@@ -5,9 +5,9 @@ from south.v2 import SchemaMigration
 from django.db import models
 
 class Migration(SchemaMigration):
 from django.db import models
 
 class Migration(SchemaMigration):
-    
+
     def forwards(self, orm):
     def forwards(self, orm):
-        
+
         # Adding model 'Sponsor'
         db.create_table('sponsors_sponsor', (
             ('url', self.gf('django.db.models.fields.URLField')(max_length=200, blank=True)),
         # Adding model 'Sponsor'
         db.create_table('sponsors_sponsor', (
             ('url', self.gf('django.db.models.fields.URLField')(max_length=200, blank=True)),
@@ -26,17 +26,17 @@ class Migration(SchemaMigration):
             ('name', self.gf('django.db.models.fields.CharField')(max_length=120)),
         ))
         db.send_create_signal('sponsors', ['SponsorPage'])
             ('name', self.gf('django.db.models.fields.CharField')(max_length=120)),
         ))
         db.send_create_signal('sponsors', ['SponsorPage'])
-    
-    
+
+
     def backwards(self, orm):
     def backwards(self, orm):
-        
+
         # Deleting model 'Sponsor'
         db.delete_table('sponsors_sponsor')
 
         # Deleting model 'SponsorPage'
         db.delete_table('sponsors_sponsorpage')
         # Deleting model 'Sponsor'
         db.delete_table('sponsors_sponsor')
 
         # Deleting model 'SponsorPage'
         db.delete_table('sponsors_sponsorpage')
-    
-    
+
+
     models = {
         'sponsors.sponsor': {
             'Meta': {'object_name': 'Sponsor'},
     models = {
         'sponsors.sponsor': {
             'Meta': {'object_name': 'Sponsor'},
@@ -54,5 +54,5 @@ class Migration(SchemaMigration):
             'sponsors': ('sponsors.fields.JSONField', [], {'default': '{}'})
         }
     }
             'sponsors': ('sponsors.fields.JSONField', [], {'default': '{}'})
         }
     }
-    
+
     complete_apps = ['sponsors']
     complete_apps = ['sponsors']
index 28ef76e..3c2ca02 100644 (file)
@@ -22,7 +22,7 @@ class Sponsor(models.Model):
             'options': ['pad', 'detail'],
         })
     url = models.URLField(_('url'), blank=True, verify_exists=False)
             'options': ['pad', 'detail'],
         })
     url = models.URLField(_('url'), blank=True, verify_exists=False)
-    
+
     def __unicode__(self):
         return self.name
 
     def __unicode__(self):
         return self.name
 
@@ -37,7 +37,7 @@ class SponsorPage(models.Model):
     name = models.CharField(_('name'), max_length=120)
     sponsors = JSONField(_('sponsors'), default={})
     _html = models.TextField(blank=True, editable=False)
     name = models.CharField(_('name'), max_length=120)
     sponsors = JSONField(_('sponsors'), default={})
     _html = models.TextField(blank=True, editable=False)
-    
+
     def populated_sponsors(self):
         result = []
         for column in self.get_sponsors_value():
     def populated_sponsors(self):
         result = []
         for column in self.get_sponsors_value():
@@ -50,7 +50,7 @@ class SponsorPage(models.Model):
                     pass
             result.append(result_group)
         return result
                     pass
             result.append(result_group)
         return result
-    
+
     def html(self):
         return self._html
     html = property(fget=html)
     def html(self):
         return self._html
     html = property(fget=html)
@@ -60,7 +60,7 @@ class SponsorPage(models.Model):
             'sponsors': self.populated_sponsors(),
         })
         return super(SponsorPage, self).save(*args, **kwargs)
             'sponsors': self.populated_sponsors(),
         })
         return super(SponsorPage, self).save(*args, **kwargs)
-    
+
     def __unicode__(self):
         return self.name
 
     def __unicode__(self):
         return self.name
 
index 4cb5eb6..33c794a 100644 (file)
@@ -4,12 +4,12 @@
       sponsors: []
     };
     $.extend(settings, options);
       sponsors: []
     };
     $.extend(settings, options);
-    
+
     var input = $(this).hide();
     var input = $(this).hide();
-    
+
     var container = $('<div class="sponsors"></div>').appendTo(input.parent());
     var groups = $.evalJSON(input.val());
     var container = $('<div class="sponsors"></div>').appendTo(input.parent());
     var groups = $.evalJSON(input.val());
-    
+
     var unusedDiv = $('<div class="sponsors-sponsor-group sponsors-unused-sponsor-group"></div>')
       .appendTo(container)
       .append('<p class="sponsors-sponsor-group-name sponsors-unused-sponsor-group-name">dostępni sponsorzy</p>');
     var unusedDiv = $('<div class="sponsors-sponsor-group sponsors-unused-sponsor-group"></div>')
       .appendTo(container)
       .append('<p class="sponsors-sponsor-group-name sponsors-unused-sponsor-group-name">dostępni sponsorzy</p>');
         .sortable({
           connectWith: '.sponsors-sponsor-group-list'
                });
         .sortable({
           connectWith: '.sponsors-sponsor-group-list'
                });
-    
+
     // Edit group name inline
     function editNameInline(name) {
       name.unbind('click.sponsorsFooter');
       var inlineInput = $('<input></input>').val(name.html());
       name.html('');
     // Edit group name inline
     function editNameInline(name) {
       name.unbind('click.sponsorsFooter');
       var inlineInput = $('<input></input>').val(name.html());
       name.html('');
-      
+
       function endEditing() {
         name.html(inlineInput.val());
         inlineInput.remove();
       function endEditing() {
         name.html(inlineInput.val());
         inlineInput.remove();
         input.parents('form').unbind('submit.sponsorsFooter', endEditing);
         return false;
       }
         input.parents('form').unbind('submit.sponsorsFooter', endEditing);
         return false;
       }
-      
+
       inlineInput.appendTo(name).focus().blur(endEditing);
       input.parents('form').bind('submit.sponsorsFooter', endEditing);
     }
       inlineInput.appendTo(name).focus().blur(endEditing);
       input.parents('form').bind('submit.sponsorsFooter', endEditing);
     }
-    
+
     // Remove sponsor with passed id from sponsors array and return it
     function popSponsor(id) {
       for (var i=0; i < settings.sponsors.length; i++) {
     // Remove sponsor with passed id from sponsors array and return it
     function popSponsor(id) {
       for (var i=0; i < settings.sponsors.length; i++) {
       }
       return null;
     }
       }
       return null;
     }
-    
+
     // Create sponsor group and bind events
     function createGroup(name, sponsors) {
       if (!sponsors) {
         sponsors = [];
       }
     // Create sponsor group and bind events
     function createGroup(name, sponsors) {
       if (!sponsors) {
         sponsors = [];
       }
-      
+
       var groupDiv = $('<div class="sponsors-sponsor-group"></div>');
       var groupDiv = $('<div class="sponsors-sponsor-group"></div>');
-      
+
       $('<a class="sponsors-remove-sponsor-group">X</a>')
         .click(function() {
           groupDiv.fadeOut('slow', function() {
       $('<a class="sponsors-remove-sponsor-group">X</a>')
         .click(function() {
           groupDiv.fadeOut('slow', function() {
             groupDiv.remove();
           });
         }).appendTo(groupDiv);
             groupDiv.remove();
           });
         }).appendTo(groupDiv);
-      
+
       $('<p class="sponsors-sponsor-group-name">' + name + '</p>')
         .bind('click.sponsorsFooter', function() {
           editNameInline($(this));
         }).appendTo(groupDiv);
       $('<p class="sponsors-sponsor-group-name">' + name + '</p>')
         .bind('click.sponsorsFooter', function() {
           editNameInline($(this));
         }).appendTo(groupDiv);
-      
+
       var groupList = $('<ol class="sponsors-sponsor-group-list"></ol>')
         .appendTo(groupDiv)
         .sortable({
           connectWith: '.sponsors-sponsor-group-list'
                });
       var groupList = $('<ol class="sponsors-sponsor-group-list"></ol>')
         .appendTo(groupDiv)
         .sortable({
           connectWith: '.sponsors-sponsor-group-list'
                });
-      
-      
+
+
       for (var i = 0; i < sponsors.length; i++) {
         $('<li class="sponsors-sponsor"><img src="' + sponsors[i].image + '" alt="' + sponsors[i].name + '"/></li>')
           .data('obj_id', sponsors[i].id)
       for (var i = 0; i < sponsors.length; i++) {
         $('<li class="sponsors-sponsor"><img src="' + sponsors[i].image + '" alt="' + sponsors[i].name + '"/></li>')
           .data('obj_id', sponsors[i].id)
       }
       return groupDiv;
     }
       }
       return groupDiv;
     }
-    
+
     // Create groups from data in input value
     for (var i = 0; i < groups.length; i++) {
       var group = groups[i];
       var sponsors = [];
     // Create groups from data in input value
     for (var i = 0; i < groups.length; i++) {
       var group = groups[i];
       var sponsors = [];
-      
+
       for (var j = 0; j < group.sponsors.length; j++) {
         var s = popSponsor(group.sponsors[j]);
         if (s) {
       for (var j = 0; j < group.sponsors.length; j++) {
         var s = popSponsor(group.sponsors[j]);
         if (s) {
       }
       createGroup(group.name, sponsors).appendTo(container);
     }
       }
       createGroup(group.name, sponsors).appendTo(container);
     }
-    
+
     // Serialize input value before submiting form
     input.parents('form').submit(function(event) {
       var groups = [];
     // Serialize input value before submiting form
     input.parents('form').submit(function(event) {
       var groups = [];
       });
       input.val($.toJSON(groups));
     });
       });
       input.val($.toJSON(groups));
     });
-    
+
     for (i = 0; i < settings.sponsors.length; i++) {
       $('<li class="sponsors-sponsor"><img src="' + settings.sponsors[i].image + '" alt="' + settings.sponsors[i].name + '"/></li>')
         .data('obj_id', settings.sponsors[i].id)
         .appendTo(unusedList);
     }
     for (i = 0; i < settings.sponsors.length; i++) {
       $('<li class="sponsors-sponsor"><img src="' + settings.sponsors[i].image + '" alt="' + settings.sponsors[i].name + '"/></li>')
         .data('obj_id', settings.sponsors[i].id)
         .appendTo(unusedList);
     }
-    
+
     $('<button type="button">Dodaj nową grupę</button>')
       .click(function() {
         var newGroup = createGroup('').appendTo(container);
         editNameInline($('.sponsors-sponsor-group-name', newGroup));
       }).prependTo(input.parent());
     $('<button type="button">Dodaj nową grupę</button>')
       .click(function() {
         var newGroup = createGroup('').appendTo(container);
         editNameInline($('.sponsors-sponsor-group-name', newGroup));
       }).prependTo(input.parent());
-    
+
     input.parent().append('<div style="clear: both"></div>');
   };
 })(jQuery);
     input.parent().append('<div style="clear: both"></div>');
   };
 })(jQuery);
index fb8e6b3..3670123 100644 (file)
@@ -17,5 +17,5 @@ def sponsor_page(name):
     except:
         return u''
     return mark_safe(page.html)
     except:
         return u''
     return mark_safe(page.html)
-    
+
 sponsor_page = register.simple_tag(sponsor_page)
 sponsor_page = register.simple_tag(sponsor_page)
index 70ddde6..e4b30bb 100644 (file)
@@ -28,6 +28,6 @@ class SponsorPageWidget(forms.Textarea):
         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'<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").sponsorsFooter({sponsors: [%s]}); });</script>\n' % 
+        output.append(u'$("#id_%s").sponsorsFooter({sponsors: [%s]}); });</script>\n' %
             (name, sponsors_js))
         return mark_safe(u''.join(output))
             (name, sponsors_js))
         return mark_safe(u''.join(output))
index 4c4a118..a25297a 100644 (file)
@@ -5,9 +5,9 @@ from south.v2 import SchemaMigration
 from django.db import models
 
 class Migration(SchemaMigration):
 from django.db import models
 
 class Migration(SchemaMigration):
-    
+
     def forwards(self, orm):
     def forwards(self, orm):
-        
+
         # Adding model 'Suggestion'
         db.create_table('suggest_suggestion', (
             ('description', self.gf('django.db.models.fields.TextField')(blank=True)),
         # Adding model 'Suggestion'
         db.create_table('suggest_suggestion', (
             ('description', self.gf('django.db.models.fields.TextField')(blank=True)),
@@ -18,14 +18,14 @@ class Migration(SchemaMigration):
             ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
         ))
         db.send_create_signal('suggest', ['Suggestion'])
             ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
         ))
         db.send_create_signal('suggest', ['Suggestion'])
-    
-    
+
+
     def backwards(self, orm):
     def backwards(self, orm):
-        
+
         # Deleting model 'Suggestion'
         db.delete_table('suggest_suggestion')
         # Deleting model 'Suggestion'
         db.delete_table('suggest_suggestion')
-    
-    
+
+
     models = {
         'auth.group': {
             'Meta': {'object_name': 'Group'},
     models = {
         'auth.group': {
             'Meta': {'object_name': 'Group'},
@@ -73,5 +73,5 @@ class Migration(SchemaMigration):
             'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
         }
     }
             'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'blank': 'True'})
         }
     }
-    
+
     complete_apps = ['suggest']
     complete_apps = ['suggest']
index f303872..e24afae 100644 (file)
@@ -12,12 +12,11 @@ class Suggestion(models.Model):
     created_at = models.DateTimeField(_('creation date'), auto_now=True)
     ip = models.IPAddressField(_('IP address'))
     user = models.ForeignKey(User, blank=True, null=True)
     created_at = models.DateTimeField(_('creation date'), auto_now=True)
     ip = models.IPAddressField(_('IP address'))
     user = models.ForeignKey(User, blank=True, null=True)
-    
+
     class Meta:
         ordering = ('-created_at',)
         verbose_name = _('suggestion')
         verbose_name_plural = _('suggestions')
     class Meta:
         ordering = ('-created_at',)
         verbose_name = _('suggestion')
         verbose_name_plural = _('suggestions')
-    
+
     def __unicode__(self):
         return unicode(self.created_at)
     def __unicode__(self):
         return unicode(self.created_at)
-    
\ No newline at end of file
index 44d606e..d5982cf 100644 (file)
@@ -7,7 +7,7 @@ from django.views.generic.simple import direct_to_template
 from suggest.forms import SuggestForm
 
 urlpatterns = patterns('',
 from suggest.forms import SuggestForm
 
 urlpatterns = patterns('',
-    url(r'^$', 'django.views.generic.simple.direct_to_template', 
+    url(r'^$', 'django.views.generic.simple.direct_to_template',
         {'template': 'suggest.html', 'extra_context': {'form': SuggestForm }}, name='suggest'),
     url(r'^wyslij/$', 'suggest.views.report', name='report'),
 )
         {'template': 'suggest.html', 'extra_context': {'form': SuggestForm }}, name='suggest'),
     url(r'^wyslij/$', 'suggest.views.report', name='report'),
 )
index 4ad1704..5d007f6 100644 (file)
@@ -11,7 +11,7 @@ from suggest import forms
 from suggest.models import Suggestion
 
 # FIXME - shouldn't be in catalogue
 from suggest.models import Suggestion
 
 # FIXME - shouldn't be in catalogue
-from catalogue.views import LazyEncoder 
+from catalogue.views import LazyEncoder
 
 
 #@require_POST
 
 
 #@require_POST
index 1305177..1995fd3 100644 (file)
@@ -21,7 +21,7 @@ def staging():
     env.python = '/usr/bin/python'
     env.virtualenv = '/usr/bin/virtualenv'
     env.pip = '/usr/bin/pip'
     env.python = '/usr/bin/python'
     env.virtualenv = '/usr/bin/virtualenv'
     env.pip = '/usr/bin/pip'
-    
+
 def production():
     """Use production server"""
     env.hosts = ['wolnelektury.pl:22123']
 def production():
     """Use production server"""
     env.hosts = ['wolnelektury.pl:22123']
@@ -54,8 +54,8 @@ def setup():
 
 def deploy():
     """
 
 def deploy():
     """
-    Deploy the latest version of the site to the servers, 
-    install any required third party modules, 
+    Deploy the latest version of the site to the servers,
+    install any required third party modules,
     install the virtual host and then restart the webserver
     """
     require('hosts', 'path', provided_by=[staging, production])
     install the virtual host and then restart the webserver
     """
     require('hosts', 'path', provided_by=[staging, production])
diff --git a/lib/librarian b/lib/librarian
new file mode 160000 (submodule)
index 0000000..d43d874
--- /dev/null
@@ -0,0 +1 @@
+Subproject commit d43d87400dcc19851442a42ff20af9fc0b549087
index 2ecf4cf..0e273f2 100644 (file)
@@ -7,27 +7,27 @@ import xml.sax
 
 class simpleHandler(xml.sax.ContentHandler):
     """A simple handler that provides us with indices of marked up content."""
 
 class simpleHandler(xml.sax.ContentHandler):
     """A simple handler that provides us with indices of marked up content."""
-    def __init__(self):        
+    def __init__(self):
         self.elements = [] #this will contain a list of elements and their start/end indices
         self.open_elements = [] #this holds info on open elements while we wait for their close
         self.content = ""
 
         self.elements = [] #this will contain a list of elements and their start/end indices
         self.open_elements = [] #this holds info on open elements while we wait for their close
         self.content = ""
 
-    def startElement(self,name,attrs):
-        if name=='foobar': return # we require an outer wrapper, which we promptly ignore.
+    def startElement(self, name, attrs):
+        if name == 'foobar': return # we require an outer wrapper, which we promptly ignore.
         self.open_elements.append({'name':name,
                                    'attrs':attrs.copy(),
                                    'start':len(self.content),
                                    })
 
     def endElement(self, name):
         self.open_elements.append({'name':name,
                                    'attrs':attrs.copy(),
                                    'start':len(self.content),
                                    })
 
     def endElement(self, name):
-        if name=='foobar': return # we require an outer wrapper, which we promptly ignore.
+        if name == 'foobar': return # we require an outer wrapper, which we promptly ignore.
         for i in range(len(self.open_elements)):
             e = self.open_elements[i]
         for i in range(len(self.open_elements)):
             e = self.open_elements[i]
-            if e['name']==name:
+            if e['name'] == name:
                 # append a  (start,end), name, attrs
                 self.elements.append(((e['start'], #start position
                 # append a  (start,end), name, attrs
                 self.elements.append(((e['start'], #start position
-                                       len(self.content)),# current (end) position
-                                      e['name'],e['attrs'])
+                                       len(self.content)), # current (end) position
+                                      e['name'], e['attrs'])
                                      )
                 del self.open_elements[i]
                 return
                                      )
                 del self.open_elements[i]
                 return
@@ -39,14 +39,14 @@ class simpleHandler(xml.sax.ContentHandler):
 class MarkupString(unicode):
     """A simple class for dealing with marked up strings. When we are sliced, we return
     valid marked up strings, preserving markup."""
 class MarkupString(unicode):
     """A simple class for dealing with marked up strings. When we are sliced, we return
     valid marked up strings, preserving markup."""
-    def __init__(self, string):        
-        unicode.__init__(self, string)
+    def __init__(self, string):
+        unicode.__init__(self)
         self.handler = simpleHandler()
         xml.sax.parseString((u"<foobar>%s</foobar>" % string).encode('utf-8'), self.handler)
         self.raw = self.handler.content
 
     def __getitem__(self, n):
         self.handler = simpleHandler()
         xml.sax.parseString((u"<foobar>%s</foobar>" % string).encode('utf-8'), self.handler)
         self.raw = self.handler.content
 
     def __getitem__(self, n):
-        return self.__getslice__(n,n+1)
+        return self.__getslice__(n, n + 1)
 
     def __getslice__(self, s, e):
         # only include relevant elements
 
     def __getslice__(self, s, e):
         # only include relevant elements
@@ -64,21 +64,21 @@ class MarkupString(unicode):
             name = el[1]
             attrs = el[2]
             # write our start tag <stag att="val"...>
             name = el[1]
             attrs = el[2]
             # write our start tag <stag att="val"...>
-            stag = "<%s"%name
-            for k,v in attrs.items(): stag += " %s=%s"%(k,xml.sax.saxutils.quoteattr(v))
+            stag = "<%s" % name
+            for k, v in attrs.items(): stag += " %s=%s" % (k, xml.sax.saxutils.quoteattr(v))
             stag += ">"
             stag += ">"
-            etag = "</%s>"%name # simple end tag
+            etag = "</%s>" % name # simple end tag
             spos = pos[0]
             epos = pos[1]
             spos = pos[0]
             epos = pos[1]
-            if spos < s: spos=s
-            if epos > e: epos=e
+            if spos < s: spos = s
+            if epos > e: epos = e
             if epos != spos: # we don't care about tags that don't markup any text
             if epos != spos: # we don't care about tags that don't markup any text
-                if not starts.has_key(spos): starts[spos]=[]
+                if not starts.has_key(spos): starts[spos] = []
                 starts[spos].append(stag)
                 starts[spos].append(stag)
-                if not ends.has_key(epos): ends[epos]=[]
+                if not ends.has_key(epos): ends[epos] = []
                 ends[epos].append(etag)
         outbuf = "" # our actual output string
                 ends[epos].append(etag)
         outbuf = "" # our actual output string
-        for pos in range(s,e): # we move through positions
+        for pos in range(s, e): # we move through positions
             char = self.raw[pos]
             if ends.has_key(pos):  # if there are endtags to insert...
                 for et in ends[pos]: outbuf += et
             char = self.raw[pos]
             if ends.has_key(pos):  # if there are endtags to insert...
                 for et in ends[pos]: outbuf += et
@@ -89,7 +89,7 @@ class MarkupString(unicode):
                 for st in mystarts: outbuf += st
             outbuf += char
         if ends.has_key(e):
                 for st in mystarts: outbuf += st
             outbuf += char
         if ends.has_key(e):
-            for et in ends[e]: outbuf+= et
+            for et in ends[e]: outbuf += et
         return MarkupString(outbuf)
 
     def __len__(self):
         return MarkupString(outbuf)
 
     def __len__(self):
index e7fa221..fe5c9e3 100644 (file)
@@ -5,7 +5,7 @@ from types import UnicodeType
 from django.template.defaultfilters import slugify
 
 # default unicode character mapping ( you may not see some chars, leave as is )
 from django.template.defaultfilters import slugify
 
 # default unicode character mapping ( you may not see some chars, leave as is )
-char_map = {u'À': 'A', u'Á': 'A', u'Â': 'A', u'Ã': 'A', u'Ä': 'Ae', u'Å': 'A', u'Æ': 'A', u'Ā': 'A', u'Ą': 'A', u'Ă': 'A', u'Ç': 'C', u'Ć': 'C', u'Č': 'C', u'Ĉ': 'C', u'Ċ': 'C', u'Ď': 'D', u'Đ': 'D', u'È': 'E', u'É': 'E', u'Ê': 'E', u'Ë': 'E', u'Ē': 'E', u'Ę': 'E', u'Ě': 'E', u'Ĕ': 'E', u'Ė': 'E', u'Ĝ': 'G', u'Ğ': 'G', u'Ġ': 'G', u'Ģ': 'G', u'Ĥ': 'H', u'Ħ': 'H', u'Ì': 'I', u'Í': 'I', u'Î': 'I', u'Ï': 'I', u'Ī': 'I', u'Ĩ': 'I', u'Ĭ': 'I', u'Į': 'I', u'İ': 'I', u'IJ': 'IJ', u'Ĵ': 'J', u'Ķ': 'K', u'Ľ': 'K', u'Ĺ': 'K', u'Ļ': 'K', u'Ŀ': 'K', u'Ł': 'L', u'Ñ': 'N', u'Ń': 'N', u'Ň': 'N', u'Ņ': 'N', u'Ŋ': 'N', u'Ò': 'O', u'Ó': 'O', u'Ô': 'O', u'Õ': 'O', u'Ö': 'Oe', u'Ø': 'O', u'Ō': 'O', u'Ő': 'O', u'Ŏ': 'O', u'Œ': 'OE', u'Ŕ': 'R', u'Ř': 'R', u'Ŗ': 'R', u'Ś': 'S', u'Ş': 'S', u'Ŝ': 'S', u'Ș': 'S', u'Š': 'S', u'Ť': 'T', u'Ţ': 'T', u'Ŧ': 'T', u'Ț': 'T', u'Ù': 'U', u'Ú': 'U', u'Û': 'U', u'Ü': 'Ue', u'Ū': 'U', u'Ů': 'U', u'Ű': 'U', u'Ŭ': 'U', u'Ũ': 'U', u'Ų': 'U', u'Ŵ': 'W', u'Ŷ': 'Y', u'Ÿ': 'Y', u'Ý': 'Y', u'Ź': 'Z', u'Ż': 'Z', u'Ž': 'Z', u'à': 'a', u'á': 'a', u'â': 'a', u'ã': 'a', u'ä': 'ae', u'ā': 'a', u'ą': 'a', u'ă': 'a', u'å': 'a', u'æ': 'ae', u'ç': 'c', u'ć': 'c', u'č': 'c', u'ĉ': 'c', u'ċ': 'c', u'ď': 'd', u'đ': 'd', u'è': 'e', u'é': 'e', u'ê': 'e', u'ë': 'e', u'ē': 'e', u'ę': 'e', u'ě': 'e', u'ĕ': 'e', u'ė': 'e', u'ƒ': 'f', u'ĝ': 'g', u'ğ': 'g', u'ġ': 'g', u'ģ': 'g', u'ĥ': 'h', u'ħ': 'h', u'ì': 'i', u'í': 'i', u'î': 'i', u'ï': 'i', u'ī': 'i', u'ĩ': 'i', u'ĭ': 'i', u'į': 'i', u'ı': 'i', u'ij': 'ij', u'ĵ': 'j', u'ķ': 'k', u'ĸ': 'k', u'ł': 'l', u'ľ': 'l', u'ĺ': 'l', u'ļ': 'l', u'ŀ': 'l', u'ñ': 'n', u'ń': 'n', u'ň': 'n', u'ņ': 'n', u'ʼn': 'n', u'ŋ': 'n', u'ò': 'o', u'ó': 'o', u'ô': 'o', u'õ': 'o', u'ö': 'oe', u'ø': 'o', u'ō': 'o', u'ő': 'o', u'ŏ': 'o', u'œ': 'oe', u'ŕ': 'r', u'ř': 'r', u'ŗ': 'r', u'ś': 's', u'š': 's', u'ť': 't', u'ù': 'u', u'ú': 'u', u'û': 'u', u'ü': 'ue', u'ū': 'u', u'ů': 'u', u'ű': 'u', u'ŭ': 'u', u'ũ': 'u', u'ų': 'u', u'ŵ': 'w', u'ÿ': 'y', u'ý': 'y', u'ŷ': 'y', u'ż': 'z', u'ź': 'z', u'ž': 'z', u'ß': 'ss', u'ſ': 'ss', u'Α': 'A', u'Ά': 'A', u'Ἀ': 'A', u'Ἁ': 'A', u'Ἂ': 'A', u'Ἃ': 'A', u'Ἄ': 'A', u'Ἅ': 'A', u'Ἆ': 'A', u'Ἇ': 'A', u'ᾈ': 'A', u'ᾉ': 'A', u'ᾊ': 'A', u'ᾋ': 'A', u'ᾌ': 'A', u'ᾍ': 'A', u'ᾎ': 'A', u'ᾏ': 'A', u'Ᾰ': 'A', u'Ᾱ': 'A', u'Ὰ': 'A', u'Ά': 'A', u'ᾼ': 'A', u'Β': 'B', u'Γ': 'G', u'Δ': 'D', u'Ε': 'E', u'Έ': 'E', u'Ἐ': 'E', u'Ἑ': 'E', u'Ἒ': 'E', u'Ἓ': 'E', u'Ἔ': 'E', u'Ἕ': 'E', u'Έ': 'E', u'Ὲ': 'E', u'Ζ': 'Z', u'Η': 'I', u'Ή': 'I', u'Ἠ': 'I', u'Ἡ': 'I', u'Ἢ': 'I', u'Ἣ': 'I', u'Ἤ': 'I', u'Ἥ': 'I', u'Ἦ': 'I', u'Ἧ': 'I', u'ᾘ': 'I', u'ᾙ': 'I', u'ᾚ': 'I', u'ᾛ': 'I', u'ᾜ': 'I', u'ᾝ': 'I', u'ᾞ': 'I', u'ᾟ': 'I', u'Ὴ': 'I', u'Ή': 'I', u'ῌ': 'I', u'Θ': 'TH', u'Ι': 'I', u'Ί': 'I', u'Ϊ': 'I', u'Ἰ': 'I', u'Ἱ': 'I', u'Ἲ': 'I', u'Ἳ': 'I', u'Ἴ': 'I', u'Ἵ': 'I', u'Ἶ': 'I', u'Ἷ': 'I', u'Ῐ': 'I', u'Ῑ': 'I', u'Ὶ': 'I', u'Ί': 'I', u'Κ': 'K', u'Λ': 'L', u'Μ': 'M', u'Ν': 'N', u'Ξ': 'KS', u'Ο': 'O', u'Ό': 'O', u'Ὀ': 'O', u'Ὁ': 'O', u'Ὂ': 'O', u'Ὃ': 'O', u'Ὄ': 'O', u'Ὅ': 'O', u'Ὸ': 'O', u'Ό': 'O', u'Π': 'P', u'Ρ': 'R', u'Ῥ': 'R', u'Σ': 'S', u'Τ': 'T', u'Υ': 'Y', u'Ύ': 'Y', u'Ϋ': 'Y', u'Ὑ': 'Y', u'Ὓ': 'Y', u'Ὕ': 'Y', u'Ὗ': 'Y', u'Ῠ': 'Y', u'Ῡ': 'Y', u'Ὺ': 'Y', u'Ύ': 'Y', u'Φ': 'F', u'Χ': 'X', u'Ψ': 'PS', u'Ω': 'O', u'Ώ': 'O', u'Ὠ': 'O', u'Ὡ': 'O', u'Ὢ': 'O', u'Ὣ': 'O', u'Ὤ': 'O', u'Ὥ': 'O', u'Ὦ': 'O', u'Ὧ': 'O', u'ᾨ': 'O', u'ᾩ': 'O', u'ᾪ': 'O', u'ᾫ': 'O', u'ᾬ': 'O', u'ᾭ': 'O', u'ᾮ': 'O', u'ᾯ': 'O', u'Ὼ': 'O', u'Ώ': 'O', u'ῼ': 'O', u'α': 'a', u'ά': 'a', u'ἀ': 'a', u'ἁ': 'a', u'ἂ': 'a', u'ἃ': 'a', u'ἄ': 'a', u'ἅ': 'a', u'ἆ': 'a', u'ἇ': 'a', u'ᾀ': 'a', u'ᾁ': 'a', u'ᾂ': 'a', u'ᾃ': 'a', u'ᾄ': 'a', u'ᾅ': 'a', u'ᾆ': 'a', u'ᾇ': 'a', u'ὰ': 'a', u'ά': 'a', u'ᾰ': 'a', u'ᾱ': 'a', u'ᾲ': 'a', u'ᾳ': 'a', u'ᾴ': 'a', u'ᾶ': 'a', u'ᾷ': 'a', u'β': 'b', u'γ': 'g', u'δ': 'd', u'ε': 'e', u'έ': 'e', u'ἐ': 'e', u'ἑ': 'e', u'ἒ': 'e', u'ἓ': 'e', u'ἔ': 'e', u'ἕ': 'e', u'ὲ': 'e', u'έ': 'e', u'ζ': 'z', u'η': 'i', u'ή': 'i', u'ἠ': 'i', u'ἡ': 'i', u'ἢ': 'i', u'ἣ': 'i', u'ἤ': 'i', u'ἥ': 'i', u'ἦ': 'i', u'ἧ': 'i', u'ᾐ': 'i', u'ᾑ': 'i', u'ᾒ': 'i', u'ᾓ': 'i', u'ᾔ': 'i', u'ᾕ': 'i', u'ᾖ': 'i', u'ᾗ': 'i', u'ὴ': 'i', u'ή': 'i', u'ῂ': 'i', u'ῃ': 'i', u'ῄ': 'i', u'ῆ': 'i', u'ῇ': 'i', u'θ': 'th', u'ι': 'i', u'ί': 'i', u'ϊ': 'i', u'ΐ': 'i', u'ἰ': 'i', u'ἱ': 'i', u'ἲ': 'i', u'ἳ': 'i', u'ἴ': 'i', u'ἵ': 'i', u'ἶ': 'i', u'ἷ': 'i', u'ὶ': 'i', u'ί': 'i', u'ῐ': 'i', u'ῑ': 'i', u'ῒ': 'i', u'ΐ': 'i', u'ῖ': 'i', u'ῗ': 'i', u'κ': 'k', u'λ': 'l', u'μ': 'm', u'ν': 'n', u'ξ': 'ks', u'ο': 'o', u'ό': 'o', u'ὀ': 'o', u'ὁ': 'o', u'ὂ': 'o', u'ὃ': 'o', u'ὄ': 'o', u'ὅ': 'o', u'ὸ': 'o', u'ό': 'o', u'π': 'p', u'ρ': 'r', u'ῤ': 'r', u'ῥ': 'r', u'σ': 's', u'ς': 's', u'τ': 't', u'υ': 'y', u'ύ': 'y', u'ϋ': 'y', u'ΰ': 'y', u'ὐ': 'y', u'ὑ': 'y', u'ὒ': 'y', u'ὓ': 'y', u'ὔ': 'y', u'ὕ': 'y', u'ὖ': 'y', u'ὗ': 'y', u'ὺ': 'y', u'ύ': 'y', u'ῠ': 'y', u'ῡ': 'y', u'ῢ': 'y', u'ΰ': 'y', u'ῦ': 'y', u'ῧ': 'y', u'φ': 'f', u'χ': 'x', u'ψ': 'ps', u'ω': 'o', u'ώ': 'o', u'ὠ': 'o', u'ὡ': 'o', u'ὢ': 'o', u'ὣ': 'o', u'ὤ': 'o', u'ὥ': 'o', u'ὦ': 'o', u'ὧ': 'o', u'ᾠ': 'o', u'ᾡ': 'o', u'ᾢ': 'o', u'ᾣ': 'o', u'ᾤ': 'o', u'ᾥ': 'o', u'ᾦ': 'o', u'ᾧ': 'o', u'ὼ': 'o', u'ώ': 'o', u'ῲ': 'o', u'ῳ': 'o', u'ῴ': 'o', u'ῶ': 'o', u'ῷ': 'o', u'¨': '', u'΅': '', u'᾿': '', u'῾': '', u'῍': '', u'῝': '', u'῎': '', u'῞': '', u'῏': '', u'῟': '', u'῀': '', u'῁': '', u'΄': '', u'΅': '', u'`': '', u'῭': '', u'ͺ': '', u'᾽': '', u'А': 'A', u'Б': 'B', u'В': 'V', u'Г': 'G', u'Д': 'D', u'Е': 'E', u'Ё': 'E', u'Ж': 'ZH', u'З': 'Z', u'И': 'I', u'Й': 'I', u'К': 'K', u'Л': 'L', u'М': 'M', u'Н': 'N', u'О': 'O', u'П': 'P', u'Р': 'R', u'С': 'S', u'Т': 'T', u'У': 'U', u'Ф': 'F', u'Х': 'KH', u'Ц': 'TS', u'Ч': 'CH', u'Ш': 'SH', u'Щ': 'SHCH', u'Ы': 'Y', u'Э': 'E', u'Ю': 'YU', u'Я': 'YA', u'а': 'A', u'б': 'B', u'в': 'V', u'г': 'G', u'д': 'D', u'е': 'E', u'ё': 'E', u'ж': 'ZH', u'з': 'Z', u'и': 'I', u'й': 'I', u'к': 'K', u'л': 'L', u'м': 'M', u'н': 'N', u'о': 'O', u'п': 'P', u'р': 'R', u'с': 'S', u'т': 'T', u'у': 'U', u'ф': 'F', u'х': 'KH', u'ц': 'TS', u'ч': 'CH', u'ш': 'SH', u'щ': 'SHCH', u'ы': 'Y', u'э': 'E', u'ю': 'YU', u'я': 'YA', u'Ъ': '', u'ъ': '', u'Ь': '', u'ь': '', u'ð': 'd', u'Ð': 'D', u'þ': 'th', u'Þ': 'TH', 
+char_map = {u'À': 'A', u'Á': 'A', u'Â': 'A', u'Ã': 'A', u'Ä': 'Ae', u'Å': 'A', u'Æ': 'A', u'Ā': 'A', u'Ą': 'A', u'Ă': 'A', u'Ç': 'C', u'Ć': 'C', u'Č': 'C', u'Ĉ': 'C', u'Ċ': 'C', u'Ď': 'D', u'Đ': 'D', u'È': 'E', u'É': 'E', u'Ê': 'E', u'Ë': 'E', u'Ē': 'E', u'Ę': 'E', u'Ě': 'E', u'Ĕ': 'E', u'Ė': 'E', u'Ĝ': 'G', u'Ğ': 'G', u'Ġ': 'G', u'Ģ': 'G', u'Ĥ': 'H', u'Ħ': 'H', u'Ì': 'I', u'Í': 'I', u'Î': 'I', u'Ï': 'I', u'Ī': 'I', u'Ĩ': 'I', u'Ĭ': 'I', u'Į': 'I', u'İ': 'I', u'IJ': 'IJ', u'Ĵ': 'J', u'Ķ': 'K', u'Ľ': 'K', u'Ĺ': 'K', u'Ļ': 'K', u'Ŀ': 'K', u'Ł': 'L', u'Ñ': 'N', u'Ń': 'N', u'Ň': 'N', u'Ņ': 'N', u'Ŋ': 'N', u'Ò': 'O', u'Ó': 'O', u'Ô': 'O', u'Õ': 'O', u'Ö': 'Oe', u'Ø': 'O', u'Ō': 'O', u'Ő': 'O', u'Ŏ': 'O', u'Œ': 'OE', u'Ŕ': 'R', u'Ř': 'R', u'Ŗ': 'R', u'Ś': 'S', u'Ş': 'S', u'Ŝ': 'S', u'Ș': 'S', u'Š': 'S', u'Ť': 'T', u'Ţ': 'T', u'Ŧ': 'T', u'Ț': 'T', u'Ù': 'U', u'Ú': 'U', u'Û': 'U', u'Ü': 'Ue', u'Ū': 'U', u'Ů': 'U', u'Ű': 'U', u'Ŭ': 'U', u'Ũ': 'U', u'Ų': 'U', u'Ŵ': 'W', u'Ŷ': 'Y', u'Ÿ': 'Y', u'Ý': 'Y', u'Ź': 'Z', u'Ż': 'Z', u'Ž': 'Z', u'à': 'a', u'á': 'a', u'â': 'a', u'ã': 'a', u'ä': 'ae', u'ā': 'a', u'ą': 'a', u'ă': 'a', u'å': 'a', u'æ': 'ae', u'ç': 'c', u'ć': 'c', u'č': 'c', u'ĉ': 'c', u'ċ': 'c', u'ď': 'd', u'đ': 'd', u'è': 'e', u'é': 'e', u'ê': 'e', u'ë': 'e', u'ē': 'e', u'ę': 'e', u'ě': 'e', u'ĕ': 'e', u'ė': 'e', u'ƒ': 'f', u'ĝ': 'g', u'ğ': 'g', u'ġ': 'g', u'ģ': 'g', u'ĥ': 'h', u'ħ': 'h', u'ì': 'i', u'í': 'i', u'î': 'i', u'ï': 'i', u'ī': 'i', u'ĩ': 'i', u'ĭ': 'i', u'į': 'i', u'ı': 'i', u'ij': 'ij', u'ĵ': 'j', u'ķ': 'k', u'ĸ': 'k', u'ł': 'l', u'ľ': 'l', u'ĺ': 'l', u'ļ': 'l', u'ŀ': 'l', u'ñ': 'n', u'ń': 'n', u'ň': 'n', u'ņ': 'n', u'ʼn': 'n', u'ŋ': 'n', u'ò': 'o', u'ó': 'o', u'ô': 'o', u'õ': 'o', u'ö': 'oe', u'ø': 'o', u'ō': 'o', u'ő': 'o', u'ŏ': 'o', u'œ': 'oe', u'ŕ': 'r', u'ř': 'r', u'ŗ': 'r', u'ś': 's', u'š': 's', u'ť': 't', u'ù': 'u', u'ú': 'u', u'û': 'u', u'ü': 'ue', u'ū': 'u', u'ů': 'u', u'ű': 'u', u'ŭ': 'u', u'ũ': 'u', u'ų': 'u', u'ŵ': 'w', u'ÿ': 'y', u'ý': 'y', u'ŷ': 'y', u'ż': 'z', u'ź': 'z', u'ž': 'z', u'ß': 'ss', u'ſ': 'ss', u'Α': 'A', u'Ά': 'A', u'Ἀ': 'A', u'Ἁ': 'A', u'Ἂ': 'A', u'Ἃ': 'A', u'Ἄ': 'A', u'Ἅ': 'A', u'Ἆ': 'A', u'Ἇ': 'A', u'ᾈ': 'A', u'ᾉ': 'A', u'ᾊ': 'A', u'ᾋ': 'A', u'ᾌ': 'A', u'ᾍ': 'A', u'ᾎ': 'A', u'ᾏ': 'A', u'Ᾰ': 'A', u'Ᾱ': 'A', u'Ὰ': 'A', u'Ά': 'A', u'ᾼ': 'A', u'Β': 'B', u'Γ': 'G', u'Δ': 'D', u'Ε': 'E', u'Έ': 'E', u'Ἐ': 'E', u'Ἑ': 'E', u'Ἒ': 'E', u'Ἓ': 'E', u'Ἔ': 'E', u'Ἕ': 'E', u'Έ': 'E', u'Ὲ': 'E', u'Ζ': 'Z', u'Η': 'I', u'Ή': 'I', u'Ἠ': 'I', u'Ἡ': 'I', u'Ἢ': 'I', u'Ἣ': 'I', u'Ἤ': 'I', u'Ἥ': 'I', u'Ἦ': 'I', u'Ἧ': 'I', u'ᾘ': 'I', u'ᾙ': 'I', u'ᾚ': 'I', u'ᾛ': 'I', u'ᾜ': 'I', u'ᾝ': 'I', u'ᾞ': 'I', u'ᾟ': 'I', u'Ὴ': 'I', u'Ή': 'I', u'ῌ': 'I', u'Θ': 'TH', u'Ι': 'I', u'Ί': 'I', u'Ϊ': 'I', u'Ἰ': 'I', u'Ἱ': 'I', u'Ἲ': 'I', u'Ἳ': 'I', u'Ἴ': 'I', u'Ἵ': 'I', u'Ἶ': 'I', u'Ἷ': 'I', u'Ῐ': 'I', u'Ῑ': 'I', u'Ὶ': 'I', u'Ί': 'I', u'Κ': 'K', u'Λ': 'L', u'Μ': 'M', u'Ν': 'N', u'Ξ': 'KS', u'Ο': 'O', u'Ό': 'O', u'Ὀ': 'O', u'Ὁ': 'O', u'Ὂ': 'O', u'Ὃ': 'O', u'Ὄ': 'O', u'Ὅ': 'O', u'Ὸ': 'O', u'Ό': 'O', u'Π': 'P', u'Ρ': 'R', u'Ῥ': 'R', u'Σ': 'S', u'Τ': 'T', u'Υ': 'Y', u'Ύ': 'Y', u'Ϋ': 'Y', u'Ὑ': 'Y', u'Ὓ': 'Y', u'Ὕ': 'Y', u'Ὗ': 'Y', u'Ῠ': 'Y', u'Ῡ': 'Y', u'Ὺ': 'Y', u'Ύ': 'Y', u'Φ': 'F', u'Χ': 'X', u'Ψ': 'PS', u'Ω': 'O', u'Ώ': 'O', u'Ὠ': 'O', u'Ὡ': 'O', u'Ὢ': 'O', u'Ὣ': 'O', u'Ὤ': 'O', u'Ὥ': 'O', u'Ὦ': 'O', u'Ὧ': 'O', u'ᾨ': 'O', u'ᾩ': 'O', u'ᾪ': 'O', u'ᾫ': 'O', u'ᾬ': 'O', u'ᾭ': 'O', u'ᾮ': 'O', u'ᾯ': 'O', u'Ὼ': 'O', u'Ώ': 'O', u'ῼ': 'O', u'α': 'a', u'ά': 'a', u'ἀ': 'a', u'ἁ': 'a', u'ἂ': 'a', u'ἃ': 'a', u'ἄ': 'a', u'ἅ': 'a', u'ἆ': 'a', u'ἇ': 'a', u'ᾀ': 'a', u'ᾁ': 'a', u'ᾂ': 'a', u'ᾃ': 'a', u'ᾄ': 'a', u'ᾅ': 'a', u'ᾆ': 'a', u'ᾇ': 'a', u'ὰ': 'a', u'ά': 'a', u'ᾰ': 'a', u'ᾱ': 'a', u'ᾲ': 'a', u'ᾳ': 'a', u'ᾴ': 'a', u'ᾶ': 'a', u'ᾷ': 'a', u'β': 'b', u'γ': 'g', u'δ': 'd', u'ε': 'e', u'έ': 'e', u'ἐ': 'e', u'ἑ': 'e', u'ἒ': 'e', u'ἓ': 'e', u'ἔ': 'e', u'ἕ': 'e', u'ὲ': 'e', u'έ': 'e', u'ζ': 'z', u'η': 'i', u'ή': 'i', u'ἠ': 'i', u'ἡ': 'i', u'ἢ': 'i', u'ἣ': 'i', u'ἤ': 'i', u'ἥ': 'i', u'ἦ': 'i', u'ἧ': 'i', u'ᾐ': 'i', u'ᾑ': 'i', u'ᾒ': 'i', u'ᾓ': 'i', u'ᾔ': 'i', u'ᾕ': 'i', u'ᾖ': 'i', u'ᾗ': 'i', u'ὴ': 'i', u'ή': 'i', u'ῂ': 'i', u'ῃ': 'i', u'ῄ': 'i', u'ῆ': 'i', u'ῇ': 'i', u'θ': 'th', u'ι': 'i', u'ί': 'i', u'ϊ': 'i', u'ΐ': 'i', u'ἰ': 'i', u'ἱ': 'i', u'ἲ': 'i', u'ἳ': 'i', u'ἴ': 'i', u'ἵ': 'i', u'ἶ': 'i', u'ἷ': 'i', u'ὶ': 'i', u'ί': 'i', u'ῐ': 'i', u'ῑ': 'i', u'ῒ': 'i', u'ΐ': 'i', u'ῖ': 'i', u'ῗ': 'i', u'κ': 'k', u'λ': 'l', u'μ': 'm', u'ν': 'n', u'ξ': 'ks', u'ο': 'o', u'ό': 'o', u'ὀ': 'o', u'ὁ': 'o', u'ὂ': 'o', u'ὃ': 'o', u'ὄ': 'o', u'ὅ': 'o', u'ὸ': 'o', u'ό': 'o', u'π': 'p', u'ρ': 'r', u'ῤ': 'r', u'ῥ': 'r', u'σ': 's', u'ς': 's', u'τ': 't', u'υ': 'y', u'ύ': 'y', u'ϋ': 'y', u'ΰ': 'y', u'ὐ': 'y', u'ὑ': 'y', u'ὒ': 'y', u'ὓ': 'y', u'ὔ': 'y', u'ὕ': 'y', u'ὖ': 'y', u'ὗ': 'y', u'ὺ': 'y', u'ύ': 'y', u'ῠ': 'y', u'ῡ': 'y', u'ῢ': 'y', u'ΰ': 'y', u'ῦ': 'y', u'ῧ': 'y', u'φ': 'f', u'χ': 'x', u'ψ': 'ps', u'ω': 'o', u'ώ': 'o', u'ὠ': 'o', u'ὡ': 'o', u'ὢ': 'o', u'ὣ': 'o', u'ὤ': 'o', u'ὥ': 'o', u'ὦ': 'o', u'ὧ': 'o', u'ᾠ': 'o', u'ᾡ': 'o', u'ᾢ': 'o', u'ᾣ': 'o', u'ᾤ': 'o', u'ᾥ': 'o', u'ᾦ': 'o', u'ᾧ': 'o', u'ὼ': 'o', u'ώ': 'o', u'ῲ': 'o', u'ῳ': 'o', u'ῴ': 'o', u'ῶ': 'o', u'ῷ': 'o', u'¨': '', u'΅': '', u'᾿': '', u'῾': '', u'῍': '', u'῝': '', u'῎': '', u'῞': '', u'῏': '', u'῟': '', u'῀': '', u'῁': '', u'΄': '', u'΅': '', u'`': '', u'῭': '', u'ͺ': '', u'᾽': '', u'А': 'A', u'Б': 'B', u'В': 'V', u'Г': 'G', u'Д': 'D', u'Е': 'E', u'Ё': 'E', u'Ж': 'ZH', u'З': 'Z', u'И': 'I', u'Й': 'I', u'К': 'K', u'Л': 'L', u'М': 'M', u'Н': 'N', u'О': 'O', u'П': 'P', u'Р': 'R', u'С': 'S', u'Т': 'T', u'У': 'U', u'Ф': 'F', u'Х': 'KH', u'Ц': 'TS', u'Ч': 'CH', u'Ш': 'SH', u'Щ': 'SHCH', u'Ы': 'Y', u'Э': 'E', u'Ю': 'YU', u'Я': 'YA', u'а': 'A', u'б': 'B', u'в': 'V', u'г': 'G', u'д': 'D', u'е': 'E', u'ё': 'E', u'ж': 'ZH', u'з': 'Z', u'и': 'I', u'й': 'I', u'к': 'K', u'л': 'L', u'м': 'M', u'н': 'N', u'о': 'O', u'п': 'P', u'р': 'R', u'с': 'S', u'т': 'T', u'у': 'U', u'ф': 'F', u'х': 'KH', u'ц': 'TS', u'ч': 'CH', u'ш': 'SH', u'щ': 'SHCH', u'ы': 'Y', u'э': 'E', u'ю': 'YU', u'я': 'YA', u'Ъ': '', u'ъ': '', u'Ь': '', u'ь': '', u'ð': 'd', u'Ð': 'D', u'þ': 'th', u'Þ': 'TH',
             u'ა': 'a', u'ბ': 'b', u'გ': 'g', u'დ': 'd', u'ე': 'e', u'ვ': 'v', u'ზ': 'z', u'თ': 't', u'ი': 'i', u'კ': 'k', u'ლ': 'l', u'მ': 'm', u'ნ': 'n', u'ო': 'o', u'პ': 'p', u'ჟ': 'zh', u'რ': 'r', u'ს': 's', u'ტ': 't', u'უ': 'u', u'ფ': 'p', u'ქ': 'k', u'ღ': 'gh', u'ყ': 'q', u'შ': 'sh', u'ჩ': 'ch', u'ც': 'ts', u'ძ': 'dz', u'წ': 'ts', u'ჭ': 'ch', u'ხ': 'kh', u'ჯ': 'j', u'ჰ': 'h' }
 
 def replace_char(m):
             u'ა': 'a', u'ბ': 'b', u'გ': 'g', u'დ': 'd', u'ე': 'e', u'ვ': 'v', u'ზ': 'z', u'თ': 't', u'ი': 'i', u'კ': 'k', u'ლ': 'l', u'მ': 'm', u'ნ': 'n', u'ო': 'o', u'პ': 'p', u'ჟ': 'zh', u'რ': 'r', u'ს': 's', u'ტ': 't', u'უ': 'u', u'ფ': 'p', u'ქ': 'k', u'ღ': 'gh', u'ყ': 'q', u'შ': 'sh', u'ჩ': 'ch', u'ც': 'ts', u'ძ': 'dz', u'წ': 'ts', u'ჭ': 'ch', u'ხ': 'kh', u'ჯ': 'j', u'ჰ': 'h' }
 
 def replace_char(m):
@@ -14,43 +14,43 @@ def replace_char(m):
         return char_map[char]
     else:
         return char
         return char_map[char]
     else:
         return char
-        
+
 def slughifi(value, do_slugify=True, overwrite_char_map={}):
     """
         High Fidelity slugify - slughifi.py, v 0.1
 def slughifi(value, do_slugify=True, overwrite_char_map={}):
     """
         High Fidelity slugify - slughifi.py, v 0.1
-        
+
         Examples :
         Examples :
-        
+
         >>> text = 'C\'est déjà l\'été.'
         >>> text = 'C\'est déjà l\'été.'
-        
+
         >>> slughifi(text)
         'cest-deja-lete'
         >>> slughifi(text)
         'cest-deja-lete'
-        
+
         >>> slughifi(text, overwrite_char_map={u'\'': '-',})
         'c-est-deja-l-ete'
         >>> slughifi(text, overwrite_char_map={u'\'': '-',})
         'c-est-deja-l-ete'
-        
+
         >>> slughifi(text, do_slugify=False)
         "C'est deja l'ete."
         >>> slughifi(text, do_slugify=False)
         "C'est deja l'ete."
-        
+
         # Normal slugify removes accented characters
         >>> slugify(text)
         'cest-dj-lt'
         # Normal slugify removes accented characters
         >>> slugify(text)
         'cest-dj-lt'
-        
+
     """
 
     # unicodification
     if type(value) != UnicodeType:
         value = unicode(value, 'utf-8', 'ignore')
     """
 
     # unicodification
     if type(value) != UnicodeType:
         value = unicode(value, 'utf-8', 'ignore')
-        
+
     # overwrite chararcter mapping
     char_map.update(overwrite_char_map)
 
     # try to replace chars
     value = re.sub('[^a-zA-Z0-9\\s\\-]{1}', replace_char, value)
     # overwrite chararcter mapping
     char_map.update(overwrite_char_map)
 
     # try to replace chars
     value = re.sub('[^a-zA-Z0-9\\s\\-]{1}', replace_char, value)
-    
+
     # apply django default slugify
     if do_slugify:
         value = slugify(value)
     # apply django default slugify
     if do_slugify:
         value = slugify(value)
-        
+
     return value.encode('ascii', 'ignore')
 
     return value.encode('ascii', 'ignore')
 
index a577d71..62485f3 100644 (file)
@@ -17,6 +17,6 @@ sorl-thumbnail>=3.2
 
 # home-brewed & dependencies
 lxml>=2.2.2
 
 # home-brewed & dependencies
 lxml>=2.2.2
--e git+git://github.com/fnp/librarian.git@d43d87400dcc19851442#egg=librarian
+-e git+git://github.com/fnp/librarian.git@d43d87400dcc19851442#egg=librarian
 
 # MySQL-python>=1.2,<2.0
 
 # MySQL-python>=1.2,<2.0
index 247fc2c..f798d69 100644 (file)
@@ -17,13 +17,13 @@ doc = etree.parse('rodziny.xml')
 
 for element in doc.findall('//span'):
     themes = [s.strip() for s in element.text.split(',')]
 
 for element in doc.findall('//span'):
     themes = [s.strip() for s in element.text.split(',')]
-    
+
     element.text = u''
     element.text = u''
-    
+
     for theme in themes:
         try:
             Tag.objects.get(slug=slughifi(theme))
     for theme in themes:
         try:
             Tag.objects.get(slug=slughifi(theme))
-        
+
             link = etree.SubElement(element, 'a', href=u'/katalog/%s' % slughifi(theme))
             link.text = theme
             link.tail = ', '
             link = etree.SubElement(element, 'a', href=u'/katalog/%s' % slughifi(theme))
             link.text = theme
             link.tail = ', '
index 9cc721b..3268f45 100755 (executable)
@@ -25,19 +25,19 @@ for file_name in os.listdir('mp3'):
     base_name, ext = splitext(file_name)
     if ext != '.mp3':
         continue
     base_name, ext = splitext(file_name)
     if ext != '.mp3':
         continue
-    
+
     audio = easyid3.EasyID3(join('mp3', file_name))
     title = audio['title'][0]
     artist = title.split(',', 1)[0].strip()
     artist_slug = slughifi(artist)
     title_part = slughifi(title.rsplit(',', 1)[1].strip())
     audio = easyid3.EasyID3(join('mp3', file_name))
     title = audio['title'][0]
     artist = title.split(',', 1)[0].strip()
     artist_slug = slughifi(artist)
     title_part = slughifi(title.rsplit(',', 1)[1].strip())
-    
+
     print "--------------------"
     print "File: %s" % file_name
     print "Title: %s" % title
     print
     print "Matching books:"
     print "--------------------"
     print "File: %s" % file_name
     print "Title: %s" % title
     print
     print "Matching books:"
-    
+
     matching_books = [book for book in Book.tagged.with_all(artist_slug) if book.slug not in chosen_book_slugs]
     matching_books = [book for book in matching_books if title_part in book.slug]
 
     matching_books = [book for book in Book.tagged.with_all(artist_slug) if book.slug not in chosen_book_slugs]
     matching_books = [book for book in matching_books if title_part in book.slug]
 
@@ -51,11 +51,10 @@ for file_name in os.listdir('mp3'):
     else:
         print "Skipping %s: No matching book found" % file_name
         continue
     else:
         print "Skipping %s: No matching book found" % file_name
         continue
-    
+
     print "You chose %d (%s)" % (i, matching_books[i].slug)
     print "You chose %d (%s)" % (i, matching_books[i].slug)
-    
+
     chosen_book_slugs.add(matching_books[i].slug)
     os.rename(join('mp3', file_name), join('new_mp3', matching_books[i].slug + '.mp3'))
     os.rename(join('oggvorbis', base_name + '.ogg'), join('new_ogg', matching_books[i].slug + '.ogg'))
     chosen_book_slugs.add(matching_books[i].slug)
     os.rename(join('mp3', file_name), join('new_mp3', matching_books[i].slug + '.mp3'))
     os.rename(join('oggvorbis', base_name + '.ogg'), join('new_ogg', matching_books[i].slug + '.ogg'))
-    
-    
\ No newline at end of file
+
index e83a07f..3244243 100755 (executable)
@@ -31,7 +31,7 @@ for tag in Tag.objects.all():
         tag.main_page = True
     else:
         tag.main_page = False
         tag.main_page = True
     else:
         tag.main_page = False
-    
+
     tag.save()
     sys.stderr.write('.')
 
     tag.save()
     sys.stderr.write('.')
 
index a9acc04..93b2805 100755 (executable)
@@ -1,12 +1,18 @@
 #!/usr/bin/env python
 #!/usr/bin/env python
-from os.path import abspath, dirname, join
+import os.path
 import sys
 
 import sys
 
+ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
+
 # Add apps and lib directories to PYTHONPATH
 # Add apps and lib directories to PYTHONPATH
-sys.path.insert(0, abspath(join(dirname(__file__), '../apps')))
-sys.path.insert(0, abspath(join(dirname(__file__), '../lib')))
+sys.path = [
+    os.path.join(ROOT, 'apps'),
+    os.path.join(ROOT, 'lib'),
+    os.path.join(ROOT, 'lib/librarian'),
+] + sys.path
 
 from django.core.management import execute_manager
 
 from django.core.management import execute_manager
+
 try:
     import settings # Assumed to be in the same directory.
 except ImportError:
 try:
     import settings # Assumed to be in the same directory.
 except ImportError:
index c9a17dc..60b382c 100644 (file)
@@ -118,7 +118,7 @@ class ProfileMiddleware(object):
             response.content += self.summary_for_files(stats_str)
 
             os.unlink(self.tmpfile)
             response.content += self.summary_for_files(stats_str)
 
             os.unlink(self.tmpfile)
-            
+
             response.content += '\n%d SQL Queries:\n' % len(connection.queries)
             response.content += pprint.pformat(connection.queries)
 
             response.content += '\n%d SQL Queries:\n' % len(connection.queries)
             response.content += pprint.pformat(connection.queries)
 
index b7c55fd..2ece0b1 100644 (file)
@@ -153,8 +153,8 @@ COMPRESS_JS = {
         'output_filename': 'js/jquery.min.js',
     },
     'all': {
         'output_filename': 'js/jquery.min.js',
     },
     'all': {
-        'source_filenames': ('js/jquery.autocomplete.js', 'js/jquery.form.js', 
-            'js/jquery.countdown.js', 'js/jquery.countdown-pl.js', 
+        'source_filenames': ('js/jquery.autocomplete.js', 'js/jquery.form.js',
+            'js/jquery.countdown.js', 'js/jquery.countdown-pl.js',
             'js/jquery.countdown-de.js', 'js/jquery.countdown-uk.js',
             'js/jquery.countdown-es.js', 'js/jquery.countdown-lt.js',
             'js/jquery.countdown-ru.js', 'js/jquery.countdown-fr.js',
             'js/jquery.countdown-de.js', 'js/jquery.countdown-uk.js',
             'js/jquery.countdown-es.js', 'js/jquery.countdown-lt.js',
             'js/jquery.countdown-ru.js', 'js/jquery.countdown-fr.js',
index 41e3be2..598ef2e 100644 (file)
@@ -1,4 +1,4 @@
-$(function() {    
+$(function() {
     function scrollToAnchor(anchor) {
         if (anchor) {
             var element = $('a[name="' + anchor.slice(1) + '"]');
     function scrollToAnchor(anchor) {
         if (anchor) {
             var element = $('a[name="' + anchor.slice(1) + '"]');
@@ -9,22 +9,22 @@ $(function() {
             }
         }
     }
             }
         }
     }
-    
+
     $.highlightFade.defaults.speed = 3000;
     $('#toc').hide();
     if ($('#toc li').length == 0) {
         $('#menu li a[href="#toc"]').remove();
     }
     $.highlightFade.defaults.speed = 3000;
     $('#toc').hide();
     if ($('#toc li').length == 0) {
         $('#menu li a[href="#toc"]').remove();
     }
-    
+
     // On page load, scroll to anchor
     scrollToAnchor(window.location.hash)
     // On page load, scroll to anchor
     scrollToAnchor(window.location.hash)
-    
+
     $('#toc, #themes, #book-text').delegate('click', 'a', function(event) {
         event.preventDefault();
         $('#menu li a.selected').click();
         scrollToAnchor($(this).attr('href'));
     });
     $('#toc, #themes, #book-text').delegate('click', 'a', function(event) {
         event.preventDefault();
         $('#menu li a.selected').click();
         scrollToAnchor($(this).attr('href'));
     });
-    
+
     $('#menu li a').toggle(function() {
         $('#menu li a.selected').click();
         $(this).addClass('selected');
     $('#menu li a').toggle(function() {
         $('#menu li a.selected').click();
         $(this).addClass('selected');
index dc4c07d..6e0f562 100644 (file)
@@ -3,49 +3,49 @@ var LOCALE_TEXTS = {
                "DELETE_SHELF": "Czy na pewno usunąć półkę",
                "HIDE_DESCRIPTION": "Zwiń opis",
                "EXPAND_DESCRIPTION": "Rozwiń opis",
                "DELETE_SHELF": "Czy na pewno usunąć półkę",
                "HIDE_DESCRIPTION": "Zwiń opis",
                "EXPAND_DESCRIPTION": "Rozwiń opis",
-               "LOADING": "Ładowanie"         
+               "LOADING": "Ładowanie"
        },
     "de": {
         "DELETE_SHELF": "Translate me!",
         "HIDE_DESCRIPTION": "Translate me!",
         "EXPAND_DESCRIPTION": "Translate me!",
        },
     "de": {
         "DELETE_SHELF": "Translate me!",
         "HIDE_DESCRIPTION": "Translate me!",
         "EXPAND_DESCRIPTION": "Translate me!",
-        "LOADING": "Translate me!"             
+        "LOADING": "Translate me!"
     },
        "fr": {
                "DELETE_SHELF": "Translate me!",
                "HIDE_DESCRIPTION": "Translate me!",
                "EXPAND_DESCRIPTION": "Translate me!",
     },
        "fr": {
                "DELETE_SHELF": "Translate me!",
                "HIDE_DESCRIPTION": "Translate me!",
                "EXPAND_DESCRIPTION": "Translate me!",
-               "LOADING": "Translate me!"                              
+               "LOADING": "Translate me!"
        },
        "en": {
                "DELETE_SHELF": "Translate me!",
                "HIDE_DESCRIPTION": "Translate me!",
                "EXPAND_DESCRIPTION": "Translate me!",
        },
        "en": {
                "DELETE_SHELF": "Translate me!",
                "HIDE_DESCRIPTION": "Translate me!",
                "EXPAND_DESCRIPTION": "Translate me!",
-               "LOADING": "Translate me!"              
-       }, 
+               "LOADING": "Translate me!"
+       },
        "ru": {
                "DELETE_SHELF": "Translate me!",
                "HIDE_DESCRIPTION": "Translate me!",
                "EXPAND_DESCRIPTION": "Translate me!",
        "ru": {
                "DELETE_SHELF": "Translate me!",
                "HIDE_DESCRIPTION": "Translate me!",
                "EXPAND_DESCRIPTION": "Translate me!",
-               "LOADING": "Translate me!"              
+               "LOADING": "Translate me!"
        },
        "es": {
                "DELETE_SHELF": "Translate me!",
                "HIDE_DESCRIPTION": "Translate me!",
                "EXPAND_DESCRIPTION": "Translate me!",
        },
        "es": {
                "DELETE_SHELF": "Translate me!",
                "HIDE_DESCRIPTION": "Translate me!",
                "EXPAND_DESCRIPTION": "Translate me!",
-               "LOADING": "Translate me!"                              
+               "LOADING": "Translate me!"
        },
     "lt":{
         "DELETE_SHELF": "Translate me!",
         "HIDE_DESCRIPTION": "Translate me!",
         "EXPAND_DESCRIPTION": "Translate me!",
        },
     "lt":{
         "DELETE_SHELF": "Translate me!",
         "HIDE_DESCRIPTION": "Translate me!",
         "EXPAND_DESCRIPTION": "Translate me!",
-        "LOADING": "Translate me!"             
+        "LOADING": "Translate me!"
     },
     "uk":{
         "DELETE_SHELF": "Translate me!",
         "HIDE_DESCRIPTION": "Translate me!",
         "EXPAND_DESCRIPTION": "Translate me!",
     },
     "uk":{
         "DELETE_SHELF": "Translate me!",
         "HIDE_DESCRIPTION": "Translate me!",
         "EXPAND_DESCRIPTION": "Translate me!",
-        "LOADING": "Translate me!"             
+        "LOADING": "Translate me!"
     }
 }
 var BANNER_TEXTS = [
     }
 }
 var BANNER_TEXTS = [
@@ -85,7 +85,7 @@ function changeBannerText() {
             $(this).html(BANNER_TEXTS[index]);
             $(this).fadeIn('slow');
         });
             $(this).html(BANNER_TEXTS[index]);
             $(this).fadeIn('slow');
         });
-        
+
         setTimeout(changeBannerText, 30 * 1000);
     }
 }
         setTimeout(changeBannerText, 30 * 1000);
     }
 }
@@ -93,35 +93,35 @@ function changeBannerText() {
 function autocomplete_result_handler(event, item) {
     $(event.target).closest('form').submit();
 }
 function autocomplete_result_handler(event, item) {
     $(event.target).closest('form').submit();
 }
-function serverTime() { 
-    var time = null; 
-    $.ajax({url: '/katalog/zegar/', 
-        async: false, dataType: 'text', 
-        success: function(text) { 
+function serverTime() {
+    var time = null;
+    $.ajax({url: '/katalog/zegar/',
+        async: false, dataType: 'text',
+        success: function(text) {
             time = new Date(text);
         }, error: function(http, message, exc) {
             time = new Date(text);
         }, error: function(http, message, exc) {
-            time = new Date(); 
-    }}); 
-    return time; 
+            time = new Date();
+    }});
+    return time;
 }
 
 (function($) {
     $(function() {
 }
 
 (function($) {
     $(function() {
-       
+
         $('form input').labelify({labelledClass: 'blur'});
         $('form input').labelify({labelledClass: 'blur'});
-        
+
         target = $('#login-register-window div.target');
         target = $('#login-register-window div.target');
-        
+
         $('#show-registration-form').click(function() {
             $('#login-form').hide();
             $('#registration-form').show();
         });
         $('#show-registration-form').click(function() {
             $('#login-form').hide();
             $('#registration-form').show();
         });
-        
+
         $('#show-login-form').click(function() {
             $('#registration-form').hide();
             $('#login-form').show();
         });
         $('#show-login-form').click(function() {
             $('#registration-form').hide();
             $('#login-form').show();
         });
-        
+
         // Fragments
         $('.fragment-text').each(function() {
             if ($(this).prev().filter('.fragment-short-text').length) {
         // Fragments
         $('.fragment-text').each(function() {
             if ($(this).prev().filter('.fragment-short-text').length) {
@@ -136,7 +136,7 @@ function serverTime() {
                 })
             }
         });
                 })
             }
         });
-        
+
         $('.fragment-short-text').click(function() {
             $(this).fadeOut(function() { $(this).next().fadeIn() });
             return false;
         $('.fragment-short-text').click(function() {
             $(this).fadeOut(function() { $(this).next().fadeIn() });
             return false;
@@ -144,21 +144,21 @@ function serverTime() {
             function() { $(this).css({background: '#F3F3F3', cursor: 'pointer'}); },
             function() { $(this).css({background: '#FFF'}); }
         );
             function() { $(this).css({background: '#F3F3F3', cursor: 'pointer'}); },
             function() { $(this).css({background: '#FFF'}); }
         );
-        
+
         $('.show-all-tags').click(function() {
         $('.show-all-tags').click(function() {
-            $(this).parent().parent().fadeOut(function() { 
+            $(this).parent().parent().fadeOut(function() {
                 $(this).next().fadeIn();
             });
             return false;
         });
                 $(this).next().fadeIn();
             });
             return false;
         });
-        
+
         $('.hide-all-tags').click(function() {
            $(this).parent().parent().fadeOut(function() {
                $(this).prev().fadeIn();
            });
         $('.hide-all-tags').click(function() {
            $(this).parent().parent().fadeOut(function() {
                $(this).prev().fadeIn();
            });
-           return false; 
+           return false;
         });
         });
-        
+
         $('#registration-form').ajaxForm({
             dataType: 'json',
             beforeSubmit: function() {
         $('#registration-form').ajaxForm({
             dataType: 'json',
             beforeSubmit: function() {
@@ -179,7 +179,7 @@ function serverTime() {
                 }
             }
         });
                 }
             }
         });
-        
+
         $('#login-form').ajaxForm({
             dataType: 'json',
             beforeSubmit: function() {
         $('#login-form').ajaxForm({
             dataType: 'json',
             beforeSubmit: function() {
@@ -200,7 +200,7 @@ function serverTime() {
                 }
             }
         });
                 }
             }
         });
-        
+
         $('#login-register-window').jqm({
             target: target[0],
             overlay: 60,
         $('#login-register-window').jqm({
             target: target[0],
             overlay: 60,
@@ -212,7 +212,7 @@ function serverTime() {
                 hash.w.show();
             }
         });
                 hash.w.show();
             }
         });
-        
+
         $('ul.shelf-list li').hover(function() {
             $(this).css({background: '#EEE', cursor: 'pointer'});
         }, function() {
         $('ul.shelf-list li').hover(function() {
             $(this).css({background: '#EEE', cursor: 'pointer'});
         }, function() {
@@ -220,8 +220,8 @@ function serverTime() {
         }).click(function() {
             location.href = $('a.visit-shelf', this).attr('href');
         });
         }).click(function() {
             location.href = $('a.visit-shelf', this).attr('href');
         });
-        
-        $('.delete-shelf').click(function() { 
+
+        $('.delete-shelf').click(function() {
             var link = $(this);
             var shelf_name = $('.visit-shelf', link.parent()).text();
             if (confirm(LOCALE_TEXTS[LANGUAGE_CODE]['DELETE_SHELF']+ ' '+ shelf_name + '?')) {
             var link = $(this);
             var shelf_name = $('.visit-shelf', link.parent()).text();
             if (confirm(LOCALE_TEXTS[LANGUAGE_CODE]['DELETE_SHELF']+ ' '+ shelf_name + '?')) {
@@ -231,7 +231,7 @@ function serverTime() {
             }
             return false;
         });
             }
             return false;
         });
-        
+
         $('#user-shelves-window').jqm({
             ajax: '@href',
             target: $('#user-shelves-window div.target')[0],
         $('#user-shelves-window').jqm({
             ajax: '@href',
             target: $('#user-shelves-window div.target')[0],
@@ -243,14 +243,14 @@ function serverTime() {
                 $('div.header', hash.w).css({width: $(hash.t).width()});
                 hash.w.show();
             },
                 $('div.header', hash.w).css({width: $(hash.t).width()});
                 hash.w.show();
             },
-            onLoad: function(hash) { 
+            onLoad: function(hash) {
                 $('form', hash.w).ajaxForm({
                     target: $('#user-shelves-window div.target'),
                     success: function() { setTimeout(function() { $('#user-shelves-window').jqmHide() }, 1000) }
                 });
                 $('form', hash.w).ajaxForm({
                     target: $('#user-shelves-window div.target'),
                     success: function() { setTimeout(function() { $('#user-shelves-window').jqmHide() }, 1000) }
                 });
-                
+
                 $('input', hash.w).labelify({labelledClass: 'blur'});
                 $('input', hash.w).labelify({labelledClass: 'blur'});
-                
+
                 $('ul.shelf-list li', hash.w).hover(function() {
                     $(this).css({background: '#EEE', cursor: 'pointer'});
                 }, function() {
                 $('ul.shelf-list li', hash.w).hover(function() {
                     $(this).css({background: '#EEE', cursor: 'pointer'});
                 }, function() {
@@ -258,7 +258,7 @@ function serverTime() {
                 }).click(function() {
                     location.href = $('a.visit-shelf', this).attr('href');
                 });
                 }).click(function() {
                     location.href = $('a.visit-shelf', this).attr('href');
                 });
-                
+
                 $('.delete-shelf').click(function() {
                     var link = $(this);
                     var shelf_name = $('.visit-shelf', link.parent()).text();
                 $('.delete-shelf').click(function() {
                     var link = $(this);
                     var shelf_name = $('.visit-shelf', link.parent()).text();
@@ -283,7 +283,7 @@ function serverTime() {
                 $('div.header', hash.w).css({width: $(hash.t).width()});
                 hash.w.show();
             },
                 $('div.header', hash.w).css({width: $(hash.t).width()});
                 hash.w.show();
             },
-            onLoad: function(hash) { 
+            onLoad: function(hash) {
                 $('form', hash.w).ajaxForm({
                                        dataType: 'json',
                     target: $('#suggest-window div.target'),
                 $('form', hash.w).ajaxForm({
                                        dataType: 'json',
                     target: $('#suggest-window div.target'),
@@ -304,14 +304,14 @@ function serverTime() {
                 });
             }
         });
                 });
             }
         });
-    
+
         $('#books-list .book').hover(
             function() { $(this).css({background: '#F3F3F3', cursor: 'pointer'}); },
             function() { $(this).css({background: '#FFF'}); }
         ).click(function() {
             location.href = $('h2 a', this).attr('href');
         });
         $('#books-list .book').hover(
             function() { $(this).css({background: '#F3F3F3', cursor: 'pointer'}); },
             function() { $(this).css({background: '#FFF'}); }
         ).click(function() {
             location.href = $('h2 a', this).attr('href');
         });
-        
+
                function toggled_by_slide(cont, short_el, long_el, button, short_text, long_text) {
                        function toggle(cont, short_el, long_el, button, short_text, long_text) {
                    if (cont.hasClass('short')) {
                function toggled_by_slide(cont, short_el, long_el, button, short_text, long_text) {
                        function toggle(cont, short_el, long_el, button, short_text, long_text) {
                    if (cont.hasClass('short')) {
@@ -343,8 +343,8 @@ function serverTime() {
                 toggle(cont, short_el, long_el, button, short_text, long_text)
             })
                }
                 toggle(cont, short_el, long_el, button, short_text, long_text)
             })
                }
-        toggled_by_slide($('#description'), $('#description-short'), $('#description-long'),  
-          $('#toggle-description p'), 
+        toggled_by_slide($('#description'), $('#description-short'), $('#description-long'),
+          $('#toggle-description p'),
           LOCALE_TEXTS[LANGUAGE_CODE]['EXPAND_DESCRIPTION']+' ▼',
                  LOCALE_TEXTS[LANGUAGE_CODE]['HIDE_DESCRIPTION'] + ' ▲'
                  );
           LOCALE_TEXTS[LANGUAGE_CODE]['EXPAND_DESCRIPTION']+' ▼',
                  LOCALE_TEXTS[LANGUAGE_CODE]['HIDE_DESCRIPTION'] + ' ▲'
                  );
@@ -361,17 +361,17 @@ function serverTime() {
         });
 
         var target = $('#set-window div.target');
         });
 
         var target = $('#set-window div.target');
-    
+
         $('#set-window').jqm({
         $('#set-window').jqm({
-            ajax: '@href', 
+            ajax: '@href',
             target: target[0],
             overlay: 60,
             target: target[0],
             overlay: 60,
-            trigger: 'a.jqm-trigger', 
-            onShow: function(hash) { 
+            trigger: 'a.jqm-trigger',
+            onShow: function(hash) {
                 var offset = $(hash.t).offset();
                 target.html('<p><img src="/static/img/indicator.gif" />'+LOCALE_TEXTS[LANGUAGE_CODE]['DELETE_SHELF']+'</p>');
                 hash.w.css({position: 'absolute', left: offset.left, top: offset.top}).show() },
                 var offset = $(hash.t).offset();
                 target.html('<p><img src="/static/img/indicator.gif" />'+LOCALE_TEXTS[LANGUAGE_CODE]['DELETE_SHELF']+'</p>');
                 hash.w.css({position: 'absolute', left: offset.left, top: offset.top}).show() },
-            onLoad: function(hash) { 
+            onLoad: function(hash) {
                try {
                        $('#createShelfTrigger').click(function(){
                                $('#createNewShelf').show();
                try {
                        $('#createShelfTrigger').click(function(){
                                $('#createNewShelf').show();
@@ -380,14 +380,14 @@ function serverTime() {
 
                 $('form', hash.w).ajaxForm({
                     target: target,
 
                 $('form', hash.w).ajaxForm({
                     target: target,
-                    success: function() { 
-                       setTimeout(function() { 
+                    success: function() {
+                       setTimeout(function() {
                                        $('#set-window').jqmHide();
                                   }, 1000)}
                 });
             }
         });
                                        $('#set-window').jqmHide();
                                   }, 1000)}
                 });
             }
         });
-        
+
         $('a.remove-from-shelf').click(function(event) {
             event.preventDefault();
             link = $(this);
         $('a.remove-from-shelf').click(function(event) {
             event.preventDefault();
             link = $(this);
@@ -395,18 +395,18 @@ function serverTime() {
                 link.parent().remove();
             });
         });
                 link.parent().remove();
             });
         });
-               
+
         $('#share-shelf').hide().addClass('hidden');
                $('#share-shelf input').focus(function(){this.select();});
         $('#share-shelf').hide().addClass('hidden');
                $('#share-shelf input').focus(function(){this.select();});
-                
+
         $('#user-info').show();
         changeBannerText();
         $('#onepercent-banner').show();
         $('#user-info').show();
         changeBannerText();
         $('#onepercent-banner').show();
-        
+
         var formatsDownloaded = false;
         $('#download-shelf').click(function() {
             $('#download-shelf-menu').slideDown('fast');
         var formatsDownloaded = false;
         $('#download-shelf').click(function() {
             $('#download-shelf-menu').slideDown('fast');
-            
+
             if (!formatsDownloaded) {
                 // Get info about the formats
                 formatsDownloaded = true;
             if (!formatsDownloaded) {
                 // Get info about the formats
                 formatsDownloaded = true;
@@ -435,7 +435,7 @@ function serverTime() {
             }
             return false;
         });
             }
             return false;
         });
-        
+
         $('#download-formats-form-cancel').click(function() {
             $('#download-shelf-menu').slideUp('fast');
             return false;
         $('#download-formats-form-cancel').click(function() {
             $('#download-shelf-menu').slideUp('fast');
             return false;
index 4e425e8..6f46e1b 100644 (file)
@@ -16,7 +16,7 @@
  */
 
 ;(function($) {
  */
 
 ;(function($) {
-       
+
 $.fn.extend({
        autocomplete: function(urlOrData, options) {
                var isUrl = typeof urlOrData == "string";
 $.fn.extend({
        autocomplete: function(urlOrData, options) {
                var isUrl = typeof urlOrData == "string";
@@ -26,13 +26,13 @@ $.fn.extend({
                        delay: isUrl ? $.Autocompleter.defaults.delay : 10,
                        max: options && !options.scroll ? 10 : 150
                }, options);
                        delay: isUrl ? $.Autocompleter.defaults.delay : 10,
                        max: options && !options.scroll ? 10 : 150
                }, options);
-               
+
                // if highlight is set to false, replace it with a do-nothing function
                options.highlight = options.highlight || function(value) { return value; };
                // if highlight is set to false, replace it with a do-nothing function
                options.highlight = options.highlight || function(value) { return value; };
-               
+
                // if the formatMatch option is not specified, then use formatItem for backwards compatibility
                options.formatMatch = options.formatMatch || options.formatItem;
                // if the formatMatch option is not specified, then use formatItem for backwards compatibility
                options.formatMatch = options.formatMatch || options.formatItem;
-               
+
                return this.each(function() {
                        new $.Autocompleter(this, options);
                });
                return this.each(function() {
                        new $.Autocompleter(this, options);
                });
@@ -81,9 +81,9 @@ $.Autocompleter = function(input, options) {
                mouseDownOnSelect: false
        };
        var select = $.Autocompleter.Select(options, input, selectCurrent, config);
                mouseDownOnSelect: false
        };
        var select = $.Autocompleter.Select(options, input, selectCurrent, config);
-       
+
        var blockSubmit;
        var blockSubmit;
-       
+
        // prevent form submit in opera when selecting with return key
        $.browser.opera && $(input.form).bind("submit.autocomplete", function() {
                if (blockSubmit) {
        // prevent form submit in opera when selecting with return key
        $.browser.opera && $(input.form).bind("submit.autocomplete", function() {
                if (blockSubmit) {
@@ -91,7 +91,7 @@ $.Autocompleter = function(input, options) {
                        return false;
                }
        });
                        return false;
                }
        });
-       
+
        // only opera doesn't trigger keydown multiple times while pressed, others don't work with keypress at all
        $input.bind(($.browser.opera ? "keypress" : "keydown") + ".autocomplete", function(event) {
                // a keypress means the input has focus
        // only opera doesn't trigger keydown multiple times while pressed, others don't work with keypress at all
        $input.bind(($.browser.opera ? "keypress" : "keydown") + ".autocomplete", function(event) {
                // a keypress means the input has focus
@@ -100,7 +100,7 @@ $.Autocompleter = function(input, options) {
                // track last key pressed
                lastKeyPressCode = event.keyCode;
                switch(event.keyCode) {
                // track last key pressed
                lastKeyPressCode = event.keyCode;
                switch(event.keyCode) {
-               
+
                        case KEY.UP:
                                event.preventDefault();
                                if ( select.visible() ) {
                        case KEY.UP:
                                event.preventDefault();
                                if ( select.visible() ) {
@@ -109,7 +109,7 @@ $.Autocompleter = function(input, options) {
                                        onChange(0, true);
                                }
                                break;
                                        onChange(0, true);
                                }
                                break;
-                               
+
                        case KEY.DOWN:
                                event.preventDefault();
                                if ( select.visible() ) {
                        case KEY.DOWN:
                                event.preventDefault();
                                if ( select.visible() ) {
@@ -118,7 +118,7 @@ $.Autocompleter = function(input, options) {
                                        onChange(0, true);
                                }
                                break;
                                        onChange(0, true);
                                }
                                break;
-                               
+
                        case KEY.PAGEUP:
                                event.preventDefault();
                                if ( select.visible() ) {
                        case KEY.PAGEUP:
                                event.preventDefault();
                                if ( select.visible() ) {
@@ -127,7 +127,7 @@ $.Autocompleter = function(input, options) {
                                        onChange(0, true);
                                }
                                break;
                                        onChange(0, true);
                                }
                                break;
-                               
+
                        case KEY.PAGEDOWN:
                                event.preventDefault();
                                if ( select.visible() ) {
                        case KEY.PAGEDOWN:
                                event.preventDefault();
                                if ( select.visible() ) {
@@ -136,7 +136,7 @@ $.Autocompleter = function(input, options) {
                                        onChange(0, true);
                                }
                                break;
                                        onChange(0, true);
                                }
                                break;
-                       
+
                        // matches also semicolon
                        case options.multiple && $.trim(options.multipleSeparator) == "," && KEY.COMMA:
                        case KEY.TAB:
                        // matches also semicolon
                        case options.multiple && $.trim(options.multipleSeparator) == "," && KEY.COMMA:
                        case KEY.TAB:
@@ -148,11 +148,11 @@ $.Autocompleter = function(input, options) {
                                        return false;
                                }
                                break;
                                        return false;
                                }
                                break;
-                               
+
                        case KEY.ESC:
                                select.hide();
                                break;
                        case KEY.ESC:
                                select.hide();
                                break;
-                               
+
                        default:
                                clearTimeout(timeout);
                                timeout = setTimeout(onChange, options.delay);
                        default:
                                clearTimeout(timeout);
                                timeout = setTimeout(onChange, options.delay);
@@ -203,16 +203,16 @@ $.Autocompleter = function(input, options) {
                $input.unbind();
                $(input.form).unbind(".autocomplete");
        });
                $input.unbind();
                $(input.form).unbind(".autocomplete");
        });
-       
-       
+
+
        function selectCurrent() {
                var selected = select.selected();
                if( !selected )
                        return false;
        function selectCurrent() {
                var selected = select.selected();
                if( !selected )
                        return false;
-               
+
                var v = selected.result;
                previousValue = v;
                var v = selected.result;
                previousValue = v;
-               
+
                if ( options.multiple ) {
                        var words = trimWords($input.val());
                        if ( words.length > 1 ) {
                if ( options.multiple ) {
                        var words = trimWords($input.val());
                        if ( words.length > 1 ) {
@@ -234,26 +234,26 @@ $.Autocompleter = function(input, options) {
                        }
                        v += options.multipleSeparator;
                }
                        }
                        v += options.multipleSeparator;
                }
-               
+
                $input.val(v);
                hideResultsNow();
                $input.trigger("result", [selected.data, selected.value]);
                return true;
        }
                $input.val(v);
                hideResultsNow();
                $input.trigger("result", [selected.data, selected.value]);
                return true;
        }
-       
+
        function onChange(crap, skipPrevCheck) {
                if( lastKeyPressCode == KEY.DEL ) {
                        select.hide();
                        return;
                }
        function onChange(crap, skipPrevCheck) {
                if( lastKeyPressCode == KEY.DEL ) {
                        select.hide();
                        return;
                }
-               
+
                var currentValue = $input.val();
                var currentValue = $input.val();
-               
+
                if ( !skipPrevCheck && currentValue == previousValue )
                        return;
                if ( !skipPrevCheck && currentValue == previousValue )
                        return;
-               
+
                previousValue = currentValue;
                previousValue = currentValue;
-               
+
                currentValue = lastWord(currentValue);
                if ( currentValue.length >= options.minChars) {
                        $input.addClass(options.loadingClass);
                currentValue = lastWord(currentValue);
                if ( currentValue.length >= options.minChars) {
                        $input.addClass(options.loadingClass);
@@ -265,7 +265,7 @@ $.Autocompleter = function(input, options) {
                        select.hide();
                }
        };
                        select.hide();
                }
        };
-       
+
        function trimWords(value) {
                if (!value)
                        return [""];
        function trimWords(value) {
                if (!value)
                        return [""];
@@ -275,12 +275,12 @@ $.Autocompleter = function(input, options) {
                        return $.trim(value).length ? $.trim(word) : null;
                });
        }
                        return $.trim(value).length ? $.trim(word) : null;
                });
        }
-       
+
        function lastWord(value) {
                if ( !options.multiple )
                        return value;
                var words = trimWords(value);
        function lastWord(value) {
                if ( !options.multiple )
                        return value;
                var words = trimWords(value);
-               if (words.length == 1) 
+               if (words.length == 1)
                        return words[0];
                var cursorAt = $(input).selection().start;
                if (cursorAt == value.length) {
                        return words[0];
                var cursorAt = $(input).selection().start;
                if (cursorAt == value.length) {
@@ -290,7 +290,7 @@ $.Autocompleter = function(input, options) {
                }
                return words[words.length - 1];
        }
                }
                return words[words.length - 1];
        }
-       
+
        // fills in the input box w/the first match (assumed to be the best match)
        // q: the term entered
        // sValue: the first matching result
        // fills in the input box w/the first match (assumed to be the best match)
        // q: the term entered
        // sValue: the first matching result
@@ -355,14 +355,14 @@ $.Autocompleter = function(input, options) {
                        success(term, data);
                // if an AJAX url has been supplied, try loading the data now
                } else if( (typeof options.url == "string") && (options.url.length > 0) ){
                        success(term, data);
                // if an AJAX url has been supplied, try loading the data now
                } else if( (typeof options.url == "string") && (options.url.length > 0) ){
-                       
+
                        var extraParams = {
                                timestamp: +new Date()
                        };
                        $.each(options.extraParams, function(key, param) {
                                extraParams[key] = typeof param == "function" ? param() : param;
                        });
                        var extraParams = {
                                timestamp: +new Date()
                        };
                        $.each(options.extraParams, function(key, param) {
                                extraParams[key] = typeof param == "function" ? param() : param;
                        });
-                       
+
                        $.ajax({
                                // try to leverage ajaxQueue plugin to abort previous requests
                                mode: "abort",
                        $.ajax({
                                // try to leverage ajaxQueue plugin to abort previous requests
                                mode: "abort",
@@ -386,7 +386,7 @@ $.Autocompleter = function(input, options) {
                        failure(term);
                }
        };
                        failure(term);
                }
        };
-       
+
        function parse(data) {
                var parsed = [];
                var rows = data.split("\n");
        function parse(data) {
                var parsed = [];
                var rows = data.split("\n");
@@ -455,9 +455,9 @@ $.Autocompleter.Cache = function(options) {
 
        var data = {};
        var length = 0;
 
        var data = {};
        var length = 0;
-       
+
        function matchSubset(s, sub) {
        function matchSubset(s, sub) {
-               if (!options.matchCase) 
+               if (!options.matchCase)
                        s = s.toLowerCase();
                var i = s.indexOf(sub);
                if (options.matchContains == "word"){
                        s = s.toLowerCase();
                var i = s.indexOf(sub);
                if (options.matchContains == "word"){
@@ -467,17 +467,17 @@ $.Autocompleter.Cache = function(options) {
                if (i == -1) return false;
                return i == 0 || options.matchContains;
        };
                if (i == -1) return false;
                return i == 0 || options.matchContains;
        };
-       
+
        function add(q, value) {
                if (length > options.cacheLength){
                        flush();
                }
        function add(q, value) {
                if (length > options.cacheLength){
                        flush();
                }
-               if (!data[q]){ 
+               if (!data[q]){
                        length++;
                }
                data[q] = value;
        }
                        length++;
                }
                data[q] = value;
        }
-       
+
        function populate(){
                if( !options.data ) return false;
                // track the matches
        function populate(){
                if( !options.data ) return false;
                // track the matches
@@ -486,23 +486,23 @@ $.Autocompleter.Cache = function(options) {
 
                // no url was specified, we need to adjust the cache length to make sure it fits the local data store
                if( !options.url ) options.cacheLength = 1;
 
                // no url was specified, we need to adjust the cache length to make sure it fits the local data store
                if( !options.url ) options.cacheLength = 1;
-               
+
                // track all options for minChars = 0
                stMatchSets[""] = [];
                // track all options for minChars = 0
                stMatchSets[""] = [];
-               
+
                // loop through the array and create a lookup structure
                for ( var i = 0, ol = options.data.length; i < ol; i++ ) {
                        var rawValue = options.data[i];
                        // if rawValue is a string, make an array otherwise just reference the array
                        rawValue = (typeof rawValue == "string") ? [rawValue] : rawValue;
                // loop through the array and create a lookup structure
                for ( var i = 0, ol = options.data.length; i < ol; i++ ) {
                        var rawValue = options.data[i];
                        // if rawValue is a string, make an array otherwise just reference the array
                        rawValue = (typeof rawValue == "string") ? [rawValue] : rawValue;
-                       
+
                        var value = options.formatMatch(rawValue, i+1, options.data.length);
                        if ( value === false )
                                continue;
                        var value = options.formatMatch(rawValue, i+1, options.data.length);
                        if ( value === false )
                                continue;
-                               
+
                        var firstChar = value.charAt(0).toLowerCase();
                        // if no lookup array for this character exists, look it up now
                        var firstChar = value.charAt(0).toLowerCase();
                        // if no lookup array for this character exists, look it up now
-                       if( !stMatchSets[firstChar] ) 
+                       if( !stMatchSets[firstChar] )
                                stMatchSets[firstChar] = [];
 
                        // if the match is a string
                                stMatchSets[firstChar] = [];
 
                        // if the match is a string
@@ -511,7 +511,7 @@ $.Autocompleter.Cache = function(options) {
                                data: rawValue,
                                result: options.formatResult && options.formatResult(rawValue) || value
                        };
                                data: rawValue,
                                result: options.formatResult && options.formatResult(rawValue) || value
                        };
-                       
+
                        // push the current match into the set list
                        stMatchSets[firstChar].push(row);
 
                        // push the current match into the set list
                        stMatchSets[firstChar].push(row);
 
@@ -529,15 +529,15 @@ $.Autocompleter.Cache = function(options) {
                        add(i, value);
                });
        }
                        add(i, value);
                });
        }
-       
+
        // populate any existing data
        setTimeout(populate, 25);
        // populate any existing data
        setTimeout(populate, 25);
-       
+
        function flush(){
                data = {};
                length = 0;
        }
        function flush(){
                data = {};
                length = 0;
        }
-       
+
        return {
                flush: flush,
                add: add,
        return {
                flush: flush,
                add: add,
@@ -545,7 +545,7 @@ $.Autocompleter.Cache = function(options) {
                load: function(q) {
                        if (!options.cacheLength || !length)
                                return null;
                load: function(q) {
                        if (!options.cacheLength || !length)
                                return null;
-                       /* 
+                       /*
                         * if dealing w/local data and matchContains than we must make sure
                         * to loop through all the data collections looking for matches
                         */
                         * if dealing w/local data and matchContains than we must make sure
                         * to loop through all the data collections looking for matches
                         */
@@ -565,9 +565,9 @@ $.Autocompleter.Cache = function(options) {
                                                        }
                                                });
                                        }
                                                        }
                                                });
                                        }
-                               }                               
+                               }
                                return csub;
                                return csub;
-                       } else 
+                       } else
                        // if the exact item exists, use it
                        if (data[q]){
                                return data[q];
                        // if the exact item exists, use it
                        if (data[q]){
                                return data[q];
@@ -595,7 +595,7 @@ $.Autocompleter.Select = function (options, input, select, config) {
        var CLASSES = {
                ACTIVE: "ac_over"
        };
        var CLASSES = {
                ACTIVE: "ac_over"
        };
-       
+
        var listItems,
                active = -1,
                data,
        var listItems,
                active = -1,
                data,
@@ -603,7 +603,7 @@ $.Autocompleter.Select = function (options, input, select, config) {
                needsInit = true,
                element,
                list;
                needsInit = true,
                element,
                list;
-       
+
        // Create results
        function init() {
                if (!needsInit)
        // Create results
        function init() {
                if (!needsInit)
@@ -613,11 +613,11 @@ $.Autocompleter.Select = function (options, input, select, config) {
                .addClass(options.resultsClass)
                .css("position", "absolute")
                .appendTo(document.body);
                .addClass(options.resultsClass)
                .css("position", "absolute")
                .appendTo(document.body);
-       
+
                list = $("<ul/>").appendTo(element).mouseover( function(event) {
                        if(target(event).nodeName && target(event).nodeName.toUpperCase() == 'LI') {
                    active = $("li", list).removeClass(CLASSES.ACTIVE).index(target(event));
                list = $("<ul/>").appendTo(element).mouseover( function(event) {
                        if(target(event).nodeName && target(event).nodeName.toUpperCase() == 'LI') {
                    active = $("li", list).removeClass(CLASSES.ACTIVE).index(target(event));
-                           $(target(event)).addClass(CLASSES.ACTIVE);            
+                           $(target(event)).addClass(CLASSES.ACTIVE);
                }
                }).click(function(event) {
                        $(target(event)).addClass(CLASSES.ACTIVE);
                }
                }).click(function(event) {
                        $(target(event)).addClass(CLASSES.ACTIVE);
@@ -630,13 +630,13 @@ $.Autocompleter.Select = function (options, input, select, config) {
                }).mouseup(function() {
                        config.mouseDownOnSelect = false;
                });
                }).mouseup(function() {
                        config.mouseDownOnSelect = false;
                });
-               
+
                if( options.width > 0 )
                        element.css("width", options.width);
                if( options.width > 0 )
                        element.css("width", options.width);
-                       
+
                needsInit = false;
                needsInit = false;
-       } 
-       
+       }
+
        function target(event) {
                var element = event.target;
                while(element && element.tagName != "LI")
        function target(event) {
                var element = event.target;
                while(element && element.tagName != "LI")
@@ -663,7 +663,7 @@ $.Autocompleter.Select = function (options, input, select, config) {
             }
         }
        };
             }
         }
        };
-       
+
        function movePosition(step) {
                active += step;
                if (active < 0) {
        function movePosition(step) {
                active += step;
                if (active < 0) {
@@ -672,13 +672,13 @@ $.Autocompleter.Select = function (options, input, select, config) {
                        active = 0;
                }
        }
                        active = 0;
                }
        }
-       
+
        function limitNumberOfItems(available) {
                return options.max && options.max < available
                        ? options.max
                        : available;
        }
        function limitNumberOfItems(available) {
                return options.max && options.max < available
                        ? options.max
                        : available;
        }
-       
+
        function fillList() {
                list.empty();
                var max = limitNumberOfItems(data.length);
        function fillList() {
                list.empty();
                var max = limitNumberOfItems(data.length);
@@ -700,7 +700,7 @@ $.Autocompleter.Select = function (options, input, select, config) {
                if ( $.fn.bgiframe )
                        list.bgiframe();
        }
                if ( $.fn.bgiframe )
                        list.bgiframe();
        }
-       
+
        return {
                display: function(d, q) {
                        init();
        return {
                display: function(d, q) {
                        init();
@@ -752,7 +752,7 @@ $.Autocompleter.Select = function (options, input, select, config) {
                                        maxHeight: options.scrollHeight,
                                        overflow: 'auto'
                                });
                                        maxHeight: options.scrollHeight,
                                        overflow: 'auto'
                                });
-                               
+
                 if($.browser.msie && typeof document.body.style.maxHeight === "undefined") {
                                        var listHeight = 0;
                                        listItems.each(function() {
                 if($.browser.msie && typeof document.body.style.maxHeight === "undefined") {
                                        var listHeight = 0;
                                        listItems.each(function() {
@@ -765,7 +765,7 @@ $.Autocompleter.Select = function (options, input, select, config) {
                                                listItems.width( list.width() - parseInt(listItems.css("padding-left")) - parseInt(listItems.css("padding-right")) );
                                        }
                 }
                                                listItems.width( list.width() - parseInt(listItems.css("padding-left")) - parseInt(listItems.css("padding-right")) );
                                        }
                 }
-                
+
             }
                },
                selected: function() {
             }
                },
                selected: function() {
index 0e02ce5..5a3f43d 100644 (file)
@@ -1,12 +1,12 @@
-/* http://keith-wood.name/countdown.html\r
-   German initialisation for the jQuery countdown extension\r
-   Written by Keith Wood (kbwood@virginbroadband.com.au) Jan 2008. */\r
-(function($) {\r
-       $.countdown.regional['de'] = {\r
-               labels: ['Jahren', 'Monate', 'Wochen', 'Tage', 'Stunden', 'Minuten', 'Sekunden'],\r
-               labels1: ['Jahre', 'Monat', 'Woche', 'Tag', 'Stunde', 'Minute', 'Sekunde'],\r
-               compactLabels: ['J', 'M', 'W', 'T'],\r
-               whichLabels: null,\r
-               timeSeparator: ':', isRTL: false};\r
-       $.countdown.setDefaults($.countdown.regional['de']);\r
-})(jQuery);\r
+/* http://keith-wood.name/countdown.html
+   German initialisation for the jQuery countdown extension
+   Written by Keith Wood (kbwood@virginbroadband.com.au) Jan 2008. */
+(function($) {
+       $.countdown.regional['de'] = {
+               labels: ['Jahren', 'Monate', 'Wochen', 'Tage', 'Stunden', 'Minuten', 'Sekunden'],
+               labels1: ['Jahre', 'Monat', 'Woche', 'Tag', 'Stunde', 'Minute', 'Sekunde'],
+               compactLabels: ['J', 'M', 'W', 'T'],
+               whichLabels: null,
+               timeSeparator: ':', isRTL: false};
+       $.countdown.setDefaults($.countdown.regional['de']);
+})(jQuery);
index 09657bc..362f58c 100644 (file)
@@ -1,12 +1,12 @@
-/* http://keith-wood.name/countdown.html\r
- * Spanish initialisation for the jQuery countdown extension\r
- * Written by Sergio Carracedo Martinez webmaster@neodisenoweb.com (2008) */\r
-(function($) {\r
-       $.countdown.regional['es'] = {\r
-               labels: ['Años', 'Meses', 'Semanas', 'Dias', 'Horas', 'Minutos', 'Segundos'],\r
-               labels1: ['Años', 'Meses', 'Semanas', 'Dias', 'Horas', 'Minutos', 'Segundos'],\r
-               compactLabels: ['a', 'm', 's', 'g'],\r
-               whichLabels: null,\r
-               timeSeparator: ':', isRTL: false};\r
-       $.countdown.setDefaults($.countdown.regional['es']);\r
-})(jQuery);\r
+/* http://keith-wood.name/countdown.html
+ * Spanish initialisation for the jQuery countdown extension
+ * Written by Sergio Carracedo Martinez webmaster@neodisenoweb.com (2008) */
+(function($) {
+       $.countdown.regional['es'] = {
+               labels: ['Años', 'Meses', 'Semanas', 'Dias', 'Horas', 'Minutos', 'Segundos'],
+               labels1: ['Años', 'Meses', 'Semanas', 'Dias', 'Horas', 'Minutos', 'Segundos'],
+               compactLabels: ['a', 'm', 's', 'g'],
+               whichLabels: null,
+               timeSeparator: ':', isRTL: false};
+       $.countdown.setDefaults($.countdown.regional['es']);
+})(jQuery);
index 5f5fac9..70e17de 100644 (file)
@@ -1,12 +1,12 @@
-/* http://keith-wood.name/countdown.html\r
-   French initialisation for the jQuery countdown extension\r
-   Written by Keith Wood (kbwood{at}iinet.com.au) Jan 2008. */\r
-(function($) {\r
-       $.countdown.regional['fr'] = {\r
-               labels: ['Années', 'Mois', 'Semaines', 'Jours', 'Heures', 'Minutes', 'Secondes'],\r
-               labels1: ['Année', 'Mois', 'Semaine', 'Jour', 'Heure', 'Minute', 'Seconde'],\r
-               compactLabels: ['a', 'm', 's', 'j'],\r
-               whichLabels: null,\r
-               timeSeparator: ':', isRTL: false};\r
-       $.countdown.setDefaults($.countdown.regional['fr']);\r
-})(jQuery);\r
+/* http://keith-wood.name/countdown.html
+   French initialisation for the jQuery countdown extension
+   Written by Keith Wood (kbwood{at}iinet.com.au) Jan 2008. */
+(function($) {
+       $.countdown.regional['fr'] = {
+               labels: ['Années', 'Mois', 'Semaines', 'Jours', 'Heures', 'Minutes', 'Secondes'],
+               labels1: ['Année', 'Mois', 'Semaine', 'Jour', 'Heure', 'Minute', 'Seconde'],
+               compactLabels: ['a', 'm', 's', 'j'],
+               whichLabels: null,
+               timeSeparator: ':', isRTL: false};
+       $.countdown.setDefaults($.countdown.regional['fr']);
+})(jQuery);
index 77a8a17..6860a4b 100644 (file)
@@ -1,17 +1,17 @@
-/* http://keith-wood.name/countdown.html\r
- * Polish initialisation for the jQuery countdown extension\r
- * Written by Pawel Lewtak lewtak@gmail.com (2008) */\r
-(function($) {\r
-       $.countdown.regional['pl'] = {\r
-               labels: ['lat', 'miesięcy', 'tygodni', 'dni', 'godzin', 'minut', 'sekund'],\r
-               labels1: ['rok', 'miesiąc', 'tydzień', 'dzień', 'godzina', 'minuta', 'sekunda'],\r
-               labels2: ['lata', 'miesiące', 'tygodnie', 'dni', 'godziny', 'minuty', 'sekundy'],\r
-               compactLabels: ['l', 'm', 't', 'd'], compactLabels1: ['r', 'm', 't', 'd'],\r
-               whichLabels: function(amount) {\r
-                       var units = amount % 10;\r
-                       var tens = Math.floor((amount % 100) / 10);\r
-                       return (amount == 1 ? 1 : (units >= 2 && units <= 4 && tens != 1 ? 2 : 0));\r
-               },\r
-               timeSeparator: ':', isRTL: false};\r
-       $.countdown.setDefaults($.countdown.regional['pl']);\r
-})(jQuery);\r
+/* http://keith-wood.name/countdown.html
+ * Polish initialisation for the jQuery countdown extension
+ * Written by Pawel Lewtak lewtak@gmail.com (2008) */
+(function($) {
+       $.countdown.regional['pl'] = {
+               labels: ['lat', 'miesięcy', 'tygodni', 'dni', 'godzin', 'minut', 'sekund'],
+               labels1: ['rok', 'miesiąc', 'tydzień', 'dzień', 'godzina', 'minuta', 'sekunda'],
+               labels2: ['lata', 'miesiące', 'tygodnie', 'dni', 'godziny', 'minuty', 'sekundy'],
+               compactLabels: ['l', 'm', 't', 'd'], compactLabels1: ['r', 'm', 't', 'd'],
+               whichLabels: function(amount) {
+                       var units = amount % 10;
+                       var tens = Math.floor((amount % 100) / 10);
+                       return (amount == 1 ? 1 : (units >= 2 && units <= 4 && tens != 1 ? 2 : 0));
+               },
+               timeSeparator: ':', isRTL: false};
+       $.countdown.setDefaults($.countdown.regional['pl']);
+})(jQuery);
index 1d1ca96..badd3eb 100644 (file)
@@ -1,12 +1,12 @@
-/* http://keith-wood.name/countdown.html\r
- * Russian initialisation for the jQuery countdown extension\r
- * Written by Dominus i3rixon@gmail.com (2008) */\r
-(function($) {\r
-       $.countdown.regional['ru'] = {\r
-               labels: ['Лет', 'Месяцев', 'Недель', 'Дней', 'Часов', 'Минут', 'Секунд'],\r
-               labels1: ['Год', 'Месяц', 'Неделя', 'День', 'Час', 'Минута', 'Секунда'],\r
-               compactLabels: ['l', 'm', 'n', 'd'], compactLabels1: ['g', 'm', 'n', 'd'],\r
-               whichLabels: null,\r
-               timeSeparator: ':', isRTL: false};\r
-       $.countdown.setDefaults($.countdown.regional['ru']);\r
-})(jQuery);\r
+/* http://keith-wood.name/countdown.html
+ * Russian initialisation for the jQuery countdown extension
+ * Written by Dominus i3rixon@gmail.com (2008) */
+(function($) {
+       $.countdown.regional['ru'] = {
+               labels: ['Лет', 'Месяцев', 'Недель', 'Дней', 'Часов', 'Минут', 'Секунд'],
+               labels1: ['Год', 'Месяц', 'Неделя', 'День', 'Час', 'Минута', 'Секунда'],
+               compactLabels: ['l', 'm', 'n', 'd'], compactLabels1: ['g', 'm', 'n', 'd'],
+               whichLabels: null,
+               timeSeparator: ':', isRTL: false};
+       $.countdown.setDefaults($.countdown.regional['ru']);
+})(jQuery);
index e38ab04..c98791e 100644 (file)
@@ -1,12 +1,12 @@
-/* http://keith-wood.name/countdown.html\r
- * Ukrainian initialisation for the jQuery countdown extension\r
- * Written by Goloborodko M misha.gm@gmail.com (2009) */\r
-(function($) {\r
-       $.countdown.regional['uk'] = {\r
-               labels: ['Років', 'Місяців', 'Тижднів', 'Днів', 'Годин', 'Хвилин', 'Секунд'],\r
-               labels1: ['Рік', 'Місяць', 'Тиждень', 'День', 'Година', 'Хвилина', 'Секунда'],\r
-               compactLabels: ['r', 'm', 't', 'd'],\r
-               whichLabels: null,\r
-               timeSeparator: ':', isRTL: false};\r
-       $.countdown.setDefaults($.countdown.regional['uk']);\r
-})(jQuery);\r
+/* http://keith-wood.name/countdown.html
+ * Ukrainian initialisation for the jQuery countdown extension
+ * Written by Goloborodko M misha.gm@gmail.com (2009) */
+(function($) {
+       $.countdown.regional['uk'] = {
+               labels: ['Років', 'Місяців', 'Тижднів', 'Днів', 'Годин', 'Хвилин', 'Секунд'],
+               labels1: ['Рік', 'Місяць', 'Тиждень', 'День', 'Година', 'Хвилина', 'Секунда'],
+               compactLabels: ['r', 'm', 't', 'd'],
+               whichLabels: null,
+               timeSeparator: ':', isRTL: false};
+       $.countdown.setDefaults($.countdown.regional['uk']);
+})(jQuery);
index 27e2f4a..f9c58d3 100644 (file)
@@ -1,8 +1,8 @@
 /* http://keith-wood.name/countdown.html
    Countdown for jQuery v1.5.8.
    Written by Keith Wood (kbwood{at}iinet.com.au) January 2008.
 /* http://keith-wood.name/countdown.html
    Countdown for jQuery v1.5.8.
    Written by Keith Wood (kbwood{at}iinet.com.au) January 2008.
-   Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and 
-   MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses. 
+   Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and
+   MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses.
    Please attribute the author if you use it. */
 
 /* Display a countdown timer.
    Please attribute the author if you use it. */
 
 /* Display a countdown timer.
@@ -68,12 +68,12 @@ var S = 6; // Seconds
 $.extend(Countdown.prototype, {
        /* Class name added to elements to indicate already configured with countdown. */
        markerClassName: 'hasCountdown',
 $.extend(Countdown.prototype, {
        /* Class name added to elements to indicate already configured with countdown. */
        markerClassName: 'hasCountdown',
-       
+
        /* Shared timer for all countdowns. */
        _timer: setInterval(function() { $.countdown._updateTargets(); }, 980),
        /* List of currently active countdown targets. */
        _timerTargets: [],
        /* Shared timer for all countdowns. */
        _timer: setInterval(function() { $.countdown._updateTargets(); }, 980),
        /* List of currently active countdown targets. */
        _timerTargets: [],
-       
+
        /* Override the default settings for all instances of the countdown widget.
           @param  options  (object) the new settings to use as defaults */
        setDefaults: function(options) {
        /* Override the default settings for all instances of the countdown widget.
           @param  options  (object) the new settings to use as defaults */
        setDefaults: function(options) {
@@ -277,7 +277,7 @@ $.extend(Countdown.prototype, {
                        }
                }
        },
                        }
                }
        },
-       
+
        /* Calculate interal settings for an instance.
           @param  target  (element) the containing division
           @param  inst    (object) the current settings for this instance */
        /* Calculate interal settings for an instance.
           @param  target  (element) the containing division
           @param  inst    (object) the current settings for this instance */
@@ -362,7 +362,7 @@ $.extend(Countdown.prototype, {
                                inst[inst._since ? '_since' : '_until'] =
                                        this._determineTime(sign + inst._periods[0] + 'y' +
                                                sign + inst._periods[1] + 'o' + sign + inst._periods[2] + 'w' +
                                inst[inst._since ? '_since' : '_until'] =
                                        this._determineTime(sign + inst._periods[0] + 'y' +
                                                sign + inst._periods[1] + 'o' + sign + inst._periods[2] + 'w' +
-                                               sign + inst._periods[3] + 'd' + sign + inst._periods[4] + 'h' + 
+                                               sign + inst._periods[3] + 'd' + sign + inst._periods[4] + 'h' +
                                                sign + inst._periods[5] + 'm' + sign + inst._periods[6] + 's');
                                this._addTarget(target);
                        }
                                                sign + inst._periods[5] + 'm' + sign + inst._periods[6] + 's');
                                this._addTarget(target);
                        }
@@ -421,7 +421,7 @@ $.extend(Countdown.prototype, {
                                        case 'd': day += parseInt(matches[1], 10); break;
                                        case 'w': day += parseInt(matches[1], 10) * 7; break;
                                        case 'o':
                                        case 'd': day += parseInt(matches[1], 10); break;
                                        case 'w': day += parseInt(matches[1], 10) * 7; break;
                                        case 'o':
-                                               month += parseInt(matches[1], 10); 
+                                               month += parseInt(matches[1], 10);
                                                day = Math.min(day, $.countdown._getDaysInMonth(year, month));
                                                break;
                                        case 'y':
                                                day = Math.min(day, $.countdown._getDaysInMonth(year, month));
                                                break;
                                        case 'y':
@@ -508,8 +508,8 @@ $.extend(Countdown.prototype, {
                return (layout ? this._buildLayout(inst, show, layout, compact, significant, showSignificant) :
                        ((compact ? // Compact version
                        '<span class="countdown_row countdown_amount' +
                return (layout ? this._buildLayout(inst, show, layout, compact, significant, showSignificant) :
                        ((compact ? // Compact version
                        '<span class="countdown_row countdown_amount' +
-                       (inst._hold ? ' countdown_holding' : '') + '">' + 
-                       showCompact(Y) + showCompact(O) + showCompact(W) + showCompact(D) + 
+                       (inst._hold ? ' countdown_holding' : '') + '">' +
+                       showCompact(Y) + showCompact(O) + showCompact(W) + showCompact(D) +
                        (show[H] ? this._minDigits(inst._periods[H], 2) : '') +
                        (show[M] ? (show[H] ? timeSeparator : '') +
                        this._minDigits(inst._periods[M], 2) : '') +
                        (show[H] ? this._minDigits(inst._periods[H], 2) : '') +
                        (show[M] ? (show[H] ? timeSeparator : '') +
                        this._minDigits(inst._periods[M], 2) : '') +
@@ -616,7 +616,7 @@ $.extend(Countdown.prototype, {
                show[S] = (format.match('s') ? '?' : (format.match('S') ? '!' : null));
                return show;
        },
                show[S] = (format.match('s') ? '?' : (format.match('S') ? '!' : null));
                return show;
        },
-       
+
        /* Calculate the requested periods between now and the target time.
           @param  inst         (object) the current settings for this instance
           @param  show         (string[7]) flags indicating which periods are requested/required
        /* Calculate the requested periods between now and the target time.
           @param  inst         (object) the current settings for this instance
           @param  show         (string[7]) flags indicating which periods are requested/required
index 5ecba6e..52fce07 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * jQuery Event Delegation Plugin - jquery.eventdelegation.js
  * Fast flexible event handling
  *
  * jQuery Event Delegation Plugin - jquery.eventdelegation.js
  * Fast flexible event handling
  *
                'keydown',
                'keypress',
                'keyup'
                'keydown',
                'keypress',
                'keyup'
-               ], function(i, eventName) {     
+               ], function(i, eventName) {
                        allowed[eventName] = true;
        });
                        allowed[eventName] = true;
        });
-       
+
        $.fn.extend({
                delegate: function (event, selector, f) {
                        return $(this).each(function () {
        $.fn.extend({
                delegate: function (event, selector, f) {
                        return $(this).each(function () {
@@ -32,7 +32,7 @@
                                        $(this).bind(event, function (e) {
                                                var el = $(e.target),
                                                        result = false;
                                        $(this).bind(event, function (e) {
                                                var el = $(e.target),
                                                        result = false;
-                                               
+
                                                while (!$(el).is('body')) {
                                                        if ($(el).is(selector)) {
                                                                result = f.apply($(el)[0], [e]);
                                                while (!$(el).is('body')) {
                                                        if ($(el).is(selector)) {
                                                                result = f.apply($(el)[0], [e]);
@@ -40,7 +40,7 @@
                                                                        e.preventDefault();
                                                                return;
                                                        }
                                                                        e.preventDefault();
                                                                return;
                                                        }
-                                                       
+
                                                        el = $(el).parent();
                                                }
                                        });
                                                        el = $(el).parent();
                                                }
                                        });
index 659baa9..36af6b1 100644 (file)
@@ -13,7 +13,7 @@
 (function($) {
 
 /*
 (function($) {
 
 /*
-    Usage Note:  
+    Usage Note:
     -----------
     Do not use both ajaxSubmit and ajaxForm on the same form.  These
     functions are intended to be exclusive.  Use ajaxSubmit if you want
     -----------
     Do not use both ajaxSubmit and ajaxForm on the same form.  These
     functions are intended to be exclusive.  Use ajaxSubmit if you want
             target: '#output'
         });
     });
             target: '#output'
         });
     });
-        
+
     When using ajaxForm, the ajaxSubmit function will be invoked for you
     When using ajaxForm, the ajaxSubmit function will be invoked for you
-    at the appropriate time.  
+    at the appropriate time.
 */
 
 /**
 */
 
 /**
- * ajaxSubmit() provides a mechanism for immediately submitting 
+ * ajaxSubmit() provides a mechanism for immediately submitting
  * an HTML form using AJAX.
  */
 $.fn.ajaxSubmit = function(options) {
  * an HTML form using AJAX.
  */
 $.fn.ajaxSubmit = function(options) {
@@ -80,14 +80,14 @@ $.fn.ajaxSubmit = function(options) {
     if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
         log('ajaxSubmit: submit aborted via beforeSubmit callback');
         return this;
     if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
         log('ajaxSubmit: submit aborted via beforeSubmit callback');
         return this;
-    }    
+    }
 
     // fire vetoable 'validate' event
     this.trigger('form-submit-validate', [a, this, options, veto]);
     if (veto.veto) {
         log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
         return this;
 
     // fire vetoable 'validate' event
     this.trigger('form-submit-validate', [a, this, options, veto]);
     if (veto.veto) {
         log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
         return this;
-    }    
+    }
 
     var q = $.param(a);
 
 
     var q = $.param(a);
 
@@ -125,7 +125,7 @@ $.fn.ajaxSubmit = function(options) {
             found = true;
 
     // options.iframe allows user to force iframe mode
             found = true;
 
     // options.iframe allows user to force iframe mode
-   if (options.iframe || found) { 
+   if (options.iframe || found) {
        // hack to fix Safari hang (thanks to Tim Molendijk for this)
        // see:  http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
        if ($.browser.safari && options.closeKeepAlive)
        // hack to fix Safari hang (thanks to Tim Molendijk for this)
        // see:  http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
        if ($.browser.safari && options.closeKeepAlive)
@@ -144,19 +144,19 @@ $.fn.ajaxSubmit = function(options) {
     // private function for handling file uploads (hat tip to YAHOO!)
     function fileUpload() {
         var form = $form[0];
     // private function for handling file uploads (hat tip to YAHOO!)
     function fileUpload() {
         var form = $form[0];
-        
+
         if ($(':input[@name=submit]', form).length) {
             alert('Error: Form elements must not be named "submit".');
             return;
         }
         if ($(':input[@name=submit]', form).length) {
             alert('Error: Form elements must not be named "submit".');
             return;
         }
-        
+
         var opts = $.extend({}, $.ajaxSettings, options);
 
         var id = 'jqFormIO' + (new Date().getTime());
         var $io = $('<iframe id="' + id + '" name="' + id + '" />');
         var io = $io[0];
 
         var opts = $.extend({}, $.ajaxSettings, options);
 
         var id = 'jqFormIO' + (new Date().getTime());
         var $io = $('<iframe id="' + id + '" name="' + id + '" />');
         var io = $io[0];
 
-        if ($.browser.msie || $.browser.opera) 
+        if ($.browser.msie || $.browser.opera)
             io.src = 'javascript:false;document.write("");';
         $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
 
             io.src = 'javascript:false;document.write("");';
         $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
 
@@ -191,7 +191,7 @@ $.fn.ajaxSubmit = function(options) {
                 }
             }
         }
                 }
             }
         }
-        
+
         // take a breath so that pending repaints get some cpu time before the upload starts
         setTimeout(function() {
             // make sure form attrs are set
         // take a breath so that pending repaints get some cpu time before the upload starts
         setTimeout(function() {
             // make sure form attrs are set
@@ -216,7 +216,7 @@ $.fn.ajaxSubmit = function(options) {
                         extraInputs.push(
                             $('<input type="hidden" name="'+n+'" value="'+options.extraData[n]+'" />')
                                 .appendTo(form)[0]);
                         extraInputs.push(
                             $('<input type="hidden" name="'+n+'" value="'+options.extraData[n]+'" />')
                                 .appendTo(form)[0]);
-            
+
                 // add iframe to doc and submit the form
                 $io.appendTo('body');
                 io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false);
                 // add iframe to doc and submit the form
                 $io.appendTo('body');
                 io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false);
@@ -232,7 +232,7 @@ $.fn.ajaxSubmit = function(options) {
 
         function cb() {
             if (cbInvoked++) return;
 
         function cb() {
             if (cbInvoked++) return;
-            
+
             io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false);
 
             var operaHack = 0;
             io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false);
 
             var operaHack = 0;
@@ -243,7 +243,7 @@ $.fn.ajaxSubmit = function(options) {
                 var data, doc;
 
                 doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;
                 var data, doc;
 
                 doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;
-                
+
                 if (doc.body == null && !operaHack && $.browser.opera) {
                     // In Opera 9.2.x the iframe DOM is not always traversable when
                     // the onload callback fires so we give Opera 100ms to right itself
                 if (doc.body == null && !operaHack && $.browser.opera) {
                     // In Opera 9.2.x the iframe DOM is not always traversable when
                     // the onload callback fires so we give Opera 100ms to right itself
@@ -252,7 +252,7 @@ $.fn.ajaxSubmit = function(options) {
                     setTimeout(cb, 100);
                     return;
                 }
                     setTimeout(cb, 100);
                     return;
                 }
-                
+
                 xhr.responseText = doc.body ? doc.body.innerHTML : null;
                 xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
                 xhr.getResponseHeader = function(header){
                 xhr.responseText = doc.body ? doc.body.innerHTML : null;
                 xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
                 xhr.getResponseHeader = function(header){
@@ -317,7 +317,7 @@ $.fn.ajaxSubmit = function(options) {
  * The options argument for ajaxForm works exactly as it does for ajaxSubmit.  ajaxForm merely
  * passes the options argument along after properly binding events for submit elements and
  * the form itself.
  * The options argument for ajaxForm works exactly as it does for ajaxSubmit.  ajaxForm merely
  * passes the options argument along after properly binding events for submit elements and
  * the form itself.
- */ 
+ */
 $.fn.ajaxForm = function(options) {
     return this.ajaxFormUnbind().bind('submit.form-plugin',function() {
         $(this).ajaxSubmit(options);
 $.fn.ajaxForm = function(options) {
     return this.ajaxFormUnbind().bind('submit.form-plugin',function() {
         $(this).ajaxSubmit(options);
@@ -563,10 +563,10 @@ $.fn.resetForm = function() {
 /**
  * Enables or disables any matching elements.
  */
 /**
  * Enables or disables any matching elements.
  */
-$.fn.enable = function(b) { 
+$.fn.enable = function(b) {
     if (b == undefined) b = true;
     if (b == undefined) b = true;
-    return this.each(function() { 
-        this.disabled = !b 
+    return this.each(function() {
+        this.disabled = !b
     });
 };
 
     });
 };
 
@@ -576,7 +576,7 @@ $.fn.enable = function(b) {
  */
 $.fn.select = function(select) {
     if (select == undefined) select = true;
  */
 $.fn.select = function(select) {
     if (select == undefined) select = true;
-    return this.each(function() { 
+    return this.each(function() {
         var t = this.type;
         if (t == 'checkbox' || t == 'radio')
             this.checked = select;
         var t = this.type;
         if (t == 'checkbox' || t == 'radio')
             this.checked = select;
index 600cfe1..bbe39f0 100644 (file)
@@ -12,9 +12,9 @@
  * As of now (Aug. 16, 2006) the plugin has been written with the 1.0.1 release of jQuery (rev 249) which
  * is available from http://jquery.com/src/jquery-1.0.1.js
  *
  * As of now (Aug. 16, 2006) the plugin has been written with the 1.0.1 release of jQuery (rev 249) which
  * is available from http://jquery.com/src/jquery-1.0.1.js
  *
- * A note regarding rgb() syntax: I noticed that most browsers implement rgb syntax as either an integer 
- * (0-255) or percentage (0-100%) value for each field, that is, rgb(i/p,i/p,i/p); however, the W3C 
- * standard clearly defines it as "either three integer values or three percentage values" [http://www.w3.org/TR/CSS21/syndata.html] 
+ * A note regarding rgb() syntax: I noticed that most browsers implement rgb syntax as either an integer
+ * (0-255) or percentage (0-100%) value for each field, that is, rgb(i/p,i/p,i/p); however, the W3C
+ * standard clearly defines it as "either three integer values or three percentage values" [http://www.w3.org/TR/CSS21/syndata.html]
  * which I choose to follow despite the error redundancy of the typical behaviour browsers employ.
  *
  * Changelog:
  * which I choose to follow despite the error redundancy of the typical behaviour browsers employ.
  *
  * Changelog:
@@ -42,7 +42,7 @@
  *        - Fixed bug where multiple events on the same element would speed each subsequent event
  *    0.1:
  *        - Initial Release
  *        - Fixed bug where multiple events on the same element would speed each subsequent event
  *    0.1:
  *        - Initial Release
- * 
+ *
  * @author          Blair Mitchelmore (blair@offput.ca)
  * @version         0.5
  */
  * @author          Blair Mitchelmore (blair@offput.ca)
  * @version         0.5
  */
@@ -73,7 +73,7 @@ jQuery.fn.highlightFade = function(settings) {
 };
 
 jQuery.highlightFade = function(e,a,o,t) {
 };
 
 jQuery.highlightFade = function(e,a,o,t) {
-       e.highlighting[a].timer = window.setInterval(function() { 
+       e.highlighting[a].timer = window.setInterval(function() {
                var newR = t(e.highlighting[a].start[0],e.highlighting[a].end[0],e.highlighting[a].steps,e.highlighting[a].currentStep);
                var newG = t(e.highlighting[a].start[1],e.highlighting[a].end[1],e.highlighting[a].steps,e.highlighting[a].currentStep);
                var newB = t(e.highlighting[a].start[2],e.highlighting[a].end[2],e.highlighting[a].steps,e.highlighting[a].currentStep);
                var newR = t(e.highlighting[a].start[0],e.highlighting[a].end[0],e.highlighting[a].steps,e.highlighting[a].currentStep);
                var newG = t(e.highlighting[a].start[1],e.highlighting[a].end[1],e.highlighting[a].steps,e.highlighting[a].currentStep);
                var newB = t(e.highlighting[a].start[2],e.highlighting[a].end[2],e.highlighting[a].steps,e.highlighting[a].currentStep);
@@ -119,7 +119,7 @@ jQuery.highlightFade.getBaseValue = function(e,a,b) {
        t = a = a || jQuery.highlightFade.defaults['attr'];
        do {
                s = jQuery(e).css(t || 'backgroundColor');
        t = a = a || jQuery.highlightFade.defaults['attr'];
        do {
                s = jQuery(e).css(t || 'backgroundColor');
-               if ((s  != '' && s != 'transparent') || (e.tagName.toLowerCase() == "body") || (!b && e.highlighting && e.highlighting[a] && e.highlighting[a].end)) break; 
+               if ((s  != '' && s != 'transparent') || (e.tagName.toLowerCase() == "body") || (!b && e.highlighting && e.highlighting[a] && e.highlighting[a].end)) break;
                t = false;
        } while (e = e.parentNode);
        if (!b && e.highlighting && e.highlighting[a] && e.highlighting[a].end) s = e.highlighting[a].end;
                t = false;
        } while (e = e.parentNode);
        if (!b && e.highlighting && e.highlighting[a] && e.highlighting[a].end) s = e.highlighting[a].end;
index 966336a..248bb19 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (c) 2007 Brice Burgess <bhb@iceburg.net>, http://www.iceburg.net
  * Licensed under the MIT License:
  * http://www.opensource.org/licenses/mit-license.php
  * Copyright (c) 2007 Brice Burgess <bhb@iceburg.net>, http://www.iceburg.net
  * Licensed under the MIT License:
  * http://www.opensource.org/licenses/mit-license.php
- * 
+ *
  * $Version: 2007.??.?? +r12 beta
  * Requires: jQuery 1.1.3+
  */
  * $Version: 2007.??.?? +r12 beta
  * Requires: jQuery 1.1.3+
  */
  * notices, modal windows, and image containers. An expando ("_jqm") containing
  * the UUID or "serial" of the modal is added to each element. This expando helps
  * reference the modal's settings in the jqModal Hash Object (jQuery.jqm.hash)
  * notices, modal windows, and image containers. An expando ("_jqm") containing
  * the UUID or "serial" of the modal is added to each element. This expando helps
  * reference the modal's settings in the jqModal Hash Object (jQuery.jqm.hash)
- * 
+ *
  * Accepts a parameter object with the following modal settings;
  * Accepts a parameter object with the following modal settings;
- * 
- * (Integer) zIndex - Desired z-Index of the modal. This setting does not override (has no effect on) preexisting z-Index styling (set via CSS or inline style).  
- * (Integer) overlay - [0-100] Translucency percentage (opacity) of the body covering overlay. Set to 0 for NO overlay, and up to 100 for a 100% opaque overlay.  
+ *
+ * (Integer) zIndex - Desired z-Index of the modal. This setting does not override (has no effect on) preexisting z-Index styling (set via CSS or inline style).
+ * (Integer) overlay - [0-100] Translucency percentage (opacity) of the body covering overlay. Set to 0 for NO overlay, and up to 100 for a 100% opaque overlay.
  * (String) overlayClass - This class is applied to the body covering overlay. Allows CSS control of the overlay look (tint, background image, etc.).
  * (String) closeClass - A close trigger is added to all elements matching this class within the modal.
  * (Mixed) trigger - An open trigger is added to all matching elements within the DOM. Trigger can be a selector String, a jQuery collection of elements, a DOM element, or a False boolean.
  * (String) overlayClass - This class is applied to the body covering overlay. Allows CSS control of the overlay look (tint, background image, etc.).
  * (String) closeClass - A close trigger is added to all elements matching this class within the modal.
  * (Mixed) trigger - An open trigger is added to all matching elements within the DOM. Trigger can be a selector String, a jQuery collection of elements, a DOM element, or a False boolean.
@@ -59,7 +59,7 @@ onLoad: false
 //    *AND*...
 return this.each(function(){if(this._jqm)return;s++;this._jqm=s;
 
 //    *AND*...
 return this.each(function(){if(this._jqm)return;s++;this._jqm=s;
 
-// ... Add this element's serial to the jqModal Hash Object 
+// ... Add this element's serial to the jqModal Hash Object
 //  Hash is globally accessible via jQuery.jqm.hash. It consists of;
 //   c: {obj} config/options
 //   a: {bool} active state (true: active/visible, false: inactive/hidden)
 //  Hash is globally accessible via jQuery.jqm.hash. It consists of;
 //   c: {obj} config/options
 //   a: {bool} active state (true: active/visible, false: inactive/hidden)
@@ -74,7 +74,7 @@ o.trigger&&$(this).jqmAddTrigger(o.trigger);
 });};
 
 // Adds behavior to triggering elements via the hide-show (HS) function.
 });};
 
 // Adds behavior to triggering elements via the hide-show (HS) function.
-// 
+//
 $.fn.jqmAddClose=function(e){return HS(this,e,'jqmHide');};
 $.fn.jqmAddTrigger=function(e){return HS(this,e,'jqmShow');};
 
 $.fn.jqmAddClose=function(e){return HS(this,e,'jqmHide');};
 $.fn.jqmAddTrigger=function(e){return HS(this,e,'jqmShow');};
 
@@ -98,23 +98,23 @@ hash:{},
 // mark this modal as active (h.a === true)
 // set the triggering object (h.t) and the modal's z-Index.
 open:function(s,t){var h=H[s],c=h.c,cc='.'+c.closeClass,z=/^\d+$/.test(h.w.css('z-index'))&&h.w.css('z-index')||c.zIndex,o=$('<div></div>').css({height:'100%',width:'100%',position:'fixed',left:0,top:0,'z-index':z-1,opacity:c.overlay/100});h.t=t;h.a=true;h.w.css('z-index',z);
 // mark this modal as active (h.a === true)
 // set the triggering object (h.t) and the modal's z-Index.
 open:function(s,t){var h=H[s],c=h.c,cc='.'+c.closeClass,z=/^\d+$/.test(h.w.css('z-index'))&&h.w.css('z-index')||c.zIndex,o=$('<div></div>').css({height:'100%',width:'100%',position:'fixed',left:0,top:0,'z-index':z-1,opacity:c.overlay/100});h.t=t;h.a=true;h.w.css('z-index',z);
+
  // IF the modal argument was passed as true;
  //    Bind the Keep Focus Function if no other Modals are open (!A[0]),
  //    Add this modal to the opened modals stack (A) for nested modal support,
  //    and Mark overlay to show wait cursor when mouse hovers over it.
  if(c.modal) {!A[0]&&F('bind');A.push(s);o.css('cursor','wait');}
  // IF the modal argument was passed as true;
  //    Bind the Keep Focus Function if no other Modals are open (!A[0]),
  //    Add this modal to the opened modals stack (A) for nested modal support,
  //    and Mark overlay to show wait cursor when mouse hovers over it.
  if(c.modal) {!A[0]&&F('bind');A.push(s);o.css('cursor','wait');}
+
  // ELSE IF an overlay was requested (translucency set greater than 0);
  //    Attach a Close event to overlay to hide modal when overlay is clicked.
  else if(c.overlay > 0)h.w.jqmAddClose(o);
  // ELSE IF an overlay was requested (translucency set greater than 0);
  //    Attach a Close event to overlay to hide modal when overlay is clicked.
  else if(c.overlay > 0)h.w.jqmAddClose(o);
+
  // ELSE disable the overlay
  else o=false;
 
  // Add the Overlay to BODY if not disabled.
  h.o=(o)?o.addClass(c.overlayClass).prependTo('body'):false;
  // ELSE disable the overlay
  else o=false;
 
  // Add the Overlay to BODY if not disabled.
  h.o=(o)?o.addClass(c.overlayClass).prependTo('body'):false;
+
  // IF IE6;
  //  Set the Overlay to 100% height/width, and fix-position it via JS workaround
  if(ie6&&$('html,body').css({height:'100%',width:'100%'})&&o){o=o.css({position:'absolute'})[0];for(var y in {Top:1,Left:1})o.style.setExpression(y.toLowerCase(),"(_=(document.documentElement.scroll"+y+" || document.body.scroll"+y+"))+'px'");}
  // IF IE6;
  //  Set the Overlay to 100% height/width, and fix-position it via JS workaround
  if(ie6&&$('html,body').css({height:'100%',width:'100%'})&&o){o=o.css({position:'absolute'})[0];for(var y in {Top:1,Left:1})o.style.setExpression(y.toLowerCase(),"(_=(document.documentElement.scroll"+y+" || document.body.scroll"+y+"))+'px'");}
@@ -123,13 +123,13 @@ open:function(s,t){var h=H[s],c=h.c,cc='.'+c.closeClass,z=/^\d+$/.test(h.w.css('
  //  determine the target element {JQ} to recieve content (r),
  //  determine the URL {STR} to load content from (u)
  if(c.ajax) {var r=c.target||h.w,u=c.ajax,r=(typeof r == 'string')?$(r,h.w):$(r),u=(u.substr(0,1) == '@')?$(t).attr(u.substring(1)):u;
  //  determine the target element {JQ} to recieve content (r),
  //  determine the URL {STR} to load content from (u)
  if(c.ajax) {var r=c.target||h.w,u=c.ajax,r=(typeof r == 'string')?$(r,h.w):$(r),u=(u.substr(0,1) == '@')?$(t).attr(u.substring(1)):u;
+
   // Load the Content (and once loaded);
    // Fire the onLoad callback (if exists),
    // Attach closing events to elements inside the modal that match the closingClass,
    // and Execute the jqModal default Open Callback
   r.load(u,function(){c.onLoad&&c.onLoad.call(this,h);cc&&h.w.jqmAddClose($(cc,h.w));O(h);});}
   // Load the Content (and once loaded);
    // Fire the onLoad callback (if exists),
    // Attach closing events to elements inside the modal that match the closingClass,
    // and Execute the jqModal default Open Callback
   r.load(u,function(){c.onLoad&&c.onLoad.call(this,h);cc&&h.w.jqmAddClose($(cc,h.w));O(h);});}
+
  // ELSE the modal content is NOT to be loaded via ajax;
  //  Attach closing events to elements inside the modal that match the closingClass
  else cc&&h.w.jqmAddClose($(cc,h.w));
  // ELSE the modal content is NOT to be loaded via ajax;
  //  Attach closing events to elements inside the modal that match the closingClass
  else cc&&h.w.jqmAddClose($(cc,h.w));
@@ -137,13 +137,13 @@ open:function(s,t){var h=H[s],c=h.c,cc='.'+c.closeClass,z=/^\d+$/.test(h.w.css('
  // IF toTop was passed and an overlay exists;
  //  Remember the DOM posistion of the modal by inserting a tagged (matching serial) <SPAN> before the modal
  //  Move the Modal from its current position to a first child of the body tag (after the overlay)
  // IF toTop was passed and an overlay exists;
  //  Remember the DOM posistion of the modal by inserting a tagged (matching serial) <SPAN> before the modal
  //  Move the Modal from its current position to a first child of the body tag (after the overlay)
- c.toTop&&h.o&&h.w.before('<span id="jqmP'+h.w[0]._jqm+'"></span>').insertAfter(h.o);  
+ c.toTop&&h.o&&h.w.before('<span id="jqmP'+h.w[0]._jqm+'"></span>').insertAfter(h.o);
+
  // Execute user defined onShow callback, or else show (make visible) the modal.
  // Execute the jqModal default Open Callback.
  // Return false to prevent trigger click from being followed.
  (c.onShow)?c.onShow(h):h.w.show();O(h);return false;
  // Execute user defined onShow callback, or else show (make visible) the modal.
  // Execute the jqModal default Open Callback.
  // Return false to prevent trigger click from being followed.
  (c.onShow)?c.onShow(h):h.w.show();O(h);return false;
+
 },
 
 // Function is executed by $.jqmHide to hide a modal
 },
 
 // Function is executed by $.jqmHide to hide a modal
@@ -152,11 +152,11 @@ close:function(s){var h=H[s];h.a=false;
  // If modal, remove from modal stack.
    // If no modals in modal stack, unbind the Keep Focus Function
  if(h.c.modal){A.pop();!A[0]&&F('unbind');}
  // If modal, remove from modal stack.
    // If no modals in modal stack, unbind the Keep Focus Function
  if(h.c.modal){A.pop();!A[0]&&F('unbind');}
+
  // IF toTop was passed and an overlay exists;
  //  Move modal back to its previous ("remembered") position.
  h.c.toTop&&h.o&&$('#jqmP'+h.w[0]._jqm).after(h.w).remove();
  // IF toTop was passed and an overlay exists;
  //  Move modal back to its previous ("remembered") position.
  h.c.toTop&&h.o&&$('#jqmP'+h.w[0]._jqm).after(h.w).remove();
+
  // Execute user defined onHide callback, or else hide (make invisible) the modal and remove the overlay.
  if(h.c.onHide)h.c.onHide(h);else{h.w.hide()&&h.o&&h.o.remove()}return false;
 }};
  // Execute user defined onHide callback, or else hide (make invisible) the modal and remove the overlay.
  if(h.c.onHide)h.c.onHide(h);else{h.w.hide()&&h.o&&h.o.remove()}return false;
 }};
@@ -191,10 +191,10 @@ F=function(t){$()[t]("keypress",x)[t]("keydown",x)[t]("mousedown",x);},
 //      ELSE if so (r===false); follow event (return true [!false])
 x=function(e){var h=H[A[A.length-1]],r=(!$(e.target).parents('.jqmID'+h.s)[0]);r&&f(h);return !r;},
 
 //      ELSE if so (r===false); follow event (return true [!false])
 x=function(e){var h=H[A[A.length-1]],r=(!$(e.target).parents('.jqmID'+h.s)[0]);r&&f(h);return !r;},
 
-// hide-show function; assigns click events to trigger elements that 
+// hide-show function; assigns click events to trigger elements that
 //   hide, show, or hide AND show modals.
 
 //   hide, show, or hide AND show modals.
 
-// Expandos (jqmShow and/or jqmHide) are added to all trigger elements. 
+// Expandos (jqmShow and/or jqmHide) are added to all trigger elements.
 // These Expandos hold an array of modal serials {INT} to show or hide.
 
 //  w: {DOM Element} The modal element (window/dialog/notice/etc. container)
 // These Expandos hold an array of modal serials {INT} to show or hide.
 
 //  w: {DOM Element} The modal element (window/dialog/notice/etc. container)
@@ -207,7 +207,7 @@ HS=function(w,e,y){var s=[];w.each(function(){s.push(this._jqm)});
 // for each triggering element attach the jqmHide or jqmShow expando (y)
 //  or else expand the expando with the current serial array
  $(e).each(function(){if(this[y])$.extend(this[y],s);
 // for each triggering element attach the jqmHide or jqmShow expando (y)
 //  or else expand the expando with the current serial array
  $(e).each(function(){if(this[y])$.extend(this[y],s);
+
  // Assign a click event on the trigger element which examines the element's
  //  jqmHide/Show expandos and attempts to execute $.jqmHide/Show on matching modals
  else{this[y]=s;$(this).click(function(){for(var i in {jqmShow:1,jqmHide:1})for(var s in this[i])if(H[this[i][s]])H[this[i][s]].w[i](this);return false;});}});return w;};
  // Assign a click event on the trigger element which examines the element's
  //  jqmHide/Show expandos and attempts to execute $.jqmHide/Show on matching modals
  else{this[y]=s;$(this).click(function(){for(var i in {jqmShow:1,jqmHide:1})for(var s in this[i])if(H[this[i][s]])H[this[i][s]].w[i](this);return false;});}});return w;};
index 13196b2..49b76a3 100644 (file)
@@ -12,7 +12,7 @@
  *
  * You can also pass an options object with the following keys:
  *   text
  *
  * You can also pass an options object with the following keys:
  *   text
- *     "title" to get the in-field label from the field's title attribute 
+ *     "title" to get the in-field label from the field's title attribute
  *      (this is the default)
  *     "label" to get the in-field label from the inner text of the field's label
  *      (note that the label must be attached to the field with for="fieldid")
  *      (this is the default)
  *     "label" to get the in-field label from the inner text of the field's label
  *      (note that the label must be attached to the field with for="fieldid")
@@ -22,7 +22,7 @@
  *   labelledClass
  *     a class that will be applied to the input field when it contains the
  *      label and removed when it contains user input. Defaults to blank.
  *   labelledClass
  *     a class that will be applied to the input field when it contains the
  *      label and removed when it contains user input. Defaults to blank.
- *  
+ *
  */
 jQuery.fn.labelify = function(settings) {
   settings = jQuery.extend({
  */
 jQuery.fn.labelify = function(settings) {
   settings = jQuery.extend({
@@ -51,7 +51,7 @@ jQuery.fn.labelify = function(settings) {
     if (!lookupval) { return; }
 
     // need to strip newlines because the browser strips them
     if (!lookupval) { return; }
 
     // need to strip newlines because the browser strips them
-    // if you set textbox.value to a string containing them    
+    // if you set textbox.value to a string containing them
     $(this).data("label",lookup(this).replace(/\n/g,''));
     $(this).focus(function() {
       if (this.value === $(this).data("label")) {
     $(this).data("label",lookup(this).replace(/\n/g,''));
     $(this).focus(function() {
       if (this.value === $(this).data("label")) {
@@ -64,7 +64,7 @@ jQuery.fn.labelify = function(settings) {
         $(this).addClass(settings.labelledClass);
       }
     });
         $(this).addClass(settings.labelledClass);
       }
     });
-    
+
     var removeValuesOnExit = function() {
       jQuery_labellified_elements.each(function(){
         if (this.value === $(this).data("label")) {
     var removeValuesOnExit = function() {
       jQuery_labellified_elements.each(function(){
         if (this.value === $(this).data("label")) {
@@ -73,10 +73,10 @@ jQuery.fn.labelify = function(settings) {
         }
       })
     };
         }
       })
     };
-    
+
     $(this).parents("form").submit(removeValuesOnExit);
     $(window).unload(removeValuesOnExit);
     $(this).parents("form").submit(removeValuesOnExit);
     $(window).unload(removeValuesOnExit);
-    
+
     if (this.value !== this.defaultValue) {
       // user already started typing; don't overwrite their work!
       return;
     if (this.value !== this.defaultValue) {
       // user already started typing; don't overwrite their work!
       return;
index 7f42489..c403ab9 100644 (file)
-/**\r
- * jQuery.ScrollTo\r
- * Copyright (c) 2007-2008 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com\r
- * Dual licensed under MIT and GPL.\r
- * Date: 9/11/2008\r
- *\r
- * @projectDescription Easy element scrolling using jQuery.\r
- * http://flesler.blogspot.com/2007/10/jqueryscrollto.html\r
- * Tested with jQuery 1.2.6. On FF 2/3, IE 6/7, Opera 9.2/5 and Safari 3. on Windows.\r
- *\r
- * @author Ariel Flesler\r
- * @version 1.4\r
- *\r
- * @id jQuery.scrollTo\r
- * @id jQuery.fn.scrollTo\r
- * @param {String, Number, DOMElement, jQuery, Object} target Where to scroll the matched elements.\r
- *       The different options for target are:\r
- *             - A number position (will be applied to all axes).\r
- *             - A string position ('44', '100px', '+=90', etc ) will be applied to all axes\r
- *             - A jQuery/DOM element ( logically, child of the element to scroll )\r
- *             - A string selector, that will be relative to the element to scroll ( 'li:eq(2)', etc )\r
- *             - A hash { top:x, left:y }, x and y can be any kind of number/string like above.\r
- * @param {Number} duration The OVERALL length of the animation, this argument can be the settings object instead.\r
- * @param {Object,Function} settings Optional set of settings or the onAfter callback.\r
- *      @option {String} axis Which axis must be scrolled, use 'x', 'y', 'xy' or 'yx'.\r
- *      @option {Number} duration The OVERALL length of the animation.\r
- *      @option {String} easing The easing method for the animation.\r
- *      @option {Boolean} margin If true, the margin of the target element will be deducted from the final position.\r
- *      @option {Object, Number} offset Add/deduct from the end position. One number for both axes or { top:x, left:y }.\r
- *      @option {Object, Number} over Add/deduct the height/width multiplied by 'over', can be { top:x, left:y } when using both axes.\r
- *      @option {Boolean} queue If true, and both axis are given, the 2nd axis will only be animated after the first one ends.\r
- *      @option {Function} onAfter Function to be called after the scrolling ends. \r
- *      @option {Function} onAfterFirst If queuing is activated, this function will be called after the first scrolling ends.\r
- * @return {jQuery} Returns the same jQuery object, for chaining.\r
- *\r
- * @desc Scroll to a fixed position\r
- * @example $('div').scrollTo( 340 );\r
- *\r
- * @desc Scroll relatively to the actual position\r
- * @example $('div').scrollTo( '+=340px', { axis:'y' } );\r
- *\r
- * @dec Scroll using a selector (relative to the scrolled element)\r
- * @example $('div').scrollTo( 'p.paragraph:eq(2)', 500, { easing:'swing', queue:true, axis:'xy' } );\r
- *\r
- * @ Scroll to a DOM element (same for jQuery object)\r
- * @example var second_child = document.getElementById('container').firstChild.nextSibling;\r
- *                     $('#container').scrollTo( second_child, { duration:500, axis:'x', onAfter:function(){\r
- *                             alert('scrolled!!');                                                                                                                               \r
- *                     }});\r
- *\r
- * @desc Scroll on both axes, to different values\r
- * @example $('div').scrollTo( { top: 300, left:'+=200' }, { axis:'xy', offset:-20 } );\r
- */\r
-;(function( $ ){\r
-       \r
-       var $scrollTo = $.scrollTo = function( target, duration, settings ){\r
-               $(window).scrollTo( target, duration, settings );\r
-       };\r
-\r
-       $scrollTo.defaults = {\r
-               axis:'y',\r
-               duration:1\r
-       };\r
-\r
-       // Returns the element that needs to be animated to scroll the window.\r
-       // Kept for backwards compatibility (specially for localScroll & serialScroll)\r
-       $scrollTo.window = function( scope ){\r
-               return $(window).scrollable();\r
-       };\r
-\r
-       // Hack, hack, hack... stay away!\r
-       // Returns the real elements to scroll (supports window/iframes, documents and regular nodes)\r
-       $.fn.scrollable = function(){\r
-               return this.map(function(){\r
-                       // Just store it, we might need it\r
-                       var win = this.parentWindow || this.defaultView,\r
-                               // If it's a document, get its iframe or the window if it's THE document\r
-                               elem = this.nodeName == '#document' ? win.frameElement || win : this,\r
-                               // Get the corresponding document\r
-                               doc = elem.contentDocument || (elem.contentWindow || elem).document,\r
-                               isWin = elem.setInterval;\r
-\r
-                       return elem.nodeName == 'IFRAME' || isWin && $.browser.safari ? doc.body\r
-                               : isWin ? doc.documentElement\r
-                               : this;\r
-               });\r
-       };\r
-\r
-       $.fn.scrollTo = function( target, duration, settings ){\r
-               if( typeof duration == 'object' ){\r
-                       settings = duration;\r
-                       duration = 0;\r
-               }\r
-               if( typeof settings == 'function' )\r
-                       settings = { onAfter:settings };\r
-                       \r
-               settings = $.extend( {}, $scrollTo.defaults, settings );\r
-               // Speed is still recognized for backwards compatibility\r
-               duration = duration || settings.speed || settings.duration;\r
-               // Make sure the settings are given right\r
-               settings.queue = settings.queue && settings.axis.length > 1;\r
-               \r
-               if( settings.queue )\r
-                       // Let's keep the overall duration\r
-                       duration /= 2;\r
-               settings.offset = both( settings.offset );\r
-               settings.over = both( settings.over );\r
-\r
-               return this.scrollable().each(function(){\r
-                       var elem = this,\r
-                               $elem = $(elem),\r
-                               targ = target, toff, attr = {},\r
-                               win = $elem.is('html,body');\r
-\r
-                       switch( typeof targ ){\r
-                               // A number will pass the regex\r
-                               case 'number':\r
-                               case 'string':\r
-                                       if( /^([+-]=)?\d+(px)?$/.test(targ) ){\r
-                                               targ = both( targ );\r
-                                               // We are done\r
-                                               break;\r
-                                       }\r
-                                       // Relative selector, no break!\r
-                                       targ = $(targ,this);\r
-                               case 'object':\r
-                                       // DOMElement / jQuery\r
-                                       if( targ.is || targ.style )\r
-                                               // Get the real position of the target \r
-                                               toff = (targ = $(targ)).offset();\r
-                       }\r
-                       $.each( settings.axis.split(''), function( i, axis ){\r
-                               var Pos = axis == 'x' ? 'Left' : 'Top',\r
-                                       pos = Pos.toLowerCase(),\r
-                                       key = 'scroll' + Pos,\r
-                                       old = elem[key],\r
-                                       Dim = axis == 'x' ? 'Width' : 'Height',\r
-                                       dim = Dim.toLowerCase();\r
-\r
-                               if( toff ){// jQuery / DOMElement\r
-                                       attr[key] = toff[pos] + ( win ? 0 : old - $elem.offset()[pos] );\r
-\r
-                                       // If it's a dom element, reduce the margin\r
-                                       if( settings.margin ){\r
-                                               attr[key] -= parseInt(targ.css('margin'+Pos)) || 0;\r
-                                               attr[key] -= parseInt(targ.css('border'+Pos+'Width')) || 0;\r
-                                       }\r
-                                       \r
-                                       attr[key] += settings.offset[pos] || 0;\r
-                                       \r
-                                       if( settings.over[pos] )\r
-                                               // Scroll to a fraction of its width/height\r
-                                               attr[key] += targ[dim]() * settings.over[pos];\r
-                               }else\r
-                                       attr[key] = targ[pos];\r
-\r
-                               // Number or 'number'\r
-                               if( /^\d+$/.test(attr[key]) )\r
-                                       // Check the limits\r
-                                       attr[key] = attr[key] <= 0 ? 0 : Math.min( attr[key], max(Dim) );\r
-\r
-                               // Queueing axes\r
-                               if( !i && settings.queue ){\r
-                                       // Don't waste time animating, if there's no need.\r
-                                       if( old != attr[key] )\r
-                                               // Intermediate animation\r
-                                               animate( settings.onAfterFirst );\r
-                                       // Don't animate this axis again in the next iteration.\r
-                                       delete attr[key];\r
-                               }\r
-                       });                     \r
-                       animate( settings.onAfter );                    \r
-\r
-                       function animate( callback ){\r
-                               $elem.animate( attr, duration, settings.easing, callback && function(){\r
-                                       callback.call(this, target, settings);\r
-                               });\r
-                       };\r
-                       function max( Dim ){\r
-                               var attr ='scroll'+Dim,\r
-                                       doc = elem.ownerDocument;\r
-                               \r
-                               return win\r
-                                               ? Math.max( doc.documentElement[attr], doc.body[attr]  )\r
-                                               : elem[attr];\r
-                       };\r
-               }).end();\r
-       };\r
-\r
-       function both( val ){\r
-               return typeof val == 'object' ? val : { top:val, left:val };\r
-       };\r
-\r
+/**
+ * jQuery.ScrollTo
+ * Copyright (c) 2007-2008 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
+ * Dual licensed under MIT and GPL.
+ * Date: 9/11/2008
+ *
+ * @projectDescription Easy element scrolling using jQuery.
+ * http://flesler.blogspot.com/2007/10/jqueryscrollto.html
+ * Tested with jQuery 1.2.6. On FF 2/3, IE 6/7, Opera 9.2/5 and Safari 3. on Windows.
+ *
+ * @author Ariel Flesler
+ * @version 1.4
+ *
+ * @id jQuery.scrollTo
+ * @id jQuery.fn.scrollTo
+ * @param {String, Number, DOMElement, jQuery, Object} target Where to scroll the matched elements.
+ *       The different options for target are:
+ *             - A number position (will be applied to all axes).
+ *             - A string position ('44', '100px', '+=90', etc ) will be applied to all axes
+ *             - A jQuery/DOM element ( logically, child of the element to scroll )
+ *             - A string selector, that will be relative to the element to scroll ( 'li:eq(2)', etc )
+ *             - A hash { top:x, left:y }, x and y can be any kind of number/string like above.
+ * @param {Number} duration The OVERALL length of the animation, this argument can be the settings object instead.
+ * @param {Object,Function} settings Optional set of settings or the onAfter callback.
+ *      @option {String} axis Which axis must be scrolled, use 'x', 'y', 'xy' or 'yx'.
+ *      @option {Number} duration The OVERALL length of the animation.
+ *      @option {String} easing The easing method for the animation.
+ *      @option {Boolean} margin If true, the margin of the target element will be deducted from the final position.
+ *      @option {Object, Number} offset Add/deduct from the end position. One number for both axes or { top:x, left:y }.
+ *      @option {Object, Number} over Add/deduct the height/width multiplied by 'over', can be { top:x, left:y } when using both axes.
+ *      @option {Boolean} queue If true, and both axis are given, the 2nd axis will only be animated after the first one ends.
+ *      @option {Function} onAfter Function to be called after the scrolling ends.
+ *      @option {Function} onAfterFirst If queuing is activated, this function will be called after the first scrolling ends.
+ * @return {jQuery} Returns the same jQuery object, for chaining.
+ *
+ * @desc Scroll to a fixed position
+ * @example $('div').scrollTo( 340 );
+ *
+ * @desc Scroll relatively to the actual position
+ * @example $('div').scrollTo( '+=340px', { axis:'y' } );
+ *
+ * @dec Scroll using a selector (relative to the scrolled element)
+ * @example $('div').scrollTo( 'p.paragraph:eq(2)', 500, { easing:'swing', queue:true, axis:'xy' } );
+ *
+ * @ Scroll to a DOM element (same for jQuery object)
+ * @example var second_child = document.getElementById('container').firstChild.nextSibling;
+ *                     $('#container').scrollTo( second_child, { duration:500, axis:'x', onAfter:function(){
+ *                             alert('scrolled!!');
+ *                     }});
+ *
+ * @desc Scroll on both axes, to different values
+ * @example $('div').scrollTo( { top: 300, left:'+=200' }, { axis:'xy', offset:-20 } );
+ */
+;(function( $ ){
+
+       var $scrollTo = $.scrollTo = function( target, duration, settings ){
+               $(window).scrollTo( target, duration, settings );
+       };
+
+       $scrollTo.defaults = {
+               axis:'y',
+               duration:1
+       };
+
+       // Returns the element that needs to be animated to scroll the window.
+       // Kept for backwards compatibility (specially for localScroll & serialScroll)
+       $scrollTo.window = function( scope ){
+               return $(window).scrollable();
+       };
+
+       // Hack, hack, hack... stay away!
+       // Returns the real elements to scroll (supports window/iframes, documents and regular nodes)
+       $.fn.scrollable = function(){
+               return this.map(function(){
+                       // Just store it, we might need it
+                       var win = this.parentWindow || this.defaultView,
+                               // If it's a document, get its iframe or the window if it's THE document
+                               elem = this.nodeName == '#document' ? win.frameElement || win : this,
+                               // Get the corresponding document
+                               doc = elem.contentDocument || (elem.contentWindow || elem).document,
+                               isWin = elem.setInterval;
+
+                       return elem.nodeName == 'IFRAME' || isWin && $.browser.safari ? doc.body
+                               : isWin ? doc.documentElement
+                               : this;
+               });
+       };
+
+       $.fn.scrollTo = function( target, duration, settings ){
+               if( typeof duration == 'object' ){
+                       settings = duration;
+                       duration = 0;
+               }
+               if( typeof settings == 'function' )
+                       settings = { onAfter:settings };
+
+               settings = $.extend( {}, $scrollTo.defaults, settings );
+               // Speed is still recognized for backwards compatibility
+               duration = duration || settings.speed || settings.duration;
+               // Make sure the settings are given right
+               settings.queue = settings.queue && settings.axis.length > 1;
+
+               if( settings.queue )
+                       // Let's keep the overall duration
+                       duration /= 2;
+               settings.offset = both( settings.offset );
+               settings.over = both( settings.over );
+
+               return this.scrollable().each(function(){
+                       var elem = this,
+                               $elem = $(elem),
+                               targ = target, toff, attr = {},
+                               win = $elem.is('html,body');
+
+                       switch( typeof targ ){
+                               // A number will pass the regex
+                               case 'number':
+                               case 'string':
+                                       if( /^([+-]=)?\d+(px)?$/.test(targ) ){
+                                               targ = both( targ );
+                                               // We are done
+                                               break;
+                                       }
+                                       // Relative selector, no break!
+                                       targ = $(targ,this);
+                               case 'object':
+                                       // DOMElement / jQuery
+                                       if( targ.is || targ.style )
+                                               // Get the real position of the target
+                                               toff = (targ = $(targ)).offset();
+                       }
+                       $.each( settings.axis.split(''), function( i, axis ){
+                               var Pos = axis == 'x' ? 'Left' : 'Top',
+                                       pos = Pos.toLowerCase(),
+                                       key = 'scroll' + Pos,
+                                       old = elem[key],
+                                       Dim = axis == 'x' ? 'Width' : 'Height',
+                                       dim = Dim.toLowerCase();
+
+                               if( toff ){// jQuery / DOMElement
+                                       attr[key] = toff[pos] + ( win ? 0 : old - $elem.offset()[pos] );
+
+                                       // If it's a dom element, reduce the margin
+                                       if( settings.margin ){
+                                               attr[key] -= parseInt(targ.css('margin'+Pos)) || 0;
+                                               attr[key] -= parseInt(targ.css('border'+Pos+'Width')) || 0;
+                                       }
+
+                                       attr[key] += settings.offset[pos] || 0;
+
+                                       if( settings.over[pos] )
+                                               // Scroll to a fraction of its width/height
+                                               attr[key] += targ[dim]() * settings.over[pos];
+                               }else
+                                       attr[key] = targ[pos];
+
+                               // Number or 'number'
+                               if( /^\d+$/.test(attr[key]) )
+                                       // Check the limits
+                                       attr[key] = attr[key] <= 0 ? 0 : Math.min( attr[key], max(Dim) );
+
+                               // Queueing axes
+                               if( !i && settings.queue ){
+                                       // Don't waste time animating, if there's no need.
+                                       if( old != attr[key] )
+                                               // Intermediate animation
+                                               animate( settings.onAfterFirst );
+                                       // Don't animate this axis again in the next iteration.
+                                       delete attr[key];
+                               }
+                       });
+                       animate( settings.onAfter );
+
+                       function animate( callback ){
+                               $elem.animate( attr, duration, settings.easing, callback && function(){
+                                       callback.call(this, target, settings);
+                               });
+                       };
+                       function max( Dim ){
+                               var attr ='scroll'+Dim,
+                                       doc = elem.ownerDocument;
+
+                               return win
+                                               ? Math.max( doc.documentElement[attr], doc.body[attr]  )
+                                               : elem[attr];
+                       };
+               }).end();
+       };
+
+       function both( val ){
+               return typeof val == 'object' ? val : { top:val, left:val };
+       };
+
 })( jQuery );
\ No newline at end of file
 })( jQuery );
\ No newline at end of file
index e4fd74d..06ad40c 100644 (file)
@@ -4,10 +4,10 @@
       choices: []
     };
     $.extend(settings, options);
       choices: []
     };
     $.extend(settings, options);
-    
+
     var input = $(this).hide();
     var values = input.val().split(',');
     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 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
@@ -19,7 +19,7 @@
     $.each(settings.choices, function() {
       choiceIds.push('' + this.id);
     });
     $.each(settings.choices, function() {
       choiceIds.push('' + this.id);
     });
-    
+
     function createItem(hash) {
       return $('<li>' + hash.name + '</li>').css({
         backgroundColor: '#cff',
     function createItem(hash) {
       return $('<li>' + hash.name + '</li>').css({
         backgroundColor: '#cff',
         margin: 0
       }).data('obj-id', hash.id);
     }
         margin: 0
       }).data('obj-id', hash.id);
     }
-    
+
     $.each(settings.choices, function() {
       if ($.inArray('' + this.id, values) == -1) {
         choicesList.append(createItem(this));
       }
     });
     $.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]));
       }
     });
     $.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();
     choicesList.sortable({
                connectWith: '.connectedSortable'
        }).disableSelection();
-       
+
        valuesList.sortable({
                connectWith: '.connectedSortable',
                update: function() {
        valuesList.sortable({
                connectWith: '.connectedSortable',
                update: function() {
index 4cb5eb6..33c794a 100644 (file)
@@ -4,12 +4,12 @@
       sponsors: []
     };
     $.extend(settings, options);
       sponsors: []
     };
     $.extend(settings, options);
-    
+
     var input = $(this).hide();
     var input = $(this).hide();
-    
+
     var container = $('<div class="sponsors"></div>').appendTo(input.parent());
     var groups = $.evalJSON(input.val());
     var container = $('<div class="sponsors"></div>').appendTo(input.parent());
     var groups = $.evalJSON(input.val());
-    
+
     var unusedDiv = $('<div class="sponsors-sponsor-group sponsors-unused-sponsor-group"></div>')
       .appendTo(container)
       .append('<p class="sponsors-sponsor-group-name sponsors-unused-sponsor-group-name">dostępni sponsorzy</p>');
     var unusedDiv = $('<div class="sponsors-sponsor-group sponsors-unused-sponsor-group"></div>')
       .appendTo(container)
       .append('<p class="sponsors-sponsor-group-name sponsors-unused-sponsor-group-name">dostępni sponsorzy</p>');
         .sortable({
           connectWith: '.sponsors-sponsor-group-list'
                });
         .sortable({
           connectWith: '.sponsors-sponsor-group-list'
                });
-    
+
     // Edit group name inline
     function editNameInline(name) {
       name.unbind('click.sponsorsFooter');
       var inlineInput = $('<input></input>').val(name.html());
       name.html('');
     // Edit group name inline
     function editNameInline(name) {
       name.unbind('click.sponsorsFooter');
       var inlineInput = $('<input></input>').val(name.html());
       name.html('');
-      
+
       function endEditing() {
         name.html(inlineInput.val());
         inlineInput.remove();
       function endEditing() {
         name.html(inlineInput.val());
         inlineInput.remove();
         input.parents('form').unbind('submit.sponsorsFooter', endEditing);
         return false;
       }
         input.parents('form').unbind('submit.sponsorsFooter', endEditing);
         return false;
       }
-      
+
       inlineInput.appendTo(name).focus().blur(endEditing);
       input.parents('form').bind('submit.sponsorsFooter', endEditing);
     }
       inlineInput.appendTo(name).focus().blur(endEditing);
       input.parents('form').bind('submit.sponsorsFooter', endEditing);
     }
-    
+
     // Remove sponsor with passed id from sponsors array and return it
     function popSponsor(id) {
       for (var i=0; i < settings.sponsors.length; i++) {
     // Remove sponsor with passed id from sponsors array and return it
     function popSponsor(id) {
       for (var i=0; i < settings.sponsors.length; i++) {
       }
       return null;
     }
       }
       return null;
     }
-    
+
     // Create sponsor group and bind events
     function createGroup(name, sponsors) {
       if (!sponsors) {
         sponsors = [];
       }
     // Create sponsor group and bind events
     function createGroup(name, sponsors) {
       if (!sponsors) {
         sponsors = [];
       }
-      
+
       var groupDiv = $('<div class="sponsors-sponsor-group"></div>');
       var groupDiv = $('<div class="sponsors-sponsor-group"></div>');
-      
+
       $('<a class="sponsors-remove-sponsor-group">X</a>')
         .click(function() {
           groupDiv.fadeOut('slow', function() {
       $('<a class="sponsors-remove-sponsor-group">X</a>')
         .click(function() {
           groupDiv.fadeOut('slow', function() {
             groupDiv.remove();
           });
         }).appendTo(groupDiv);
             groupDiv.remove();
           });
         }).appendTo(groupDiv);
-      
+
       $('<p class="sponsors-sponsor-group-name">' + name + '</p>')
         .bind('click.sponsorsFooter', function() {
           editNameInline($(this));
         }).appendTo(groupDiv);
       $('<p class="sponsors-sponsor-group-name">' + name + '</p>')
         .bind('click.sponsorsFooter', function() {
           editNameInline($(this));
         }).appendTo(groupDiv);
-      
+
       var groupList = $('<ol class="sponsors-sponsor-group-list"></ol>')
         .appendTo(groupDiv)
         .sortable({
           connectWith: '.sponsors-sponsor-group-list'
                });
       var groupList = $('<ol class="sponsors-sponsor-group-list"></ol>')
         .appendTo(groupDiv)
         .sortable({
           connectWith: '.sponsors-sponsor-group-list'
                });
-      
-      
+
+
       for (var i = 0; i < sponsors.length; i++) {
         $('<li class="sponsors-sponsor"><img src="' + sponsors[i].image + '" alt="' + sponsors[i].name + '"/></li>')
           .data('obj_id', sponsors[i].id)
       for (var i = 0; i < sponsors.length; i++) {
         $('<li class="sponsors-sponsor"><img src="' + sponsors[i].image + '" alt="' + sponsors[i].name + '"/></li>')
           .data('obj_id', sponsors[i].id)
       }
       return groupDiv;
     }
       }
       return groupDiv;
     }
-    
+
     // Create groups from data in input value
     for (var i = 0; i < groups.length; i++) {
       var group = groups[i];
       var sponsors = [];
     // Create groups from data in input value
     for (var i = 0; i < groups.length; i++) {
       var group = groups[i];
       var sponsors = [];
-      
+
       for (var j = 0; j < group.sponsors.length; j++) {
         var s = popSponsor(group.sponsors[j]);
         if (s) {
       for (var j = 0; j < group.sponsors.length; j++) {
         var s = popSponsor(group.sponsors[j]);
         if (s) {
       }
       createGroup(group.name, sponsors).appendTo(container);
     }
       }
       createGroup(group.name, sponsors).appendTo(container);
     }
-    
+
     // Serialize input value before submiting form
     input.parents('form').submit(function(event) {
       var groups = [];
     // Serialize input value before submiting form
     input.parents('form').submit(function(event) {
       var groups = [];
       });
       input.val($.toJSON(groups));
     });
       });
       input.val($.toJSON(groups));
     });
-    
+
     for (i = 0; i < settings.sponsors.length; i++) {
       $('<li class="sponsors-sponsor"><img src="' + settings.sponsors[i].image + '" alt="' + settings.sponsors[i].name + '"/></li>')
         .data('obj_id', settings.sponsors[i].id)
         .appendTo(unusedList);
     }
     for (i = 0; i < settings.sponsors.length; i++) {
       $('<li class="sponsors-sponsor"><img src="' + settings.sponsors[i].image + '" alt="' + settings.sponsors[i].name + '"/></li>')
         .data('obj_id', settings.sponsors[i].id)
         .appendTo(unusedList);
     }
-    
+
     $('<button type="button">Dodaj nową grupę</button>')
       .click(function() {
         var newGroup = createGroup('').appendTo(container);
         editNameInline($('.sponsors-sponsor-group-name', newGroup));
       }).prependTo(input.parent());
     $('<button type="button">Dodaj nową grupę</button>')
       .click(function() {
         var newGroup = createGroup('').appendTo(container);
         editNameInline($('.sponsors-sponsor-group-name', newGroup));
       }).prependTo(input.parent());
-    
+
     input.parent().append('<div style="clear: both"></div>');
   };
 })(jQuery);
     input.parent().append('<div style="clear: both"></div>');
   };
 })(jQuery);
index d7bbdc0..86ad6ac 100644 (file)
@@ -12,7 +12,7 @@
 
 {% block bodycontent %}
     <div id="onepercent-content" class="container_12">
 
 {% block bodycontent %}
     <div id="onepercent-content" class="container_12">
-        
+
         <div id="header" class="grid_12">
             <div id="logos" class="alpha grid_5 suffix_1">
                 <img src="{{ STATIC_URL }}img/logo-big.png" />
         <div id="header" class="grid_12">
             <div id="logos" class="alpha grid_5 suffix_1">
                 <img src="{{ STATIC_URL }}img/logo-big.png" />
@@ -22,7 +22,7 @@
                 <img src="{{ STATIC_URL }}img/tagline.png" />
             </div>
         </div>
                 <img src="{{ STATIC_URL }}img/tagline.png" />
             </div>
         </div>
-        
+
         <div id="lists" class="grid_12">
             <div id="why" class="alpha grid_6">
                 <h2>Dlaczego warto?</h2>
         <div id="lists" class="grid_12">
             <div id="why" class="alpha grid_6">
                 <h2>Dlaczego warto?</h2>
@@ -46,12 +46,12 @@ KRS 0000070056</pre>
                 <p>Skorzystaj z programu ułatwiającego przygotowanie deklaracji podatkowej on-line.</p>
             </div>
         </div>
                 <p>Skorzystaj z programu ułatwiającego przygotowanie deklaracji podatkowej on-line.</p>
             </div>
         </div>
-        
+
         <div id="copy" class="grid_12">
             <p>Biblioteka Wolne Lektury to projekt realizowany przez Fundację Nowoczesna Polska. Rozwijamy się tylko dzięki pomocy wolontariuszy i darczyńców. Pomóż nam! Dzięki 1% podatku dodajemy nowe lektury i nowe funkcjonalności.</p>
             <p>Fundacja jest organizacją pożytku publicznego. Bez ponoszenia dodatkowych kosztów Twoi rodzice mogą wspomóc rozwój internetowej biblioteki Wolne Lektury. Co ważne, te pieniądze i tak nie zostaną w ich kieszeni. Jeśli nie podarują ich Fundacji Nowoczesna Polska lub innej organizacji pożytku publicznego, to rząd zdecyduje, jak je wydać. Powiedz rodzicom o możliwości przekazania 1% podatku i przekonaj ich, że warto samodzielnie zadecydować, co stanie się z częścią ich podatków.

Dzięki uzyskanym w ten sposób środkom będziemy mogli opublikować na stronie Wolnych Lektur jeszcze więcej tekstów oraz dodać nowe narzędzia ułatwiające czytanie. Dzięki temu biblioteka będzie jeszcze bardziej przydatnym i przyjaznym miejscem w sieci.</p>
         </div>
         <div id="copy" class="grid_12">
             <p>Biblioteka Wolne Lektury to projekt realizowany przez Fundację Nowoczesna Polska. Rozwijamy się tylko dzięki pomocy wolontariuszy i darczyńców. Pomóż nam! Dzięki 1% podatku dodajemy nowe lektury i nowe funkcjonalności.</p>
             <p>Fundacja jest organizacją pożytku publicznego. Bez ponoszenia dodatkowych kosztów Twoi rodzice mogą wspomóc rozwój internetowej biblioteki Wolne Lektury. Co ważne, te pieniądze i tak nie zostaną w ich kieszeni. Jeśli nie podarują ich Fundacji Nowoczesna Polska lub innej organizacji pożytku publicznego, to rząd zdecyduje, jak je wydać. Powiedz rodzicom o możliwości przekazania 1% podatku i przekonaj ich, że warto samodzielnie zadecydować, co stanie się z częścią ich podatków.

Dzięki uzyskanym w ten sposób środkom będziemy mogli opublikować na stronie Wolnych Lektur jeszcze więcej tekstów oraz dodać nowe narzędzia ułatwiające czytanie. Dzięki temu biblioteka będzie jeszcze bardziej przydatnym i przyjaznym miejscem w sieci.</p>
         </div>
-        
+
         <div class="grid_12">
             <a id="back" href="{% url main_page %}">Wróć do serwisu Wolne Lektury</a>
         </div>
         <div class="grid_12">
             <a id="back" href="{% url main_page %}">Wróć do serwisu Wolne Lektury</a>
         </div>
index cc8ccc9..50a56ea 100644 (file)
@@ -5,7 +5,7 @@
 <head>
 <title>404 - {% trans "Page does not exist" %} - WolneLektury.pl</title>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 <head>
 <title>404 - {% trans "Page does not exist" %} - WolneLektury.pl</title>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.5.2/build/reset/reset-min.css"> 
+<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.5.2/build/reset/reset-min.css">
 <link rel="stylesheet" href="{{ STATIC_URL }}css/error.css" type="text/css" />
 </head>
 
 <link rel="stylesheet" href="{{ STATIC_URL }}css/error.css" type="text/css" />
 </head>
 
index 4ecf3ad..e0b2bbb 100644 (file)
@@ -5,11 +5,11 @@
 <head>
 <title>500 - {% trans "Server error" %} WolneLektury.pl</title>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 <head>
 <title>500 - {% trans "Server error" %} WolneLektury.pl</title>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.5.2/build/reset/reset-min.css"> 
+<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.5.2/build/reset/reset-min.css">
 <style type="text/css">
 
 body {
 <style type="text/css">
 
 body {
-font-family: verdana, arial, sans-serif; 
+font-family: verdana, arial, sans-serif;
 margin: 2em;
 font-size: 100%;
 }
 margin: 2em;
 font-size: 100%;
 }
@@ -30,7 +30,7 @@ img {
 
 a:link {
     color: #037;
 
 a:link {
     color: #037;
-    text-decoration: underline; 
+    text-decoration: underline;
 }
 
 a:visited {
 }
 
 a:visited {
index 7d444a2..3b9ebe1 100644 (file)
@@ -5,11 +5,11 @@
 <head>
 <title>503 - {% trans "Service unavailable" %} WolneLektury.pl</title>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 <head>
 <title>503 - {% trans "Service unavailable" %} WolneLektury.pl</title>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
-<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.5.2/build/reset/reset-min.css"> 
+<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.5.2/build/reset/reset-min.css">
 <style type="text/css">
 
 body {
 <style type="text/css">
 
 body {
-font-family: verdana, arial, sans-serif; 
+font-family: verdana, arial, sans-serif;
 margin: 2em;
 font-size: 100%;
 }
 margin: 2em;
 font-size: 100%;
 }
@@ -30,7 +30,7 @@ img {
 
 a:link {
     color: #037;
 
 a:link {
     color: #037;
-    text-decoration: underline; 
+    text-decoration: underline;
 }
 
 a:visited {
 }
 
 a:visited {
index 2e80c55..a168ff7 100644 (file)
@@ -16,7 +16,7 @@
         </ol>
         <p><input type="hidden" name="next" value="{{ next }}" /></p>
     </form>
         </ol>
         <p><input type="hidden" name="next" value="{{ next }}" /></p>
     </form>
-    
+
     <form action="." method="post" accept-charset="utf-8" id="registration-form">
         <h2>{% trans "Register" %}</h2>
 
     <form action="." method="post" accept-charset="utf-8" id="registration-form">
         <h2>{% trans "Register" %}</h2>
 
index ddec560..ca41767 100644 (file)
@@ -46,7 +46,7 @@
             <div class="social-links" style="float:right">
                 <a href="http://pl-pl.facebook.com/pages/Wolne-Lektury/203084073268"><img src="{{ STATIC_URL }}img/social/facebook.png" alt="WolneLektury @ Facebook" /></a>
                 <a href="http://twitter.com/wolnelektury"><img src="{{ STATIC_URL }}img/social/twitter.png" alt="WolneLektury @ Twitter" /></a>
             <div class="social-links" style="float:right">
                 <a href="http://pl-pl.facebook.com/pages/Wolne-Lektury/203084073268"><img src="{{ STATIC_URL }}img/social/facebook.png" alt="WolneLektury @ Facebook" /></a>
                 <a href="http://twitter.com/wolnelektury"><img src="{{ STATIC_URL }}img/social/twitter.png" alt="WolneLektury @ Twitter" /></a>
-                <a href="http://nasza-klasa.pl/profile/30441509"><img src="{{ STATIC_URL }}img/social/naszaklasa.png" alt="WolneLektury @ Nasza-Klasa" /></a>     
+                <a href="http://nasza-klasa.pl/profile/30441509"><img src="{{ STATIC_URL }}img/social/naszaklasa.png" alt="WolneLektury @ Nasza-Klasa" /></a>
             </div>
                        <div class="lang-menu" style="float:right;">
                                <form action="/i18n/setlang/" method="post">
             </div>
                        <div class="lang-menu" style="float:right;">
                                <form action="/i18n/setlang/" method="post">
                                        </select>
                                        <input type="submit" value="{% trans "Choose language" %}">
                                </form>
                                        </select>
                                        <input type="submit" value="{% trans "Choose language" %}">
                                </form>
-                       </div>                  
+                       </div>
             <div class="clearboth"></div>
         </div>
         <div id="maincontent">
             {% block body %}
             <div class="clearboth"></div>
         </div>
         <div id="maincontent">
             {% block body %}
-            {% endblock %}    
+            {% endblock %}
         </div>
         <div class="clearboth"></div>
         <div id="footer">
             <p>
                {% blocktrans %}
                                Wolne Lektury is a project lead by <a href="http://nowoczesnapolska.org.pl/">Modern Poland Foundation</a>.
         </div>
         <div class="clearboth"></div>
         <div id="footer">
             <p>
                {% blocktrans %}
                                Wolne Lektury is a project lead by <a href="http://nowoczesnapolska.org.pl/">Modern Poland Foundation</a>.
-                               Digital reproductions are made by <a href="http://www.bn.org.pl/">The National Library</a>, based on TNL resources. 
+                               Digital reproductions are made by <a href="http://www.bn.org.pl/">The National Library</a>, based on TNL resources.
                                Hosting <a href="http://eo.pl/">EO Networks</a>.
                                {% endblocktrans %}
             </p>
                                Hosting <a href="http://eo.pl/">EO Networks</a>.
                                {% endblocktrans %}
             </p>
index 7963fe6..809bd1a 100644 (file)
@@ -11,7 +11,7 @@
     <form action="{% url search %}" method="get" accept-charset="utf-8" id="search-form">
         <p>{{ form.q }} <input type="submit" value="{% trans "Search" %}" /> <strong>{% trans "or" %}</strong> <a href="{% url main_page %}">{% trans "return to main page" %}</a></p>
     </form>
     <form action="{% url search %}" method="get" accept-charset="utf-8" id="search-form">
         <p>{{ form.q }} <input type="submit" value="{% trans "Search" %}" /> <strong>{% trans "or" %}</strong> <a href="{% url main_page %}">{% trans "return to main page" %}</a></p>
     </form>
-    
+
     <div id="books-list">
         {% if extra_info.license %}
         <p>{% trans "Work is licensed under " %}<a href="{{ extra_info.license }}">{{ extra_info.license_description }}</a>.</p>
     <div id="books-list">
         {% if extra_info.license %}
         <p>{% trans "Work is licensed under " %}<a href="{{ extra_info.license }}">{{ extra_info.license_description }}</a>.</p>
@@ -44,7 +44,7 @@
             {% endif %}
             {% if book.mp3_file %}
                 <div id="czytamy-sluchajac-info">
             {% endif %}
             {% if book.mp3_file %}
                 <div id="czytamy-sluchajac-info">
-                    <a href="http://czytamysluchajac.pl/" id="czytamysluchajac-logo"><img src="{{ STATIC_URL }}img/czytamysluchajac-logo-small.png" /></a>     
+                    <a href="http://czytamysluchajac.pl/" id="czytamysluchajac-logo"><img src="{{ STATIC_URL }}img/czytamysluchajac-logo-small.png" /></a>
                     <p>{% trans "Artist" %}: {{ book.get_extra_info_value.artist_name }}</p>
                                        {% if book.get_extra_info_value.director_name %}
                         <p>{% trans "Director" %}: {{ book.get_extra_info_value.director_name }}</p>
                     <p>{% trans "Artist" %}: {{ book.get_extra_info_value.artist_name }}</p>
                                        {% if book.get_extra_info_value.director_name %}
                         <p>{% trans "Director" %}: {{ book.get_extra_info_value.director_name }}</p>
@@ -62,7 +62,7 @@
             {% endif %}
             </div>
         </div>
             {% endif %}
             </div>
         </div>
-    
+
         {% if book_children %}
         {% autopaginate book_children 10 %}
         <div id="book-children">
         {% if book_children %}
         {% autopaginate book_children 10 %}
         <div id="book-children">
         </div>
         {% paginate %}
         {% endif %}
         </div>
         {% paginate %}
         {% endif %}
-    
+
     </div>
     </div>
-        
+
     <div id="tags-list">
         <div id="book-info">
             <h2>{% trans "Details" %}</h2>
             <ul>
                 <li>
     <div id="tags-list">
         <div id="book-info">
             <h2>{% trans "Details" %}</h2>
             <ul>
                 <li>
-                    {% trans "Author" %}: 
+                    {% trans "Author" %}:
                     {% for tag in categories.author %}
                     <a href="{{ tag.get_absolute_url }}">{{ tag }}</a>
                     {% endfor %}
                     {% for tag in categories.author %}
                     <a href="{{ tag.get_absolute_url }}">{{ tag }}</a>
                     {% endfor %}
index 3e6a9c5..c5f9164 100644 (file)
@@ -11,7 +11,7 @@
     <form action="{% url search %}" method="GET" accept-charset="utf-8" id="search-form">
         <p>{{ form.q }} <input type="submit" value="{% trans "Search" %}" /> <strong>{% trans "or" %}</strong> <a href="{% url main_page %}">{% trans "return to main page" %}</a></p>
     </form>
     <form action="{% url search %}" method="GET" accept-charset="utf-8" id="search-form">
         <p>{{ form.q }} <input type="submit" value="{% trans "Search" %}" /> <strong>{% trans "or" %}</strong> <a href="{% url main_page %}">{% trans "return to main page" %}</a></p>
     </form>
-    
+
     <div id="book-list">
         {% for first_letter, group in books_by_first_letter.items %}
         <div class="group">
     <div id="book-list">
         {% for first_letter, group in books_by_first_letter.items %}
         <div class="group">
@@ -22,6 +22,6 @@
             {% endfor %}
             </ol>
         </div>
             {% endfor %}
             </ol>
         </div>
-        {% endfor %}    
+        {% endfor %}
     </div>
 {% endblock %}
\ No newline at end of file
     </div>
 {% endblock %}
\ No newline at end of file
index 5f19220..e35d1d8 100644 (file)
     <form action="{% url search %}" method="get" accept-charset="utf-8" id="search-form">
         <p>{{ form.q }} <input type="submit" value="{% trans "Search" %}" /> <strong>{% trans "or" %}</strong> <a href="{% url main_page %}">{% trans "return to main page" %}</a></p>
     </form>
     <form action="{% url search %}" method="get" accept-charset="utf-8" id="search-form">
         <p>{{ form.q }} <input type="submit" value="{% trans "Search" %}" /> <strong>{% trans "or" %}</strong> <a href="{% url main_page %}">{% trans "return to main page" %}</a></p>
     </form>
-    
+
     <div id="books-list">
     {% if book.in_pd %}
     <div id="books-list">
     {% if book.in_pd %}
-               {% trans "This work is in public domain and will be published on Internet school library of Wolne Lektury soon." %} 
+               {% trans "This work is in public domain and will be published on Internet school library of Wolne Lektury soon." %}
        {% else %}
            {% if book.pd %}
                        {% trans "This work will become part of public domain and will be allowed to be published without restrictions in" %}
        {% else %}
            {% if book.pd %}
                        {% trans "This work will become part of public domain and will be allowed to be published without restrictions in" %}
index 51b3821..1e7a1a7 100644 (file)
@@ -9,7 +9,7 @@
 {% block body %}
     <h1>{% title_from_tags tags %}</h1>
     {% breadcrumbs tags %}
 {% block body %}
     <h1>{% title_from_tags tags %}</h1>
     {% breadcrumbs tags %}
-    
+
        <p>{% trans "The criteria are ambiguous. Please select one of the following options:" %}</p>
     <div id="books-list">
         {% for option in options %}
        <p>{% trans "The criteria are ambiguous. Please select one of the following options:" %}</p>
     <div id="books-list">
         {% for option in options %}
index 62a5820..a6ff53a 100644 (file)
@@ -18,7 +18,7 @@
             {% for tag in tags %}
                 <li><a href="{% catalogue_url choices tag %}">{{ tag }}&nbsp;({{ tag.count }})</a></li>
             {% endfor %}
             {% for tag in tags %}
                 <li><a href="{% catalogue_url choices tag %}">{{ tag }}&nbsp;({{ tag.count }})</a></li>
             {% endfor %}
-        </ul>    
+        </ul>
         <p><a href="#" class="hide-all-tags">{% trans "Hide" %}</a></p>
     </div>
 {% endif %}
         <p><a href="#" class="hide-all-tags">{% trans "Hide" %}</a></p>
     </div>
 {% endif %}
index 2b9e1fa..8fb3b96 100644 (file)
@@ -12,7 +12,7 @@
     <form action="{% url search %}" method="get" accept-charset="utf-8" id="search-form">
         <p>{{ form.q }} {{ form.tags }} <input type="submit" value="{% trans "Search" %}" /> <strong>{% trans "or" %}</strong> <a href="{% url catalogue.views.book_list %}">{% trans "check list of books" %}</a> {% trans "in our repository" %}</p>
     </form>
     <form action="{% url search %}" method="get" accept-charset="utf-8" id="search-form">
         <p>{{ form.q }} {{ form.tags }} <input type="submit" value="{% trans "Search" %}" /> <strong>{% trans "or" %}</strong> <a href="{% url catalogue.views.book_list %}">{% trans "check list of books" %}</a> {% trans "in our repository" %}</p>
     </form>
-    
+
     <div id="intro">
         <p id="tags-description">↓ {% trans "Browse books by categories" %} ↓</p>
         <div id="propaganda">
     <div id="intro">
         <p id="tags-description">↓ {% trans "Browse books by categories" %} ↓</p>
         <div id="propaganda">
@@ -80,7 +80,7 @@
 
                         <li>polityczny obraz świata
                         <span class="subcategories"><a href="/katalog/panstwo/">Państwo</a>, <a href="/katalog/obowiazek/">Obowiązek</a>, <a href="/katalog/cnota/">Cnota</a>, <a href="/katalog/obywatel/">Obywatel</a>, <a href="/katalog/patriota/">Patriota</a>, <a href="/katalog/ojczyzna/">Ojczyzna</a>, <a href="/katalog/narod/">Naród</a>, <a href="/katalog/przywodca/">Przywódca</a>, <a href="/katalog/wladza/">Władza</a>, <a href="/katalog/urzednik/">Urzędnik</a>, <a href="/katalog/krol/">Król</a>, <a href="/katalog/rycerz/">Rycerz</a>, <a href="/katalog/zolnierz/">Żołnierz</a>, <a href="/katalog/wojna/">Wojna</a>, <a href="/katalog/wrog/">Wróg</a>, <a href="/katalog/zwyciestwo/">Zwycięstwo</a>, <a href="/katalog/walka/">Walka</a>, <a href="/katalog/sila/">Siła</a>, <a href="/katalog/historia/">Historia</a>, <a href="/katalog/powstanie/">Powstanie</a>, <a href="/katalog/smierc-bohaterska/">Śmierć bohaterska</a>, <a href="/katalog/slawa/">Sława</a>, <a href="/katalog/rewolucja/">Rewolucja</a>, <a href="/katalog/sad/">Sąd</a>, <a href="/katalog/zdrada/">Zdrada</a></span></li>
 
                         <li>polityczny obraz świata
                         <span class="subcategories"><a href="/katalog/panstwo/">Państwo</a>, <a href="/katalog/obowiazek/">Obowiązek</a>, <a href="/katalog/cnota/">Cnota</a>, <a href="/katalog/obywatel/">Obywatel</a>, <a href="/katalog/patriota/">Patriota</a>, <a href="/katalog/ojczyzna/">Ojczyzna</a>, <a href="/katalog/narod/">Naród</a>, <a href="/katalog/przywodca/">Przywódca</a>, <a href="/katalog/wladza/">Władza</a>, <a href="/katalog/urzednik/">Urzędnik</a>, <a href="/katalog/krol/">Król</a>, <a href="/katalog/rycerz/">Rycerz</a>, <a href="/katalog/zolnierz/">Żołnierz</a>, <a href="/katalog/wojna/">Wojna</a>, <a href="/katalog/wrog/">Wróg</a>, <a href="/katalog/zwyciestwo/">Zwycięstwo</a>, <a href="/katalog/walka/">Walka</a>, <a href="/katalog/sila/">Siła</a>, <a href="/katalog/historia/">Historia</a>, <a href="/katalog/powstanie/">Powstanie</a>, <a href="/katalog/smierc-bohaterska/">Śmierć bohaterska</a>, <a href="/katalog/slawa/">Sława</a>, <a href="/katalog/rewolucja/">Rewolucja</a>, <a href="/katalog/sad/">Sąd</a>, <a href="/katalog/zdrada/">Zdrada</a></span></li>
-                       
+
                         <li>przyroda
                         <span class="subcategories"><a href="/katalog/natura/">Natura</a>, <a href="/katalog/zywioly/">Żywioły</a>, <a href="/katalog/ogien/">Ogień</a>, <a href="/katalog/ziemia/">Ziemia</a>, <a href="/katalog/wiatr/">Wiatr</a>, <a href="/katalog/woda/">Woda</a>, <a href="/katalog/wiosna/">Wiosna</a>, <a href="/katalog/lato/">Lato</a>, <a href="/katalog/jesien/">Jesień</a>, <a href="/katalog/zima/">Zima</a>, <a href="/katalog/przemijanie/">Przemijanie</a>, <a href="/katalog/slonce/">Słońce</a>, <a href="/katalog/ksiezyc/">Księżyc</a>, <a href="/katalog/gwiazda/">Gwiazda</a>, <a href="/katalog/oblok/">Obłok</a>, <a href="/katalog/noc/">Noc</a>, <a href="/katalog/swiatlo/">Światło</a>, <a href="/katalog/gora/">Góra</a>, <a href="/katalog/rzeka/">Rzeka</a>, <a href="/katalog/morze/">Morze</a>, <a href="/katalog/burza/">Burza</a>, <a href="/katalog/deszcz/">Deszcz</a>, <a href="/katalog/bloto/">Błoto</a>, <a href="/katalog/przyroda-nieozywiona/">Przyroda nieożywiona</a>, <a href="/katalog/rosliny/">Rośliny</a>, <a href="/katalog/kwiaty/">Kwiaty</a>, <a href="/katalog/ogrod/">Ogród</a>, <a href="/katalog/sielanka/">Sielanka</a>, <a href="/katalog/raj/">Raj</a>, <a href="/katalog/jablko/">Jabłko</a>, <a href="/katalog/drzewo/">Drzewo</a>, <a href="/katalog/zwierzeta/">Zwierzęta</a>, <a href="/katalog/ptak/">Ptak</a>, <a href="/katalog/motyl/">Motyl</a>, <a href="/katalog/kot/">Kot</a>, <a href="/katalog/kon/">Koń</a>, <a href="/katalog/pies/">Pies</a>, <a href="/katalog/waz/">Wąż</a>, <a href="/katalog/potwor/">Potwór</a></span></li>
                     </ol>
                         <li>przyroda
                         <span class="subcategories"><a href="/katalog/natura/">Natura</a>, <a href="/katalog/zywioly/">Żywioły</a>, <a href="/katalog/ogien/">Ogień</a>, <a href="/katalog/ziemia/">Ziemia</a>, <a href="/katalog/wiatr/">Wiatr</a>, <a href="/katalog/woda/">Woda</a>, <a href="/katalog/wiosna/">Wiosna</a>, <a href="/katalog/lato/">Lato</a>, <a href="/katalog/jesien/">Jesień</a>, <a href="/katalog/zima/">Zima</a>, <a href="/katalog/przemijanie/">Przemijanie</a>, <a href="/katalog/slonce/">Słońce</a>, <a href="/katalog/ksiezyc/">Księżyc</a>, <a href="/katalog/gwiazda/">Gwiazda</a>, <a href="/katalog/oblok/">Obłok</a>, <a href="/katalog/noc/">Noc</a>, <a href="/katalog/swiatlo/">Światło</a>, <a href="/katalog/gora/">Góra</a>, <a href="/katalog/rzeka/">Rzeka</a>, <a href="/katalog/morze/">Morze</a>, <a href="/katalog/burza/">Burza</a>, <a href="/katalog/deszcz/">Deszcz</a>, <a href="/katalog/bloto/">Błoto</a>, <a href="/katalog/przyroda-nieozywiona/">Przyroda nieożywiona</a>, <a href="/katalog/rosliny/">Rośliny</a>, <a href="/katalog/kwiaty/">Kwiaty</a>, <a href="/katalog/ogrod/">Ogród</a>, <a href="/katalog/sielanka/">Sielanka</a>, <a href="/katalog/raj/">Raj</a>, <a href="/katalog/jablko/">Jabłko</a>, <a href="/katalog/drzewo/">Drzewo</a>, <a href="/katalog/zwierzeta/">Zwierzęta</a>, <a href="/katalog/ptak/">Ptak</a>, <a href="/katalog/motyl/">Motyl</a>, <a href="/katalog/kot/">Kot</a>, <a href="/katalog/kon/">Koń</a>, <a href="/katalog/pies/">Pies</a>, <a href="/katalog/waz/">Wąż</a>, <a href="/katalog/potwor/">Potwór</a></span></li>
                     </ol>
         </div>
     </div>
     <div class="clearboth"></div>
         </div>
     </div>
     <div class="clearboth"></div>
-    
+
     <div id="site-info">
         <div id="latest-blog-posts">
             <h2>{% trans "News" %}</h2>
     <div id="site-info">
         <div id="latest-blog-posts">
             <h2>{% trans "News" %}</h2>
index 7296317..79c0ada 100644 (file)
@@ -2,5 +2,5 @@
 <script>
 $.countdown.setDefaults($.countdown.regional['{{ LANGUAGE_CODE }}']);
 d = new Date({{ pd_counter }}, 1, 1);
 <script>
 $.countdown.setDefaults($.countdown.regional['{{ LANGUAGE_CODE }}']);
 d = new Date({{ pd_counter }}, 1, 1);
-$('#countdown').countdown({until: d, format: 'ydHMS', serverSync: serverTime}); 
+$('#countdown').countdown({until: d, format: 'ydHMS', serverSync: serverTime});
 </script>
 </script>
index fe45140..8e99cdc 100644 (file)
@@ -9,7 +9,7 @@
 {% block body %}
     <h1>{% title_from_tags tags %}</h1>
     {% breadcrumbs tags %}
 {% block body %}
     <h1>{% title_from_tags tags %}</h1>
     {% breadcrumbs tags %}
-    
+
     <div id="books-list">
         <p>{% trans "More than one result matching the criteria found." %}</p>
                <ul class='matches'>
     <div id="books-list">
         <p>{% trans "More than one result matching the criteria found." %}</p>
                <ul class='matches'>
index f7e08ac..1a92e4b 100644 (file)
@@ -9,10 +9,10 @@
 {% block body %}
     <h1>{% title_from_tags tags %}</h1>
     {% breadcrumbs tags %}
 {% block body %}
     <h1>{% title_from_tags tags %}</h1>
     {% breadcrumbs tags %}
-    
+
     <div id="books-list">
         <p>{% trans "Sorry! Search cirteria did not match any resources." %}</p>
     <div id="books-list">
         <p>{% trans "Sorry! Search cirteria did not match any resources." %}</p>
-               
+
                <p>{% blocktrans %}Search engine supports following criteria: title, author, theme/topic, epoch, kind and genre.
                As for now we do not support full text search.{% endblocktrans %}</p>
         {% include "info/join_us.html" %}
                <p>{% blocktrans %}Search engine supports following criteria: title, author, theme/topic, epoch, kind and genre.
                As for now we do not support full text search.{% endblocktrans %}</p>
         {% include "info/join_us.html" %}
index f68d065..e10ddc2 100644 (file)
@@ -9,7 +9,7 @@
 {% block body %}
     <h1>{% title_from_tags tags %}</h1>
     {% breadcrumbs tags %}
 {% block body %}
     <h1>{% title_from_tags tags %}</h1>
     {% breadcrumbs tags %}
-    
+
     <div id="books-list">
         <p>{% trans "Sorry! Search query must have at least two characters." %}</p>
         {% include "info/join_us.html" %}
     <div id="books-list">
         <p>{% trans "Sorry! Search query must have at least two characters." %}</p>
         {% include "info/join_us.html" %}
index 5f7d69f..952ba2b 100644 (file)
@@ -9,7 +9,7 @@
 {% block body %}
     <h1>{% title_from_tags tags %}</h1>
     {% breadcrumbs tags %}
 {% block body %}
     <h1>{% title_from_tags tags %}</h1>
     {% breadcrumbs tags %}
-    
+
     {% if shelf_is_set and not object_list %}
     <div id="books-list">
         <h2>{% trans "Your shelf is empty" %}</h2>
     {% if shelf_is_set and not object_list %}
     <div id="books-list">
         <h2>{% trans "Your shelf is empty" %}</h2>
                                        {% trans "This author's works are copyrighted." %}
                                {% else %}{% comment %} Is dead {% endcomment %}
                    {% if last_tag.in_pd %}
                                        {% trans "This author's works are copyrighted." %}
                                {% else %}{% comment %} Is dead {% endcomment %}
                    {% if last_tag.in_pd %}
-                                               <p>{% trans "This author's works are in public domain and will be published on Internet school library of Wolne Lektury soon." %}</p>            
+                                               <p>{% trans "This author's works are in public domain and will be published on Internet school library of Wolne Lektury soon." %}</p>
                        {% else %}
                                                {% comment %} Is dead, but not yet in public domain {% endcomment %}
                        <div>
                        {% else %}
                                                {% comment %} Is dead, but not yet in public domain {% endcomment %}
                        <div>
             {% if categories.epoch %}
                 <h2>{% trans "Epochs" %}</h2>
                 {% tag_list categories.epoch tags %}
             {% if categories.epoch %}
                 <h2>{% trans "Epochs" %}</h2>
                 {% tag_list categories.epoch tags %}
-            {% endif %}        
+            {% endif %}
         </div>
         <div id="themes-list">
             {% if categories.theme %}
         </div>
         <div id="themes-list">
             {% if categories.theme %}
index afc3d69..d0186ae 100644 (file)
@@ -8,7 +8,7 @@
     <form action="{% url search %}" method="GET" accept-charset="utf-8" id="search-form">
         <p>{{ form.q }} <input type="submit" value="{% trans "Search" %}" /> <strong>{% trans "or" %}</strong> <a href="{% url lessons_document_list %}">{% trans "return to list of materials" %}</a></p>
     </form>
     <form action="{% url search %}" method="GET" accept-charset="utf-8" id="search-form">
         <p>{{ form.q }} <input type="submit" value="{% trans "Search" %}" /> <strong>{% trans "or" %}</strong> <a href="{% url lessons_document_list %}">{% trans "return to list of materials" %}</a></p>
     </form>
-    
+
     <div id="document-detail">
         <p class="download"><a href="{{ object.file.url }}">{% trans "Download" %}</a> {% if object.author %}({% trans "author" %}: {{ object.author }}){% endif %}</p>
         {% if object.slideshare_id %}
     <div id="document-detail">
         <p class="download"><a href="{{ object.file.url }}">{% trans "Download" %}</a> {% if object.author %}({% trans "author" %}: {{ object.author }}){% endif %}</p>
         {% if object.slideshare_id %}
index 79ba80d..d8564a5 100644 (file)
@@ -17,9 +17,9 @@
                 }
                 return false;
             });
                 }
                 return false;
             });
-            
+
             var lastHash = null;
             var lastHash = null;
-            
+
             function checkHash() {
                 if (document.location.hash != lastHash) {
                     lastHash = document.location.hash;
             function checkHash() {
                 if (document.location.hash != lastHash) {
                     lastHash = document.location.hash;
@@ -28,7 +28,7 @@
                         $('#document-list a').removeClass('active');
                         documentLink.addClass('active');
                     };
                         $('#document-list a').removeClass('active');
                         documentLink.addClass('active');
                     };
-                    
+
                     if ($('#document-detail').attr('data-hash') != lastHash) {
                         $('#document-detail')
                             .attr('data-hash', lastHash)
                     if ($('#document-detail').attr('data-hash') != lastHash) {
                         $('#document-detail')
                             .attr('data-hash', lastHash)
                 } else if (!document.location.hash) {
                     $('#document-list a:first').click();
                 }
                 } else if (!document.location.hash) {
                     $('#document-list a:first').click();
                 }
-                
+
                 setTimeout(checkHash, 500);
             };
                 setTimeout(checkHash, 500);
             };
-            
+
             checkHash();
         });
     </script>
             checkHash();
         });
     </script>
@@ -50,7 +50,7 @@
     <form action="{% url search %}" method="GET" accept-charset="utf-8" id="search-form">
         <p>{{ form.q }} <input type="submit" value="{% trans "Search" %}" /> <strong>{% trans "or" %}</strong> <a href="{% url main_page %}">{% trans "return to main page" %}</a></p>
     </form>
     <form action="{% url search %}" method="GET" accept-charset="utf-8" id="search-form">
         <p>{{ form.q }} <input type="submit" value="{% trans "Search" %}" /> <strong>{% trans "or" %}</strong> <a href="{% url main_page %}">{% trans "return to main page" %}</a></p>
     </form>
-    
+
     <div id="document-list">
         <ol>
         {% for object in object_list %}
     <div id="document-list">
         <ol>
         {% for object in object_list %}
@@ -61,4 +61,3 @@
     <div id="document-detail">
     </div>
 {% endblock %}
     <div id="document-detail">
     </div>
 {% endblock %}
-            
\ No newline at end of file
index 5101355..4026ea3 100644 (file)
@@ -21,39 +21,39 @@ urlpatterns = patterns('',
     url(r'^katalog/', include('catalogue.urls')),
     url(r'^materialy/', include('lessons.urls')),
     url(r'^sugestia/', include('suggest.urls')),
     url(r'^katalog/', include('catalogue.urls')),
     url(r'^materialy/', include('lessons.urls')),
     url(r'^sugestia/', include('suggest.urls')),
-    
+
     # Static pages
     # Static pages
-    url(r'^wolontariat/$', 'django.views.generic.list_detail.object_detail', 
+    url(r'^wolontariat/$', 'django.views.generic.list_detail.object_detail',
         dict(infopages, slug='voluntary_services'), name='voluntary_services'),
         dict(infopages, slug='voluntary_services'), name='voluntary_services'),
-    url(r'^mozesz-nam-pomoc/$', 'django.views.generic.list_detail.object_detail', 
+    url(r'^mozesz-nam-pomoc/$', 'django.views.generic.list_detail.object_detail',
         dict(infopages, slug='help_us'), name='help_us'),
         dict(infopages, slug='help_us'), name='help_us'),
-    url(r'^o-projekcie/$', 'django.views.generic.list_detail.object_detail', 
+    url(r'^o-projekcie/$', 'django.views.generic.list_detail.object_detail',
         dict(infopages, slug='about_us'), name='about_us'),
         dict(infopages, slug='about_us'), name='about_us'),
-        
+
     url(r'^1procent/$', 'django.views.generic.simple.direct_to_template', {
         'template': '1percent.html'
     }, name='1percent'),
     url(r'^1procent/$', 'django.views.generic.simple.direct_to_template', {
         'template': '1percent.html'
     }, name='1percent'),
-    
+
     # Admin panel
     url(r'^admin/catalogue/book/import$', 'catalogue.views.import_book', name='import_book'),
     url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
     url(r'^admin/(.*)$', admin.site.root),
     # Admin panel
     url(r'^admin/catalogue/book/import$', 'catalogue.views.import_book', name='import_book'),
     url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
     url(r'^admin/(.*)$', admin.site.root),
-    
+
     # Authentication
     url(r'^uzytkownicy/zaloguj/$', 'catalogue.views.login', name='login'),
     url(r'^uzytkownicy/wyloguj/$', 'catalogue.views.logout_then_redirect', name='logout'),
     url(r'^uzytkownicy/utworz/$', 'catalogue.views.register', name='register'),
     # Authentication
     url(r'^uzytkownicy/zaloguj/$', 'catalogue.views.login', name='login'),
     url(r'^uzytkownicy/wyloguj/$', 'catalogue.views.logout_then_redirect', name='logout'),
     url(r'^uzytkownicy/utworz/$', 'catalogue.views.register', name='register'),
-    
+
     # API
     (r'^api/', include('api.urls')),
     # API
     (r'^api/', include('api.urls')),
-    
+
     # Static files
     # Static files
-    url(r'^%s(?P<path>.*)$' % settings.MEDIA_URL[1:], 'django.views.static.serve', 
+    url(r'^%s(?P<path>.*)$' % settings.MEDIA_URL[1:], 'django.views.static.serve',
         {'document_root': settings.MEDIA_ROOT, 'show_indexes': True}),
     url(r'^%s(?P<path>.*)$' % settings.STATIC_URL[1:], 'django.views.static.serve',
         {'document_root': settings.STATIC_ROOT, 'show_indexes': True}),
     url(r'^$', 'django.views.generic.simple.redirect_to', {'url': 'katalog/'}),
         {'document_root': settings.MEDIA_ROOT, 'show_indexes': True}),
     url(r'^%s(?P<path>.*)$' % settings.STATIC_URL[1:], 'django.views.static.serve',
         {'document_root': settings.STATIC_ROOT, 'show_indexes': True}),
     url(r'^$', 'django.views.generic.simple.redirect_to', {'url': 'katalog/'}),
-    url(r'^i18n/', include('django.conf.urls.i18n')),    
+    url(r'^i18n/', include('django.conf.urls.i18n')),
 )
 
 if 'rosetta' in settings.INSTALLED_APPS:
 )
 
 if 'rosetta' in settings.INSTALLED_APPS: