Ajax Scroll Loading
authorveltr
Wed, 11 Sep 2013 17:52:17 +0200
changeset 106 219e27e5e26d
parent 105 d9434a9d7130
child 107 e30c9bfaf945
child 108 c0d227e8b0c4
Ajax Scroll Loading
src/jocondelab/management/commands/import_dbpedia_geo_years.py
src/jocondelab/settings.py
src/jocondelab/static/jocondelab/css/front-common.css
src/jocondelab/static/jocondelab/img/flag_br.png
src/jocondelab/static/jocondelab/img/flag_ca.png
src/jocondelab/static/jocondelab/img/flag_de.png
src/jocondelab/static/jocondelab/img/flag_en.png
src/jocondelab/static/jocondelab/img/flag_es.png
src/jocondelab/static/jocondelab/img/flag_eu.png
src/jocondelab/static/jocondelab/img/flag_fr.png
src/jocondelab/static/jocondelab/img/flag_it.png
src/jocondelab/static/jocondelab/img/flag_ja.png
src/jocondelab/static/jocondelab/img/flag_pt.png
src/jocondelab/static/jocondelab/img/flag_zh.png
src/jocondelab/static/jocondelab/img/loader.gif
src/jocondelab/static/jocondelab/js/front-common.js
src/jocondelab/static/jocondelab/js/front-geo.js
src/jocondelab/static/jocondelab/js/front-notice.js
src/jocondelab/static/jocondelab/js/front-search.js
src/jocondelab/static/jocondelab/js/front-timeline.js
src/jocondelab/templates/jocondelab/ajax_contents.html
src/jocondelab/templates/jocondelab/front_base.html
src/jocondelab/templates/jocondelab/front_geo.html
src/jocondelab/templates/jocondelab/front_notice.html
src/jocondelab/templates/jocondelab/front_search.html
src/jocondelab/templates/jocondelab/front_timeline.html
src/jocondelab/templates/jocondelab/partial/datasheet_row.html
src/jocondelab/templates/jocondelab/partial/notice_list.html
src/jocondelab/templates/jocondelab/partial/wrapped_notice_list.html
src/jocondelab/templatetags/__init__.py
src/jocondelab/templatetags/jlutils.py
src/jocondelab/urls.py
src/jocondelab/views/ajax.py
src/jocondelab/views/front_office.py
--- a/src/jocondelab/management/commands/import_dbpedia_geo_years.py	Mon Sep 09 18:13:02 2013 +0200
+++ b/src/jocondelab/management/commands/import_dbpedia_geo_years.py	Wed Sep 11 17:52:17 2013 +0200
@@ -56,14 +56,10 @@
     select distinct * where {
         OPTIONAL {
           <%s> dbpedia-owl:activeYearsStartYear ?startyear .
-        }
-        OPTIONAL {
           <%s> dbpedia-owl:activeYearsEndYear ?endyear .
         }
         OPTIONAL {
           <%s> dbpedia-owl:birthDate ?birthdate .
-        }
-        OPTIONAL {
           <%s> dbpedia-owl:deathDate ?deathdate .
         }
         OPTIONAL {
--- a/src/jocondelab/settings.py	Mon Sep 09 18:13:02 2013 +0200
+++ b/src/jocondelab/settings.py	Wed Sep 11 17:52:17 2013 +0200
@@ -41,6 +41,16 @@
 LANGUAGES = ( 
     ('fr', ugettext('French')),
     ('en', ugettext('English')),
+    ('it', ugettext('Italian')),
+    ('es', ugettext('Spanish')),
+    ('de', ugettext('German')),
+    ('pt', ugettext('Portuguese')),
+    ('ar', ugettext('Arabic')),
+    ('zh-cn', ugettext('Chinese')),
+    ('ja', ugettext('Japanese')),
+    ('ca', ugettext('Catalan')),
+    ('eu', ugettext('Basque')),
+    ('br', ugettext('Breton')),
 )
 
 
--- a/src/jocondelab/static/jocondelab/css/front-common.css	Mon Sep 09 18:13:02 2013 +0200
+++ b/src/jocondelab/static/jocondelab/css/front-common.css	Wed Sep 11 17:52:17 2013 +0200
@@ -113,10 +113,6 @@
     font-family: 'OpenSans'; font-size: 10px; overflow-x: hidden;
 }
 
-.menus-container {
-    position: absolute; top: 70px; left: 0; width: 100%; z-index: 20;
-}
-
 .header-wrapper, .menus-wrapper, .main-wrapper {
     padding: 0 10px;
 }
@@ -182,6 +178,7 @@
 .search-input, .search-form .tagit {
     border-radius: 8px; box-shadow: 1px 1px 1px #666666 inset; border: none;
     background: url(../img/search-icon.png) right center no-repeat #ffffff;
+    overflow: hidden;
 }
 
 .header-search-input, .header-search-form .tagit {
@@ -324,4 +321,16 @@
 
 .notice-term:hover {
     background: #ffffff;
-}
\ No newline at end of file
+}
+
+.loading-please-wait {
+    display: none; width: 48px; height: 48px; margin: 10px auto;
+}
+
+.loading-please-wait img {
+    width: 100%; height: 100%;
+}
+
+.load-more {
+    display: none; margin: 20px 0 10px; text-align: center; font-size: 14px; font-weight: 700;
+}
Binary file src/jocondelab/static/jocondelab/img/flag_br.png has changed
Binary file src/jocondelab/static/jocondelab/img/flag_ca.png has changed
Binary file src/jocondelab/static/jocondelab/img/flag_de.png has changed
Binary file src/jocondelab/static/jocondelab/img/flag_en.png has changed
Binary file src/jocondelab/static/jocondelab/img/flag_es.png has changed
Binary file src/jocondelab/static/jocondelab/img/flag_eu.png has changed
Binary file src/jocondelab/static/jocondelab/img/flag_fr.png has changed
Binary file src/jocondelab/static/jocondelab/img/flag_it.png has changed
Binary file src/jocondelab/static/jocondelab/img/flag_ja.png has changed
Binary file src/jocondelab/static/jocondelab/img/flag_pt.png has changed
Binary file src/jocondelab/static/jocondelab/img/flag_zh.png has changed
Binary file src/jocondelab/static/jocondelab/img/loader.gif has changed
--- a/src/jocondelab/static/jocondelab/js/front-common.js	Mon Sep 09 18:13:02 2013 +0200
+++ b/src/jocondelab/static/jocondelab/js/front-common.js	Wed Sep 11 17:52:17 2013 +0200
@@ -50,14 +50,14 @@
         $abstract = $overlay.find(".dbpedia-abstract"),
         $source = $overlay.find(".dbpedia-source a");
     
-    window.setDbpediaBoxAnchor = function(a) {
+    function setDbpediaBoxAnchor(a) {
         anchor = a || null;
         if (anchor) {
             recentreDbpediaBox();
         }
     }
     
-    window.recentreDbpediaBox = function() {
+    function recentreDbpediaBox() {
         if (!anchor) { return; }
         var ovw = $overlay.outerWidth(),
             ovh = $overlay.outerHeight();
@@ -98,7 +98,7 @@
         }
     }
         
-    window.showDbpediaBox = function(dbpediaUri, cancelClose) {
+    function showDbpediaBox(dbpediaUri, cancelClose) {
         if (!dbpediaUri) {
             return;
         }
@@ -150,23 +150,23 @@
             }
             dbpediaCache[dbpediaUri] = cacheData;
             if (hovering === dbpediaUri) {
-                window.showDbpediaBox(dbpediaUri);
+                showDbpediaBox(dbpediaUri);
             }
         });
     }
         
