2011-04-05 13:36:42 +09:00
var QnA = {
// hide all the 'close' and 'best' buttons for this question
// @fixme: Should use ID
close : function ( closeButt ) {
2011-04-12 18:22:47 +09:00
notice = $ ( closeButt ) . closest ( 'li.hentry.notice.question' ) ;
notice . find ( 'input[name=best],[name=close]' ) . hide ( ) ;
notice . find ( 'textarea' ) . hide ( ) ;
notice . find ( 'li.notice-answer-placeholder' ) . hide ( ) ;
notice . find ( '#answer-form' ) . hide ( ) ;
2011-04-05 13:36:42 +09:00
} ,
init : function ( ) {
2011-04-12 18:22:47 +09:00
2011-04-05 13:36:42 +09:00
var that = this ;
2011-04-12 18:22:47 +09:00
QnA . NoticeInlineAnswerSetup ( ) ;
2011-04-05 13:36:42 +09:00
$ ( 'input[name=close]' ) . live ( 'click' , function ( ) {
that . close ( this ) ;
} ) ;
$ ( 'input[name=best]' ) . live ( 'click' , function ( ) {
that . close ( this ) ;
} ) ;
2011-04-12 18:22:47 +09:00
} ,
/ * *
* Open up a question ' s inline answer box .
*
* @ param { jQuery } notice : jQuery object containing one notice
* /
NoticeInlineAnswerTrigger : function ( notice ) {
2011-04-16 11:50:05 +09:00
// Find the notice we're replying to...
2011-04-12 18:22:47 +09:00
var id = $ ( $ ( '.notice_id' , notice ) [ 0 ] ) . text ( ) ;
2011-04-16 11:50:05 +09:00
console . log ( "NoticeInlineAnswerTrigger - replying to notice " + id ) ;
2011-04-12 18:22:47 +09:00
2011-04-16 11:50:05 +09:00
var parentNotice = notice ;
2011-04-12 18:22:47 +09:00
2011-04-16 11:50:05 +09:00
// Find the threaded replies view we'll be adding to...
var list = notice . closest ( '.notices' ) ;
if ( list . hasClass ( 'threaded-replies' ) ) {
console . log ( "NoticeInlineAnswerTrigger - there's already a threaded-replies ul above me" ) ;
// 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' ) ;
console . log ( "NoticeInlineAnswerTrigger - trying to find the closed .notice above me" ) ;
if ( parentNotice . length > 0 ) {
console . log ( "NoticeInlineAnswerTrigger - found that closest .notice" ) ;
}
2011-04-12 18:22:47 +09:00
} else {
2011-04-16 11:50:05 +09:00
console . log ( "NoticeInlineAnswerTrigger - this notice does not have a threaded-reples ul" ) ;
// 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 ) ;
console . log ( 'NoticeInlineAnswerTrigger - looking for threaded-replies ul on the parent notice (on the passed in notice)' ) ;
if ( list . length == 0 ) {
console . log ( "NoticeInlineAnswerTrigger - there is no threaded-replies ul on the parent notice" ) ;
console . log ( "NoticeInlineAnswerTrigger - calling NoticeInlineAnswerPlaceholder(notice)" ) ;
QnA . NoticeInlineAnswerPlaceholder ( notice ) ;
console . log ( "NoticeInlineAnswerTrigger - checking once again for a ul.threaded-replies on the notice" ) ;
list = $ ( 'ul.threaded-replies' , notice ) ;
}
2011-04-12 18:22:47 +09:00
}
var nextStep = function ( ) {
2011-04-16 11:50:05 +09:00
console . log ( "NoticeInlineAnswerTrigger (nextStep) - begin" ) ;
2011-04-12 18:22:47 +09:00
// Set focus...
var text = answerForm . find ( 'textarea' ) ;
if ( text . length == 0 ) {
throw "No textarea" ;
}
2011-04-16 11:50:05 +09:00
console . log ( "NoticeInlineAnswerTrigger (nextStep) - setting up body click handler to hide open form when clicking away" ) ;
2011-04-12 18:22:47 +09:00
$ ( 'body' ) . click ( function ( e ) {
2011-04-16 11:50:05 +09:00
console . log ( "body click handler - got click" ) ;
2011-04-12 18:22:47 +09:00
var openAnswers = $ ( 'li.notice-answer' ) ;
if ( openAnswers . length > 0 ) {
2011-04-16 11:50:05 +09:00
console . log ( "body click handler - Found one or more open answer forms to close" ) ;
2011-04-12 18:22:47 +09:00
var target = $ ( e . target ) ;
openAnswers . each ( function ( ) {
2011-04-16 11:50:05 +09:00
console . log ( "body click handler - found an open answer form" ) ;
2011-04-12 18:22:47 +09:00
// Did we click outside this one?
var answerItem = $ ( this ) ;
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' ) ) {
2011-04-16 11:50:05 +09:00
console . log ( "body click handler - no text in answer form, closing it" ) ;
2011-04-12 18:22:47 +09:00
var parentNotice = answerItem . closest ( 'li.notice' ) ;
answerItem . remove ( ) ;
2011-04-16 11:50:05 +09:00
console . log ( "body click handler - showing answer placeholder" ) ;
2011-04-12 18:22:47 +09:00
parentNotice . find ( 'li.notice-answer-placeholder' ) . show ( ) ;
2011-04-16 11:50:05 +09:00
} else {
console . log ( "body click handler - there is text in the answer form, wont close it" ) ;
2011-04-12 18:22:47 +09:00
}
}
} ) ;
}
} ) ;
text . focus ( ) ;
2011-04-16 11:50:05 +09:00
console . log ( 'body click handler - exit' ) ;
2011-04-12 18:22:47 +09:00
} ;
2011-04-16 11:50:05 +09:00
// See if the form's already open...
var answerForm = $ ( '.notice-answer-form' , list ) ;
if ( answerForm . length > 0 ) {
console . log ( "NoticeInlineAnswerTrigger - found an open .notice-answer-form - doing nextStep()" ) ;
2011-04-12 18:22:47 +09:00
nextStep ( ) ;
} else {
2011-04-16 11:50:05 +09:00
console . log ( "NoticeInlineAnswerTrigger - hiding the answer placeholder" ) ;
var placeholder = list . find ( 'li.notice-answer-placeholder' ) . hide ( ) ;
// Create the answer form entry at the end
2011-04-12 18:22:47 +09:00
2011-04-16 11:50:05 +09:00
var answerItem = $ ( 'li.notice-answer' , list ) ;
if ( answerItem . length > 0 ) {
console . log ( "NoticeInlineAnswerTrigger - Found answer item (notice-answer li)" ) ;
}
if ( answerItem . length == 0 ) {
console . log ( "NoticeInlineAnswerTrigger - no answer item (notice-answer li)" ) ;
2011-04-12 18:22:47 +09:00
answerItem = $ ( '<li class="notice-answer"></li>' ) ;
var intermediateStep = function ( formMaster ) {
2011-04-16 11:50:05 +09:00
console . log ( "NoticeInlineAnswerTrigger - (intermediate) step begin" ) ;
2011-04-12 18:22:47 +09:00
var formEl = document . _importNode ( formMaster , true ) ;
2011-04-16 11:50:05 +09:00
console . log ( "NoticeInlineAnswerTrigger - (intermediate step) appending answer form to answer item" ) ;
2011-04-12 18:22:47 +09:00
answerItem . append ( formEl ) ;
2011-04-16 11:50:05 +09:00
console . log ( "NoticeInlineAnswerTrigger - (intermediate step) appending answer to replies list, after placeholder" ) ;
2011-04-12 18:22:47 +09:00
list . append ( answerItem ) ; // *after* the placeholder
var form = answerForm = $ ( formEl ) ;
2011-04-16 11:50:05 +09:00
console . log ( "NoticeInlineAnswerTrigger - (intermediate step) calling QnA.AnswerFormSetup on the form" )
2011-04-12 18:22:47 +09:00
QnA . AnswerFormSetup ( form ) ;
2011-04-16 11:50:05 +09:00
console . log ( "NoticeInlineAnswerTrigger - (intermediate step) calling nextstep()" ) ;
2011-04-12 18:22:47 +09:00
nextStep ( ) ;
} ;
if ( QnA . AnswerFormMaster ) {
2011-04-16 11:50:05 +09:00
console . log ( "NoticeInlineAnswerTrigger - found a cached copy of the answer form" ) ;
2011-04-12 18:22:47 +09:00
// We've already saved a master copy of the form.
// Clone it in!
2011-04-16 11:50:05 +09:00
console . log ( "NoticeInlineAnswerTrigger - calling intermediateStep with cached form" ) ;
2011-04-12 18:22:47 +09:00
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' ) ;
2011-04-16 11:50:05 +09:00
console . log ( "NoticeInlineAnswerTrigger - fetching new form via HXR" ) ;
2011-04-12 18:22:47 +09:00
$ . get ( url , { ajax : 1 } , function ( data , textStatus , xhr ) {
2011-04-16 11:50:05 +09:00
console . log ( "NoticeInlineAnswerTrigger - got a new form via HXR, calling intermediateStep" ) ;
2011-04-12 18:22:47 +09:00
intermediateStep ( $ ( 'form' , data ) [ 0 ] ) ;
} ) ;
}
}
}
console . log ( 'NoticeInlineAnswerTrigger - exit' ) ;
} ,
/ * *
* 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 .
* /
NoticeInlineAnswerSetup : function ( ) {
console . log ( "NoticeInlineAnswerSetup - begin" ) ;
$ ( 'li.notice-answer-placeholder input.placeholder' )
. live ( 'focus' , function ( ) {
var notice = $ ( this ) . closest ( 'li.notice' ) ;
QnA . NoticeInlineAnswerTrigger ( notice ) ;
return false ;
} ) ;
console . log ( "NoticeInlineAnswerSetup - exit" ) ;
2011-04-16 07:07:17 +09:00
} ,
AnswerFormSetup : function ( form ) {
console . log ( "AnswerFormSetup" ) ;
$ ( 'input[type=submit]' ) . live ( 'click' , function ( ) {
console . log ( "AnswerFormSetup click" ) ;
QnA . FormAnswerXHR ( form ) ;
} ) ;
} ,
2011-04-16 11:50:05 +09:00
NoticeInlineAnswerPlaceholder : function ( notice ) {
console . log ( "NoticeInlineAnswerPlaceholder - begin" )
var list = notice . find ( 'ul.threaded-replies' ) ;
if ( list . length == 0 ) {
list = $ ( '<ul class="notices threaded-replies xoxo"></ul>' ) ;
notice . append ( list ) ;
list = notice . find ( 'ul.threaded-replies' ) ;
}
var placeholder = $ ( '<li class="notice-answer-placeholder">' +
'<input class="placeholder">' +
'</li>' ) ;
placeholder . find ( 'input' )
. val ( SN . msg ( 'reply_placeholder' ) ) ;
list . append ( placeholder ) ;
console . log ( "NoticeInlineAnswerPlaceholder - exit" ) ;
} ,
2011-04-16 07:07:17 +09:00
/ * *
* Setup function -- DOES NOT trigger actions immediately .
*
* Sets up event handlers for special - cased async submission of the
* notice - posting form , including some pre - post validation .
*
* Unlike FormXHR ( ) this does NOT submit the form immediately !
* It sets up event handlers so that any method of submitting the
* form ( click on submit button , enter , submit ( ) etc ) will trigger
* it properly .
*
* Also unlike FormXHR ( ) , this system will use a hidden iframe
* automatically to handle file uploads via < input type = "file" >
* controls .
*
* @ fixme tl ; dr
* @ fixme vast swaths of duplicate code and really long variable names clutter this function up real bad
* @ fixme error handling is unreliable
* @ fixme cookieValue is a global variable , but probably shouldn ' t be
* @ fixme saving the location cache cookies should be split out
* @ fixme some error messages are hardcoded english : needs i18n
* @ fixme special - case for bookmarklet is confusing and uses a global var "self" . Is this ok ?
*
* @ param { jQuery } form : jQuery object whose first element is a form
*
* @ access public
* /
FormAnswerXHR : function ( form ) {
console . log ( "FormAanwerXHR - begin" ) ;
//SN.C.I.NoticeDataGeo = {};
form . append ( '<input type="hidden" name="ajax" value="1"/>' ) ;
2011-04-16 11:50:05 +09:00
console . log ( "FormAnswerXHR - appended ajax flag to form" ) ;
2011-04-16 07:07:17 +09:00
// Make sure we don't have a mixed HTTP/HTTPS submission...
form . attr ( 'action' , SN . U . RewriteAjaxAction ( form . attr ( 'action' ) ) ) ;
2011-04-16 11:50:05 +09:00
console . log ( "FormAnswerXHR rewrote action so we don't have a mixed HTTP/HTTPS submission" ) ;
2011-04-16 07:07:17 +09:00
/ * *
* 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
* /
var showFeedback = function ( cls , text ) {
form . append (
$ ( '<p class="form_response"></p>' )
. addClass ( cls )
. text ( text )
) ;
} ;
/ * *
* Hide the previous response feedback , if any .
* /
var removeFeedback = function ( ) {
form . find ( '.form_response' ) . remove ( ) ;
} ;
2011-04-16 11:50:05 +09:00
console . log ( "FormAnswerXHR - doing ajaxForm call" ) ;
2011-04-16 07:07:17 +09:00
form . ajaxForm ( {
dataType : 'xml' ,
timeout : '60000' ,
beforeSend : function ( formData ) {
2011-04-16 11:50:05 +09:00
console . log ( "FormAnswerXHR - beforeSend" ) ;
2011-04-16 07:07:17 +09: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 ) ;
SN . U . normalizeGeoData ( form ) ;
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.' ) ;
}
}
}
} ,
success : function ( data , textStatus ) {
2011-04-16 11:50:05 +09:00
console . log ( "FormAnswerHXR - success" ) ;
2011-04-16 07:07:17 +09: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 ) ;
2011-04-16 11:50:05 +09:00
console . log ( "FormAnswerXHR - loaded the notice, now trying to insert it somewhere" ) ;
2011-04-16 07:07:17 +09:00
var notices = $ ( '#notices_primary .notices:first' ) ;
2011-04-16 11:50:05 +09:00
console . log ( "FormAnswerXHR - looking for the closest notice with a notice-reply class" ) ;
var replyItem = form . closest ( 'li.notice-answer, .notice-reply' ) ;
2011-04-16 07:07:17 +09:00
if ( replyItem . length > 0 ) {
2011-04-16 11:50:05 +09:00
console . log ( "FormAnswerXHR - I found a reply li to append to" ) ;
2011-04-16 07:07:17 +09:00
// If this is an inline reply, remove the form...
2011-04-16 11:50:05 +09:00
console . log ( "FormAnswerXHR - looking for the closest .threaded-replies ul" )
2011-04-16 07:07:17 +09:00
var list = form . closest ( '.threaded-replies' ) ;
2011-04-16 11:50:05 +09:00
console . log ( "FormAnswerXHR - search list for the answer placeholder" )
2011-04-16 07:07:17 +09:00
var placeholder = list . find ( '.notice-answer-placeholder' ) ;
2011-04-16 11:50:05 +09:00
console . log ( "FormAnswerXHR - removing reply item" ) ;
2011-04-16 07:07:17 +09:00
replyItem . remove ( ) ;
var id = $ ( notice ) . attr ( 'id' ) ;
2011-04-16 11:50:05 +09:00
console . log ( "FormAnswerXHR - the new notice id is: " + id ) ;
2011-04-16 07:07:17 +09:00
if ( $ ( "#" + id ) . length == 0 ) {
2011-04-16 11:50:05 +09:00
console . log ( "FormAnswerXHR - the notice is not there already so realtime hasn't inserted it before us" ) ;
console . log ( "FormAnswerXHR - inserting new notice before placeholder" ) ;
$ ( placeholder ) . removeClass ( 'notice-answer-placeholder' ) . addClass ( 'notice-reply-placeholder' ) ;
2011-04-16 07:07:17 +09:00
$ ( notice ) . insertBefore ( placeholder ) ;
2011-04-16 11:50:05 +09:00
placeholder . show ( ) ;
2011-04-16 07:07:17 +09:00
} else {
// Realtime came through before us...
}
2011-04-16 11:50:05 +09:00
2011-04-16 07:07:17 +09:00
} else if ( notices . length > 0 && SN . U . belongsOnTimeline ( notice ) ) {
2011-04-16 11:50:05 +09:00
console . log ( 'FormAnswerXHR - there is at least one notice on the timeline and the new notice should be added to the list' ) ;
// Not a reply. If on our timeline, show it at the
2011-04-16 07:07:17 +09:00
if ( $ ( '#' + notice . id ) . length === 0 ) {
2011-04-16 11:50:05 +09:00
console . log ( "FormAnswerXHR - The notice is not yet on the timeline." )
2011-04-16 07:07:17 +09:00
var notice _irt _value = form . find ( '#inreplyto' ) . val ( ) ;
2011-04-16 11:50:05 +09:00
console . log ( "FormAnswerXHR - getting value from #inreplyto inside the form: " + notice _irt _value ) ;
2011-04-16 07:07:17 +09:00
var notice _irt = '#notices_primary #notice-' + notice _irt _value ;
2011-04-16 11:50:05 +09:00
console . log ( "notice_irt selector = " + notice _irt _value ) ;
2011-04-16 07:07:17 +09:00
if ( $ ( 'body' ) [ 0 ] . id == 'conversation' ) {
2011-04-16 11:50:05 +09:00
console . log ( "FormAnswerXHR - we're on a conversation page" ) ;
2011-04-16 07:07:17 +09:00
if ( notice _irt _value . length > 0 && $ ( notice _irt + ' .notices' ) . length < 1 ) {
$ ( notice _irt ) . append ( '<ul class="notices"></ul>' ) ;
}
2011-04-16 11:50:05 +09:00
console . log ( "FormAnswerXHR - appending notice after notice_irt selector" ) ;
2011-04-16 07:07:17 +09:00
$ ( $ ( notice _irt + ' .notices' ) [ 0 ] ) . append ( notice ) ;
}
else {
2011-04-16 11:50:05 +09:00
console . log ( "FormAnswerXHR prepending notice to top of the notice list" ) ;
2011-04-16 07:07:17 +09:00
notices . prepend ( notice ) ;
}
$ ( '#' + notice . id )
. css ( { display : 'none' } )
. fadeIn ( 2500 ) ;
}
2011-04-16 11:50:05 +09:00
// realtime injected the notice first
2011-04-16 07:07:17 +09:00
} else {
// Not on a timeline that this belongs on?
// Just show a success message.
// @fixme inline
showFeedback ( 'success' , $ ( 'title' , data ) . text ( ) ) ;
}
//form.resetForm();
//SN.U.FormNoticeEnhancements(form);
}
} ,
complete : function ( xhr , textStatus ) {
form
. removeClass ( SN . C . S . Processing )
. find ( '.submit' )
. removeAttr ( SN . C . S . Disabled )
. removeClass ( SN . C . S . Disabled ) ;
form . find ( '[name=lat]' ) . val ( SN . C . I . NoticeDataGeo . NLat ) ;
form . find ( '[name=lon]' ) . val ( SN . C . I . NoticeDataGeo . NLon ) ;
form . find ( '[name=location_ns]' ) . val ( SN . C . I . NoticeDataGeo . NLNS ) ;
form . find ( '[name=location_id]' ) . val ( SN . C . I . NoticeDataGeo . NLID ) ;
form . find ( '[name=notice_data-geo]' ) . attr ( 'checked' , SN . C . I . NoticeDataGeo . NDG ) ;
}
} ) ;
2011-04-05 13:36:42 +09:00
}
2011-04-12 18:22:47 +09:00
2011-04-05 13:36:42 +09:00
} ;
$ ( document ) . ready ( function ( ) {
QnA . init ( ) ;
} ) ;