--- a/web/hdalab/static/hdalab/css/completion.css Fri Aug 31 10:48:51 2012 +0200
+++ b/web/hdalab/static/hdalab/css/completion.css Wed Sep 05 19:11:34 2012 +0200
@@ -145,25 +145,33 @@
width: 100%; font-size: 16px; font-weight: bold; border-style: none; border-bottom: 1px solid #000;
}
-#tagsearch.grise {
- color: #666; font-style: italic; font-weight: normal;
+#tagsearch.waiting {
+ background: url(../img/small-loader.gif) no-repeat right;
}
ul.ui-autocomplete {
- width: 180px; font-family: "Open Sans";
- max-height: 600px; overflow-y: auto; overflow-x: hidden; padding-right: 20px;
+ font-family: "Open Sans"; max-width: 230px;
+ max-height: 400px; overflow-y: auto; overflow-x: hidden;
+}
+
+.wpinfo {
+ margin-left: 240px;
+}
+
+.ui-menu-item:hover .acwp {
+ display: block;
+}
+
+.acnb {
+ float: right; font-size: 12px; margin: 2px 0 0 2px;
}
h4.actitle {
- font-size: 14px; font-weight: bold;
-}
-
-.acimgwrap {
- float: left; width: 80px; text-align: center;
+ font-size: 13px; font-weight: bold;
}
img.acimg {
- max-width: 80px; max-height: 60px;
+ max-width: 80px; max-height: 60px; float: left; margin: 5px 2px 2px 0;
}
p.acabstract {
Binary file web/hdalab/static/hdalab/img/small-loader.gif has changed
--- a/web/hdalab/static/hdalab/js/completion.js Fri Aug 31 10:48:51 2012 +0200
+++ b/web/hdalab/static/hdalab/js/completion.js Wed Sep 05 19:11:34 2012 +0200
@@ -28,7 +28,7 @@
+ _d.description.replace(/(^.{0,160})([\s]|$)(.*)/,'$1…')
+ '</p><ul class="content-tags">'
+ _d.tags.map(function(_t) {
- return '<li class="content-tag-item"><a href="#" onclick="tagInfo(this.getAttribute(\'original-label\'), true); return false;" original-label="'
+ return '<li class="content-tag-item"><a href="#" onclick="getContents(this.textContent.trim()); return false;" original-label="'
+ _t.label
+ '"'
+ (_t.match ? ' class="tagmatch"' : '')
@@ -50,11 +50,9 @@
function getContents(label) {
$.getJSON(
- gomNs.urls['filter'],
+ gomNs.urls['contentsbytag'],
{
- label: label,
- tagcount: 0,
- contentcount: 30
+ label: label
},
showResults
);
@@ -64,24 +62,60 @@
$(" #tagform ").submit(function() {
return false;
});
+ var cache = {}, /*CACHE => http://jqueryui.com/demos/autocomplete/#remote-with-cache */
+ lastXhr;
$( "#tagsearch" ).autocomplete({
- source: gomNs.urls['tag_search'],
+ source: function( request, response ) {
+ var term = request.term;
+ if ( term in cache ) {
+ $("#tagsearch").removeClass("waiting");
+ response( cache[ term ] );
+ return;
+ }
+ $("#tagsearch").addClass("waiting");
+ lastXhr = $.getJSON( gomNs.urls['tag_search'], request, function( data, status, xhr ) {
+ cache[ term ] = data;
+ if ( xhr === lastXhr ) {
+ response( data );
+ $("#tagsearch").removeClass("waiting");
+ }
+ });
+ },
minLength: 2,
+ focus: function( event, ui ) {
+ var _title = $('<h4>')
+ .addClass("actitle")
+ .html(
+ ui.item.value.replace(
+ new RegExp('('
+ + $("#tagsearch").val().replace(/(\W)/g, '\\$1')
+ + ')','gi') ,
+ '<strong>$1</strong>')
+ );
+ $(".wpinfo").html(_title);
+ if (ui.item.thumbnail) {
+ var _img = $('<img>')
+ .addClass("acimg")
+ .attr("src",ui.item.thumbnail);
+ $(".wpinfo").append(_img);
+ }
+ if (ui.item.abstract) {
+ var _abstract = $('<p>')
+ .addClass("acabstract")
+ .text( ui.item.abstract.replace(/(^.{0,240})([\s]|$)(.*)/,'$1…') );
+ $(".wpinfo").append(_abstract);
+ }
+ $(".wpinfo").append('<div class="clear"></div>');
+ },
select: function( event, ui ) {
- getContents(ui.item.original_label);
- }
- })
- .addClass("grise")
- .focusin(function() {
- $(this).removeClass("grise");
- })
- .focusout(function() {
- if (!$(this).val()) {
- $(this).addClass("grise");
+ getContents(ui.item.label);
}
})
.data("autocomplete")._renderItem = function(ul, item) {
var _contents = $('<a>'),
+ _nb = $('<span>')
+ .addClass("acnb")
+ .text(item.nb),
_title = $('<h4>')
.addClass("actitle")
.html(
@@ -90,25 +124,8 @@
+ $("#tagsearch").val().replace(/(\W)/g, '\\$1')
+ ')','gi') ,
'<strong>$1</strong>')
- ),
- _clear = $('<div>').addClass('clear');
- _contents.append(_title);
- if (item.thumbnail) {
- var _img = $('<img>')
- .addClass("acimg")
- .attr("src",item.thumbnail),
- _imgwrap = $('<div>')
- .addClass("acimgwrap")
- .append(_img);
- _contents.append(_imgwrap);
- }
- if (item.abstract) {
- var _abstract = $('<p>')
- .addClass("acabstract")
- .text( item.abstract.replace(/(^.{0,240})([\s]|$)(.*)/,'$1…') );
- _contents.append(_abstract);
- }
- _contents.append(_clear);
+ );
+ _contents.append(_nb).append(_title);
return $( "<li>" )
.data( "item.autocomplete", item )
.append( _contents )
--- a/web/hdalab/templates/completion.html Fri Aug 31 10:48:51 2012 +0200
+++ b/web/hdalab/templates/completion.html Wed Sep 05 19:11:34 2012 +0200
@@ -23,7 +23,7 @@
<script type="text/javascript">
gomNs.languageCode = '{{LANGUAGE_CODE}}';
gomNs.urls = {
- 'filter': "{% url filter %}",
+ 'contentsbytag': "{% url contentsbytag %}",
'tag_search': "{% url tag_search %}"
};
</script>
@@ -59,6 +59,9 @@
<form id="tagform">
<input id="tagsearch" placeholder="{% trans "Rechercher un tag" %}" />
</form>
+ <div class="wpinfo">
+
+ </div>
</div>
</div>
<div class="bloc" id="bloc_translationinfo">
--- a/web/hdalab/urls.py Fri Aug 31 10:48:51 2012 +0200
+++ b/web/hdalab/urls.py Wed Sep 05 19:11:34 2012 +0200
@@ -36,4 +36,5 @@
(r'^a/tagsearch$', 'tagsearch', {}, 'tag_search'),
(r'^a/catsearch$', 'catsearch', {}, 'cat_search'),
(r'^a/cattree$', 'cattree', {}, 'cat_tree'),
+ (r'^a/contentsbytag$', 'contentsbytag', {}, 'contentsbytag'),
)
--- a/web/hdalab/views/ajax.py Fri Aug 31 10:48:51 2012 +0200
+++ b/web/hdalab/views/ajax.py Wed Sep 05 19:11:34 2012 +0200
@@ -184,6 +184,7 @@
def tagsearch(request):
q = request.GET.get('term',None)
+ maxcount = int(request.GET.get('count','40'))
lang = request.GET.get('lang',request.LANGUAGE_CODE)
stemming_langs = [ 'fr', 'en', 'de', 'it' ]
@@ -201,13 +202,13 @@
qs = qs.filter( label__icontains = q )
else:
if lang in stemming_langs:
- qs = qs.filter( Q(label__iregex=q ) | Q(dbpedia_fields__translations__label__iregex=q, dbpedia_fields__translations__language_code=lang), ~Q(dbpedia_uri = None))
+ qs = qs.filter(dbpedia_fields__translations__label__iregex=qrx, dbpedia_fields__translations__language_code=lang)
else:
- qs = qs.filter( Q(label__icontains=q ) | Q(dbpedia_fields__translations__label__icontains=q, dbpedia_fields__translations__language_code=lang), ~Q(dbpedia_uri = None))
+ qs = qs.filter(dbpedia_fields__translations__label__icontains=q, dbpedia_fields__translations__language_code=lang)
else:
qs = Tag.objects.filter(~Q(dbpedia_uri = None))
- qs = qs.annotate(nb=Count('datasheet',distinct=True)).order_by('-nb')[:20]
+ qs = qs.annotate(nb=Count('datasheet',distinct=True)).order_by('-nb')[:maxcount]
qslist = list(qs)
@@ -231,7 +232,6 @@
resobj['abstract'] = dbfields.abstract if dbfields is not None else None
if q is None or resobj['value'].lower().find(lq) != -1:
res.append(resobj)
- res.sort(key=lambda resobj: resobj['value'])
return HttpResponse(content=json.dumps(res), mimetype='application/json')
@@ -258,7 +258,7 @@
label = request.GET.get('label', None)
country = request.GET.get('country', None)
contentlist = request.GET.get('contentlist', None)
- max_tag_order = request.GET.get('mto', 12)
+ max_tag_order = int(request.GET.get('mto', '12'))
content_count = request.GET.get('contentcount', 12)
tag_count = request.GET.get('tagcount', 30)
@@ -419,3 +419,61 @@
cache.set(cache_key, outputstr)
return HttpResponse(content=outputstr, mimetype='application/json')
+
+def contentsbytag(request):
+
+ lang = request.GET.get('lang',request.LANGUAGE_CODE)
+ label = request.GET.get('label', None).strip().lower()
+ max_tag_order = int(request.GET.get('mto', '30'))
+ content_count = int(request.GET.get('contentcount', '30'))
+
+ cache_key = fix_cache_key("contentsbytag-%s"%unicode(label).encode("utf-8"))
+
+ outputstr = cache.get(cache_key)
+
+ if outputstr is None:
+
+ matchtagids = []
+
+ contentqs = Datasheet.objects.filter(validated=True)
+
+ no_translate_langs = [ 'fr' ]
+ if lang in no_translate_langs:
+ tagsqs = Tag.objects.filter( label__iexact = label )
+ else:
+ tagsqs = Tag.objects.select_related('dbpedia_fields').filter(dbpedia_fields__translations__label__iexact = label, dbpedia_fields__translations__language_code=lang)
+
+ contentqs = contentqs.select_related('taggedsheet__tag').filter(taggedsheet__tag__in=tagsqs).distinct()
+
+ cont_count = contentqs.count()
+
+ contenus = dict([(content.id, {'score' : 0, 'tags' : [], 'id':content.id, 'title': content.title, 'description': content.description, 'url': content.url}) for content in contentqs[0:content_count]])
+ contentids = contenus.keys()
+
+ qs = DatasheetExtras.objects.select_related('insee').filter(datasheet__in = contentids)
+ for dse in qs:
+ contenus[dse.datasheet_id]['coords'] = {'city_name': dse.insee.city_name, 'latitude': dse.insee.latitude, 'longitude': dse.insee.longitude}
+
+ qs = list(TaggedSheet.objects.select_related('tag', 'tag__dbpedia_fields').filter(datasheet__in = contentids).order_by('order'))
+
+ if lang in no_translate_langs:
+ translations = {}
+ else:
+ transqs = DbpediaFieldsTranslation.objects.filter(master__in = [ts.tag.dbpedia_fields for ts in qs], language_code = lang)
+ translations = dict([(trans.master_id,trans.label) for trans in transqs])
+
+ for ts in qs:
+ translated_label = translations.get(ts.tag.dbpedia_fields.id, ts.tag.label) if ts.tag.dbpedia_fields is not None else ts.tag.label
+ match_tag = ( label == translated_label.lower() )
+ contenus[ts.datasheet_id]['tags'].append({'id': ts.tag.id, 'label':ts.tag.label, 'order':ts.order, 'match': match_tag , 'translated_label': translated_label})
+
+ if match_tag:
+ contenus[ts.datasheet_id]['score'] += 2*max_tag_order - ts.order
+
+ contenus = sorted(contenus.values(),key=lambda e: -e['score'])
+
+ output = {'count': cont_count, 'contents': contenus}
+ outputstr = json.dumps(output)
+ cache.set(cache_key, outputstr)
+
+ return HttpResponse(content=outputstr, mimetype='application/json')
\ No newline at end of file