1/* 2 * change-request.js â вÑÑÑоеннÑй Ð²Ð¸Ð´Ð¶ÐµÑ Â«ÐÑедложиÑÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸ÐµÂ» Ð´Ð»Ñ ÑайÑа antishkola.com 3 * 4 * ÐнÑегÑиÑован Ñ Ð±Ð°Ð·Ð¾Ð¹ даннÑÑ Ð¸ ÑиÑÑемой change_requests ÐаÑии (src/maria/change_requests.py). 5 * ÐагÑÑжаеÑÑÑ Ð¢ÐÐЬÐРлениво по Ñ Ð¾ÑÐºÐµÑ (Cmd+Shift+B / Ctrl+Shift+B) или ÑÑÐ¾Ð¹Ð½Ð¾Ð¼Ñ ÑапÑ. 6 * Ðе влиÑÐµÑ Ð½Ð° ÑкоÑоÑÑÑ ÑайÑа, SEO и Core Web Vitals обÑÑнÑÑ Ð¿Ð¾ÑеÑиÑелей. 7 */ 8(function () { 9 'use strict'; 10 11 if (window.__antishkolaCRObject) return; 12 13 var recentErrors = []; 14 var origError = window.console && window.console.error; 15 if (origError) { 16 window.console.error = function () { 17 try { 18 var msg = Array.prototype.slice.call(arguments).map(String).join(' '); 19 recentErrors.push(msg.slice(0, 300)); 20 if (recentErrors.length > 5) recentErrors.shift(); 21 } catch (_) {} 22 origError.apply(window.console, arguments); 23 }; 24 } 25 26 var STYLES = '' + 27 '#as-cr-overlay {' + 28 ' position: fixed; inset: 0; z-index: 2147483647; background: rgba(10,15,18,0.78);' + 29 ' backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);' + 30 ' display: flex; align-items: center; justify-content: center; padding: 16px;' + 31 ' font-family: -apple-system, BlinkMacSystemFont, "Manrope", "Segoe UI", Roboto, sans-serif;' + 32 ' opacity: 0; pointer-events: none; transition: opacity 0.2s cubic-bezier(0.4,0,0.2,1);' + 33 '}' + 34 '#as-cr-overlay.is-visible { opacity: 1; pointer-events: auto; }' + 35 '#as-cr-modal {' + 36 ' width: 100%; max-width: 520px; background: #0A0F12; color: #fff;' + 37 ' border: 1px solid rgba(255,255,255,0.14); border-radius: 20px;' + 38 ' box-shadow: 0 24px 60px rgba(0,0,0,0.6), 0 0 0 1px rgba(217,22,176,0.2);' + 39 ' overflow: hidden; display: flex; flex-direction: column;' + 40 ' transform: scale(0.96) translateY(10px); transition: transform 0.25s cubic-bezier(0.4,0,0.2,1);' + 41 '}' + 42 '#as-cr-overlay.is-visible #as-cr-modal { transform: scale(1) translateY(0); }' + 43 '#as-cr-header {' + 44 ' padding: 18px 22px 14px; border-bottom: 1px solid rgba(255,255,255,0.08);' + 45 ' display: flex; align-items: center; justify-content: space-between;' + 46 '}' + 47 '#as-cr-header h3 {' + 48 ' margin: 0; font-size: 17px; font-weight: 700; color: #fff;' + 49 ' display: flex; align-items: center; gap: 8px;' + 50 '}' + 51 '#as-cr-header h3 span { color: #d916b0; font-size: 18px; }' + 52 '#as-cr-close {' + 53 ' background: rgba(255,255,255,0.08); border: 1px solid rgba(255,255,255,0.12);' + 54 ' color: #fff; width: 32px; height: 32px; border-radius: 8px; cursor: pointer;' + 55 ' display: flex; align-items: center; justify-content: center; font-size: 16px;' + 56 ' transition: 0.15s;' + 57 '}' + 58 '#as-cr-close:hover { background: rgba(255,255,255,0.18); }' + 59 '#as-cr-body { padding: 18px 22px 22px; display: flex; flex-direction: column; gap: 14px; }' + 60 '.as-cr-row { display: flex; flex-direction: column; gap: 6px; }' + 61 '.as-cr-row label { font-size: 12.5px; font-weight: 600; color: rgba(255,255,255,0.7); }' + 62 '.as-cr-input, .as-cr-textarea {' + 63 ' width: 100%; background: rgba(255,255,255,0.05); border: 1px solid rgba(255,255,255,0.14);' + 64 ' border-radius: 10px; padding: 11px 14px; font-size: 14.5px; color: #fff;' + 65 ' font-family: inherit; box-sizing: border-box; outline: none; transition: 0.2s;' + 66 '}' + 67 '.as-cr-input:focus, .as-cr-textarea:focus {' + 68 ' border-color: #d916b0; background: rgba(255,255,255,0.08);' + 69 ' box-shadow: 0 0 0 3px rgba(217,22,176,0.2);' + 70 '}' + 71 '.as-cr-textarea { resize: vertical; min-height: 95px; line-height: 1.5; }' + 72 '#as-cr-context {' + 73 ' background: rgba(255,255,255,0.03); border: 1px solid rgba(255,255,255,0.06);' + 74 ' border-radius: 10px; padding: 10px 12px; font-size: 11.5px; color: rgba(255,255,255,0.5);' + 75 ' font-family: ui-monospace, SFMono-Regular, "JetBrains Mono", Menlo, monospace;' + 76 ' line-height: 1.45; word-break: break-all;' + 77 '}
77' + 78 '#as-cr-actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 4px; }' + 79 '.as-cr-btn {' + 80 ' padding: 11px 20px; border-radius: 10px; font-size: 14px; font-weight: 700;' + 81 ' cursor: pointer; border: none; transition: 0.15s; font-family: inherit;' + 82 '}' + 83 '.as-cr-btn-cancel {' + 84 ' background: transparent; color: rgba(255,255,255,0.6);' + 85 ' border: 1px solid rgba(255,255,255,0.12);' + 86 '}' + 87 '.as-cr-btn-cancel:hover { background: rgba(255,255,255,0.06); color: #fff; }' + 88 '.as-cr-btn-submit {' + 89 ' background: #d916b0; color: #fff; box-shadow: 0 4px 14px rgba(217,22,176,0.35);' + 90 '}' + 91 '.as-cr-btn-submit:hover { background: #b3128f; }' + 92 '.as-cr-btn-submit:disabled { opacity: 0.5; cursor: not-allowed; }' + 93 '#as-cr-success {' + 94 ' padding: 36px 20px; text-align: center; display: none;' + 95 '}' + 96 '#as-cr-success h4 { font-size: 18px; margin: 0 0 8px; color: #51cf66; }' + 97 '#as-cr-success p { font-size: 13.5px; color: rgba(255,255,255,0.7); margin: 0; }'; 98 99 function injectDOM() { 100 var style = document.createElement('style'); 101 style.id = 'as-cr-styles'; 102 style.textContent = STYLES; 103 document.head.appendChild(style); 104 105 var wrap = document.createElement('div'); 106 wrap.id = 'as-cr-overlay'; 107 wrap.setAttribute('aria-hidden', 'true'); 108 wrap.innerHTML = '' + 109 '<div id="as-cr-modal" role="dialog" aria-modal="true" aria-labelledby="as-cr-title">' + 110 ' <div id="as-cr-header">' + 111 ' <h3 id="as-cr-title"><span>ð¡</span> ÐÑедложиÑÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ðµ</h3>' + 112 ' <button type="button" id="as-cr-close" aria-label="ÐакÑÑÑÑ">â</button>' + 113 ' </div>' + 114 ' <form id="as-cr-form">' + 115 ' <div id="as-cr-body">' + 116 ' <div class="as-cr-row">' + 117 ' <label for="as-cr-author">ÐвÑоÑ:</label>' + 118 ' <input type="text" id="as-cr-author" class="as-cr-input" placeholder="ÐаÑе имÑ" required autocomplete="name">' + 119 ' </div>' + 120 ' <div class="as-cr-row">' + 121 ' <label for="as-cr-text">ЧÑо и где измениÑÑ:</label>' + 122 ' <textarea id="as-cr-text" class="as-cr-textarea" placeholder="ЧÑо и где измениÑÑ..." required></textarea>' + 123 ' </div>' + 124 ' <div id="as-cr-context"></div>' + 125 ' <div id="as-cr-actions">' + 126 ' <button type="button" class="as-cr-btn as-cr-btn-cancel" id="as-cr-cancel-btn">ÐÑмена</button>' + 127 ' <button type="submit" class="as-cr-btn as-cr-btn-submit" id="as-cr-submit-btn">ÐÑпÑавиÑÑ Ð² базÑ</button>' + 128 ' </div>' + 129 ' </div>' + 130 ' </form>' + 131 ' <div id="as-cr-success">' + 132 ' <h4>â ÐÑедложение оÑпÑавлено!</h4>' + 133 ' <p>ÐапиÑÑ Ñоздана в базе Maria CRM. СпаÑибо за помоÑÑ!</p>' + 134 ' </div>' + 135 '</div>'; 136 137 document.body.appendChild(wrap); 138 bindEvents(wrap); 139 } 140 141 function getAutoContext() { 142 var host = window.location.hostname || ''; 143 var prefix = 'website:'; 144 if (host.indexOf('playsend') !== -1) prefix = 'website:playsend:'; 145 else if (host.indexOf('nativespeakers') !== -1) prefix = 'website:ns:'; 146 else prefix = 'website:as:'; 147 148 var cur = (document.querySelector('#asp-root') && document.querySelector('#asp-root').getAttribute('data-cur')) || 'default'; 149 var path = window.location.pathname || '/'; 150 var slug = path.replace(/^\/|\/$/g, '').replace(/\//g, '_'); 151 var sectionName = prefix + (slug || 'main'); 152 153 var tz = 'unknown'; 154 try { tz = Intl.DateTimeFormat().resolvedOptions().timeZone; } catch (_) {} 155 156 return { 157 section: sectionName, 158 page_url: window.location.href, 159 referrer: document.referrer || '', 160 viewport: window.innerWidth + 'x' + window.innerHeight, 161 screen: (window.screen ? (window.screen.width + 'x' + window.screen.height) : 'unknown') + ' @' + (window.devicePixelRatio || 1) + 'x', 162 currency: cur, 163 timezone: tz, 164 language: navigator.language || '', 165 recent_errors: recentErrors.join('; '), 166 user_agent: navigator.userAgent || 'unknown' 167 }; 168 } 169 170 function openModal() {
171 var overlay = document.getElementById('as-cr-overlay'); 172 if (!overlay) { 173 injectDOM(); 174 overlay = document.getElementById('as-cr-overlay'); 175 } 176 177 var ctx = getAutoContext(); 178 var ctxBox = document.getElementById('as-cr-context'); 179 if (ctxBox) { 180 ctxBox.textContent = 'ð ' + ctx.page_url + '\nð± ÐкÑан: ' + ctx.viewport + ' | ÐалÑÑа: ' + ctx.currency; 181 } 182 183 var authorInput = document.getElementById('as-cr-author'); 184 if (authorInput) { 185 var saved = localStorage.getItem('antishkola_operator_name'); 186 if (saved) authorInput.value = saved; 187 } 188 189 var form = document.getElementById('as-cr-form'); 190 var succ = document.getElementById('as-cr-success'); 191 if (form) form.style.display = 'block'; 192 if (succ) succ.style.display = 'none'; 193 194 overlay.classList.add('is-visible'); 195 overlay.setAttribute('aria-hidden', 'false'); 196 197 var textInput = document.getElementById('as-cr-text'); 198 setTimeout(function () { 199 if (authorInput && !authorInput.value) { 200 authorInput.focus(); 201 } else if (textInput) { 202 textInput.focus(); 203 } 204 }, 150); 205 } 206 207 function closeModal() { 208 var overlay = document.getElementById('as-cr-overlay'); 209 if (!overlay) return; 210 overlay.classList.remove('is-visible'); 211 overlay.setAttribute('aria-hidden', 'true'); 212 var textInput = document.getElementById('as-cr-text'); 213 if (textInput) textInput.value = ''; 214 } 215 216 function bindEvents(overlay) { 217 var closeBtn = document.getElementById('as-cr-close'); 218 var cancelBtn = document.getElementById('as-cr-cancel-btn'); 219 var form = document.getElementById('as-cr-form'); 220 221 if (closeBtn) closeBtn.addEventListener('click', closeModal); 222 if (cancelBtn) cancelBtn.addEventListener('click', closeModal); 223 224 overlay.addEventListener('click', function (e) { 225 if (e.target === overlay) closeModal(); 226 }); 227 228 document.addEventListener('keydown', function (e) { 229 if (e.key === 'Escape' && overlay.classList.contains('is-visible')) { 230 closeModal(); 231 } 232 }); 233 234 if (form) { 235 form.addEventListener('submit', function (e) { 236 e.preventDefault(); 237 var author = (document.getElementById('as-cr-author').value || '').trim(); 238 var text = (document.getElementById('as-cr-text').value || '').trim(); 239 var submitBtn = document.getElementById('as-cr-submit-btn'); 240 241 if (!text) return; 242 if (author) localStorage.setItem('antishkola_operator_name', author); 243 244 if (submitBtn) { 245 submitBtn.disabled = true; 246 submitBtn.textContent = 'ÐÑпÑавка...'; 247 } 248 249 var ctx = getAutoContext(); 250 var payload = { 251 body: text, 252 author: author || 'operator', 253 section: ctx.section, 254 page_url: ctx.page_url, 255 context: { 256 viewport: ctx.viewport, 257 screen: ctx.screen, 258 currency: ctx.currency, 259 user_agent: ctx.user_agent, 260 recent_errors: ctx.recent_errors, 261 source: 'website_hotkey' 262 } 263 }; 264 265 fetch('https://sec.antishkola.com/change-request', { 266 method: 'POST', 267 headers: { 'Content-Type': 'application/json' }, 268 body: JSON.stringify(payload) 269 }).then(function (res) { 270 if (!res.ok) { 271 throw new Error('HTTP ' + res.status); 272 } 273 return res.json(); 274 }).then(function () { 275 showSuccess(); 276 }).catch(function (err) { 277 showError(err); 278 }); 279 }); 280 } 281 } 282 283 function showError(err) { 284 var submitBtn = document.getElementById('as-cr-submit-btn'); 285 if (submitBtn) { 286 submitBtn.disabled = false; 287 submitBtn.textContent = 'â ÐÑибка ÑеÑи. ÐовÑоÑиÑÑ?'; 288 submitBtn.style.background = '#e03131'; 289 setTimeout(function () { 290 if (submitBtn) { 291 submitBtn.textContent = 'ÐÑпÑавиÑÑ Ð² базÑ'; 292 submitBtn.style.background = '#d916b0'; 293 } 294 }, 4000); 295 } 296 } 297 298 function showSuccess() { 299 var form = document.getElementById('as-cr-form'); 300 var succ = document.getElementById('as-cr-success'); 301 var submitBtn = document.getElementById('as-cr-submit-btn'); 302 if (form) form.style.display = 'none'; 303 if (succ) succ.style.display = 'block'; 304 if (submitBtn) { 305 submitBtn.disabled = false;
306 submitBtn.textContent = 'ÐÑпÑавиÑÑ Ð² базÑ'; 307 } 308 setTimeout(closeModal, 2000); 309 } 310 311 window.__antishkolaChangeRequestOpen = openModal; 312 window.__antishkolaCRObject = true; 313})();
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.