Added timeline view
authorveltr
Thu, 22 Aug 2013 16:46:19 +0200
changeset 98 b174c4467f7c
parent 97 e7c675c54816
child 99 dc08f5692d80
Added timeline view
src/jocondelab/static/jocondelab/css/front-common.css
src/jocondelab/static/jocondelab/css/front-timeline.css
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-timeline.js
src/jocondelab/static/jocondelab/lib/jquery.mousewheel.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_search.html
src/jocondelab/templates/jocondelab/front_timeline.html
src/jocondelab/urls.py
src/jocondelab/views/ajax.py
src/jocondelab/views/front_office.py
--- a/src/jocondelab/static/jocondelab/css/front-common.css	Wed Aug 21 19:20:14 2013 +0200
+++ b/src/jocondelab/static/jocondelab/css/front-common.css	Thu Aug 22 16:46:19 2013 +0200
@@ -74,6 +74,10 @@
     text-decoration: underline;
 }
 
+b {
+    font-weight: 800;
+}
+
 /* FONT DECLARATIONS */
 
 @font-face {
@@ -170,36 +174,58 @@
     background: url(../img/search-icon.png) right center no-repeat #ffffff;
 }
 
+/* HEADER > MENUS */
+
+.top-menus {
+    float: right;
+}
+
+.menu-container {
+    float: right; position: relative;
+}
+
+.menu-list {
+    position: absolute; top: 25px; right: 0; background: #ffffff; display: none;
+    font-size: 12px; box-shadow: 1px 1px 3px #333333; z-index: 2; text-align: right;
+}
+
+.menu-item {
+    border-bottom: 1px solid #cccccc; height: 20px;
+    line-height: 20px; padding: 0 5px;
+}
+
+.menu-container:hover .menu-list {
+    display: block;
+}
+
 /* HEADER > FLAGS */
 
-.language-select {
-    position: absolute; text-align: right; top: 5px; height: 22px; right: 0; width: 28px;
-}
-
 .language-current {
-    display: block; margin: 5px 0;
+    display: block; margin: 10px 0 10px 10px;
 }
 
 .language-list {
-    position: absolute; top: 22px; right: 0; background: #ffffff; display: none;
-    font-size: 12px; width: 100px; box-shadow: 1px 1px 3px #333333; z-index: 2;
-}
-
-.language-select:hover .language-list {
-    display: block;
-}
-
-.language-item {
-    border-bottom: 1px solid #cccccc; height: 20px;
+    width: 100px;
 }
 
 .language-label {
-    line-height: 20px; cursor: pointer;
+    cursor: pointer;
 }
 
 .language-button {
     width: 18px; height: 12px; border: none; padding: 0; text-indent: -9999px;
-    float: right; margin: 4px 4px 0 6px; cursor: pointer;
+    float: right; margin: 4px 0 0 6px; cursor: pointer;
+}
+
+/* HEADER > MAIN MENU */
+
+.main-menu-title {
+    display: block; height: 16px; line-height: 16px; font-size: 13px;
+    text-transform: uppercase; margin: 7px;
+}
+
+.main-menu-list {
+    width: 140px;
 }
 
 /* DBPEDIA OVERLAY */
@@ -227,6 +253,10 @@
 
 /* RESULTS LIST */
 
