summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeny Fadeev <evgeny.fadeev@gmail.com>2010-09-20 14:04:25 -0400
committerEvgeny Fadeev <evgeny.fadeev@gmail.com>2010-09-20 14:04:25 -0400
commitbd0c24f9fdc1a72c87e5ab653d9483d340faea0e (patch)
tree96b01daa1b54614f1664ffde1f2298b7da825f76
parent9f6d0b3b64e709409f591462892a5907338b9637 (diff)
downloadaskbot-bd0c24f9fdc1a72c87e5ab653d9483d340faea0e.tar.gz
askbot-bd0c24f9fdc1a72c87e5ab653d9483d340faea0e.tar.bz2
askbot-bd0c24f9fdc1a72c87e5ab653d9483d340faea0e.zip
search results can be fetched via ajax - via a.k.a live search
-rw-r--r--askbot/const/__init__.py2
-rw-r--r--askbot/skins/default/media/js/live_search.js285
-rw-r--r--askbot/skins/default/templates/input_bar.html11
-rw-r--r--askbot/skins/default/templates/questions.html13
-rw-r--r--askbot/skins/default/templates/questions_ajax.html118
-rw-r--r--askbot/views/readers.py197
6 files changed, 595 insertions, 31 deletions
diff --git a/askbot/const/__init__.py b/askbot/const/__init__.py
index 98b8e49c..dedbd115 100644
--- a/askbot/const/__init__.py
+++ b/askbot/const/__init__.py
@@ -205,7 +205,7 @@ USERS_PAGE_SIZE = 28#todo: move it to settings?
USERNAME_REGEX_STRING = r'^[\w \-]+$'
#chars that can go before or after @mention
-TWITTER_STYLE_MENTION_TERMINATION_CHARS = '\n ;:,.!?<>'
+TWITTER_STYLE_MENTION_TERMINATION_CHARS = '\n ;:,.!?<>"\''
COMMENT_HARD_MAX_LENGTH = 2048
diff --git a/askbot/skins/default/media/js/live_search.js b/askbot/skins/default/media/js/live_search.js
new file mode 100644
index 00000000..0cf7817b
--- /dev/null
+++ b/askbot/skins/default/media/js/live_search.js
@@ -0,0 +1,285 @@
+$(document).ready(function(){
+ var query = $('input#keywords');
+ var prev_text = $.trim(query.val());
+ var running = false;
+ var q_list_sel = 'listA';//id of question listing div
+
+ var refresh_x_button = function(){
+ if ($.trim(query.val()).length > 0){
+ if (query.attr('class') == 'searchInput'){
+ query.attr('class', 'searchInputCancelable');
+ x_button = $('<input class="cancelSearchBtn" type="button" name="reset_query"/>');
+ //x_button.click(reset_query);
+ x_button.val('x');
+ x_button.click(
+ function(){
+ query.val('');
+ reset_query();
+ }
+ );
+ query.after(x_button);
+ }
+ }
+ else {
+ $('input[name=reset_query]').remove();
+ query.attr('class', 'searchInput');
+ }
+ };
+
+ var eval_query = function(){
+ cur_text = $.trim(query.val());
+ if (cur_text != prev_text && running === false){
+ if (cur_text.length > 3){
+ send_query(cur_text);
+ running = true;
+ }
+ else if (cur_text.length === 0){
+ reset_query();
+ running = true;
+ }
+ }
+ }
+
+ var listen = function(){
+ running = false;
+ refresh_x_button();
+ query.keydown(function(e){
+ refresh_x_button();
+ if (running === false){
+ setTimeout(eval_query, 50);
+ }
+ });
+ query.keyup(function(){
+ refresh_x_button();
+ });
+ }
+
+ var render_counter = function(count, word, color, bgcolor){
+ return '<div class="votes"' +
+ '<span class="item-count" ' +
+ 'style="color:' + color +
+ ';background:' + bgcolor + '"' +
+ '>' +
+ count +
+ '</span>' +
+ '<div>' + word + '</div>' +
+ '</div>';
+ }
+
+ var render_title = function(result){
+ return '<h2>' +
+ '<a title="' + result['summary'] + '" ' +
+ 'href="' + result['url'] + '"' +
+ '>' +
+ result['title'] +
+ '</a>' +
+ '</h2>';
+ };
+
+ var render_user_link = function(result){
+ if (result['u_url'] !== false){
+ return '<a ' +
+ 'href="' + result['u_url'] + '"' +
+ '>' +
+ result['u_name'] +
+ '</a> ';
+ }
+ else {
+ return '';
+ }
+ };
+
+ var render_badge = function(result, key){
+ return '<span ' +
+ 'title="' + result[key + '_title'] + '"' +
+ '>' +
+ '<span ' +
+ 'class="' + result[key + '_css_class'] + '"' +
+ '>' + result[key + '_badge_symbol'] + '</span>' +
+ '<span class="badgecount">' + result[key] + '</span>';
+ };
+
+ var render_user_badge_and_karma = function(result){
+ var rep_title = result['u_rep'] + ' ' + result['u_rep_word'];
+ var html = '<span ' +
+ 'class="reputation-score" ' +
+ 'title="' + rep_title + '"' +
+ '>' + result['u_rep'] + '</span>';
+ if (result['u_gold'] > 0){
+ html += render_badge(result, 'u_gold');
+ }
+ if (result['u_silver'] > 0){
+ html += render_badge(result, 'u_silver');
+ }
+ if (result['u_bronze'] > 0){
+ html += render_badge(result, 'u_bronze');
+ }
+ return html;
+ };
+
+ var render_user_info = function(result){
+ var user_html =
+ '<div class="userinfo">' +
+ '<span class="relativetime" ' +
+ 'title="' + result['timestamp'] + '"' +
+ '>' +
+ result['timesince'] +
+ '</span> ' +
+ render_user_link(result) +
+ render_user_badge_and_karma(result) +
+ '</div>';
+ return user_html;
+ };
+
+ var render_tag = function(tag_name){
+ var url = scriptUrl +
+ $.i18n._('questions/') +
+ '?tags=' + encodeURI(tag_name);
+ var tag_title = $.i18n._(
+ "see questions tagged '{tag}'"
+ ).replace(
+ '{tag}',
+ tag_name
+ );
+ return '<a ' +
+ 'href="' + url + '" ' +
+ 'title="' + tag_title + '" rel="tag"' +
+ '>' + tag_name + '</a>';
+ };
+
+ var render_tags = function(tags){
+ var tags_html = '<div class="tags">';
+ for (var i=0; i<tags.length; i++){
+ tags_html += render_tag(tags[i]);
+ }
+ tags_html += '</div>';
+ return tags_html;
+ };
+
+ var render_question = function(question){
+ var entry_html =
+ '<div class="short-summary">' +
+ '<div class="counts">' +
+ render_counter(
+ question['votes'],
+ question['votes_word'],
+ question['votes_color'],
+ question['votes_bgcolor']
+ ) +
+ render_counter(
+ question['answers'],
+ question['answers_word'],
+ question['answers_color'],
+ question['answers_bgcolor']
+ ) +
+ render_counter(
+ question['views'],
+ question['views_word'],
+ question['views_color'],
+ question['views_bgcolor']
+ ) +
+ '</div>' +
+ render_title(question) +
+ render_user_info(question) +
+ render_tags(question['tags']) +
+ '</div>';
+ return entry_html;
+ };
+
+ var render_question_list = function(questions){
+ var output = '';
+ //alert(questions.length);
+ for (var i=0; i<questions.length; i++){
+ output += render_question(questions[i]);
+ }
+ return output;//render_question(questions[2]);
+ };
+
+ var render_faces = function(faces){
+ if (faces.length === 0){
+ return;
+ }
+ $('#contrib-users>a').remove();
+ var html = '';
+ for (var i=0; i<faces.length; i++){
+ html += faces[i];
+ }
+ //alert(html);
+ $('#contrib-users').append(html);
+ };
+
+ var render_related_tags = function(tags){
+ if (tags.length === 0){
+ return;
+ }
+ var html = '';
+ for (var i=0; i<tags.length; i++){
+ html += render_tag(tags[i]['name']);
+ html += '<span class="tag-number">&#215; ' +
+ tags[i]['used_count'] +
+ '</span>' +
+ '<br />';
+ }
+ $('#related-tags').html(html);
+ };
+
+ var render_paginator = function(paginator){
+ var pager = $('#pager');
+ if (! pager.is(':empty')){
+ pager.html(paginator);
+ }
+ };
+
+ var set_question_count = function(count_html){
+ $('#question-count').html(count_html);
+ }
+
+ var render_result = function(data, text_status, xhr){
+ var old_list = $('#' + q_list_sel);
+ var new_list = $('<div></div>');
+ if (data['questions'].length > 0){
+ new_list.html(render_question_list(data['questions']));
+ old_list.hide();
+ old_list.after(new_list);
+ old_list.remove();
+ //rename new div to old
+ new_list.attr('id', q_list_sel);
+ render_paginator(data['paginator']);
+ set_question_count(data['question_counter']);
+ }
+ render_faces(data['faces']);
+ render_related_tags(data['related_tags']);
+ query.focus();
+ //show new div
+ }
+
+ var try_again = function(){
+ running = false;
+ eval_query();
+ }
+
+ var send_query = function(query_text){
+ $.ajax({
+ url: scriptUrl + $.i18n._('questions/'),
+ data: {query: query_text},
+ dataType: 'json',
+ success: render_result,
+ complete: try_again,
+ });
+ prev_text = query_text;
+ }
+
+ var reset_query = function(){
+ refresh_x_button();
+ $.ajax({
+ url: scriptUrl + $.i18n._('questions/'),
+ data: {reset_query: true},
+ dataType: 'json',
+ success: render_result,
+ complete: try_again,
+ });
+ prev_text = '';
+ }
+
+ listen();
+});
diff --git a/askbot/skins/default/templates/input_bar.html b/askbot/skins/default/templates/input_bar.html
index 66e6ed94..018f79d9 100644
--- a/askbot/skins/default/templates/input_bar.html
+++ b/askbot/skins/default/templates/input_bar.html
@@ -1,6 +1,7 @@
{% load i18n %}
{% load smart_if %}
{% if active_tab != "ask" %}
+{% spaceless %}
<div id="searchBar">
{% comment %}url action depends on which tab is active{% endcomment %}
<form
@@ -22,12 +23,11 @@
name="query"
id="keywords"/>
{% if query %}{% comment %}query is only defined by questions view{% endcomment %}
- <input type="button"
- value="x"
- name="reset_query"
+ <input type="button"
+ value="x"
+ name="reset_query"
{% comment %}todo - make sure it works on Enter keypress{% endcomment %}
- onclick="window.location.href='{% url questions %}?reset_query=true'"
- value="true"
+ onclick="window.location.href='{% url questions %}?reset_query=true'"
class="cancelSearchBtn"/>
{% endif %}
<input type="submit" value="{% trans "search" %}" name="search" class="searchBtn" />
@@ -40,6 +40,7 @@
{% endif %}
</form>
</div>
+{% endspaceless %}
{% else %}
{% include "ask_form.html" %}
{% endif %}
diff --git a/askbot/skins/default/templates/questions.html b/askbot/skins/default/templates/questions.html
index cf9517e1..36a15ae1 100644
--- a/askbot/skins/default/templates/questions.html
+++ b/askbot/skins/default/templates/questions.html
@@ -27,7 +27,7 @@
{% endblock %}
{% block content %}
{% get_current_language as LANGUAGE_CODE %}
-{% cache 600 "scope_sort_tabs" search_tags scope sort query context.page context.page_size LANGUAGE_CODE %}
+{% cache 600 "scope_sort_tabs" search_tags request.user scope sort query context.page context.page_size LANGUAGE_CODE %}
<div class="tabBar">
<div class="tabsC">
<span class="label">{% trans "In:" %}</span>
@@ -128,7 +128,7 @@
alt="{% trans "subscribe to the questions feed" %}"
src="{% media "/images/feed-icon-small.png" %}"/> {% trans "rss feed" %}</a>)
</p>
- <p class="search-result-summary">
+ <p id="question-count" class="search-result-summary">
{% if author_name or search_tags or query %}
{% blocktrans count questions_count as cnt with questions_count|intcomma as q_num %}
{{q_num}} question found
@@ -231,7 +231,7 @@
<div class="userinfo">
<span class="relativetime" title="{{question.last_activity_at}}">{% diff_date question.last_activity_at %}</span>
{% if question.last_activity_by %}
- &nbsp;<a href="{% url user_profile question.last_activity_by.id question.last_activity_by.username|slugify %}">{{ question.last_activity_by }}</a>&nbsp;{% get_score_badge question.last_activity_by %}
+ <a href="{% url user_profile question.last_activity_by.id question.last_activity_by.username|slugify %}">{{ question.last_activity_by }}</a> {% get_score_badge question.last_activity_by %}
{% endif %}
</div>
<div class="tags">
@@ -286,11 +286,12 @@
</p>
{% endif %}
</div>
+<script type="text/javascript" src="{% media "/js/live_search.js" %}"></script>
{% endblock %}
{% block tail %}
{% if questions_count > 10 %}{%comment%}todo: remove magic number{%endcomment%}
- <div class="pager">{% cnprog_paginator context %}</div>
+ <div id="pager" class="pager">{% cnprog_paginator context %}</div>
<div class="pagesize">{% cnprog_pagesize context %}</div>
{% endif %}
{% endblock %}
@@ -299,7 +300,7 @@
{% if contributors %}
{% get_current_language as LANGUAGE_CODE %}
{% cache 600 contributors search_tags scope sort query context.page context.page_size LANGUAGE_CODE %}
- <div class="boxC">
+ <div id="contrib-users" class="boxC">
<h3 class="subtitle">{% trans "Contributors" %}</h3>
{% for person in contributors %}
{% gravatar person 48 %}
@@ -317,7 +318,7 @@
{% cache 600 tags search_tags scope sort query context.page context.page_size LANGUAGE_CODE %}
<div class="boxC">
<h3 class="subtitle">{% trans "Related tags" %}</h3>
- <div class="tags">
+ <div id="related-tags" class="tags">
{% for tag in tags %}
<a
rel="tag"
diff --git a/askbot/skins/default/templates/questions_ajax.html b/askbot/skins/default/templates/questions_ajax.html
new file mode 100644
index 00000000..83e4d09f
--- /dev/null
+++ b/askbot/skins/default/templates/questions_ajax.html
@@ -0,0 +1,118 @@
+<!-- questions_ajax.html -->
+{% load extra_tags %}
+{% load i18n %}
+{% load humanize %}
+{% load extra_filters %}
+{% load smart_if %}
+{% load cache %}
+{% get_current_language as LANGUAGE_CODE %}
+{% cache 60 questions search_tags scope sort query context.page context.page_size LANGUAGE_CODE %}
+ {% for question in questions.object_list %}
+ <div class="short-summary">
+ <div class="counts">
+ <div class="votes">
+ <span
+ class="item-count"
+ {% if question.score == 0 %}
+ style="background:{{settings.COLORS_VOTE_COUNTER_EMPTY_BG}};color:{{settings.COLORS_VOTE_COUNTER_EMPTY_FG}}"
+ {% else %}
+ style="background:{{settings.COLORS_VOTE_COUNTER_MIN_BG}};color:{{settings.COLORS_VOTE_COUNTER_MIN_FG}}"
+ {% endif %}
+ >{{question.score|humanize_counter}}</span>
+ <div>
+ {% blocktrans count question.score as cnt %}vote{% plural %}votes{% endblocktrans %}
+ </div>
+ </div >
+ {% comment %}
+ <div {% if question.answer_accepted %}title="{% trans "this answer has been accepted to be correct" %}"{% endif %} class="status {% if question.answer_accepted %}answered-accepted{% endif %} {% ifequal question.answer_count 0 %}unanswered{% endifequal %}{% ifnotequal question.answer_count 0 %}answered{% endifnotequal %}">
+ {% endcomment %}
+ <div class="votes">
+ <span
+ class="item-count"
+ {% if question.answer_count == 0 %}
+ style="background:{{settings.COLORS_ANSWER_COUNTER_EMPTY_BG}};color:{{settings.COLORS_ANSWER_COUNTER_EMPTY_FG}}"
+ {% else %}
+ {% if question.answer_accepted %}
+ style="background:{{settings.COLORS_ANSWER_COUNTER_ACCEPTED_BG}};color:{{settings.COLORS_ANSWER_COUNTER_ACCEPTED_FG}}"
+ {% else %}
+ style="background:{{settings.COLORS_ANSWER_COUNTER_MIN_BG}};color:{{settings.COLORS_ANSWER_COUNTER_MIN_FG}}"
+ {% endif %}
+ {% endif %}
+ >{{question.answer_count|humanize_counter}}</span>
+ <div>
+ {% blocktrans count question.answer_count as cnt %}answer{% plural %}answers{% endblocktrans %}
+ </div>
+ </div>
+ <div class="votes">
+ <span class="item-count"
+ {% if question.view_count == 0 %}
+ style="background:{{settings.COLORS_VIEW_COUNTER_EMPTY_BG}};color:{{settings.COLORS_VIEW_COUNTER_EMPTY_FG}}"
+ {% else %}
+ style="background:{{settings.COLORS_VIEW_COUNTER_MIN_BG}};color:{{settings.COLORS_VIEW_COUNTER_MIN_FG}}"
+ {% endif %}
+ >{{question.view_count|humanize_counter}}</span>
+ <div>
+ {% blocktrans count question.view_count as cnt %}view{% plural %}views{% endblocktrans %}
+ </div>
+ </div>
+ </div>
+ <h2><a title="{{question.summary}}" href="{% url question id=question.id %}{{question.title|slugify}}">{{question.title}}</a></h2>
+ <div class="userinfo">
+ <span class="relativetime" title="{{question.last_activity_at}}">{% diff_date question.last_activity_at %}</span>
+ {% if question.last_activity_by %}
+ <a href="{% url user_profile question.last_activity_by.id question.last_activity_by.username|slugify %}">{{ question.last_activity_by }}</a> {% get_score_badge question.last_activity_by %}
+ {% endif %}
+ </div>
+ <div class="tags">
+ {% for tag in question.tagname_list %}
+ <a href="{% url questions %}?tags={{tag|urlencode}}" title="{% blocktrans %}see questions tagged '{{ tag }}'{%endblocktrans %}" rel="tag">{{ tag }}</a>
+ {% endfor %}
+ </div>
+ </div>
+ {% endfor %}
+{% endcache %}
+ {% comment %}todo: fix css here{% endcomment %}
+ {% if questions_count == 0 %}
+ {% comment %}todo: add tips to widen selection{% endcomment%}
+ <p class="evenMore" style="padding-top:30px;text-align:center;">
+ {% if scope == "unanswered" %}
+ {% trans "There are no unanswered questions here" %}
+ {% endif %}
+ {% if scope == "favorite" %}
+ {% trans "No favorite questions here. " %}
+ {% trans "Please start (bookmark) some questions when you visit them" %}
+ {% endif %}
+ </p>
+ {% if query or search_tags or author_name %}
+ <p class="evenMore" style="text-align:center">
+ {% trans "You can expand your search by " %}
+ {% ifmany query search_tags author_name %}
+ {% joinitems using ', ' ' or ' %}
+ {% if author_name %}
+ <a href="{% url questions %}?reset_author=true">{% trans "resetting author" %}</a>
+ {% endif %}
+ {% separator %}
+ {% if search_tags %}
+ <a href="{% url questions %}?reset_tags=true">{% trans "resetting tags" %}</a>
+ {% endif %}
+ {% separator %}
+ {% ifmany query search_tags author_name %}
+ <a href="{% url questions %}?start_over=true">{% trans "starting over" %}</a>
+ {% endifmany %}
+ {% endjoinitems %}
+ {% else %}
+ <a href="{% url questions %}?start_over=true">{% trans "starting over" %}</a>
+ {% endifmany %}
+ </p>
+ {% endif %}
+ <p class="evenMore" style="text-align:center">
+ <a href="{% url ask %}">{% trans "Please always feel free to ask your question!" %}</a>
+ </p>
+ {% else %}
+ <p class="evenMore" style="padding-left:9px">
+ {% trans "Did not find what you were looking for?" %}
+ <a href="{% url ask %}">{% trans "Please, post your question!" %}</a>
+ </p>
+ {% endif %}
+</div>
+<!-- end questions_ajax.html -->
diff --git a/askbot/views/readers.py b/askbot/views/readers.py
index 31eeee67..5baac3ab 100644
--- a/askbot/views/readers.py
+++ b/askbot/views/readers.py
@@ -13,7 +13,9 @@ from django.conf import settings
from django.shortcuts import render_to_response, get_object_or_404
from django.http import HttpResponseRedirect, HttpResponse, HttpResponseForbidden, Http404
from django.core.paginator import Paginator, EmptyPage, InvalidPage
-from django.template import RequestContext
+from django.template import RequestContext, Context
+from django.template import loader
+from django.template import defaultfilters
from django.utils.html import *
from django.utils import simplejson
from django.db.models import Q
@@ -21,6 +23,7 @@ from django.utils.translation import ugettext as _
from django.core.urlresolvers import reverse
from django.views.decorators.cache import cache_page
from django.core import exceptions as django_exceptions
+from django.contrib.humanize.templatetags import humanize
from askbot.utils.slug import slugify
from askbot.utils.html import sanitize_html
@@ -35,6 +38,9 @@ from askbot.utils.forms import get_next_url
from askbot.utils.functions import not_a_robot_request
from askbot.utils.decorators import profile
from askbot.search.state_manager import SearchState
+from askbot.templatetags import extra_tags
+from askbot.templatetags import extra_filters
+from askbot.conf import settings as askbot_settings
# used in index page
#todo: - take these out of const or settings
@@ -130,16 +136,164 @@ def questions(request):
raise Http404
questions = objects_list.page(search_state.page)
+
#todo maybe do this search on query the set instead
related_tags = Tag.objects.get_tags_by_questions(questions.object_list)
+ contributors = Question.objects.get_question_and_answer_contributors(questions.object_list)
+
+ paginator_context = {
+ 'is_paginated' : True,
+ 'pages': objects_list.num_pages,
+ 'page': search_state.page,
+ 'has_previous': questions.has_previous(),
+ 'has_next': questions.has_next(),
+ 'previous': questions.previous_page_number(),
+ 'next': questions.next_page_number(),
+ 'base_url' : request.path + '?sort=%s&' % search_state.sort,#todo in T sort=>sort_method
+ 'page_size' : search_state.page_size,#todo in T pagesize -> page_size
+ }
+
+ if request.is_ajax():
+ q_count = objects_list.count
+ question_counter = ungettext(
+ '%(q_num)s question',
+ '%(q_num)s questions',
+ q_count
+ ) % {
+ 'q_num': humanize.intcomma(q_count),
+ }
+
+ paginator_tpl = loader.get_template('paginator.html')
+ paginator_html = paginator_tpl.render(
+ Context(
+ extra_tags.cnprog_paginator(
+ paginator_context
+ )
+ )
+ )
+
+ ajax_data = {
+ #current page is 1 by default now
+ #because ajax is only called by update in the search button
+ 'paginator': paginator_html,
+ 'question_counter': question_counter,
+ 'questions': list(),
+ 'related_tags': list(),
+ 'faces': list()
+ }
+
+ badge_levels = dict(Badge.TYPE_CHOICES)
+ def pluralize_badge_count(count, level):
+ return ungettext(
+ '%(badge_count)d %(badge_level)s badge',
+ '%(badge_count)d %(badge_level)s badges',
+ count
+ ) % {
+ 'badge_count': count,
+ 'badge_level': badge_levels[level]
+ }
+
+ gold_badge_css_class = Badge.CSS_CLASSES[Badge.GOLD],
+ silver_badge_css_class = Badge.CSS_CLASSES[Badge.SILVER],
+ bronze_badge_css_class = Badge.CSS_CLASSES[Badge.BRONZE],
+
+ for tag in related_tags:
+ tag_data = {
+ 'name': tag.name,
+ 'used_count': humanize.intcomma(tag.used_count)
+ }
+ ajax_data['related_tags'].append(tag_data)
+
+ for contributor in contributors:
+ ajax_data['faces'].append(extra_tags.gravatar(contributor, 48))
+
+ for question in questions.object_list:
+ timestamp = question.last_activity_at
+ author = question.last_activity_by
+ #'u_gold_title': pluralized_gold_badge_title,
+ #'u_silver': author.silver,
+ #'u_silver_title': pluralized_silver_badge_title,
+ #'u_bronze': author.bronze,
+ #'u_bronze_title': pluralized_bronze_badge_title,
+ if question.score == 0:
+ votes_color = askbot_settings.COLORS_VOTE_COUNTER_EMPTY_FG
+ votes_bgcolor = askbot_settings.COLORS_VOTE_COUNTER_EMPTY_BG
+ else:
+ votes_color = askbot_settings.COLORS_VOTE_COUNTER_MIN_FG
+ votes_bgcolor = askbot_settings.COLORS_VOTE_COUNTER_MIN_BG
+
+ if question.answer_count == 0:
+ answers_color = askbot_settings.COLORS_ANSWER_COUNTER_EMPTY_FG
+ answers_bgcolor = askbot_settings.COLORS_ANSWER_COUNTER_EMPTY_BG
+ elif question.answer_accepted:
+ answers_color = askbot_settings.COLORS_ANSWER_COUNTER_ACCEPTED_FG
+ answers_bgcolor = askbot_settings.COLORS_ANSWER_COUNTER_ACCEPTED_BG
+ else:
+ answers_color = askbot_settings.COLORS_ANSWER_COUNTER_MIN_FG
+ answers_bgcolor = askbot_settings.COLORS_ANSWER_COUNTER_MIN_BG
+
+ if question.view_count == 0:
+ views_color = askbot_settings.COLORS_VIEW_COUNTER_EMPTY_FG
+ views_bgcolor = askbot_settings.COLORS_VIEW_COUNTER_EMPTY_BG
+ else:
+ views_color = askbot_settings.COLORS_VIEW_COUNTER_MIN_FG
+ views_bgcolor = askbot_settings.COLORS_VIEW_COUNTER_MIN_BG
+
+ question_data = {
+ 'title': question.title,
+ 'summary': question.summary,
+ 'url': question.get_absolute_url(),
+ 'tags': question.get_tag_names(),
+ 'votes': extra_filters.humanize_counter(question.score),
+ 'votes_color': votes_color,
+ 'votes_bgcolor': votes_bgcolor,
+ 'votes_word': ungettext('vote', 'votes', question.score),
+ 'answers': extra_filters.humanize_counter(question.answer_count),
+ 'answers_color': answers_color,
+ 'answers_bgcolor': answers_bgcolor,
+ 'answers_word': ungettext('answer', 'answers', question.answer_count),
+ 'views': extra_filters.humanize_counter(question.view_count),
+ 'views_color': views_color,
+ 'views_bgcolor': views_bgcolor,
+ 'views_word': ungettext('view', 'views', question.view_count),
+ 'timestamp': unicode(timestamp),
+ 'timesince': extra_tags.diff_date(timestamp),
+ 'u_url': author.get_absolute_url(),
+ 'u_name': author.username,
+ 'u_rep': author.reputation,
+ 'u_gold': author.gold,
+ 'u_gold_title': pluralize_badge_count(
+ author.gold,
+ Badge.GOLD
+ ),
+ 'u_gold_badge_symbol': Badge.DISPLAY_SYMBOL,
+ 'u_gold_css_class': gold_badge_css_class,
+ 'u_silver': author.silver,
+ 'u_silver_title': pluralize_badge_count(
+ author.silver,
+ Badge.SILVER
+ ),
+ 'u_silver_badge_symbol': Badge.DISPLAY_SYMBOL,
+ 'u_silver_css_class': silver_badge_css_class,
+ 'u_bronze': author.bronze,
+ 'u_bronze_title': pluralize_badge_count(
+ author.bronze,
+ Badge.BRONZE
+ ),
+ 'u_bronze_badge_symbol': Badge.DISPLAY_SYMBOL,
+ 'u_bronze_css_class': bronze_badge_css_class,
+ }
+ ajax_data['questions'].append(question_data)
+
+ return HttpResponse(
+ simplejson.dumps(ajax_data),
+ mimetype = 'application/json'
+ )
tags_autocomplete = _get_tags_cache_json()
- contributors = Question.objects.get_question_and_answer_contributors(questions.object_list)
- #todo: organize variables by type
- #before = datetime.datetime.now()
- output = render_to_response('questions.html', {
+ template_context = RequestContext(request, {
'view_name': 'questions',
'active_tab': 'questions',
'questions' : questions,
@@ -156,20 +310,21 @@ def questions(request):
'ignored_tag_names': meta_data.get('ignored_tag_names',None),
'sort': search_state.sort,
'scope': search_state.scope,
- 'context' : {
- 'is_paginated' : True,
- 'pages': objects_list.num_pages,
- 'page': search_state.page,
- 'has_previous': questions.has_previous(),
- 'has_next': questions.has_next(),
- 'previous': questions.previous_page_number(),
- 'next': questions.next_page_number(),
- 'base_url' : request.path + '?sort=%s&' % search_state.sort,#todo in T sort=>sort_method
- 'page_size' : search_state.page_size,#todo in T pagesize -> page_size
- }}, context_instance=RequestContext(request))
+ 'context' : paginator_context,
+ })
+
+ #todo: organize variables by type
+ if request.is_ajax():
+ template = loader.get_template('questions_ajax.html')
+ question_snippet = template.render(template_context)
+ output = {'question_snippet': question_snippet}
+ #print simplejson.dumps(output)
+ return HttpResponse(simplejson.dumps(output), mimetype='application/json')
+ else:
+ template = loader.get_template('questions.html')
+ return HttpResponse(template.render(template_context))
#after = datetime.datetime.now()
#print 'time to render %s' % (after - before)
- return output
def search(request): #generates listing of questions matching a search query - including tags and just words
"""redirects to people and tag search pages
@@ -267,9 +422,13 @@ def question(request, id):#refactor - long subroutine. display question body, an
question = get_object_or_404(Question, id=id)
try:
- path_prefix = r'/%s%s%d/' % (settings.ASKBOT_URL,_('question/'), question.id)
+ path_prefix = r'/%s%s%d/' % (
+ settings.ASKBOT_URL,
+ _('question/'),
+ question.id
+ )
if not request.path.startswith(path_prefix):
- logging.critical('bad request path %s' % request_path)
+ logging.critical('bad request path %s' % request.path)
raise Http404
slug = request.path.replace(path_prefix, '', 1)
logging.debug('have slug %s' % slug)