- added multi character support per user, #314
- improved client site storage (IndexedDB) setup
This commit is contained in:
@@ -779,7 +779,7 @@ class Map extends Controller\AccessController {
|
||||
$systemPosX = 0;
|
||||
$systemPosY = 30;
|
||||
|
||||
$sourceSystemId = (int)$this->getF3()->get(User::SESSION_KEY_CHARACTER_PREV_SYSTEM_ID);
|
||||
$sourceSystemId = (int)$this->getF3()->get(User::SESSION_KEY_CHARACTERS_PREV_SYSTEM_ID);
|
||||
$targetSystemId = (int)$log->systemId;
|
||||
|
||||
if($sourceSystemId){
|
||||
|
||||
@@ -25,14 +25,12 @@ class User extends Controller\Controller{
|
||||
const SESSION_KEY_USER_NAME = 'SESSION.USER.NAME';
|
||||
|
||||
// character specific session keys
|
||||
const SESSION_KEY_CHARACTER = 'SESSION.CHARACTER';
|
||||
const SESSION_KEY_CHARACTER_ID = 'SESSION.CHARACTER.ID';
|
||||
const SESSION_KEY_CHARACTER_NAME = 'SESSION.CHARACTER.NAME';
|
||||
const SESSION_KEY_CHARACTER_TIME = 'SESSION.CHARACTER.TIME';
|
||||
const SESSION_KEY_CHARACTER_PREV_SYSTEM_ID = 'SESSION.CHARACTER.PREV_SYSTEM_ID';
|
||||
const SESSION_KEY_CHARACTERS = 'SESSION.CHARACTERS';
|
||||
//const SESSION_KEY_CHARACTERS_PREV_SYSTEM_ID = 'SESSION.CHARACTERS.PREV_SYSTEM_ID';
|
||||
const SESSION_KEY_CHARACTERS_PREV_SYSTEM_ID = 'SESSION.TEST.PREV_SYSTEM_ID';
|
||||
|
||||
const SESSION_KEY_CHARACTER_ACCESS_TOKEN = 'SESSION.CHARACTER.ACCESS_TOKEN';
|
||||
const SESSION_KEY_CHARACTER_REFRESH_TOKEN = 'SESSION.CHARACTER.REFRESH_TOKEN';
|
||||
// temp login character ID (during HTTP redirects on login)
|
||||
const SESSION_KEY_TEMP_CHARACTER_ID = 'SESSION.TEMP_CHARACTER_ID';
|
||||
|
||||
// log text
|
||||
const LOG_LOGGED_IN = 'userId: [%10s], userName: [%30s], charId: [%20s], charName: %s';
|
||||
@@ -45,6 +43,29 @@ class User extends Controller\Controller{
|
||||
*/
|
||||
private static $captchaReason = [self::SESSION_CAPTCHA_ACCOUNT_UPDATE, self::SESSION_CAPTCHA_ACCOUNT_DELETE];
|
||||
|
||||
/**
|
||||
* merges two multidimensional characterSession arrays by checking characterID
|
||||
* @param array $characterDataBase
|
||||
* @param array $characterData
|
||||
* @return array
|
||||
*/
|
||||
private function mergeSessionCharacterData($characterDataBase = [], $characterData = []){
|
||||
$addData = [];
|
||||
foreach($characterDataBase as $i => $baseData){
|
||||
foreach($characterData as $data){
|
||||
if((int)$baseData['ID'] === (int)$data['ID']){
|
||||
// overwrite changes
|
||||
$characterDataBase[$i]['NAME'] = $data['NAME'];
|
||||
$characterDataBase[$i]['TIME'] = $data['TIME'];
|
||||
}else{
|
||||
$addData[] = $data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return array_merge($characterDataBase, $addData);
|
||||
}
|
||||
|
||||
/**
|
||||
* login a valid character
|
||||
* @param Model\CharacterModel $characterModel
|
||||
@@ -54,24 +75,43 @@ class User extends Controller\Controller{
|
||||
$login = false;
|
||||
|
||||
if($user = $characterModel->getUser()){
|
||||
// set user/character data to session -------------------
|
||||
$this->f3->set(self::SESSION_KEY_USER, [
|
||||
'ID' => $user->_id,
|
||||
'NAME' => $user->name
|
||||
]);
|
||||
// check if character belongs to current user
|
||||
// -> If there is already a logged in user! (e.g. multi character use)
|
||||
$currentUser = $this->getUser();
|
||||
|
||||
$dateTime = new \DateTime();
|
||||
$this->f3->set(self::SESSION_KEY_CHARACTER, [
|
||||
'ID' => $characterModel->_id,
|
||||
'NAME' => $characterModel->name,
|
||||
'TIME' => $dateTime->getTimestamp()
|
||||
]);
|
||||
$sessionCharacters = [
|
||||
[
|
||||
'ID' => $characterModel->_id,
|
||||
'NAME' => $characterModel->name,
|
||||
'TIME' => (new \DateTime())->getTimestamp()
|
||||
]
|
||||
];
|
||||
|
||||
// save user login information ---------------------------
|
||||
if(
|
||||
is_null($currentUser) ||
|
||||
$currentUser->_id !== $user->_id
|
||||
){
|
||||
// user has changed OR new user ---------------------------------------------------
|
||||
//-> set user/character data to session
|
||||
$this->f3->set(self::SESSION_KEY_USER, [
|
||||
'ID' => $user->_id,
|
||||
'NAME' => $user->name
|
||||
]);
|
||||
}else{
|
||||
// user has NOT changed -----------------------------------------------------------
|
||||
// -> get current session characters
|
||||
$currentSessionCharacters = (array)$this->f3->get(self::SESSION_KEY_CHARACTERS);
|
||||
|
||||
$sessionCharacters = $this->mergeSessionCharacterData($sessionCharacters, $currentSessionCharacters);
|
||||
}
|
||||
|
||||
$this->f3->set(self::SESSION_KEY_CHARACTERS, $sessionCharacters);
|
||||
|
||||
// save user login information --------------------------------------------------------
|
||||
$characterModel->touch('lastLogin');
|
||||
$characterModel->save();
|
||||
|
||||
// write login log --------------------------------------
|
||||
// write login log --------------------------------------------------------------------
|
||||
self::getLogger('LOGIN')->write(
|
||||
sprintf(self::LOG_LOGGED_IN,
|
||||
$user->_id,
|
||||
@@ -210,7 +250,7 @@ class User extends Controller\Controller{
|
||||
if($activeCharacter = $this->getCharacter(0)){
|
||||
$user = $activeCharacter->getUser();
|
||||
|
||||
// captcha is send -> check captcha ---------------------------------
|
||||
// captcha is send -> check captcha -------------------------------------------
|
||||
if(
|
||||
isset($formData['captcha']) &&
|
||||
!empty($formData['captcha'])
|
||||
@@ -250,7 +290,7 @@ class User extends Controller\Controller{
|
||||
}
|
||||
}
|
||||
|
||||
// sharing config ---------------------------------------------------
|
||||
// sharing config -------------------------------------------------------------
|
||||
if(isset($formData['share'])){
|
||||
$privateSharing = 0;
|
||||
$corporationSharing = 0;
|
||||
|
||||
@@ -115,6 +115,10 @@ class Sso extends Api\User{
|
||||
if($loginCheck){
|
||||
// set "login" cookie
|
||||
$this->setLoginCookie($character);
|
||||
|
||||
// -> pass current character data to target page
|
||||
$f3->set(Api\User::SESSION_KEY_TEMP_CHARACTER_ID, $character->_id);
|
||||
|
||||
// route to "map"
|
||||
$f3->reroute('@map');
|
||||
}
|
||||
@@ -218,15 +222,18 @@ class Sso extends Api\User{
|
||||
// -> update character log (current location,...)
|
||||
$characterModel = $characterModel->updateLog();
|
||||
|
||||
// check if there is already an active user logged in
|
||||
if($activeCharacter = $this->getCharacter()){
|
||||
// connect character with current user
|
||||
$user = $activeCharacter->getUser();
|
||||
}elseif( is_null( $user = $characterModel->getUser()) ){
|
||||
// no user found (new character) -> create new user and connect to character
|
||||
$user = Model\BasicModel::getNew('UserModel');
|
||||
$user->name = $characterModel->name;
|
||||
$user->save();
|
||||
// connect character with current user
|
||||
if( is_null($user = $this->getUser()) ){
|
||||
// connect character with existing user (no changes)
|
||||
if( is_null( $user = $characterModel->getUser()) ){
|
||||
// no user found (new character) -> create new user and connect to character
|
||||
/**
|
||||
* @var $user Model\UserModel
|
||||
*/
|
||||
$user = Model\BasicModel::getNew('UserModel');
|
||||
$user->name = $characterModel->name;
|
||||
$user->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -251,6 +258,9 @@ class Sso extends Api\User{
|
||||
// set "login" cookie
|
||||
$this->setLoginCookie($characterModel);
|
||||
|
||||
// -> pass current character data to target page
|
||||
$f3->set(Api\User::SESSION_KEY_TEMP_CHARACTER_ID, $characterModel->_id);
|
||||
|
||||
// route to "map"
|
||||
$f3->reroute('@map');
|
||||
}else{
|
||||
@@ -308,6 +318,10 @@ class Sso extends Api\User{
|
||||
// login by character
|
||||
$loginCheck = $this->loginByCharacter($character);
|
||||
if($loginCheck){
|
||||
// set character id
|
||||
// -> pass current character data to target page
|
||||
$f3->set(Api\User::SESSION_KEY_TEMP_CHARACTER_ID, $character->_id);
|
||||
|
||||
// route to "map"
|
||||
$f3->reroute('@map');
|
||||
}
|
||||
|
||||
@@ -318,17 +318,81 @@ class Controller {
|
||||
}
|
||||
|
||||
/**
|
||||
* checks whether a user is currently logged in
|
||||
* get current character data from session
|
||||
* @return array
|
||||
*/
|
||||
protected function getSessionCharacterData(){
|
||||
$data = [];
|
||||
$currentSessionCharacters = (array)$this->getF3()->get(Api\User::SESSION_KEY_CHARACTERS);
|
||||
$requestedCharacterId = 0;
|
||||
|
||||
// get all characterData from currently active characters
|
||||
if($this->getF3()->get('AJAX')){
|
||||
// Ajax request -> get characterId from Header (if already available!)
|
||||
$header = $this->getRequestHeaders();
|
||||
$requestedCharacterId = (int)$header['Pf-Character'];
|
||||
|
||||
if(
|
||||
$requestedCharacterId > 0 &&
|
||||
(int)$this->getF3()->get(Api\User::SESSION_KEY_TEMP_CHARACTER_ID) === $requestedCharacterId
|
||||
){
|
||||
// characterId is available in Javascript
|
||||
// -> clear temp characterId for next character login/switch
|
||||
$this->getF3()->clear(Api\User::SESSION_KEY_TEMP_CHARACTER_ID);
|
||||
}
|
||||
}
|
||||
|
||||
if($requestedCharacterId <= 0){
|
||||
// Ajax BUT characterID not yet set as HTTP header
|
||||
// OR non Ajax -> get characterId from temp session (e.g. from HTTP redirect)
|
||||
$requestedCharacterId = (int)$this->getF3()->get(Api\User::SESSION_KEY_TEMP_CHARACTER_ID);
|
||||
}
|
||||
|
||||
if($requestedCharacterId > 0){
|
||||
// search for session character data
|
||||
foreach($currentSessionCharacters as $characterData){
|
||||
if($requestedCharacterId === (int)$characterData['ID']){
|
||||
$data = $characterData;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}elseif( !empty($currentSessionCharacters) ){
|
||||
// no character was requested ($requestedCharacterId = 0) AND session characters were found
|
||||
// -> get first matched character (e.g. user open browser tab)
|
||||
$data = $currentSessionCharacters[0];
|
||||
}
|
||||
|
||||
if( !empty($data) ){
|
||||
// check if character still exists on DB (e.g. was manually removed in the meantime)
|
||||
// -> This should NEVER happen just for security and "local development"
|
||||
$character = Model\BasicModel::getNew('CharacterModel');
|
||||
$character->getById( (int)$data['ID']);
|
||||
|
||||
if(
|
||||
$character->dry() ||
|
||||
!$character->hasUserCharacter()
|
||||
){
|
||||
// character data is invalid!
|
||||
$data = [];
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* checks whether a user/character is currently logged in
|
||||
* @param \Base $f3
|
||||
* @return bool
|
||||
*/
|
||||
protected function checkLogTimer($f3){
|
||||
$loginCheck = false;
|
||||
$characterData = $this->getSessionCharacterData();
|
||||
|
||||
if($f3->get(Api\User::SESSION_KEY_CHARACTER_TIME) > 0){
|
||||
if( !empty($characterData) ){
|
||||
// check logIn time
|
||||
$logInTime = new \DateTime();
|
||||
$logInTime->setTimestamp( $f3->get(Api\User::SESSION_KEY_CHARACTER_TIME) );
|
||||
$logInTime->setTimestamp( (int)$characterData['TIME'] );
|
||||
$now = new \DateTime();
|
||||
|
||||
$timeDiff = $now->diff($logInTime);
|
||||
@@ -346,35 +410,66 @@ class Controller {
|
||||
}
|
||||
|
||||
/**
|
||||
* get current character model
|
||||
* get current character
|
||||
* @param int $ttl
|
||||
* @return Model\CharacterModel|null
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getCharacter($ttl = 0){
|
||||
$character = null;
|
||||
$characterData = $this->getSessionCharacterData();
|
||||
|
||||
if( $this->getF3()->exists(Api\User::SESSION_KEY_CHARACTER_ID) ){
|
||||
$characterId = (int)$this->getF3()->get(Api\User::SESSION_KEY_CHARACTER_ID);
|
||||
if($characterId){
|
||||
/**
|
||||
* @var $characterModel Model\CharacterModel
|
||||
*/
|
||||
$characterModel = Model\BasicModel::getNew('CharacterModel');
|
||||
$characterModel->getById($characterId, $ttl);
|
||||
if( !empty($characterData) ){
|
||||
/**
|
||||
* @var $characterModel Model\CharacterModel
|
||||
*/
|
||||
$characterModel = Model\BasicModel::getNew('CharacterModel');
|
||||
$characterModel->getById( (int)$characterData['ID'], $ttl);
|
||||
|
||||
if(
|
||||
!$characterModel->dry() &&
|
||||
$characterModel->hasUserCharacter()
|
||||
){
|
||||
$character = &$characterModel;
|
||||
}
|
||||
if(
|
||||
!$characterModel->dry() &&
|
||||
$characterModel->hasUserCharacter()
|
||||
){
|
||||
$character = &$characterModel;
|
||||
}
|
||||
}
|
||||
|
||||
return $character;
|
||||
}
|
||||
|
||||
/**
|
||||
* get current user
|
||||
* @param int $ttl
|
||||
* @return Model\UserModel|null
|
||||
*/
|
||||
public function getUser($ttl = 0){
|
||||
$user = null;
|
||||
|
||||
if( $this->getF3()->exists(Api\User::SESSION_KEY_USER_ID) ){
|
||||
$userId = (int)$this->getF3()->get(Api\User::SESSION_KEY_USER_ID);
|
||||
if($userId){
|
||||
/**
|
||||
* @var $userModel Model\UserModel
|
||||
*/
|
||||
$userModel = Model\BasicModel::getNew('UserModel');
|
||||
$userModel->getById($userId, $ttl);
|
||||
|
||||
if(
|
||||
!$userModel->dry() &&
|
||||
$userModel->hasUserCharacters()
|
||||
){
|
||||
$user = &$userModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
public function getCharacterSessionData(){
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* log out current character
|
||||
* @param \Base $f3
|
||||
@@ -384,7 +479,7 @@ class Controller {
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// delete server side cookie validation data
|
||||
// for the current character as well
|
||||
// for the active character
|
||||
if(
|
||||
$params['clearCookies'] === '1' &&
|
||||
( $activeCharacter = $this->getCharacter())
|
||||
|
||||
@@ -212,12 +212,12 @@ class CharacterLogModel extends BasicModel {
|
||||
( $activeCharacter = $controller->getCharacter() ) &&
|
||||
( $activeCharacter->_id === $this->characterId->_id )
|
||||
){
|
||||
$prevSystemId = (int)$f3->get( User::SESSION_KEY_CHARACTER_PREV_SYSTEM_ID);
|
||||
$prevSystemId = (int)$f3->get( User::SESSION_KEY_CHARACTERS_PREV_SYSTEM_ID);
|
||||
|
||||
if($prevSystemId === 0){
|
||||
$f3->set( User::SESSION_KEY_CHARACTER_PREV_SYSTEM_ID, $systemId);
|
||||
$f3->set( User::SESSION_KEY_CHARACTERS_PREV_SYSTEM_ID, $systemId);
|
||||
}else{
|
||||
$f3->set( User::SESSION_KEY_CHARACTER_PREV_SYSTEM_ID, (int)$this->systemId);
|
||||
$f3->set( User::SESSION_KEY_CHARACTERS_PREV_SYSTEM_ID, (int)$this->systemId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,6 +133,16 @@ class UserModel extends BasicModel {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* check whether this character has already a user assigned to it
|
||||
* @return bool
|
||||
*/
|
||||
public function hasUserCharacters(){
|
||||
$this->filter('userCharacters', ['active = ?', 1]);
|
||||
|
||||
return is_object($this->userCharacters);
|
||||
}
|
||||
|
||||
/**
|
||||
* search for user by unique username
|
||||
* @param $name
|
||||
|
||||
@@ -508,7 +508,7 @@ define([
|
||||
var getLocaleData = function(type, objectId){
|
||||
if(objectId > 0){
|
||||
var storageKey = getLocalStoragePrefixByType(type) + objectId;
|
||||
return Util.localforage.getItem(storageKey);
|
||||
return Util.getLocalStorage().getItem(storageKey);
|
||||
}else{
|
||||
console.warn('Local storage requires object id > 0');
|
||||
}
|
||||
@@ -525,13 +525,13 @@ define([
|
||||
if(objectId > 0){
|
||||
// get current map config
|
||||
var storageKey = getLocalStoragePrefixByType(type) + objectId;
|
||||
Util.localforage.getItem(storageKey).then(function(data) {
|
||||
Util.getLocalStorage().getItem(storageKey).then(function(data) {
|
||||
// This code runs once the value has been loaded
|
||||
// from the offline store.
|
||||
data = (data === null) ? {} : data;
|
||||
// set/update value
|
||||
data[this.key] = this.value;
|
||||
Util.localforage.setItem(this.storageKey, data);
|
||||
Util.getLocalStorage().setItem(this.storageKey, data);
|
||||
}.bind({
|
||||
key: key,
|
||||
value: value,
|
||||
@@ -555,13 +555,13 @@ define([
|
||||
if(objectId > 0){
|
||||
// get current map config
|
||||
var storageKey = getLocalStoragePrefixByType(type) + objectId;
|
||||
Util.localforage.getItem(storageKey).then(function(data) {
|
||||
Util.getLocalStorage().getItem(storageKey).then(function(data) {
|
||||
if(
|
||||
data &&
|
||||
data.hasOwnProperty(key)
|
||||
){
|
||||
delete data[key];
|
||||
Util.localforage.setItem(this.storageKey, data);
|
||||
Util.getLocalStorage().setItem(this.storageKey, data);
|
||||
}
|
||||
}.bind({
|
||||
storageKey: storageKey
|
||||
|
||||
@@ -19,7 +19,10 @@ define([
|
||||
* main init "map" page
|
||||
*/
|
||||
$(function(){
|
||||
// set Dialog default config
|
||||
// set default AJAX config
|
||||
Util.ajaxSetup();
|
||||
|
||||
// set default dialog config
|
||||
Util.initDefaultBootboxConfig();
|
||||
|
||||
// load page
|
||||
@@ -28,11 +31,6 @@ define([
|
||||
// show app information in browser console
|
||||
Util.showVersionInfo();
|
||||
|
||||
// init local storage
|
||||
Util.localforage.config({
|
||||
name: 'Pathfinder local storage'
|
||||
});
|
||||
|
||||
// init logging
|
||||
Logging.init();
|
||||
|
||||
|
||||
@@ -573,10 +573,11 @@ define([
|
||||
$(document).on('pf:menuLogout', function(e, data){
|
||||
|
||||
var clearCookies = false;
|
||||
if( typeof data === 'object' ){
|
||||
if( data.hasOwnProperty('clearCookies') ){
|
||||
clearCookies = data.clearCookies;
|
||||
}
|
||||
if(
|
||||
typeof data === 'object' &&
|
||||
data.hasOwnProperty('clearCookies')
|
||||
){
|
||||
clearCookies = data.clearCookies;
|
||||
}
|
||||
|
||||
// logout
|
||||
@@ -674,6 +675,7 @@ define([
|
||||
|
||||
var userInfoElement = $('.' + config.headUserCharacterClass);
|
||||
var currentCharacterId = userInfoElement.data('characterId');
|
||||
var currentCharactersOptionIds = userInfoElement.data('characterOptionIds') ? userInfoElement.data('characterOptionIds') : [];
|
||||
var newCharacterId = 0;
|
||||
var newCharacterName = '';
|
||||
|
||||
@@ -691,7 +693,6 @@ define([
|
||||
visibility : 'hidden',
|
||||
duration: 500,
|
||||
complete: function(){
|
||||
|
||||
// callback
|
||||
callback();
|
||||
|
||||
@@ -727,25 +728,31 @@ define([
|
||||
}
|
||||
}
|
||||
|
||||
// update user character data ---------------------------------------------------
|
||||
if(currentCharacterId !== newCharacterId){
|
||||
var newCharactersOptionIds = userData.characters.map(function(data){
|
||||
return data.id;
|
||||
});
|
||||
|
||||
var showCharacterElement = true;
|
||||
if(newCharacterId === 0){
|
||||
showCharacterElement = false;
|
||||
// update user character data ---------------------------------------------------
|
||||
if(currentCharactersOptionIds.toString() !== newCharactersOptionIds.toString()){
|
||||
|
||||
var currentCharacterChanged = false;
|
||||
if(currentCharacterId !== newCharacterId){
|
||||
currentCharacterChanged = true;
|
||||
}
|
||||
|
||||
// toggle element
|
||||
animateHeaderElement(userInfoElement, function(){
|
||||
userInfoElement.find('span').text( newCharacterName );
|
||||
userInfoElement.find('img').attr('src', Init.url.ccpImageServer + 'Character/' + newCharacterId + '_32.jpg' );
|
||||
|
||||
if(currentCharacterChanged){
|
||||
userInfoElement.find('span').text( newCharacterName );
|
||||
userInfoElement.find('img').attr('src', Init.url.ccpImageServer + 'Character/' + newCharacterId + '_32.jpg' );
|
||||
}
|
||||
// init "character switch" popover
|
||||
userInfoElement.initCharacterSwitchPopover(userData);
|
||||
}, showCharacterElement);
|
||||
}, true);
|
||||
|
||||
// set new id for next check
|
||||
// store new id(s) for next check
|
||||
userInfoElement.data('characterId', newCharacterId);
|
||||
userInfoElement.data('characterOptionIds', newCharactersOptionIds);
|
||||
}
|
||||
|
||||
// update user ship data --------------------------------------------------------
|
||||
|
||||
110
js/app/util.js
110
js/app/util.js
@@ -64,6 +64,8 @@ define([
|
||||
|
||||
var animationTimerCache = {}; // cache for table row animation timeout
|
||||
|
||||
var localStorage; // cache for "localForage" singleton
|
||||
|
||||
/*
|
||||
* ===========================================================================================================
|
||||
* Global jQuery plugins for some common and frequently used functions
|
||||
@@ -589,40 +591,48 @@ define([
|
||||
return elements.each(function() {
|
||||
var element = $(this);
|
||||
|
||||
// destroy "popover" and remove "click" event for animation
|
||||
element.popover('destroy').off();
|
||||
|
||||
// init popover and add specific class to it (for styling)
|
||||
element.popover({
|
||||
html: true,
|
||||
title: 'select character',
|
||||
trigger: 'click',
|
||||
placement: 'bottom',
|
||||
container: 'body',
|
||||
content: content,
|
||||
animation: false
|
||||
}).data('bs.popover').tip().addClass('pf-popover');
|
||||
// check if tooltip already exists -> remove it
|
||||
if(element.data('bs.popover') !== undefined){
|
||||
element.off('click').popover('destroy');
|
||||
}
|
||||
|
||||
element.on('click', function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
var easeEffect = $(this).attr('data-easein');
|
||||
var popover = $(this).data('bs.popover').tip();
|
||||
var popoverData = $(this).data('bs.popover');
|
||||
var popoverElement = null;
|
||||
|
||||
var velocityOptions = {
|
||||
duration: Init.animationSpeed.dialogEvents
|
||||
};
|
||||
|
||||
switch(easeEffect){
|
||||
case 'shake':
|
||||
case 'pulse':
|
||||
case 'tada':
|
||||
case 'flash':
|
||||
case 'bounce':
|
||||
case 'swing':
|
||||
popover.velocity('callout.' + easeEffect, velocityOptions);
|
||||
break;
|
||||
default:
|
||||
popover.velocity('transition.' + easeEffect, velocityOptions);
|
||||
break;
|
||||
if(popoverData === undefined){
|
||||
|
||||
// init popover and add specific class to it (for styling)
|
||||
$(this).popover({
|
||||
html: true,
|
||||
title: 'select character',
|
||||
trigger: 'manual',
|
||||
placement: 'bottom',
|
||||
container: 'body',
|
||||
content: content,
|
||||
animation: false
|
||||
}).data('bs.popover').tip().addClass('pf-popover');
|
||||
|
||||
$(this).popover('show');
|
||||
|
||||
popoverElement = $(this).data('bs.popover').tip();
|
||||
popoverElement.velocity('transition.' + easeEffect, velocityOptions);
|
||||
}else{
|
||||
popoverElement = $(this).data('bs.popover').tip();
|
||||
if(popoverElement.is(':visible')){
|
||||
popoverElement.velocity('reverse');
|
||||
}else{
|
||||
$(this).popover('show');
|
||||
popoverElement.velocity('transition.' + easeEffect, velocityOptions);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -650,7 +660,14 @@ define([
|
||||
popoverElement.has(e.target).length === 0 &&
|
||||
$('.popover').has(e.target).length === 0
|
||||
){
|
||||
popoverElement.popover('hide');
|
||||
var popover = popoverElement.data('bs.popover');
|
||||
|
||||
if(
|
||||
popover !== undefined &&
|
||||
popover.tip().is(':visible')
|
||||
){
|
||||
popoverElement.popover('hide');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1014,6 +1031,28 @@ define([
|
||||
return logInfo;
|
||||
};
|
||||
|
||||
/**
|
||||
* set default jQuery AJAX configuration
|
||||
*/
|
||||
var ajaxSetup = function(){
|
||||
$.ajaxSetup({
|
||||
beforeSend: function(xhr) {
|
||||
// add current character data to ANY XHR request (HTTP HEADER)
|
||||
// -> This helps to identify multiple characters on multiple browser tabs
|
||||
var userData = getCurrentUserData();
|
||||
var currentCharacterId = 0;
|
||||
if(
|
||||
userData &&
|
||||
userData.character
|
||||
){
|
||||
currentCharacterId = parseInt( userData.character.id );
|
||||
}
|
||||
|
||||
xhr.setRequestHeader('Pf-Character', currentCharacterId);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if the user hit Esc or navigated away from the
|
||||
* current page before an AJAX call was done. (The response
|
||||
@@ -1665,6 +1704,20 @@ define([
|
||||
return price + ' ISK';
|
||||
};
|
||||
|
||||
/**
|
||||
* get localForage instance (singleton) for offline client site storage
|
||||
* @returns {localforage}
|
||||
*/
|
||||
var getLocalStorage = function(){
|
||||
if(localStorage === undefined){
|
||||
localStorage = localforage.createInstance({
|
||||
driver: localforage.INDEXEDDB,
|
||||
name: 'Pathfinder local storage'
|
||||
});
|
||||
}
|
||||
return localStorage;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create Date as UTC
|
||||
* @param date
|
||||
@@ -1756,7 +1809,6 @@ define([
|
||||
|
||||
return {
|
||||
config: config,
|
||||
localforage: localforage,
|
||||
showVersionInfo: showVersionInfo,
|
||||
initDefaultBootboxConfig: initDefaultBootboxConfig,
|
||||
getCurrentTriggerDelay: getCurrentTriggerDelay,
|
||||
@@ -1769,6 +1821,7 @@ define([
|
||||
showNotify: showNotify,
|
||||
stopTabBlink: stopTabBlink,
|
||||
getLogInfo: getLogInfo,
|
||||
ajaxSetup: ajaxSetup,
|
||||
isXHRAborted: isXHRAborted,
|
||||
getMapModule: getMapModule,
|
||||
getSystemEffectData: getSystemEffectData,
|
||||
@@ -1797,6 +1850,7 @@ define([
|
||||
convertDateToString: convertDateToString,
|
||||
getOpenDialogs: getOpenDialogs,
|
||||
formatPrice: formatPrice,
|
||||
getLocalStorage: getLocalStorage,
|
||||
getDocumentPath: getDocumentPath,
|
||||
redirect: redirect,
|
||||
logout: logout
|
||||
|
||||
@@ -508,7 +508,7 @@ define([
|
||||
var getLocaleData = function(type, objectId){
|
||||
if(objectId > 0){
|
||||
var storageKey = getLocalStoragePrefixByType(type) + objectId;
|
||||
return Util.localforage.getItem(storageKey);
|
||||
return Util.getLocalStorage().getItem(storageKey);
|
||||
}else{
|
||||
console.warn('Local storage requires object id > 0');
|
||||
}
|
||||
@@ -525,13 +525,13 @@ define([
|
||||
if(objectId > 0){
|
||||
// get current map config
|
||||
var storageKey = getLocalStoragePrefixByType(type) + objectId;
|
||||
Util.localforage.getItem(storageKey).then(function(data) {
|
||||
Util.getLocalStorage().getItem(storageKey).then(function(data) {
|
||||
// This code runs once the value has been loaded
|
||||
// from the offline store.
|
||||
data = (data === null) ? {} : data;
|
||||
// set/update value
|
||||
data[this.key] = this.value;
|
||||
Util.localforage.setItem(this.storageKey, data);
|
||||
Util.getLocalStorage().setItem(this.storageKey, data);
|
||||
}.bind({
|
||||
key: key,
|
||||
value: value,
|
||||
@@ -555,13 +555,13 @@ define([
|
||||
if(objectId > 0){
|
||||
// get current map config
|
||||
var storageKey = getLocalStoragePrefixByType(type) + objectId;
|
||||
Util.localforage.getItem(storageKey).then(function(data) {
|
||||
Util.getLocalStorage().getItem(storageKey).then(function(data) {
|
||||
if(
|
||||
data &&
|
||||
data.hasOwnProperty(key)
|
||||
){
|
||||
delete data[key];
|
||||
Util.localforage.setItem(this.storageKey, data);
|
||||
Util.getLocalStorage().setItem(this.storageKey, data);
|
||||
}
|
||||
}.bind({
|
||||
storageKey: storageKey
|
||||
|
||||
@@ -19,7 +19,10 @@ define([
|
||||
* main init "map" page
|
||||
*/
|
||||
$(function(){
|
||||
// set Dialog default config
|
||||
// set default AJAX config
|
||||
Util.ajaxSetup();
|
||||
|
||||
// set default dialog config
|
||||
Util.initDefaultBootboxConfig();
|
||||
|
||||
// load page
|
||||
@@ -28,11 +31,6 @@ define([
|
||||
// show app information in browser console
|
||||
Util.showVersionInfo();
|
||||
|
||||
// init local storage
|
||||
Util.localforage.config({
|
||||
name: 'Pathfinder local storage'
|
||||
});
|
||||
|
||||
// init logging
|
||||
Logging.init();
|
||||
|
||||
|
||||
@@ -573,10 +573,11 @@ define([
|
||||
$(document).on('pf:menuLogout', function(e, data){
|
||||
|
||||
var clearCookies = false;
|
||||
if( typeof data === 'object' ){
|
||||
if( data.hasOwnProperty('clearCookies') ){
|
||||
clearCookies = data.clearCookies;
|
||||
}
|
||||
if(
|
||||
typeof data === 'object' &&
|
||||
data.hasOwnProperty('clearCookies')
|
||||
){
|
||||
clearCookies = data.clearCookies;
|
||||
}
|
||||
|
||||
// logout
|
||||
@@ -674,6 +675,7 @@ define([
|
||||
|
||||
var userInfoElement = $('.' + config.headUserCharacterClass);
|
||||
var currentCharacterId = userInfoElement.data('characterId');
|
||||
var currentCharactersOptionIds = userInfoElement.data('characterOptionIds') ? userInfoElement.data('characterOptionIds') : [];
|
||||
var newCharacterId = 0;
|
||||
var newCharacterName = '';
|
||||
|
||||
@@ -691,7 +693,6 @@ define([
|
||||
visibility : 'hidden',
|
||||
duration: 500,
|
||||
complete: function(){
|
||||
|
||||
// callback
|
||||
callback();
|
||||
|
||||
@@ -727,25 +728,31 @@ define([
|
||||
}
|
||||
}
|
||||
|
||||
// update user character data ---------------------------------------------------
|
||||
if(currentCharacterId !== newCharacterId){
|
||||
var newCharactersOptionIds = userData.characters.map(function(data){
|
||||
return data.id;
|
||||
});
|
||||
|
||||
var showCharacterElement = true;
|
||||
if(newCharacterId === 0){
|
||||
showCharacterElement = false;
|
||||
// update user character data ---------------------------------------------------
|
||||
if(currentCharactersOptionIds.toString() !== newCharactersOptionIds.toString()){
|
||||
|
||||
var currentCharacterChanged = false;
|
||||
if(currentCharacterId !== newCharacterId){
|
||||
currentCharacterChanged = true;
|
||||
}
|
||||
|
||||
// toggle element
|
||||
animateHeaderElement(userInfoElement, function(){
|
||||
userInfoElement.find('span').text( newCharacterName );
|
||||
userInfoElement.find('img').attr('src', Init.url.ccpImageServer + 'Character/' + newCharacterId + '_32.jpg' );
|
||||
|
||||
if(currentCharacterChanged){
|
||||
userInfoElement.find('span').text( newCharacterName );
|
||||
userInfoElement.find('img').attr('src', Init.url.ccpImageServer + 'Character/' + newCharacterId + '_32.jpg' );
|
||||
}
|
||||
// init "character switch" popover
|
||||
userInfoElement.initCharacterSwitchPopover(userData);
|
||||
}, showCharacterElement);
|
||||
}, true);
|
||||
|
||||
// set new id for next check
|
||||
// store new id(s) for next check
|
||||
userInfoElement.data('characterId', newCharacterId);
|
||||
userInfoElement.data('characterOptionIds', newCharactersOptionIds);
|
||||
}
|
||||
|
||||
// update user ship data --------------------------------------------------------
|
||||
|
||||
@@ -64,6 +64,8 @@ define([
|
||||
|
||||
var animationTimerCache = {}; // cache for table row animation timeout
|
||||
|
||||
var localStorage; // cache for "localForage" singleton
|
||||
|
||||
/*
|
||||
* ===========================================================================================================
|
||||
* Global jQuery plugins for some common and frequently used functions
|
||||
@@ -589,40 +591,48 @@ define([
|
||||
return elements.each(function() {
|
||||
var element = $(this);
|
||||
|
||||
// destroy "popover" and remove "click" event for animation
|
||||
element.popover('destroy').off();
|
||||
|
||||
// init popover and add specific class to it (for styling)
|
||||
element.popover({
|
||||
html: true,
|
||||
title: 'select character',
|
||||
trigger: 'click',
|
||||
placement: 'bottom',
|
||||
container: 'body',
|
||||
content: content,
|
||||
animation: false
|
||||
}).data('bs.popover').tip().addClass('pf-popover');
|
||||
// check if tooltip already exists -> remove it
|
||||
if(element.data('bs.popover') !== undefined){
|
||||
element.off('click').popover('destroy');
|
||||
}
|
||||
|
||||
element.on('click', function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
var easeEffect = $(this).attr('data-easein');
|
||||
var popover = $(this).data('bs.popover').tip();
|
||||
var popoverData = $(this).data('bs.popover');
|
||||
var popoverElement = null;
|
||||
|
||||
var velocityOptions = {
|
||||
duration: Init.animationSpeed.dialogEvents
|
||||
};
|
||||
|
||||
switch(easeEffect){
|
||||
case 'shake':
|
||||
case 'pulse':
|
||||
case 'tada':
|
||||
case 'flash':
|
||||
case 'bounce':
|
||||
case 'swing':
|
||||
popover.velocity('callout.' + easeEffect, velocityOptions);
|
||||
break;
|
||||
default:
|
||||
popover.velocity('transition.' + easeEffect, velocityOptions);
|
||||
break;
|
||||
if(popoverData === undefined){
|
||||
|
||||
// init popover and add specific class to it (for styling)
|
||||
$(this).popover({
|
||||
html: true,
|
||||
title: 'select character',
|
||||
trigger: 'manual',
|
||||
placement: 'bottom',
|
||||
container: 'body',
|
||||
content: content,
|
||||
animation: false
|
||||
}).data('bs.popover').tip().addClass('pf-popover');
|
||||
|
||||
$(this).popover('show');
|
||||
|
||||
popoverElement = $(this).data('bs.popover').tip();
|
||||
popoverElement.velocity('transition.' + easeEffect, velocityOptions);
|
||||
}else{
|
||||
popoverElement = $(this).data('bs.popover').tip();
|
||||
if(popoverElement.is(':visible')){
|
||||
popoverElement.velocity('reverse');
|
||||
}else{
|
||||
$(this).popover('show');
|
||||
popoverElement.velocity('transition.' + easeEffect, velocityOptions);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -650,7 +660,14 @@ define([
|
||||
popoverElement.has(e.target).length === 0 &&
|
||||
$('.popover').has(e.target).length === 0
|
||||
){
|
||||
popoverElement.popover('hide');
|
||||
var popover = popoverElement.data('bs.popover');
|
||||
|
||||
if(
|
||||
popover !== undefined &&
|
||||
popover.tip().is(':visible')
|
||||
){
|
||||
popoverElement.popover('hide');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -1014,6 +1031,28 @@ define([
|
||||
return logInfo;
|
||||
};
|
||||
|
||||
/**
|
||||
* set default jQuery AJAX configuration
|
||||
*/
|
||||
var ajaxSetup = function(){
|
||||
$.ajaxSetup({
|
||||
beforeSend: function(xhr) {
|
||||
// add current character data to ANY XHR request (HTTP HEADER)
|
||||
// -> This helps to identify multiple characters on multiple browser tabs
|
||||
var userData = getCurrentUserData();
|
||||
var currentCharacterId = 0;
|
||||
if(
|
||||
userData &&
|
||||
userData.character
|
||||
){
|
||||
currentCharacterId = parseInt( userData.character.id );
|
||||
}
|
||||
|
||||
xhr.setRequestHeader('Pf-Character', currentCharacterId);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if the user hit Esc or navigated away from the
|
||||
* current page before an AJAX call was done. (The response
|
||||
@@ -1665,6 +1704,20 @@ define([
|
||||
return price + ' ISK';
|
||||
};
|
||||
|
||||
/**
|
||||
* get localForage instance (singleton) for offline client site storage
|
||||
* @returns {localforage}
|
||||
*/
|
||||
var getLocalStorage = function(){
|
||||
if(localStorage === undefined){
|
||||
localStorage = localforage.createInstance({
|
||||
driver: localforage.INDEXEDDB,
|
||||
name: 'Pathfinder local storage'
|
||||
});
|
||||
}
|
||||
return localStorage;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create Date as UTC
|
||||
* @param date
|
||||
@@ -1756,7 +1809,6 @@ define([
|
||||
|
||||
return {
|
||||
config: config,
|
||||
localforage: localforage,
|
||||
showVersionInfo: showVersionInfo,
|
||||
initDefaultBootboxConfig: initDefaultBootboxConfig,
|
||||
getCurrentTriggerDelay: getCurrentTriggerDelay,
|
||||
@@ -1769,6 +1821,7 @@ define([
|
||||
showNotify: showNotify,
|
||||
stopTabBlink: stopTabBlink,
|
||||
getLogInfo: getLogInfo,
|
||||
ajaxSetup: ajaxSetup,
|
||||
isXHRAborted: isXHRAborted,
|
||||
getMapModule: getMapModule,
|
||||
getSystemEffectData: getSystemEffectData,
|
||||
@@ -1797,6 +1850,7 @@ define([
|
||||
convertDateToString: convertDateToString,
|
||||
getOpenDialogs: getOpenDialogs,
|
||||
formatPrice: formatPrice,
|
||||
getLocalStorage: getLocalStorage,
|
||||
getDocumentPath: getDocumentPath,
|
||||
redirect: redirect,
|
||||
logout: logout
|
||||
|
||||
Reference in New Issue
Block a user