+.resultcount {
+    font-size: 18px; margin: 10px 0;
+}
+
 .notice-list {
     margin: 0 auto;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jocondelab/static/jocondelab/css/front-timeline.css	Thu Aug 22 16:46:19 2013 +0200
@@ -0,0 +1,30 @@
+.timeline-container {
+    position: relative; width: 100%; height: 376px; margin-top: 10px;
+    background: #ffffff; overflow: hidden;
+}
+
+.timeline-canvas {
+    width: 100%; height: 100%;
+}
+
+.timeline-list {
+    position: absolute; left: 0; top: 20px; width: 100%;
+}
+
+.timeline-item {
+    position: relative; height: 28px; width: 100%;
+}
+
+.timeline-item-box {
+    position: absolute; height: 16px; top: 0; margin-bottom: 4px;
+    border-bottom: 8px solid #0000c0; cursor: pointer;
+}
+
+.timeline-item-label {
+    position: absolute; top: 0; text-align: center; width: 200px; margin-left: -100px;
+    font-size: 13px; left: 50%; line-height: 16px;
+}
+
+.timeline-current {
+    border-color: #e06000;
+}
--- a/src/jocondelab/static/jocondelab/js/front-common.js	Wed Aug 21 19:20:14 2013 +0200
+++ b/src/jocondelab/static/jocondelab/js/front-common.js	Thu Aug 22 16:46:19 2013 +0200
@@ -271,10 +271,11 @@
     $(".language-label").click(function() {
        $(this).siblings(".language-button").click(); 
     });
+/*
     $(".language-current").click(function() {
         $(".language-list").toggle();
     });
-    
+*/    
     $overlayImg.load(moveDbpediaPopin);
     
 });
--- a/src/jocondelab/static/jocondelab/js/front-geo.js	Wed Aug 21 19:20:14 2013 +0200
+++ b/src/jocondelab/static/jocondelab/js/front-geo.js	Thu Aug 22 16:46:19 2013 +0200
@@ -34,6 +34,9 @@
                         coordCache.push(coord);
                     }
                 });
+                coordCache = _(coordCache).sortBy(function(coord) {
+                    return -coord.nb_notice;
+                });
                 showData();
             }
         );
@@ -102,6 +105,9 @@
             if (coordIdCache.indexOf(coord.term_id) === -1) {
                 coordIdCache.push(coord.term_id);
                 coordCache.push(coord);
+                coordCache = _(coordCache).sortBy(function(coord) {
+                    return -coord.nb_notice;
+                });
             }
             selectCoord(coord);
         }
