Dodanie wyświetlania obrazków na lewo od edytora/podglądu HTML.
authorMarek Stępniowski <marek@stepniowski.com>
Fri, 7 Aug 2009 08:51:27 +0000 (10:51 +0200)
committerMarek Stępniowski <marek@stepniowski.com>
Fri, 7 Aug 2009 08:51:27 +0000 (10:51 +0200)
apps/explorer/forms.py
apps/explorer/models.py
apps/explorer/views.py
project/settings.py
project/static/css/master.css
project/static/js/jquery.lazyload.js [new file with mode: 0644]
project/templates/base.html
project/templates/explorer/file_html.html
project/templates/explorer/file_xml.html
project/templates/explorer/folder_images.html [new file with mode: 0644]
project/urls.py

index 065a815..2d1c99a 100644 (file)
@@ -1,6 +1,16 @@
 from django import forms
 
 from django import forms
 
+from explorer import models
+
 
 class BookForm(forms.Form):
     text = forms.CharField(widget=forms.Textarea)
     
 
 class BookForm(forms.Form):
     text = forms.CharField(widget=forms.Textarea)
     
+
+class ImageFoldersForm(forms.Form):
+    folders = forms.ChoiceField(required=False)
+    
+    def __init__(self, *args, **kwargs):
+        super(ImageFoldersForm, self).__init__(*args, **kwargs)
+        self.fields['folders'].choices = [('', '-- Wybierz folder z obrazkami --')] + [(fn, fn) for fn in models.get_image_folders()]
+
index e69de29..3b5848b 100644 (file)
@@ -0,0 +1,14 @@
+import os
+
+from django.conf import settings
+
+
+def get_image_folders():
+    return [fn for fn in os.listdir(settings.IMAGE_DIR) if not fn.startswith('.')]
+
+
+def get_images_from_folder(folder):
+    return ['/media/images/' + folder + '/' + fn for fn 
+            in os.listdir(os.path.join(settings.IMAGE_DIR, folder))
+            if not fn.startswith('.')]
+
index b1513e0..b8d00cf 100644 (file)
@@ -5,7 +5,7 @@ from django.views.generic.simple import direct_to_template
 from django.conf import settings
 from django.http import HttpResponseRedirect
 
 from django.conf import settings
 from django.http import HttpResponseRedirect
 
-from explorer import forms
+from explorer import forms, models
 
 
 repo = hg.Repository(settings.REPOSITORY_PATH)
 
 
 repo = hg.Repository(settings.REPOSITORY_PATH)
@@ -23,7 +23,7 @@ def file_xml(request, path):
         if form.is_valid():
             repo.add_file(path, form.cleaned_data['text'])
             repo.commit()
         if form.is_valid():
             repo.add_file(path, form.cleaned_data['text'])
             repo.commit()
-            return HttpResponseRedirect('/')
+            return HttpResponseRedirect(request.get_full_path())
     else:
         form = forms.BookForm()
         form.fields['text'].initial = repo.get_file(path).data()
     else:
         form = forms.BookForm()
         form.fields['text'].initial = repo.get_file(path).data()
@@ -31,6 +31,7 @@ def file_xml(request, path):
     return direct_to_template(request, 'explorer/file_xml.html', extra_context={
         'hash': path,
         'form': form,
     return direct_to_template(request, 'explorer/file_xml.html', extra_context={
         'hash': path,
         'form': form,
+        'image_folders_form': forms.ImageFoldersForm(),
     })
 
 
     })
 
 
@@ -38,5 +39,12 @@ def file_html(request, path):
     return direct_to_template(request, 'explorer/file_html.html', extra_context={
         'object': html.transform(repo.get_file(path).data(), is_file=False),
         'hash': path,
     return direct_to_template(request, 'explorer/file_html.html', extra_context={
         'object': html.transform(repo.get_file(path).data(), is_file=False),
         'hash': path,
+        'image_folders_form': forms.ImageFoldersForm(),
     })
     })
-    
\ No newline at end of file
+    
+
+def folder_images(request, folder):
+    return direct_to_template(request, 'explorer/folder_images.html', extra_context={
+        'images': models.get_images_from_folder(folder),
+    })
+
index ea7114d..aad5a88 100644 (file)
@@ -104,7 +104,8 @@ INSTALLED_APPS = (
     'explorer'
 )
 
     'explorer'
 )
 
-REPOSITORY_PATH = '/Users/zuber/Projekty/books/01'
+REPOSITORY_PATH = '/Users/zuber/Projekty/platforma/files/books'
+IMAGE_DIR = '/Users/zuber/Projekty/platforma/files/images'
 
 try:
     from localsettings import *
 
 try:
     from localsettings import *
