function RegisterSteamOnWebPanelShownHandler( f ) { $J(document).on( 'visibilitychange', function() { if ( document.visibilityState === "visible" ) f(); }); } function RegisterSteamOnWebPanelHiddenHandler( f ) { $J(document).on( 'visibilitychange', function() { if ( document.visibilityState === "hidden" ) f(); }); } function RefreshNotificationArea() { // the new way - updates both the old envelope and responsive menu UpdateNotificationCounts(); } function vIE() { return (navigator.appName=='Microsoft Internet Explorer') ? parseFloat( ( new RegExp( "MSIE ([0-9]{1,}[.0-9]{0,})" ) ).exec( navigator.userAgent )[1] ) : -1; } function checkAbuseSub( elForm ) { if ( !$J(elForm).find('input[name=abuseType]:checked').length ) { alert( 'Пожалуйста, укажите причину жалобы' ); return false; } CModal.DismissActiveModal(); var params = $J(elForm).serializeArray(); params.push( {name: 'json', value: 1} ); $J.post( 'https://steamcommunity.com/actions/ReportAbuse/', params).done( function() { ShowAlertDialog( 'Спасибо!', 'Спасибо, что отправили жалобу. Благодаря вам сообщество Steam остаётся приятным и дружелюбным.' ); }).fail( function() { ShowAlertDialog( 'Пожаловаться', 'При попытке пожаловаться произошла ошибка. Пожалуйста, попробуйте позже.' ); }); return false; } var g_whiteListedDomains = [ "steampowered.com", "steamgames.com", "steamcommunity.com", "valvesoftware.com", "youtube.com", "youtu.be", "live.com", "msn.com", "myspace.com", "facebook.com", "hi5.com", "wikipedia.org", "orkut.com", "blogger.com", "friendster.com", "fotolog.net", "google.fr", "baidu.com", "microsoft.com", "shacknews.com", "bbc.co.uk", "cnn.com", "foxsports.com", "pcmag.com", "nytimes.com", "flickr.com", "amazon.com", "veoh.com", "pcgamer.com", "metacritic.com", "fileplanet.com", "gamespot.com", "gametap.com", "ign.com", "kotaku.com", "xfire.com", "pcgames.gwn.com", "gamezone.com", "gamesradar.com", "digg.com", "engadget.com", "gizmodo.com", "gamesforwindows.com", "xbox.com", "cnet.com", "l4d.com", "teamfortress.com", "tf2.com", "half-life2.com", "aperturescience.com", "dayofdefeat.com", "dota2.com", "playdota.com", "kickstarter.com", "gamingheads.com", "reddit.com", "counter-strike.net", "imgur.com" ]; function getHostname( str ) { var re = new RegExp( '^(steam://openurl(_external)?/)?(f|ht)tps?://([^@/?#]*@)?([^/#?]+)', 'im' ); return str.trim().match(re)[5].toString(); } function AlertNonSteamSite( elem ) { var url = elem.href; var hostname = getHostname( url ); if ( hostname ) { hostname = hostname.toLowerCase(); for ( var i = 0; i < g_whiteListedDomains.length; ++i ) { var index = hostname.lastIndexOf( g_whiteListedDomains[i] ); if ( index != -1 && index == ( hostname.length - g_whiteListedDomains[i].length ) && ( index == 0 || hostname.charAt( index - 1 ) == '.' ) ) { return true; } } return confirm( 'Внимание: ссылка, по которой вы переходите, не ведет на официальный сайт Steam.\n\n' + url.replace( new RegExp( '^steam://openurl(_external)?/' ), '' ) + '\n\n' + 'Если на этом сайте вас попросят ввести свой логин или пароль, ни при каких условиях не делайте этого. Вы можете лишиться своего аккаунта в Steam и всех купленных игр!\n' + 'Вы уверены, что хотите перейти на эту страницу? Нажмите ОК, чтобы продолжить на свой страх и риск.\n' ); } ShowAlertDialog( '', 'Ошибка в адресе ссылки.'); return false; } var lastFilters = new Object(); function FilterListFast( target, str ) { var lastFilter = lastFilters[target]; if ( !lastFilter ) lastFilter = ''; str = str.toLowerCase(); if ( str == lastFilter ) return false; var expanding = false; var contracting = false; if ( str.length > lastFilter.length && str.startsWith( lastFilter ) ) expanding = true; if ( !str || str.length < lastFilter.length && lastFilter.startsWith( str ) ) contracting = true; var strParts = str.split(/\W/); var elemTarget = $(target); var elemParent = elemTarget.parentNode; elemParent.removeChild( elemTarget ); var rgChildren = elemTarget.childNodes; for ( var i = 0; i < rgChildren.length; i++ ) { var child = rgChildren[i]; if ( child.nodeType != child.ELEMENT_NODE ) continue; if ( expanding && child.style.display=='none' || contracting && child.style.display != 'none' ) continue; if ( !child.lcText ) child.lcText = (child.innerText || child.textContent).toLowerCase(); var text = child.lcText; var show = true; for ( var iPart = 0; show && iPart < strParts.length; iPart++ ) if ( !text.include( strParts[iPart] ) ) show=false; if ( show ) child.style.display = ''; else child.style.display = 'none'; } lastFilters[target] = str; elemParent.appendChild( elemTarget ); return true; } // goes into fullscreen, returning false if the browser doesn't support it function requestFullScreen( element ) { // Supports most browsers and their versions. var requestMethod = element.requestFullScreen || element.webkitRequestFullScreen || element.mozRequestFullScreen || element.msRequestFullScreen; if (requestMethod) { // Native full screen. requestMethod.call(element); return true; } return false; } function exitFullScreen() { if (document.exitFullscreen) { document.exitFullscreen(); } else if (document.mozCancelFullScreen) { document.mozCancelFullScreen(); } else if (document.webkitCancelFullScreen) { document.webkitCancelFullScreen(); } } function RecordAJAXPageView( url ) { if ( typeof ga != "undefined" && ga ) { var rgURLs = [ 'https://steamcommunity.com', 'https://steamcommunity.com' ]; for ( var i = 0; i < rgURLs.length; ++i ) { var baseURL = rgURLs[i]; var idx = url.indexOf(baseURL); if ( idx != -1 ) { url = url.substring( idx + baseURL.length ); } ga( 'send', 'pageview', url ); return; } } } var g_SNR = false; var g_strLanguage = 'english'; // given an array of impressions as strings, this will handle joining them all together into a singular string, but enforcing that it doesn't // go above the cookie size limit which can otherwise cause users to become stuck since the page requests will start failing function JoinImpressionsUpToLimit( rgImpressions ) { //cookies generally can go up to 4k bytes, but we can have problems when we start getting that close, so cut it off earlier var nRemainingLen = 3200; var result = ''; for ( var i = 0; i < rgImpressions.length; i++ ) { var impression = String( rgImpressions[ i ] ); var nImpressionLen = encodeURIComponent( impression + '|' ).length; //did we run out of room in our list? if ( nRemainingLen < nImpressionLen ) break; //add the separator if not the first entry if ( result !== '' ) result += '|'; //add our impression and remove that space from what is available result += impression; nRemainingLen -= nImpressionLen; } return result; } function RecordAppImpression( appid, snr ) { if ( appid == 0 || !snr ) return; if ( typeof g_bAllowAppImpressions == 'undefined' || !g_bAllowAppImpressions ) { return; } var strImpressions = V_GetCookie( "app_impressions" ); var rgImpressions = strImpressions && strImpressions.length != 0 ? strImpressions.split( "|" ) : []; var strImpressionData = appid + '@' + snr; rgImpressions.push( strImpressionData ); V_SetCookie( "app_impressions", JoinImpressionsUpToLimit( rgImpressions ) ); } // doesn't properly handle cookies with ; in them (needs to look for escape char) function GetCookie( strCookieName ) { var rgMatches = document.cookie.match( '(^|; )' + strCookieName + '=([^;]*)' ); if ( rgMatches && rgMatches[2] ) return rgMatches[2]; else return null; } function SetCookie( strCookieName, strValue, expiryInDays, path ) { if ( !expiryInDays ) expiryInDays = 0; if ( !path ) path = '/'; var dateExpires = new Date(); dateExpires.setTime( dateExpires.getTime() + 1000 * 60 * 60 * 24 * expiryInDays ); document.cookie = strCookieName + '=' + strValue + '; expires=' + dateExpires.toGMTString() + ';path=' + path; } // included data: strCode, eCurrencyCode, strSymbol, bSymbolIsPrefix, bWholeUnitsOnly g_rgCurrencyData = {"USD":{"strCode":"USD","eCurrencyCode":1,"strSymbol":"$","bSymbolIsPrefix":true,"bWholeUnitsOnly":false,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":""},"GBP":{"strCode":"GBP","eCurrencyCode":2,"strSymbol":"\u00a3","bSymbolIsPrefix":true,"bWholeUnitsOnly":false,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":""},"EUR":{"strCode":"EUR","eCurrencyCode":3,"strSymbol":"\u20ac","bSymbolIsPrefix":false,"bWholeUnitsOnly":false,"strDecimalSymbol":",","strThousandsSeparator":" ","strSymbolAndNumberSeparator":""},"CHF":{"strCode":"CHF","eCurrencyCode":4,"strSymbol":"CHF","bSymbolIsPrefix":true,"bWholeUnitsOnly":false,"strDecimalSymbol":".","strThousandsSeparator":" ","strSymbolAndNumberSeparator":" "},"RUB":{"strCode":"RUB","eCurrencyCode":5,"strSymbol":"p\u0443\u0431.","bSymbolIsPrefix":false,"bWholeUnitsOnly":true,"strDecimalSymbol":",","strThousandsSeparator":"","strSymbolAndNumberSeparator":" "},"BRL":{"strCode":"BRL","eCurrencyCode":7,"strSymbol":"R$","bSymbolIsPrefix":true,"bWholeUnitsOnly":false,"strDecimalSymbol":",","strThousandsSeparator":".","strSymbolAndNumberSeparator":" "},"JPY":{"strCode":"JPY","eCurrencyCode":8,"strSymbol":"\u00a5","bSymbolIsPrefix":true,"bWholeUnitsOnly":true,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":" "},"NOK":{"strCode":"NOK","eCurrencyCode":9,"strSymbol":"kr","bSymbolIsPrefix":false,"bWholeUnitsOnly":false,"strDecimalSymbol":",","strThousandsSeparator":".","strSymbolAndNumberSeparator":" "},"IDR":{"strCode":"IDR","eCurrencyCode":10,"strSymbol":"Rp","bSymbolIsPrefix":true,"bWholeUnitsOnly":true,"strDecimalSymbol":".","strThousandsSeparator":" ","strSymbolAndNumberSeparator":" "},"MYR":{"strCode":"MYR","eCurrencyCode":11,"strSymbol":"RM","bSymbolIsPrefix":true,"bWholeUnitsOnly":false,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":""},"PHP":{"strCode":"PHP","eCurrencyCode":12,"strSymbol":"P","bSymbolIsPrefix":true,"bWholeUnitsOnly":false,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":""},"SGD":{"strCode":"SGD","eCurrencyCode":13,"strSymbol":"S$","bSymbolIsPrefix":true,"bWholeUnitsOnly":false,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":""},"THB":{"strCode":"THB","eCurrencyCode":14,"strSymbol":"\u0e3f","bSymbolIsPrefix":true,"bWholeUnitsOnly":false,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":""},"VND":{"strCode":"VND","eCurrencyCode":15,"strSymbol":"\u20ab","bSymbolIsPrefix":false,"bWholeUnitsOnly":true,"strDecimalSymbol":",","strThousandsSeparator":".","strSymbolAndNumberSeparator":""},"KRW":{"strCode":"KRW","eCurrencyCode":16,"strSymbol":"\u20a9","bSymbolIsPrefix":true,"bWholeUnitsOnly":true,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":" "},"TRY":{"strCode":"TRY","eCurrencyCode":17,"strSymbol":"TL","bSymbolIsPrefix":false,"bWholeUnitsOnly":false,"strDecimalSymbol":",","strThousandsSeparator":".","strSymbolAndNumberSeparator":" "},"UAH":{"strCode":"UAH","eCurrencyCode":18,"strSymbol":"\u20b4","bSymbolIsPrefix":false,"bWholeUnitsOnly":true,"strDecimalSymbol":",","strThousandsSeparator":" ","strSymbolAndNumberSeparator":""},"MXN":{"strCode":"MXN","eCurrencyCode":19,"strSymbol":"Mex$","bSymbolIsPrefix":true,"bWholeUnitsOnly":false,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":" "},"CAD":{"strCode":"CAD","eCurrencyCode":20,"strSymbol":"CDN$","bSymbolIsPrefix":true,"bWholeUnitsOnly":false,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":" "},"AUD":{"strCode":"AUD","eCurrencyCode":21,"strSymbol":"A$","bSymbolIsPrefix":true,"bWholeUnitsOnly":false,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":" "},"NZD":{"strCode":"NZD","eCurrencyCode":22,"strSymbol":"NZ$","bSymbolIsPrefix":true,"bWholeUnitsOnly":false,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":" "},"PLN":{"strCode":"PLN","eCurrencyCode":6,"strSymbol":"z\u0142","bSymbolIsPrefix":false,"bWholeUnitsOnly":false,"strDecimalSymbol":",","strThousandsSeparator":" ","strSymbolAndNumberSeparator":""},"CNY":{"strCode":"CNY","eCurrencyCode":23,"strSymbol":"\u00a5","bSymbolIsPrefix":true,"bWholeUnitsOnly":false,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":" "},"INR":{"strCode":"INR","eCurrencyCode":24,"strSymbol":"\u20b9","bSymbolIsPrefix":true,"bWholeUnitsOnly":true,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":" "},"CLP":{"strCode":"CLP","eCurrencyCode":25,"strSymbol":"CLP$","bSymbolIsPrefix":true,"bWholeUnitsOnly":true,"strDecimalSymbol":",","strThousandsSeparator":".","strSymbolAndNumberSeparator":" "},"PEN":{"strCode":"PEN","eCurrencyCode":26,"strSymbol":"S\/.","bSymbolIsPrefix":true,"bWholeUnitsOnly":false,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":""},"COP":{"strCode":"COP","eCurrencyCode":27,"strSymbol":"COL$","bSymbolIsPrefix":true,"bWholeUnitsOnly":true,"strDecimalSymbol":",","strThousandsSeparator":".","strSymbolAndNumberSeparator":" "},"ZAR":{"strCode":"ZAR","eCurrencyCode":28,"strSymbol":"R","bSymbolIsPrefix":true,"bWholeUnitsOnly":false,"strDecimalSymbol":".","strThousandsSeparator":" ","strSymbolAndNumberSeparator":" "},"HKD":{"strCode":"HKD","eCurrencyCode":29,"strSymbol":"HK$","bSymbolIsPrefix":true,"bWholeUnitsOnly":false,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":" "},"TWD":{"strCode":"TWD","eCurrencyCode":30,"strSymbol":"NT$","bSymbolIsPrefix":true,"bWholeUnitsOnly":true,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":" "},"SAR":{"strCode":"SAR","eCurrencyCode":31,"strSymbol":"SR","bSymbolIsPrefix":false,"bWholeUnitsOnly":false,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":" "},"AED":{"strCode":"AED","eCurrencyCode":32,"strSymbol":"AED","bSymbolIsPrefix":false,"bWholeUnitsOnly":false,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":" "},"SEK":{"strCode":"SEK","eCurrencyCode":33,"strSymbol":"kr","bSymbolIsPrefix":false,"bWholeUnitsOnly":false,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":" "},"ARS":{"strCode":"ARS","eCurrencyCode":34,"strSymbol":"ARS$","bSymbolIsPrefix":true,"bWholeUnitsOnly":false,"strDecimalSymbol":",","strThousandsSeparator":".","strSymbolAndNumberSeparator":" "},"ILS":{"strCode":"ILS","eCurrencyCode":35,"strSymbol":"\u20aa","bSymbolIsPrefix":true,"bWholeUnitsOnly":false,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":""},"BYN":{"strCode":"BYN","eCurrencyCode":36,"strSymbol":"Br","bSymbolIsPrefix":true,"bWholeUnitsOnly":false,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":""},"KZT":{"strCode":"KZT","eCurrencyCode":37,"strSymbol":"\u20b8","bSymbolIsPrefix":false,"bWholeUnitsOnly":true,"strDecimalSymbol":",","strThousandsSeparator":" ","strSymbolAndNumberSeparator":""},"KWD":{"strCode":"KWD","eCurrencyCode":38,"strSymbol":"KD","bSymbolIsPrefix":false,"bWholeUnitsOnly":false,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":" "},"QAR":{"strCode":"QAR","eCurrencyCode":39,"strSymbol":"QR","bSymbolIsPrefix":false,"bWholeUnitsOnly":false,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":" "},"CRC":{"strCode":"CRC","eCurrencyCode":40,"strSymbol":"\u20a1","bSymbolIsPrefix":true,"bWholeUnitsOnly":true,"strDecimalSymbol":",","strThousandsSeparator":".","strSymbolAndNumberSeparator":""},"UYU":{"strCode":"UYU","eCurrencyCode":41,"strSymbol":"$U","bSymbolIsPrefix":true,"bWholeUnitsOnly":true,"strDecimalSymbol":",","strThousandsSeparator":".","strSymbolAndNumberSeparator":""},"BGN":{"strCode":"BGN","eCurrencyCode":42,"strSymbol":"\u043b\u0432","bSymbolIsPrefix":false,"bWholeUnitsOnly":false,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":" "},"HRK":{"strCode":"HRK","eCurrencyCode":43,"strSymbol":"kn","bSymbolIsPrefix":false,"bWholeUnitsOnly":false,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":" "},"CZK":{"strCode":"CZK","eCurrencyCode":44,"strSymbol":"K\u010d","bSymbolIsPrefix":false,"bWholeUnitsOnly":false,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":" "},"DKK":{"strCode":"DKK","eCurrencyCode":45,"strSymbol":"kr.","bSymbolIsPrefix":false,"bWholeUnitsOnly":false,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":" "},"HUF":{"strCode":"HUF","eCurrencyCode":46,"strSymbol":"Ft","bSymbolIsPrefix":false,"bWholeUnitsOnly":false,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":" "},"RON":{"strCode":"RON","eCurrencyCode":47,"strSymbol":"lei","bSymbolIsPrefix":false,"bWholeUnitsOnly":false,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":" "},"RMB":{"strCode":"RMB","eCurrencyCode":9000,"strSymbol":"\u5200\u5e01","bSymbolIsPrefix":false,"bWholeUnitsOnly":true,"strDecimalSymbol":".","strThousandsSeparator":"","strSymbolAndNumberSeparator":" "},"NXP":{"strCode":"NXP","eCurrencyCode":9001,"strSymbol":"\uc6d0","bSymbolIsPrefix":false,"bWholeUnitsOnly":true,"strDecimalSymbol":".","strThousandsSeparator":",","strSymbolAndNumberSeparator":""}}; // takes an integer function v_currencyformat( valueInCents, currencyCode, countryCode ) { var currencyFormat = (valueInCents / 100).toFixed(2); if ( g_rgCurrencyData[currencyCode] ) { var currencyData = g_rgCurrencyData[currencyCode]; if ( IsCurrencyWholeUnits( currencyCode ) ) { currencyFormat = currencyFormat.replace( '.00', '' ); } if ( currencyData.strDecimalSymbol != '.' ) { currencyFormat = currencyFormat.replace( '.', currencyData.strDecimalSymbol ); } var currencyReturn = IsCurrencySymbolBeforeValue( currencyCode ) ? GetCurrencySymbol( currencyCode ) + currencyData.strSymbolAndNumberSeparator + currencyFormat : currencyFormat + currencyData.strSymbolAndNumberSeparator + GetCurrencySymbol( currencyCode ); if ( currencyCode == 'USD' && typeof(countryCode) != 'undefined' && countryCode != 'US' ) { return currencyReturn + ' USD'; } else if ( currencyCode == 'EUR' ) { return currencyReturn.replace( ',00', ',--' ); } else { return currencyReturn; } } else { return currencyFormat + ' ' + currencyCode; } } function IsCurrencySymbolBeforeValue( currencyCode ) { return g_rgCurrencyData[currencyCode] && g_rgCurrencyData[currencyCode].bSymbolIsPrefix; } function IsCurrencyWholeUnits( currencyCode ) { return g_rgCurrencyData[currencyCode] && g_rgCurrencyData[currencyCode].bWholeUnitsOnly && currencyCode != 'RUB'; } // Return the symbol to use for a currency function GetCurrencySymbol( currencyCode ) { return g_rgCurrencyData[currencyCode] ? g_rgCurrencyData[currencyCode].strSymbol : currencyCode + ' '; } function GetCurrencyCode( currencyId ) { for ( var code in g_rgCurrencyData ) { if ( g_rgCurrencyData[code].eCurrencyCode == currencyId ) return code; } return 'Unknown'; } function GetAvatarURLFromHash( hash, size ) { var strURL = 'https://avatars.akamai.steamstatic.com/' + hash; if ( size == 'full' ) strURL += '_full.jpg'; else if ( size == 'medium' ) strURL += '_medium.jpg'; else strURL += '.jpg'; return strURL; } // need to hold on to this so it doesn't get lost when we remove() the dialog element var g_AbuseModalContents = null; function ShowAbuseDialog() { if ( !g_AbuseModalContents ) g_AbuseModalContents = $J('#reportAbuseModalContents'); if ( g_AbuseModalContents ) { var Modal = ShowDialog( 'Пожаловаться', g_AbuseModalContents ); } } function StandardCommunityBan( steamid, elemLink ) { $J.get( 'https://steamcommunity.com/actions/communitybandialog', { 'sessionID' : g_sessionID, 'steamID' : steamid } ) .done( function( data ) { var $Content = $J(data); var Modal = ShowConfirmDialog( "Community Ban", $Content, 'Submit' ).done( function( ) { var $Form = $Content.find( 'form#community_ban_form' ); $J.post( "https://steamcommunity.com/actions/StandardCommunityBan", $Form.serialize() ) .done( function( data ) { if ( !$J.isEmptyObject( elemLink ) ) { $J(elemLink).replaceWith( 'Banned' ); } else { location.reload(); } }).fail( function( jqxhr ) { // jquery doesn't parse json on fail var data = V_ParseJSON( jqxhr.responseText ); ShowAlertDialog( 'Community Ban & Delete Comments', 'Failed with error message: ' + data.success ); }); } ); }).fail( function( data ) { ShowAlertDialog( 'Community Ban & Delete Comments', 'You do not have permissions to view this or you are not logged in.' ); }); } function ReportProfile( steamID ) { var $Content = $J('
'); var $Modal = ShowDialog( null, $Content ); var sURL = 'https://steamcommunity.com/actions/ReportProfile/' + steamID; $J.ajax( { url: sURL, type: 'GET' }).done( function ( data ) { var $DialogHTML = $J( data ); $Content.replaceWith( $DialogHTML ); $Modal.SetMaxHeight( '850' ); } ); } function CEmoticonPopup( $EmoticonButton, $Textarea, strBaseURL ) { this.m_$EmoticonButton = $EmoticonButton; this.m_$TextArea = $Textarea; this.m_strBaseURL = strBaseURL || 'https://steamcommunity.com'; if ( CEmoticonPopup.sm_deferEmoticonsLoaded == null ) CEmoticonPopup.sm_deferEmoticonsLoaded = new jQuery.Deferred(); this.m_bVisible = false; this.m_$Popup = null; var _this = this; this.m_$EmoticonButton.one('mouseenter', function() { _this.LoadEmoticons(); } ); this.m_$EmoticonButton.click( function() { _this.LoadEmoticons(); CEmoticonPopup.sm_deferEmoticonsLoaded.done( function() { _this.OnButtonClick(); } ) } ); this.m_fnOnDocumentClick = function() { _this.DismissPopup(); }; } CEmoticonPopup.sm_rgEmoticons = []; CEmoticonPopup.sm_bEmoticonsLoaded = false; CEmoticonPopup.sm_deferEmoticonsLoaded = null; CEmoticonPopup.prototype.LoadEmoticons = function() { if ( CEmoticonPopup.sm_bEmoticonsLoaded ) return; CEmoticonPopup.sm_bEmoticonsLoaded = true; CEmoticonPopup.sm_rgEmoticons = []; $J.get( this.m_strBaseURL + '/actions/EmoticonList' ) .done( function(data) { if ( data ) CEmoticonPopup.sm_rgEmoticons = data; }).always( function() { CEmoticonPopup.sm_deferEmoticonsLoaded.resolve() } ); }; CEmoticonPopup.prototype.OnButtonClick = function() { if ( this.m_bVisible ) { this.DismissPopup(); } else { if ( !this.m_$Popup ) this.BuildPopup(); else PositionEmoticonHover( this.m_$Popup, this.m_$EmoticonButton ); this.m_$EmoticonButton.addClass( 'focus' ); this.m_$Popup.stop(); this.m_$Popup.fadeIn( 'fast' ); this.m_bVisible = true; if ( window.UseSmallScreenMode && window.UseSmallScreenMode() ) { // scroll such that the emoticon button is just above the popup window we're showing at the bottom of the screen // the 10 pixels represents the popup being positioned 5px from the bottom of the screen, and 5px between the popup and button $J(window).scrollTop( this.m_$EmoticonButton.offset().top - $J(window).height() + this.m_$Popup.height() + this.m_$EmoticonButton.height() + 10 ); } var _this = this; window.setTimeout( function() { $J(document).one( 'click.EmoticonPopup', _this.m_fnOnDocumentClick ) }, 0 ); } }; CEmoticonPopup.prototype.DismissPopup = function() { this.m_$Popup.fadeOut( 'fast' ); this.m_$EmoticonButton.removeClass( 'focus' ); this.m_bVisible = false; $J(document).off( 'click.EmoticonPopup' ); }; CEmoticonPopup.prototype.BuildPopup = function() { this.m_$Popup = $J('
', {'class': 'emoticon_popup_ctn' } ); var $PopupInner = $J('
', {'class': 'emoticon_popup' } ); this.m_$Popup.append( $PopupInner ); var $Content = $J('
', {'class': 'emoticon_popup_content' } ); $PopupInner.append( $Content ); for( var i = 0; i < CEmoticonPopup.sm_rgEmoticons.length; i++ ) { var strEmoticonName = CEmoticonPopup.sm_rgEmoticons[i].replace( /:/g, '' ); var strEmoticonURL = 'https://community.akamai.steamstatic.com/economy/emoticon/' + strEmoticonName; var $Emoticon = $J('
', {'class': 'emoticon_option', 'data-emoticon': strEmoticonName } ); var $Img = $J('', {'src': strEmoticonURL, 'class': 'emoticon' } ); $Emoticon.append( $Img ); $Emoticon.click( this.GetEmoticonClickClosure( strEmoticonName ) ); $Content.append( $Emoticon ); } $J(document.body).append( this.m_$Popup ); PositionEmoticonHover( this.m_$Popup, this.m_$EmoticonButton ); }; CEmoticonPopup.prototype.GetEmoticonClickClosure = function ( strEmoticonName ) { var _this = this; var strTextToInsert = ':' + strEmoticonName + ':'; return function() { var elTextArea = _this.m_$TextArea[0]; if ( elTextArea ) { var nSelectionStart = elTextArea.selectionStart; elTextArea.value = elTextArea.value.substr( 0, nSelectionStart ) + strTextToInsert + elTextArea.value.substr( nSelectionStart ); elTextArea.selectionStart = nSelectionStart + strTextToInsert.length; } _this.m_$TextArea.focus(); _this.DismissPopup(); if ( window.DismissEmoticonHover ) window.setTimeout( DismissEmoticonHover, 1 ); }; }; function PositionEmoticonHover( $Hover, $Target ) { // we position fixed in CSS for responsive mode if ( window.UseSmallScreenMode && window.UseSmallScreenMode() ) { $Hover.css( 'left', '' ).css('top', '' ); return; } $Hover.css( 'visibility', 'hidden' ); $Hover.show(); var offset = $Target.offset(); $Hover.css( 'left', offset.left + 'px' ); $Hover.css( 'top', offset.top + 'px'); var $HoverBox = $Hover.children( '.emoticon_popup' ); var $HoverArrowLeft = $Hover.children( '.miniprofile_arrow_left' ); var $HoverArrowRight = $Hover.children( '.miniprofile_arrow_right' ); var nWindowScrollTop = $J(window).scrollTop(); var nWindowScrollLeft = $J(window).scrollLeft(); var nViewportWidth = $J(window).width(); var nViewportHeight = $J(window).height(); var $HoverArrow = $HoverArrowRight; var nBoxRightViewport = ( offset.left - nWindowScrollLeft ) + $Target.outerWidth() + $HoverBox.width(); var nSpaceRight = nViewportWidth - nBoxRightViewport; var nSpaceLeft = offset.left - $Hover.width(); if ( nSpaceLeft > 0 || nSpaceLeft > nSpaceRight) { $Hover.css( 'left', ( offset.left - $Hover.width() - 12) + 'px' ); $HoverArrowLeft.hide(); $HoverArrowRight.show(); } else { $Hover.css( 'left', ( offset.left + $Target.outerWidth() ) + 'px' ); $HoverArrow = $HoverArrowLeft; $HoverArrowLeft.show(); $HoverArrowRight.hide(); } var nTopAdjustment = 0; if ( $Target.height() < 48 ) nTopAdjustment = Math.floor( $Target.height() / 2 ) - 12; var nDesiredHoverTop = offset.top - 0 + nTopAdjustment; $Hover.css( 'top', nDesiredHoverTop + 'px' ); // see if the hover is cut off by the bottom of the window, and bump it up if neccessary var nTargetTopViewport = ( offset.top - nWindowScrollTop ) + nTopAdjustment; if ( nTargetTopViewport + $HoverBox.height() + 35 > nViewportHeight ) { var nViewportAdjustment = ( $HoverBox.height() + 35 ) - ( nViewportHeight - nTargetTopViewport ); var nViewportAdjustedHoverTop = offset.top - nViewportAdjustment; $Hover.css( 'top', nViewportAdjustedHoverTop + 'px' ); // arrow is normally offset 30pixels. we move it down the same distance we moved the hover up, so it is "fixed" to where it was initially $HoverArrow.css( 'top', ( 30 + nDesiredHoverTop - nViewportAdjustedHoverTop ) + 'px' ); } else { $HoverArrow.css( 'top', '' ); } $Hover.hide(); $Hover.css( 'visibility', '' ); } function InitEconomyHovers( strEconomyCSSURL, strEconomyCommonJSURL, strEconomyJSURL ) { var $Hover = $J('
', {'class': 'economyitem_hover'} ); var $HoverContent = $J('
', {'class': 'economyitem_hover_content'} ); $Hover.append( $HoverContent ); $Hover.hide(); var fnOneTimeEconomySetup = function() { $J(document.body).append( $Hover ); if ( typeof UserYou == 'undefined' ) { var css = document.createElement( "link" ); css.setAttribute( "rel", "stylesheet" ); css.setAttribute( "type", "text/css" ); css.setAttribute( "href", strEconomyCSSURL ); var js1 = document.createElement( "script" ); js1.setAttribute( "type", "text/javascript" ); js1.setAttribute( "src", strEconomyCommonJSURL ); var js2 = document.createElement( "script" ); js2.setAttribute( "type", "text/javascript" ); js2.setAttribute( "src", strEconomyJSURL ); var head = $J('head')[0]; head.appendChild( css ); head.appendChild( js1 ); head.appendChild( js2 ); } }; var fnDataFactory = function( key ) { var rgItemKey = key.split('/'); if ( rgItemKey.length >= 3 && rgItemKey.length <= 5 ) { if ( fnOneTimeEconomySetup ) { fnOneTimeEconomySetup(); fnOneTimeEconomySetup = null; } // pop amount off the end first if it's present var nAmount; var strLastEntry = rgItemKey[rgItemKey.length - 1]; if ( strLastEntry && strLastEntry.length > 2 && strLastEntry.substr( 0, 2 ) == 'a:' ) { nAmount = strLastEntry.substr( 2 ); rgItemKey.pop(); } var strURL = null; var appid = rgItemKey[0]; if ( appid == 'classinfo' ) { // class info style appid = rgItemKey[1]; var classid = rgItemKey[2]; var instanceid = ( rgItemKey.length > 3 ? rgItemKey[3] : 0 ); strURL = 'economy/itemclasshover/' + appid + '/' + classid + '/' + instanceid; strURL += '?content_only=1&l=russian'; } else { // real asset var contextid = rgItemKey[1]; var assetid = rgItemKey[2]; var strURL = 'economy/itemhover/' + appid + '/' + contextid + '/' + assetid; strURL += '?content_only=1&omit_owner=1&l=russian'; if ( rgItemKey.length == 4 && rgItemKey[3] ) { var strOwner = rgItemKey[3]; if ( strOwner.indexOf( 'id:' ) == 0 ) strURL += '&o_url=' + strOwner.substr( 3 ); else strURL += '&o=' + strOwner; } } if ( nAmount && nAmount > 1 ) strURL += '&amount=' + nAmount; return new CDelayedAJAXData( strURL, 100 ); } else return null; }; var rgCallbacks = BindAJAXHovers( $Hover, $HoverContent, { fnDataFactory: fnDataFactory, strDataName: 'economy-item', strURLMatch: 'itemhover' } ); } function ShowTradeOffer( tradeOfferID, rgParams ) { var strParams = ''; if ( rgParams ) strParams = '?' + $J.param( rgParams ); var strKey = ( tradeOfferID == 'new' ? 'NewTradeOffer' + rgParams['partner'] : 'TradeOffer' + tradeOfferID ); var winHeight = 1120; if ( Steam.BIsUserInSteamClient() && Steam.GetClientPackageVersion() < 1407800248 ) { // workaround for client break when the popup window is too tall for the screen. Try and pick a height that will fit here. var nClientChromePX = 92; if ( window.screen.availHeight && window.screen.availHeight - nClientChromePX < winHeight ) winHeight = window.screen.availHeight - nClientChromePX; } var strURL = 'https://steamcommunity.com/tradeoffer/' + tradeOfferID + '/' + strParams; if ( Steam.BIsUserInSteamMobileApp() ) { window.location = strURL; } else { var winOffer = window.open( strURL, strKey, 'height=' + winHeight + ',width=1028,resize=yes,scrollbars=yes' ); winOffer.focus(); } } function Logout() { PostToURLWithSession( 'https://steamcommunity.com/login/logout/' ); } function ChangeLanguage( strTargetLanguage, bStayOnPage ) { var Modal = ShowBlockingWaitDialog( 'Изменить язык', '' ); $J.post( 'https://steamcommunity.com/actions/SetLanguage/', {language: strTargetLanguage, sessionid: g_sessionID }) .done( function() { if ( bStayOnPage ) Modal.Dismiss(); else { if( g_steamID ) window.location = 'https://store.steampowered.com/account/languagepreferences/'; else if ( window.location.href.match( /[?&]l=/ ) ) window.location = window.location.href.replace( /([?&])l=[^&]*&?/, '$1' ); else window.location.reload(); } }).fail( function() { Modal.Dismiss(); ShowAlertDialog( 'Изменить язык', 'При подключении к серверам Steam возникла проблема. Повторите попытку позже.' ); }); } var g_ContentDescriptorPreferences = [ 3, 4 ]; var g_UGCWithNoBlur = {}; var g_bLoadedUGCWithNoBlur = false; var g_UGCSkipAdultContentCheckForAppID = false; function LoadUGCWithNoBlur() { if ( g_bLoadedUGCWithNoBlur ) { return; } var strUGCNoBlur = WebStorage.GetLocal( 'rgUGCNoBlur', false ); if ( strUGCNoBlur != null ) { g_UGCWithNoBlur = JSON.parse( strUGCNoBlur ); } } function SaveUGCWithNoBlur() { var keys = Object.keys( g_UGCWithNoBlur ); var maxKeys = 1000; if ( keys.length >= maxKeys ) { var rgTemp = []; for ( var i = 0; i < keys.length; ++i ) { var key = keys[i]; var value = g_UGCWithNoBlur[key]; rgTemp.push( { v: value['timestamp'], k: key } ); } rgTemp.sort( function( a, b ) { if ( a.v > b.v ) { return 1; } if ( a.v < b.v ) { return -1; } return 0; }); var delta = rgTemp.length - maxKeys; for ( var i = 0; i < rgTemp.length && i < delta; ++i ) { var a = rgTemp[i]; delete g_UGCWithNoBlur[a.k]; } } WebStorage.SetLocal( 'rgUGCNoBlur', JSON.stringify( g_UGCWithNoBlur ), false ); } function ApplyAdultContentPreferences() { LoadUGCWithNoBlur(); var elementsWithAdultContent = $J( '[data-descids]'); if ( elementsWithAdultContent.length == 0 ) { return; } for ( var i = 0; i < elementsWithAdultContent.length; ++i ) { var e = $J( elementsWithAdultContent[i] ); ApplyAdultContentPreferencesHelper( e, g_ContentDescriptorPreferences, false ); } } function ReapplyAdultContentPreferences() { var elementsWithAdultContent = $J( '[data-descids]'); if ( elementsWithAdultContent.length == 0 ) { return; } for ( var i = 0; i < elementsWithAdultContent.length; ++i ) { var e = $J( elementsWithAdultContent[i] ); ApplyAdultContentPreferencesHelper( e, g_ContentDescriptorPreferences, true ); } } function EditContentDescriptors( publishedfileid, callback ) { $J.get( 'https://steamcommunity.com/sharedfiles/ajaxeditcontentdescriptors/', { publishedfileid: publishedfileid } ) .done( function( json ) { if ( json.success == 1 ) { var content = $J( json.html ); var dialog = ShowConfirmDialog( 'Обновить дескрипторы контента', content ); dialog.done( function() { var rgCheckboxes = $J("input:checkbox", content ); var add = []; var remove = []; for ( var i = 0; i < rgCheckboxes.length; ++i ) { let checkbox = rgCheckboxes[i]; if ( checkbox.checked && !checkbox.disabled ) { add.push( checkbox.value ); } else { remove.push( checkbox.value ); } } if ( add.length == 0 && remove.length == 0 ) return; $J.post( 'https://steamcommunity.com/sharedfiles/ajaxupdatecontentdescriptors/', { sessionid: g_sessionID, publishedfileid: publishedfileid, add: add, remove: remove }, ).done( function( json ) { if ( json.success == 1 ) { if ( callback ) { callback( publishedfileid ); } else { window.location.reload(); } } else { ShowAlertDialog( 'Обновить дескрипторы контента', 'При обновлении дескрипторов этого контента произошла ошибка: ' + json.success ); } } ); } ); } } ); } function HandleRelatedContentDescriptors( $topContainer, $elem, bAnimate ) { var checked = $elem.prop( "checked" ) && !$elem.attr( "disabled" ); var descid = $elem.val(); var $container = $elem.closest( '[data-parentdescid]' ); var parentDescID = $container.data( 'parentdescid' ); var childrenDescriptors = $topContainer.find( '[data-parentdescid="' + descid + '"]' ); if ( checked ) { // check all ancestors if ( parentDescID ) { var $parentElem = $topContainer.find( '#descriptor_' + parentDescID ); $parentElem.prop( 'checked', true ); HandleRelatedContentDescriptors( $topContainer, $parentElem, bAnimate ); } } else { childrenDescriptors.each( function( ) { var child = $J( this ); child.find( 'input[type="checkbox"]' ).each( function() { $J( this ).prop( "checked", false ); HandleRelatedContentDescriptors( $topContainer, $J( this ), bAnimate ); } ); } ); } } // override where necessary function HandleNewDynamicLink( newDynamicLinkElement ) { if ( newDynamicLinkElement.hasClass( "has_adult_content" ) ) { ApplyAdultContentPreferencesHelper( newDynamicLinkElement, g_ContentDescriptorPreferences, false ); } } function UGCAdultContentPreferencesMenu( elSource ) { var $El = $J(this); var $elSource = $J(elSource.parentNode); $El.empty(); var appid = $elSource.data('appid'); var publishedFileID = $elSource.data('publishedfileid'); // preferences { var fnViewPreferences = function () { top.location.href = 'https://store.steampowered.com//account/preferences/#CommunityContentPreferences'; return true; }; var $elViewPreferences = $J( '
' ).click( fnViewPreferences ).text( 'Изменить настройки' ).addClass( 'option' ); $El.append( $elViewPreferences ); } } function ApplyAdultContentPreferencesHelper( e, rgContentDescriptorsToExclude, bForce ) { if ( !bForce && e.data( 'processed_adult_content') ) { return; } if ( ( typeof( g_bViewingOwnProfile ) != 'undefined' ) && g_bViewingOwnProfile ) { e.removeClass( 'has_adult_content' ); return; } if ( ( typeof( g_bIsAppHubModerator ) != 'undefined' ) && g_bIsAppHubModerator ) { e.removeClass( 'has_adult_content' ); return; } e.data( 'processed_adult_content', true ); var bIsAnchor = e.is('a'); var publishedFileID = e.data( 'publishedfileid' ); var bCountryDisallowed = e.data( 'adult-disallowed' ); var rgContentDescriptorIDs = e.data( 'descids' ) ?? []; var appid = e.data( 'appid' ); var bForceDeBlur = ( publishedFileID && g_UGCWithNoBlur.hasOwnProperty( publishedFileID ) ) || ( appid && g_UGCSkipAdultContentCheckForAppID == appid ); var filteredArray = rgContentDescriptorIDs.filter( function( descid ) { return rgContentDescriptorsToExclude.indexOf( descid ) !== -1; } ); var bHasExcludedContent = filteredArray.length != 0; if ( bForceDeBlur || !bHasExcludedContent ) { e.removeClass( 'has_adult_content' ); } else if ( bHasExcludedContent ) { e.addClass( 'has_adult_content' ); } if ( e.data( 'ugclinktextonly' ) === 1 || bCountryDisallowed ) { } else { // widget { var $elMenu = $J( '
', { 'class': 'ugc_options' } ).append( $J( '
' ) ); $elMenu.v_tooltip( { 'tooltipClass': 'ugc_options_tooltip', 'location': 'bottom left', 'offsetY': -20, 'useClickEvent': true, 'useMouseEnterEvent': false, 'preventDefault': true, 'stopPropagation': true, func: UGCAdultContentPreferencesMenu } ); e.append( $elMenu ); } // warning if ( e.width() > 100 && !e.hasClass( 'ugc_show_warning_image' ) && !e.hasClass( 'dynamiclink_box' ) ) { var $elWarning = $J( '
', { 'class': 'ugc_warning' } ); if ( e.width() > 350 ) { $elWarning.addClass( "large" ); } if ( e.height() > 125 ) { e.addClass( "ugc_show_warning_image" ); } else { $elWarning.append( $J( '
', { 'class': 'ugc_warning_image' } ) ); } $elWarning.append( $J( '', { 'text': 'Судя по вашим настройкам, контент может вам не подойти '} ) ); var $elOptions = $J( '
' ); var $elViewOption = $J( '
', { 'class': 'ugc_inline_option', 'text': 'Показать контент' } ); $elViewOption.click( function ( event ) { event.preventDefault(); event.stopPropagation(); if ( bIsAnchor && !e.hasClass( "modalContentLink" ) ) { top.location.href = e[0].href; } else { e.removeClass( 'has_adult_content' ); e.click(); e.addClass( 'has_adult_content' ); } return false; } ); $elOptions.append( $elViewOption ); $elOptions.append( " | " ); var $elPreferencesOption = $J( '
', { 'class': 'ugc_inline_option', 'text': 'Изменить настройки' } ); $elPreferencesOption.click( function ( event ) { event.stopPropagation(); top.location.href = 'https://store.steampowered.com/account/preferences'; return false; } ); $elOptions.append( $elPreferencesOption ); $elWarning.append( $elOptions ); e.append( $elWarning ); } else { e.addClass( "ugc_show_warning_image" ); } } } function abuseSSDescripCheck() { var chkd_inap = $('abuseType1').checked; var chkd_cprt = $('abuseType5').checked; if ( chkd_inap ) { $('abuseDescriptionLabel').setStyle( { color: '#777777', fontStyle: 'italic' } ); $('abuseDescriptionArea').disable(); $('abuseDescriptionArea').clear(); } else if ( chkd_cprt ) { $('abuseDescriptionLabel').setStyle( { color: '#898989', fontStyle: 'normal' } ); $('abuseDescriptionArea').enable(); $('abuseDescriptionArea').focus(); } } function BindOnHashChange( fnCallback ) { if ( 'onhashchange' in window ) { Event.observe( window, 'hashchange', function(e) { fnCallback( this.location.hash ); } ); } else { new LocationHashObserver( null, 0.1, function( el, hash ) { fnCallback( hash ); } ); } } LocationHashObserver = Class.create(Abstract.TimedObserver, { getValue: function() { return window.location.hash; } } ); var CAutoSizingTextArea = Class.create( { m_elTextArea: null, m_nMinHeight: 20, m_nMaxHeight: 500, m_cCurrentSize: Number.MAX_VALUE, m_fnChangeCallback: null, m_nTextAreaPadding: null, initialize: function( elTextArea, nMinHeight, fnChangeCallback ) { this.m_elTextArea = elTextArea; var _this = this; $J(this.m_elTextArea ).on( 'keyup blur click paste cut', function( e ) { if ( e.type == 'paste' || e.type == 'blur' ) _this.OnPasteText(); else _this.OnTextInput(); }); this.m_elTextArea.style.overflow = 'hidden'; this.m_cEntryLength = Number.MAX_VALUE; this.m_nMinHeight = nMinHeight || 20; this.m_fnChangeCallback = fnChangeCallback || null; this.m_elTextArea.style.height = this.m_nMinHeight + 'px'; this.OnTextInput(); }, CalculatePadding: function() { // briefly empty the text area and set the height so we can see how much padding there is var strContents = this.m_elTextArea.value; this.m_elTextArea.value = ''; this.m_elTextArea.style.height = this.m_nMinHeight + 'px'; this.m_nTextAreaPadding = this.m_elTextArea.scrollHeight - this.m_nMinHeight; this.m_elTextArea.value = strContents; }, OnPasteText: function() { this.OnTextInput.bind( this ).defer(); }, OnTextInput: function() { var iScrollOffset = undefined; var cNewLength = this.m_elTextArea.value.length; // we delay this until first input as some values get reported incorrectly if the element isn't visible. if ( this.m_nTextAreaPadding === null && $J(this.m_elTextArea ).is(':visible') ) this.CalculatePadding(); // force a resize if ( cNewLength < this.m_cEntryLength ) { // when we shrink this box, we might scroll the window. Remember where we are so we can jump back iScrollOffset = window.scrollY; this.m_elTextArea.style.height = this.m_nMinHeight + 'px'; } if ( this.m_elTextArea.scrollHeight > this.m_nMaxHeight ) { this.m_elTextArea.style.height = this.m_nMaxHeight + 'px'; this.m_elTextArea.style.overflow = 'auto'; } else if ( this.m_elTextArea.scrollHeight != this.m_elTextArea.getHeight() ) { var nHeight = Math.max( this.m_elTextArea.scrollHeight, this.m_nMinHeight ); this.m_elTextArea.style.height = ( nHeight - this.m_nTextAreaPadding ) + 'px'; if ( this.m_elTextArea.style.overflow == 'auto' ) this.m_elTextArea.style.overflow = 'hidden'; } if ( this.m_fnChangeCallback ) this.m_fnChangeCallback( this.m_elTextArea ); if ( iScrollOffset ) window.scrollTo( window.scrollX, iScrollOffset ); this.m_cEntryLength = cNewLength; } }); function UpdateParameterInCurrentURL( strParamName, strParamValue, rgRemoveParameters ) { var path = window.location.pathname; var query = window.location.search; var params = {}; if ( query && query.length > 2 ) params = $J.deparam( query.substr( 1 ) ); if ( strParamValue === null ) delete params[strParamName]; else params[strParamName] = strParamValue; // comment thread specific if ( rgRemoveParameters ) for( var i = 0; i < rgRemoveParameters.length; i++ ) delete params[ rgRemoveParameters[i] ]; query = $J.param( params ); return path + ( query ? '?' + query : '' ); } var g_rgCommentThreads = {}; function InitializeCommentThread( type, name, rgCommentData, url, nQuoteBoxHeight ) { // see if we have a custom comment thread class for this type var commentclass = CCommentThread; if ( window['CCommentThread' + type] ) commentclass = window['CCommentThread' + type]; g_rgCommentThreads[name] = new commentclass( type, name, rgCommentData, url, nQuoteBoxHeight ); } function BindCommentThreadSubscribeButtons( type, owner, gidfeature, gidfeature2, btnSubscribe, btnUnsubscribe ) { var CommentThread = FindCommentThread( type, owner, gidfeature, gidfeature2 ); if ( CommentThread ) CommentThread.BindSubscribeButtons( btnSubscribe, btnUnsubscribe ); } function FindCommentThread( type, owner, gidFeature, gidFeature2 ) { for ( var key in g_rgCommentThreads ) { if ( g_rgCommentThreads[key].BMatches( type, owner, gidFeature, gidFeature2 ) ) return g_rgCommentThreads[key]; } return null; } var CCommentThread = Class.create( { m_strName: null, m_strCommentThreadType: null, m_rgCommentData: null, m_strActionURL: null, m_elTextArea: null, m_cPageSize: null, m_nQuoteBoxHeight: 40, m_cTotalCount: 0, m_iCurrentPage: 0, m_cMaxPages: 0, m_cDropdownPages: 0, m_bLoading: false, m_bLoadingUserHasUpVoted : false, m_cUpVotes: 0, m_bIncludeRaw: false, m_rgRawCommentCache: null, m_bHasPaging: true, m_bTrackNavigation: false, // should we track navigation in the URL? // these vars are id's we'll update when values change m_votecountID: null, m_voteupID: null, m_commentcountID: null, m_oTextAreaSizer: null, m_bSubscribed: null, m_$SubscribeCheckbox: null, initialize: function( type, name, rgCommentData, url, nQuoteBoxHeight ) { this.m_strName = name; this.m_strCommentThreadType = type; this.m_rgCommentData = rgCommentData; this.m_strActionURL = url; this.m_nQuoteBoxHeight = nQuoteBoxHeight; var start = rgCommentData['start'] ? rgCommentData['start'] : 0; this.m_cTotalCount = rgCommentData['total_count']; this.m_cPageSize = rgCommentData['pagesize']; this.m_iCurrentPage = Math.floor( start / this.m_cPageSize ); this.m_cMaxPages = Math.ceil( this.m_cTotalCount / this.m_cPageSize ); this.m_bLoadingUserHasUpVoted = rgCommentData['has_upvoted']; this.m_cUpVotes = rgCommentData['upvotes']; this.m_votecountID = rgCommentData['votecountid']; this.m_voteupID = rgCommentData['voteupid']; this.m_commentcountID = rgCommentData['commentcountid']; this.m_bSubscribed = rgCommentData['subscribed']; this.m_bHasPaging = !rgCommentData['no_paging']; this.m_bTrackNavigation = !!rgCommentData['track_navigation']; var strPrefix = 'commentthread_' + this.m_strName; this.m_elTextArea = $( strPrefix + '_textarea'); if ( rgCommentData['comments_raw'] ) { this.m_bIncludeRaw = true; this.m_rgRawCommentCache = rgCommentData['comments_raw']; rgCommentData['comments_raw'] = undefined; } if ( this.m_elTextArea ) { var elSaveButton = $('commentthread_' + this.m_strName + '_submit_container'); var iMinHeight = this.m_nQuoteBoxHeight; if ( this.m_strName.startsWith( 'Profile_' ) ) iMinHeight = 20; this.m_oTextAreaSizer = new CAutoSizingTextArea( this.m_elTextArea, iMinHeight, this.OnTextInput.bind( this, elSaveButton ) ); } var _this = this; if ( this.m_bHasPaging ) { $(strPrefix + '_pagebtn_prev').observe( 'click', this.OnPagingButtonClick.bindAsEventListener( this , this.PrevPage ) ); $(strPrefix + '_fpagebtn_prev').observe( 'click', this.OnPagingButtonClick.bindAsEventListener( this , this.PrevPage ) ); $(strPrefix + '_pagebtn_next').observe( 'click', this.OnPagingButtonClick.bindAsEventListener( this , this.NextPage ) ); $(strPrefix + '_fpagebtn_next').observe( 'click', this.OnPagingButtonClick.bindAsEventListener( this , this.NextPage ) ); if ( this.m_bTrackNavigation && window.history && window.history.pushState ) { window.history.replaceState( {comment_thread_page: this.m_iCurrentPage }, '' ); $J(window).on('popstate', function( e ) { var oState = e.originalEvent.state; if ( oState && typeof oState.comment_thread_page != 'undefined' ) _this.GoToPage( oState.comment_thread_page ); }); } } var elForm = $( strPrefix + '_form'); if ( elForm ) { elForm.observe( 'submit', this.OnSubmit.bind( this ) ); } var elSubmit = $(strPrefix + '_submit'); if ( elSubmit ) { elSubmit.observe( 'click', this.OnSubmit.bind( this ) ); } var elAutosubscribe = $(strPrefix + '_autosubscribe' ); if ( elAutosubscribe ) { // initialize check state based on preferences elAutosubscribe.checked = this.m_bSubscribed || GetValueLocalStorage( 'forum_autosubscribe', false ); elAutosubscribe.observe( 'change', this.OnAutosubscribeToggle.bind( this ) ); } var elSubscribe = $(strPrefix + '_subscribe'); var elUnsubscribe = $(strPrefix + '_unsubscribe' ); if ( elSubscribe && elUnsubscribe ) { this.BindSubscribeButtons( elSubscribe, elUnsubscribe ); } this.m_$SubscribeCheckbox = $J('#' + strPrefix + '_subscribe_checkbox'); this.m_$SubscribeCheckbox.click( function() { if ( _this.m_$SubscribeCheckbox.hasClass( 'waiting' ) ) return; if ( _this.m_bSubscribed ) _this.Unsubscribe( function() {}, function() {ShowAlertDialog('Подписаться', 'При обновлении подписки произошла ошибка. Пожалуйста, повторите попытку позже.');}); else _this.Subscribe( function() {}, function() {ShowAlertDialog('Подписаться', 'При обновлении подписки произошла ошибка. Пожалуйста, повторите попытку позже.');}); }); this.UpdatePagingDisplay(); this.HighlightComment(); }, HighlightComment: function() { var urlParams = new URLSearchParams( window.location.search ); var gidComment = urlParams.get( 'gidcommenthighlight' ); if ( gidComment ) { $J( "#comment_" + gidComment ).addClass( 'highlighted' ); setTimeout( function() { $J( "#comment_" + gidComment )[0].scrollIntoView(); },500 ); } }, BMatches: function( strType, steamidOwner, gidFeature, gidFeature2 ) { return this.m_strCommentThreadType == strType && this.m_rgCommentData['owner'] == steamidOwner && this.m_rgCommentData['feature'] == gidFeature && this.m_rgCommentData['feature2'] == gidFeature2; }, CheckTextAreaSize: function() { this.m_oTextAreaSizer.OnTextInput(); }, OnTextInput: function( elSaveButton, elTextArea ) { if ( elSaveButton ) { var strPrepoulatedText = $J(this.m_elTextArea ).data('prepopulated-text'); var bEnteredText = elTextArea.value.length > 0; if ( bEnteredText && strPrepoulatedText && !$J(this.m_elTextArea ).data('replaced-prepopulated-text') ) { strPrepoulatedText = v_trim( strPrepoulatedText ).replace( /[\n\r]/g, '' ); var strEnteredText = v_trim( elTextArea.value ).replace( /[\n\r]/g, '' ); bEnteredText = strPrepoulatedText != strEnteredText; // save so we don't have to keep doing this check as they enter more text. if ( bEnteredText ) $J(this.m_elTextArea ).data('replaced-prepopulated-text', true ); } if ( bEnteredText ) elSaveButton.show(); else elSaveButton.hide(); } }, GetActionURL: function( action ) { var url = this.m_strActionURL + action + '/'; url += this.m_rgCommentData['owner'] + '/'; url += this.m_rgCommentData['feature'] + '/'; return url; }, ParametersWithDefaults: function( params ) { if ( !params ) params = {}; params['count'] = this.m_cPageSize; params['sessionid'] = g_sessionID; if ( this.m_rgCommentData['extended_data'] ) params['extended_data'] = this.m_rgCommentData['extended_data']; if ( this.m_rgCommentData['feature2'] ) params['feature2'] = this.m_rgCommentData['feature2']; if ( this.m_rgCommentData['oldestfirst'] ) params['oldestfirst'] = true; if ( this.m_rgCommentData['newestfirstpagination'] ) params['newestfirstpagination'] = true; if ( this.m_rgCommentData['lastvisit'] ) params['lastvisit'] = this.m_rgCommentData['lastvisit']; if ( this.m_bIncludeRaw ) params['include_raw'] = true; return params; }, OnSubmit: function() { if ( this.m_bLoading ) return; var strPrepoulatedText = $J(this.m_elTextArea ).data('prepopulated-text'); if ( strPrepoulatedText && v_trim( strPrepoulatedText ).replace( /[\n\r]/g, '' ) == v_trim( this.m_elTextArea.value ).replace( /[\n\r]/g, '' ) ) { ShowAlertDialog( '', 'Введите здесь свой комментарий.' ); return; } var params = this.ParametersWithDefaults( { comment: this.m_elTextArea.value } ); this.m_bLoading = true; new Ajax.Request( this.GetActionURL( 'post' ), { method: 'post', parameters: params, onSuccess: this.OnResponseAddComment.bind( this, ++this.m_nRenderAjaxSequenceNumber ), onFailure: this.OnFailureDisplayError.bind( this ), onComplete: this.OnAJAXComplete.bind( this ) } ); var elAutosubscribe = $( 'commentthread_' + this.m_strName + '_autosubscribe' ); if ( elAutosubscribe && elAutosubscribe.checked && !this.m_bSubscribed ) this.Subscribe(); return false; }, DeleteComment: function( gidComment, bUndelete, fnOnSuccess ) { if ( this.m_bLoading ) return; var params = this.ParametersWithDefaults( { gidcomment: gidComment, start: this.m_cPageSize * this.m_iCurrentPage } ); if ( bUndelete ) params.undelete = 1; this.m_bLoading = true; new Ajax.Request( this.GetActionURL( 'delete' ), { method: 'post', parameters: params, onSuccess: fnOnSuccess ? fnOnSuccess : this.OnResponseDeleteComment.bind( this, ++this.m_nRenderAjaxSequenceNumber ), onFailure: this.OnFailureDisplayError.bind( this ), onComplete: this.OnAJAXComplete.bind( this ) } ); }, MarkSpam: function( gidComment, authorAccountID, fnOnSuccess ) { if ( this.m_bLoading ) return; var params = this.ParametersWithDefaults( { gidcomment: gidComment, author_accountid: authorAccountID, start: this.m_cPageSize * this.m_iCurrentPage } ); var thread = this; var dialog = ShowConfirmDialog( 'Пометить как подозрительное', 'Автор будет заблокирован в сообществе, и все его комментарии будут удалены. Наша система проанализирует этот комментарий, чтобы скрывать подобный контент автоматически. Вы уверены, что хотите сделать это?', 'Пометить как подозрительное' ); dialog.done( function() { thread.m_bLoading = true; new Ajax.Request( thread.GetActionURL( 'markspam' ), { method: 'post', parameters: params, onSuccess: fnOnSuccess ? fnOnSuccess : thread.OnResponseDeleteComment.bind( thread, ++thread.m_nRenderAjaxSequenceNumber ), onFailure: thread.OnFailureDisplayError.bind( thread ), onComplete: thread.OnAJAXComplete.bind( thread ) } ); } ); }, ClearContentCheckFlag: function( gidComment, fnOnSuccess ) { if ( this.m_bLoading ) return; var params = this.ParametersWithDefaults( { gidcomment: gidComment, start: this.m_cPageSize * this.m_iCurrentPage } ); var thread = this; var dialog = ShowConfirmDialog( 'Снять пометку о блокируемом контенте', 'Вы уверены, что хотите снять пометку о блокируемом контенте с этого комментария? Это действие нельзя отменить.', 'Снять пометку о блокируемом контенте' ); dialog.done( function() { thread.m_bLoading = true; new Ajax.Request( thread.GetActionURL( 'clearcontentcheckflag' ), { method: 'post', parameters: params, onSuccess: fnOnSuccess ? fnOnSuccess : thread.OnResponseDeleteComment.bind( thread, ++thread.m_nRenderAjaxSequenceNumber ), onFailure: thread.OnFailureDisplayError.bind( thread ), onComplete: thread.OnAJAXComplete.bind( thread ) } ); } ); }, HideAndReport: function( gidComment, bHide, fnOnSuccess ) { if ( this.m_bLoading ) return; var params = this.ParametersWithDefaults( { gidcomment: gidComment, hide: bHide, start: this.m_cPageSize * this.m_iCurrentPage } ); this.m_bLoading = true; new Ajax.Request( this.GetActionURL( 'hideandreport' ), { method: 'post', parameters: params, onSuccess: fnOnSuccess ? fnOnSuccess : this.OnResponseHideAndReportComment.bind( this, ++this.m_nRenderAjaxSequenceNumber ), onFailure: this.OnFailureDisplayError.bind( this ), onComplete: this.OnAJAXComplete.bind( this ) } ); }, OnResponseHideAndReportComment: function( nAjaxSequenceNumber, transport ) { if ( transport.responseJSON && transport.responseJSON.success ) this.OnResponseRenderComments( CCommentThread.RENDER_GOTOCOMMENT, nAjaxSequenceNumber, transport ); else this.OnFailureDisplayError( transport ); }, DisplayEditComment: function( gidComment ) { var elForm = $('editcommentform_' + gidComment); var elTextarea = $('comment_edit_text_' + gidComment); var elContent = $('comment_content_' + gidComment); elContent.hide(); if ( elContent.next('.forum_audit') ) elContent.next('.forum_audit').hide(); $('comment_edit_' + gidComment).show(); $('comment_edit_' + gidComment + '_error').update(''); if ( !elTextarea.value || elTextarea.value.length == 0 ) elTextarea.value = this.m_rgRawCommentCache[ gidComment ].text; if ( !elForm.m_bEventsBound ) { new CAutoSizingTextArea( elTextarea, 40 ); elForm.observe( 'submit', this.SubmitEditComment.bind( this, elForm ) ); elForm.observe( 'reset', this.HideEditComment.bind( this, gidComment ) ); elForm.m_bEventsBound = true; } }, VoteUp: function() { if ( this.m_bLoading ) return; var params = this.ParametersWithDefaults( { vote: this.m_bLoadingUserHasUpVoted ? 0 : 1 // flip our vote } ); this.m_bLoading = true; new Ajax.Request( this.GetActionURL( 'voteup' ), { method: 'post', parameters: params, onSuccess: this.OnResponseVoteUp.bind( this, ++this.m_nRenderAjaxSequenceNumber ), onFailure: this.OnFailureDisplayError.bind( this ), onComplete: this.OnAJAXComplete.bind( this ) } ); }, UpdateAnswer: function( gidComment, bExisting ) { // see if it's on the current page if ( this.m_bLoading ) return; if ( !gidComment ) { $modal = ShowConfirmDialog( 'Удалить ответ', 'Вы уверены, что это сообщение не является ответом на обсуждение? Решение можно будет изменить.', 'Удалить ответ' ); } else { var strModalBody = 'Вы хотите сделать это сообщение ответом на тему? В ней появится пометка об ответе и отдельная ссылка на него. Пометку можно будет удалить или переместить на другое сообщение.'; if ( bExisting ) strModalBody = 'В этом обсуждении уже выбран ответ. Вы уверены, что хотите сделать это сообщение новым ответом?'; $modal = ShowConfirmDialog( 'Отметить как ответ', strModalBody, 'Выбрать ответ' ); $modal.SetMaxWidth(500); } var _$this = this; $modal.done( function(){ var params = _$this.ParametersWithDefaults( { gidcommentanswer: gidComment } ); _$this.m_bLoading = true; new Ajax.Request( _$this.GetActionURL( 'updateanswer' ), { method: 'post', parameters: params, onSuccess: function() { window.location.hash = 'c' + gidComment; window.location.reload(); }, onFailure: function( transport ) { if ( transport.responseJSON && transport.responseJSON.success ) { var strError = 'Не удалось изменить ответ. Ошибка: ' + transport.responseJSON.success; if ( transport.responseJSON.success == 15 ) { strError = 'У вас нет разрешения обновить ответ этой темы.' } ShowAlertDialog( 'Ошибка', strError ); } }, onComplete: _$this.OnAJAXComplete.bind( _$this ) }); } ); }, GetRawComment: function( gidComment ) { return this.m_rgRawCommentCache[ gidComment ]; }, GetCommentTextEntryElement: function() { return this.m_elTextArea; }, HideEditComment: function( gidComment ) { $('comment_content_' + gidComment).show(); $('comment_edit_' + gidComment).hide(); }, OnResponseEditComment: function( gidComment, nAjaxSequenceNumber, transport ) { if ( transport.responseJSON && transport.responseJSON.success) { // no need to hide because render will replace our whole element this.OnResponseRenderComments( CCommentThread.RENDER_DELETEDPOST, nAjaxSequenceNumber, transport ); //display the updated comment thread } else { this.OnEditFailureDisplayError( gidComment, transport ); } }, OnEditFailureDisplayError: function( gidComment, transport ) { this.DisplayError( $('comment_edit_' + gidComment + '_error'), transport ); }, SubmitEditComment: function( elForm ) { if ( this.m_bLoading ) return false; var gidComment = elForm.elements['gidcomment'].value; var strComment = elForm.elements['comment'].value; var params = this.ParametersWithDefaults( { gidcomment: gidComment, comment: strComment, start: this.m_cPageSize * this.m_iCurrentPage } ); this.m_bLoading = true; new Ajax.Request( this.GetActionURL( 'edit' ), { method: 'post', parameters: params, onSuccess: this.OnResponseEditComment.bind( this, gidComment, ++this.m_nRenderAjaxSequenceNumber ), onFailure: this.OnEditFailureDisplayError.bind( this, gidComment ), onComplete: this.OnAJAXComplete.bind( this ) } ); return false; }, OnAJAXComplete: function() { this.m_bLoading = false; }, OnPagingButtonClick: function( event, fnToExecute ) { event.stop(); fnToExecute.call( this ); }, NextPage: function() { if ( this.m_iCurrentPage < this.m_cMaxPages - 1 ) this.GoToPage( this.m_iCurrentPage + 1 ); }, PrevPage: function() { if ( this.m_iCurrentPage > 0 ) this.GoToPage( this.m_iCurrentPage - 1 ); }, m_nRenderAjaxSequenceNumber: 0, GoToPage: function( iPage, eRenderReason ) { if ( iPage >= this.m_cMaxPages || iPage < 0 || ( iPage == this.m_iCurrentPage && !this.m_bLoading ) ) return; var params = this.ParametersWithDefaults( { start: this.m_cPageSize * iPage, totalcount: this.m_cTotalCount } ); this.m_bLoading = true; new Ajax.Request( this.GetActionURL( 'render' ), { method: 'post', parameters: params, onSuccess: this.OnResponseRenderComments.bind( this, eRenderReason || CCommentThread.RENDER_GOTOPAGE, ++this.m_nRenderAjaxSequenceNumber ), onComplete: this.OnAJAXComplete.bind( this ) }); }, GoToPageWithComment: function( gidComment, eRenderReason ) { // see if it's on the current page if ( this.m_bLoading || $('comment_' + gidComment ) ) return; // nope, load var params = this.ParametersWithDefaults( { gidComment: gidComment } ); new Ajax.Request( this.GetActionURL( 'render' ), { method: 'post', parameters: params, onSuccess: this.OnResponseRenderComments.bind( this, eRenderReason || CCommentThread.RENDER_GOTOCOMMENT, ++this.m_nRenderAjaxSequenceNumber ), onComplete: this.OnAJAXComplete.bind( this ) }); }, OnResponseAddComment: function( nAjaxSequenceNumber, transport ) { if ( transport.responseJSON && transport.responseJSON.success) { $('commentthread_' + this.m_strName + '_entry_error').hide(); this.m_elTextArea.value=''; this.CheckTextAreaSize(); this.OnResponseRenderComments( CCommentThread.RENDER_NEWPOST, nAjaxSequenceNumber, transport ); //display the updated comment thread if ( $('commentthread_' + this.m_strName + '_subscribeoptions') ) $('commentthread_' + this.m_strName + '_subscribeoptions').show(); } else { this.OnFailureDisplayError( transport ); } }, OnResponseDeleteComment: function( nAjaxSequenceNumber, transport ) { if ( transport.responseJSON && transport.responseJSON.success ) this.OnResponseRenderComments( CCommentThread.RENDER_DELETEDPOST, nAjaxSequenceNumber, transport ); else this.OnFailureDisplayError( transport ); }, OnResponseVoteUp: function( nAjaxSequenceNumber, transport ) { if ( transport.responseJSON && transport.responseJSON.success ) { this.OnResponseRenderComments( CCommentThread.RENDER_GOTOCOMMENT, nAjaxSequenceNumber, transport ); this.m_bLoadingUserHasUpVoted = !this.m_bLoadingUserHasUpVoted; // we can switch this to getting from the response after 8/24/2012 this.m_cUpVotes = transport.responseJSON.upvotes; if ( this.m_votecountID && $(this.m_votecountID) && transport.responseJSON.votetext ) { $(this.m_votecountID).innerHTML = transport.responseJSON.votetext; } if ( this.m_voteupID && $(this.m_voteupID) ) { if ( this.m_bLoadingUserHasUpVoted ) $(this.m_voteupID).addClassName('active'); else $(this.m_voteupID).removeClassName('active'); } } else this.OnFailureDisplayError( transport ); }, OnFailureDisplayError: function( transport ) { this.DisplayError( $('commentthread_' + this.m_strName + '_entry_error'), transport ); }, DisplayError: function( elError, transport ) { var strMessage = 'Простите, что-то пошло не так: '; if ( transport.responseJSON && transport.responseJSON.error ) strMessage += transport.responseJSON.error; else strMessage += 'Ошибка соединения с сетью. Пожалуйста, повторите попытку позже.'; elError.update( strMessage ); elError.show(); }, OnResponseRenderComments: function( eRenderReason, nAjaxSequenceNumber, transport ) { if ( this.m_nRenderAjaxSequenceNumber != nAjaxSequenceNumber ) return; if ( transport.responseJSON ) { var response = transport.responseJSON; this.m_cTotalCount = response.total_count; this.m_cMaxPages = Math.ceil( response.total_count / response.pagesize ); this.m_iCurrentPage = Math.floor( response.start / response.pagesize ); if ( response.comments_raw ) this.m_rgRawCommentCache = response.comments_raw; if ( this.m_commentcountID && $(this.m_commentcountID) ) $(this.m_commentcountID).innerHTML = this.m_cTotalCount; if ( this.m_cTotalCount <= response.start && this.m_iCurrentPage > 0 ) { // this page is no logner valid, flip back a page (deferred so that the AJAX handler exits and reset m_bLoading) this.GoToPage.bind( this, this.m_iCurrentPage - 1 ).defer(); return; } if ( this.m_bTrackNavigation && window.history && window.history.pushState ) { var params = window.location.search.length ? $J.deparam( window.location.search.substr(1) ) : {}; if ( ( !params['ctp'] && this.m_iCurrentPage != 0 ) || ( params['ctp'] && params['ctp'] != this.m_iCurrentPage + 1 ) ) { var fnStateUpdate = window.history.pushState.bind( window.history ); var url = UpdateParameterInCurrentURL( 'ctp', this.m_iCurrentPage == 0 ? null : this.m_iCurrentPage + 1, ['tscn'] ); if ( eRenderReason == CCommentThread.RENDER_GOTOPAGE_HASHCHANGE || eRenderReason == CCommentThread.RENDER_GOTOCOMMENT_HASHCHANGE ) { fnStateUpdate = window.history.replaceState.bind( window.history ); if ( eRenderReason == CCommentThread.RENDER_GOTOCOMMENT_HASHCHANGE ) url += window.location.hash; } fnStateUpdate( { comment_thread_page: this.m_iCurrentPage }, '', url ); } } this.DoTransitionToNewPosts( response, eRenderReason ); // if we're viewing the most recent page of comments, refresh notifications if ( ( !this.m_rgCommentData['oldestfirst'] && this.m_iCurrentPage == 0 ) || this.m_rgCommentData['oldestfirst'] && ( this.m_iCurrentPage + 1 ) * this.m_cPageSize > this.m_cTotalCount ) { RefreshNotificationArea(); } this.UpdatePagingDisplay(); } }, DoTransitionToNewPosts: function( response, eRenderReason ) { var strNewHTML = response.comments_html; var elPosts = $('commentthread_' + this.m_strName + '_posts' ); var elContainer = $('commentthread_' + this.m_strName + '_postcontainer' ); elContainer.style.display = 'block'; elContainer.style.height = elContainer.getHeight() + 'px'; elContainer.style.overflow = 'hidden'; elContainer.style.display = this.m_cTotalCount ? 'block' : 'none'; var bNewPost = ( eRenderReason == CCommentThread.RENDER_NEWPOST ); if ( bNewPost && this.m_cTotalCount <= this.m_cPageSize && !this.m_rgCommentData['oldestfirst'] && !this.m_rgCommentData['newestfirstpagination'] ) { elContainer.style.position = 'relative'; elPosts.style.position = 'absolute'; elPosts.style.left = '0px'; elPosts.style.right = '0px'; elPosts.style.bottom = '0px'; } else { elPosts.style.position = 'static'; } elPosts.update( strNewHTML ); ScrollToIfNotInView( $('commentthread_' + this.m_strName + '_area'), 40, 20 ); if ( elContainer.effect ) elContainer.effect.cancel(); ( function() { elContainer.effect = new Effect.Morph( elContainer, { style: 'height: ' + elPosts.getHeight() + 'px', duration: 0.25, afterFinish: function() { elPosts.style.position = 'static'; elContainer.style.height = 'auto'; elContainer.style.overflow = ''; } } ); }).defer(); }, UpdatePagingDisplay: function() { if ( !this.m_bHasPaging ) return; var strPrefix = 'commentthread_' + this.m_strName; // this element not displayed on the forum topic page $(strPrefix + '_totalcount') && $(strPrefix + '_totalcount').update( v_numberformat( this.m_cTotalCount ) ); var rgPagingControls = [ strPrefix + '_page', strPrefix + '_fpage' ]; for ( var i = 0; i < rgPagingControls.length; i++ ) { var strPagePrefix = rgPagingControls[i]; // these elements are displayed on the forum topic page $(strPagePrefix + 'total') && $(strPagePrefix + 'total').update( v_numberformat( this.m_cTotalCount ) ); $(strPagePrefix + 'start') && $(strPagePrefix + 'start').update( v_numberformat( this.m_iCurrentPage * this.m_cPageSize + 1 ) ); $(strPagePrefix + 'end') && $(strPagePrefix + 'end').update( Math.min( ( this.m_iCurrentPage + 1 ) * this.m_cPageSize, this.m_cTotalCount ) ); if ( $(strPagePrefix + 'ctn' ) ) { if ( this.m_cTotalCount > 0 ) $(strPagePrefix + 'ctn' ).show(); else $(strPagePrefix + 'ctn' ).hide(); } if ( this.m_cMaxPages <= 1 ) { $(strPagePrefix + 'controls').hide(); } else { $(strPagePrefix + 'controls').show(); if ( this.m_iCurrentPage > 0 ) { $(strPagePrefix + 'btn_prev').removeClassName('disabled'); if ( this.m_bTrackNavigation ) $(strPagePrefix + 'btn_prev').href = UpdateParameterInCurrentURL( 'ctp', this.m_iCurrentPage == 1 ? null : this.m_iCurrentPage, ['tscn'] ); } else { $(strPagePrefix + 'btn_prev').addClassName('disabled'); if ( this.m_bTrackNavigation ) $(strPagePrefix + 'btn_prev').href = 'javascript:void(0);'; } if ( this.m_iCurrentPage < this.m_cMaxPages - 1 ) { $(strPagePrefix + 'btn_next').removeClassName('disabled'); if ( this.m_bTrackNavigation ) $(strPagePrefix + 'btn_next').href = UpdateParameterInCurrentURL( 'ctp', this.m_iCurrentPage + 2, ['tscn'] ); } else { $(strPagePrefix + 'btn_next').addClassName('disabled'); if ( this.m_bTrackNavigation ) $(strPagePrefix + 'btn_next').href = 'javascript:void(0);'; } var elPageLinks = $(strPagePrefix + 'links'); elPageLinks.update(''); // we always show first, last, + 3 page links closest to current page var cPageLinksAheadBehind = 2; var firstPageLink = Math.max( this.m_iCurrentPage - cPageLinksAheadBehind, 1 ); var lastPageLink = Math.min( this.m_iCurrentPage + (cPageLinksAheadBehind*2) + ( firstPageLink - this.m_iCurrentPage ), this.m_cMaxPages - 2 ); if ( lastPageLink - this.m_iCurrentPage < cPageLinksAheadBehind ) firstPageLink = Math.max( this.m_iCurrentPage - (cPageLinksAheadBehind*2) + ( lastPageLink - this.m_iCurrentPage ), 1 ); this.AddPageLink( elPageLinks, 0 ); if ( firstPageLink != 1 ) elPageLinks.insert( ' ... ' ); for ( var iPage = firstPageLink; iPage <= lastPageLink; iPage++ ) { this.AddPageLink( elPageLinks, iPage ); } if ( lastPageLink != this.m_cMaxPages - 2 ) elPageLinks.insert( ' ... ' ); this.AddPageLink( elPageLinks, this.m_cMaxPages - 1 ); } // update the dropdown list with the total. var $DropdownCtn = $J( '#' + strPagePrefix + 'dropdown'); var $Select = $DropdownCtn.children( 'select' ); if ( true ) { if ( !$Select.length ) { $Select = $J('