--- a/src/jocondelab/static/jocondelab/js/front-notice.js	Wed Aug 21 19:20:14 2013 +0200
+++ b/src/jocondelab/static/jocondelab/js/front-notice.js	Thu Aug 22 16:46:19 2013 +0200
@@ -1,3 +1,4 @@
 $(function() {
     $('.notice-images a').magnificPopup({type:'image'});
+    bindDbpediaBox(".notice-term a");
 });
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jocondelab/static/jocondelab/js/front-timeline.js	Thu Aug 22 16:46:19 2013 +0200
@@ -0,0 +1,166 @@
+$(function() {
+    var startYear = -500,
+        endYear = 2012,
+        zoomLevel = 1,
+        zoomStep = Math.SQRT2,
+        minZoomLevel = .5,
+        maxZoomLevel = 128,
+        baseSpan = (endYear - startYear),
+        $tlcontainer = $(".timeline-container"),
+        canvas = $tlcontainer.find('canvas')[0],
+        lineDistances = [ 1000, 500, 200, 100, 50, 25, 10, 5, 2, 1 ],
+        cWidth, cHeight,
+        wSpan, wStart, wEnd, wScale, wLineDist,
+        wCenter = baseSpan / 2 + startYear,
+        itemCount = 12,
+        tlCache = [], tlIdCache = [], currentTerm = null;
+    
+    function updateCoords() {
+        cWidth = $tlcontainer.width();
+        cHeight = $tlcontainer.height();
+        wSpan = baseSpan / zoomLevel;
+        wStart = wCenter - wSpan / 2;
+        wEnd = wCenter + wSpan / 2;
+        wScale = cWidth / wSpan;
+        wLineDist = null;
+        for (var i = 0; i < lineDistances.length; i++) {
+            if (lineDistances[i] * wScale < 50) {
+                break;
+            }
+            wLineDist = lineDistances[i];
+        }
+    }
+    
+    function yrToX(yr) {
+        return wScale * (yr - wStart);
+    }
+    
+    function xToYr(x) {
+        return wStart + x / wScale;
+    }
+    
+    var itemTpl = _.template(
+        '<li class="timeline-item">'
+        + '<div class="timeline-item-box<%- current ? " timeline-current" : "" %>" data-term-id="<%- item.term_id %>"'
+        + ' data-dbpedia-uri="<%- item.dbpedia_uri %>" style="left: <%- left %>px; width: <%- width %>px;">'
+        + '<div class="timeline-item-label"><%- item.label %></div></div></li>'
+    );
+    
+    function redrawView() {
+        canvas.width = cWidth;
+        canvas.height = cHeight;
+        
+        var ctx = canvas.getContext("2d");
+        
+        for (var y = wLineDist * Math.ceil(wStart/wLineDist); y <= wEnd; y += wLineDist ) {
+            var x = yrToX(y+1/2);
+            ctx.beginPath();
+            ctx.moveTo(x, 20);
+            ctx.lineTo(x, cHeight - 20);
+            ctx.stroke();
+            ctx.textAlign = 'center';
+            ctx.fillText(y || 1, x, 12);
+            ctx.fillText(y || 1, x, cHeight - 8);
+        }
+        var html = _(tlCache).chain()
+            .filter(function(item) {
+                return (item.end_year >= wStart && item.start_year <= wEnd);
+            }).first(itemCount)
+            .sortBy(function(item) {
+                return (item.start_year + item.end_year)
+            }).map(function(item) {
+                var l = Math.max(0, yrToX(item.start_year)),
+                    r = Math.min(cWidth, yrToX(item.end_year + 1));
+                return itemTpl({
+                    current: (item.term_id == currentTerm),
+                    item: item,
+                    left: l,
+                    width: (r-l)
+                });
+            }).value().join("");
+        $(".timeline-list").html(html);
+        bindDbpediaBox(".timeline-item-box");
+        $(".timeline-item-box").click(function() {
+            var $this = $(this);
+            currentTerm = $this.attr("data-term-id")
+            $(".timeline-item-box").removeClass("timeline-current");
+            $this.addClass("timeline-current");
+            $(".results").empty().load(
+                urls.ajax_contents_by_term + "?random=1&term_id=" + currentTerm
+            );
+        })
+    }
+    
+    function getData() {
+        $.getJSON(
+            urls.ajax_years,
+            {
+                from_year: Math.floor(wStart),
+                to_year: Math.floor(wEnd)
+            },
+            function(data) {
+                _(data).each(function(term) {
+                    if (tlIdCache.indexOf(term.term_id) === -1) {
+                        tlIdCache.push(term.term_id);
+                        tlCache.push(term);
+                    }
+                });
+                tlCache = _(tlCache).sortBy(function(item) {
+                    return -item.nb_notice;
+                });
+                throttledRedraw();
+            }
+        );
+    }
+    
+    var throttledRedraw = _.throttle(function() {
+        updateCoords();
+        redrawView();
+    }, 100);
+    
+    var debouncedGetData = _.debounce(getData, 1000);
+        
+    var mousedown = false, dragging = false, xstart = null, wcStart;
+    
+    throttledRedraw();
+    
+    $tlcontainer.mousedown(function(e) {
+        dragging = false;
+        mousedown = true;
+        xstart = e.clientX;
+        wcStart = wCenter;
+        return false;
+    }).mousemove(function(e) {
+        if (mousedown) {
+            dragging = true;
+            wCenter = Math.max(startYear, Math.min(endYear, wcStart + (xstart - e.clientX) / wScale ));
+            throttledRedraw();
+            debouncedGetData();
+            return false;
+        }
+    }).mousewheel(function(e, d) {
+        var yrMouse = xToYr(e.clientX - $(this).offset().left),
+            scaleRatio = (d > 0 ? zoomStep : 1/zoomStep);
+        if (d < 0 && zoomLevel <= minZoomLevel) {
+            return;
+        }
+        if (d >= 0 && zoomLevel >= maxZoomLevel) {
+            return;
+        }
+        zoomLevel *= scaleRatio;
+        console.log(zoomLevel);
+        wCenter = Math.max(startYear, Math.min(endYear, yrMouse * (1 - 1 / scaleRatio) + wCenter / scaleRatio ));
+        throttledRedraw();
+        debouncedGetData();
+    });
+    
+    $("body").mouseup(function() {
+        mousedown = false;
+        dragging = false;
+    });
+    
+    getData();
+    
+    $(window).resize(throttledRedraw);
+    
+});
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jocondelab/static/jocondelab/lib/jquery.mousewheel.js	Thu Aug 22 16:46:19 2013 +0200
@@ -0,0 +1,117 @@
+/*! Copyright (c) 2013 Brandon Aaron (http://brandonaaron.net)
+ * Licensed under the MIT License (LICENSE.txt).
+ *
+ * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
+ * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
+ * Thanks to: Seamus Leahy for adding deltaX and deltaY
+ *
+ * Version: 3.1.3
+ *
+ * Requires: 1.2.2+
+ */
+
+(function (factory) {
+    if ( typeof define === 'function' && define.amd ) {
+        // AMD. Register as an anonymous module.
+        define(['jquery'], factory);
+    } else if (typeof exports === 'object') {
+        // Node/CommonJS style for Browserify
+        module.exports = factory;
+    } else {
+        // Browser globals
+        factory(jQuery);
+    }
+}(function ($) {
+
+    var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'];
+    var toBind = 'onwheel' in document || document.documentMode >= 9 ? ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'];
+    var lowestDelta, lowestDeltaXY;
+
+    if ( $.event.fixHooks ) {
+        for ( var i = toFix.length; i; ) {
+            $.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks;
+        }
+    }
+
+    $.event.special.mousewheel = {
+        setup: function() {
+            if ( this.addEventListener ) {
+                for ( var i = toBind.length; i; ) {
+                    this.addEventListener( toBind[--i], handler, false );
+                }
+            } else {
+                this.onmousewheel = handler;
+            }
+        },
+
+        teardown: function() {
+            if ( this.removeEventListener ) {
+                for ( var i = toBind.length; i; ) {
+                    this.removeEventListener( toBind[--i], handler, false );
+                }
+            } else {
+                this.onmousewheel = null;
+            }
+        }
+    };
+
+    $.fn.extend({
+        mousewheel: function(fn) {
+            return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
+        },
+
+        unmousewheel: function(fn) {
+            return this.unbind("mousewheel", fn);
+        }
+    });
+
+
+    function handler(event) {
+        var orgEvent = event || window.event,
+            args = [].slice.call(arguments, 1),
+            delta = 0,
+            deltaX = 0,
+            deltaY = 0,
+            absDelta = 0,
+            absDeltaXY = 0,
+            fn;
+        event = $.event.fix(orgEvent);
+        event.type = "mousewheel";
+
+        // Old school scrollwheel delta
+        if ( orgEvent.wheelDelta ) { delta = orgEvent.wheelDelta; }
+        if ( orgEvent.detail )     { delta = orgEvent.detail * -1; }
+
+        // New school wheel delta (wheel event)
+        if ( orgEvent.deltaY ) {
+            deltaY = orgEvent.deltaY * -1;
+            delta  = deltaY;
+        }
+        if ( orgEvent.deltaX ) {
+            deltaX = orgEvent.deltaX;
+            delta  = deltaX * -1;
+        }
+
+        // Webkit
+        if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY; }
+        if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = orgEvent.wheelDeltaX * -1; }
+
+        // Look for lowest delta to normalize the delta values
+        absDelta = Math.abs(delta);
+        if ( !lowestDelta || absDelta < lowestDelta ) { lowestDelta = absDelta; }
+        absDeltaXY = Math.max(Math.abs(deltaY), Math.abs(deltaX));
+        if ( !lowestDeltaXY || absDeltaXY < lowestDeltaXY ) { lowestDeltaXY = absDeltaXY; }
+
+        // Get a whole value for the deltas
+        fn = delta > 0 ? 'floor' : 'ceil';
+        delta  = Math[fn](delta / lowestDelta);
+        deltaX = Math[fn](deltaX / lowestDeltaXY);
+        deltaY = Math[fn](deltaY / lowestDeltaXY);
+
+        // Add event and delta to the front of the arguments
+        args.unshift(event, delta, deltaX, deltaY);
+
+        return ($.event.dispatch || $.event.handle).apply(this, args);
+    }
+
+}));
--- a/src/jocondelab/templates/jocondelab/ajax_contents.html	Wed Aug 21 19:20:14 2013 +0200
+++ b/src/jocondelab/templates/jocondelab/ajax_contents.html	Thu Aug 22 16:46:19 2013 +0200
@@ -1,5 +1,5 @@
 {% load i18n %}