index 1bc59da..87262b5 100644 (file)
@@ -58,12 +58,31 @@ li a:hover {
     display: none;
 }
 
     display: none;
 }
 
+label {
+    display: block;
+}
+
 textarea {
 textarea {
-    width: 97%;
-    height: 42em;
+    width: 480px;
+    height: 480px;
     padding: 5px 10px;
 }
 
 #file-text {
     padding: 5px 10px;
     padding: 5px 10px;
 }
 
 #file-text {
     padding: 5px 10px;
+    overflow-x: hidden;
+    overflow-y: scroll;
+    width: 480px;
+    height: 480px;
+    border: 1px solid #999;
+}
+
+#images {
+    float: left;
+    width: 480px;
+    height: 480px;
+    border: 1px solid #999;
+    padding: 5px 10px;
+    overflow-y: scroll;
+    overflow-x: hidden;
 }
 }
diff --git a/project/static/js/jquery.lazyload.js b/project/static/js/jquery.lazyload.js
new file mode 100644 (file)
index 0000000..98a74c1
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Lazy Load - jQuery plugin for lazy loading images
+ *
+ * Copyright (c) 2007-2009 Mika Tuupola
+ *
+ * Licensed under the MIT license:
+ *   http://www.opensource.org/licenses/mit-license.php
+ *
+ * Project home:
+ *   http://www.appelsiini.net/projects/lazyload
+ *
+ * Version:  1.3.2
+ *
+ */
+(function($) {
+
+    $.fn.lazyload = function(options) {
+        var settings = {
+            threshold    : 0,
+            failurelimit : 0,
+            event        : "scroll",
+            effect       : "show",
+            container    : window
+        };
+                
+        if(options) {
+            $.extend(settings, options);
+        }
+
+        /* Fire one scroll event per scroll. Not one scroll event per image. */
+        var elements = this;
+        if ("scroll" == settings.event) {
+            $(settings.container).bind("scroll", function(event) {
+                var counter = 0;
+                elements.each(function() {
+                    if (!$.belowthefold(this, settings) &&
+                        !$.rightoffold(this, settings)) {
+                            $(this).trigger("appear");
+                    } else {
+                        if (counter++ > settings.failurelimit) {
+                            return false;
+                        }
+                    }
+                });
+                /* Remove image from array so it is not looped next time. */
+                var temp = $.grep(elements, function(element) {
+                    return !element.loaded;
+                });
+                elements = $(temp);
+            });
+        }
+        
+        return this.each(function() {
+            var self = this;
+            /* TODO: use .data() instead of .attr() */
+            $(self).attr("original", $(self).attr("src"));
+            if ("scroll" != settings.event 
+                         || $.belowthefold(self, settings) 
+                         || $.rightoffold(self, settings)) {
+                if (settings.placeholder) {
+                    $(self).attr("src", settings.placeholder);      
+                } else {
+                    $(self).removeAttr("src");
+                }
+                self.loaded = false;
+            } else {
+                self.loaded = true;
+            }
+            
+            /* When appear is triggered load original image. */
+            $(self).one("appear", function() {
+                if (!this.loaded) {
+                    $("<img />")
+                        .bind("load", function() {
+                            $(self)
+                                .hide()
+                                .attr("src", $(self).attr("original"))
+                                [settings.effect](settings.effectspeed);
+                            self.loaded = true;
+                        })
+                        .attr("src", $(self).attr("original"));
+                };
+            });
+
+            /* When wanted event is triggered load original image */
+            /* by triggering appear.                              */
+            if ("scroll" != settings.event) {
+                $(self).bind(settings.event, function(event) {
+                    if (!self.loaded) {
+                        $(self).trigger("appear");
+                    }
+                });
+            }
+        });
+
+    };
+
+    /* Convenience methods in jQuery namespace.           */
+    /* Use as  $.belowthefold(element, {threshold : 100, container : window}) */
+
+    $.belowthefold = function(element, settings) {
+        if (settings.container === undefined || settings.container === window) {
+            var fold = $(window).height() + $(window).scrollTop();
+        }
+        else {
+            var fold = $(settings.container).offset().top + $(settings.container).height();
+        }
+        return fold <= $(element).offset().top - settings.threshold;
+    };
+    
+    $.rightoffold = function(element, settings) {
+        if (settings.container === undefined || settings.container === window) {
+            var fold = $(window).width() + $(window).scrollLeft();
+        }
+        else {
+            var fold = $(settings.container).offset().left + $(settings.container).width();
+        }
+        return fold <= $(element).offset().left - settings.threshold;
+    };
+    
+    $.aboveViewport = function(element, settings) {
+        if (settings.container === undefined || settings.container === window) {
+            var top = $(window).scrollTop();
+        }
+        else {
+            var top = $(settings.container).offset().top;
+        }
+        return top >= $(element).offset().bottom - settings.threshold;
+    };
+    
+    /* Custom selectors for your convenience.   */
+    /* Use as $("img:below-the-fold").something() */
+
+    $.extend($.expr[':'], {
+        "below-the-fold" : "$.belowthefold(a, {threshold : 0, container: window})",
+        "above-the-fold" : "!$.belowthefold(a, {threshold : 0, container: window})",
+        "right-of-fold"  : "$.rightoffold(a, {threshold : 0, container: window})",
+        "left-of-fold"   : "!$.rightoffold(a, {threshold : 0, container: window})"
+    });
+    
+})(jQuery);
index 7e2457b..515a02e 100644 (file)
@@ -5,6 +5,7 @@
         <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
         <title>{% block title %}Platforma Redakcyjna{% endblock %}</title>
         <link rel="stylesheet" href="/static/css/master.css" type="text/css" />
         <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
         <title>{% block title %}Platforma Redakcyjna{% endblock %}</title>
         <link rel="stylesheet" href="/static/css/master.css" type="text/css" />
