PageRenderTime 123ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 1ms

/content/themes/default/board.js

http://github.com/FoOlRulez/FoOlFuuka
JavaScript | 900 lines | 765 code | 109 blank | 26 comment | 135 complexity | e5a5239ac6bbb4f2c0433195d5216daa MD5 | raw file
Possible License(s): Apache-2.0, MIT
  1. var bindFunctions = function()
  2. {
  3. // the following block of code deals with drag and drop of images for MD5 hashing
  4. var search_dropdown = jQuery('#image');
  5. if(isEventSupported('dragstart') && isEventSupported('drop') && !!window.FileReader)
  6. {
  7. search_dropdown.on('dragover', function(e) {
  8. e.preventDefault();
  9. e.stopPropagation();
  10. e.originalEvent.dataTransfer.dropEffect = 'copy';
  11. });
  12. search_dropdown.on('dragenter', function(e) {
  13. e.preventDefault();
  14. e.stopPropagation();
  15. });
  16. search_dropdown.on('drop', function(event) {
  17. if(event.originalEvent.dataTransfer){
  18. if(event.originalEvent.dataTransfer.files.length) {
  19. event.preventDefault();
  20. event.stopPropagation();
  21. findSameImageFromFile(event.originalEvent.dataTransfer);
  22. }
  23. }
  24. });
  25. }
  26. jQuery("body").click(function(event){
  27. var search_el = jQuery('.search-dropdown');
  28. if(search_el.find(event.target).length != 1)
  29. {
  30. search_el.find('.search-dropdown-menu').hide();
  31. search_el.removeClass('active');
  32. }
  33. });
  34. // unite all the onclick functions in here
  35. jQuery("body").on("click",
  36. "a.[data-function], button.[data-function], input.[data-function]",
  37. function(event) {
  38. var el = jQuery(this);
  39. var post = el.data("post");
  40. var modal = jQuery("#post_tools_modal");
  41. switch (el.data("function")) {
  42. case 'highlight':
  43. if (post) replyHighlight(post);
  44. break;
  45. case 'quote':
  46. jQuery("#reply_chennodiscursus").val(jQuery("#reply_chennodiscursus").val() + ">>" + post + "\n");
  47. break;
  48. case 'comment':
  49. // sending an image
  50. if(jQuery("#file_image").val())
  51. return true;
  52. var originalText = el.attr('value');
  53. el.attr({'value': backend_vars.gettext['submit_state'], 'disabled': 'disabled'});
  54. // to make sure nobody gets pissed off with a blocked button
  55. var buttonTimeout = setTimeout(function(){
  56. el.attr({'value': originalText});
  57. el.removeAttr('disabled');
  58. }, 15000);
  59. var reply_alert = jQuery('#reply_ajax_notices');
  60. reply_alert.removeClass('error').removeClass('success');
  61. jQuery.ajax({
  62. url: backend_vars.site_url + backend_vars.board_shortname + '/submit/' ,
  63. dataType: 'json',
  64. type: 'POST',
  65. cache: false,
  66. data: {
  67. reply_numero: post,
  68. reply_bokunonome: jQuery("#reply_bokunonome").val(),
  69. reply_elitterae: jQuery("#reply_elitterae").val(),
  70. reply_talkingde: jQuery("#reply_talkingde").val(),
  71. reply_chennodiscursus: jQuery("#reply_chennodiscursus").val(),
  72. reply_nymphassword: jQuery("#reply_nymphassword").val(),
  73. reply_postas: jQuery("#reply_postas").val(),
  74. reply_gattai: 'Submit',
  75. theme: backend_vars.selected_theme,
  76. csrf_fool: backend_vars.csrf_hash
  77. },
  78. success: function(data){
  79. // clear button's timeout, we can deal with the rest now
  80. clearTimeout(buttonTimeout);
  81. el.attr({'value': originalText});
  82. el.removeAttr('disabled');
  83. if (typeof data.error !== "undefined")
  84. {
  85. reply_alert.html(data.error);
  86. reply_alert.addClass('error'); // deals with showing the alert
  87. return false;
  88. }
  89. reply_alert.html(data.success);
  90. reply_alert.addClass('success'); // deals with showing the alert
  91. jQuery("#reply_chennodiscursus").val("");
  92. realtimethread();
  93. },
  94. error: function(jqXHR, textStatus, errorThrown) {
  95. reply_alert.html('Connection error.');
  96. reply_alert.addClass('error');
  97. reply_alert.show();
  98. },
  99. complete: function() {
  100. }
  101. });
  102. event.preventDefault();
  103. break;
  104. case 'realtimethread':
  105. realtimethread();
  106. event.preventDefault();
  107. break
  108. case 'delete':
  109. var foolfuuka_reply_password = getCookie(backend_vars.cookie_prefix + 'foolfuuka_reply_password');
  110. modal.find(".title").html('Delete » Post No. ' + el.data("post-id"));
  111. modal.find(".modal-loading").hide();
  112. modal.find(".modal-information").html('\
  113. <span class="modal-label">Password</span>\n\
  114. <input type="password" class="modal-password" />\n\
  115. <input type="hidden" class="modal-post-id" value="' + post + '" />');
  116. modal.find(".submitModal").data("action", 'delete');
  117. if(foolfuuka_reply_password != null)
  118. {
  119. modal.find(".modal-password").val(foolfuuka_reply_password);
  120. }
  121. break;
  122. case 'report':
  123. modal.find(".title").html('Report &raquo; Post No.' + el.data("post-id"));
  124. modal.find(".modal-loading").hide();
  125. modal.find(".modal-information").html('\
  126. <span class="modal-label">Post ID</span>\n\
  127. <input type="text" class="modal-post" value="' + el.data("post-id") + '" readonly="readonly" />\n\
  128. <input type="hidden" class="modal-post-id" value="' + post + '" />\n\
  129. <span class="modal-field">Comment</span>\n\
  130. <textarea class="modal-comment"></textarea>');
  131. modal.find(".submitModal").data("action", 'report');
  132. break;
  133. case 'mod':
  134. el.attr({'disabled': 'disabled'});
  135. jQuery.ajax({
  136. url: backend_vars.mod_url,
  137. dataType: 'json',
  138. type: 'POST',
  139. cache: false,
  140. data: {
  141. board: el.data('board'),
  142. doc_id: el.data('id'),
  143. actions: [el.data('action')],
  144. theme: backend_vars.selected_theme,
  145. csrf_fool: backend_vars.csrf_hash
  146. },
  147. success: function(data){
  148. el.removeAttr('disabled');
  149. if (typeof data.error !== "undefined")
  150. {
  151. alert(data.error);
  152. return false;
  153. }
  154. // might need to be upgraded to array support
  155. switch(el.data('action'))
  156. {
  157. case 'remove_post':
  158. jQuery('.doc_id_' + el.data('id')).remove();
  159. break;
  160. case 'remove_image':
  161. jQuery('.doc_id_' + el.data('id')).find('.thread_image_box:eq(0) img')
  162. .attr('src', backend_vars.images['missing_image'])
  163. .css({
  164. width: backend_vars.images['missing_image_width'],
  165. height: backend_vars.images['missing_image_height']
  166. });
  167. break;
  168. case 'remove_report':
  169. jQuery('.doc_id_' + el.data('id')).removeClass('reported')
  170. break;
  171. case 'ban_user':
  172. jQuery('.doc_id_' + el.data('id')).find('[data-action=ban_user]').text('Banned');
  173. break;
  174. case 'ban_md5':
  175. jQuery('.doc_id_' + el.data('id')).find('.thread_image_box:eq(0) img')
  176. .attr('src', backend_vars.images['banned_image'])
  177. .css({
  178. width: backend_vars.images['banned_image_width'],
  179. height: backend_vars.images['banned_image_height']
  180. });
  181. break;
  182. }
  183. },
  184. error: function(jqXHR, textStatus, errorThrown) {
  185. },
  186. complete: function() {
  187. }
  188. });
  189. return false;
  190. break;
  191. case 'activateModeration':
  192. jQuery('button[data-function=activateModeration]').parent().hide();
  193. jQuery('.post_mod_controls button[data-function]').attr({'disabled': 'disabled'});
  194. setTimeout(function(){
  195. jQuery('.post_mod_controls button[data-function]').removeAttr('disabled');
  196. }, 700);
  197. jQuery('.post_mod_controls').show();
  198. break;
  199. case 'closeModal':
  200. el.closest(".modal").modal('hide');
  201. return false;
  202. break;
  203. case 'submitModal':
  204. var loading = modal.find(".modal-loading");
  205. var action = $(this).data("action");
  206. var _post = modal.find(".modal-post-id").val();
  207. var _href = $(this).data(action) + _post + '/';
  208. if (action == 'report') {
  209. var _data = {
  210. post: _post,
  211. reason: modal.find(".modal-comment").val(),
  212. csrf_fool: backend_vars.csrf_hash
  213. };
  214. }
  215. else if (action == 'delete') {
  216. var _data = {
  217. post: _post,
  218. password: modal.find(".modal-password").val(),
  219. csrf_fool: backend_vars.csrf_hash
  220. };
  221. }
  222. else {
  223. // Stop It! Unable to determine what action to use.
  224. return false;
  225. }
  226. jQuery.post(_href, _data, function(result) {
  227. loading.hide();
  228. if (result.status == 'failed') {
  229. modal.find(".modal-error").html('<div class="alert alert-error" data-alert="alert"><a class="close" href="#">&times;</a><p>' + result.reason + '</p></div>');
  230. return false;
  231. }
  232. modal.modal('hide');
  233. if (action == 'report') {
  234. toggleHighlight(modal.find(".modal-post").val().replace(',', '_'), 'reported', false);
  235. }
  236. else if (action == 'delete') {
  237. jQuery('.doc_id_' + post).hide();
  238. }
  239. }, 'json');
  240. return false;
  241. break;
  242. case 'searchShow':
  243. el.parent().find('.search-dropdown-menu').show();
  244. el.parent().parent().addClass('active');
  245. break;
  246. case 'clearLatestSearches':
  247. setCookie(backend_vars.cookie_prefix + 'search_latest_5', '', 0, '/', backend_vars.cookie_domain);
  248. jQuery('li.latest_search').each(function(idx){
  249. jQuery(this).remove();
  250. });
  251. return false;
  252. break;
  253. case 'searchUser':
  254. window.location.href = backend_vars.site_url + $(this).data('board') +
  255. '/search/poster_ip/' + $(this).data('poster-ip');
  256. //return false;
  257. break;
  258. case 'searchUserGlobal':
  259. window.location.href = backend_vars.site_url + 'search/poster_ip/' + $(this).data('poster-ip');
  260. //return false;
  261. break;
  262. default:
  263. break;
  264. }
  265. });
  266. // how could we make it working well on cellphones?
  267. if( navigator.userAgent.match(/Android/i) ||
  268. navigator.userAgent.match(/webOS/i) ||
  269. navigator.userAgent.match(/iPhone/i) ||
  270. navigator.userAgent.match(/iPad/i) ||
  271. navigator.userAgent.match(/iPod/i) ||
  272. navigator.userAgent.match(/BlackBerry/)
  273. ){
  274. return false;
  275. }
  276. // variable for ajax backlinks that we can clear them if the mouse hovered out
  277. var backlink_jqxhr;
  278. var backlink_spin;
  279. // hover functions go here
  280. jQuery("#main").on("mouseover mouseout", "article a.[data-backlink]", function(event) {
  281. if(event.type == "mouseover")
  282. {
  283. var backlink = jQuery("#backlink");
  284. var that = jQuery(this);
  285. var pos = that.offset();
  286. var height = that.height();
  287. var width = that.width();
  288. if(that.attr('data-backlink') != 'true')
  289. {
  290. // gallery
  291. var thread_id = that.attr('data-backlink');
  292. quote = backend_vars.threads_data[thread_id];
  293. backlink.css('display', 'block');
  294. backlink.html(quote.formatted);
  295. }
  296. else if(backend_vars.thread_id == that.data('post'))
  297. {
  298. // OP
  299. quote = backend_vars.thread_op_data;
  300. backlink.css('display', 'block');
  301. backlink.html(quote.formatted);
  302. }
  303. else if(jQuery('#' + that.data('post')).hasClass('post'))
  304. {
  305. // normal posts
  306. var toClone = jQuery('#' + that.data('post'));
  307. if (toClone.length == 0)
  308. return false;
  309. backlink.css('display', 'block');
  310. backlink.html(toClone.clone());
  311. }
  312. else if (typeof backend_vars.loaded_posts[that.data('post')] !== 'undefined')
  313. {
  314. if(backend_vars.loaded_posts[that.data('post')] === false)
  315. {
  316. shakeBacklink(that);
  317. return false;
  318. }
  319. var data = backend_vars.loaded_posts[that.data('post')];
  320. backlink.html(data.formatted);
  321. backlink.css('display', 'block');
  322. }
  323. else
  324. {
  325. backlink_spin = that;
  326. backlink_spin.spin('small');
  327. backlink_jqxhr = jQuery.ajax({
  328. url: backend_vars.api_url + 'api/chan/post/' ,
  329. dataType: 'jsonp',
  330. type: 'GET',
  331. cache: false,
  332. data: {
  333. board: that.data('board'),
  334. num: that.data('post'),
  335. theme: backend_vars.selected_theme,
  336. format: 'jsonp'
  337. },
  338. beforeSend: function(xhr) {
  339. xhr.withCredentials = true;
  340. },
  341. success: function(data){
  342. backlink_spin.spin(false);
  343. if (typeof data.error !== "undefined")
  344. {
  345. backend_vars.loaded_posts[that.data('post')] = false;
  346. shakeBacklink(that);
  347. return false;
  348. }
  349. backend_vars.loaded_posts[that.data('post')] = data;
  350. backlink.html(data.formatted);
  351. backlink.css('display', 'block');
  352. showBacklink(backlink, pos, height, width);
  353. }
  354. });
  355. return false;
  356. }
  357. showBacklink(backlink, pos, height, width);
  358. }
  359. else
  360. {
  361. // kill the ajax call so the backlink doesn't appear
  362. if(typeof backlink_jqxhr === 'object')
  363. {
  364. backlink_spin.spin(false);
  365. backlink_jqxhr.abort()
  366. }
  367. jQuery("#backlink").css('display', 'none').html('');
  368. }
  369. });
  370. }
  371. var shakeBacklink = function(el)
  372. {
  373. el.css({position:'relative'});
  374. el.animate({left: '-5px'},100)
  375. .animate({left: '+5px'}, 100)
  376. .animate({left: '-5px'}, 100)
  377. .animate({left: '+5px'}, 100)
  378. .animate({left: '+0px'}, 100, 'linear', function(){
  379. el.css({position:'static'});
  380. });
  381. }
  382. var showBacklink = function(backlink, pos, height, width)
  383. {
  384. if(jQuery(window).width()/2 < pos.left + width/2)
  385. {
  386. backlink.css({
  387. right: (jQuery(window).width() - pos.left - width) + 'px',
  388. top: (pos.top + height + 3) + 'px',
  389. left: 'auto'
  390. });
  391. }
  392. else
  393. {
  394. backlink.css({
  395. left: (pos.left) + 'px',
  396. top: (pos.top + height + 3) + 'px',
  397. right: 'auto'
  398. });
  399. }
  400. backlink.find("article").removeAttr("id").find(".post_controls").remove();
  401. backlink.find(".post_file_controls").remove();
  402. // remove the image from the backlink box if it's a gallery
  403. if(typeof page_function !== 'undefined' && backend_vars.page_function == "gallery")
  404. {
  405. backlink.find(".thread_image_box").remove();
  406. }
  407. var swap_image = backlink.find('[data-original]');
  408. if(swap_image.length > 0)
  409. {
  410. swap_image.attr('src', swap_image.attr('data-original'));
  411. }
  412. }
  413. var backlinkify = function(elem, post_id, subnum)
  414. {
  415. var backlinks = {};
  416. if(subnum > 0)
  417. post_id += "_" + subnum;
  418. elem.find("a.[data-backlink=true]").each(function(idx, post) {
  419. p_id = jQuery(post).text().replace('>>', '').replace(',', '_');
  420. if (typeof backlinks[p_id] === "undefined")
  421. {
  422. backlinks[p_id] = [];
  423. }
  424. backlinks[p_id].push('<a href="' + backend_vars.site_url + backend_vars.board_shortname + '/thread/' + backend_vars.thread_id + '/#' + post_id + '" data-function="highlight" data-backlink="true" data-post="' + post_id + '">&gt;&gt;' + post_id.replace('_', ',') + '</a>');
  425. backlinks[p_id] = eliminateDuplicates(backlinks[p_id]);
  426. });
  427. jQuery.each(backlinks, function(key, val){
  428. var post = jQuery("#" + key);
  429. if(post.length == 0)
  430. return false;
  431. var post_backlink = post.find(".post_backlink:eq(0)");
  432. var already_backlinked = post_backlink.text().replace('>>', '').split(' ');
  433. jQuery.each(already_backlinked, function(i,v){
  434. if(typeof val[v] !== "undefined")
  435. {
  436. delete val[v];
  437. }
  438. });
  439. post_backlink.html(post_backlink.html() + ((post_backlink.html().length > 0)?" ":"") + val.join(" "));
  440. post_backlink.parent().show();
  441. });
  442. }
  443. var timelapse = 10;
  444. var currentlapse = 0;
  445. var realtimethread = function(){
  446. clearTimeout(currentlapse);
  447. jQuery.ajax({
  448. url: backend_vars.api_url + 'api/chan/thread/',
  449. dataType: 'jsonp',
  450. type: 'GET',
  451. data: {
  452. num : backend_vars.thread_id,
  453. board: backend_vars.board_shortname,
  454. latest_doc_id: backend_vars.latest_doc_id,
  455. theme: backend_vars.selected_theme,
  456. format: 'jsonp'
  457. },
  458. success: function(data){
  459. var w_height = jQuery(document).height();
  460. var found_posts = false;
  461. if(typeof data[backend_vars.thread_id] !== "undefined" && typeof data[backend_vars.thread_id].posts !== "undefined") {
  462. jQuery.each(data[backend_vars.thread_id].posts, function(idx, value){
  463. found_posts = true;
  464. var post = jQuery(value.formatted)
  465. post.find("time").localize('ddd mmm dd HH:MM:ss yyyy');
  466. post.find('[rel=tooltip]').tooltip({
  467. placement: 'top',
  468. delay: 200
  469. });
  470. post.find('[rel=tooltip_right]').tooltip({
  471. placement: 'right',
  472. delay: 200
  473. });
  474. backlinkify(jQuery('<div>' + value.comment_processed + '</div>'), value.num, value.subnum);
  475. // avoid inserting twice
  476. if(jQuery('.doc_id_' + value.doc_id).length == 0)
  477. jQuery('article.thread aside.posts').append(post);
  478. if(backend_vars.latest_doc_id < value.doc_id)
  479. backend_vars.latest_doc_id = value.doc_id;
  480. });
  481. }
  482. if(found_posts)
  483. {
  484. if(jQuery('#reply_form :focus').length > 0)
  485. {
  486. window.scrollBy(0, jQuery(document).height() - w_height);
  487. }
  488. timelapse = 10;
  489. }
  490. else
  491. {
  492. if(timelapse < 30)
  493. {
  494. timelapse += 5;
  495. }
  496. }
  497. currentlapse = setTimeout(realtimethread, timelapse*1000);
  498. },
  499. error: function(jqXHR, textStatus, errorThrown) {
  500. },
  501. complete: function() {
  502. }
  503. });
  504. return false;
  505. }
  506. var toggleSearch = function(mode)
  507. {
  508. var search;
  509. if (!(search = document.getElementById('search_' + mode))) return;
  510. search.style.display = search.style.display ? "" : "none";
  511. }
  512. var findSameImageFromFile = function(obj)
  513. {
  514. var reader = new FileReader();
  515. reader.onloadend = function(evt){
  516. if (evt.target.readyState == FileReader.DONE) {
  517. var fileContents = evt.target.result;
  518. var digestBytes = Crypto.MD5(Crypto.charenc.Binary.stringToBytes(fileContents), {
  519. asBytes: true
  520. });
  521. var digestBase64 = Crypto.util.bytesToBase64(digestBytes);
  522. var digestBase64URL = digestBase64.replace('==', '').replace(/\//g, '_').replace(/\+/g, '-');
  523. document.location = backend_vars.site_url + backend_vars.board_shortname + '/image/' + digestBase64URL;
  524. }
  525. }
  526. reader.readAsBinaryString(obj.files[0]);
  527. }
  528. var getSearch = function(type, searchForm)
  529. {
  530. var location = searchForm.action;
  531. if (searchForm.text.value != "")
  532. location += 'text/' + encodeURIComponent(searchForm.text.value) + '/';
  533. if (type == 'advanced')
  534. {
  535. if (searchForm.subject.value != "")
  536. location += 'subject/' + encodeURIComponent(searchForm.subject.value) + '/';
  537. if (searchForm.username.value != "")
  538. location += 'username/' + encodeURIComponent(searchForm.username.value) + '/';
  539. if (searchForm.tripcode.value != "")
  540. location += 'tripcode/' + encodeURIComponent(searchForm.tripcode.value) + '/';
  541. if (getRadioValue(searchForm.capcode) != "")
  542. location += 'capcode/' + getRadioValue(searchForm.capcode) + '/';
  543. if (searchForm.image.value != "")
  544. location += 'image/' + encodeURIComponent(searchForm.image.value) + '/';
  545. if (getRadioValue(searchForm.deleted) != "")
  546. location += 'deleted/' + getRadioValue(searchForm.deleted) + '/';
  547. if (getRadioValue(searchForm.ghost) != "")
  548. location += 'ghost/' + getRadioValue(searchForm.ghost) + '/';
  549. if (getRadioValue(searchForm.type) != "")
  550. location += 'type/' + getRadioValue(searchForm.type) + '/';
  551. if (getRadioValue(searchForm.filter) != "")
  552. location += 'filter/' + getRadioValue(searchForm.filter) + '/';
  553. if (searchForm.date_start.value != "")
  554. {
  555. var validate_date = /^\d{4}-\d{2}-\d{2}$/;
  556. if (validate_date.test(searchForm.date_start.value))
  557. {
  558. location += 'start/' + encodeURIComponent(searchForm.date_start.value) + '/';
  559. }
  560. else
  561. {
  562. alert('Sorry, you have entered an invalid date format. (Ex: YYYY-MM-DD)');
  563. return false;
  564. }
  565. }
  566. if (searchForm.date_end.value != "")
  567. {
  568. var validate_date = /^\d{4}-\d{2}-\d{2}$/;
  569. if (validate_date.test(searchForm.date_end.value))
  570. {
  571. location += 'end/' + encodeURIComponent(searchForm.date_end.value) + '/';
  572. }
  573. else
  574. {
  575. alert('Sorry, you have entered an invalid date format. (Ex: YYYY-MM-DD)');
  576. return false;
  577. }
  578. }
  579. location += 'order/' + getRadioValue(searchForm.order) + '/';
  580. }
  581. window.location = location;
  582. }
  583. var getPost = function(postForm)
  584. {
  585. if (postForm.post.value == "") {
  586. alert('Sorry, you must insert a valid post number.');
  587. return false;
  588. }
  589. var post = postForm.post.value.match(/(?:^|\/)(\d+)(?:[_,]([0-9]*))?/);
  590. window.location = postForm.action + encodeURIComponent(((typeof post[1] != 'undefined') ? post[1] : '') + ((typeof post[2] != 'undefined') ? '_' + post[2] : '')) + '/';
  591. }
  592. var getRadioValue = function(group)
  593. {
  594. if (typeof group == "undefined")
  595. return '';
  596. for (index = 0; index < group.length; index++)
  597. {
  598. if (group[index].checked == true)
  599. return encodeURIComponent(group[index].value);
  600. }
  601. }
  602. var getCheckValue = function(group)
  603. {
  604. if (typeof group == "undefined")
  605. return '';
  606. var values = new Array();
  607. for (index = 0; index < group.length; index++)
  608. {
  609. if (group[index].checked == true)
  610. values.push(group[index].value);
  611. }
  612. return encodeURIComponent(values.join("-"));
  613. }
  614. function toggleHighlight(id, classn, single)
  615. {
  616. jQuery("article").each(function() {
  617. var post = jQuery(this);
  618. if (post.hasClass(classn) && single)
  619. {
  620. post.removeClass(classn);
  621. }
  622. if (post.attr("id") == id)
  623. {
  624. post.addClass(classn);
  625. }
  626. })
  627. }
  628. function replyHighlight(id)
  629. {
  630. toggleHighlight(id, 'highlight', true);
  631. }
  632. var changeTheme = function(theme)
  633. {
  634. setCookie(backend_vars.cookie_prefix + 'theme', theme, 30, '/');
  635. window.location.reload();
  636. }
  637. var changeLanguage = function(language)
  638. {
  639. setCookie(backend_vars.cookie_prefix + 'language', language, 30, '/');
  640. window.location.reload();
  641. }
  642. function setCookie( name, value, expires, path, domain, secure )
  643. {
  644. var today = new Date();
  645. today.setTime( today.getTime() );
  646. if ( expires )
  647. {
  648. expires = expires * 1000 * 60 * 60 * 24;
  649. }
  650. var expires_date = new Date( today.getTime() + (expires) );
  651. document.cookie = name + "=" +escape( value ) +
  652. ( ( expires ) ? ";expires=" + expires_date.toGMTString() : "" ) +
  653. ( ( path ) ? ";path=" + path : "" ) +
  654. ( ( domain ) ? ";domain=" + domain : "" ) +
  655. ( ( secure ) ? ";secure" : "" );
  656. }
  657. function getCookie( check_name ) {
  658. var a_all_cookies = document.cookie.split( ';' );
  659. var a_temp_cookie = '';
  660. var cookie_name = '';
  661. var cookie_value = '';
  662. var b_cookie_found = false;
  663. for ( i = 0; i < a_all_cookies.length; i++ )
  664. {
  665. a_temp_cookie = a_all_cookies[i].split( '=' );
  666. cookie_name = a_temp_cookie[0].replace(/^\s+|\s+$/g, '');
  667. if ( cookie_name == check_name )
  668. {
  669. b_cookie_found = true;
  670. if ( a_temp_cookie.length > 1 )
  671. {
  672. cookie_value = unescape( a_temp_cookie[1].replace(/^\s+|\s+$/g, '') );
  673. }
  674. return cookie_value;
  675. break;
  676. }
  677. a_temp_cookie = null;
  678. cookie_name = '';
  679. }
  680. if ( !b_cookie_found )
  681. {
  682. return null;
  683. }
  684. }
  685. function eliminateDuplicates(arr) {
  686. var i,
  687. len=arr.length,
  688. out=[],
  689. obj={};
  690. for (i=0;i<len;i++) {
  691. obj[arr[i]]=0;
  692. }
  693. for (i in obj) {
  694. out.push(i);
  695. }
  696. return out;
  697. }
  698. var isEventSupported = (function() {
  699. var TAGNAMES = {
  700. 'select': 'input',
  701. 'change': 'input',
  702. 'submit': 'form',
  703. 'reset': 'form',
  704. 'error': 'img',
  705. 'load': 'img',
  706. 'abort': 'img'
  707. };
  708. function isEventSupported( eventName, element ) {
  709. element = element || document.createElement(TAGNAMES[eventName] || 'div');
  710. eventName = 'on' + eventName;
  711. // When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize", whereas `in` "catches" those
  712. var isSupported = eventName in element;
  713. if ( !isSupported ) {
  714. // If it has no `setAttribute` (i.e. doesn't implement Node interface), try generic element
  715. if ( !element.setAttribute ) {
  716. element = document.createElement('div');
  717. }
  718. if ( element.setAttribute && element.removeAttribute ) {
  719. element.setAttribute(eventName, '');
  720. isSupported = typeof element[eventName] == 'function';
  721. // If property was created, "remove it" (by setting value to `undefined`)
  722. if ( typeof element[eventName] != 'undefined' ) {
  723. element[eventName] = undefined;
  724. }
  725. element.removeAttribute(eventName);
  726. }
  727. }
  728. element = null;
  729. return isSupported;
  730. }
  731. return isEventSupported;
  732. })();
  733. jQuery(document).ready(function() {
  734. // settings
  735. jQuery.support.cors = true;
  736. backend_vars.loaded_posts = [];
  737. var lazyloaded = jQuery('img.lazyload');
  738. if(lazyloaded.length > 149)
  739. {
  740. lazyloaded.lazyload({
  741. threshold: 1000,
  742. event: 'scroll'
  743. });
  744. }
  745. // check if input[date] is supported, so we can use by default input[text] with placeholder without breaking w3
  746. var i = document.createElement("input");
  747. i.setAttribute("type", "date");
  748. if(i.type !== "text")
  749. {
  750. jQuery('#date_end').replaceWith(jQuery('<input>').attr({id: 'date_end', name: 'end', type: 'date'}));
  751. jQuery('#date_start').replaceWith(jQuery('<input>').attr({id: 'date_start', name: 'start', type: 'date'}));
  752. }
  753. // firefox sucks at styling input, so we need to add size="", that guess what? It's not w3 compliant!
  754. jQuery('#file_search').attr({size: '4'});
  755. jQuery('#file_image').attr({size: '16'});
  756. // destroy the file search box if the browser doesn't support file API
  757. if(!window.FileReader)
  758. {
  759. jQuery('.file_search_remove').remove();
  760. }
  761. var post = location.href.split(/#/);
  762. if (post[1]) {
  763. if (post[1].match(/^q\d+(_\d+)?$/)) {
  764. post[1] = post[1].replace('q', '').replace('_', ',');
  765. jQuery("#reply_chennodiscursus").append(">>" + post[1] + "\n");
  766. post[1] = post[1].replace(',', '_');
  767. }
  768. replyHighlight(post[1]);
  769. }
  770. if (typeof backend_vars.thread_id !== "undefined" && (Math.round(new Date().getTime() / 1000) - backend_vars.latest_timestamp < 24 * 60 * 60))
  771. {
  772. jQuery('.js_hook_realtimethread').html(backend_vars.gettext['thread_is_real_time'] + ' <a class="btnr" href="#" onClick="realtimethread(); return false;">' + backend_vars.gettext['update_now'] + '</a>');
  773. setTimeout(realtimethread, 10000);
  774. }
  775. bindFunctions();
  776. // localize and add 4chan tooltip where title
  777. jQuery("article time").localize('ddd mmm dd HH:MM:ss yyyy').filter('[title]').tooltip({
  778. placement: 'top',
  779. delay: 300,
  780. animation: false
  781. });
  782. jQuery('input[title]').tooltip({
  783. placement: 'right',
  784. delay: 200,
  785. animation: false
  786. });
  787. jQuery('li.latest_search').tooltip({
  788. placement: 'left',
  789. animation: false
  790. });
  791. });