-<div class="resultcount">{{count}} {% trans 'results for' %} {{termlabel}}</div>
+<h2 class="resultcount"><b>{{count}}</b> {% trans 'results for:' %} <b>{{termlabel}}</b></h2>
 
 <ul class="notice-list clearfix">
     {% include 'jocondelab/partial/notice_list.html' %}
--- a/src/jocondelab/templates/jocondelab/front_base.html	Wed Aug 21 19:20:14 2013 +0200
+++ b/src/jocondelab/templates/jocondelab/front_base.html	Thu Aug 22 16:46:19 2013 +0200
@@ -37,22 +37,38 @@
                         <h1><a href="{% url 'front_search' %}">Joconde<span class="title-lab">Lab</span></a></h1>
                         <h2 class="breadcrumbs">{% block breadcrumbs %}{% endblock %}</h2>
                     </div>
-                    <form action="{% url 'django.views.i18n.set_language' %}" method="post" id="lang_form" class="language-select">
-                        {% csrf_token %}
-                        <a class="language-current" href="#"><img src="{{STATIC_URL}}jocondelab/img/flag_{% if lang %}{{lang}}{% else %}{{LANGUAGE_CODE}}{% endif %}.png" /></a>
-                        <ul class="language-list">
-                        {% get_language_info_list for LANGUAGES as languages %}
-                        {% for language in languages %}
-                            <li class="language-item">
-                                <label for="language" class="language-label">{{ language.name_local }}</label>
-                                <input type="submit" name="language" class="language-button" style="background-image: url({{STATIC_URL}}jocondelab/img/flag_{{ language.code }}.png)" value="{{ language.code }}" title="{{ language.name_local }}" />
-                            </li>
-                        {% endfor %}
-                        </ul>
-                    </form>
+                    <div class="top-menus">
+                        <form action="{% url 'django.views.i18n.set_language' %}" method="post" id="lang_form" class="menu-container">
+                            {% csrf_token %}
+                            <a class="language-current" href="#"><img src="{{STATIC_URL}}jocondelab/img/flag_{% if lang %}{{lang}}{% else %}{{LANGUAGE_CODE}}{% endif %}.png" /></a>
+                            <ul class="menu-list language-list">
+                            {% get_language_info_list for LANGUAGES as languages %}
+                            {% for language in languages %}
+                                <li class="menu-item">
+                                    <label for="language" class="language-label">{{ language.name_local }}</label>
+                                    <input type="submit" name="language" class="language-button" style="background-image: url({{STATIC_URL}}jocondelab/img/flag_{{ language.code }}.png)" value="{{ language.code }}" title="{{ language.name_local }}" />
+                                </li>
+                            {% endfor %}
+                            </ul>
+                        </form>
+                        <div class="menu-container">
+                            <a class="main-menu-title">{% trans 'Menu' %}</a>
+                            <ul class="menu-list main-menu-list">
+                                <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>
+                        </div>
+                    </div>
                     {% block header_search %}
                     <form class="header-search-form" action="{% url 'front_search' %}">