-    window.hideDbpediaBox = function() {
+    function hideDbpediaBox() {
         hovering = null;
         setTimeout(function() {
             if (!hovering) {
                 $overlay.hide();
-                window.setDbpediaBoxAnchor();
+                setDbpediaBoxAnchor();
                 deferredRemovePopin();
             }
         }, 0);
     }
     
-    window.bindDbpediaBox = function(selector, defaultUri) {
+    function bindDbpediaBox(selector, defaultUri) {
         var $sel = $(selector);
         $sel.off("mouseenter mouseleave");
         $sel.mouseenter(function(e) {
@@ -176,10 +176,10 @@
             if (!dbpediaUri || dbpediaUri === "None") {
                 return;
             }
-            window.showDbpediaBox(dbpediaUri);
+            showDbpediaBox(dbpediaUri);
         });
-        $sel.mouseleave(window.hideDbpediaBox);
-    }    
+        $sel.mouseleave(hideDbpediaBox);
+    }
         
     $overlay.hover(function() {
         var $this = $(this),
@@ -189,10 +189,18 @@
         }
     }, function() {
         if (!dontclose) {
-            window.hideDbpediaBox();
+            hideDbpediaBox();
         }
     });
     
+    window.dbpediaBox = {
+        bind: bindDbpediaBox,
+        hide: hideDbpediaBox,
+        show: showDbpediaBox,
+        setAnchor: setDbpediaBoxAnchor,
+        recentre: recentreDbpediaBox
+    }
+    
     /* END DBPEDIA OVERLAY MANAGEMENT */
    
     /* NOTICE LIST MANAGEMENT */
@@ -298,6 +306,65 @@
         adaptGrid();
     }
     
