summaryrefslogtreecommitdiffstats
path: root/templates
diff options
context:
space:
mode:
authorhrcerqueira <hrcerqueira@gmail.com>2010-01-20 16:43:55 +0000
committerhrcerqueira <hrcerqueira@gmail.com>2010-01-20 16:43:55 +0000
commit7518716209e49ecd76ea4de1f169216f8f4fa268 (patch)
treeb8cbf934e8f0a94bc6cac1b4bcab57e0b1d6f5ea /templates
parente8bfbf711f9681d315767c75591c3d63d055b320 (diff)
downloadaskbot-7518716209e49ecd76ea4de1f169216f8f4fa268.tar.gz
askbot-7518716209e49ecd76ea4de1f169216f8f4fa268.tar.bz2
askbot-7518716209e49ecd76ea4de1f169216f8f4fa268.zip
Fixed the redirect when anonymous users try to vote.
Diffstat (limited to 'templates')
-rw-r--r--templates/content/js/com.cnprog.post.js1377
-rw-r--r--templates/question.html1020
2 files changed, 1200 insertions, 1197 deletions
diff --git a/templates/content/js/com.cnprog.post.js b/templates/content/js/com.cnprog.post.js
index 33df1e21..02ed7757 100644
--- a/templates/content/js/com.cnprog.post.js
+++ b/templates/content/js/com.cnprog.post.js
@@ -1,687 +1,690 @@
-/*
-Scripts for cnprog.com
-Project Name: Lanai
-All Rights Resevred 2008. CNPROG.COM
-*/
-var lanai =
-{
- /**
- * Finds any <pre><code></code></pre> tags which aren't registered for
- * pretty printing, adds the appropriate class name and invokes prettify.
- */
- highlightSyntax: function(){
- var styled = false;
- $("pre code").parent().each(function(){
- if (!$(this).hasClass('prettyprint')){
- $(this).addClass('prettyprint');
- styled = true;
- }
- });
-
- if (styled){
- prettyPrint();
- }
- }
-};
-
-var Vote = function(){
- // All actions are related to a question
- var questionId;
- // The object we operate on actually. It can be a question or an answer.
- var postId;
- var questionAuthorId;
- var currentUserId;
- var answerContainerIdPrefix = 'answer-container-';
- var voteContainerId = 'vote-buttons';
- var imgIdPrefixAccept = 'answer-img-accept-';
- var imgClassPrefixFavorite = 'question-img-favorite';
- var imgIdPrefixQuestionVoteup = 'question-img-upvote-';
- var imgIdPrefixQuestionVotedown = 'question-img-downvote-';
- var imgIdPrefixAnswerVoteup = 'answer-img-upvote-';
- var imgIdPrefixAnswerVotedown = 'answer-img-downvote-';
- var divIdFavorite = 'favorite-number';
- var commentLinkIdPrefix = 'comment-';
- var voteNumberClass = "vote-number";
- var offensiveIdPrefixQuestionFlag = 'question-offensive-flag-';
- var offensiveIdPrefixAnswerFlag = 'answer-offensive-flag-';
- var offensiveClassFlag = 'offensive-flag';
- var questionControlsId = 'question-controls';
- var removeQuestionLinkIdPrefix = 'question-delete-link-';
- var removeAnswerLinkIdPrefix = 'answer-delete-link-';
- var questionSubscribeUpdates = 'question-subscribe-updates';
-
- var acceptAnonymousMessage = $.i18n._('insufficient privilege');
- var acceptOwnAnswerMessage = $.i18n._('cannot pick own answer as best');
-
- var pleaseLogin = "<a href='" + scriptUrl + $.i18n._("account/") + $.i18n._("signin/")
- + "?next=" + scriptUrl + $.i18n._("questions/") + "{{QuestionID}}'>"
- + $.i18n._('please login') + "</a>";
-
- var pleaseSeeFAQ = $.i18n._('please see') + "<a href='" + scriptUrl + $.i18n._("faq/") + "'>faq</a>";
-
- var favoriteAnonymousMessage = $.i18n._('anonymous users cannot select favorite questions')
- var voteAnonymousMessage = $.i18n._('anonymous users cannot vote') + pleaseLogin;
- var upVoteRequiredScoreMessage = $.i18n._('>15 points requried to upvote') + pleaseSeeFAQ;
- var downVoteRequiredScoreMessage = $.i18n._('>100 points required to downvote') + pleaseSeeFAQ;
- var voteOwnDeniedMessage = $.i18n._('cannot vote for own posts');
- var voteRequiredMoreVotes = $.i18n._('daily vote cap exhausted') + pleaseSeeFAQ;
- var voteDenyCancelMessage = $.i18n._('cannot revoke old vote') + pleaseSeeFAQ;
- var offensiveConfirmation = $.i18n._('please confirm offensive');
- var offensiveAnonymousMessage = $.i18n._('anonymous users cannot flag offensive posts') + pleaseLogin;
- var offensiveTwiceMessage = $.i18n._('cannot flag message as offensive twice') + pleaseSeeFAQ;
- var offensiveNoFlagsLeftMessage = $.i18n._('flag offensive cap exhausted') + pleaseSeeFAQ;
- var offensiveNoPermissionMessage = $.i18n._('need >15 points to report spam') + pleaseSeeFAQ;
- var removeConfirmation = $.i18n._('confirm delete');
- var removeAnonymousMessage = $.i18n._('anonymous users cannot delete/undelete');
- var recoveredMessage = $.i18n._('post recovered');
- var deletedMessage = $.i18n._('post deleted');
-
- var VoteType = {
- acceptAnswer : 0,
- questionUpVote : 1,
- questionDownVote : 2,
- favorite : 4,
- answerUpVote: 5,
- answerDownVote:6,
- offensiveQuestion : 7,
- offensiveAnswer:8,
- removeQuestion: 9,
- removeAnswer:10,
- questionSubscribeUpdates:11,
- questionUnsubscribeUpdates:12
- };
-
- var getFavoriteButton = function(){
- var favoriteButton = 'div.'+ voteContainerId +' img[class='+ imgClassPrefixFavorite +']';
- return $(favoriteButton);
- };
- var getFavoriteNumber = function(){
- var favoriteNumber = '#'+ divIdFavorite ;
- return $(favoriteNumber);
- };
- var getQuestionVoteUpButton = function(){
- var questionVoteUpButton = 'div.'+ voteContainerId +' img[id^='+ imgIdPrefixQuestionVoteup +']';
- return $(questionVoteUpButton);
- };
- var getQuestionVoteDownButton = function(){
- var questionVoteDownButton = 'div.'+ voteContainerId +' img[id^='+ imgIdPrefixQuestionVotedown +']';
- return $(questionVoteDownButton);
- };
- var getAnswerVoteUpButtons = function(){
- var answerVoteUpButton = 'div.'+ voteContainerId +' img[id^='+ imgIdPrefixAnswerVoteup +']';
- return $(answerVoteUpButton);
- };
- var getAnswerVoteDownButtons = function(){
- var answerVoteDownButton = 'div.'+ voteContainerId +' img[id^='+ imgIdPrefixAnswerVotedown +']';
- return $(answerVoteDownButton);
- };
- var getAnswerVoteUpButton = function(id){
- var answerVoteUpButton = 'div.'+ voteContainerId +' img[id='+ imgIdPrefixAnswerVoteup + id + ']';
- return $(answerVoteUpButton);
- };
- var getAnswerVoteDownButton = function(id){
- var answerVoteDownButton = 'div.'+ voteContainerId +' img[id='+ imgIdPrefixAnswerVotedown + id + ']';
- return $(answerVoteDownButton);
- };
-
- var getOffensiveQuestionFlag = function(){
- var offensiveQuestionFlag = '#question-table span[class='+ offensiveClassFlag +']';
- return $(offensiveQuestionFlag);
- };
-
- var getOffensiveAnswerFlags = function(){
- var offensiveQuestionFlag = 'div.answer span[class='+ offensiveClassFlag +']';
- return $(offensiveQuestionFlag);
- };
-
- var getremoveQuestionLink = function(){
- var removeQuestionLink = 'div#question-controls a[id^='+ removeQuestionLinkIdPrefix +']';
- return $(removeQuestionLink);
- };
-
- var getquestionSubscribeUpdatesCheckbox = function(){
- return $('#' + questionSubscribeUpdates);
- };
-
- var getremoveAnswersLinks = function(){
- var removeAnswerLinks = 'div.answer-controls a[id^='+ removeAnswerLinkIdPrefix +']';
- return $(removeAnswerLinks);
- };
-
- var setVoteImage = function(voteType, undo, object){
- var flag = undo ? "" : "-on";
- var arrow = (voteType == VoteType.questionUpVote || voteType == VoteType.answerUpVote) ? "up" : "down";
- object.attr("src", scriptUrl + "content/images/vote-arrow-"+ arrow + flag +".png");
-
- // if undo voting, then undo the pair of arrows.
- if(undo){
- if(voteType == VoteType.questionUpVote || voteType == VoteType.questionDownVote){
- $(getQuestionVoteUpButton()).attr("src", scriptUrl + "content/images/vote-arrow-up.png");
- $(getQuestionVoteDownButton()).attr("src", scriptUrl + "content/images/vote-arrow-down.png");
- }
- else{
- $(getAnswerVoteUpButton(postId)).attr("src", scriptUrl + "content/images/vote-arrow-up.png");
- $(getAnswerVoteDownButton(postId)).attr("src", scriptUrl + "content/images/vote-arrow-down.png");
- }
- }
- };
-
- var setVoteNumber = function(object, number){
- var voteNumber = object.parent('div.'+ voteContainerId).find('div.'+ voteNumberClass);
- $(voteNumber).text(number);
- };
-
- var bindEvents = function(){
- // accept answers
- if(questionAuthorId == currentUserId){
- var acceptedButtons = 'div.'+ voteContainerId +' img[id^='+ imgIdPrefixAccept +']';
- $(acceptedButtons).unbind('click').click(function(event){
- Vote.accept($(event.target));
- });
- }
- // set favorite question
- var favoriteButton = getFavoriteButton();
- favoriteButton.unbind('click').click(function(event){
- Vote.favorite($(event.target));
- });
-
- // question vote up
- var questionVoteUpButton = getQuestionVoteUpButton();
- questionVoteUpButton.unbind('click').click(function(event){
- Vote.vote($(event.target), VoteType.questionUpVote);
- });
-
- var questionVoteDownButton = getQuestionVoteDownButton();
- questionVoteDownButton.unbind('click').click(function(event){
- Vote.vote($(event.target), VoteType.questionDownVote);
- });
-
- var answerVoteUpButton = getAnswerVoteUpButtons();
- answerVoteUpButton.unbind('click').click(function(event){
- Vote.vote($(event.target), VoteType.answerUpVote);
- });
-
- var answerVoteDownButton = getAnswerVoteDownButtons();
- answerVoteDownButton.unbind('click').click(function(event){
- Vote.vote($(event.target), VoteType.answerDownVote);
- });
-
- getOffensiveQuestionFlag().unbind('click').click(function(event){
- Vote.offensive(this, VoteType.offensiveQuestion);
- });
-
- getOffensiveAnswerFlags().unbind('click').click(function(event){
- Vote.offensive(this, VoteType.offensiveAnswer);
- });
-
- getremoveQuestionLink().unbind('click').click(function(event){
- Vote.remove(this, VoteType.removeQuestion);
- });
-
- getquestionSubscribeUpdatesCheckbox().unbind('click').click(function(event){
- if (this.checked){
- Vote.vote($(event.target), VoteType.questionSubscribeUpdates);
- }
- else {
- Vote.vote($(event.target), VoteType.questionUnsubscribeUpdates);
- }
- });
-
- getremoveAnswersLinks().unbind('click').click(function(event){
- Vote.remove(this, VoteType.removeAnswer);
- });
- };
-
- var submit = function(object, voteType, callback) {
- $.ajax({
- type: "POST",
- cache: false,
- dataType: "json",
- url: scriptUrl + $.i18n._("questions/") + questionId + "/" + $.i18n._("vote/"),
- data: { "type": voteType, "postId": postId },
- error: handleFail,
- success: function(data){callback(object, voteType, data)}});
- };
-
- var handleFail = function(xhr, msg){
- alert("Callback invoke error: " + msg);
- };
-
- // callback function for Accept Answer action
- var callback_accept = function(object, voteType, data){
- if(data.allowed == "0" && data.success == "0"){
- showMessage(object, acceptAnonymousMessage);
- }
- else if(data.allowed == "-1"){
- showMessage(object, acceptOwnAnswerMessage);
- }
- else if(data.status == "1"){
- object.attr("src", scriptUrl + "content/images/vote-accepted.png");
- $("#"+answerContainerIdPrefix+postId).removeClass("accepted-answer");
- $("#"+commentLinkIdPrefix+postId).removeClass("comment-link-accepted");
- }
- else if(data.success == "1"){
- var acceptedButtons = 'div.'+ voteContainerId +' img[id^='+ imgIdPrefixAccept +']';
- $(acceptedButtons).attr("src", scriptUrl + "content/images/vote-accepted.png");
- var answers = ("div[id^="+answerContainerIdPrefix +"]");
- $(answers).removeClass("accepted-answer");
- var commentLinks = ("div[id^="+answerContainerIdPrefix +"] div[id^="+ commentLinkIdPrefix +"]");
- $(commentLinks).removeClass("comment-link-accepted");
-
- object.attr("src", scriptUrl + "content/images/vote-accepted-on.png");
- $("#"+answerContainerIdPrefix+postId).addClass("accepted-answer");
- $("#"+commentLinkIdPrefix+postId).addClass("comment-link-accepted");
- }
- else{
- showMessage(object, data.message);
- }
- };
-
- var callback_favorite = function(object, voteType, data){
- if(data.allowed == "0" && data.success == "0"){
- showMessage(object, favoriteAnonymousMessage.replace("{{QuestionID}}", questionId));
- }
- else if(data.status == "1"){
- object.attr("src", scriptUrl + "content/images/vote-favorite-off.png");
- var fav = getFavoriteNumber();
- fav.removeClass("my-favorite-number");
- if(data.count == 0)
- data.count = '';
- fav.text(data.count);
- }
- else if(data.success == "1"){
- object.attr("src", scriptUrl + "content/images/vote-favorite-on.png");
- var fav = getFavoriteNumber();
- fav.text(data.count);
- fav.addClass("my-favorite-number");
- }
- else{
- showMessage(object, data.message);
- }
- };
-
- var callback_vote = function(object, voteType, data){
- if(data.allowed == "0" && data.success == "0"){
- showMessage(object, voteAnonymousMessage.replace("{{QuestionID}}", questionId));
- }
- else if (data.allowed == "-3"){
- showMessage(object, voteRequiredMoreVotes);
- }
- else if (data.allowed == "-2"){
- if (voteType == VoteType.questionUpVote || voteType == VoteType.answerUpVote){
- showMessage(object, upVoteRequiredScoreMessage);
- }
- else if (voteType == VoteType.questionDownVote || voteType == VoteType.answerDownVote){
- showMessage(object, downVoteRequiredScoreMessage);
- }
- }
- else if (data.allowed == "-1"){
- showMessage(object, voteOwnDeniedMessage);
- }
- else if (data.status == "2"){
- showMessage(object, voteDenyCancelMessage);
- }
- else if (data.status == "1"){
- setVoteImage(voteType, true, object);
- setVoteNumber(object, data.count);
- }
- else if (data.success == "1"){
- setVoteImage(voteType, false, object);
- setVoteNumber(object, data.count);
- if (data.message.length > 0){
- showMessage(object, data.message);
- }
- }
- };
-
- var callback_offensive = function(object, voteType, data){
- object = $(object);
- if (data.allowed == "0" && data.success == "0"){
- showMessage(object, offensiveAnonymousMessage.replace("{{QuestionID}}", questionId));
- }
- else if (data.allowed == "-3"){
- showMessage(object, offensiveNoFlagsLeftMessage);
- }
- else if (data.allowed == "-2"){
- showMessage(object, offensiveNoPermissionMessage);
- }
- else if (data.status == "1"){
- showMessage(object, offensiveTwiceMessage);
- }
- else if (data.success == "1"){
- $(object).children('span[class=darkred]').text("("+ data.count +")");
- }
- };
-
- var callback_remove = function(object, voteType, data){
- if (data.allowed == "0" && data.success == "0"){
- showMessage(object, removeAnonymousMessage.replace("{{QuestionID}}", questionId));
- }
- else if (data.success == "1"){
- if (voteType == VoteType.removeQuestion){
- window.location.href = scriptUrl + $.i18n._("questions/");
- }
- else {
- if (removeActionType == 'delete'){
- postNode.addClass('deleted');
- postRemoveLink.innerHTML = $.i18n._('undelete');
- showMessage(object, deletedMessage);
- }
- else if (removeActionType == 'undelete') {
- postNode.removeClass('deleted');
- postRemoveLink.innerHTML = $.i18n._('delete');
- showMessage(object, recoveredMessage);
- }
- }
- }
- };
-
- return {
- init : function(qId, questionAuthor, userId){
- questionId = qId;
- questionAuthorId = questionAuthor;
- currentUserId = userId;
- bindEvents();
- },
-
- // Accept answer public function
- accept: function(object){
- postId = object.attr("id").substring(imgIdPrefixAccept.length);
- submit(object, VoteType.acceptAnswer, callback_accept);
- },
-
- favorite: function(object){
- if (!currentUserId || currentUserId.toUpperCase() == "NONE"){
- showMessage(object, favoriteAnonymousMessage.replace("{{QuestionID}}", questionId));
- return false;
- }
- submit(object, VoteType.favorite, callback_favorite);
- },
-
- vote: function(object, voteType){
- if (!currentUserId || currentUserId.toUpperCase() == "NONE"){
- showMessage(object, voteAnonymousMessage.replace("{{QuestionID}}", questionId));
- return false;
- }
- if (voteType == VoteType.answerUpVote){
- postId = object.attr("id").substring(imgIdPrefixAnswerVoteup.length);
- }
- else if (voteType == VoteType.answerDownVote){
- postId = object.attr("id").substring(imgIdPrefixAnswerVotedown.length);
- }
-
- submit(object, voteType, callback_vote);
- },
-
- offensive: function(object, voteType){
- if (!currentUserId || currentUserId.toUpperCase() == "NONE"){
- showMessage($(object), offensiveAnonymousMessage.replace("{{QuestionID}}", questionId));
- return false;
- }
- if (confirm(offensiveConfirmation)){
- postId = object.id.substr(object.id.lastIndexOf('-') + 1);
- submit(object, voteType, callback_offensive);
- }
- },
-
- remove: function(object, voteType){
- if (!currentUserId || currentUserId.toUpperCase() == "NONE"){
- showMessage($(object), removeAnonymousMessage.replace("{{QuestionID}}", questionId));
- return false;
- }
- bits = object.id.split('-');
- postId = bits.pop();/* this seems to be used within submit! */
- postType = bits.shift();
-
- var do_proceed = false;
- if (postType == 'answer'){
- postNode = $('#answer-container-' + postId);
- postRemoveLink = object;
- if (postNode.hasClass('deleted')){
- removeActionType = 'undelete';
- do_proceed = true;
- }
- else {
- removeActionType = 'delete';
- do_proceed = confirm(removeConfirmation);
- }
- }
- else {
- do_proceed = confirm(removeConfirmation);
- }
- if (do_proceed) {
- submit($(object), voteType, callback_remove);
- }
- }
- }
-} ();
-
-
-// site comments
-function createComments(type) {
- var objectType = type;
- var jDivInit = function(id) {
- return $("#comments-container-" + objectType + '-' + id);
- };
-
- var appendLoaderImg = function(id) {
- appendLoader("#comments-container-" + objectType + '-' + id);
- };
-
- var canPostComments = function(id) {
- var jHidden = $("#can-post-comments-" + objectType + '-' + id);
- return jHidden.val().toLowerCase() == "true";
- };
-
- var renderForm = function(id) {
- var formId = "form-comments-" + objectType + "-" + id;
- var jDiv = $('#comments-link-' + objectType + "-" + id).parent();
- $(jDiv).css('background','none');
- $(jDiv).css('padding-left',0);
- if (canPostComments(id)) {
- if (jDiv.find("#" + formId).length == 0) {
- var form = '<form id="' + formId + '" class="post-comments"><div>';
- form += '<textarea name="comment" cols="60" rows="5" maxlength="300" onblur="'+ objectType +'Comments.updateTextCounter(this)" ';
- form += 'onfocus="' + objectType + 'Comments.updateTextCounter(this)" onkeyup="'+ objectType +'Comments.updateTextCounter(this)"></textarea>';
- form += '<input type="submit" value="'
- + $.i18n._('add comment') + '" /><br><span class="text-counter"></span>';
- form += '<span class="form-error"></span></div></form>';
-
- jDiv.append(form);
-
- setupFormValidation("#" + formId,
- { comment: { required: true, minlength: 10} }, '',
- function() { postComment(id, formId); });
- }
- }
- else {
- var divId = "comments-rep-needed-" + objectType + '-' + id;
- if (jDiv.find("#" + divId).length == 0) {
- jDiv.append('<p id="' + divId + '" class="comment">'
- + $.i18n._('to comment, need') + ' ' +
- + repNeededForComments + ' ' + $.i18n._('community karma points')
- + '<a href="' + scriptUrl + $.i18n._('faq/') + '" class="comment-user">'
- + $.i18n._('please see') + 'faq</a></span></p>');
- }
- }
- };
-
- var getComments = function(id, jDiv) {
- //appendLoaderImg(id);
- $.getJSON(scriptUrl + objectType + "s/" + id + "/" + $.i18n._("comments/")
- , function(json) { showComments(id, json); });
- };
-
- var showComments = function(id, json) {
- var jDiv = jDivInit(id);
-
- //jDiv = jDiv.find("div.comments"); // this div should contain any fetched comments..
- //jDiv.find("div[id^='comment-" + objectType + "-'" + "]").remove(); // clean previous calls..
- jDiv.children().remove();
- removeLoader();
- if (json && json.length > 0) {
- for (var i = 0; i < json.length; i++)
- renderComment(jDiv, json[i]);
- jDiv.children().show();
- }
- };
-
- var renderDeleteCommentIcon = function(post_id, delete_url){
- if (canPostComments(post_id)){
- var html = '';
- var img = scriptUrl + "content/images/close-small.png";
- var imgHover = scriptUrl + "content/images/close-small-hover.png";
- html += '<img class="delete-icon" onclick="' + objectType + 'Comments.deleteComment($(this), ' + post_id + ', \'' + delete_url + '\')" src="' + img;
- html += '" onmouseover="$(this).attr(\'src\', \'' + imgHover + '\')" onmouseout="$(this).attr(\'src\', \'' + img
- html += '\')" title="' + $.i18n._('delete this comment') + '" />';
- return html;
- }
- else{
- return '';
- }
- }
-
- // {"Id":6,"PostId":38589,"CreationDate":"an hour ago","Text":"hello there!","UserDisplayName":"Jarrod Dixon","UserUrl":"/users/3/jarrod-dixon","DeleteUrl":null}
- var renderComment = function(jDiv, json) {
- var html = '<p id="comment-' + json.id + '" class="comment" style="display:none">' + json.text;
- html += json.user_url ? ' - <a href="' + json.user_url + '"' : '<span';
- html += ' class="comment-user">' + json.user_display_name + (json.user_url ? '</a>' : '</span>');
- html += ' (' + json.comment_age + ')';
-
- if (json.delete_url){
- html += renderDeleteCommentIcon(json.object_id, json.delete_url);
- }
-
- if (json.delete_url) {
- }
-
- html += '</p>';
-
- jDiv.append(html);
- };
-
- var postComment = function(id, formId) {
- //appendLoaderImg(id);
-
- var formSelector = "#" + formId;
- var textarea = $(formSelector + " textarea");
-
- //todo fix url translations!!!
- $.ajax({
- type: "POST",
- url: scriptUrl + objectType + "s/" + id + "/" + $.i18n._("comments/"),
- dataType: "json",
- data: { comment: textarea.val() },
- success: function(json) {
- showComments(id, json);
- textarea.val("");
- commentsFactory[objectType].updateTextCounter(textarea);
- enableSubmitButton(formSelector);
- },
- error: function(res, textStatus, errorThrown) {
- removeLoader();
- showMessage(formSelector, res.responseText);
- enableSubmitButton(formSelector);
- }
- });
- };
-
- // public methods..
- return {
-
- init: function() {
- // Setup "show comments" clicks..
- $("a[id^='comments-link-" + objectType + "-" + "']").unbind("click").click(function() {
- commentsFactory[objectType].show($(this).attr("id").substr(("comments-link-" + objectType + "-").length));
- });
-
- var cBox = $("[id^='comments-container-" + objectType + "']");
- cBox.each( function(i){
- var post_id = $(this).attr('id').replace('comments-container-' + objectType + '-', '');
- $(this).children().each(
- function(i){
- var comment_id = $(this).attr('id').replace('comment-','');
- var delete_url = scriptUrl + objectType + 's/' + post_id + '/'
- + $.i18n._('comments/') + comment_id + '/' + $.i18n._('delete/');
- var html = $(this).html();
- var CommentsClass;
- if (objectType == 'question'){
- CommentsClass = questionComments;
- }
- else if (objectType == 'answer') {
- CommentsClass = answerComments;
- }
- var delete_icon = $(this).find('img.delete-icon');
- delete_icon.click(function(){CommentsClass.deleteComment($(this),comment_id,delete_url);});
- delete_icon.unbind('mouseover').bind('mouseover',
- function(){
- $(this).attr('src',scriptUrl + 'content/images/close-small-hover.png');
- }
- );
- delete_icon.unbind('mouseout').bind('mouseout',
- function(){
- $(this).attr('src',scriptUrl + 'content/images/close-small.png');
- }
- );
- }
- );
- });
- },
-
- show: function(id) {
- var jDiv = jDivInit(id);
- getComments(id, jDiv);
- renderForm(id);
- jDiv.show();
-
- var link = $('#comments-link-' + objectType + '-' + id);
- if (canPostComments(id)) link.parent().find("textarea").get(0).focus();
- link.remove();
- },
-
- hide: function(id) {
- var jDiv = jDivInit(id);
- var len = jDiv.children("div.comments").children().length;
- var anchorText = len == 0 ? $.i18n._('add a comment') : $.i18n._('comments') + ' (<b>' + len + "</b>)";
-
- jDiv.hide();
- jDiv.siblings("a").unbind("click").click(function() { commentsFactory[objectType].show(id); }).html(anchorText);
- jDiv.children("div.comments").children().hide();
- },
-
- deleteComment: function(jImg, id, deleteUrl) {
- if (confirm($.i18n._('confirm delete comment'))) {
- jImg.hide();
- $.post(deleteUrl, { dataNeeded: "forIIS7" }, function(json) {
- var par = jImg.parent();
- par.remove();
- }, "json");
- }
- },
-
- updateTextCounter: function(textarea) {
- var length = textarea.value ? textarea.value.length : 0;
- var color = length > 270 ? "#f00" : length > 200 ? "#f60" : "#999";
- var jSpan = $(textarea).siblings("span.text-counter");
- jSpan.html($.i18n._('can write')
- + (300 - length) + ' '
- + $.i18n._('characters')).css("color", color);
- }
- };
-}
-
-var questionComments = createComments('question');
-var answerComments = createComments('answer');
-
-$().ready(function() {
- questionComments.init();
- answerComments.init();
-});
-
-var commentsFactory = {'question' : questionComments, 'answer' : answerComments};
-
-/*
-Prettify
-http://www.apache.org/licenses/LICENSE-2.0
-*/
-var PR_SHOULD_USE_CONTINUATION = true; var PR_TAB_WIDTH = 8; var PR_normalizedHtml; var PR; var prettyPrintOne; var prettyPrint; function _pr_isIE6() { var isIE6 = navigator && navigator.userAgent && /\bMSIE 6\./.test(navigator.userAgent); _pr_isIE6 = function() { return isIE6; }; return isIE6; } (function() { function wordSet(words) { words = words.split(/ /g); var set = {}; for (var i = words.length; --i >= 0; ) { var w = words[i]; if (w) { set[w] = null; } } return set; } var FLOW_CONTROL_KEYWORDS = "break continue do else for if return while "; var C_KEYWORDS = FLOW_CONTROL_KEYWORDS + "auto case char const default " + "double enum extern float goto int long register short signed sizeof " + "static struct switch typedef union unsigned void volatile "; var COMMON_KEYWORDS = C_KEYWORDS + "catch class delete false import " + "new operator private protected public this throw true try "; var CPP_KEYWORDS = COMMON_KEYWORDS + "alignof align_union asm axiom bool " + "concept concept_map const_cast constexpr decltype " + "dynamic_cast explicit export friend inline late_check " + "mutable namespace nullptr reinterpret_cast static_assert static_cast " + "template typeid typename typeof using virtual wchar_t where "; var JAVA_KEYWORDS = COMMON_KEYWORDS + "boolean byte extends final finally implements import instanceof null " + "native package strictfp super synchronized throws transient "; var CSHARP_KEYWORDS = JAVA_KEYWORDS + "as base by checked decimal delegate descending event " + "fixed foreach from group implicit in interface internal into is lock " + "object out override orderby params readonly ref sbyte sealed " + "stackalloc string select uint ulong unchecked unsafe ushort var "; var JSCRIPT_KEYWORDS = COMMON_KEYWORDS + "debugger eval export function get null set undefined var with " + "Infinity NaN "; var PERL_KEYWORDS = "caller delete die do dump elsif eval exit foreach for " + "goto if import last local my next no our print package redo require " + "sub undef unless until use wantarray while BEGIN END "; var PYTHON_KEYWORDS = FLOW_CONTROL_KEYWORDS + "and as assert class def del " + "elif except exec finally from global import in is lambda " + "nonlocal not or pass print raise try with yield " + "False True None "; var RUBY_KEYWORDS = FLOW_CONTROL_KEYWORDS + "alias and begin case class def" + " defined elsif end ensure false in module next nil not or redo rescue " + "retry self super then true undef unless until when yield BEGIN END "; var SH_KEYWORDS = FLOW_CONTROL_KEYWORDS + "case done elif esac eval fi " + "function in local set then until "; var ALL_KEYWORDS = (CPP_KEYWORDS + CSHARP_KEYWORDS + JSCRIPT_KEYWORDS + PERL_KEYWORDS + PYTHON_KEYWORDS + RUBY_KEYWORDS + SH_KEYWORDS); var PR_STRING = 'str'; var PR_KEYWORD = 'kwd'; var PR_COMMENT = 'com'; var PR_TYPE = 'typ'; var PR_LITERAL = 'lit'; var PR_PUNCTUATION = 'pun'; var PR_PLAIN = 'pln'; var PR_TAG = 'tag'; var PR_DECLARATION = 'dec'; var PR_SOURCE = 'src'; var PR_ATTRIB_NAME = 'atn'; var PR_ATTRIB_VALUE = 'atv'; var PR_NOCODE = 'nocode'; function isWordChar(ch) { return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'); } function spliceArrayInto(inserted, container, containerPosition, countReplaced) { inserted.unshift(containerPosition, countReplaced || 0); try { container.splice.apply(container, inserted); } finally { inserted.splice(0, 2); } } var REGEXP_PRECEDER_PATTERN = function() { var preceders = ["!", "!=", "!==", "#", "%", "%=", "&", "&&", "&&=", "&=", "(", "*", "*=", "+=", ",", "-=", "->", "/", "/=", ":", "::", ";", "<", "<<", "<<=", "<=", "=", "==", "===", ">", ">=", ">>", ">>=", ">>>", ">>>=", "?", "@", "[", "^", "^=", "^^", "^^=", "{", "|", "|=", "||", "||=", "~", "break", "case", "continue", "delete", "do", "else", "finally", "instanceof", "return", "throw", "try", "typeof"]; var pattern = '(?:' + '(?:(?:^|[^0-9.])\\.{1,3})|' + '(?:(?:^|[^\\+])\\+)|' + '(?:(?:^|[^\\-])-)'; for (var i = 0; i < preceders.length; ++i) { var preceder = preceders[i]; if (isWordChar(preceder.charAt(0))) { pattern += '|\\b' + preceder; } else { pattern += '|' + preceder.replace(/([^=<>:&])/g, '\\$1'); } } pattern += '|^)\\s*$'; return new RegExp(pattern); } (); var pr_amp = /&/g; var pr_lt = /</g; var pr_gt = />/g; var pr_quot = /\"/g; function attribToHtml(str) { return str.replace(pr_amp, '&amp;').replace(pr_lt, '&lt;').replace(pr_gt, '&gt;').replace(pr_quot, '&quot;'); } function textToHtml(str) { return str.replace(pr_amp, '&amp;').replace(pr_lt, '&lt;').replace(pr_gt, '&gt;'); } var pr_ltEnt = /&lt;/g; var pr_gtEnt = /&gt;/g; var pr_aposEnt = /&apos;/g; var pr_quotEnt = /&quot;/g; var pr_ampEnt = /&amp;/g; var pr_nbspEnt = /&nbsp;/g; function htmlToText(html) { var pos = html.indexOf('&'); if (pos < 0) { return html; } for (--pos; (pos = html.indexOf('&#', pos + 1)) >= 0; ) { var end = html.indexOf(';', pos); if (end >= 0) { var num = html.substring(pos + 3, end); var radix = 10; if (num && num.charAt(0) === 'x') { num = num.substring(1); radix = 16; } var codePoint = parseInt(num, radix); if (!isNaN(codePoint)) { html = (html.substring(0, pos) + String.fromCharCode(codePoint) + html.substring(end + 1)); } } } return html.replace(pr_ltEnt, '<').replace(pr_gtEnt, '>').replace(pr_aposEnt, "'").replace(pr_quotEnt, '"').replace(pr_ampEnt, '&').replace(pr_nbspEnt, ' '); } function isRawContent(node) { return 'XMP' === node.tagName; } function normalizedHtml(node, out) { switch (node.nodeType) { case 1: var name = node.tagName.toLowerCase(); out.push('<', name); for (var i = 0; i < node.attributes.length; ++i) { var attr = node.attributes[i]; if (!attr.specified) { continue; } out.push(' '); normalizedHtml(attr, out); } out.push('>'); for (var child = node.firstChild; child; child = child.nextSibling) { normalizedHtml(child, out); } if (node.firstChild || !/^(?:br|link|img)$/.test(name)) { out.push('<\/', name, '>'); } break; case 2: out.push(node.name.toLowerCase(), '="', attribToHtml(node.value), '"'); break; case 3: case 4: out.push(textToHtml(node.nodeValue)); break; } } var PR_innerHtmlWorks = null; function getInnerHtml(node) { if (null === PR_innerHtmlWorks) { var testNode = document.createElement('PRE'); testNode.appendChild(document.createTextNode('<!DOCTYPE foo PUBLIC "foo bar">\n<foo />')); PR_innerHtmlWorks = !/</.test(testNode.innerHTML); } if (PR_innerHtmlWorks) { var content = node.innerHTML; if (isRawContent(node)) { content = textToHtml(content); } return content; } var out = []; for (var child = node.firstChild; child; child = child.nextSibling) { normalizedHtml(child, out); } return out.join(''); } function makeTabExpander(tabWidth) { var SPACES = ' '; var charInLine = 0; return function(plainText) { var out = null; var pos = 0; for (var i = 0, n = plainText.length; i < n; ++i) { var ch = plainText.charAt(i); switch (ch) { case '\t': if (!out) { out = []; } out.push(plainText.substring(pos, i)); var nSpaces = tabWidth - (charInLine % tabWidth); charInLine += nSpaces; for (; nSpaces >= 0; nSpaces -= SPACES.length) { out.push(SPACES.substring(0, nSpaces)); } pos = i + 1; break; case '\n': charInLine = 0; break; default: ++charInLine; } } if (!out) { return plainText; } out.push(plainText.substring(pos)); return out.join(''); }; } var pr_chunkPattern = /(?:[^<]+|<!--[\s\S]*?-->|<!\[CDATA\[([\s\S]*?)\]\]>|<\/?[a-zA-Z][^>]*>|<)/g; var pr_commentPrefix = /^<!--/; var pr_cdataPrefix = /^<\[CDATA\[/; var pr_brPrefix = /^<br\b/i; var pr_tagNameRe = /^<(\/?)([a-zA-Z]+)/; function extractTags(s) { var matches = s.match(pr_chunkPattern); var sourceBuf = []; var sourceBufLen = 0; var extractedTags = []; if (matches) { for (var i = 0, n = matches.length; i < n; ++i) { var match = matches[i]; if (match.length > 1 && match.charAt(0) === '<') { if (pr_commentPrefix.test(match)) { continue; } if (pr_cdataPrefix.test(match)) { sourceBuf.push(match.substring(9, match.length - 3)); sourceBufLen += match.length - 12; } else if (pr_brPrefix.test(match)) { sourceBuf.push('\n'); ++sourceBufLen; } else { if (match.indexOf(PR_NOCODE) >= 0 && isNoCodeTag(match)) { var name = match.match(pr_tagNameRe)[2]; var depth = 1; end_tag_loop: for (var j = i + 1; j < n; ++j) { var name2 = matches[j].match(pr_tagNameRe); if (name2 && name2[2] === name) { if (name2[1] === '/') { if (--depth === 0) { break end_tag_loop; } } else { ++depth; } } } if (j < n) { extractedTags.push(sourceBufLen, matches.slice(i, j + 1).join('')); i = j; } else { extractedTags.push(sourceBufLen, match); } } else { extractedTags.push(sourceBufLen, match); } } } else { var literalText = htmlToText(match); sourceBuf.push(literalText); sourceBufLen += literalText.length; } } } return { source: sourceBuf.join(''), tags: extractedTags }; } function isNoCodeTag(tag) { return !!tag.replace(/\s(\w+)\s*=\s*(?:\"([^\"]*)\"|'([^\']*)'|(\S+))/g, ' $1="$2$3$4"').match(/[cC][lL][aA][sS][sS]=\"[^\"]*\bnocode\b/); } function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) { var shortcuts = {}; (function() { var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns); for (var i = allPatterns.length; --i >= 0; ) { var patternParts = allPatterns[i]; var shortcutChars = patternParts[3]; if (shortcutChars) { for (var c = shortcutChars.length; --c >= 0; ) { shortcuts[shortcutChars.charAt(c)] = patternParts; } } } })(); var nPatterns = fallthroughStylePatterns.length; var notWs = /\S/; return function(sourceCode, opt_basePos) { opt_basePos = opt_basePos || 0; var decorations = [opt_basePos, PR_PLAIN]; var lastToken = ''; var pos = 0; var tail = sourceCode; while (tail.length) { var style; var token = null; var match; var patternParts = shortcuts[tail.charAt(0)]; if (patternParts) { match = tail.match(patternParts[1]); token = match[0]; style = patternParts[0]; } else { for (var i = 0; i < nPatterns; ++i) { patternParts = fallthroughStylePatterns[i]; var contextPattern = patternParts[2]; if (contextPattern && !contextPattern.test(lastToken)) { continue; } match = tail.match(patternParts[1]); if (match) { token = match[0]; style = patternParts[0]; break; } } if (!token) { style = PR_PLAIN; token = tail.substring(0, 1); } } decorations.push(opt_basePos + pos, style); pos += token.length; tail = tail.substring(token.length); if (style !== PR_COMMENT && notWs.test(token)) { lastToken = token; } } return decorations; }; } var PR_MARKUP_LEXER = createSimpleLexer([], [[PR_PLAIN, /^[^<]+/, null], [PR_DECLARATION, /^<!\w[^>]*(?:>|$)/, null], [PR_COMMENT, /^<!--[\s\S]*?(?:-->|$)/, null], [PR_SOURCE, /^<\?[\s\S]*?(?:\?>|$)/, null], [PR_SOURCE, /^<%[\s\S]*?(?:%>|$)/, null], [PR_SOURCE, /^<(script|style|xmp)\b[^>]*>[\s\S]*?<\/\1\b[^>]*>/i, null], [PR_TAG, /^<\/?\w[^<>]*>/, null]]); var PR_SOURCE_CHUNK_PARTS = /^(<[^>]*>)([\s\S]*)(<\/[^>]*>)$/; function tokenizeMarkup(source) { var decorations = PR_MARKUP_LEXER(source); for (var i = 0; i < decorations.length; i += 2) { if (decorations[i + 1] === PR_SOURCE) { var start, end; start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; var sourceChunk = source.substring(start, end); var match = sourceChunk.match(PR_SOURCE_CHUNK_PARTS); if (match) { decorations.splice(i, 2, start, PR_TAG, start + match[1].length, PR_SOURCE, start + match[1].length + (match[2] || '').length, PR_TAG); } } } return decorations; } var PR_TAG_LEXER = createSimpleLexer([[PR_ATTRIB_VALUE, /^\'[^\']*(?:\'|$)/, null, "'"], [PR_ATTRIB_VALUE, /^\"[^\"]*(?:\"|$)/, null, '"'], [PR_PUNCTUATION, /^[<>\/=]+/, null, '<>/=']], [[PR_TAG, /^[\w:\-]+/, /^</], [PR_ATTRIB_VALUE, /^[\w\-]+/, /^=/], [PR_ATTRIB_NAME, /^[\w:\-]+/, null], [PR_PLAIN, /^\s+/, null, ' \t\r\n']]); function splitTagAttributes(source, decorations) { for (var i = 0; i < decorations.length; i += 2) { var style = decorations[i + 1]; if (style === PR_TAG) { var start, end; start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; var chunk = source.substring(start, end); var subDecorations = PR_TAG_LEXER(chunk, start); spliceArrayInto(subDecorations, decorations, i, 2); i += subDecorations.length - 2; } } return decorations; } function sourceDecorator(options) { var shortcutStylePatterns = [], fallthroughStylePatterns = []; if (options.tripleQuotedStrings) { shortcutStylePatterns.push([PR_STRING, /^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/, null, '\'"']); } else if (options.multiLineStrings) { shortcutStylePatterns.push([PR_STRING, /^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/, null, '\'"`']); } else { shortcutStylePatterns.push([PR_STRING, /^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/, null, '"\'']); } fallthroughStylePatterns.push([PR_PLAIN, /^(?:[^\'\"\`\/\#]+)/, null, ' \r\n']); if (options.hashComments) { shortcutStylePatterns.push([PR_COMMENT, /^#[^\r\n]*/, null, '#']); } if (options.cStyleComments) { fallthroughStylePatterns.push([PR_COMMENT, /^\/\/[^\r\n]*/, null]); fallthroughStylePatterns.push([PR_COMMENT, /^\/\*[\s\S]*?(?:\*\/|$)/, null]); } if (options.regexLiterals) { var REGEX_LITERAL = ('^/(?=[^/*])' + '(?:[^/\\x5B\\x5C]' + '|\\x5C[\\s\\S]' + '|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+' + '(?:/|$)'); fallthroughStylePatterns.push([PR_STRING, new RegExp(REGEX_LITERAL), REGEXP_PRECEDER_PATTERN]); } var keywords = wordSet(options.keywords); options = null; var splitStringAndCommentTokens = createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns); var styleLiteralIdentifierPuncRecognizer = createSimpleLexer([], [[PR_PLAIN, /^\s+/, null, ' \r\n'], [PR_PLAIN, /^[a-z_$@][a-z_$@0-9]*/i, null], [PR_LITERAL, /^0x[a-f0-9]+[a-z]/i, null], [PR_LITERAL, /^(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d+)(?:e[+\-]?\d+)?[a-z]*/i, null, '123456789'], [PR_PUNCTUATION, /^[^\s\w\.$@]+/, null]]); function splitNonStringNonCommentTokens(source, decorations) { for (var i = 0; i < decorations.length; i += 2) { var style = decorations[i + 1]; if (style === PR_PLAIN) { var start, end, chunk, subDecs; start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; chunk = source.substring(start, end); subDecs = styleLiteralIdentifierPuncRecognizer(chunk, start); for (var j = 0, m = subDecs.length; j < m; j += 2) { var subStyle = subDecs[j + 1]; if (subStyle === PR_PLAIN) { var subStart = subDecs[j]; var subEnd = j + 2 < m ? subDecs[j + 2] : chunk.length; var token = source.substring(subStart, subEnd); if (token === '.') { subDecs[j + 1] = PR_PUNCTUATION; } else if (token in keywords) { subDecs[j + 1] = PR_KEYWORD; } else if (/^@?[A-Z][A-Z$]*[a-z][A-Za-z$]*$/.test(token)) { subDecs[j + 1] = token.charAt(0) === '@' ? PR_LITERAL : PR_TYPE; } } } spliceArrayInto(subDecs, decorations, i, 2); i += subDecs.length - 2; } } return decorations; } return function(sourceCode) { var decorations = splitStringAndCommentTokens(sourceCode); decorations = splitNonStringNonCommentTokens(sourceCode, decorations); return decorations; }; } var decorateSource = sourceDecorator({ keywords: ALL_KEYWORDS, hashComments: true, cStyleComments: true, multiLineStrings: true, regexLiterals: true }); function splitSourceNodes(source, decorations) { for (var i = 0; i < decorations.length; i += 2) { var style = decorations[i + 1]; if (style === PR_SOURCE) { var start, end; start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; var subDecorations = decorateSource(source.substring(start, end)); for (var j = 0, m = subDecorations.length; j < m; j += 2) { subDecorations[j] += start; } spliceArrayInto(subDecorations, decorations, i, 2); i += subDecorations.length - 2; } } return decorations; } function splitSourceAttributes(source, decorations) { var nextValueIsSource = false; for (var i = 0; i < decorations.length; i += 2) { var style = decorations[i + 1]; var start, end; if (style === PR_ATTRIB_NAME) { start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; nextValueIsSource = /^on|^style$/i.test(source.substring(start, end)); } else if (style === PR_ATTRIB_VALUE) { if (nextValueIsSource) { start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; var attribValue = source.substring(start, end); var attribLen = attribValue.length; var quoted = (attribLen >= 2 && /^[\"\']/.test(attribValue) && attribValue.charAt(0) === attribValue.charAt(attribLen - 1)); var attribSource; var attribSourceStart; var attribSourceEnd; if (quoted) { attribSourceStart = start + 1; attribSourceEnd = end - 1; attribSource = attribValue; } else { attribSourceStart = start + 1; attribSourceEnd = end - 1; attribSource = attribValue.substring(1, attribValue.length - 1); } var attribSourceDecorations = decorateSource(attribSource); for (var j = 0, m = attribSourceDecorations.length; j < m; j += 2) { attribSourceDecorations[j] += attribSourceStart; } if (quoted) { attribSourceDecorations.push(attribSourceEnd, PR_ATTRIB_VALUE); spliceArrayInto(attribSourceDecorations, decorations, i + 2, 0); } else { spliceArrayInto(attribSourceDecorations, decorations, i, 2); } } nextValueIsSource = false; } } return decorations; } function decorateMarkup(sourceCode) { var decorations = tokenizeMarkup(sourceCode); decorations = splitTagAttributes(sourceCode, decorations); decorations = splitSourceNodes(sourceCode, decorations); decorations = splitSourceAttributes(sourceCode, decorations); return decorations; } function recombineTagsAndDecorations(sourceText, extractedTags, decorations) { var html = []; var outputIdx = 0; var openDecoration = null; var currentDecoration = null; var tagPos = 0; var decPos = 0; var tabExpander = makeTabExpander(PR_TAB_WIDTH); var adjacentSpaceRe = /([\r\n ]) /g; var startOrSpaceRe = /(^| ) /gm; var newlineRe = /\r\n?|\n/g; var trailingSpaceRe = /[ \r\n]$/; var lastWasSpace = true; function emitTextUpTo(sourceIdx) { if (sourceIdx > outputIdx) { if (openDecoration && openDecoration !== currentDecoration) { html.push('</span>'); openDecoration = null; } if (!openDecoration && currentDecoration) { openDecoration = currentDecoration; html.push('<span class="', openDecoration, '">'); } var htmlChunk = textToHtml(tabExpander(sourceText.substring(outputIdx, sourceIdx))).replace(lastWasSpace ? startOrSpaceRe : adjacentSpaceRe, '$1&nbsp;'); lastWasSpace = trailingSpaceRe.test(htmlChunk); html.push(htmlChunk.replace(newlineRe, '<br />')); outputIdx = sourceIdx; } } while (true) { var outputTag; if (tagPos < extractedTags.length) { if (decPos < decorations.length) { outputTag = extractedTags[tagPos] <= decorations[decPos]; } else { outputTag = true; } } else { outputTag = false; } if (outputTag) { emitTextUpTo(extractedTags[tagPos]); if (openDecoration) { html.push('</span>'); openDecoration = null; } html.push(extractedTags[tagPos + 1]); tagPos += 2; } else if (decPos < decorations.length) { emitTextUpTo(decorations[decPos]); currentDecoration = decorations[decPos + 1]; decPos += 2; } else { break; } } emitTextUpTo(sourceText.length); if (openDecoration) { html.push('</span>'); } return html.join(''); } var langHandlerRegistry = {}; function registerLangHandler(handler, fileExtensions) { for (var i = fileExtensions.length; --i >= 0; ) { var ext = fileExtensions[i]; if (!langHandlerRegistry.hasOwnProperty(ext)) { langHandlerRegistry[ext] = handler; } else if ('console' in window) { console.log('cannot override language handler %s', ext); } } } registerLangHandler(decorateSource, ['default-code']); registerLangHandler(decorateMarkup, ['default-markup', 'html', 'htm', 'xhtml', 'xml', 'xsl']); registerLangHandler(sourceDecorator({ keywords: CPP_KEYWORDS, hashComments: true, cStyleComments: true }), ['c', 'cc', 'cpp', 'cs', 'cxx', 'cyc']); registerLangHandler(sourceDecorator({ keywords: JAVA_KEYWORDS, cStyleComments: true }), ['java']); registerLangHandler(sourceDecorator({ keywords: SH_KEYWORDS, hashComments: true, multiLineStrings: true }), ['bsh', 'csh', 'sh']); registerLangHandler(sourceDecorator({ keywords: PYTHON_KEYWORDS, hashComments: true, multiLineStrings: true, tripleQuotedStrings: true }), ['cv', 'py']); registerLangHandler(sourceDecorator({ keywords: PERL_KEYWORDS, hashComments: true, multiLineStrings: true, regexLiterals: true }), ['perl', 'pl', 'pm']); registerLangHandler(sourceDecorator({ keywords: RUBY_KEYWORDS, hashComments: true, multiLineStrings: true, regexLiterals: true }), ['rb']); registerLangHandler(sourceDecorator({ keywords: JSCRIPT_KEYWORDS, cStyleComments: true, regexLiterals: true }), ['js']); function prettyPrintOne(sourceCodeHtml, opt_langExtension) { try { var sourceAndExtractedTags = extractTags(sourceCodeHtml); var source = sourceAndExtractedTags.source; var extractedTags = sourceAndExtractedTags.tags; if (!langHandlerRegistry.hasOwnProperty(opt_langExtension)) { opt_langExtension = /^\s*</.test(source) ? 'default-markup' : 'default-code'; } var decorations = langHandlerRegistry[opt_langExtension].call({}, source); return recombineTagsAndDecorations(source, extractedTags, decorations); } catch (e) { if ('console' in window) { console.log(e); console.trace(); } return sourceCodeHtml; } } function prettyPrint(opt_whenDone) { var isIE6 = _pr_isIE6(); var codeSegments = [document.getElementsByTagName('pre'), document.getElementsByTagName('code'), document.getElementsByTagName('xmp')]; var elements = []; for (var i = 0; i < codeSegments.length; ++i) { for (var j = 0; j < codeSegments[i].length; ++j) { elements.push(codeSegments[i][j]); } } codeSegments = null; var k = 0; function doWork() { var endTime = (PR_SHOULD_USE_CONTINUATION ? new Date().getTime() + 250 : Infinity); for (; k < elements.length && new Date().getTime() < endTime; k++) { var cs = elements[k]; if (cs.className && cs.className.indexOf('prettyprint') >= 0) { var langExtension = cs.className.match(/\blang-(\w+)\b/); if (langExtension) { langExtension = langExtension[1]; } var nested = false; for (var p = cs.parentNode; p; p = p.parentNode) { if ((p.tagName === 'pre' || p.tagName === 'code' || p.tagName === 'xmp') && p.className && p.className.indexOf('prettyprint') >= 0) { nested = true; break; } } if (!nested) { var content = getInnerHtml(cs); content = content.replace(/(?:\r\n?|\n)$/, ''); var newContent = prettyPrintOne(content, langExtension); if (!isRawContent(cs)) { cs.innerHTML = newContent; } else { var pre = document.createElement('PRE'); for (var i = 0; i < cs.attributes.length; ++i) { var a = cs.attributes[i]; if (a.specified) { var aname = a.name.toLowerCase(); if (aname === 'class') { pre.className = a.value; } else { pre.setAttribute(a.name, a.value); } } } pre.innerHTML = newContent; cs.parentNode.replaceChild(pre, cs); cs = pre; } if (isIE6 && cs.tagName === 'PRE') { var lineBreaks = cs.getElementsByTagName('br'); for (var j = lineBreaks.length; --j >= 0; ) { var lineBreak = lineBreaks[j]; lineBreak.parentNode.replaceChild(document.createTextNode('\r\n'), lineBreak); } } } } } if (k < elements.length) { setTimeout(doWork, 250); } else if (opt_whenDone) { opt_whenDone(); } } doWork(); } window['PR_normalizedHtml'] = normalizedHtml; window['prettyPrintOne'] = prettyPrintOne; window['prettyPrint'] = prettyPrint; window['PR'] = { 'createSimpleLexer': createSimpleLexer, 'registerLangHandler': registerLangHandler, 'sourceDecorator': sourceDecorator, 'PR_ATTRIB_NAME': PR_ATTRIB_NAME, 'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE, 'PR_COMMENT': PR_COMMENT, 'PR_DECLARATION': PR_DECLARATION, 'PR_KEYWORD': PR_KEYWORD, 'PR_LITERAL': PR_LITERAL, 'PR_NOCODE': PR_NOCODE, 'PR_PLAIN': PR_PLAIN, 'PR_PUNCTUATION': PR_PUNCTUATION, 'PR_SOURCE': PR_SOURCE, 'PR_STRING': PR_STRING, 'PR_TAG': PR_TAG, 'PR_TYPE': PR_TYPE }; })();
+/*
+Scripts for cnprog.com
+Project Name: Lanai
+All Rights Resevred 2008. CNPROG.COM
+*/
+var lanai =
+{
+ /**
+ * Finds any <pre><code></code></pre> tags which aren't registered for
+ * pretty printing, adds the appropriate class name and invokes prettify.
+ */
+ highlightSyntax: function(){
+ var styled = false;
+ $("pre code").parent().each(function(){
+ if (!$(this).hasClass('prettyprint')){
+ $(this).addClass('prettyprint');
+ styled = true;
+ }
+ });
+
+ if (styled){
+ prettyPrint();
+ }
+ }
+};
+
+var Vote = function(){
+ // All actions are related to a question
+ var questionId;
+ //question slug to build redirect urls
+ var questionSlug;
+ // The object we operate on actually. It can be a question or an answer.
+ var postId;
+ var questionAuthorId;
+ var currentUserId;
+ var answerContainerIdPrefix = 'answer-container-';
+ var voteContainerId = 'vote-buttons';
+ var imgIdPrefixAccept = 'answer-img-accept-';
+ var imgClassPrefixFavorite = 'question-img-favorite';
+ var imgIdPrefixQuestionVoteup = 'question-img-upvote-';
+ var imgIdPrefixQuestionVotedown = 'question-img-downvote-';
+ var imgIdPrefixAnswerVoteup = 'answer-img-upvote-';
+ var imgIdPrefixAnswerVotedown = 'answer-img-downvote-';
+ var divIdFavorite = 'favorite-number';
+ var commentLinkIdPrefix = 'comment-';
+ var voteNumberClass = "vote-number";
+ var offensiveIdPrefixQuestionFlag = 'question-offensive-flag-';
+ var offensiveIdPrefixAnswerFlag = 'answer-offensive-flag-';
+ var offensiveClassFlag = 'offensive-flag';
+ var questionControlsId = 'question-controls';
+ var removeQuestionLinkIdPrefix = 'question-delete-link-';
+ var removeAnswerLinkIdPrefix = 'answer-delete-link-';
+ var questionSubscribeUpdates = 'question-subscribe-updates';
+
+ var acceptAnonymousMessage = $.i18n._('insufficient privilege');
+ var acceptOwnAnswerMessage = $.i18n._('cannot pick own answer as best');
+
+ var pleaseLogin = "<a href='" + scriptUrl + $.i18n._("account/") + $.i18n._("signin/")
+ + "?next=" + scriptUrl + $.i18n._("question/") + "{{QuestionID}}/{{questionSlug}}'>"
+ + $.i18n._('please login') + "</a>";
+
+ var pleaseSeeFAQ = $.i18n._('please see') + "<a href='" + scriptUrl + $.i18n._("faq/") + "'>faq</a>";
+
+ var favoriteAnonymousMessage = $.i18n._('anonymous users cannot select favorite questions')
+ var voteAnonymousMessage = $.i18n._('anonymous users cannot vote') + pleaseLogin;
+ var upVoteRequiredScoreMessage = $.i18n._('>15 points requried to upvote') + pleaseSeeFAQ;
+ var downVoteRequiredScoreMessage = $.i18n._('>100 points required to downvote') + pleaseSeeFAQ;
+ var voteOwnDeniedMessage = $.i18n._('cannot vote for own posts');
+ var voteRequiredMoreVotes = $.i18n._('daily vote cap exhausted') + pleaseSeeFAQ;
+ var voteDenyCancelMessage = $.i18n._('cannot revoke old vote') + pleaseSeeFAQ;
+ var offensiveConfirmation = $.i18n._('please confirm offensive');
+ var offensiveAnonymousMessage = $.i18n._('anonymous users cannot flag offensive posts') + pleaseLogin;
+ var offensiveTwiceMessage = $.i18n._('cannot flag message as offensive twice') + pleaseSeeFAQ;
+ var offensiveNoFlagsLeftMessage = $.i18n._('flag offensive cap exhausted') + pleaseSeeFAQ;
+ var offensiveNoPermissionMessage = $.i18n._('need >15 points to report spam') + pleaseSeeFAQ;
+ var removeConfirmation = $.i18n._('confirm delete');
+ var removeAnonymousMessage = $.i18n._('anonymous users cannot delete/undelete');
+ var recoveredMessage = $.i18n._('post recovered');
+ var deletedMessage = $.i18n._('post deleted');
+
+ var VoteType = {
+ acceptAnswer : 0,
+ questionUpVote : 1,
+ questionDownVote : 2,
+ favorite : 4,
+ answerUpVote: 5,
+ answerDownVote:6,
+ offensiveQuestion : 7,
+ offensiveAnswer:8,
+ removeQuestion: 9,
+ removeAnswer:10,
+ questionSubscribeUpdates:11,
+ questionUnsubscribeUpdates:12
+ };
+
+ var getFavoriteButton = function(){
+ var favoriteButton = 'div.'+ voteContainerId +' img[class='+ imgClassPrefixFavorite +']';
+ return $(favoriteButton);
+ };
+ var getFavoriteNumber = function(){
+ var favoriteNumber = '#'+ divIdFavorite ;
+ return $(favoriteNumber);
+ };
+ var getQuestionVoteUpButton = function(){
+ var questionVoteUpButton = 'div.'+ voteContainerId +' img[id^='+ imgIdPrefixQuestionVoteup +']';
+ return $(questionVoteUpButton);
+ };
+ var getQuestionVoteDownButton = function(){
+ var questionVoteDownButton = 'div.'+ voteContainerId +' img[id^='+ imgIdPrefixQuestionVotedown +']';
+ return $(questionVoteDownButton);
+ };
+ var getAnswerVoteUpButtons = function(){
+ var answerVoteUpButton = 'div.'+ voteContainerId +' img[id^='+ imgIdPrefixAnswerVoteup +']';
+ return $(answerVoteUpButton);
+ };
+ var getAnswerVoteDownButtons = function(){
+ var answerVoteDownButton = 'div.'+ voteContainerId +' img[id^='+ imgIdPrefixAnswerVotedown +']';
+ return $(answerVoteDownButton);
+ };
+ var getAnswerVoteUpButton = function(id){
+ var answerVoteUpButton = 'div.'+ voteContainerId +' img[id='+ imgIdPrefixAnswerVoteup + id + ']';
+ return $(answerVoteUpButton);
+ };
+ var getAnswerVoteDownButton = function(id){
+ var answerVoteDownButton = 'div.'+ voteContainerId +' img[id='+ imgIdPrefixAnswerVotedown + id + ']';
+ return $(answerVoteDownButton);
+ };
+
+ var getOffensiveQuestionFlag = function(){
+ var offensiveQuestionFlag = '#question-table span[class='+ offensiveClassFlag +']';
+ return $(offensiveQuestionFlag);
+ };
+
+ var getOffensiveAnswerFlags = function(){
+ var offensiveQuestionFlag = 'div.answer span[class='+ offensiveClassFlag +']';
+ return $(offensiveQuestionFlag);
+ };
+
+ var getremoveQuestionLink = function(){
+ var removeQuestionLink = 'div#question-controls a[id^='+ removeQuestionLinkIdPrefix +']';
+ return $(removeQuestionLink);
+ };
+
+ var getquestionSubscribeUpdatesCheckbox = function(){
+ return $('#' + questionSubscribeUpdates);
+ };
+
+ var getremoveAnswersLinks = function(){
+ var removeAnswerLinks = 'div.answer-controls a[id^='+ removeAnswerLinkIdPrefix +']';
+ return $(removeAnswerLinks);
+ };
+
+ var setVoteImage = function(voteType, undo, object){
+ var flag = undo ? "" : "-on";
+ var arrow = (voteType == VoteType.questionUpVote || voteType == VoteType.answerUpVote) ? "up" : "down";
+ object.attr("src", scriptUrl + "content/images/vote-arrow-"+ arrow + flag +".png");
+
+ // if undo voting, then undo the pair of arrows.
+ if(undo){
+ if(voteType == VoteType.questionUpVote || voteType == VoteType.questionDownVote){
+ $(getQuestionVoteUpButton()).attr("src", scriptUrl + "content/images/vote-arrow-up.png");
+ $(getQuestionVoteDownButton()).attr("src", scriptUrl + "content/images/vote-arrow-down.png");
+ }
+ else{
+ $(getAnswerVoteUpButton(postId)).attr("src", scriptUrl + "content/images/vote-arrow-up.png");
+ $(getAnswerVoteDownButton(postId)).attr("src", scriptUrl + "content/images/vote-arrow-down.png");
+ }
+ }
+ };
+
+ var setVoteNumber = function(object, number){
+ var voteNumber = object.parent('div.'+ voteContainerId).find('div.'+ voteNumberClass);
+ $(voteNumber).text(number);
+ };
+
+ var bindEvents = function(){
+ // accept answers
+ if(questionAuthorId == currentUserId){
+ var acceptedButtons = 'div.'+ voteContainerId +' img[id^='+ imgIdPrefixAccept +']';
+ $(acceptedButtons).unbind('click').click(function(event){
+ Vote.accept($(event.target));
+ });
+ }
+ // set favorite question
+ var favoriteButton = getFavoriteButton();
+ favoriteButton.unbind('click').click(function(event){
+ Vote.favorite($(event.target));
+ });
+
+ // question vote up
+ var questionVoteUpButton = getQuestionVoteUpButton();
+ questionVoteUpButton.unbind('click').click(function(event){
+ Vote.vote($(event.target), VoteType.questionUpVote);
+ });
+
+ var questionVoteDownButton = getQuestionVoteDownButton();
+ questionVoteDownButton.unbind('click').click(function(event){
+ Vote.vote($(event.target), VoteType.questionDownVote);
+ });
+
+ var answerVoteUpButton = getAnswerVoteUpButtons();
+ answerVoteUpButton.unbind('click').click(function(event){
+ Vote.vote($(event.target), VoteType.answerUpVote);
+ });
+
+ var answerVoteDownButton = getAnswerVoteDownButtons();
+ answerVoteDownButton.unbind('click').click(function(event){
+ Vote.vote($(event.target), VoteType.answerDownVote);
+ });
+
+ getOffensiveQuestionFlag().unbind('click').click(function(event){
+ Vote.offensive(this, VoteType.offensiveQuestion);
+ });
+
+ getOffensiveAnswerFlags().unbind('click').click(function(event){
+ Vote.offensive(this, VoteType.offensiveAnswer);
+ });
+
+ getremoveQuestionLink().unbind('click').click(function(event){
+ Vote.remove(this, VoteType.removeQuestion);
+ });
+
+ getquestionSubscribeUpdatesCheckbox().unbind('click').click(function(event){
+ if (this.checked){
+ Vote.vote($(event.target), VoteType.questionSubscribeUpdates);
+ }
+ else {
+ Vote.vote($(event.target), VoteType.questionUnsubscribeUpdates);
+ }
+ });
+
+ getremoveAnswersLinks().unbind('click').click(function(event){
+ Vote.remove(this, VoteType.removeAnswer);
+ });
+ };
+
+ var submit = function(object, voteType, callback) {
+ $.ajax({
+ type: "POST",
+ cache: false,
+ dataType: "json",
+ url: scriptUrl + $.i18n._("questions/") + questionId + "/" + $.i18n._("vote/"),
+ data: { "type": voteType, "postId": postId },
+ error: handleFail,
+ success: function(data){callback(object, voteType, data)}});
+ };
+
+ var handleFail = function(xhr, msg){
+ alert("Callback invoke error: " + msg);
+ };
+
+ // callback function for Accept Answer action
+ var callback_accept = function(object, voteType, data){
+ if(data.allowed == "0" && data.success == "0"){
+ showMessage(object, acceptAnonymousMessage);
+ }
+ else if(data.allowed == "-1"){
+ showMessage(object, acceptOwnAnswerMessage);
+ }
+ else if(data.status == "1"){
+ object.attr("src", scriptUrl + "content/images/vote-accepted.png");
+ $("#"+answerContainerIdPrefix+postId).removeClass("accepted-answer");
+ $("#"+commentLinkIdPrefix+postId).removeClass("comment-link-accepted");
+ }
+ else if(data.success == "1"){
+ var acceptedButtons = 'div.'+ voteContainerId +' img[id^='+ imgIdPrefixAccept +']';
+ $(acceptedButtons).attr("src", scriptUrl + "content/images/vote-accepted.png");
+ var answers = ("div[id^="+answerContainerIdPrefix +"]");
+ $(answers).removeClass("accepted-answer");
+ var commentLinks = ("div[id^="+answerContainerIdPrefix +"] div[id^="+ commentLinkIdPrefix +"]");
+ $(commentLinks).removeClass("comment-link-accepted");
+
+ object.attr("src", scriptUrl + "content/images/vote-accepted-on.png");
+ $("#"+answerContainerIdPrefix+postId).addClass("accepted-answer");
+ $("#"+commentLinkIdPrefix+postId).addClass("comment-link-accepted");
+ }
+ else{
+ showMessage(object, data.message);
+ }
+ };
+
+ var callback_favorite = function(object, voteType, data){
+ if(data.allowed == "0" && data.success == "0"){
+ showMessage(object, favoriteAnonymousMessage.replace("{{QuestionID}}", questionId));
+ }
+ else if(data.status == "1"){
+ object.attr("src", scriptUrl + "content/images/vote-favorite-off.png");
+ var fav = getFavoriteNumber();
+ fav.removeClass("my-favorite-number");
+ if(data.count == 0)
+ data.count = '';
+ fav.text(data.count);
+ }
+ else if(data.success == "1"){
+ object.attr("src", scriptUrl + "content/images/vote-favorite-on.png");
+ var fav = getFavoriteNumber();
+ fav.text(data.count);
+ fav.addClass("my-favorite-number");
+ }
+ else{
+ showMessage(object, data.message);
+ }
+ };
+
+ var callback_vote = function(object, voteType, data){
+ if(data.allowed == "0" && data.success == "0"){
+ showMessage(object, voteAnonymousMessage.replace("{{QuestionID}}", questionId));
+ }
+ else if (data.allowed == "-3"){
+ showMessage(object, voteRequiredMoreVotes);
+ }
+ else if (data.allowed == "-2"){
+ if (voteType == VoteType.questionUpVote || voteType == VoteType.answerUpVote){
+ showMessage(object, upVoteRequiredScoreMessage);
+ }
+ else if (voteType == VoteType.questionDownVote || voteType == VoteType.answerDownVote){
+ showMessage(object, downVoteRequiredScoreMessage);
+ }
+ }
+ else if (data.allowed == "-1"){
+ showMessage(object, voteOwnDeniedMessage);
+ }
+ else if (data.status == "2"){
+ showMessage(object, voteDenyCancelMessage);
+ }
+ else if (data.status == "1"){
+ setVoteImage(voteType, true, object);
+ setVoteNumber(object, data.count);
+ }
+ else if (data.success == "1"){
+ setVoteImage(voteType, false, object);
+ setVoteNumber(object, data.count);
+ if (data.message.length > 0){
+ showMessage(object, data.message);
+ }
+ }
+ };
+
+ var callback_offensive = function(object, voteType, data){
+ object = $(object);
+ if (data.allowed == "0" && data.success == "0"){
+ showMessage(object, offensiveAnonymousMessage.replace("{{QuestionID}}", questionId));
+ }
+ else if (data.allowed == "-3"){
+ showMessage(object, offensiveNoFlagsLeftMessage);
+ }
+ else if (data.allowed == "-2"){
+ showMessage(object, offensiveNoPermissionMessage);
+ }
+ else if (data.status == "1"){
+ showMessage(object, offensiveTwiceMessage);
+ }
+ else if (data.success == "1"){
+ $(object).children('span[class=darkred]').text("("+ data.count +")");
+ }
+ };
+
+ var callback_remove = function(object, voteType, data){
+ if (data.allowed == "0" && data.success == "0"){
+ showMessage(object, removeAnonymousMessage.replace("{{QuestionID}}", questionId));
+ }
+ else if (data.success == "1"){
+ if (voteType == VoteType.removeQuestion){
+ window.location.href = scriptUrl + $.i18n._("questions/");
+ }
+ else {
+ if (removeActionType == 'delete'){
+ postNode.addClass('deleted');
+ postRemoveLink.innerHTML = $.i18n._('undelete');
+ showMessage(object, deletedMessage);
+ }
+ else if (removeActionType == 'undelete') {
+ postNode.removeClass('deleted');
+ postRemoveLink.innerHTML = $.i18n._('delete');
+ showMessage(object, recoveredMessage);
+ }
+ }
+ }
+ };
+
+ return {
+ init : function(qId, qSlug, questionAuthor, userId){
+ questionId = qId;
+ questionSlug = qSlug;
+ questionAuthorId = questionAuthor;
+ currentUserId = userId;
+ bindEvents();
+ },
+
+ // Accept answer public function
+ accept: function(object){
+ postId = object.attr("id").substring(imgIdPrefixAccept.length);
+ submit(object, VoteType.acceptAnswer, callback_accept);
+ },
+
+ favorite: function(object){
+ if (!currentUserId || currentUserId.toUpperCase() == "NONE"){
+ showMessage(object, favoriteAnonymousMessage.replace("{{QuestionID}}", questionId));
+ return false;
+ }
+ submit(object, VoteType.favorite, callback_favorite);
+ },
+
+ vote: function(object, voteType){
+ if (!currentUserId || currentUserId.toUpperCase() == "NONE"){
+ showMessage(object, voteAnonymousMessage.replace("{{QuestionID}}", questionId).replace("{{questionSlug}}", questionSlug));
+ return false;
+ }
+ if (voteType == VoteType.answerUpVote){
+ postId = object.attr("id").substring(imgIdPrefixAnswerVoteup.length);
+ }
+ else if (voteType == VoteType.answerDownVote){
+ postId = object.attr("id").substring(imgIdPrefixAnswerVotedown.length);
+ }
+
+ submit(object, voteType, callback_vote);
+ },
+
+ offensive: function(object, voteType){
+ if (!currentUserId || currentUserId.toUpperCase() == "NONE"){
+ showMessage($(object), offensiveAnonymousMessage.replace("{{QuestionID}}", questionId));
+ return false;
+ }
+ if (confirm(offensiveConfirmation)){
+ postId = object.id.substr(object.id.lastIndexOf('-') + 1);
+ submit(object, voteType, callback_offensive);
+ }
+ },
+
+ remove: function(object, voteType){
+ if (!currentUserId || currentUserId.toUpperCase() == "NONE"){
+ showMessage($(object), removeAnonymousMessage.replace("{{QuestionID}}", questionId));
+ return false;
+ }
+ bits = object.id.split('-');
+ postId = bits.pop();/* this seems to be used within submit! */
+ postType = bits.shift();
+
+ var do_proceed = false;
+ if (postType == 'answer'){
+ postNode = $('#answer-container-' + postId);
+ postRemoveLink = object;
+ if (postNode.hasClass('deleted')){
+ removeActionType = 'undelete';
+ do_proceed = true;
+ }
+ else {
+ removeActionType = 'delete';
+ do_proceed = confirm(removeConfirmation);
+ }
+ }
+ else {
+ do_proceed = confirm(removeConfirmation);
+ }
+ if (do_proceed) {
+ submit($(object), voteType, callback_remove);
+ }
+ }
+ }
+} ();
+
+
+// site comments
+function createComments(type) {
+ var objectType = type;
+ var jDivInit = function(id) {
+ return $("#comments-container-" + objectType + '-' + id);
+ };
+
+ var appendLoaderImg = function(id) {
+ appendLoader("#comments-container-" + objectType + '-' + id);
+ };
+
+ var canPostComments = function(id) {
+ var jHidden = $("#can-post-comments-" + objectType + '-' + id);
+ return jHidden.val().toLowerCase() == "true";
+ };
+
+ var renderForm = function(id) {
+ var formId = "form-comments-" + objectType + "-" + id;
+ var jDiv = $('#comments-link-' + objectType + "-" + id).parent();
+ $(jDiv).css('background','none');
+ $(jDiv).css('padding-left',0);
+ if (canPostComments(id)) {
+ if (jDiv.find("#" + formId).length == 0) {
+ var form = '<form id="' + formId + '" class="post-comments"><div>';
+ form += '<textarea name="comment" cols="60" rows="5" maxlength="300" onblur="'+ objectType +'Comments.updateTextCounter(this)" ';
+ form += 'onfocus="' + objectType + 'Comments.updateTextCounter(this)" onkeyup="'+ objectType +'Comments.updateTextCounter(this)"></textarea>';
+ form += '<input type="submit" value="'
+ + $.i18n._('add comment') + '" /><br><span class="text-counter"></span>';
+ form += '<span class="form-error"></span></div></form>';
+
+ jDiv.append(form);
+
+ setupFormValidation("#" + formId,
+ { comment: { required: true, minlength: 10} }, '',
+ function() { postComment(id, formId); });
+ }
+ }
+ else {
+ var divId = "comments-rep-needed-" + objectType + '-' + id;
+ if (jDiv.find("#" + divId).length == 0) {
+ jDiv.append('<p id="' + divId + '" class="comment">'
+ + $.i18n._('to comment, need') + ' ' +
+ + repNeededForComments + ' ' + $.i18n._('community karma points')
+ + '<a href="' + scriptUrl + $.i18n._('faq/') + '" class="comment-user">'
+ + $.i18n._('please see') + 'faq</a></span></p>');
+ }
+ }
+ };
+
+ var getComments = function(id, jDiv) {
+ //appendLoaderImg(id);
+ $.getJSON(scriptUrl + objectType + "s/" + id + "/" + $.i18n._("comments/")
+ , function(json) { showComments(id, json); });
+ };
+
+ var showComments = function(id, json) {
+ var jDiv = jDivInit(id);
+
+ //jDiv = jDiv.find("div.comments"); // this div should contain any fetched comments..
+ //jDiv.find("div[id^='comment-" + objectType + "-'" + "]").remove(); // clean previous calls..
+ jDiv.children().remove();
+ removeLoader();
+ if (json && json.length > 0) {
+ for (var i = 0; i < json.length; i++)
+ renderComment(jDiv, json[i]);
+ jDiv.children().show();
+ }
+ };
+
+ var renderDeleteCommentIcon = function(post_id, delete_url){
+ if (canPostComments(post_id)){
+ var html = '';
+ var img = scriptUrl + "content/images/close-small.png";
+ var imgHover = scriptUrl + "content/images/close-small-hover.png";
+ html += '<img class="delete-icon" onclick="' + objectType + 'Comments.deleteComment($(this), ' + post_id + ', \'' + delete_url + '\')" src="' + img;
+ html += '" onmouseover="$(this).attr(\'src\', \'' + imgHover + '\')" onmouseout="$(this).attr(\'src\', \'' + img
+ html += '\')" title="' + $.i18n._('delete this comment') + '" />';
+ return html;
+ }
+ else{
+ return '';
+ }
+ }
+
+ // {"Id":6,"PostId":38589,"CreationDate":"an hour ago","Text":"hello there!","UserDisplayName":"Jarrod Dixon","UserUrl":"/users/3/jarrod-dixon","DeleteUrl":null}
+ var renderComment = function(jDiv, json) {
+ var html = '<p id="comment-' + json.id + '" class="comment" style="display:none">' + json.text;
+ html += json.user_url ? ' - <a href="' + json.user_url + '"' : '<span';
+ html += ' class="comment-user">' + json.user_display_name + (json.user_url ? '</a>' : '</span>');
+ html += ' (' + json.comment_age + ')';
+
+ if (json.delete_url){
+ html += renderDeleteCommentIcon(json.object_id, json.delete_url);
+ }
+
+ if (json.delete_url) {
+ }
+
+ html += '</p>';
+
+ jDiv.append(html);
+ };
+
+ var postComment = function(id, formId) {
+ //appendLoaderImg(id);
+
+ var formSelector = "#" + formId;
+ var textarea = $(formSelector + " textarea");
+
+ //todo fix url translations!!!
+ $.ajax({
+ type: "POST",
+ url: scriptUrl + objectType + "s/" + id + "/" + $.i18n._("comments/"),
+ dataType: "json",
+ data: { comment: textarea.val() },
+ success: function(json) {
+ showComments(id, json);
+ textarea.val("");
+ commentsFactory[objectType].updateTextCounter(textarea);
+ enableSubmitButton(formSelector);
+ },
+ error: function(res, textStatus, errorThrown) {
+ removeLoader();
+ showMessage(formSelector, res.responseText);
+ enableSubmitButton(formSelector);
+ }
+ });
+ };
+
+ // public methods..
+ return {
+
+ init: function() {
+ // Setup "show comments" clicks..
+ $("a[id^='comments-link-" + objectType + "-" + "']").unbind("click").click(function() {
+ commentsFactory[objectType].show($(this).attr("id").substr(("comments-link-" + objectType + "-").length));
+ });
+
+ var cBox = $("[id^='comments-container-" + objectType + "']");
+ cBox.each( function(i){
+ var post_id = $(this).attr('id').replace('comments-container-' + objectType + '-', '');
+ $(this).children().each(
+ function(i){
+ var comment_id = $(this).attr('id').replace('comment-','');
+ var delete_url = scriptUrl + objectType + 's/' + post_id + '/'
+ + $.i18n._('comments/') + comment_id + '/' + $.i18n._('delete/');
+ var html = $(this).html();
+ var CommentsClass;
+ if (objectType == 'question'){
+ CommentsClass = questionComments;
+ }
+ else if (objectType == 'answer') {
+ CommentsClass = answerComments;
+ }
+ var delete_icon = $(this).find('img.delete-icon');
+ delete_icon.click(function(){CommentsClass.deleteComment($(this),comment_id,delete_url);});
+ delete_icon.unbind('mouseover').bind('mouseover',
+ function(){
+ $(this).attr('src',scriptUrl + 'content/images/close-small-hover.png');
+ }
+ );
+ delete_icon.unbind('mouseout').bind('mouseout',
+ function(){
+ $(this).attr('src',scriptUrl + 'content/images/close-small.png');
+ }
+ );
+ }
+ );
+ });
+ },
+
+ show: function(id) {
+ var jDiv = jDivInit(id);
+ getComments(id, jDiv);
+ renderForm(id);
+ jDiv.show();
+
+ var link = $('#comments-link-' + objectType + '-' + id);
+ if (canPostComments(id)) link.parent().find("textarea").get(0).focus();
+ link.remove();
+ },
+
+ hide: function(id) {
+ var jDiv = jDivInit(id);
+ var len = jDiv.children("div.comments").children().length;
+ var anchorText = len == 0 ? $.i18n._('add a comment') : $.i18n._('comments') + ' (<b>' + len + "</b>)";
+
+ jDiv.hide();
+ jDiv.siblings("a").unbind("click").click(function() { commentsFactory[objectType].show(id); }).html(anchorText);
+ jDiv.children("div.comments").children().hide();
+ },
+
+ deleteComment: function(jImg, id, deleteUrl) {
+ if (confirm($.i18n._('confirm delete comment'))) {
+ jImg.hide();
+ $.post(deleteUrl, { dataNeeded: "forIIS7" }, function(json) {
+ var par = jImg.parent();
+ par.remove();
+ }, "json");
+ }
+ },
+
+ updateTextCounter: function(textarea) {
+ var length = textarea.value ? textarea.value.length : 0;
+ var color = length > 270 ? "#f00" : length > 200 ? "#f60" : "#999";
+ var jSpan = $(textarea).siblings("span.text-counter");
+ jSpan.html($.i18n._('can write')
+ + (300 - length) + ' '
+ + $.i18n._('characters')).css("color", color);
+ }
+ };
+}
+
+var questionComments = createComments('question');
+var answerComments = createComments('answer');
+
+$().ready(function() {
+ questionComments.init();
+ answerComments.init();
+});
+
+var commentsFactory = {'question' : questionComments, 'answer' : answerComments};
+
+/*
+Prettify
+http://www.apache.org/licenses/LICENSE-2.0
+*/
+var PR_SHOULD_USE_CONTINUATION = true; var PR_TAB_WIDTH = 8; var PR_normalizedHtml; var PR; var prettyPrintOne; var prettyPrint; function _pr_isIE6() { var isIE6 = navigator && navigator.userAgent && /\bMSIE 6\./.test(navigator.userAgent); _pr_isIE6 = function() { return isIE6; }; return isIE6; } (function() { function wordSet(words) { words = words.split(/ /g); var set = {}; for (var i = words.length; --i >= 0; ) { var w = words[i]; if (w) { set[w] = null; } } return set; } var FLOW_CONTROL_KEYWORDS = "break continue do else for if return while "; var C_KEYWORDS = FLOW_CONTROL_KEYWORDS + "auto case char const default " + "double enum extern float goto int long register short signed sizeof " + "static struct switch typedef union unsigned void volatile "; var COMMON_KEYWORDS = C_KEYWORDS + "catch class delete false import " + "new operator private protected public this throw true try "; var CPP_KEYWORDS = COMMON_KEYWORDS + "alignof align_union asm axiom bool " + "concept concept_map const_cast constexpr decltype " + "dynamic_cast explicit export friend inline late_check " + "mutable namespace nullptr reinterpret_cast static_assert static_cast " + "template typeid typename typeof using virtual wchar_t where "; var JAVA_KEYWORDS = COMMON_KEYWORDS + "boolean byte extends final finally implements import instanceof null " + "native package strictfp super synchronized throws transient "; var CSHARP_KEYWORDS = JAVA_KEYWORDS + "as base by checked decimal delegate descending event " + "fixed foreach from group implicit in interface internal into is lock " + "object out override orderby params readonly ref sbyte sealed " + "stackalloc string select uint ulong unchecked unsafe ushort var "; var JSCRIPT_KEYWORDS = COMMON_KEYWORDS + "debugger eval export function get null set undefined var with " + "Infinity NaN "; var PERL_KEYWORDS = "caller delete die do dump elsif eval exit foreach for " + "goto if import last local my next no our print package redo require " + "sub undef unless until use wantarray while BEGIN END "; var PYTHON_KEYWORDS = FLOW_CONTROL_KEYWORDS + "and as assert class def del " + "elif except exec finally from global import in is lambda " + "nonlocal not or pass print raise try with yield " + "False True None "; var RUBY_KEYWORDS = FLOW_CONTROL_KEYWORDS + "alias and begin case class def" + " defined elsif end ensure false in module next nil not or redo rescue " + "retry self super then true undef unless until when yield BEGIN END "; var SH_KEYWORDS = FLOW_CONTROL_KEYWORDS + "case done elif esac eval fi " + "function in local set then until "; var ALL_KEYWORDS = (CPP_KEYWORDS + CSHARP_KEYWORDS + JSCRIPT_KEYWORDS + PERL_KEYWORDS + PYTHON_KEYWORDS + RUBY_KEYWORDS + SH_KEYWORDS); var PR_STRING = 'str'; var PR_KEYWORD = 'kwd'; var PR_COMMENT = 'com'; var PR_TYPE = 'typ'; var PR_LITERAL = 'lit'; var PR_PUNCTUATION = 'pun'; var PR_PLAIN = 'pln'; var PR_TAG = 'tag'; var PR_DECLARATION = 'dec'; var PR_SOURCE = 'src'; var PR_ATTRIB_NAME = 'atn'; var PR_ATTRIB_VALUE = 'atv'; var PR_NOCODE = 'nocode'; function isWordChar(ch) { return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'); } function spliceArrayInto(inserted, container, containerPosition, countReplaced) { inserted.unshift(containerPosition, countReplaced || 0); try { container.splice.apply(container, inserted); } finally { inserted.splice(0, 2); } } var REGEXP_PRECEDER_PATTERN = function() { var preceders = ["!", "!=", "!==", "#", "%", "%=", "&", "&&", "&&=", "&=", "(", "*", "*=", "+=", ",", "-=", "->", "/", "/=", ":", "::", ";", "<", "<<", "<<=", "<=", "=", "==", "===", ">", ">=", ">>", ">>=", ">>>", ">>>=", "?", "@", "[", "^", "^=", "^^", "^^=", "{", "|", "|=", "||", "||=", "~", "break", "case", "continue", "delete", "do", "else", "finally", "instanceof", "return", "throw", "try", "typeof"]; var pattern = '(?:' + '(?:(?:^|[^0-9.])\\.{1,3})|' + '(?:(?:^|[^\\+])\\+)|' + '(?:(?:^|[^\\-])-)'; for (var i = 0; i < preceders.length; ++i) { var preceder = preceders[i]; if (isWordChar(preceder.charAt(0))) { pattern += '|\\b' + preceder; } else { pattern += '|' + preceder.replace(/([^=<>:&])/g, '\\$1'); } } pattern += '|^)\\s*$'; return new RegExp(pattern); } (); var pr_amp = /&/g; var pr_lt = /</g; var pr_gt = />/g; var pr_quot = /\"/g; function attribToHtml(str) { return str.replace(pr_amp, '&amp;').replace(pr_lt, '&lt;').replace(pr_gt, '&gt;').replace(pr_quot, '&quot;'); } function textToHtml(str) { return str.replace(pr_amp, '&amp;').replace(pr_lt, '&lt;').replace(pr_gt, '&gt;'); } var pr_ltEnt = /&lt;/g; var pr_gtEnt = /&gt;/g; var pr_aposEnt = /&apos;/g; var pr_quotEnt = /&quot;/g; var pr_ampEnt = /&amp;/g; var pr_nbspEnt = /&nbsp;/g; function htmlToText(html) { var pos = html.indexOf('&'); if (pos < 0) { return html; } for (--pos; (pos = html.indexOf('&#', pos + 1)) >= 0; ) { var end = html.indexOf(';', pos); if (end >= 0) { var num = html.substring(pos + 3, end); var radix = 10; if (num && num.charAt(0) === 'x') { num = num.substring(1); radix = 16; } var codePoint = parseInt(num, radix); if (!isNaN(codePoint)) { html = (html.substring(0, pos) + String.fromCharCode(codePoint) + html.substring(end + 1)); } } } return html.replace(pr_ltEnt, '<').replace(pr_gtEnt, '>').replace(pr_aposEnt, "'").replace(pr_quotEnt, '"').replace(pr_ampEnt, '&').replace(pr_nbspEnt, ' '); } function isRawContent(node) { return 'XMP' === node.tagName; } function normalizedHtml(node, out) { switch (node.nodeType) { case 1: var name = node.tagName.toLowerCase(); out.push('<', name); for (var i = 0; i < node.attributes.length; ++i) { var attr = node.attributes[i]; if (!attr.specified) { continue; } out.push(' '); normalizedHtml(attr, out); } out.push('>'); for (var child = node.firstChild; child; child = child.nextSibling) { normalizedHtml(child, out); } if (node.firstChild || !/^(?:br|link|img)$/.test(name)) { out.push('<\/', name, '>'); } break; case 2: out.push(node.name.toLowerCase(), '="', attribToHtml(node.value), '"'); break; case 3: case 4: out.push(textToHtml(node.nodeValue)); break; } } var PR_innerHtmlWorks = null; function getInnerHtml(node) { if (null === PR_innerHtmlWorks) { var testNode = document.createElement('PRE'); testNode.appendChild(document.createTextNode('<!DOCTYPE foo PUBLIC "foo bar">\n<foo />')); PR_innerHtmlWorks = !/</.test(testNode.innerHTML); } if (PR_innerHtmlWorks) { var content = node.innerHTML; if (isRawContent(node)) { content = textToHtml(content); } return content; } var out = []; for (var child = node.firstChild; child; child = child.nextSibling) { normalizedHtml(child, out); } return out.join(''); } function makeTabExpander(tabWidth) { var SPACES = ' '; var charInLine = 0; return function(plainText) { var out = null; var pos = 0; for (var i = 0, n = plainText.length; i < n; ++i) { var ch = plainText.charAt(i); switch (ch) { case '\t': if (!out) { out = []; } out.push(plainText.substring(pos, i)); var nSpaces = tabWidth - (charInLine % tabWidth); charInLine += nSpaces; for (; nSpaces >= 0; nSpaces -= SPACES.length) { out.push(SPACES.substring(0, nSpaces)); } pos = i + 1; break; case '\n': charInLine = 0; break; default: ++charInLine; } } if (!out) { return plainText; } out.push(plainText.substring(pos)); return out.join(''); }; } var pr_chunkPattern = /(?:[^<]+|<!--[\s\S]*?-->|<!\[CDATA\[([\s\S]*?)\]\]>|<\/?[a-zA-Z][^>]*>|<)/g; var pr_commentPrefix = /^<!--/; var pr_cdataPrefix = /^<\[CDATA\[/; var pr_brPrefix = /^<br\b/i; var pr_tagNameRe = /^<(\/?)([a-zA-Z]+)/; function extractTags(s) { var matches = s.match(pr_chunkPattern); var sourceBuf = []; var sourceBufLen = 0; var extractedTags = []; if (matches) { for (var i = 0, n = matches.length; i < n; ++i) { var match = matches[i]; if (match.length > 1 && match.charAt(0) === '<') { if (pr_commentPrefix.test(match)) { continue; } if (pr_cdataPrefix.test(match)) { sourceBuf.push(match.substring(9, match.length - 3)); sourceBufLen += match.length - 12; } else if (pr_brPrefix.test(match)) { sourceBuf.push('\n'); ++sourceBufLen; } else { if (match.indexOf(PR_NOCODE) >= 0 && isNoCodeTag(match)) { var name = match.match(pr_tagNameRe)[2]; var depth = 1; end_tag_loop: for (var j = i + 1; j < n; ++j) { var name2 = matches[j].match(pr_tagNameRe); if (name2 && name2[2] === name) { if (name2[1] === '/') { if (--depth === 0) { break end_tag_loop; } } else { ++depth; } } } if (j < n) { extractedTags.push(sourceBufLen, matches.slice(i, j + 1).join('')); i = j; } else { extractedTags.push(sourceBufLen, match); } } else { extractedTags.push(sourceBufLen, match); } } } else { var literalText = htmlToText(match); sourceBuf.push(literalText); sourceBufLen += literalText.length; } } } return { source: sourceBuf.join(''), tags: extractedTags }; } function isNoCodeTag(tag) { return !!tag.replace(/\s(\w+)\s*=\s*(?:\"([^\"]*)\"|'([^\']*)'|(\S+))/g, ' $1="$2$3$4"').match(/[cC][lL][aA][sS][sS]=\"[^\"]*\bnocode\b/); } function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) { var shortcuts = {}; (function() { var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns); for (var i = allPatterns.length; --i >= 0; ) { var patternParts = allPatterns[i]; var shortcutChars = patternParts[3]; if (shortcutChars) { for (var c = shortcutChars.length; --c >= 0; ) { shortcuts[shortcutChars.charAt(c)] = patternParts; } } } })(); var nPatterns = fallthroughStylePatterns.length; var notWs = /\S/; return function(sourceCode, opt_basePos) { opt_basePos = opt_basePos || 0; var decorations = [opt_basePos, PR_PLAIN]; var lastToken = ''; var pos = 0; var tail = sourceCode; while (tail.length) { var style; var token = null; var match; var patternParts = shortcuts[tail.charAt(0)]; if (patternParts) { match = tail.match(patternParts[1]); token = match[0]; style = patternParts[0]; } else { for (var i = 0; i < nPatterns; ++i) { patternParts = fallthroughStylePatterns[i]; var contextPattern = patternParts[2]; if (contextPattern && !contextPattern.test(lastToken)) { continue; } match = tail.match(patternParts[1]); if (match) { token = match[0]; style = patternParts[0]; break; } } if (!token) { style = PR_PLAIN; token = tail.substring(0, 1); } } decorations.push(opt_basePos + pos, style); pos += token.length; tail = tail.substring(token.length); if (style !== PR_COMMENT && notWs.test(token)) { lastToken = token; } } return decorations; }; } var PR_MARKUP_LEXER = createSimpleLexer([], [[PR_PLAIN, /^[^<]+/, null], [PR_DECLARATION, /^<!\w[^>]*(?:>|$)/, null], [PR_COMMENT, /^<!--[\s\S]*?(?:-->|$)/, null], [PR_SOURCE, /^<\?[\s\S]*?(?:\?>|$)/, null], [PR_SOURCE, /^<%[\s\S]*?(?:%>|$)/, null], [PR_SOURCE, /^<(script|style|xmp)\b[^>]*>[\s\S]*?<\/\1\b[^>]*>/i, null], [PR_TAG, /^<\/?\w[^<>]*>/, null]]); var PR_SOURCE_CHUNK_PARTS = /^(<[^>]*>)([\s\S]*)(<\/[^>]*>)$/; function tokenizeMarkup(source) { var decorations = PR_MARKUP_LEXER(source); for (var i = 0; i < decorations.length; i += 2) { if (decorations[i + 1] === PR_SOURCE) { var start, end; start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; var sourceChunk = source.substring(start, end); var match = sourceChunk.match(PR_SOURCE_CHUNK_PARTS); if (match) { decorations.splice(i, 2, start, PR_TAG, start + match[1].length, PR_SOURCE, start + match[1].length + (match[2] || '').length, PR_TAG); } } } return decorations; } var PR_TAG_LEXER = createSimpleLexer([[PR_ATTRIB_VALUE, /^\'[^\']*(?:\'|$)/, null, "'"], [PR_ATTRIB_VALUE, /^\"[^\"]*(?:\"|$)/, null, '"'], [PR_PUNCTUATION, /^[<>\/=]+/, null, '<>/=']], [[PR_TAG, /^[\w:\-]+/, /^</], [PR_ATTRIB_VALUE, /^[\w\-]+/, /^=/], [PR_ATTRIB_NAME, /^[\w:\-]+/, null], [PR_PLAIN, /^\s+/, null, ' \t\r\n']]); function splitTagAttributes(source, decorations) { for (var i = 0; i < decorations.length; i += 2) { var style = decorations[i + 1]; if (style === PR_TAG) { var start, end; start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; var chunk = source.substring(start, end); var subDecorations = PR_TAG_LEXER(chunk, start); spliceArrayInto(subDecorations, decorations, i, 2); i += subDecorations.length - 2; } } return decorations; } function sourceDecorator(options) { var shortcutStylePatterns = [], fallthroughStylePatterns = []; if (options.tripleQuotedStrings) { shortcutStylePatterns.push([PR_STRING, /^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/, null, '\'"']); } else if (options.multiLineStrings) { shortcutStylePatterns.push([PR_STRING, /^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/, null, '\'"`']); } else { shortcutStylePatterns.push([PR_STRING, /^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/, null, '"\'']); } fallthroughStylePatterns.push([PR_PLAIN, /^(?:[^\'\"\`\/\#]+)/, null, ' \r\n']); if (options.hashComments) { shortcutStylePatterns.push([PR_COMMENT, /^#[^\r\n]*/, null, '#']); } if (options.cStyleComments) { fallthroughStylePatterns.push([PR_COMMENT, /^\/\/[^\r\n]*/, null]); fallthroughStylePatterns.push([PR_COMMENT, /^\/\*[\s\S]*?(?:\*\/|$)/, null]); } if (options.regexLiterals) { var REGEX_LITERAL = ('^/(?=[^/*])' + '(?:[^/\\x5B\\x5C]' + '|\\x5C[\\s\\S]' + '|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+' + '(?:/|$)'); fallthroughStylePatterns.push([PR_STRING, new RegExp(REGEX_LITERAL), REGEXP_PRECEDER_PATTERN]); } var keywords = wordSet(options.keywords); options = null; var splitStringAndCommentTokens = createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns); var styleLiteralIdentifierPuncRecognizer = createSimpleLexer([], [[PR_PLAIN, /^\s+/, null, ' \r\n'], [PR_PLAIN, /^[a-z_$@][a-z_$@0-9]*/i, null], [PR_LITERAL, /^0x[a-f0-9]+[a-z]/i, null], [PR_LITERAL, /^(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d+)(?:e[+\-]?\d+)?[a-z]*/i, null, '123456789'], [PR_PUNCTUATION, /^[^\s\w\.$@]+/, null]]); function splitNonStringNonCommentTokens(source, decorations) { for (var i = 0; i < decorations.length; i += 2) { var style = decorations[i + 1]; if (style === PR_PLAIN) { var start, end, chunk, subDecs; start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; chunk = source.substring(start, end); subDecs = styleLiteralIdentifierPuncRecognizer(chunk, start); for (var j = 0, m = subDecs.length; j < m; j += 2) { var subStyle = subDecs[j + 1]; if (subStyle === PR_PLAIN) { var subStart = subDecs[j]; var subEnd = j + 2 < m ? subDecs[j + 2] : chunk.length; var token = source.substring(subStart, subEnd); if (token === '.') { subDecs[j + 1] = PR_PUNCTUATION; } else if (token in keywords) { subDecs[j + 1] = PR_KEYWORD; } else if (/^@?[A-Z][A-Z$]*[a-z][A-Za-z$]*$/.test(token)) { subDecs[j + 1] = token.charAt(0) === '@' ? PR_LITERAL : PR_TYPE; } } } spliceArrayInto(subDecs, decorations, i, 2); i += subDecs.length - 2; } } return decorations; } return function(sourceCode) { var decorations = splitStringAndCommentTokens(sourceCode); decorations = splitNonStringNonCommentTokens(sourceCode, decorations); return decorations; }; } var decorateSource = sourceDecorator({ keywords: ALL_KEYWORDS, hashComments: true, cStyleComments: true, multiLineStrings: true, regexLiterals: true }); function splitSourceNodes(source, decorations) { for (var i = 0; i < decorations.length; i += 2) { var style = decorations[i + 1]; if (style === PR_SOURCE) { var start, end; start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; var subDecorations = decorateSource(source.substring(start, end)); for (var j = 0, m = subDecorations.length; j < m; j += 2) { subDecorations[j] += start; } spliceArrayInto(subDecorations, decorations, i, 2); i += subDecorations.length - 2; } } return decorations; } function splitSourceAttributes(source, decorations) { var nextValueIsSource = false; for (var i = 0; i < decorations.length; i += 2) { var style = decorations[i + 1]; var start, end; if (style === PR_ATTRIB_NAME) { start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; nextValueIsSource = /^on|^style$/i.test(source.substring(start, end)); } else if (style === PR_ATTRIB_VALUE) { if (nextValueIsSource) { start = decorations[i]; end = i + 2 < decorations.length ? decorations[i + 2] : source.length; var attribValue = source.substring(start, end); var attribLen = attribValue.length; var quoted = (attribLen >= 2 && /^[\"\']/.test(attribValue) && attribValue.charAt(0) === attribValue.charAt(attribLen - 1)); var attribSource; var attribSourceStart; var attribSourceEnd; if (quoted) { attribSourceStart = start + 1; attribSourceEnd = end - 1; attribSource = attribValue; } else { attribSourceStart = start + 1; attribSourceEnd = end - 1; attribSource = attribValue.substring(1, attribValue.length - 1); } var attribSourceDecorations = decorateSource(attribSource); for (var j = 0, m = attribSourceDecorations.length; j < m; j += 2) { attribSourceDecorations[j] += attribSourceStart; } if (quoted) { attribSourceDecorations.push(attribSourceEnd, PR_ATTRIB_VALUE); spliceArrayInto(attribSourceDecorations, decorations, i + 2, 0); } else { spliceArrayInto(attribSourceDecorations, decorations, i, 2); } } nextValueIsSource = false; } } return decorations; } function decorateMarkup(sourceCode) { var decorations = tokenizeMarkup(sourceCode); decorations = splitTagAttributes(sourceCode, decorations); decorations = splitSourceNodes(sourceCode, decorations); decorations = splitSourceAttributes(sourceCode, decorations); return decorations; } function recombineTagsAndDecorations(sourceText, extractedTags, decorations) { var html = []; var outputIdx = 0; var openDecoration = null; var currentDecoration = null; var tagPos = 0; var decPos = 0; var tabExpander = makeTabExpander(PR_TAB_WIDTH); var adjacentSpaceRe = /([\r\n ]) /g; var startOrSpaceRe = /(^| ) /gm; var newlineRe = /\r\n?|\n/g; var trailingSpaceRe = /[ \r\n]$/; var lastWasSpace = true; function emitTextUpTo(sourceIdx) { if (sourceIdx > outputIdx) { if (openDecoration && openDecoration !== currentDecoration) { html.push('</span>'); openDecoration = null; } if (!openDecoration && currentDecoration) { openDecoration = currentDecoration; html.push('<span class="', openDecoration, '">'); } var htmlChunk = textToHtml(tabExpander(sourceText.substring(outputIdx, sourceIdx))).replace(lastWasSpace ? startOrSpaceRe : adjacentSpaceRe, '$1&nbsp;'); lastWasSpace = trailingSpaceRe.test(htmlChunk); html.push(htmlChunk.replace(newlineRe, '<br />')); outputIdx = sourceIdx; } } while (true) { var outputTag; if (tagPos < extractedTags.length) { if (decPos < decorations.length) { outputTag = extractedTags[tagPos] <= decorations[decPos]; } else { outputTag = true; } } else { outputTag = false; } if (outputTag) { emitTextUpTo(extractedTags[tagPos]); if (openDecoration) { html.push('</span>'); openDecoration = null; } html.push(extractedTags[tagPos + 1]); tagPos += 2; } else if (decPos < decorations.length) { emitTextUpTo(decorations[decPos]); currentDecoration = decorations[decPos + 1]; decPos += 2; } else { break; } } emitTextUpTo(sourceText.length); if (openDecoration) { html.push('</span>'); } return html.join(''); } var langHandlerRegistry = {}; function registerLangHandler(handler, fileExtensions) { for (var i = fileExtensions.length; --i >= 0; ) { var ext = fileExtensions[i]; if (!langHandlerRegistry.hasOwnProperty(ext)) { langHandlerRegistry[ext] = handler; } else if ('console' in window) { console.log('cannot override language handler %s', ext); } } } registerLangHandler(decorateSource, ['default-code']); registerLangHandler(decorateMarkup, ['default-markup', 'html', 'htm', 'xhtml', 'xml', 'xsl']); registerLangHandler(sourceDecorator({ keywords: CPP_KEYWORDS, hashComments: true, cStyleComments: true }), ['c', 'cc', 'cpp', 'cs', 'cxx', 'cyc']); registerLangHandler(sourceDecorator({ keywords: JAVA_KEYWORDS, cStyleComments: true }), ['java']); registerLangHandler(sourceDecorator({ keywords: SH_KEYWORDS, hashComments: true, multiLineStrings: true }), ['bsh', 'csh', 'sh']); registerLangHandler(sourceDecorator({ keywords: PYTHON_KEYWORDS, hashComments: true, multiLineStrings: true, tripleQuotedStrings: true }), ['cv', 'py']); registerLangHandler(sourceDecorator({ keywords: PERL_KEYWORDS, hashComments: true, multiLineStrings: true, regexLiterals: true }), ['perl', 'pl', 'pm']); registerLangHandler(sourceDecorator({ keywords: RUBY_KEYWORDS, hashComments: true, multiLineStrings: true, regexLiterals: true }), ['rb']); registerLangHandler(sourceDecorator({ keywords: JSCRIPT_KEYWORDS, cStyleComments: true, regexLiterals: true }), ['js']); function prettyPrintOne(sourceCodeHtml, opt_langExtension) { try { var sourceAndExtractedTags = extractTags(sourceCodeHtml); var source = sourceAndExtractedTags.source; var extractedTags = sourceAndExtractedTags.tags; if (!langHandlerRegistry.hasOwnProperty(opt_langExtension)) { opt_langExtension = /^\s*</.test(source) ? 'default-markup' : 'default-code'; } var decorations = langHandlerRegistry[opt_langExtension].call({}, source); return recombineTagsAndDecorations(source, extractedTags, decorations); } catch (e) { if ('console' in window) { console.log(e); console.trace(); } return sourceCodeHtml; } } function prettyPrint(opt_whenDone) { var isIE6 = _pr_isIE6(); var codeSegments = [document.getElementsByTagName('pre'), document.getElementsByTagName('code'), document.getElementsByTagName('xmp')]; var elements = []; for (var i = 0; i < codeSegments.length; ++i) { for (var j = 0; j < codeSegments[i].length; ++j) { elements.push(codeSegments[i][j]); } } codeSegments = null; var k = 0; function doWork() { var endTime = (PR_SHOULD_USE_CONTINUATION ? new Date().getTime() + 250 : Infinity); for (; k < elements.length && new Date().getTime() < endTime; k++) { var cs = elements[k]; if (cs.className && cs.className.indexOf('prettyprint') >= 0) { var langExtension = cs.className.match(/\blang-(\w+)\b/); if (langExtension) { langExtension = langExtension[1]; } var nested = false; for (var p = cs.parentNode; p; p = p.parentNode) { if ((p.tagName === 'pre' || p.tagName === 'code' || p.tagName === 'xmp') && p.className && p.className.indexOf('prettyprint') >= 0) { nested = true; break; } } if (!nested) { var content = getInnerHtml(cs); content = content.replace(/(?:\r\n?|\n)$/, ''); var newContent = prettyPrintOne(content, langExtension); if (!isRawContent(cs)) { cs.innerHTML = newContent; } else { var pre = document.createElement('PRE'); for (var i = 0; i < cs.attributes.length; ++i) { var a = cs.attributes[i]; if (a.specified) { var aname = a.name.toLowerCase(); if (aname === 'class') { pre.className = a.value; } else { pre.setAttribute(a.name, a.value); } } } pre.innerHTML = newContent; cs.parentNode.replaceChild(pre, cs); cs = pre; } if (isIE6 && cs.tagName === 'PRE') { var lineBreaks = cs.getElementsByTagName('br'); for (var j = lineBreaks.length; --j >= 0; ) { var lineBreak = lineBreaks[j]; lineBreak.parentNode.replaceChild(document.createTextNode('\r\n'), lineBreak); } } } } } if (k < elements.length) { setTimeout(doWork, 250); } else if (opt_whenDone) { opt_whenDone(); } } doWork(); } window['PR_normalizedHtml'] = normalizedHtml; window['prettyPrintOne'] = prettyPrintOne; window['prettyPrint'] = prettyPrint; window['PR'] = { 'createSimpleLexer': createSimpleLexer, 'registerLangHandler': registerLangHandler, 'sourceDecorator': sourceDecorator, 'PR_ATTRIB_NAME': PR_ATTRIB_NAME, 'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE, 'PR_COMMENT': PR_COMMENT, 'PR_DECLARATION': PR_DECLARATION, 'PR_KEYWORD': PR_KEYWORD, 'PR_LITERAL': PR_LITERAL, 'PR_NOCODE': PR_NOCODE, 'PR_PLAIN': PR_PLAIN, 'PR_PUNCTUATION': PR_PUNCTUATION, 'PR_SOURCE': PR_SOURCE, 'PR_STRING': PR_STRING, 'PR_TAG': PR_TAG, 'PR_TYPE': PR_TYPE }; })();
diff --git a/templates/question.html b/templates/question.html
index 9183767f..3955c059 100644
--- a/templates/question.html
+++ b/templates/question.html
@@ -1,510 +1,510 @@
-{% extends "base.html" %}
-<!-- question.html -->
-{% load extra_tags %}
-{% load extra_filters %}
-{% load smart_if %}
-{% load humanize %}
-{% load i18n %}
-{% block title %}{% spaceless %}{{ question.get_question_title }}{% endspaceless %}{% endblock %}
-{% block forejs %}
- <meta name="description" content="{{question.summary}}" />
- <meta name="keywords" content="{{question.tagname_meta_generator}}" />
- <link rel="canonical" href="{{settings.APP_URL}}{{question.get_absolute_url}}" />
- {% if not question.closed %}
- <script type='text/javascript' src='{% href "/content/js/com.cnprog.editor.js" %}'></script>
- <script type='text/javascript' src='{% href "/content/js/wmd/showdown.js" %}'></script>
- <script type='text/javascript' src='{% href "/content/js/wmd/wmd.js" %}'></script>
- <link rel="stylesheet" type="text/css" href="{% href "/content/js/wmd/wmd.css" %}" />
- {% endif %}
- <script type='text/javascript' src='{% href "/content/js/com.cnprog.post.js" %}'></script>
- <script type='text/javascript' src='{% href "/content/js/jquery.validate.pack.js" %}'></script>
-
- <script type="text/javascript">
- // define reputation needs for comments
- var repNeededForComments = 50;
- $().ready(function(){
- $("#nav_questions").attr('className',"on");
- var answer_sort_tab = "{{ tab_id }}";
- $("#" + answer_sort_tab).attr('className',"on");
-
- Vote.init({{ question.id }}, '{{ question.author.id }}','{{ request.user.id }}');
-
- {% if not question.closed and request.user.is_authenticated %}initEditor();{% endif %}
-
- lanai.highlightSyntax();
- $('#btLogin').bind('click', function(){window.location.href='{% url user_signin %}'; } )
- });
-
- function initEditor(){
- $('#editor').TextAreaResizer();
- //highlight code synctax when editor has new text
- $("#editor").typeWatch({highlight: false, wait: 3000,
- captureLength: 5, callback: lanai.highlightSyntax});
-
- var display = true;
- var txt = "[{% trans "hide preview" %}]";
- $('#pre-collapse').text(txt);
- $('#pre-collapse').bind('click', function(){
- txt = display ? "[{% trans "show preview" %}]" : "[{% trans "hide preview" %}]";
- display = !display;
- $('#previewer').toggle();
- $('#pre-collapse').text(txt);
- });
-
- setupFormValidation("#fmanswer", CPValidator.getQuestionFormRules(), CPValidator.getQuestionFormMessages());
- }
-
- </script>
-{% endblock %}
-
-{% block content %}
-<div class="headNormal">
- <a href="{{ question.get_absolute_url }}">{{ question.get_question_title }}</a>
-</div>
-<div id="main-body" class="">
- <div id="askform">
- <table style="width:100%;" id="question-table" {% if question.deleted %}class="deleted"{%endif%}>
- <tr>
- <td style="width:30px;vertical-align:top">
- <div class="vote-buttons">
- {% if question_vote %}
- <img id="question-img-upvote-{{ question.id }}" class="question-img-upvote"
- {% if question_vote.is_upvote %}
- src="{% href "/content/images/vote-arrow-up-on.png" %}"
- {% else %}
- src="{% href "/content/images/vote-arrow-up.png" %}"
- {% endif %}
- alt="{% trans "i like this post (click again to cancel)" %}"
- title="{% trans "i like this post (click again to cancel)" %}" />
- <div id="question-vote-number-{{ question.id }}" class="vote-number"
- title="{% trans "current number of votes" %}">
- {{ question.score }}
- </div>
- <img id="question-img-downvote-{{ question.id }}" class="question-img-downvote"
- {% if question_vote.is_downvote %}
- src="{% href "/content/images/vote-arrow-down-on.png" %}"
- {% else %}
- src="{% href "/content/images/vote-arrow-down.png" %}"
- {% endif %}
- alt="{% trans "i dont like this post (click again to cancel)" %}"
- title="{% trans "i dont like this post (click again to cancel)" %}" />
-
- {% else %}
- <img id="question-img-upvote-{{ question.id }}" class="question-img-upvote"
- alt="{% trans "i like this post (click again to cancel)" %}"
- src="{% href "/content/images/vote-arrow-up.png" %}"
- title="{% trans "i like this post (click again to cancel)" %}" />
- <div id="question-vote-number-{{ question.id }}" class="vote-number"
- title="{% trans "current number of votes" %}">
- {{ question.score }}
- </div>
- <img id="question-img-downvote-{{ question.id }}" class="question-img-downvote"
- src="{% href "/content/images/vote-arrow-down.png" %}"
- alt="{% trans "i dont like this post (click again to cancel)" %}"
- title="{% trans "i dont like this post (click again to cancel)" %}" />
-
- {% endif %}
- {% if favorited %}
- <img class="question-img-favorite" src="{% href "/content/images/vote-favorite-on.png" %}"
- alt="{% trans "mark this question as favorite (click again to cancel)" %}"
- title="{% trans "mark this question as favorite (click again to cancel)" %}" />
- <div id="favorite-number" class="favorite-number my-favorite-number">
- {{ question.favourite_count }}
- </div>
- {% else %}
- <img class="question-img-favorite" src="{% href "/content/images/vote-favorite-off.png" %}"
- alt="{% trans "remove favorite mark from this question (click again to restore mark)" %}"
- title="{% trans "remove favorite mark from this question (click again to restore mark)" %}" />
- <div id="favorite-number" class="favorite-number">
- {% ifnotequal question.favourite_count 0 %}{{ question.favourite_count }}{% endifnotequal %}
- </div>
-
- {% endif %}
-
- </div>
- </td>
- <td>
- <div id="item-right">
- <div class="question-body">
- {{ question.html|safe }}
- </div>
- <div id="question-controls" class="post-controls">
- <div id="question-tags" class="tags">
- {% for tag in question.tagname_list %}
- <a href="{% url forum.views.tag tag|urlencode %}" class="post-tag"
- title="{% blocktrans with tag as tagname %}see questions tagged '{{ tagname }}'{% endblocktrans %}" rel="tag">{{ tag }}</a>
- {% endfor %}
- </div>
- {% joinitems using '<span class="action-link-separator">|</span>' %}
- {% if request.user|can_edit_post:question %}
- <span class="action-link"><a href="{% url edit_question question.id %}">{% trans 'edit' %}</a></span>
- {% endif %}
- {% separator %}
- {% if question.closed %}
- {% if request.user|can_reopen_question:question %}
- <span class="action-link"><a href="{% url reopen question.id %}">{% trans "reopen" %}</a></span>
- {% endif %}
- {% else %}
- {% if request.user|can_close_question:question %}
- <span class="action-link"><a href="{% url close question.id %}">{% trans "close" %}</a></span>
- {% endif %}
- {% endif %}
- {% separator %}
- {% if request.user|can_flag_offensive %}
- <span id="question-offensive-flag-{{ question.id }}" class="offensive-flag"
- title="{% trans "report as offensive (i.e containing spam, advertising, malicious text, etc.)" %}">
- <a>{% trans "flag offensive" %}</a>
- {% if request.user|can_view_offensive_flags and question.offensive_flag_count %}
- <span class="darkred">({{ question.offensive_flag_count }})</span>
- {% endif %}
- </span>
- {% endif %}
- {% separator %}
- {% if request.user|can_delete_post:question %}
- <span class="action-link"><a id="question-delete-link-{{question.id}}">{% trans "delete" %}</a></span>
- {% endif %}
- {% endjoinitems %}
- </div>
- <div class="post-update-info-container">
- {% post_contributor_info question "original_author" %}
- {% post_contributor_info question "last_updater" %}
- </div>
- <div class="comments-container" id="comments-container-question-{{question.id}}">
- {% for comment in question.get_comments|slice:":5" %}
- <p class="comment" id="comment-{{comment.id}}">
- {{comment.comment}}
- - <a class="comment-user" href="{{comment.user.get_profile_url}}">{{comment.user}}</a>
- {% spaceless %}
- <span class="comment-age">({% diff_date comment.added_at %})</span>
- {% if request.user|can_delete_comment:comment %}
- <img class="delete-icon"
- src="{% href "/content/images/close-small.png" %}"
- title="{% trans "delete this comment" %}"/>
- {% endif %}
- {% endspaceless %}
- </p>
- {% endfor %}
- </div>
- <div class="post-comments" style="margin-bottom:20px">
- <input id="can-post-comments-question-{{question.id}}" type="hidden" value="{{ request.user|can_add_comments:question }}"/>
- {% if request.user|can_add_comments:question or question.comment_count > 5 %}
- <a id="comments-link-question-{{question.id}}" class="comments-link">
- {% if request.user|can_add_comments:question %}
- {% trans "add comment" %}
- {% endif %}
- {% if question.comment_count > 5 %}
- {% if request.user|can_add_comments:question %}/
- {% blocktrans count question.get_comments|slice:"5:"|length as counter %}
- see <strong>one</strong> more
- {% plural %}
- see <strong>{{counter}}</strong> more
- {% endblocktrans %}
- {% else %}
- {% blocktrans count question.get_comments|slice:"5:"|length as counter %}
- see <strong>one</strong> more comment
- {% plural %}
- see <strong>{{counter}}</strong> more comments
- {% endblocktrans %}
- {% endif %}
- {% endif %}</a>
- {% endif %}
- </div>
- </div>
-
- </td>
- </tr>
- </table>
- {% if question.closed %}
- <div class="question-status" style="margin-bottom:15px">
- <h3>{% blocktrans with question.get_close_reason_display as close_reason %}The question has been closed for the following reason "{{ close_reason }}" by{% endblocktrans %}
- <a href="{{ question.closed_by.get_profile_url }}">{{ question.closed_by.username }}</a>
- {% blocktrans with question.closed_at as closed_at %}close date {{closed_at}}{% endblocktrans %}</h3>
- </div>
- {% endif %}
- {% if answers %}
- <hr/>
- <div class="tabBar">
- <a name="sort-top"></a>
- <div class="headQuestions">
- {% blocktrans count answers|length as counter %}
- One Answer:
- {% plural %}
- {{counter}} Answers:
- {% endblocktrans %}
- </div>
- <div class="tabsA">
- <a id="oldest" href="{% url question question.id %}?sort=oldest#sort-top"
- title="{% trans "oldest answers will be shown first" %}">{% trans "oldest answers" %}</a>
- <a id="latest" href="{% url question question.id %}?sort=latest#sort-top"
- title="{% trans "newest answers will be shown first" %}">{% trans "newest answers" %}</a>
- <a id="votes" href="{% url question question.id %}?sort=votes#sort-top"
- title="{% trans "most voted answers will be shown first" %}">{% trans "popular answers" %}</a>
- </div>
- </div>
- {% cnprog_paginator context %}
-
- {% for answer in answers %}
- <a name="{{ answer.id }}"></a>
- <div id="answer-container-{{ answer.id }}" class="answer {% if answer.accepted %}accepted-answer{% endif %} {% ifequal answer.author_id question.author_id %} answered-by-owner{% endifequal %} {% if answer.deleted %}deleted{% endif %}">
- <table style="width:100%;">
- <tr>
- <td style="width:30px;vertical-align:top">
- <div class="vote-buttons">
- <img id="answer-img-upvote-{{ answer.id }}" class="answer-img-upvote"
- src="{% blockresource %}/content/images/vote-arrow-up{% get_user_vote_image user_answer_votes answer.id 1 %}.png{% endblockresource %}"
- alt="{% trans "i like this answer (click again to cancel)" %}"
- title="{% trans "i like this answer (click again to cancel)" %}"/>
- <div id="answer-vote-number-{{ answer.id }}" class="vote-number" title="{% trans "current number of votes" %}">
- {{ answer.score }}
- </div>
- <img id="answer-img-downvote-{{ answer.id }}" class="answer-img-downvote"
- src="{% blockresource %}/content/images/vote-arrow-down{% get_user_vote_image user_answer_votes answer.id -1 %}.png{% endblockresource %}"
- alt="{% trans "i dont like this answer (click again to cancel)" %}"
- title="{% trans "i dont like this answer (click again to cancel)" %}" />
-
- {% ifequal request.user question.author %}
- <img id="answer-img-accept-{{ answer.id }}" class="answer-img-accept"
- src="{% blockresource %}/content/images/vote-accepted{% if answer.accepted %}-on{% endif %}.png{% endblockresource %}"
- alt="{% trans "mark this answer as favorite (click again to undo)" %}"
- title="{% trans "mark this answer as favorite (click again to undo)" %}" />
- {% else %}
- {% if answer.accepted %}
- <img id="answer-img-accept-{{ answer.id }}" class="answer-img-accept"
- src="{% blockresource %}/content/images/vote-accepted{% if answer.accepted %}-on{% endif %}.png{% endblockresource %}"
- alt="{% trans "the author of the question has selected this answer as correct" %}"
- title="{% trans "the author of the question has selected this answer as correct" %}" />
- {% endif %}
- {% endifequal %}
- </div>
- </td>
- <td>
- <div class="item-right">
- <div class="answer-body">
- {{ answer.html|safe }}
- </div>
- <div class="answer-controls post-controls">
- {% joinitems using '<span class="action-link-separator">|</span>' %}
- <span class="linksopt">
- <a href="#{{ answer.id }}" title="{% trans "answer permanent link" %}">
- {% trans "permanent link" %}
- </a>
- </span>
- {% separator %}
- {% if request.user|can_edit_post:answer %}
- <span class="action-link"><a href="{% url edit_answer answer.id %}">{% trans 'edit' %}</a></span>
- {% endif %}
- {% separator %}
- {% if request.user|can_flag_offensive %}
- <span id="answer-offensive-flag-{{ answer.id }}" class="offensive-flag"
- title="{% trans "report as offensive (i.e containing spam, advertising, malicious text, etc.)" %}">
- <a>{% trans "flag offensive" %}</a>
- {% if request.user|can_view_offensive_flags and answer.offensive_flag_count %}
- <span class="darkred">({{ answer.offensive_flag_count }})</span>
- {% endif %}
- </span>
- {% endif %}
- {% separator %}
- {% if request.user|can_delete_post:answer %}
- {% spaceless %}
- <span class="action-link">
- <a id="answer-delete-link-{{answer.id}}">
- {% if answer.deleted %}{% trans "undelete" %}{% else %}{% trans "delete" %}{% endif %}</a>
- </span>
- {% endspaceless %}
- {% endif %}
- {% endjoinitems %}
- </div>
- <div class="post-update-info-container">
- {% post_contributor_info answer "original_author" %}
- {% post_contributor_info answer "last_updater" %}
- </div>
- <div class="comments-container" id="comments-container-answer-{{answer.id}}">
- {% for comment in answer.get_comments|slice:":5" %}
- <p id="comment-{{comment.id}}" class="comment">
- {{comment.comment}}
- - <a class="comment-user" href="{{comment.user.get_profile_url}}">{{comment.user}}</a>
- {% spaceless %}
- <span class="comment-age">({% diff_date comment.added_at %})</span>
- {% if request.user|can_delete_comment:comment %}
- <img class="delete-icon"
- src="{% href "/content/images/close-small.png" %}"
- title="{% trans "delete this comment" %}"/>
- {% endif %}
- {% endspaceless %}
- </p>
- {% endfor %}
- </div>
- <div class="post-comments" style="margin-bottom:20px">
- <input id="can-post-comments-answer-{{answer.id}}" type="hidden" value="{{ request.user|can_add_comments:answer}}"/>
- {% if request.user|can_add_comments:answer or answer.comment_count > 5 %}
- <a id="comments-link-answer-{{answer.id}}" class="comments-link">
- {% if request.user|can_add_comments:answer %}
- {% trans "add comment" %}
- {% endif %}
- {% if answer.comment_count > 5 %}
- {% if request.user|can_add_comments:answer %}/
- {% blocktrans count answer.get_comments|slice:"5:"|length as counter %}
- see <strong>one</strong> more
- {% plural %}
- see <strong>{{counter}}</strong> more
- {% endblocktrans %}
- {% else %}
- {% blocktrans count answer.get_comments|slice:"5:"|length as counter %}
- see <strong>one</strong> more comment
- {% plural %}
- see <strong>{{counter}}</strong> more comments
- {% endblocktrans %}
- {% endif %}
- {% endif %}</a>
- {% endif %}
- </div>
- </div>
-
- </td>
- </tr>
- </table>
- </div>
- {% endfor %}
- <div class="paginator-container-left">
- {% cnprog_paginator context %}
- </div>
- {% endif %}
- <form id="fmanswer" action="{% url answer question.id %}" method="post">
- {% if request.user.is_authenticated %}
- <p style="padding-left:3px">
- {{ answer.email_notify }}
- <label for="question-subscribe-updates">
- {% ifequal request.user.get_q_sel_email_feed_frequency 'n' %}
- {% trans "Notify me once a day when there are any new answers" %}
- {% else %}
- {% ifequal request.user.get_q_sel_email_feed_frequency 'd' %}
- {% trans "Notify me once a day when there are any new answers" %}
- {% else %}
- {% ifequal request.user.get_q_sel_email_feed_frequency 'w' %}
- {% trans "Notify me weekly when there are any new answers" %}
- {% endifequal %}
- {% endifequal %}
- {% endifequal %}
- </label>
- {% blocktrans with request.user.get_profile_url as profile_url %}
- You can always adjust frequency of email updates from your {{profile_url}}
- {% endblocktrans %}
- </p>
- {% else %}
- <p style="padding-left:3px">
- <input class="nomargin" type="checkbox" disabled="disabled" />
- <label>{% trans "once you sign in you will be able to subscribe for any updates here" %}</label>
- </p>
- {% endif %}
- <div style="clear:both">
- </div>
-
- {% if not question.closed %}
- <div style="padding:10px 0 0 0;">
- {% spaceless %}
- <div class="headNormal">
- {% if answers %}
- {% trans "Your answer" %}
- {% else %}
- {% trans "Be the first one to answer this question!" %}
- {% endif %}
- </div>
- {% endspaceless %}
- </div>
- {% if not request.user.is_authenticated %}
- <div class="message">{% trans "you can answer anonymously and then login" %}</div>
- {% else %}
- <p class="message">
- {% ifequal request.user question.author %}
- {% trans "answer your own question only to give an answer" %}
- {% else %}
- {% trans "please only give an answer, no discussions" %}
- {% endifequal %}
- </p>
- {% endif %}
-
- <div id="description" class="" >
- <div id="wmd-button-bar" class="wmd-panel"></div>
- {{ answer.text }}
- <div class="preview-toggle">
- <table width="100%">
- <tr>
- <td>
- <span id="pre-collapse"
- title="{% trans "Toggle the real time Markdown editor preview" %}">
- {% trans "toggle preview" %}
- </span>
- </td>
- {% if settings.WIKI_ON %}
- <td style="text-align:right;">
- {{ answer.wiki }}
- <span style="font-weight:normal;cursor:help"
- title="{{answer.wiki.help_text}}">
- {{ answer.wiki.label_tag }}
- </span>
- </td>
- {% endif %}
- </tr>
-
- </table>
- </div>
- <div id="previewer" class="wmd-preview"></div>
- {{ answer.text.errors }}
- </div>
- <p><span class="form-error"></span></p>
- <input type="submit"
- {% if user.is_anonymous %}
- value="{% trans "Login/Signup to Post Your Answer" %}"
- {% else %}
- {% if user == question.author %}
- value="{% trans "Answer Your Own Question" %}"
- {% else %}
- value="{% trans "Answer the question" %}"
- {% endif %}
- {% endif %}
- class="submit" style="float:left"/>
- {% endif %}
- </form>
- </div>
-</div>
-{% endblock %}
-
-{% block sidebar %}
-<div class="boxC">
- <p>
- {% trans "Question tags" %}:
- </p>
- <p class="tags" >
- {% for tag in tags %}
- <a href="{% url forum.views.tag tag.name|urlencode %}"
- title="{% trans "see questions tagged"%}'{{tag.name}}'{% trans "using tags" %}"
- rel="tag">{{ tag.name }}</a> <span class="tag-number">&#215;{{ tag.used_count|intcomma }}</span><br/>
- {% endfor %}
- </p>
- <p>
- {% trans "question asked" %}: <strong title="{{ question.added_at }}">{% diff_date question.added_at %}</strong>
- </p>
- <p>
- {% trans "question was seen" %}: <strong>{{ question.view_count|intcomma }} {% trans "times" %}</strong>
- </p>
- <p>
- {% trans "last updated" %}: <strong title="{{ question.last_activity_at }}">{% diff_date question.last_activity_at %}</strong>
- </p>
-</div>
-
-<div class="boxC">
- <h3 class="subtitle">{% trans "Related questions" %}</h3>
- <div class="questions-related">
- {% for question in similar_questions %}
- <p>
- <a href="{{ question.get_absolute_url }}">{{ question.get_question_title }}</a>
- </p>
- {% endfor %}
- </div>
-</div>
-
-{% endblock %}
-
-{% block endjs %}
-{% endblock %}
-<!-- end question.html -->
+{% extends "base.html" %}
+<!-- question.html -->
+{% load extra_tags %}
+{% load extra_filters %}
+{% load smart_if %}
+{% load humanize %}
+{% load i18n %}
+{% block title %}{% spaceless %}{{ question.get_question_title }}{% endspaceless %}{% endblock %}
+{% block forejs %}
+ <meta name="description" content="{{question.summary}}" />
+ <meta name="keywords" content="{{question.tagname_meta_generator}}" />
+ <link rel="canonical" href="{{settings.APP_URL}}{{question.get_absolute_url}}" />
+ {% if not question.closed %}
+ <script type='text/javascript' src='{% href "/content/js/com.cnprog.editor.js" %}'></script>
+ <script type='text/javascript' src='{% href "/content/js/wmd/showdown.js" %}'></script>
+ <script type='text/javascript' src='{% href "/content/js/wmd/wmd.js" %}'></script>
+ <link rel="stylesheet" type="text/css" href="{% href "/content/js/wmd/wmd.css" %}" />
+ {% endif %}
+ <script type='text/javascript' src='{% href "/content/js/com.cnprog.post.js" %}'></script>
+ <script type='text/javascript' src='{% href "/content/js/jquery.validate.pack.js" %}'></script>
+
+ <script type="text/javascript">
+ // define reputation needs for comments
+ var repNeededForComments = 50;
+ $().ready(function(){
+ $("#nav_questions").attr('className',"on");
+ var answer_sort_tab = "{{ tab_id }}";
+ $("#" + answer_sort_tab).attr('className',"on");
+
+ Vote.init({{ question.id }}, '{{ question.title|slugify }}', '{{ question.author.id }}','{{ request.user.id }}');
+
+ {% if not question.closed and request.user.is_authenticated %}initEditor();{% endif %}
+
+ lanai.highlightSyntax();
+ $('#btLogin').bind('click', function(){window.location.href='{% url user_signin %}'; } )
+ });
+
+ function initEditor(){
+ $('#editor').TextAreaResizer();
+ //highlight code synctax when editor has new text
+ $("#editor").typeWatch({highlight: false, wait: 3000,
+ captureLength: 5, callback: lanai.highlightSyntax});
+
+ var display = true;
+ var txt = "[{% trans "hide preview" %}]";
+ $('#pre-collapse').text(txt);
+ $('#pre-collapse').bind('click', function(){
+ txt = display ? "[{% trans "show preview" %}]" : "[{% trans "hide preview" %}]";
+ display = !display;
+ $('#previewer').toggle();
+ $('#pre-collapse').text(txt);
+ });
+
+ setupFormValidation("#fmanswer", CPValidator.getQuestionFormRules(), CPValidator.getQuestionFormMessages());
+ }
+
+ </script>
+{% endblock %}
+
+{% block content %}
+<div class="headNormal">
+ <a href="{{ question.get_absolute_url }}">{{ question.get_question_title }}</a>
+</div>
+<div id="main-body" class="">
+ <div id="askform">
+ <table style="width:100%;" id="question-table" {% if question.deleted %}class="deleted"{%endif%}>
+ <tr>
+ <td style="width:30px;vertical-align:top">
+ <div class="vote-buttons">
+ {% if question_vote %}
+ <img id="question-img-upvote-{{ question.id }}" class="question-img-upvote"
+ {% if question_vote.is_upvote %}
+ src="{% href "/content/images/vote-arrow-up-on.png" %}"
+ {% else %}
+ src="{% href "/content/images/vote-arrow-up.png" %}"
+ {% endif %}
+ alt="{% trans "i like this post (click again to cancel)" %}"
+ title="{% trans "i like this post (click again to cancel)" %}" />
+ <div id="question-vote-number-{{ question.id }}" class="vote-number"
+ title="{% trans "current number of votes" %}">
+ {{ question.score }}
+ </div>
+ <img id="question-img-downvote-{{ question.id }}" class="question-img-downvote"
+ {% if question_vote.is_downvote %}
+ src="{% href "/content/images/vote-arrow-down-on.png" %}"
+ {% else %}
+ src="{% href "/content/images/vote-arrow-down.png" %}"
+ {% endif %}
+ alt="{% trans "i dont like this post (click again to cancel)" %}"
+ title="{% trans "i dont like this post (click again to cancel)" %}" />
+
+ {% else %}
+ <img id="question-img-upvote-{{ question.id }}" class="question-img-upvote"
+ alt="{% trans "i like this post (click again to cancel)" %}"
+ src="{% href "/content/images/vote-arrow-up.png" %}"
+ title="{% trans "i like this post (click again to cancel)" %}" />
+ <div id="question-vote-number-{{ question.id }}" class="vote-number"
+ title="{% trans "current number of votes" %}">
+ {{ question.score }}
+ </div>
+ <img id="question-img-downvote-{{ question.id }}" class="question-img-downvote"
+ src="{% href "/content/images/vote-arrow-down.png" %}"
+ alt="{% trans "i dont like this post (click again to cancel)" %}"
+ title="{% trans "i dont like this post (click again to cancel)" %}" />
+
+ {% endif %}
+ {% if favorited %}
+ <img class="question-img-favorite" src="{% href "/content/images/vote-favorite-on.png" %}"
+ alt="{% trans "mark this question as favorite (click again to cancel)" %}"
+ title="{% trans "mark this question as favorite (click again to cancel)" %}" />
+ <div id="favorite-number" class="favorite-number my-favorite-number">
+ {{ question.favourite_count }}
+ </div>
+ {% else %}
+ <img class="question-img-favorite" src="{% href "/content/images/vote-favorite-off.png" %}"
+ alt="{% trans "remove favorite mark from this question (click again to restore mark)" %}"
+ title="{% trans "remove favorite mark from this question (click again to restore mark)" %}" />
+ <div id="favorite-number" class="favorite-number">
+ {% ifnotequal question.favourite_count 0 %}{{ question.favourite_count }}{% endifnotequal %}
+ </div>
+
+ {% endif %}
+
+ </div>
+ </td>
+ <td>
+ <div id="item-right">
+ <div class="question-body">
+ {{ question.html|safe }}
+ </div>
+ <div id="question-controls" class="post-controls">
+ <div id="question-tags" class="tags">
+ {% for tag in question.tagname_list %}
+ <a href="{% url forum.views.tag tag|urlencode %}" class="post-tag"
+ title="{% blocktrans with tag as tagname %}see questions tagged '{{ tagname }}'{% endblocktrans %}" rel="tag">{{ tag }}</a>
+ {% endfor %}
+ </div>
+ {% joinitems using '<span class="action-link-separator">|</span>' %}
+ {% if request.user|can_edit_post:question %}
+ <span class="action-link"><a href="{% url edit_question question.id %}">{% trans 'edit' %}</a></span>
+ {% endif %}
+ {% separator %}
+ {% if question.closed %}
+ {% if request.user|can_reopen_question:question %}
+ <span class="action-link"><a href="{% url reopen question.id %}">{% trans "reopen" %}</a></span>
+ {% endif %}
+ {% else %}
+ {% if request.user|can_close_question:question %}
+ <span class="action-link"><a href="{% url close question.id %}">{% trans "close" %}</a></span>
+ {% endif %}
+ {% endif %}
+ {% separator %}
+ {% if request.user|can_flag_offensive %}
+ <span id="question-offensive-flag-{{ question.id }}" class="offensive-flag"
+ title="{% trans "report as offensive (i.e containing spam, advertising, malicious text, etc.)" %}">
+ <a>{% trans "flag offensive" %}</a>
+ {% if request.user|can_view_offensive_flags and question.offensive_flag_count %}
+ <span class="darkred">({{ question.offensive_flag_count }})</span>
+ {% endif %}
+ </span>
+ {% endif %}
+ {% separator %}
+ {% if request.user|can_delete_post:question %}
+ <span class="action-link"><a id="question-delete-link-{{question.id}}">{% trans "delete" %}</a></span>
+ {% endif %}
+ {% endjoinitems %}
+ </div>
+ <div class="post-update-info-container">
+ {% post_contributor_info question "original_author" %}
+ {% post_contributor_info question "last_updater" %}
+ </div>
+ <div class="comments-container" id="comments-container-question-{{question.id}}">
+ {% for comment in question.get_comments|slice:":5" %}
+ <p class="comment" id="comment-{{comment.id}}">
+ {{comment.comment}}
+ - <a class="comment-user" href="{{comment.user.get_profile_url}}">{{comment.user}}</a>
+ {% spaceless %}
+ <span class="comment-age">({% diff_date comment.added_at %})</span>
+ {% if request.user|can_delete_comment:comment %}
+ <img class="delete-icon"
+ src="{% href "/content/images/close-small.png" %}"
+ title="{% trans "delete this comment" %}"/>
+ {% endif %}
+ {% endspaceless %}
+ </p>
+ {% endfor %}
+ </div>
+ <div class="post-comments" style="margin-bottom:20px">
+ <input id="can-post-comments-question-{{question.id}}" type="hidden" value="{{ request.user|can_add_comments:question }}"/>
+ {% if request.user|can_add_comments:question or question.comment_count > 5 %}
+ <a id="comments-link-question-{{question.id}}" class="comments-link">
+ {% if request.user|can_add_comments:question %}
+ {% trans "add comment" %}
+ {% endif %}
+ {% if question.comment_count > 5 %}
+ {% if request.user|can_add_comments:question %}/
+ {% blocktrans count question.get_comments|slice:"5:"|length as counter %}
+ see <strong>one</strong> more
+ {% plural %}
+ see <strong>{{counter}}</strong> more
+ {% endblocktrans %}
+ {% else %}
+ {% blocktrans count question.get_comments|slice:"5:"|length as counter %}
+ see <strong>one</strong> more comment
+ {% plural %}
+ see <strong>{{counter}}</strong> more comments
+ {% endblocktrans %}
+ {% endif %}
+ {% endif %}</a>
+ {% endif %}
+ </div>
+ </div>
+
+ </td>
+ </tr>
+ </table>
+ {% if question.closed %}
+ <div class="question-status" style="margin-bottom:15px">
+ <h3>{% blocktrans with question.get_close_reason_display as close_reason %}The question has been closed for the following reason "{{ close_reason }}" by{% endblocktrans %}
+ <a href="{{ question.closed_by.get_profile_url }}">{{ question.closed_by.username }}</a>
+ {% blocktrans with question.closed_at as closed_at %}close date {{closed_at}}{% endblocktrans %}</h3>
+ </div>
+ {% endif %}
+ {% if answers %}
+ <hr/>
+ <div class="tabBar">
+ <a name="sort-top"></a>
+ <div class="headQuestions">
+ {% blocktrans count answers|length as counter %}
+ One Answer:
+ {% plural %}
+ {{counter}} Answers:
+ {% endblocktrans %}
+ </div>
+ <div class="tabsA">
+ <a id="oldest" href="{% url question question.id %}?sort=oldest#sort-top"
+ title="{% trans "oldest answers will be shown first" %}">{% trans "oldest answers" %}</a>
+ <a id="latest" href="{% url question question.id %}?sort=latest#sort-top"
+ title="{% trans "newest answers will be shown first" %}">{% trans "newest answers" %}</a>
+ <a id="votes" href="{% url question question.id %}?sort=votes#sort-top"
+ title="{% trans "most voted answers will be shown first" %}">{% trans "popular answers" %}</a>
+ </div>
+ </div>
+ {% cnprog_paginator context %}
+
+ {% for answer in answers %}
+ <a name="{{ answer.id }}"></a>
+ <div id="answer-container-{{ answer.id }}" class="answer {% if answer.accepted %}accepted-answer{% endif %} {% ifequal answer.author_id question.author_id %} answered-by-owner{% endifequal %} {% if answer.deleted %}deleted{% endif %}">
+ <table style="width:100%;">
+ <tr>
+ <td style="width:30px;vertical-align:top">
+ <div class="vote-buttons">
+ <img id="answer-img-upvote-{{ answer.id }}" class="answer-img-upvote"
+ src="{% blockresource %}/content/images/vote-arrow-up{% get_user_vote_image user_answer_votes answer.id 1 %}.png{% endblockresource %}"
+ alt="{% trans "i like this answer (click again to cancel)" %}"
+ title="{% trans "i like this answer (click again to cancel)" %}"/>
+ <div id="answer-vote-number-{{ answer.id }}" class="vote-number" title="{% trans "current number of votes" %}">
+ {{ answer.score }}
+ </div>
+ <img id="answer-img-downvote-{{ answer.id }}" class="answer-img-downvote"
+ src="{% blockresource %}/content/images/vote-arrow-down{% get_user_vote_image user_answer_votes answer.id -1 %}.png{% endblockresource %}"
+ alt="{% trans "i dont like this answer (click again to cancel)" %}"
+ title="{% trans "i dont like this answer (click again to cancel)" %}" />
+
+ {% ifequal request.user question.author %}
+ <img id="answer-img-accept-{{ answer.id }}" class="answer-img-accept"
+ src="{% blockresource %}/content/images/vote-accepted{% if answer.accepted %}-on{% endif %}.png{% endblockresource %}"
+ alt="{% trans "mark this answer as favorite (click again to undo)" %}"
+ title="{% trans "mark this answer as favorite (click again to undo)" %}" />
+ {% else %}
+ {% if answer.accepted %}
+ <img id="answer-img-accept-{{ answer.id }}" class="answer-img-accept"
+ src="{% blockresource %}/content/images/vote-accepted{% if answer.accepted %}-on{% endif %}.png{% endblockresource %}"
+ alt="{% trans "the author of the question has selected this answer as correct" %}"
+ title="{% trans "the author of the question has selected this answer as correct" %}" />
+ {% endif %}
+ {% endifequal %}
+ </div>
+ </td>
+ <td>
+ <div class="item-right">
+ <div class="answer-body">
+ {{ answer.html|safe }}
+ </div>
+ <div class="answer-controls post-controls">
+ {% joinitems using '<span class="action-link-separator">|</span>' %}
+ <span class="linksopt">
+ <a href="#{{ answer.id }}" title="{% trans "answer permanent link" %}">
+ {% trans "permanent link" %}
+ </a>
+ </span>
+ {% separator %}
+ {% if request.user|can_edit_post:answer %}
+ <span class="action-link"><a href="{% url edit_answer answer.id %}">{% trans 'edit' %}</a></span>
+ {% endif %}
+ {% separator %}
+ {% if request.user|can_flag_offensive %}
+ <span id="answer-offensive-flag-{{ answer.id }}" class="offensive-flag"
+ title="{% trans "report as offensive (i.e containing spam, advertising, malicious text, etc.)" %}">
+ <a>{% trans "flag offensive" %}</a>
+ {% if request.user|can_view_offensive_flags and answer.offensive_flag_count %}
+ <span class="darkred">({{ answer.offensive_flag_count }})</span>
+ {% endif %}
+ </span>
+ {% endif %}
+ {% separator %}
+ {% if request.user|can_delete_post:answer %}
+ {% spaceless %}
+ <span class="action-link">
+ <a id="answer-delete-link-{{answer.id}}">
+ {% if answer.deleted %}{% trans "undelete" %}{% else %}{% trans "delete" %}{% endif %}</a>
+ </span>
+ {% endspaceless %}
+ {% endif %}
+ {% endjoinitems %}
+ </div>
+ <div class="post-update-info-container">
+ {% post_contributor_info answer "original_author" %}
+ {% post_contributor_info answer "last_updater" %}
+ </div>
+ <div class="comments-container" id="comments-container-answer-{{answer.id}}">
+ {% for comment in answer.get_comments|slice:":5" %}
+ <p id="comment-{{comment.id}}" class="comment">
+ {{comment.comment}}
+ - <a class="comment-user" href="{{comment.user.get_profile_url}}">{{comment.user}}</a>
+ {% spaceless %}
+ <span class="comment-age">({% diff_date comment.added_at %})</span>
+ {% if request.user|can_delete_comment:comment %}
+ <img class="delete-icon"
+ src="{% href "/content/images/close-small.png" %}"
+ title="{% trans "delete this comment" %}"/>
+ {% endif %}
+ {% endspaceless %}
+ </p>
+ {% endfor %}
+ </div>
+ <div class="post-comments" style="margin-bottom:20px">
+ <input id="can-post-comments-answer-{{answer.id}}" type="hidden" value="{{ request.user|can_add_comments:answer}}"/>
+ {% if request.user|can_add_comments:answer or answer.comment_count > 5 %}
+ <a id="comments-link-answer-{{answer.id}}" class="comments-link">
+ {% if request.user|can_add_comments:answer %}
+ {% trans "add comment" %}
+ {% endif %}
+ {% if answer.comment_count > 5 %}
+ {% if request.user|can_add_comments:answer %}/
+ {% blocktrans count answer.get_comments|slice:"5:"|length as counter %}
+ see <strong>one</strong> more
+ {% plural %}
+ see <strong>{{counter}}</strong> more
+ {% endblocktrans %}
+ {% else %}
+ {% blocktrans count answer.get_comments|slice:"5:"|length as counter %}
+ see <strong>one</strong> more comment
+ {% plural %}
+ see <strong>{{counter}}</strong> more comments
+ {% endblocktrans %}
+ {% endif %}
+ {% endif %}</a>
+ {% endif %}
+ </div>
+ </div>
+
+ </td>
+ </tr>
+ </table>
+ </div>
+ {% endfor %}
+ <div class="paginator-container-left">
+ {% cnprog_paginator context %}
+ </div>
+ {% endif %}
+ <form id="fmanswer" action="{% url answer question.id %}" method="post">
+ {% if request.user.is_authenticated %}
+ <p style="padding-left:3px">
+ {{ answer.email_notify }}
+ <label for="question-subscribe-updates">
+ {% ifequal request.user.get_q_sel_email_feed_frequency 'n' %}
+ {% trans "Notify me once a day when there are any new answers" %}
+ {% else %}
+ {% ifequal request.user.get_q_sel_email_feed_frequency 'd' %}
+ {% trans "Notify me once a day when there are any new answers" %}
+ {% else %}
+ {% ifequal request.user.get_q_sel_email_feed_frequency 'w' %}
+ {% trans "Notify me weekly when there are any new answers" %}
+ {% endifequal %}
+ {% endifequal %}
+ {% endifequal %}
+ </label>
+ {% blocktrans with request.user.get_profile_url as profile_url %}
+ You can always adjust frequency of email updates from your {{profile_url}}
+ {% endblocktrans %}
+ </p>
+ {% else %}
+ <p style="padding-left:3px">
+ <input class="nomargin" type="checkbox" disabled="disabled" />
+ <label>{% trans "once you sign in you will be able to subscribe for any updates here" %}</label>
+ </p>
+ {% endif %}
+ <div style="clear:both">
+ </div>
+
+ {% if not question.closed %}
+ <div style="padding:10px 0 0 0;">
+ {% spaceless %}
+ <div class="headNormal">
+ {% if answers %}
+ {% trans "Your answer" %}
+ {% else %}
+ {% trans "Be the first one to answer this question!" %}
+ {% endif %}
+ </div>
+ {% endspaceless %}
+ </div>
+ {% if not request.user.is_authenticated %}
+ <div class="message">{% trans "you can answer anonymously and then login" %}</div>
+ {% else %}
+ <p class="message">
+ {% ifequal request.user question.author %}
+ {% trans "answer your own question only to give an answer" %}
+ {% else %}
+ {% trans "please only give an answer, no discussions" %}
+ {% endifequal %}
+ </p>
+ {% endif %}
+
+ <div id="description" class="" >
+ <div id="wmd-button-bar" class="wmd-panel"></div>
+ {{ answer.text }}
+ <div class="preview-toggle">
+ <table width="100%">
+ <tr>
+ <td>
+ <span id="pre-collapse"
+ title="{% trans "Toggle the real time Markdown editor preview" %}">
+ {% trans "toggle preview" %}
+ </span>
+ </td>
+ {% if settings.WIKI_ON %}
+ <td style="text-align:right;">
+ {{ answer.wiki }}
+ <span style="font-weight:normal;cursor:help"
+ title="{{answer.wiki.help_text}}">
+ {{ answer.wiki.label_tag }}
+ </span>
+ </td>
+ {% endif %}
+ </tr>
+
+ </table>
+ </div>
+ <div id="previewer" class="wmd-preview"></div>
+ {{ answer.text.errors }}
+ </div>
+ <p><span class="form-error"></span></p>
+ <input type="submit"
+ {% if user.is_anonymous %}
+ value="{% trans "Login/Signup to Post Your Answer" %}"
+ {% else %}
+ {% if user == question.author %}
+ value="{% trans "Answer Your Own Question" %}"
+ {% else %}
+ value="{% trans "Answer the question" %}"
+ {% endif %}
+ {% endif %}
+ class="submit" style="float:left"/>
+ {% endif %}
+ </form>
+ </div>
+</div>
+{% endblock %}
+
+{% block sidebar %}
+<div class="boxC">
+ <p>
+ {% trans "Question tags" %}:
+ </p>
+ <p class="tags" >
+ {% for tag in tags %}
+ <a href="{% url forum.views.tag tag.name|urlencode %}"
+ title="{% trans "see questions tagged"%}'{{tag.name}}'{% trans "using tags" %}"
+ rel="tag">{{ tag.name }}</a> <span class="tag-number">&#215;{{ tag.used_count|intcomma }}</span><br/>
+ {% endfor %}
+ </p>
+ <p>
+ {% trans "question asked" %}: <strong title="{{ question.added_at }}">{% diff_date question.added_at %}</strong>
+ </p>
+ <p>
+ {% trans "question was seen" %}: <strong>{{ question.view_count|intcomma }} {% trans "times" %}</strong>
+ </p>
+ <p>
+ {% trans "last updated" %}: <strong title="{{ question.last_activity_at }}">{% diff_date question.last_activity_at %}</strong>
+ </p>
+</div>
+
+<div class="boxC">
+ <h3 class="subtitle">{% trans "Related questions" %}</h3>
+ <div class="questions-related">
+ {% for question in similar_questions %}
+ <p>
+ <a href="{{ question.get_absolute_url }}">{{ question.get_question_title }}</a>
+ </p>
+ {% endfor %}
+ </div>
+</div>
+
+{% endblock %}
+
+{% block endjs %}
+{% endblock %}
+<!-- end question.html -->