-                        <input class="header-search-input" type="search" name="q" />
+                        <input class="header-search-input" type="search" name="q" placeholder="{% trans 'Search in contents' %}" />
                     </form>
                     {% endblock %}
                 {% endblock %}
--- a/src/jocondelab/templates/jocondelab/front_geo.html	Wed Aug 21 19:20:14 2013 +0200
+++ b/src/jocondelab/templates/jocondelab/front_geo.html	Thu Aug 22 16:46:19 2013 +0200
@@ -31,9 +31,9 @@
     <link rel="stylesheet" type="text/css" href="{{STATIC_URL}}jocondelab/css/front-geo.css"></script>
 {% endblock %}
 
-{% block title %}JocondeLab &raquo; {% trans 'Geographic search' %}{% endblock %}
+{% block title %}JocondeLab &raquo; {% trans 'World map' %}{% endblock %}
 
-{% block breadcrumbs %}<a href="{% url 'front_geo' %}">{% trans 'Geographic search' %}</a>{% endblock %}
+{% block breadcrumbs %}<a href="{% url 'front_geo' %}">{% trans 'World map' %}</a>{% endblock %}
 
 {% block main %}
             
--- a/src/jocondelab/templates/jocondelab/front_search.html	Wed Aug 21 19:20:14 2013 +0200
+++ b/src/jocondelab/templates/jocondelab/front_search.html	Thu Aug 22 16:46:19 2013 +0200
@@ -32,7 +32,7 @@
                 {% endfor %}
             </ul>
             
