2011-04-05 05:36:42 +01:00
var QnA = {
// @fixme: Should use ID
2013-09-10 17:52:09 +01:00
close : function ( form , best ) {
2014-06-21 20:01:17 +01:00
var notice = $ ( form ) . closest ( 'li.h-entry.notice.question' ) ;
2011-04-18 10:27:56 +01:00
notice . find ( 'input#qna-best-answer,#qna-question-close' ) . hide ( ) ;
2011-04-12 10:22:47 +01:00
notice . find ( 'textarea' ) . hide ( ) ;
2011-04-18 10:27:56 +01:00
var list = notice . find ( 'ul' ) ;
notice . find ( 'ul > li.notice-answer-placeholder' ) . remove ( ) ;
notice . find ( 'ul > li.notice-answer' ) . remove ( ) ;
2011-04-18 23:31:48 +01:00
if ( best ) {
var p = notice . parent ( ) . find ( 'div.question-description > form > fieldset > p' ) ;
if ( p . length != 0 ) {
p . append ( $ ( '<span class="question-closed">This question is closed.</span>' ) ) ;
}
}
2011-04-05 05:36:42 +01:00
} ,
2013-09-10 17:52:09 +01:00
init : function ( ) {
2011-04-12 10:22:47 +01:00
QnA . NoticeInlineAnswerSetup ( ) ;
2013-09-10 17:52:09 +01:00
$ ( document ) . on ( 'submit' , 'form.form_question_show' , function ( ) {
2011-04-18 10:27:56 +01:00
QnA . close ( this ) ;
2011-04-05 05:36:42 +01:00
} ) ;
2013-09-10 17:52:09 +01:00
$ ( document ) . on ( 'submit' , 'form.form_answer_show' , function ( ) {
2011-04-18 23:31:48 +01:00
QnA . close ( this , true ) ;
2011-04-05 05:36:42 +01:00
} ) ;
2011-04-12 10:22:47 +01:00
} ,
/ * *
* Open up a question ' s inline answer box .
*
* @ param { jQuery } notice : jQuery object containing one notice
* /
2013-09-10 17:52:09 +01:00
NoticeInlineAnswerTrigger : function ( notice ) {
2011-04-16 03:50:05 +01:00
// Find the notice we're replying to...
2011-04-12 10:22:47 +01:00
var id = $ ( $ ( '.notice_id' , notice ) [ 0 ] ) . text ( ) ;
2011-04-16 03:50:05 +01:00
var parentNotice = notice ;
2011-04-12 10:22:47 +01:00
2011-04-16 03:50:05 +01:00
// Find the threaded replies view we'll be adding to...
var list = notice . closest ( '.notices' ) ;
if ( list . hasClass ( 'threaded-replies' ) ) {
2011-04-19 00:42:20 +01:00
2011-04-16 03:50:05 +01:00
// We're replying to a reply; use reply form on the end of this list.
// We'll add our form at the end of this; grab the root notice.
parentNotice = list . closest ( '.notice' ) ;
2011-04-19 00:42:20 +01:00
2011-04-12 10:22:47 +01:00
} else {
2011-04-19 00:42:20 +01:00
2011-04-16 03:50:05 +01:00
// We're replying to a parent notice; pull its threaded list
// and we'll add on the end of it. Will add if needed.
list = $ ( 'ul.threaded-replies' , notice ) ;
2011-04-12 10:22:47 +01:00
}
2011-04-19 00:42:20 +01:00
2011-04-18 10:27:56 +01:00
// See if the form's already open...
var answerForm = $ ( '.qna_answer_form' , list ) ;
2011-04-12 10:22:47 +01:00
2013-09-10 17:52:09 +01:00
var hideReplyPlaceholders = function ( notice ) {
2011-04-18 21:48:35 +01:00
// Do we still have a dummy answer placeholder? If so get rid of
// reply place holders for this question. If the current user hasn't
// answered the question we want to direct her to providing an
// answer. She can still reply by hitting the reply button if she
// really wants to.
var dummyAnswer = $ ( 'ul.qna-dummy' , notice ) ;
if ( dummyAnswer . length > 0 ) {
notice . find ( 'li.notice-reply-placeholder' ) . hide ( ) ;
}
}
2013-09-10 17:52:09 +01:00
var nextStep = function ( ) {
2011-04-18 21:48:35 +01:00
var dummyAnswer = $ ( 'ul.qna-dummy' , notice ) ;
dummyAnswer . hide ( ) ;
2011-04-18 10:27:56 +01:00
// Set focus...
2011-04-12 10:22:47 +01:00
var text = answerForm . find ( 'textarea' ) ;
if ( text . length == 0 ) {
throw "No textarea" ;
}
2011-04-18 10:27:56 +01:00
text . focus ( ) ;
2013-09-10 17:52:09 +01:00
$ ( 'body' ) . click ( function ( e ) {
2011-04-18 23:31:48 +01:00
var dummyAnswer = $ ( 'ul.qna-dummy' , notice ) ;
var style = dummyAnswer . attr ( 'style' ) ;
2014-06-21 20:01:17 +01:00
var ans = $ ( notice ) . find ( 'li.h-entry.notice.anwer' , notice )
2011-04-19 00:42:20 +01:00
if ( ans > 0 ) {
2011-04-18 23:31:48 +01:00
hideReplyPlaceholders ( notice ) ;
2011-04-19 00:42:20 +01:00
}
2011-04-18 10:27:56 +01:00
2011-04-12 10:22:47 +01:00
var openAnswers = $ ( 'li.notice-answer' ) ;
if ( openAnswers . length > 0 ) {
var target = $ ( e . target ) ;
2013-09-10 17:52:09 +01:00
openAnswers . each ( function ( ) {
2011-04-19 00:42:20 +01:00
2011-04-12 10:22:47 +01:00
// Did we click outside this one?
var answerItem = $ ( this ) ;
2011-04-18 10:27:56 +01:00
var parentNotice = answerItem . closest ( 'li.notice' ) ;
2011-04-19 00:42:20 +01:00
2011-04-12 10:22:47 +01:00
if ( answerItem . has ( e . target ) . length == 0 ) {
var textarea = answerItem . find ( '.notice_data-text:first' ) ;
var cur = $ . trim ( textarea . val ( ) ) ;
// Only close if there's been no edit.
if ( cur == '' || cur == textarea . data ( 'initialText' ) ) {
answerItem . remove ( ) ;
2011-04-18 21:48:35 +01:00
dummyAnswer . show ( ) ;
2011-04-12 10:22:47 +01:00
}
}
} ) ;
}
2011-04-18 10:27:56 +01:00
} ) ;
2011-04-12 10:22:47 +01:00
} ;
2011-04-16 03:50:05 +01:00
// See if the form's already open...
if ( answerForm . length > 0 ) {
2011-04-12 10:22:47 +01:00
nextStep ( ) ;
} else {
2011-04-18 10:27:56 +01:00
var placeholder = list . find ( 'li.qna-dummy-placeholder' ) . hide ( ) ;
2011-04-16 03:50:05 +01:00
// Create the answer form entry at the end
var answerItem = $ ( 'li.notice-answer' , list ) ;
if ( answerItem . length == 0 ) {
2011-04-12 10:22:47 +01:00
answerItem = $ ( '<li class="notice-answer"></li>' ) ;
2013-09-10 17:52:09 +01:00
var intermediateStep = function ( formMaster ) {
2011-04-19 00:42:20 +01:00
// @todo cache the form if we can (worth it?)
var formEl = document . _importNode ( formMaster , true ) ;
$ ( formEl ) . data ( 'NoticeFormSetup' , true ) ;
answerItem . append ( formEl ) ;
list . prepend ( answerItem ) ; // *before* the placeholder
var form = answerForm = $ ( formEl ) ;
QnA . AnswerFormSetup ( form ) ;
nextStep ( ) ;
} ;
if ( QnA . AnswerFormMaster ) {
// @todo if we had a cached for here's where we'd use it'
intermediateStep ( QnA . AnswerFormMaster ) ;
} else {
// Fetch a fresh copy of the answer form over AJAX.
// Warning: this can have a delay, which looks bad.
// @fixme this fallback may or may not work
var url = $ ( '#answer-action' ) . attr ( 'value' ) ;
2013-09-10 17:52:09 +01:00
$ . get ( url , { ajax : 1 } , function ( data , textStatus , xhr ) {
2011-04-12 10:22:47 +01:00
intermediateStep ( $ ( 'form' , data ) [ 0 ] ) ;
} ) ;
}
}
}
} ,
/ * *
* Setup function -- DOES NOT apply immediately .
*
* Sets up event handlers for inline reply mini - form placeholders .
* Uses 'live' rather than 'bind' , so applies to future as well as present items .
* /
2013-09-10 17:52:09 +01:00
NoticeInlineAnswerSetup : function ( ) {
2011-04-19 00:42:20 +01:00
2013-09-10 17:52:09 +01:00
$ ( document ) . on ( 'focus' ,
'li.qna-dummy-placeholder input.placeholder' ,
function ( ) {
2011-04-12 10:22:47 +01:00
var notice = $ ( this ) . closest ( 'li.notice' ) ;
QnA . NoticeInlineAnswerTrigger ( notice ) ;
return false ;
} ) ;
2011-04-19 00:42:20 +01:00
2011-04-15 23:07:17 +01:00
} ,
2013-09-10 17:52:09 +01:00
AnswerFormSetup : function ( form ) {
2011-04-19 00:42:20 +01:00
2011-04-18 21:48:35 +01:00
form . find ( 'textarea' ) . focus ( ) ;
2011-04-16 03:50:05 +01:00
2011-04-18 21:48:35 +01:00
if ( ! form . data ( 'NoticeFormSetup' ) ) {
alert ( 'gargargar' ) ;
}
2011-04-16 03:50:05 +01:00
2011-04-18 21:48:35 +01:00
if ( ! form . data ( 'AnswerFormSetup' ) ) {
//SN.U.NoticeLocationAttach(form);
QnA . FormAnswerXHR ( form ) ;
//SN.U.FormNoticeEnhancements(form);
//SN.U.NoticeDataAttach(form);
form . data ( 'NoticeFormSetup' , true ) ;
}
2011-04-18 10:27:56 +01:00
} ,
2011-04-15 23:07:17 +01:00
/ * *
* Setup function -- DOES NOT trigger actions immediately .
*
* Sets up event handlers for special - cased async submission of the
2011-04-18 21:48:35 +01:00
* answer - posting form , including some pre - post validation .
2011-04-15 23:07:17 +01:00
*
2011-04-18 21:48:35 +01:00
* @ fixme geodata
* @ fixme refactor and unify with FormNoticeXHR in util . js
2011-04-15 23:07:17 +01:00
*
* @ param { jQuery } form : jQuery object whose first element is a form
*
* @ access public
* /
2013-09-10 17:52:09 +01:00
FormAnswerXHR : function ( form ) {
2011-04-19 00:42:20 +01:00
2011-04-15 23:07:17 +01:00
//SN.C.I.NoticeDataGeo = {};
form . append ( '<input type="hidden" name="ajax" value="1"/>' ) ;
// Make sure we don't have a mixed HTTP/HTTPS submission...
form . attr ( 'action' , SN . U . RewriteAjaxAction ( form . attr ( 'action' ) ) ) ;
/ * *
* Show a response feedback bit under the new - notice dialog .
*
* @ param { String } cls : CSS class name to use ( 'error' or 'success' )
* @ param { String } text
* @ access private
* /
2013-09-10 17:52:09 +01:00
var showFeedback = function ( cls , text ) {
2011-04-15 23:07:17 +01:00
form . append (
$ ( '<p class="form_response"></p>' )
. addClass ( cls )
. text ( text )
) ;
} ;
/ * *
* Hide the previous response feedback , if any .
* /
2013-09-10 17:52:09 +01:00
var removeFeedback = function ( ) {
2011-04-15 23:07:17 +01:00
form . find ( '.form_response' ) . remove ( ) ;
} ;
form . ajaxForm ( {
dataType : 'xml' ,
timeout : '60000' ,
2011-04-18 21:48:35 +01:00
2013-09-10 17:52:09 +01:00
beforeSend : function ( formData ) {
2011-04-19 00:42:20 +01:00
2011-04-15 23:07:17 +01:00
if ( form . find ( '.notice_data-text:first' ) . val ( ) == '' ) {
form . addClass ( SN . C . S . Warning ) ;
return false ;
}
form
. addClass ( SN . C . S . Processing )
. find ( '.submit' )
. addClass ( SN . C . S . Disabled )
. attr ( SN . C . S . Disabled , SN . C . S . Disabled ) ;
return true ;
} ,
error : function ( xhr , textStatus , errorThrown ) {
form
. removeClass ( SN . C . S . Processing )
. find ( '.submit' )
. removeClass ( SN . C . S . Disabled )
. removeAttr ( SN . C . S . Disabled , SN . C . S . Disabled ) ;
removeFeedback ( ) ;
if ( textStatus == 'timeout' ) {
// @fixme i18n
showFeedback ( 'error' , 'Sorry! We had trouble sending your notice. The servers are overloaded. Please try again, and contact the site administrator if this problem persists.' ) ;
}
else {
var response = SN . U . GetResponseXML ( xhr ) ;
if ( $ ( '.' + SN . C . S . Error , response ) . length > 0 ) {
form . append ( document . _importNode ( $ ( '.' + SN . C . S . Error , response ) [ 0 ] , true ) ) ;
}
else {
if ( parseInt ( xhr . status ) === 0 || jQuery . inArray ( parseInt ( xhr . status ) , SN . C . I . HTTP20x30x ) >= 0 ) {
form
. resetForm ( )
. find ( '.attach-status' ) . remove ( ) ;
SN . U . FormNoticeEnhancements ( form ) ;
}
else {
// @fixme i18n
showFeedback ( 'error' , '(Sorry! We had trouble sending your notice (' + xhr . status + ' ' + xhr . statusText + '). Please report the problem to the site administrator if this happens again.' ) ;
}
}
}
} ,
2013-09-10 17:52:09 +01:00
success : function ( data , textStatus ) {
2011-04-19 00:42:20 +01:00
2011-04-15 23:07:17 +01:00
removeFeedback ( ) ;
var errorResult = $ ( '#' + SN . C . S . Error , data ) ;
if ( errorResult . length > 0 ) {
showFeedback ( 'error' , errorResult . text ( ) ) ;
}
else {
// New notice post was successful. If on our timeline, show it!
var notice = document . _importNode ( $ ( 'li' , data ) [ 0 ] , true ) ;
var notices = $ ( '#notices_primary .notices:first' ) ;
2011-04-18 21:48:35 +01:00
var answerItem = form . closest ( 'li.notice-answer' ) ;
2011-04-18 10:27:56 +01:00
var questionItem = form . closest ( 'li.question' ) ;
2011-04-18 21:48:35 +01:00
2011-04-19 00:42:20 +01:00
var dummyAnswer = form . find ( 'ul.qna-dummy' , questionItem ) . remove ( ) ;
2011-04-18 21:48:35 +01:00
if ( answerItem . length > 0 ) {
2011-04-18 10:27:56 +01:00
2011-04-19 00:42:20 +01:00
// If this is an inline answer, remove the form...
var list = form . closest ( '.threaded-replies' ) ;
// if the inserted notice's parent question needs it give it a placeholder
2014-06-21 20:01:17 +01:00
var ans = questionItem . find ( 'ul > li.h-entry.notice.answer' ) ;
2011-04-19 00:42:20 +01:00
if ( ans . length == 0 ) {
SN . U . NoticeInlineReplyPlaceholder ( questionItem ) ;
}
var id = $ ( notice ) . attr ( 'id' ) ;
if ( $ ( "#" + id ) . length == 0 ) {
$ ( notice ) . insertBefore ( answerItem ) ;
answerItem . remove ( ) ;
2011-04-15 23:07:17 +01:00
} else {
2011-04-19 00:42:20 +01:00
// NOP
2011-04-15 23:07:17 +01:00
// Realtime came through before us...
}
2011-04-19 00:42:20 +01:00
2011-04-15 23:07:17 +01:00
} else if ( notices . length > 0 && SN . U . belongsOnTimeline ( notice ) ) {
2011-04-19 00:42:20 +01:00
2011-04-16 03:50:05 +01:00
// Not a reply. If on our timeline, show it at the
2011-04-15 23:07:17 +01:00
if ( $ ( '#' + notice . id ) . length === 0 ) {
var notice _irt _value = form . find ( '#inreplyto' ) . val ( ) ;
var notice _irt = '#notices_primary #notice-' + notice _irt _value ;
if ( $ ( 'body' ) [ 0 ] . id == 'conversation' ) {
if ( notice _irt _value . length > 0 && $ ( notice _irt + ' .notices' ) . length < 1 ) {
$ ( notice _irt ) . append ( '<ul class="notices"></ul>' ) ;
}
$ ( $ ( notice _irt + ' .notices' ) [ 0 ] ) . append ( notice ) ;
}
else {
notices . prepend ( notice ) ;
}
$ ( '#' + notice . id )
. css ( { display : 'none' } )
. fadeIn ( 2500 ) ;
}
2011-04-16 03:50:05 +01:00
// realtime injected the notice first
2011-04-15 23:07:17 +01:00
} else {
// Not on a timeline that this belongs on?
// Just show a success message.
// @fixme inline
showFeedback ( 'success' , $ ( 'title' , data ) . text ( ) ) ;
}
}
} ,
2013-09-10 17:52:09 +01:00
complete : function ( xhr , textStatus ) {
2011-04-15 23:07:17 +01:00
form
. removeClass ( SN . C . S . Processing )
. find ( '.submit' )
. removeAttr ( SN . C . S . Disabled )
. removeClass ( SN . C . S . Disabled ) ;
}
} ) ;
2011-04-05 05:36:42 +01:00
}
} ;
2013-09-10 17:52:09 +01:00
$ ( document ) . ready ( function ( ) {
2011-04-05 05:36:42 +01:00
QnA . init ( ) ;
} ) ;