+        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js" type="text/javascript" charset="utf-8"></script>
         {% block extrahead %}
         {% endblock %}
     </head>
         {% block extrahead %}
         {% endblock %}
     </head>
index 8fed082..7e126f0 100644 (file)
@@ -1,9 +1,63 @@
 {% extends "base.html" %}
 
 {% extends "base.html" %}
 
+{% block extrahead %}
+    <script src="/static/js/jquery.lazyload.js" type="text/javascript" charset="utf-8"></script>
+    <script type="text/javascript" charset="utf-8">        
+        function aboveViewport(container, element, treshold) {
+            return $(container).offset().top >= $(element).offset().top + $(element).height() + treshold;
+        }
+        
+        function belowViewport(container, element, treshold) {
+            return $(container).offset().top + $(container).height() + treshold <= $(element).offset().top;
+        }
+        
+        var TRESHOLD = 600;
+        var lastScroll = -1000;
+                    
+        function checkScroll() {
+            console.log('checkScroll', $('#images').scrollTop(), lastScroll);
+            
+            if (Math.abs($('#images').scrollTop() - lastScroll) > 300) {
+                console.log('checking!');
+                
+                var container = $('#images');
+                lastScroll = container.scrollTop();
+                
+                $('#images .image-box').each(function() {
+                    if (aboveViewport(container, this, TRESHOLD)) {
+                        $(this).html('loading...');
+                    } else if (belowViewport(container, this, TRESHOLD)) {
+                        $(this).html('loading...');
+                    } else {
+                        $(this).html('<img src="' + $(this).attr('src') + '" width="460" height="460"/>');
+                    }
+                })
+            }
+            setTimeout(checkScroll, 2000);
+        }
+        
+        $(function() {
+            $('#id_folders').change(function() {
+                $('#images').load('/images/' + $('#id_folders').val() + '/', function() {
+                    lastScroll = -1000;
+                });
+            });
+            
+            setTimeout(checkScroll, 2000);
+        });
+    </script>
+{% endblock extrahead %}
+
 {% block breadcrumbs %}<a href="/">Platforma Redakcyjna</a> ❯ plik {{ hash }}{% endblock breadcrumbs %}
 
 {% block maincontent %}
 {% block breadcrumbs %}<a href="/">Platforma Redakcyjna</a> ❯ plik {{ hash }}{% endblock breadcrumbs %}
 
 {% block maincontent %}
-    <div id="tabs"><a href="{% url file_xml hash %}">Źródło</a><a href="{% url file_html hash %}" class="active">HTML</a><div style="clear: both; height: 0; width: 0">&nbsp;</div></div>
+    <div id="tabs"><a href="{% url file_xml hash %}">Źródło</a><a href="{% url file_html hash %}" class="active">HTML</a><div style="padding: 3px; margin-left: 10px">{{ image_folders_form.folders }}</div><div style="clear: both; height: 0; width: 0">&nbsp;</div></div>    
+
+    <div id="images">
+        <div class="image-box">
+            <p>Aby zobaczyć obrazki wybierz folder z obrazkami powyżej.</p>
+        </div>
+    </div>
     <div id="file-text">
     {{ object|safe }}
     </div>
     <div id="file-text">
     {{ object|safe }}
     </div>
index 14ae61e..3f50659 100644 (file)
@@ -1,11 +1,65 @@
 {% extends "base.html" %}
 
 {% extends "base.html" %}
 