-            <div class="resultcount">{{rescount}} {% trans 'results' %} -- {{duration}} secondes</div>
+            <h2 class="resultcount"><b>{{rescount}}</b> {% if queryterms %}{% trans 'results for:' %} <b>{{queryterms}}</b>{% else %}{% trans 'results' %}{% endif %}</h2>
             
             <ul class="notice-list clearfix">
                 {% include 'jocondelab/partial/notice_list.html' %}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jocondelab/templates/jocondelab/front_timeline.html	Thu Aug 22 16:46:19 2013 +0200
@@ -0,0 +1,40 @@
+{% extends "jocondelab/front_base.html" %}
+{% load i18n %}
+{% load l10n %}
+
+{% block js_import %}
+    {{block.super}}
+    <script type="text/javascript" src="{{STATIC_URL}}jocondelab/lib/jquery.mousewheel.js"></script>
+{% endblock %}
+
+{% block js_declaration %}
+    {{block.super}}
+    <script type="text/javascript">
+        var urls = {
+            image_prefix: "{{JOCONDE_IMG_BASE_URL}}",
+            static_url: "{{STATIC_URL}}",
+            ajax_years: "{% url 'ajax_years' %}",
+            ajax_contents_by_term: "{% url 'ajax_contents_by_term' %}"
+        }
+    </script>
+    <script type="text/javascript" src="{{STATIC_URL}}jocondelab/js/front-timeline.js"></script>
+{% endblock %}
+
+{% block css_declaration %}
+    {{block.super}}
+    <link rel="stylesheet" type="text/css" href="{{STATIC_URL}}jocondelab/css/front-timeline.css"></script>
+{% endblock %}
+
+{% block title %}JocondeLab &raquo; {% trans 'Timeline' %}{% endblock %}
+
+{% block breadcrumbs %}<a href="{% url 'front_timeline' %}">{% trans 'Timeline' %}</a>{% endblock %}
+
+{% block main %}
+            
+            <div class="timeline-container">
+                <canvas class="timeline-canvas"></canvas>
+                <ul class="timeline-list"></ul>
+            </div>
+                        
+            <div class="results"></div>
+{% endblock %}
--- a/src/jocondelab/urls.py	Wed Aug 21 19:20:14 2013 +0200
+++ b/src/jocondelab/urls.py	Thu Aug 22 16:46:19 2013 +0200
@@ -1,12 +1,13 @@
 from jocondelab.views.back_office import (TermListView, TermEditView, TermModifyWpLink, 
     TermRemoveWpLink, TermValidate, TermWikipediaEdition, 
     TermLinkSemanticLevelEdition, ThesaurusTree, TermListTableView)
