1function getCid() { 2 var cidRegex = /[?&]cid=(\d+)/; 3 var cid = cidRegex.exec(document.location); 4 return cid ? cid[1] : null; 5} 6 7function readUnreadMode() { 8 const newin = document.getElementById('newin'); 9 if (newin && newin.dataset.stickyShowHidden === "1") 10 return 1; 11 return /[?&]show_hidden=1/.exec(document.location) ? 1 : 2; 12} 13 14const getunread = readUnreadMode(); 15var csrf_ham = /csrf_ham=([0-9a-z-]+)/.exec(document.cookie); 16csrf_ham = csrf_ham ? csrf_ham[1] : null; 17const cid = getCid(); 18 19function getUpdatedComics() { 20 var res = []; 21 document.querySelectorAll('li').forEach(function(li, i) { 22 if (li.dataset.cid !== undefined) { 23 res.push({cid: parseInt(li.dataset.cid), 24 n: parseInt(li.dataset.unread), 25 href: li.children[0].href 26 }); 27 } 28 }); 29 return res; 30} 31 32(function( $ ){ 33 $.fn.tagSelect = function() { 34 $(this).on('change', function(){ 35 $('.maincategory').hide(); 36 var id = 'cat-'+$(this).find(':selected').val(); 37 $('#'+id).show(); 38 }); 39 return this; 40 }; 41 42 $.fn.updatedComics = function(a,b,c) { 43 var cids = {}; 44 $(this).find('li').each(function(x,y) { 45 var cid = $(this).data('cid'); 46 if (cid) { 47 cids[cid] = true; 48 } 49 }); 50 return cids; 51 } 52 53 return this; 54})( jQuery ); 55 56function submitSuccess(reply) { 57 if (typeof reply != 'undefined') { 58 $('#msgdiv').html(''); 59 if (reply.ok) { 60 $('.hideafterdone').slideUp(); 61 $('.removeafterdone').remove(); 62 $('#msgdiv').hide().html(reply.msg).slideDown(); 63 } else if (reply.errmsg) { 64 enableSubmitcomic(); 65 $('.submitcomic button[type=submit]').removeAttr('disabled'); 66 $('#msgdiv').hide().html(reply.errmsg).slideDown(); 67 } 68 } 69} 70 71function submitError() { 72 enableSubmitcomic(); 73 $('.submitcomic button[type=submit]').removeAttr('disabled'); 74 $('#msgdiv').hide().html("Unexpected error").slideDown(); 75} 76 77function enableSubmitcomic() { 78 var submitButton = $('.submitcomic button[type=submit]'); 79 submitButton.removeAttr('disabled'); 80 $('.submitcomic').one('submit', function() { 81 submitButton.attr('disabled', 1); 82 var options = {url: '/s/submit', 83 type: 'POST', 84 dataType: 'json', 85 error: submitError, 86 success: submitSuccess 87 }; 88 if (window.FormData) { 89 options.data = new FormData(this); 90 options.processData = false; 91 options.contentType = false;
92 } else { 93 options.data = $(this).serialize(); 94 } 95 $.ajax(options); 96 return false; 97 }); 98 if (window.FormData) { 99 $('.script.hasformdata').show(); 100 } else { 101 $('.script.noformdata').show(); 102 } 103} 104 105function setTagsEpedias(rpy) { 106 $('#tagdiff .diff').empty(); 107 var origtags = {}; 108 $.each(rpy.origtags, function(idx, tagid){ 109 origtags[tagid] = true; 110 }); 111 $('#tags-container') 112 .off('change', 'input[type=checkbox]') 113 .find('input[type=checkbox]').prop('checked', false); 114 $('#tags-container').on('change', 'input[type=checkbox]', function() { 115 var tagid = this.getAttribute('value'); 116 const desc = $('label[for='+this.getAttribute('id')+']').text(); 117 if (desc.startsWith('site:')) 118 return; 119 if ((origtags[tagid] && this.checked) || (!origtags[tagid] && !this.checked)) { 120 $('span#difftag-'+tagid).remove(); 121 } else { 122 var diffelem = document.createElement('span'); 123 diffelem.id = 'difftag-'+tagid; 124 diffelem.textContent = desc; 125 if (origtags[tagid]) { 126 $('#removedtags').show(); 127 $('#removedtags .diff').append(diffelem); 128 } else { 129 $('#addedtags').show(); 130 $('#addedtags .diff').append(diffelem); 131 } 132 } 133 }); 134 var initialNewtags = {}; 135 $.each(rpy.tags, function(idx, tagid){ 136 $('#cat-sel-'+tagid).click(); 137 initialNewtags[tagid] = true; 138 }); 139 $.each(rpy.origtags, function(idx, tagid){ 140 if (!initialNewtags[tagid]) 141 $('#cat-sel-'+tagid).trigger('change'); 142 }); 143 $.each(rpy.epedias, function(idx, dat) { 144 var epid = dat.epid || dat[0]; 145 var entry = dat.entry || dat[1]; 146 $('input[name=epedia-entry-'+epid+']').val(entry); 147 }); 148} 149 150function resetSubmitForm() { 151 $('.submitcomic input[type=text]').val(''); 152 $('.submitcomic textarea').val(''); 153 $('.submitcomic input[type=checkbox]').removeAttr('checked'); 154 $('.submitcomic').off('change'); 155 $('#tagdiff .diff').html(''); 156} 157 158function updateUnread(unread) { 159 if (unread.total_new > 0) { 160 var newin = $('#newin').show(); 161 newin.text('('+unread.total_new+' new in '+unread.new_in+')'); 162 var newinHeader = $('#unread-header').show(); 163 newinHeader.text(unread.total_new+' new in '+unread.new_in); 164 } else { 165 $('#newin, #unread-header').hide(); 166 } 167} 168 169// Also shows the account settings section that sets this. 170function getBookForward() { 171 const key = 'alwaysUseForward'; 172 let hasStorage = false; 173 try { 174 const x = '__storage_test__'; 175 window.localStorage.setItem(x, x); 176 window.localStorage.removeItem(x); 177 hasStorage = true; 178 } catch (e) {} 179 if (hasStorage) { 180 const alwaysUse = !!window.localStorage.getItem(key) 181 const el = document.getElementById('alwaysForwardBtn'); 182 if (el) { 183 el.checked = alwaysUse; 184 addEventListener('change', function(event) { 185 if (event.target.checked) { 186 window.localStorage.setItem(key, '1'); 187 } else { 188 window.localStorage.removeItem(key); 189 } 190 }); 191 } 192 193 $('#alwaysForwardBtnSection').show(); 194 if (alwaysUse) { 195 return '.booklink,.bookredir'; 196 } 197 } 198 return '.booklink'; 199} 200 201$(document).ready(function(){ 202 var popup = $('.mobile #popup-container'); 203 var menubuttonsvg = $('.mobile #menu-button'); 204 var repage; 205 const bookForward = getBookForward(); 206 $('.noscript').hide(); 207 $('.script.show').show(); 208 $('.scripthidden.show').removeClass('scripthidden'); 209 $(bookForward).prepend($('<button type="button" class="bookmarkforward">></button>') 210 .click(function(){ 211 var par = $(this).parent() 212 const cid = par.data('cid'); 213 $.ajax({url: '/s/uprefs', 214 data: { 215 bookmark: [cid, 'max'], 216 csrf_ham: csrf_ham, 217 getunread: getunread 218 } 219 }) 220 .done(function(rpy) { 221 if (rpy && rpy.ok) { 222 par.fadeOut('fast'); 223 updateUnread(rpy); 224 } 225 }); 226 })); 227 if ($('.submitcomic').length > 0) { 228 if (cid != null && $('.submitcomic input[name="cid"]').length > 0) { 229 $.ajax({url:'/s/cinfo/'+cid, 230 dataType: 'json', 231 success:function(rpy){ 232 if (rpy != null) { 233 rpy.origtags = rpy.tags; 234 setTagsEpedias(rpy); 235 enableSubmitcomic(); 236 } 237 }}); 238 } else { 239 enableSubmitcomic(); 240 } 241 } 242 243 var hilitedialog; 244 var loadedtags = new Object; 245 var tagcounts = new Object; 246 $('form:has(#piperka_list)').on('hilite', '#piperka_list', function(){ 247 $('#piperka_list li > a').each(function(){ 248 var cid = this.href.match(/\d+/); 249 if (cid) 250 cid = cid[0]; 251 if (cid && tagcounts[cid] != undefined) { 252 var li = $(this).parent(); 253 if (tagcounts[cid] > 0) { 254 li.addClass('hilite'); 255 } else { 256 li.removeClass('hilite'); 257 } 258 } 259 }); 260 }); 261 $('#tagselect').tagSelect().trigger('change'); 262 $('button.hilitetags').on('click', function() { 263 if (hilitedialog == undefined) { 264 $.ajax({url: '/d/tags.xml', 265 dataType: 'html', 266 success: function(content){ 267 hilitedialog = $('#hilitedialog').html(content); 268 hilitedialog.find('#tagselect').tagSelect().trigger('change'); 269 var lastTop, lastLeft; 270 hilitedialog.dialog({appendTo: '#notmuch', dialogClass: 'isover', minWidth:200, width:400, open: function(){ 271 if (lastTop != undefined) { 272 var style = this.parentNode.style; 273 style.top = lastTop; 274 style.left = lastLeft; 275 } 276 }, close: function(){ 277 var style = this.parentNode.style; 278 lastTop = style.top; 279 lastLeft = style.left; 280 }}); 281 hilitedialog.on('change', 'input', function() { 282 function updateTagcounts(tagid, diff) { 283 $.each(loadedtags[tagid], function() { 284 if (tagcounts[this] == undefined) { 285 tagcounts[this] = 0; 286 } 287 tagcounts[this] += diff; 288 }); 289 $('#piperka_list').trigger('hilite'); 290 } 291 var tagid = this.getAttribute('value'); 292 var diff = this.checked ? 1 : -1; 293 if (loadedtags[tagid] == undefined) { 294 hilitedialog.find('.tagselector').hide(); 295 $.ajax({url:'/s/tagslist/'+tagid, 296 method:'GET', 297 dataType:'json', 298 success:function(rpy){ 299 hilitedialog.find('.tagselector').show(); 300 if (rpy != null) { 301 if (rpy.cids) { 302 loadedtags[tagid] = rpy.cids; 303 } 304 } 305 updateTagcounts(tagid, diff); 306 }}); 307 } else { 308 updateTagcounts(tagid, diff); 309 } 310 }); 311 }}); 312 } else { 313 hilitedialog.dialog('open'); 314 } 315 }); 316 317 // Reader history chart 318 if ($('.chart').length > 0) { 319 var rhist = $('#readerchart'); 320 if (cid != null && rhist.length > 0) { 321 $.when($.ajax({url:'/d/readershistory/'+cid, method:'GET', dataType:'json'})) 322 .then(function(rpy){ 323 chart = rpy; 324 if (rpy.length > 1) { 325 var day = new Date(), dateTicks = []; 326 for (var i=0; i < 5; ++i) { 327 dateTicks[4-i] = day.toISOString().substring(0,10); 328 day.setTime(day.getTime()-7*24*60*60*1000); 329 } 330 var maxReader = 0, minReader; 331 $.each(rpy, function() { 332 var reader = this[1]; 333 minReader = minReader == null || reader < minReader ? reader : minReader; 334 maxReader = maxReader < reader ? reader : maxReader; 335 }); 336 var readerTicks = [minReader-1 < 0 ? 0 : minReader-1], lastTick = minReader-1, j=1; 337 for (var i=0; i < 5; ++i) { 338 var num = Math.floor(minReader + (maxReader-minReader)/5*i); 339 if (num != lastTick) { 340 lastTick = num; 341 readerTicks[j++] = num; 342 } 343 } 344 readerTicks[j++] = maxReader; 345 readerTicks[j] = maxReader+1; 346 rhist.show(); 347 $.jqplot('readerchart', [chart], 348 {axes:{xaxis:{renderer: $.jqplot.DateAxisRenderer, 349 ticks:dateTicks, 350 tickRenderer: $.jqplot.CanvasAxisTickRenderer, 351 tickOptions: {angle: -30, formatString: '%m-%d'} 352 }, 353 yaxis:{ticks:readerTicks, 354 tickOptions:{formatString: '%i'}} 355 }, 356 title:"Reader history" 357 }); 358 } 359 }); 360 } 361 } 362 363 if ($('#quicksearch').length > 0) { 364 var form = $('#quicksearch form'); 365 form.on('submit', function() { 366 var cid = form.data('cid'); 367 var sorttype = $('#quicksearch input[name=sorttype]').attr('value'); 368 if (cid) { 369 $.getJSON('/s/qsearch', {cid: cid, sorttype: sorttype}, function(rpy) { 370 if (rpy && rpy.offset != undefined) { 371 if (repage != undefined) { 372 repage(rpy.offset); 373 } else {
374 if (sorttype == 'top') { 375 document.location = '/top.html?offset='+rpy.offset; 376 } else { 377 document.location = '/browse.html?sort='+sorttype+'&offset='+rpy.offset; 378 } 379 } 380 } 381 }); 382 } 383 return false; 384 }); 385 $('#quicksearch').qsearch({ 386 select: function(event, ui) { 387 form.data('cid', ui.item.cid); 388 form.submit(); 389 }}); 390 } 391 392 // AJAX subscribe buttons 393 $('form:has(#piperka_list)').on('click', 'button', function(event) { 394 event.preventDefault(); 395 var name = this.getAttribute('name'); 396 var subscid = this.getAttribute('value'); 397 var button = this; 398 if (name == 'subscribe') { 399 var startAtFirst = $('#atfirst:checked').length > 0; 400 $.ajax({url: '/s/uprefs', 401 method: 'POST', 402 data: {bookmark: [subscid, startAtFirst ? 0 : 'max'], csrf_ham: csrf_ham, getunread: getunread}, 403 success: function(rpy) { 404 if (rpy && rpy.ord != undefined) { 405 $(button).attr('name', 'unsubscribe').attr('class', 'minus').text('-'); 406 updateUnread(rpy); 407 } 408 } 409 }); 410 } else if (name == 'unsubscribe') { 411 $.ajax({url: '/s/uprefs', 412 method: 'POST', 413 data: {bookmark: [subscid, 'del'], csrf_ham: csrf_ham, getunread:getunread}, 414 success: function(rpy) { 415 if (rpy && rpy.ok) { 416 $(button).attr('name', 'subscribe').attr('class', 'plus').text('+'); 417 updateUnread(rpy); 418 } 419 } 420 }); 421 } 422 }); 423 424 // AJAX paginate 425 if (!!(window.history && history.pushState) && $('.paginate').length > 0) { 426 var b = {start: $('.paginate .start'), 427 prev: $('.paginate .prev'), 428 next: $('.paginate .next'), 429 end: $('.paginate .end')}; 430 var getOffsetRegexp = /[?&].*offset=([0-9]+)/; 431 var getOffset = function(url) { 432 var matches = getOffsetRegexp.exec(url); 433 if (matches != undefined && matches.length > 1) 434 return parseInt(matches[1]); 435 else 436 return null; 437 } 438 var getMaxcidRegexp = /&_max=([0-9]+)/; 439 var getMaxcid = function(url) { 440 var matches = getMaxcidRegexp.exec(url); 441 if (matches && matches.length > 1) 442 return parseInt(matches[1]); 443 else 444 return null; 445 }; 446 var offset = getOffset(window.location.href); 447 var sorttype; 448 if (window.location.pathname == '/top.html') { 449 sorttype = 'top'; 450 } else { 451 sorttype = /[?&]sort=([a-z]+)/.exec(window.location.search); 452 if (sorttype) { 453 sorttype = sorttype[1]; 454 switch (sorttype) { 455 case 'top': case 'name': case 'new': case 'update': case 'hot': case 'recommend': 456 break; 457 default: 458 sorttype = 'name'; 459 } 460 } else { 461 sorttype = 'name'; 462 } 463 } 464 var prev = getOffset(b.prev.attr('href')); 465 var container = $('#piperka_list'); 466 if (offset == undefined) { 467 offset = 0; 468 } 469 var total, perPage = getOffset($(b.next).attr('href')); 470 if (perPage == undefined) { 471 if (prev != undefined) { 472 perPage = offset-prev; 473 total = $('#piperka_list li').length+offset; 474 } 475 } else { 476 perPage -= offset; 477 total = getOffset(b.end.attr('href'))+perPage; 478 } 479 if (total != undefined) { 480 var lastAjax; 481 repage = function(event) { 482 popup.slideUp(); 483 menubuttonsvg.removeClass('active'); 484 var newOffset, newSorttype, href, maxcidMarker = ''; 485 if (typeof event == 'number') { 486 newOffset = event; 487 newSorttype = sorttype; 488 } else { 489 event.stopPropagation(); 490 event.preventDefault(); 491 var forceUpdate = false; 492 if (event.type == 'popstate') { 493 href = document.location.href; 494 if (event.originalEvent.state) { 495 forceUpdate = true; 496 } 497 } else { 498 href = this.getAttribute('href'); 499 if (href == undefined) 500 return; 501 } 502 newOffset = getOffset(href); 503 if (window.location.pathname == '/top.html') { 504 newSorttype = 'top'; 505 } else { 506 newSorttype = /\?.*sort=([a-z]+)/.exec(href); 507 if (newSorttype) 508 newSorttype = newSorttype[1]; 509 else 510 newSorttype = 'name'; 511 switch (newSorttype) { 512 case 'top': case 'name': case 'new': case 'update': case 'hot': case 'recommend': 513 if (newSorttype != sorttype) { 514 if (newSorttype == 'name') { 515 $('#alphabet_index').show(); 516 } else if (sorttype == 'name') { 517 $('#alphabet_index').hide(); 518 } 519 $('#quicksearch input[name=sorttype]').attr('value', newSorttype); 520 } 521 break; 522 default: 523 newSorttype = sorttype; 524 } 525 } 526 if (newOffset == undefined) { 527 newOffset = 0; 528 var maxcid; 529 if (newSorttype == 'new' && (maxcid = getMaxcid(href))) 530 maxcidMarker = '&_max='+maxcid; 531 } 532 } 533 newOffset = newOffset < 0 ? 0 : newOffset >= total ? (total-1) : newOffset; 534 if (!forceUpdate && offset == newOffset && sorttype == newSorttype) 535 return; 536 sorttype = newSorttype; 537 offset = newOffset; 538 if (window.location.pathname == '/top.html') { 539 href = '/top.html?offset=' 540 } else { 541 var search = window.location.search 542 .replace(/[?&]offset=[^&#]*/, '') 543 .replace(/[?&]sort=[^&#]*/, '') 544 .replace(/[?&]_max=[^&#]*/, ''); 545 if (search == '') { 546 search = '?' 547 } else { 548 search = search.replace(/^./, '?') + '&'; 549 } 550 href = window.location.pathname + search + 'sort='+sorttype+'&offset='; 551 } 552 if (offset == 0) { 553 b.start.removeAttr('href'); 554 b.prev.removeAttr('href'); 555 } else { 556 b.start.attr('href', href + '0'); 557 var newPrev = offset-perPage; 558 if (newPrev < 0) 559 newPrev = 0; 560 b.prev.attr('href', href + newPrev); 561 } 562 var newNext = offset+perPage; 563 if (newNext >= total) { 564 b.next.removeAttr('href'); 565 b.end.removeAttr('href'); 566 } else { 567 b.next.attr('href', href + newNext); 568 b.end.attr('href', href + (total-perPage)); 569 } 570 container.fadeTo('slow', 0, 'linear'); 571 if (lastAjax) 572 lastAjax.abort(); 573 href = href + offset + maxcidMarker; 574 lastAjax = $.ajax({url: href, 575 dataType: 'html', 576 data: {min: 1}, 577 success: function(content) { 578 lastAjax = null; 579 container.stop(); 580 var newContent = $(content); 581 var newContainer = newContent.filter('#piperka_list'); 582 if (newContainer.length == 0) 583 newContainer = newContent.find('#piperka_list'); 584 let newTotal = newContainer.data('total'); 585 if (newTotal && total != newTotal) { 586 total = newTotal; 587 b.end.attr('href', href.substring(0, href.indexOf('offset=')+7)+(total-perPage)); 588 } 589 container.replaceWith(newContainer); 590 container = newContainer; 591 if (event.type != 'popstate') 592 history.pushState(true, null, href); 593 container.trigger('hilite'); 594 }}); 595 }; 596 $('.paginate').on('click', 'a', repage); 597 $('#alphabet_index').on('click', 'a', repage); 598 $('#sort_by').on('click', 'a', repage); 599 $(window).on('popstate', repage); 600 href = undefined; 601 $('body').on('click', 'a', function(event) { 602 history.replaceState(false, $('title').text()); 603 return true; 604 }); 605 } 606 } 607 608 $(".followcheck").on('change', 'input[type="checkbox"]', function(){ 609 var type = this.getAttribute('name'); 610 var name = this.getAttribute('value'); 611 var checkbox = this; 612 var action; 613 if (type == 'followee') { 614 action = this.checked ? 'permit' : 'deny'; 615 } else if (type == 'follow') { 616 action = this.checked ? 'follow' : 'unfollow'; 617 } 618 if (action == undefined) { 619 this.checked = !this.checked; 620 return; 621 } 622 var docancel = function() { 623 checkbox.checked = (action == 'permit' || action == 'follow') ? false : true; 624 }; 625 this.setAttribute('disabled', true); 626 $.ajax({url: '/s/profile', 627 method: 'POST', 628 data: {action: action, name: name, csrf_ham: csrf_ham}, 629 success: function(rpy) { 630 if (!(rpy && rpy.rows && rpy.rows > 0)) { 631 docancel(); 632 } 633 checkbox.removeAttribute('disabled'); 634 }, 635 failure: function(rpy) { 636 docancel(); 637 checkbox.removeAttribute('disabled'); 638 } 639 }); 640 }); 641 642 $('#followee').on('click', 'button', function(){ 643 var row = $(this).parents('tr'); 644 var button = this; 645 this.setAttribute('disabled', true); 646 $.ajax({url: '/s/profile', 647 method: 'POST', 648 data: {action: 'unfollow', name: this.getAttribute('name'), csrf_ham: csrf_ham}, 649 success: function(rpy) { 650 if (rpy.rows != undefined && rpy.rows > 0) { 651 row.fadeOut(); 652 } else { 653 button.removeAttribute('disabled'); 654 } 655 }, 656 failure: function(rpy) { 657 button.removeAttribute('disabled'); 658 } 659 }); 660 }); 661 662 $('span#interest').on('click', 'button', function() { 663 var action = this.getAttribute('id') == 'cancel' ? 'unfollow' : 'follow'; 664 var button = this; 665 button.setAttribute('disabled', true); 666 $.ajax({url: '/s/profile', 667 method: 'POST', 668 data: {action: action, name: this.getAttribute('name'), csrf_ham: csrf_ham}, 669 success: function(rpy) { 670 if (rpy.rows != undefined && rpy.rows > 0) { 671 window.location.href = window.location.href; 672 } else { 673 button.removeAttribute('disabled'); 674 } 675 } 676 }); 677 }); 678 679 if ($('#ticket').length >
679 0 && $('#ticket').tabs().length > 0) { 680 $('input[name="jsok"]').val(1); 681 } 682 683 // Account management field disables and enables 684 var oldPasswdInput = $('input[name="_password"]'); 685 $('#authenticate_with').on('change', function() { 686 if ($(this).val() == 'Password') { 687 oldPasswdInput.removeAttr('disabled'); 688 } else { 689 oldPasswdInput.attr('disabled', 1); 690 } 691 }); 692 var passwdInput = $('input[name="new_passwd"], input[name="new_passwd_retype"]'); 693 $('#only_oauth2').on('change', function() { 694 var checkbox = this; 695 if (this.checked) { 696 passwdInput.attr('disabled', 1); 697 } else { 698 passwdInput.removeAttr('disabled'); 699 } 700 }); 701 702 // Switch links on updates page to point to Reader 703 var readerCheck = $('#openinreader'); 704 if (readerCheck.length > 0) { 705 readerCheck.parent().show(); 706 readerCheck.on('readerChange', function() { 707 var rg = /redir=(\d+)/; 708 var links = $('#piperka_list a'); 709 if (readerCheck[0].checked) { 710 links.each(function(idx, item) { 711 var cid = rg.exec(item.href)[1]; 712 $(item).data('orig', [item.href, item.getAttribute('target')]); 713 item.href = 'http://'+window.location.hostname+'/reader/?cid='+cid; 714 item.setAttribute('target', 'reader'); 715 }); 716 } else { 717 links.each(function(idx, item) { 718 var orig = $(item).data('orig'); 719 item.href = orig[0]; 720 item.setAttribute('target', orig[1]); 721 }); 722 } 723 }); 724 readerCheck.on('change', function() { 725 readerCheck.trigger('readerChange'); 726 }); 727 } 728 729 var archive; 730 $('#info-archive').on('click', function() { 731 var userreq, subscriptions; 732 if (!archive) { 733 $('#archivedialog').pPageDialog(); 734 $('#thumbdialog').pThumbDialog(); 735 $('#archivedialog').on('archive_select', 'tr:has(td)', function(ev, existing) { 736 if (!existing) { 737 var info = $('#archivedialog').data(); 738 const page = $(this).data('page'); 739 var url; 740 if (page === null) { 741 url = info.fixed_head ? info.fixed_head : info.homepage; 742 } else { 743 url = info.url_base+$(this).data('page')+info.url_tail; 744 } 745 window.open(url, 'ArchivePage'); 746 } 747 }) 748 archive = makePageDialog(cid); 749 } 750 $.when(archive) 751 .then(function(archive) { 752 $('#archivedialog').dialog('open'); 753 }); 754 return false; 755 }); 756 757 var updateWatch = $('#updatewatch'); 758 var supportsWebSockets = 'WebSocket' in window || 'MozWebSocket' in window; 759 $('.updatewatch-message').hide().removeClass('scripthidden'); 760 var updateWatchMsg = function(id) { 761 $('.updatewatch-message').hide(); 762 $('#'+id).show(); 763 }; 764 var updateWatchCustomMsg = function(msg) { 765 $('.updatewatch-message').hide(); 766 $('#updatewatch-msg-custom').text(msg).show(); 767 }; 768 if (csrf_ham && updateWatch.length > 0 && supportsWebSockets) { 769 $('#watch-messages').removeClass('script'); 770 var tgl = $('#updatewatch-toggle'); 771 tgl.prop('checked', false); 772 var schedule = [10000, 20000, 40000, 100000] 773 var updatedComics = $('#piperka_list').updatedComics(); 774 var icon = $('link[rel="icon"]'); 775 window.onfocus = function() { 776 icon.attr('href', '/favicon.png'); 777 }; 778 var watchFailed = function() { 779 updateWatchMsg('updatewatch-msg-connfailed'); 780 tgl.prop('checked', false); 781 }; 782 var watchUpdating = function() { 783 updateWatchMsg('updatewatch-msg-upd'); 784 }; 785 var watchReconn = function() { 786 updateWatchMsg('updatewatch-msg-reconnecting'); 787 }; 788 function initUpdateWatchWs(reconnect) { 789 ws = new WebSocket(wsUri); 790 ws.onerror = function(ev) { 791 if (tgl.prop('checked')) { 792 watchFailed(); 793 } 794 console.log({x: 'error', ev: ev}) 795 }; 796 ws.onopen = function(ev) { 797 $('.updatewatch-message').hide(); 798 }; 799 ws.onclose = function(ev) { 800 if (!tgl.prop('checked')) { 801 return; 802 } 803 if (schedule[reconnect]) { 804 $('#updatewatch-msg-reconnecting').show(); 805 window.setTimeout(initUpdateWatchWs, schedule[reconnect], reconnect+1); 806 } else { 807 $('#updatewatch-msg-connfailed').show(); 808 } 809 }; 810 ws.onmessage = function(ev) { 811 watchUpdating(); 812 $.ajax({url: '/?min=1', 813 dataType: 'html', 814 success: function(content) { 815 $('.updatewatch-message').hide(); 816 var newContent = $(content); 817 $('#piperka_list').replaceWith(newContent.find('#piperka_list')); 818 $('#newin').text(newContent.filter('#newin').text()); 819 var newComics = newContent.filter('#newcomics').children().detach(); 820 if (newComics.length > 0) { 821 $('#menu-button circle').addClass('newcomics'); 822 } else { 823 $('#menu-button circle').removeClass('newcomics'); 824 } 825 $('#newcomics').empty().append(newComics); 826 var newExpected = newContent.filter('#expected-updates'); 827 var oldExpected = $('#expected-updates'); 828 if (oldExpected.length) { 829 oldExpected.replaceWith(newExpected); 830 } else if (newExpected.length) { 831 $('#pre-expected-updates').after(newExpected); 832 } 833 if (readerCheck[0].checked) { 834 readerCheck.trigger('readerChange'); 835 } 836 var newUpdated = $('#piperka_list').updatedComics(); 837 var anyNew = Object.keys(newUpdated).some(function(cid) { 838 return !updatedComics[cid]; 839 }); 840 if (anyNew) { 841 icon.attr('href', '/favicon-updates.png'); 842 } 843 updatedComics = newUpdated; 844 }, 845 failure: function() { 846 watchFailed(); 847 } 848 }); 849 }; 850 return ws; 851 } 852 853 updateWatch.removeClass('scripthidden'); 854 var wsUri = 'wss://'+window.location.host+'/s/updateWatch/init/'+csrf_ham; 855 tgl.on('change', function(ev) { 856 $('.updatewatch-message').hide(); 857 if (ev.target.checked) { 858 initUpdateWatchWs(0); 859 } else { 860 ws.close(); 861 } 862 }); 863 } 864 var supportsNotification = 'Notification' in window && navigator.serviceWorker; 865 if (csrf_ham && updateWatch.length > 0 && supportsNotification) { 866 $('#update-push-container').removeClass('scripthidden'); 867 var tgl2 = $('#update-push-toggle'); 868 var updateSubscription = function(subscription) { 869 var keys = subscription.toJSON().keys; 870 var call = $.ajax({url: '/s/push/subscribe', 871 method: 'POST', 872 data: {'csrf_ham': csrf_ham, 873 'endpoint': subscription.endpoint,
874 'auth': keys.auth, 875 'p256dh': keys.p256dh 876 } 877 }); 878 return call; 879 }; 880 // Determine if notifications start as enabled 881 navigator.serviceWorker.getRegistration('/push.js') 882 .then(function(registration) { 883 if (registration && Notification.permission == 'granted') { 884 // SW has been registered, proceed to check if 885 // there's an existing push subscription. 886 registration.pushManager.getSubscription() 887 .then(function(subscription) { 888 if (subscription) { 889 updateSubscription(subscription) 890 .catch(function(e) { 891 tgl2.prop('checked', false); 892 throw e; 893 }) 894 .then(function() { 895 tgl2.prop('checked', true); 896 }); 897 } 898 }); 899 } else { 900 // Explicit uncheck since browsers may restore an 901 // old state for the checkbox. 902 tgl2.prop('checked', false); 903 } 904 }); 905 906 tgl2.on('change', function(ev) { 907 $('.updatewatch-message').hide(); 908 if (ev.target.checked) { 909 // Request permission 910 Notification.requestPermission(function(status) { 911 if (Notification.permission == 'granted') { 912 var errored = false; 913 navigator.serviceWorker.register('/push.js') 914 .then(function(reg) { 915 var key = atob(document.getElementById('update-push-toggle').dataset.pushkey); 916 var buf = new Uint8Array(key.length); 917 for (i = 0; i < key.length; ++i) { 918 buf[i] = key.charCodeAt(i); 919 } 920 var options = {userVisibleOnly: true, 921 applicationServerKey: buf}; 922 reg.pushManager.subscribe(options) 923 .catch(function(err) { 924 console.log(err); 925 updateWatchCustomMsg('Push subscription failed on browser'); 926 errored = true; 927 tgl2.prop('checked', false); 928 throw err; 929 }) 930 .then(updateSubscription) 931 .catch(function(err) { 932 if (errored) 933 return; 934 console.log(err); 935 updateWatchCustomMsg('Push subscription failed on server'); 936 tgl2.prop('checked', false); 937 }); 938 }); 939 } else { 940 updateWatchCustomMsg('No permission for notifications'); 941 tgl2.prop('checked', false); 942 } 943 }); 944 } else { 945 // Unsubscribe 946 navigator.serviceWorker.getRegistration('/push.js') 947 .then(function(registration) { 948 if (!registration) 949 return; 950 registration.pushManager.getSubscription() 951 .then(function(subscription) { 952 if (!subscription) 953 return; 954 var endpoint = subscription.endpoint; 955 subscription.unsubscribe() 956 .then(function(success) { 957 $.ajax({url: '/s/push/unsubscribe', 958 method: 'POST', 959 data: {'csrf_ham': csrf_ham, 960 'endpoint': endpoint 961 } 962 }); 963 }); 964 }); 965 }); 966 } 967 }); 968 } 969 970 var editAuthor = $('#editAuthor'); 971 if (editAuthor.length > 0) { 972 var comicTable = $('#comics'); 973 $('#editAuthorForm').on('submit', function(ev) { 974 $.ajax({url: '/s/editAuthor', 975 method: 'POST', 976 data: $(this).serialize() 977 }) 978 .done(function(res) { 979 $('#editAuthorForm input[name=auid]').val(res.auid); 980 $('#editAuthorForm button[type=submit]').text('Update'); 981 $('#error').text(); 982 }) 983 .fail(function() { 984 $('#error').text('update/create failed'); 985 }); 986 return false; 987 }); 988 $('#editAuthorForm').on('click', 'button.delete', function(ev) { 989 this.parentElement.parentElement.remove(); 990 }); 991 $('#editAuthorSearch').qsearch({ 992 select: function(event, ui) { 993 var form = this.parentElement; 994 form.dataset.cid = ui.item.cid; 995 form.dataset.label = ui.item.label; 996 $(form).submit(); 997 }}); 998 $('#editAuthorSearch form').on('submit', function() { 999 var cid = this.dataset.cid; 1000 var label = this.dataset.label; 1001 if ($('#editAuthorForm input[name="cid"][value="'+cid+'"]').length > 0) 1002 return false; 1003 $('<tr/>') 1004 .data('cid', cid) 1005 .append($('<td/>') 1006 .text(cid) 1007 .append($('<input/>') 1008 .attr('type', 'hidden') 1009 .attr('name', 'cid') 1010 .attr('value', cid)) 1011 ) 1012 .append($('<td/>') 1013 .append($('<a/>') 1014 .text(label) 1015 .attr('target', '_blank') 1016 .attr('href', 'info.html?cid='+cid)) 1017 ) 1018 .append($('<td/>') 1019 .append($('<button>
1019Delete</button>') 1020 .attr('type', 'button') 1021 .attr('class', 'delete')) 1022 ) 1023 .appendTo($('#comics')); 1024 return false; 1025 }); 1026 } 1027 1028 // Epedias paste event 1029 $('#epedias').on('paste', 'input[type=text]', function(ev) { 1030 var paste = ev.originalEvent.clipboardData.getData('text/plain'); 1031 var base = this.dataset.base; 1032 var tail = this.dataset.tail; 1033 if (paste.startsWith(base)) { 1034 paste = paste.slice(base.length); 1035 } 1036 if (tail && paste.endsWith(tail)) { 1037 paste = paste.slice(0, paste.length-tail.length); 1038 } 1039 this.value=paste; 1040 return false; 1041 }); 1042 1043 $('.ads-question input').on('change', function() { 1044 $('.ads-question span.message').text(''); 1045 }); 1046 $('.ads-question button').on('click', function(el) { 1047 var consent; 1048 var refresh = false; 1049 if (el.target.name == 'ads') { 1050 consent = el.target.value; 1051 refresh = true; 1052 } else { 1053 consent = $('.ads-question input:checked').val(); 1054 } 1055 if (typeof(consent) != 'undefined') { 1056 document.cookie="ads="+consent+";path=/;max-age=157680000; Secure; SameSite=Strict"; 1057 if (refresh) { 1058 document.location = 'ad_settings.html'; 1059 } else { 1060 $('.ads-question span.message').text('Done'); 1061 } 1062 } 1063 }); 1064 1065 const unreadInNewTabs = document.getElementById('unreadInNewTabs'); 1066 if (unreadInNewTabs) { 1067 const minNewTab = document.getElementById('minNewTab'); 1068 const unreadTabOpenResult = document.getElementById('unreadTabOpenResult'); 1069 unreadInNewTabs.onclick = function() { 1070 const lim = minNewTab.valueAsNumber; 1071 const tabs = getUpdatedComics() 1072 .filter(function(c) {return c.n <= lim && c.n > 0;}) 1073 .map(function(update) { 1074 return window.open(update.href, "Piperka Update "+update.cid); 1075 }); 1076 if (tabs[0]) { 1077 tabs[0].focus(); 1078 } 1079 unreadTabOpenResult.style.display = "inline"; 1080 unreadTabOpenResult.children[0].textContent = tabs.length; 1081 }; 1082 } 1083 1084 // Mobile site 1085 $('.selectMobile').on('click', function() { 1086 var mobi = this.dataset.sel; 1087 document.cookie="mobi="+mobi+";path=/;max-age=157680000; Secure; SameSite=Strict"; 1088 if (mobi == "1" && this.tagName == "BUTTON") { 1089 $('#uncommittedMobileQuestion').hide(600); 1090 } else { 1091 document.location=document.location; 1092 } 1093 }); 1094 1095 var popupVisible = false; 1096 $('.mobile #page-controls').children().detach().appendTo(popup); 1097 popup.append('<hr/>'); 1098 $('.mobile .sidebar').children().detach().appendTo(popup); 1099 $('.mobile #menu-button').on('click', function() { 1100 popup.slideToggle(300); 1101 menubuttonsvg.toggleClass('active'); 1102 }); 1103 1104 if (csrf_ham && /^https:\/\/[^/]+\/sso_redir.html/.exec(document.documentURI)) { 1105 $('form#sso').submit(); 1106 } 1107 1108 var userHiatus = $('#user_hiatus'); 1109 if (userHiatus.length > 0) { 1110 var hiatusButton = $('#user_hiatus button'); 1111 userHiatus.attr('action', '/info.html?cid='+userHiatus.data('cid')); 1112 $('#user_hiatus select').on('change', function(ev) { 1113 hiatusButton.prop('disabled', ev.target.value === ''); 1114 }); 1115 1116 userHiatus.on('submit', function() { 1117 return !hiatusButton.prop('disabled'); 1118 }); 1119 } 1120 1121 // Moderator interface 1122 if ($.fn.pModerate) { 1123 $('#user-edits tbody').pModerate(); 1124 $('#user-submits tbody').pSubmissions(); 1125 $('#refresh-comiclists').pRefreshComicLists(); 1126 } 1127});
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.