@ -1,5 +1,9 @@
window . chat = function ( ) { } ;
//
// timestamp and clear management
//
window . chat . _oldFactionTimestamp = - 1 ;
window . chat . _newFactionTimestamp = - 1 ;
window . chat . _oldPublicTimestamp = - 1 ;
@ -13,8 +17,27 @@ window.chat.getNewestTimestamp = function(public) {
return chat [ '_new' + ( public ? 'Public' : 'Faction' ) + 'Timestamp' ] ;
}
window . chat . _needsClearing = false ;
window . chat . clear = function ( ) {
console . log ( 'clearing now' ) ;
window . chat . _displayedFactionGuids = [ ] ;
window . chat . _displayedPublicGuids = [ ] ;
window . chat . _displayedPlayerActionTime = { } ;
window . chat . _oldFactionTimestamp = - 1 ;
window . chat . _newFactionTimestamp = - 1 ;
window . chat . _oldPublicTimestamp = - 1 ;
window . chat . _newPublicTimestamp = - 1 ;
$ ( '#chatfaction, #chatpublic, #chatautomated' ) . data ( 'ignoreNextScroll' , true ) . html ( '' ) ;
}
window . chat . clearIfRequired = function ( ) {
if ( ! chat . _needsClearing ) return ;
chat . clear ( ) ;
chat . _needsClearing = false ;
}
window . chat . _oldBBox = null ;
window . chat . genPostData = function ( public , getOlderMsgs ) {
if ( typeof public !== 'boolean' ) throw ( 'Need to know if public or faction chat.' ) ;
@ -23,14 +46,14 @@ window.chat.genPostData = function(public, getOlderMsgs) {
var b = map . getBounds ( ) . extend ( chat . _localRangeCircle . getBounds ( ) ) ;
var bbs = b . toBBoxString ( ) ;
chat . _needsClearing = chat . _oldBBox && chat . _oldBBox !== bbs ;
chat . _needsClearing = chat . _needsClearing || chat . _ oldBBox && chat . _oldBBox !== bbs ;
if ( chat . _needsClearing ) console . log ( 'Bounding Box changed, chat will be cleared (old: ' + chat . _oldBBox + ' ; new: ' + bbs + ' )' ) ;
chat . _oldBBox = bbs ;
var ne = b . getNorthEast ( ) ;
var sw = b . getSouthWest ( ) ;
var data = {
desiredNumItems : public ? 100 : 50 , // public contains so much crap
desiredNumItems : public ? CHAT _PUBLIC _ITEMS : CHAT _FACTION _ITEMS ,
minLatE6 : Math . round ( sw . lat * 1E6 ) ,
minLngE6 : Math . round ( sw . lng * 1E6 ) ,
maxLatE6 : Math . round ( ne . lat * 1E6 ) ,
@ -66,6 +89,8 @@ window.chat.genPostData = function(public, getOlderMsgs) {
return data ;
}
//
// requesting faction
//
@ -108,6 +133,7 @@ window.chat.requestNewFaction = function(isRetry) {
requests . add ( r ) ;
}
//
// handle faction
//
@ -122,6 +148,8 @@ window.chat.handleNewFaction = function(data, textStatus, jqXHR) {
chat . handleFaction ( data , textStatus , jqXHR , false ) ;
}
window . chat . _displayedFactionGuids = [ ] ;
window . chat . handleFaction = function ( data , textStatus , jqXHR , isOldMsgs ) {
if ( ! data || ! data . result ) {
@ -129,55 +157,25 @@ window.chat.handleFaction = function(data, textStatus, jqXHR, isOldMsgs) {
return console . warn ( 'faction chat error. Waiting for next auto-refresh.' ) ;
}
chat . clearIfRequired ( ) ;
if ( data . result . length === 0 ) return ;
chat . _newFactionTimestamp = data . result [ 0 ] [ 1 ] ;
chat . _oldFactionTimestamp = data . result [ data . result . length - 1 ] [ 1 ] ;
chat . clearIfRequired ( ) ;
var msgs = '' ;
var prevTime = null ;
$ . each ( data . result . reverse ( ) , function ( ind , json ) { // oldest first!
// avoid duplicates
if ( window . chat . _displayedFactionGuids . indexOf ( json [ 0 ] ) !== - 1 ) return ;
window . chat . _displayedFactionGuids . push ( json [ 0 ] ) ;
var time = json [ 1 ] ;
var msg = json [ 2 ] . plext . markup [ 2 ] [ 1 ] . plain ;
var team = json [ 2 ] . plext . team === 'ALIENS' ? TEAM _ENL : TEAM _RES ;
var nick = json [ 2 ] . plext . markup [ 1 ] [ 1 ] . plain . slice ( 0 , - 2 ) ; // cut “: ” at end
var pguid = json [ 2 ] . plext . markup [ 1 ] [ 1 ] . guid ;
window . setPlayerName ( pguid , nick ) ; // free nick name resolves
var nowTime = new Date ( time ) . toLocaleDateString ( ) ;
if ( prevTime && prevTime !== nowTime )
msgs += chat . renderDivider ( nowTime ) ;
msgs += chat . renderMsg ( msg , nick , time , team ) ;
prevTime = nowTime ;
} ) ;
// if there is a change of day between two requests, handle the
// divider insertion here.
if ( isOldMsgs ) {
var ts = $ ( '#chatfaction time:first' ) . data ( 'timestamp' ) ;
var nextTime = new Date ( ts ) . toLocaleDateString ( ) ;
if ( prevTime && prevTime !== nextTime && ts )
msgs += chat . renderDivider ( nextTime ) ;
}
var c = $ ( '#chatfaction' ) ;
var scrollBefore = scrollBottom ( c ) ;
if ( isOldMsgs )
c . prepend ( msgs ) ;
else
c . append ( msgs ) ;
chat . renderPlayerMsgsTo ( true , data , isOldMsgs , chat . _displayedFactionGuids ) ;
chat . keepScrollPosition ( c , scrollBefore , isOldMsgs ) ;
chat . needMoreMessages ( ) ;
if ( data . result . length >= CHAT _FACTION _ITEMS ) chat . needMoreMessages ( ) ;
}
//
// requesting public
//
@ -244,25 +242,27 @@ window.chat.handlePublic = function(data, textStatus, jqXHR, isOldMsgs) {
return console . warn ( 'public chat error. Waiting for next auto-refresh.' ) ;
}
chat . clearIfRequired ( ) ;
if ( data . result . length === 0 ) return ;
chat . _newPublicTimestamp = data . result [ 0 ] [ 1 ] ;
chat . _oldPublicTimestamp = data . result [ data . result . length - 1 ] [ 1 ] ;
chat . clearIfRequired ( ) ;
var c = $ ( '#chat > div:visible' ) ;
var c = $ ( '#chatautomated' ) ;
var scrollBefore = scrollBottom ( c ) ;
chat . handlePublicAutomated ( data ) ;
//chat.handlePublicPlayer(data, isOldMsgs);
chat . keepScrollPosition ( c , scrollBefore , isOldMsgs ) ;
chat . needMoreMessages ( ) ;
c = $ ( '#chatpublic' ) ;
var scrollBefore = scrollBottom ( c ) ;
chat . renderPlayerMsgsTo ( false , data , isOldMsgs , chat . _displayedPublicGuids ) ;
chat . keepScrollPosition ( c , scrollBefore , isOldMsgs ) ;
if ( data . result . length >= CHAT _PUBLIC _ITEMS ) chat . needMoreMessages ( ) ;
}
window . chat . handlePublicAutomated = function ( data ) {
$ . each ( data . result , function ( ind , json ) { // newest first!
var time = json [ 1 ] ;
@ -310,14 +310,10 @@ window.chat.handlePublicAutomated = function(data) {
} ) ;
if ( chat . getActive ( ) === 'automated' )
window . chat . renderAutomatedMsgsToBox ( ) ;
window . chat . renderAutomatedMsgsTo ( ) ;
}
window . chat . getActive = function ( ) {
return $ ( '#chatcontrols .active' ) . text ( ) ;
}
window . chat . renderAutomatedMsgsToBox = function ( ) {
window . chat . renderAutomatedMsgsTo = function ( ) {
var x = window . chat . _displayedPlayerActionTime ;
// we don’ t care about the GUIDs anymore
var vals = $ . map ( x , function ( v , k ) { return [ v ] ; } ) ;
@ -342,24 +338,89 @@ window.chat.renderAutomatedMsgsToBox = function() {
window . chat . clear = function ( ) {
console . log ( 'clearing now' ) ;
window . chat . _displayedFactionGuids = [ ] ;
window . chat . _displayedPublicGuids = [ ] ;
window . chat . _displayedPlayerActionTime = { } ;
window . chat . _oldFactionTimestamp = - 1 ;
window . chat . _newFactionTimestamp = - 1 ;
window . chat . _oldPublicTimestamp = - 1 ;
window . chat . _newPublicTimestamp = - 1 ;
$ ( '#chatfaction, #chatpublic, #chatautomated' ) . data ( 'ignoreNextScroll' , true ) . html ( '' ) ;
//
// common
//
window . chat . renderPlayerMsgsTo = function ( isFaction , data , isOldMsgs , dupCheckArr ) {
var msgs = '' ;
var prevTime = null ;
$ . each ( data . result . reverse ( ) , function ( ind , json ) { // oldest first!
if ( json [ 2 ] . plext . plextType !== 'PLAYER_GENERATED' ) return true ;
// avoid duplicates
if ( dupCheckArr . indexOf ( json [ 0 ] ) !== - 1 ) return true ;
dupCheckArr . push ( json [ 0 ] ) ;
var time = json [ 1 ] ;
var team = json [ 2 ] . plext . team === 'ALIENS' ? TEAM _ENL : TEAM _RES ;
var msg , nick , pguid ;
$ . each ( json [ 2 ] . plext . markup , function ( ind , markup ) {
if ( markup [ 0 ] === 'SENDER' ) {
nick = markup [ 1 ] . plain . slice ( 0 , - 2 ) ; // cut “: ” at end
pguid = markup [ 1 ] . guid ;
window . setPlayerName ( pguid , nick ) ; // free nick name resolves
}
if ( markup [ 0 ] === 'TEXT' ) msg = markup [ 1 ] . plain ;
if ( ! isFaction && markup [ 0 ] === 'SECURE' ) {
nick = null ;
return false ; // aka break
}
} ) ;
if ( ! nick ) return true ; // aka next
var nowTime = new Date ( time ) . toLocaleDateString ( ) ;
if ( prevTime && prevTime !== nowTime )
msgs += chat . renderDivider ( nowTime ) ;
msgs += chat . renderMsg ( msg , nick , time , team ) ;
prevTime = nowTime ;
} ) ;
var addTo = isFaction ? $ ( '#chatfaction' ) : $ ( '#chatpublic' ) ;
// if there is a change of day between two requests, handle the
// divider insertion here.
if ( isOldMsgs ) {
var ts = addTo . find ( 'time:first' ) . data ( 'timestamp' ) ;
var nextTime = new Date ( ts ) . toLocaleDateString ( ) ;
if ( prevTime && prevTime !== nextTime && ts )
msgs += chat . renderDivider ( nextTime ) ;
}
if ( isOldMsgs )
addTo . prepend ( msgs ) ;
else
addTo . append ( msgs ) ;
}
window . chat . clearIfRequired = function ( ) {
if ( ! chat . _needsClearing ) return ;
chat . clear ( ) ;
chat . _needsClearing = false ;
window . chat . renderDivider = function ( text ) {
return '<summary>─ ' + text + ' ────────────────────────────────────────────────────────────────────────────</summary>' ;
}
window . chat . renderMsg = function ( msg , nick , time , team ) {
var ta = unixTimeToHHmm ( time ) ;
var tb = unixTimeToString ( time , true ) ;
var t = '<time title="' + tb + '" data-timestamp="' + time + '">' + ta + '</time>' ;
var s = 'style="color:' + COLORS [ team ] + '"' ;
var title = nick . length >= 8 ? 'title="' + nick + '"' : '' ;
return '<p>' + t + '<mark ' + s + '>' + nick + '</mark><span>' + msg + '</span></p>' ;
}
window . chat . getActive = function ( ) {
return $ ( '#chatcontrols .active' ) . text ( ) ;
}
window . chat . toggle = function ( ) {
var c = $ ( '#chat, #chatcontrols' ) ;
if ( c . hasClass ( 'expand' ) ) {
@ -375,12 +436,14 @@ window.chat.toggle = function() {
}
}
window . chat . request = function ( ) {
console . log ( 'refreshing chat' ) ;
chat . requestNewFaction ( ) ;
chat . requestNewPublic ( ) ;
}
// checks if there are enough messages in the selected chat tab and
// loads more if not.
window . chat . needMoreMessages = function ( ) {
@ -393,19 +456,62 @@ window.chat.needMoreMessages = function() {
chat . requestOldPublic ( ) ;
}
window . chat . setupTime = function ( ) {
var inputTime = $ ( '#chatinput time' ) ;
var updateTime = function ( ) {
if ( window . isIdle ( ) ) return ;
var d = new Date ( ) ;
inputTime . text ( d . toLocaleTimeString ( ) . slice ( 0 , 5 ) ) ;
// update ON the minute (1ms after)
setTimeou t( updateTime , ( 60 - d . getSeconds ( ) ) * 1000 + 1 ) ;
} ;
updateTim e( ) ;
window . addResumeFunction ( updateTime ) ;
window . chat . chooser = function ( event ) {
var t = $ ( event . target ) ;
var tt = t . text ( ) ;
var span = $ ( '#chatinput span' ) ;
$ ( '#chatcontrols .active' ) . removeClass ( 'active' ) ;
t . addClass ( 'active' ) ;
$ ( '#chat > div' ) . hid e( ) ;
switch ( tt ) {
case 'faction' :
span . css ( 'color' , '' ) ;
span . text ( 'tell faction:' ) ;
$ ( '#chatfaction' ) . show ( ) ;
break ;
case 'public' :
span . css ( 'cssText' , 'color: red !important' ) ;
span . text ( 'tell public:' ) ;
$ ( '#chatpublic' ) . show ( ) ;
break ;
case 'automated' :
span . css ( 'cssText' , 'color: #bbb !important' ) ;
span . text ( 'tell Jarvis:' ) ;
chat . renderAutomatedMsgsTo ( ) ;
$ ( '#chatautomated' ) . show ( ) ;
break ;
}
chat . needMoreMessages ( ) ;
}
// contains the logic to keep the correct scroll position.
window . chat . keepScrollPosition = function ( box , scrollBefore , isOldMsgs ) {
// If scrolled down completely, keep it that way so new messages can
// be seen easily. If scrolled up, only need to fix scroll position
// when old messages are added. New messages added at the bottom don’ t
// change the view and enabling this would make the chat scroll down
// for every added message, even if the user wants to read old stuff.
if ( scrollBefore === 0 || isOldMsgs ) {
box . data ( 'ignoreNextScroll' , true ) ;
box . scrollTop ( box . scrollTop ( ) + ( scrollBottom ( box ) - scrollBefore ) ) ;
}
}
//
// setup
//
window . chat . setup = function ( ) {
window . chat . _localRangeCircle = L . circle ( map . getCenter ( ) , CHAT _MIN _RANGE * 1000 ) ;
@ -420,6 +526,7 @@ window.chat.setup = function() {
} ) ;
window . chat . setupTime ( ) ;
window . chat . setupPosting ( ) ;
$ ( '#chatfaction' ) . scroll ( function ( ) {
var t = $ ( this ) ;
@ -444,61 +551,61 @@ window.chat.setup = function() {
}
window . chat . renderMsg = function ( msg , nick , time , team ) {
var ta = unixTimeToHHmm ( time) ;
var tb = unixTimeToString ( time , true ) ;
var t = '<time title="' + tb + '" data-timestamp="' + time + '">' + ta + '</time>' ;
var s = 'style="color:' + COLORS [ team ] + '"' ;
var title = nick . length >= 8 ? 'title="' + nick + '"' : '' ;
return '<p>' + t + '<mark ' + s + '>' + nick + '</mark><span>' + msg + '</span></p>' ;
}
window . chat . renderDivider = function ( text ) {
return '<summary>─ ' + text + ' ────────────────────────────────────────────────────────────────────────────</summary>' ;
}
window . chat . chooser = function ( event ) {
var t = $ ( event . target ) ;
var tt = t . text ( ) ;
var span = $ ( '#chatinput span' ) ;
$ ( '#chatcontrols .active' ) . removeClass ( 'active' ) ;
t . addClass ( 'active' ) ;
$ ( '#chat > div' ) . hide ( ) ;
switch ( tt ) {
case 'faction' :
span . css ( 'color' , '' ) ;
span . text ( 'tell faction:' ) ;
$ ( '#chatfaction' ) . show ( ) ;
break ;
case 'public' :
span . css ( 'cssText' , 'color: red !important' ) ;
span . text ( 'spam public:' ) ;
$ ( '#chatpublic' ) . show ( ) ;
break ;
case 'automated' :
span . css ( 'cssText' , 'color: #bbb !important' ) ;
span . text ( 'tell Jarvis:' ) ;
chat . renderAutomatedMsgsToBox ( ) ;
$ ( '#chatautomated' ) . show ( ) ;
break ;
}
window . chat . setupTime = function ( ) {
var inputTime = $ ( '#chatinput time' ) ;
var updateTime = function ( ) {
if ( window . isIdle ( ) ) return ;
var d = new Date ( ) ;
inputTime . text ( d . toLocaleTimeString ( ) . slice ( 0 , 5 ) ) ;
// update ON the minute (1ms after)
setTimeout ( updateTime , ( 60 - d . getSeconds ( ) ) * 1000 + 1 ) ;
} ;
updateTime ( ) ;
window . addResumeFunction ( updateTime ) ;
}
// contains the logic to keep the correct scroll position.
window . chat . keepScrollP osi tion = function ( box , scrollBefore , isOldMsgs ) {
// If scrolled down completely, keep it that way so new messages can
// be seen easily. If scrolled up, only need to fix scroll position
// when old messages are added. New messages added at the bottom don’ t
// change the view and enabling this would make the chat scroll down
// for every added message, even if the user wants to read old stuff.
if ( scrollBefore === 0 || isOldMsgs ) {
box . data ( 'ignoreNextScroll' , true ) ;
box . scrollTop ( box . scrollTop ( ) + ( scrollBottom ( box ) - scrollBefore ) ) ;
}
//
// p osting
//
window . chat . setupPosting = function ( ) {
$ ( '#chatinput input' ) . keypress ( function ( e ) {
if ( ( e . keyCode ? e . keyCode : e . which ) != 13 ) return ;
chat . postMsg ( ) ;
e . preventDefault ( ) ;
} ) ;
$ ( '#chatinput' ) . submit ( function ( e ) {
chat . postMsg ( ) ;
e . preventDefault ( ) ;
} ) ;
}
window . chat . postMsg = function ( ) {
var c = chat . getActive ( ) ;
if ( c === 'automated' ) return alert ( 'Jarvis: A strange game. The only winning move is not to play. How about a nice game of chess?' ) ;
var msg = $ . trim ( $ ( '#chatinput input' ) . val ( ) ) ;
if ( ! msg || msg === '' ) return ;
var public = c === 'public' ;
var latlng = map . getCenter ( ) ;
var data = { message : msg ,
latE6 : Math . round ( latlng . lat * 1E6 ) ,
lngE6 : Math . round ( latlng . lng * 1E6 ) ,
factionOnly : ! public } ;
window . postAjax ( 'sendPlext' , data ,
function ( ) { if ( public ) chat . requestNewPublic ( ) ; else chat . requestNewFaction ( ) ; } ,
function ( ) {
alert ( 'Your message could not be delivered. You can copy&' +
'paste it here and try again if you want:\n\n' + msg ) ;
}
) ;
$ ( '#chatinput input' ) . val ( '' ) ;
}