+{% block extrahead %}
+    <script src="/static/js/jquery.lazyload.js" type="text/javascript" charset="utf-8"></script>
+    <script type="text/javascript" charset="utf-8">        
+        function aboveViewport(container, element, treshold) {
+            return $(container).offset().top >= $(element).offset().top + $(element).height() + treshold;
+        }
+        
+        function belowViewport(container, element, treshold) {
+            return $(container).offset().top + $(container).height() + treshold <= $(element).offset().top;
+        }
+        
+        var TRESHOLD = 600;
+        var lastScroll = -1000;
+                    
+        function checkScroll() {
+            console.log('checkScroll', $('#images').scrollTop(), lastScroll);
+            
+            if (Math.abs($('#images').scrollTop() - lastScroll) > 300) {
+                console.log('checking!');
+                
+                var container = $('#images');
+                lastScroll = container.scrollTop();
+                
+                $('#images .image-box').each(function() {
+                    if (aboveViewport(container, this, TRESHOLD)) {
+                        $(this).html('loading...');
+                    } else if (belowViewport(container, this, TRESHOLD)) {
+                        $(this).html('loading...');
+                    } else {
+                        $(this).html('<img src="' + $(this).attr('src') + '" width="460" height="460"/>');
+                    }
+                })
+            }
+            setTimeout(checkScroll, 2000);
+        }
+        
+        $(function() {
+            $('#id_folders').change(function() {
+                $('#images').load('/images/' + $('#id_folders').val() + '/', function() {
+                    lastScroll = -1000;
+                });
+            });
+            
+            setTimeout(checkScroll, 2000);
+        });
+    </script>
+{% endblock extrahead %}
+
 {% block breadcrumbs %}<a href="/">Platforma Redakcyjna</a> ❯ plik {{ hash }}{% endblock breadcrumbs %}
 
 {% block maincontent %}
 {% block breadcrumbs %}<a href="/">Platforma Redakcyjna</a> ❯ plik {{ hash }}{% endblock breadcrumbs %}
 
 {% block maincontent %}
-    <div id="tabs"><a href="{% url file_xml hash %}" class="active">Źródło</a><a href="{% url file_html hash %}">HTML</a><div style="clear: both; height: 0; width: 0">&nbsp;</div></div>    
+    <div id="tabs"><a href="{% url file_xml hash %}" class="active">Źródło</a><a href="{% url file_html hash %}">HTML</a>    <div style="padding: 3px; margin-left: 10px">{{ image_folders_form.folders }}</div><div style="clear: both; height: 0; width: 0">&nbsp;</div></div>    
+
+    <div id="images">
+        <div class="image-box">
+            <p>Aby zobaczyć obrazki wybierz folder z obrazkami powyżej.</p>
+        </div>
+    </div>
     <form action="." method="post" accept-charset="utf-8">
     <form action="." method="post" accept-charset="utf-8">
-        {{ form }}
+        {{ form.text }}
         <p><input type="submit" value="Zapisz"/></p>
     </form>
 {% endblock maincontent %}    
         <p><input type="submit" value="Zapisz"/></p>
     </form>
 {% endblock maincontent %}    
diff --git a/project/templates/explorer/folder_images.html b/project/templates/explorer/folder_images.html
new file mode 100644 (file)
index 0000000..e6beb07
--- /dev/null
@@ -0,0 +1,5 @@
+{% for image in images %}
+    <div class="image-box" src="{{ image }}" style="width: 460px; height: 460px; margin: 5px; background-color: gray">
+        <p>{{ image }}</p>
+    </div>
+{% endfor %}
\ No newline at end of file
index c3b14c8..3b75849 100644 (file)
@@ -10,8 +10,9 @@ urlpatterns = patterns('',
     # Example:
     url(r'^$', 'explorer.views.file_list', name='file_list'),
     url(r'^file/(?P<path>[^/]+)/$', 'explorer.views.file_xml', name='file_xml'),
     # Example:
     url(r'^$', 'explorer.views.file_list', name='file_list'),
     url(r'^file/(?P<path>[^/]+)/$', 'explorer.views.file_xml', name='file_xml'),
-    url(r'^html/(?P<path>[^/]+)/', 'explorer.views.file_html', name='file_html'),
-
+    url(r'^html/(?P<path>[^/]+)/$', 'explorer.views.file_html', name='file_html'),
+    url(r'^images/(?P<folder>[^/]+)/$', 'explorer.views.folder_images', name='folder_image'),
+    
     # Admin panel
     url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
     url(r'^admin/(.*)', admin.site.root),
     # Admin panel
     url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
     url(r'^admin/(.*)', admin.site.root),