+    /* AJAX SCROLL LOAD */
+    
+    var max_scroll_pages = 3;
+    
+    window.scrollLoad = function(data) {
+        var loadingnext = false,
+            currentpage = parseInt($(".notice-list").attr("data-current-page")),
+            page_count = parseInt($(".notice-list").attr("data-page-count")),
+            max_page = Math.min(currentpage + max_scroll_pages, page_count),
+            margin = 20;
+        $win.on("scroll.ajaxload", function() {
+            if (loadingnext || currentpage >= max_page) {
+                return;
+            }
+            var $datablock = $(".notice-list"),
+                winbottom = $win.scrollTop() + $win.height(),
+                databottom = $datablock.offset().top + $datablock.height();
+            if (winbottom > databottom - margin) {
+                loadingnext = true;
+                $(".loading-please-wait").show();
+                $.ajax({
+                    url: urls.ajax_search,
+                    data: _({ page: ++currentpage }).extend(data),
+                    dataType: "html",
+                    success: function(html) {
+                        $datablock.append(html);
+                        loadingnext = false;
+                        bindResultsMouseover();
+                        $(".loading-please-wait").hide();
+                        if (currentpage >= max_page && currentpage < page_count) {
+                            $(".load-more").show().find("a").attr("href",
+                                urls.ajax_search + "?" + $.param(_({ page: currentpage + 1 }).extend(data))
+                            );
+                        }
+                    }
+                });
+            }
+        });
+    }
+    
+    window.loadContentsByUri = function(dbpedia_uri) {
+        $win.off("scroll.ajaxload");
+        $(".results").empty();
+        $.ajax({
+            url: urls.ajax_search,
+            data: {
+                dbpedia_uri: dbpedia_uri
+            },
+            dataType: "html",
+            success: function(html) {
+                $(".results").html(html);
+                bindResultsMouseover();
+                scrollLoad({ dbpedia_uri: dbpedia_uri });
+            }
+        });
+    }
+    /* */
+    
+    
     $win.resize(function() {
         adaptGrid();
         recentreDbpediaBox();
@@ -305,24 +372,28 @@
     
     $overlayImg.load(recentreDbpediaBox);
     
-    $(".menu-link a").mouseenter(function() {
-        $($(this).attr("href")).stop(true).slideDown();
-    }).mouseleave(function() {
-        $($(this).attr("href")).stop(true).delay(3000).slideUp();
+    $(".menu-link a").mouseover(function() {
+        var $menu = $($(this).attr("href"));
+        $menu.stop(true).slideDown(function(){ $menu.css("height",""); });
+    }).mouseout(function() {
+        var $menu = $($(this).attr("href"));
+        $menu.stop(true).delay(3000).slideUp(function(){ $menu.css("height",""); });
     }).click(function() {
         return false;
     });
     
-    $(".menu-list").mouseenter(function() {
-        $(this).stop(true).slideDown();
-    }).mouseleave(function() {
-        $(this).stop(true).delay(3000).slideUp();
+    $(".menu-list").mouseover(function() {
+        $menu = $(this);
+        $menu.stop(true).show().css("height","");
+    }).mouseout(function() {
+        $menu = $(this);
+        $menu.stop(true).delay(3000).slideUp(function(){ $menu.css("height",""); });
     });
     
     $("#language-menu a").click(function() {
         $(".language-input").val($(this).attr("data-language-code"));
         $(".language-form").submit();
         return false;
-    })
+    });
     
 });
--- a/src/jocondelab/static/jocondelab/js/front-geo.js	Mon Sep 09 18:13:02 2013 +0200
+++ b/src/jocondelab/static/jocondelab/js/front-geo.js	Wed Sep 11 17:52:17 2013 +0200
@@ -63,11 +63,8 @@
             }
         })
         stickyFeature = feature;
-        console.log("Set sticky on", feature.dbpedia_uri);
         showDbpedia(feature);
-        $(".results").empty().load(
-            urls.ajax_contents + "?random=1&dbpedia_uri=" + encodeURIComponent(feature.dbpedia_uri)
-        );
+        loadContentsByUri(feature.dbpedia_uri);
     }
     
     function selectMarker(coord) {
@@ -90,11 +87,11 @@
         }
         currentFeature = feature;
         if (!feature) {
-            window.hideDbpediaBox();
+            dbpediaBox.hide();
             return;
         }
-        window.showDbpediaBox(feature.dbpedia_uri, (feature === stickyFeature));
-        window.setDbpediaBoxAnchor({type: "callback", callback: moveCurrentFeature, positioning: "bottom"});
+        dbpediaBox.show(feature.dbpedia_uri, (feature === stickyFeature));
+        dbpediaBox.setAnchor({type: "callback", callback: moveCurrentFeature, positioning: "bottom"});
         throttledMove();
     }
     
@@ -126,15 +123,15 @@
         return ({ top: y - (fb ? 0 : 30), left: p.x + mo.left, bottom: y });
     }
     
-    var throttledMove = _.throttle(window.recentreDbpediaBox,200);
+    var throttledMove = _.throttle(dbpediaBox.recentre,200);
     
     function hideDbpedia(force) {
         if (!stickyFeature) {
             currentFeature = null;
         }
         if (!stickyFeature || force) {
-            window.setDbpediaBoxAnchor();
-            window.hideDbpediaBox();
+            dbpediaBox.setAnchor();
+            dbpediaBox.hide();
         }
     }
     
