4 // hide all the 'close' and 'best' buttons for this question
6 // @fixme: Should use ID
7 close: function(closeButt) {
8 notice = $(closeButt).closest('li.hentry.notice.question');
9 notice.find('input[name=best],[name=close]').hide();
10 notice.find('textarea').hide();
11 notice.find('li.notice-answer-placeholder').hide();
12 notice.find('#answer-form').hide();
19 QnA.NoticeInlineAnswerSetup();
21 $('input[name=close]').live('click', function() {
24 $('input[name=best]').live('click', function() {
30 * Open up a question's inline answer box.
32 * @param {jQuery} notice: jQuery object containing one notice
34 NoticeInlineAnswerTrigger: function(notice) {
35 console.log('NoticeInlineAnswerTrigger - begin');
37 // Find the question notice we're answering...
38 var id = $($('.notice_id', notice)[0]).text();
39 console.log("parent notice id = " + id);
40 var parentNotice = notice;
42 // See if the form's already there...
43 var answerForm = $('#answer-form', parentNotice);
46 console.log("Found the answer form.");
48 console.log("Did not find the answer form.");
51 var placeholder = parentNotice.find('li.notice-answer-placeholder');
53 // Pull the parents threaded list and we'll add on the end of it.
54 var list = $('ul.threaded-replies', notice);
57 console.log("Found the " + list.length + " notice place holders.");
59 console.log("Found the notice answer placeholder");
62 if (list.length == 0) {
63 console.log("list length = 0 adding <ul>");
64 list = $('<ul class="notices threaded-replies xoxo"></ul>');
66 } else if (list.length == 2) {
67 // remove duplicate ul added by util.js
71 var answerItem = $('li.notice-answer', list);
73 var nextStep = function() {
74 console.log("nextStep - enter");
77 var text = answerForm.find('textarea');
79 if (text.length == 0) {
83 $('body').click(function(e) {
84 console.log("got click");
86 var openAnswers = $('li.notice-answer');
87 if (openAnswers.length > 0) {
88 console.log("Found and open answer to close");
89 var target = $(e.target);
90 openAnswers.each(function() {
91 console.log("found an open answer");
92 // Did we click outside this one?
93 var answerItem = $(this);
94 if (answerItem.has(e.target).length == 0) {
95 var textarea = answerItem.find('.notice_data-text:first');
96 var cur = $.trim(textarea.val());
97 // Only close if there's been no edit.
98 if (cur == '' || cur == textarea.data('initialText')) {
99 var parentNotice = answerItem.closest('li.notice');
101 parentNotice.find('li.notice-answer-placeholder').show();
109 console.log('finished dealing with body click');
114 if (answerItem.length > 0) {
115 console.log('answerItem length > 0');
116 // Update the existing form...
120 // Create the answer form entry at the end
122 if (answerItem.length == 0) {
123 console.log("QQQQQ no notice-answer li");
124 answerItem = $('<li class="notice-answer"></li>');
126 var intermediateStep = function(formMaster) {
127 console.log("Intermediate step");
128 var formEl = document._importNode(formMaster, true);
129 answerItem.append(formEl);
130 console.log("appending answerItem");
131 list.append(answerItem); // *after* the placeholder
132 console.log("appended answerItem");
133 console.log(answerItem);
134 var form = answerForm = $(formEl);
135 QnA.AnswerFormSetup(form);
140 if (QnA.AnswerFormMaster) {
141 // We've already saved a master copy of the form.
143 intermediateStep(QnA.AnswerFormMaster);
145 // Fetch a fresh copy of the answer form over AJAX.
146 // Warning: this can have a delay, which looks bad.
147 // @fixme this fallback may or may not work
148 var url = $('#answer-action').attr('value');
150 console.log("fetching new form via HXR");
152 $.get(url, {ajax: 1}, function(data, textStatus, xhr) {
153 intermediateStep($('form', data)[0]);
158 console.log('NoticeInlineAnswerTrigger - exit');
163 * Setup function -- DOES NOT apply immediately.
165 * Sets up event handlers for inline reply mini-form placeholders.
166 * Uses 'live' rather than 'bind', so applies to future as well as present items.
168 NoticeInlineAnswerSetup: function() {
169 console.log("NoticeInlineAnswerSetup - begin");
170 $('li.notice-answer-placeholder input.placeholder')
171 .live('focus', function() {
172 var notice = $(this).closest('li.notice');
173 QnA.NoticeInlineAnswerTrigger(notice);
176 console.log("NoticeInlineAnswerSetup - exit");
179 AnswerFormSetup: function(form) {
180 console.log("AnswerFormSetup");
181 $('input[type=submit]').live('click', function() {
182 console.log("AnswerFormSetup click");
183 QnA.FormAnswerXHR(form);
189 * Setup function -- DOES NOT trigger actions immediately.
191 * Sets up event handlers for special-cased async submission of the
192 * notice-posting form, including some pre-post validation.
194 * Unlike FormXHR() this does NOT submit the form immediately!
195 * It sets up event handlers so that any method of submitting the
196 * form (click on submit button, enter, submit() etc) will trigger
199 * Also unlike FormXHR(), this system will use a hidden iframe
200 * automatically to handle file uploads via <input type="file">
204 * @fixme vast swaths of duplicate code and really long variable names clutter this function up real bad
205 * @fixme error handling is unreliable
206 * @fixme cookieValue is a global variable, but probably shouldn't be
207 * @fixme saving the location cache cookies should be split out
208 * @fixme some error messages are hardcoded english: needs i18n
209 * @fixme special-case for bookmarklet is confusing and uses a global var "self". Is this ok?
211 * @param {jQuery} form: jQuery object whose first element is a form
215 FormAnswerXHR: function(form) {
216 console.log("FormAanwerXHR - begin");
217 //SN.C.I.NoticeDataGeo = {};
218 form.append('<input type="hidden" name="ajax" value="1"/>');
219 console.log("appended ajax flag");
221 // Make sure we don't have a mixed HTTP/HTTPS submission...
222 form.attr('action', SN.U.RewriteAjaxAction(form.attr('action')));
223 console.log("rewrote action");
226 * Show a response feedback bit under the new-notice dialog.
228 * @param {String} cls: CSS class name to use ('error' or 'success')
229 * @param {String} text
232 var showFeedback = function(cls, text) {
234 $('<p class="form_response"></p>')
241 * Hide the previous response feedback, if any.
243 var removeFeedback = function() {
244 form.find('.form_response').remove();
247 console.log("doing ajax");
252 beforeSend: function(formData) {
253 console.log("beforeSend");
254 if (form.find('.notice_data-text:first').val() == '') {
255 form.addClass(SN.C.S.Warning);
259 .addClass(SN.C.S.Processing)
261 .addClass(SN.C.S.Disabled)
262 .attr(SN.C.S.Disabled, SN.C.S.Disabled);
264 SN.U.normalizeGeoData(form);
268 error: function (xhr, textStatus, errorThrown) {
270 .removeClass(SN.C.S.Processing)
272 .removeClass(SN.C.S.Disabled)
273 .removeAttr(SN.C.S.Disabled, SN.C.S.Disabled);
275 if (textStatus == 'timeout') {
277 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.');
280 var response = SN.U.GetResponseXML(xhr);
281 if ($('.'+SN.C.S.Error, response).length > 0) {
282 form.append(document._importNode($('.'+SN.C.S.Error, response)[0], true));
285 if (parseInt(xhr.status) === 0 || jQuery.inArray(parseInt(xhr.status), SN.C.I.HTTP20x30x) >= 0) {
288 .find('.attach-status').remove();
289 SN.U.FormNoticeEnhancements(form);
293 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.');
298 success: function(data, textStatus) {
299 console.log("FormAnswerHXR success");
301 var errorResult = $('#'+SN.C.S.Error, data);
302 if (errorResult.length > 0) {
303 showFeedback('error', errorResult.text());
307 // New notice post was successful. If on our timeline, show it!
308 var notice = document._importNode($('li', data)[0], true);
310 var notices = $('#notices_primary .notices:first');
311 var replyItem = form.closest('li.notice-reply');
313 if (replyItem.length > 0) {
314 console.log("I found a reply li to append to");
315 // If this is an inline reply, remove the form...
316 var list = form.closest('.threaded-replies');
317 var placeholder = list.find('.notice-answer-placeholder');
320 var id = $(notice).attr('id');
321 console.log("got notice id " + id);
322 if ($("#"+id).length == 0) {
323 console.log("inserting before placeholder");
324 $(notice).insertBefore(placeholder);
326 // Realtime came through before us...
329 // ...and show the placeholder form.
331 console.log('qqqq made it this far')
332 } else if (notices.length > 0 && SN.U.belongsOnTimeline(notice)) {
333 // Not a reply. If on our timeline, show it at the top!
334 if ($('#'+notice.id).length === 0) {
335 console.log("couldn't find a notice id for " + notice.id);
336 var notice_irt_value = form.find('#inreplyto').val();
337 var notice_irt = '#notices_primary #notice-'+notice_irt_value;
338 console.log("notice_irt value = " + notice_irt_value);
339 if($('body')[0].id == 'conversation') {
340 console.log("found conversation");
341 if(notice_irt_value.length > 0 && $(notice_irt+' .notices').length < 1) {
342 $(notice_irt).append('<ul class="notices"></ul>');
344 $($(notice_irt+' .notices')[0]).append(notice);
347 console.log("prepending notice")
348 notices.prepend(notice);
351 .css({display:'none'})
355 // Not on a timeline that this belongs on?
356 // Just show a success message.
358 showFeedback('success', $('title', data).text());
362 //SN.U.FormNoticeEnhancements(form);
365 complete: function(xhr, textStatus) {
367 .removeClass(SN.C.S.Processing)
369 .removeAttr(SN.C.S.Disabled)
370 .removeClass(SN.C.S.Disabled);
372 form.find('[name=lat]').val(SN.C.I.NoticeDataGeo.NLat);
373 form.find('[name=lon]').val(SN.C.I.NoticeDataGeo.NLon);
374 form.find('[name=location_ns]').val(SN.C.I.NoticeDataGeo.NLNS);
375 form.find('[name=location_id]').val(SN.C.I.NoticeDataGeo.NLID);
376 form.find('[name=notice_data-geo]').attr('checked', SN.C.I.NoticeDataGeo.NDG);
383 $(document).ready(function() {