diff options
author | Evgeny Fadeev <evgeny.fadeev@gmail.com> | 2010-09-20 14:04:25 -0400 |
---|---|---|
committer | Evgeny Fadeev <evgeny.fadeev@gmail.com> | 2010-09-20 14:04:25 -0400 |
commit | bd0c24f9fdc1a72c87e5ab653d9483d340faea0e (patch) | |
tree | 96b01daa1b54614f1664ffde1f2298b7da825f76 | |
parent | 9f6d0b3b64e709409f591462892a5907338b9637 (diff) | |
download | askbot-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__.py | 2 | ||||
-rw-r--r-- | askbot/skins/default/media/js/live_search.js | 285 | ||||
-rw-r--r-- | askbot/skins/default/templates/input_bar.html | 11 | ||||
-rw-r--r-- | askbot/skins/default/templates/questions.html | 13 | ||||
-rw-r--r-- | askbot/skins/default/templates/questions_ajax.html | 118 | ||||
-rw-r--r-- | askbot/views/readers.py | 197 |
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">× ' + + 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 %} - <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 %} + <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) |