1$(document).ready(function (e) { 2 3/* $.ajax({ 4 url: '/get_max_symb', 5 type: 'POST', 6 success: function(response) { 7 $('#maxs').val(response); 8 }, 9 error: function(response) { 10 console.log(response); 11 } 12 }); */ 13 14 $('button.clear-btn').attr('disabled', true); 15 $('button.actionBtn').attr('disabled', true); 16 //$('button.checkai-btn').attr('disabled', true); 17 $('button.copy-btn').attr('disabled', true); 18 $('div.exportBtn').addClass('pointer_event_none'); 19 20 $('.download-btn').prop('disabled', true); 21 22 // start from here step-1 23 $(".input-text-orignaltext").on('keyup input', function () { 24 var words = 0; 25 // console.log(this.value, this.value.match(/\S+/g)); 26 if (this.value != null && this.value != '') { 27 words = this.value.match(/\S+/g).length; 28 $('button.clear-btn').attr('disabled', false); 29 //$('button.actionBtn').attr('disabled', false); 30 $(this).prev().hide(); 31 $(".textPasteBtn").hide(); 32 $(".upbtn1").hide(); 33 } else { 34 $('button.clear-btn').attr('disabled', true); 35 //$('button.actionBtn').attr('disabled', true); 36 $(this).prev().show(); 37 $(".textPasteBtn").show(); 38 $(".upbtn1").show(); 39 } 40 41 const getroutenamvalue = $('#getroutenamvalue').text(); 42 if (getroutenamvalue == 'index' ) { 43 var allowedWords = getLimitWord(); 44 } else { 45 var allowedWords = parseInt($('#allowedWords').text()) !== 0 ? 1500 : 250; 46 } 47 if (words > allowedWords) { 48 var trimmed = this.value; 49 words = trimmed.match(/\S+/g).length; 50 $('span.display_count').text(words); 51 $('span.display_count').addClass('text-danger'); 52 if ( i == 1 ){ 53 $("#wLimitModal").modal("show"); 54 i++; 55 } 56 } else { 57 $('span.display_count').text(words); 58 $('span.display_count').removeClass('text-danger'); 59 i = 1 ; 60 } 61 62 }); 63 64 65 function initTruncation() { 66 const $maxs = $('#maxs'); 67 if (!$maxs.length) return; 68 69 const MAX_LENGTH = parseInt($maxs.val(), 10) || 100; 70 const $textarea = $('#textInput'); 71 72 if ($textarea.length) { 73 $textarea.on('input', function() { 74 if (this.value.length > MAX_LENGTH) { 75 this.value = truncateTextByWords(this.value, MAX_LENGTH); 76 this.setSelectionRange(this.value.length, this.value.length); 77 } 78 updateCounter(); 79 }); 80 updateCounter(); 81 $('button.actionBtn').attr('disabled', false); 82 } 83 } 84 85 // ÐаблÑдаем за изменениÑми в body 86 const observer = new MutationObserver(function(mutations) { 87 if ($('#maxs').length > 0) { 88 observer.disconnect(); // оÑÑанавливаем наблÑдение 89 initTruncation(); 90 } 91 }); 92 93 observer.observe(document.body, { 94 childList: true, 95 subtree: true 96 }); 97 98 $(".textPasteBtn").on("click", function () { 99 try { 100 navigator.clipboard.readText().then((clipText) => { 101 const maxChars = $('#maxs').val(); 102 var truncText = truncateTextByWords(clipText, maxChars); 103 if (truncText != null || truncText != ""){ 104 $("#textInput").val(truncText); 105 $(".textPasteBtn").hide(); 106 $(".upbtn1").hide(); 107 $('button.clear-btn').attr('disabled', false); 108 $('button.actionBtn').attr('disabled', false); 109 110 //add the length of pasted text 111 var txtlen = $("#textInput").val().match(/\S+/g).length; 112 $("span.display_count").text(txtlen); 113 WordCountColor(txtlen); 114 updateCounter(); 115 } 116 }); 117 } catch (error) { 118 console.error("Error: "+error); 119 } 120 }); 121 122 $('.clear-btn').on('click', function () { 123 $('#textInput').val(''); //inputtextarea 124 $('span.display_count').text(0); 125 $('span#rephrase_count').text(0); 126 $(".textPasteBtn").show(); 127 $(".upbtn1").show(); 128 $('button.clear-btn').attr('disabled', true); 129 //$('button.actionBtn').attr('disabled', true); 130 //$('button.checkai-btn').attr('disabled', true); 131 $('#output_text_div').text(''); 132 $('#output_text_exp').text(''); 133 $('.placeHoldertext').attr('hidden', false); 134 135 $("#uploadFile").attr('disabled', false); 136 updateCounter(); 137 }); 138 139 $(document).on("click", "#exportPdf", function(e) { 140 var box2 = $("#output_text_exp").html(); // get HTML including spans 141 142 if (box2.trim() !== "") { 143 // Convert HTML to plain text or handle span parsing (if needed) 144 let tempDiv = document.createElement("div"); 145 tempDiv.innerHTML = box2; 146 147 // Optional: clean or convert span styles (e.g., bold, color) here 148 let textWithFormatting = [];
149 tempDiv.childNodes.forEach(node => { 150 if (node.nodeType === Node.TEXT_NODE) { 151 textWithFormatting.push({ text: node.textContent }); 152 } else if (node.nodeType === Node.ELEMENT_NODE) { 153 if (node.tagName === "SPAN") { 154 let color = node.style.color || "#000000"; 155 let fontWeight = node.style.fontWeight === "bold" ? true : false; 156 157 textWithFormatting.push({ 158 text: node.textContent, 159 color: color, 160 bold: fontWeight 161 }); 162 } else { 163 textWithFormatting.push({ text: node.textContent }); 164 } 165 } 166 }); 167 168 // Prepare the document 169 var docDefinition = { 170 content: [ 171 { 172 text: textWithFormatting, 173 fontSize: 12, 174 font: 'TimesNewRoman' 175 } 176 ], 177 defaultStyle: { 178 font: 'TimesNewRoman' 179 }, 180 info: { 181 title: 'RewriteGPT' 182 } 183 }; 184 185 pdfMake.createPdf(docDefinition).download("result_SokratiAI.pdf"); 186 } else { 187 console.log("Please enter some text!"); 188 $(".boxs p").html("Please enter some text!"); 189 $("#largeFileAlert").removeClass("d-none"); 190 setTimeout(function () { 191 $("#largeFileAlert").addClass("d-none"); 192 }, 3000); 193 } 194 }); 195 196 $(document).on("click", "#exportTxt", function (e) { 197 e.preventDefault(); 198 199 var box = $("#output_text_exp").text(); 200 if (box != "") { 201 console.log(box); 202 203 // â ÐобавлÑем BOM Ð´Ð»Ñ UTF-8 204 const bom = new Uint8Array([0xEF, 0xBB, 0xBF]); 205 const textEncoder = new TextEncoder(); 206 const textData = textEncoder.encode(box); 207 const finalData = new Uint8Array(bom.length + textData.length); 208 finalData.set(bom); 209 finalData.set(textData, bom.length); 210 211 // â СоздаÑм Blob Ñ Ð¿ÑавилÑнÑм Ñипом и даннÑми 212 const textToBLOB = new Blob([finalData], { 213 type: "text/plain;charset=utf-8" 214 }); 215 216 const sFileName = "result_SokratiAI.txt"; 217 218 let newLink = document.createElement("a"); 219 newLink.download = sFileName; 220 221 if (window.webkitURL != null) { 222 newLink.href = window.webkitURL.createObjectURL(textToBLOB); 223 } else { 224 newLink.href = window.URL.createObjectURL(textToBLOB); 225 newLink.style.display = "none"; 226 document.body.appendChild(newLink); 227 } 228 229 newLink.click(); 230 231 // â ÐÑиÑÑка URL 232 setTimeout(() => { 233 window.URL.revokeObjectURL(newLink.href); 234 if (newLink.parentNode) { 235 document.body.removeChild(newLink); 236 } 237 }, 100); 238 239 } else { 240 $(".boxs p").html("Please enter some text!"); 241 $("#largeFileAlert").removeClass("d-none"); 242 setTimeout(function () { 243 $("#largeFileAlert").addClass("d-none"); 244 }, 3000); 245 } 246 }); 247 248 $('.input-file input[type=file]').on('change', function(){ 249 let file = this.files[0]; 250 $(this).next().html(file.name); 251 }); 252 253 $('#uploadFile').on('change', handleFileUpload); 254 255 // ФÑнкÑÐ¸Ñ Ð¾Ð±ÑабоÑки загÑÑзки Ñайла 256 function handleFileUpload(e) { 257 const file = e.target.files[0]; 258 const textArea = $('#textInput'); 259 const maxChars = $('#maxs').val(); 260 const fileSize = file.size; 261 262 // ÐÑовеÑка базовÑÑ ÑÑловий 263 if (!file) return; 264 if (fileSize > 50 * 1024 * 1024) { // ÐгÑаниÑение 50MB 265 showStatus('Файл ÑлиÑком болÑÑой (макÑимÑм 50MB)', true); 266 return; 267 } 268 269 const fileExtension = file.name.split('.').pop().toLowerCase(); 270 const allowedExtensions = ['txt', 'doc', 'docx']; 271 const fileName = file.name.toLowerCase(); 272 273 if (!allowedExtensions.includes(fileExtension)) { 274 showStatus('РазÑеÑÐµÐ½Ñ ÑолÑко ÑÐ°Ð¹Ð»Ñ Ñ ÑаÑÑиÑениÑми: .txt, .doc, .docx', true); 275 return; 276 } 277 278 $(".upbtn1").prop("disabled", true); 279 $(".upbtn1 .loadSpinner").removeClass("d-none"); 280 281 //$(this).prop( "disabled", true ); 282 $('.loader').show(); 283 284 switch(fileExtension) { 285 case 'txt': 286 handleTextFile(file, textArea, maxChars); 287 break; 288 289 case 'docx': 290 handleDocxFile(file, textArea, maxChars); 291 break; 292 293 case 'doc': 294 handleDocFile(file, maxChars); 295 //newOrderActionsMsg('ÐзвиниÑе, ÑÑение .'+fileExtension+' Ñайлов не поддеÑживаеÑÑÑ'); 296 break; 297 298 default: 299 newOrderActionsMsg('ÐагÑÑзиÑе Ñайл в ÑоÑмаÑе txt,doc,docx или вÑÑавÑÑе ÑекÑÑом'); 300 showStatus('ÐеподдеÑживаемÑй ÑоÑÐ¼Ð°Ñ Ñайла',true); 301 break; 302 } 303 } 304 305 // ÐбÑабоÑка ÑекÑÑовÑÑ Ñайлов
306 function handleTextFile(file, textArea, maxChars) { 307 const reader = new FileReader(); 308 309 reader.onload = function(e) { 310 let content = e.target.result; 311 const truncated = truncateTextByWords(content, maxChars); 312 313 $(".upbtn1 .loadSpinner").addClass("d-none"); 314 $(".upbtn1").prop("disabled", false); 315 $("#uploadFile").val(""); 316 317 $("#textInput").val(truncated); 318 319 $(".textPasteBtn").hide(); 320 $('button.actionBtn').attr('disabled', false); 321 $('button.clear-btn').attr('disabled', false); 322 323 $(".upbtn1").hide(); 324 var txtlen = $("#textInput").val().match(/\S+/g).length; 325 $("span.display_count").text(txtlen); 326 WordCountColor(txtlen); 327 updateCounter(); 328 }; 329 330 reader.onerror = function() { 331 console.log('ÐÑибка ÑÑÐµÐ½Ð¸Ñ Ñайла'); 332 }; 333 334 reader.readAsText(file, "UTF-8"); 335 } 336 337 // ÐбÑабоÑка DOC Ñайлов ÑеÑез php 338 function handleDocFile(file,maxChars) { 339 const textArea = $('#textInput'); 340 const formData = new FormData(); 341 //const maxChars = $('#maxs').val(); 342 formData.append('file', file); 343 344 $.ajax({ 345 url: '/convert', 346 type: 'POST', 347 data: formData, 348 cache : false, 349 processData: false, 350 contentType: false, 351 success: function(res) { 352 //console.log(res.file); 353 if(res.ok){ 354 355 // ÐагÑÑжаем Ñайл Ñ ÑеÑвеÑа как Blob 356 fetch(res.file) 357 .then(response => { 358 if (!response.ok) { 359 throw new Error("ÐÑибка загÑÑзки docx"); 360 } 361 return response.blob(); // ÐолÑÑаем как Blob 362 }) 363 .then(blob => { 364 // ÐÑевÑаÑаем blob в Ñайл-подобнÑй обÑÐµÐºÑ 365 const file = new File([blob], res.file, { type: blob.type }); 366 handleDocxFile(file,textArea,maxChars); // пеÑедаÑм в ÑÑÑеÑÑвÑÑÑÑÑ ÑÑнкÑÐ¸Ñ 367 }) 368 .catch(err => { 369 console.error("ÐÑибка обÑабоÑки docx:", err); 370 }); 371 } 372 373 }, 374 error: function(res) { 375 console.log(res); 376 } 377 }); 378 379 } 380 381 //ÑÐµÐ¶ÐµÑ ÑекÑÑ Ð´Ð¾ maxLength Ñимолов по Ñловам (ÑÑÐ¾Ð±Ñ Ð½Ðµ обÑÑваÑÑ Ñлово поÑÑеди) 382 function truncateTextByWords(text, maxLength) { 383 if (text.length <= maxLength) { 384 return text; 385 } 386 387 // ÐбÑезаем до maxLength и ÑдалÑем поÑледнее неполное Ñлово 388 const truncated = text.substring(0, maxLength); 389 const lastSpaceIndex = truncated.lastIndexOf(' '); 390 391 // ÐÑли еÑÑÑ Ð¿Ñобел, обÑезаем до него 392 if (lastSpaceIndex > 0) { 393 return truncated.substring(0, lastSpaceIndex) + '...'; 394 } 395 396 // ÐÑли Ð½ÐµÑ Ð¿Ñобелов â возвÑаÑаем пÑоÑÑо обÑезаннÑй ÑекÑÑ 397 return truncated + '...'; 398 } 399 400 // ÐбÑабоÑка DOCX Ñайлов 401 function handleDocxFile(file, textArea, maxChars) { 402 const reader = new FileReader(); 403 //console.log(reader); 404 reader.onload = function(e) { 405 const arrayBuffer = e.target.result; 406 mammoth.extractRawText({ arrayBuffer }) 407 .then(function(result) { 408 let content = result.value; 409 const truncated = truncateTextByWords(content, maxChars); 410 411 $(".upbtn1 .loadSpinner").addClass("d-none"); 412 $(".upbtn1").prop("disabled", false); 413 $("#uploadFile").val(""); 414 415 $("#textInput").val(truncated); 416 417 $(".textPasteBtn").hide(); 418 $('button.actionBtn').attr('disabled', false); 419 $('button.clear-btn').attr('disabled', false); 420 421 $(".upbtn1").hide(); 422 var txtlen = $("#textInput").val().match(/\S+/g).length; 423 $("span.display_count").text(txtlen); 424 WordCountColor(txtlen); 425 updateCounter(); 426 427 if(truncated.length > maxChars){ 428 $('#msg').html('ТекÑÑ Ð´Ð¾Ð»Ð¶ÐµÐ½ ÑодеÑжаÑÑ Ð½Ðµ более 300к Ñимволов.').show().delay(2000).fadeOut(300);
429 $(textArea).prop('disabled', true); 430 $('.check-button').prop('disabled', true); 431 newOrderActions(); 432 } 433 }) 434 .catch(function(error) { 435 console.log('ÐÑибка обÑабоÑки DOC,DOCX: ${error.message}'); 436 }); 437 }; 438 439 reader.onerror = function() { 440 showStatus('ÐÑибка ÑÑÐµÐ½Ð¸Ñ Ñайла',true); 441 }; 442 443 reader.readAsArrayBuffer(file); 444 } 445 446 // ÐÑпомогаÑелÑнÑе ÑÑнкÑии 447 function showError(message) { 448 showNotification(message, 'error'); 449 } 450 451 function showInfo(message) { 452 showNotification(message, 'info'); 453 } 454 455 function showNotification(message, type) { 456 const notification = $('#resultContainer'); 457 notification.removeClass('error info').addClass(type); 458 notification.text(message); 459 notification.fadeIn(200).delay(5000).fadeOut(200); 460 } 461 462 function newOrderActions() { 463 $('.check-button').hide(); 464 $('.input-file input').prop( "disabled", true ); 465 $('.another').show(); 466 } 467 468 function newOrderActionsMsg(msg){ 469 $('#msg').html(msg).show().delay(2000).fadeOut(300); 470 $('.loader').hide(); 471 $('.input-file input').prop( "disabled", false ); 472 $('.input-file span').html('ÐÑбеÑиÑе Ñайл'); 473 } 474 475 function extractTextFromDocx(arrayBuffer) { 476 var zip = new JSZip(); 477 zip.loadAsync(arrayBuffer).then(function(zip) { 478 return zip.file("word/document.xml").async("string"); 479 }).then(function(content) { 480 var parser = new DOMParser(); 481 var xmlDoc = parser.parseFromString(content, "text/xml"); 482 var body = xmlDoc.getElementsByTagName("w:body")[0]; 483 var textNodes = body.getElementsByTagName("w:t"); 484 var text = ""; 485 for (var i = 0; i < textNodes.length; i++) { 486 text += textNodes[i].textContent + " "; 487 } 488 $('#textInput').val(text.trim()); 489 updateCounter() 490 $('.loader').hide(); 491 }); 492 } 493 494 document.querySelectorAll('.scroll-link').forEach(anchor => { 495 anchor.addEventListener('click', function (e) { 496 e.preventDefault(); 497 const targetId = this.getAttribute('data-target'); 498 const targetElement = document.getElementById(targetId); 499 if (targetElement) { 500 targetElement.scrollIntoView({ 501 behavior: 'smooth' 502 }); 503 } 504 }); 505 }); 506 507 function changeCount() { 508 $.ajax({ 509 url: '/counter_change', 510 type: 'POST', 511 success: function(response) { 512 $('.count_check span').html(response.count_value); 513 }, 514 error: function(response) { 515 console.log(response); 516 } 517 }); 518 519 //return false; 520 } 521 522 $("#fileBtn, #fileBtn1").on("click", function () { 523 var text = document.getElementById("uploadFile").click(); 524 }); 525 526 let i = 1 ; 527 //word count color 528 function WordCountColor(words) { 529 const getRouteNameValue = $('#getroutenamvalue').text(); 530 const allowedWordsElement = parseInt($('#allowedWords').text()); 531 let allowedWords; 532 533 if (getRouteNameValue === 'index') { 534 allowedWords = getLimitWord(); 535 } else { 536 allowedWords = allowedWordsElement !== 0 ? 1500 : 250; 537 } 538 539 if (words > allowedWords) { 540 $('span.display_count').addClass('text-danger'); 541 if ( i == 1 ){ 542 $("#wLimitModal").modal("show"); 543 i++; 544 } 545 } else { 546 $('span.display_count').removeClass('text-danger'); 547 i = 1; 548 } 549 } 550 551 552 // simultaneously 553 const inputTextarea = document.getElementById('textInput'); 554 const outputTextDiv = document.getElementById('output_text_div'); 555 556 // Function to update scrollbar visibility 557 function updateScrollbars() { 558 inputTextarea.style.overflowY = inputTextarea.value.trim() ? 'auto' : 'hidden'; 559 outputTextDiv.style.overflowY = outputTextDiv.innerText.trim() ? 'auto' : 'hidden'; 560 } 561 562 // Sync scroll positions 563 function syncScroll(source, target) { 564 target.scrollTop = source.scrollTop; 565 } 566 567 // --- ФÑнкÑÐ¸Ñ Ð´Ð»Ñ Ð¾ÑобÑÐ°Ð¶ÐµÐ½Ð¸Ñ ÑÑаÑÑÑа --- 568 function showStatus(message, isError = false) { 569 const statusDiv = $('#status-message'); 570 //console.log(message); 571 statusDiv.html(message); 572 statusDiv.removeClass('text-success text-danger'); 573 if (isError) { 574 statusDiv.addClass('text-danger'); 575 // ÐÑиÑÑиÑÑ ÑообÑение ÑеÑез 3 ÑекÑÐ½Ð´Ñ 576 setTimeout(() => { 577 if (statusDiv.html() === message) { 578 statusDiv.html(''); 579 statusDiv.removeClass('text-danger'); 580 } 581 }, 3000); 582 } else { 583 statusDiv.addClass('text-success'); 584 } 585 } 586 587 function updateCounterEnd() { 588 const text = $('#output_text_div').text(); 589 const words = text.trim().split(/\s+/).filter(word => word.length > 0).length; 590 const characters = text.length; 591 document.getElementById('rephrase_count').textContent = `Символов: ${characters} | Слов: ${words}`; 592 } 593 594 $('#process-btn').click(function() { 595 596 var percent_compress = 100-parseInt($("#percent_compress").val()), 597 protect_numbers = $("#protect_important_numbers").val(); 598 const text = $('#textInput').val().trim(); 599 600 if (!text) { 601 showStatus('ÐожалÑйÑÑа, введиÑе ÑекÑÑ', true); 602 return; 603 } 604 if ((percent_compress<5) || (percent_compress>95)) { 605 showStatus('ÐÑоÑÐµÐ½Ñ % ÑжаÑÐ¸Ñ ÑекÑÑа должен бÑÑÑ Ð¾Ñ 5 до 95%', true); 606 return; 607 } 608 //console.log(percent_compress); 609 const startTime = performance.now(); 610 611 // ÐлокиÑÑем ÐºÐ½Ð¾Ð¿ÐºÑ Ð½Ð° вÑÐµÐ¼Ñ Ð·Ð°Ð¿ÑоÑа 612 const processBtn = $(this); 613 614 const originalHtml = processBtn.html(); 615 processBtn.prop('disabled', true).html('<span class="spinner-border spinner-border-sm mr-2" role="status" aria-hidden="true"></span> ÐбÑабоÑка...'); 616 $(".bodyArea").addClass("disabled"); 617 618/* let timerInterval = setInterval(() => {
619 const elapsed = ((performance.now() - startTime) / 1000).toFixed(1); 620 $('#status-message').html('ÐÑÐµÐ¼Ñ Ð¾Ð±ÑабоÑки: '+elapsed+ 'Ñек.'); 621 }, 100); */ 622 623/* console.log(JSON.stringify({ 624 text: text, 625 keep_ratio_percent: percent_compress, 626 preserve_structure: protect_numbers 627 })); */ 628 629 $.ajax({ 630 url: '/api/summarize', 631 type: 'POST', 632 contentType: 'application/json', 633 data: JSON.stringify({ 634 text: text, 635 keep_ratio_percent: percent_compress, 636 preserve_structure: protect_numbers 637 }), 638 dataType: 'json', 639 beforeSend: function() { 640 $('#result').html('<p>ÐнализиÑÑем...</p>').show(); 641 }, 642 success: function(response) { 643 //console.log(percent_compress); 644 //console.log(response); 645 646 $('#result').html(''); 647 $('div#output_text_div').html(response.summary_text); 648 $('div#output_text_exp').html(response.summary_text); 649 $('.placeHoldertext').attr('hidden', false); 650 $('button.copy-btn').attr('disabled', false); 651 $('.placeHoldertext').attr('hidden', true); 652 $('div.exportBtn').removeClass('pointer_event_none').removeClass('disabled'); 653 $('.win2').css('display', 'block'); 654 $('.win2').addClass('win3'); 655 showStatus(response.message, false); 656 $('.bodyArea').removeClass('disabled'); 657 658 $('.clear').hide(); 659 //$('.clear-btn').hide(); 660 //$('#process-btn').hide(); 661 //$('#process-btn').hide(); 662 processBtn.prop('disabled', false).text('СокÑаÑиÑÑ ÑекÑÑ ÐµÑе Ñаз'); 663 //$('#process-btn'); 664 $('#afterblock').removeClass('d-none'); 665 666 const highlightedHtml = highlightRemovedText(text,response.spans); 667 668 var resultHtml = `<div id="watermark"></div> 669 <div class="result reportArea" id="reportArea"> 670 <div class="row"> 671 <h3 class="col-8 col-md-10 mb-4">ÐÑÑÐµÑ Ð¿Ð¾ ÑжаÑÐ¸Ñ ÑекÑÑа</h3> 672 <span class="col-4 col-md-2"><img src="/theme/img/sokrati_logo.webp" class="logo-icon mr-2">Sokrati.AI</span> 673 </div> 674 <div class="row explanation"> 675 <p><span style="color:#5A2D91">ðª - ФиолеÑовÑм Ñоном вÑделен ÑекÑÑ, коÑоÑÑй бÑл Ñдален</span> </p> 676 </div> 677 <div class="row ml-1"> 678 Удалено пÑедоженией ${response.stats.removed} из ${response.stats.total} (ÐÑÑавлено: ${response.stats.kept}) 679 </div> 680 <div class="row pt-4"> 681 <div class="col-md-12" id="content-to-export"> 682 ${highlightedHtml} 683 </div> 684 </div> 685 </div> 686 <p class="text-center inbuttons"> 687 <button class="btn btn-danger1 mb-2" id="screenshotBtn3">Ð¡Ð¾Ñ ÑаниÑÑ Ð¾ÑÑеÑ</button> 688 689 </p> 690 <div class="loader_btn"></div>`; 691 692 $('div#report-container').html(resultHtml); 693 //document.getElementById('report-container').innerHTML = highlightedHtml; 694 695 updateCounterEnd() 696 changeCount(); 697 698 699 700 }, 701 error: function(xhr, status, error) { 702 let msg = 'ÐÑоизоÑла оÑибка пÑи анализе.'; 703 if (xhr.responseJSON && xhr.responseJSON.detail) { 704 msg = xhr.responseJSON.detail; 705 } 706 $('#result').html(msg); 707 } 708 }); 709 710 711 }); 712 713 // ÐбÑабоÑÑик Ð´Ð»Ñ ÐºÐ½Ð¾Ð¿ÐºÐ¸ "анализ ÑекÑÑа" 714 $('#detailedAnalysisButton').click(function(e) { 715 e.preventDefault(); 716 $('#detailedAnalysisTable').toggle(); 717 }); 718 719/** 720 * ÐодÑвеÑÐ¸Ð²Ð°ÐµÑ ÑдалÑннÑе ÑÑагменÑÑ ÑекÑÑа. 721 * @param {string} text - ÐолнÑй иÑÑ Ð¾Ð´Ð½Ñй ÑекÑÑ. 722 * @param {Array<Array<number>>} spans - ÐаÑÑив Ñпанов [[start, end], ...] 723 * @returns {string} - HTML-ÑÑÑока Ñ Ð¿Ð¾Ð´ÑвеÑеннÑми ÑÑаÑÑками. 724 */ 725function highlightRemovedText(text, spans) { 726 if (!spans || spans.length === 0) { 727 return text.replace(/\n/g, '<br>'); 728 } 729 730 // СоÑÑиÑÑем ÑÐ¿Ð°Ð½Ñ Ð¿Ð¾ возÑаÑÑÐ°Ð½Ð¸Ñ start (на вÑÑкий ÑлÑÑай) 731 const sortedSpans = [...spans].sort((a, b) => a[0] - b[0]); 732 733 let result = ''; 734 let lastEnd = 0; 735 736 for (const [start, end] of sortedSpans) { 737 // ÐобавлÑем ÑекÑÑ Ð´Ð¾ наÑала ÑдалÑнного ÑÑагменÑа 738 if (start > lastEnd) { 739 result += escapeHtml(text.slice(lastEnd, start)); 740 } 741
742 // ÐобавлÑем ÑдалÑннÑй ÑÑÐ°Ð³Ð¼ÐµÐ½Ñ Ð² обÑÑÑке 743 const removedFragment = text.slice(start, end); 744 result += `<span class="removed">${escapeHtml(removedFragment)}</span>`; 745 746 lastEnd = end; 747 } 748 749 // ÐобавлÑем оÑÑаÑок ÑекÑÑа поÑле поÑледнего Ñпана 750 if (lastEnd < text.length) { 751 result += escapeHtml(text.slice(lastEnd)); 752 } 753 754 // ÐаменÑем пеÑеноÑÑ ÑÑÑок на <br> Ð´Ð»Ñ ÐºÐ¾ÑÑекÑного оÑобÑÐ°Ð¶ÐµÐ½Ð¸Ñ Ð² HTML 755 return result.replace(/\n/g, '<br>'); 756} 757 758/** 759 * ÐкÑаниÑÑÐµÑ HTML-ÑÐ¸Ð¼Ð²Ð¾Ð»Ñ Ð´Ð»Ñ Ð±ÐµÐ·Ð¾Ð¿Ð°ÑноÑÑи. 760 */ 761function escapeHtml(unsafe) { 762 return unsafe 763 .replace(/&/g, "&") 764 .replace(/</g, "<") 765 .replace(/>/g, ">") 766 .replace(/"/g, """) 767 .replace(/'/g, "'"); 768} 769 770 771 // OnClick Copy button 1 Text 772 $(".copy-btn").click(function () { 773 774 if ($("#output_text_div").text() != "") { 775 let divText = $("#output_text_exp").text(); 776 navigator.clipboard.writeText(divText); 777 $("#copyAlert").removeClass("d-none"); 778 779 setTimeout(function () { 780 $("#copyAlert").addClass("d-none"); 781 }, 2000); 782 } else { 783 $("#copyAlert").addClass("d-none"); 784 } 785 786 }); 787 788 $(document).on('click','#screenshotBtn',function(){ 789 790 const inButtons = $('.inbuttons'); 791 const originalDisplay = inButtons.css('display'); 792 //inButtons.css('display', 'none'); 793 $('.loader_btn').show(); 794 $('body').addClass('body_loader'); 795 const now = new Date(); 796 function padZero(num) { 797 return num < 10 ? "0" + num : num; 798 } 799 const filename = `report_SokratiAI_${padZero(now.getDate())}${padZero(now.getMonth() + 1)}${String(now.getFullYear()).slice(-2)}_${padZero(now.getHours())}${padZero(now.getMinutes())}${padZero(now.getSeconds())}`; 800 801 const targetElement = $('.reportArea')[0]; 802 const watermark = $('#watermark')[0]; 803 804 // Создаем вÑеменнÑй конÑÐµÐ¹Ð½ÐµÑ Ð´Ð»Ñ Ð¾Ð±ÑÐµÐ´Ð¸Ð½ÐµÐ½Ð¸Ñ Ð¾Ñновного ÑлеменÑа и водÑного знака
805 const tempContainer = $('<div></div>'); 806 tempContainer.css({ 807 position: 'relative', 808 width: targetElement.offsetWidth + 'px', 809 height: targetElement.offsetHeight + 'px' 810 }); 811 812 // ÐлониÑÑем оÑновной ÑÐ»ÐµÐ¼ÐµÐ½Ñ Ð¸ водÑной знак 813 const targetClone = $(targetElement).clone(); 814 const watermarkClone = $(watermark).clone(); 815 816 // УÑÑанавливаем ÑÑили Ð´Ð»Ñ ÐºÐ»Ð¾Ð½Ð¾Ð² 817 targetClone.css({ 818 position: 'absolute', 819 top: '0', 820 left: '0', 821 zIndex: '1' 822 }); 823 824 watermarkClone.css({ 825 position: 'absolute', 826 top: '50%', 827 left: '50%', 828 transform: 'translate(-50%, -50%) rotate(-5deg)', 829 color: 'rgba(255, 0, 0, 0.5)', 830 fontSize: '24px', 831 zIndex: '2', 832 whiteSpace: 'nowrap', 833 pointerEvents: 'none', 834 display: 'flex', 835 flexDirection: 'column', 836 alignItems: 'center', 837 justifyContent: 'center', 838 height: '100%', 839 width: '100%', 840 transformOrigin: 'center' 841 }); 842 843 // ÐобавлÑем клониÑованнÑе ÑлеменÑÑ Ð² вÑеменнÑй конÑÐµÐ¹Ð½ÐµÑ 844 tempContainer.append(targetClone); 845 tempContainer.append(watermarkClone); 846 847 // ÐобавлÑем вÑеменнÑй конÑÐµÐ¹Ð½ÐµÑ Ð² докÑÐ¼ÐµÐ½Ñ 848 $('body').append(tempContainer); 849 850 domtoimage.toPng(tempContainer[0]).then(function(dataUrl) { 851 // УдалÑем вÑеменнÑй конÑÐµÐ¹Ð½ÐµÑ Ð¿Ð¾Ñле ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ Ñнимка 852 tempContainer.remove(); 853 854 // Создаем ÑÑÑÐ»ÐºÑ Ð´Ð»Ñ ÑкаÑÐ¸Ð²Ð°Ð½Ð¸Ñ Ñайла 855 const link = $('<a></a>'); 856 link.attr('href', dataUrl); 857 link.attr('download', `${filename}.png`); 858 $('body').append(link); 859 link[0].click(); 860 link.remove(); 861 $('.loader_btn').hide(); 862 $('body').removeClass('body_loader'); 863 // ÐоÑÑÑанавливаем оÑобÑажение кнопок 864 //inButtons.css('display', originalDisplay); 865 }).catch(function(error) { 866 $('.loader_btn').hide(); 867 $('body').removeClass('body_loader'); 868 //inButtons.css('display', originalDisplay); 869 console.log("ÐÑибка пÑи Ñоздании ÑкÑинÑоÑа: " + error); 870 }); 871 }); 872 873 document.body.addEventListener('click', function(e) { 874 if (e.target && e.target.id === 'screenshotBtn3') { 875 const element = document.getElementById('content-to-export'); 876 877 const content = convertHtmlToPdfMakeContent(element.innerHTML); 878 879 const docDefinition = { 880 content: [ 881 { 882 text: content, 883 fontSize: 12 884 } 885 ], 886 defaultStyle: { 887 font: 'TimesNewRoman' // или дÑÑгой ÑÑиÑÑ Ñ ÐºÐ¸ÑиллиÑей 888 } 889 }; 890 891 pdfMake.createPdf(docDefinition).download('report_SokratiAI_text.pdf'); 892 } 893 }); 894 895 896 function convertHtmlToPdfMakeContent(html) { 897 const tempDiv = document.createElement('div'); 898 tempDiv.innerHTML = html; 899 900 const result = []; 901 902 function traverse(node) { 903 if (node.nodeType === Node.TEXT_NODE) { 904 result.push(node.textContent); 905 } else if (node.nodeType === Node.ELEMENT_NODE) { 906 if (node.tagName === 'BR') { 907 result.push('\n'); 908 } else if (node.classList.contains('removed')) { 909 result.push({ 910 text: node.textContent, 911 background: '#E6D8FF' // или дÑÑгой ÑÐ²ÐµÑ 912 }); 913 } else { 914 for (let child of node.childNodes) { 915 traverse(child); 916 } 917 } 918 } 919 } 920 921 for (let child of tempDiv.childNodes) { 922 traverse(child); 923 } 924 925 return result; 926 } 927 928 929});
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.