1$(document).ready(function(){ 2 3 // ÐапÑÑкаем меÑод init, когда докÑÐ¼ÐµÐ½Ñ Ð±ÑÐ´ÐµÑ Ð³Ð¾Ñов: 4 chat.init(); 5 6}); 7 8var chat = { 9 10 // data ÑодеÑÐ¶Ð¸Ñ Ð¿ÐµÑеменнÑе Ð´Ð»Ñ Ð¸ÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð² клаÑÑÐ°Ñ : 11 data : { 12 lastID : 0, 13 noActivity : 0, 14 userInteracted : false, 15 pageLoaded : false, // Ñлаг загÑÑзки ÑÑÑаниÑÑ 16 toastAlways : true // true - ÑоÑÑ Ð¿Ñи ÐÐÐÐÐРновоÑÑи, false - ÑÐ¼Ð½Ð°Ñ Ð»Ð¾Ð³Ð¸ÐºÐ° 17 }, 18 19 // Init пÑивÑзÑÐ²Ð°ÐµÑ Ð¾Ð±ÑабоÑÑики ÑобÑÑий и ÑÑÑÐ°Ð½Ð°Ð²Ð»Ð¸Ð²Ð°ÐµÑ ÑаймеÑÑ: 20 init : function(){ 21 22 // ÐÑполÑзÑем плагин jQuery defaultText, вклÑÑеннÑй внизÑ: 23 $('#name').defaultText('УкажиÑе ÐаÑе имÑ'); 24 $('#email').defaultText(''); 25 26 // Ð¡Ð¾Ñ ÑанÑем ÑÑÑÐ»ÐºÑ Ð½Ð° конÑÐµÐ¹Ð½ÐµÑ 27 chat.data.container = $('#chatLineHolder'); 28 29 // ÐобавлÑем клаÑÑ Ð´Ð»Ñ ÑкÑолла 30 chat.data.container.addClass('native-scroll'); 31 32 // ÐÑÑлеживаем взаимодейÑÑвие полÑзоваÑÐµÐ»Ñ Ñо ÑкÑоллом 33 chat.data.container.on('scroll', function() { 34 chat.data.userInteracted = true; 35 }); 36 37 // ÐÑполÑзÑем пеÑеменнÑÑ working Ð´Ð»Ñ Ð¿ÑедоÑвÑаÑÐµÐ½Ð¸Ñ 38 // множеÑÑвеннÑÑ Ð¾ÑпÑавок ÑоÑмÑ: 39 var working = false; 40 41 // РегиÑÑÑиÑÑем пеÑÑÐ¾Ð½Ñ Ð² ÑаÑе: 42 $('#loginForm').submit(function(){ 43 44 if(working) return false; 45 working = true; 46 47 $.tzPOST('login',$(this).serialize(),function(r){ 48 working = false; 49 50 if(r.error){ 51 chat.displayError(r.error); 52 } 53 else chat.login(r.name,r.gravatar); 54 }); 55 56 return false; 57 }); 58 59 // ÐÑпÑавлÑем даннÑе новой ÑÑÑоки ÑаÑа: 60 $('#submitForm').submit(function(){ 61 62 var text = $('#chatText').val(); 63 64 if(text.length == 0){ 65 return false; 66 } 67 68 if(working) return false; 69 working = true; 70 71 // ÐенеÑиÑÑем вÑеменнÑй ID Ð´Ð»Ñ ÑаÑа: 72 var tempID = 't'+Math.round(Math.random()*1000000), 73 params = { 74 id : tempID, 75 author : chat.data.name, 76 text : text.replace(/</g,'<').replace(/>/g,'>'), 77 ip : chat.data.ip 78 }; 79 80 // ÐобавлÑем вÑеменное ÑообÑение в ÐÐÐÐЦ конÑейнеÑа 81 chat.addChatLine($.extend({},params), true); 82 83 $.tzPOST('submitChat',$(this).serialize(),function(r){ 84 working = false; 85 86 $('#chatText').val(''); 87 $('div.chat-'+tempID).remove(); 88 89 params['id'] = r.insertID; 90 // ÐобавлÑем поÑÑоÑнное ÑообÑение в ÐÐÐÐЦ конÑейнеÑа 91 chat.addChatLine($.extend({},params), false); 92 }); 93 94 return false; 95 }); 96 97 // ÐÑклÑÑаем полÑзоваÑелÑ: 98 $('#chatContainer').on('click', '.logoutButton', function(){ 99 100 $('#chatTopBar > span').fadeOut(function(){ 101 $(this).remove(); 102 }); 103 104 $('#submitForm').fadeOut(function(){ 105 $('#loginForm').fadeIn(); 106 }); 107 108 $.tzPOST('logout'); 109 110 return false; 111 }); 112 113 // ÐÑовеÑÑем ÑоÑÑоÑние подклÑÑÐµÐ½Ð¸Ñ Ð¿Ð¾Ð»ÑзоваÑÐµÐ»Ñ 114 $.tzGET('checkLogged',function(r){ 115 if(r.logged){ 116 chat.login(r.loggedAs.name,r.loggedAs.gravatar); 117 } 118 }); 119 120 // ÐапÑÑкаем полÑÑение новÑÑ ÑообÑений 121 (function getChatsTimeoutFunction(){ 122 chat.getChats(getChatsTimeoutFunction); 123 })(); 124 125 }, 126 127 login : function(name){ 128 129 chat.data.name = name; 130 $('#chatTopBar').html(chat.render('loginTopBar',chat.data)); 131 132 $('#loginForm').fadeOut(function(){ 133 $('#submitForm').fadeIn(); 134 $('#chatText'); 135 }); 136 137 }, 138 139// ÐеÑод Ð´Ð»Ñ Ð¿ÑбликаÑии новоÑÑи ÑеÑез Web Share API 140shareNews: function(text, url, fullText) { 141 if (typeof ym !== 'undefined') { 142 ym('24810671', 'reachGoal', 'share_news'); 143 } 144 // ÐекодиÑÑем ÑекÑÑ Ð´Ð»Ñ Ð¾ÑобÑÐ°Ð¶ÐµÐ½Ð¸Ñ 145 var decodedText = decodeURIComponent(text); 146 var decodedUrl = decodeURIComponent(url); 147 var decodedFullText = fullText ? decodeURIComponent(fullText) : decodedText; 148 149 // ÐобавлÑем паÑамеÑÑ share=news к URL 150 var shareUrl = decodedUrl; 151 if (shareUrl.indexOf('?') === -1) { 152 shareUrl += '?share=news'; 153 } else { 154 shareUrl += '&share=news'; 155 } 156 157 // ФоÑмиÑÑем единÑй ÑекÑÑ Ð´Ð»Ñ Ð¾ÑпÑавки 158 var shareText = decodedFullText + '\n\n' + shareUrl; 159 160 // ÐÑполÑзÑем Web Share API 161 if (navigator.share) { 162 navigator.share({ 163 title: 'ÐовоÑÑÑ', 164 text: shareText 165 }) 166 .catch(function(error) { 167 console.log('ÐоделиÑÑÑÑ Ð¾Ñменено или оÑибка:', error); 168 }); 169 } else { 170 alert('ÐоделиÑÑÑÑ ÑеÑез ÑоÑÑеÑи можно ÑкопиÑовав ÑÑÑÐ»ÐºÑ Ð¸Ð· адÑеÑной ÑÑÑоки'); 171 } 172}, 173 174 // ÐеÑод Ð´Ð»Ñ Ð¿Ð¾ÐºÐ°Ð·Ð° подÑказки 175 showNewMessageToast: function() { 176 // ÐÑовеÑÑем, еÑÑÑ Ð»Ð¸ Ñже ÑоÑÑ 177 if ($('#new-message-toast').length > 0) return; 178 179 // ÐпÑеделÑем мобилÑное ÑÑÑÑойÑÑво 180 var isMobile = window.innerWidth <= 768; 181 182 var toast = $('<div>', { 183 id: 'new-message-toast', 184 html: 'ÐÐ¾Ð²Ð°Ñ Ð½Ð¾Ð²Ð¾ÑÑÑ â', 185 css: { 186 position: 'fixed', 187 bottom: isMobile ? '60px' : '40px', 188 left: '50%', 189 transform: 'translateX(-50%)', 190 background: '#6EB238', 191 color: 'white', 192 padding: isMobile ? '18px 28px' : '10px 12px', 193 borderRadius: '30px', 194 boxShadow: '0 4px 12px rgba(0,0,0,0.2)', 195 cursor: 'pointer', 196 zIndex: 9999, 197 fontSize: isMobile ? '21px' : '16px', 198 fontWeight: isMobile ? '700' : '400', 199 animation: 'slideUp 0.3s ease', 200 border: '2px solid rgba(255,255,255,0.3)', 201 width: isMobile ? 'auto' : 'auto', 202 minWidth: isMobile ? '200px' : '150px', 203 textAlign: 'center', 204 letterSpacing: '0.5px'
205 } 206 }); 207 208 toast.click(function() { 209 if (typeof ym !== 'undefined') { 210 // ÐамениÑе 'toast_click' на название ваÑей Ñели 211 ym('24810671', 'reachGoal', 'toast_click'); 212 } 213 // ÐомеÑаем ÑÑо полÑзоваÑÐµÐ»Ñ Ð²Ð·Ð°Ð¸Ð¼Ð¾Ð´ÐµÐ¹ÑÑвовал (ÑеÑез клик по ÑоÑÑÑ) 214 chat.data.userInteracted = true; 215 216 var containerOffset = $('#chatContainer').offset().top; 217 var windowHeight = $(window).height(); 218 var containerHeight = $('#chatContainer').height(); 219 220 var isMobile = window.innerWidth <= 768; 221 var targetScroll; 222 223 if (isMobile) { 224 targetScroll = containerOffset - 10; 225 } else { 226 targetScroll = containerOffset + containerHeight - windowHeight + 50; 227 } 228 229 $('html, body').animate({ 230 scrollTop: targetScroll 231 }, 500, function() { 232 setTimeout(function() { 233 chat.scrollToBottom(); 234 }, 100); 235 }); 236 237 toast.fadeOut(300, function() { $(this).remove(); }); 238 }); 239 240 $('body').append(toast); 241 242 // ÐвÑомаÑиÑеÑки ÑкÑÑваем ÑеÑез 7 ÑекÑнд 243 setTimeout(function() { 244 toast.fadeOut(300, function() { $(this).remove(); }); 245 }, 7000); 246 }, 247 248render : function(template,params){ 249 var arr = []; 250 switch(template){ 251 case 'chatLine': 252 // ===== 1. ÐÑделÑем ÑиÑÑÑ ===== 253 var textWithNumbers = params.text.replace(/(\d+[\d\s]*[%â½$â¬]?)/g, '<b>$1</b>'); 254 255 // ===== 2. Рандомное колиÑеÑÑво Ñлов Ð¾Ñ 3 до 7 ===== 256 var words = textWithNumbers.split(' '); 257 var formattedText = textWithNumbers; 258 259 // ÐенеÑиÑÑем ÑлÑÑайное ÑиÑло Ð¾Ñ 3 до 7 260 var randomWords = Math.floor(Math.random() * 5) + 3; // 3,4,5,6,7 261 262 if (words.length >= randomWords) { 263 var firstPart = words.slice(0, randomWords).join(' '); 264 var rest = words.slice(randomWords).join(' '); 265 formattedText = '<b style="color:#0000009e;">' + firstPart + '</b> ' + rest; 266 } else { 267 formattedText = '<b style="color:#0000009e;">' + textWithNumbers + '</b>'; 268 } 269 270 // ===== 3. Ð¦Ð²ÐµÑ ÑоÑки в завиÑимоÑÑи Ð¾Ñ Ð°Ð²ÑоÑа ===== 271 var dotColor = '#6EB238'; // зеленÑй по ÑмолÑÐ°Ð½Ð¸Ñ 272 273 if (params.author === 'СÑоÑнÑе новоÑÑи' || 274 params.author === 'СРÐЧÐЫРÐÐÐÐСТÐ' || 275 (params.author && params.author.toLowerCase().includes('ÑÑоÑн'))) { 276 dotColor = '#e44139'; // кÑаÑнÑй 277 } 278 279 // ===== 4. Ðнопка поделиÑÑÑÑ (бÑÐ´ÐµÑ Ð²Ð¸Ð´Ð½Ð° ÑолÑко на мобилÑнÑÑ ) ===== 280 var shareText = encodeURIComponent(params.text.substring(0, 100) + (params.text.length > 100 ? '...' : '')); 281 var fullText = encodeURIComponent(params.text); 282 var currentUrl = encodeURIComponent('https://ÑоÑÑм-ÑÑейдеÑов.ÑÑ/chart-online.php'); 283 284 var shareButton = ` 285 <div class="share-button" onclick="event.stopPropagation(); chat.shareNews('${shareText}', '${currentUrl}', '${fullText}')"> 286 <svg style="filter: drop-shadow(0 1px 1px rgba(0,0,0,0.2));" width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 287 <path d="M13.52,7.17V2.91a0.63,0.63,0,0,1,1-.51l9.22,7.46a0.61,0.61,0,0,1,0,1L14.5,18.34a0.63,0.63,0,0,1-1-.51V13.88c-5.76,0-10.65,2.57-12.44,7a11.29,11.29,0,0,1-.16-1.82C0.91,12.5,6.55,7.17,13.52,7.17Z" fill="#6EB238"/> 288 289 </svg> 290 </div> 291 `; 292 293 arr = [ 294 '<div class="chat chat-',params.id,' rounded" data-news-id="',params.id,'">', 295 '<span class="text">', 296 '<style>.chat-',params.id,' .author::before { background: ',dotColor,' !important; }</style>', 297 formattedText, 298 '</span>', 299 '<span class="author">', 300 '<span style="color:#64748bab;">',params.time,'</span> ', 301 '<b style="display:none;"><a class="dropdown-top" style="color: #469e00e0;" title="" href="javascript:void(0)" onclick="getText_author(this)">',params.author,'</a></b>', 302 '</span>', 303 shareButton, 304 '</div>' 305 ]; 306 break; 307 } 308 return arr.join(''); 309}, 310 311 // ÐеÑод addChatLine добавлÑÐµÑ ÑÑÑÐ¾ÐºÑ ÑаÑа на ÑÑÑаниÑÑ 312 addChatLine : function(params, isTemp){ 313 314 // ÐÑе Ð¿Ð¾ÐºÐ°Ð·Ð°Ð½Ð¸Ñ Ð²Ñемени вÑводÑÑÑÑ Ð² ÑоÑмаÑе вÑеменного поÑÑа полÑзоваÑÐµÐ»Ñ 315 var d = new Date(); 316 if(params.time) { 317 d.setUTCHours(params.time.hours,params.time.minutes); 318 } 319 320 params.time = (d.getHours() < 10 ? '0' : '' ) + d.getHours()+':'+ 321 (d.getMinutes() < 10 ? '0':'') + d.getMinutes(); 322 323 var markup = chat.render('chatLine',params), 324 exists = $('#chatLineHolder .chat-'+params.id); 325 326 if(exists.length){ 327 exists.remove(); 328 } 329 330 if(!chat.data.lastID){ 331 // ÐÑли ÑÑо пеÑÐ²Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑ Ð² ÑаÑе, ÑдалÑем 332 // паÑагÑÐ°Ñ Ñ ÑообÑением о Ñом, ÑÑо еÑе ниÑего не напиÑано: 333 $('#chatLineHolder p').remove(); 334 } 335 336 // ÐобавлÑем новоÑÑÑ Ð² ÐÐÐÐЦ конÑейнеÑа (append) 337 if (params.id.toString().charAt(0) != 't') { 338 // ÐÐ»Ñ Ð¿Ð¾ÑÑоÑннÑÑ ÑообÑений добавлÑем Ñ Ð°Ð½Ð¸Ð¼Ð°Ñией 339 var $newElement = $(markup).hide().fadeIn(1500); 340 chat.data.container.append($newElement); 341 342 // ÐÑовеÑÑем, видно ли поÑледнее ÑообÑение 343 var container = chat.data.container[0]; 344 345 // ÐÑÑиÑлÑем, видно ли поÑледнее ÑообÑение (Ñ Ð¿Ð¾Ð³ÑеÑноÑÑÑÑ 100px) 346 var scrollPosition = container.scrollTop + container.clientHeight; 347 var totalHeight = container.scrollHeight; 348 var isAtBottom = (totalHeight - scrollPosition < 100); 349 350 // ===== ÐСÐÐ ÐÐÐÐÐÐÐЯ ÐÐÐÐÐÐ ===== 351 // ÐÑли ÑÑо пеÑÐ²Ð°Ñ Ð·Ð°Ð³ÑÑзка ÑÑÑаниÑÑ 352 if (!chat.data.pageLoaded) { 353 // ÐÑоÑÑо ÑкÑоллим вниз, ÑоÑÑ ÐРпоказÑваем 354 chat.scrollToBottom(); 355 } 356 // ÐÑли вклÑÑен Ñежим "вÑегда показÑваÑÑ ÑоÑÑ" 357 else if (chat.data.toastAlways) { 358 // ÐоказÑваем ÑоÑÑ Ð¿Ñи каждой новой новоÑÑи (кÑоме пеÑвой загÑÑзки) 359 chat.showNewMessageToast(); 360 } 361 // ÐнаÑе ÑабоÑаем по обÑÑной логике 362 else if (chat.data.userInteracted) { 363 if (!isAtBottom) { // еÑли не Ð²Ð½Ð¸Ð·Ñ 364 chat.showNewMessageToast(); 365 } else { // еÑли Ð²Ð½Ð¸Ð·Ñ 366 chat.scrollToBottom(); 367 } 368 } else { 369 // ÐеÑвое взаимодейÑÑвие поÑле загÑÑзки 370 chat.scrollToBottom(); 371 } 372 // ================================ 373 374 } else { 375 // ÐÐ»Ñ Ð²ÑеменнÑÑ Ð´Ð¾Ð±Ð°Ð²Ð»Ñем ÑÑÐ°Ð·Ñ 376 chat.data.container.append(markup); 377 chat.scrollToBottom(); 378 } 379 380 // ÐбновлÑем lastID еÑли ÑÑо поÑÑоÑнное ÑообÑение 381 if(params.id.toString().charAt(0) != 't' && params.id > chat.data.lastID){ 382 chat.data.lastID = params.id; 383 } 384 385 }, 386 387 // ÐеÑод Ð´Ð»Ñ ÑкÑолла вниз 388 scrollToBottom: function() { 389 var container = chat.data.container[0]; 390 container.scrollTop = container.scrollHeight; 391 }, 392 393 // ÐаннÑй меÑод запÑаÑÐ¸Ð²Ð°ÐµÑ Ð¿Ð¾ÑледнÑÑ Ð·Ð°Ð¿Ð¸ÑÑ Ð² ÑаÑе 394 getChats : function(callback){ 395 $.tzGET('getChats',{lastID: chat.data.lastID},function(r){ 396 397 // Ð¡Ð¾Ñ ÑанÑем позиÑÐ¸Ñ ÑкÑолла 398 var container = chat.data.container[0]; 399 var wasAtBottom = container.scrollHeight - container.scrollTop <= container.clientHeight + 50; 400 401 for(var i=0;i<r.chats.length;i++){ 402 chat.addChatLine(r.chats[i], false); 403 } 404 405 if(r.chats.length){ 406 chat.data.noActivity = 0; 407 chat.data.lastID = r.chats[i-1].id; 408 409 // ÐÑли полÑзоваÑÐµÐ»Ñ Ð±Ñл внизÑ, оÑÑаемÑÑ Ð²Ð½Ð¸Ð·Ñ 410 if (wasAtBottom) { 411 chat.scrollToBottom(); 412 } 413 } 414 else{ 415 chat.data.noActivity++; 416 } 417 418 if(!chat.data.lastID){ 419 chat.data.container.html('<p class="noChats">Ð§Ð°Ñ Ð¾ÑиÑен модеÑаÑоÑом, пожалÑйÑÑа ÑоблÑдайÑе пÑавила обÑениÑ<br></br><b>ÐÑиÑÑного обÑениÑ! ÐапиÑиÑе ÑообÑение и бÑдÑÑе пеÑвÑм!</b> <br><br><img src="/img/img18.jpg"></p>'); 420 } 421 422 // УÑÑанавливаем Ñлаг, ÑÑо ÑÑÑаниÑа загÑÑжена 423 chat.data.pageLoaded = true; 424 425 var nextRequest = 15000; 426 427 if(chat.data.noActivity > 8){ 428 nextRequest = 60000; 429 } 430 431 if(chat.data.noActivity > 40){ 432 nextRequest = 120000; 433 } 434 435 setTimeout(callback,nextRequest); 436 }); 437 }, 438 439 displayError : function(msg){ 440 var elem = $('<div>',{ 441 id : 'chatErrorMessage', 442 html : msg 443 }); 444 445 elem.click(function(){ 446 $(this).fadeOut(function(){ 447 $(this).remove(); 448 }); 449 }); 450 451 setTimeout(function(){ 452 elem.click(); 453 },10000); 454 455 elem.hide().appendTo('body').slideDown(); 456 } 457}; 458 459// ФоÑмиÑование GET & POST: 460$.tzPOST = function(action,data,callback){ 461 $.post('php/post.php?action='+action,data,callback,'json'); 462} 463 464$.tzGET = function(action,data,callback){ 465 $.get('php/ajax.php?action='+action,data,callback,'json'); 466} 467 468// ÐеÑод jQuery Ð´Ð»Ñ Ð·Ð°Ð¼ÐµÑаÑÑего ÑекÑÑа: 469$.fn.defaultText = function(value){ 470 471 var element = this.eq(0); 472 element.data('defaultText',value); 473 474 element.focus(function(){ 475 if(element.val() == value){ 476 element.val('').removeClass('defaultText'); 477 } 478 }).blur(function(){ 479 if(element.val() == '' || element.val() == value){ 480 element.addClass('defaultText').val(value); 481 } 482 }); 483 484 return element.blur(); 485} 486 487// ÐобавлÑем CSS Ð´Ð»Ñ ÑоÑÑа и кнопки поделиÑÑÑÑ 488// ÐобавлÑем CSS Ð´Ð»Ñ ÑоÑÑа и кнопки поделиÑÑÑÑ 489// ÐобавлÑем CSS Ð´Ð»Ñ ÑоÑÑа и кнопки поделиÑÑÑÑ 490if (!$('#toast-styles').length) { 491 $('<style id="toast-styles">') 492 .text(` 493 @keyframes slideUp { 494 from { opacity:0; transform:translate(-50%,20px); } 495 to { opacity:1; transform:translate(-50%,0); } 496 } 497 #new-message-toast:hover { 498 background:#5a9a2c; 499 } 500 .share-button { 501 display: none; 502 } 503 504 /* ТолÑко Ð´Ð»Ñ Ð¼Ð¾Ð±Ð¸Ð»ÑнÑÑ ÑÑÑÑойÑÑв */ 505 @media only screen and (max-width: 768px) { 506 .chat { 507 position: relative; 508 padding-bottom: 20px; 509 -webkit-tap-highlight-color: transparent; 510 } 511 512 .share-button { 513 position: absolute; 514 bottom: 20px; 515 right: 20px; 516 width: 40px; 517 height: 40px; 518 border-radius: 50%; 519 background: #fff; 520 display: flex; 521 align-items: center; 522 justify-content: center; 523 cursor: pointer; 524 /* box-shadow: 0 6px 10px rgba(0,0,0,0.4); */ 525 z-index: 10; 526 transition: transform 0.2s ease; 527 opacity: 0; 528 visibility: hidden; 529 pointer-events: none; 530 } 531
532 .chat:hover .share-button { 533 opacity: 1; 534 visibility: visible; 535 pointer-events: auto; 536 } 537 538 .share-button:hover { 539 transform: scale(1.1); 540 } 541 542 .share-button svg { 543 width: 28px; 544 height: 28px; 545 shadow: 0 2px 8px rgba(0,0,0,0.2); 546 } 547 } 548 `) 549 .appendTo('head'); 550}
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.