--- a/src/jocondelab/static/jocondelab/js/front-notice.js	Mon Sep 09 18:13:02 2013 +0200
+++ b/src/jocondelab/static/jocondelab/js/front-notice.js	Wed Sep 11 17:52:17 2013 +0200
@@ -1,7 +1,7 @@
 $(function() {
         
     $('.notice-images a').magnificPopup({type:'image'});
-    bindDbpediaBox(".notice-term a");
+    dbpediaBox.bind(".notice-term a");
     
     var lang = document.querySelector("html").lang.substr(0,2) || "en",
         labelsCache = {},
@@ -232,7 +232,7 @@
             getDbpedia(ui.item.label, function(label, termdata) {
                 $newItem.find(".term-link").text(gettext("Saving contribution…"));
                 if (termdata.dbpedia_uri) {
-                    bindDbpediaBox($newItem.find("term-link"), termdata.dbpedia_uri);
+                    dbpediaBox.bind($newItem.find("term-link"), termdata.dbpedia_uri);
                     $.ajax({
                         url: urls.ajax_contribute,
                         dataType: "json",
--- a/src/jocondelab/static/jocondelab/js/front-search.js	Mon Sep 09 18:13:02 2013 +0200
+++ b/src/jocondelab/static/jocondelab/js/front-search.js	Wed Sep 11 17:52:17 2013 +0200
@@ -5,6 +5,9 @@
 $(function() {
     
     bindResultsMouseover();
-    bindDbpediaBox(".term-cloud a");
+    dbpediaBox.bind(".term-cloud a");
+    if (searchterm) {
+        scrollLoad({ q: searchterm });
+    }
     
 });
--- a/src/jocondelab/static/jocondelab/js/front-timeline.js	Mon Sep 09 18:13:02 2013 +0200
+++ b/src/jocondelab/static/jocondelab/js/front-timeline.js	Wed Sep 11 17:52:17 2013 +0200
@@ -78,15 +78,13 @@
                 });
             }).value().join("");
         $(".timeline-list").html(html);
-        bindDbpediaBox(".timeline-item-box");
+        dbpediaBox.bind(".timeline-item-box");
         $(".timeline-item-box").click(function() {
             var $this = $(this);
             currentTerm = $this.attr("data-dbpedia-uri")
             $(".timeline-item-box").removeClass("timeline-current");
             $this.addClass("timeline-current");
-            $(".results").empty().load(
-                urls.ajax_contents + "?random=1&dbpedia_uri=" + encodeURIComponent(currentTerm)
-            );
+            loadContentsByUri(currentTerm);
         })
     }
     
--- a/src/jocondelab/templates/jocondelab/ajax_contents.html	Mon Sep 09 18:13:02 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-{% load i18n %}
-
-{% include 'jocondelab/partial/notice_list.html' %}
-
-<script type="text/javascript">
-    bindResultsMouseover();
-</script>
\ No newline at end of file
--- a/src/jocondelab/templates/jocondelab/front_base.html	Mon Sep 09 18:13:02 2013 +0200
+++ b/src/jocondelab/templates/jocondelab/front_base.html	Wed Sep 11 17:52:17 2013 +0200
@@ -26,7 +26,10 @@
         
         {% block js_declaration %}
         <script type="text/javascript">
-            var urls = { ajax_terms: "{% url 'ajax_terms' %}" };
+            var urls = {
+                ajax_terms: "{% url 'ajax_terms' %}",
+                ajax_search: "{% url 'front_search' %}"
+            };
         </script>
         <script type="text/javascript" src="{{STATIC_URL}}jocondelab/js/front-common.js"></script>
         {% endblock %}
@@ -58,28 +61,26 @@
             {% csrf_token %}
             <input class="language-input" type="hidden" name="language" value="{% if lang %}{{lang|slice:':2'}}{% else %}{{LANGUAGE_CODE|slice:':2'}}{% endif %}" />
         </form>
-        <div class="menus-container">
-            <div class="menus-wrapper">
-                <ul class="menu-list" id="main-menu">
-                    <li class="menu-item">
-                        <a href="{% url 'front_search' %}">{% trans 'Multilingual search' %}</a>
-                    </li>
-                    <li class="menu-item">
-                        <a href="{% url 'front_timeline' %}">{% trans 'Timeline' %}</a>
-                    </li>
-                    <li class="menu-item">
-                        <a href="{% url 'front_geo' %}">{% trans 'World map' %}</a>
-                    </li>
-                </ul>
-                <ul class="menu-list" id="language-menu">
-                {% get_language_info_list for LANGUAGES as languages %}
-                {% for language in languages %}
-                    <li class="menu-item">
-                        <a href="#" data-language-code="{{ language.code }}">{{ language.name_local }}</a>
-                    </li>
-                {% endfor %}
-                </ul>
-            </div>
+        <div class="menus-wrapper">
+            <ul class="menu-list" id="main-menu">
+                <li class="menu-item">
+                    <a href="{% url 'front_search' %}">{% trans 'Multilingual search' %}</a>
+                </li>
+                <li class="menu-item">
+                    <a href="{% url 'front_timeline' %}">{% trans 'Timeline' %}</a>
+                </li>
+                <li class="menu-item">
+                    <a href="{% url 'front_geo' %}">{% trans 'World map' %}</a>
+                </li>
+            </ul>
+            <ul class="menu-list" id="language-menu">
+            {% get_language_info_list for LANGUAGES as languages %}
+            {% for language in languages %}
+                <li class="menu-item">
+                    <a href="#" data-language-code="{{ language.code }}">{{ language.name_local }}</a>
+                </li>
+            {% endfor %}
+            </ul>
         </div>
         <div class="main-wrapper">
             <section class="main">
--- a/src/jocondelab/templates/jocondelab/front_geo.html	Mon Sep 09 18:13:02 2013 +0200
+++ b/src/jocondelab/templates/jocondelab/front_geo.html	Wed Sep 11 17:52:17 2013 +0200
@@ -18,7 +18,6 @@
         urls.orange_marker = "{{STATIC_URL}}jocondelab/lib/images/marker-orange.png";
         urls.ajax_geo_coords = "{% url 'ajax_geo_coords' %}";
         urls.ajax_geo_search = "{% url 'ajax_geo_search' %}";
-        urls.ajax_contents = "{% url 'ajax_contents' %}";
         urls.countries_geo_json = "{{STATIC_URL}}jocondelab/lib/countries.geo.json";
         var countries = {{countries|safe}};
     </script>
@@ -43,4 +42,8 @@
             </div>
             
             <div class="results"></div>
+            
+            <div class="loading-please-wait"><img src="{{STATIC_URL}}jocondelab/img/loader.gif" /></div>
+            <p class="load-more"><a href="#">{% trans 'Show more results' %}</a></p>
+            
 {% endblock %}
--- a/src/jocondelab/templates/jocondelab/front_notice.html	Mon Sep 09 18:13:02 2013 +0200
+++ b/src/jocondelab/templates/jocondelab/front_notice.html	Wed Sep 11 17:52:17 2013 +0200
@@ -1,6 +1,6 @@
 {% extends "jocondelab/front_base.html" %}
 {% load i18n %}
-{% load l10n %}
+{% load jlutils %}
 
 {% block js_import %}
     {{block.super}}
@@ -45,62 +45,39 @@
             </ul>
             
             <table class="notice-datasheet">
-            {% if object.titr %}
-                <tr class="notice-title">
-                    <th>{% trans 'Title:' %}</th>
-                    <td>{{object.titr}}</td>
-                </tr>
-            {% endif %}
-            {% if object.deno %}
-                <tr {% if not object.titr %}class="notice-title"{% endif %}>
-                    <th>{% trans 'Denomination:' %}</th>
-                    <td>{{object.deno}}</td>
-                </tr>
-            {% endif %}
-            {% for thesaurus, terms in terms_by_thesaurus.items %}
-                <tr>
-                     <th>{% trans thesaurus context 'Thesaurus label' %}{% trans ':' %}</th>
-                     <td>
-                         <ul class="notice-term-list">
-                         {% for termtype, terms in terms.items %}
-                            {% for term in terms %}
-                            <li class="notice-term term-{{termtype}}"><a href="{% url 'front_search' %}?q={{term.locale_label|urlencode}}" data-dbpedia-uri="{{term.dbpedia_uri}}">{{term.locale_label}}</a></li>
-                            {% endfor %}
-                         {% endfor %}
-                         </ul>
-                     </td>
-                </tr>
-            {% endfor %}
-            {% if object.desc %}
-                <tr>
-                    <th>{% trans 'Description:' %}</th>
-                    <td>{{object.desc}}</td>
-                </tr>
-            {% endif %}
-            {% if object.hist %}
-                <tr>
-                    <th>{% trans 'History:' %}</th>
-                    <td>{{object.hist}}</td>
-                </tr>
-            {% endif %}
-            {% if object.loca %}
-                <tr>
-                    <th>{% trans 'Conservation location:' %}</th>
-                    <td>{{object.loca}}</td>
-                </tr>
-            {% endif %}
-            {% if object.copy %}
-                <tr class="datasheet-small">
-                    <th>{% trans 'Datasheet rights:' %}</th>
-                    <td>{{object.copy}}</td>
-                </tr>
-            {% endif %}
-            {% if object.phot %}
-                <tr class="datasheet-item datasheet-small">
-                    <th>{% trans 'Images rights:' %}</th>
-                    <td>{{object.phot}}</td>
-                </tr>
-            {% endif %}
+            
+            {% show_datasheet_row 'AUTR' rowclass='notice-title' %}
+                        
+            {% show_datasheet_row 'ECOL' %}
+            
+            {% show_datasheet_row 'DOMN' %}
+            
+            {% show_datasheet_row 'TITR' rowclass='notice-title' %}
+            {% show_datasheet_row 'APPL' rowclass='notice-title' %}
+            {% show_datasheet_row 'DENO' rowclass='notice-title' %}
+            
+            {% show_datasheet_row 'REPR' %}
+            {% show_datasheet_row 'SREP' %}
+            
+            {% show_datasheet_row 'PERI' %}
+            {% show_datasheet_row 'MILL' %}
+            {% show_datasheet_row 'EPOQ' %}
+            
+            {% show_datasheet_row 'TECH' %}
+            
+            {% show_datasheet_row 'DIMS' %}
+            
+            {% show_datasheet_row 'LIEUX' %}
+            
+            {% show_datasheet_row 'DECV' %}
+            
+            {% show_datasheet_row 'HIST' %}
+            
+            {% show_datasheet_row 'LOCA' %}
+            
+            {% show_datasheet_row 'COPY' %}
+            {% show_datasheet_row 'PHOT' %}
+
             </table>
             
             <h2 style="float: left; padding: 20px 20px 0; font-size: 18px; font-weight : 800;">Contribuer</h2>
--- a/src/jocondelab/templates/jocondelab/front_search.html	Mon Sep 09 18:13:02 2013 +0200
+++ b/src/jocondelab/templates/jocondelab/front_search.html	Wed Sep 11 17:52:17 2013 +0200
@@ -5,6 +5,9 @@
 {% block js_declaration %}
     {{block.super}}
     <script type="text/javascript" src="{{STATIC_URL}}jocondelab/js/front-search.js"></script>
+    <script type="text/javascript">
+        var searchterm = "{{searchterm|safe}}";
+    </script>
 {% endblock %}
 
 {% block css_declaration %}
@@ -24,7 +27,7 @@
                 <input class="big-search-input search-input" type="search" name="q" value="{{searchterm}}" />
             </form>
             
-            {% if not searchterm %}
+            {% if words %}
             <ul class="term-cloud">
                 {% for word in words %}
                     <li style="font-size: {{word.font_size|unlocalize}}em">
@@ -34,6 +37,9 @@
             </ul>
             {% endif %}
             
-            {% include 'jocondelab/partial/notice_list.html' %}
+            {% include 'jocondelab/partial/wrapped_notice_list.html' %}
+            
+            <div class="loading-please-wait"><img src="{{STATIC_URL}}jocondelab/img/loader.gif" /></div>
+            <p class="load-more"><a href="#">{% trans 'Show more results' %}</a></p>
             
 {% endblock %}
--- a/src/jocondelab/templates/jocondelab/front_timeline.html	Mon Sep 09 18:13:02 2013 +0200
+++ b/src/jocondelab/templates/jocondelab/front_timeline.html	Wed Sep 11 17:52:17 2013 +0200
@@ -11,7 +11,6 @@
     {{block.super}}
     <script type="text/javascript">
         urls.ajax_years = "{% url 'ajax_years' %}";
-        urls.ajax_contents = "{% url 'ajax_contents' %}";
     </script>
     <script type="text/javascript" src="{{STATIC_URL}}jocondelab/js/front-timeline.js"></script>
 {% endblock %}
@@ -31,6 +30,10 @@
                 <canvas class="timeline-canvas"></canvas>
                 <ul class="timeline-list"></ul>
             </div>
-                        
+            
             <div class="results"></div>
+            
+            <div class="loading-please-wait"><img src="{{STATIC_URL}}jocondelab/img/loader.gif" /></div>
+            <p class="load-more"><a href="#">{% trans 'Show more results' %}</a></p>
+            
 {% endblock %}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jocondelab/templates/jocondelab/partial/datasheet_row.html	Wed Sep 11 17:52:17 2013 +0200
@@ -0,0 +1,24 @@
+{% load i18n %}
+
+{% if linked_terms %}
+<tr{% if row_class %} class="{{row_class}}"{% endif %}>
+    <th>{% trans fieldname context 'Thesaurus label' %}{% trans ':' %}</th>
+    <td>
+        <ul class="notice-term-list">
+        {% for termtype, terms in linked_terms.items %}
+            {% for term in terms %}
+            <li class="notice-term term-{{termtype}}">
+                <a href="{% url 'front_search' %}?q={{term.locale_label|urlencode}}" data-dbpedia-uri="{{term.dbpedia_uri}}">{{term.locale_label}}</a>
+            </li>
+            {% endfor %}
+        {% endfor %}
+        </ul>
+    </td>
+</tr>
+{% elif base_field %}
+<tr{% if rowclass %} class="{{row_class}}"{% endif %}>
+    <th>{% trans fieldname context 'Thesaurus label' %}{% trans ':' %}</th>
+    <td>{{base_field}}</td>
+</tr>
+{% endif %}
+
--- a/src/jocondelab/templates/jocondelab/partial/notice_list.html	Mon Sep 09 18:13:02 2013 +0200
+++ b/src/jocondelab/templates/jocondelab/partial/notice_list.html	Wed Sep 11 17:52:17 2013 +0200
@@ -1,8 +1,5 @@
 {% load i18n %}
 
-<h2 class="resultcount"><b>{{count}}</b> {% if searchterm %}{% trans 'results for:' %} <b>{{searchterm}}</b>{% else %}{% trans 'results' %}{% endif %}</h2>
-
-<ul class="notice-list clearfix">
 {% for notice in notices %}
     <li class="notice-item" data-notice-id="{{notice.id}}">
         <div class="notice-contents">
@@ -37,5 +34,4 @@
             </div>
         </div>
     </li>
-{% endfor %}
-</ul>
\ No newline at end of file
+{% endfor %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jocondelab/templates/jocondelab/partial/wrapped_notice_list.html	Wed Sep 11 17:52:17 2013 +0200
@@ -0,0 +1,7 @@
+{% load i18n %}
+
+<h2 class="resultcount"><b>{{count}}</b> {% if searchterm %}{% trans 'results for:' %} <b>{{searchterm}}</b>{% else %}{% trans 'results' %}{% endif %}</h2>
+
+<ul class="notice-list clearfix"{% if page_count %} data-page-count="{{page_count}}"{% endif %} data-current-page="{{current_page}}">
+{% include 'jocondelab/partial/notice_list.html' %}
+</ul>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jocondelab/templatetags/jlutils.py	Wed Sep 11 17:52:17 2013 +0200
@@ -0,0 +1,12 @@
+from django import template
+
+register = template.Library()
+
+@register.inclusion_tag('jocondelab/partial/datasheet_row.html', takes_context=True)
+def show_datasheet_row(context, fieldname, **kwargs):
+    return {
+            "fieldname": fieldname,
+            "linked_terms": context['terms_by_thesaurus'].get(fieldname.upper(),None),
+            "base_field": getattr(context['object'],fieldname.lower()),
+            "row_class": kwargs.get("row_class", None)
+    }
\ No newline at end of file
--- a/src/jocondelab/urls.py	Mon Sep 09 18:13:02 2013 +0200
+++ b/src/jocondelab/urls.py	Wed Sep 11 17:52:17 2013 +0200
@@ -40,7 +40,6 @@
     url(r'^ajax/years/$', 'jocondelab.views.ajax.years', name='ajax_years'),
     url(r'^ajax/geocoords/$', 'jocondelab.views.ajax.geo_coords', name='ajax_geo_coords'),
     url(r'^ajax/geosearch/$', 'jocondelab.views.ajax.geo_search', name='ajax_geo_search'),
-    url(r'^ajax/contents/$', 'jocondelab.views.ajax.contents', name='ajax_contents'),
     url(r'^ajax/contribute/$', 'jocondelab.views.ajax.contribute', name='ajax_contribute'),
 )
 
--- a/src/jocondelab/views/ajax.py	Mon Sep 09 18:13:02 2013 +0200
+++ b/src/jocondelab/views/ajax.py	Wed Sep 11 17:52:17 2013 +0200
@@ -8,11 +8,11 @@
 from jocondelab.models import DbpediaYears, DbpediaGeo, DbpediaFields, ContributedTerm, ContributedFields, Contribution
 from core.models import Notice, Term, Thesaurus
 import django.utils.simplejson as json
+from django.core.paginator import Paginator
 from django.http import HttpResponse
 from django.template.response import TemplateResponse
 from django.db.models import Sum
 from django.conf import settings
-from jocondelab.views.front_office import get_notices
 
 def terms(request):
     
@@ -85,46 +85,6 @@
     
     return HttpResponse(content=json.dumps(results), mimetype='application/json')
 
-def contents(request):
-    
-    lang = request.GET.get('lang', request.LANGUAGE_CODE)[:2]
-    count = request.GET.get('count', 24)
-    random = ("random" in request.GET and request.GET["random"])
-    format = request.GET.get('format', 'text/html')
-    term_id = request.GET.get('term_id', None)
-    dbpedia_uri = request.GET.get('dbpedia_uri', None)
-    
-    qs = Notice.objects.filter(image=True)
-    searchlabel = ""
-    termobj = None
-    if term_id:
-        qs = qs.filter(noticeterm__term_id=term_id)
-        termobj = Term.objects.get(id=term_id)
-    if dbpedia_uri:
-        qs = qs.filter(noticeterm__term__dbpedia_uri=dbpedia_uri)
-        termobj = Term.objects.filter(dbpedia_uri=dbpedia_uri)[0]
-    rescount = qs.count()
-    if random:
-        qs = qs.order_by('?')
-    results = get_notices(qs[:count], lang)
-    if termobj:
-        termtrans = termobj.dbpedia_fields.filter(language_code = lang)
-        searchlabel = termtrans[0].label if termtrans.count() else termobj.label
-    
-    context = {
-               "searchterm": searchlabel,
-               "count": rescount,
-               "notices": results
-            }
-    
-    if format == 'text/html':
-        return TemplateResponse(request, 'jocondelab/ajax_contents.html', context )
-    
-    if format == 'application/json':
-        return HttpResponse(content=json.dumps(context), mimetype='application/json')
-    
-    return HttpResponse(status=400, content='Unknown Format')
-
 def geo_search(request):
     
     lang = request.GET.get('lang', request.LANGUAGE_CODE)[:2]
--- a/src/jocondelab/views/front_office.py	Mon Sep 09 18:13:02 2013 +0200
+++ b/src/jocondelab/views/front_office.py	Wed Sep 11 17:52:17 2013 +0200
@@ -7,6 +7,7 @@
 
 from core.models import (Notice, Thesaurus, Term)
 from jocondelab.models import (DbpediaFields, Country)
+from django.core.paginator import Paginator
 import django.utils.simplejson as json
 from django.conf import settings
 from django.views.generic import View, DetailView
@@ -15,88 +16,93 @@
 import re
 import time
 
-def get_notices(noticeset, lang):
-    notices = []
-    thesauruscache = {t.id: t.label for t in Thesaurus.objects.all()}
-    for n in noticeset:
-        terms = [{
-            "locale_label": ts.term.dbpedia_fields.get(language_code=lang).label,
-            "thesaurus": thesauruscache[ts.term.thesaurus_id],
-            "dbpedia_uri": ts.term.dbpedia_uri
-        } for ts in n.noticeterm_set.filter(term__dbpedia_fields__language_code=lang)]
-        termsbythesaurus = {}
-        for term in terms:
-            if not term["thesaurus"] in termsbythesaurus:
-                termsbythesaurus[term["thesaurus"]] = []
-            termsbythesaurus[term["thesaurus"]].append(term)
-        noticedict = {
-            "id": n.id,
-            "imagetitle": n.titr if n.titr else n.deno,
-            "title": n.titr,
-            "denomination": n.deno,
-            "image": (settings.JOCONDE_IMG_BASE_URL + n.images.all()[0].url) if n.images.count() else "",
-            "authors": re.split("\s?;\s?", n.autr) if n.autr else [],
-            "terms_by_thesaurus": termsbythesaurus
-        }
-        notices.append(noticedict)
-    return notices
-
 class SearchView(View, TemplateResponseMixin):
     
-    template_name = "jocondelab/front_search.html"
-    
     def get(self, request):
-        
-        starttime = time.time()
-        
+                
         context = {}
         lang = request.GET.get('lang',request.LANGUAGE_CODE)[:2]
+        page = request.GET.get('page',1)
         querystr = request.GET.get('q', "")
-        show_tagcloud = request.GET.get('show_tagcloud', True)
+        is_ajax = request.is_ajax()
         queryterms = [s.strip(" ") for s in re.split("[,;]",querystr) if s.strip(" ")]
-        
-        npp = 48 if queryterms else 24
+        dbpedia_uri = request.GET.get('dbpedia_uri', None)
+        emptysearch = (not queryterms and not dbpedia_uri)
+        show_tagcloud = (emptysearch and not is_ajax)
+        npp = request.GET.get('count', 12 if emptysearch else 36)
+        wpp = 50
+        context["current_page"] = page
+        context["lang"] = lang
+        if is_ajax and page > 1:
+            self.template_name = "jocondelab/partial/notice_list.html"
+        else:
+            if is_ajax:
+                self.template_name = "jocondelab/partial/wrapped_notice_list.html"
+            else:
+                self.template_name = "jocondelab/front_search.html"
         
-        if queryterms:
-            qs = Notice.objects.filter(image=True)
-            for term in queryterms:
-                fs = DbpediaFields.objects.filter(label=term, language_code=lang).values('term_id').distinct()
-                qs = qs.filter(noticeterm__term__in=fs)
-            nbnotices = qs.count()
-            ns = qs[:npp]
+        qs = Notice.objects.filter(image=True)
+        if emptysearch:
+            context["count"] = qs.count()
+            ns = qs.order_by('?')[:npp]
         else:
-            qs = Notice.objects.filter(image=True)
-            nbnotices = qs.count()
-            ns = qs.order_by('?')[:npp]
+            if dbpedia_uri:
+                qs = qs.filter(noticeterm__term__dbpedia_uri=dbpedia_uri)
+                if page == 1:
+                    termobj = Term.objects.filter(dbpedia_uri=dbpedia_uri)[0]
+                    if termobj:
+                        termtrans = termobj.dbpedia_fields.filter(language_code = lang)
+                        context["searchterm"] = termtrans[0].label if termtrans.count() else termobj.label
+            if queryterms:
+                context["searchterm"] = querystr
+                for term in queryterms:
+                    fs = DbpediaFields.objects.filter(label=term, language_code=lang).values('term_id').distinct()
+                    qs = qs.filter(noticeterm__term__in=fs)
+            qs = qs.distinct()
+            paginator = Paginator(qs, npp)
+            context["count"] = paginator.count
+            ns = paginator.page(page)
+            context["page_count"] = paginator.num_pages
         
-        context["lang"] = lang
-        context["count"] = nbnotices
-        context["notices"] = get_notices(ns, lang)
-        context["searchterm"] = querystr
+        notices = []
+        thesauruscache = {t.id: t.label for t in Thesaurus.objects.all()}
+        for n in ns:
+            terms = [{
+                "locale_label": ts.term.dbpedia_fields.get(language_code=lang).label,
+                "thesaurus": thesauruscache[ts.term.thesaurus_id],
+                "dbpedia_uri": ts.term.dbpedia_uri
+            } for ts in n.noticeterm_set.filter(term__dbpedia_fields__language_code=lang)]
+            termsbythesaurus = {}
+            for term in terms:
+                if not term["thesaurus"] in termsbythesaurus:
+                    termsbythesaurus[term["thesaurus"]] = []
+                termsbythesaurus[term["thesaurus"]].append(term)
+            noticedict = {
+                "id": n.id,
+                "imagetitle": n.titr if n.titr else n.deno,
+                "title": n.titr,
+                "denomination": n.deno,
+                "image": (settings.JOCONDE_IMG_BASE_URL + n.images.all()[0].url) if n.images.count() else "",
+                "authors": re.split("\s?;\s?", n.autr) if n.autr else [],
+                "terms_by_thesaurus": termsbythesaurus
+            }
+            notices.append(noticedict)
+        context["notices"] = notices
         
-        wpp = 50
-        if show_tagcloud and not queryterms:
+        if show_tagcloud:
             ts = Term.objects.filter(dbpedia_fields__language_code=lang).order_by('-nb_notice')[:wpp]
             words = [{
                 "uri": t.dbpedia_uri,
                 "label": t.dbpedia_fields.get(language_code=lang).label,
                 "notice_count": t.nb_notice
             } for t in ts]
-        else:
-            words = []
-        if words:
             fontmax = 2.5
             fontmin = 1.
             scale = (fontmax - fontmin)/max(1,words[0]["notice_count"]-words[-1]["notice_count"])
-             
             for w in words:
                 w["font_size"] = fontmin + scale * w["notice_count"]
-         
-        context["words"] = words
-        context['JOCONDE_IMG_BASE_URL'] = settings.JOCONDE_IMG_BASE_URL
-        
-        context['duration'] = "%.2f"%(time.time() - starttime)
-        
+            context["words"] = words
+                
         return self.render_to_response(context)
 
 class GeoView(View, TemplateResponseMixin):