1/* 2 Question2Answer by Gideon Greenspan and contributors 3 http://www.question2answer.org/ 4 5 Description: Common Javascript for Q2A pages including posting and AJAX 6 7 This program is free software; you can redistribute it and/or 8 modify it under the terms of the GNU General Public License 9 as published by the Free Software Foundation; either version 2 10 of the License, or (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 More about this license: http://www.question2answer.org/license.php 18*/ 19 20// General page functions 21 22function qa_reveal(elem, type, callback) 23{ 24 if (elem) 25 $(elem).slideDown(400, callback); 26} 27 28function qa_conceal(elem, type, callback) 29{ 30 if (elem) 31 $(elem).slideUp(400); 32} 33 34function qa_set_inner_html(elem, type, html) 35{ 36 if (elem) 37 elem.innerHTML = html; 38} 39 40function qa_set_outer_html(elem, type, html) 41{ 42 if (elem) { 43 var e = document.createElement('div'); 44 e.innerHTML = html; 45 elem.parentNode.replaceChild(e.firstChild, elem); 46 } 47} 48 49function qa_show_waiting_after(elem, inside) 50{ 51 if (elem && !elem.qa_waiting_shown) { 52 var w = document.getElementById('qa-waiting-template'); 53 54 if (w) { 55 var c = w.cloneNode(true); 56 c.id = null; 57 58 if (inside) 59 elem.insertBefore(c, null); 60 else 61 elem.parentNode.insertBefore(c, elem.nextSibling); 62 63 elem.qa_waiting_shown = c; 64 } 65 } 66} 67 68function qa_hide_waiting(elem) 69{ 70 var c = elem.qa_waiting_shown; 71 72 if (c) { 73 c.parentNode.removeChild(c); 74 elem.qa_waiting_shown = null; 75 } 76} 77 78function qa_vote_click(elem) 79{ 80 var ens = elem.name.split('_'); 81 var postid = ens[1]; 82 var vote = parseInt(ens[2]); 83 var code = elem.form.elements.code.value; 84 var anchor = ens[3]; 85 86 qa_ajax_post('vote', {postid: postid, vote: vote, code: code}, 87 function(lines) { 88 if (lines[0] == '1') { 89 qa_set_inner_html(document.getElementById('voting_' + postid), 'voting', lines.slice(1).join("\n")); 90 91 } else if (lines[0] == '0') { 92 var mess = document.getElementById('errorbox'); 93 94 if (!mess) { 95 mess = document.createElement('div'); 96 mess.id = 'errorbox'; 97 mess.className = 'qa-error'; 98 mess.innerHTML = lines[1]; 99 mess.style.display = 'none'; 100 } 101 102 var postelem = document.getElementById(anchor); 103 var e = postelem.parentNode.insertBefore(mess, postelem); 104 qa_reveal(e); 105 106 } else 107 qa_ajax_error(); 108 } 109 ); 110 111 return false; 112} 113 114function qa_notice_click(elem) 115{ 116 var ens = elem.name.split('_'); 117 var code = elem.form.elements.code.value; 118 119 qa_ajax_post('notice', {noticeid: ens[1], code: code}, 120 function(lines) { 121 if (lines[0] == '1') 122 qa_conceal(document.getElementById('notice_' + ens[1]), 'notice'); 123 else if (lines[0] == '0') 124 alert(lines[1]); 125 else 126 qa_ajax_error(); 127 } 128 ); 129 130 return false; 131} 132 133function qa_favorite_click(elem) 134{ 135 var ens = elem.name.split('_'); 136 var code = elem.form.elements.code.value; 137 138 qa_ajax_post('favorite', {entitytype: ens[1], entityid: ens[2], favorite: parseInt(ens[3]), code: code}, 139 function(lines) { 140 if (lines[0] == '1') 141 qa_set_inner_html(document.getElementById('favoriting'), 'favoriting', lines.slice(1).join("\n")); 142 else if (lines[0] == '0') { 143 alert(lines[1]); 144 qa_hide_waiting(elem); 145 } else 146 qa_ajax_error(); 147 } 148 ); 149 150 qa_show_waiting_after(elem, false); 151 152 return false; 153} 154 155function qa_ajax_post(operation, params, callback) 156{ 157 $.extend(params, {qa: 'ajax', qa_operation: operation, qa_root: qa_root, qa_request: qa_request}); 158 159 $.post(qa_root, params, function(response) { 160 var header = 'QA_AJAX_RESPONSE'; 161 var headerpos = response.indexOf(header); 162 163 if (headerpos >= 0) 164 callback(response.substr(headerpos + header.length).replace(/^\s+/, '').split("\n")); 165 else 166 callback([]); 167 168 }, 'text').fail(function(jqXHR) { 169 if (jqXHR.readyState > 0) 170 callback([]) 171 }); 172} 173 174function qa_ajax_error() 175{ 176 alert('Unexpected response from server - please try again or switch off Javascript.'); 177} 178 179function qa_display_rule_show(target, show, first) 180{ 181 var e = document.getElementById(target); 182 if (e) { 183 if (first || e.nodeName == 'SPAN') 184 e.style.display = (show ? '' : 'none'); 185 else if (show) 186 $(e).fadeIn(); 187 else 188 $(e).fadeOut(); 189 } 190} 191 192 193// Question page actions 194 195var qa_element_revealed = null; 196
197function qa_toggle_element(elem) 198{ 199 var e = elem ? document.getElementById(elem) : null; 200 201 if (e && e.qa_disabled) 202 e = null; 203 204 if (e && (qa_element_revealed == e)) { 205 qa_conceal(qa_element_revealed, 'form'); 206 qa_element_revealed = null; 207 208 } else { 209 if (qa_element_revealed) 210 qa_conceal(qa_element_revealed, 'form'); 211 212 if (e) { 213 if (e.qa_load && !e.qa_loaded) { 214 e.qa_load(); 215 e.qa_loaded = true; 216 } 217 218 if (e.qa_show) 219 e.qa_show(); 220 221 qa_reveal(e, 'form', function() { 222 var t = $(e).offset().top; 223 var h = $(e).height() + 16; 224 var wt = $(window).scrollTop(); 225 var wh = $(window).height(); 226 227 if ((t < wt) || (t > (wt + wh))) 228 qa_scroll_page_to(t); 229 else if ((t + h) > (wt + wh)) 230 qa_scroll_page_to(t + h - wh); 231 232 if (e.qa_focus) 233 e.qa_focus(); 234 }); 235 } 236 237 qa_element_revealed = e; 238 } 239 240 return !(e || !elem); // failed to find item 241} 242 243function qa_submit_answer(questionid, elem) 244{ 245 var params = qa_form_params('a_form'); 246 247 params.a_questionid = questionid; 248 249 qa_ajax_post('answer', params, 250 function(lines) { 251 if (lines[0] == '1') { 252 if (lines[1] < 1) { 253 var b = document.getElementById('q_doanswer'); 254 if (b) 255 b.style.display = 'none'; 256 } 257 258 var t = document.getElementById('a_list_title'); 259 qa_set_inner_html(t, 'a_list_title', lines[2]); 260 qa_reveal(t, 'a_list_title'); 261 262 var e = document.createElement('div'); 263 e.innerHTML = lines.slice(3).join("\n"); 264 265 var c = e.firstChild; 266 c.style.display = 'none'; 267 268 var l = document.getElementById('a_list'); 269 l.insertBefore(c, l.firstChild); 270 271 var a = document.getElementById('anew'); 272 a.qa_disabled = true; 273 274 qa_reveal(c, 'answer'); 275 qa_conceal(a, 'form'); 276 277 } else if (lines[0] == '0') { 278 document.forms['a_form'].submit(); 279 280 } else { 281 qa_ajax_error(); 282 } 283 } 284 ); 285 286 qa_show_waiting_after(elem, false); 287 288 return false; 289} 290 291function qa_submit_comment(questionid, parentid, elem) 292{ 293 var params = qa_form_params('c_form_' + parentid); 294 295 params.c_questionid = questionid; 296 params.c_parentid = parentid; 297 298 qa_ajax_post('comment', params, 299 function(lines) { 300 301 if (lines[0] == '1') { 302 var l = document.getElementById('c' + parentid + '_list'); 303 l.innerHTML = lines.slice(2).join("\n"); 304 l.style.display = ''; 305 306 var a = document.getElementById('c' + parentid); 307 a.qa_disabled = true; 308 309 var c = document.getElementById(lines[1]); // id of comment 310 if (c) { 311 c.style.display = 'none'; 312 qa_reveal(c, 'comment'); 313 } 314 315 qa_conceal(a, 'form'); 316 317 } else if (lines[0] == '0') { 318 document.forms['c_form_' + parentid].submit(); 319 320 } else { 321 qa_ajax_error(); 322 } 323 324 } 325 ); 326 327 qa_show_waiting_after(elem, false); 328 329 return false; 330} 331 332function qa_answer_click(answerid, questionid, target) 333{ 334 var params = {}; 335 336 params.answerid = answerid; 337 params.questionid = questionid; 338 params.code = target.form.elements.code.value; 339 params[target.name] = target.value; 340 341 qa_ajax_post('click_a', params, 342 function(lines) { 343 if (lines[0] == '1') { 344 qa_set_inner_html(document.getElementById('a_list_title'), 'a_list_title', lines[1]); 345 346 var l = document.getElementById('a' + answerid); 347 var h = lines.slice(2).join("\n"); 348 349 if (h.length) 350 qa_set_outer_html(l, 'answer', h); 351 else 352 qa_conceal(l, 'answer'); 353 354 } else { 355 target.form.elements.qa_click.value = target.name; 356 target.form.submit(); 357 } 358 } 359 ); 360 361 qa_show_waiting_after(target, false); 362 363 return false; 364} 365 366function qa_comment_click(commentid, questionid, parentid, target) 367{ 368 var params = {}; 369 370 params.commentid = commentid; 371 params.questionid = questionid; 372 params.parentid = parentid; 373 params.code = target.form.elements.code.value; 374 params[target.name] = target.value; 375 376 qa_ajax_post('click_c', params, 377 function(lines) { 378 if (lines[0] == '1') { 379 var l = document.getElementById('c' + commentid); 380 var h = lines.slice(1).join("\n"); 381 382 if (h.length) 383 qa_set_outer_html(l, 'comment', h); 384 else 385 qa_conceal(l, 'comment'); 386 387 } else { 388 target.form.elements.qa_click.value = target.name; 389 target.form.submit(); 390 } 391 } 392 ); 393 394 qa_show_waiting_after(target, false); 395 396 return false;
397} 398 399function qa_show_comments(questionid, parentid, elem) 400{ 401 var params = {}; 402 403 params.c_questionid = questionid; 404 params.c_parentid = parentid; 405 406 qa_ajax_post('show_cs', params, 407 function(lines) { 408 if (lines[0] == '1') { 409 var l = document.getElementById('c' + parentid + '_list'); 410 l.innerHTML = lines.slice(1).join("\n"); 411 l.style.display = 'none'; 412 qa_reveal(l, 'comments'); 413 414 } else { 415 qa_ajax_error(); 416 } 417 } 418 ); 419 420 qa_show_waiting_after(elem, true); 421 422 return false; 423} 424 425function qa_form_params(formname) 426{ 427 var es = document.forms[formname].elements; 428 var params = {}; 429 430 for (var i = 0; i < es.length; i++) { 431 var e = es[i]; 432 var t = (e.type || '').toLowerCase(); 433 434 if (((t != 'checkbox') && (t != 'radio')) || e.checked) 435 params[e.name] = e.value; 436 } 437 438 return params; 439} 440 441function qa_scroll_page_to(scroll) 442{ 443 $('html,body').animate({scrollTop: scroll}, 400); 444} 445 446 447// Ask form 448 449function qa_title_change(value) 450{ 451 qa_ajax_post('asktitle', {title: value}, function(lines) { 452 if (lines[0] == '1') { 453 if (lines[1].length) { 454 qa_tags_examples = lines[1]; 455 qa_tag_hints(true); 456 } 457 458 if (lines.length > 2) { 459 var simelem = document.getElementById('similar'); 460 if (simelem) 461 simelem.innerHTML = lines.slice(2).join('\n'); 462 } 463 464 } else if (lines[0] == '0') 465 alert(lines[1]); 466 else 467 qa_ajax_error(); 468 }); 469 470 qa_show_waiting_after(document.getElementById('similar'), true); 471} 472 473function qa_html_unescape(html) 474{ 475 return html.replace(/&/g, '&').replace(/"/g, '"').replace(/</g, '<').replace(/>/g, '>'); 476} 477 478function qa_html_escape(text) 479{ 480 return text.replace(/&/g, '&').replace(/"/g, '"').replace(/</g, '<').replace(/>/g, '>'); 481} 482 483function qa_tag_click(link) 484{ 485 var elem = document.getElementById('tags'); 486 var parts = qa_tag_typed_parts(elem); 487 488 // removes any HTML tags and ampersand 489 var tag = qa_html_unescape(link.innerHTML.replace(/<[^>]*>/g, '')); 490 491 var separator = qa_tag_onlycomma ? ', ' : ' '; 492 493 // replace if matches typed, otherwise append 494 var newvalue = (parts.typed && (tag.toLowerCase().indexOf(parts.typed.toLowerCase()) >= 0)) 495 ? (parts.before + separator + tag + separator + parts.after + separator) : (elem.value + separator + tag + separator); 496 497 // sanitize and set value 498 if (qa_tag_onlycomma) 499 elem.value = newvalue.replace(/[\s,]*,[\s,]*/g, ', ').replace(/^[\s,]+/g, ''); 500 else 501 elem.value = newvalue.replace(/[\s,]+/g, ' ').replace(/^[\s,]+/g, ''); 502 503 elem.focus(); 504 qa_tag_hints(); 505 506 return false; 507} 508 509function qa_tag_hints(skipcomplete) 510{ 511 var elem = document.getElementById('tags'); 512 var html = ''; 513 var completed = false; 514 515 // first try to auto-complete 516 if (qa_tags_complete && !skipcomplete) { 517 var parts = qa_tag_typed_parts(elem); 518 519 if (parts.typed) { 520 html = qa_tags_to_html((qa_html_unescape(qa_tags_examples + ',' + qa_tags_complete)).split(','), parts.typed.toLowerCase()); 521 completed = html ? true : false; 522 } 523 } 524 525 // otherwise show examples 526 if (qa_tags_examples && !completed) 527 html = qa_tags_to_html((qa_html_unescape(qa_tags_examples)).split(','), null); 528 529 // set title visiblity and hint list 530 document.getElementById('tag_examples_title').style.display = (html && !completed) ? '' : 'none'; 531 document.getElementById('tag_complete_title').style.display = (html && completed) ? '' : 'none'; 532 document.getElementById('tag_hints').innerHTML = html; 533} 534 535function qa_tags_to_html(tags, matchlc) 536{ 537 var html = ''; 538 var added = 0; 539 var tagseen = {}; 540 541 for (var i = 0; i < tags.length; i++) { 542 var tag = tags[i]; 543 var taglc = tag.toLowerCase(); 544 545 if (!tagseen[taglc]) { 546 tagseen[taglc] = true; 547 548 if ((!matchlc) || (taglc.indexOf(matchlc) >= 0)) { // match if necessary 549 if (matchlc) { // if matching, show appropriate part in bold 550 var matchstart = taglc.indexOf(matchlc); 551 var matchend = matchstart + matchlc.length; 552 inner = '<span style="font-weight:normal;">' + qa_html_escape(tag.substring(0, matchstart)) + '<b>' + 553 qa_html_escape(tag.substring(matchstart, matchend)) + '</b>' + qa_html_escape(tag.substring(matchend)) + '</span>'; 554 } else // otherwise show as-is 555 inner = qa_html_escape(tag); 556 557 html += qa_tag_template.replace(/\^/g, inner.replace('$', '$$$$')) + ' '; // replace ^ in template, escape $s 558 559 if (++added >= qa_tags_max) 560 break; 561 } 562 } 563 } 564 565 return html; 566} 567 568function qa_caret_from_end(elem) 569{ 570 if (document.selection) { // for IE 571 elem.focus(); 572 var sel = document.selection.createRange(); 573 sel.moveStart('character', -elem.value.length); 574 575 return elem.value.length - sel.text.length; 576 577 } else if (typeof (elem.selectionEnd) != 'undefined') // other browsers 578 return elem.value.length - elem.selectionEnd; 579 580 else // by default return safest value 581 return 0; 582} 583 584function qa_tag_typed_parts(elem) 585{ 586 var caret = elem.value.length - qa_caret_from_end(elem); 587 var active = elem.value.substring(0, caret); 588 var passive = elem.value.substring(active.length); 589 590 // if the caret is in the middle of a word, move the end of word from passive to active 591 if ( 592 active.match(qa_tag_onlycomma ? /[^\s,][^,]*$/ : /[^\s,]$/) && 593 (adjoinmatch = passive.match(qa_tag_onlycomma ? /^[^,]*[^\s,][^,]*/ : /^[^\s,]+/)) 594 ) { 595 active += adjoinmatch[0]; 596 passive = elem.value.substring(active.length); 597 } 598 599 // find what has been typed so far 600 var typedmatch = active.match(qa_tag_onlycomma ? /[^\s,]+[^,]*$/ : /[^\s,]+$/) || ['']; 601 602 return {before: active.substring(0, active.length - typedmatch[0].length), after: passive, typed: typedmatch[0]}; 603} 604 605function qa_category_select(idprefix, startpath) 606{ 607 var startval = startpath ? startpath.split("/") : []; 608 var setdescnow = true; 609 610 for (var l = 0; l <= qa_cat_maxdepth; l++) { 611 var elem = document.getElementById(idprefix + '_' + l); 612 613 if (elem) { 614 if (l) { 615 if (l < startval.length && startval[l].length) { 616 var val = startval[l]; 617 618 for (var j = 0; j < elem.options.length; j++) 619 if (elem.options[j].value == val) 620 elem.selectedIndex = j; 621 } else 622 var val = elem.options[elem.selectedIndex].value; 623 } else 624 val = ''; 625 626 if (elem.qa_last_sel !== val) { 627 elem.qa_last_sel = val; 628 629 var subelem = document.getElementById(idprefix + '_' + l + '_sub'); 630 if (subelem) 631 subelem.parentNode.removeChild(subelem); 632 633 if (val.length || (l == 0)) { 634 subelem = elem.parentNode.insertBefore(document.createElement('span'), elem.nextSibling); 635 subelem.id = idprefix + '_' + l + '_sub'; 636 qa_show_waiting_after(subelem, true); 637 638 qa_ajax_post('category', {categoryid: val}, 639 (function(elem, l) { 640 return function(lines) { 641 var subelem = document.getElementById(idprefix + '_' + l + '_sub'); 642 if (subelem) 643 subelem.parentNode.removeChild(subelem); 644 645 if (lines[0] == '1') { 646 elem.qa_cat_desc = lines[1]; 647 648 var addedoption = false;
649 650 if (lines.length > 2) { 651 subelem = elem.parentNode.insertBefore(document.createElement('span'), elem.nextSibling); 652 subelem.id = idprefix + '_' + l + '_sub'; 653 subelem.innerHTML = ' '; 654 655 var newelem = elem.cloneNode(false); 656 657 newelem.name = newelem.id = idprefix + '_' + (l + 1); 658 newelem.options.length = 0; 659 660 if (l ? qa_cat_allownosub : qa_cat_allownone) 661 newelem.options[0] = new Option(l ? '' : elem.options[0].text, '', true, true); 662 663 for (var i = 2; i < lines.length; i++) { 664 var parts = lines[i].split('/'); 665 666 if (String(qa_cat_exclude).length && (String(qa_cat_exclude) == parts[0])) 667 continue; 668 669 newelem.options[newelem.options.length] = new Option(parts.slice(1).join('/'), parts[0]); 670 addedoption = true; 671 } 672 673 if (addedoption) { 674 subelem.appendChild(newelem); 675 qa_category_select(idprefix, startpath); 676 677 } 678 679 if (l == 0) 680 elem.style.display = 'none'; 681 } 682 683 if (!addedoption) 684 set_category_description(idprefix); 685 686 } else if (lines[0] == '0') 687 alert(lines[1]); 688 else 689 qa_ajax_error(); 690 } 691 })(elem, l) 692 ); 693 694 setdescnow = false; 695 } 696 697 break; 698 } 699 } 700 } 701 702 if (setdescnow) 703 set_category_description(idprefix); 704} 705 706function set_category_description(idprefix) 707{ 708 var n = document.getElementById(idprefix + '_note'); 709 710 if (n) { 711 desc = ''; 712 713 for (var l = 1; l <= qa_cat_maxdepth; l++) { 714 var elem = document.getElementById(idprefix + '_' + l); 715 716 if (elem && elem.options[elem.selectedIndex].value.length) 717 desc = elem.qa_cat_desc; 718 } 719 720 n.innerHTML = desc; 721 } 722} 723 724 725// User functions 726 727function qa_submit_wall_post(elem, morelink) 728{ 729 var params = {}; 730 731 params.message = document.forms.wallpost.message.value; 732 params.handle = document.forms.wallpost.handle.value; 733 params.start = document.forms.wallpost.start.value; 734 params.code = document.forms.wallpost.code.value; 735 params.morelink = morelink ? 1 : 0; 736 737 qa_ajax_post('wallpost', params, 738 function(lines) { 739 if (lines[0] == '1') { 740 var l = document.getElementById('wallmessages'); 741 l.innerHTML = lines.slice(2).join("\n"); 742 743 var c = document.getElementById(lines[1]); // id of new message 744 if (c) { 745 c.style.display = 'none'; 746 qa_reveal(c, 'wallpost'); 747 } 748 749 document.forms.wallpost.message.value = ''; 750 qa_hide_waiting(elem); 751 752 } else if (lines[0] == '0') { 753 document.forms.wallpost.qa_click.value = elem.name; 754 document.forms.wallpost.submit(); 755 756 } else { 757 qa_ajax_error(); 758 } 759 } 760 ); 761 762 qa_show_waiting_after(elem, false); 763 764 return false; 765} 766 767function qa_wall_post_click(messageid, target) 768{ 769 var params = {}; 770 771 params.messageid = messageid; 772 params.handle = document.forms.wallpost.handle.value; 773 params.start = document.forms.wallpost.start.value; 774 params.code = document.forms.wallpost.code.value; 775 776 params[target.name] = target.value; 777 778 qa_ajax_post('click_wall', params, 779 function(lines) { 780 if (lines[0] == '1') { 781 var l = document.getElementById('m' + messageid); 782 var h = lines.slice(1).join("\n"); 783 784 if (h.length) 785 qa_set_outer_html(l, 'wallpost', h); 786 else 787 qa_conceal(l, 'wallpost'); 788 789 } else { 790 document.forms.wallpost.qa_click.value = target.name; 791 document.forms.wallpost.submit(); 792 } 793 } 794 ); 795 796 qa_show_waiting_after(target, false); 797 798 return false; 799} 800 801function qa_pm_click(messageid, target, box) 802{ 803 var params = {}; 804 805 params.messageid = messageid; 806 params.box = box; 807 params.handle = document.forms.pmessage.handle.value; 808 params.start = document.forms.pmessage.start.value; 809 params.code = document.forms.pmessage.code.value; 810 811 params[target.name] = target.value; 812 813 qa_ajax_post('click_pm', params, 814 function(lines) { 815 if (lines[0] == '1') { 816 var l = document.getElementById('m' + messageid); 817 var h = lines.slice(1).join("\n"); 818 819 if (h.length) 820 qa_set_outer_html(l, 'pmessage', h); 821 else 822 qa_conceal(l, 'pmessage'); 823 824 } else { 825 document.forms.pmessage.qa_click.value = target.name; 826 document.forms.pmessage.submit(); 827 } 828 } 829 ); 830 831 qa_show_waiting_after(target, false); 832 833 return false
vendor: 4 bytes, lines 833-834
833; 834}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.