-from jocondelab.views.front_office import (SearchView, NoticeView, GeoView)
+from jocondelab.views.front_office import (SearchView, NoticeView)
 from core import urls as core_urls
 from django.conf.urls import patterns, include, url
 from django.contrib import admin
 from django.contrib.auth import urls as auth_urls
 from django.contrib.auth.decorators import login_required
+from django.views.generic import TemplateView
 
 js_info_dict = {
     'packages': ('core', 'jocondelab'),
@@ -32,7 +33,8 @@
     url(r'^bo/term/validate/$', login_required(TermValidate.as_view()), name='validate_term'),
     url(r'^bo/tree/(?P<thes_id>\d+)/$', login_required(ThesaurusTree.as_view()), name='term_tree'),
     url(r'^search/$', SearchView.as_view(), name='front_search'),
-    url(r'^geo/$', GeoView.as_view(), name='front_geo'),
+    url(r'^geo/$', TemplateView.as_view(template_name="jocondelab/front_geo.html"), name='front_geo'),
+    url(r'^timeline/$', TemplateView.as_view(template_name="jocondelab/front_timeline.html"), name='front_timeline'),
     url(r'^notice/(?P<notice_id>\d+)/$', NoticeView.as_view(), name='front_notice'),
     url(r'^ajax/years/$', 'jocondelab.views.ajax.years', name='ajax_years'),
     url(r'^ajax/geocoords/$', 'jocondelab.views.ajax.geo_coords', name='ajax_geo_coords'),
--- a/src/jocondelab/views/ajax.py	Wed Aug 21 19:20:14 2013 +0200
+++ b/src/jocondelab/views/ajax.py	Thu Aug 22 16:46:19 2013 +0200
@@ -23,15 +23,15 @@
     qs = DbpediaYears.objects.filter(term__dbpedia_fields__language_code=lang).order_by('-term__nb_notice')
     
     if to_year:
-        qs = qs.filter(start_year__lt=to_year)
+        qs = qs.filter(start_year__lte=to_year)
     if from_year:
-        qs = qs.filter(end_year__gt=to_year)
+        qs = qs.filter(end_year__gte=from_year)
     
     qs = qs[:count]
     
     results = [{
                 "start_year": y.start_year,
-                "to_year": y.end_year,
+                "end_year": y.end_year,
                 "term_id": y.term.id,
                 "label": y.term.dbpedia_fields.get(language_code=lang).label,
                 "nb_notice": y.term.nb_notice,
--- a/src/jocondelab/views/front_office.py	Wed Aug 21 19:20:14 2013 +0200
+++ b/src/jocondelab/views/front_office.py	Thu Aug 22 16:46:19 2013 +0200
@@ -83,7 +83,7 @@
         context["notices"] = get_notices(ns, lang)
         context["queryterms"] = querystr
         
-        wpp = 30
+        wpp = 50
         if show_tagcloud:
             ts = Term.objects.filter(dbpedia_fields__language_code=lang).order_by('-nb_notice')[:wpp]
             words = [{
@@ -148,15 +148,4 @@
         
         return self.render_to_response(context)
 
-class GeoView(View, TemplateResponseMixin):
-    
-    template_name = "jocondelab/front_geo.html"
-    
-    def get(self, request):
-        
-        context = {}
-        lang = request.GET.get('lang',request.LANGUAGE_CODE)
-        context["lang"] = lang
-        context['JOCONDE_IMG_BASE_URL'] = settings.JOCONDE_IMG_BASE_URL
-        return self.render_to_response(context)
     
\ No newline at end of file