Merge pull request #813 from exodus4d/develop

v1.5.2
This commit is contained in:
Mark Friedrich
2019-07-22 14:52:10 +02:00
committed by GitHub
280 changed files with 25902 additions and 25118 deletions

4
.gitignore vendored
View File

@@ -50,10 +50,10 @@ Temporary Items
.sass-cache
.usage
*.gz
*.lock
composer-dev.lock
package-lock.json
/conf/
/node_modules/
/public/js/vX.X.X/
/vendor/
/history/
/package-lock.json

View File

@@ -75,7 +75,8 @@ Issues should be reported in the [Issue](https://github.com/exodus4d/pathfinder/
***
### Thanks!
### Contributing
[![](https://sourcerer.io/fame/exodus4d/exodus4d/pathfinder/images/0)](https://sourcerer.io/fame/exodus4d/exodus4d/pathfinder/links/0)[![](https://sourcerer.io/fame/exodus4d/exodus4d/pathfinder/images/1)](https://sourcerer.io/fame/exodus4d/exodus4d/pathfinder/links/1)[![](https://sourcerer.io/fame/exodus4d/exodus4d/pathfinder/images/2)](https://sourcerer.io/fame/exodus4d/exodus4d/pathfinder/links/2)[![](https://sourcerer.io/fame/exodus4d/exodus4d/pathfinder/images/3)](https://sourcerer.io/fame/exodus4d/exodus4d/pathfinder/links/3)[![](https://sourcerer.io/fame/exodus4d/exodus4d/pathfinder/images/4)](https://sourcerer.io/fame/exodus4d/exodus4d/pathfinder/links/4)[![](https://sourcerer.io/fame/exodus4d/exodus4d/pathfinder/images/5)](https://sourcerer.io/fame/exodus4d/exodus4d/pathfinder/links/5)[![](https://sourcerer.io/fame/exodus4d/exodus4d/pathfinder/images/6)](https://sourcerer.io/fame/exodus4d/exodus4d/pathfinder/links/6)[![](https://sourcerer.io/fame/exodus4d/exodus4d/pathfinder/images/7)](https://sourcerer.io/fame/exodus4d/exodus4d/pathfinder/links/7)
It took me month of time in development until this project got into the first *BETA*. If you like it, please help to improve it.
(report bugs, find security issues,...)

View File

@@ -119,9 +119,9 @@ class Cron extends \Prefab {
if (!preg_match($this->windows?'/^[A-Z]:\\\\/i':'/^\//',$dir))
$dir=getcwd().'/'.$dir;
if ($this->windows) {
pclose(popen(sprintf('start "cron" "%s" "%s\\%s" "/cron/%s"',$this->binary,$dir,$file,$job),'r'));
pclose(popen(sprintf('start /b "cron" "%s" "%s\\%s" "/cron/%s"',$this->binary,$dir,$file,$job),'r'));
} else {
exec(sprintf('cd "%s" & %s %s /cron/%s >/dev/null 2>/dev/null &',$dir,$this->binary,$file,$job));
exec(sprintf('cd "%s" && %s %s /cron/%s >/dev/null 2>/dev/null &',$dir,$this->binary,$file,$job));
}
return FALSE;
}
@@ -256,4 +256,4 @@ class Cron extends \Prefab {
$f3->route(array('GET /cron','GET /cron/@job'),array($this,'route'));
}
}
}

View File

@@ -74,15 +74,25 @@ class AccessController extends Controller {
return $loginStatus;
}
/**
* broadcast MapModel to clients
* @see broadcastMapData()
* @param Pathfinder\MapModel $map
*/
protected function broadcastMap(Pathfinder\MapModel $map) : void {
$this->broadcastMapData($this->getFormattedMapData($map));
}
/**
* broadcast map data to clients
* -> send over TCP Socket
* @param Pathfinder\MapModel $map
* @throws \Exception
* @param array|null $mapData
*/
protected function broadcastMapData(Pathfinder\MapModel $map) : void {
$mapData = $this->getFormattedMapData($map);
$this->getF3()->webSocket()->write('mapUpdate', $mapData);
protected function broadcastMapData(?array $mapData) : void {
if(!empty($mapData)){
$this->getF3()->webSocket()->write('mapUpdate', $mapData);
}
}
/**
@@ -91,16 +101,27 @@ class AccessController extends Controller {
* @return array
* @throws \Exception
*/
protected function getFormattedMapData(Pathfinder\MapModel $map) : array {
$mapData = $map->getData();
return [
'config' => $mapData->mapData,
'data' => [
'systems' => $mapData->systems,
'connections' => $mapData->connections,
]
];
/**
* @param Pathfinder\MapModel $map
* @return array|null
*/
protected function getFormattedMapData(Pathfinder\MapModel $map) : ?array {
$data = null;
try{
$mapData = $map->getData();
$data = [
'config' => $mapData->mapData,
'data' => [
'systems' => $mapData->systems,
'connections' => $mapData->connections,
]
];
}catch(\Exception $e){
}
return $data;
}
}

View File

@@ -25,7 +25,6 @@ class Map extends Controller\AccessController {
// cache keys
const CACHE_KEY_INIT = 'CACHED_INIT';
const CACHE_KEY_MAP_DATA = 'CACHED.MAP_DATA.%s';
const CACHE_KEY_USER_DATA = 'CACHED.USER_DATA.%s';
const CACHE_KEY_HISTORY = 'CACHED_MAP_HISTORY_%s';
@@ -652,6 +651,7 @@ class Map extends Controller\AccessController {
protected function broadcastMapAccess(Pathfinder\MapModel $map){
$mapAccess = [
'id' => $map->_id,
'name' => $map->name,
'characterIds' => array_map(function ($data){
return $data->id;
}, $map->getCharactersData())
@@ -660,7 +660,7 @@ class Map extends Controller\AccessController {
$this->getF3()->webSocket()->write('mapAccess', $mapAccess);
// map has (probably) active connections that should receive map Data
$this->broadcastMapData($map);
$this->broadcastMap($map);
}
/**
@@ -689,18 +689,22 @@ class Map extends Controller\AccessController {
unset($characterData->corporation->rights);
}
// access token
$token = bin2hex(random_bytes(16));
$return->data = [
'id' => $activeCharacter->_id,
'token' => bin2hex(random_bytes(16)), // token for character access
'id' => $activeCharacter->_id,
'token' => $token, // character access
'characterData' => $characterData,
'mapData' => []
'mapData' => []
];
if($maps){
foreach($maps as $map){
$return->data['mapData'][] = [
'id' => $map->_id,
'token' => bin2hex(random_bytes(16)) // token for map access
'id' => $map->_id,
'token' => $token, // map access
'name' => $map->name
];
}
}
@@ -721,41 +725,33 @@ class Map extends Controller\AccessController {
}
/**
* update map data
* -> function is called continuously (trigger) by any active client
* @param \Base $f3
* @throws Exception
* update maps with $mapsData where $character has access to
* @param Pathfinder\CharacterModel $character
* @param array $mapsData
* @return \stdClass
*/
public function updateData(\Base $f3){
$postData = (array)$f3->get('POST');
$mapData = (array)$postData['mapData'];
$userDataRequired = (bool)$postData['getUserData'];
protected function updateMapsData(Pathfinder\CharacterModel $character, array $mapsData) : \stdClass {
$return = (object) [];
$return->error = [];
$return->mapData = [];
$activeCharacter = $this->getCharacter();
$mapIdsChanged = [];
$maps = $character->getMaps();
// get current map data
$maps = $activeCharacter->getMaps();
// if there is any system/connection change data submitted -> save new data
if( !empty($maps) && !empty($mapData) ){
// loop all submitted map data that should be saved
if(!empty($mapsData) && !empty($maps)){
// loop all $mapsData that should be saved
// -> currently there will only be ONE map data change submitted -> single loop
foreach($mapData as $data){
foreach($mapsData as $data){
$systems = [];
$connections = [];
// check whether system data and/or connection data is send
// empty arrays are not included in ajax requests
if( isset($data['data']['systems']) ){
if(isset($data['data']['systems'])){
$systems = (array)$data['data']['systems'];
}
if( isset($data['data']['connections']) ){
if(isset($data['data']['connections'])){
$connections = (array)$data['data']['connections'];
}
@@ -768,15 +764,15 @@ class Map extends Controller\AccessController {
// loop current user maps and check for changes
foreach($maps as $map){
$mapChanged = false;
// update system data -------------------------------------------------------------------------
foreach($systems as $i => $systemData){
// check if current system belongs to the current map
if($system = $map->getSystemById((int)$systemData['id'])){
$system->copyfrom($systemData, ['alias', 'status', 'position', 'locked', 'rallyUpdated', 'rallyPoke']);
if($system->save($activeCharacter)){
$mapChanged = true;
if($system->save($character)){
if(!in_array($map->_id, $mapIdsChanged)){
$mapIdsChanged[] = $map->_id;
}
// one system belongs to ONE map -> speed up for multiple maps
unset($systemData[$i]);
}else{
@@ -790,8 +786,10 @@ class Map extends Controller\AccessController {
// check if the current connection belongs to the current map
if($connection = $map->getConnectionById((int)$connectionData['id'])){
$connection->copyfrom($connectionData, ['scope', 'type', 'endpoints']);
if($connection->save($activeCharacter)){
$mapChanged = true;
if($connection->save($character)){
if(!in_array($map->_id, $mapIdsChanged)){
$mapIdsChanged[] = $map->_id;
}
// one connection belongs to ONE map -> speed up for multiple maps
unset($connectionData[$i]);
}else{
@@ -799,17 +797,39 @@ class Map extends Controller\AccessController {
}
}
}
if($mapChanged){
$this->broadcastMapData($map);
}
}
}
}
}
// format map Data for return
$return->mapData = $this->getFormattedMapsData($maps);
foreach($maps as $map){
// format map Data for return/broadcast
if($mapData = $this->getFormattedMapData($map)){
if(in_array($map->_id, $mapIdsChanged)){
$this->broadcastMapData($mapData);
}
$return->mapData[] = $mapData;
}
}
return $return;
}
/**
* update map data
* -> function is called continuously (trigger) by any active client
* @param \Base $f3
* @throws Exception
*/
public function updateData(\Base $f3){
$postData = (array)$f3->get('POST');
$mapsData = (array)$postData['mapData'];
$userDataRequired = (bool)$postData['getUserData'];
$activeCharacter = $this->getCharacter();
$return = $this->updateMapsData($activeCharacter, $mapsData);
// if userData is requested -> add it as well
// -> Only first trigger call should request this data!
@@ -821,18 +841,22 @@ class Map extends Controller\AccessController {
}
/**
* get formatted map data
* @param Pathfinder\MapModel[] $mapModels
* @return array
* onUnload map sync
* @see https://developer.mozilla.org/docs/Web/API/Navigator/sendBeacon
* @param \Base $f3
* @throws Exception
*/
protected function getFormattedMapsData(array $mapModels) : array {
$mapData = [];
foreach($mapModels as $mapModel){
$mapData[] = $this->getFormattedMapData($mapModel);
}
public function updateUnloadData(\Base $f3){
$postData = (array)$f3->get('POST');
return $mapData;
if(!empty($mapsData = (string)$postData['mapData'])){
$mapsData = (array)json_decode($mapsData, true);
if(($jsonError = json_last_error()) === JSON_ERROR_NONE){
$activeCharacter = $this->getCharacter();
$this->updateMapsData($activeCharacter, $mapsData);
}
}
}
/**
@@ -862,7 +886,7 @@ class Map extends Controller\AccessController {
if( !is_null($map = $activeCharacter->getMap($mapId)) ){
// check character log (current system) and manipulate map (e.g. add new system)
if($mapTracking){
$map = $this->updateMapData($activeCharacter, $map);
$map = $this->updateMapByCharacter($map, $activeCharacter);
}
// mapUserData ----------------------------------------------------------------------------------------
@@ -887,7 +911,7 @@ class Map extends Controller\AccessController {
// data for currently selected system
$return->system = $system->getData();
$return->system->signatures = $system->getSignaturesData();
$return->system->sigHistory = $system ->getSignaturesHistoryData();
$return->system->sigHistory = $system->getSignaturesHistory();
$return->system->structures = $system->getStructuresData();
}
@@ -904,78 +928,73 @@ class Map extends Controller\AccessController {
echo json_encode($return);
}
/**
* add new map connection based on current $character location
* @param Pathfinder\CharacterModel $character
* update map connections/systems based on $character´s location logs
* @param Pathfinder\MapModel $map
* @param Pathfinder\CharacterModel $character
* @return Pathfinder\MapModel
* @throws Exception
*/
protected function updateMapData(Pathfinder\CharacterModel $character, Pathfinder\MapModel $map){
protected function updateMapByCharacter(Pathfinder\MapModel $map, Pathfinder\CharacterModel $character) : Pathfinder\MapModel {
// map changed. update cache (system/connection) changed
$mapDataChanged = false;
if(
( $mapScope = $map->getScope() ) &&
( $mapScope->name != 'none' ) && // tracking is disabled for map
( $log = $character->getLog() )
( $targetLog = $character->getLog() )
){
// character is currently in a system
$targetSystemId = (int)$targetLog->systemId;
$sameSystem = false;
$sourceExists = true;
$targetExists = true;
// system coordinates
$systemOffsetX = 130;
$systemOffsetY = 0;
$systemPosX = 0;
$systemPosY = 30;
$sessionCharacter = $this->getSessionCharacterData();
$sourceSystemId = (int)$sessionCharacter['PREV_SYSTEM_ID'];
$targetSystemId = (int)$log->systemId;
// get 'character log' from source system. If not log found -> assume $sourceLog == $targetLog
$sourceLog = $character->getLogPrevSystem($targetSystemId) ? : $targetLog;
$sourceSystemId = (int)$sourceLog->systemId;
if($sourceSystemId){
$sourceSystem = null;
$targetSystem = null;
// check if source and target systems are equal
// -> NO target system available
if($sourceSystemId === $targetSystemId){
// check if previous (solo) system is already on the map
$sourceSystem = $map->getSystemByCCPId($sourceSystemId, [AbstractModel::getFilter('active', true)]);
$sameSystem = true;
}else{
// check if previous (source) system is already on the map
$sourceSystem = $map->getSystemByCCPId($sourceSystemId, [AbstractModel::getFilter('active', true)]);
$sourceExists = false;
$targetExists = false;
// -> check if system is already on this map
$targetSystem = $map->getSystemByCCPId($targetSystemId, [AbstractModel::getFilter('active', true)]);
}
$sameSystem = false;
// system coordinates for system tha might be added next
$systemOffsetX = 130;
$systemOffsetY = 0;
$systemPosX = 0;
$systemPosY = 30;
// check if previous (solo) system is already on the map ----------------------------------------------
$sourceSystem = $map->getSystemByCCPId($sourceSystemId, [AbstractModel::getFilter('active', true)]);
// if systems don´t already exists on map -> get "blank" system
// -> required for system type check (e.g. wormhole, k-space)
if(
!$sourceSystem &&
$sourceSystemId
){
$sourceExists = false;
$sourceSystem = $map->getNewSystem($sourceSystemId);
}else{
if($sourceSystem){
$sourceExists = true;
// system exists -> add target to the "right"
$systemPosX = $sourceSystem->posX + $systemOffsetX;
$systemPosY = $sourceSystem->posY + $systemOffsetY;
}else{
$sourceSystem = $map->getNewSystem($sourceSystemId);
}
if(
!$sameSystem &&
!$targetSystem
){
$targetExists = false;
$targetSystem = $map->getNewSystem($targetSystemId);
// check if source and target systems are equal -------------------------------------------------------
if($sourceSystemId === $targetSystemId){
$sameSystem = true;
$targetExists = $sourceExists;
$targetSystem = $sourceSystem;
}elseif($targetSystemId){
// check if target system is already on this map
$targetSystem = $map->getSystemByCCPId($targetSystemId, [AbstractModel::getFilter('active', true)]);
if($targetSystem){
$targetExists = true;
}else{
$targetSystem = $map->getNewSystem($targetSystemId);
}
}
// make sure we have system objects to work with
@@ -1077,6 +1096,7 @@ class Map extends Controller\AccessController {
}
if(
!$sameSystem &&
$sourceExists &&
$targetExists &&
$sourceSystem &&
@@ -1091,17 +1111,17 @@ class Map extends Controller\AccessController {
){
// .. do not add connection if character got "podded" -------------------------------------
if(
$log->shipTypeId == 670 &&
$targetLog->shipTypeId == 670 &&
$character->cloneLocationId
){
// .. current character location must be clone location
if(
(
'station' == $character->cloneLocationType &&
$character->cloneLocationId == $log->stationId
$character->cloneLocationId == $targetLog->stationId
) || (
'structure' == $character->cloneLocationType &&
$character->cloneLocationId == $log->structureId
$character->cloneLocationId == $targetLog->structureId
)
){
// .. now we need to check jump distance between systems
@@ -1132,7 +1152,7 @@ class Map extends Controller\AccessController {
$connection &&
$connection->isWormhole()
){
$connection->logMass($log);
$connection->logMass($targetLog);
}
}
}
@@ -1140,7 +1160,7 @@ class Map extends Controller\AccessController {
}
if($mapDataChanged){
$this->broadcastMapData($map);
$this->broadcastMap($map);
}
return $map;
@@ -1171,7 +1191,7 @@ class Map extends Controller\AccessController {
// get specific connections by id
$connectionIds = null;
if(is_array($postData['connectionIds'])){
$connectionIds = $postData['connectionIds'];
$connectionIds = array_map('intval', $postData['connectionIds']);
}
$connections = $map->getConnections($connectionIds, 'wh');

View File

@@ -56,7 +56,7 @@ class Connection extends AbstractRestController {
$connectionData = $connection->getData();
// broadcast map changes
$this->broadcastMapData($connection->mapId);
$this->broadcastMap($connection->mapId);
}
}
}
@@ -86,16 +86,16 @@ class Connection extends AbstractRestController {
if($map->hasAccess($activeCharacter)){
foreach($connectionIds as $connectionId){
if($connection = $map->getConnectionById($connectionId)){
$connection->delete( $activeCharacter );
if($connection->delete($activeCharacter)){
$deletedConnectionIds[] = $connectionId;
}
$connection->reset();
$deletedConnectionIds[] = $connectionId;
}
}
// broadcast map changes
if(count($deletedConnectionIds)){
$this->broadcastMapData($map);
$this->broadcastMap($map);
}
}
}

View File

@@ -82,8 +82,9 @@ class Signature extends AbstractRestController {
$signatures = $system->getSignatures();
foreach($signatures as $signature){
if(!in_array($signature->_id, $updatedSignatureIds)){
$signature->delete();
$updateSignaturesHistory = true;
if($signature->delete()){
$updateSignaturesHistory = true;
}
}
}
}

View File

@@ -33,7 +33,7 @@ class SignatureHistory extends AbstractRestController {
$system->getById($systemId);
if($system->hasAccess($activeCharacter)){
$historyDataAll = $system->getSignaturesHistoryData();
$historyDataAll = $system->getSignaturesHistory();
foreach($historyDataAll as $historyEntry){
$label = [
$historyEntry['character']->name,
@@ -74,7 +74,7 @@ class SignatureHistory extends AbstractRestController {
$system = Pathfinder\AbstractPathfinderModel::getNew('SystemModel');
$system->getById($systemId, 0);
if($system->hasAccess($activeCharacter)){
if($historyEntry = $system->getSignatureHistoryData($stamp)){
if($historyEntry = $system->getSignatureHistoryEntry($stamp)){
$updateSignaturesHistory = false;
// history entry found for $stamp -> format signatures data
@@ -108,8 +108,9 @@ class SignatureHistory extends AbstractRestController {
$signatures = $system->getSignatures();
foreach($signatures as $signature){
if(!in_array($signature->_id, $updatedSignatureIds)){
$signature->delete();
$updateSignaturesHistory = true;
if($signature->delete()){
$updateSignaturesHistory = true;
}
}
}

View File

@@ -36,7 +36,7 @@ class System extends AbstractRestController {
){
$systemData = $system->getData();
$systemData->signatures = $system->getSignaturesData();
$systemData->sigHistory = $system->getSignaturesHistoryData();
$systemData->sigHistory = $system->getSignaturesHistory();
$systemData->structures = $system->getStructuresData();
}
}
@@ -144,7 +144,7 @@ class System extends AbstractRestController {
}
// broadcast map changes
if(count($deletedSystemIds)){
$this->broadcastMapData($map);
$this->broadcastMap($map);
}
}
}
@@ -187,13 +187,13 @@ class System extends AbstractRestController {
$newSystem->clearCacheData();
// broadcast map changes
$this->broadcastMapData($newSystem->mapId);
$this->broadcastMap($newSystem->mapId);
return $newSystem;
}
/**
* checks whether a system should be "deleted" or set "inactive" (keep some data)
* checks whether a system should be "deleted" or set "inactive" (keep persistent data)
* @param Pathfinder\MapModel $map
* @param Pathfinder\SystemModel $system
* @return bool
@@ -201,7 +201,7 @@ class System extends AbstractRestController {
private function checkDeleteMode(Pathfinder\MapModel $map, Pathfinder\SystemModel $system) : bool {
$delete = true;
if( !empty($system->description) ){
if(!empty($system->description)){
// never delete systems with custom description set!
$delete = false;
}elseif(
@@ -212,6 +212,13 @@ class System extends AbstractRestController {
// map setting "persistentAliases" is active (default) AND
// alias is set and != name
$delete = false;
}elseif(
$map->persistentSignatures &&
!empty($system->getSignatures())
){
// map setting "persistentSignatures" is active (default) AND
// signatures exist
$delete = false;
}
return $delete;

View File

@@ -154,13 +154,13 @@ class Route extends Controller\AccessController {
$includeTypes[] = 'wh_critical';
}
if( $filterData['wormholesFrigate'] !== true ){
$excludeTypes[] = 'frigate';
}
if( $filterData['wormholesEOL'] === false ){
$includeEOL = false;
}
if(!empty($filterData['excludeTypes'])){
$excludeTypes = $filterData['excludeTypes'];
}
}
if( $filterData['endpointsBubble'] !== true ){
@@ -300,7 +300,7 @@ class Route extends Controller\AccessController {
private function filterJumpData($filterData = [], $keepSystems = []){
if($filterData['flag'] == 'secure'){
// remove all systems (TrueSec < 0.5) from search arrays
$this->jumpArray = array_filter($this->jumpArray, function($systemId) use($keepSystems) {
$this->jumpArray = array_filter($this->jumpArray, function($systemId) use ($keepSystems) {
$systemNameData = $this->nameArray[$systemId];
$systemSec = $systemNameData[3];
@@ -733,8 +733,9 @@ class Route extends Controller\AccessController {
'wormholes' => (bool) $routeData['wormholes'],
'wormholesReduced' => (bool) $routeData['wormholesReduced'],
'wormholesCritical' => (bool) $routeData['wormholesCritical'],
'wormholesFrigate' => (bool) $routeData['wormholesFrigate'],
'wormholesEOL' => (bool) $routeData['wormholesEOL'],
'wormholesSizeMin' => (string) $routeData['wormholesSizeMin'],
'excludeTypes' => (array) $routeData['excludeTypes'],
'endpointsBubble' => (bool) $routeData['endpointsBubble'],
'flag' => $routeData['flag']
];

View File

@@ -189,20 +189,10 @@ class User extends Controller\Controller{
echo json_encode($return);
}
/**
* delete the character log entry for the current active (main) character
* @param \Base $f3
* @throws Exception
*/
public function deleteLog(\Base $f3){
if($activeCharacter = $this->getCharacter()){
$activeCharacter->logout(false, true, false);
}
}
/**
* log the current user out + clear character system log data
* @param \Base $f3
* @throws Exception
*/
public function logout(\Base $f3){
$this->logoutCharacter($f3, false, true, true, true);

View File

@@ -251,7 +251,7 @@ class Sso extends Api\User{
$this->setLoginCookie($characterModel);
// -> pass current character data to target page
$f3->set(Api\User::SESSION_KEY_TEMP_CHARACTER_DATA, $characterModel->_id);
$this->setTempCharacterData($characterModel->_id);
// route to "map"
if($rootAlias == 'admin'){
@@ -401,8 +401,7 @@ class Sso extends Api\User{
if( !empty($authCodeRequestData['expiresIn']) ){
// expire time for accessToken
try{
$timezone = $this->getF3()->get('getTimeZone')();
$accessTokenExpires = new \DateTime('now', $timezone);
$accessTokenExpires = $this->getF3()->get('getDateTime')();
$accessTokenExpires->add(new \DateInterval('PT' . (int)$authCodeRequestData['expiresIn'] . 'S'));
$accessData->esiAccessTokenExpires = $accessTokenExpires->format('Y-m-d H:i:s');

View File

@@ -162,6 +162,7 @@ class Controller {
'style' => $f3->get('BASE') . '/public/css/' . Config::getPathfinderData('version'),
'script' => $f3->get('BASE') . '/public/js/' . Config::getPathfinderData('version'),
'font' => $f3->get('BASE') . '/public/fonts',
'document' => $f3->get('BASE') . '/public/templates',
'image' => $f3->get('BASE') . '/public/img'
]);
@@ -387,12 +388,12 @@ class Controller {
public function getSessionCharacterData() : array {
$data = [];
if($user = $this->getUser()){
$header = self::getRequestHeaders();
$requestedCharacterId = (int)$header['Pf-Character'];
$header = self::getRequestHeaders();
$requestedCharacterId = (int)$header['Pf-Character'];
if( !$this->getF3()->get('AJAX') ){
$requestedCharacterId = (int)$_COOKIE['old_char_id'];
if(!$requestedCharacterId){
$tempCharacterData = (array)$this->getF3()->get(Api\User::SESSION_KEY_TEMP_CHARACTER_DATA);
$tempCharacterData = (array)$this->getF3()->get(Api\User::SESSION_KEY_TEMP_CHARACTER_DATA);
if((int)$tempCharacterData['ID'] > 0){
$requestedCharacterId = (int)$tempCharacterData['ID'];
}
@@ -763,17 +764,27 @@ class Controller {
$return->error[] = $error;
echo json_encode($return);
}else{
// non AJAX (e.g. GET/POST)
// recursively clear existing output buffers
while(ob_get_level()){
ob_end_clean();
}
$f3->set('tplPageTitle', 'ERROR - ' . $error->code);
// set error data for template rendering
$error->redirectUrl = $this->getRouteUrl();
$f3->set('errorData', $error);
// 4xx/5xx error -> set error page template
if( preg_match('/^4[0-9]{2}$/', $error->code) ){
// 4xx error -> render error page
$f3->set('tplPageContent', Config::getPathfinderData('STATUS.4XX') );
}elseif( preg_match('/^5[0-9]{2}$/', $error->code) ){
$f3->set('tplPageContent', Config::getPathfinderData('STATUS.5XX'));
}
// stop script - die(); after this fkt is done
// -> unload() fkt is still called
$f3->set('HALT', true);
}
}
@@ -859,7 +870,8 @@ class Controller {
*/
static function getRequestHeaders() : array {
$headers = [];
$headerPrefix = 'http_';
$prefixLength = mb_strlen($headerPrefix);
$serverData = self::getServerData();
if(
@@ -874,8 +886,9 @@ class Controller {
// Therefore we can´t use this for all servers
// https://github.com/exodus4d/pathfinder/issues/58
foreach($_SERVER as $name => $value){
if(substr($name, 0, 5) == 'HTTP_'){
$headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
$name = mb_strtolower($name);
if(mb_substr($name, 0, $prefixLength) == $headerPrefix){
$headers[mb_convert_case(str_replace('_', '-', mb_substr($name, $prefixLength)), MB_CASE_TITLE)] = $value;
}
}
}

View File

@@ -9,6 +9,7 @@
namespace Controller;
use lib\Config;
use lib\Resource;
class MapController extends AccessController {
@@ -18,6 +19,9 @@ class MapController extends AccessController {
* @throws \Exception
*/
public function init(\Base $f3) {
$resource = Resource::instance();
$resource->register('script', 'app/mappage');
$character = $this->getCharacter();
// characterId

View File

@@ -24,31 +24,31 @@ class Setup extends Controller {
* @var array
*/
protected $environmentVars = [
'ENVIRONMENT_CONFIG',
'BASE',
'URL',
'DEBUG',
'DB_PF_DNS',
'DB_PF_NAME',
'DB_PF_USER',
'DB_PF_PASS',
'DB_UNIVERSE_DNS',
'DB_UNIVERSE_NAME',
'DB_UNIVERSE_USER',
'DB_UNIVERSE_PASS',
'CCP_SSO_URL',
'CCP_SSO_CLIENT_ID',
'CCP_SSO_SECRET_KEY',
'CCP_SSO_DOWNTIME',
'CCP_ESI_URL',
'CCP_ESI_DATASOURCE',
'SMTP_HOST',
'SMTP_PORT',
'SMTP_SCHEME',
'SMTP_USER',
'SMTP_PASS',
'SMTP_FROM',
'SMTP_ERROR'
'ENVIRONMENT_CONFIG' => [],
'BASE' => ['missingOk' => true],
'URL' => [],
'DEBUG' => [],
'DB_PF_DNS' => [],
'DB_PF_NAME' => [],
'DB_PF_USER' => [],
'DB_PF_PASS' => [],
'DB_UNIVERSE_DNS' => [],
'DB_UNIVERSE_NAME' => [],
'DB_UNIVERSE_USER' => [],
'DB_UNIVERSE_PASS' => [],
'CCP_SSO_URL' => [],
'CCP_SSO_CLIENT_ID' => [],
'CCP_SSO_SECRET_KEY' => [],
'CCP_SSO_DOWNTIME' => [],
'CCP_ESI_URL' => [],
'CCP_ESI_DATASOURCE' => [],
'SMTP_HOST' => [],
'SMTP_PORT' => [],
'SMTP_SCHEME' => [],
'SMTP_USER' => [],
'SMTP_PASS' => [],
'SMTP_FROM' => [],
'SMTP_ERROR' => []
];
/**
@@ -313,12 +313,12 @@ class Setup extends Controller {
// obscure some values
$obscureVars = ['CCP_SSO_CLIENT_ID', 'CCP_SSO_SECRET_KEY', 'SMTP_PASS'];
foreach($this->environmentVars as $var){
foreach($this->environmentVars as $var => $options){
if( !in_array($var, $excludeVars) ){
$value = Config::getEnvironmentData($var);
$check = true;
if(is_null($value)){
if(is_null($value) && !array_key_exists('missingOk', $options)){
// variable missing
$check = false;
$value = '[missing]';
@@ -1557,23 +1557,29 @@ class Setup extends Controller {
'class' => 'txt-color-danger'
];
$webSocketStatus = [
$statusWeb = [
'type' => 'danger',
'label' => 'INIT CONNECTION…',
'class' => 'txt-color-danger'
];
$statsTcp = [
'startup' => 0,
'connections' => 0,
'maxConnections' => 0
];
$statsTcp = false;
$statsWeb = false;
$setStats = function(array $stats) use (&$statsTcp, &$statsWeb) {
if(!empty($stats['tcpSocket'])){
$statsTcp = $stats['tcpSocket'];
}
if(!empty($stats['webSocket'])){
$statsWeb = $stats['webSocket'];
}
};
// ping TCP Socket with "healthCheck" task
$f3->webSocket(['timeout' => $ttl])
->write($task, $healthCheckToken)
->then(
function($payload) use ($task, $healthCheckToken, &$statusTcp, &$statsTcp) {
function($payload) use ($task, $healthCheckToken, &$statusTcp, $setStats) {
if(
$payload['task'] == $task &&
$payload['load'] == $healthCheckToken
@@ -1581,24 +1587,26 @@ class Setup extends Controller {
$statusTcp['type'] = 'success';
$statusTcp['label'] = 'PING OK';
$statusTcp['class'] = 'txt-color-success';
// statistics (e.g. current connection count)
if(!empty($payload['stats'])){
$statsTcp = $payload['stats'];
}
}else{
$statusTcp['type'] = 'warning';
$statusTcp['label'] = is_string($payload['load']) ? $payload['load'] : 'INVALID RESPONSE';
$statusTcp['class'] = 'txt-color-warning';
}
// statistics (e.g. current connection count)
$setStats((array)$payload['stats']);
},
function($payload) use (&$statusTcp) {
function($payload) use (&$statusTcp, $setStats) {
$statusTcp['label'] = $payload['load'];
// statistics (e.g. current connection count)
$setStats((array)$payload['stats']);
});
$socketInformation = [
'tcpSocket' => [
'label' => 'Socket (intern) [TCP]',
'label' => 'TCP-Socket (intern)',
'icon' => 'fa-exchange-alt',
'status' => $statusTcp,
'stats' => $statsTcp,
'data' => [
@@ -1620,15 +1628,17 @@ class Setup extends Controller {
'check' => !empty( $ttl )
],[
'label' => 'uptime',
'value' => Config::formatTimeInterval($statsTcp['startup']),
'value' => Config::formatTimeInterval($statsTcp['startup'] ? : 0),
'check' => $statsTcp['startup'] > 0
]
],
'token' => $healthCheckToken
],
'webSocket' => [
'label' => 'WebSocket (clients) [HTTP]',
'status' => $webSocketStatus,
'label' => 'Web-Socket',
'icon' => 'fa-random',
'status' => $statusWeb,
'stats' => $statsWeb,
'data' => [
[
'label' => 'URI',

View File

@@ -64,10 +64,15 @@ class CharacterUpdate extends AbstractCron {
* @var $characterLog Pathfinder\CharacterLogModel
*/
if(is_object($characterLog->characterId)){
// force characterLog as "updated" even if no changes were made
$characterLog->characterId->updateLog([
'markUpdated' => true
]);
if($accessToken = $characterLog->characterId->getAccessToken()){
if($this->isOnline($accessToken)){
// force characterLog as "updated" even if no changes were made
$characterLog->touch('updated');
$characterLog->save();
}else{
$characterLog->erase();
}
}
}else{
// character_log does not have a character assigned -> delete
$characterLog->erase();

View File

@@ -14,7 +14,10 @@ use data\filesystem\Search;
class MapHistory extends AbstractCron {
const LOG_TEXT = '%s [%4s] log files, [%4s] not writable, [%4s] read error, [%4s] write error, [%4s] rename error, [%4s] delete error, exec (%.3Fs)';
/**
* log msg for truncateFiles() cronjob
*/
const LOG_TEXT = '%s [%4s] log files, [%s] truncated, [%4s] not writable, [%4s] read error, [%4s] write error, [%4s] rename error, [%4s] delete error, exec (%.3Fs)';
/**
* default log file size limit before truncate, bytes (1MB)
@@ -65,6 +68,7 @@ class MapHistory extends AbstractCron {
$writeErrors = 0;
$renameErrors = 0;
$deleteErrors = 0;
$truncatedFileNames = [];
if($f3->exists('PATHFINDER.HISTORY.LOG', $dir)){
$fileHandler = FileHandler::instance();
@@ -98,7 +102,8 @@ class MapHistory extends AbstractCron {
// move temp file from PHP temp dir into Pathfinders history log dir...
// ... overwrite old log file with new file
if(rename($temp, $file->getRealPath())){
// map history logs should be writable non cronjob user too
$truncatedFileNames[] = $file->getFilename();
// map history logs should be writable for non cronjob user too
@chmod($file->getRealPath(), 0666);
}else{
$renameErrors++;
@@ -120,6 +125,6 @@ class MapHistory extends AbstractCron {
// Log ------------------------
$log = new \Log('cron_' . __FUNCTION__ . '.log');
$log->write(sprintf(self::LOG_TEXT, __FUNCTION__, $largeFiles, $notWritableFiles, $readErrors, $writeErrors, $renameErrors, $deleteErrors, $execTime));
$log->write(sprintf(self::LOG_TEXT, __FUNCTION__, $largeFiles, implode(', ', $truncatedFileNames), $notWritableFiles, $readErrors, $writeErrors, $renameErrors, $deleteErrors, $execTime));
}
}

View File

@@ -301,7 +301,7 @@ class Config extends \Prefab {
'PASS' => self::getEnvironmentData('DB_' . $alias . '_PASS')
];
$pdoReg = '/^(?<SCHEME>[[:alpha:]]+):((host=(?<HOST>[a-zA-Z0-9\.]*))|(unix_socket=(?<SOCKET>[a-zA-Z0-9\/]*\.sock)))((;dbname=(?<NAME>\w*))|(;port=(?<PORT>\d*))){0,2}/';
$pdoReg = '/^(?<SCHEME>[[:alpha:]]+):((host=(?<HOST>[a-zA-Z0-9-_\.]*))|(unix_socket=(?<SOCKET>[a-zA-Z0-9\/]*\.sock)))((;dbname=(?<NAME>\w*))|(;port=(?<PORT>\d*))){0,2}/';
if(preg_match($pdoReg, self::getEnvironmentData('DB_' . $alias . '_DNS'), $matches)){
// remove unnamed matches
$matches = array_intersect_key($matches, $config);

View File

@@ -76,4 +76,17 @@ class SQL extends \DB\SQL {
);
}
}
/**
* @see https://fatfreeframework.com/3.6/sql#exec
* @param array|string $cmds
* @param null $args
* @param int $ttl
* @param bool $log (we use false as default parameter)
* @param bool $stamp
* @return array|FALSE|int
*/
function exec($cmds, $args = null, $ttl = 0, $log = false, $stamp = false) {
return parent::exec($cmds, $args, $ttl, $log, $stamp);
}
}

View File

@@ -116,7 +116,7 @@ abstract class AbstractLog implements LogInterface {
// add custom log processor callback -> add "extra" (meta) data
$f3 = $this->f3;
$processorExtraData = function($record) use(&$f3){
$processorExtraData = function($record) use (&$f3){
$record['extra'] = [
'path' => $f3->get('PATH'),
'ip' => $f3->get('IP')

View File

@@ -24,6 +24,7 @@ class Resource extends \Prefab {
'style' => 'style',
'script' => 'script',
'font' => 'font',
'document' => 'document',
'image' => 'image'
];
@@ -49,6 +50,7 @@ class Resource extends \Prefab {
'style' => '',
'script' => '',
'font' => '',
'document' => '',
'image' => ''
];
@@ -60,6 +62,7 @@ class Resource extends \Prefab {
private $fileExt = [
'style' => 'css',
'script' => 'js',
'document' => 'html',
'font' => 'woff2'
];

View File

@@ -17,6 +17,12 @@ use Clue\React\NDJson;
abstract class AbstractSocket implements SocketInterface {
/**
* max length for JSON data string
* -> throw OverflowException on exceed
*/
const JSON_DECODE_MAX_LENGTH = 65536 * 4;
/**
* @var EventLoop\LoopInterface|null
*/
@@ -195,7 +201,7 @@ abstract class AbstractSocket implements SocketInterface {
// new empty stream for processing JSON
$stream = new Stream\ThroughStream();
$streamDecoded = new NDJson\Decoder($stream, true);
$streamDecoded = new NDJson\Decoder($stream, true, 512, 0, self::JSON_DECODE_MAX_LENGTH);
// promise get resolved on first emit('data')
$promise = Promise\Stream\first($streamDecoded);

View File

@@ -9,6 +9,7 @@
namespace Model;
use DB\Cortex;
use DB\CortexCollection;
use DB\SQL\Schema;
use lib\logging;
use Controller;
@@ -330,6 +331,13 @@ abstract class AbstractModel extends Cortex {
$valid = true;
}
break;
case Schema::DT_VARCHAR128:
case Schema::DT_VARCHAR256:
case Schema::DT_VARCHAR512:
if(!empty($val)){
$valid = true;
}
break;
default:
}
}
@@ -542,7 +550,34 @@ abstract class AbstractModel extends Cortex {
/**
* @var $relModel self|bool
*/
$relModel = $this->rel($key)->findone($this->mergeFilter([$this->mergeWithRelFilter($key, $filter), $relFilter]));
$relModel = $this->rel($key)->findone($this->mergeFilter([$relFilter, $this->mergeWithRelFilter($key, $filter)]));
}
return $relModel ? : null;
}
/**
* get all models from a relation that match $filter
* @param string $key
* @param array $filter
* @return CortexCollection|null
*/
protected function relFind(string $key, array $filter) : ?CortexCollection {
$relModel = null;
$relFilter = [];
if($this->exists($key, true)){
$fieldConf = $this->getFieldConfiguration();
if(array_key_exists($key, $fieldConf)){
if(array_key_exists($type = 'has-many', $fieldConf[$key])){
$fromConf = $fieldConf[$key][$type];
$relFilter = self::getFilter($fromConf[1], $this->getRaw($fromConf['relField']));
}
}
/**
* @var $relModel CortexCollection|bool
*/
$relModel = $this->rel($key)->find($this->mergeFilter([$relFilter, $this->mergeWithRelFilter($key, $filter)]));
}
return $relModel ? : null;
@@ -862,13 +897,18 @@ abstract class AbstractModel extends Cortex {
}
/**
* get filter for Cortex
* get new filter array representation
* -> $suffix can be used fore unique placeholder,
* in case the same $key is used with different $values in the same query
* @param string $key
* @param $value
* @param mixed $value
* @param string $operator
* @param string $suffix
* @return array
*/
public static function getFilter(string $key, $value) : array {
return [$key . ' = :' . $key, ':' . $key => $value];
public static function getFilter(string $key, $value, string $operator = '=', string $suffix = '') : array {
$placeholder = ':' . implode('_', array_filter([$key, $suffix]));
return [$key . ' ' . $operator . ' ' . $placeholder, $placeholder => $value];
}
/**

View File

@@ -8,14 +8,19 @@
namespace Model\Pathfinder;
use Controller\Api\User as User;
use Controller\Controller as Controller;
use DB\SQL\Schema;
class CharacterLogModel extends AbstractPathfinderModel {
/**
* @var string
*/
protected $table = 'character_log';
/**
* @var array
*/
protected $fieldConf = [
'active' => [
'type' => Schema::DT_BOOL,
@@ -38,32 +43,37 @@ class CharacterLogModel extends AbstractPathfinderModel {
'systemId' => [
'type' => Schema::DT_INT,
'index' => true,
'activity-log' => true
'activity-log' => true,
'validate' => 'notEmpty'
],
'systemName' => [
'type' => Schema::DT_VARCHAR128,
'nullable' => false,
'default' => ''
'default' => '',
'activity-log' => true,
'validate' => 'notEmpty'
],
'shipTypeId' => [
'type' => Schema::DT_INT,
'index' => true,
'activity-log' => true
'activity-log' => true
],
'shipTypeName' => [
'type' => Schema::DT_VARCHAR128,
'nullable' => false,
'default' => ''
'default' => '',
'activity-log' => true
],
'shipId' => [
'type' => Schema::DT_BIGINT,
'index' => true,
'activity-log' => true
'activity-log' => true
],
'shipMass' => [
'type' => Schema::DT_FLOAT,
'nullable' => false,
'default' => 0
'default' => 0,
'activity-log' => true
],
'shipName' => [
'type' => Schema::DT_VARCHAR128,
@@ -73,22 +83,24 @@ class CharacterLogModel extends AbstractPathfinderModel {
'stationId' => [
'type' => Schema::DT_INT,
'index' => true,
'activity-log' => true
'activity-log' => true
],
'stationName' => [
'type' => Schema::DT_VARCHAR128,
'nullable' => false,
'default' => ''
'default' => '',
'activity-log' => true
],
'structureId' => [
'type' => Schema::DT_BIGINT,
'index' => true,
'activity-log' => true
'activity-log' => true
],
'structureName' => [
'type' => Schema::DT_VARCHAR128,
'nullable' => false,
'default' => ''
'default' => '',
'activity-log' => true
]
];
@@ -139,10 +151,10 @@ class CharacterLogModel extends AbstractPathfinderModel {
}
/**
* get all character log data
* @return object
* get character log data
* @return \stdClass
*/
public function getData(){
public function getData() : \stdClass {
$logData = (object) [];
$logData->system = (object) [];
@@ -168,16 +180,11 @@ class CharacterLogModel extends AbstractPathfinderModel {
}
/**
* setter for systemId
* @param int $systemId
* @return int
* @throws \Exception
* get 'character log' data as array
* @return array
*/
public function set_systemId($systemId){
if($systemId > 0){
$this->updateCharacterSessionLocation($systemId);
}
return $systemId;
public function getDataAsArray() : array {
return json_decode(json_encode($this->getData()), true);
}
/**
@@ -197,6 +204,8 @@ class CharacterLogModel extends AbstractPathfinderModel {
* @param $pkeys
*/
public function afterUpdateEvent($self, $pkeys){
$self->updateLogsHistory('update');
// check if any "relevant" column has changed
if(!empty($this->fieldChanges)){
$self->clearCacheData();
@@ -210,6 +219,7 @@ class CharacterLogModel extends AbstractPathfinderModel {
* @param $pkeys
*/
public function afterEraseEvent($self, $pkeys){
$self->deleteLogsHistory();
$self->clearCacheData();
}
@@ -229,30 +239,40 @@ class CharacterLogModel extends AbstractPathfinderModel {
}
/**
* update session data for active character
* @param int $systemId
* @throws \Exception
* update 'character log' history data
* -> checks $this->fieldChanges
* @param string $action
*/
protected function updateCharacterSessionLocation(int $systemId){
$controller = new Controller();
protected function updateLogsHistory(string $action){
// add new log history entry if 'systemId' changed
// -> if e.g. 'shipTypeId', 'stationId',.. changed -> no new entry (for now)
if(
!empty($sessionCharacter = $controller->getSessionCharacterData()) &&
$sessionCharacter['ID'] === $this->get('characterId', true)
!empty($this->fieldChanges) &&
array_key_exists('systemId', $this->fieldChanges) && // new history entry
is_object($this->characterId)
){
$systemChanged = false;
if((int)$sessionCharacter['PREV_SYSTEM_ID'] === 0){
$sessionCharacter['PREV_SYSTEM_ID'] = (int)$systemId;
$systemChanged = true;
}elseif((int)$sessionCharacter['PREV_SYSTEM_ID'] !== $this->systemId){
$sessionCharacter['PREV_SYSTEM_ID'] = $this->systemId;
$systemChanged = true;
}
$oldLog = clone $this;
if($systemChanged){
$sessionCharacters = CharacterModel::mergeSessionCharacterData([$sessionCharacter]);
$this->getF3()->set(User::SESSION_KEY_CHARACTERS, $sessionCharacters);
// get 'updated' timestamp and reapply after __set() fields data
// -> because any __set() call updates 'updated' col
$updated = $oldLog->updated;
foreach($this->fieldChanges as $key => $change){
if($oldLog->exists($key)){
$oldLog->$key = $change['old'];
}
}
$oldLog->updated = $updated;
$oldLog->characterId->updateLogsHistory($oldLog, $action);
}
}
/**
* delete 'character log' history data
*/
protected function deleteLogsHistory(){
if(is_object($this->characterId)){
$this->characterId->clearCacheDataWithPrefix(CharacterModel::DATA_CACHE_KEY_LOG_HISTORY);
}
}

View File

@@ -19,17 +19,32 @@ class CharacterModel extends AbstractPathfinderModel {
/**
* @var string
*/
protected $table = 'character';
protected $table = 'character';
/**
* cache key prefix for getData(); result WITH log data
*/
const DATA_CACHE_KEY_LOG = 'LOG';
const DATA_CACHE_KEY_LOG = 'LOG';
/**
* log message for character access
*/
const LOG_ACCESS = 'charId: [%20s], status: %s, charName: %s';
const LOG_ACCESS = 'charId: [%20s], status: %s, charName: %s';
/**
* max count of historic character logs
*/
const MAX_LOG_HISTORY_DATA = 5;
/**
* TTL for historic character logs
*/
const TTL_LOG_HISTORY = 60 * 60 * 22;
/**
* cache key prefix historic character logs
*/
const DATA_CACHE_KEY_LOG_HISTORY = 'LOG_HISTORY';
/**
* character authorization status
@@ -186,56 +201,60 @@ class CharacterModel extends AbstractPathfinderModel {
/**
* get character data
* @param bool|false $addCharacterLogData
* @return null|object|\stdClass
* @param bool $addLogData
* @param bool $addLogHistoryData
* @return mixed|object|null
* @throws \Exception
*/
public function getData($addCharacterLogData = false){
$cacheKeyModifier = '';
// check if there is cached data
// -> IMPORTANT: $addCharacterLogData is optional! -> therefore we need 2 cache keys!
if($addCharacterLogData){
$cacheKeyModifier = self::DATA_CACHE_KEY_LOG;
}
$characterData = $this->getCacheData($cacheKeyModifier);
if(is_null($characterData)){
public function getData($addLogData = false, $addLogHistoryData = false){
// check for cached data
if(is_null($characterData = $this->getCacheData())){
// no cached character data found
$characterData = (object) [];
$characterData->id = $this->_id;
$characterData->name = $this->name;
$characterData->role = $this->roleId->getData();
$characterData->shared = $this->shared;
$characterData->logLocation = $this->logLocation;
$characterData->selectLocation = $this->selectLocation;
if($addCharacterLogData){
if($logModel = $this->getLog()){
$characterData->log = $logModel->getData();
}
}
$characterData = (object) [];
$characterData->id = $this->_id;
$characterData->name = $this->name;
$characterData->role = $this->roleId->getData();
$characterData->shared = $this->shared;
$characterData->logLocation = $this->logLocation;
$characterData->selectLocation = $this->selectLocation;
// check for corporation
if($corporation = $this->getCorporation()){
$characterData->corporation = $corporation->getData();
$characterData->corporation = $corporation->getData();
}
// check for alliance
if($alliance = $this->getAlliance()){
$characterData->alliance = $alliance->getData();
$characterData->alliance = $alliance->getData();
}
// max caching time for a system
// the cached date has to be cleared manually on any change
// this includes system, connection,... changes (all dependencies)
$this->updateCacheData($characterData, $cacheKeyModifier);
// cached date has to be cleared manually on any change
// this applies to system, connection,... changes (+ all other dependencies)
$this->updateCacheData($characterData);
}
if($addLogData){
if(is_null($logData = $this->getCacheData(self::DATA_CACHE_KEY_LOG))){
if($logModel = $this->getLog()){
$logData = $logModel->getData();
$this->updateCacheData($logData, self::DATA_CACHE_KEY_LOG);
}
}
if($logData){
$characterData->log = $logData;
}
}
if($addLogHistoryData && $characterData->log){
$characterData->logHistory = $this->getLogsHistory();
}
// temp "authStatus" should not be cached
if($this->authStatus){
$characterData->authStatus = $this->authStatus;
$characterData->authStatus = $this->authStatus;
}
return $characterData;
@@ -507,7 +526,7 @@ class CharacterModel extends AbstractPathfinderModel {
/**
* get ESI API "access_token" from OAuth
* @return bool|mixed
* @return bool|string
*/
public function getAccessToken(){
$accessToken = false;
@@ -797,6 +816,31 @@ class CharacterModel extends AbstractPathfinderModel {
$this->roleId = $this->requestRole();
}
/**
* get online status data from ESI
* @param string $accessToken
* @return array
*/
protected function getOnlineData(string $accessToken) : array {
return self::getF3()->ccpClient()->getCharacterOnlineData($this->_id, $accessToken);
}
/**
* check online state from ESI
* @param string $accessToken
* @return bool
*/
public function isOnline(string $accessToken) : bool {
$isOnline = false;
$onlineData = $this->getOnlineData($accessToken);
if($onlineData['online'] === true){
$isOnline = true;
}
return $isOnline;
}
/**
* update character log (active system, ...)
* -> API request for character log data
@@ -815,170 +859,162 @@ class CharacterModel extends AbstractPathfinderModel {
$this->hasBasicScopes()
){
// Try to pull data from API
if( $accessToken = $this->getAccessToken() ){
$onlineData = self::getF3()->ccpClient()->getCharacterOnlineData($this->_id, $accessToken);
if($accessToken = $this->getAccessToken()){
if($this->isOnline($accessToken)){
$locationData = self::getF3()->ccpClient()->getCharacterLocationData($this->_id, $accessToken);
// check whether character is currently ingame online
if(is_bool($onlineData['online'])){
if($onlineData['online'] === true){
$locationData = self::getF3()->ccpClient()->getCharacterLocationData($this->_id, $accessToken);
if( !empty($locationData['system']['id']) ){
// character is currently in-game
if( !empty($locationData['system']['id']) ){
// character is currently in-game
// get current $characterLog or get new ---------------------------------------------------
if( !($characterLog = $this->getLog()) ){
// create new log
$characterLog = $this->rel('characterLog');
}
// get current $characterLog or get new ---------------------------------------------------
if( !($characterLog = $this->getLog()) ){
// create new log
$characterLog = $this->rel('characterLog');
}
// get current log data and modify on change
$logData = $characterLog->getDataAsArray();
// get current log data and modify on change
$logData = json_decode(json_encode( $characterLog->getData()), true);
// check system and station data for changes ----------------------------------------------
// check system and station data for changes ----------------------------------------------
// IDs for "systemId", "stationId" that require more data
$lookupUniverseIds = [];
// IDs for "systemId", "stationId" that require more data
$lookupUniverseIds = [];
if(
empty($logData['system']['name']) ||
$logData['system']['id'] !== $locationData['system']['id']
){
// system changed -> request "system name" for current system
$lookupUniverseIds[] = $locationData['system']['id'];
}
if( !empty($locationData['station']['id']) ){
if(
empty($logData['system']['name']) ||
$logData['system']['id'] !== $locationData['system']['id']
empty($logData['station']['name']) ||
$logData['station']['id'] !== $locationData['station']['id']
){
// system changed -> request "system name" for current system
$lookupUniverseIds[] = $locationData['system']['id'];
// station changed -> request "station name" for current station
$lookupUniverseIds[] = $locationData['station']['id'];
}
}else{
unset($logData['station']);
}
if( !empty($locationData['station']['id']) ){
$logData = array_replace_recursive($logData, $locationData);
// get "more" data for systemId and/or stationId -----------------------------------------
if( !empty($lookupUniverseIds) ){
// get "more" information for some Ids (e.g. name)
$universeData = self::getF3()->ccpClient()->getUniverseNamesData($lookupUniverseIds);
if( !empty($universeData) && !isset($universeData['error']) ){
// We expect max ONE system AND/OR station data, not an array of e.g. systems
if(!empty($universeData['system'])){
$universeData['system'] = reset($universeData['system']);
}
if(!empty($universeData['station'])){
$universeData['station'] = reset($universeData['station']);
}
$logData = array_replace_recursive($logData, $universeData);
}else{
// this is important! universe data is a MUST HAVE!
$deleteLog = true;
}
}
// check structure data for changes -------------------------------------------------------
if(!$deleteLog){
// IDs for "structureId" that require more data
$lookupStructureId = 0;
if( !empty($locationData['structure']['id']) ){
if(
empty($logData['station']['name']) ||
$logData['station']['id'] !== $locationData['station']['id']
empty($logData['structure']['name']) ||
$logData['structure']['id'] !== $locationData['structure']['id']
){
// station changed -> request "station name" for current station
$lookupUniverseIds[] = $locationData['station']['id'];
// structure changed -> request "structure name" for current station
$lookupStructureId = $locationData['structure']['id'];
}
}else{
unset($logData['station']);
unset($logData['structure']);
}
$logData = array_replace_recursive($logData, $locationData);
// get "more" data for systemId and/or stationId -----------------------------------------
if( !empty($lookupUniverseIds) ){
// get "more" information for some Ids (e.g. name)
$universeData = self::getF3()->ccpClient()->getUniverseNamesData($lookupUniverseIds);
if( !empty($universeData) && !isset($universeData['error']) ){
// We expect max ONE system AND/OR station data, not an array of e.g. systems
if(!empty($universeData['system'])){
$universeData['system'] = reset($universeData['system']);
}
if(!empty($universeData['station'])){
$universeData['station'] = reset($universeData['station']);
}
$logData = array_replace_recursive($logData, $universeData);
}else{
// this is important! universe data is a MUST HAVE!
$deleteLog = true;
}
}
// check structure data for changes -------------------------------------------------------
if(!$deleteLog){
// IDs for "structureId" that require more data
$lookupStructureId = 0;
if( !empty($locationData['structure']['id']) ){
if(
empty($logData['structure']['name']) ||
$logData['structure']['id'] !== $locationData['structure']['id']
){
// structure changed -> request "structure name" for current station
$lookupStructureId = $locationData['structure']['id'];
}
// get "more" data for structureId ---------------------------------------------------
if($lookupStructureId > 0){
/**
* @var $structureModel Universe\StructureModel
*/
$structureModel = Universe\AbstractUniverseModel::getNew('StructureModel');
$structureModel->loadById($lookupStructureId, $accessToken, $additionalOptions);
if(!$structureModel->dry()){
$structureData['structure'] = (array)$structureModel->getData();
$logData = array_replace_recursive($logData, $structureData);
}else{
unset($logData['structure']);
}
}
}
// get "more" data for structureId ---------------------------------------------------
if($lookupStructureId > 0){
/**
* @var $structureModel Universe\StructureModel
*/
$structureModel = Universe\AbstractUniverseModel::getNew('StructureModel');
$structureModel->loadById($lookupStructureId, $accessToken, $additionalOptions);
if(!$structureModel->dry()){
$structureData['structure'] = (array)$structureModel->getData();
$logData = array_replace_recursive($logData, $structureData);
}else{
unset($logData['structure']);
}
// check ship data for changes ------------------------------------------------------------
if( !$deleteLog ){
$shipData = self::getF3()->ccpClient()->getCharacterShipData($this->_id, $accessToken);
// IDs for "shipTypeId" that require more data
$lookupShipTypeId = 0;
if( !empty($shipData['ship']['typeId']) ){
if(
empty($logData['ship']['typeName']) ||
$logData['ship']['typeId'] !== $shipData['ship']['typeId']
){
// ship changed -> request "station name" for current station
$lookupShipTypeId = $shipData['ship']['typeId'];
}
// "shipName"/"shipId" could have changed...
$logData = array_replace_recursive($logData, $shipData);
}else{
// ship data should never be empty -> keep current one
//unset($logData['ship']);
$invalidResponse = true;
}
// check ship data for changes ------------------------------------------------------------
if( !$deleteLog ){
$shipData = self::getF3()->ccpClient()->getCharacterShipData($this->_id, $accessToken);
// IDs for "shipTypeId" that require more data
$lookupShipTypeId = 0;
if( !empty($shipData['ship']['typeId']) ){
if(
empty($logData['ship']['typeName']) ||
$logData['ship']['typeId'] !== $shipData['ship']['typeId']
){
// ship changed -> request "station name" for current station
$lookupShipTypeId = $shipData['ship']['typeId'];
}
// "shipName"/"shipId" could have changed...
// get "more" data for shipTypeId ----------------------------------------------------
if($lookupShipTypeId > 0){
/**
* @var $typeModel Universe\TypeModel
*/
$typeModel = Universe\AbstractUniverseModel::getNew('TypeModel');
$typeModel->loadById($lookupShipTypeId, '', $additionalOptions);
if(!$typeModel->dry()){
$shipData['ship'] = (array)$typeModel->getShipData();
$logData = array_replace_recursive($logData, $shipData);
}else{
// ship data should never be empty -> keep current one
//unset($logData['ship']);
$invalidResponse = true;
}
// get "more" data for shipTypeId ----------------------------------------------------
if($lookupShipTypeId > 0){
/**
* @var $typeModel Universe\TypeModel
*/
$typeModel = Universe\AbstractUniverseModel::getNew('TypeModel');
$typeModel->loadById($lookupShipTypeId, '', $additionalOptions);
if(!$typeModel->dry()){
$shipData['ship'] = (array)$typeModel->getShipData();
$logData = array_replace_recursive($logData, $shipData);
}else{
// this is important! ship data is a MUST HAVE!
$deleteLog = true;
}
// this is important! ship data is a MUST HAVE!
$deleteLog = true;
}
}
}
if( !$deleteLog ){
// mark log as "updated" even if no changes were made
if($additionalOptions['markUpdated'] === true){
$characterLog->touch('updated');
}
$characterLog->setData($logData);
$characterLog->characterId = $this->id;
$characterLog->save();
$this->characterLog = $characterLog;
if( !$deleteLog ){
// mark log as "updated" even if no changes were made
if($additionalOptions['markUpdated'] === true){
$characterLog->touch('updated');
}
}else{
// systemId should always exists
$invalidResponse = true;
$characterLog->setData($logData);
$characterLog->characterId = $this->_id;
$characterLog->save();
$this->characterLog = $characterLog;
}
}else{
// user is in-game offline
$deleteLog = true;
// systemId should always exists
$invalidResponse = true;
}
}else{
// online status request failed
$invalidResponse = true;
// user is in-game offline
$deleteLog = true;
}
}else{
// access token request failed
@@ -996,6 +1032,51 @@ class CharacterModel extends AbstractPathfinderModel {
return $this;
}
/**
* filter'character log' history data by $callback
* @param \Closure $callback
* @return array
*/
protected function filterLogsHistory(\Closure $callback) : array {
return array_filter($this->getLogsHistory() , $callback);
}
/**
* @return array
*/
public function getLogsHistory() : array {
if(!is_array($logHistoryData = $this->getCacheData(self::DATA_CACHE_KEY_LOG_HISTORY))){
$logHistoryData = [];
}
return $logHistoryData;
}
/**
* add new 'character log' history entry
* @param CharacterLogModel $characterLog
* @param string $action
*/
public function updateLogsHistory(CharacterLogModel $characterLog, string $action = 'update'){
if(
!$this->dry() &&
$this->_id === $characterLog->get('characterId', true)
){
$logHistoryData = $this->getLogsHistory();
$historyEntry = [
'stamp' => strtotime($characterLog->updated),
'action' => $action,
'log' => $characterLog->getDataAsArray()
];
array_unshift($logHistoryData, $historyEntry);
// limit max history data
array_splice($logHistoryData, self::MAX_LOG_HISTORY_DATA);
$this->updateCacheData($logHistoryData, self::DATA_CACHE_KEY_LOG_HISTORY, self::TTL_LOG_HISTORY);
}
}
/**
* broadcast characterData
*/
@@ -1055,15 +1136,33 @@ class CharacterModel extends AbstractPathfinderModel {
/**
* get the character log entry for this character
* @return bool|CharacterLogModel
* @return CharacterLogModel|null
*/
public function getLog(){
$characterLog = false;
if(
$this->hasLog() &&
!$this->characterLog->dry()
){
$characterLog = $this->characterLog;
public function getLog() : ?CharacterLogModel {
return ($this->hasLog() && !$this->characterLog->dry()) ? $this->characterLog : null;
}
/**
* get the first matched (most recent) log entry before $systemId.
* -> The returned log entry *might* be previous system for this character
* @param int $systemId
* @return CharacterLogModel|null
*/
public function getLogPrevSystem(int $systemId) : ?CharacterLogModel {
$logHistoryData = $this->filterLogsHistory(function(array $historyEntry) use ($systemId) : bool {
return (
!empty($historySystemId = (int)$historyEntry['log']['system']['id']) &&
$historySystemId !== $systemId
);
});
$characterLog = null;
if(!empty($historyEntry = reset($logHistoryData))){
/**
* @var $characterLog CharacterLogModel
*/
$characterLog = $this->rel('characterLog');
$characterLog->setData($historyEntry['log']);
}
return $characterLog;

View File

@@ -88,6 +88,29 @@ class ConnectionModel extends AbstractMapTrackingModel {
]
];
/**
* allowed connection types
* @var array
*/
protected static $connectionTypeWhitelist = [
// base type for scopes
'abyssal',
'jumpbridge',
'stargate',
// wh mass reduction types
'wh_fresh',
'wh_reduced',
'wh_critical',
// wh jump mass types
'wh_jump_mass_s',
'wh_jump_mass_m',
'wh_jump_mass_l',
'wh_jump_mass_xl',
// other types
'wh_eol',
'preserve_mass'
];
/**
* get connection data
* @param bool $addSignatureData
@@ -130,13 +153,15 @@ class ConnectionModel extends AbstractMapTrackingModel {
* @return int|number
*/
public function set_type($type){
$newTypes = (array)$type;
// remove unwanted types -> they should not be send from client
// -> reset keys! otherwise JSON format results in object and not in array
$type = array_values(array_intersect(array_unique((array)$type), self::$connectionTypeWhitelist));
// set EOL timestamp
if( !in_array('wh_eol', $newTypes) ){
if( !in_array('wh_eol', $type) ){
$this->eolUpdated = null;
}elseif(
in_array('wh_eol', $newTypes) &&
in_array('wh_eol', $type) &&
!in_array('wh_eol', (array)$this->type) // $this->type == null for new connection! (e.g. map import)
){
// connection EOL status change
@@ -307,35 +332,31 @@ class ConnectionModel extends AbstractMapTrackingModel {
* @return logging\LogInterface
* @throws \Exception\ConfigException
*/
public function newLog($action = '') : Logging\LogInterface {
public function newLog(string $action = '') : Logging\LogInterface {
return $this->getMap()->newLog($action)->setTempData($this->getLogObjectData());
}
/**
* @return MapModel
*/
public function getMap() : MapModel{
public function getMap() : MapModel {
return $this->get('mapId');
}
/**
* delete a connection
* @param CharacterModel $characterModel
* @return bool
*/
public function delete(CharacterModel $characterModel){
if( !$this->dry() ){
// check if character has access
if($this->hasAccess($characterModel)){
$this->erase();
}
}
public function delete(CharacterModel $characterModel) : bool {
return ($this->valid() && $this->hasAccess($characterModel)) ? $this->erase() : false;
}
/**
* get object relevant data for model log
* @return array
*/
public function getLogObjectData() : array{
public function getLogObjectData() : array {
return [
'objId' => $this->_id,
'objName' => $this->scope

View File

@@ -185,7 +185,7 @@ class CorporationModel extends AbstractPathfinderModel {
* @param array $options
* @return array
*/
public function getMaps($mapIds = [], $options = []){
public function getMaps($mapIds = [], $options = []) : array {
$maps = [];
$this->filterRel();

View File

@@ -8,6 +8,7 @@
namespace Model\Pathfinder;
use DB\CortexCollection;
use DB\SQL\Schema;
use data\file\FileHandler;
use Exception\ConfigException;
@@ -91,6 +92,12 @@ class MapModel extends AbstractMapTrackingModel {
'default' => 1,
'activity-log' => true
],
'persistentSignatures' => [
'type' => Schema::DT_BOOL,
'nullable' => false,
'default' => 1,
'activity-log' => true
],
'logActivity' => [
'type' => Schema::DT_BOOL,
'nullable' => false,
@@ -215,6 +222,7 @@ class MapModel extends AbstractMapTrackingModel {
$mapData->deleteExpiredConnections = $this->deleteExpiredConnections;
$mapData->deleteEolConnections = $this->deleteEolConnections;
$mapData->persistentAliases = $this->persistentAliases;
$mapData->persistentSignatures = $this->persistentSignatures;
// map scope
$mapData->scope = (object) [];
@@ -614,36 +622,27 @@ class MapModel extends AbstractMapTrackingModel {
}
/**
* get all connections in this map
* get connections in this map
* -> $connectionIds can be used for filter
* @param null $connectionIds
* @param string $scope
* @return ConnectionModel[]
* @return CortexCollection|array
*/
public function getConnections($connectionIds = null, $scope = ''){
$connections = [];
$query = [
'active = :active AND source > 0 AND target > 0',
':active' => 1
$filters = [
self::getFilter('source', 0, '>'),
self::getFilter('target', 0, '>')
];
if(!empty($scope)){
$query[0] .= ' AND scope = :scope';
$query[':scope'] = $scope;
$filters[] = self::getFilter('scope', $scope);
}
if(!empty($connectionIds)){
$query[0] .= ' AND id IN (?)';
$query[] = $connectionIds;
$filters[] = self::getFilter('id', $connectionIds, 'IN');
}
$this->filter('connections', $query);
if($this->connections){
$connections = $this->connections;
}
return $connections;
return $this->relFind('connections', $this->mergeFilter($filters)) ? : [];
}
/**
@@ -658,7 +657,7 @@ class MapModel extends AbstractMapTrackingModel {
/**
* @var $connection ConnectionModel
*/
$connectionData[] = $connection->getData();
$connectionData[] = $connection->getData(true);
}
return $connectionData;
@@ -798,12 +797,11 @@ class MapModel extends AbstractMapTrackingModel {
public function hasAccess(CharacterModel $characterModel) : bool {
$hasAccess = false;
if( !$this->dry() ){
if($this->valid()){
// get all maps the user has access to
// this includes corporation and alliance maps
$maps = $characterModel->getMaps();
foreach($maps as $map){
if($map->id === $this->id){
foreach($characterModel->getMaps() as $map){
if($map->_id === $this->_id){
$hasAccess = true;
break;
}
@@ -977,7 +975,7 @@ class MapModel extends AbstractMapTrackingModel {
* @return logging\LogInterface
* @throws ConfigException
*/
public function newLog($action = '') : Logging\LogInterface{
public function newLog(string $action = '') : Logging\LogInterface{
$logChannelData = $this->getLogChannelData();
$logObjectData = $this->getLogObjectData();
$log = (new logging\MapLog($action, $logChannelData))->setTempData($logObjectData);
@@ -1303,32 +1301,30 @@ class MapModel extends AbstractMapTrackingModel {
* @param SystemModel $targetSystem
* @return ConnectionModel|null
*/
public function searchConnection(SystemModel $sourceSystem, SystemModel $targetSystem){
public function searchConnection(SystemModel $sourceSystem, SystemModel $targetSystem) : ?ConnectionModel {
$connection = null;
// check if both systems belong to this map
if(
$sourceSystem->get('mapId', true) === $this->id &&
$targetSystem->get('mapId', true) === $this->id
$sourceSystem->get('mapId', true) === $this->_id &&
$targetSystem->get('mapId', true) === $this->_id
){
$this->filter('connections', [
'active = :active AND
(
(
source = :sourceId AND
target = :targetId
) OR (
source = :targetId AND
target = :sourceId
)
)',
':active' => 1,
':sourceId' => $sourceSystem->id,
':targetId' => $targetSystem->id,
], ['limit'=> 1]);
$filter = $this->mergeFilter([
$this->mergeFilter([self::getFilter('source', $sourceSystem->id, '=', 'A'), self::getFilter('target', $targetSystem->id, '=', 'A')]),
$this->mergeFilter([self::getFilter('source', $targetSystem->id, '=', 'B'), self::getFilter('target', $sourceSystem->id, '=', 'B')])
], 'or');
return ($this->connections) ? reset($this->connections) : null;
}else{
return null;
$connection = $this->relFindOne('connections', $filter);
}
return $connection;
}
/**
* @see parent
*/
public function filterRel() : void {
$this->filter('connections', self::getFilter('active', true));
}
/**
@@ -1447,7 +1443,7 @@ class MapModel extends AbstractMapTrackingModel {
* get all maps
* @param array $mapIds
* @param array $options
* @return \DB\CortexCollection
* @return CortexCollection
*/
public static function getAll($mapIds = [], $options = []){
$query = [

View File

@@ -17,37 +17,37 @@ class SystemModel extends AbstractMapTrackingModel {
/**
* system position x max
*/
const MAX_POS_X = 2440;
const MAX_POS_X = 2440;
/**
* system position y max
*/
const MAX_POS_Y = 1480;
const MAX_POS_Y = 1480;
/**
* max count of history signature data in cache
*/
const MAX_HISTORY_SIGNATURES = 10;
const MAX_SIGNATURES_HISTORY_DATA = 10;
/**
* TTL for history signature data
*/
const TTL_HISTORY_SIGNATURES = 7200;
const TTL_SIGNATURES_HISTORY = 7200;
/**
* cache key prefix for getData(); result WITH log data
*/
const DATA_CACHE_KEY_SIGNATURES = 'SIGNATURES';
const DATA_CACHE_KEY_SIGNATURES_HISTORY = 'HISTORY_SIGNATURES';
/**
* @var string
*/
protected $table = 'system';
protected $table = 'system';
/**
* @var array
*/
protected $staticSystemDataCache = [];
protected $staticSystemDataCache = [];
/**
* @var array
@@ -258,7 +258,7 @@ class SystemModel extends AbstractMapTrackingModel {
/**
* get static system data by key
* @param string $key
* @return null
* @return mixed|null
* @throws \Exception
*/
private function getStaticSystemValue(string $key){
@@ -483,16 +483,22 @@ class SystemModel extends AbstractMapTrackingModel {
public function beforeUpdateEvent($self, $pkeys) : bool {
$status = parent::beforeUpdateEvent($self, $pkeys);
if( !$self->isActive()){
if($status && !$self->isActive()){
// reset "rally point" fields
$self->rallyUpdated = 0;
$self->rallyPoke = false;
// delete connections
$connections = $self->getConnections();
foreach($connections as $connection){
foreach($self->getConnections() as $connection){
$connection->erase();
}
// delete signatures
if(!$self->getMap()->persistentSignatures){
foreach($self->getSignatures() as $signature){
$signature->erase();
}
}
}
return $status;
@@ -538,14 +544,14 @@ class SystemModel extends AbstractMapTrackingModel {
* @return logging\LogInterface
* @throws \Exception\ConfigException
*/
public function newLog($action = '') : Logging\LogInterface{
public function newLog(string $action = '') : Logging\LogInterface{
return $this->getMap()->newLog($action)->setTempData($this->getLogObjectData());
}
/**
* @return MapModel
*/
public function getMap() : MapModel{
public function getMap() : MapModel {
return $this->get('mapId');
}
@@ -562,14 +568,10 @@ class SystemModel extends AbstractMapTrackingModel {
* delete a system from a map
* hint: signatures and connections will be deleted on cascade
* @param CharacterModel $characterModel
* @return bool
*/
public function delete(CharacterModel $characterModel){
if( !$this->dry() ){
// check if character has access
if($this->hasAccess($characterModel)){
$this->erase();
}
}
return ($this->valid() && $this->hasAccess($characterModel)) ? $this->erase() : false;
}
/**
@@ -794,8 +796,8 @@ class SystemModel extends AbstractMapTrackingModel {
* @param string $stamp
* @return array|null
*/
public function getSignatureHistoryData(string $stamp) : ?array {
$signatureHistoryData = array_filter($this->getSignaturesHistoryData(), function($historyEntry) use ($stamp){
public function getSignatureHistoryEntry(string $stamp) : ?array {
$signatureHistoryData = array_filter($this->getSignaturesHistory(), function($historyEntry) use ($stamp){
return md5($historyEntry['stamp']) == $stamp;
});
return empty($signatureHistoryData) ? null : reset($signatureHistoryData);
@@ -804,22 +806,24 @@ class SystemModel extends AbstractMapTrackingModel {
/**
* @return array
*/
public function getSignaturesHistoryData() : array {
if(!is_array($signaturesHistoryData = $this->getCacheData(self::DATA_CACHE_KEY_SIGNATURES))){
public function getSignaturesHistory() : array {
if(!is_array($signaturesHistoryData = $this->getCacheData(self::DATA_CACHE_KEY_SIGNATURES_HISTORY))){
$signaturesHistoryData = [];
}
return $signaturesHistoryData;
}
/**
* CharacterModel $character
* Updates the signature history cache
* -> each (bulk) change to signatures of this system must result in a new signature history cache entry
* -> This method also clears the cache of this system, so that new signature data gets returned for in getData()
* @param CharacterModel $character
* @param string $action
* @throws \Exception
*/
public function updateSignaturesHistory(CharacterModel $character, string $action = 'edit'){
public function updateSignaturesHistory(CharacterModel $character, string $action = 'edit') : void {
if(!$this->dry()){
$signaturesHistoryData = $this->getSignaturesHistoryData();
$signaturesHistoryData = $this->getSignaturesHistory();
$historyEntry = [
'stamp' => microtime(true),
'character' => $character->getBasicData(),
@@ -830,9 +834,14 @@ class SystemModel extends AbstractMapTrackingModel {
array_unshift($signaturesHistoryData, $historyEntry);
// limit max history data
array_splice($signaturesHistoryData, self::MAX_HISTORY_SIGNATURES);
array_splice($signaturesHistoryData, self::MAX_SIGNATURES_HISTORY_DATA);
$this->updateCacheData($signaturesHistoryData, self::DATA_CACHE_KEY_SIGNATURES, self::TTL_HISTORY_SIGNATURES);
$this->updateCacheData($signaturesHistoryData, self::DATA_CACHE_KEY_SIGNATURES_HISTORY, self::TTL_SIGNATURES_HISTORY);
// clear system cache here
// -> Signature model updates should NOT update the system cache on change
// because a "bulk" change to signatures would clear the system cache multiple times
$this->clearCacheData();
}
}

View File

@@ -173,7 +173,7 @@ class SystemSignatureModel extends AbstractMapTrackingModel {
* @return logging\LogInterface
* @throws \Exception\ConfigException
*/
public function newLog($action = ''): Logging\LogInterface{
public function newLog(string $action = ''): Logging\LogInterface{
return $this->getMap()->newLog($action)->setTempData($this->getLogObjectData());
}
@@ -231,7 +231,7 @@ class SystemSignatureModel extends AbstractMapTrackingModel {
* @return bool
*/
public function delete() : bool {
return !$this->dry() ? $this->erase() : false;
return $this->valid() ? $this->erase() : false;
}
/**

View File

@@ -57,7 +57,7 @@ class UserModel extends AbstractPathfinderModel {
* @return \stdClass
* @throws Exception
*/
public function getData(){
public function getData() : \stdClass {
// get public user data for this user
$userData = $this->getSimpleData();
@@ -77,7 +77,7 @@ class UserModel extends AbstractPathfinderModel {
// get active character with log data
$activeCharacter = $this->getActiveCharacter();
$userData->character = $activeCharacter->getData(true);
$userData->character = $activeCharacter->getData(true, true);
return $userData;
}
@@ -87,7 +87,7 @@ class UserModel extends AbstractPathfinderModel {
* - check out getData() for all user data
* @return \stdClass
*/
public function getSimpleData(){
public function getSimpleData() : \stdClass{
$userData = (object) [];
$userData->id = $this->id;
$userData->name = $this->name;
@@ -143,7 +143,7 @@ class UserModel extends AbstractPathfinderModel {
* checks whether user has a valid email address and pathfinder has a valid SMTP config
* @return bool
*/
protected function isMailSendEnabled() : bool{
protected function isMailSendEnabled() : bool {
return Config::isValidSMTPConfig($this->getSMTPConfig());
}
@@ -151,7 +151,7 @@ class UserModel extends AbstractPathfinderModel {
* get SMTP config for this user
* @return \stdClass
*/
protected function getSMTPConfig() : \stdClass{
protected function getSMTPConfig() : \stdClass {
$config = Config::getSMTPConfig();
$config->to = $this->email;
return $config;
@@ -164,7 +164,7 @@ class UserModel extends AbstractPathfinderModel {
* @return bool
* @throws Exception\ValidationException
*/
protected function validate_name(string $key, string $val): bool {
protected function validate_name(string $key, string $val) : bool {
$valid = true;
if(
mb_strlen($val) < 3 ||
@@ -183,7 +183,7 @@ class UserModel extends AbstractPathfinderModel {
* @return bool
* @throws Exception\ValidationException
*/
protected function validate_email(string $key, string $val): bool {
protected function validate_email(string $key, string $val) : bool {
$valid = true;
if ( !empty($val) && \Audit::instance()->email($val) == false ){
$valid = false;
@@ -196,14 +196,14 @@ class UserModel extends AbstractPathfinderModel {
* check whether this character has already a user assigned to it
* @return bool
*/
public function hasUserCharacters(){
public function hasUserCharacters() : bool {
$this->filter('userCharacters', ['active = ?', 1]);
return is_object($this->userCharacters);
}
/**
* get current character data from session
* -> if §characterID == 0 -> get first character data (random)
* -> if $characterId == 0 -> get first character data (random)
* @param int $characterId
* @param bool $objectCheck
* @return array
@@ -218,9 +218,12 @@ class UserModel extends AbstractPathfinderModel {
// user matches session data
if($characterId > 0){
$data = $this->findSessionCharacterData($characterId);
}elseif( !empty($sessionCharacters = (array)$this->getF3()->get(User::SESSION_KEY_CHARACTERS)) ){
}elseif(
is_array($sessionCharacters = $this->getF3()->get(User::SESSION_KEY_CHARACTERS)) && // check for null
!empty($sessionCharacters)
){
// no character was requested ($requestedCharacterId = 0) AND session characters were found
// -> get first matched character (e.g. user open browser tab)
// -> get first matched character (e.g. user open /login browser tab)
$data = $sessionCharacters[0];
}
}
@@ -235,7 +238,7 @@ class UserModel extends AbstractPathfinderModel {
* @var $character CharacterModel
*/
$character = AbstractPathfinderModel::getNew('CharacterModel');
$character->getById( (int)$data['ID']);
$character->getById((int)$data['ID']);
if(
$character->dry() ||
@@ -254,7 +257,7 @@ class UserModel extends AbstractPathfinderModel {
* @param int $characterId
* @return array
*/
public function findSessionCharacterData(int $characterId): array {
public function findSessionCharacterData(int $characterId) : array {
$data = [];
if($characterId){
$sessionCharacters = (array)$this->getF3()->get(User::SESSION_KEY_CHARACTERS);
@@ -292,7 +295,7 @@ class UserModel extends AbstractPathfinderModel {
* @return null|CharacterModel
* @throws Exception
*/
public function getActiveCharacter(){
public function getActiveCharacter() : ?CharacterModel {
$activeCharacter = null;
$controller = new Controller\Controller();
$currentActiveCharacter = $controller->getCharacter();
@@ -316,7 +319,7 @@ class UserModel extends AbstractPathfinderModel {
* get all characters for this user
* @return CharacterModel[]
*/
public function getCharacters(){
public function getCharacters() : array {
$characters = [];
$userCharacters = $this->getUserCharacters();
@@ -339,11 +342,10 @@ class UserModel extends AbstractPathfinderModel {
* hint: a user can have multiple active characters
* @return CharacterModel[]
*/
public function getActiveCharacters(){
public function getActiveCharacters() : array {
$activeCharacters = [];
$userCharacters = $this->getUserCharacters();
foreach($userCharacters as $userCharacter){
foreach($this->getUserCharacters() as $userCharacter){
/**
* @var $userCharacter UserCharacterModel
*/

View File

@@ -14,7 +14,7 @@ NAME = Pathfinder
; e.g. public/js/vX.X.X/app.js
; Syntax: String (current version)
; Default: v1.5.0
VERSION = v1.5.1
VERSION = v1.5.2
; Contact information [optional]
; Shown on 'licence', 'contact' page.
@@ -255,14 +255,14 @@ DELAY = 5000
; Requests that exceed the limit are logged as 'warning'.
; Syntax: Integer (milliseconds)
; Default: 200
EXECUTION_LIMIT = 200
EXECUTION_LIMIT = 500
[PATHFINDER.TIMER.UPDATE_CLIENT_MAP]
; Execution limit for client side (javascript) map data updates
; Map data updates that exceed the limit are logged as 'warning'.
; Syntax: Integer (milliseconds)
; Default: 50
EXECUTION_LIMIT = 50
EXECUTION_LIMIT = 100
[PATHFINDER.TIMER.UPDATE_SERVER_USER_DATA]
; User data update interval (ajax long polling)
@@ -275,7 +275,7 @@ DELAY = 5000
; Requests that exceed the limit are logged as 'warning'.
; Syntax: Integer (milliseconds)
; Default: 500
EXECUTION_LIMIT = 500
EXECUTION_LIMIT = 1000
; update client user data (milliseconds)
[PATHFINDER.TIMER.UPDATE_CLIENT_USER_DATA]
@@ -283,11 +283,12 @@ EXECUTION_LIMIT = 500
; User data updates that exceed the limit are logged as 'warning'.
; Syntax: Integer (milliseconds)
; Default: 50
EXECUTION_LIMIT = 50
EXECUTION_LIMIT = 100
; CACHE ===========================================================================================
[PATHFINDER.CACHE]
; Delete character log data if nothing (ship/system/...) changed for X seconds
; Checks "character log" data by cronjob after x seconds
; If character is ingame offline -> delete "character log"
; Syntax: Integer (seconds)
; Default: 180
CHARACTER_LOG_INACTIVE = 180

View File

@@ -22,9 +22,6 @@ PCRE_VERSION = 8.02
; Redis extension (optional), required if you want to use Redis as caching Engine (recommended)
REDIS = 3.0.0
; ZeroMQ (ØMQ) extension (optional) required for WebSocket Server extension (recommended)
ZMQ = 1.1.3
; Event extension (optional) for WebSocket configuration. Better performance
; https://pecl.php.net/package/event
EVENT = 2.3.0
@@ -48,9 +45,6 @@ MAX_INPUT_VARS = 3000
; Formatted HTML StackTraces
HTML_ERRORS = 0
[REQUIREMENTS.LIBS]
ZMQ = 4.1.3
[REQUIREMENTS.MYSQL]
; min MySQL Version
; newer "deviation" of MySQL like "MariaDB" > 10.1 are recommended

View File

@@ -18,6 +18,9 @@ GET|POST /api/@controller/@action [ajax] = Controller\Api\@cont
GET|POST /api/@controller/@action/@arg1 [ajax] = Controller\Api\@controller->@action, 0, 512
GET|POST /api/@controller/@action/@arg1/@arg2 [ajax] = Controller\Api\@controller->@action, 0, 512
; onUnload route or final map sync (@see https://developer.mozilla.org/docs/Web/API/Navigator/sendBeacon)
POST /api/map/updateUnloadData = Controller\Api\map->updateUnloadData, 0, 512
[maps]
; REST API wildcard endpoints (not cached, throttled)
/api/rest/@controller* [ajax] = Controller\Api\Rest\@controller, 0, 512

2164
composer.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -9,14 +9,16 @@ var jsBaseUrl = document.body.getAttribute('data-js-path');
// requireJs configuration
requirejs.config({
baseUrl: 'js', // path for baseUrl - dynamically set !below! ("build_js" | "js")
baseUrl: 'js', // src root path - dynamically set !below! ("build_js" | "js")
paths: {
layout: 'layout',
conf: 'app/conf', // path for "config" files dir
dialog: 'app/ui/dialog', // path for "dialog" files dir
templates: '../../templates', // template dir
img: '../../img', // images dir
conf: 'app/conf', // path config files
dialog: 'app/ui/dialog', // path dialog files
layout: 'app/ui/layout', // path layout files
module: 'app/ui/module', // path module files
templates: '../../templates', // path template base dir
img: '../../img', // path image base dir
// main views
login: './app/login', // initial start "login page" view
@@ -28,24 +30,23 @@ requirejs.config({
jquery: 'lib/jquery-3.3.1.min', // v3.3.1 jQuery
bootstrap: 'lib/bootstrap.min', // v3.3.0 Bootstrap js code - http://getbootstrap.com/javascript
text: 'lib/requirejs/text', // v2.0.12 A RequireJS/AMD loader plugin for loading text resources.
mustache: 'lib/mustache.min', // v1.0.0 Javascript template engine - http://mustache.github.io
localForage: 'lib/localforage.min', // v1.4.2 localStorage library - https://mozilla.github.io/localForage
mustache: 'lib/mustache.min', // v3.0.1 Javascript template engine - http://mustache.github.io
localForage: 'lib/localforage.min', // v1.7.3 localStorage library - https://localforage.github.io/localForage/
velocity: 'lib/velocity.min', // v1.5.1 animation engine - http://julian.com/research/velocity
velocityUI: 'lib/velocity.ui.min', // v5.2.0 plugin for velocity - http://julian.com/research/velocity/#uiPack
slidebars: 'lib/slidebars', // v0.10 Slidebars - side menu plugin http://plugins.adchsm.me/slidebars
jsPlumb: 'lib/dom.jsPlumb-1.7.6', // v1.7.6 jsPlumb (Vanilla)- main map draw plugin https://jsplumbtoolkit.com
farahey: 'lib/farahey-0.5', // v0.5 jsPlumb "magnetizing" extension - https://github.com/jsplumb/farahey
slidebars: 'lib/slidebars', // v2.0.2 Slidebars - side menu plugin https://www.adchsm.com/slidebars/
jsPlumb: 'lib/jsplumb', // v2.9.3 jsPlumb main map draw plugin http://jsplumb.github.io/jsplumb/home.html
farahey: 'lib/farahey', // v1.1.2 jsPlumb "magnetizing" plugin extension - https://github.com/ThomasChan/farahey
customScrollbar: 'lib/jquery.mCustomScrollbar.min', // v3.1.5 Custom scroll bars - http://manos.malihu.gr
mousewheel: 'lib/jquery.mousewheel.min', // v3.1.13 Mousewheel - https://github.com/jquery/jquery-mousewheel
xEditable: 'lib/bootstrap-editable.min', // v1.5.1 X-editable - in placed editing
morris: 'lib/morris.min', // v0.5.1 Morris.js - graphs and charts
raphael: 'lib/raphael-min', // v2.1.2 Raphaël - required for morris (dependency)
raphael: 'lib/raphael.min', // v2.2.8 Raphaël - required for morris - https://dmitrybaranovskiy.github.io/raphael
bootbox: 'lib/bootbox.min', // v4.4.0 Bootbox.js - custom dialogs - http://bootboxjs.com
easyPieChart: 'lib/jquery.easypiechart.min', // v2.1.6 Easy Pie Chart - HTML 5 pie charts - http://rendro.github.io/easy-pie-chart
peityInlineChart: 'lib/jquery.peity.min', // v3.2.1 Inline Chart - http://benpickles.github.io/peity/
dragToSelect: 'lib/jquery.dragToSelect', // v1.1 Drag to Select - http://andreaslagerkvist.com/jquery/drag-to-select
hoverIntent: 'lib/jquery.hoverIntent.min', // v1.9.0 Hover intention - http://cherne.net/brian/resources/jquery.hoverIntent.html
fullScreen: 'lib/jquery.fullscreen.min', // v0.6.0 Full screen mode - https://github.com/private-face/jquery.fullscreen
select2: 'lib/select2.min', // v4.0.3 Drop Down customization - https://select2.github.io
validator: 'lib/validator.min', // v0.10.1 Validator for Bootstrap 3 - https://github.com/1000hz/bootstrap-validator
lazylinepainter: 'lib/jquery.lazylinepainter-1.5.1.min', // v1.5.1 SVG line animation plugin - http://lazylinepainter.info
@@ -64,13 +65,13 @@ requirejs.config({
easePack: 'lib/EasePack.min',
tweenLite: 'lib/TweenLite.min',
// datatables // v1.10.12 DataTables - https://datatables.net
// datatables // v1.10.18 DataTables - https://datatables.net
'datatables.loader': './app/datatables.loader',
'datatables.net': 'lib/datatables/DataTables-1.10.12/js/jquery.dataTables.min',
'datatables.net-buttons': 'lib/datatables/Buttons-1.2.1/js/dataTables.buttons.min',
'datatables.net-buttons-html': 'lib/datatables/Buttons-1.2.1/js/buttons.html5.min',
'datatables.net-responsive': 'lib/datatables/Responsive-2.1.0/js/dataTables.responsive.min',
'datatables.net-select': 'lib/datatables/Select-1.2.0/js/dataTables.select.min',
'datatables.net': 'lib/datatables/DataTables-1.10.18/js/jquery.dataTables.min',
'datatables.net-buttons': 'lib/datatables/Buttons-1.5.6/js/dataTables.buttons.min',
'datatables.net-buttons-html': 'lib/datatables/Buttons-1.5.6/js/buttons.html5.min',
'datatables.net-responsive': 'lib/datatables/Responsive-2.2.2/js/dataTables.responsive.min',
'datatables.net-select': 'lib/datatables/Select-1.3.0/js/dataTables.select.min',
'datatables.plugins.render.ellipsis': 'lib/datatables/plugins/render/ellipsis',
// notification plugin
@@ -152,9 +153,6 @@ requirejs.config({
hoverIntent: {
deps: ['jquery']
},
fullScreen: {
deps: ['jquery']
},
select2: {
deps: ['jquery', 'mousewheel'],
exports: 'Select2'

View File

@@ -69,7 +69,7 @@ define([
Util.initDefaultBootboxConfig();
// hide splash loading animation
$('.' + config.splashOverlayClass).hideSplashOverlay();
$('.' + config.splashOverlayClass + '[data-status="ok"]').hideSplashOverlay();
setPageObserver();

View File

@@ -203,9 +203,9 @@ define([], () => {
* @param version
*/
let showVersionInfo = (version) => {
console.ok('%c PATHFINDER',
'color: #477372; font-size: 25px; margin-left: 10px; line-height: 100px; text-shadow: 1px 1px 0 #212C30; ' +
'background: url(https://i.imgur.com/1Gw8mjL.png) no-repeat;');
console.ok('%c PATHFINDER',
'color: #477372; font-size: 25px; margin-left: 10px; line-height: 50px; text-shadow: 1px 1px 0 #212C30; ' +
'background: url(https://i.imgur.com/bhSr6LI.png) no-repeat;');
console.pf('Release: %s', version);
};

View File

@@ -2,7 +2,7 @@
* Init
*/
define(['jquery'], ($) => {
define([], () => {
'use strict';
@@ -16,7 +16,6 @@ define(['jquery'], ($) => {
getCookieCharacterData: '/api/user/getCookieCharacter', // ajax URL - get character data from cookie
logIn: '/api/user/logIn', // ajax URL - login
logout: '/api/user/logout', // ajax URL - logout
deleteLog: '/api/user/deleteLog', // ajax URL - delete character log
openIngameWindow: '/api/user/openIngameWindow', // ajax URL - open inGame Window
saveUserConfig: '/api/user/saveAccount', // ajax URL - saves/update user account
deleteAccount: '/api/user/deleteAccount', // ajax URL - delete Account data
@@ -27,6 +26,7 @@ define(['jquery'], ($) => {
getAccessData: '/api/map/getAccessData', // ajax URL - get map access tokens (WebSocket)
updateMapData: '/api/map/updateData', // ajax URL - main map update trigger
updateUserData: '/api/map/updateUserData', // ajax URL - main map user data trigger
updateUnloadData: '/api/map/updateUnloadData', // post URL - for my sync onUnload
// map API
saveMap: '/api/map/save', // ajax URL - save/update map
deleteMap: '/api/map/delete', // ajax URL - delete map
@@ -103,6 +103,14 @@ define(['jquery'], ($) => {
class: 'fa-anchor',
label: 'anchor',
unicode: '&#xf13d;'
},{
class: 'fa-satellite',
label: 'satellite',
unicode: '&#xf7bf;'
},{
class: 'fa-skull-crossbones',
label: 'skull crossbones',
unicode: '&#xf714;'
},{
class: 'fa-fire',
label: 'fire',
@@ -119,6 +127,10 @@ define(['jquery'], ($) => {
class: 'fa-star',
label: 'star',
unicode: '&#xf005;'
},{
class: 'fa-hat-wizard',
label: 'hat wizard',
unicode: '&#xf6e8;'
},{
class: 'fa-plane',
label: 'plane',
@@ -145,7 +157,6 @@ define(['jquery'], ($) => {
unicode: '&#xf619;'
}
],
classes: {
// log types
logTypes: {
@@ -343,51 +354,97 @@ define(['jquery'], ($) => {
}
},
wh_eol: {
cssClass: 'pf-map-connection-wh-eol',
paintStyle: {
dashstyle: '0' // solid line
}
cssClass: 'pf-map-connection-wh-eol'
},
wh_fresh: {
cssClass: 'pf-map-connection-wh-fresh',
paintStyle: {
dashstyle: '0' // solid line
}
cssClass: 'pf-map-connection-wh-fresh'
},
wh_reduced: {
cssClass: 'pf-map-connection-wh-reduced',
paintStyle: {
dashstyle: '0' // solid line
}
cssClass: 'pf-map-connection-wh-reduced'
},
wh_critical: {
cssClass: 'pf-map-connection-wh-critical',
paintStyle: {
dashstyle: '0' // solid line
}
cssClass: 'pf-map-connection-wh-critical'
},
frigate: {
cssClass: 'pf-map-connection-frig',
wh_jump_mass_s: {
cssClass: 'pf-map-connection-wh-size-s',
paintStyle: {
dashstyle: '0.99'
dashstyle: '0.5 1',
strokeWidth: 3
},
overlays:[
overlays: [
['Label',
{
label: 'frig',
cssClass: ['pf-map-component-overlay', 'frig'].join(' '),
location: 0.6
label: '<i class="fas fa-char pf-jump-mass-s" data-char-content="S"></i>',
cssClass: ['pf-map-component-overlay', 'small', 'text-center'].join(' '),
location: 0.65,
id: 'pf-map-connection-jump-mass-overlay'
}]
]
},
wh_jump_mass_m: {
cssClass: 'pf-map-connection-wh-size-m',
paintStyle: {
dashstyle: '3 1'
},
overlays: [
['Label',
{
label: '<i class="fas fa-char pf-jump-mass-m" data-char-content="M"></i>',
cssClass: ['pf-map-component-overlay', 'small', 'text-center'].join(' '),
location: 0.65,
id: 'pf-map-connection-jump-mass-overlay'
}]
]
},
wh_jump_mass_l: {
cssClass: 'pf-map-connection-wh-size-l',
overlays: [
['Label',
{
label: '<i class="fas fa-char pf-jump-mass-l" data-char-content="L"></i>',
cssClass: ['pf-map-component-overlay', 'small', 'text-center'].join(' '),
location: 0.65,
id: 'pf-map-connection-jump-mass-overlay'
}]
]
},
wh_jump_mass_xl: {
cssClass: 'pf-map-connection-wh-size-xl',
paintStyle: {
strokeWidth: 6
},
overlays: [
['Label',
{
label: '<i class="fas fa-char pf-jump-mass-xl" data-char-content="XL"></i>',
cssClass: ['pf-map-component-overlay', 'small', 'text-center'].join(' '),
location: 0.65,
id: 'pf-map-connection-jump-mass-overlay'
}]
]
},
preserve_mass: {
cssClass: 'pf-map-connection-preserve-mass',
overlays:[
overlays: [
['Label',
{
label: '<i class="fas fa-fw fa-exclamation-triangle"></i>&nbsp;save mass',
cssClass: ['pf-map-component-overlay', 'mass'].join(' '),
location: 0.6
location: 0.35
}]
]
},
info_signature: {
overlays: [
['Arrow',
{
id: 'pf-map-connection-arrow-overlay',
cssClass: 'pf-map-connection-arrow-overlay',
width: 12,
length: 15,
direction: 1,
foldback: 0.8,
location: 0.5
}]
]
},
@@ -396,40 +453,70 @@ define(['jquery'], ($) => {
},
state_process: {
cssClass: 'pf-map-connection-process',
overlays:[
overlays: [
['Label',
{
label: '<i class="fas fa-fw fa-sync fa-spin"></i>',
cssClass: ['pf-map-connection-state-overlay'].join(' '),
location: 0.6
location: 0.5
}]
]
}
},
wormholeSizes: {
wh_jump_mass_xl: {
jumpMassMin: 1000000000,
type: 'wh_jump_mass_xl',
class: 'pf-jump-mass-xl',
label: 'XL',
text: 'capital ships'
},
wh_jump_mass_l: {
jumpMassMin: 300000000,
type: 'wh_jump_mass_l',
class: 'pf-jump-mass-l',
label: 'L',
text: 'larger ships'
},
wh_jump_mass_m: {
jumpMassMin: 20000000,
type: 'wh_jump_mass_m',
class: 'pf-jump-mass-m',
label: 'M',
text: 'medium ships'
},
wh_jump_mass_s: {
jumpMassMin: 1000,
type: 'wh_jump_mass_s',
class: 'pf-jump-mass-s',
label: 'S',
text: 'smallest ships'
}
},
// signature groups
signatureGroups: {
1: {
name: '(combat site|kampfgebiet|site de combat|Боевой район)', //*
name: '(combat site|kampfgebiet|site de combat|Боевой район|战斗地点)',
label: 'Combat'
},
2: {
name: '(relic site|reliktgebiet|site de reliques|Археологический район)', //*
name: '(relic site|reliktgebiet|site de reliques|Археологический район|遗迹地点)',
label: 'Relic'
},
3: {
name: '(data site|datengebiet|site de données|Информационный район)',
name: '(data site|datengebiet|site de données|Информационный район|数据地点)',
label: 'Data'
},
4: {
name: '(gas site|gasgebiet|site de collecte de gaz|Газовый район)',
name: '(gas site|gasgebiet|site de collecte de gaz|Газовый район|气云地点)',
label: 'Gas'
},
5: {
name: '(wormhole|wurmloch|trou de ver|Червоточина)',
name: '(wormhole|wurmloch|trou de ver|Червоточина|虫洞)',
label: 'Wormhole'
},
6: {
name: '(ore site|mineraliengebiet|site de minerai|Астероидный район)',
name: '(ore site|mineraliengebiet|site de minerai|Астероидный район|矿石地点)',
label: 'Ore'
},
7: {

View File

@@ -10,6 +10,12 @@ define([
label: 'Close open dialog',
keyNames: ['ESC']
},
// map ----------------------------------------------------------------------------------------------
mapMove: {
group: 'map',
label: 'Move map section',
keyNames: ['space', 'drag']
},
// signature ----------------------------------------------------------------------------------------
signatureSelect: {
group: 'signatures',
@@ -37,6 +43,11 @@ define([
keyNames: ['CONTROL', 'V'],
alias: 'paste'
},
renameSystem: {
group: 'map',
label: 'Rename system',
keyNames: ['ALT', 'N']
},
newSignature: {
group: 'signatures',
label: 'New Signature',
@@ -79,12 +90,6 @@ define([
*/
let debug = false;
/**
* check interval for "new" active keys
* @type {number}
*/
let keyWatchPeriod = 100;
/**
* DOM data key for an element that lists all active events (comma separated)
* @type {string}
@@ -133,6 +138,13 @@ define([
return Object.keys(map);
};
/**
* checks whether a key is currently active (keydown)
* @param key
* @returns {boolean}
*/
let isActive = key => map.hasOwnProperty(key) && map[key] === true;
/**
* callback function that compares two arrays
* @param element
@@ -460,6 +472,7 @@ define([
};
return {
isActive: isActive,
getGroupedShortcuts: getGroupedShortcuts
};
});

View File

@@ -7,7 +7,7 @@ define([
'app/init',
'app/util',
'bootbox'
], function($, Init, Util, bootbox){
], ($, Init, Util, bootbox) => {
'use strict';
@@ -27,27 +27,16 @@ define([
moduleHeadlineIconClass: 'pf-module-icon-button' // class for toolbar icons in the head
};
/**
* get log time string
* @returns {string}
*/
let getLogTime = function(){
let serverTime = Util.getServerTime();
let logTime = serverTime.toLocaleTimeString('en-US', { hour12: false });
return logTime;
};
/**
* updated "sync status" dynamic dialog area
*/
let updateSyncStatus = function(){
let updateSyncStatus = () => {
// check if task manager dialog is open
let logDialog = $('#' + config.taskDialogId);
if(logDialog.length){
// dialog is open
requirejs(['text!templates/modules/sync_status.html', 'mustache'], function(templateSyncStatus, Mustache){
requirejs(['text!templates/modules/sync_status.html', 'mustache'], (templateSyncStatus, Mustache) => {
let data = {
timestampCounterClass: config.timestampCounterClass,
syncStatus: Init.syncStatus,
@@ -59,7 +48,7 @@ define([
}
};
let syncStatusElement = $( Mustache.render(templateSyncStatus, data ) );
let syncStatusElement = $(Mustache.render(templateSyncStatus, data ));
logDialog.find('.' + config.taskDialogStatusAreaClass).html( syncStatusElement );
@@ -76,7 +65,7 @@ define([
/**
* shows the logging dialog
*/
let showDialog = function(){
let showDialog = () => {
// dialog content
requirejs(['text!templates/dialog/task_manager.html', 'mustache', 'datatables.loader'], function(templateTaskManagerDialog, Mustache){
@@ -108,19 +97,27 @@ define([
buttons: [
{
extend: 'copy',
tag: 'a',
className: config.moduleHeadlineIconClass,
text: '<i class="fas fa-fw fa-copy"></i> copy'
text: '<i class="fas fa-fw fa-copy"></i> copy',
exportOptions: {
orthogonal: 'export'
}
},
{
extend: 'csv',
tag: 'a',
className: config.moduleHeadlineIconClass,
text: '<i class="fas fa-fw fa-download"></i> csv'
text: '<i class="fas fa-fw fa-download"></i> csv',
exportOptions: {
orthogonal: 'export'
}
}
]
},
paging: true,
ordering: true,
order: [ 1, 'desc' ],
order: [1, 'desc'],
hover: false,
pageLength: 10,
lengthMenu: [[5, 10, 25, 50, 100, -1], [5, 10, 25, 50, 100, 'All']],
@@ -134,42 +131,69 @@ define([
columnDefs: [
{
targets: 0,
name: 'status',
title: '<i class="fas fa-tag"></i>',
width: '18px',
width: 18,
searchable: false,
class: ['text-center'].join(' '),
data: 'status'
data: 'status',
render: {
display: (cellData, type, rowData, meta) => {
let statusClass = Util.getLogInfo(cellData, 'class');
return '<i class="fas fa-fw fa-circle txt-color ' + statusClass + '"></i>';
}
}
},{
targets: 1,
title: '<i class="far fa-fw fa-clock"></i>&nbsp;&nbsp;',
width: '50px',
name: 'time',
title: '<i class="far fa-fw fa-clock"></i>',
width: 50,
searchable: true,
class: 'text-right',
data: 'time'
data: 'timestamp',
render: {
display: (cellData, type, rowData, meta) => rowData.timestampFormatted
}
},{
targets: 2,
title: '<i class="fas fa-fw fa-history"></i>&nbsp;&nbsp;',
width: '35px',
name: 'duration',
title: '<i class="fas fa-fw fa-history"></i>',
width: 35,
searchable: false,
class: 'text-right',
sType: 'html',
data: 'duration'
data: 'duration',
render: {
display: (cellData, type, rowData, meta) => {
let logStatus = getLogStatusByDuration(rowData.key, cellData);
let statusClass = Util.getLogInfo(logStatus, 'class');
return '<span class="txt-color ' + statusClass + '">' + cellData + '<small>ms</small></span>';
}
}
},{
targets: 3,
name: 'description',
title: 'description',
searchable: true,
data: 'description'
},{
targets: 4,
name: 'logType',
title: 'type',
width: '40px',
width: 40,
searchable: true,
class: ['text-center'].join(' '),
data: 'type'
data: 'logType',
render: {
display: (cellData, type, rowData, meta) => {
let typeIconClass = getLogTypeIconClass(cellData);
return '<i class="fas ' + typeIconClass + '"></i>';
}
}
},{
targets: 5,
title: 'Prozess-ID&nbsp;&nbsp;&nbsp;',
width: '80px',
name: 'process',
title: 'Prozess-ID',
width: 80,
searchable: false,
class: 'text-right',
data: 'key'
@@ -197,10 +221,7 @@ define([
// show Morris graphs ----------------------------------------------------------
// function for chart label formation
let labelYFormat = function(y){
return Math.round(y) + 'ms';
};
let labelYFormat = val => Math.round(val) + 'ms';
for(let key in chartData){
if(chartData.hasOwnProperty(key)){
@@ -241,8 +262,8 @@ define([
});
headline.append(averageElement);
colElementGraph.append( headline );
colElementGraph.append( graphArea );
colElementGraph.append(headline);
colElementGraph.append(graphArea);
graphArea.showLoadingAnimation();
@@ -321,10 +342,10 @@ define([
* @param key
* @param duration (if undefined -> just update graph with current data)
*/
let updateLogGraph = function(key, duration){
let updateLogGraph = (key, duration) => {
// check if graph data already exist
if( !(chartData.hasOwnProperty(key))){
if(!(chartData.hasOwnProperty(key))){
chartData[key] = {};
chartData[key].data = [];
chartData[key].graph = null;
@@ -341,7 +362,7 @@ define([
chartData[key].data = chartData[key].data.slice(0, maxGraphDataCount);
}
function getGraphData(data){
let getGraphData = data => {
let tempChartData = {
data: [],
dataSum: 0,
@@ -352,7 +373,7 @@ define([
let value = 0;
if(data[x]){
value = data[x];
tempChartData.dataSum = Number( (tempChartData.dataSum + value).toFixed(2) );
tempChartData.dataSum = Number((tempChartData.dataSum + value).toFixed(2));
}
tempChartData.data.push({
@@ -362,10 +383,10 @@ define([
}
// calculate average
tempChartData.average = Number( ( tempChartData.dataSum / data.length ).toFixed(2) );
tempChartData.average = Number((tempChartData.dataSum / data.length).toFixed(2));
return tempChartData;
}
};
let tempChartData = getGraphData(chartData[key].data);
@@ -374,17 +395,17 @@ define([
let avgElement = chartData[key].averageElement;
let updateElement = chartData[key].updateElement;
let delay = Util.getCurrentTriggerDelay( key, 0 );
let delay = Util.getCurrentTriggerDelay(key, 0);
if(delay){
updateElement[0].textContent = ' delay: ' + delay + 'ms ';
updateElement[0].textContent = ' delay: ' + delay.toFixed(2) + ' ms';
}
// set/change average line
chartData[key].graph.options.goals = [tempChartData.average];
// change avg. display
avgElement[0].textContent = 'Avg. ' + tempChartData.average + 'ms';
avgElement[0].textContent = 'avg. ' + tempChartData.average.toFixed(2) + ' ms';
let avgStatus = getLogStatusByDuration(key, tempChartData.average);
let avgStatusClass = Util.getLogInfo( avgStatus, 'class');
@@ -417,9 +438,9 @@ define([
* @param logDuration
* @returns {string}
*/
let getLogStatusByDuration = function(logKey, logDuration){
let getLogStatusByDuration = (logKey, logDuration) => {
let logStatus = 'info';
if( logDuration > Init.timer[logKey].EXECUTION_LIMIT ){
if(logDuration > Init.timer[logKey].EXECUTION_LIMIT){
logStatus = 'warning';
}
return logStatus;
@@ -430,8 +451,7 @@ define([
* @param logType
* @returns {string}
*/
let getLogTypeIconClass = function(logType){
let getLogTypeIconClass = logType => {
let logIconClass = '';
switch(logType){
@@ -470,24 +490,23 @@ define([
let logDuration = options.duration;
let logType = options.type;
// check log status by duration
let logStatus = getLogStatusByDuration(logKey, logDuration);
let statusClass = Util.getLogInfo( logStatus, 'class');
let typeIconClass = getLogTypeIconClass(logType);
// update graph data
updateLogGraph(logKey, logDuration);
let time = Util.getServerTime();
let timestamp = time.getTime();
let timestampFormatted = time.toLocaleTimeString('en-US', { hour12: false });
let logRowData = {
status: '<i class="fas fa-fw fa-circle txt-color ' + statusClass + '"></i>',
time: getLogTime(),
duration: '<span class="txt-color ' + statusClass + '">' + logDuration + '<small>ms</small></span>',
status: getLogStatusByDuration(logKey, logDuration),
timestamp: timestamp,
timestampFormatted: timestampFormatted,
duration: logDuration,
description: logDescription,
type: '<i class="fas ' + typeIconClass + '"></i>',
logType: logType,
key: logKey
};
if(logDataTable){
// add row if dataTable is initialized before new log
logDataTable.row.add( logRowData ).draw(false);
@@ -500,7 +519,7 @@ define([
// delete old log entries from table ---------------------------------
let rowCount = logData.length;
if( rowCount >= maxEntries ){
if(rowCount >= maxEntries){
if(logDataTable){
logDataTable.rows(0, {order:'index'}).remove().draw(false);
@@ -520,7 +539,6 @@ define([
return {
init: init,
getLogTime: getLogTime,
showDialog: showDialog
};
});

View File

@@ -10,9 +10,9 @@ define([
'blueImpGallery',
'bootbox',
'lazyload',
'app/ui/header',
'app/ui/logo',
'app/ui/demo_map',
'layout/header_login',
'layout/logo',
'layout/demo_map',
'dialog/account_settings',
'dialog/notification',
'dialog/manual',
@@ -798,7 +798,7 @@ define([
});
// hide splash loading animation
$('.' + config.splashOverlayClass).hideSplashOverlay();
$('.' + config.splashOverlayClass + '[data-status="ok"]').hideSplashOverlay();
// init server status information
initServerStatus();

View File

@@ -93,20 +93,25 @@ define([
let moduleData = {
id: config.connectionContextMenuId,
items: [
{icon: 'fa-plane', action: 'frigate', text: 'frigate hole'},
{icon: 'fa-hourglass-end', action: 'wh_eol', text: 'toggle EOL'},
{icon: 'fa-exclamation-triangle', action: 'preserve_mass', text: 'preserve mass'},
{icon: 'fa-crosshairs', action: 'change_scope', text: 'change scope', subitems: [
{subIcon: 'fa-minus-circle', subIconClass: '', subAction: 'scope_wh', subText: 'wormhole'},
{subIcon: 'fa-minus-circle', subIconClass: 'txt-color txt-color-indigoDarkest', subAction: 'scope_stargate', subText: 'stargate'},
{subIcon: 'fa-minus-circle', subIconClass: 'txt-color txt-color-tealLighter', subAction: 'scope_jumpbridge', subText: 'jumpbridge'}
{icon: 'fa-reply fa-rotate-180', action: 'change_status', text: 'mass status', subitems: [
{subIcon: 'fa-circle', subIconClass: 'txt-color txt-color-gray', subAction: 'status_fresh', subText: 'stage 1 (fresh)'},
{subIcon: 'fa-circle', subIconClass: 'txt-color txt-color-orange', subAction: 'status_reduced', subText: 'stage 2 (reduced)'},
{subIcon: 'fa-circle', subIconClass: 'txt-color txt-color-redDarker', subAction: 'status_critical', subText: 'stage 3 (critical)'}
]},
{icon: 'fa-reply fa-rotate-180', action: 'change_status', text: 'change status', subitems: [
{subIcon: 'fa-clock', subAction: 'wh_eol', subText: 'toggle EOL'},
{subDivider: true},
{subIcon: 'fa-circle', subAction: 'status_fresh', subText: 'stage 1 (fresh)'},
{subIcon: 'fa-adjust', subAction: 'status_reduced', subText: 'stage 2 (reduced)'},
{subIcon: 'fa-circle', subAction: 'status_critical', subText: 'stage 3 (critical)'}
{icon: 'fa-reply fa-rotate-180', action: 'wh_jump_mass_change', text: 'ship size', subitems: [
{subIcon: 'fa-char', subChar: 'S', subAction: 'wh_jump_mass_s', subText: 'smallest ships'},
{subIcon: 'fa-char', subChar: 'M', subAction: 'wh_jump_mass_m', subText: 'medium ships'},
{subIcon: 'fa-char', subChar: 'L', subAction: 'wh_jump_mass_l', subText: 'larger ships'},
{subIcon: 'fa-char', subChar: 'XL', subAction: 'wh_jump_mass_xl', subText: 'capital ships'}
]},
{icon: 'fa-crosshairs', action: 'change_scope', text: 'change scope', subitems: [
{subIcon: 'fa-minus-circle', subIconClass: '', subAction: 'scope_wh', subText: 'wormhole'},
{subIcon: 'fa-minus-circle', subIconClass: 'txt-color txt-color-indigoDarkest', subAction: 'scope_stargate', subText: 'stargate'},
{subIcon: 'fa-minus-circle', subIconClass: 'txt-color txt-color-tealLighter', subAction: 'scope_jumpbridge', subText: 'jumpbridge'}
]},
{divider: true, action: 'separator'} ,

View File

@@ -38,7 +38,7 @@ define(() => {
* @returns {*}
* @private
*/
this._getElementDimension = (element) => {
this._getElementDimension = element => {
let dim = null;
let left = 0;

View File

@@ -1,135 +1,173 @@
/**
* Map "magnetizing" feature
* jsPlumb extension used: http://morrisonpitt.com/farahey/
* jsPlumb extension used: https://github.com/ThomasChan/farahey
*/
define([
'jquery',
'app/map/util',
'farahey'
], function($, MapUtil){
], ($, MapUtil) => {
'use strict';
/**
* Cached current "Magnetizer" object
* @type {Magnetizer}
* active magnetizer instances (cache object)
* @type {{}}
*/
let m8 = null;
let magnetizerInstances = {};
/**
* init a jsPlumb (map) Element for "magnetised" function.
* this is optional and prevents systems from being overlapped
* magnetizer instance exists for mapId
* @param mapId
* @returns {boolean}
*/
$.fn.initMagnetizer = function(){
let mapContainer = this;
let systems = mapContainer.getSystems();
let hasInstance = mapId => magnetizerInstances.hasOwnProperty(mapId);
/**
* helper function
* get current system offset
* @param system
* @returns {{left, top}}
* @private
*/
let _offset = function(system){
/**
* get magnetizer instance by mapId
* @param mapId
* @returns {null}
*/
let getInstance = mapId => hasInstance(mapId) ? magnetizerInstances[mapId] : null;
let _ = function(p){
let v = system.style[p];
return parseInt(v.substring(0, v.length - 2));
};
return {
left:_('left'),
top:_('top')
};
};
/**
* helper function
* set new system offset
* @param system
* @param o
* @private
*/
let _setOffset = function(system, o){
let markAsUpdated = false;
// new position must be within parent container
// no negative offset!
if(
o.left >= 0 &&
o.left <= 2300
){
markAsUpdated = true;
system.style.left = o.left + 'px';
}
if(
o.top >= 0 &&
o.top <= 498
){
markAsUpdated = true;
system.style.top = o.top + 'px';
}
if(markAsUpdated === true){
MapUtil.markAsChanged($(system));
}
};
/**
* helper function
* exclude current dragged element(s) from position update
* @param id
* @returns {boolean}
* @private
*/
let _dragFilter = function(id){
return !$('#' + id).is('.jsPlumb_dragged, .pf-system-locked');
};
let gridConstrain = function(gridX, gridY){
return function(id, current, delta){
if( mapContainer.hasClass(MapUtil.config.mapGridClass) ){
// active grid
return {
left:(gridX * Math.floor( (current[0] + delta.left) / gridX )) - current[0],
top:(gridY * Math.floor( (current[1] + delta.top) / gridY )) - current[1]
};
}else{
// no grid
return delta;
}
};
};
// main init for "magnetize" feature ------------------------------------------------------
m8 = new Magnetizer({
container: mapContainer,
getContainerPosition: function(c){
return c.offset();
},
getPosition:_offset,
getSize: function(system){
return [ $(system).outerWidth(), $(system).outerHeight() ];
},
getId : function(system){
return $(system).attr('id');
},
setPosition:_setOffset,
elements: systems,
filter: _dragFilter,
padding: [6, 6],
constrain: gridConstrain(MapUtil.config.mapSnapToGridDimension, MapUtil.config.mapSnapToGridDimension)
});
/**
* set new magnetizer instance for mapId
* @param mapId
* @param magnetizer
*/
let setInstance = (mapId, magnetizer) => {
if(mapId && magnetizer){
magnetizerInstances[mapId] = magnetizer;
}
};
$.fn.destroyMagnetizer = function(){
let mapContainer = this;
/**
* init new magnetizer instance for a map
* @param mapContainer
*/
let initMagnetizer = mapContainer => {
let mapId = mapContainer.data('id');
// remove cached "magnetizer" instance
m8 = null;
if(!hasInstance(mapId)){
// magnetizer not exist -> new instance
let systems = mapContainer.getSystems();
/**
* function that takes an element from your list and returns its position as a JS object
* @param system
* @returns {{top: number, left: number}}
* @private
*/
let _offset = system => {
let _ = p => {
let v = system.style[p];
return parseInt(v.substring(0, v.length - 2));
};
return {left: _('left'), top: _('top')};
};
/**
* function that takes an element id and position, and applies that position to the related element
* @param system
* @param o
* @private
*/
let _setOffset = (system, o) => {
o.left = Math.round(o.left);
o.top = Math.round(o.top);
let left = o.left + 'px';
let top = o.top + 'px';
let markAsUpdated = false;
// new position must be within parent container
// no negative offset!
if(
o.left >= 0 && o.left <= 2300 &&
system.style.left !== left
){
system.style.left = left;
markAsUpdated = true;
}
if(
o.top >= 0 && o.top <= 1400 &&
system.style.top !== top
){
system.style.top = top;
markAsUpdated = true;
}
if(markAsUpdated){
MapUtil.markAsChanged($(system));
}
};
/**
* filter some element8s) from being moved
* @param systemId
* @returns {boolean}
* @private
*/
let _dragFilter = systemId => {
let filterClasses = ['jtk-drag', 'pf-system-locked'];
return ![...document.getElementById(systemId).classList].some(className => filterClasses.indexOf(className) >= 0);
};
/**
* grid snap constraint
* @param gridX
* @param gridY
* @returns {Function}
*/
let gridConstrain = (gridX, gridY) => {
return (id, current, delta) => {
if(mapContainer.hasClass(MapUtil.config.mapGridClass)){
// active grid
return {
left: (gridX * Math.floor( (Math.round(current[0]) + delta.left) / gridX )) - current[0],
top: (gridY * Math.floor( (Math.round(current[1]) + delta.top) / gridY )) - current[1]
};
}else{
// no grid
delta.left = Math.round(delta.left);
delta.top = Math.round(delta.top);
return delta;
}
};
};
// create new magnetizer instance -------------------------------------------------------------------------
setInstance(mapId, window.Farahey.getInstance({
container: mapContainer,
getContainerPosition: mapContainer => mapContainer.offset(),
getPosition:_offset,
getSize: system => {
let clientRect = system.getBoundingClientRect();
return [Math.floor(clientRect.width), Math.floor(clientRect.height)];
},
getId : system => system.id,
setPosition:_setOffset,
elements: systems.toArray(),
filter: _dragFilter,
padding: [3, 3],
constrain: gridConstrain(MapUtil.config.mapSnapToGridDimension, MapUtil.config.mapSnapToGridDimension),
executeNow: false, // no initial rearrange after initialization
excludeFocus: true
}));
}
};
/**
* destroy Magnetizer instance
*/
let destroyMagnetizer = mapContainer => {
let mapId = mapContainer.data('id');
let magnetizer = getInstance(mapId);
if(magnetizer){
magnetizer.reset();
delete magnetizerInstances[mapId];
}
};
/**
@@ -137,44 +175,50 @@ define([
* @param map
* @param e
*/
let executeAtEvent = function(map, e){
if(m8 !== null && e ){
m8.executeAtEvent(e);
let executeAtEvent = (map, e) => {
let mapContainer = $(map.getContainer());
let mapId = mapContainer.data('id');
let magnetizer = getInstance(mapId);
if(magnetizer && e){
magnetizer.executeAtEvent(e, {
iterations: 2,
excludeFocus: true
});
map.repaintEverything();
}
};
/**
* rearrange all systems of a map
* needs "magnetization" to be active
* @param map
* add system to magnetizer instance
* @param mapId
* @param system
* @param doNotTestForDuplicates
*/
let executeAtCenter = function(map){
if(m8 !== null){
m8.executeAtCenter();
map.repaintEverything();
let addElement = (mapId, system, doNotTestForDuplicates) => {
let magnetizer = getInstance(mapId);
if(magnetizer){
magnetizer.addElement(system, doNotTestForDuplicates);
}
};
/**
* set/update elements for "magnetization"
* -> (e.g. new systems was added)
* @param map
* remove system element from magnetizer instance
* @param mapId
* @param system
*/
let setElements = function(map){
if(m8 !== null){
let mapContainer = $(map.getContainer());
let systems = mapContainer.getSystems();
m8.setElements(systems);
// re-arrange systems
executeAtCenter(map);
let removeElement = (mapId, system) => {
let magnetizer = getInstance(mapId);
if(magnetizer){
magnetizer.removeElement(system);
}
};
return {
executeAtCenter: executeAtCenter,
initMagnetizer: initMagnetizer,
destroyMagnetizer: destroyMagnetizer,
executeAtEvent: executeAtEvent,
setElements: setElements
addElement: addElement,
removeElement: removeElement
};
});

File diff suppressed because it is too large Load Diff

View File

@@ -1,747 +0,0 @@
/**
* map overlay functions
*/
define([
'jquery',
'app/init',
'app/util',
'app/map/util'
], ($, Init, Util, MapUtil) => {
'use strict';
let config = {
logTimerCount: 3, // map log timer in seconds
// map
mapWrapperClass: 'pf-map-wrapper', // wrapper div (scrollable)
// map overlay positions
mapOverlayClass: 'pf-map-overlay', // class for all map overlays
mapOverlayTimerClass: 'pf-map-overlay-timer', // class for map overlay timer e.g. map timer
mapOverlayInfoClass: 'pf-map-overlay-info', // class for map overlay info e.g. map info
overlayLocalClass: 'pf-map-overlay-local', // class for map overlay "local" table
// system
systemHeadClass: 'pf-system-head', // class for system head
// overlay IDs
connectionOverlayWhId: 'pf-map-connection-wh-overlay', // connection WH overlay ID (jsPlumb)
connectionOverlayEolId: 'pf-map-connection-eol-overlay', // connection EOL overlay ID (jsPlumb)
connectionOverlayArrowId: 'pf-map-connection-arrow-overlay', // connection Arrows overlay ID (jsPlumb)
endpointOverlayId: 'pf-map-endpoint-overlay', // endpoint overlay ID (jsPlumb)
// overlay classes
componentOverlayClass: 'pf-map-component-overlay', // class for "normal size" overlay
connectionArrowOverlayClass: 'pf-map-connection-arrow-overlay', // class for "connection arrow" overlay
connectionDiamondOverlayClass: 'pf-map-connection-diamond-overlay' // class for "connection diamond" overlay
};
/**
* get MapObject (jsPlumb) from mapElement
* @param mapElement
* @returns {*}
*/
let getMapObjectFromMapElement = mapElement => {
let Map = require('app/map/map');
return Map.getMapInstance( mapElement.data('id') );
};
/**
* get map object (jsPlumb) from iconElement
* @param overlayIcon
* @returns {*}
*/
let getMapObjectFromOverlayIcon = overlayIcon => {
let mapElement = Util.getMapElementFromOverlay(overlayIcon);
return getMapObjectFromMapElement( mapElement );
};
/**
* add overlays to connections (signature based data)
* @param connections
* @param connectionsData
*/
let addConnectionsOverlay = (connections, connectionsData) => {
let SystemSignatures = require('app/ui/module/system_signature');
/**
* add label to endpoint
* @param endpoint
* @param label
*/
let addEndpointOverlay = (endpoint, label) => {
label = label.join(', ');
endpoint.addOverlay([
'Label',
{
label: MapUtil.getEndpointOverlayContent(label),
id: config.endpointOverlayId,
cssClass: [config.componentOverlayClass, label.length ? 'small' : 'icon'].join(' '),
location: MapUtil.getLabelEndpointOverlayLocation(endpoint, label),
parameters: {
label: label
}
}
]);
};
// loop through all map connections (get from DOM)
for(let connection of connections){
let connectionId = connection.getParameter('connectionId');
let sourceEndpoint = connection.endpoints[0];
let targetEndpoint = connection.endpoints[1];
let signatureTypeNames = {
sourceLabels: [],
targetLabels: []
};
// ... find matching connectionData (from Ajax)
for(let connectionData of connectionsData){
if(connectionData.id === connectionId){
signatureTypeNames = MapUtil.getConnectionDataFromSignatures(connection, connectionData);
// ... connection matched -> continue with next one
break;
}
}
let sourceLabel = signatureTypeNames.sourceLabels;
let targetLabel = signatureTypeNames.targetLabels;
// add endpoint overlays ------------------------------------------------------
addEndpointOverlay(sourceEndpoint, sourceLabel);
addEndpointOverlay(targetEndpoint, targetLabel);
// add arrow (connection) overlay that points from "XXX" => "K162" ------------
let overlayType = 'Diamond'; // not specified
let arrowDirection = 1;
if(
(sourceLabel.indexOf('K162') !== -1 && targetLabel.indexOf('K162') !== -1) ||
(sourceLabel.length === 0 && targetLabel.length === 0) ||
(
sourceLabel.length > 0 && targetLabel.length > 0 &&
sourceLabel.indexOf('K162') === -1 && targetLabel.indexOf('K162') === -1
)
){
// unknown direction
overlayType = 'Diamond'; // not specified
arrowDirection = 1;
}else if(
(sourceLabel.indexOf('K162') !== -1) ||
(sourceLabel.length === 0 && targetLabel.indexOf('K162') === -1)
){
// convert default arrow direction
overlayType = 'Arrow';
arrowDirection = -1;
}else{
// default arrow direction is fine
overlayType = 'Arrow';
arrowDirection = 1;
}
connection.addOverlay([
overlayType,
{
width: 12,
length: 15,
location: 0.5,
foldback: 0.85,
direction: arrowDirection,
id: config.connectionOverlayArrowId,
cssClass: (overlayType === 'Arrow') ? config.connectionArrowOverlayClass : config.connectionDiamondOverlayClass
}
]);
}
};
/**
* remove overviews from a Tooltip
* @param endpoint
* @param i
*/
let removeEndpointOverlay = (endpoint, i) => {
endpoint.removeOverlays(config.endpointOverlayId);
};
/**
* format json object with "time parts" into string
* @param parts
* @returns {string}
*/
let formatTimeParts = parts => {
let label = '';
if(parts.days){
label += parts.days + 'd ';
}
label += ('00' + parts.hours).slice(-2);
label += ':' + ('00' + parts.min).slice(-2);
return label;
};
/**
* hide default icon and replace it with "loading" icon
* @param iconElement
*/
let showLoading = iconElement => {
iconElement = $(iconElement);
let dataName = 'default-icon';
let defaultIconClass = iconElement.data(dataName);
// get default icon class
if( !defaultIconClass ){
// index 0 == 'fa-fw', index 1 == IconName
defaultIconClass = $(iconElement).attr('class').match(/\bfa-\S*/g)[1];
iconElement.data(dataName, defaultIconClass);
}
iconElement.toggleClass( defaultIconClass + ' fa-sync fa-spin');
};
/**
* hide "loading" icon and replace with default icon
* @param iconElement
*/
let hideLoading = iconElement => {
iconElement = $(iconElement);
let dataName = 'default-icon';
let defaultIconClass = iconElement.data(dataName);
iconElement.toggleClass( defaultIconClass + ' fa-sync fa-spin');
};
/**
* git signature data that is linked to a connection for a mapId
* @param mapElement
* @param connections
* @param callback
*/
let getConnectionSignatureData = (mapElement, connections, callback) => {
let mapOverlay = $(mapElement).getMapOverlay('info');
let overlayConnectionIcon = mapOverlay.find('.pf-map-overlay-endpoint');
showLoading(overlayConnectionIcon);
let requestData = {
mapId: mapElement.data('id'),
addData : ['signatures'],
filterData : ['signatures']
};
$.ajax({
type: 'POST',
url: Init.path.getMapConnectionData,
data: requestData,
dataType: 'json',
context: {
mapElement: mapElement,
connections: connections,
overlayConnectionIcon: overlayConnectionIcon
}
}).done(function(connectionsData){
// hide all connection before add them (refresh)
this.mapElement.hideEndpointOverlays();
// ... add overlays
callback(this.connections, connectionsData);
}).always(function(){
hideLoading(this.overlayConnectionIcon);
});
};
/**
* showEndpointOverlays
* -> used by "refresh" overlays (hover) AND/OR initial menu trigger
*/
$.fn.showEndpointOverlays = function(){
let mapElement = $(this);
let map = getMapObjectFromMapElement(mapElement);
let MapUtil = require('app/map/util');
let connections = MapUtil.searchConnectionsByScopeAndType(map, 'wh', undefined, true);
// get connection signature information ---------------------------------------
getConnectionSignatureData(mapElement, connections, addConnectionsOverlay);
};
/**
* hideEndpointOverlays
* -> see showEndpointOverlays()
*/
$.fn.hideEndpointOverlays = function(){
let map = getMapObjectFromMapElement($(this));
let MapUtil = require('app/map/util');
let connections = MapUtil.searchConnectionsByScopeAndType(map, 'wh');
for(let connection of connections){
connection.removeOverlays(config.connectionOverlayArrowId);
connection.endpoints.forEach(removeEndpointOverlay);
}
};
/**
* Overlay options (all available map options shown in overlay)
* "active": (active || hover) indicated whether an icon/option
* is marked as "active".
* "active": Makes icon active when visible
* "hover": Make icon active on hover
*/
let options = {
filter: {
title: 'active filter',
trigger: 'active',
class: 'pf-map-overlay-filter',
iconClass: ['fas', 'fa-fw', 'fa-filter'],
onClick: function(e){
// clear all filter
let mapElement = Util.getMapElementFromOverlay(this);
let map = getMapObjectFromOverlayIcon(this);
MapUtil.storeLocalData('map', mapElement.data('id'), 'filterScopes', []);
MapUtil.filterMapByScopes(map, []);
}
},
mapSnapToGrid: {
title: 'active grid',
trigger: 'active',
class: 'pf-map-overlay-grid',
iconClass: ['fas', 'fa-fw', 'fa-th']
},
mapMagnetizer: {
title: 'active magnetizer',
trigger: 'active',
class: 'pf-map-overlay-magnetizer',
iconClass: ['fas', 'fa-fw', 'fa-magnet']
},
systemRegion: {
title: 'show regions',
trigger: 'hover',
class: 'pf-map-overlay-region',
iconClass: ['fas', 'fa-fw', 'fa-tags'],
hoverIntent: {
over: function(e){
let mapElement = Util.getMapElementFromOverlay(this);
mapElement.find('.' + config.systemHeadClass).each(function(){
let systemHead = $(this);
// init popover if not already exists
if(!systemHead.data('bs.popover')){
let system = systemHead.parent();
systemHead.popover({
placement: 'right',
html: true,
trigger: 'manual',
container: mapElement,
title: false,
content: Util.getSystemRegionTable(
system.data('region'),
system.data('faction') || null
)
});
}
systemHead.setPopoverSmall();
systemHead.popover('show');
});
},
out: function(e){
let mapElement = Util.getMapElementFromOverlay(this);
mapElement.find('.' + config.systemHeadClass).popover('hide');
}
}
},
mapEndpoint: {
title: 'refresh signature overlays',
trigger: 'refresh',
class: 'pf-map-overlay-endpoint',
iconClass: ['fas', 'fa-fw', 'fa-link'],
hoverIntent: {
over: function(e){
let mapElement = Util.getMapElementFromOverlay(this);
mapElement.showEndpointOverlays();
},
out: function(e){
// just "refresh" on hover
}
}
},
mapCompact: {
title: 'compact layout',
trigger: 'active',
class: 'pf-map-overlay-compact',
iconClass: ['fas', 'fa-fw', 'fa-compress']
},
connection: {
title: 'WH data',
trigger: 'hover',
class: 'pf-map-overlay-connection-wh',
iconClass: ['fas', 'fa-fw', 'fa-fighter-jet'],
hoverIntent: {
over: function(e){
let map = getMapObjectFromOverlayIcon(this);
let MapUtil = require('app/map/util');
let connections = MapUtil.searchConnectionsByScopeAndType(map, 'wh');
let serverDate = Util.getServerTime();
// show connection overlays ---------------------------------------------------
for(let connection of connections){
let createdTimestamp = connection.getParameter('created');
let updatedTimestamp = connection.getParameter('updated');
let createdDate = Util.convertTimestampToServerTime(createdTimestamp);
let updatedDate = Util.convertTimestampToServerTime(updatedTimestamp);
let createdDiff = Util.getTimeDiffParts(createdDate, serverDate);
let updatedDiff = Util.getTimeDiffParts(updatedDate, serverDate);
// format overlay label
let labels = [
'<i class="fas fa-fw fa-plus-square"></i>&nbsp;' + formatTimeParts(createdDiff),
'<i class="fas fa-fw fa-pen-square"></i>&nbsp;' + formatTimeParts(updatedDiff)
];
// add label overlay ------------------------------------------------------
connection.addOverlay([
'Label',
{
label: labels.join('<br>'),
id: config.connectionOverlayWhId,
cssClass: [config.componentOverlayClass, 'small'].join(' '),
location: 0.35
}
]);
}
},
out: function(e){
let map = getMapObjectFromOverlayIcon(this);
let MapUtil = require('app/map/util');
let connections = MapUtil.searchConnectionsByScopeAndType(map, 'wh');
for(let connection of connections){
connection.removeOverlays(config.connectionOverlayWhId);
}
}
}
},
connectionEol: {
title: 'EOL timer',
trigger: 'hover',
class: 'pf-map-overlay-connection-eol',
iconClass: ['far', 'fa-fw', 'fa-clock'],
hoverIntent: {
over: function(e){
let map = getMapObjectFromOverlayIcon(this);
let MapUtil = require('app/map/util');
let connections = MapUtil.searchConnectionsByScopeAndType(map, 'wh', ['wh_eol']);
let serverDate = Util.getServerTime();
for(let connection of connections){
let eolTimestamp = connection.getParameter('eolUpdated');
let eolDate = Util.convertTimestampToServerTime(eolTimestamp);
let diff = Util.getTimeDiffParts(eolDate, serverDate);
connection.addOverlay([
'Label',
{
label: '<i class="far fa-fw fa-clock"></i>&nbsp;' + formatTimeParts(diff),
id: config.connectionOverlayEolId,
cssClass: [config.componentOverlayClass, 'eol'].join(' '),
location: 0.25
}
]);
}
},
out: function(e){
let map = getMapObjectFromOverlayIcon(this);
let MapUtil = require('app/map/util');
let connections = MapUtil.searchConnectionsByScopeAndType(map, 'wh', ['wh_eol']);
for(let connection of connections){
connection.removeOverlay(config.connectionOverlayEolId);
}
}
}
}
};
/**
* get map overlay element by type e.g. timer/counter, info - overlay
* @param overlayType
* @returns {*}
*/
$.fn.getMapOverlay = function(overlayType){
let mapWrapperElement = $(this).parents('.' + config.mapWrapperClass);
let mapOverlay = null;
switch(overlayType){
case 'timer':
mapOverlay = mapWrapperElement.find('.' + config.mapOverlayTimerClass);
break;
case 'info':
mapOverlay = mapWrapperElement.find('.' + config.mapOverlayInfoClass);
break;
case 'local':
mapOverlay = mapWrapperElement.find('.' + config.overlayLocalClass);
break;
}
return mapOverlay;
};
/**
* draws the map update counter to the map overlay timer
* @param percent
* @param value
* @returns {*}
*/
$.fn.setMapUpdateCounter = function(percent, value){
let mapOverlayTimer = $(this);
// check if counter already exists
let counterChart = mapOverlayTimer.getMapCounter();
if(counterChart.length === 0){
// create new counter
counterChart = $('<div>', {
class: [Init.classes.pieChart.class, Init.classes.pieChart.pieChartMapCounterClass].join(' ')
}).attr('data-percent', percent).append(
$('<span>', {
text: value
})
);
mapOverlayTimer.append(counterChart);
// init counter
counterChart.initMapUpdateCounter();
// set tooltip
mapOverlayTimer.attr('data-placement', 'left');
mapOverlayTimer.attr('title', 'update counter');
mapOverlayTimer.tooltip();
}
return counterChart;
};
/**
* get the map counter chart from overlay
* @returns {JQuery|*|T|{}|jQuery}
*/
$.fn.getMapCounter = function(){
return $(this).find('.' + Init.classes.pieChart.pieChartMapCounterClass);
};
$.fn.getMapOverlayInterval = function(){
return $(this).getMapOverlay('timer').getMapCounter().data('interval');
};
/**
* start the map update counter or reset
*/
$.fn.startMapUpdateCounter = function(){
let mapOverlayTimer = $(this);
let counterChart = mapOverlayTimer.getMapCounter();
let maxSeconds = config.logTimerCount;
let counterChartLabel = counterChart.find('span');
let percentPerCount = 100 / maxSeconds;
// update counter
let updateChart = function(tempSeconds){
let pieChart = counterChart.data('easyPieChart');
if(pieChart !== undefined){
counterChart.data('easyPieChart').update( percentPerCount * tempSeconds);
}
counterChartLabel.text(tempSeconds);
};
// main timer function is called on any counter update
let timer = function(mapUpdateCounter){
// decrease timer
let currentSeconds = counterChart.data('currentSeconds');
currentSeconds--;
counterChart.data('currentSeconds', currentSeconds);
if(currentSeconds >= 0){
// update counter
updateChart(currentSeconds);
}else{
// hide counter and reset
clearInterval(mapUpdateCounter);
mapOverlayTimer.velocity('transition.whirlOut', {
duration: Init.animationSpeed.mapOverlay,
complete: function(){
counterChart.data('interval', false);
Util.getMapElementFromOverlay(mapOverlayTimer).trigger('pf:unlocked');
}
});
}
};
// get current seconds (in case the timer is already running)
let currentSeconds = counterChart.data('currentSeconds');
// start values for timer and chart
counterChart.data('currentSeconds', maxSeconds);
updateChart(maxSeconds);
if(
currentSeconds === undefined ||
currentSeconds < 0
){
// start timer
let mapUpdateCounter = setInterval(() => {
timer(mapUpdateCounter);
}, 1000);
// store counter interval
counterChart.data('interval', mapUpdateCounter);
// show overlay
if(mapOverlayTimer.is(':hidden')){
mapOverlayTimer.velocity('stop').velocity('transition.whirlIn', { duration: Init.animationSpeed.mapOverlay });
}
}
};
/**
* update (show/hide) a overlay icon in the "info"-overlay
* show/hide the overlay itself is no icons are visible
* @param option
* @param viewType
*/
$.fn.updateOverlayIcon = function(option, viewType){
let mapOverlayInfo = $(this);
let showOverlay = false;
let mapOverlayIconClass = options[option].class;
// look for the overlay icon that should be updated
let iconElement = mapOverlayInfo.find('.' + mapOverlayIconClass);
if(iconElement){
if(viewType === 'show'){
showOverlay = true;
// check "trigger" and mark as "active"
if(
options[option].trigger === 'active' ||
options[option].trigger === 'refresh'
){
iconElement.addClass('active');
}
// check if icon is not already visible
// -> prevents unnecessary "show" animation
if( !iconElement.data('visible') ){
// display animation for icon
iconElement.velocity({
opacity: [0.8, 0],
scale: [1, 0],
width: ['20px', 0],
height: ['20px', 0],
marginRight: ['10px', 0]
},{
duration: 240,
easing: 'easeInOutQuad'
});
iconElement.data('visible', true);
}
}else if(viewType === 'hide'){
// check if icon is not already visible
// -> prevents unnecessary "hide" animation
if(iconElement.data('visible')){
iconElement.removeClass('active').velocity('reverse');
iconElement.data('visible', false);
}
// check if there is any visible icon remaining
let visibleIcons = mapOverlayInfo.find('i:visible');
if(visibleIcons.length > 0){
showOverlay = true;
}
}
}
// show the entire overlay if there is at least one active icon
if(
showOverlay === true &&
mapOverlayInfo.is(':hidden')
){
// show overlay
mapOverlayInfo.velocity('stop').velocity('transition.whirlIn', { duration: Init.animationSpeed.mapOverlay });
}else if(
showOverlay === false &&
mapOverlayInfo.is(':visible')
){
// hide overlay
mapOverlayInfo.velocity('stop').velocity('transition.whirlOut', { duration: Init.animationSpeed.mapOverlay });
}
};
/**
* init all map overlays on a "parent" element
* @returns {*}
*/
$.fn.initMapOverlays = function(){
return this.each(function(){
let parentElement = $(this);
let mapOverlayTimer = $('<div>', {
class: [config.mapOverlayClass, config.mapOverlayTimerClass].join(' ')
});
parentElement.append(mapOverlayTimer);
// ------------------------------------------------------------------------------------
// add map overlay info. after scrollbar is initialized
let mapOverlayInfo = $('<div>', {
class: [config.mapOverlayClass, config.mapOverlayInfoClass].join(' ')
});
// add all overlay elements
for(let prop in options){
if(options.hasOwnProperty(prop)){
let icon = $('<i>', {
class: options[prop].iconClass.concat( ['pull-right', options[prop].class] ).join(' ')
}).attr('title', options[prop].title).tooltip({
placement: 'bottom',
container: 'body',
delay: 150
});
// add "hover" action for some icons
if(
options[prop].trigger === 'hover' ||
options[prop].trigger === 'refresh'
){
icon.hoverIntent(options[prop].hoverIntent);
}
// add "click" handler for some icons
if(options[prop].hasOwnProperty('onClick')){
icon.on('click', options[prop].onClick);
}
mapOverlayInfo.append(icon);
}
}
parentElement.append(mapOverlayInfo);
// reset map update timer
mapOverlayTimer.setMapUpdateCounter(100, config.logTimerCount);
});
};
});

View File

@@ -0,0 +1,892 @@
/**
* map overlay functions
*/
define([
'jquery',
'app/init',
'app/util',
'app/map/overlay/util',
'app/map/util'
], ($, Init, Util, MapOverlayUtil, MapUtil) => {
'use strict';
/**
* get map object (jsPlumb) from iconElement
* @param overlayIcon
* @returns {*}
*/
let getMapObjectFromOverlayIcon = overlayIcon => {
return MapUtil.getMapInstance(Util.getMapElementFromOverlay(overlayIcon).data('id'));
};
/**
* add/update endpoints with overlays from signature mapping
* @param endpoint
* @param labelData
*/
let updateEndpointOverlaySignatureLabel = (endpoint, labelData) => {
let labels = labelData.labels;
let names = labelData.names;
let overlay = endpoint.getOverlay(MapOverlayUtil.config.endpointOverlayId);
if(overlay instanceof jsPlumb.Overlays.Label){
// update existing overlay
if(
!labels.equalValues(overlay.getParameter('signatureLabels')) ||
!names.equalValues(overlay.getParameter('signatureNames'))
){
// update label only on label changes
overlay.setLabel(MapUtil.formatEndpointOverlaySignatureLabel(labels));
overlay.setParameter('fullSize', false);
overlay.setParameter('signatureLabels', labels);
overlay.setParameter('signatureNames', names);
overlay.updateClasses(labels.length ? 'small' : 'icon', labels.length ? 'icon' : 'small');
overlay.setLocation(MapUtil.getEndpointOverlaySignatureLocation(endpoint, labels));
}
}else{
// add new overlay
endpoint.addOverlay([
'Label',
{
label: MapUtil.formatEndpointOverlaySignatureLabel(labels),
id: MapOverlayUtil.config.endpointOverlayId,
cssClass: [MapOverlayUtil.config.componentOverlayClass, labels.length ? 'small' : 'icon'].join(' '),
location: MapUtil.getEndpointOverlaySignatureLocation(endpoint, labels),
events: {
toggleSize: function(fullSize){
let signatureNames = this.getParameter('signatureNames');
if(fullSize && !this.getParameter('fullSize') && signatureNames.length){
this.setLabel(this.getLabel() + '<br>' + '<span class="initialism">' + signatureNames.join(', ') + '</span>');
this.setParameter('fullSize', true);
}else if(this.getParameter('fullSize')){
this.setLabel(MapUtil.formatEndpointOverlaySignatureLabel(this.getParameter('signatureLabels')));
this.setParameter('fullSize', false);
}
}
},
parameters: {
fullSize: false,
signatureLabels: labels,
signatureNames: names
}
}
]);
}
};
/**
* get overlay parameters for connection overlay (type 'diamond' or 'arrow')
* @param overlayType
* @param direction
* @returns {{length: number, foldback: number, direction: number}}
*/
let getConnectionArrowOverlayParams = (overlayType, direction = 1) => {
switch(overlayType){
case 'arrow':
return {
length: 15,
direction: direction,
foldback: 0.8
};
default: // diamond
return {
length: 10,
direction: 1,
foldback: 2
};
}
};
/**
* add overlays to connections (signature based data)
* @param map
* @param connectionsData
*/
let updateInfoSignatureOverlays = (map, connectionsData) => {
let type = 'info_signature';
connectionsData = Util.arrayToObject(connectionsData);
map.batch(() => {
map.getAllConnections().forEach(connection => {
let connectionId = connection.getParameter('connectionId');
let sourceEndpoint = connection.endpoints[0];
let targetEndpoint = connection.endpoints[1];
let connectionData = connectionsData.hasOwnProperty(connectionId) ? connectionsData[connectionId] : undefined;
let signatureTypeData = MapUtil.getConnectionDataFromSignatures(connection, connectionData);
let sizeLockedBySignature = false;
if(connection.scope === 'wh'){
if(!connection.hasType(type)){
connection.addType(type);
}
let overlayArrow = connection.getOverlay(MapOverlayUtil.config.connectionOverlayArrowId);
// Arrow overlay needs to be cleared() (removed) if 'info_signature' gets removed!
// jsPlumb does not handle overlay updates for Arrow overlays... so we need to re-apply the the overlay manually
if(overlayArrow.path && !overlayArrow.path.isConnected){
connection.canvas.appendChild(overlayArrow.path);
}
// since there "could" be multiple sig labels on each endpoint,
// there can only one "primary label picked up for wormhole jump mass detection!
let primLabel;
let overlayType = 'diamond'; // not specified
let arrowDirection = 1;
if(connectionData && connectionData.signatures){
// signature data found for current connection
let sourceLabel = signatureTypeData.source.labels;
let targetLabel = signatureTypeData.target.labels;
// add arrow (connection) overlay that points from "XXX" => "K162" ----------------------------
if(
(sourceLabel.includes('K162') && targetLabel.includes('K162')) ||
(sourceLabel.length === 0 && targetLabel.length === 0) ||
(
sourceLabel.length > 0 && targetLabel.length > 0 &&
!sourceLabel.includes('K162') && !targetLabel.includes('K162')
)
){
// unknown direction -> show default 'diamond' overlay
overlayType = 'diamond';
}else if(
(sourceLabel.includes('K162')) ||
(sourceLabel.length === 0 && !targetLabel.includes('K162'))
){
// convert default arrow direction
overlayType = 'arrow';
arrowDirection = -1;
primLabel = targetLabel.find(label => label !== 'K162');
}else{
// default arrow direction is fine
overlayType = 'arrow';
primLabel = sourceLabel.find(label => label !== 'K162');
}
}
// class changes must be done on "connection" itself not on "overlayArrow"
// -> because Arrow might not be rendered to map at this point (if it does not exist already)
if(overlayType === 'arrow'){
connection.updateClasses(
MapOverlayUtil.config.connectionArrowOverlaySuccessClass,
MapOverlayUtil.config.connectionArrowOverlayDangerClass
);
}else{
connection.updateClasses(
MapOverlayUtil.config.connectionArrowOverlayDangerClass,
MapOverlayUtil.config.connectionArrowOverlaySuccessClass
);
}
overlayArrow.updateFrom(getConnectionArrowOverlayParams(overlayType, arrowDirection));
// update/add endpoint overlays -------------------------------------------------------------------
updateEndpointOverlaySignatureLabel(sourceEndpoint, signatureTypeData.source);
updateEndpointOverlaySignatureLabel(targetEndpoint, signatureTypeData.target);
// fix/overwrite existing jump mass connection type -----------------------------------------------
// if a connection type for "jump mass" (e.g. S, M, L, XL) is set for this connection
// we should check/compare it with the current primary signature label from signature mapping
// and change it if necessary
if(Init.wormholes.hasOwnProperty(primLabel)){
// connection size from mapped signature
sizeLockedBySignature = true;
let wormholeData = Object.assign({}, Init.wormholes[primLabel]);
// get 'connection mass type' from wormholeData
let massType = Util.getObjVal(wormholeData, 'size.type');
if(massType && !connection.hasType(massType)){
MapOverlayUtil.getMapOverlay(connection.canvas, 'timer').startMapUpdateCounter();
MapUtil.setConnectionJumpMassType(connection, wormholeData.size.type);
MapUtil.markAsChanged(connection);
}
}
}else{
// connection is not 'wh' scope
if(connection.hasType(type)){
connection.removeType(type);
}
}
// lock/unlock connection for manual size changes (from contextmenu)
connection.setParameter('sizeLocked', sizeLockedBySignature);
});
});
};
/**
* format json object with "time parts" into string
* @param parts
* @returns {string}
*/
let formatTimeParts = parts => {
let label = '';
if(parts.days){
label += parts.days + 'd ';
}
label += ('00' + parts.hours).slice(-2);
label += ':' + ('00' + parts.min).slice(-2);
return label;
};
/**
* hide default icon and replace it with "loading" icon
* @param iconElement
*/
let showLoading = iconElement => {
iconElement = $(iconElement);
let dataName = 'default-icon';
let defaultIconClass = iconElement.data(dataName);
// get default icon class
if( !defaultIconClass ){
// index 0 == 'fa-fw', index 1 == IconName
defaultIconClass = $(iconElement).attr('class').match(/\bfa-\S*/g)[1];
iconElement.data(dataName, defaultIconClass);
}
iconElement.toggleClass( defaultIconClass + ' fa-sync fa-spin');
};
/**
* hide "loading" icon and replace with default icon
* @param iconElement
*/
let hideLoading = iconElement => {
iconElement = $(iconElement);
let dataName = 'default-icon';
let defaultIconClass = iconElement.data(dataName);
iconElement.toggleClass( defaultIconClass + ' fa-sync fa-spin');
};
/**
* get overlay icon from e.g. mapElement
* @param element
* @param iconClass
* @param overlayType
* @returns {*}
*/
let getOverlayIcon = (element, iconClass, overlayType = 'info') => {
return MapOverlayUtil.getMapOverlay(element, overlayType).find('.' + iconClass);
};
/**
* showInfoSignatureOverlays
* -> used by "refresh" overlays (hover) AND/OR initial menu trigger
*/
let showInfoSignatureOverlays = mapElement => {
let mapId = mapElement.data('id');
let map = MapUtil.getMapInstance(mapId);
let mapData = Util.getCurrentMapData(mapId);
let connectionsData = Util.getObjVal(mapData, 'data.connections');
if(connectionsData){
let overlayIcon = getOverlayIcon(mapElement, options.mapSignatureOverlays.class);
showLoading(overlayIcon);
updateInfoSignatureOverlays(map, connectionsData);
hideLoading(overlayIcon);
}
};
/**
* hideInfoSignatureOverlays
* -> see showInfoSignatureOverlays()
*/
let hideInfoSignatureOverlays = mapElement => {
let mapId = mapElement.data('id');
let map = MapUtil.getMapInstance(mapId);
let type = 'info_signature';
map.batch(() => {
map.getAllConnections().forEach(connection => {
let overlayArrow = connection.getOverlay(MapOverlayUtil.config.connectionOverlayArrowId);
if(overlayArrow){
overlayArrow.cleanup();
}
if(connection.hasType(type)){
connection.removeType(type, {}, true);
}
});
map.selectEndpoints().removeOverlay(MapOverlayUtil.config.endpointOverlayId);
});
};
/**
* Overlay options (all available map options shown in overlay)
* "active": (active || hover) indicated whether an icon/option
* is marked as "active".
* "active": Makes icon active when visible
* "hover": Make icon active on hover
*/
let options = {
filter: {
title: 'active filter',
trigger: 'active',
class: 'pf-map-overlay-filter',
iconClass: ['fas', 'fa-fw', 'fa-filter'],
onClick: function(e){
// clear all filter
let mapElement = Util.getMapElementFromOverlay(this);
let map = getMapObjectFromOverlayIcon(this);
MapUtil.storeLocalData('map', mapElement.data('id'), 'filterScopes', []);
MapUtil.filterMapByScopes(map, []);
}
},
mapSnapToGrid: {
title: 'active grid',
trigger: 'active',
class: 'pf-map-overlay-grid',
iconClass: ['fas', 'fa-fw', 'fa-th']
},
mapMagnetizer: {
title: 'active magnetizer',
trigger: 'active',
class: 'pf-map-overlay-magnetizer',
iconClass: ['fas', 'fa-fw', 'fa-magnet']
},
systemRegion: {
title: 'show regions',
trigger: 'hover',
class: 'pf-map-overlay-region',
iconClass: ['fas', 'fa-fw', 'fa-tags'],
hoverIntent: {
over: function(e){
let mapElement = Util.getMapElementFromOverlay(this);
mapElement.find('.' + MapOverlayUtil.config.systemHeadClass).each(function(){
let systemHead = $(this);
// init popover if not already exists
if(!systemHead.data('bs.popover')){
let system = systemHead.parent();
systemHead.popover({
placement: 'right',
html: true,
trigger: 'manual',
container: mapElement,
title: false,
content: Util.getSystemRegionTable(
system.data('region'),
system.data('faction') || null
)
});
}
systemHead.setPopoverSmall();
systemHead.popover('show');
});
},
out: function(e){
let mapElement = Util.getMapElementFromOverlay(this);
mapElement.find('.' + MapOverlayUtil.config.systemHeadClass).popover('hide');
}
}
},
mapSignatureOverlays: {
title: 'active signature overlays',
trigger: 'active',
class: 'pf-map-overlay-endpoint',
iconClass: ['fas', 'fa-fw', 'fa-link']
},
mapCompact: {
title: 'compact layout',
trigger: 'active',
class: 'pf-map-overlay-compact',
iconClass: ['fas', 'fa-fw', 'fa-compress']
},
connection: {
title: 'WH data',
trigger: 'hover',
class: 'pf-map-overlay-connection-wh',
iconClass: ['fas', 'fa-fw', 'fa-fighter-jet'],
hoverIntent: {
over: function(e){
let map = getMapObjectFromOverlayIcon(this);
let connections = MapUtil.searchConnectionsByScopeAndType(map, 'wh');
let serverDate = Util.getServerTime();
// show connection overlays -----------------------------------------------------------------------
for(let connection of connections){
let createdTimestamp = connection.getParameter('created');
let updatedTimestamp = connection.getParameter('updated');
let createdDate = Util.convertTimestampToServerTime(createdTimestamp);
let updatedDate = Util.convertTimestampToServerTime(updatedTimestamp);
let createdDiff = Util.getTimeDiffParts(createdDate, serverDate);
let updatedDiff = Util.getTimeDiffParts(updatedDate, serverDate);
// format overlay label
let labels = [
formatTimeParts(createdDiff) + '&nbsp;<i class="fas fa-fw fa-plus-square"></i>',
formatTimeParts(updatedDiff) + '&nbsp;<i class="fas fa-fw fa-pen-square"></i>'
];
// add label overlay --------------------------------------------------------------------------
connection.addOverlay([
'Label',
{
label: labels.join('<br>'),
id: MapOverlayUtil.config.connectionOverlayWhId,
cssClass: [MapOverlayUtil.config.componentOverlayClass, 'small', 'text-right'].join(' '),
location: 0.35
}
]);
}
},
out: function(e){
let map = getMapObjectFromOverlayIcon(this);
let connections = MapUtil.searchConnectionsByScopeAndType(map, 'wh');
for(let connection of connections){
connection.removeOverlay(MapOverlayUtil.config.connectionOverlayWhId);
}
}
}
},
connectionEol: {
title: 'EOL timer',
trigger: 'hover',
class: 'pf-map-overlay-connection-eol',
iconClass: ['fas', 'fa-fw', 'fa-hourglass-end'],
hoverIntent: {
over: function(e){
let map = getMapObjectFromOverlayIcon(this);
let connections = MapUtil.searchConnectionsByScopeAndType(map, 'wh', ['wh_eol']);
let serverDate = Util.getServerTime();
for(let connection of connections){
let eolTimestamp = connection.getParameter('eolUpdated');
let eolDate = Util.convertTimestampToServerTime(eolTimestamp);
let diff = Util.getTimeDiffParts(eolDate, serverDate);
connection.addOverlay([
'Label',
{
label: '<i class="fas fa-fw fa-hourglass-end"></i>&nbsp;' + formatTimeParts(diff),
id: MapOverlayUtil.config.connectionOverlayEolId,
cssClass: [MapOverlayUtil.config.componentOverlayClass, 'eol'].join(' '),
location: 0.25
}
]);
}
},
out: function(e){
let map = getMapObjectFromOverlayIcon(this);
let connections = MapUtil.searchConnectionsByScopeAndType(map, 'wh', ['wh_eol']);
for(let connection of connections){
connection.removeOverlay(MapOverlayUtil.config.connectionOverlayEolId);
}
}
}
}
};
/**
* draws the map update counter to the map overlay timer
* @param mapOverlayTimer
* @param percent
* @param value
* @returns {*}
*/
let setMapUpdateCounter = (mapOverlayTimer, percent, value) => {
// check if counter already exists
let counterChart = MapOverlayUtil.getMapCounter(mapOverlayTimer);
if(counterChart.length === 0){
// create new counter
counterChart = $('<div>', {
class: [Init.classes.pieChart.class, Init.classes.pieChart.pieChartMapCounterClass].join(' ')
}).attr('data-percent', percent).append(
$('<span>', {
text: value
})
);
mapOverlayTimer.append(counterChart);
// init counter
counterChart.initMapUpdateCounter();
// set tooltip
mapOverlayTimer.attr('data-placement', 'left');
mapOverlayTimer.attr('title', 'update counter');
mapOverlayTimer.tooltip();
}
return counterChart;
};
/**
* start the map update counter or reset
*/
$.fn.startMapUpdateCounter = function(){
let mapOverlayTimer = $(this);
let counterChart = MapOverlayUtil.getMapCounter(mapOverlayTimer);
let maxSeconds = MapOverlayUtil.config.logTimerCount;
let counterChartLabel = counterChart.find('span');
let percentPerCount = 100 / maxSeconds;
// update counter
let updateChart = tempSeconds => {
let pieChart = counterChart.data('easyPieChart');
if(pieChart !== undefined){
counterChart.data('easyPieChart').update( percentPerCount * tempSeconds);
}
counterChartLabel.text(tempSeconds);
};
// main timer function is called on any counter update
let timer = mapUpdateCounter => {
// decrease timer
let currentSeconds = counterChart.data('currentSeconds');
currentSeconds--;
counterChart.data('currentSeconds', currentSeconds);
if(currentSeconds >= 0){
// update counter
updateChart(currentSeconds);
}else{
// hide counter and reset
clearInterval(mapUpdateCounter);
mapOverlayTimer.velocity('transition.whirlOut', {
duration: Init.animationSpeed.mapOverlay,
complete: function(){
counterChart.data('interval', false);
Util.getMapElementFromOverlay(mapOverlayTimer).trigger('pf:unlocked');
}
});
}
};
// get current seconds (in case the timer is already running)
let currentSeconds = counterChart.data('currentSeconds');
// start values for timer and chart
counterChart.data('currentSeconds', maxSeconds);
updateChart(maxSeconds);
if(
currentSeconds === undefined ||
currentSeconds < 0
){
// start timer
let mapUpdateCounter = setInterval(() => {
timer(mapUpdateCounter);
}, 1000);
// store counter interval
counterChart.data('interval', mapUpdateCounter);
// show overlay
if(mapOverlayTimer.is(':hidden')){
mapOverlayTimer.velocity('stop').velocity('transition.whirlIn', { duration: Init.animationSpeed.mapOverlay });
}
}
};
/**
* update (show/hide) a overlay icon in the "info"-overlay
* show/hide the overlay itself is no icons are visible
* @param option
* @param viewType
*/
$.fn.updateOverlayIcon = function(option, viewType){
let mapOverlayInfo = $(this);
let showOverlay = false;
let mapOverlayIconClass = options[option].class;
// look for the overlay icon that should be updated
let iconElement = mapOverlayInfo.find('.' + mapOverlayIconClass);
if(iconElement){
if(viewType === 'show'){
showOverlay = true;
// check "trigger" and mark as "active"
if(
options[option].trigger === 'active' ||
options[option].trigger === 'refresh'
){
iconElement.addClass('active');
}
// check if icon is not already visible
// -> prevents unnecessary "show" animation
if( !iconElement.data('visible') ){
// display animation for icon
iconElement.velocity({
opacity: [0.8, 0],
scale: [1, 0],
width: ['20px', 0],
height: ['20px', 0],
marginRight: ['10px', 0]
},{
duration: 240,
easing: 'easeInOutQuad'
});
iconElement.data('visible', true);
}
}else if(viewType === 'hide'){
// check if icon is not already visible
// -> prevents unnecessary "hide" animation
if(iconElement.data('visible')){
iconElement.removeClass('active').velocity('reverse');
iconElement.data('visible', false);
}
// check if there is any visible icon remaining
let visibleIcons = mapOverlayInfo.find('i:visible');
if(visibleIcons.length > 0){
showOverlay = true;
}
}
}
// show the entire overlay if there is at least one active icon
if(
showOverlay === true &&
mapOverlayInfo.is(':hidden')
){
// show overlay
mapOverlayInfo.velocity('stop').velocity('transition.whirlIn', { duration: Init.animationSpeed.mapOverlay });
}else if(
showOverlay === false &&
mapOverlayInfo.is(':visible')
){
// hide overlay
mapOverlayInfo.velocity('stop').velocity('transition.whirlOut', { duration: Init.animationSpeed.mapOverlay });
}
};
/**
* update map zoom overlay information
* @param map
*/
let updateZoomOverlay = map => {
let zoom = map.getZoom();
let zoomPercent = Math.round(zoom * 1000) / 10;
let zoomOverlay = MapOverlayUtil.getMapOverlay(map.getContainer(), 'zoom');
let zoomValue = zoomOverlay.find('.' + MapOverlayUtil.config.zoomOverlayValueClass);
let zoomUp = zoomOverlay.find('.' + MapOverlayUtil.config.zoomOverlayUpClass);
let zoomDown = zoomOverlay.find('.' + MapOverlayUtil.config.zoomOverlayDownClass);
zoomValue.toggleClass('active', zoom !== 1).text(zoomPercent);
zoomUp.toggleClass('disabled', zoom >= MapUtil.config.zoomMax);
zoomDown.toggleClass('disabled', zoom <= MapUtil.config.zoomMin);
};
/**
* map debug overlays for connections/endpoints
* -> requires manual added "debug" GET param to URL
* @param map
*/
let initMapDebugOverlays = map => {
let url = new URL(window.location.href);
if(url.searchParams.has('debug')){
let mapContainer = $(map.getContainer());
// debug map overlays for connection/endpoints
mapContainer.on('mouseover', '.jtk-connector', function(e){
e.stopPropagation();
if(e.target.classList.contains('jtk-connector-outline')){
let connection = e.currentTarget._jsPlumb;
// show debug overlay only if there is no active debug
if(!connection.getOverlay(MapOverlayUtil.config.debugOverlayId)){
// find nearby connections
let connections = [];
let endpoints = [];
let hasComponentId = id => {
return component => component.id === id;
};
for(let endpoint of connection.endpoints){
let connectionsInfo = map.anchorManager.getConnectionsFor(endpoint.elementId);
for(let connectionInfo of connectionsInfo){
if(!connections.some(hasComponentId(connectionInfo[0].id))){
connections.push(connectionInfo[0]);
for(let endpointTemp of connectionInfo[0].endpoints){
if(!endpoints.some(hasComponentId(endpointTemp.id))){
endpoints.push(endpointTemp);
}
}
}
}
}
let createConnectionOverlay = connection => {
let data = MapUtil.getDataByConnection(connection);
let html = '<div><table>';
html += '<tr><td>' + connection.id + '</td><td class="text-right">' + data.id + '</td></tr>';
html += '<tr><td>Scope:</td><td class="text-right">' + data.scope + '</td></tr>';
html += '<tr><td>Type:</td><td class="text-right">' + data.type.toString() + '</td></tr>';
html += '</table></div>';
return $(html).on('click', function(){
console.info(connection);
});
};
for(let connection of connections){
connection.addOverlay([
'Custom',
{
id: MapOverlayUtil.config.debugOverlayId,
cssClass: [MapOverlayUtil.config.componentOverlayClass, 'debug'].join(' '),
create: createConnectionOverlay
}
]);
}
let createEndpointOverlay = endpoint => {
let types = MapUtil.filterDefaultTypes(endpoint.getType());
let html = '<div><table>';
html += '<tr><td>' + endpoint.id + '</td><td class="text-right"></td></tr>';
html += '<tr><td>Scope:</td><td class="text-right">' + endpoint.scope + '</td></tr>';
html += '<tr><td>Type:</td><td class="text-right">' + types.toString() + '</td></tr>';
html += '</table></div>';
return $(html).on('click', function(){
console.info(endpoint);
});
};
for(let endpoint of endpoints){
endpoint.addOverlay([
'Custom',
{
id: MapOverlayUtil.config.debugOverlayId,
cssClass: [MapOverlayUtil.config.componentOverlayClass, 'debug'].join(' '),
create: createEndpointOverlay
}
]);
}
}
}
});
mapContainer.on('mouseover', function(e){
e.stopPropagation();
if(e.target === e.currentTarget){
map.select().removeOverlay(MapOverlayUtil.config.debugOverlayId);
map.selectEndpoints().removeOverlay(MapOverlayUtil.config.debugOverlayId);
}
});
}
};
/**
* init map zoom overlay
* @returns {jQuery}
*/
let initZoomOverlay = () => {
let clickHandler = e => {
let zoomIcon = $(e.target);
if(!zoomIcon.hasClass('disabled')){
let zoomAction = zoomIcon.attr('data-zoom');
let map = getMapObjectFromOverlayIcon(zoomIcon);
MapUtil.changeZoom(map, zoomAction);
}
};
return $('<div>', {
class: [MapOverlayUtil.config.mapOverlayClass, MapOverlayUtil.config.mapOverlayZoomClass].join(' ')
}).append(
$('<i>', {
class: ['fas', 'fa-caret-up', MapOverlayUtil.config.zoomOverlayUpClass].join(' ')
}).attr('data-zoom', 'up').on('click', clickHandler),
$('<span>', {
class: MapOverlayUtil.config.zoomOverlayValueClass,
text: '100'
}),
$('<i>', {
class: ['fas', 'fa-caret-down', MapOverlayUtil.config.zoomOverlayDownClass].join(' ')
}).attr('data-zoom', 'down').on('click', clickHandler)
);
};
/**
* init all map overlays on a "parent" element
* @returns {*}
*/
$.fn.initMapOverlays = function(){
return this.each(function(){
let parentElement = $(this);
let mapOverlayTimer = $('<div>', {
class: [MapOverlayUtil.config.mapOverlayClass, MapOverlayUtil.config.mapOverlayTimerClass].join(' ')
});
parentElement.append(mapOverlayTimer);
parentElement.append(initZoomOverlay());
// --------------------------------------------------------------------------------------------------------
// add map overlay info. after scrollbar is initialized
let mapOverlayInfo = $('<div>', {
class: [MapOverlayUtil.config.mapOverlayClass, MapOverlayUtil.config.mapOverlayInfoClass].join(' ')
});
// add all overlay elements
for(let prop in options){
if(options.hasOwnProperty(prop)){
let icon = $('<i>', {
class: options[prop].iconClass.concat( ['pull-right', options[prop].class] ).join(' ')
}).attr('title', options[prop].title).tooltip({
placement: 'bottom',
container: 'body',
delay: 150
});
// add "hover" action for some icons
if(
options[prop].trigger === 'hover' ||
options[prop].trigger === 'refresh'
){
icon.hoverIntent(options[prop].hoverIntent);
}
// add "click" handler for some icons
if(options[prop].hasOwnProperty('onClick')){
icon.on('click', options[prop].onClick);
}
mapOverlayInfo.append(icon);
}
}
parentElement.append(mapOverlayInfo);
// reset map update timer
setMapUpdateCounter(mapOverlayTimer, 100, MapOverlayUtil.config.logTimerCount);
});
};
return {
showInfoSignatureOverlays: showInfoSignatureOverlays,
hideInfoSignatureOverlays: hideInfoSignatureOverlays,
updateZoomOverlay: updateZoomOverlay,
initMapDebugOverlays: initMapDebugOverlays
};
});

View File

@@ -0,0 +1,97 @@
/**
* map overlay util functions
*/
define([
'jquery',
'app/init',
'app/util',
'app/map/util'
], ($, Init, Util) => {
'use strict';
let config = {
logTimerCount: 3, // map log timer in seconds
mapWrapperClass: 'pf-map-wrapper', // wrapper div (scrollable)
// map overlays sections
mapOverlayClass: 'pf-map-overlay', // class for all map overlays
mapOverlayTimerClass: 'pf-map-overlay-timer', // class for map overlay timer e.g. map timer
mapOverlayZoomClass: 'pf-map-overlay-zoom', // class for map overlay zoom
mapOverlayInfoClass: 'pf-map-overlay-info', // class for map overlay info e.g. map info
overlayLocalClass: 'pf-map-overlay-local', // class for map overlay "local" table
// system
systemHeadClass: 'pf-system-head', // class for system head
// connection overlay ids (they are not unique like CSS ids!)
connectionOverlayArrowId: 'pf-map-connection-arrow-overlay', // connection Arrows overlay ID (jsPlumb)
connectionOverlayWhId: 'pf-map-connection-wh-overlay', // connection WH overlay ID (jsPlumb)
connectionOverlayEolId: 'pf-map-connection-eol-overlay', // connection EOL overlay ID (jsPlumb)
debugOverlayId: 'pf-map-debug-overlay', // connection/endpoint overlay ID (jsPlumb)
endpointOverlayId: 'pf-map-endpoint-overlay', // endpoint overlay ID (jsPlumb)
// connection overlay classes classes
componentOverlayClass: 'pf-map-component-overlay', // class for "normal size" overlay
connectionArrowOverlaySuccessClass: 'pf-map-connection-arrow-overlay-success', // class for "success" arrow overlays
connectionArrowOverlayDangerClass: 'pf-map-connection-arrow-overlay-danger', // class for "danger" arrow overlays
// zoom overlay
zoomOverlayUpClass: 'pf-zoom-overlay-up',
zoomOverlayDownClass: 'pf-zoom-overlay-down',
zoomOverlayValueClass: 'pf-zoom-overlay-value'
};
/**
* get map overlay element by type e.g. timer/counter, info - overlay
* @param element
* @param overlayType
* @returns {null}
*/
let getMapOverlay = (element, overlayType) => {
let mapWrapperElement = $(element).parents('.' + config.mapWrapperClass);
let mapOverlay = null;
switch(overlayType){
case 'timer':
mapOverlay = mapWrapperElement.find('.' + config.mapOverlayTimerClass);
break;
case 'info':
mapOverlay = mapWrapperElement.find('.' + config.mapOverlayInfoClass);
break;
case 'zoom':
mapOverlay = mapWrapperElement.find('.' + config.mapOverlayZoomClass);
break;
case 'local':
mapOverlay = mapWrapperElement.find('.' + config.overlayLocalClass);
break;
}
return mapOverlay;
};
/**
* get the map counter chart from overlay
* @param element
* @returns {jQuery}
*/
let getMapCounter = element => $(element).find('.' + Init.classes.pieChart.pieChartMapCounterClass);
/**
* get interval value from map timer overlay
* @param element
* @returns {*}
*/
let getMapOverlayInterval = element => getMapCounter(getMapOverlay(element, 'timer')).data('interval');
return {
config: config,
getMapOverlay: getMapOverlay,
getMapCounter: getMapCounter,
getMapOverlayInterval: getMapOverlayInterval
};
});

View File

@@ -34,8 +34,9 @@ define([
},
advanced: {
autoUpdateTimeout: 120, // auto-update timeout (default: 60)
updateOnContentResize: true,
autoExpandHorizontalScroll: true,
autoExpandHorizontalScroll: false, // on resize css scale() scroll content should not change
//autoExpandHorizontalScroll: 2,
autoScrollOnFocus: 'div',
},
@@ -72,25 +73,24 @@ define([
/**
* scroll to a specific position on map
* demo: http://manos.malihu.gr/repository/custom-scrollbar/demo/examples/scrollTo_demo.html
* @param scrollWrapper
* @param position
* @param options
*/
$.fn.scrollToPosition = function(position){
return this.each(function(){
$(this).mCustomScrollbar('scrollTo', position);
});
let scrollToPosition = (scrollWrapper, position, options) => {
$(scrollWrapper).mCustomScrollbar('scrollTo', position, options);
};
/**
* scroll to a specific system on map
* -> subtract some offset for tooltips/connections
* @param scrollWrapper
* @param position
* @returns {*}
* @param options
*/
$.fn.scrollToSystem = function(position){
let scrollToSystem = (scrollWrapper, position, options) => {
position = getOffsetPosition(position, {x: -15, y: -35});
return this.each(function(){
$(this).mCustomScrollbar('scrollTo', position);
});
scrollToPosition(scrollWrapper, position, options);
};
/**
@@ -106,4 +106,9 @@ define([
y: Math.max(0, position.y + offset.y)
};
};
return {
scrollToPosition: scrollToPosition,
scrollToSystem: scrollToSystem
};
});

View File

@@ -9,8 +9,9 @@ define([
'app/util',
'bootbox',
'app/map/util',
'app/map/layout'
], ($, Init, Util, bootbox, MapUtil, Layout) => {
'app/map/layout',
'app/map/magnetizing'
], ($, Init, Util, bootbox, MapUtil, Layout, Magnetizer) => {
'use strict';
let config = {
@@ -39,6 +40,7 @@ define([
dialogSystemSectionInfoId: 'pf-system-dialog-section-info', // id for "info" section element
dialogSystemSectionInfoStatusId: 'pf-system-dialog-section-info-status', // id for "status" message in "info" element
dialogSystemAliasId: 'pf-system-dialog-alias', // id for "alias" static element
dialogSystemSignaturesId: 'pf-system-dialog-signatures', // id for "signatures" count static element
dialogSystemDescriptionId: 'pf-system-dialog-description', // id for "description" static element
dialogSystemCreatedId: 'pf-system-dialog-created', // id for "created" static element
dialogSystemUpdatedId: 'pf-system-dialog-updated', // id for "updated" static element
@@ -84,6 +86,7 @@ define([
let statusId = false; // -> no value change
let alias = labelEmpty;
let signaturesCount = 0;
let description = labelEmpty;
let createdTime = labelUnknown;
let updatedTime = labelUnknown;
@@ -95,6 +98,7 @@ define([
info = labelExist;
statusId = parseInt(Util.getObjVal(systemData, 'status.id')) || statusId;
alias = systemData.alias.length ? Util.htmlEncode(systemData.alias) : alias;
signaturesCount = (Util.getObjVal(systemData, 'signatures') || []).length;
description = systemData.description.length ? systemData.description : description;
let dateCreated = new Date(systemData.created.created * 1000);
@@ -116,6 +120,7 @@ define([
dialogElement.find('#' + config.dialogSystemStatusSelectId).val(statusId).trigger('change');
}
dialogElement.find('#' + config.dialogSystemAliasId).html(alias);
dialogElement.find('#' + config.dialogSystemSignaturesId).toggleClass('txt-color-green', signaturesCount > 0).html(signaturesCount);
dialogElement.find('#' + config.dialogSystemDescriptionId).html(description);
dialogElement.find('#' + config.dialogSystemCreatedId).html('<i class="fas fa-fw fa-plus"></i>&nbsp' + createdTime);
dialogElement.find('#' + config.dialogSystemUpdatedId).html('<i class="fas fa-fw fa-pen"></i>&nbsp' + updatedTime);
@@ -172,22 +177,29 @@ define([
sectionInfoId: config.dialogSystemSectionInfoId,
sectionInfoStatusId: config.dialogSystemSectionInfoStatusId,
aliasId: config.dialogSystemAliasId,
signaturesId: config.dialogSystemSignaturesId,
descriptionId: config.dialogSystemDescriptionId,
createdId: config.dialogSystemCreatedId,
updatedId: config.dialogSystemUpdatedId,
statusData: statusData
};
// set current position as "default" system to add ------------------------------------------------------------
let currentCharacterLog = Util.getCurrentCharacterLog();
// check for pre-selected system ------------------------------------------------------------------------------
let systemData;
if(options.systemData){
systemData = options.systemData;
}else{
// ... check for current active system (characterLog) -----------------------------------------------------
let currentCharacterLog = Util.getCurrentCharacterLog();
if(currentCharacterLog !== false){
// set system from 'characterLog' data as pre-selected system
systemData = Util.getObjVal(currentCharacterLog, 'system');
}
}
if(
currentCharacterLog !== false &&
mapSystemIds.indexOf( currentCharacterLog.system.id ) === -1
){
// current system is NOT already on this map
// set current position as "default" system to add
data.currentSystem = currentCharacterLog.system;
// check if pre-selected system is NOT already on this map
if(mapSystemIds.indexOf(Util.getObjVal(systemData, 'id')) === -1){
data.currentSystem = systemData;
}
requirejs(['text!templates/dialog/system.html', 'mustache'], (template, Mustache) => {
@@ -234,7 +246,7 @@ define([
// get new position
newPosition = calculateNewSystemPosition(sourceSystem);
}else{
}else if(options.position){
// check mouse cursor position (add system to map)
newPosition = {
x: options.position.x,
@@ -417,7 +429,7 @@ define([
system.setSystemRally(1, {
poke: Boolean(formData.pokeDesktop)
});
system.markAsChanged();
MapUtil.markAsChanged(system);
// send poke data to server
sendPoke(formData, {
@@ -637,7 +649,7 @@ define([
* @param system
* @returns {string}
*/
let getSystemTooltipPlacement = (system) => {
let getSystemTooltipPlacement = system => {
let offsetParent = system.parent().offset();
let offsetSystem = system.offset();
@@ -651,7 +663,7 @@ define([
* @param systems
* @param callback function
*/
let deleteSystems = (map, systems = [], callback = (systems) => {}) => {
let deleteSystems = (map, systems = [], callback = systems => {}) => {
let mapContainer = $( map.getContainer() );
let systemIds = systems.map(system => $(system).data('id'));
@@ -699,9 +711,11 @@ define([
$(tabContentElement).trigger('pf:removeSystemModules');
}
// remove endpoints and their connections
// do not fire a "connectionDetached" event
map.detachAllConnections(system, {fireEvent: false});
// remove connections do not fire a "connectionDetached" event
map.deleteConnectionsForElement(system, {fireEvent: false});
// unregister from "magnetizer"
Magnetizer.removeElement(system.data('mapid'), system[0]);
// destroy tooltip/popover
system.toggleSystemTooltip('destroy', {});
@@ -723,7 +737,6 @@ define([
let calculateNewSystemPosition = sourceSystem => {
let mapContainer = sourceSystem.parent();
let grid = [MapUtil.config.mapSnapToGridDimension, MapUtil.config.mapSnapToGridDimension];
let x = 0;
let y = 0;
@@ -753,12 +766,7 @@ define([
y = currentY + config.newSystemOffset.y;
}
let newPosition = {
x: x,
y: y
};
return newPosition;
return {x: x, y: y};
};
/**
@@ -767,7 +775,7 @@ define([
* @param data
* @returns {*}
*/
let getHeadInfoElement = (data) => {
let getHeadInfoElement = data => {
let headInfo = null;
let headInfoLeft = [];
let headInfoRight = [];

File diff suppressed because it is too large Load Diff

View File

@@ -4,13 +4,9 @@
define([
'app/util'
], function(Util){
], (Util) => {
'use strict';
let config = {
};
let sharedWorker = null;
let MsgWorker = null;
let characterId = null;
@@ -29,17 +25,13 @@ define([
* get SharedWorker Script path
* @returns {string}
*/
let getWorkerScript = () => {
return '/public/js/' + Util.getVersion() + '/app/worker/map.js';
};
let getWorkerScript = () => '/public/js/' + Util.getVersion() + '/app/worker/map.js';
/**
* get path to message object
* @returns {string}
*/
let getMessageWorkerObjectPath = () => {
return '/public/js/' + Util.getVersion() + '/app/worker/message.js';
};
let getMessageWorkerObjectPath = () => '/public/js/' + Util.getVersion() + '/app/worker/message.js';
/**
* init (connect) WebSocket within SharedWorker
@@ -51,14 +43,14 @@ define([
characterId: characterId,
});
sharedWorker.port.postMessage(MsgWorkerInit);
sendMessage(MsgWorkerInit);
};
/**
* init (start/connect) to "SharedWorker"
* init (start/connect) to "SharedWorker" thread
* -> set worker events
*/
let init = (config) => {
let init = config => {
// set characterId that is connected with this SharedWorker PORT
characterId = parseInt(config.characterId);
@@ -67,9 +59,9 @@ define([
MsgWorker = window.MsgWorker;
// start/connect to "SharedWorker"
sharedWorker = new SharedWorker( getWorkerScript(), getMessageWorkerObjectPath() );
sharedWorker = new SharedWorker(getWorkerScript(), getMessageWorkerObjectPath());
sharedWorker.port.addEventListener('message', (e) => {
sharedWorker.port.addEventListener('message', e => {
let MsgWorkerMessage = e.data;
Object.setPrototypeOf(MsgWorkerMessage, MsgWorker.prototype);
@@ -90,7 +82,7 @@ define([
}
}, false);
sharedWorker.onerror = (e) => {
sharedWorker.onerror = e => {
// could not connect to SharedWorker script -> send error back
let MsgWorkerError = new MsgWorker('sw:error');
MsgWorkerError.meta({
@@ -111,17 +103,52 @@ define([
});
};
/**
* send data to "SharedWorker" thread
* @param task
* @param data
*/
let send = (task, data) => {
let MsgWorkerSend = new MsgWorker('ws:send');
MsgWorkerSend.task(task);
MsgWorkerSend.data(data);
sharedWorker.port.postMessage(MsgWorkerSend);
sendMessage(MsgWorkerSend);
};
/**
* send close port task to "SharedWorker" thread
* -> this removes the port from its port collection and closes it
*/
let close = () => {
// check if MsgWorker is available (SharedWorker was initialized)
if(MsgWorker){
let MsgWorkerClose = new MsgWorker('sw:closePort');
MsgWorkerClose.task('unsubscribe');
sendMessage(MsgWorkerClose);
}
};
/**
*
* @param {window.MsgWorker} MsgWorkerSend
*/
let sendMessage = MsgWorkerSend => {
if(sharedWorker instanceof SharedWorker){
if(MsgWorkerSend instanceof window.MsgWorker){
sharedWorker.port.postMessage(MsgWorkerSend);
}else{
console.error('MsgWorkerSend must be instance of window.MsgWorker');
}
}else{
console.error('SharedWorker thread not found');
}
};
return {
getWebSocketURL: getWebSocketURL,
init: init,
send: send
send: send,
close: close
};
});

View File

@@ -6,14 +6,13 @@ define([
'jquery',
'app/init',
'app/util',
'app/render',
'app/logging',
'app/page',
'app/map/worker',
'app/module_map',
'app/key',
'app/ui/form_element'
], ($, Init, Util, Render, Logging, Page, MapWorker, ModuleMap) => {
], ($, Init, Util, Logging, Page, MapWorker, ModuleMap) => {
'use strict';
@@ -39,7 +38,7 @@ define([
Util.initDefaultEditableConfig();
// load page
$('body').loadPageStructure().setGlobalShortcuts();
Page.loadPageStructure();
// show app information in browser console
Util.showVersionInfo();
@@ -121,6 +120,25 @@ define([
*/
let initData = () => {
/**
* add wormhole size data for each wormhole
* @param wormholes
* @returns {*}
*/
let addWormholeSizeData = wormholes => {
for(let [wormholeName, wormholeData] of Object.entries(wormholes)){
wormholeData.class = Util.getSecurityClassForSystem(wormholeData.security);
for(let [sizeName, sizeData] of Object.entries(Init.wormholeSizes)){
if(wormholeData.massIndividual >= sizeData.jumpMassMin){
wormholeData.size = sizeData;
break;
}
}
}
return wormholes;
};
let initDataExecutor = (resolve, reject) => {
$.getJSON(Init.path.initData).done(response => {
if( response.error.length > 0 ){
@@ -139,7 +157,7 @@ define([
Init.connectionScopes = response.connectionScopes;
Init.systemStatus = response.systemStatus;
Init.systemType = response.systemType;
Init.wormholes = response.wormholes;
Init.wormholes = addWormholeSizeData(response.wormholes);
Init.characterStatus = response.characterStatus;
Init.routes = response.routes;
Init.url = response.url;
@@ -202,7 +220,7 @@ define([
* @param payload
* @returns {Promise<any>}
*/
let initMapModule = (payload) => {
let initMapModule = payload => {
let initMapModuleExecutor = (resolve, reject) => {
// init browser tab change observer, Once the timers are available
@@ -229,10 +247,10 @@ define([
* @param payloadMapAccessData
* @returns {Promise<any>}
*/
let initMapWorker = (payloadMapAccessData) => {
let initMapWorker = payloadMapAccessData => {
let initMapWorkerExecutor = (resolve, reject) => {
let getPayload = (command) => {
let getPayload = command => {
return {
action: 'initMapWorker',
data: {
@@ -251,7 +269,7 @@ define([
// init SharedWorker for maps
MapWorker.init({
characterId: response.data.id,
characterId: response.data.id,
callbacks: {
onInit: (MsgWorkerMessage) => {
Util.setSyncStatus(MsgWorkerMessage.command);
@@ -398,7 +416,7 @@ define([
data.error.length > 0
){
// any error in the main trigger functions result in a user log-off
$(document).trigger('pf:menuLogout');
Util.triggerMenuAction(document, 'Logout');
}else{
$(document).setProgramStatus('online');
@@ -474,13 +492,13 @@ define([
data.error.length > 0
){
// any error in the main trigger functions result in a user log-off
$(document).trigger('pf:menuLogout');
Util.triggerMenuAction(document, 'Logout');
}else{
$(document).setProgramStatus('online');
if(data.userData !== undefined){
// store current user data global (cache)
let userData = Util.setCurrentUserData(data.userData);
Util.setCurrentUserData(data.userData);
// update system info panels
if(data.system){
@@ -530,11 +548,42 @@ define([
// initial start of the map update function
triggerMapUpdatePing(true);
/**
* handles "final" map update request before window.unload event
* -> navigator.sendBeacon browser support required
* ajax would not work here, because browsers might cancel the request!
* @param mapModule
*/
let mapUpdateUnload = mapModule => {
// get updated map data
let mapData = ModuleMap.getMapModuleDataForUpdate(mapModule);
if(mapData.length){
let fd = new FormData();
fd.set('mapData', JSON.stringify(mapData));
navigator.sendBeacon(Init.path.updateUnloadData, fd);
console.info('Map update request send by: %O', navigator.sendBeacon);
}
};
// Send map update request on tab close/reload, in order to save map changes that
// haven´t been saved through default update trigger
window.addEventListener('beforeunload', function(e){
// close "SharedWorker" connection
MapWorker.close();
// clear periodic update timeouts
// -> this function will handle the final map update request
clearUpdateTimeouts();
// save unsaved map changes ...
triggerMapUpdatePing();
if(navigator.sendBeacon){
mapUpdateUnload(mapModule);
}else{
// fallback if sendBeacon() is not supported by browser
triggerMapUpdatePing();
}
// check if character should be switched on reload or current character should be loaded afterwards
let characterSwitch = Boolean( $('body').data('characterSwitch') );
@@ -547,7 +596,7 @@ define([
// IMPORTANT, return false in order to not "abort" ajax request in background!
return false;
});
}, false);
};

View File

@@ -5,13 +5,13 @@ define([
'app/map/map',
'app/map/util',
'sortable',
'app/ui/module/system_info',
'app/ui/module/system_graph',
'app/ui/module/system_signature',
'app/ui/module/system_route',
'app/ui/module/system_intel',
'app/ui/module/system_killboard',
'app/ui/module/connection_info',
'module/system_info',
'module/system_graph',
'module/system_signature',
'module/system_route',
'module/system_intel',
'module/system_killboard',
'module/connection_info',
'app/counter'
], (
$,
@@ -54,18 +54,16 @@ define([
moduleClass: 'pf-module', // class for a module
moduleSpacerClass: 'pf-module-spacer', // class for "spacer" module (preserves height during hide/show animation)
moduleClosedClass: 'pf-module-closed' // class for a closed module
};
let mapTabChangeBlocked = false; // flag for preventing map tab switch
/**
* get all maps for a maps module
* @returns {*}
* @param mapModule
* @returns {jQuery}
*/
$.fn.getMaps = function(){
return $(this).find('.' + config.mapClass);
};
let getMaps = mapModule => $(mapModule).find('.' + config.mapClass);
/**
* get the current active mapElement
@@ -748,7 +746,7 @@ define([
MapUtil.storeLocaleCharacterData('defaultMapId', mapId);
}else{
// add new Tab selected
$(document).trigger('pf:menuShowMapSettings', {tab: 'new'});
Util.triggerMenuAction(document, 'ShowMapSettings', {tab: 'new'});
e.preventDefault();
}
});
@@ -1217,7 +1215,7 @@ define([
clearMapModule(mapModule)
.then(payload => {
// no map data available -> show "new map" dialog
$(document).trigger('pf:menuShowMapSettings', {tab: 'new'});
Util.triggerMenuAction(document, 'ShowMapSettings', {tab: 'new'});
})
.then(payload => resolve());
}else{
@@ -1341,16 +1339,17 @@ define([
* collect all data (systems/connections) for export/save from each active map in the map module
* if no change detected -> do not attach map data to return array
* @param mapModule
* @param filter
* @returns {Array}
*/
let getMapModuleDataForUpdate = mapModule => {
let getMapModuleDataForUpdate = (mapModule, filter = ['hasId', 'hasChanged']) => {
// get all active map elements for module
let mapElements = mapModule.getMaps();
let mapElements = getMaps(mapModule);
let data = [];
for(let i = 0; i < mapElements.length; i++){
// get all changed (system / connection) data from this map
let mapData = Map.getMapDataForSync($(mapElements[i]), ['hasId', 'hasChanged']);
let mapData = Map.getMapDataForSync($(mapElements[i]), filter);
if(mapData !== false){
if(
mapData.data.systems.length > 0 ||

File diff suppressed because it is too large Load Diff

View File

@@ -6,12 +6,15 @@ define([
'jquery',
'app/init',
'app/util',
'app/map/worker'
], function($, Init, Util, MapWorker){
'app/map/worker',
'mustache',
], function($, Init, Util, MapWorker, Mustache){
'use strict';
let config = {
splashOverlayClass: 'pf-splash' // class for "splash" overlay
splashOverlayClass: 'pf-splash', // class for "splash" overlay
webSocketStatsId: 'pf-setup-webSocket-stats', // id for webSocket "stats" panel
webSocketRefreshStatsId: 'pf-setup-webSocket-stats-refresh' // class for "reload stats" button
};
/**
@@ -42,6 +45,18 @@ define([
});
};
/**
*
* @param container
* @param selector
*/
let setCollapseObserver = (container, selector) => {
container.find(selector).css({cursor: 'pointer'});
container.on('click', selector, function(){
$(this).find('.pf-animate-rotate').toggleClass('right');
});
};
/**
* set page observer
*/
@@ -52,9 +67,7 @@ define([
Util.initPageScroll(body);
// collapse ---------------------------------------------------------------------------------------------------
body.find('[data-toggle="collapse"]').css({cursor: 'pointer'}).on('click', function(){
$(this).find('.pf-animate-rotate').toggleClass('right');
});
setCollapseObserver(body, '[data-toggle="collapse"]');
// buttons ----------------------------------------------------------------------------------------------------
// exclude "download" && "navigation" buttons
@@ -128,6 +141,29 @@ define([
}
};
/**
* get WebSockets "subscriptions" <table> HTML
* @param subscriptionStats
* @returns {Promise<any>}
*/
let getWebSocketSubscriptionTable = subscriptionStats => {
let executor = resolve => {
requirejs(['text!templates/modules/subscriptions_table.html', 'mustache'], (template, Mustache) => {
let data = {
panelId: config.webSocketStatsId,
refreshButtonId: config.webSocketRefreshStatsId,
subStats: subscriptionStats,
channelCount: (Util.getObjVal(subscriptionStats, 'channels') || []).length
};
resolve(Mustache.render(template, data));
});
};
return new Promise(executor);
};
/**
* perform a basic check if Clients (browser) can connect to the webSocket server
*/
@@ -158,7 +194,7 @@ define([
let socketDangerCount = parseInt(badgeSocketDanger.text()) || 0;
if(data.uri){
let uriRow = webSocketPanel.find('.panel-body table tr');
let uriRow = webSocketPanel.find('.panel-body').filter(':first').find('table tr');
uriRow.find('td:nth-child(2) kbd').html(data.uri.value);
if(data.uri.status){
let statusIcon = uriRow.find('td:nth-child(3) i');
@@ -206,6 +242,18 @@ define([
}
});
/**
* @param socket
* @param task
* @param load
*/
let sendMessage = (socket, task, load) => {
socket.send(JSON.stringify({
task: task,
load: load
}));
};
// try to connect to WebSocket server
let socket = new WebSocket(webSocketURI);
@@ -219,10 +267,7 @@ define([
});
// sent token and check response
socket.send(JSON.stringify({
task: 'healthCheck',
load: tcpSocketPanel.data('token')
}));
sendMessage(socket, 'healthCheck', tcpSocketPanel.attr('data-token'));
webSocketPanel.hideLoadingAnimation();
};
@@ -230,7 +275,7 @@ define([
socket.onmessage = (e) => {
let response = JSON.parse(e.data);
if(response === 1){
if(Util.getObjVal(response, 'load.isValid') === true){
// SUCCESS
updateWebSocketPanel({
status: {
@@ -239,6 +284,23 @@ define([
class: 'txt-color-success'
}
});
// show subscription stats table
getWebSocketSubscriptionTable(Util.getObjVal(response, 'load.subStats')).then(payload => {
// remove existing table -> then insert new
$('#' + config.webSocketStatsId).remove();
$(payload).insertAfter(webSocketPanel).initTooltips();
let token = Util.getObjVal(response, 'load.token');
tcpSocketPanel.attr('data-token', token);
// set "reload stats" observer
$('#' + config.webSocketRefreshStatsId).on('click', function(){
$('#' + config.webSocketStatsId).showLoadingAnimation();
sendMessage(socket, 'healthCheck', token);
});
});
}else{
// Got response but INVALID
updateWebSocketPanel({
@@ -274,6 +336,8 @@ define([
});
webSocketPanel.hideLoadingAnimation();
$('#' + config.webSocketStatsId).remove();
};
};
@@ -286,7 +350,7 @@ define([
Util.showVersionInfo();
// hide splash loading animation ------------------------------------------------------------------------------
$('.' + config.splashOverlayClass).hideSplashOverlay();
$('.' + config.splashOverlayClass + '[data-status="ok"]').hideSplashOverlay();
setPageObserver();

View File

@@ -6,9 +6,8 @@ define([
'jquery',
'app/init',
'app/util',
'app/render',
'bootbox'
], function($, Init, Util, Render, bootbox){
], ($, Init, Util, bootbox) => {
'use strict';
let config = {
@@ -130,10 +129,9 @@ define([
Util.showNotify({title: 'Account saved', type: 'success'});
// close dialog/menu
$(document).trigger('pf:closeMenu', [{}]);
Util.triggerMenuAction(document, 'Close');
accountSettingsDialog.modal('hide');
}
}).fail(function(jqXHR, status, error){
accountSettingsDialog.find('.modal-content').hideLoadingAnimation();

View File

@@ -6,9 +6,8 @@ define([
'jquery',
'app/init',
'app/util',
'app/render',
'bootbox'
], ($, Init, Util, Render, bootbox) => {
], ($, Init, Util, bootbox) => {
'use strict';
let config = {

View File

@@ -6,9 +6,8 @@ define([
'jquery',
'app/init',
'app/util',
'app/render',
'bootbox'
], ($, Init, Util, Render, bootbox) => {
], ($, Init, Util, bootbox) => {
'use strict';
let config = {

View File

@@ -6,10 +6,9 @@ define([
'jquery',
'app/init',
'app/util',
'app/render',
'bootbox',
'app/ui/logo'
], function($, Init, Util, Render, bootbox){
'layout/logo'
], ($, Init, Util, bootbox) => {
'use strict';
let config = {
@@ -23,7 +22,7 @@ define([
*/
$.fn.showCreditsDialog = function(callback, enableHover){
requirejs(['text!templates/dialog/credit.html', 'mustache'], function(template, Mustache){
requirejs(['text!templates/dialog/credit.html', 'mustache'], (template, Mustache) => {
let data = {
logoContainerId: config.creditsDialogLogoContainerId,

View File

@@ -6,15 +6,21 @@ define([
'jquery',
'app/init',
'app/util',
'app/render',
'bootbox',
], ($, Init, Util, Render, bootbox) => {
'app/map/util'
], ($, Init, Util, bootbox, MapUtil) => {
'use strict';
let config = {
// jump info dialog
jumpInfoDialogClass: 'pf-jump-info-dialog', // class for jump info dialog
wormholeInfoDialogListId: 'pf-wormhole-info-dialog-list', // id for map "list" container
wormholeInfoDialogStaticId: 'pf-wormhole-info-dialog-static', // id for map "static" container
wormholeInfoDialogJumpId: 'pf-wormhole-info-dialog-jump', // id for map "jump" container
wormholeInfoMassTableClass: 'pf-wormhole-info-mass-table', // class for "wormhole mass" table
wormholeInfoStaticTableClass: 'pf-wormhole-info-static-table', // class for "static" table
wormholeInfoJumpTableClass: 'pf-wormhole-info-jump-table' // class for "wormhole jump" table
};
@@ -23,15 +29,40 @@ define([
*/
$.fn.showJumpInfoDialog = function(){
requirejs(['text!templates/dialog/jump_info.html', 'mustache', 'datatables.loader'], (template, Mustache) => {
let staticsMatrixHead = [
['From╲To', 'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'H', 'L', '0.0', 'C12', 'C13']
];
let staticsMatrixBody = [
['C1', 'H121', 'C125', 'O883', 'M609', 'L614', 'S804', 'N110', 'J244', 'Z060', 'F353', ''],
['C2', 'Z647', 'D382', 'O477', 'Y683', 'N062', 'R474', 'B274', 'A239', 'E545', 'F135', ''],
['C3', 'V301', 'I182', 'N968', 'T405', 'N770', 'A982', 'D845', 'U210', 'K346', 'F135', ''],
['C4', 'P060', 'N766', 'C247', 'X877', 'H900', 'U574', 'S047', 'N290', 'K329', '' , ''],
['C5', 'Y790', 'D364', 'M267', 'E175', 'H296', 'V753', 'D792', 'C140', 'Z142', '' , ''],
['C6', 'Q317', 'G024', 'L477', 'Z457', 'V911', 'W237', ['B520', 'D792'], ['C140', 'C391'], ['C248', 'Z142'], '', ''],
['H', 'Z971', 'R943', 'X702', 'O128', 'M555', 'B041', 'A641', 'R051', 'V283', 'T458', ''],
['L', 'Z971', 'R943', 'X702', 'O128', 'N432', 'U319', 'B449', 'N944', 'S199', 'M164', ''],
['0.0', 'Z971', 'R943', 'X702', 'O128', 'N432', 'U319', 'B449', 'N944', 'S199', 'L031', ''],
['C12', '' , '' , '' , '' , '' , '' , 'Q063', 'V898', 'E587', '' , ''],
['?', 'E004', 'L005', 'Z006', 'M001', 'C008', 'G008', '' , '' , 'Q003', '' , 'A009']
];
let data = {
config: config,
popoverTriggerClass: Util.config.popoverTriggerClass,
wormholes: Object.keys(Init.wormholes).map(function(k){ return Init.wormholes[k]; }), // convert Json to array
securityClass: function(){
return function(value, render){
return this.Util.getSecurityClassForSystem( render(value) );
}.bind(this);
}.bind({
Util: Util
staticsMatrixHead: staticsMatrixHead,
staticsMatrixBody: staticsMatrixBody.map((row, rowIndex) => {
return row.map((label, colIndex) => {
// get security name from "matrix Head" data if NOT first column
let secName = colIndex ? staticsMatrixHead[0][colIndex] : label;
return {
label: label,
class: Util.getSecurityClassForSystem(secName),
hasPopover: colIndex && label.length
};
});
}),
massValue: function(){
return function(value, render){
@@ -66,22 +97,26 @@ define([
let float = render(value);
return float.length ? parseFloat(float).toLocaleString() + '&nbsp;&#37;' : 'unknown';
};
},
securityClass: function(){
return function(value, render){
return Util.getSecurityClassForSystem(this);
};
}
};
let content = Mustache.render(template, data);
let jumpDialog = bootbox.dialog({
className: config.jumpInfoDialogClass,
title: 'Wormhole jump information',
title: 'Wormhole data',
message: content,
show: false
});
jumpDialog.on('show.bs.modal', function(e){
// init dataTable
$(this).find('.' + config.wormholeInfoMassTableClass).DataTable({
pageLength: 25,
lengthMenu: [[10, 20, 25, 30, 40, -1], [10, 20, 25, 30, 40, 'All']],
pageLength: 35,
lengthMenu: [[15, 25, 35, 50, -1], [15, 25, 35, 50, 'All']],
autoWidth: false,
language: {
emptyTable: 'No wormholes',
@@ -93,6 +128,18 @@ define([
data: null // use DOM data overwrites [] default -> data.loader.js
});
$(this).find('.' + config.wormholeInfoStaticTableClass).DataTable({
pageLength: -1,
paging: false,
lengthChange: false,
ordering: false,
searching: false,
info: false,
autoWidth: false,
columnDefs: [],
data: null // use DOM data overwrites [] default -> data.loader.js
});
$(this).find('.' + config.wormholeInfoJumpTableClass).DataTable({
pageLength: -1,
paging: false,
@@ -110,6 +157,11 @@ define([
columnDefs: [],
data: null // use DOM data overwrites [] default -> data.loader.js
});
MapUtil.initWormholeInfoTooltip(
$(this).find('.' + config.wormholeInfoStaticTableClass),
'.' + Util.config.popoverTriggerClass
);
});
jumpDialog.initTooltips();

View File

@@ -6,9 +6,8 @@ define([
'jquery',
'app/init',
'app/util',
'app/render',
'bootbox',
], ($, Init, Util, Render, bootbox) => {
], ($, Init, Util, bootbox) => {
'use strict';
@@ -62,23 +61,17 @@ define([
let disableOnScrollEvent = false;
// scroll breakpoints
let scrolLBreakpointElements = null;
let scrollBreakpointElements = $('.pf-manual-scroll-break');
// scroll navigation links
let scrollNavLiElements = null;
mapManualDialog.on('shown.bs.modal', function(e){
// modal on open
scrolLBreakpointElements = $('.pf-manual-scroll-break');
scrollNavLiElements = $('.' + config.dialogNavigationListItemClass);
});
let scrollNavLiElements = $('.' + config.dialogNavigationListItemClass);
let scrollspyElement = $('#' + config.mapManualScrollspyId);
let whileScrolling = function(){
if(disableOnScrollEvent === false){
for(let i = 0; i < scrolLBreakpointElements.length; i++){
let offset = $(scrolLBreakpointElements[i]).offset().top;
for(let i = 0; i < scrollBreakpointElements.length; i++){
let offset = $(scrollBreakpointElements[i]).offset().top;
if( (offset - modalOffsetTop) > 0){

View File

@@ -307,7 +307,7 @@ define([
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
// select system
$(cell).on('click', function(e){
Util.getMapModule().getActiveMap().triggerMenuEvent('SelectSystem', {systemId: rowData.id});
Util.triggerMenuAction(Util.getMapModule().getActiveMap(), 'SelectSystem', {systemId: rowData.id});
});
}
},{
@@ -382,9 +382,7 @@ define([
let statics = [];
for(let wormholeName of cellData){
let wormholeData = Object.assign({}, Init.wormholes[wormholeName]);
let security = wormholeData.security;
let secClass = Util.getSecurityClassForSystem(security);
statics.push('<span class="' + secClass + '">' + security + '</span>');
statics.push('<span class="' + wormholeData.class + '">' + wormholeData.security + '</span>');
}
return statics.join('&nbsp;&nbsp;');
}
@@ -566,7 +564,7 @@ define([
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
// select system
$(cell).on('click', function(e){
Util.getMapModule().getActiveMap().triggerMenuEvent('SelectSystem', {systemId: rowData.source});
Util.triggerMenuAction(Util.getMapModule().getActiveMap(), 'SelectSystem', {systemId: rowData.source});
});
}
},{
@@ -596,7 +594,7 @@ define([
display: (cellData, type, rowData, meta) => {
let connectionClasses = MapUtil.getConnectionFakeClassesByTypes(cellData);
connectionClasses = connectionClasses.join(' ');
return '<div class="pf-fake-connection ' + connectionClasses + '"></div>';
return '<div class="' + connectionClasses + '"></div>';
}
}
},{
@@ -622,7 +620,7 @@ define([
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
// select system
$(cell).on('click', function(e){
Util.getMapModule().getActiveMap().triggerMenuEvent('SelectSystem', {systemId: rowData.target});
Util.triggerMenuAction(Util.getMapModule().getActiveMap(), 'SelectSystem', {systemId: rowData.target});
});
}
},{
@@ -812,8 +810,8 @@ define([
},
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
// open character information window (ingame)
$(cell).on('click', { tableApi: this.DataTable() }, function(e){
let rowData = e.data.tableApi.row(this).data();
$(cell).on('click', { tableApi: this.api(), rowIndex: rowIndex }, function(e){
let rowData = e.data.tableApi.row(e.data.rowIndex).data();
Util.openIngameWindow(rowData.id);
});
}
@@ -852,7 +850,7 @@ define([
},
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
// open character information window (ingame)
$(cell).on('click', { tableApi: this.DataTable() }, function(e){
$(cell).on('click', { tableApi: this.api() }, function(e){
let cellData = e.data.tableApi.cell(this).data();
Util.openIngameWindow(cellData.id);
});
@@ -1134,8 +1132,8 @@ define([
},
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
// open character information window (ingame)
$(cell).on('click', { tableApi: this.DataTable() }, function(e){
let rowData = e.data.tableApi.row(this).data();
$(cell).on('click', { tableApi: this.api(), rowIndex: rowIndex }, function(e){
let rowData = e.data.tableApi.row(e.data.rowIndex).data();
Util.openIngameWindow(rowData.context.data.character.id);
});
}
@@ -1260,7 +1258,7 @@ define([
]
} );
logDataTable.buttons().container().appendTo( $(this).find('.' + config.tableToolsClass));
logDataTable.buttons().container().appendTo($(this).find('.' + config.tableToolsClass));
};
/**

View File

@@ -35,6 +35,7 @@ define([
deleteExpiredConnectionsId: 'pf-map-dialog-delete-connections-expired', // id for "deleteExpiredConnections" checkbox
deleteEolConnectionsId: 'pf-map-dialog-delete-connections-eol', // id for "deleteEOLConnections" checkbox
persistentAliasesId: 'pf-map-dialog-persistent-aliases', // id for "persistentAliases" checkbox
persistentSignaturesId: 'pf-map-dialog-persistent-signatures', // id for "persistentSignatures" checkbox
logHistoryId: 'pf-map-dialog-history', // id for "history logging" checkbox
logActivityId: 'pf-map-dialog-activity', // id for "activity" checkbox
@@ -157,6 +158,7 @@ define([
let deleteExpiredConnections = true;
let deleteEolConnections = true;
let persistentAliases = true;
let persistentSignatures = true;
let logActivity = true;
let logHistory = true;
@@ -194,6 +196,7 @@ define([
deleteExpiredConnections = mapData.config.deleteExpiredConnections;
deleteEolConnections = mapData.config.deleteEolConnections;
persistentAliases = mapData.config.persistentAliases;
persistentSignatures = mapData.config.persistentSignatures;
logActivity = mapData.config.logging.activity;
logHistory = mapData.config.logging.history;
@@ -251,9 +254,11 @@ define([
deleteExpiredConnectionsId : config.deleteExpiredConnectionsId,
deleteEolConnectionsId : config.deleteEolConnectionsId,
persistentAliasesId : config.persistentAliasesId,
persistentSignaturesId : config.persistentSignaturesId,
deleteExpiredConnections: deleteExpiredConnections,
deleteEolConnections: deleteEolConnections,
persistentAliases: persistentAliases,
persistentSignatures: persistentSignatures,
logHistoryId: config.logHistoryId,
logActivityId: config.logActivityId,
@@ -390,8 +395,8 @@ define([
if( form.find('#' + config.persistentAliasesId).length ){
formData.persistentAliases = formData.hasOwnProperty('persistentAliases') ? parseInt( formData.persistentAliases ) : 0;
}
if( form.find('#' + config.persistentAliasesId).length ){
formData.persistentAliases = formData.hasOwnProperty('persistentAliases') ? parseInt( formData.persistentAliases ) : 0;
if( form.find('#' + config.persistentSignaturesId).length ){
formData.persistentSignatures = formData.hasOwnProperty('persistentSignatures') ? parseInt( formData.persistentSignatures ) : 0;
}
if( form.find('#' + config.logHistoryId).length ){
formData.logHistory = formData.hasOwnProperty('logHistory') ? parseInt( formData.logHistory ) : 0;
@@ -422,7 +427,7 @@ define([
}
$(mapInfoDialog).modal('hide');
$(document).trigger('pf:closeMenu', [{}]);
Util.triggerMenuAction(document, 'Close');
}
}).fail(function(jqXHR, status, error){
let reason = status + ' ' + error;

View File

@@ -6,9 +6,8 @@ define([
'jquery',
'app/init',
'app/util',
'app/render',
'bootbox'
], function($, Init, Util, Render, bootbox){
], ($, Init, Util, bootbox) => {
'use strict';

View File

@@ -6,10 +6,9 @@ define([
'jquery',
'app/init',
'app/util',
'app/render',
'bootbox',
'app/key',
], function($, Init, Util, Render, bootbox, Key){
], function($, Init, Util, bootbox, Key){
'use strict';

View File

@@ -10,7 +10,7 @@ define([
'app/render',
'bootbox',
'peityInlineChart'
], function($, Init, Util, Render, bootbox){
], ($, Init, Util, Render, bootbox) => {
'use strict';
let config = {
@@ -83,12 +83,14 @@ define([
buttons: [
{
extend: 'copy',
tag: 'a',
className: config.moduleHeadlineIconClass,
text: '<i class="fas fa-fw fa-copy"></i> copy',
exportOptions: { orthogonal: 'filter' }
},
{
extend: 'csv',
tag: 'a',
className: config.moduleHeadlineIconClass,
text: '<i class="fas fa-fw fa-download"></i> csv',
exportOptions: { orthogonal: 'filter' }

View File

@@ -6,10 +6,9 @@ define([
'jquery',
'app/init',
'app/util',
'app/render',
'bootbox',
'app/map/util'
], ($, Init, Util, Render, bootbox, MapUtil) => {
], ($, Init, Util, bootbox, MapUtil) => {
'use strict';
let config = {
@@ -57,7 +56,7 @@ define([
for(let [areaId, areaData] of Object.entries(effectData)){
let systemType = 'C' + areaId;
let securityClass = Util.getSecurityClassForSystem( systemType );
let securityClass = Util.getSecurityClassForSystem(systemType);
if(areaId === '1'){
rows.push( $('<tr>') );

View File

@@ -166,7 +166,7 @@ define([
if(type.includes('wh_critical')){
styleClass.push('pf-wh-critical');
}
if(type.includes('frigate')){
if(type.includes('wh_jump_mass_s')){
styleClass.push('pf-wh-frig');
}
}
@@ -211,6 +211,53 @@ define([
);
};
/**
* init a select element as "select2" for connection size types
* @param options
*/
$.fn.initConnectionSizeSelect = function(options){
let selectElement = $(this);
let defaultConfig = {
dropdownParent: selectElement.parents('.modal-body'),
minimumResultsForSearch: -1,
width: '100%',
maxSelectionLength: 1
};
options = $.extend({}, defaultConfig, options);
let formatConnectionSizeResultData = data => {
if(data.loading) return data.text;
if(data.placeholder) return data.placeholder;
let connectionClass = MapUtil.getConnectionInfo(data.text, 'cssClass');
let label = Util.getObjVal(Init.wormholeSizes, data.text + '.label') || '?';
let text = Util.getObjVal(Init.wormholeSizes, data.text + '.text') || 'all';
let markup = '<div class="clearfix">';
markup += '<div class="col-xs-1">';
markup += '<i class="fas fa-char fa-fw" data-char-content="' + label + '"></i>';
markup += '</div>';
markup += '<div class="col-xs-3">';
markup += '<div class="pf-fake-connection ' + connectionClass + '"></div>';
markup += '</div>';
markup += '<div class="col-xs-8">';
markup += text;
markup += '</div>';
markup += '</div>';
return $(markup);
};
options.templateSelection = formatConnectionSizeResultData;
options.templateResult = formatConnectionSizeResultData;
$.when(
selectElement.select2(options)
);
};
/**
* init a sselect element as "select2" for "status" selection
* @param options

View File

@@ -5,7 +5,7 @@
define([
'jquery',
'lazylinepainter'
], function($){
], ($) => {
'use strict';

View File

@@ -59,7 +59,7 @@ define([
};
// load Logo svg
requirejs(['text!templates/ui/logo.html', 'mustache'], function(template, Mustache){
requirejs(['text!templates/layout/logo.html', 'mustache'], function(template, Mustache){
let logoData = {
staticLogoId: config.staticLogoId,
logoPartTopRightClass: config.logoPartTopRightClass,

View File

@@ -18,8 +18,6 @@ define([
moduleHeadClass: 'pf-module-head', // class for module header
moduleHandlerClass: 'pf-module-handler-drag', // class for "drag" handler
headUserShipClass: 'pf-head-user-ship', // class for "user settings" link
// connection info module
moduleTypeClass: 'pf-connection-info-module', // class for this module
@@ -100,15 +98,13 @@ define([
* @returns {jQuery}
*/
let getConnectionElement = (mapId, connectionId) => {
let connectionElement = $('<div>', {
return $('<div>', {
id: getConnectionElementId(connectionId),
class: ['col-xs-12', 'col-sm-4', 'col-lg-3' , config.connectionInfoPanelClass].join(' ')
}).data({
mapId: mapId,
connectionId: connectionId
});
return connectionElement;
};
/**
@@ -116,13 +112,11 @@ define([
* @param mapId
* @returns {void|jQuery|*}
*/
let getInfoPanelControl = (mapId) => {
let connectionElement = getConnectionElement(mapId, 0).append($('<div>', {
let getInfoPanelControl = mapId => {
return getConnectionElement(mapId, 0).append($('<div>', {
class: [Util.config.dynamicAreaClass, config.controlAreaClass].join(' '),
html: '<i class="fas fa-fw fa-plus"></i>&nbsp;add connection&nbsp;&nbsp;<kbd>ctrl</kbd>&nbsp;+&nbsp;<kbd>click</kbd>'
}));
return connectionElement;
};
/**
@@ -168,7 +162,7 @@ define([
class: 'pf-link',
html: connectionData.sourceAlias + '&nbsp;&nbsp;'
}).on('click', function(){
Util.getMapModule().getActiveMap().triggerMenuEvent('SelectSystem', {systemId: connectionData.source});
Util.triggerMenuAction(Util.getMapModule().getActiveMap(), 'SelectSystem', {systemId: connectionData.source});
}),
$('<span>', {
class: [config.connectionInfoTableLabelSourceClass].join(' ')
@@ -183,7 +177,7 @@ define([
class: 'pf-link',
html: '&nbsp;&nbsp;' + connectionData.targetAlias
}).on('click', function(){
Util.getMapModule().getActiveMap().triggerMenuEvent('SelectSystem', {systemId: connectionData.target});
Util.triggerMenuAction(Util.getMapModule().getActiveMap(), 'SelectSystem', {systemId: connectionData.target});
})
)
)
@@ -306,22 +300,22 @@ define([
let connection = $().getConnectionById(data.mapId, data.connectionId);
let signatureTypeNames = MapUtil.getConnectionDataFromSignatures(connection, connectionData);
let sourceLabel = signatureTypeNames.sourceLabels;
let targetLabel = signatureTypeNames.targetLabels;
sourceLabelElement.html(MapUtil.getEndpointOverlayContent(sourceLabel.join(', ')));
targetLabelElement.html(MapUtil.getEndpointOverlayContent(targetLabel.join(', ')));
let sourceLabels = signatureTypeNames.source.labels;
let targetLabels = signatureTypeNames.target.labels;
sourceLabelElement.html(MapUtil.formatEndpointOverlaySignatureLabel(sourceLabels));
targetLabelElement.html(MapUtil.formatEndpointOverlaySignatureLabel(targetLabels));
// remove K162
sourceLabel = sourceLabel.diff(['K162']);
targetLabel = targetLabel.diff(['K162']);
sourceLabels = sourceLabels.diff(['K162']);
targetLabels = targetLabels.diff(['K162']);
// get static wormhole data by endpoint Labels
let wormholeName = '';
let wormholeData = null;
if(sourceLabel.length === 1 && targetLabel.length === 0){
wormholeName = sourceLabel[0];
}else if(sourceLabel.length === 0 && targetLabel.length === 1){
wormholeName = targetLabel[0];
if(sourceLabels.length === 1 && targetLabels.length === 0){
wormholeName = sourceLabels[0];
}else if(sourceLabels.length === 0 && targetLabels.length === 1){
wormholeName = targetLabels[0];
}
if(
@@ -329,7 +323,6 @@ define([
Init.wormholes.hasOwnProperty(wormholeName)
){
wormholeData = Object.assign({}, Init.wormholes[wormholeName]);
wormholeData.class = Util.getSecurityClassForSystem(wormholeData.security);
// init wormhole tooltip ----------------------------------------------
let massTotalTooltipCell = tableElement.find('.' + config.connectionInfoTableCellMassTotalTooltipClass);
@@ -416,7 +409,7 @@ define([
// get current ship data ----------------------------------------------------------
massShipCell.parent().toggle(showShip);
if(showShip){
shipData = $('.' + config.headUserShipClass).data('shipData');
shipData = Util.getObjVal(Util.getCurrentCharacterLog(), 'ship');
if(shipData){
if(shipData.mass){
massShip = parseInt(shipData.mass);
@@ -507,18 +500,14 @@ define([
* @param connectionId
* @returns {string}
*/
let getConnectionElementId = (connectionId) => {
return config.connectionInfoPanelId + connectionId;
};
let getConnectionElementId = connectionId => config.connectionInfoPanelId + connectionId;
/**
* get all visible connection panel elements
* @param moduleElement
* @returns {*|T|{}}
*/
let getConnectionElements = (moduleElement) => {
return moduleElement.find('.' + config.connectionInfoPanelClass).not('#' + getConnectionElementId(0));
};
let getConnectionElements = moduleElement => moduleElement.find('.' + config.connectionInfoPanelClass).not('#' + getConnectionElementId(0));
/**
* enrich connectionData with "logs" data (if available) and other "missing" data
@@ -703,6 +692,7 @@ define([
buttons: [
{
name: 'addLog',
tag: 'a',
className: config.moduleHeadlineIconClass,
text: '<i class="fa fa-plus"></i>',
action: function(e, tableApi, node, conf){
@@ -1108,7 +1098,7 @@ define([
selectElementType.initUniverseTypeSelect({
categoryIds: [6],
maxSelectionLength: 1,
selected: [Util.getObjVal(logData, 'ship.id')]
selected: [Util.getObjVal(logData, 'ship.typeId')]
}).on('select2:select select2:unselecting', function(e){
// get ship mass from selected ship type and update mass input field
let shipMass = e.params.data ? e.params.data.mass / 1000 : '';

View File

@@ -143,7 +143,6 @@ define([
){
for(let wormholeName of systemData.statics){
let wormholeData = Object.assign({}, Init.wormholes[wormholeName]);
wormholeData.class = Util.getSecurityClassForSystem(wormholeData.security);
staticsData.push(wormholeData);
}
}

View File

@@ -53,7 +53,7 @@ define([
* @param statusData
* @returns {string}
*/
let getStatusData = (statusData) => {
let getStatusData = statusData => {
return '<i class="fas fa-fw fa-circle ' + statusData.class + '" title="' + statusData.label + '"></i>';
};
@@ -430,7 +430,7 @@ define([
name: 'status',
title: '',
width: 2,
class: 'text-center',
className: ['text-center', 'all'].join(' '),
data: 'status',
render: {
display: data => getStatusData(data),
@@ -445,7 +445,7 @@ define([
title: '',
width: 26,
orderable: false,
className: [config.tableCellImageClass, 'text-center'].join(' '),
className: [config.tableCellImageClass, 'text-center', 'all'].join(' '),
data: 'structure.id',
defaultContent: '<i class="fas fa-question txt-color txt-color-orangeDark"></i>',
render: {
@@ -462,7 +462,7 @@ define([
name: 'structureType',
title: 'type',
width: 30,
className: [config.tableCellEllipsisClass].join(' '),
className: [config.tableCellEllipsisClass, 'all'].join(' '),
data: 'structure.name',
defaultContent: '<i class="fas fa-question txt-color txt-color-orangeDark"></i>',
},{
@@ -470,7 +470,7 @@ define([
name: 'name',
title: 'name',
width: 60,
className: [config.tableCellEllipsisClass].join(' '),
className: [config.tableCellEllipsisClass, 'all'].join(' '),
data: 'name'
},{
targets: 4,
@@ -478,7 +478,7 @@ define([
title: '',
width: 26,
orderable: false,
className: [config.tableCellImageClass, 'text-center'].join(' '),
className: [config.tableCellImageClass, 'text-center', 'all'].join(' '),
data: 'owner.id',
defaultContent: '<i class="fas fa-question txt-color txt-color-orangeDark"></i>',
render: {
@@ -497,14 +497,14 @@ define([
name: 'ownerName',
title: 'owner',
width: 50,
className: [config.tableCellEllipsisClass].join(' '),
className: [config.tableCellEllipsisClass, 'all'].join(' '),
data: 'owner.name',
defaultContent: '<i class="fas fa-question txt-color txt-color-orangeDark"></i>',
},{
targets: 6,
name: 'note',
title: 'note',
className: [config.tableCellEllipsisClass].join(' '),
className: [config.tableCellEllipsisClass, 'all'].join(' '),
data: 'description'
},{
targets: 7,
@@ -519,7 +519,7 @@ define([
title: '',
orderable: false,
width: 10,
class: ['text-center', config.dataTableActionCellClass, config.moduleHeadlineIconClass].join(' '),
className: ['text-center', config.dataTableActionCellClass, config.moduleHeadlineIconClass, 'all'].join(' '),
data: null,
render: {
display: data => {
@@ -550,7 +550,7 @@ define([
title: '',
orderable: false,
width: 10,
class: ['text-center', config.dataTableActionCellClass].join(' '),
className: ['text-center', config.dataTableActionCellClass, 'all'].join(' '),
data: null,
render: {
display: data => {
@@ -607,6 +607,7 @@ define([
},{
targets: 10,
name: 'corporation',
className: 'never', // never show this column. see: https://datatables.net/extensions/responsive/classes
data: 'corporation',
visible: false,
render: {

View File

@@ -34,7 +34,9 @@ define([
routeDialogId: 'pf-route-dialog', // id for route "search" dialog
systemDialogSelectClass: 'pf-system-dialog-select', // class for system select Element
systemInfoRoutesTableClass: 'pf-system-route-table', // class for route tables
mapSelectId: 'pf-route-dialog-map-select', // id for "map" select
routeDialogMapSelectId: 'pf-route-dialog-map-select', // id for "map" select
routeDialogSizeSelectId: 'pf-route-dialog-size-select', // id for "wh size" select
dataTableActionCellClass: 'pf-table-action-cell', // class for "action" cells
dataTableRouteCellClass: 'pf-table-route-cell', // class for "route" cells
@@ -207,8 +209,8 @@ define([
};
let routeData = [];
dataTable.rows().every( function(){
routeData.push( getRouteRequestDataFromRowData(this.data()));
dataTable.rows().every(function(){
routeData.push(getRouteRequestDataFromRowData(this.data()));
});
getRouteData({routeData: routeData}, context, callbackAddRouteRows);
@@ -219,7 +221,7 @@ define([
* @param {Object} rowData
* @returns {Object}
*/
let getRouteRequestDataFromRowData = (rowData) => {
let getRouteRequestDataFromRowData = rowData => {
return {
mapIds: (rowData.hasOwnProperty('mapIds')) ? rowData.mapIds : [],
systemFromData: (rowData.hasOwnProperty('systemFromData')) ? rowData.systemFromData : {},
@@ -230,8 +232,9 @@ define([
wormholes: (rowData.hasOwnProperty('wormholes')) ? rowData.wormholes | 0 : 1,
wormholesReduced: (rowData.hasOwnProperty('wormholesReduced')) ? rowData.wormholesReduced | 0 : 1,
wormholesCritical: (rowData.hasOwnProperty('wormholesCritical')) ? rowData.wormholesCritical | 0 : 1,
wormholesFrigate: (rowData.hasOwnProperty('wormholesFrigate')) ? rowData.wormholesFrigate | 0 : 1,
wormholesEOL: (rowData.hasOwnProperty('wormholesEOL')) ? rowData.wormholesEOL | 0 : 1,
wormholesSizeMin: (rowData.hasOwnProperty('wormholesSizeMin')) ? rowData.wormholesSizeMin : '',
excludeTypes: (rowData.hasOwnProperty('excludeTypes')) ? rowData.excludeTypes : [],
endpointsBubble: (rowData.hasOwnProperty('endpointsBubble')) ? rowData.endpointsBubble | 0 : 1,
connections: (rowData.hasOwnProperty('connections')) ? rowData.connections.value | 0 : 0,
flag: (rowData.hasOwnProperty('flag')) ? rowData.flag.value : 'shortest'
@@ -255,13 +258,25 @@ define([
});
}
}
let sizeOptions = MapUtil.allConnectionJumpMassTypes().map(type => {
return {
id: type,
name: type,
selected: false
};
});
let data = {
id: config.routeDialogId,
select2Class: Util.config.select2Class,
selectClass: config.systemDialogSelectClass,
mapSelectId: config.mapSelectId,
routeDialogMapSelectId: config.routeDialogMapSelectId,
routeDialogSizeSelectId: config.routeDialogSizeSelectId,
systemFromData: dialogData.systemFromData,
systemToData: dialogData.systemToData,
mapSelectOptions: mapSelectOptions
mapSelectOptions: mapSelectOptions,
sizeOptions: sizeOptions
};
requirejs(['text!templates/dialog/route.html', 'mustache'], (template, Mustache) => {
@@ -300,6 +315,7 @@ define([
}
// get all system data from select2
// -> we could also get value from "routeDialogData" var, but we need systemName also
let systemSelectData = form.find('.' + config.systemDialogSelectClass).select2('data');
if(
@@ -324,8 +340,9 @@ define([
wormholes: routeDialogData.hasOwnProperty('wormholes') ? parseInt(routeDialogData.wormholes) : 0,
wormholesReduced: routeDialogData.hasOwnProperty('wormholesReduced') ? parseInt(routeDialogData.wormholesReduced) : 0,
wormholesCritical: routeDialogData.hasOwnProperty('wormholesCritical') ? parseInt(routeDialogData.wormholesCritical) : 0,
wormholesFrigate: routeDialogData.hasOwnProperty('wormholesFrigate') ? parseInt(routeDialogData.wormholesFrigate) : 0,
wormholesEOL: routeDialogData.hasOwnProperty('wormholesEOL') ? parseInt(routeDialogData.wormholesEOL) : 0,
wormholesSizeMin: routeDialogData.wormholesSizeMin || '',
excludeTypes: getLowerSizeConnectionTypes(routeDialogData.wormholesSizeMin),
endpointsBubble: routeDialogData.hasOwnProperty('endpointsBubble') ? parseInt(routeDialogData.endpointsBubble) : 0
}]
};
@@ -343,15 +360,18 @@ define([
// init some dialog/form observer
setDialogObserver( $(this) );
// init map select ----------------------------------------------------------------
let mapSelect = $(this).find('#' + config.mapSelectId);
// init map select ------------------------------------------------------------------------------------
let mapSelect = findRouteDialog.find('#' + config.routeDialogMapSelectId);
mapSelect.initMapSelect();
// init connection jump size select -------------------------------------------------------------------
findRouteDialog.find('#' + config.routeDialogSizeSelectId).initConnectionSizeSelect();
});
findRouteDialog.on('shown.bs.modal', function(e){
// init system select live search ------------------------------------------------
// init system select live search --------------------------------------------------------------------
// -> add some delay until modal transition has finished
let systemTargetSelect = $(this).find('.' + config.systemDialogSelectClass);
systemTargetSelect.delay(240).initSystemSelect({key: 'id'});
@@ -399,7 +419,7 @@ define([
skipSearch: requestRouteData.length >= defaultRoutesCount
};
requestRouteData.push( getRouteRequestDataFromRowData( searchData ));
requestRouteData.push(getRouteRequestDataFromRowData(searchData));
}
}
}
@@ -493,7 +513,7 @@ define([
settingsDialog.on('shown.bs.modal', function(e){
// init default system select -----------------------------------------------------
// init default system select ---------------------------------------------------------------------
// -> add some delay until modal transition has finished
let systemTargetSelect = $(this).find('.' + config.systemDialogSelectClass);
systemTargetSelect.delay(240).initSystemSelect({key: 'id', maxSelectionLength: maxSelectionLength});
@@ -532,14 +552,13 @@ define([
let wormholeCheckbox = routeDialog.find('input[type="checkbox"][name="wormholes"]');
let wormholeReducedCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesReduced"]');
let wormholeCriticalCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesCritical"]');
let wormholeFrigateCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesFrigate"]');
let wormholeEolCheckbox = routeDialog.find('input[type="checkbox"][name="wormholesEOL"]');
let wormholeSizeSelect = routeDialog.find('#' + config.routeDialogSizeSelectId);
// store current "checked" state for each box ---------------------------------------------
let storeCheckboxStatus = function(){
wormholeReducedCheckbox.data('selectState', wormholeReducedCheckbox.prop('checked'));
wormholeCriticalCheckbox.data('selectState', wormholeCriticalCheckbox.prop('checked'));
wormholeFrigateCheckbox.data('selectState', wormholeFrigateCheckbox.prop('checked'));
wormholeEolCheckbox.data('selectState', wormholeEolCheckbox.prop('checked'));
};
@@ -547,24 +566,24 @@ define([
let onWormholeCheckboxChange = function(){
if( $(this).is(':checked') ){
wormholeSizeSelect.prop('disabled', false);
wormholeReducedCheckbox.prop('disabled', false);
wormholeCriticalCheckbox.prop('disabled', false);
wormholeFrigateCheckbox.prop('disabled', false);
wormholeEolCheckbox.prop('disabled', false);
wormholeReducedCheckbox.prop('checked', wormholeReducedCheckbox.data('selectState'));
wormholeCriticalCheckbox.prop('checked', wormholeCriticalCheckbox.data('selectState'));
wormholeFrigateCheckbox.prop('checked', wormholeFrigateCheckbox.data('selectState'));
wormholeEolCheckbox.prop('checked', wormholeEolCheckbox.data('selectState'));
}else{
wormholeSizeSelect.prop('disabled', true);
storeCheckboxStatus();
wormholeReducedCheckbox.prop('checked', false);
wormholeReducedCheckbox.prop('disabled', true);
wormholeCriticalCheckbox.prop('checked', false);
wormholeCriticalCheckbox.prop('disabled', true);
wormholeFrigateCheckbox.prop('checked', false);
wormholeFrigateCheckbox.prop('disabled', true);
wormholeEolCheckbox.prop('checked', false);
wormholeEolCheckbox.prop('disabled', true);
}
@@ -760,8 +779,9 @@ define([
wormholes: routeData.wormholes,
wormholesReduced: routeData.wormholesReduced,
wormholesCritical: routeData.wormholesCritical,
wormholesFrigate: routeData.wormholesFrigate,
wormholesEOL: routeData.wormholesEOL,
wormholesSizeMin: routeData.wormholesSizeMin,
excludeTypes: routeData.excludeTypes,
endpointsBubble: routeData.endpointsBubble,
connections: {
value: 0,
@@ -823,7 +843,7 @@ define([
// check for wormhole
let icon = 'fas fa-square';
if( /^J\d+$/.test(systemName) ){
icon = 'far fa-dot-circle';
icon = 'fas fa-dot-circle';
}
let system = '<i class="' + icon + ' ' + systemSecClass + '" ';
@@ -861,7 +881,7 @@ define([
tableRowData.route.value = routeJumpElements.join(' ');
}
// route status data ----------------------------------------------------------------------
// route status data ------------------------------------------------------------------------------------------
tableRowData.status = {
value: routeStatus,
formatted: getStatusIcon(routeStatus)
@@ -1300,12 +1320,12 @@ define([
let routesTableElement = moduleElement.find('.' + config.systemInfoRoutesTableClass);
let routesTable = routesTableElement.DataTable();
// init refresh routes --------------------------------------------------------------------
// init refresh routes ----------------------------------------------------------------------------------------
moduleElement.find('.' + config.moduleHeadlineIconRefreshClass).on('click', function(e){
updateRoutesTable(moduleElement, routesTable);
});
// init search routes dialog --------------------------------------------------------------
// init search routes dialog ----------------------------------------------------------------------------------
moduleElement.find('.' + config.moduleHeadlineIconSearchClass).on('click', function(e){
let maxRouteSearchLimit = this.Init.routeSearch.limit;
@@ -1326,7 +1346,7 @@ define([
Init: Init
}));
// init settings dialog -------------------------------------------------------------------
// init settings dialog ---------------------------------------------------------------------------------------
moduleElement.find('.' + config.moduleHeadlineIconSettingsClass).on('click', function(e){
let dialogData = {
mapId: mapId
@@ -1335,7 +1355,7 @@ define([
showSettingsDialog(dialogData, moduleElement, systemFromData, routesTable);
});
// fill routesTable with data -------------------------------------------------------------
// fill routesTable with data --------------------------------------------------------------------------------
let promiseStore = MapUtil.getLocaleData('map', mapId);
promiseStore.then(function(dataStore){
// selected systems (if already stored)
@@ -1369,6 +1389,26 @@ define([
tableApi.destroy();
};
/**
* get all jump mass related connection types that have a lower "jumpMassMin" than connectionType
* @param connectionType
* @returns {Array}
*/
let getLowerSizeConnectionTypes = connectionType => {
let lowerSizeTypes = [];
let jumpMassMin = Util.getObjVal(Init.wormholeSizes, connectionType + '.jumpMassMin') || 0;
if(jumpMassMin){
for(let [type, data] of Object.entries(Init.wormholeSizes)){
if(data.jumpMassMin < jumpMassMin){
lowerSizeTypes.push(type);
}
}
}
return lowerSizeTypes;
};
return {
config: config,
getModule: getModule,

View File

@@ -68,7 +68,7 @@ define([
'Kosmische Anomalie', // de: "Cosmic Anomaly"
'Kosmische Signatur', // de: "Cosmic Signature"
'Космическая аномалия', // ru: "Cosmic Anomaly"
'Скрытый сигнал', // rm: "Cosmic Signature"
'Скрытый сигнал', // ru: "Cosmic Signature"
'Anomalie cosmique', // fr: "Cosmic Anomaly"
'Signature cosmique', // fr: "Cosmic Signature"
'宇宙の特異点', // ja: "Cosmic Anomaly"
@@ -2186,21 +2186,25 @@ define([
buttons: [
{
name: 'filterGroup',
tag: 'a',
className: config.moduleHeadlineIconClass,
text: '' // set by js (xEditable)
},
{
name: 'undo',
tag: 'a',
className: config.moduleHeadlineIconClass,
text: '' // set by js (xEditable)
},
{
name: 'selectAll',
tag: 'a',
className: config.moduleHeadlineIconClass,
text: '<i class="fas fa-check-double"></i>select all'
},
{
name: 'delete',
tag: 'a',
className: [config.moduleHeadlineIconClass, config.sigTableClearButtonClass].join(' '),
text: '<i class="fas fa-trash"></i>delete&nbsp;(<span>0</span>)'
}
@@ -2351,8 +2355,7 @@ define([
// "lazy update" toggle ---------------------------------------------------------------------------------------
moduleElement.find('.' + config.moduleHeadlineIconLazyClass).on('click', function(e){
let button = $(this);
button.toggleClass('active');
$(this).toggleClass('active');
});
// set multi row select ---------------------------------------------------------------------------------------
@@ -2383,31 +2386,22 @@ define([
// event listener for global "paste" signatures into the page -------------------------------------------------
moduleElement.on('pf:updateSystemSignatureModuleByClipboard', {tableApi: primaryTableApi}, function(e, clipboard){
let lazyUpdateToggle = moduleElement.find('.' + config.moduleHeadlineIconLazyClass);
let signatureOptions = {
deleteOld: moduleElement.find('.' + config.moduleHeadlineIconLazyClass).hasClass('active') ? 1 : 0
deleteOld: lazyUpdateToggle.hasClass('active') ? 1 : 0
};
// "disable" lazy update icon -> prevents accidental removal for next paste #724
lazyUpdateToggle.toggleClass('active', false);
updateSignatureTableByClipboard(e.data.tableApi, systemData, clipboard, signatureOptions);
});
// signature column - "type" popover --------------------------------------------------------------------------
moduleElement.find('.' + config.sigTableClass).hoverIntent({
over: function(e){
let staticWormholeElement = $(this);
let wormholeName = staticWormholeElement.attr('data-name');
let wormholeData = Util.getObjVal(Init, 'wormholes.' + wormholeName);
if(wormholeData){
staticWormholeElement.addWormholeInfoTooltip(wormholeData, {
trigger: 'manual',
placement: 'top',
show: true
});
}
},
out: function(e){
$(this).destroyPopover();
},
selector: '.editable-click:not(.editable-open) span[class^="pf-system-sec-"]'
});
MapUtil.initWormholeInfoTooltip(
moduleElement.find('.' + config.sigTableClass),
'.editable-click:not(.editable-open) span[class^="pf-system-sec-"]'
);
// signature column - "info" popover --------------------------------------------------------------------------
moduleElement.find('.' + config.sigTablePrimaryClass).hoverIntent({

View File

@@ -38,7 +38,7 @@ define([
// head
headMapTrackingId: 'pf-head-map-tracking', // id for "map tracking" toggle (checkbox)
headCurrentLocationId: 'pf-head-current-location', // id for "show current location" element
headUserLocationId: 'pf-head-user-location', // id for "location" breadcrumb
// menu
menuButtonFullScreenId: 'pf-menu-button-fullscreen', // id for menu button "fullScreen"
@@ -399,7 +399,7 @@ define([
};
/**
* check multiple element if they arecurrently visible in viewport
* check multiple element if they are currently visible in viewport
* @returns {Array}
*/
$.fn.isInViewport = function(){
@@ -963,11 +963,35 @@ define([
* init utility prototype functions
*/
let initPrototypes = () => {
// Array diff
// [1,2,3,4,5,6].diff( [3,4,5] );
// => [1, 2, 6]
/**
* Array diff
* [1,2,3,4,5].diff([4,5,6]) => [1,2,3]
* @param a
* @returns {*[]}
*/
Array.prototype.diff = function(a){
return this.filter(function(i){return a.indexOf(i) < 0;});
return this.filter(i => !a.includes(i));
};
/**
* Array intersect
* [1,2,3,4,5].intersect([4,5,6]) => [4,5]
* @param a
* @returns {*[]}
*/
Array.prototype.intersect = function(a){
return this.filter(i => a.includes(i));
};
/**
* compares two arrays if all elements in a are also in b
* element order is ignored
* @param a
* @returns {boolean}
*/
Array.prototype.equalValues = function(a){
return this.diff(a).concat(a.diff(this)).length === 0;
};
/**
@@ -1484,21 +1508,29 @@ define([
};
/**
* set currentUserData as "global" variable
* this function should be called continuously after data change
* to keep the data always up2data
* set currentUserData as "global" store var
* this function should be called whenever userData changed
* @param userData
* @returns {boolean} true on success
*/
let setCurrentUserData = (userData) => {
Init.currentUserData = userData;
let setCurrentUserData = userData => {
let isSet = false;
// check if function is available
// this is not the case in "login" page
if( $.fn.updateHeaderUserData ){
$.fn.updateHeaderUserData();
// check if userData is valid
if(userData && userData.character && userData.characters){
let changes = compareUserData(getCurrentUserData(), userData);
// check if there is any change
if(Object.values(changes).some(val => val)){
$(document).trigger('pf:changedUserData', [userData, changes]);
}
Init.currentUserData = userData;
isSet = true;
}else{
console.error('Could not set userData %o. Missing or malformed obj', userData);
}
return getCurrentUserData();
return isSet;
};
/**
@@ -1514,14 +1546,7 @@ define([
* @returns {number}
*/
let getCurrentCharacterId = () => {
let userData = getCurrentUserData();
let currentCharacterId = 0;
if(
userData &&
userData.character
){
currentCharacterId = parseInt( userData.character.id );
}
let currentCharacterId = parseInt(getObjVal(getCurrentUserData(), 'character.id')) || 0;
if(!currentCharacterId){
// no active character... -> get default characterId from initial page load
@@ -1531,6 +1556,28 @@ define([
return currentCharacterId;
};
/**
* compares two userData objects for changes that are relevant
* @param oldUserData
* @param newUserData
* @returns {{characterShipType: *, charactersIds: boolean, characterLogLocation: *, characterSystemId: *, userId: *, characterId: *}}
*/
let compareUserData = (oldUserData, newUserData) => {
let valueChanged = key => getObjVal(oldUserData, key) !== getObjVal(newUserData, key);
let oldCharactersIds = (getObjVal(oldUserData, 'characters') || []).map(data => data.id).sort();
let newCharactersIds = (getObjVal(newUserData, 'characters') || []).map(data => data.id).sort();
return {
userId: valueChanged('id'),
characterId: valueChanged('character.id'),
characterLogLocation: valueChanged('character.logLocation'),
characterSystemId: valueChanged('character.log.system.id'),
characterShipType: valueChanged('character.log.ship.typeId'),
charactersIds: oldCharactersIds.toString() !== newCharactersIds.toString()
};
};
/**
* get a unique ID for each tab
* -> store ID in session storage
@@ -1808,16 +1855,34 @@ define([
* @param jqXHR XMLHttpRequest instance
* @returns {boolean}
*/
let isXHRAborted = (jqXHR) => {
let isXHRAborted = jqXHR => {
return !jqXHR.getAllResponseHeaders();
};
/**
* trigger global menu action 'event' on dom 'element' with optional 'data'
* @param element
* @param action
* @param data
*/
let triggerMenuAction = (element, action, data) => {
if(element){
if(typeof(action) === 'string' && action.length){
$(element).trigger('pf:menuAction', [action, data]);
}else{
console.error('Invalid action: %o', action);
}
}else{
console.error('Invalid element: %o', element);
}
};
/**
* get label element for role data
* @param role
* @returns {*|jQuery|HTMLElement}
*/
let getLabelByRole = (role) => {
let getLabelByRole = role => {
return $('<span>', {
class: ['label', 'label-' + role.style].join(' '),
text: role.label
@@ -1829,7 +1894,7 @@ define([
* @param mapOverlay
* @returns {jQuery}
*/
let getMapElementFromOverlay = (mapOverlay) => {
let getMapElementFromOverlay = mapOverlay => {
return $(mapOverlay).parents('.' + config.mapWrapperClass).find('.' + config.mapClass);
};
@@ -2266,7 +2331,7 @@ define([
*/
let getDataIndexByMapId = (data, mapId) => {
let index = false;
if( Array.isArray(data) && mapId === parseInt(mapId, 10) ){
if(Array.isArray(data) && mapId === parseInt(mapId, 10)){
for(let i = 0; i < data.length; i++){
if(data[i].config.id === mapId){
index = i;
@@ -2330,9 +2395,7 @@ define([
* @param mapId
* @returns {boolean|int}
*/
let getCurrentMapUserDataIndex = mapId => {
return getDataIndexByMapId(Init.currentMapUserData, mapId);
};
let getCurrentMapUserDataIndex = mapId => getDataIndexByMapId(Init.currentMapUserData, mapId);
/**
* update cached mapUserData for a single map
@@ -2375,17 +2438,13 @@ define([
let getCurrentMapData = mapId => {
let currentMapData = false;
if( mapId === parseInt(mapId, 10) ){
// search for a specific map
for(let i = 0; i < Init.currentMapData.length; i++){
if(Init.currentMapData[i].config.id === mapId){
currentMapData = Init.currentMapData[i];
break;
}
if(Init.currentMapData){
if(mapId === parseInt(mapId, 10)){
currentMapData = Init.currentMapData.find(mapData => mapData.config.id === mapId);
}else{
// get data for all maps
currentMapData = Init.currentMapData;
}
}else{
// get data for all maps
currentMapData = Init.currentMapData;
}
return currentMapData;
@@ -2405,7 +2464,7 @@ define([
* @param mapData
*/
let updateCurrentMapData = mapData => {
let mapDataIndex = getCurrentMapDataIndex( mapData.config.id );
let mapDataIndex = getCurrentMapDataIndex(mapData.config.id);
if(mapDataIndex !== false){
Init.currentMapData[mapDataIndex].config = mapData.config;
@@ -2424,8 +2483,8 @@ define([
let filterCurrentMapData = (path, value) => {
let currentMapData = getCurrentMapData();
if(currentMapData){
currentMapData = currentMapData.filter((mapData) => {
return (getObjVal(mapData, path) === value);
currentMapData = currentMapData.filter(mapData => {
return getObjVal(mapData, path) === value;
});
}
return currentMapData;
@@ -2436,7 +2495,7 @@ define([
* @param mapId
*/
let deleteCurrentMapData = mapId => {
Init.currentMapData = Init.currentMapData.filter((mapData) => {
Init.currentMapData = Init.currentMapData.filter(mapData => {
return (mapData.config.id !== mapId);
});
};
@@ -2445,20 +2504,7 @@ define([
* get the current log data for the current user character
* @returns {boolean}
*/
let getCurrentCharacterLog = () => {
let characterLog = false;
let currentUserData = getCurrentUserData();
if(
currentUserData &&
currentUserData.character &&
currentUserData.character.log
){
characterLog = currentUserData.character.log;
}
return characterLog;
};
let getCurrentCharacterLog = () => getObjVal(getCurrentUserData(), 'character.log') || false;
/**
* get information for the current mail user
@@ -2793,28 +2839,16 @@ define([
return Init.currentSystemData;
};
/**
* set current location data
* -> system data where current user is located
* @param systemId
* @param systemName
*/
let setCurrentLocationData = (systemId, systemName) => {
let locationLink = $('#' + config.headCurrentLocationId).find('a');
locationLink.data('systemId', systemId);
locationLink.data('systemName', systemName);
};
/**
* get current location data
* -> system data where current user is located
* @returns {{id: *, name: *}}
*/
let getCurrentLocationData = () => {
let locationLink = $('#' + config.headCurrentLocationId).find('a');
let breadcrumbElement = $('#' + config.headUserLocationId + '>li:last-of-type');
return {
id: locationLink.data('systemId') || 0,
name: locationLink.data('systemName') || false
id: parseInt(breadcrumbElement.attr('data-systemId')) || 0,
name: breadcrumbElement.attr('data-systemName') || false
};
};
@@ -3056,6 +3090,18 @@ define([
*/
let isDomElement = obj => !!(obj && obj.nodeType === 1);
/**
* converts array of objects into object with properties
* @param array
* @param keyField
* @returns {*}
*/
let arrayToObject = (array, keyField = 'id') =>
array.reduce((obj, item) => {
obj[item[keyField]] = item;
return obj;
}, {});
/**
* get deep json object value if exists
* -> e.g. key = 'first.last.third' string
@@ -3204,6 +3250,7 @@ define([
setSyncStatus: setSyncStatus,
getSyncType: getSyncType,
isXHRAborted: isXHRAborted,
triggerMenuAction: triggerMenuAction,
getLabelByRole: getLabelByRole,
getMapElementFromOverlay: getMapElementFromOverlay,
getMapModule: getMapModule,
@@ -3233,7 +3280,6 @@ define([
getCurrentCharacterId: getCurrentCharacterId,
setCurrentSystemData: setCurrentSystemData,
getCurrentSystemData: getCurrentSystemData,
setCurrentLocationData: setCurrentLocationData,
getCurrentLocationData: getCurrentLocationData,
getCurrentUserInfo: getCurrentUserInfo,
getCurrentCharacterLog: getCurrentCharacterLog,
@@ -3262,6 +3308,7 @@ define([
htmlDecode: htmlDecode,
isValidHtml: isValidHtml,
isDomElement: isDomElement,
arrayToObject: arrayToObject,
getObjVal: getObjVal,
redirect: redirect,
logout: logout,

View File

@@ -12,14 +12,14 @@ let ports = [];
let characterPorts = [];
// init "WebSocket" connection ========================================================================================
let initSocket = (uri) => {
let initSocket = uri => {
let MsgWorkerOpen = new MsgWorker('ws:open');
if(socket === null){
socket = new WebSocket(uri);
// "WebSocket" open -----------------------------------------------------------------------
socket.onopen = (e) => {
socket.onopen = e => {
MsgWorkerOpen.meta({
readyState: socket.readyState
});
@@ -28,7 +28,7 @@ let initSocket = (uri) => {
};
// "WebSocket message ---------------------------------------------------------------------
socket.onmessage = (e) => {
socket.onmessage = e => {
let response = JSON.parse(e.data);
let MsgWorkerSend = new MsgWorker('ws:send');
@@ -43,7 +43,7 @@ let initSocket = (uri) => {
};
// "WebSocket" close ----------------------------------------------------------------------
socket.onclose = (closeEvent) => {
socket.onclose = closeEvent => {
let MsgWorkerClosed = new MsgWorker('ws:closed');
MsgWorkerClosed.meta({
readyState: socket.readyState,
@@ -57,7 +57,7 @@ let initSocket = (uri) => {
};
// "WebSocket" error ----------------------------------------------------------------------
socket.onerror = (e) => {
socket.onerror = e => {
let MsgWorkerError = new MsgWorker('ws:error');
MsgWorkerError.meta({
readyState: socket.readyState
@@ -75,11 +75,11 @@ let initSocket = (uri) => {
};
// send message to port(s) ============================================================================================
let sendToCurrentPort = (load) => {
let sendToCurrentPort = load => {
ports[ports.length - 1].postMessage(load);
};
let broadcastPorts = (load) => {
let broadcastPorts = load => {
// default: sent to all ports
let sentToPorts = ports;
@@ -114,7 +114,7 @@ let addPort = (port, characterId) => {
}
};
let getPortsByCharacterIds = (characterIds) => {
let getPortsByCharacterIds = characterIds => {
let ports = [];
for(let i = 0; i < characterPorts.length; i++){
@@ -128,8 +128,37 @@ let getPortsByCharacterIds = (characterIds) => {
return ports;
};
/**
*
* @param port
* @returns {int[]}
*/
let removePort = port => {
let characterIds = [];
// reverse loop required because of array index reset after splice()
let i = characterPorts.length;
while(i--){
if(characterPorts[i].port === port){
// collectt all character Ids mapped to the removed port
characterIds.push(characterPorts[i].characterId);
characterPorts.splice(i, 1);
}
}
let j = ports.length;
while(j--){
if(ports[j] === port){
ports.splice(j, 1);
}
}
// return unique characterIds
return [...new Set(characterIds)];
};
// "SharedWorker" connection ==========================================================================================
self.addEventListener('connect', (event) => { // jshint ignore:line
self.addEventListener('connect', event => { // jshint ignore:line
let port = event.ports[0];
addPort(port);
@@ -145,12 +174,28 @@ self.addEventListener('connect', (event) => { // jshint ignore:line
initSocket(data.uri);
break;
case 'ws:send':
let MsgSocket = {
socket.send(JSON.stringify({
task: MsgWorkerMessage.task(),
load: MsgWorkerMessage.data()
};
}));
break;
case 'sw:closePort':
port.close();
socket.send(JSON.stringify(MsgSocket));
// remove port from store
// -> charIds managed by closed port
let characterIds = removePort(port);
// check if there are still other ports active that manage removed ports
// .. if not -> send "unsubscribe" event to WebSocket server
let portsLeft = getPortsByCharacterIds(characterIds);
if(!portsLeft.length){
socket.send(JSON.stringify({
task: MsgWorkerMessage.task(),
load: characterIds
}));
}
break;
case 'ws:close':
// closeSocket();

File diff suppressed because one or more lines are too long

View File

@@ -1,35 +0,0 @@
/*!
Buttons for DataTables 1.2.1
©2016 SpryMedia Ltd - datatables.net/license
*/
(function(d){"function"===typeof define&&define.amd?define(["jquery","datatables.net"],function(o){return d(o,window,document)}):"object"===typeof exports?module.exports=function(o,n){o||(o=window);if(!n||!n.fn.dataTable)n=require("datatables.net")(o,n).$;return d(n,o,o.document)}:d(jQuery,window,document)})(function(d,o,n,l){var i=d.fn.dataTable,u=0,v=0,k=i.ext.buttons,m=function(a,b){!0===b&&(b={});d.isArray(b)&&(b={buttons:b});this.c=d.extend(!0,{},m.defaults,b);b.buttons&&(this.c.buttons=b.buttons);
this.s={dt:new i.Api(a),buttons:[],listenKeys:"",namespace:"dtb"+u++};this.dom={container:d("<"+this.c.dom.container.tag+"/>").addClass(this.c.dom.container.className)};this._constructor()};d.extend(m.prototype,{action:function(a,b){var c=this._nodeToButton(a);if(b===l)return c.conf.action;c.conf.action=b;return this},active:function(a,b){var c=this._nodeToButton(a),e=this.c.dom.button.active,c=d(c.node);if(b===l)return c.hasClass(e);c.toggleClass(e,b===l?!0:b);return this},add:function(a,b){var c=
this.s.buttons;if("string"===typeof b){for(var e=b.split("-"),c=this.s,d=0,h=e.length-1;d<h;d++)c=c.buttons[1*e[d]];c=c.buttons;b=1*e[e.length-1]}this._expandButton(c,a,!1,b);this._draw();return this},container:function(){return this.dom.container},disable:function(a){a=this._nodeToButton(a);d(a.node).addClass(this.c.dom.button.disabled);return this},destroy:function(){d("body").off("keyup."+this.s.namespace);var a=this.s.buttons.slice(),b,c;b=0;for(c=a.length;b<c;b++)this.remove(a[b].node);this.dom.container.remove();
a=this.s.dt.settings()[0];b=0;for(c=a.length;b<c;b++)if(a.inst===this){a.splice(b,1);break}return this},enable:function(a,b){if(!1===b)return this.disable(a);var c=this._nodeToButton(a);d(c.node).removeClass(this.c.dom.button.disabled);return this},name:function(){return this.c.name},node:function(a){a=this._nodeToButton(a);return d(a.node)},remove:function(a){var b=this._nodeToButton(a),c=this._nodeToHost(a),e=this.s.dt;if(b.buttons.length)for(var g=b.buttons.length-1;0<=g;g--)this.remove(b.buttons[g].node);
b.conf.destroy&&b.conf.destroy.call(e.button(a),e,d(a),b.conf);this._removeKey(b.conf);d(b.node).remove();a=d.inArray(b,c);c.splice(a,1);return this},text:function(a,b){var c=this._nodeToButton(a),e=this.c.dom.collection.buttonLiner,e=c.inCollection&&e&&e.tag?e.tag:this.c.dom.buttonLiner.tag,g=this.s.dt,h=d(c.node),f=function(a){return"function"===typeof a?a(g,h,c.conf):a};if(b===l)return f(c.conf.text);c.conf.text=b;e?h.children(e).html(f(b)):h.html(f(b));return this},_constructor:function(){var a=
this,b=this.s.dt,c=b.settings()[0],e=this.c.buttons;c._buttons||(c._buttons=[]);c._buttons.push({inst:this,name:this.c.name});for(var c=0,g=e.length;c<g;c++)this.add(e[c]);b.on("destroy",function(){a.destroy()});d("body").on("keyup."+this.s.namespace,function(b){if(!n.activeElement||n.activeElement===n.body){var c=String.fromCharCode(b.keyCode).toLowerCase();a.s.listenKeys.toLowerCase().indexOf(c)!==-1&&a._keypress(c,b)}})},_addKey:function(a){a.key&&(this.s.listenKeys+=d.isPlainObject(a.key)?a.key.key:
a.key)},_draw:function(a,b){a||(a=this.dom.container,b=this.s.buttons);a.children().detach();for(var c=0,d=b.length;c<d;c++)a.append(b[c].inserter),b[c].buttons&&b[c].buttons.length&&this._draw(b[c].collection,b[c].buttons)},_expandButton:function(a,b,c,e){for(var g=this.s.dt,h=0,b=!d.isArray(b)?[b]:b,f=0,q=b.length;f<q;f++){var j=this._resolveExtends(b[f]);if(j)if(d.isArray(j))this._expandButton(a,j,c,e);else{var p=this._buildButton(j,c);if(p){e!==l?(a.splice(e,0,p),e++):a.push(p);if(p.conf.buttons){var s=
this.c.dom.collection;p.collection=d("<"+s.tag+"/>").addClass(s.className);p.conf._collection=p.collection;this._expandButton(p.buttons,p.conf.buttons,!0,e)}j.init&&j.init.call(g.button(p.node),g,d(p.node),j);h++}}}},_buildButton:function(a,b){var c=this.c.dom.button,e=this.c.dom.buttonLiner,g=this.c.dom.collection,h=this.s.dt,f=function(b){return"function"===typeof b?b(h,j,a):b};b&&g.button&&(c=g.button);b&&g.buttonLiner&&(e=g.buttonLiner);if(a.available&&!a.available(h,a))return!1;var q=function(a,
b,c,e){e.action.call(b.button(c),a,b,c,e);d(b.table().node()).triggerHandler("buttons-action.dt",[b.button(c),b,c,e])},j=d("<"+c.tag+"/>").addClass(c.className).attr("tabindex",this.s.dt.settings()[0].iTabIndex).attr("aria-controls",this.s.dt.table().node().id).on("click.dtb",function(b){b.preventDefault();!j.hasClass(c.disabled)&&a.action&&q(b,h,j,a);j.blur()}).on("keyup.dtb",function(b){b.keyCode===13&&!j.hasClass(c.disabled)&&a.action&&q(b,h,j,a)});"a"===c.tag.toLowerCase()&&j.attr("href","#");
e.tag?(g=d("<"+e.tag+"/>").html(f(a.text)).addClass(e.className),"a"===e.tag.toLowerCase()&&g.attr("href","#"),j.append(g)):j.html(f(a.text));!1===a.enabled&&j.addClass(c.disabled);a.className&&j.addClass(a.className);a.titleAttr&&j.attr("title",a.titleAttr);a.namespace||(a.namespace=".dt-button-"+v++);e=(e=this.c.dom.buttonContainer)&&e.tag?d("<"+e.tag+"/>").addClass(e.className).append(j):j;this._addKey(a);return{conf:a,node:j.get(0),inserter:e,buttons:[],inCollection:b,collection:null}},_nodeToButton:function(a,
b){b||(b=this.s.buttons);for(var c=0,d=b.length;c<d;c++){if(b[c].node===a)return b[c];if(b[c].buttons.length){var g=this._nodeToButton(a,b[c].buttons);if(g)return g}}},_nodeToHost:function(a,b){b||(b=this.s.buttons);for(var c=0,d=b.length;c<d;c++){if(b[c].node===a)return b;if(b[c].buttons.length){var g=this._nodeToHost(a,b[c].buttons);if(g)return g}}},_keypress:function(a,b){var c=function(e){for(var g=0,h=e.length;g<h;g++){var f=e[g].conf,q=e[g].node;if(f.key)if(f.key===a)d(q).click();else if(d.isPlainObject(f.key)&&
f.key.key===a&&(!f.key.shiftKey||b.shiftKey))if(!f.key.altKey||b.altKey)if(!f.key.ctrlKey||b.ctrlKey)(!f.key.metaKey||b.metaKey)&&d(q).click();e[g].buttons.length&&c(e[g].buttons)}};c(this.s.buttons)},_removeKey:function(a){if(a.key){var b=d.isPlainObject(a.key)?a.key.key:a.key,a=this.s.listenKeys.split(""),b=d.inArray(b,a);a.splice(b,1);this.s.listenKeys=a.join("")}},_resolveExtends:function(a){for(var b=this.s.dt,c,e,g=function(c){for(var e=0;!d.isPlainObject(c)&&!d.isArray(c);){if(c===l)return;
if("function"===typeof c){if(c=c(b,a),!c)return!1}else if("string"===typeof c){if(!k[c])throw"Unknown button type: "+c;c=k[c]}e++;if(30<e)throw"Buttons: Too many iterations";}return d.isArray(c)?c:d.extend({},c)},a=g(a);a&&a.extend;){if(!k[a.extend])throw"Cannot extend unknown button type: "+a.extend;var h=g(k[a.extend]);if(d.isArray(h))return h;if(!h)return!1;c=h.className;a=d.extend({},h,a);c&&a.className!==c&&(a.className=c+" "+a.className);var f=a.postfixButtons;if(f){a.buttons||(a.buttons=[]);
c=0;for(e=f.length;c<e;c++)a.buttons.push(f[c]);a.postfixButtons=null}if(f=a.prefixButtons){a.buttons||(a.buttons=[]);c=0;for(e=f.length;c<e;c++)a.buttons.splice(c,0,f[c]);a.prefixButtons=null}a.extend=h.extend}return a}});m.background=function(a,b,c){c===l&&(c=400);a?d("<div/>").addClass(b).css("display","none").appendTo("body").fadeIn(c):d("body > div."+b).fadeOut(c,function(){d(this).remove()})};m.instanceSelector=function(a,b){if(!a)return d.map(b,function(a){return a.inst});var c=[],e=d.map(b,
function(a){return a.name}),g=function(a){if(d.isArray(a))for(var f=0,q=a.length;f<q;f++)g(a[f]);else"string"===typeof a?-1!==a.indexOf(",")?g(a.split(",")):(a=d.inArray(d.trim(a),e),-1!==a&&c.push(b[a].inst)):"number"===typeof a&&c.push(b[a].inst)};g(a);return c};m.buttonSelector=function(a,b){for(var c=[],e=function(a,b,c){for(var d,g,f=0,h=b.length;f<h;f++)if(d=b[f])g=c!==l?c+f:f+"",a.push({node:d.node,name:d.conf.name,idx:g}),d.buttons&&e(a,d.buttons,g+"-")},g=function(a,b){var f,h,i=[];e(i,b.s.buttons);
f=d.map(i,function(a){return a.node});if(d.isArray(a)||a instanceof d){f=0;for(h=a.length;f<h;f++)g(a[f],b)}else if(null===a||a===l||"*"===a){f=0;for(h=i.length;f<h;f++)c.push({inst:b,node:i[f].node})}else if("number"===typeof a)c.push({inst:b,node:b.s.buttons[a].node});else if("string"===typeof a)if(-1!==a.indexOf(",")){i=a.split(",");f=0;for(h=i.length;f<h;f++)g(d.trim(i[f]),b)}else if(a.match(/^\d+(\-\d+)*$/))f=d.map(i,function(a){return a.idx}),c.push({inst:b,node:i[d.inArray(a,f)].node});else if(-1!==
a.indexOf(":name")){var k=a.replace(":name","");f=0;for(h=i.length;f<h;f++)i[f].name===k&&c.push({inst:b,node:i[f].node})}else d(f).filter(a).each(function(){c.push({inst:b,node:this})});else"object"===typeof a&&a.nodeName&&(i=d.inArray(a,f),-1!==i&&c.push({inst:b,node:f[i]}))},h=0,f=a.length;h<f;h++)g(b,a[h]);return c};m.defaults={buttons:["copy","excel","csv","pdf","print"],name:"main",tabIndex:0,dom:{container:{tag:"div",className:"dt-buttons"},collection:{tag:"div",className:"dt-button-collection"},
button:{tag:"a",className:"dt-button",active:"active",disabled:"disabled"},buttonLiner:{tag:"span",className:""}}};m.version="1.2.1";d.extend(k,{collection:{text:function(a){return a.i18n("buttons.collection","Collection")},className:"buttons-collection",action:function(a,b,c,e){var a=c.offset(),g=d(b.table().container()),h=!1;d("div.dt-button-background").length&&(h=d("div.dt-button-collection").offset(),d("body").trigger("click.dtb-collection"));e._collection.addClass(e.collectionLayout).css("display",
"none").appendTo("body").fadeIn(e.fade);var f=e._collection.css("position");h&&"absolute"===f?e._collection.css({top:h.top+5,left:h.left+5}):"absolute"===f?(e._collection.css({top:a.top+c.outerHeight(),left:a.left}),c=a.left+e._collection.outerWidth(),g=g.offset().left+g.width(),c>g&&e._collection.css("left",a.left-(c-g))):(a=e._collection.height()/2,a>d(o).height()/2&&(a=d(o).height()/2),e._collection.css("marginTop",-1*a));e.background&&m.background(!0,e.backgroundClassName,e.fade);setTimeout(function(){d("div.dt-button-background").on("click.dtb-collection",
function(){});d("body").on("click.dtb-collection",function(a){if(!d(a.target).parents().andSelf().filter(e._collection).length){e._collection.fadeOut(e.fade,function(){e._collection.detach()});d("div.dt-button-background").off("click.dtb-collection");m.background(false,e.backgroundClassName,e.fade);d("body").off("click.dtb-collection");b.off("buttons-action.b-internal")}})},10);if(e.autoClose)b.on("buttons-action.b-internal",function(){d("div.dt-button-background").click()})},background:!0,collectionLayout:"",
backgroundClassName:"dt-button-background",autoClose:!1,fade:400},copy:function(a,b){if(k.copyHtml5)return"copyHtml5";if(k.copyFlash&&k.copyFlash.available(a,b))return"copyFlash"},csv:function(a,b){if(k.csvHtml5&&k.csvHtml5.available(a,b))return"csvHtml5";if(k.csvFlash&&k.csvFlash.available(a,b))return"csvFlash"},excel:function(a,b){if(k.excelHtml5&&k.excelHtml5.available(a,b))return"excelHtml5";if(k.excelFlash&&k.excelFlash.available(a,b))return"excelFlash"},pdf:function(a,b){if(k.pdfHtml5&&k.pdfHtml5.available(a,
b))return"pdfHtml5";if(k.pdfFlash&&k.pdfFlash.available(a,b))return"pdfFlash"},pageLength:function(a){var a=a.settings()[0].aLengthMenu,b=d.isArray(a[0])?a[0]:a,c=d.isArray(a[0])?a[1]:a,e=function(a){return a.i18n("buttons.pageLength",{"-1":"Show all rows",_:"Show %d rows"},a.page.len())};return{extend:"collection",text:e,className:"buttons-page-length",autoClose:!0,buttons:d.map(b,function(a,b){return{text:c[b],action:function(b,c){c.page.len(a).draw()},init:function(b,c,d){var e=this,c=function(){e.active(b.page.len()===
a)};b.on("length.dt"+d.namespace,c);c()},destroy:function(a,b,c){a.off("length.dt"+c.namespace)}}}),init:function(a,b,c){var d=this;a.on("length.dt"+c.namespace,function(){d.text(e(a))})},destroy:function(a,b,c){a.off("length.dt"+c.namespace)}}}});i.Api.register("buttons()",function(a,b){b===l&&(b=a,a=l);return this.iterator(!0,"table",function(c){if(c._buttons)return m.buttonSelector(m.instanceSelector(a,c._buttons),b)},!0)});i.Api.register("button()",function(a,b){var c=this.buttons(a,b);1<c.length&&
c.splice(1,c.length);return c});i.Api.registerPlural("buttons().active()","button().active()",function(a){return a===l?this.map(function(a){return a.inst.active(a.node)}):this.each(function(b){b.inst.active(b.node,a)})});i.Api.registerPlural("buttons().action()","button().action()",function(a){return a===l?this.map(function(a){return a.inst.action(a.node)}):this.each(function(b){b.inst.action(b.node,a)})});i.Api.register(["buttons().enable()","button().enable()"],function(a){return this.each(function(b){b.inst.enable(b.node,
a)})});i.Api.register(["buttons().disable()","button().disable()"],function(){return this.each(function(a){a.inst.disable(a.node)})});i.Api.registerPlural("buttons().nodes()","button().node()",function(){var a=d();d(this.each(function(b){a=a.add(b.inst.node(b.node))}));return a});i.Api.registerPlural("buttons().text()","button().text()",function(a){return a===l?this.map(function(a){return a.inst.text(a.node)}):this.each(function(b){b.inst.text(b.node,a)})});i.Api.registerPlural("buttons().trigger()",
"button().trigger()",function(){return this.each(function(a){a.inst.node(a.node).trigger("click")})});i.Api.registerPlural("buttons().containers()","buttons().container()",function(){var a=d();d(this.each(function(b){a=a.add(b.inst.container())}));return a});i.Api.register("button().add()",function(a,b){1===this.length&&this[0].inst.add(b,a);return this.button(a)});i.Api.register("buttons().destroy()",function(){this.pluck("inst").unique().each(function(a){a.destroy()});return this});i.Api.registerPlural("buttons().remove()",
"buttons().remove()",function(){this.each(function(a){a.inst.remove(a.node)});return this});var r;i.Api.register("buttons.info()",function(a,b,c){var e=this;if(!1===a)return d("#datatables_buttons_info").fadeOut(function(){d(this).remove()}),clearTimeout(r),r=null,this;r&&clearTimeout(r);d("#datatables_buttons_info").length&&d("#datatables_buttons_info").remove();d('<div id="datatables_buttons_info" class="dt-button-info"/>').html(a?"<h2>"+a+"</h2>":"").append(d("<div/>")["string"===typeof b?"html":
"append"](b)).css("display","none").appendTo("body").fadeIn();c!==l&&0!==c&&(r=setTimeout(function(){e.buttons.info(!1)},c));return this});i.Api.register("buttons.exportData()",function(a){if(this.context.length){for(var b=new i.Api(this.context[0]),c=d.extend(!0,{},{rows:null,columns:"",modifier:{search:"applied",order:"applied"},orthogonal:"display",stripHtml:!0,stripNewlines:!0,decodeEntities:!0,trim:!0,format:{header:function(a){return e(a)},footer:function(a){return e(a)},body:function(a){return e(a)}}},
a),e=function(a){if("string"!==typeof a)return a;c.stripHtml&&(a=a.replace(/<[^>]*>/g,""));c.trim&&(a=a.replace(/^\s+|\s+$/g,""));c.stripNewlines&&(a=a.replace(/\n/g," "));c.decodeEntities&&(t.innerHTML=a,a=t.value);return a},a=b.columns(c.columns).indexes().map(function(a){return c.format.header(b.column(a).header().innerHTML,a)}).toArray(),g=b.table().footer()?b.columns(c.columns).indexes().map(function(a){var d=b.column(a).footer();return c.format.footer(d?d.innerHTML:"",a)}).toArray():null,h=
b.rows(c.rows,c.modifier).indexes().toArray(),h=b.cells(h,c.columns).render(c.orthogonal).toArray(),f=a.length,k=0<f?h.length/f:0,j=Array(k),m=0,l=0;l<k;l++){for(var o=Array(f),n=0;n<f;n++)o[n]=c.format.body(h[m],n,l),m++;j[l]=o}return{header:a,footer:g,body:j}}});var t=d("<textarea/>")[0];d.fn.dataTable.Buttons=m;d.fn.DataTable.Buttons=m;d(n).on("init.dt plugin-init.dt",function(a,b){if("dt"===a.namespace){var c=b.oInit.buttons||i.defaults.buttons;c&&!b._buttons&&(new m(b,c)).container()}});i.ext.feature.push({fnInit:function(a){var a=
new i.Api(a),b=a.init().buttons||i.defaults.buttons;return(new m(a,b)).container()},cFeature:"B"});return m});

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,45 @@
/*!
Buttons for DataTables 1.5.6
©2016-2019 SpryMedia Ltd - datatables.net/license
*/
var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.findInternal=function(d,q,n){d instanceof String&&(d=String(d));for(var l=d.length,u=0;u<l;u++){var p=d[u];if(q.call(n,p,u,d))return{i:u,v:p}}return{i:-1,v:void 0}};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.SIMPLE_FROUND_POLYFILL=!1;
$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(d,q,n){d!=Array.prototype&&d!=Object.prototype&&(d[q]=n.value)};$jscomp.getGlobal=function(d){return"undefined"!=typeof window&&window===d?d:"undefined"!=typeof global&&null!=global?global:d};$jscomp.global=$jscomp.getGlobal(this);
$jscomp.polyfill=function(d,q,n,l){if(q){n=$jscomp.global;d=d.split(".");for(l=0;l<d.length-1;l++){var u=d[l];u in n||(n[u]={});n=n[u]}d=d[d.length-1];l=n[d];q=q(l);q!=l&&null!=q&&$jscomp.defineProperty(n,d,{configurable:!0,writable:!0,value:q})}};$jscomp.polyfill("Array.prototype.find",function(d){return d?d:function(d,n){return $jscomp.findInternal(this,d,n).v}},"es6","es3");
(function(d){"function"===typeof define&&define.amd?define(["jquery","datatables.net"],function(q){return d(q,window,document)}):"object"===typeof exports?module.exports=function(q,n){q||(q=window);n&&n.fn.dataTable||(n=require("datatables.net")(q,n).$);return d(n,q,q.document)}:d(jQuery,window,document)})(function(d,q,n,l){function u(a){a=new p.Api(a);var b=a.init().buttons||p.defaults.buttons;return(new t(a,b)).container()}var p=d.fn.dataTable,B=0,C=0,r=p.ext.buttons,t=function(a,b){if(!(this instanceof
t))return function(b){return(new t(b,a)).container()};"undefined"===typeof b&&(b={});!0===b&&(b={});d.isArray(b)&&(b={buttons:b});this.c=d.extend(!0,{},t.defaults,b);b.buttons&&(this.c.buttons=b.buttons);this.s={dt:new p.Api(a),buttons:[],listenKeys:"",namespace:"dtb"+B++};this.dom={container:d("<"+this.c.dom.container.tag+"/>").addClass(this.c.dom.container.className)};this._constructor()};d.extend(t.prototype,{action:function(a,b){a=this._nodeToButton(a);if(b===l)return a.conf.action;a.conf.action=
b;return this},active:function(a,b){var c=this._nodeToButton(a);a=this.c.dom.button.active;c=d(c.node);if(b===l)return c.hasClass(a);c.toggleClass(a,b===l?!0:b);return this},add:function(a,b){var c=this.s.buttons;if("string"===typeof b){b=b.split("-");c=this.s;for(var d=0,f=b.length-1;d<f;d++)c=c.buttons[1*b[d]];c=c.buttons;b=1*b[b.length-1]}this._expandButton(c,a,!1,b);this._draw();return this},container:function(){return this.dom.container},disable:function(a){a=this._nodeToButton(a);d(a.node).addClass(this.c.dom.button.disabled);
return this},destroy:function(){d("body").off("keyup."+this.s.namespace);var a=this.s.buttons.slice(),b;var c=0;for(b=a.length;c<b;c++)this.remove(a[c].node);this.dom.container.remove();a=this.s.dt.settings()[0];c=0;for(b=a.length;c<b;c++)if(a.inst===this){a.splice(c,1);break}return this},enable:function(a,b){if(!1===b)return this.disable(a);a=this._nodeToButton(a);d(a.node).removeClass(this.c.dom.button.disabled);return this},name:function(){return this.c.name},node:function(a){if(!a)return this.dom.container;
a=this._nodeToButton(a);return d(a.node)},processing:function(a,b){a=this._nodeToButton(a);if(b===l)return d(a.node).hasClass("processing");d(a.node).toggleClass("processing",b);return this},remove:function(a){var b=this._nodeToButton(a),c=this._nodeToHost(a),e=this.s.dt;if(b.buttons.length)for(var f=b.buttons.length-1;0<=f;f--)this.remove(b.buttons[f].node);b.conf.destroy&&b.conf.destroy.call(e.button(a),e,d(a),b.conf);this._removeKey(b.conf);d(b.node).remove();a=d.inArray(b,c);c.splice(a,1);return this},
text:function(a,b){var c=this._nodeToButton(a);a=this.c.dom.collection.buttonLiner;a=c.inCollection&&a&&a.tag?a.tag:this.c.dom.buttonLiner.tag;var e=this.s.dt,f=d(c.node),g=function(a){return"function"===typeof a?a(e,f,c.conf):a};if(b===l)return g(c.conf.text);c.conf.text=b;a?f.children(a).html(g(b)):f.html(g(b));return this},_constructor:function(){var a=this,b=this.s.dt,c=b.settings()[0],e=this.c.buttons;c._buttons||(c._buttons=[]);c._buttons.push({inst:this,name:this.c.name});for(var f=0,g=e.length;f<
g;f++)this.add(e[f]);b.on("destroy",function(b,d){d===c&&a.destroy()});d("body").on("keyup."+this.s.namespace,function(b){if(!n.activeElement||n.activeElement===n.body){var c=String.fromCharCode(b.keyCode).toLowerCase();-1!==a.s.listenKeys.toLowerCase().indexOf(c)&&a._keypress(c,b)}})},_addKey:function(a){a.key&&(this.s.listenKeys+=d.isPlainObject(a.key)?a.key.key:a.key)},_draw:function(a,b){a||(a=this.dom.container,b=this.s.buttons);a.children().detach();for(var c=0,d=b.length;c<d;c++)a.append(b[c].inserter),
a.append(" "),b[c].buttons&&b[c].buttons.length&&this._draw(b[c].collection,b[c].buttons)},_expandButton:function(a,b,c,e){var f=this.s.dt,g=0;b=d.isArray(b)?b:[b];for(var h=0,k=b.length;h<k;h++){var v=this._resolveExtends(b[h]);if(v)if(d.isArray(v))this._expandButton(a,v,c,e);else{var m=this._buildButton(v,c);if(m){e!==l?(a.splice(e,0,m),e++):a.push(m);if(m.conf.buttons){var y=this.c.dom.collection;m.collection=d("<"+y.tag+"/>").addClass(y.className).attr("role","menu");m.conf._collection=m.collection;
this._expandButton(m.buttons,m.conf.buttons,!0,e)}v.init&&v.init.call(f.button(m.node),f,d(m.node),v);g++}}}},_buildButton:function(a,b){var c=this.c.dom.button,e=this.c.dom.buttonLiner,f=this.c.dom.collection,g=this.s.dt,h=function(b){return"function"===typeof b?b(g,m,a):b};b&&f.button&&(c=f.button);b&&f.buttonLiner&&(e=f.buttonLiner);if(a.available&&!a.available(g,a))return!1;var k=function(a,b,c,e){e.action.call(b.button(c),a,b,c,e);d(b.table().node()).triggerHandler("buttons-action.dt",[b.button(c),
b,c,e])};f=a.tag||c.tag;var v=a.clickBlurs===l?!0:a.clickBlurs,m=d("<"+f+"/>").addClass(c.className).attr("tabindex",this.s.dt.settings()[0].iTabIndex).attr("aria-controls",this.s.dt.table().node().id).on("click.dtb",function(b){b.preventDefault();!m.hasClass(c.disabled)&&a.action&&k(b,g,m,a);v&&m.blur()}).on("keyup.dtb",function(b){13===b.keyCode&&!m.hasClass(c.disabled)&&a.action&&k(b,g,m,a)});"a"===f.toLowerCase()&&m.attr("href","#");"button"===f.toLowerCase()&&m.attr("type","button");e.tag?(f=
d("<"+e.tag+"/>").html(h(a.text)).addClass(e.className),"a"===e.tag.toLowerCase()&&f.attr("href","#"),m.append(f)):m.html(h(a.text));!1===a.enabled&&m.addClass(c.disabled);a.className&&m.addClass(a.className);a.titleAttr&&m.attr("title",h(a.titleAttr));a.attr&&m.attr(a.attr);a.namespace||(a.namespace=".dt-button-"+C++);e=(e=this.c.dom.buttonContainer)&&e.tag?d("<"+e.tag+"/>").addClass(e.className).append(m):m;this._addKey(a);this.c.buttonCreated&&(e=this.c.buttonCreated(a,e));return{conf:a,node:m.get(0),
inserter:e,buttons:[],inCollection:b,collection:null}},_nodeToButton:function(a,b){b||(b=this.s.buttons);for(var c=0,d=b.length;c<d;c++){if(b[c].node===a)return b[c];if(b[c].buttons.length){var f=this._nodeToButton(a,b[c].buttons);if(f)return f}}},_nodeToHost:function(a,b){b||(b=this.s.buttons);for(var c=0,d=b.length;c<d;c++){if(b[c].node===a)return b;if(b[c].buttons.length){var f=this._nodeToHost(a,b[c].buttons);if(f)return f}}},_keypress:function(a,b){if(!b._buttonsHandled){var c=function(e){for(var f=
0,g=e.length;f<g;f++){var h=e[f].conf,k=e[f].node;h.key&&(h.key===a?(b._buttonsHandled=!0,d(k).click()):!d.isPlainObject(h.key)||h.key.key!==a||h.key.shiftKey&&!b.shiftKey||h.key.altKey&&!b.altKey||h.key.ctrlKey&&!b.ctrlKey||h.key.metaKey&&!b.metaKey||(b._buttonsHandled=!0,d(k).click()));e[f].buttons.length&&c(e[f].buttons)}};c(this.s.buttons)}},_removeKey:function(a){if(a.key){var b=d.isPlainObject(a.key)?a.key.key:a.key;a=this.s.listenKeys.split("");b=d.inArray(b,a);a.splice(b,1);this.s.listenKeys=
a.join("")}},_resolveExtends:function(a){var b=this.s.dt,c,e=function(c){for(var e=0;!d.isPlainObject(c)&&!d.isArray(c);){if(c===l)return;if("function"===typeof c){if(c=c(b,a),!c)return!1}else if("string"===typeof c){if(!r[c])throw"Unknown button type: "+c;c=r[c]}e++;if(30<e)throw"Buttons: Too many iterations";}return d.isArray(c)?c:d.extend({},c)};for(a=e(a);a&&a.extend;){if(!r[a.extend])throw"Cannot extend unknown button type: "+a.extend;var f=e(r[a.extend]);if(d.isArray(f))return f;if(!f)return!1;
var g=f.className;a=d.extend({},f,a);g&&a.className!==g&&(a.className=g+" "+a.className);var h=a.postfixButtons;if(h){a.buttons||(a.buttons=[]);g=0;for(c=h.length;g<c;g++)a.buttons.push(h[g]);a.postfixButtons=null}if(h=a.prefixButtons){a.buttons||(a.buttons=[]);g=0;for(c=h.length;g<c;g++)a.buttons.splice(g,0,h[g]);a.prefixButtons=null}a.extend=f.extend}return a}});t.background=function(a,b,c,e){c===l&&(c=400);e||(e=n.body);a?d("<div/>").addClass(b).css("display","none").insertAfter(e).stop().fadeIn(c):
d("div."+b).stop().fadeOut(c,function(){d(this).removeClass(b).remove()})};t.instanceSelector=function(a,b){if(!a)return d.map(b,function(a){return a.inst});var c=[],e=d.map(b,function(a){return a.name}),f=function(a){if(d.isArray(a))for(var g=0,k=a.length;g<k;g++)f(a[g]);else"string"===typeof a?-1!==a.indexOf(",")?f(a.split(",")):(a=d.inArray(d.trim(a),e),-1!==a&&c.push(b[a].inst)):"number"===typeof a&&c.push(b[a].inst)};f(a);return c};t.buttonSelector=function(a,b){for(var c=[],e=function(a,b,c){for(var d,
f,g=0,k=b.length;g<k;g++)if(d=b[g])f=c!==l?c+g:g+"",a.push({node:d.node,name:d.conf.name,idx:f}),d.buttons&&e(a,d.buttons,f+"-")},f=function(a,b){var g,h=[];e(h,b.s.buttons);var k=d.map(h,function(a){return a.node});if(d.isArray(a)||a instanceof d)for(k=0,g=a.length;k<g;k++)f(a[k],b);else if(null===a||a===l||"*"===a)for(k=0,g=h.length;k<g;k++)c.push({inst:b,node:h[k].node});else if("number"===typeof a)c.push({inst:b,node:b.s.buttons[a].node});else if("string"===typeof a)if(-1!==a.indexOf(","))for(h=
a.split(","),k=0,g=h.length;k<g;k++)f(d.trim(h[k]),b);else if(a.match(/^\d+(\-\d+)*$/))k=d.map(h,function(a){return a.idx}),c.push({inst:b,node:h[d.inArray(a,k)].node});else if(-1!==a.indexOf(":name"))for(a=a.replace(":name",""),k=0,g=h.length;k<g;k++)h[k].name===a&&c.push({inst:b,node:h[k].node});else d(k).filter(a).each(function(){c.push({inst:b,node:this})});else"object"===typeof a&&a.nodeName&&(h=d.inArray(a,k),-1!==h&&c.push({inst:b,node:k[h]}))},g=0,h=a.length;g<h;g++)f(b,a[g]);return c};t.defaults=
{buttons:["copy","excel","csv","pdf","print"],name:"main",tabIndex:0,dom:{container:{tag:"div",className:"dt-buttons"},collection:{tag:"div",className:"dt-button-collection"},button:{tag:"ActiveXObject"in q?"a":"button",className:"dt-button",active:"active",disabled:"disabled"},buttonLiner:{tag:"span",className:""}}};t.version="1.5.6";d.extend(r,{collection:{text:function(a){return a.i18n("buttons.collection","Collection")},className:"buttons-collection",init:function(a,b,c){b.attr("aria-expanded",
!1)},action:function(a,b,c,e){var f=function(){b.buttons('[aria-haspopup="true"][aria-expanded="true"]').nodes().each(function(){var a=d(this).siblings(".dt-button-collection");a.length&&a.stop().fadeOut(e.fade,function(){a.detach()});d(this).attr("aria-expanded","false")});d("div.dt-button-background").off("click.dtb-collection");t.background(!1,e.backgroundClassName,e.fade,l);d("body").off(".dtb-collection");b.off("buttons-action.b-internal")};a="true"===c.attr("aria-expanded");f();if(!a){var g=
d(c).parents("div.dt-button-collection");a=c.position();var h=d(b.table().container()),k=!1,l=c;c.attr("aria-expanded","true");g.length&&(k=d(".dt-button-collection").position(),l=g,d("body").trigger("click.dtb-collection"));l.parents("body")[0]!==n.body&&(l=n.body.lastChild);e._collection.find(".dt-button-collection-title").remove();e._collection.prepend('<div class="dt-button-collection-title">'+e.collectionTitle+"</div>");e._collection.addClass(e.collectionLayout).css("display","none").insertAfter(l).stop().fadeIn(e.fade);
g=e._collection.css("position");if(k&&"absolute"===g)e._collection.css({top:k.top,left:k.left});else if("absolute"===g){e._collection.css({top:a.top+c.outerHeight(),left:a.left});k=h.offset().top+h.height();k=a.top+c.outerHeight()+e._collection.outerHeight()-k;g=a.top-e._collection.outerHeight();var m=h.offset().top;(k>m-g||e.dropup)&&e._collection.css("top",a.top-e._collection.outerHeight()-5);e._collection.hasClass(e.rightAlignClassName)&&e._collection.css("left",a.left+c.outerWidth()-e._collection.outerWidth());
k=a.left+e._collection.outerWidth();h=h.offset().left+h.width();k>h&&e._collection.css("left",a.left-(k-h));c=c.offset().left+e._collection.outerWidth();c>d(q).width()&&e._collection.css("left",a.left-(c-d(q).width()))}else c=e._collection.height()/2,c>d(q).height()/2&&(c=d(q).height()/2),e._collection.css("marginTop",-1*c);e.background&&t.background(!0,e.backgroundClassName,e.fade,l);setTimeout(function(){d("div.dt-button-background").on("click.dtb-collection",function(){});d("body").on("click.dtb-collection",
function(a){var b=d.fn.addBack?"addBack":"andSelf";d(a.target).parents()[b]().filter(e._collection).length||f()}).on("keyup.dtb-collection",function(a){27===a.keyCode&&f()});if(e.autoClose)b.on("buttons-action.b-internal",function(){f()})},10)}},background:!0,collectionLayout:"",collectionTitle:"",backgroundClassName:"dt-button-background",rightAlignClassName:"dt-button-right",autoClose:!1,fade:400,attr:{"aria-haspopup":!0}},copy:function(a,b){if(r.copyHtml5)return"copyHtml5";if(r.copyFlash&&r.copyFlash.available(a,
b))return"copyFlash"},csv:function(a,b){if(r.csvHtml5&&r.csvHtml5.available(a,b))return"csvHtml5";if(r.csvFlash&&r.csvFlash.available(a,b))return"csvFlash"},excel:function(a,b){if(r.excelHtml5&&r.excelHtml5.available(a,b))return"excelHtml5";if(r.excelFlash&&r.excelFlash.available(a,b))return"excelFlash"},pdf:function(a,b){if(r.pdfHtml5&&r.pdfHtml5.available(a,b))return"pdfHtml5";if(r.pdfFlash&&r.pdfFlash.available(a,b))return"pdfFlash"},pageLength:function(a){a=a.settings()[0].aLengthMenu;var b=d.isArray(a[0])?
a[0]:a,c=d.isArray(a[0])?a[1]:a;return{extend:"collection",text:function(a){return a.i18n("buttons.pageLength",{"-1":"Show all rows",_:"Show %d rows"},a.page.len())},className:"buttons-page-length",autoClose:!0,buttons:d.map(b,function(a,b){return{text:c[b],className:"button-page-length",action:function(b,c){c.page.len(a).draw()},init:function(b,c,d){var e=this;c=function(){e.active(b.page.len()===a)};b.on("length.dt"+d.namespace,c);c()},destroy:function(a,b,c){a.off("length.dt"+c.namespace)}}}),
init:function(a,b,c){var d=this;a.on("length.dt"+c.namespace,function(){d.text(c.text)})},destroy:function(a,b,c){a.off("length.dt"+c.namespace)}}}});p.Api.register("buttons()",function(a,b){b===l&&(b=a,a=l);this.selector.buttonGroup=a;var c=this.iterator(!0,"table",function(c){if(c._buttons)return t.buttonSelector(t.instanceSelector(a,c._buttons),b)},!0);c._groupSelector=a;return c});p.Api.register("button()",function(a,b){a=this.buttons(a,b);1<a.length&&a.splice(1,a.length);return a});p.Api.registerPlural("buttons().active()",
"button().active()",function(a){return a===l?this.map(function(a){return a.inst.active(a.node)}):this.each(function(b){b.inst.active(b.node,a)})});p.Api.registerPlural("buttons().action()","button().action()",function(a){return a===l?this.map(function(a){return a.inst.action(a.node)}):this.each(function(b){b.inst.action(b.node,a)})});p.Api.register(["buttons().enable()","button().enable()"],function(a){return this.each(function(b){b.inst.enable(b.node,a)})});p.Api.register(["buttons().disable()",
"button().disable()"],function(){return this.each(function(a){a.inst.disable(a.node)})});p.Api.registerPlural("buttons().nodes()","button().node()",function(){var a=d();d(this.each(function(b){a=a.add(b.inst.node(b.node))}));return a});p.Api.registerPlural("buttons().processing()","button().processing()",function(a){return a===l?this.map(function(a){return a.inst.processing(a.node)}):this.each(function(b){b.inst.processing(b.node,a)})});p.Api.registerPlural("buttons().text()","button().text()",function(a){return a===
l?this.map(function(a){return a.inst.text(a.node)}):this.each(function(b){b.inst.text(b.node,a)})});p.Api.registerPlural("buttons().trigger()","button().trigger()",function(){return this.each(function(a){a.inst.node(a.node).trigger("click")})});p.Api.registerPlural("buttons().containers()","buttons().container()",function(){var a=d(),b=this._groupSelector;this.iterator(!0,"table",function(c){if(c._buttons){c=t.instanceSelector(b,c._buttons);for(var d=0,f=c.length;d<f;d++)a=a.add(c[d].container())}});
return a});p.Api.register("button().add()",function(a,b){var c=this.context;c.length&&(c=t.instanceSelector(this._groupSelector,c[0]._buttons),c.length&&c[0].add(b,a));return this.button(this._groupSelector,a)});p.Api.register("buttons().destroy()",function(){this.pluck("inst").unique().each(function(a){a.destroy()});return this});p.Api.registerPlural("buttons().remove()","buttons().remove()",function(){this.each(function(a){a.inst.remove(a.node)});return this});var w;p.Api.register("buttons.info()",
function(a,b,c){var e=this;if(!1===a)return d("#datatables_buttons_info").fadeOut(function(){d(this).remove()}),clearTimeout(w),w=null,this;w&&clearTimeout(w);d("#datatables_buttons_info").length&&d("#datatables_buttons_info").remove();a=a?"<h2>"+a+"</h2>":"";d('<div id="datatables_buttons_info" class="dt-button-info"/>').html(a).append(d("<div/>")["string"===typeof b?"html":"append"](b)).css("display","none").appendTo("body").fadeIn();c!==l&&0!==c&&(w=setTimeout(function(){e.buttons.info(!1)},c));
return this});p.Api.register("buttons.exportData()",function(a){if(this.context.length)return D(new p.Api(this.context[0]),a)});p.Api.register("buttons.exportInfo()",function(a){a||(a={});var b=a;var c="*"===b.filename&&"*"!==b.title&&b.title!==l&&null!==b.title&&""!==b.title?b.title:b.filename;"function"===typeof c&&(c=c());c===l||null===c?c=null:(-1!==c.indexOf("*")&&(c=d.trim(c.replace("*",d("head > title").text()))),c=c.replace(/[^a-zA-Z0-9_\u00A1-\uFFFF\.,\-_ !\(\)]/g,""),(b=x(b.extension))||
(b=""),c+=b);b=x(a.title);b=null===b?null:-1!==b.indexOf("*")?b.replace("*",d("head > title").text()||"Exported data"):b;return{filename:c,title:b,messageTop:z(this,a.message||a.messageTop,"top"),messageBottom:z(this,a.messageBottom,"bottom")}});var x=function(a){return null===a||a===l?null:"function"===typeof a?a():a},z=function(a,b,c){b=x(b);if(null===b)return null;a=d("caption",a.table().container()).eq(0);return"*"===b?a.css("caption-side")!==c?null:a.length?a.text():"":b},A=d("<textarea/>")[0],
D=function(a,b){var c=d.extend(!0,{},{rows:null,columns:"",modifier:{search:"applied",order:"applied"},orthogonal:"display",stripHtml:!0,stripNewlines:!0,decodeEntities:!0,trim:!0,format:{header:function(a){return e(a)},footer:function(a){return e(a)},body:function(a){return e(a)}},customizeData:null},b),e=function(a){if("string"!==typeof a)return a;a=a.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,"");a=a.replace(/<!\-\-.*?\-\->/g,"");c.stripHtml&&(a=a.replace(/<[^>]*>/g,""));c.trim&&
(a=a.replace(/^\s+|\s+$/g,""));c.stripNewlines&&(a=a.replace(/\n/g," "));c.decodeEntities&&(A.innerHTML=a,a=A.value);return a};b=a.columns(c.columns).indexes().map(function(b){var d=a.column(b).header();return c.format.header(d.innerHTML,b,d)}).toArray();var f=a.table().footer()?a.columns(c.columns).indexes().map(function(b){var d=a.column(b).footer();return c.format.footer(d?d.innerHTML:"",b,d)}).toArray():null,g=d.extend({},c.modifier);a.select&&"function"===typeof a.select.info&&g.selected===l&&
a.rows(c.rows,d.extend({selected:!0},g)).any()&&d.extend(g,{selected:!0});g=a.rows(c.rows,g).indexes().toArray();var h=a.cells(g,c.columns);g=h.render(c.orthogonal).toArray();h=h.nodes().toArray();for(var k=b.length,p=[],m=0,n=0,q=0<k?g.length/k:0;n<q;n++){for(var t=[k],r=0;r<k;r++)t[r]=c.format.body(g[m],n,r,h[m]),m++;p[n]=t}b={header:b,footer:f,body:p};c.customizeData&&c.customizeData(b);return b};d.fn.dataTable.Buttons=t;d.fn.DataTable.Buttons=t;d(n).on("init.dt plugin-init.dt",function(a,b){"dt"===
a.namespace&&(a=b.oInit.buttons||p.defaults.buttons)&&!b._buttons&&(new t(b,a)).container()});p.ext.feature.push({fnInit:u,cFeature:"B"});p.ext.features&&p.ext.features.register("buttons",u);return t});

View File

@@ -1,166 +0,0 @@
/*!
DataTables 1.10.12
©2008-2015 SpryMedia Ltd - datatables.net/license
*/
(function(h){"function"===typeof define&&define.amd?define(["jquery"],function(D){return h(D,window,document)}):"object"===typeof exports?module.exports=function(D,I){D||(D=window);I||(I="undefined"!==typeof window?require("jquery"):require("jquery")(D));return h(I,D,D.document)}:h(jQuery,window,document)})(function(h,D,I,k){function X(a){var b,c,d={};h.each(a,function(e){if((b=e.match(/^([^A-Z]+?)([A-Z])/))&&-1!=="a aa ai ao as b fn i m o s ".indexOf(b[1]+" "))c=e.replace(b[0],b[2].toLowerCase()),
d[c]=e,"o"===b[1]&&X(a[e])});a._hungarianMap=d}function K(a,b,c){a._hungarianMap||X(a);var d;h.each(b,function(e){d=a._hungarianMap[e];if(d!==k&&(c||b[d]===k))"o"===d.charAt(0)?(b[d]||(b[d]={}),h.extend(!0,b[d],b[e]),K(a[d],b[d],c)):b[d]=b[e]})}function Da(a){var b=m.defaults.oLanguage,c=a.sZeroRecords;!a.sEmptyTable&&(c&&"No data available in table"===b.sEmptyTable)&&E(a,a,"sZeroRecords","sEmptyTable");!a.sLoadingRecords&&(c&&"Loading..."===b.sLoadingRecords)&&E(a,a,"sZeroRecords","sLoadingRecords");
a.sInfoThousands&&(a.sThousands=a.sInfoThousands);(a=a.sDecimal)&&db(a)}function eb(a){A(a,"ordering","bSort");A(a,"orderMulti","bSortMulti");A(a,"orderClasses","bSortClasses");A(a,"orderCellsTop","bSortCellsTop");A(a,"order","aaSorting");A(a,"orderFixed","aaSortingFixed");A(a,"paging","bPaginate");A(a,"pagingType","sPaginationType");A(a,"pageLength","iDisplayLength");A(a,"searching","bFilter");"boolean"===typeof a.sScrollX&&(a.sScrollX=a.sScrollX?"100%":"");"boolean"===typeof a.scrollX&&(a.scrollX=
a.scrollX?"100%":"");if(a=a.aoSearchCols)for(var b=0,c=a.length;b<c;b++)a[b]&&K(m.models.oSearch,a[b])}function fb(a){A(a,"orderable","bSortable");A(a,"orderData","aDataSort");A(a,"orderSequence","asSorting");A(a,"orderDataType","sortDataType");var b=a.aDataSort;b&&!h.isArray(b)&&(a.aDataSort=[b])}function gb(a){if(!m.__browser){var b={};m.__browser=b;var c=h("<div/>").css({position:"fixed",top:0,left:0,height:1,width:1,overflow:"hidden"}).append(h("<div/>").css({position:"absolute",top:1,left:1,
width:100,overflow:"scroll"}).append(h("<div/>").css({width:"100%",height:10}))).appendTo("body"),d=c.children(),e=d.children();b.barWidth=d[0].offsetWidth-d[0].clientWidth;b.bScrollOversize=100===e[0].offsetWidth&&100!==d[0].clientWidth;b.bScrollbarLeft=1!==Math.round(e.offset().left);b.bBounding=c[0].getBoundingClientRect().width?!0:!1;c.remove()}h.extend(a.oBrowser,m.__browser);a.oScroll.iBarWidth=m.__browser.barWidth}function hb(a,b,c,d,e,f){var g,j=!1;c!==k&&(g=c,j=!0);for(;d!==e;)a.hasOwnProperty(d)&&
(g=j?b(g,a[d],d,a):a[d],j=!0,d+=f);return g}function Ea(a,b){var c=m.defaults.column,d=a.aoColumns.length,c=h.extend({},m.models.oColumn,c,{nTh:b?b:I.createElement("th"),sTitle:c.sTitle?c.sTitle:b?b.innerHTML:"",aDataSort:c.aDataSort?c.aDataSort:[d],mData:c.mData?c.mData:d,idx:d});a.aoColumns.push(c);c=a.aoPreSearchCols;c[d]=h.extend({},m.models.oSearch,c[d]);ja(a,d,h(b).data())}function ja(a,b,c){var b=a.aoColumns[b],d=a.oClasses,e=h(b.nTh);if(!b.sWidthOrig){b.sWidthOrig=e.attr("width")||null;var f=
(e.attr("style")||"").match(/width:\s*(\d+[pxem%]+)/);f&&(b.sWidthOrig=f[1])}c!==k&&null!==c&&(fb(c),K(m.defaults.column,c),c.mDataProp!==k&&!c.mData&&(c.mData=c.mDataProp),c.sType&&(b._sManualType=c.sType),c.className&&!c.sClass&&(c.sClass=c.className),h.extend(b,c),E(b,c,"sWidth","sWidthOrig"),c.iDataSort!==k&&(b.aDataSort=[c.iDataSort]),E(b,c,"aDataSort"));var g=b.mData,j=Q(g),i=b.mRender?Q(b.mRender):null,c=function(a){return"string"===typeof a&&-1!==a.indexOf("@")};b._bAttrSrc=h.isPlainObject(g)&&
(c(g.sort)||c(g.type)||c(g.filter));b._setter=null;b.fnGetData=function(a,b,c){var d=j(a,b,k,c);return i&&b?i(d,b,a,c):d};b.fnSetData=function(a,b,c){return R(g)(a,b,c)};"number"!==typeof g&&(a._rowReadObject=!0);a.oFeatures.bSort||(b.bSortable=!1,e.addClass(d.sSortableNone));a=-1!==h.inArray("asc",b.asSorting);c=-1!==h.inArray("desc",b.asSorting);!b.bSortable||!a&&!c?(b.sSortingClass=d.sSortableNone,b.sSortingClassJUI=""):a&&!c?(b.sSortingClass=d.sSortableAsc,b.sSortingClassJUI=d.sSortJUIAscAllowed):
!a&&c?(b.sSortingClass=d.sSortableDesc,b.sSortingClassJUI=d.sSortJUIDescAllowed):(b.sSortingClass=d.sSortable,b.sSortingClassJUI=d.sSortJUI)}function Y(a){if(!1!==a.oFeatures.bAutoWidth){var b=a.aoColumns;Fa(a);for(var c=0,d=b.length;c<d;c++)b[c].nTh.style.width=b[c].sWidth}b=a.oScroll;(""!==b.sY||""!==b.sX)&&ka(a);u(a,null,"column-sizing",[a])}function Z(a,b){var c=la(a,"bVisible");return"number"===typeof c[b]?c[b]:null}function $(a,b){var c=la(a,"bVisible"),c=h.inArray(b,c);return-1!==c?c:null}
function aa(a){var b=0;h.each(a.aoColumns,function(a,d){d.bVisible&&"none"!==h(d.nTh).css("display")&&b++});return b}function la(a,b){var c=[];h.map(a.aoColumns,function(a,e){a[b]&&c.push(e)});return c}function Ga(a){var b=a.aoColumns,c=a.aoData,d=m.ext.type.detect,e,f,g,j,i,h,l,q,t;e=0;for(f=b.length;e<f;e++)if(l=b[e],t=[],!l.sType&&l._sManualType)l.sType=l._sManualType;else if(!l.sType){g=0;for(j=d.length;g<j;g++){i=0;for(h=c.length;i<h;i++){t[i]===k&&(t[i]=B(a,i,e,"type"));q=d[g](t[i],a);if(!q&&
g!==d.length-1)break;if("html"===q)break}if(q){l.sType=q;break}}l.sType||(l.sType="string")}}function ib(a,b,c,d){var e,f,g,j,i,n,l=a.aoColumns;if(b)for(e=b.length-1;0<=e;e--){n=b[e];var q=n.targets!==k?n.targets:n.aTargets;h.isArray(q)||(q=[q]);f=0;for(g=q.length;f<g;f++)if("number"===typeof q[f]&&0<=q[f]){for(;l.length<=q[f];)Ea(a);d(q[f],n)}else if("number"===typeof q[f]&&0>q[f])d(l.length+q[f],n);else if("string"===typeof q[f]){j=0;for(i=l.length;j<i;j++)("_all"==q[f]||h(l[j].nTh).hasClass(q[f]))&&
d(j,n)}}if(c){e=0;for(a=c.length;e<a;e++)d(e,c[e])}}function N(a,b,c,d){var e=a.aoData.length,f=h.extend(!0,{},m.models.oRow,{src:c?"dom":"data",idx:e});f._aData=b;a.aoData.push(f);for(var g=a.aoColumns,j=0,i=g.length;j<i;j++)g[j].sType=null;a.aiDisplayMaster.push(e);b=a.rowIdFn(b);b!==k&&(a.aIds[b]=f);(c||!a.oFeatures.bDeferRender)&&Ha(a,e,c,d);return e}function ma(a,b){var c;b instanceof h||(b=h(b));return b.map(function(b,e){c=Ia(a,e);return N(a,c.data,e,c.cells)})}function B(a,b,c,d){var e=a.iDraw,
f=a.aoColumns[c],g=a.aoData[b]._aData,j=f.sDefaultContent,i=f.fnGetData(g,d,{settings:a,row:b,col:c});if(i===k)return a.iDrawError!=e&&null===j&&(L(a,0,"Requested unknown parameter "+("function"==typeof f.mData?"{function}":"'"+f.mData+"'")+" for row "+b+", column "+c,4),a.iDrawError=e),j;if((i===g||null===i)&&null!==j&&d!==k)i=j;else if("function"===typeof i)return i.call(g);return null===i&&"display"==d?"":i}function jb(a,b,c,d){a.aoColumns[c].fnSetData(a.aoData[b]._aData,d,{settings:a,row:b,col:c})}
function Ja(a){return h.map(a.match(/(\\.|[^\.])+/g)||[""],function(a){return a.replace(/\\./g,".")})}function Q(a){if(h.isPlainObject(a)){var b={};h.each(a,function(a,c){c&&(b[a]=Q(c))});return function(a,c,f,g){var j=b[c]||b._;return j!==k?j(a,c,f,g):a}}if(null===a)return function(a){return a};if("function"===typeof a)return function(b,c,f,g){return a(b,c,f,g)};if("string"===typeof a&&(-1!==a.indexOf(".")||-1!==a.indexOf("[")||-1!==a.indexOf("("))){var c=function(a,b,f){var g,j;if(""!==f){j=Ja(f);
for(var i=0,n=j.length;i<n;i++){f=j[i].match(ba);g=j[i].match(U);if(f){j[i]=j[i].replace(ba,"");""!==j[i]&&(a=a[j[i]]);g=[];j.splice(0,i+1);j=j.join(".");if(h.isArray(a)){i=0;for(n=a.length;i<n;i++)g.push(c(a[i],b,j))}a=f[0].substring(1,f[0].length-1);a=""===a?g:g.join(a);break}else if(g){j[i]=j[i].replace(U,"");a=a[j[i]]();continue}if(null===a||a[j[i]]===k)return k;a=a[j[i]]}}return a};return function(b,e){return c(b,e,a)}}return function(b){return b[a]}}function R(a){if(h.isPlainObject(a))return R(a._);
if(null===a)return function(){};if("function"===typeof a)return function(b,d,e){a(b,"set",d,e)};if("string"===typeof a&&(-1!==a.indexOf(".")||-1!==a.indexOf("[")||-1!==a.indexOf("("))){var b=function(a,d,e){var e=Ja(e),f;f=e[e.length-1];for(var g,j,i=0,n=e.length-1;i<n;i++){g=e[i].match(ba);j=e[i].match(U);if(g){e[i]=e[i].replace(ba,"");a[e[i]]=[];f=e.slice();f.splice(0,i+1);g=f.join(".");if(h.isArray(d)){j=0;for(n=d.length;j<n;j++)f={},b(f,d[j],g),a[e[i]].push(f)}else a[e[i]]=d;return}j&&(e[i]=e[i].replace(U,
""),a=a[e[i]](d));if(null===a[e[i]]||a[e[i]]===k)a[e[i]]={};a=a[e[i]]}if(f.match(U))a[f.replace(U,"")](d);else a[f.replace(ba,"")]=d};return function(c,d){return b(c,d,a)}}return function(b,d){b[a]=d}}function Ka(a){return G(a.aoData,"_aData")}function na(a){a.aoData.length=0;a.aiDisplayMaster.length=0;a.aiDisplay.length=0;a.aIds={}}function oa(a,b,c){for(var d=-1,e=0,f=a.length;e<f;e++)a[e]==b?d=e:a[e]>b&&a[e]--; -1!=d&&c===k&&a.splice(d,1)}function ca(a,b,c,d){var e=a.aoData[b],f,g=function(c,d){for(;c.childNodes.length;)c.removeChild(c.firstChild);
c.innerHTML=B(a,b,d,"display")};if("dom"===c||(!c||"auto"===c)&&"dom"===e.src)e._aData=Ia(a,e,d,d===k?k:e._aData).data;else{var j=e.anCells;if(j)if(d!==k)g(j[d],d);else{c=0;for(f=j.length;c<f;c++)g(j[c],c)}}e._aSortData=null;e._aFilterData=null;g=a.aoColumns;if(d!==k)g[d].sType=null;else{c=0;for(f=g.length;c<f;c++)g[c].sType=null;La(a,e)}}function Ia(a,b,c,d){var e=[],f=b.firstChild,g,j,i=0,n,l=a.aoColumns,q=a._rowReadObject,d=d!==k?d:q?{}:[],t=function(a,b){if("string"===typeof a){var c=a.indexOf("@");
-1!==c&&(c=a.substring(c+1),R(a)(d,b.getAttribute(c)))}},S=function(a){if(c===k||c===i)j=l[i],n=h.trim(a.innerHTML),j&&j._bAttrSrc?(R(j.mData._)(d,n),t(j.mData.sort,a),t(j.mData.type,a),t(j.mData.filter,a)):q?(j._setter||(j._setter=R(j.mData)),j._setter(d,n)):d[i]=n;i++};if(f)for(;f;){g=f.nodeName.toUpperCase();if("TD"==g||"TH"==g)S(f),e.push(f);f=f.nextSibling}else{e=b.anCells;f=0;for(g=e.length;f<g;f++)S(e[f])}if(b=b.firstChild?b:b.nTr)(b=b.getAttribute("id"))&&R(a.rowId)(d,b);return{data:d,cells:e}}
function Ha(a,b,c,d){var e=a.aoData[b],f=e._aData,g=[],j,i,n,l,q;if(null===e.nTr){j=c||I.createElement("tr");e.nTr=j;e.anCells=g;j._DT_RowIndex=b;La(a,e);l=0;for(q=a.aoColumns.length;l<q;l++){n=a.aoColumns[l];i=c?d[l]:I.createElement(n.sCellType);i._DT_CellIndex={row:b,column:l};g.push(i);if((!c||n.mRender||n.mData!==l)&&(!h.isPlainObject(n.mData)||n.mData._!==l+".display"))i.innerHTML=B(a,b,l,"display");n.sClass&&(i.className+=" "+n.sClass);n.bVisible&&!c?j.appendChild(i):!n.bVisible&&c&&i.parentNode.removeChild(i);
n.fnCreatedCell&&n.fnCreatedCell.call(a.oInstance,i,B(a,b,l),f,b,l)}u(a,"aoRowCreatedCallback",null,[j,f,b])}e.nTr.setAttribute("role","row")}function La(a,b){var c=b.nTr,d=b._aData;if(c){var e=a.rowIdFn(d);e&&(c.id=e);d.DT_RowClass&&(e=d.DT_RowClass.split(" "),b.__rowc=b.__rowc?pa(b.__rowc.concat(e)):e,h(c).removeClass(b.__rowc.join(" ")).addClass(d.DT_RowClass));d.DT_RowAttr&&h(c).attr(d.DT_RowAttr);d.DT_RowData&&h(c).data(d.DT_RowData)}}function kb(a){var b,c,d,e,f,g=a.nTHead,j=a.nTFoot,i=0===
h("th, td",g).length,n=a.oClasses,l=a.aoColumns;i&&(e=h("<tr/>").appendTo(g));b=0;for(c=l.length;b<c;b++)f=l[b],d=h(f.nTh).addClass(f.sClass),i&&d.appendTo(e),a.oFeatures.bSort&&(d.addClass(f.sSortingClass),!1!==f.bSortable&&(d.attr("tabindex",a.iTabIndex).attr("aria-controls",a.sTableId),Ma(a,f.nTh,b))),f.sTitle!=d[0].innerHTML&&d.html(f.sTitle),Na(a,"header")(a,d,f,n);i&&da(a.aoHeader,g);h(g).find(">tr").attr("role","row");h(g).find(">tr>th, >tr>td").addClass(n.sHeaderTH);h(j).find(">tr>th, >tr>td").addClass(n.sFooterTH);
if(null!==j){a=a.aoFooter[0];b=0;for(c=a.length;b<c;b++)f=l[b],f.nTf=a[b].cell,f.sClass&&h(f.nTf).addClass(f.sClass)}}function ea(a,b,c){var d,e,f,g=[],j=[],i=a.aoColumns.length,n;if(b){c===k&&(c=!1);d=0;for(e=b.length;d<e;d++){g[d]=b[d].slice();g[d].nTr=b[d].nTr;for(f=i-1;0<=f;f--)!a.aoColumns[f].bVisible&&!c&&g[d].splice(f,1);j.push([])}d=0;for(e=g.length;d<e;d++){if(a=g[d].nTr)for(;f=a.firstChild;)a.removeChild(f);f=0;for(b=g[d].length;f<b;f++)if(n=i=1,j[d][f]===k){a.appendChild(g[d][f].cell);
for(j[d][f]=1;g[d+i]!==k&&g[d][f].cell==g[d+i][f].cell;)j[d+i][f]=1,i++;for(;g[d][f+n]!==k&&g[d][f].cell==g[d][f+n].cell;){for(c=0;c<i;c++)j[d+c][f+n]=1;n++}h(g[d][f].cell).attr("rowspan",i).attr("colspan",n)}}}}function O(a){var b=u(a,"aoPreDrawCallback","preDraw",[a]);if(-1!==h.inArray(!1,b))C(a,!1);else{var b=[],c=0,d=a.asStripeClasses,e=d.length,f=a.oLanguage,g=a.iInitDisplayStart,j="ssp"==y(a),i=a.aiDisplay;a.bDrawing=!0;g!==k&&-1!==g&&(a._iDisplayStart=j?g:g>=a.fnRecordsDisplay()?0:g,a.iInitDisplayStart=
-1);var g=a._iDisplayStart,n=a.fnDisplayEnd();if(a.bDeferLoading)a.bDeferLoading=!1,a.iDraw++,C(a,!1);else if(j){if(!a.bDestroying&&!lb(a))return}else a.iDraw++;if(0!==i.length){f=j?a.aoData.length:n;for(j=j?0:g;j<f;j++){var l=i[j],q=a.aoData[l];null===q.nTr&&Ha(a,l);l=q.nTr;if(0!==e){var t=d[c%e];q._sRowStripe!=t&&(h(l).removeClass(q._sRowStripe).addClass(t),q._sRowStripe=t)}u(a,"aoRowCallback",null,[l,q._aData,c,j]);b.push(l);c++}}else c=f.sZeroRecords,1==a.iDraw&&"ajax"==y(a)?c=f.sLoadingRecords:
f.sEmptyTable&&0===a.fnRecordsTotal()&&(c=f.sEmptyTable),b[0]=h("<tr/>",{"class":e?d[0]:""}).append(h("<td />",{valign:"top",colSpan:aa(a),"class":a.oClasses.sRowEmpty}).html(c))[0];u(a,"aoHeaderCallback","header",[h(a.nTHead).children("tr")[0],Ka(a),g,n,i]);u(a,"aoFooterCallback","footer",[h(a.nTFoot).children("tr")[0],Ka(a),g,n,i]);d=h(a.nTBody);d.children().detach();d.append(h(b));u(a,"aoDrawCallback","draw",[a]);a.bSorted=!1;a.bFiltered=!1;a.bDrawing=!1}}function T(a,b){var c=a.oFeatures,d=c.bFilter;
c.bSort&&mb(a);d?fa(a,a.oPreviousSearch):a.aiDisplay=a.aiDisplayMaster.slice();!0!==b&&(a._iDisplayStart=0);a._drawHold=b;O(a);a._drawHold=!1}function nb(a){var b=a.oClasses,c=h(a.nTable),c=h("<div/>").insertBefore(c),d=a.oFeatures,e=h("<div/>",{id:a.sTableId+"_wrapper","class":b.sWrapper+(a.nTFoot?"":" "+b.sNoFooter)});a.nHolding=c[0];a.nTableWrapper=e[0];a.nTableReinsertBefore=a.nTable.nextSibling;for(var f=a.sDom.split(""),g,j,i,n,l,q,t=0;t<f.length;t++){g=null;j=f[t];if("<"==j){i=h("<div/>")[0];
n=f[t+1];if("'"==n||'"'==n){l="";for(q=2;f[t+q]!=n;)l+=f[t+q],q++;"H"==l?l=b.sJUIHeader:"F"==l&&(l=b.sJUIFooter);-1!=l.indexOf(".")?(n=l.split("."),i.id=n[0].substr(1,n[0].length-1),i.className=n[1]):"#"==l.charAt(0)?i.id=l.substr(1,l.length-1):i.className=l;t+=q}e.append(i);e=h(i)}else if(">"==j)e=e.parent();else if("l"==j&&d.bPaginate&&d.bLengthChange)g=ob(a);else if("f"==j&&d.bFilter)g=pb(a);else if("r"==j&&d.bProcessing)g=qb(a);else if("t"==j)g=rb(a);else if("i"==j&&d.bInfo)g=sb(a);else if("p"==
j&&d.bPaginate)g=tb(a);else if(0!==m.ext.feature.length){i=m.ext.feature;q=0;for(n=i.length;q<n;q++)if(j==i[q].cFeature){g=i[q].fnInit(a);break}}g&&(i=a.aanFeatures,i[j]||(i[j]=[]),i[j].push(g),e.append(g))}c.replaceWith(e);a.nHolding=null}function da(a,b){var c=h(b).children("tr"),d,e,f,g,j,i,n,l,q,t;a.splice(0,a.length);f=0;for(i=c.length;f<i;f++)a.push([]);f=0;for(i=c.length;f<i;f++){d=c[f];for(e=d.firstChild;e;){if("TD"==e.nodeName.toUpperCase()||"TH"==e.nodeName.toUpperCase()){l=1*e.getAttribute("colspan");
q=1*e.getAttribute("rowspan");l=!l||0===l||1===l?1:l;q=!q||0===q||1===q?1:q;g=0;for(j=a[f];j[g];)g++;n=g;t=1===l?!0:!1;for(j=0;j<l;j++)for(g=0;g<q;g++)a[f+g][n+j]={cell:e,unique:t},a[f+g].nTr=d}e=e.nextSibling}}}function qa(a,b,c){var d=[];c||(c=a.aoHeader,b&&(c=[],da(c,b)));for(var b=0,e=c.length;b<e;b++)for(var f=0,g=c[b].length;f<g;f++)if(c[b][f].unique&&(!d[f]||!a.bSortCellsTop))d[f]=c[b][f].cell;return d}function ra(a,b,c){u(a,"aoServerParams","serverParams",[b]);if(b&&h.isArray(b)){var d={},
e=/(.*?)\[\]$/;h.each(b,function(a,b){var c=b.name.match(e);c?(c=c[0],d[c]||(d[c]=[]),d[c].push(b.value)):d[b.name]=b.value});b=d}var f,g=a.ajax,j=a.oInstance,i=function(b){u(a,null,"xhr",[a,b,a.jqXHR]);c(b)};if(h.isPlainObject(g)&&g.data){f=g.data;var n=h.isFunction(f)?f(b,a):f,b=h.isFunction(f)&&n?n:h.extend(!0,b,n);delete g.data}n={data:b,success:function(b){var c=b.error||b.sError;c&&L(a,0,c);a.json=b;i(b)},dataType:"json",cache:!1,type:a.sServerMethod,error:function(b,c){var d=u(a,null,"xhr",
[a,null,a.jqXHR]);-1===h.inArray(!0,d)&&("parsererror"==c?L(a,0,"Invalid JSON response",1):4===b.readyState&&L(a,0,"Ajax error",7));C(a,!1)}};a.oAjaxData=b;u(a,null,"preXhr",[a,b]);a.fnServerData?a.fnServerData.call(j,a.sAjaxSource,h.map(b,function(a,b){return{name:b,value:a}}),i,a):a.sAjaxSource||"string"===typeof g?a.jqXHR=h.ajax(h.extend(n,{url:g||a.sAjaxSource})):h.isFunction(g)?a.jqXHR=g.call(j,b,i,a):(a.jqXHR=h.ajax(h.extend(n,g)),g.data=f)}function lb(a){return a.bAjaxDataGet?(a.iDraw++,C(a,
!0),ra(a,ub(a),function(b){vb(a,b)}),!1):!0}function ub(a){var b=a.aoColumns,c=b.length,d=a.oFeatures,e=a.oPreviousSearch,f=a.aoPreSearchCols,g,j=[],i,n,l,q=V(a);g=a._iDisplayStart;i=!1!==d.bPaginate?a._iDisplayLength:-1;var k=function(a,b){j.push({name:a,value:b})};k("sEcho",a.iDraw);k("iColumns",c);k("sColumns",G(b,"sName").join(","));k("iDisplayStart",g);k("iDisplayLength",i);var S={draw:a.iDraw,columns:[],order:[],start:g,length:i,search:{value:e.sSearch,regex:e.bRegex}};for(g=0;g<c;g++)n=b[g],
l=f[g],i="function"==typeof n.mData?"function":n.mData,S.columns.push({data:i,name:n.sName,searchable:n.bSearchable,orderable:n.bSortable,search:{value:l.sSearch,regex:l.bRegex}}),k("mDataProp_"+g,i),d.bFilter&&(k("sSearch_"+g,l.sSearch),k("bRegex_"+g,l.bRegex),k("bSearchable_"+g,n.bSearchable)),d.bSort&&k("bSortable_"+g,n.bSortable);d.bFilter&&(k("sSearch",e.sSearch),k("bRegex",e.bRegex));d.bSort&&(h.each(q,function(a,b){S.order.push({column:b.col,dir:b.dir});k("iSortCol_"+a,b.col);k("sSortDir_"+
a,b.dir)}),k("iSortingCols",q.length));b=m.ext.legacy.ajax;return null===b?a.sAjaxSource?j:S:b?j:S}function vb(a,b){var c=sa(a,b),d=b.sEcho!==k?b.sEcho:b.draw,e=b.iTotalRecords!==k?b.iTotalRecords:b.recordsTotal,f=b.iTotalDisplayRecords!==k?b.iTotalDisplayRecords:b.recordsFiltered;if(d){if(1*d<a.iDraw)return;a.iDraw=1*d}na(a);a._iRecordsTotal=parseInt(e,10);a._iRecordsDisplay=parseInt(f,10);d=0;for(e=c.length;d<e;d++)N(a,c[d]);a.aiDisplay=a.aiDisplayMaster.slice();a.bAjaxDataGet=!1;O(a);a._bInitComplete||
ta(a,b);a.bAjaxDataGet=!0;C(a,!1)}function sa(a,b){var c=h.isPlainObject(a.ajax)&&a.ajax.dataSrc!==k?a.ajax.dataSrc:a.sAjaxDataProp;return"data"===c?b.aaData||b[c]:""!==c?Q(c)(b):b}function pb(a){var b=a.oClasses,c=a.sTableId,d=a.oLanguage,e=a.oPreviousSearch,f=a.aanFeatures,g='<input type="search" class="'+b.sFilterInput+'"/>',j=d.sSearch,j=j.match(/_INPUT_/)?j.replace("_INPUT_",g):j+g,b=h("<div/>",{id:!f.f?c+"_filter":null,"class":b.sFilter}).append(h("<label/>").append(j)),f=function(){var b=!this.value?
"":this.value;b!=e.sSearch&&(fa(a,{sSearch:b,bRegex:e.bRegex,bSmart:e.bSmart,bCaseInsensitive:e.bCaseInsensitive}),a._iDisplayStart=0,O(a))},g=null!==a.searchDelay?a.searchDelay:"ssp"===y(a)?400:0,i=h("input",b).val(e.sSearch).attr("placeholder",d.sSearchPlaceholder).bind("keyup.DT search.DT input.DT paste.DT cut.DT",g?Oa(f,g):f).bind("keypress.DT",function(a){if(13==a.keyCode)return!1}).attr("aria-controls",c);h(a.nTable).on("search.dt.DT",function(b,c){if(a===c)try{i[0]!==I.activeElement&&i.val(e.sSearch)}catch(d){}});
return b[0]}function fa(a,b,c){var d=a.oPreviousSearch,e=a.aoPreSearchCols,f=function(a){d.sSearch=a.sSearch;d.bRegex=a.bRegex;d.bSmart=a.bSmart;d.bCaseInsensitive=a.bCaseInsensitive};Ga(a);if("ssp"!=y(a)){wb(a,b.sSearch,c,b.bEscapeRegex!==k?!b.bEscapeRegex:b.bRegex,b.bSmart,b.bCaseInsensitive);f(b);for(b=0;b<e.length;b++)xb(a,e[b].sSearch,b,e[b].bEscapeRegex!==k?!e[b].bEscapeRegex:e[b].bRegex,e[b].bSmart,e[b].bCaseInsensitive);yb(a)}else f(b);a.bFiltered=!0;u(a,null,"search",[a])}function yb(a){for(var b=
m.ext.search,c=a.aiDisplay,d,e,f=0,g=b.length;f<g;f++){for(var j=[],i=0,n=c.length;i<n;i++)e=c[i],d=a.aoData[e],b[f](a,d._aFilterData,e,d._aData,i)&&j.push(e);c.length=0;h.merge(c,j)}}function xb(a,b,c,d,e,f){if(""!==b)for(var g=a.aiDisplay,d=Pa(b,d,e,f),e=g.length-1;0<=e;e--)b=a.aoData[g[e]]._aFilterData[c],d.test(b)||g.splice(e,1)}function wb(a,b,c,d,e,f){var d=Pa(b,d,e,f),e=a.oPreviousSearch.sSearch,f=a.aiDisplayMaster,g;0!==m.ext.search.length&&(c=!0);g=zb(a);if(0>=b.length)a.aiDisplay=f.slice();
else{if(g||c||e.length>b.length||0!==b.indexOf(e)||a.bSorted)a.aiDisplay=f.slice();b=a.aiDisplay;for(c=b.length-1;0<=c;c--)d.test(a.aoData[b[c]]._sFilterRow)||b.splice(c,1)}}function Pa(a,b,c,d){a=b?a:Qa(a);c&&(a="^(?=.*?"+h.map(a.match(/"[^"]+"|[^ ]+/g)||[""],function(a){if('"'===a.charAt(0))var b=a.match(/^"(.*)"$/),a=b?b[1]:a;return a.replace('"',"")}).join(")(?=.*?")+").*$");return RegExp(a,d?"i":"")}function zb(a){var b=a.aoColumns,c,d,e,f,g,j,i,h,l=m.ext.type.search;c=!1;d=0;for(f=a.aoData.length;d<
f;d++)if(h=a.aoData[d],!h._aFilterData){j=[];e=0;for(g=b.length;e<g;e++)c=b[e],c.bSearchable?(i=B(a,d,e,"filter"),l[c.sType]&&(i=l[c.sType](i)),null===i&&(i=""),"string"!==typeof i&&i.toString&&(i=i.toString())):i="",i.indexOf&&-1!==i.indexOf("&")&&(ua.innerHTML=i,i=Zb?ua.textContent:ua.innerText),i.replace&&(i=i.replace(/[\r\n]/g,"")),j.push(i);h._aFilterData=j;h._sFilterRow=j.join(" ");c=!0}return c}function Ab(a){return{search:a.sSearch,smart:a.bSmart,regex:a.bRegex,caseInsensitive:a.bCaseInsensitive}}
function Bb(a){return{sSearch:a.search,bSmart:a.smart,bRegex:a.regex,bCaseInsensitive:a.caseInsensitive}}function sb(a){var b=a.sTableId,c=a.aanFeatures.i,d=h("<div/>",{"class":a.oClasses.sInfo,id:!c?b+"_info":null});c||(a.aoDrawCallback.push({fn:Cb,sName:"information"}),d.attr("role","status").attr("aria-live","polite"),h(a.nTable).attr("aria-describedby",b+"_info"));return d[0]}function Cb(a){var b=a.aanFeatures.i;if(0!==b.length){var c=a.oLanguage,d=a._iDisplayStart+1,e=a.fnDisplayEnd(),f=a.fnRecordsTotal(),
g=a.fnRecordsDisplay(),j=g?c.sInfo:c.sInfoEmpty;g!==f&&(j+=" "+c.sInfoFiltered);j+=c.sInfoPostFix;j=Db(a,j);c=c.fnInfoCallback;null!==c&&(j=c.call(a.oInstance,a,d,e,f,g,j));h(b).html(j)}}function Db(a,b){var c=a.fnFormatNumber,d=a._iDisplayStart+1,e=a._iDisplayLength,f=a.fnRecordsDisplay(),g=-1===e;return b.replace(/_START_/g,c.call(a,d)).replace(/_END_/g,c.call(a,a.fnDisplayEnd())).replace(/_MAX_/g,c.call(a,a.fnRecordsTotal())).replace(/_TOTAL_/g,c.call(a,f)).replace(/_PAGE_/g,c.call(a,g?1:Math.ceil(d/
e))).replace(/_PAGES_/g,c.call(a,g?1:Math.ceil(f/e)))}function ga(a){var b,c,d=a.iInitDisplayStart,e=a.aoColumns,f;c=a.oFeatures;var g=a.bDeferLoading;if(a.bInitialised){nb(a);kb(a);ea(a,a.aoHeader);ea(a,a.aoFooter);C(a,!0);c.bAutoWidth&&Fa(a);b=0;for(c=e.length;b<c;b++)f=e[b],f.sWidth&&(f.nTh.style.width=x(f.sWidth));u(a,null,"preInit",[a]);T(a);e=y(a);if("ssp"!=e||g)"ajax"==e?ra(a,[],function(c){var f=sa(a,c);for(b=0;b<f.length;b++)N(a,f[b]);a.iInitDisplayStart=d;T(a);C(a,!1);ta(a,c)},a):(C(a,!1),
ta(a))}else setTimeout(function(){ga(a)},200)}function ta(a,b){a._bInitComplete=!0;(b||a.oInit.aaData)&&Y(a);u(a,null,"plugin-init",[a,b]);u(a,"aoInitComplete","init",[a,b])}function Ra(a,b){var c=parseInt(b,10);a._iDisplayLength=c;Sa(a);u(a,null,"length",[a,c])}function ob(a){for(var b=a.oClasses,c=a.sTableId,d=a.aLengthMenu,e=h.isArray(d[0]),f=e?d[0]:d,d=e?d[1]:d,e=h("<select/>",{name:c+"_length","aria-controls":c,"class":b.sLengthSelect}),g=0,j=f.length;g<j;g++)e[0][g]=new Option(d[g],f[g]);var i=
h("<div><label/></div>").addClass(b.sLength);a.aanFeatures.l||(i[0].id=c+"_length");i.children().append(a.oLanguage.sLengthMenu.replace("_MENU_",e[0].outerHTML));h("select",i).val(a._iDisplayLength).bind("change.DT",function(){Ra(a,h(this).val());O(a)});h(a.nTable).bind("length.dt.DT",function(b,c,d){a===c&&h("select",i).val(d)});return i[0]}function tb(a){var b=a.sPaginationType,c=m.ext.pager[b],d="function"===typeof c,e=function(a){O(a)},b=h("<div/>").addClass(a.oClasses.sPaging+b)[0],f=a.aanFeatures;
d||c.fnInit(a,b,e);f.p||(b.id=a.sTableId+"_paginate",a.aoDrawCallback.push({fn:function(a){if(d){var b=a._iDisplayStart,i=a._iDisplayLength,h=a.fnRecordsDisplay(),l=-1===i,b=l?0:Math.ceil(b/i),i=l?1:Math.ceil(h/i),h=c(b,i),k,l=0;for(k=f.p.length;l<k;l++)Na(a,"pageButton")(a,f.p[l],l,h,b,i)}else c.fnUpdate(a,e)},sName:"pagination"}));return b}function Ta(a,b,c){var d=a._iDisplayStart,e=a._iDisplayLength,f=a.fnRecordsDisplay();0===f||-1===e?d=0:"number"===typeof b?(d=b*e,d>f&&(d=0)):"first"==b?d=0:
"previous"==b?(d=0<=e?d-e:0,0>d&&(d=0)):"next"==b?d+e<f&&(d+=e):"last"==b?d=Math.floor((f-1)/e)*e:L(a,0,"Unknown paging action: "+b,5);b=a._iDisplayStart!==d;a._iDisplayStart=d;b&&(u(a,null,"page",[a]),c&&O(a));return b}function qb(a){return h("<div/>",{id:!a.aanFeatures.r?a.sTableId+"_processing":null,"class":a.oClasses.sProcessing}).html(a.oLanguage.sProcessing).insertBefore(a.nTable)[0]}function C(a,b){a.oFeatures.bProcessing&&h(a.aanFeatures.r).css("display",b?"block":"none");u(a,null,"processing",
[a,b])}function rb(a){var b=h(a.nTable);b.attr("role","grid");var c=a.oScroll;if(""===c.sX&&""===c.sY)return a.nTable;var d=c.sX,e=c.sY,f=a.oClasses,g=b.children("caption"),j=g.length?g[0]._captionSide:null,i=h(b[0].cloneNode(!1)),n=h(b[0].cloneNode(!1)),l=b.children("tfoot");l.length||(l=null);i=h("<div/>",{"class":f.sScrollWrapper}).append(h("<div/>",{"class":f.sScrollHead}).css({overflow:"hidden",position:"relative",border:0,width:d?!d?null:x(d):"100%"}).append(h("<div/>",{"class":f.sScrollHeadInner}).css({"box-sizing":"content-box",
width:c.sXInner||"100%"}).append(i.removeAttr("id").css("margin-left",0).append("top"===j?g:null).append(b.children("thead"))))).append(h("<div/>",{"class":f.sScrollBody}).css({position:"relative",overflow:"auto",width:!d?null:x(d)}).append(b));l&&i.append(h("<div/>",{"class":f.sScrollFoot}).css({overflow:"hidden",border:0,width:d?!d?null:x(d):"100%"}).append(h("<div/>",{"class":f.sScrollFootInner}).append(n.removeAttr("id").css("margin-left",0).append("bottom"===j?g:null).append(b.children("tfoot")))));
var b=i.children(),k=b[0],f=b[1],t=l?b[2]:null;if(d)h(f).on("scroll.DT",function(){var a=this.scrollLeft;k.scrollLeft=a;l&&(t.scrollLeft=a)});h(f).css(e&&c.bCollapse?"max-height":"height",e);a.nScrollHead=k;a.nScrollBody=f;a.nScrollFoot=t;a.aoDrawCallback.push({fn:ka,sName:"scrolling"});return i[0]}function ka(a){var b=a.oScroll,c=b.sX,d=b.sXInner,e=b.sY,b=b.iBarWidth,f=h(a.nScrollHead),g=f[0].style,j=f.children("div"),i=j[0].style,n=j.children("table"),j=a.nScrollBody,l=h(j),q=j.style,t=h(a.nScrollFoot).children("div"),
m=t.children("table"),o=h(a.nTHead),F=h(a.nTable),p=F[0],r=p.style,u=a.nTFoot?h(a.nTFoot):null,Eb=a.oBrowser,Ua=Eb.bScrollOversize,s=G(a.aoColumns,"nTh"),P,v,w,y,z=[],A=[],B=[],C=[],D,E=function(a){a=a.style;a.paddingTop="0";a.paddingBottom="0";a.borderTopWidth="0";a.borderBottomWidth="0";a.height=0};v=j.scrollHeight>j.clientHeight;if(a.scrollBarVis!==v&&a.scrollBarVis!==k)a.scrollBarVis=v,Y(a);else{a.scrollBarVis=v;F.children("thead, tfoot").remove();u&&(w=u.clone().prependTo(F),P=u.find("tr"),w=
w.find("tr"));y=o.clone().prependTo(F);o=o.find("tr");v=y.find("tr");y.find("th, td").removeAttr("tabindex");c||(q.width="100%",f[0].style.width="100%");h.each(qa(a,y),function(b,c){D=Z(a,b);c.style.width=a.aoColumns[D].sWidth});u&&J(function(a){a.style.width=""},w);f=F.outerWidth();if(""===c){r.width="100%";if(Ua&&(F.find("tbody").height()>j.offsetHeight||"scroll"==l.css("overflow-y")))r.width=x(F.outerWidth()-b);f=F.outerWidth()}else""!==d&&(r.width=x(d),f=F.outerWidth());J(E,v);J(function(a){B.push(a.innerHTML);
z.push(x(h(a).css("width")))},v);J(function(a,b){if(h.inArray(a,s)!==-1)a.style.width=z[b]},o);h(v).height(0);u&&(J(E,w),J(function(a){C.push(a.innerHTML);A.push(x(h(a).css("width")))},w),J(function(a,b){a.style.width=A[b]},P),h(w).height(0));J(function(a,b){a.innerHTML='<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+B[b]+"</div>";a.style.width=z[b]},v);u&&J(function(a,b){a.innerHTML='<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+C[b]+"</div>";a.style.width=
A[b]},w);if(F.outerWidth()<f){P=j.scrollHeight>j.offsetHeight||"scroll"==l.css("overflow-y")?f+b:f;if(Ua&&(j.scrollHeight>j.offsetHeight||"scroll"==l.css("overflow-y")))r.width=x(P-b);(""===c||""!==d)&&L(a,1,"Possible column misalignment",6)}else P="100%";q.width=x(P);g.width=x(P);u&&(a.nScrollFoot.style.width=x(P));!e&&Ua&&(q.height=x(p.offsetHeight+b));c=F.outerWidth();n[0].style.width=x(c);i.width=x(c);d=F.height()>j.clientHeight||"scroll"==l.css("overflow-y");e="padding"+(Eb.bScrollbarLeft?"Left":
"Right");i[e]=d?b+"px":"0px";u&&(m[0].style.width=x(c),t[0].style.width=x(c),t[0].style[e]=d?b+"px":"0px");F.children("colgroup").insertBefore(F.children("thead"));l.scroll();if((a.bSorted||a.bFiltered)&&!a._drawHold)j.scrollTop=0}}function J(a,b,c){for(var d=0,e=0,f=b.length,g,j;e<f;){g=b[e].firstChild;for(j=c?c[e].firstChild:null;g;)1===g.nodeType&&(c?a(g,j,d):a(g,d),d++),g=g.nextSibling,j=c?j.nextSibling:null;e++}}function Fa(a){var b=a.nTable,c=a.aoColumns,d=a.oScroll,e=d.sY,f=d.sX,g=d.sXInner,
j=c.length,i=la(a,"bVisible"),n=h("th",a.nTHead),l=b.getAttribute("width"),k=b.parentNode,t=!1,m,o,p=a.oBrowser,d=p.bScrollOversize;(m=b.style.width)&&-1!==m.indexOf("%")&&(l=m);for(m=0;m<i.length;m++)o=c[i[m]],null!==o.sWidth&&(o.sWidth=Fb(o.sWidthOrig,k),t=!0);if(d||!t&&!f&&!e&&j==aa(a)&&j==n.length)for(m=0;m<j;m++)i=Z(a,m),null!==i&&(c[i].sWidth=x(n.eq(m).width()));else{j=h(b).clone().css("visibility","hidden").removeAttr("id");j.find("tbody tr").remove();var r=h("<tr/>").appendTo(j.find("tbody"));
j.find("thead, tfoot").remove();j.append(h(a.nTHead).clone()).append(h(a.nTFoot).clone());j.find("tfoot th, tfoot td").css("width","");n=qa(a,j.find("thead")[0]);for(m=0;m<i.length;m++)o=c[i[m]],n[m].style.width=null!==o.sWidthOrig&&""!==o.sWidthOrig?x(o.sWidthOrig):"",o.sWidthOrig&&f&&h(n[m]).append(h("<div/>").css({width:o.sWidthOrig,margin:0,padding:0,border:0,height:1}));if(a.aoData.length)for(m=0;m<i.length;m++)t=i[m],o=c[t],h(Gb(a,t)).clone(!1).append(o.sContentPadding).appendTo(r);h("[name]",
j).removeAttr("name");o=h("<div/>").css(f||e?{position:"absolute",top:0,left:0,height:1,right:0,overflow:"hidden"}:{}).append(j).appendTo(k);f&&g?j.width(g):f?(j.css("width","auto"),j.removeAttr("width"),j.width()<k.clientWidth&&l&&j.width(k.clientWidth)):e?j.width(k.clientWidth):l&&j.width(l);for(m=e=0;m<i.length;m++)k=h(n[m]),g=k.outerWidth()-k.width(),k=p.bBounding?Math.ceil(n[m].getBoundingClientRect().width):k.outerWidth(),e+=k,c[i[m]].sWidth=x(k-g);b.style.width=x(e);o.remove()}l&&(b.style.width=
x(l));if((l||f)&&!a._reszEvt)b=function(){h(D).bind("resize.DT-"+a.sInstance,Oa(function(){Y(a)}))},d?setTimeout(b,1E3):b(),a._reszEvt=!0}function Fb(a,b){if(!a)return 0;var c=h("<div/>").css("width",x(a)).appendTo(b||I.body),d=c[0].offsetWidth;c.remove();return d}function Gb(a,b){var c=Hb(a,b);if(0>c)return null;var d=a.aoData[c];return!d.nTr?h("<td/>").html(B(a,c,b,"display"))[0]:d.anCells[b]}function Hb(a,b){for(var c,d=-1,e=-1,f=0,g=a.aoData.length;f<g;f++)c=B(a,f,b,"display")+"",c=c.replace($b,
""),c=c.replace(/&nbsp;/g," "),c.length>d&&(d=c.length,e=f);return e}function x(a){return null===a?"0px":"number"==typeof a?0>a?"0px":a+"px":a.match(/\d$/)?a+"px":a}function V(a){var b,c,d=[],e=a.aoColumns,f,g,j,i;b=a.aaSortingFixed;c=h.isPlainObject(b);var n=[];f=function(a){a.length&&!h.isArray(a[0])?n.push(a):h.merge(n,a)};h.isArray(b)&&f(b);c&&b.pre&&f(b.pre);f(a.aaSorting);c&&b.post&&f(b.post);for(a=0;a<n.length;a++){i=n[a][0];f=e[i].aDataSort;b=0;for(c=f.length;b<c;b++)g=f[b],j=e[g].sType||
"string",n[a]._idx===k&&(n[a]._idx=h.inArray(n[a][1],e[g].asSorting)),d.push({src:i,col:g,dir:n[a][1],index:n[a]._idx,type:j,formatter:m.ext.type.order[j+"-pre"]})}return d}function mb(a){var b,c,d=[],e=m.ext.type.order,f=a.aoData,g=0,j,i=a.aiDisplayMaster,h;Ga(a);h=V(a);b=0;for(c=h.length;b<c;b++)j=h[b],j.formatter&&g++,Ib(a,j.col);if("ssp"!=y(a)&&0!==h.length){b=0;for(c=i.length;b<c;b++)d[i[b]]=b;g===h.length?i.sort(function(a,b){var c,e,g,j,i=h.length,k=f[a]._aSortData,m=f[b]._aSortData;for(g=
0;g<i;g++)if(j=h[g],c=k[j.col],e=m[j.col],c=c<e?-1:c>e?1:0,0!==c)return"asc"===j.dir?c:-c;c=d[a];e=d[b];return c<e?-1:c>e?1:0}):i.sort(function(a,b){var c,g,j,i,k=h.length,m=f[a]._aSortData,p=f[b]._aSortData;for(j=0;j<k;j++)if(i=h[j],c=m[i.col],g=p[i.col],i=e[i.type+"-"+i.dir]||e["string-"+i.dir],c=i(c,g),0!==c)return c;c=d[a];g=d[b];return c<g?-1:c>g?1:0})}a.bSorted=!0}function Jb(a){for(var b,c,d=a.aoColumns,e=V(a),a=a.oLanguage.oAria,f=0,g=d.length;f<g;f++){c=d[f];var j=c.asSorting;b=c.sTitle.replace(/<.*?>/g,
"");var i=c.nTh;i.removeAttribute("aria-sort");c.bSortable&&(0<e.length&&e[0].col==f?(i.setAttribute("aria-sort","asc"==e[0].dir?"ascending":"descending"),c=j[e[0].index+1]||j[0]):c=j[0],b+="asc"===c?a.sSortAscending:a.sSortDescending);i.setAttribute("aria-label",b)}}function Va(a,b,c,d){var e=a.aaSorting,f=a.aoColumns[b].asSorting,g=function(a,b){var c=a._idx;c===k&&(c=h.inArray(a[1],f));return c+1<f.length?c+1:b?null:0};"number"===typeof e[0]&&(e=a.aaSorting=[e]);c&&a.oFeatures.bSortMulti?(c=h.inArray(b,
G(e,"0")),-1!==c?(b=g(e[c],!0),null===b&&1===e.length&&(b=0),null===b?e.splice(c,1):(e[c][1]=f[b],e[c]._idx=b)):(e.push([b,f[0],0]),e[e.length-1]._idx=0)):e.length&&e[0][0]==b?(b=g(e[0]),e.length=1,e[0][1]=f[b],e[0]._idx=b):(e.length=0,e.push([b,f[0]]),e[0]._idx=0);T(a);"function"==typeof d&&d(a)}function Ma(a,b,c,d){var e=a.aoColumns[c];Wa(b,{},function(b){!1!==e.bSortable&&(a.oFeatures.bProcessing?(C(a,!0),setTimeout(function(){Va(a,c,b.shiftKey,d);"ssp"!==y(a)&&C(a,!1)},0)):Va(a,c,b.shiftKey,d))})}
function va(a){var b=a.aLastSort,c=a.oClasses.sSortColumn,d=V(a),e=a.oFeatures,f,g;if(e.bSort&&e.bSortClasses){e=0;for(f=b.length;e<f;e++)g=b[e].src,h(G(a.aoData,"anCells",g)).removeClass(c+(2>e?e+1:3));e=0;for(f=d.length;e<f;e++)g=d[e].src,h(G(a.aoData,"anCells",g)).addClass(c+(2>e?e+1:3))}a.aLastSort=d}function Ib(a,b){var c=a.aoColumns[b],d=m.ext.order[c.sSortDataType],e;d&&(e=d.call(a.oInstance,a,b,$(a,b)));for(var f,g=m.ext.type.order[c.sType+"-pre"],j=0,i=a.aoData.length;j<i;j++)if(c=a.aoData[j],
c._aSortData||(c._aSortData=[]),!c._aSortData[b]||d)f=d?e[j]:B(a,j,b,"sort"),c._aSortData[b]=g?g(f):f}function wa(a){if(a.oFeatures.bStateSave&&!a.bDestroying){var b={time:+new Date,start:a._iDisplayStart,length:a._iDisplayLength,order:h.extend(!0,[],a.aaSorting),search:Ab(a.oPreviousSearch),columns:h.map(a.aoColumns,function(b,d){return{visible:b.bVisible,search:Ab(a.aoPreSearchCols[d])}})};u(a,"aoStateSaveParams","stateSaveParams",[a,b]);a.oSavedState=b;a.fnStateSaveCallback.call(a.oInstance,a,
b)}}function Kb(a){var b,c,d=a.aoColumns;if(a.oFeatures.bStateSave){var e=a.fnStateLoadCallback.call(a.oInstance,a);if(e&&e.time&&(b=u(a,"aoStateLoadParams","stateLoadParams",[a,e]),-1===h.inArray(!1,b)&&(b=a.iStateDuration,!(0<b&&e.time<+new Date-1E3*b)&&d.length===e.columns.length))){a.oLoadedState=h.extend(!0,{},e);e.start!==k&&(a._iDisplayStart=e.start,a.iInitDisplayStart=e.start);e.length!==k&&(a._iDisplayLength=e.length);e.order!==k&&(a.aaSorting=[],h.each(e.order,function(b,c){a.aaSorting.push(c[0]>=
d.length?[0,c[1]]:c)}));e.search!==k&&h.extend(a.oPreviousSearch,Bb(e.search));b=0;for(c=e.columns.length;b<c;b++){var f=e.columns[b];f.visible!==k&&(d[b].bVisible=f.visible);f.search!==k&&h.extend(a.aoPreSearchCols[b],Bb(f.search))}u(a,"aoStateLoaded","stateLoaded",[a,e])}}}function xa(a){var b=m.settings,a=h.inArray(a,G(b,"nTable"));return-1!==a?b[a]:null}function L(a,b,c,d){c="DataTables warning: "+(a?"table id="+a.sTableId+" - ":"")+c;d&&(c+=". For more information about this error, please see http://datatables.net/tn/"+
d);if(b)D.console&&console.log&&console.log(c);else if(b=m.ext,b=b.sErrMode||b.errMode,a&&u(a,null,"error",[a,d,c]),"alert"==b)alert(c);else{if("throw"==b)throw Error(c);"function"==typeof b&&b(a,d,c)}}function E(a,b,c,d){h.isArray(c)?h.each(c,function(c,d){h.isArray(d)?E(a,b,d[0],d[1]):E(a,b,d)}):(d===k&&(d=c),b[c]!==k&&(a[d]=b[c]))}function Lb(a,b,c){var d,e;for(e in b)b.hasOwnProperty(e)&&(d=b[e],h.isPlainObject(d)?(h.isPlainObject(a[e])||(a[e]={}),h.extend(!0,a[e],d)):a[e]=c&&"data"!==e&&"aaData"!==
e&&h.isArray(d)?d.slice():d);return a}function Wa(a,b,c){h(a).bind("click.DT",b,function(b){a.blur();c(b)}).bind("keypress.DT",b,function(a){13===a.which&&(a.preventDefault(),c(a))}).bind("selectstart.DT",function(){return!1})}function z(a,b,c,d){c&&a[b].push({fn:c,sName:d})}function u(a,b,c,d){var e=[];b&&(e=h.map(a[b].slice().reverse(),function(b){return b.fn.apply(a.oInstance,d)}));null!==c&&(b=h.Event(c+".dt"),h(a.nTable).trigger(b,d),e.push(b.result));return e}function Sa(a){var b=a._iDisplayStart,
c=a.fnDisplayEnd(),d=a._iDisplayLength;b>=c&&(b=c-d);b-=b%d;if(-1===d||0>b)b=0;a._iDisplayStart=b}function Na(a,b){var c=a.renderer,d=m.ext.renderer[b];return h.isPlainObject(c)&&c[b]?d[c[b]]||d._:"string"===typeof c?d[c]||d._:d._}function y(a){return a.oFeatures.bServerSide?"ssp":a.ajax||a.sAjaxSource?"ajax":"dom"}function ya(a,b){var c=[],c=Mb.numbers_length,d=Math.floor(c/2);b<=c?c=W(0,b):a<=d?(c=W(0,c-2),c.push("ellipsis"),c.push(b-1)):(a>=b-1-d?c=W(b-(c-2),b):(c=W(a-d+2,a+d-1),c.push("ellipsis"),
c.push(b-1)),c.splice(0,0,"ellipsis"),c.splice(0,0,0));c.DT_el="span";return c}function db(a){h.each({num:function(b){return za(b,a)},"num-fmt":function(b){return za(b,a,Xa)},"html-num":function(b){return za(b,a,Aa)},"html-num-fmt":function(b){return za(b,a,Aa,Xa)}},function(b,c){v.type.order[b+a+"-pre"]=c;b.match(/^html\-/)&&(v.type.search[b+a]=v.type.search.html)})}function Nb(a){return function(){var b=[xa(this[m.ext.iApiIndex])].concat(Array.prototype.slice.call(arguments));return m.ext.internal[a].apply(this,
b)}}var m=function(a){this.$=function(a,b){return this.api(!0).$(a,b)};this._=function(a,b){return this.api(!0).rows(a,b).data()};this.api=function(a){return a?new r(xa(this[v.iApiIndex])):new r(this)};this.fnAddData=function(a,b){var c=this.api(!0),d=h.isArray(a)&&(h.isArray(a[0])||h.isPlainObject(a[0]))?c.rows.add(a):c.row.add(a);(b===k||b)&&c.draw();return d.flatten().toArray()};this.fnAdjustColumnSizing=function(a){var b=this.api(!0).columns.adjust(),c=b.settings()[0],d=c.oScroll;a===k||a?b.draw(!1):
(""!==d.sX||""!==d.sY)&&ka(c)};this.fnClearTable=function(a){var b=this.api(!0).clear();(a===k||a)&&b.draw()};this.fnClose=function(a){this.api(!0).row(a).child.hide()};this.fnDeleteRow=function(a,b,c){var d=this.api(!0),a=d.rows(a),e=a.settings()[0],h=e.aoData[a[0][0]];a.remove();b&&b.call(this,e,h);(c===k||c)&&d.draw();return h};this.fnDestroy=function(a){this.api(!0).destroy(a)};this.fnDraw=function(a){this.api(!0).draw(a)};this.fnFilter=function(a,b,c,d,e,h){e=this.api(!0);null===b||b===k?e.search(a,
c,d,h):e.column(b).search(a,c,d,h);e.draw()};this.fnGetData=function(a,b){var c=this.api(!0);if(a!==k){var d=a.nodeName?a.nodeName.toLowerCase():"";return b!==k||"td"==d||"th"==d?c.cell(a,b).data():c.row(a).data()||null}return c.data().toArray()};this.fnGetNodes=function(a){var b=this.api(!0);return a!==k?b.row(a).node():b.rows().nodes().flatten().toArray()};this.fnGetPosition=function(a){var b=this.api(!0),c=a.nodeName.toUpperCase();return"TR"==c?b.row(a).index():"TD"==c||"TH"==c?(a=b.cell(a).index(),
[a.row,a.columnVisible,a.column]):null};this.fnIsOpen=function(a){return this.api(!0).row(a).child.isShown()};this.fnOpen=function(a,b,c){return this.api(!0).row(a).child(b,c).show().child()[0]};this.fnPageChange=function(a,b){var c=this.api(!0).page(a);(b===k||b)&&c.draw(!1)};this.fnSetColumnVis=function(a,b,c){a=this.api(!0).column(a).visible(b);(c===k||c)&&a.columns.adjust().draw()};this.fnSettings=function(){return xa(this[v.iApiIndex])};this.fnSort=function(a){this.api(!0).order(a).draw()};this.fnSortListener=
function(a,b,c){this.api(!0).order.listener(a,b,c)};this.fnUpdate=function(a,b,c,d,e){var h=this.api(!0);c===k||null===c?h.row(b).data(a):h.cell(b,c).data(a);(e===k||e)&&h.columns.adjust();(d===k||d)&&h.draw();return 0};this.fnVersionCheck=v.fnVersionCheck;var b=this,c=a===k,d=this.length;c&&(a={});this.oApi=this.internal=v.internal;for(var e in m.ext.internal)e&&(this[e]=Nb(e));this.each(function(){var e={},e=1<d?Lb(e,a,!0):a,g=0,j,i=this.getAttribute("id"),n=!1,l=m.defaults,q=h(this);if("table"!=
this.nodeName.toLowerCase())L(null,0,"Non-table node initialisation ("+this.nodeName+")",2);else{eb(l);fb(l.column);K(l,l,!0);K(l.column,l.column,!0);K(l,h.extend(e,q.data()));var t=m.settings,g=0;for(j=t.length;g<j;g++){var p=t[g];if(p.nTable==this||p.nTHead.parentNode==this||p.nTFoot&&p.nTFoot.parentNode==this){g=e.bRetrieve!==k?e.bRetrieve:l.bRetrieve;if(c||g)return p.oInstance;if(e.bDestroy!==k?e.bDestroy:l.bDestroy){p.oInstance.fnDestroy();break}else{L(p,0,"Cannot reinitialise DataTable",3);
return}}if(p.sTableId==this.id){t.splice(g,1);break}}if(null===i||""===i)this.id=i="DataTables_Table_"+m.ext._unique++;var o=h.extend(!0,{},m.models.oSettings,{sDestroyWidth:q[0].style.width,sInstance:i,sTableId:i});o.nTable=this;o.oApi=b.internal;o.oInit=e;t.push(o);o.oInstance=1===b.length?b:q.dataTable();eb(e);e.oLanguage&&Da(e.oLanguage);e.aLengthMenu&&!e.iDisplayLength&&(e.iDisplayLength=h.isArray(e.aLengthMenu[0])?e.aLengthMenu[0][0]:e.aLengthMenu[0]);e=Lb(h.extend(!0,{},l),e);E(o.oFeatures,
e,"bPaginate bLengthChange bFilter bSort bSortMulti bInfo bProcessing bAutoWidth bSortClasses bServerSide bDeferRender".split(" "));E(o,e,["asStripeClasses","ajax","fnServerData","fnFormatNumber","sServerMethod","aaSorting","aaSortingFixed","aLengthMenu","sPaginationType","sAjaxSource","sAjaxDataProp","iStateDuration","sDom","bSortCellsTop","iTabIndex","fnStateLoadCallback","fnStateSaveCallback","renderer","searchDelay","rowId",["iCookieDuration","iStateDuration"],["oSearch","oPreviousSearch"],["aoSearchCols",
"aoPreSearchCols"],["iDisplayLength","_iDisplayLength"],["bJQueryUI","bJUI"]]);E(o.oScroll,e,[["sScrollX","sX"],["sScrollXInner","sXInner"],["sScrollY","sY"],["bScrollCollapse","bCollapse"]]);E(o.oLanguage,e,"fnInfoCallback");z(o,"aoDrawCallback",e.fnDrawCallback,"user");z(o,"aoServerParams",e.fnServerParams,"user");z(o,"aoStateSaveParams",e.fnStateSaveParams,"user");z(o,"aoStateLoadParams",e.fnStateLoadParams,"user");z(o,"aoStateLoaded",e.fnStateLoaded,"user");z(o,"aoRowCallback",e.fnRowCallback,
"user");z(o,"aoRowCreatedCallback",e.fnCreatedRow,"user");z(o,"aoHeaderCallback",e.fnHeaderCallback,"user");z(o,"aoFooterCallback",e.fnFooterCallback,"user");z(o,"aoInitComplete",e.fnInitComplete,"user");z(o,"aoPreDrawCallback",e.fnPreDrawCallback,"user");o.rowIdFn=Q(e.rowId);gb(o);i=o.oClasses;e.bJQueryUI?(h.extend(i,m.ext.oJUIClasses,e.oClasses),e.sDom===l.sDom&&"lfrtip"===l.sDom&&(o.sDom='<"H"lfr>t<"F"ip>'),o.renderer)?h.isPlainObject(o.renderer)&&!o.renderer.header&&(o.renderer.header="jqueryui"):
o.renderer="jqueryui":h.extend(i,m.ext.classes,e.oClasses);q.addClass(i.sTable);o.iInitDisplayStart===k&&(o.iInitDisplayStart=e.iDisplayStart,o._iDisplayStart=e.iDisplayStart);null!==e.iDeferLoading&&(o.bDeferLoading=!0,g=h.isArray(e.iDeferLoading),o._iRecordsDisplay=g?e.iDeferLoading[0]:e.iDeferLoading,o._iRecordsTotal=g?e.iDeferLoading[1]:e.iDeferLoading);var r=o.oLanguage;h.extend(!0,r,e.oLanguage);""!==r.sUrl&&(h.ajax({dataType:"json",url:r.sUrl,success:function(a){Da(a);K(l.oLanguage,a);h.extend(true,
r,a);ga(o)},error:function(){ga(o)}}),n=!0);null===e.asStripeClasses&&(o.asStripeClasses=[i.sStripeOdd,i.sStripeEven]);var g=o.asStripeClasses,v=q.children("tbody").find("tr").eq(0);-1!==h.inArray(!0,h.map(g,function(a){return v.hasClass(a)}))&&(h("tbody tr",this).removeClass(g.join(" ")),o.asDestroyStripes=g.slice());t=[];g=this.getElementsByTagName("thead");0!==g.length&&(da(o.aoHeader,g[0]),t=qa(o));if(null===e.aoColumns){p=[];g=0;for(j=t.length;g<j;g++)p.push(null)}else p=e.aoColumns;g=0;for(j=
p.length;g<j;g++)Ea(o,t?t[g]:null);ib(o,e.aoColumnDefs,p,function(a,b){ja(o,a,b)});if(v.length){var s=function(a,b){return a.getAttribute("data-"+b)!==null?b:null};h(v[0]).children("th, td").each(function(a,b){var c=o.aoColumns[a];if(c.mData===a){var d=s(b,"sort")||s(b,"order"),e=s(b,"filter")||s(b,"search");if(d!==null||e!==null){c.mData={_:a+".display",sort:d!==null?a+".@data-"+d:k,type:d!==null?a+".@data-"+d:k,filter:e!==null?a+".@data-"+e:k};ja(o,a)}}})}var w=o.oFeatures;e.bStateSave&&(w.bStateSave=
!0,Kb(o,e),z(o,"aoDrawCallback",wa,"state_save"));if(e.aaSorting===k){t=o.aaSorting;g=0;for(j=t.length;g<j;g++)t[g][1]=o.aoColumns[g].asSorting[0]}va(o);w.bSort&&z(o,"aoDrawCallback",function(){if(o.bSorted){var a=V(o),b={};h.each(a,function(a,c){b[c.src]=c.dir});u(o,null,"order",[o,a,b]);Jb(o)}});z(o,"aoDrawCallback",function(){(o.bSorted||y(o)==="ssp"||w.bDeferRender)&&va(o)},"sc");g=q.children("caption").each(function(){this._captionSide=q.css("caption-side")});j=q.children("thead");0===j.length&&
(j=h("<thead/>").appendTo(this));o.nTHead=j[0];j=q.children("tbody");0===j.length&&(j=h("<tbody/>").appendTo(this));o.nTBody=j[0];j=q.children("tfoot");if(0===j.length&&0<g.length&&(""!==o.oScroll.sX||""!==o.oScroll.sY))j=h("<tfoot/>").appendTo(this);0===j.length||0===j.children().length?q.addClass(i.sNoFooter):0<j.length&&(o.nTFoot=j[0],da(o.aoFooter,o.nTFoot));if(e.aaData)for(g=0;g<e.aaData.length;g++)N(o,e.aaData[g]);else(o.bDeferLoading||"dom"==y(o))&&ma(o,h(o.nTBody).children("tr"));o.aiDisplay=
o.aiDisplayMaster.slice();o.bInitialised=!0;!1===n&&ga(o)}});b=null;return this},v,r,p,s,Ya={},Ob=/[\r\n]/g,Aa=/<.*?>/g,ac=/^[\w\+\-]/,bc=/[\w\+\-]$/,cc=RegExp("(\\/|\\.|\\*|\\+|\\?|\\||\\(|\\)|\\[|\\]|\\{|\\}|\\\\|\\$|\\^|\\-)","g"),Xa=/[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfk]/gi,M=function(a){return!a||!0===a||"-"===a?!0:!1},Pb=function(a){var b=parseInt(a,10);return!isNaN(b)&&isFinite(a)?b:null},Qb=function(a,b){Ya[b]||(Ya[b]=RegExp(Qa(b),"g"));return"string"===typeof a&&"."!==b?a.replace(/\./g,
"").replace(Ya[b],"."):a},Za=function(a,b,c){var d="string"===typeof a;if(M(a))return!0;b&&d&&(a=Qb(a,b));c&&d&&(a=a.replace(Xa,""));return!isNaN(parseFloat(a))&&isFinite(a)},Rb=function(a,b,c){return M(a)?!0:!(M(a)||"string"===typeof a)?null:Za(a.replace(Aa,""),b,c)?!0:null},G=function(a,b,c){var d=[],e=0,f=a.length;if(c!==k)for(;e<f;e++)a[e]&&a[e][b]&&d.push(a[e][b][c]);else for(;e<f;e++)a[e]&&d.push(a[e][b]);return d},ha=function(a,b,c,d){var e=[],f=0,g=b.length;if(d!==k)for(;f<g;f++)a[b[f]][c]&&
e.push(a[b[f]][c][d]);else for(;f<g;f++)e.push(a[b[f]][c]);return e},W=function(a,b){var c=[],d;b===k?(b=0,d=a):(d=b,b=a);for(var e=b;e<d;e++)c.push(e);return c},Sb=function(a){for(var b=[],c=0,d=a.length;c<d;c++)a[c]&&b.push(a[c]);return b},pa=function(a){var b=[],c,d,e=a.length,f,g=0;d=0;a:for(;d<e;d++){c=a[d];for(f=0;f<g;f++)if(b[f]===c)continue a;b.push(c);g++}return b};m.util={throttle:function(a,b){var c=b!==k?b:200,d,e;return function(){var b=this,g=+new Date,h=arguments;d&&g<d+c?(clearTimeout(e),
e=setTimeout(function(){d=k;a.apply(b,h)},c)):(d=g,a.apply(b,h))}},escapeRegex:function(a){return a.replace(cc,"\\$1")}};var A=function(a,b,c){a[b]!==k&&(a[c]=a[b])},ba=/\[.*?\]$/,U=/\(\)$/,Qa=m.util.escapeRegex,ua=h("<div>")[0],Zb=ua.textContent!==k,$b=/<.*?>/g,Oa=m.util.throttle,Tb=[],w=Array.prototype,dc=function(a){var b,c,d=m.settings,e=h.map(d,function(a){return a.nTable});if(a){if(a.nTable&&a.oApi)return[a];if(a.nodeName&&"table"===a.nodeName.toLowerCase())return b=h.inArray(a,e),-1!==b?[d[b]]:
null;if(a&&"function"===typeof a.settings)return a.settings().toArray();"string"===typeof a?c=h(a):a instanceof h&&(c=a)}else return[];if(c)return c.map(function(){b=h.inArray(this,e);return-1!==b?d[b]:null}).toArray()};r=function(a,b){if(!(this instanceof r))return new r(a,b);var c=[],d=function(a){(a=dc(a))&&(c=c.concat(a))};if(h.isArray(a))for(var e=0,f=a.length;e<f;e++)d(a[e]);else d(a);this.context=pa(c);b&&h.merge(this,b);this.selector={rows:null,cols:null,opts:null};r.extend(this,this,Tb)};
m.Api=r;h.extend(r.prototype,{any:function(){return 0!==this.count()},concat:w.concat,context:[],count:function(){return this.flatten().length},each:function(a){for(var b=0,c=this.length;b<c;b++)a.call(this,this[b],b,this);return this},eq:function(a){var b=this.context;return b.length>a?new r(b[a],this[a]):null},filter:function(a){var b=[];if(w.filter)b=w.filter.call(this,a,this);else for(var c=0,d=this.length;c<d;c++)a.call(this,this[c],c,this)&&b.push(this[c]);return new r(this.context,b)},flatten:function(){var a=
[];return new r(this.context,a.concat.apply(a,this.toArray()))},join:w.join,indexOf:w.indexOf||function(a,b){for(var c=b||0,d=this.length;c<d;c++)if(this[c]===a)return c;return-1},iterator:function(a,b,c,d){var e=[],f,g,h,i,n,l=this.context,m,t,p=this.selector;"string"===typeof a&&(d=c,c=b,b=a,a=!1);g=0;for(h=l.length;g<h;g++){var o=new r(l[g]);if("table"===b)f=c.call(o,l[g],g),f!==k&&e.push(f);else if("columns"===b||"rows"===b)f=c.call(o,l[g],this[g],g),f!==k&&e.push(f);else if("column"===b||"column-rows"===
b||"row"===b||"cell"===b){t=this[g];"column-rows"===b&&(m=Ba(l[g],p.opts));i=0;for(n=t.length;i<n;i++)f=t[i],f="cell"===b?c.call(o,l[g],f.row,f.column,g,i):c.call(o,l[g],f,g,i,m),f!==k&&e.push(f)}}return e.length||d?(a=new r(l,a?e.concat.apply([],e):e),b=a.selector,b.rows=p.rows,b.cols=p.cols,b.opts=p.opts,a):this},lastIndexOf:w.lastIndexOf||function(a,b){return this.indexOf.apply(this.toArray.reverse(),arguments)},length:0,map:function(a){var b=[];if(w.map)b=w.map.call(this,a,this);else for(var c=
0,d=this.length;c<d;c++)b.push(a.call(this,this[c],c));return new r(this.context,b)},pluck:function(a){return this.map(function(b){return b[a]})},pop:w.pop,push:w.push,reduce:w.reduce||function(a,b){return hb(this,a,b,0,this.length,1)},reduceRight:w.reduceRight||function(a,b){return hb(this,a,b,this.length-1,-1,-1)},reverse:w.reverse,selector:null,shift:w.shift,sort:w.sort,splice:w.splice,toArray:function(){return w.slice.call(this)},to$:function(){return h(this)},toJQuery:function(){return h(this)},
unique:function(){return new r(this.context,pa(this))},unshift:w.unshift});r.extend=function(a,b,c){if(c.length&&b&&(b instanceof r||b.__dt_wrapper)){var d,e,f,g=function(a,b,c){return function(){var d=b.apply(a,arguments);r.extend(d,d,c.methodExt);return d}};d=0;for(e=c.length;d<e;d++)f=c[d],b[f.name]="function"===typeof f.val?g(a,f.val,f):h.isPlainObject(f.val)?{}:f.val,b[f.name].__dt_wrapper=!0,r.extend(a,b[f.name],f.propExt)}};r.register=p=function(a,b){if(h.isArray(a))for(var c=0,d=a.length;c<
d;c++)r.register(a[c],b);else for(var e=a.split("."),f=Tb,g,j,c=0,d=e.length;c<d;c++){g=(j=-1!==e[c].indexOf("()"))?e[c].replace("()",""):e[c];var i;a:{i=0;for(var n=f.length;i<n;i++)if(f[i].name===g){i=f[i];break a}i=null}i||(i={name:g,val:{},methodExt:[],propExt:[]},f.push(i));c===d-1?i.val=b:f=j?i.methodExt:i.propExt}};r.registerPlural=s=function(a,b,c){r.register(a,c);r.register(b,function(){var a=c.apply(this,arguments);return a===this?this:a instanceof r?a.length?h.isArray(a[0])?new r(a.context,
a[0]):a[0]:k:a})};p("tables()",function(a){var b;if(a){b=r;var c=this.context;if("number"===typeof a)a=[c[a]];else var d=h.map(c,function(a){return a.nTable}),a=h(d).filter(a).map(function(){var a=h.inArray(this,d);return c[a]}).toArray();b=new b(a)}else b=this;return b});p("table()",function(a){var a=this.tables(a),b=a.context;return b.length?new r(b[0]):a});s("tables().nodes()","table().node()",function(){return this.iterator("table",function(a){return a.nTable},1)});s("tables().body()","table().body()",
function(){return this.iterator("table",function(a){return a.nTBody},1)});s("tables().header()","table().header()",function(){return this.iterator("table",function(a){return a.nTHead},1)});s("tables().footer()","table().footer()",function(){return this.iterator("table",function(a){return a.nTFoot},1)});s("tables().containers()","table().container()",function(){return this.iterator("table",function(a){return a.nTableWrapper},1)});p("draw()",function(a){return this.iterator("table",function(b){"page"===
a?O(b):("string"===typeof a&&(a="full-hold"===a?!1:!0),T(b,!1===a))})});p("page()",function(a){return a===k?this.page.info().page:this.iterator("table",function(b){Ta(b,a)})});p("page.info()",function(){if(0===this.context.length)return k;var a=this.context[0],b=a._iDisplayStart,c=a.oFeatures.bPaginate?a._iDisplayLength:-1,d=a.fnRecordsDisplay(),e=-1===c;return{page:e?0:Math.floor(b/c),pages:e?1:Math.ceil(d/c),start:b,end:a.fnDisplayEnd(),length:c,recordsTotal:a.fnRecordsTotal(),recordsDisplay:d,
serverSide:"ssp"===y(a)}});p("page.len()",function(a){return a===k?0!==this.context.length?this.context[0]._iDisplayLength:k:this.iterator("table",function(b){Ra(b,a)})});var Ub=function(a,b,c){if(c){var d=new r(a);d.one("draw",function(){c(d.ajax.json())})}if("ssp"==y(a))T(a,b);else{C(a,!0);var e=a.jqXHR;e&&4!==e.readyState&&e.abort();ra(a,[],function(c){na(a);for(var c=sa(a,c),d=0,e=c.length;d<e;d++)N(a,c[d]);T(a,b);C(a,!1)})}};p("ajax.json()",function(){var a=this.context;if(0<a.length)return a[0].json});
p("ajax.params()",function(){var a=this.context;if(0<a.length)return a[0].oAjaxData});p("ajax.reload()",function(a,b){return this.iterator("table",function(c){Ub(c,!1===b,a)})});p("ajax.url()",function(a){var b=this.context;if(a===k){if(0===b.length)return k;b=b[0];return b.ajax?h.isPlainObject(b.ajax)?b.ajax.url:b.ajax:b.sAjaxSource}return this.iterator("table",function(b){h.isPlainObject(b.ajax)?b.ajax.url=a:b.ajax=a})});p("ajax.url().load()",function(a,b){return this.iterator("table",function(c){Ub(c,
!1===b,a)})});var $a=function(a,b,c,d,e){var f=[],g,j,i,n,l,m;i=typeof b;if(!b||"string"===i||"function"===i||b.length===k)b=[b];i=0;for(n=b.length;i<n;i++){j=b[i]&&b[i].split?b[i].split(","):[b[i]];l=0;for(m=j.length;l<m;l++)(g=c("string"===typeof j[l]?h.trim(j[l]):j[l]))&&g.length&&(f=f.concat(g))}a=v.selector[a];if(a.length){i=0;for(n=a.length;i<n;i++)f=a[i](d,e,f)}return pa(f)},ab=function(a){a||(a={});a.filter&&a.search===k&&(a.search=a.filter);return h.extend({search:"none",order:"current",
page:"all"},a)},bb=function(a){for(var b=0,c=a.length;b<c;b++)if(0<a[b].length)return a[0]=a[b],a[0].length=1,a.length=1,a.context=[a.context[b]],a;a.length=0;return a},Ba=function(a,b){var c,d,e,f=[],g=a.aiDisplay;c=a.aiDisplayMaster;var j=b.search;d=b.order;e=b.page;if("ssp"==y(a))return"removed"===j?[]:W(0,c.length);if("current"==e){c=a._iDisplayStart;for(d=a.fnDisplayEnd();c<d;c++)f.push(g[c])}else if("current"==d||"applied"==d)f="none"==j?c.slice():"applied"==j?g.slice():h.map(c,function(a){return-1===
h.inArray(a,g)?a:null});else if("index"==d||"original"==d){c=0;for(d=a.aoData.length;c<d;c++)"none"==j?f.push(c):(e=h.inArray(c,g),(-1===e&&"removed"==j||0<=e&&"applied"==j)&&f.push(c))}return f};p("rows()",function(a,b){a===k?a="":h.isPlainObject(a)&&(b=a,a="");var b=ab(b),c=this.iterator("table",function(c){var e=b;return $a("row",a,function(a){var b=Pb(a);if(b!==null&&!e)return[b];var j=Ba(c,e);if(b!==null&&h.inArray(b,j)!==-1)return[b];if(!a)return j;if(typeof a==="function")return h.map(j,function(b){var e=
c.aoData[b];return a(b,e._aData,e.nTr)?b:null});b=Sb(ha(c.aoData,j,"nTr"));if(a.nodeName){if(a._DT_RowIndex!==k)return[a._DT_RowIndex];if(a._DT_CellIndex)return[a._DT_CellIndex.row];b=h(a).closest("*[data-dt-row]");return b.length?[b.data("dt-row")]:[]}if(typeof a==="string"&&a.charAt(0)==="#"){j=c.aIds[a.replace(/^#/,"")];if(j!==k)return[j.idx]}return h(b).filter(a).map(function(){return this._DT_RowIndex}).toArray()},c,e)},1);c.selector.rows=a;c.selector.opts=b;return c});p("rows().nodes()",function(){return this.iterator("row",
function(a,b){return a.aoData[b].nTr||k},1)});p("rows().data()",function(){return this.iterator(!0,"rows",function(a,b){return ha(a.aoData,b,"_aData")},1)});s("rows().cache()","row().cache()",function(a){return this.iterator("row",function(b,c){var d=b.aoData[c];return"search"===a?d._aFilterData:d._aSortData},1)});s("rows().invalidate()","row().invalidate()",function(a){return this.iterator("row",function(b,c){ca(b,c,a)})});s("rows().indexes()","row().index()",function(){return this.iterator("row",
function(a,b){return b},1)});s("rows().ids()","row().id()",function(a){for(var b=[],c=this.context,d=0,e=c.length;d<e;d++)for(var f=0,g=this[d].length;f<g;f++){var h=c[d].rowIdFn(c[d].aoData[this[d][f]]._aData);b.push((!0===a?"#":"")+h)}return new r(c,b)});s("rows().remove()","row().remove()",function(){var a=this;this.iterator("row",function(b,c,d){var e=b.aoData,f=e[c],g,h,i,n,l;e.splice(c,1);g=0;for(h=e.length;g<h;g++)if(i=e[g],l=i.anCells,null!==i.nTr&&(i.nTr._DT_RowIndex=g),null!==l){i=0;for(n=
l.length;i<n;i++)l[i]._DT_CellIndex.row=g}oa(b.aiDisplayMaster,c);oa(b.aiDisplay,c);oa(a[d],c,!1);Sa(b);c=b.rowIdFn(f._aData);c!==k&&delete b.aIds[c]});this.iterator("table",function(a){for(var c=0,d=a.aoData.length;c<d;c++)a.aoData[c].idx=c});return this});p("rows.add()",function(a){var b=this.iterator("table",function(b){var c,f,g,h=[];f=0;for(g=a.length;f<g;f++)c=a[f],c.nodeName&&"TR"===c.nodeName.toUpperCase()?h.push(ma(b,c)[0]):h.push(N(b,c));return h},1),c=this.rows(-1);c.pop();h.merge(c,b);
return c});p("row()",function(a,b){return bb(this.rows(a,b))});p("row().data()",function(a){var b=this.context;if(a===k)return b.length&&this.length?b[0].aoData[this[0]]._aData:k;b[0].aoData[this[0]]._aData=a;ca(b[0],this[0],"data");return this});p("row().node()",function(){var a=this.context;return a.length&&this.length?a[0].aoData[this[0]].nTr||null:null});p("row.add()",function(a){a instanceof h&&a.length&&(a=a[0]);var b=this.iterator("table",function(b){return a.nodeName&&"TR"===a.nodeName.toUpperCase()?
ma(b,a)[0]:N(b,a)});return this.row(b[0])});var cb=function(a,b){var c=a.context;if(c.length&&(c=c[0].aoData[b!==k?b:a[0]])&&c._details)c._details.remove(),c._detailsShow=k,c._details=k},Vb=function(a,b){var c=a.context;if(c.length&&a.length){var d=c[0].aoData[a[0]];if(d._details){(d._detailsShow=b)?d._details.insertAfter(d.nTr):d._details.detach();var e=c[0],f=new r(e),g=e.aoData;f.off("draw.dt.DT_details column-visibility.dt.DT_details destroy.dt.DT_details");0<G(g,"_details").length&&(f.on("draw.dt.DT_details",
function(a,b){e===b&&f.rows({page:"current"}).eq(0).each(function(a){a=g[a];a._detailsShow&&a._details.insertAfter(a.nTr)})}),f.on("column-visibility.dt.DT_details",function(a,b){if(e===b)for(var c,d=aa(b),f=0,h=g.length;f<h;f++)c=g[f],c._details&&c._details.children("td[colspan]").attr("colspan",d)}),f.on("destroy.dt.DT_details",function(a,b){if(e===b)for(var c=0,d=g.length;c<d;c++)g[c]._details&&cb(f,c)}))}}};p("row().child()",function(a,b){var c=this.context;if(a===k)return c.length&&this.length?
c[0].aoData[this[0]]._details:k;if(!0===a)this.child.show();else if(!1===a)cb(this);else if(c.length&&this.length){var d=c[0],c=c[0].aoData[this[0]],e=[],f=function(a,b){if(h.isArray(a)||a instanceof h)for(var c=0,k=a.length;c<k;c++)f(a[c],b);else a.nodeName&&"tr"===a.nodeName.toLowerCase()?e.push(a):(c=h("<tr><td/></tr>").addClass(b),h("td",c).addClass(b).html(a)[0].colSpan=aa(d),e.push(c[0]))};f(a,b);c._details&&c._details.remove();c._details=h(e);c._detailsShow&&c._details.insertAfter(c.nTr)}return this});
p(["row().child.show()","row().child().show()"],function(){Vb(this,!0);return this});p(["row().child.hide()","row().child().hide()"],function(){Vb(this,!1);return this});p(["row().child.remove()","row().child().remove()"],function(){cb(this);return this});p("row().child.isShown()",function(){var a=this.context;return a.length&&this.length?a[0].aoData[this[0]]._detailsShow||!1:!1});var ec=/^(.+):(name|visIdx|visible)$/,Wb=function(a,b,c,d,e){for(var c=[],d=0,f=e.length;d<f;d++)c.push(B(a,e[d],b));
return c};p("columns()",function(a,b){a===k?a="":h.isPlainObject(a)&&(b=a,a="");var b=ab(b),c=this.iterator("table",function(c){var e=a,f=b,g=c.aoColumns,j=G(g,"sName"),i=G(g,"nTh");return $a("column",e,function(a){var b=Pb(a);if(a==="")return W(g.length);if(b!==null)return[b>=0?b:g.length+b];if(typeof a==="function"){var e=Ba(c,f);return h.map(g,function(b,f){return a(f,Wb(c,f,0,0,e),i[f])?f:null})}var k=typeof a==="string"?a.match(ec):"";if(k)switch(k[2]){case "visIdx":case "visible":b=parseInt(k[1],
10);if(b<0){var m=h.map(g,function(a,b){return a.bVisible?b:null});return[m[m.length+b]]}return[Z(c,b)];case "name":return h.map(j,function(a,b){return a===k[1]?b:null});default:return[]}if(a.nodeName&&a._DT_CellIndex)return[a._DT_CellIndex.column];b=h(i).filter(a).map(function(){return h.inArray(this,i)}).toArray();if(b.length||!a.nodeName)return b;b=h(a).closest("*[data-dt-column]");return b.length?[b.data("dt-column")]:[]},c,f)},1);c.selector.cols=a;c.selector.opts=b;return c});s("columns().header()",
"column().header()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].nTh},1)});s("columns().footer()","column().footer()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].nTf},1)});s("columns().data()","column().data()",function(){return this.iterator("column-rows",Wb,1)});s("columns().dataSrc()","column().dataSrc()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].mData},1)});s("columns().cache()","column().cache()",
function(a){return this.iterator("column-rows",function(b,c,d,e,f){return ha(b.aoData,f,"search"===a?"_aFilterData":"_aSortData",c)},1)});s("columns().nodes()","column().nodes()",function(){return this.iterator("column-rows",function(a,b,c,d,e){return ha(a.aoData,e,"anCells",b)},1)});s("columns().visible()","column().visible()",function(a,b){var c=this.iterator("column",function(b,c){if(a===k)return b.aoColumns[c].bVisible;var f=b.aoColumns,g=f[c],j=b.aoData,i,n,l;if(a!==k&&g.bVisible!==a){if(a){var m=
h.inArray(!0,G(f,"bVisible"),c+1);i=0;for(n=j.length;i<n;i++)l=j[i].nTr,f=j[i].anCells,l&&l.insertBefore(f[c],f[m]||null)}else h(G(b.aoData,"anCells",c)).detach();g.bVisible=a;ea(b,b.aoHeader);ea(b,b.aoFooter);wa(b)}});a!==k&&(this.iterator("column",function(c,e){u(c,null,"column-visibility",[c,e,a,b])}),(b===k||b)&&this.columns.adjust());return c});s("columns().indexes()","column().index()",function(a){return this.iterator("column",function(b,c){return"visible"===a?$(b,c):c},1)});p("columns.adjust()",
function(){return this.iterator("table",function(a){Y(a)},1)});p("column.index()",function(a,b){if(0!==this.context.length){var c=this.context[0];if("fromVisible"===a||"toData"===a)return Z(c,b);if("fromData"===a||"toVisible"===a)return $(c,b)}});p("column()",function(a,b){return bb(this.columns(a,b))});p("cells()",function(a,b,c){h.isPlainObject(a)&&(a.row===k?(c=a,a=null):(c=b,b=null));h.isPlainObject(b)&&(c=b,b=null);if(null===b||b===k)return this.iterator("table",function(b){var d=a,e=ab(c),f=
b.aoData,g=Ba(b,e),j=Sb(ha(f,g,"anCells")),i=h([].concat.apply([],j)),l,n=b.aoColumns.length,m,p,r,u,v,s;return $a("cell",d,function(a){var c=typeof a==="function";if(a===null||a===k||c){m=[];p=0;for(r=g.length;p<r;p++){l=g[p];for(u=0;u<n;u++){v={row:l,column:u};if(c){s=f[l];a(v,B(b,l,u),s.anCells?s.anCells[u]:null)&&m.push(v)}else m.push(v)}}return m}if(h.isPlainObject(a))return[a];c=i.filter(a).map(function(a,b){return{row:b._DT_CellIndex.row,column:b._DT_CellIndex.column}}).toArray();if(c.length||
!a.nodeName)return c;s=h(a).closest("*[data-dt-row]");return s.length?[{row:s.data("dt-row"),column:s.data("dt-column")}]:[]},b,e)});var d=this.columns(b,c),e=this.rows(a,c),f,g,j,i,n,l=this.iterator("table",function(a,b){f=[];g=0;for(j=e[b].length;g<j;g++){i=0;for(n=d[b].length;i<n;i++)f.push({row:e[b][g],column:d[b][i]})}return f},1);h.extend(l.selector,{cols:b,rows:a,opts:c});return l});s("cells().nodes()","cell().node()",function(){return this.iterator("cell",function(a,b,c){return(a=a.aoData[b])&&
a.anCells?a.anCells[c]:k},1)});p("cells().data()",function(){return this.iterator("cell",function(a,b,c){return B(a,b,c)},1)});s("cells().cache()","cell().cache()",function(a){a="search"===a?"_aFilterData":"_aSortData";return this.iterator("cell",function(b,c,d){return b.aoData[c][a][d]},1)});s("cells().render()","cell().render()",function(a){return this.iterator("cell",function(b,c,d){return B(b,c,d,a)},1)});s("cells().indexes()","cell().index()",function(){return this.iterator("cell",function(a,
b,c){return{row:b,column:c,columnVisible:$(a,c)}},1)});s("cells().invalidate()","cell().invalidate()",function(a){return this.iterator("cell",function(b,c,d){ca(b,c,a,d)})});p("cell()",function(a,b,c){return bb(this.cells(a,b,c))});p("cell().data()",function(a){var b=this.context,c=this[0];if(a===k)return b.length&&c.length?B(b[0],c[0].row,c[0].column):k;jb(b[0],c[0].row,c[0].column,a);ca(b[0],c[0].row,"data",c[0].column);return this});p("order()",function(a,b){var c=this.context;if(a===k)return 0!==
c.length?c[0].aaSorting:k;"number"===typeof a?a=[[a,b]]:a.length&&!h.isArray(a[0])&&(a=Array.prototype.slice.call(arguments));return this.iterator("table",function(b){b.aaSorting=a.slice()})});p("order.listener()",function(a,b,c){return this.iterator("table",function(d){Ma(d,a,b,c)})});p("order.fixed()",function(a){if(!a){var b=this.context,b=b.length?b[0].aaSortingFixed:k;return h.isArray(b)?{pre:b}:b}return this.iterator("table",function(b){b.aaSortingFixed=h.extend(!0,{},a)})});p(["columns().order()",
"column().order()"],function(a){var b=this;return this.iterator("table",function(c,d){var e=[];h.each(b[d],function(b,c){e.push([c,a])});c.aaSorting=e})});p("search()",function(a,b,c,d){var e=this.context;return a===k?0!==e.length?e[0].oPreviousSearch.sSearch:k:this.iterator("table",function(e){e.oFeatures.bFilter&&fa(e,h.extend({},e.oPreviousSearch,{sSearch:a+"",bRegex:null===b?!1:b,bSmart:null===c?!0:c,bCaseInsensitive:null===d?!0:d}),1)})});s("columns().search()","column().search()",function(a,
b,c,d){return this.iterator("column",function(e,f){var g=e.aoPreSearchCols;if(a===k)return g[f].sSearch;e.oFeatures.bFilter&&(h.extend(g[f],{sSearch:a+"",bRegex:null===b?!1:b,bSmart:null===c?!0:c,bCaseInsensitive:null===d?!0:d}),fa(e,e.oPreviousSearch,1))})});p("state()",function(){return this.context.length?this.context[0].oSavedState:null});p("state.clear()",function(){return this.iterator("table",function(a){a.fnStateSaveCallback.call(a.oInstance,a,{})})});p("state.loaded()",function(){return this.context.length?
this.context[0].oLoadedState:null});p("state.save()",function(){return this.iterator("table",function(a){wa(a)})});m.versionCheck=m.fnVersionCheck=function(a){for(var b=m.version.split("."),a=a.split("."),c,d,e=0,f=a.length;e<f;e++)if(c=parseInt(b[e],10)||0,d=parseInt(a[e],10)||0,c!==d)return c>d;return!0};m.isDataTable=m.fnIsDataTable=function(a){var b=h(a).get(0),c=!1;h.each(m.settings,function(a,e){var f=e.nScrollHead?h("table",e.nScrollHead)[0]:null,g=e.nScrollFoot?h("table",e.nScrollFoot)[0]:
null;if(e.nTable===b||f===b||g===b)c=!0});return c};m.tables=m.fnTables=function(a){var b=!1;h.isPlainObject(a)&&(b=a.api,a=a.visible);var c=h.map(m.settings,function(b){if(!a||a&&h(b.nTable).is(":visible"))return b.nTable});return b?new r(c):c};m.camelToHungarian=K;p("$()",function(a,b){var c=this.rows(b).nodes(),c=h(c);return h([].concat(c.filter(a).toArray(),c.find(a).toArray()))});h.each(["on","one","off"],function(a,b){p(b+"()",function(){var a=Array.prototype.slice.call(arguments);a[0].match(/\.dt\b/)||
(a[0]+=".dt");var d=h(this.tables().nodes());d[b].apply(d,a);return this})});p("clear()",function(){return this.iterator("table",function(a){na(a)})});p("settings()",function(){return new r(this.context,this.context)});p("init()",function(){var a=this.context;return a.length?a[0].oInit:null});p("data()",function(){return this.iterator("table",function(a){return G(a.aoData,"_aData")}).flatten()});p("destroy()",function(a){a=a||!1;return this.iterator("table",function(b){var c=b.nTableWrapper.parentNode,
d=b.oClasses,e=b.nTable,f=b.nTBody,g=b.nTHead,j=b.nTFoot,i=h(e),f=h(f),k=h(b.nTableWrapper),l=h.map(b.aoData,function(a){return a.nTr}),p;b.bDestroying=!0;u(b,"aoDestroyCallback","destroy",[b]);a||(new r(b)).columns().visible(!0);k.unbind(".DT").find(":not(tbody *)").unbind(".DT");h(D).unbind(".DT-"+b.sInstance);e!=g.parentNode&&(i.children("thead").detach(),i.append(g));j&&e!=j.parentNode&&(i.children("tfoot").detach(),i.append(j));b.aaSorting=[];b.aaSortingFixed=[];va(b);h(l).removeClass(b.asStripeClasses.join(" "));
h("th, td",g).removeClass(d.sSortable+" "+d.sSortableAsc+" "+d.sSortableDesc+" "+d.sSortableNone);b.bJUI&&(h("th span."+d.sSortIcon+", td span."+d.sSortIcon,g).detach(),h("th, td",g).each(function(){var a=h("div."+d.sSortJUIWrapper,this);h(this).append(a.contents());a.detach()}));f.children().detach();f.append(l);g=a?"remove":"detach";i[g]();k[g]();!a&&c&&(c.insertBefore(e,b.nTableReinsertBefore),i.css("width",b.sDestroyWidth).removeClass(d.sTable),(p=b.asDestroyStripes.length)&&f.children().each(function(a){h(this).addClass(b.asDestroyStripes[a%
p])}));c=h.inArray(b,m.settings);-1!==c&&m.settings.splice(c,1)})});h.each(["column","row","cell"],function(a,b){p(b+"s().every()",function(a){var d=this.selector.opts,e=this;return this.iterator(b,function(f,g,h,i,n){a.call(e[b](g,"cell"===b?h:d,"cell"===b?d:k),g,h,i,n)})})});p("i18n()",function(a,b,c){var d=this.context[0],a=Q(a)(d.oLanguage);a===k&&(a=b);c!==k&&h.isPlainObject(a)&&(a=a[c]!==k?a[c]:a._);return a.replace("%d",c)});m.version="1.10.12";m.settings=[];m.models={};m.models.oSearch={bCaseInsensitive:!0,
sSearch:"",bRegex:!1,bSmart:!0};m.models.oRow={nTr:null,anCells:null,_aData:[],_aSortData:null,_aFilterData:null,_sFilterRow:null,_sRowStripe:"",src:null,idx:-1};m.models.oColumn={idx:null,aDataSort:null,asSorting:null,bSearchable:null,bSortable:null,bVisible:null,_sManualType:null,_bAttrSrc:!1,fnCreatedCell:null,fnGetData:null,fnSetData:null,mData:null,mRender:null,nTh:null,nTf:null,sClass:null,sContentPadding:null,sDefaultContent:null,sName:null,sSortDataType:"std",sSortingClass:null,sSortingClassJUI:null,
sTitle:null,sType:null,sWidth:null,sWidthOrig:null};m.defaults={aaData:null,aaSorting:[[0,"asc"]],aaSortingFixed:[],ajax:null,aLengthMenu:[10,25,50,100],aoColumns:null,aoColumnDefs:null,aoSearchCols:[],asStripeClasses:null,bAutoWidth:!0,bDeferRender:!1,bDestroy:!1,bFilter:!0,bInfo:!0,bJQueryUI:!1,bLengthChange:!0,bPaginate:!0,bProcessing:!1,bRetrieve:!1,bScrollCollapse:!1,bServerSide:!1,bSort:!0,bSortMulti:!0,bSortCellsTop:!1,bSortClasses:!0,bStateSave:!1,fnCreatedRow:null,fnDrawCallback:null,fnFooterCallback:null,
fnFormatNumber:function(a){return a.toString().replace(/\B(?=(\d{3})+(?!\d))/g,this.oLanguage.sThousands)},fnHeaderCallback:null,fnInfoCallback:null,fnInitComplete:null,fnPreDrawCallback:null,fnRowCallback:null,fnServerData:null,fnServerParams:null,fnStateLoadCallback:function(a){try{return JSON.parse((-1===a.iStateDuration?sessionStorage:localStorage).getItem("DataTables_"+a.sInstance+"_"+location.pathname))}catch(b){}},fnStateLoadParams:null,fnStateLoaded:null,fnStateSaveCallback:function(a,b){try{(-1===
a.iStateDuration?sessionStorage:localStorage).setItem("DataTables_"+a.sInstance+"_"+location.pathname,JSON.stringify(b))}catch(c){}},fnStateSaveParams:null,iStateDuration:7200,iDeferLoading:null,iDisplayLength:10,iDisplayStart:0,iTabIndex:0,oClasses:{},oLanguage:{oAria:{sSortAscending:": activate to sort column ascending",sSortDescending:": activate to sort column descending"},oPaginate:{sFirst:"First",sLast:"Last",sNext:"Next",sPrevious:"Previous"},sEmptyTable:"No data available in table",sInfo:"Showing _START_ to _END_ of _TOTAL_ entries",
sInfoEmpty:"Showing 0 to 0 of 0 entries",sInfoFiltered:"(filtered from _MAX_ total entries)",sInfoPostFix:"",sDecimal:"",sThousands:",",sLengthMenu:"Show _MENU_ entries",sLoadingRecords:"Loading...",sProcessing:"Processing...",sSearch:"Search:",sSearchPlaceholder:"",sUrl:"",sZeroRecords:"No matching records found"},oSearch:h.extend({},m.models.oSearch),sAjaxDataProp:"data",sAjaxSource:null,sDom:"lfrtip",searchDelay:null,sPaginationType:"simple_numbers",sScrollX:"",sScrollXInner:"",sScrollY:"",sServerMethod:"GET",
renderer:null,rowId:"DT_RowId"};X(m.defaults);m.defaults.column={aDataSort:null,iDataSort:-1,asSorting:["asc","desc"],bSearchable:!0,bSortable:!0,bVisible:!0,fnCreatedCell:null,mData:null,mRender:null,sCellType:"td",sClass:"",sContentPadding:"",sDefaultContent:null,sName:"",sSortDataType:"std",sTitle:null,sType:null,sWidth:null};X(m.defaults.column);m.models.oSettings={oFeatures:{bAutoWidth:null,bDeferRender:null,bFilter:null,bInfo:null,bLengthChange:null,bPaginate:null,bProcessing:null,bServerSide:null,
bSort:null,bSortMulti:null,bSortClasses:null,bStateSave:null},oScroll:{bCollapse:null,iBarWidth:0,sX:null,sXInner:null,sY:null},oLanguage:{fnInfoCallback:null},oBrowser:{bScrollOversize:!1,bScrollbarLeft:!1,bBounding:!1,barWidth:0},ajax:null,aanFeatures:[],aoData:[],aiDisplay:[],aiDisplayMaster:[],aIds:{},aoColumns:[],aoHeader:[],aoFooter:[],oPreviousSearch:{},aoPreSearchCols:[],aaSorting:null,aaSortingFixed:[],asStripeClasses:null,asDestroyStripes:[],sDestroyWidth:0,aoRowCallback:[],aoHeaderCallback:[],
aoFooterCallback:[],aoDrawCallback:[],aoRowCreatedCallback:[],aoPreDrawCallback:[],aoInitComplete:[],aoStateSaveParams:[],aoStateLoadParams:[],aoStateLoaded:[],sTableId:"",nTable:null,nTHead:null,nTFoot:null,nTBody:null,nTableWrapper:null,bDeferLoading:!1,bInitialised:!1,aoOpenRows:[],sDom:null,searchDelay:null,sPaginationType:"two_button",iStateDuration:0,aoStateSave:[],aoStateLoad:[],oSavedState:null,oLoadedState:null,sAjaxSource:null,sAjaxDataProp:null,bAjaxDataGet:!0,jqXHR:null,json:k,oAjaxData:k,
fnServerData:null,aoServerParams:[],sServerMethod:null,fnFormatNumber:null,aLengthMenu:null,iDraw:0,bDrawing:!1,iDrawError:-1,_iDisplayLength:10,_iDisplayStart:0,_iRecordsTotal:0,_iRecordsDisplay:0,bJUI:null,oClasses:{},bFiltered:!1,bSorted:!1,bSortCellsTop:null,oInit:null,aoDestroyCallback:[],fnRecordsTotal:function(){return"ssp"==y(this)?1*this._iRecordsTotal:this.aiDisplayMaster.length},fnRecordsDisplay:function(){return"ssp"==y(this)?1*this._iRecordsDisplay:this.aiDisplay.length},fnDisplayEnd:function(){var a=
this._iDisplayLength,b=this._iDisplayStart,c=b+a,d=this.aiDisplay.length,e=this.oFeatures,f=e.bPaginate;return e.bServerSide?!1===f||-1===a?b+d:Math.min(b+a,this._iRecordsDisplay):!f||c>d||-1===a?d:c},oInstance:null,sInstance:null,iTabIndex:0,nScrollHead:null,nScrollFoot:null,aLastSort:[],oPlugins:{},rowIdFn:null,rowId:null};m.ext=v={buttons:{},classes:{},builder:"-source-",errMode:"alert",feature:[],search:[],selector:{cell:[],column:[],row:[]},internal:{},legacy:{ajax:null},pager:{},renderer:{pageButton:{},
header:{}},order:{},type:{detect:[],search:{},order:{}},_unique:0,fnVersionCheck:m.fnVersionCheck,iApiIndex:0,oJUIClasses:{},sVersion:m.version};h.extend(v,{afnFiltering:v.search,aTypes:v.type.detect,ofnSearch:v.type.search,oSort:v.type.order,afnSortData:v.order,aoFeatures:v.feature,oApi:v.internal,oStdClasses:v.classes,oPagination:v.pager});h.extend(m.ext.classes,{sTable:"dataTable",sNoFooter:"no-footer",sPageButton:"paginate_button",sPageButtonActive:"current",sPageButtonDisabled:"disabled",sStripeOdd:"odd",
sStripeEven:"even",sRowEmpty:"dataTables_empty",sWrapper:"dataTables_wrapper",sFilter:"dataTables_filter",sInfo:"dataTables_info",sPaging:"dataTables_paginate paging_",sLength:"dataTables_length",sProcessing:"dataTables_processing",sSortAsc:"sorting_asc",sSortDesc:"sorting_desc",sSortable:"sorting",sSortableAsc:"sorting_asc_disabled",sSortableDesc:"sorting_desc_disabled",sSortableNone:"sorting_disabled",sSortColumn:"sorting_",sFilterInput:"",sLengthSelect:"",sScrollWrapper:"dataTables_scroll",sScrollHead:"dataTables_scrollHead",
sScrollHeadInner:"dataTables_scrollHeadInner",sScrollBody:"dataTables_scrollBody",sScrollFoot:"dataTables_scrollFoot",sScrollFootInner:"dataTables_scrollFootInner",sHeaderTH:"",sFooterTH:"",sSortJUIAsc:"",sSortJUIDesc:"",sSortJUI:"",sSortJUIAscAllowed:"",sSortJUIDescAllowed:"",sSortJUIWrapper:"",sSortIcon:"",sJUIHeader:"",sJUIFooter:""});var Ca="",Ca="",H=Ca+"ui-state-default",ia=Ca+"css_right ui-icon ui-icon-",Xb=Ca+"fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix";h.extend(m.ext.oJUIClasses,
m.ext.classes,{sPageButton:"fg-button ui-button "+H,sPageButtonActive:"ui-state-disabled",sPageButtonDisabled:"ui-state-disabled",sPaging:"dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi ui-buttonset-multi paging_",sSortAsc:H+" sorting_asc",sSortDesc:H+" sorting_desc",sSortable:H+" sorting",sSortableAsc:H+" sorting_asc_disabled",sSortableDesc:H+" sorting_desc_disabled",sSortableNone:H+" sorting_disabled",sSortJUIAsc:ia+"triangle-1-n",sSortJUIDesc:ia+"triangle-1-s",sSortJUI:ia+"carat-2-n-s",
sSortJUIAscAllowed:ia+"carat-1-n",sSortJUIDescAllowed:ia+"carat-1-s",sSortJUIWrapper:"DataTables_sort_wrapper",sSortIcon:"DataTables_sort_icon",sScrollHead:"dataTables_scrollHead "+H,sScrollFoot:"dataTables_scrollFoot "+H,sHeaderTH:H,sFooterTH:H,sJUIHeader:Xb+" ui-corner-tl ui-corner-tr",sJUIFooter:Xb+" ui-corner-bl ui-corner-br"});var Mb=m.ext.pager;h.extend(Mb,{simple:function(){return["previous","next"]},full:function(){return["first","previous","next","last"]},numbers:function(a,b){return[ya(a,
b)]},simple_numbers:function(a,b){return["previous",ya(a,b),"next"]},full_numbers:function(a,b){return["first","previous",ya(a,b),"next","last"]},_numbers:ya,numbers_length:7});h.extend(!0,m.ext.renderer,{pageButton:{_:function(a,b,c,d,e,f){var g=a.oClasses,j=a.oLanguage.oPaginate,i=a.oLanguage.oAria.paginate||{},k,l,m=0,p=function(b,d){var o,r,u,s,v=function(b){Ta(a,b.data.action,true)};o=0;for(r=d.length;o<r;o++){s=d[o];if(h.isArray(s)){u=h("<"+(s.DT_el||"div")+"/>").appendTo(b);p(u,s)}else{k=null;
l="";switch(s){case "ellipsis":b.append('<span class="ellipsis">&#x2026;</span>');break;case "first":k=j.sFirst;l=s+(e>0?"":" "+g.sPageButtonDisabled);break;case "previous":k=j.sPrevious;l=s+(e>0?"":" "+g.sPageButtonDisabled);break;case "next":k=j.sNext;l=s+(e<f-1?"":" "+g.sPageButtonDisabled);break;case "last":k=j.sLast;l=s+(e<f-1?"":" "+g.sPageButtonDisabled);break;default:k=s+1;l=e===s?g.sPageButtonActive:""}if(k!==null){u=h("<a>",{"class":g.sPageButton+" "+l,"aria-controls":a.sTableId,"aria-label":i[s],
"data-dt-idx":m,tabindex:a.iTabIndex,id:c===0&&typeof s==="string"?a.sTableId+"_"+s:null}).html(k).appendTo(b);Wa(u,{action:s},v);m++}}}},r;try{r=h(b).find(I.activeElement).data("dt-idx")}catch(o){}p(h(b).empty(),d);r&&h(b).find("[data-dt-idx="+r+"]").focus()}}});h.extend(m.ext.type.detect,[function(a,b){var c=b.oLanguage.sDecimal;return Za(a,c)?"num"+c:null},function(a){if(a&&!(a instanceof Date)&&(!ac.test(a)||!bc.test(a)))return null;var b=Date.parse(a);return null!==b&&!isNaN(b)||M(a)?"date":
null},function(a,b){var c=b.oLanguage.sDecimal;return Za(a,c,!0)?"num-fmt"+c:null},function(a,b){var c=b.oLanguage.sDecimal;return Rb(a,c)?"html-num"+c:null},function(a,b){var c=b.oLanguage.sDecimal;return Rb(a,c,!0)?"html-num-fmt"+c:null},function(a){return M(a)||"string"===typeof a&&-1!==a.indexOf("<")?"html":null}]);h.extend(m.ext.type.search,{html:function(a){return M(a)?a:"string"===typeof a?a.replace(Ob," ").replace(Aa,""):""},string:function(a){return M(a)?a:"string"===typeof a?a.replace(Ob,
" "):a}});var za=function(a,b,c,d){if(0!==a&&(!a||"-"===a))return-Infinity;b&&(a=Qb(a,b));a.replace&&(c&&(a=a.replace(c,"")),d&&(a=a.replace(d,"")));return 1*a};h.extend(v.type.order,{"date-pre":function(a){return Date.parse(a)||0},"html-pre":function(a){return M(a)?"":a.replace?a.replace(/<.*?>/g,"").toLowerCase():a+""},"string-pre":function(a){return M(a)?"":"string"===typeof a?a.toLowerCase():!a.toString?"":a.toString()},"string-asc":function(a,b){return a<b?-1:a>b?1:0},"string-desc":function(a,
b){return a<b?1:a>b?-1:0}});db("");h.extend(!0,m.ext.renderer,{header:{_:function(a,b,c,d){h(a.nTable).on("order.dt.DT",function(e,f,g,h){if(a===f){e=c.idx;b.removeClass(c.sSortingClass+" "+d.sSortAsc+" "+d.sSortDesc).addClass(h[e]=="asc"?d.sSortAsc:h[e]=="desc"?d.sSortDesc:c.sSortingClass)}})},jqueryui:function(a,b,c,d){h("<div/>").addClass(d.sSortJUIWrapper).append(b.contents()).append(h("<span/>").addClass(d.sSortIcon+" "+c.sSortingClassJUI)).appendTo(b);h(a.nTable).on("order.dt.DT",function(e,
f,g,h){if(a===f){e=c.idx;b.removeClass(d.sSortAsc+" "+d.sSortDesc).addClass(h[e]=="asc"?d.sSortAsc:h[e]=="desc"?d.sSortDesc:c.sSortingClass);b.find("span."+d.sSortIcon).removeClass(d.sSortJUIAsc+" "+d.sSortJUIDesc+" "+d.sSortJUI+" "+d.sSortJUIAscAllowed+" "+d.sSortJUIDescAllowed).addClass(h[e]=="asc"?d.sSortJUIAsc:h[e]=="desc"?d.sSortJUIDesc:c.sSortingClassJUI)}})}}});var Yb=function(a){return"string"===typeof a?a.replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;"):a};m.render={number:function(a,
b,c,d,e){return{display:function(f){if("number"!==typeof f&&"string"!==typeof f)return f;var g=0>f?"-":"",h=parseFloat(f);if(isNaN(h))return Yb(f);f=Math.abs(h);h=parseInt(f,10);f=c?b+(f-h).toFixed(c).substring(2):"";return g+(d||"")+h.toString().replace(/\B(?=(\d{3})+(?!\d))/g,a)+f+(e||"")}}},text:function(){return{display:Yb}}};h.extend(m.ext.internal,{_fnExternApiFunc:Nb,_fnBuildAjax:ra,_fnAjaxUpdate:lb,_fnAjaxParameters:ub,_fnAjaxUpdateDraw:vb,_fnAjaxDataSrc:sa,_fnAddColumn:Ea,_fnColumnOptions:ja,
_fnAdjustColumnSizing:Y,_fnVisibleToColumnIndex:Z,_fnColumnIndexToVisible:$,_fnVisbleColumns:aa,_fnGetColumns:la,_fnColumnTypes:Ga,_fnApplyColumnDefs:ib,_fnHungarianMap:X,_fnCamelToHungarian:K,_fnLanguageCompat:Da,_fnBrowserDetect:gb,_fnAddData:N,_fnAddTr:ma,_fnNodeToDataIndex:function(a,b){return b._DT_RowIndex!==k?b._DT_RowIndex:null},_fnNodeToColumnIndex:function(a,b,c){return h.inArray(c,a.aoData[b].anCells)},_fnGetCellData:B,_fnSetCellData:jb,_fnSplitObjNotation:Ja,_fnGetObjectDataFn:Q,_fnSetObjectDataFn:R,
_fnGetDataMaster:Ka,_fnClearTable:na,_fnDeleteIndex:oa,_fnInvalidate:ca,_fnGetRowElements:Ia,_fnCreateTr:Ha,_fnBuildHead:kb,_fnDrawHead:ea,_fnDraw:O,_fnReDraw:T,_fnAddOptionsHtml:nb,_fnDetectHeader:da,_fnGetUniqueThs:qa,_fnFeatureHtmlFilter:pb,_fnFilterComplete:fa,_fnFilterCustom:yb,_fnFilterColumn:xb,_fnFilter:wb,_fnFilterCreateSearch:Pa,_fnEscapeRegex:Qa,_fnFilterData:zb,_fnFeatureHtmlInfo:sb,_fnUpdateInfo:Cb,_fnInfoMacros:Db,_fnInitialise:ga,_fnInitComplete:ta,_fnLengthChange:Ra,_fnFeatureHtmlLength:ob,
_fnFeatureHtmlPaginate:tb,_fnPageChange:Ta,_fnFeatureHtmlProcessing:qb,_fnProcessingDisplay:C,_fnFeatureHtmlTable:rb,_fnScrollDraw:ka,_fnApplyToChildren:J,_fnCalculateColumnWidths:Fa,_fnThrottle:Oa,_fnConvertToWidth:Fb,_fnGetWidestNode:Gb,_fnGetMaxLenString:Hb,_fnStringToCss:x,_fnSortFlatten:V,_fnSort:mb,_fnSortAria:Jb,_fnSortListener:Va,_fnSortAttachListener:Ma,_fnSortingClasses:va,_fnSortData:Ib,_fnSaveState:wa,_fnLoadState:Kb,_fnSettingsFromNode:xa,_fnLog:L,_fnMap:E,_fnBindAction:Wa,_fnCallbackReg:z,
_fnCallbackFire:u,_fnLengthOverflow:Sa,_fnRenderer:Na,_fnDataSource:y,_fnRowAttributes:La,_fnCalculateEnd:function(){}});h.fn.dataTable=m;m.$=h;h.fn.dataTableSettings=m.settings;h.fn.dataTableExt=m.ext;h.fn.DataTable=function(a){return h(this).dataTable(a).api()};h.each(m,function(a,b){h.fn.DataTable[a]=b});return h.fn.dataTable});

View File

@@ -0,0 +1,166 @@
/*!
DataTables 1.10.18
©2008-2018 SpryMedia Ltd - datatables.net/license
*/
(function(h){"function"===typeof define&&define.amd?define(["jquery"],function(E){return h(E,window,document)}):"object"===typeof exports?module.exports=function(E,H){E||(E=window);H||(H="undefined"!==typeof window?require("jquery"):require("jquery")(E));return h(H,E,E.document)}:h(jQuery,window,document)})(function(h,E,H,k){function Z(a){var b,c,d={};h.each(a,function(e){if((b=e.match(/^([^A-Z]+?)([A-Z])/))&&-1!=="a aa ai ao as b fn i m o s ".indexOf(b[1]+" "))c=e.replace(b[0],b[2].toLowerCase()),
d[c]=e,"o"===b[1]&&Z(a[e])});a._hungarianMap=d}function J(a,b,c){a._hungarianMap||Z(a);var d;h.each(b,function(e){d=a._hungarianMap[e];if(d!==k&&(c||b[d]===k))"o"===d.charAt(0)?(b[d]||(b[d]={}),h.extend(!0,b[d],b[e]),J(a[d],b[d],c)):b[d]=b[e]})}function Ca(a){var b=n.defaults.oLanguage,c=b.sDecimal;c&&Da(c);if(a){var d=a.sZeroRecords;!a.sEmptyTable&&(d&&"No data available in table"===b.sEmptyTable)&&F(a,a,"sZeroRecords","sEmptyTable");!a.sLoadingRecords&&(d&&"Loading..."===b.sLoadingRecords)&&F(a,
a,"sZeroRecords","sLoadingRecords");a.sInfoThousands&&(a.sThousands=a.sInfoThousands);(a=a.sDecimal)&&c!==a&&Da(a)}}function eb(a){A(a,"ordering","bSort");A(a,"orderMulti","bSortMulti");A(a,"orderClasses","bSortClasses");A(a,"orderCellsTop","bSortCellsTop");A(a,"order","aaSorting");A(a,"orderFixed","aaSortingFixed");A(a,"paging","bPaginate");A(a,"pagingType","sPaginationType");A(a,"pageLength","iDisplayLength");A(a,"searching","bFilter");"boolean"===typeof a.sScrollX&&(a.sScrollX=a.sScrollX?"100%":
"");"boolean"===typeof a.scrollX&&(a.scrollX=a.scrollX?"100%":"");if(a=a.aoSearchCols)for(var b=0,c=a.length;b<c;b++)a[b]&&J(n.models.oSearch,a[b])}function fb(a){A(a,"orderable","bSortable");A(a,"orderData","aDataSort");A(a,"orderSequence","asSorting");A(a,"orderDataType","sortDataType");var b=a.aDataSort;"number"===typeof b&&!h.isArray(b)&&(a.aDataSort=[b])}function gb(a){if(!n.__browser){var b={};n.__browser=b;var c=h("<div/>").css({position:"fixed",top:0,left:-1*h(E).scrollLeft(),height:1,width:1,
overflow:"hidden"}).append(h("<div/>").css({position:"absolute",top:1,left:1,width:100,overflow:"scroll"}).append(h("<div/>").css({width:"100%",height:10}))).appendTo("body"),d=c.children(),e=d.children();b.barWidth=d[0].offsetWidth-d[0].clientWidth;b.bScrollOversize=100===e[0].offsetWidth&&100!==d[0].clientWidth;b.bScrollbarLeft=1!==Math.round(e.offset().left);b.bBounding=c[0].getBoundingClientRect().width?!0:!1;c.remove()}h.extend(a.oBrowser,n.__browser);a.oScroll.iBarWidth=n.__browser.barWidth}
function hb(a,b,c,d,e,f){var g,j=!1;c!==k&&(g=c,j=!0);for(;d!==e;)a.hasOwnProperty(d)&&(g=j?b(g,a[d],d,a):a[d],j=!0,d+=f);return g}function Ea(a,b){var c=n.defaults.column,d=a.aoColumns.length,c=h.extend({},n.models.oColumn,c,{nTh:b?b:H.createElement("th"),sTitle:c.sTitle?c.sTitle:b?b.innerHTML:"",aDataSort:c.aDataSort?c.aDataSort:[d],mData:c.mData?c.mData:d,idx:d});a.aoColumns.push(c);c=a.aoPreSearchCols;c[d]=h.extend({},n.models.oSearch,c[d]);ka(a,d,h(b).data())}function ka(a,b,c){var b=a.aoColumns[b],
d=a.oClasses,e=h(b.nTh);if(!b.sWidthOrig){b.sWidthOrig=e.attr("width")||null;var f=(e.attr("style")||"").match(/width:\s*(\d+[pxem%]+)/);f&&(b.sWidthOrig=f[1])}c!==k&&null!==c&&(fb(c),J(n.defaults.column,c),c.mDataProp!==k&&!c.mData&&(c.mData=c.mDataProp),c.sType&&(b._sManualType=c.sType),c.className&&!c.sClass&&(c.sClass=c.className),c.sClass&&e.addClass(c.sClass),h.extend(b,c),F(b,c,"sWidth","sWidthOrig"),c.iDataSort!==k&&(b.aDataSort=[c.iDataSort]),F(b,c,"aDataSort"));var g=b.mData,j=S(g),i=b.mRender?
S(b.mRender):null,c=function(a){return"string"===typeof a&&-1!==a.indexOf("@")};b._bAttrSrc=h.isPlainObject(g)&&(c(g.sort)||c(g.type)||c(g.filter));b._setter=null;b.fnGetData=function(a,b,c){var d=j(a,b,k,c);return i&&b?i(d,b,a,c):d};b.fnSetData=function(a,b,c){return N(g)(a,b,c)};"number"!==typeof g&&(a._rowReadObject=!0);a.oFeatures.bSort||(b.bSortable=!1,e.addClass(d.sSortableNone));a=-1!==h.inArray("asc",b.asSorting);c=-1!==h.inArray("desc",b.asSorting);!b.bSortable||!a&&!c?(b.sSortingClass=d.sSortableNone,
b.sSortingClassJUI=""):a&&!c?(b.sSortingClass=d.sSortableAsc,b.sSortingClassJUI=d.sSortJUIAscAllowed):!a&&c?(b.sSortingClass=d.sSortableDesc,b.sSortingClassJUI=d.sSortJUIDescAllowed):(b.sSortingClass=d.sSortable,b.sSortingClassJUI=d.sSortJUI)}function $(a){if(!1!==a.oFeatures.bAutoWidth){var b=a.aoColumns;Fa(a);for(var c=0,d=b.length;c<d;c++)b[c].nTh.style.width=b[c].sWidth}b=a.oScroll;(""!==b.sY||""!==b.sX)&&la(a);r(a,null,"column-sizing",[a])}function aa(a,b){var c=ma(a,"bVisible");return"number"===
typeof c[b]?c[b]:null}function ba(a,b){var c=ma(a,"bVisible"),c=h.inArray(b,c);return-1!==c?c:null}function V(a){var b=0;h.each(a.aoColumns,function(a,d){d.bVisible&&"none"!==h(d.nTh).css("display")&&b++});return b}function ma(a,b){var c=[];h.map(a.aoColumns,function(a,e){a[b]&&c.push(e)});return c}function Ga(a){var b=a.aoColumns,c=a.aoData,d=n.ext.type.detect,e,f,g,j,i,h,l,q,t;e=0;for(f=b.length;e<f;e++)if(l=b[e],t=[],!l.sType&&l._sManualType)l.sType=l._sManualType;else if(!l.sType){g=0;for(j=d.length;g<
j;g++){i=0;for(h=c.length;i<h;i++){t[i]===k&&(t[i]=B(a,i,e,"type"));q=d[g](t[i],a);if(!q&&g!==d.length-1)break;if("html"===q)break}if(q){l.sType=q;break}}l.sType||(l.sType="string")}}function ib(a,b,c,d){var e,f,g,j,i,m,l=a.aoColumns;if(b)for(e=b.length-1;0<=e;e--){m=b[e];var q=m.targets!==k?m.targets:m.aTargets;h.isArray(q)||(q=[q]);f=0;for(g=q.length;f<g;f++)if("number"===typeof q[f]&&0<=q[f]){for(;l.length<=q[f];)Ea(a);d(q[f],m)}else if("number"===typeof q[f]&&0>q[f])d(l.length+q[f],m);else if("string"===
typeof q[f]){j=0;for(i=l.length;j<i;j++)("_all"==q[f]||h(l[j].nTh).hasClass(q[f]))&&d(j,m)}}if(c){e=0;for(a=c.length;e<a;e++)d(e,c[e])}}function O(a,b,c,d){var e=a.aoData.length,f=h.extend(!0,{},n.models.oRow,{src:c?"dom":"data",idx:e});f._aData=b;a.aoData.push(f);for(var g=a.aoColumns,j=0,i=g.length;j<i;j++)g[j].sType=null;a.aiDisplayMaster.push(e);b=a.rowIdFn(b);b!==k&&(a.aIds[b]=f);(c||!a.oFeatures.bDeferRender)&&Ha(a,e,c,d);return e}function na(a,b){var c;b instanceof h||(b=h(b));return b.map(function(b,
e){c=Ia(a,e);return O(a,c.data,e,c.cells)})}function B(a,b,c,d){var e=a.iDraw,f=a.aoColumns[c],g=a.aoData[b]._aData,j=f.sDefaultContent,i=f.fnGetData(g,d,{settings:a,row:b,col:c});if(i===k)return a.iDrawError!=e&&null===j&&(K(a,0,"Requested unknown parameter "+("function"==typeof f.mData?"{function}":"'"+f.mData+"'")+" for row "+b+", column "+c,4),a.iDrawError=e),j;if((i===g||null===i)&&null!==j&&d!==k)i=j;else if("function"===typeof i)return i.call(g);return null===i&&"display"==d?"":i}function jb(a,
b,c,d){a.aoColumns[c].fnSetData(a.aoData[b]._aData,d,{settings:a,row:b,col:c})}function Ja(a){return h.map(a.match(/(\\.|[^\.])+/g)||[""],function(a){return a.replace(/\\\./g,".")})}function S(a){if(h.isPlainObject(a)){var b={};h.each(a,function(a,c){c&&(b[a]=S(c))});return function(a,c,f,g){var j=b[c]||b._;return j!==k?j(a,c,f,g):a}}if(null===a)return function(a){return a};if("function"===typeof a)return function(b,c,f,g){return a(b,c,f,g)};if("string"===typeof a&&(-1!==a.indexOf(".")||-1!==a.indexOf("[")||
-1!==a.indexOf("("))){var c=function(a,b,f){var g,j;if(""!==f){j=Ja(f);for(var i=0,m=j.length;i<m;i++){f=j[i].match(ca);g=j[i].match(W);if(f){j[i]=j[i].replace(ca,"");""!==j[i]&&(a=a[j[i]]);g=[];j.splice(0,i+1);j=j.join(".");if(h.isArray(a)){i=0;for(m=a.length;i<m;i++)g.push(c(a[i],b,j))}a=f[0].substring(1,f[0].length-1);a=""===a?g:g.join(a);break}else if(g){j[i]=j[i].replace(W,"");a=a[j[i]]();continue}if(null===a||a[j[i]]===k)return k;a=a[j[i]]}}return a};return function(b,e){return c(b,e,a)}}return function(b){return b[a]}}
function N(a){if(h.isPlainObject(a))return N(a._);if(null===a)return function(){};if("function"===typeof a)return function(b,d,e){a(b,"set",d,e)};if("string"===typeof a&&(-1!==a.indexOf(".")||-1!==a.indexOf("[")||-1!==a.indexOf("("))){var b=function(a,d,e){var e=Ja(e),f;f=e[e.length-1];for(var g,j,i=0,m=e.length-1;i<m;i++){g=e[i].match(ca);j=e[i].match(W);if(g){e[i]=e[i].replace(ca,"");a[e[i]]=[];f=e.slice();f.splice(0,i+1);g=f.join(".");if(h.isArray(d)){j=0;for(m=d.length;j<m;j++)f={},b(f,d[j],g),
a[e[i]].push(f)}else a[e[i]]=d;return}j&&(e[i]=e[i].replace(W,""),a=a[e[i]](d));if(null===a[e[i]]||a[e[i]]===k)a[e[i]]={};a=a[e[i]]}if(f.match(W))a[f.replace(W,"")](d);else a[f.replace(ca,"")]=d};return function(c,d){return b(c,d,a)}}return function(b,d){b[a]=d}}function Ka(a){return D(a.aoData,"_aData")}function oa(a){a.aoData.length=0;a.aiDisplayMaster.length=0;a.aiDisplay.length=0;a.aIds={}}function pa(a,b,c){for(var d=-1,e=0,f=a.length;e<f;e++)a[e]==b?d=e:a[e]>b&&a[e]--; -1!=d&&c===k&&a.splice(d,
1)}function da(a,b,c,d){var e=a.aoData[b],f,g=function(c,d){for(;c.childNodes.length;)c.removeChild(c.firstChild);c.innerHTML=B(a,b,d,"display")};if("dom"===c||(!c||"auto"===c)&&"dom"===e.src)e._aData=Ia(a,e,d,d===k?k:e._aData).data;else{var j=e.anCells;if(j)if(d!==k)g(j[d],d);else{c=0;for(f=j.length;c<f;c++)g(j[c],c)}}e._aSortData=null;e._aFilterData=null;g=a.aoColumns;if(d!==k)g[d].sType=null;else{c=0;for(f=g.length;c<f;c++)g[c].sType=null;La(a,e)}}function Ia(a,b,c,d){var e=[],f=b.firstChild,g,
j,i=0,m,l=a.aoColumns,q=a._rowReadObject,d=d!==k?d:q?{}:[],t=function(a,b){if("string"===typeof a){var c=a.indexOf("@");-1!==c&&(c=a.substring(c+1),N(a)(d,b.getAttribute(c)))}},G=function(a){if(c===k||c===i)j=l[i],m=h.trim(a.innerHTML),j&&j._bAttrSrc?(N(j.mData._)(d,m),t(j.mData.sort,a),t(j.mData.type,a),t(j.mData.filter,a)):q?(j._setter||(j._setter=N(j.mData)),j._setter(d,m)):d[i]=m;i++};if(f)for(;f;){g=f.nodeName.toUpperCase();if("TD"==g||"TH"==g)G(f),e.push(f);f=f.nextSibling}else{e=b.anCells;
f=0;for(g=e.length;f<g;f++)G(e[f])}if(b=b.firstChild?b:b.nTr)(b=b.getAttribute("id"))&&N(a.rowId)(d,b);return{data:d,cells:e}}function Ha(a,b,c,d){var e=a.aoData[b],f=e._aData,g=[],j,i,m,l,q;if(null===e.nTr){j=c||H.createElement("tr");e.nTr=j;e.anCells=g;j._DT_RowIndex=b;La(a,e);l=0;for(q=a.aoColumns.length;l<q;l++){m=a.aoColumns[l];i=c?d[l]:H.createElement(m.sCellType);i._DT_CellIndex={row:b,column:l};g.push(i);if((!c||m.mRender||m.mData!==l)&&(!h.isPlainObject(m.mData)||m.mData._!==l+".display"))i.innerHTML=
B(a,b,l,"display");m.sClass&&(i.className+=" "+m.sClass);m.bVisible&&!c?j.appendChild(i):!m.bVisible&&c&&i.parentNode.removeChild(i);m.fnCreatedCell&&m.fnCreatedCell.call(a.oInstance,i,B(a,b,l),f,b,l)}r(a,"aoRowCreatedCallback",null,[j,f,b,g])}e.nTr.setAttribute("role","row")}function La(a,b){var c=b.nTr,d=b._aData;if(c){var e=a.rowIdFn(d);e&&(c.id=e);d.DT_RowClass&&(e=d.DT_RowClass.split(" "),b.__rowc=b.__rowc?qa(b.__rowc.concat(e)):e,h(c).removeClass(b.__rowc.join(" ")).addClass(d.DT_RowClass));
d.DT_RowAttr&&h(c).attr(d.DT_RowAttr);d.DT_RowData&&h(c).data(d.DT_RowData)}}function kb(a){var b,c,d,e,f,g=a.nTHead,j=a.nTFoot,i=0===h("th, td",g).length,m=a.oClasses,l=a.aoColumns;i&&(e=h("<tr/>").appendTo(g));b=0;for(c=l.length;b<c;b++)f=l[b],d=h(f.nTh).addClass(f.sClass),i&&d.appendTo(e),a.oFeatures.bSort&&(d.addClass(f.sSortingClass),!1!==f.bSortable&&(d.attr("tabindex",a.iTabIndex).attr("aria-controls",a.sTableId),Ma(a,f.nTh,b))),f.sTitle!=d[0].innerHTML&&d.html(f.sTitle),Na(a,"header")(a,d,
f,m);i&&ea(a.aoHeader,g);h(g).find(">tr").attr("role","row");h(g).find(">tr>th, >tr>td").addClass(m.sHeaderTH);h(j).find(">tr>th, >tr>td").addClass(m.sFooterTH);if(null!==j){a=a.aoFooter[0];b=0;for(c=a.length;b<c;b++)f=l[b],f.nTf=a[b].cell,f.sClass&&h(f.nTf).addClass(f.sClass)}}function fa(a,b,c){var d,e,f,g=[],j=[],i=a.aoColumns.length,m;if(b){c===k&&(c=!1);d=0;for(e=b.length;d<e;d++){g[d]=b[d].slice();g[d].nTr=b[d].nTr;for(f=i-1;0<=f;f--)!a.aoColumns[f].bVisible&&!c&&g[d].splice(f,1);j.push([])}d=
0;for(e=g.length;d<e;d++){if(a=g[d].nTr)for(;f=a.firstChild;)a.removeChild(f);f=0;for(b=g[d].length;f<b;f++)if(m=i=1,j[d][f]===k){a.appendChild(g[d][f].cell);for(j[d][f]=1;g[d+i]!==k&&g[d][f].cell==g[d+i][f].cell;)j[d+i][f]=1,i++;for(;g[d][f+m]!==k&&g[d][f].cell==g[d][f+m].cell;){for(c=0;c<i;c++)j[d+c][f+m]=1;m++}h(g[d][f].cell).attr("rowspan",i).attr("colspan",m)}}}}function P(a){var b=r(a,"aoPreDrawCallback","preDraw",[a]);if(-1!==h.inArray(!1,b))C(a,!1);else{var b=[],c=0,d=a.asStripeClasses,e=
d.length,f=a.oLanguage,g=a.iInitDisplayStart,j="ssp"==y(a),i=a.aiDisplay;a.bDrawing=!0;g!==k&&-1!==g&&(a._iDisplayStart=j?g:g>=a.fnRecordsDisplay()?0:g,a.iInitDisplayStart=-1);var g=a._iDisplayStart,m=a.fnDisplayEnd();if(a.bDeferLoading)a.bDeferLoading=!1,a.iDraw++,C(a,!1);else if(j){if(!a.bDestroying&&!lb(a))return}else a.iDraw++;if(0!==i.length){f=j?a.aoData.length:m;for(j=j?0:g;j<f;j++){var l=i[j],q=a.aoData[l];null===q.nTr&&Ha(a,l);var t=q.nTr;if(0!==e){var G=d[c%e];q._sRowStripe!=G&&(h(t).removeClass(q._sRowStripe).addClass(G),
q._sRowStripe=G)}r(a,"aoRowCallback",null,[t,q._aData,c,j,l]);b.push(t);c++}}else c=f.sZeroRecords,1==a.iDraw&&"ajax"==y(a)?c=f.sLoadingRecords:f.sEmptyTable&&0===a.fnRecordsTotal()&&(c=f.sEmptyTable),b[0]=h("<tr/>",{"class":e?d[0]:""}).append(h("<td />",{valign:"top",colSpan:V(a),"class":a.oClasses.sRowEmpty}).html(c))[0];r(a,"aoHeaderCallback","header",[h(a.nTHead).children("tr")[0],Ka(a),g,m,i]);r(a,"aoFooterCallback","footer",[h(a.nTFoot).children("tr")[0],Ka(a),g,m,i]);d=h(a.nTBody);d.children().detach();
d.append(h(b));r(a,"aoDrawCallback","draw",[a]);a.bSorted=!1;a.bFiltered=!1;a.bDrawing=!1}}function T(a,b){var c=a.oFeatures,d=c.bFilter;c.bSort&&mb(a);d?ga(a,a.oPreviousSearch):a.aiDisplay=a.aiDisplayMaster.slice();!0!==b&&(a._iDisplayStart=0);a._drawHold=b;P(a);a._drawHold=!1}function nb(a){var b=a.oClasses,c=h(a.nTable),c=h("<div/>").insertBefore(c),d=a.oFeatures,e=h("<div/>",{id:a.sTableId+"_wrapper","class":b.sWrapper+(a.nTFoot?"":" "+b.sNoFooter)});a.nHolding=c[0];a.nTableWrapper=e[0];a.nTableReinsertBefore=
a.nTable.nextSibling;for(var f=a.sDom.split(""),g,j,i,m,l,q,k=0;k<f.length;k++){g=null;j=f[k];if("<"==j){i=h("<div/>")[0];m=f[k+1];if("'"==m||'"'==m){l="";for(q=2;f[k+q]!=m;)l+=f[k+q],q++;"H"==l?l=b.sJUIHeader:"F"==l&&(l=b.sJUIFooter);-1!=l.indexOf(".")?(m=l.split("."),i.id=m[0].substr(1,m[0].length-1),i.className=m[1]):"#"==l.charAt(0)?i.id=l.substr(1,l.length-1):i.className=l;k+=q}e.append(i);e=h(i)}else if(">"==j)e=e.parent();else if("l"==j&&d.bPaginate&&d.bLengthChange)g=ob(a);else if("f"==j&&
d.bFilter)g=pb(a);else if("r"==j&&d.bProcessing)g=qb(a);else if("t"==j)g=rb(a);else if("i"==j&&d.bInfo)g=sb(a);else if("p"==j&&d.bPaginate)g=tb(a);else if(0!==n.ext.feature.length){i=n.ext.feature;q=0;for(m=i.length;q<m;q++)if(j==i[q].cFeature){g=i[q].fnInit(a);break}}g&&(i=a.aanFeatures,i[j]||(i[j]=[]),i[j].push(g),e.append(g))}c.replaceWith(e);a.nHolding=null}function ea(a,b){var c=h(b).children("tr"),d,e,f,g,j,i,m,l,q,k;a.splice(0,a.length);f=0;for(i=c.length;f<i;f++)a.push([]);f=0;for(i=c.length;f<
i;f++){d=c[f];for(e=d.firstChild;e;){if("TD"==e.nodeName.toUpperCase()||"TH"==e.nodeName.toUpperCase()){l=1*e.getAttribute("colspan");q=1*e.getAttribute("rowspan");l=!l||0===l||1===l?1:l;q=!q||0===q||1===q?1:q;g=0;for(j=a[f];j[g];)g++;m=g;k=1===l?!0:!1;for(j=0;j<l;j++)for(g=0;g<q;g++)a[f+g][m+j]={cell:e,unique:k},a[f+g].nTr=d}e=e.nextSibling}}}function ra(a,b,c){var d=[];c||(c=a.aoHeader,b&&(c=[],ea(c,b)));for(var b=0,e=c.length;b<e;b++)for(var f=0,g=c[b].length;f<g;f++)if(c[b][f].unique&&(!d[f]||
!a.bSortCellsTop))d[f]=c[b][f].cell;return d}function sa(a,b,c){r(a,"aoServerParams","serverParams",[b]);if(b&&h.isArray(b)){var d={},e=/(.*?)\[\]$/;h.each(b,function(a,b){var c=b.name.match(e);c?(c=c[0],d[c]||(d[c]=[]),d[c].push(b.value)):d[b.name]=b.value});b=d}var f,g=a.ajax,j=a.oInstance,i=function(b){r(a,null,"xhr",[a,b,a.jqXHR]);c(b)};if(h.isPlainObject(g)&&g.data){f=g.data;var m="function"===typeof f?f(b,a):f,b="function"===typeof f&&m?m:h.extend(!0,b,m);delete g.data}m={data:b,success:function(b){var c=
b.error||b.sError;c&&K(a,0,c);a.json=b;i(b)},dataType:"json",cache:!1,type:a.sServerMethod,error:function(b,c){var d=r(a,null,"xhr",[a,null,a.jqXHR]);-1===h.inArray(!0,d)&&("parsererror"==c?K(a,0,"Invalid JSON response",1):4===b.readyState&&K(a,0,"Ajax error",7));C(a,!1)}};a.oAjaxData=b;r(a,null,"preXhr",[a,b]);a.fnServerData?a.fnServerData.call(j,a.sAjaxSource,h.map(b,function(a,b){return{name:b,value:a}}),i,a):a.sAjaxSource||"string"===typeof g?a.jqXHR=h.ajax(h.extend(m,{url:g||a.sAjaxSource})):
"function"===typeof g?a.jqXHR=g.call(j,b,i,a):(a.jqXHR=h.ajax(h.extend(m,g)),g.data=f)}function lb(a){return a.bAjaxDataGet?(a.iDraw++,C(a,!0),sa(a,ub(a),function(b){vb(a,b)}),!1):!0}function ub(a){var b=a.aoColumns,c=b.length,d=a.oFeatures,e=a.oPreviousSearch,f=a.aoPreSearchCols,g,j=[],i,m,l,k=X(a);g=a._iDisplayStart;i=!1!==d.bPaginate?a._iDisplayLength:-1;var t=function(a,b){j.push({name:a,value:b})};t("sEcho",a.iDraw);t("iColumns",c);t("sColumns",D(b,"sName").join(","));t("iDisplayStart",g);t("iDisplayLength",
i);var G={draw:a.iDraw,columns:[],order:[],start:g,length:i,search:{value:e.sSearch,regex:e.bRegex}};for(g=0;g<c;g++)m=b[g],l=f[g],i="function"==typeof m.mData?"function":m.mData,G.columns.push({data:i,name:m.sName,searchable:m.bSearchable,orderable:m.bSortable,search:{value:l.sSearch,regex:l.bRegex}}),t("mDataProp_"+g,i),d.bFilter&&(t("sSearch_"+g,l.sSearch),t("bRegex_"+g,l.bRegex),t("bSearchable_"+g,m.bSearchable)),d.bSort&&t("bSortable_"+g,m.bSortable);d.bFilter&&(t("sSearch",e.sSearch),t("bRegex",
e.bRegex));d.bSort&&(h.each(k,function(a,b){G.order.push({column:b.col,dir:b.dir});t("iSortCol_"+a,b.col);t("sSortDir_"+a,b.dir)}),t("iSortingCols",k.length));b=n.ext.legacy.ajax;return null===b?a.sAjaxSource?j:G:b?j:G}function vb(a,b){var c=ta(a,b),d=b.sEcho!==k?b.sEcho:b.draw,e=b.iTotalRecords!==k?b.iTotalRecords:b.recordsTotal,f=b.iTotalDisplayRecords!==k?b.iTotalDisplayRecords:b.recordsFiltered;if(d){if(1*d<a.iDraw)return;a.iDraw=1*d}oa(a);a._iRecordsTotal=parseInt(e,10);a._iRecordsDisplay=parseInt(f,
10);d=0;for(e=c.length;d<e;d++)O(a,c[d]);a.aiDisplay=a.aiDisplayMaster.slice();a.bAjaxDataGet=!1;P(a);a._bInitComplete||ua(a,b);a.bAjaxDataGet=!0;C(a,!1)}function ta(a,b){var c=h.isPlainObject(a.ajax)&&a.ajax.dataSrc!==k?a.ajax.dataSrc:a.sAjaxDataProp;return"data"===c?b.aaData||b[c]:""!==c?S(c)(b):b}function pb(a){var b=a.oClasses,c=a.sTableId,d=a.oLanguage,e=a.oPreviousSearch,f=a.aanFeatures,g='<input type="search" class="'+b.sFilterInput+'"/>',j=d.sSearch,j=j.match(/_INPUT_/)?j.replace("_INPUT_",
g):j+g,b=h("<div/>",{id:!f.f?c+"_filter":null,"class":b.sFilter}).append(h("<label/>").append(j)),f=function(){var b=!this.value?"":this.value;b!=e.sSearch&&(ga(a,{sSearch:b,bRegex:e.bRegex,bSmart:e.bSmart,bCaseInsensitive:e.bCaseInsensitive}),a._iDisplayStart=0,P(a))},g=null!==a.searchDelay?a.searchDelay:"ssp"===y(a)?400:0,i=h("input",b).val(e.sSearch).attr("placeholder",d.sSearchPlaceholder).on("keyup.DT search.DT input.DT paste.DT cut.DT",g?Oa(f,g):f).on("keypress.DT",function(a){if(13==a.keyCode)return!1}).attr("aria-controls",
c);h(a.nTable).on("search.dt.DT",function(b,c){if(a===c)try{i[0]!==H.activeElement&&i.val(e.sSearch)}catch(d){}});return b[0]}function ga(a,b,c){var d=a.oPreviousSearch,e=a.aoPreSearchCols,f=function(a){d.sSearch=a.sSearch;d.bRegex=a.bRegex;d.bSmart=a.bSmart;d.bCaseInsensitive=a.bCaseInsensitive};Ga(a);if("ssp"!=y(a)){wb(a,b.sSearch,c,b.bEscapeRegex!==k?!b.bEscapeRegex:b.bRegex,b.bSmart,b.bCaseInsensitive);f(b);for(b=0;b<e.length;b++)xb(a,e[b].sSearch,b,e[b].bEscapeRegex!==k?!e[b].bEscapeRegex:e[b].bRegex,
e[b].bSmart,e[b].bCaseInsensitive);yb(a)}else f(b);a.bFiltered=!0;r(a,null,"search",[a])}function yb(a){for(var b=n.ext.search,c=a.aiDisplay,d,e,f=0,g=b.length;f<g;f++){for(var j=[],i=0,m=c.length;i<m;i++)e=c[i],d=a.aoData[e],b[f](a,d._aFilterData,e,d._aData,i)&&j.push(e);c.length=0;h.merge(c,j)}}function xb(a,b,c,d,e,f){if(""!==b){for(var g=[],j=a.aiDisplay,d=Pa(b,d,e,f),e=0;e<j.length;e++)b=a.aoData[j[e]]._aFilterData[c],d.test(b)&&g.push(j[e]);a.aiDisplay=g}}function wb(a,b,c,d,e,f){var d=Pa(b,
d,e,f),f=a.oPreviousSearch.sSearch,g=a.aiDisplayMaster,j,e=[];0!==n.ext.search.length&&(c=!0);j=zb(a);if(0>=b.length)a.aiDisplay=g.slice();else{if(j||c||f.length>b.length||0!==b.indexOf(f)||a.bSorted)a.aiDisplay=g.slice();b=a.aiDisplay;for(c=0;c<b.length;c++)d.test(a.aoData[b[c]]._sFilterRow)&&e.push(b[c]);a.aiDisplay=e}}function Pa(a,b,c,d){a=b?a:Qa(a);c&&(a="^(?=.*?"+h.map(a.match(/"[^"]+"|[^ ]+/g)||[""],function(a){if('"'===a.charAt(0))var b=a.match(/^"(.*)"$/),a=b?b[1]:a;return a.replace('"',
"")}).join(")(?=.*?")+").*$");return RegExp(a,d?"i":"")}function zb(a){var b=a.aoColumns,c,d,e,f,g,j,i,h,l=n.ext.type.search;c=!1;d=0;for(f=a.aoData.length;d<f;d++)if(h=a.aoData[d],!h._aFilterData){j=[];e=0;for(g=b.length;e<g;e++)c=b[e],c.bSearchable?(i=B(a,d,e,"filter"),l[c.sType]&&(i=l[c.sType](i)),null===i&&(i=""),"string"!==typeof i&&i.toString&&(i=i.toString())):i="",i.indexOf&&-1!==i.indexOf("&")&&(va.innerHTML=i,i=Wb?va.textContent:va.innerText),i.replace&&(i=i.replace(/[\r\n]/g,"")),j.push(i);
h._aFilterData=j;h._sFilterRow=j.join(" ");c=!0}return c}function Ab(a){return{search:a.sSearch,smart:a.bSmart,regex:a.bRegex,caseInsensitive:a.bCaseInsensitive}}function Bb(a){return{sSearch:a.search,bSmart:a.smart,bRegex:a.regex,bCaseInsensitive:a.caseInsensitive}}function sb(a){var b=a.sTableId,c=a.aanFeatures.i,d=h("<div/>",{"class":a.oClasses.sInfo,id:!c?b+"_info":null});c||(a.aoDrawCallback.push({fn:Cb,sName:"information"}),d.attr("role","status").attr("aria-live","polite"),h(a.nTable).attr("aria-describedby",
b+"_info"));return d[0]}function Cb(a){var b=a.aanFeatures.i;if(0!==b.length){var c=a.oLanguage,d=a._iDisplayStart+1,e=a.fnDisplayEnd(),f=a.fnRecordsTotal(),g=a.fnRecordsDisplay(),j=g?c.sInfo:c.sInfoEmpty;g!==f&&(j+=" "+c.sInfoFiltered);j+=c.sInfoPostFix;j=Db(a,j);c=c.fnInfoCallback;null!==c&&(j=c.call(a.oInstance,a,d,e,f,g,j));h(b).html(j)}}function Db(a,b){var c=a.fnFormatNumber,d=a._iDisplayStart+1,e=a._iDisplayLength,f=a.fnRecordsDisplay(),g=-1===e;return b.replace(/_START_/g,c.call(a,d)).replace(/_END_/g,
c.call(a,a.fnDisplayEnd())).replace(/_MAX_/g,c.call(a,a.fnRecordsTotal())).replace(/_TOTAL_/g,c.call(a,f)).replace(/_PAGE_/g,c.call(a,g?1:Math.ceil(d/e))).replace(/_PAGES_/g,c.call(a,g?1:Math.ceil(f/e)))}function ha(a){var b,c,d=a.iInitDisplayStart,e=a.aoColumns,f;c=a.oFeatures;var g=a.bDeferLoading;if(a.bInitialised){nb(a);kb(a);fa(a,a.aoHeader);fa(a,a.aoFooter);C(a,!0);c.bAutoWidth&&Fa(a);b=0;for(c=e.length;b<c;b++)f=e[b],f.sWidth&&(f.nTh.style.width=v(f.sWidth));r(a,null,"preInit",[a]);T(a);e=
y(a);if("ssp"!=e||g)"ajax"==e?sa(a,[],function(c){var f=ta(a,c);for(b=0;b<f.length;b++)O(a,f[b]);a.iInitDisplayStart=d;T(a);C(a,!1);ua(a,c)},a):(C(a,!1),ua(a))}else setTimeout(function(){ha(a)},200)}function ua(a,b){a._bInitComplete=!0;(b||a.oInit.aaData)&&$(a);r(a,null,"plugin-init",[a,b]);r(a,"aoInitComplete","init",[a,b])}function Ra(a,b){var c=parseInt(b,10);a._iDisplayLength=c;Sa(a);r(a,null,"length",[a,c])}function ob(a){for(var b=a.oClasses,c=a.sTableId,d=a.aLengthMenu,e=h.isArray(d[0]),f=
e?d[0]:d,d=e?d[1]:d,e=h("<select/>",{name:c+"_length","aria-controls":c,"class":b.sLengthSelect}),g=0,j=f.length;g<j;g++)e[0][g]=new Option("number"===typeof d[g]?a.fnFormatNumber(d[g]):d[g],f[g]);var i=h("<div><label/></div>").addClass(b.sLength);a.aanFeatures.l||(i[0].id=c+"_length");i.children().append(a.oLanguage.sLengthMenu.replace("_MENU_",e[0].outerHTML));h("select",i).val(a._iDisplayLength).on("change.DT",function(){Ra(a,h(this).val());P(a)});h(a.nTable).on("length.dt.DT",function(b,c,d){a===
c&&h("select",i).val(d)});return i[0]}function tb(a){var b=a.sPaginationType,c=n.ext.pager[b],d="function"===typeof c,e=function(a){P(a)},b=h("<div/>").addClass(a.oClasses.sPaging+b)[0],f=a.aanFeatures;d||c.fnInit(a,b,e);f.p||(b.id=a.sTableId+"_paginate",a.aoDrawCallback.push({fn:function(a){if(d){var b=a._iDisplayStart,i=a._iDisplayLength,h=a.fnRecordsDisplay(),l=-1===i,b=l?0:Math.ceil(b/i),i=l?1:Math.ceil(h/i),h=c(b,i),k,l=0;for(k=f.p.length;l<k;l++)Na(a,"pageButton")(a,f.p[l],l,h,b,i)}else c.fnUpdate(a,
e)},sName:"pagination"}));return b}function Ta(a,b,c){var d=a._iDisplayStart,e=a._iDisplayLength,f=a.fnRecordsDisplay();0===f||-1===e?d=0:"number"===typeof b?(d=b*e,d>f&&(d=0)):"first"==b?d=0:"previous"==b?(d=0<=e?d-e:0,0>d&&(d=0)):"next"==b?d+e<f&&(d+=e):"last"==b?d=Math.floor((f-1)/e)*e:K(a,0,"Unknown paging action: "+b,5);b=a._iDisplayStart!==d;a._iDisplayStart=d;b&&(r(a,null,"page",[a]),c&&P(a));return b}function qb(a){return h("<div/>",{id:!a.aanFeatures.r?a.sTableId+"_processing":null,"class":a.oClasses.sProcessing}).html(a.oLanguage.sProcessing).insertBefore(a.nTable)[0]}
function C(a,b){a.oFeatures.bProcessing&&h(a.aanFeatures.r).css("display",b?"block":"none");r(a,null,"processing",[a,b])}function rb(a){var b=h(a.nTable);b.attr("role","grid");var c=a.oScroll;if(""===c.sX&&""===c.sY)return a.nTable;var d=c.sX,e=c.sY,f=a.oClasses,g=b.children("caption"),j=g.length?g[0]._captionSide:null,i=h(b[0].cloneNode(!1)),m=h(b[0].cloneNode(!1)),l=b.children("tfoot");l.length||(l=null);i=h("<div/>",{"class":f.sScrollWrapper}).append(h("<div/>",{"class":f.sScrollHead}).css({overflow:"hidden",
position:"relative",border:0,width:d?!d?null:v(d):"100%"}).append(h("<div/>",{"class":f.sScrollHeadInner}).css({"box-sizing":"content-box",width:c.sXInner||"100%"}).append(i.removeAttr("id").css("margin-left",0).append("top"===j?g:null).append(b.children("thead"))))).append(h("<div/>",{"class":f.sScrollBody}).css({position:"relative",overflow:"auto",width:!d?null:v(d)}).append(b));l&&i.append(h("<div/>",{"class":f.sScrollFoot}).css({overflow:"hidden",border:0,width:d?!d?null:v(d):"100%"}).append(h("<div/>",
{"class":f.sScrollFootInner}).append(m.removeAttr("id").css("margin-left",0).append("bottom"===j?g:null).append(b.children("tfoot")))));var b=i.children(),k=b[0],f=b[1],t=l?b[2]:null;if(d)h(f).on("scroll.DT",function(){var a=this.scrollLeft;k.scrollLeft=a;l&&(t.scrollLeft=a)});h(f).css(e&&c.bCollapse?"max-height":"height",e);a.nScrollHead=k;a.nScrollBody=f;a.nScrollFoot=t;a.aoDrawCallback.push({fn:la,sName:"scrolling"});return i[0]}function la(a){var b=a.oScroll,c=b.sX,d=b.sXInner,e=b.sY,b=b.iBarWidth,
f=h(a.nScrollHead),g=f[0].style,j=f.children("div"),i=j[0].style,m=j.children("table"),j=a.nScrollBody,l=h(j),q=j.style,t=h(a.nScrollFoot).children("div"),n=t.children("table"),o=h(a.nTHead),p=h(a.nTable),s=p[0],r=s.style,u=a.nTFoot?h(a.nTFoot):null,x=a.oBrowser,U=x.bScrollOversize,Xb=D(a.aoColumns,"nTh"),Q,L,R,w,Ua=[],y=[],z=[],A=[],B,C=function(a){a=a.style;a.paddingTop="0";a.paddingBottom="0";a.borderTopWidth="0";a.borderBottomWidth="0";a.height=0};L=j.scrollHeight>j.clientHeight;if(a.scrollBarVis!==
L&&a.scrollBarVis!==k)a.scrollBarVis=L,$(a);else{a.scrollBarVis=L;p.children("thead, tfoot").remove();u&&(R=u.clone().prependTo(p),Q=u.find("tr"),R=R.find("tr"));w=o.clone().prependTo(p);o=o.find("tr");L=w.find("tr");w.find("th, td").removeAttr("tabindex");c||(q.width="100%",f[0].style.width="100%");h.each(ra(a,w),function(b,c){B=aa(a,b);c.style.width=a.aoColumns[B].sWidth});u&&I(function(a){a.style.width=""},R);f=p.outerWidth();if(""===c){r.width="100%";if(U&&(p.find("tbody").height()>j.offsetHeight||
"scroll"==l.css("overflow-y")))r.width=v(p.outerWidth()-b);f=p.outerWidth()}else""!==d&&(r.width=v(d),f=p.outerWidth());I(C,L);I(function(a){z.push(a.innerHTML);Ua.push(v(h(a).css("width")))},L);I(function(a,b){if(h.inArray(a,Xb)!==-1)a.style.width=Ua[b]},o);h(L).height(0);u&&(I(C,R),I(function(a){A.push(a.innerHTML);y.push(v(h(a).css("width")))},R),I(function(a,b){a.style.width=y[b]},Q),h(R).height(0));I(function(a,b){a.innerHTML='<div class="dataTables_sizing">'+z[b]+"</div>";a.childNodes[0].style.height=
"0";a.childNodes[0].style.overflow="hidden";a.style.width=Ua[b]},L);u&&I(function(a,b){a.innerHTML='<div class="dataTables_sizing">'+A[b]+"</div>";a.childNodes[0].style.height="0";a.childNodes[0].style.overflow="hidden";a.style.width=y[b]},R);if(p.outerWidth()<f){Q=j.scrollHeight>j.offsetHeight||"scroll"==l.css("overflow-y")?f+b:f;if(U&&(j.scrollHeight>j.offsetHeight||"scroll"==l.css("overflow-y")))r.width=v(Q-b);(""===c||""!==d)&&K(a,1,"Possible column misalignment",6)}else Q="100%";q.width=v(Q);
g.width=v(Q);u&&(a.nScrollFoot.style.width=v(Q));!e&&U&&(q.height=v(s.offsetHeight+b));c=p.outerWidth();m[0].style.width=v(c);i.width=v(c);d=p.height()>j.clientHeight||"scroll"==l.css("overflow-y");e="padding"+(x.bScrollbarLeft?"Left":"Right");i[e]=d?b+"px":"0px";u&&(n[0].style.width=v(c),t[0].style.width=v(c),t[0].style[e]=d?b+"px":"0px");p.children("colgroup").insertBefore(p.children("thead"));l.scroll();if((a.bSorted||a.bFiltered)&&!a._drawHold)j.scrollTop=0}}function I(a,b,c){for(var d=0,e=0,
f=b.length,g,j;e<f;){g=b[e].firstChild;for(j=c?c[e].firstChild:null;g;)1===g.nodeType&&(c?a(g,j,d):a(g,d),d++),g=g.nextSibling,j=c?j.nextSibling:null;e++}}function Fa(a){var b=a.nTable,c=a.aoColumns,d=a.oScroll,e=d.sY,f=d.sX,g=d.sXInner,j=c.length,i=ma(a,"bVisible"),m=h("th",a.nTHead),l=b.getAttribute("width"),k=b.parentNode,t=!1,n,o,p=a.oBrowser,d=p.bScrollOversize;(n=b.style.width)&&-1!==n.indexOf("%")&&(l=n);for(n=0;n<i.length;n++)o=c[i[n]],null!==o.sWidth&&(o.sWidth=Eb(o.sWidthOrig,k),t=!0);if(d||
!t&&!f&&!e&&j==V(a)&&j==m.length)for(n=0;n<j;n++)i=aa(a,n),null!==i&&(c[i].sWidth=v(m.eq(n).width()));else{j=h(b).clone().css("visibility","hidden").removeAttr("id");j.find("tbody tr").remove();var s=h("<tr/>").appendTo(j.find("tbody"));j.find("thead, tfoot").remove();j.append(h(a.nTHead).clone()).append(h(a.nTFoot).clone());j.find("tfoot th, tfoot td").css("width","");m=ra(a,j.find("thead")[0]);for(n=0;n<i.length;n++)o=c[i[n]],m[n].style.width=null!==o.sWidthOrig&&""!==o.sWidthOrig?v(o.sWidthOrig):
"",o.sWidthOrig&&f&&h(m[n]).append(h("<div/>").css({width:o.sWidthOrig,margin:0,padding:0,border:0,height:1}));if(a.aoData.length)for(n=0;n<i.length;n++)t=i[n],o=c[t],h(Fb(a,t)).clone(!1).append(o.sContentPadding).appendTo(s);h("[name]",j).removeAttr("name");o=h("<div/>").css(f||e?{position:"absolute",top:0,left:0,height:1,right:0,overflow:"hidden"}:{}).append(j).appendTo(k);f&&g?j.width(g):f?(j.css("width","auto"),j.removeAttr("width"),j.width()<k.clientWidth&&l&&j.width(k.clientWidth)):e?j.width(k.clientWidth):
l&&j.width(l);for(n=e=0;n<i.length;n++)k=h(m[n]),g=k.outerWidth()-k.width(),k=p.bBounding?Math.ceil(m[n].getBoundingClientRect().width):k.outerWidth(),e+=k,c[i[n]].sWidth=v(k-g);b.style.width=v(e);o.remove()}l&&(b.style.width=v(l));if((l||f)&&!a._reszEvt)b=function(){h(E).on("resize.DT-"+a.sInstance,Oa(function(){$(a)}))},d?setTimeout(b,1E3):b(),a._reszEvt=!0}function Eb(a,b){if(!a)return 0;var c=h("<div/>").css("width",v(a)).appendTo(b||H.body),d=c[0].offsetWidth;c.remove();return d}function Fb(a,
b){var c=Gb(a,b);if(0>c)return null;var d=a.aoData[c];return!d.nTr?h("<td/>").html(B(a,c,b,"display"))[0]:d.anCells[b]}function Gb(a,b){for(var c,d=-1,e=-1,f=0,g=a.aoData.length;f<g;f++)c=B(a,f,b,"display")+"",c=c.replace(Yb,""),c=c.replace(/&nbsp;/g," "),c.length>d&&(d=c.length,e=f);return e}function v(a){return null===a?"0px":"number"==typeof a?0>a?"0px":a+"px":a.match(/\d$/)?a+"px":a}function X(a){var b,c,d=[],e=a.aoColumns,f,g,j,i;b=a.aaSortingFixed;c=h.isPlainObject(b);var m=[];f=function(a){a.length&&
!h.isArray(a[0])?m.push(a):h.merge(m,a)};h.isArray(b)&&f(b);c&&b.pre&&f(b.pre);f(a.aaSorting);c&&b.post&&f(b.post);for(a=0;a<m.length;a++){i=m[a][0];f=e[i].aDataSort;b=0;for(c=f.length;b<c;b++)g=f[b],j=e[g].sType||"string",m[a]._idx===k&&(m[a]._idx=h.inArray(m[a][1],e[g].asSorting)),d.push({src:i,col:g,dir:m[a][1],index:m[a]._idx,type:j,formatter:n.ext.type.order[j+"-pre"]})}return d}function mb(a){var b,c,d=[],e=n.ext.type.order,f=a.aoData,g=0,j,i=a.aiDisplayMaster,h;Ga(a);h=X(a);b=0;for(c=h.length;b<
c;b++)j=h[b],j.formatter&&g++,Hb(a,j.col);if("ssp"!=y(a)&&0!==h.length){b=0;for(c=i.length;b<c;b++)d[i[b]]=b;g===h.length?i.sort(function(a,b){var c,e,g,j,i=h.length,k=f[a]._aSortData,n=f[b]._aSortData;for(g=0;g<i;g++)if(j=h[g],c=k[j.col],e=n[j.col],c=c<e?-1:c>e?1:0,0!==c)return"asc"===j.dir?c:-c;c=d[a];e=d[b];return c<e?-1:c>e?1:0}):i.sort(function(a,b){var c,g,j,i,k=h.length,n=f[a]._aSortData,o=f[b]._aSortData;for(j=0;j<k;j++)if(i=h[j],c=n[i.col],g=o[i.col],i=e[i.type+"-"+i.dir]||e["string-"+i.dir],
c=i(c,g),0!==c)return c;c=d[a];g=d[b];return c<g?-1:c>g?1:0})}a.bSorted=!0}function Ib(a){for(var b,c,d=a.aoColumns,e=X(a),a=a.oLanguage.oAria,f=0,g=d.length;f<g;f++){c=d[f];var j=c.asSorting;b=c.sTitle.replace(/<.*?>/g,"");var i=c.nTh;i.removeAttribute("aria-sort");c.bSortable&&(0<e.length&&e[0].col==f?(i.setAttribute("aria-sort","asc"==e[0].dir?"ascending":"descending"),c=j[e[0].index+1]||j[0]):c=j[0],b+="asc"===c?a.sSortAscending:a.sSortDescending);i.setAttribute("aria-label",b)}}function Va(a,
b,c,d){var e=a.aaSorting,f=a.aoColumns[b].asSorting,g=function(a,b){var c=a._idx;c===k&&(c=h.inArray(a[1],f));return c+1<f.length?c+1:b?null:0};"number"===typeof e[0]&&(e=a.aaSorting=[e]);c&&a.oFeatures.bSortMulti?(c=h.inArray(b,D(e,"0")),-1!==c?(b=g(e[c],!0),null===b&&1===e.length&&(b=0),null===b?e.splice(c,1):(e[c][1]=f[b],e[c]._idx=b)):(e.push([b,f[0],0]),e[e.length-1]._idx=0)):e.length&&e[0][0]==b?(b=g(e[0]),e.length=1,e[0][1]=f[b],e[0]._idx=b):(e.length=0,e.push([b,f[0]]),e[0]._idx=0);T(a);"function"==
typeof d&&d(a)}function Ma(a,b,c,d){var e=a.aoColumns[c];Wa(b,{},function(b){!1!==e.bSortable&&(a.oFeatures.bProcessing?(C(a,!0),setTimeout(function(){Va(a,c,b.shiftKey,d);"ssp"!==y(a)&&C(a,!1)},0)):Va(a,c,b.shiftKey,d))})}function wa(a){var b=a.aLastSort,c=a.oClasses.sSortColumn,d=X(a),e=a.oFeatures,f,g;if(e.bSort&&e.bSortClasses){e=0;for(f=b.length;e<f;e++)g=b[e].src,h(D(a.aoData,"anCells",g)).removeClass(c+(2>e?e+1:3));e=0;for(f=d.length;e<f;e++)g=d[e].src,h(D(a.aoData,"anCells",g)).addClass(c+
(2>e?e+1:3))}a.aLastSort=d}function Hb(a,b){var c=a.aoColumns[b],d=n.ext.order[c.sSortDataType],e;d&&(e=d.call(a.oInstance,a,b,ba(a,b)));for(var f,g=n.ext.type.order[c.sType+"-pre"],j=0,i=a.aoData.length;j<i;j++)if(c=a.aoData[j],c._aSortData||(c._aSortData=[]),!c._aSortData[b]||d)f=d?e[j]:B(a,j,b,"sort"),c._aSortData[b]=g?g(f):f}function xa(a){if(a.oFeatures.bStateSave&&!a.bDestroying){var b={time:+new Date,start:a._iDisplayStart,length:a._iDisplayLength,order:h.extend(!0,[],a.aaSorting),search:Ab(a.oPreviousSearch),
columns:h.map(a.aoColumns,function(b,d){return{visible:b.bVisible,search:Ab(a.aoPreSearchCols[d])}})};r(a,"aoStateSaveParams","stateSaveParams",[a,b]);a.oSavedState=b;a.fnStateSaveCallback.call(a.oInstance,a,b)}}function Jb(a,b,c){var d,e,f=a.aoColumns,b=function(b){if(b&&b.time){var g=r(a,"aoStateLoadParams","stateLoadParams",[a,b]);if(-1===h.inArray(!1,g)&&(g=a.iStateDuration,!(0<g&&b.time<+new Date-1E3*g)&&!(b.columns&&f.length!==b.columns.length))){a.oLoadedState=h.extend(!0,{},b);b.start!==k&&
(a._iDisplayStart=b.start,a.iInitDisplayStart=b.start);b.length!==k&&(a._iDisplayLength=b.length);b.order!==k&&(a.aaSorting=[],h.each(b.order,function(b,c){a.aaSorting.push(c[0]>=f.length?[0,c[1]]:c)}));b.search!==k&&h.extend(a.oPreviousSearch,Bb(b.search));if(b.columns){d=0;for(e=b.columns.length;d<e;d++)g=b.columns[d],g.visible!==k&&(f[d].bVisible=g.visible),g.search!==k&&h.extend(a.aoPreSearchCols[d],Bb(g.search))}r(a,"aoStateLoaded","stateLoaded",[a,b])}}c()};if(a.oFeatures.bStateSave){var g=
a.fnStateLoadCallback.call(a.oInstance,a,b);g!==k&&b(g)}else c()}function ya(a){var b=n.settings,a=h.inArray(a,D(b,"nTable"));return-1!==a?b[a]:null}function K(a,b,c,d){c="DataTables warning: "+(a?"table id="+a.sTableId+" - ":"")+c;d&&(c+=". For more information about this error, please see http://datatables.net/tn/"+d);if(b)E.console&&console.log&&console.log(c);else if(b=n.ext,b=b.sErrMode||b.errMode,a&&r(a,null,"error",[a,d,c]),"alert"==b)alert(c);else{if("throw"==b)throw Error(c);"function"==
typeof b&&b(a,d,c)}}function F(a,b,c,d){h.isArray(c)?h.each(c,function(c,d){h.isArray(d)?F(a,b,d[0],d[1]):F(a,b,d)}):(d===k&&(d=c),b[c]!==k&&(a[d]=b[c]))}function Xa(a,b,c){var d,e;for(e in b)b.hasOwnProperty(e)&&(d=b[e],h.isPlainObject(d)?(h.isPlainObject(a[e])||(a[e]={}),h.extend(!0,a[e],d)):a[e]=c&&"data"!==e&&"aaData"!==e&&h.isArray(d)?d.slice():d);return a}function Wa(a,b,c){h(a).on("click.DT",b,function(b){h(a).blur();c(b)}).on("keypress.DT",b,function(a){13===a.which&&(a.preventDefault(),c(a))}).on("selectstart.DT",
function(){return!1})}function z(a,b,c,d){c&&a[b].push({fn:c,sName:d})}function r(a,b,c,d){var e=[];b&&(e=h.map(a[b].slice().reverse(),function(b){return b.fn.apply(a.oInstance,d)}));null!==c&&(b=h.Event(c+".dt"),h(a.nTable).trigger(b,d),e.push(b.result));return e}function Sa(a){var b=a._iDisplayStart,c=a.fnDisplayEnd(),d=a._iDisplayLength;b>=c&&(b=c-d);b-=b%d;if(-1===d||0>b)b=0;a._iDisplayStart=b}function Na(a,b){var c=a.renderer,d=n.ext.renderer[b];return h.isPlainObject(c)&&c[b]?d[c[b]]||d._:"string"===
typeof c?d[c]||d._:d._}function y(a){return a.oFeatures.bServerSide?"ssp":a.ajax||a.sAjaxSource?"ajax":"dom"}function ia(a,b){var c=[],c=Kb.numbers_length,d=Math.floor(c/2);b<=c?c=Y(0,b):a<=d?(c=Y(0,c-2),c.push("ellipsis"),c.push(b-1)):(a>=b-1-d?c=Y(b-(c-2),b):(c=Y(a-d+2,a+d-1),c.push("ellipsis"),c.push(b-1)),c.splice(0,0,"ellipsis"),c.splice(0,0,0));c.DT_el="span";return c}function Da(a){h.each({num:function(b){return za(b,a)},"num-fmt":function(b){return za(b,a,Ya)},"html-num":function(b){return za(b,
a,Aa)},"html-num-fmt":function(b){return za(b,a,Aa,Ya)}},function(b,c){x.type.order[b+a+"-pre"]=c;b.match(/^html\-/)&&(x.type.search[b+a]=x.type.search.html)})}function Lb(a){return function(){var b=[ya(this[n.ext.iApiIndex])].concat(Array.prototype.slice.call(arguments));return n.ext.internal[a].apply(this,b)}}var n=function(a){this.$=function(a,b){return this.api(!0).$(a,b)};this._=function(a,b){return this.api(!0).rows(a,b).data()};this.api=function(a){return a?new s(ya(this[x.iApiIndex])):new s(this)};
this.fnAddData=function(a,b){var c=this.api(!0),d=h.isArray(a)&&(h.isArray(a[0])||h.isPlainObject(a[0]))?c.rows.add(a):c.row.add(a);(b===k||b)&&c.draw();return d.flatten().toArray()};this.fnAdjustColumnSizing=function(a){var b=this.api(!0).columns.adjust(),c=b.settings()[0],d=c.oScroll;a===k||a?b.draw(!1):(""!==d.sX||""!==d.sY)&&la(c)};this.fnClearTable=function(a){var b=this.api(!0).clear();(a===k||a)&&b.draw()};this.fnClose=function(a){this.api(!0).row(a).child.hide()};this.fnDeleteRow=function(a,
b,c){var d=this.api(!0),a=d.rows(a),e=a.settings()[0],h=e.aoData[a[0][0]];a.remove();b&&b.call(this,e,h);(c===k||c)&&d.draw();return h};this.fnDestroy=function(a){this.api(!0).destroy(a)};this.fnDraw=function(a){this.api(!0).draw(a)};this.fnFilter=function(a,b,c,d,e,h){e=this.api(!0);null===b||b===k?e.search(a,c,d,h):e.column(b).search(a,c,d,h);e.draw()};this.fnGetData=function(a,b){var c=this.api(!0);if(a!==k){var d=a.nodeName?a.nodeName.toLowerCase():"";return b!==k||"td"==d||"th"==d?c.cell(a,b).data():
c.row(a).data()||null}return c.data().toArray()};this.fnGetNodes=function(a){var b=this.api(!0);return a!==k?b.row(a).node():b.rows().nodes().flatten().toArray()};this.fnGetPosition=function(a){var b=this.api(!0),c=a.nodeName.toUpperCase();return"TR"==c?b.row(a).index():"TD"==c||"TH"==c?(a=b.cell(a).index(),[a.row,a.columnVisible,a.column]):null};this.fnIsOpen=function(a){return this.api(!0).row(a).child.isShown()};this.fnOpen=function(a,b,c){return this.api(!0).row(a).child(b,c).show().child()[0]};
this.fnPageChange=function(a,b){var c=this.api(!0).page(a);(b===k||b)&&c.draw(!1)};this.fnSetColumnVis=function(a,b,c){a=this.api(!0).column(a).visible(b);(c===k||c)&&a.columns.adjust().draw()};this.fnSettings=function(){return ya(this[x.iApiIndex])};this.fnSort=function(a){this.api(!0).order(a).draw()};this.fnSortListener=function(a,b,c){this.api(!0).order.listener(a,b,c)};this.fnUpdate=function(a,b,c,d,e){var h=this.api(!0);c===k||null===c?h.row(b).data(a):h.cell(b,c).data(a);(e===k||e)&&h.columns.adjust();
(d===k||d)&&h.draw();return 0};this.fnVersionCheck=x.fnVersionCheck;var b=this,c=a===k,d=this.length;c&&(a={});this.oApi=this.internal=x.internal;for(var e in n.ext.internal)e&&(this[e]=Lb(e));this.each(function(){var e={},g=1<d?Xa(e,a,!0):a,j=0,i,e=this.getAttribute("id"),m=!1,l=n.defaults,q=h(this);if("table"!=this.nodeName.toLowerCase())K(null,0,"Non-table node initialisation ("+this.nodeName+")",2);else{eb(l);fb(l.column);J(l,l,!0);J(l.column,l.column,!0);J(l,h.extend(g,q.data()));var t=n.settings,
j=0;for(i=t.length;j<i;j++){var o=t[j];if(o.nTable==this||o.nTHead&&o.nTHead.parentNode==this||o.nTFoot&&o.nTFoot.parentNode==this){var s=g.bRetrieve!==k?g.bRetrieve:l.bRetrieve;if(c||s)return o.oInstance;if(g.bDestroy!==k?g.bDestroy:l.bDestroy){o.oInstance.fnDestroy();break}else{K(o,0,"Cannot reinitialise DataTable",3);return}}if(o.sTableId==this.id){t.splice(j,1);break}}if(null===e||""===e)this.id=e="DataTables_Table_"+n.ext._unique++;var p=h.extend(!0,{},n.models.oSettings,{sDestroyWidth:q[0].style.width,
sInstance:e,sTableId:e});p.nTable=this;p.oApi=b.internal;p.oInit=g;t.push(p);p.oInstance=1===b.length?b:q.dataTable();eb(g);Ca(g.oLanguage);g.aLengthMenu&&!g.iDisplayLength&&(g.iDisplayLength=h.isArray(g.aLengthMenu[0])?g.aLengthMenu[0][0]:g.aLengthMenu[0]);g=Xa(h.extend(!0,{},l),g);F(p.oFeatures,g,"bPaginate bLengthChange bFilter bSort bSortMulti bInfo bProcessing bAutoWidth bSortClasses bServerSide bDeferRender".split(" "));F(p,g,["asStripeClasses","ajax","fnServerData","fnFormatNumber","sServerMethod",
"aaSorting","aaSortingFixed","aLengthMenu","sPaginationType","sAjaxSource","sAjaxDataProp","iStateDuration","sDom","bSortCellsTop","iTabIndex","fnStateLoadCallback","fnStateSaveCallback","renderer","searchDelay","rowId",["iCookieDuration","iStateDuration"],["oSearch","oPreviousSearch"],["aoSearchCols","aoPreSearchCols"],["iDisplayLength","_iDisplayLength"]]);F(p.oScroll,g,[["sScrollX","sX"],["sScrollXInner","sXInner"],["sScrollY","sY"],["bScrollCollapse","bCollapse"]]);F(p.oLanguage,g,"fnInfoCallback");
z(p,"aoDrawCallback",g.fnDrawCallback,"user");z(p,"aoServerParams",g.fnServerParams,"user");z(p,"aoStateSaveParams",g.fnStateSaveParams,"user");z(p,"aoStateLoadParams",g.fnStateLoadParams,"user");z(p,"aoStateLoaded",g.fnStateLoaded,"user");z(p,"aoRowCallback",g.fnRowCallback,"user");z(p,"aoRowCreatedCallback",g.fnCreatedRow,"user");z(p,"aoHeaderCallback",g.fnHeaderCallback,"user");z(p,"aoFooterCallback",g.fnFooterCallback,"user");z(p,"aoInitComplete",g.fnInitComplete,"user");z(p,"aoPreDrawCallback",
g.fnPreDrawCallback,"user");p.rowIdFn=S(g.rowId);gb(p);var u=p.oClasses;h.extend(u,n.ext.classes,g.oClasses);q.addClass(u.sTable);p.iInitDisplayStart===k&&(p.iInitDisplayStart=g.iDisplayStart,p._iDisplayStart=g.iDisplayStart);null!==g.iDeferLoading&&(p.bDeferLoading=!0,e=h.isArray(g.iDeferLoading),p._iRecordsDisplay=e?g.iDeferLoading[0]:g.iDeferLoading,p._iRecordsTotal=e?g.iDeferLoading[1]:g.iDeferLoading);var v=p.oLanguage;h.extend(!0,v,g.oLanguage);v.sUrl&&(h.ajax({dataType:"json",url:v.sUrl,success:function(a){Ca(a);
J(l.oLanguage,a);h.extend(true,v,a);ha(p)},error:function(){ha(p)}}),m=!0);null===g.asStripeClasses&&(p.asStripeClasses=[u.sStripeOdd,u.sStripeEven]);var e=p.asStripeClasses,x=q.children("tbody").find("tr").eq(0);-1!==h.inArray(!0,h.map(e,function(a){return x.hasClass(a)}))&&(h("tbody tr",this).removeClass(e.join(" ")),p.asDestroyStripes=e.slice());e=[];t=this.getElementsByTagName("thead");0!==t.length&&(ea(p.aoHeader,t[0]),e=ra(p));if(null===g.aoColumns){t=[];j=0;for(i=e.length;j<i;j++)t.push(null)}else t=
g.aoColumns;j=0;for(i=t.length;j<i;j++)Ea(p,e?e[j]:null);ib(p,g.aoColumnDefs,t,function(a,b){ka(p,a,b)});if(x.length){var w=function(a,b){return a.getAttribute("data-"+b)!==null?b:null};h(x[0]).children("th, td").each(function(a,b){var c=p.aoColumns[a];if(c.mData===a){var d=w(b,"sort")||w(b,"order"),e=w(b,"filter")||w(b,"search");if(d!==null||e!==null){c.mData={_:a+".display",sort:d!==null?a+".@data-"+d:k,type:d!==null?a+".@data-"+d:k,filter:e!==null?a+".@data-"+e:k};ka(p,a)}}})}var U=p.oFeatures,
e=function(){if(g.aaSorting===k){var a=p.aaSorting;j=0;for(i=a.length;j<i;j++)a[j][1]=p.aoColumns[j].asSorting[0]}wa(p);U.bSort&&z(p,"aoDrawCallback",function(){if(p.bSorted){var a=X(p),b={};h.each(a,function(a,c){b[c.src]=c.dir});r(p,null,"order",[p,a,b]);Ib(p)}});z(p,"aoDrawCallback",function(){(p.bSorted||y(p)==="ssp"||U.bDeferRender)&&wa(p)},"sc");var a=q.children("caption").each(function(){this._captionSide=h(this).css("caption-side")}),b=q.children("thead");b.length===0&&(b=h("<thead/>").appendTo(q));
p.nTHead=b[0];b=q.children("tbody");b.length===0&&(b=h("<tbody/>").appendTo(q));p.nTBody=b[0];b=q.children("tfoot");if(b.length===0&&a.length>0&&(p.oScroll.sX!==""||p.oScroll.sY!==""))b=h("<tfoot/>").appendTo(q);if(b.length===0||b.children().length===0)q.addClass(u.sNoFooter);else if(b.length>0){p.nTFoot=b[0];ea(p.aoFooter,p.nTFoot)}if(g.aaData)for(j=0;j<g.aaData.length;j++)O(p,g.aaData[j]);else(p.bDeferLoading||y(p)=="dom")&&na(p,h(p.nTBody).children("tr"));p.aiDisplay=p.aiDisplayMaster.slice();
p.bInitialised=true;m===false&&ha(p)};g.bStateSave?(U.bStateSave=!0,z(p,"aoDrawCallback",xa,"state_save"),Jb(p,g,e)):e()}});b=null;return this},x,s,o,u,Za={},Mb=/[\r\n]/g,Aa=/<.*?>/g,Zb=/^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/,$b=RegExp("(\\/|\\.|\\*|\\+|\\?|\\||\\(|\\)|\\[|\\]|\\{|\\}|\\\\|\\$|\\^|\\-)","g"),Ya=/[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfkɃΞ]/gi,M=function(a){return!a||!0===a||"-"===a?!0:!1},Nb=function(a){var b=parseInt(a,10);return!isNaN(b)&&
isFinite(a)?b:null},Ob=function(a,b){Za[b]||(Za[b]=RegExp(Qa(b),"g"));return"string"===typeof a&&"."!==b?a.replace(/\./g,"").replace(Za[b],"."):a},$a=function(a,b,c){var d="string"===typeof a;if(M(a))return!0;b&&d&&(a=Ob(a,b));c&&d&&(a=a.replace(Ya,""));return!isNaN(parseFloat(a))&&isFinite(a)},Pb=function(a,b,c){return M(a)?!0:!(M(a)||"string"===typeof a)?null:$a(a.replace(Aa,""),b,c)?!0:null},D=function(a,b,c){var d=[],e=0,f=a.length;if(c!==k)for(;e<f;e++)a[e]&&a[e][b]&&d.push(a[e][b][c]);else for(;e<
f;e++)a[e]&&d.push(a[e][b]);return d},ja=function(a,b,c,d){var e=[],f=0,g=b.length;if(d!==k)for(;f<g;f++)a[b[f]][c]&&e.push(a[b[f]][c][d]);else for(;f<g;f++)e.push(a[b[f]][c]);return e},Y=function(a,b){var c=[],d;b===k?(b=0,d=a):(d=b,b=a);for(var e=b;e<d;e++)c.push(e);return c},Qb=function(a){for(var b=[],c=0,d=a.length;c<d;c++)a[c]&&b.push(a[c]);return b},qa=function(a){var b;a:{if(!(2>a.length)){b=a.slice().sort();for(var c=b[0],d=1,e=b.length;d<e;d++){if(b[d]===c){b=!1;break a}c=b[d]}}b=!0}if(b)return a.slice();
b=[];var e=a.length,f,g=0,d=0;a:for(;d<e;d++){c=a[d];for(f=0;f<g;f++)if(b[f]===c)continue a;b.push(c);g++}return b};n.util={throttle:function(a,b){var c=b!==k?b:200,d,e;return function(){var b=this,g=+new Date,j=arguments;d&&g<d+c?(clearTimeout(e),e=setTimeout(function(){d=k;a.apply(b,j)},c)):(d=g,a.apply(b,j))}},escapeRegex:function(a){return a.replace($b,"\\$1")}};var A=function(a,b,c){a[b]!==k&&(a[c]=a[b])},ca=/\[.*?\]$/,W=/\(\)$/,Qa=n.util.escapeRegex,va=h("<div>")[0],Wb=va.textContent!==k,Yb=
/<.*?>/g,Oa=n.util.throttle,Rb=[],w=Array.prototype,ac=function(a){var b,c,d=n.settings,e=h.map(d,function(a){return a.nTable});if(a){if(a.nTable&&a.oApi)return[a];if(a.nodeName&&"table"===a.nodeName.toLowerCase())return b=h.inArray(a,e),-1!==b?[d[b]]:null;if(a&&"function"===typeof a.settings)return a.settings().toArray();"string"===typeof a?c=h(a):a instanceof h&&(c=a)}else return[];if(c)return c.map(function(){b=h.inArray(this,e);return-1!==b?d[b]:null}).toArray()};s=function(a,b){if(!(this instanceof
s))return new s(a,b);var c=[],d=function(a){(a=ac(a))&&(c=c.concat(a))};if(h.isArray(a))for(var e=0,f=a.length;e<f;e++)d(a[e]);else d(a);this.context=qa(c);b&&h.merge(this,b);this.selector={rows:null,cols:null,opts:null};s.extend(this,this,Rb)};n.Api=s;h.extend(s.prototype,{any:function(){return 0!==this.count()},concat:w.concat,context:[],count:function(){return this.flatten().length},each:function(a){for(var b=0,c=this.length;b<c;b++)a.call(this,this[b],b,this);return this},eq:function(a){var b=
this.context;return b.length>a?new s(b[a],this[a]):null},filter:function(a){var b=[];if(w.filter)b=w.filter.call(this,a,this);else for(var c=0,d=this.length;c<d;c++)a.call(this,this[c],c,this)&&b.push(this[c]);return new s(this.context,b)},flatten:function(){var a=[];return new s(this.context,a.concat.apply(a,this.toArray()))},join:w.join,indexOf:w.indexOf||function(a,b){for(var c=b||0,d=this.length;c<d;c++)if(this[c]===a)return c;return-1},iterator:function(a,b,c,d){var e=[],f,g,j,h,m,l=this.context,
n,o,u=this.selector;"string"===typeof a&&(d=c,c=b,b=a,a=!1);g=0;for(j=l.length;g<j;g++){var r=new s(l[g]);if("table"===b)f=c.call(r,l[g],g),f!==k&&e.push(f);else if("columns"===b||"rows"===b)f=c.call(r,l[g],this[g],g),f!==k&&e.push(f);else if("column"===b||"column-rows"===b||"row"===b||"cell"===b){o=this[g];"column-rows"===b&&(n=Ba(l[g],u.opts));h=0;for(m=o.length;h<m;h++)f=o[h],f="cell"===b?c.call(r,l[g],f.row,f.column,g,h):c.call(r,l[g],f,g,h,n),f!==k&&e.push(f)}}return e.length||d?(a=new s(l,a?
e.concat.apply([],e):e),b=a.selector,b.rows=u.rows,b.cols=u.cols,b.opts=u.opts,a):this},lastIndexOf:w.lastIndexOf||function(a,b){return this.indexOf.apply(this.toArray.reverse(),arguments)},length:0,map:function(a){var b=[];if(w.map)b=w.map.call(this,a,this);else for(var c=0,d=this.length;c<d;c++)b.push(a.call(this,this[c],c));return new s(this.context,b)},pluck:function(a){return this.map(function(b){return b[a]})},pop:w.pop,push:w.push,reduce:w.reduce||function(a,b){return hb(this,a,b,0,this.length,
1)},reduceRight:w.reduceRight||function(a,b){return hb(this,a,b,this.length-1,-1,-1)},reverse:w.reverse,selector:null,shift:w.shift,slice:function(){return new s(this.context,this)},sort:w.sort,splice:w.splice,toArray:function(){return w.slice.call(this)},to$:function(){return h(this)},toJQuery:function(){return h(this)},unique:function(){return new s(this.context,qa(this))},unshift:w.unshift});s.extend=function(a,b,c){if(c.length&&b&&(b instanceof s||b.__dt_wrapper)){var d,e,f,g=function(a,b,c){return function(){var d=
b.apply(a,arguments);s.extend(d,d,c.methodExt);return d}};d=0;for(e=c.length;d<e;d++)f=c[d],b[f.name]="function"===typeof f.val?g(a,f.val,f):h.isPlainObject(f.val)?{}:f.val,b[f.name].__dt_wrapper=!0,s.extend(a,b[f.name],f.propExt)}};s.register=o=function(a,b){if(h.isArray(a))for(var c=0,d=a.length;c<d;c++)s.register(a[c],b);else for(var e=a.split("."),f=Rb,g,j,c=0,d=e.length;c<d;c++){g=(j=-1!==e[c].indexOf("()"))?e[c].replace("()",""):e[c];var i;a:{i=0;for(var m=f.length;i<m;i++)if(f[i].name===g){i=
f[i];break a}i=null}i||(i={name:g,val:{},methodExt:[],propExt:[]},f.push(i));c===d-1?i.val=b:f=j?i.methodExt:i.propExt}};s.registerPlural=u=function(a,b,c){s.register(a,c);s.register(b,function(){var a=c.apply(this,arguments);return a===this?this:a instanceof s?a.length?h.isArray(a[0])?new s(a.context,a[0]):a[0]:k:a})};o("tables()",function(a){var b;if(a){b=s;var c=this.context;if("number"===typeof a)a=[c[a]];else var d=h.map(c,function(a){return a.nTable}),a=h(d).filter(a).map(function(){var a=h.inArray(this,
d);return c[a]}).toArray();b=new b(a)}else b=this;return b});o("table()",function(a){var a=this.tables(a),b=a.context;return b.length?new s(b[0]):a});u("tables().nodes()","table().node()",function(){return this.iterator("table",function(a){return a.nTable},1)});u("tables().body()","table().body()",function(){return this.iterator("table",function(a){return a.nTBody},1)});u("tables().header()","table().header()",function(){return this.iterator("table",function(a){return a.nTHead},1)});u("tables().footer()",
"table().footer()",function(){return this.iterator("table",function(a){return a.nTFoot},1)});u("tables().containers()","table().container()",function(){return this.iterator("table",function(a){return a.nTableWrapper},1)});o("draw()",function(a){return this.iterator("table",function(b){"page"===a?P(b):("string"===typeof a&&(a="full-hold"===a?!1:!0),T(b,!1===a))})});o("page()",function(a){return a===k?this.page.info().page:this.iterator("table",function(b){Ta(b,a)})});o("page.info()",function(){if(0===
this.context.length)return k;var a=this.context[0],b=a._iDisplayStart,c=a.oFeatures.bPaginate?a._iDisplayLength:-1,d=a.fnRecordsDisplay(),e=-1===c;return{page:e?0:Math.floor(b/c),pages:e?1:Math.ceil(d/c),start:b,end:a.fnDisplayEnd(),length:c,recordsTotal:a.fnRecordsTotal(),recordsDisplay:d,serverSide:"ssp"===y(a)}});o("page.len()",function(a){return a===k?0!==this.context.length?this.context[0]._iDisplayLength:k:this.iterator("table",function(b){Ra(b,a)})});var Sb=function(a,b,c){if(c){var d=new s(a);
d.one("draw",function(){c(d.ajax.json())})}if("ssp"==y(a))T(a,b);else{C(a,!0);var e=a.jqXHR;e&&4!==e.readyState&&e.abort();sa(a,[],function(c){oa(a);for(var c=ta(a,c),d=0,e=c.length;d<e;d++)O(a,c[d]);T(a,b);C(a,!1)})}};o("ajax.json()",function(){var a=this.context;if(0<a.length)return a[0].json});o("ajax.params()",function(){var a=this.context;if(0<a.length)return a[0].oAjaxData});o("ajax.reload()",function(a,b){return this.iterator("table",function(c){Sb(c,!1===b,a)})});o("ajax.url()",function(a){var b=
this.context;if(a===k){if(0===b.length)return k;b=b[0];return b.ajax?h.isPlainObject(b.ajax)?b.ajax.url:b.ajax:b.sAjaxSource}return this.iterator("table",function(b){h.isPlainObject(b.ajax)?b.ajax.url=a:b.ajax=a})});o("ajax.url().load()",function(a,b){return this.iterator("table",function(c){Sb(c,!1===b,a)})});var ab=function(a,b,c,d,e){var f=[],g,j,i,m,l,n;i=typeof b;if(!b||"string"===i||"function"===i||b.length===k)b=[b];i=0;for(m=b.length;i<m;i++){j=b[i]&&b[i].split&&!b[i].match(/[\[\(:]/)?b[i].split(","):
[b[i]];l=0;for(n=j.length;l<n;l++)(g=c("string"===typeof j[l]?h.trim(j[l]):j[l]))&&g.length&&(f=f.concat(g))}a=x.selector[a];if(a.length){i=0;for(m=a.length;i<m;i++)f=a[i](d,e,f)}return qa(f)},bb=function(a){a||(a={});a.filter&&a.search===k&&(a.search=a.filter);return h.extend({search:"none",order:"current",page:"all"},a)},cb=function(a){for(var b=0,c=a.length;b<c;b++)if(0<a[b].length)return a[0]=a[b],a[0].length=1,a.length=1,a.context=[a.context[b]],a;a.length=0;return a},Ba=function(a,b){var c,
d,e,f=[],g=a.aiDisplay;e=a.aiDisplayMaster;var j=b.search;c=b.order;d=b.page;if("ssp"==y(a))return"removed"===j?[]:Y(0,e.length);if("current"==d){c=a._iDisplayStart;for(d=a.fnDisplayEnd();c<d;c++)f.push(g[c])}else if("current"==c||"applied"==c)if("none"==j)f=e.slice();else if("applied"==j)f=g.slice();else{if("removed"==j){var i={};c=0;for(d=g.length;c<d;c++)i[g[c]]=null;f=h.map(e,function(a){return!i.hasOwnProperty(a)?a:null})}}else if("index"==c||"original"==c){c=0;for(d=a.aoData.length;c<d;c++)"none"==
j?f.push(c):(e=h.inArray(c,g),(-1===e&&"removed"==j||0<=e&&"applied"==j)&&f.push(c))}return f};o("rows()",function(a,b){a===k?a="":h.isPlainObject(a)&&(b=a,a="");var b=bb(b),c=this.iterator("table",function(c){var e=b,f;return ab("row",a,function(a){var b=Nb(a),i=c.aoData;if(b!==null&&!e)return[b];f||(f=Ba(c,e));if(b!==null&&h.inArray(b,f)!==-1)return[b];if(a===null||a===k||a==="")return f;if(typeof a==="function")return h.map(f,function(b){var c=i[b];return a(b,c._aData,c.nTr)?b:null});if(a.nodeName){var b=
a._DT_RowIndex,m=a._DT_CellIndex;if(b!==k)return i[b]&&i[b].nTr===a?[b]:[];if(m)return i[m.row]&&i[m.row].nTr===a?[m.row]:[];b=h(a).closest("*[data-dt-row]");return b.length?[b.data("dt-row")]:[]}if(typeof a==="string"&&a.charAt(0)==="#"){b=c.aIds[a.replace(/^#/,"")];if(b!==k)return[b.idx]}b=Qb(ja(c.aoData,f,"nTr"));return h(b).filter(a).map(function(){return this._DT_RowIndex}).toArray()},c,e)},1);c.selector.rows=a;c.selector.opts=b;return c});o("rows().nodes()",function(){return this.iterator("row",
function(a,b){return a.aoData[b].nTr||k},1)});o("rows().data()",function(){return this.iterator(!0,"rows",function(a,b){return ja(a.aoData,b,"_aData")},1)});u("rows().cache()","row().cache()",function(a){return this.iterator("row",function(b,c){var d=b.aoData[c];return"search"===a?d._aFilterData:d._aSortData},1)});u("rows().invalidate()","row().invalidate()",function(a){return this.iterator("row",function(b,c){da(b,c,a)})});u("rows().indexes()","row().index()",function(){return this.iterator("row",
function(a,b){return b},1)});u("rows().ids()","row().id()",function(a){for(var b=[],c=this.context,d=0,e=c.length;d<e;d++)for(var f=0,g=this[d].length;f<g;f++){var h=c[d].rowIdFn(c[d].aoData[this[d][f]]._aData);b.push((!0===a?"#":"")+h)}return new s(c,b)});u("rows().remove()","row().remove()",function(){var a=this;this.iterator("row",function(b,c,d){var e=b.aoData,f=e[c],g,h,i,m,l;e.splice(c,1);g=0;for(h=e.length;g<h;g++)if(i=e[g],l=i.anCells,null!==i.nTr&&(i.nTr._DT_RowIndex=g),null!==l){i=0;for(m=
l.length;i<m;i++)l[i]._DT_CellIndex.row=g}pa(b.aiDisplayMaster,c);pa(b.aiDisplay,c);pa(a[d],c,!1);0<b._iRecordsDisplay&&b._iRecordsDisplay--;Sa(b);c=b.rowIdFn(f._aData);c!==k&&delete b.aIds[c]});this.iterator("table",function(a){for(var c=0,d=a.aoData.length;c<d;c++)a.aoData[c].idx=c});return this});o("rows.add()",function(a){var b=this.iterator("table",function(b){var c,f,g,h=[];f=0;for(g=a.length;f<g;f++)c=a[f],c.nodeName&&"TR"===c.nodeName.toUpperCase()?h.push(na(b,c)[0]):h.push(O(b,c));return h},
1),c=this.rows(-1);c.pop();h.merge(c,b);return c});o("row()",function(a,b){return cb(this.rows(a,b))});o("row().data()",function(a){var b=this.context;if(a===k)return b.length&&this.length?b[0].aoData[this[0]]._aData:k;var c=b[0].aoData[this[0]];c._aData=a;h.isArray(a)&&c.nTr.id&&N(b[0].rowId)(a,c.nTr.id);da(b[0],this[0],"data");return this});o("row().node()",function(){var a=this.context;return a.length&&this.length?a[0].aoData[this[0]].nTr||null:null});o("row.add()",function(a){a instanceof h&&
a.length&&(a=a[0]);var b=this.iterator("table",function(b){return a.nodeName&&"TR"===a.nodeName.toUpperCase()?na(b,a)[0]:O(b,a)});return this.row(b[0])});var db=function(a,b){var c=a.context;if(c.length&&(c=c[0].aoData[b!==k?b:a[0]])&&c._details)c._details.remove(),c._detailsShow=k,c._details=k},Tb=function(a,b){var c=a.context;if(c.length&&a.length){var d=c[0].aoData[a[0]];if(d._details){(d._detailsShow=b)?d._details.insertAfter(d.nTr):d._details.detach();var e=c[0],f=new s(e),g=e.aoData;f.off("draw.dt.DT_details column-visibility.dt.DT_details destroy.dt.DT_details");
0<D(g,"_details").length&&(f.on("draw.dt.DT_details",function(a,b){e===b&&f.rows({page:"current"}).eq(0).each(function(a){a=g[a];a._detailsShow&&a._details.insertAfter(a.nTr)})}),f.on("column-visibility.dt.DT_details",function(a,b){if(e===b)for(var c,d=V(b),f=0,h=g.length;f<h;f++)c=g[f],c._details&&c._details.children("td[colspan]").attr("colspan",d)}),f.on("destroy.dt.DT_details",function(a,b){if(e===b)for(var c=0,d=g.length;c<d;c++)g[c]._details&&db(f,c)}))}}};o("row().child()",function(a,b){var c=
this.context;if(a===k)return c.length&&this.length?c[0].aoData[this[0]]._details:k;if(!0===a)this.child.show();else if(!1===a)db(this);else if(c.length&&this.length){var d=c[0],c=c[0].aoData[this[0]],e=[],f=function(a,b){if(h.isArray(a)||a instanceof h)for(var c=0,k=a.length;c<k;c++)f(a[c],b);else a.nodeName&&"tr"===a.nodeName.toLowerCase()?e.push(a):(c=h("<tr><td/></tr>").addClass(b),h("td",c).addClass(b).html(a)[0].colSpan=V(d),e.push(c[0]))};f(a,b);c._details&&c._details.detach();c._details=h(e);
c._detailsShow&&c._details.insertAfter(c.nTr)}return this});o(["row().child.show()","row().child().show()"],function(){Tb(this,!0);return this});o(["row().child.hide()","row().child().hide()"],function(){Tb(this,!1);return this});o(["row().child.remove()","row().child().remove()"],function(){db(this);return this});o("row().child.isShown()",function(){var a=this.context;return a.length&&this.length?a[0].aoData[this[0]]._detailsShow||!1:!1});var bc=/^([^:]+):(name|visIdx|visible)$/,Ub=function(a,b,
c,d,e){for(var c=[],d=0,f=e.length;d<f;d++)c.push(B(a,e[d],b));return c};o("columns()",function(a,b){a===k?a="":h.isPlainObject(a)&&(b=a,a="");var b=bb(b),c=this.iterator("table",function(c){var e=a,f=b,g=c.aoColumns,j=D(g,"sName"),i=D(g,"nTh");return ab("column",e,function(a){var b=Nb(a);if(a==="")return Y(g.length);if(b!==null)return[b>=0?b:g.length+b];if(typeof a==="function"){var e=Ba(c,f);return h.map(g,function(b,f){return a(f,Ub(c,f,0,0,e),i[f])?f:null})}var k=typeof a==="string"?a.match(bc):
"";if(k)switch(k[2]){case "visIdx":case "visible":b=parseInt(k[1],10);if(b<0){var n=h.map(g,function(a,b){return a.bVisible?b:null});return[n[n.length+b]]}return[aa(c,b)];case "name":return h.map(j,function(a,b){return a===k[1]?b:null});default:return[]}if(a.nodeName&&a._DT_CellIndex)return[a._DT_CellIndex.column];b=h(i).filter(a).map(function(){return h.inArray(this,i)}).toArray();if(b.length||!a.nodeName)return b;b=h(a).closest("*[data-dt-column]");return b.length?[b.data("dt-column")]:[]},c,f)},
1);c.selector.cols=a;c.selector.opts=b;return c});u("columns().header()","column().header()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].nTh},1)});u("columns().footer()","column().footer()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].nTf},1)});u("columns().data()","column().data()",function(){return this.iterator("column-rows",Ub,1)});u("columns().dataSrc()","column().dataSrc()",function(){return this.iterator("column",function(a,b){return a.aoColumns[b].mData},
1)});u("columns().cache()","column().cache()",function(a){return this.iterator("column-rows",function(b,c,d,e,f){return ja(b.aoData,f,"search"===a?"_aFilterData":"_aSortData",c)},1)});u("columns().nodes()","column().nodes()",function(){return this.iterator("column-rows",function(a,b,c,d,e){return ja(a.aoData,e,"anCells",b)},1)});u("columns().visible()","column().visible()",function(a,b){var c=this.iterator("column",function(b,c){if(a===k)return b.aoColumns[c].bVisible;var f=b.aoColumns,g=f[c],j=b.aoData,
i,m,l;if(a!==k&&g.bVisible!==a){if(a){var n=h.inArray(!0,D(f,"bVisible"),c+1);i=0;for(m=j.length;i<m;i++)l=j[i].nTr,f=j[i].anCells,l&&l.insertBefore(f[c],f[n]||null)}else h(D(b.aoData,"anCells",c)).detach();g.bVisible=a;fa(b,b.aoHeader);fa(b,b.aoFooter);b.aiDisplay.length||h(b.nTBody).find("td[colspan]").attr("colspan",V(b));xa(b)}});a!==k&&(this.iterator("column",function(c,e){r(c,null,"column-visibility",[c,e,a,b])}),(b===k||b)&&this.columns.adjust());return c});u("columns().indexes()","column().index()",
function(a){return this.iterator("column",function(b,c){return"visible"===a?ba(b,c):c},1)});o("columns.adjust()",function(){return this.iterator("table",function(a){$(a)},1)});o("column.index()",function(a,b){if(0!==this.context.length){var c=this.context[0];if("fromVisible"===a||"toData"===a)return aa(c,b);if("fromData"===a||"toVisible"===a)return ba(c,b)}});o("column()",function(a,b){return cb(this.columns(a,b))});o("cells()",function(a,b,c){h.isPlainObject(a)&&(a.row===k?(c=a,a=null):(c=b,b=null));
h.isPlainObject(b)&&(c=b,b=null);if(null===b||b===k)return this.iterator("table",function(b){var d=a,e=bb(c),f=b.aoData,g=Ba(b,e),j=Qb(ja(f,g,"anCells")),i=h([].concat.apply([],j)),l,m=b.aoColumns.length,n,o,u,s,r,v;return ab("cell",d,function(a){var c=typeof a==="function";if(a===null||a===k||c){n=[];o=0;for(u=g.length;o<u;o++){l=g[o];for(s=0;s<m;s++){r={row:l,column:s};if(c){v=f[l];a(r,B(b,l,s),v.anCells?v.anCells[s]:null)&&n.push(r)}else n.push(r)}}return n}if(h.isPlainObject(a))return a.column!==
k&&a.row!==k&&h.inArray(a.row,g)!==-1?[a]:[];c=i.filter(a).map(function(a,b){return{row:b._DT_CellIndex.row,column:b._DT_CellIndex.column}}).toArray();if(c.length||!a.nodeName)return c;v=h(a).closest("*[data-dt-row]");return v.length?[{row:v.data("dt-row"),column:v.data("dt-column")}]:[]},b,e)});var d=this.columns(b),e=this.rows(a),f,g,j,i,m;this.iterator("table",function(a,b){f=[];g=0;for(j=e[b].length;g<j;g++){i=0;for(m=d[b].length;i<m;i++)f.push({row:e[b][g],column:d[b][i]})}},1);var l=this.cells(f,
c);h.extend(l.selector,{cols:b,rows:a,opts:c});return l});u("cells().nodes()","cell().node()",function(){return this.iterator("cell",function(a,b,c){return(a=a.aoData[b])&&a.anCells?a.anCells[c]:k},1)});o("cells().data()",function(){return this.iterator("cell",function(a,b,c){return B(a,b,c)},1)});u("cells().cache()","cell().cache()",function(a){a="search"===a?"_aFilterData":"_aSortData";return this.iterator("cell",function(b,c,d){return b.aoData[c][a][d]},1)});u("cells().render()","cell().render()",
function(a){return this.iterator("cell",function(b,c,d){return B(b,c,d,a)},1)});u("cells().indexes()","cell().index()",function(){return this.iterator("cell",function(a,b,c){return{row:b,column:c,columnVisible:ba(a,c)}},1)});u("cells().invalidate()","cell().invalidate()",function(a){return this.iterator("cell",function(b,c,d){da(b,c,a,d)})});o("cell()",function(a,b,c){return cb(this.cells(a,b,c))});o("cell().data()",function(a){var b=this.context,c=this[0];if(a===k)return b.length&&c.length?B(b[0],
c[0].row,c[0].column):k;jb(b[0],c[0].row,c[0].column,a);da(b[0],c[0].row,"data",c[0].column);return this});o("order()",function(a,b){var c=this.context;if(a===k)return 0!==c.length?c[0].aaSorting:k;"number"===typeof a?a=[[a,b]]:a.length&&!h.isArray(a[0])&&(a=Array.prototype.slice.call(arguments));return this.iterator("table",function(b){b.aaSorting=a.slice()})});o("order.listener()",function(a,b,c){return this.iterator("table",function(d){Ma(d,a,b,c)})});o("order.fixed()",function(a){if(!a){var b=
this.context,b=b.length?b[0].aaSortingFixed:k;return h.isArray(b)?{pre:b}:b}return this.iterator("table",function(b){b.aaSortingFixed=h.extend(!0,{},a)})});o(["columns().order()","column().order()"],function(a){var b=this;return this.iterator("table",function(c,d){var e=[];h.each(b[d],function(b,c){e.push([c,a])});c.aaSorting=e})});o("search()",function(a,b,c,d){var e=this.context;return a===k?0!==e.length?e[0].oPreviousSearch.sSearch:k:this.iterator("table",function(e){e.oFeatures.bFilter&&ga(e,
h.extend({},e.oPreviousSearch,{sSearch:a+"",bRegex:null===b?!1:b,bSmart:null===c?!0:c,bCaseInsensitive:null===d?!0:d}),1)})});u("columns().search()","column().search()",function(a,b,c,d){return this.iterator("column",function(e,f){var g=e.aoPreSearchCols;if(a===k)return g[f].sSearch;e.oFeatures.bFilter&&(h.extend(g[f],{sSearch:a+"",bRegex:null===b?!1:b,bSmart:null===c?!0:c,bCaseInsensitive:null===d?!0:d}),ga(e,e.oPreviousSearch,1))})});o("state()",function(){return this.context.length?this.context[0].oSavedState:
null});o("state.clear()",function(){return this.iterator("table",function(a){a.fnStateSaveCallback.call(a.oInstance,a,{})})});o("state.loaded()",function(){return this.context.length?this.context[0].oLoadedState:null});o("state.save()",function(){return this.iterator("table",function(a){xa(a)})});n.versionCheck=n.fnVersionCheck=function(a){for(var b=n.version.split("."),a=a.split("."),c,d,e=0,f=a.length;e<f;e++)if(c=parseInt(b[e],10)||0,d=parseInt(a[e],10)||0,c!==d)return c>d;return!0};n.isDataTable=
n.fnIsDataTable=function(a){var b=h(a).get(0),c=!1;if(a instanceof n.Api)return!0;h.each(n.settings,function(a,e){var f=e.nScrollHead?h("table",e.nScrollHead)[0]:null,g=e.nScrollFoot?h("table",e.nScrollFoot)[0]:null;if(e.nTable===b||f===b||g===b)c=!0});return c};n.tables=n.fnTables=function(a){var b=!1;h.isPlainObject(a)&&(b=a.api,a=a.visible);var c=h.map(n.settings,function(b){if(!a||a&&h(b.nTable).is(":visible"))return b.nTable});return b?new s(c):c};n.camelToHungarian=J;o("$()",function(a,b){var c=
this.rows(b).nodes(),c=h(c);return h([].concat(c.filter(a).toArray(),c.find(a).toArray()))});h.each(["on","one","off"],function(a,b){o(b+"()",function(){var a=Array.prototype.slice.call(arguments);a[0]=h.map(a[0].split(/\s/),function(a){return!a.match(/\.dt\b/)?a+".dt":a}).join(" ");var d=h(this.tables().nodes());d[b].apply(d,a);return this})});o("clear()",function(){return this.iterator("table",function(a){oa(a)})});o("settings()",function(){return new s(this.context,this.context)});o("init()",function(){var a=
this.context;return a.length?a[0].oInit:null});o("data()",function(){return this.iterator("table",function(a){return D(a.aoData,"_aData")}).flatten()});o("destroy()",function(a){a=a||!1;return this.iterator("table",function(b){var c=b.nTableWrapper.parentNode,d=b.oClasses,e=b.nTable,f=b.nTBody,g=b.nTHead,j=b.nTFoot,i=h(e),f=h(f),k=h(b.nTableWrapper),l=h.map(b.aoData,function(a){return a.nTr}),o;b.bDestroying=!0;r(b,"aoDestroyCallback","destroy",[b]);a||(new s(b)).columns().visible(!0);k.off(".DT").find(":not(tbody *)").off(".DT");
h(E).off(".DT-"+b.sInstance);e!=g.parentNode&&(i.children("thead").detach(),i.append(g));j&&e!=j.parentNode&&(i.children("tfoot").detach(),i.append(j));b.aaSorting=[];b.aaSortingFixed=[];wa(b);h(l).removeClass(b.asStripeClasses.join(" "));h("th, td",g).removeClass(d.sSortable+" "+d.sSortableAsc+" "+d.sSortableDesc+" "+d.sSortableNone);f.children().detach();f.append(l);g=a?"remove":"detach";i[g]();k[g]();!a&&c&&(c.insertBefore(e,b.nTableReinsertBefore),i.css("width",b.sDestroyWidth).removeClass(d.sTable),
(o=b.asDestroyStripes.length)&&f.children().each(function(a){h(this).addClass(b.asDestroyStripes[a%o])}));c=h.inArray(b,n.settings);-1!==c&&n.settings.splice(c,1)})});h.each(["column","row","cell"],function(a,b){o(b+"s().every()",function(a){var d=this.selector.opts,e=this;return this.iterator(b,function(f,g,h,i,m){a.call(e[b](g,"cell"===b?h:d,"cell"===b?d:k),g,h,i,m)})})});o("i18n()",function(a,b,c){var d=this.context[0],a=S(a)(d.oLanguage);a===k&&(a=b);c!==k&&h.isPlainObject(a)&&(a=a[c]!==k?a[c]:
a._);return a.replace("%d",c)});n.version="1.10.18";n.settings=[];n.models={};n.models.oSearch={bCaseInsensitive:!0,sSearch:"",bRegex:!1,bSmart:!0};n.models.oRow={nTr:null,anCells:null,_aData:[],_aSortData:null,_aFilterData:null,_sFilterRow:null,_sRowStripe:"",src:null,idx:-1};n.models.oColumn={idx:null,aDataSort:null,asSorting:null,bSearchable:null,bSortable:null,bVisible:null,_sManualType:null,_bAttrSrc:!1,fnCreatedCell:null,fnGetData:null,fnSetData:null,mData:null,mRender:null,nTh:null,nTf:null,
sClass:null,sContentPadding:null,sDefaultContent:null,sName:null,sSortDataType:"std",sSortingClass:null,sSortingClassJUI:null,sTitle:null,sType:null,sWidth:null,sWidthOrig:null};n.defaults={aaData:null,aaSorting:[[0,"asc"]],aaSortingFixed:[],ajax:null,aLengthMenu:[10,25,50,100],aoColumns:null,aoColumnDefs:null,aoSearchCols:[],asStripeClasses:null,bAutoWidth:!0,bDeferRender:!1,bDestroy:!1,bFilter:!0,bInfo:!0,bLengthChange:!0,bPaginate:!0,bProcessing:!1,bRetrieve:!1,bScrollCollapse:!1,bServerSide:!1,
bSort:!0,bSortMulti:!0,bSortCellsTop:!1,bSortClasses:!0,bStateSave:!1,fnCreatedRow:null,fnDrawCallback:null,fnFooterCallback:null,fnFormatNumber:function(a){return a.toString().replace(/\B(?=(\d{3})+(?!\d))/g,this.oLanguage.sThousands)},fnHeaderCallback:null,fnInfoCallback:null,fnInitComplete:null,fnPreDrawCallback:null,fnRowCallback:null,fnServerData:null,fnServerParams:null,fnStateLoadCallback:function(a){try{return JSON.parse((-1===a.iStateDuration?sessionStorage:localStorage).getItem("DataTables_"+
a.sInstance+"_"+location.pathname))}catch(b){}},fnStateLoadParams:null,fnStateLoaded:null,fnStateSaveCallback:function(a,b){try{(-1===a.iStateDuration?sessionStorage:localStorage).setItem("DataTables_"+a.sInstance+"_"+location.pathname,JSON.stringify(b))}catch(c){}},fnStateSaveParams:null,iStateDuration:7200,iDeferLoading:null,iDisplayLength:10,iDisplayStart:0,iTabIndex:0,oClasses:{},oLanguage:{oAria:{sSortAscending:": activate to sort column ascending",sSortDescending:": activate to sort column descending"},
oPaginate:{sFirst:"First",sLast:"Last",sNext:"Next",sPrevious:"Previous"},sEmptyTable:"No data available in table",sInfo:"Showing _START_ to _END_ of _TOTAL_ entries",sInfoEmpty:"Showing 0 to 0 of 0 entries",sInfoFiltered:"(filtered from _MAX_ total entries)",sInfoPostFix:"",sDecimal:"",sThousands:",",sLengthMenu:"Show _MENU_ entries",sLoadingRecords:"Loading...",sProcessing:"Processing...",sSearch:"Search:",sSearchPlaceholder:"",sUrl:"",sZeroRecords:"No matching records found"},oSearch:h.extend({},
n.models.oSearch),sAjaxDataProp:"data",sAjaxSource:null,sDom:"lfrtip",searchDelay:null,sPaginationType:"simple_numbers",sScrollX:"",sScrollXInner:"",sScrollY:"",sServerMethod:"GET",renderer:null,rowId:"DT_RowId"};Z(n.defaults);n.defaults.column={aDataSort:null,iDataSort:-1,asSorting:["asc","desc"],bSearchable:!0,bSortable:!0,bVisible:!0,fnCreatedCell:null,mData:null,mRender:null,sCellType:"td",sClass:"",sContentPadding:"",sDefaultContent:null,sName:"",sSortDataType:"std",sTitle:null,sType:null,sWidth:null};
Z(n.defaults.column);n.models.oSettings={oFeatures:{bAutoWidth:null,bDeferRender:null,bFilter:null,bInfo:null,bLengthChange:null,bPaginate:null,bProcessing:null,bServerSide:null,bSort:null,bSortMulti:null,bSortClasses:null,bStateSave:null},oScroll:{bCollapse:null,iBarWidth:0,sX:null,sXInner:null,sY:null},oLanguage:{fnInfoCallback:null},oBrowser:{bScrollOversize:!1,bScrollbarLeft:!1,bBounding:!1,barWidth:0},ajax:null,aanFeatures:[],aoData:[],aiDisplay:[],aiDisplayMaster:[],aIds:{},aoColumns:[],aoHeader:[],
aoFooter:[],oPreviousSearch:{},aoPreSearchCols:[],aaSorting:null,aaSortingFixed:[],asStripeClasses:null,asDestroyStripes:[],sDestroyWidth:0,aoRowCallback:[],aoHeaderCallback:[],aoFooterCallback:[],aoDrawCallback:[],aoRowCreatedCallback:[],aoPreDrawCallback:[],aoInitComplete:[],aoStateSaveParams:[],aoStateLoadParams:[],aoStateLoaded:[],sTableId:"",nTable:null,nTHead:null,nTFoot:null,nTBody:null,nTableWrapper:null,bDeferLoading:!1,bInitialised:!1,aoOpenRows:[],sDom:null,searchDelay:null,sPaginationType:"two_button",
iStateDuration:0,aoStateSave:[],aoStateLoad:[],oSavedState:null,oLoadedState:null,sAjaxSource:null,sAjaxDataProp:null,bAjaxDataGet:!0,jqXHR:null,json:k,oAjaxData:k,fnServerData:null,aoServerParams:[],sServerMethod:null,fnFormatNumber:null,aLengthMenu:null,iDraw:0,bDrawing:!1,iDrawError:-1,_iDisplayLength:10,_iDisplayStart:0,_iRecordsTotal:0,_iRecordsDisplay:0,oClasses:{},bFiltered:!1,bSorted:!1,bSortCellsTop:null,oInit:null,aoDestroyCallback:[],fnRecordsTotal:function(){return"ssp"==y(this)?1*this._iRecordsTotal:
this.aiDisplayMaster.length},fnRecordsDisplay:function(){return"ssp"==y(this)?1*this._iRecordsDisplay:this.aiDisplay.length},fnDisplayEnd:function(){var a=this._iDisplayLength,b=this._iDisplayStart,c=b+a,d=this.aiDisplay.length,e=this.oFeatures,f=e.bPaginate;return e.bServerSide?!1===f||-1===a?b+d:Math.min(b+a,this._iRecordsDisplay):!f||c>d||-1===a?d:c},oInstance:null,sInstance:null,iTabIndex:0,nScrollHead:null,nScrollFoot:null,aLastSort:[],oPlugins:{},rowIdFn:null,rowId:null};n.ext=x={buttons:{},
classes:{},builder:"-source-",errMode:"alert",feature:[],search:[],selector:{cell:[],column:[],row:[]},internal:{},legacy:{ajax:null},pager:{},renderer:{pageButton:{},header:{}},order:{},type:{detect:[],search:{},order:{}},_unique:0,fnVersionCheck:n.fnVersionCheck,iApiIndex:0,oJUIClasses:{},sVersion:n.version};h.extend(x,{afnFiltering:x.search,aTypes:x.type.detect,ofnSearch:x.type.search,oSort:x.type.order,afnSortData:x.order,aoFeatures:x.feature,oApi:x.internal,oStdClasses:x.classes,oPagination:x.pager});
h.extend(n.ext.classes,{sTable:"dataTable",sNoFooter:"no-footer",sPageButton:"paginate_button",sPageButtonActive:"current",sPageButtonDisabled:"disabled",sStripeOdd:"odd",sStripeEven:"even",sRowEmpty:"dataTables_empty",sWrapper:"dataTables_wrapper",sFilter:"dataTables_filter",sInfo:"dataTables_info",sPaging:"dataTables_paginate paging_",sLength:"dataTables_length",sProcessing:"dataTables_processing",sSortAsc:"sorting_asc",sSortDesc:"sorting_desc",sSortable:"sorting",sSortableAsc:"sorting_asc_disabled",
sSortableDesc:"sorting_desc_disabled",sSortableNone:"sorting_disabled",sSortColumn:"sorting_",sFilterInput:"",sLengthSelect:"",sScrollWrapper:"dataTables_scroll",sScrollHead:"dataTables_scrollHead",sScrollHeadInner:"dataTables_scrollHeadInner",sScrollBody:"dataTables_scrollBody",sScrollFoot:"dataTables_scrollFoot",sScrollFootInner:"dataTables_scrollFootInner",sHeaderTH:"",sFooterTH:"",sSortJUIAsc:"",sSortJUIDesc:"",sSortJUI:"",sSortJUIAscAllowed:"",sSortJUIDescAllowed:"",sSortJUIWrapper:"",sSortIcon:"",
sJUIHeader:"",sJUIFooter:""});var Kb=n.ext.pager;h.extend(Kb,{simple:function(){return["previous","next"]},full:function(){return["first","previous","next","last"]},numbers:function(a,b){return[ia(a,b)]},simple_numbers:function(a,b){return["previous",ia(a,b),"next"]},full_numbers:function(a,b){return["first","previous",ia(a,b),"next","last"]},first_last_numbers:function(a,b){return["first",ia(a,b),"last"]},_numbers:ia,numbers_length:7});h.extend(!0,n.ext.renderer,{pageButton:{_:function(a,b,c,d,e,
f){var g=a.oClasses,j=a.oLanguage.oPaginate,i=a.oLanguage.oAria.paginate||{},m,l,n=0,o=function(b,d){var k,s,u,r,v=function(b){Ta(a,b.data.action,true)};k=0;for(s=d.length;k<s;k++){r=d[k];if(h.isArray(r)){u=h("<"+(r.DT_el||"div")+"/>").appendTo(b);o(u,r)}else{m=null;l="";switch(r){case "ellipsis":b.append('<span class="ellipsis">&#x2026;</span>');break;case "first":m=j.sFirst;l=r+(e>0?"":" "+g.sPageButtonDisabled);break;case "previous":m=j.sPrevious;l=r+(e>0?"":" "+g.sPageButtonDisabled);break;case "next":m=
j.sNext;l=r+(e<f-1?"":" "+g.sPageButtonDisabled);break;case "last":m=j.sLast;l=r+(e<f-1?"":" "+g.sPageButtonDisabled);break;default:m=r+1;l=e===r?g.sPageButtonActive:""}if(m!==null){u=h("<a>",{"class":g.sPageButton+" "+l,"aria-controls":a.sTableId,"aria-label":i[r],"data-dt-idx":n,tabindex:a.iTabIndex,id:c===0&&typeof r==="string"?a.sTableId+"_"+r:null}).html(m).appendTo(b);Wa(u,{action:r},v);n++}}}},s;try{s=h(b).find(H.activeElement).data("dt-idx")}catch(u){}o(h(b).empty(),d);s!==k&&h(b).find("[data-dt-idx="+
s+"]").focus()}}});h.extend(n.ext.type.detect,[function(a,b){var c=b.oLanguage.sDecimal;return $a(a,c)?"num"+c:null},function(a){if(a&&!(a instanceof Date)&&!Zb.test(a))return null;var b=Date.parse(a);return null!==b&&!isNaN(b)||M(a)?"date":null},function(a,b){var c=b.oLanguage.sDecimal;return $a(a,c,!0)?"num-fmt"+c:null},function(a,b){var c=b.oLanguage.sDecimal;return Pb(a,c)?"html-num"+c:null},function(a,b){var c=b.oLanguage.sDecimal;return Pb(a,c,!0)?"html-num-fmt"+c:null},function(a){return M(a)||
"string"===typeof a&&-1!==a.indexOf("<")?"html":null}]);h.extend(n.ext.type.search,{html:function(a){return M(a)?a:"string"===typeof a?a.replace(Mb," ").replace(Aa,""):""},string:function(a){return M(a)?a:"string"===typeof a?a.replace(Mb," "):a}});var za=function(a,b,c,d){if(0!==a&&(!a||"-"===a))return-Infinity;b&&(a=Ob(a,b));a.replace&&(c&&(a=a.replace(c,"")),d&&(a=a.replace(d,"")));return 1*a};h.extend(x.type.order,{"date-pre":function(a){a=Date.parse(a);return isNaN(a)?-Infinity:a},"html-pre":function(a){return M(a)?
"":a.replace?a.replace(/<.*?>/g,"").toLowerCase():a+""},"string-pre":function(a){return M(a)?"":"string"===typeof a?a.toLowerCase():!a.toString?"":a.toString()},"string-asc":function(a,b){return a<b?-1:a>b?1:0},"string-desc":function(a,b){return a<b?1:a>b?-1:0}});Da("");h.extend(!0,n.ext.renderer,{header:{_:function(a,b,c,d){h(a.nTable).on("order.dt.DT",function(e,f,g,h){if(a===f){e=c.idx;b.removeClass(c.sSortingClass+" "+d.sSortAsc+" "+d.sSortDesc).addClass(h[e]=="asc"?d.sSortAsc:h[e]=="desc"?d.sSortDesc:
c.sSortingClass)}})},jqueryui:function(a,b,c,d){h("<div/>").addClass(d.sSortJUIWrapper).append(b.contents()).append(h("<span/>").addClass(d.sSortIcon+" "+c.sSortingClassJUI)).appendTo(b);h(a.nTable).on("order.dt.DT",function(e,f,g,h){if(a===f){e=c.idx;b.removeClass(d.sSortAsc+" "+d.sSortDesc).addClass(h[e]=="asc"?d.sSortAsc:h[e]=="desc"?d.sSortDesc:c.sSortingClass);b.find("span."+d.sSortIcon).removeClass(d.sSortJUIAsc+" "+d.sSortJUIDesc+" "+d.sSortJUI+" "+d.sSortJUIAscAllowed+" "+d.sSortJUIDescAllowed).addClass(h[e]==
"asc"?d.sSortJUIAsc:h[e]=="desc"?d.sSortJUIDesc:c.sSortingClassJUI)}})}}});var Vb=function(a){return"string"===typeof a?a.replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;"):a};n.render={number:function(a,b,c,d,e){return{display:function(f){if("number"!==typeof f&&"string"!==typeof f)return f;var g=0>f?"-":"",h=parseFloat(f);if(isNaN(h))return Vb(f);h=h.toFixed(c);f=Math.abs(h);h=parseInt(f,10);f=c?b+(f-h).toFixed(c).substring(2):"";return g+(d||"")+h.toString().replace(/\B(?=(\d{3})+(?!\d))/g,
a)+f+(e||"")}}},text:function(){return{display:Vb}}};h.extend(n.ext.internal,{_fnExternApiFunc:Lb,_fnBuildAjax:sa,_fnAjaxUpdate:lb,_fnAjaxParameters:ub,_fnAjaxUpdateDraw:vb,_fnAjaxDataSrc:ta,_fnAddColumn:Ea,_fnColumnOptions:ka,_fnAdjustColumnSizing:$,_fnVisibleToColumnIndex:aa,_fnColumnIndexToVisible:ba,_fnVisbleColumns:V,_fnGetColumns:ma,_fnColumnTypes:Ga,_fnApplyColumnDefs:ib,_fnHungarianMap:Z,_fnCamelToHungarian:J,_fnLanguageCompat:Ca,_fnBrowserDetect:gb,_fnAddData:O,_fnAddTr:na,_fnNodeToDataIndex:function(a,
b){return b._DT_RowIndex!==k?b._DT_RowIndex:null},_fnNodeToColumnIndex:function(a,b,c){return h.inArray(c,a.aoData[b].anCells)},_fnGetCellData:B,_fnSetCellData:jb,_fnSplitObjNotation:Ja,_fnGetObjectDataFn:S,_fnSetObjectDataFn:N,_fnGetDataMaster:Ka,_fnClearTable:oa,_fnDeleteIndex:pa,_fnInvalidate:da,_fnGetRowElements:Ia,_fnCreateTr:Ha,_fnBuildHead:kb,_fnDrawHead:fa,_fnDraw:P,_fnReDraw:T,_fnAddOptionsHtml:nb,_fnDetectHeader:ea,_fnGetUniqueThs:ra,_fnFeatureHtmlFilter:pb,_fnFilterComplete:ga,_fnFilterCustom:yb,
_fnFilterColumn:xb,_fnFilter:wb,_fnFilterCreateSearch:Pa,_fnEscapeRegex:Qa,_fnFilterData:zb,_fnFeatureHtmlInfo:sb,_fnUpdateInfo:Cb,_fnInfoMacros:Db,_fnInitialise:ha,_fnInitComplete:ua,_fnLengthChange:Ra,_fnFeatureHtmlLength:ob,_fnFeatureHtmlPaginate:tb,_fnPageChange:Ta,_fnFeatureHtmlProcessing:qb,_fnProcessingDisplay:C,_fnFeatureHtmlTable:rb,_fnScrollDraw:la,_fnApplyToChildren:I,_fnCalculateColumnWidths:Fa,_fnThrottle:Oa,_fnConvertToWidth:Eb,_fnGetWidestNode:Fb,_fnGetMaxLenString:Gb,_fnStringToCss:v,
_fnSortFlatten:X,_fnSort:mb,_fnSortAria:Ib,_fnSortListener:Va,_fnSortAttachListener:Ma,_fnSortingClasses:wa,_fnSortData:Hb,_fnSaveState:xa,_fnLoadState:Jb,_fnSettingsFromNode:ya,_fnLog:K,_fnMap:F,_fnBindAction:Wa,_fnCallbackReg:z,_fnCallbackFire:r,_fnLengthOverflow:Sa,_fnRenderer:Na,_fnDataSource:y,_fnRowAttributes:La,_fnExtend:Xa,_fnCalculateEnd:function(){}});h.fn.dataTable=n;n.$=h;h.fn.dataTableSettings=n.settings;h.fn.dataTableExt=n.ext;h.fn.DataTable=function(a){return h(this).dataTable(a).api()};
h.each(n,function(a,b){h.fn.DataTable[a]=b});return h.fn.dataTable});

View File

@@ -1,26 +0,0 @@
/*!
Responsive 2.1.0
2014-2016 SpryMedia Ltd - datatables.net/license
*/
(function(c){"function"===typeof define&&define.amd?define(["jquery","datatables.net"],function(l){return c(l,window,document)}):"object"===typeof exports?module.exports=function(l,k){l||(l=window);if(!k||!k.fn.dataTable)k=require("datatables.net")(l,k).$;return c(k,l,l.document)}:c(jQuery,window,document)})(function(c,l,k,p){var m=c.fn.dataTable,j=function(a,b){if(!m.versionCheck||!m.versionCheck("1.10.3"))throw"DataTables Responsive requires DataTables 1.10.3 or newer";this.s={dt:new m.Api(a),columns:[],
current:[]};this.s.dt.settings()[0].responsive||(b&&"string"===typeof b.details?b.details={type:b.details}:b&&!1===b.details?b.details={type:!1}:b&&!0===b.details&&(b.details={type:"inline"}),this.c=c.extend(!0,{},j.defaults,m.defaults.responsive,b),a.responsive=this,this._constructor())};c.extend(j.prototype,{_constructor:function(){var a=this,b=this.s.dt,d=b.settings()[0],e=c(l).width();b.settings()[0]._responsive=this;c(l).on("resize.dtr orientationchange.dtr",m.util.throttle(function(){var b=
c(l).width();b!==e&&(a._resize(),e=b)}));d.oApi._fnCallbackReg(d,"aoRowCreatedCallback",function(e){-1!==c.inArray(!1,a.s.current)&&c("td, th",e).each(function(e){e=b.column.index("toData",e);!1===a.s.current[e]&&c(this).css("display","none")})});b.on("destroy.dtr",function(){b.off(".dtr");c(b.table().body()).off(".dtr");c(l).off("resize.dtr orientationchange.dtr");c.each(a.s.current,function(b,e){!1===e&&a._setColumnVis(b,!0)})});this.c.breakpoints.sort(function(a,b){return a.width<b.width?1:a.width>
b.width?-1:0});this._classLogic();this._resizeAuto();d=this.c.details;!1!==d.type&&(a._detailsInit(),b.on("column-visibility.dtr",function(){a._classLogic();a._resizeAuto();a._resize()}),b.on("draw.dtr",function(){a._redrawChildren()}),c(b.table().node()).addClass("dtr-"+d.type));b.on("column-reorder.dtr",function(){a._classLogic();a._resizeAuto();a._resize()});b.on("column-sizing.dtr",function(){a._resizeAuto();a._resize()});b.on("init.dtr",function(){a._resizeAuto();a._resize();c.inArray(false,
a.s.current)&&b.columns.adjust()});this._resize()},_columnsVisiblity:function(a){var b=this.s.dt,d=this.s.columns,e,f,g=d.map(function(a,b){return{columnIdx:b,priority:a.priority}}).sort(function(a,b){return a.priority!==b.priority?a.priority-b.priority:a.columnIdx-b.columnIdx}),h=c.map(d,function(b){return b.auto&&null===b.minWidth?!1:!0===b.auto?"-":-1!==c.inArray(a,b.includeIn)}),n=0;e=0;for(f=h.length;e<f;e++)!0===h[e]&&(n+=d[e].minWidth);e=b.settings()[0].oScroll;e=e.sY||e.sX?e.iBarWidth:0;b=
b.table().container().offsetWidth-e-n;e=0;for(f=h.length;e<f;e++)d[e].control&&(b-=d[e].minWidth);n=!1;e=0;for(f=g.length;e<f;e++){var i=g[e].columnIdx;"-"===h[i]&&(!d[i].control&&d[i].minWidth)&&(n||0>b-d[i].minWidth?(n=!0,h[i]=!1):h[i]=!0,b-=d[i].minWidth)}g=!1;e=0;for(f=d.length;e<f;e++)if(!d[e].control&&!d[e].never&&!h[e]){g=!0;break}e=0;for(f=d.length;e<f;e++)d[e].control&&(h[e]=g);-1===c.inArray(!0,h)&&(h[0]=!0);return h},_classLogic:function(){var a=this,b=this.c.breakpoints,d=this.s.dt,e=
d.columns().eq(0).map(function(a){var b=this.column(a),e=b.header().className,a=d.settings()[0].aoColumns[a].responsivePriority;a===p&&(b=c(b.header()).data("priority"),a=b!==p?1*b:1E4);return{className:e,includeIn:[],auto:!1,control:!1,never:e.match(/\bnever\b/)?!0:!1,priority:a}}),f=function(a,b){var d=e[a].includeIn;-1===c.inArray(b,d)&&d.push(b)},g=function(c,d,i,g){if(i)if("max-"===i){g=a._find(d).width;d=0;for(i=b.length;d<i;d++)b[d].width<=g&&f(c,b[d].name)}else if("min-"===i){g=a._find(d).width;
d=0;for(i=b.length;d<i;d++)b[d].width>=g&&f(c,b[d].name)}else{if("not-"===i){d=0;for(i=b.length;d<i;d++)-1===b[d].name.indexOf(g)&&f(c,b[d].name)}}else e[c].includeIn.push(d)};e.each(function(a,e){for(var d=a.className.split(" "),f=!1,j=0,l=d.length;j<l;j++){var k=c.trim(d[j]);if("all"===k){f=!0;a.includeIn=c.map(b,function(a){return a.name});return}if("none"===k||a.never){f=!0;return}if("control"===k){f=!0;a.control=!0;return}c.each(b,function(a,b){var d=b.name.split("-"),c=k.match(RegExp("(min\\-|max\\-|not\\-)?("+
d[0]+")(\\-[_a-zA-Z0-9])?"));c&&(f=!0,c[2]===d[0]&&c[3]==="-"+d[1]?g(e,b.name,c[1],c[2]+c[3]):c[2]===d[0]&&!c[3]&&g(e,b.name,c[1],c[2]))})}f||(a.auto=!0)});this.s.columns=e},_detailsDisplay:function(a,b){var d=this,e=this.s.dt,f=this.c.details;if(f&&!1!==f.type){var g=f.display(a,b,function(){return f.renderer(e,a[0],d._detailsObj(a[0]))});(!0===g||!1===g)&&c(e.table().node()).triggerHandler("responsive-display.dt",[e,a,g,b])}},_detailsInit:function(){var a=this,b=this.s.dt,d=this.c.details;"inline"===
d.type&&(d.target="td:first-child, th:first-child");b.on("draw.dtr",function(){a._tabIndexes()});a._tabIndexes();c(b.table().body()).on("keyup.dtr","td, th",function(a){a.keyCode===13&&c(this).data("dtr-keyboard")&&c(this).click()});var e=d.target;c(b.table().body()).on("click.dtr mousedown.dtr mouseup.dtr","string"===typeof e?e:"td, th",function(d){if(c(b.table().node()).hasClass("collapsed")&&b.row(c(this).closest("tr")).length){if(typeof e==="number"){var g=e<0?b.columns().eq(0).length+e:e;if(b.cell(this).index().column!==
g)return}g=b.row(c(this).closest("tr"));d.type==="click"?a._detailsDisplay(g,false):d.type==="mousedown"?c(this).css("outline","none"):d.type==="mouseup"&&c(this).blur().css("outline","")}})},_detailsObj:function(a){var b=this,d=this.s.dt;return c.map(this.s.columns,function(e,c){if(!e.never&&!e.control)return{title:d.settings()[0].aoColumns[c].sTitle,data:d.cell(a,c).render(b.c.orthogonal),hidden:d.column(c).visible()&&!b.s.current[c],columnIndex:c,rowIndex:a}})},_find:function(a){for(var b=this.c.breakpoints,
d=0,c=b.length;d<c;d++)if(b[d].name===a)return b[d]},_redrawChildren:function(){var a=this,b=this.s.dt;b.rows({page:"current"}).iterator("row",function(c,e){b.row(e);a._detailsDisplay(b.row(e),!0)})},_resize:function(){var a=this,b=this.s.dt,d=c(l).width(),e=this.c.breakpoints,f=e[0].name,g=this.s.columns,h,j=this.s.current.slice();for(h=e.length-1;0<=h;h--)if(d<=e[h].width){f=e[h].name;break}var i=this._columnsVisiblity(f);this.s.current=i;e=!1;h=0;for(d=g.length;h<d;h++)if(!1===i[h]&&!g[h].never&&
!g[h].control){e=!0;break}c(b.table().node()).toggleClass("collapsed",e);var k=!1;b.columns().eq(0).each(function(b,c){i[c]!==j[c]&&(k=!0,a._setColumnVis(b,i[c]))});k&&(this._redrawChildren(),c(b.table().node()).trigger("responsive-resize.dt",[b,this.s.current]))},_resizeAuto:function(){var a=this.s.dt,b=this.s.columns;if(this.c.auto&&-1!==c.inArray(!0,c.map(b,function(a){return a.auto}))){a.table().node();var d=a.table().node().cloneNode(!1),e=c(a.table().header().cloneNode(!1)).appendTo(d),f=c(a.table().body()).clone(!1,
!1).empty().appendTo(d),g=a.columns().header().filter(function(b){return a.column(b).visible()}).to$().clone(!1).css("display","table-cell");c(f).append(c(a.rows({page:"current"}).nodes()).clone(!1)).find("th, td").css("display","");if(f=a.table().footer()){var f=c(f.cloneNode(!1)).appendTo(d),h=a.columns().footer().filter(function(b){return a.column(b).visible()}).to$().clone(!1).css("display","table-cell");c("<tr/>").append(h).appendTo(f)}c("<tr/>").append(g).appendTo(e);"inline"===this.c.details.type&&
c(d).addClass("dtr-inline collapsed");c(d).find("[name]").removeAttr("name");d=c("<div/>").css({width:1,height:1,overflow:"hidden"}).append(d);d.insertBefore(a.table().node());g.each(function(c){c=a.column.index("fromVisible",c);b[c].minWidth=this.offsetWidth||0});d.remove()}},_setColumnVis:function(a,b){var d=this.s.dt,e=b?"":"none";c(d.column(a).header()).css("display",e);c(d.column(a).footer()).css("display",e);d.column(a).nodes().to$().css("display",e)},_tabIndexes:function(){var a=this.s.dt,
b=a.cells({page:"current"}).nodes().to$(),d=a.settings()[0],e=this.c.details.target;b.filter("[data-dtr-keyboard]").removeData("[data-dtr-keyboard]");c("number"===typeof e?":eq("+e+")":e,a.rows({page:"current"}).nodes()).attr("tabIndex",d.iTabIndex).data("dtr-keyboard",1)}});j.breakpoints=[{name:"desktop",width:Infinity},{name:"tablet-l",width:1024},{name:"tablet-p",width:768},{name:"mobile-l",width:480},{name:"mobile-p",width:320}];j.display={childRow:function(a,b,d){if(b){if(c(a.node()).hasClass("parent"))return a.child(d(),
"child").show(),!0}else{if(a.child.isShown())return a.child(!1),c(a.node()).removeClass("parent"),!1;a.child(d(),"child").show();c(a.node()).addClass("parent");return!0}},childRowImmediate:function(a,b,d){if(!b&&a.child.isShown()||!a.responsive.hasHidden())return a.child(!1),c(a.node()).removeClass("parent"),!1;a.child(d(),"child").show();c(a.node()).addClass("parent");return!0},modal:function(a){return function(b,d,e){if(d)c("div.dtr-modal-content").empty().append(e());else{var f=function(){g.remove();
c(k).off("keypress.dtr")},g=c('<div class="dtr-modal"/>').append(c('<div class="dtr-modal-display"/>').append(c('<div class="dtr-modal-content"/>').append(e())).append(c('<div class="dtr-modal-close">&times;</div>').click(function(){f()}))).append(c('<div class="dtr-modal-background"/>').click(function(){f()})).appendTo("body");c(k).on("keyup.dtr",function(a){27===a.keyCode&&(a.stopPropagation(),f())})}a&&a.header&&c("div.dtr-modal-content").prepend("<h2>"+a.header(b)+"</h2>")}}};j.renderer={listHidden:function(){return function(a,
b,d){return(a=c.map(d,function(a){return a.hidden?'<li data-dtr-index="'+a.columnIndex+'" data-dt-row="'+a.rowIndex+'" data-dt-column="'+a.columnIndex+'"><span class="dtr-title">'+a.title+'</span> <span class="dtr-data">'+a.data+"</span></li>":""}).join(""))?c('<ul data-dtr-index="'+b+'"/>').append(a):!1}},tableAll:function(a){a=c.extend({tableClass:""},a);return function(b,d,e){b=c.map(e,function(a){return'<tr data-dt-row="'+a.rowIndex+'" data-dt-column="'+a.columnIndex+'"><td>'+a.title+":</td> <td>"+
a.data+"</td></tr>"}).join("");return c('<table class="'+a.tableClass+'" width="100%"/>').append(b)}}};j.defaults={breakpoints:j.breakpoints,auto:!0,details:{display:j.display.childRow,renderer:j.renderer.listHidden(),target:0,type:"inline"},orthogonal:"display"};var o=c.fn.dataTable.Api;o.register("responsive()",function(){return this});o.register("responsive.index()",function(a){a=c(a);return{column:a.data("dtr-index"),row:a.parent().data("dtr-index")}});o.register("responsive.rebuild()",function(){return this.iterator("table",
function(a){a._responsive&&a._responsive._classLogic()})});o.register("responsive.recalc()",function(){return this.iterator("table",function(a){a._responsive&&(a._responsive._resizeAuto(),a._responsive._resize())})});o.register("responsive.hasHidden()",function(){var a=this.context[0];return a._responsive?-1!==c.inArray(!1,a._responsive.s.current):!1});j.version="2.1.0";c.fn.dataTable.Responsive=j;c.fn.DataTable.Responsive=j;c(k).on("preInit.dt.dtr",function(a,b){if("dt"===a.namespace&&(c(b.nTable).hasClass("responsive")||
c(b.nTable).hasClass("dt-responsive")||b.oInit.responsive||m.defaults.responsive)){var d=b.oInit.responsive;!1!==d&&new j(b,c.isPlainObject(d)?d:{})}});return j});

View File

@@ -0,0 +1,30 @@
/*!
Responsive 2.2.2
2014-2018 SpryMedia Ltd - datatables.net/license
*/
(function(d){"function"===typeof define&&define.amd?define(["jquery","datatables.net"],function(l){return d(l,window,document)}):"object"===typeof exports?module.exports=function(l,j){l||(l=window);if(!j||!j.fn.dataTable)j=require("datatables.net")(l,j).$;return d(j,l,l.document)}:d(jQuery,window,document)})(function(d,l,j,q){function t(a,b,c){var e=b+"-"+c;if(n[e])return n[e];for(var d=[],a=a.cell(b,c).node().childNodes,b=0,c=a.length;b<c;b++)d.push(a[b]);return n[e]=d}function r(a,b,d){var e=b+
"-"+d;if(n[e]){for(var a=a.cell(b,d).node(),d=n[e][0].parentNode.childNodes,b=[],f=0,g=d.length;f<g;f++)b.push(d[f]);d=0;for(f=b.length;d<f;d++)a.appendChild(b[d]);n[e]=q}}var o=d.fn.dataTable,i=function(a,b){if(!o.versionCheck||!o.versionCheck("1.10.10"))throw"DataTables Responsive requires DataTables 1.10.10 or newer";this.s={dt:new o.Api(a),columns:[],current:[]};this.s.dt.settings()[0].responsive||(b&&"string"===typeof b.details?b.details={type:b.details}:b&&!1===b.details?b.details={type:!1}:
b&&!0===b.details&&(b.details={type:"inline"}),this.c=d.extend(!0,{},i.defaults,o.defaults.responsive,b),a.responsive=this,this._constructor())};d.extend(i.prototype,{_constructor:function(){var a=this,b=this.s.dt,c=b.settings()[0],e=d(l).width();b.settings()[0]._responsive=this;d(l).on("resize.dtr orientationchange.dtr",o.util.throttle(function(){var b=d(l).width();b!==e&&(a._resize(),e=b)}));c.oApi._fnCallbackReg(c,"aoRowCreatedCallback",function(e){-1!==d.inArray(!1,a.s.current)&&d(">td, >th",
e).each(function(e){e=b.column.index("toData",e);!1===a.s.current[e]&&d(this).css("display","none")})});b.on("destroy.dtr",function(){b.off(".dtr");d(b.table().body()).off(".dtr");d(l).off("resize.dtr orientationchange.dtr");d.each(a.s.current,function(b,e){!1===e&&a._setColumnVis(b,!0)})});this.c.breakpoints.sort(function(a,b){return a.width<b.width?1:a.width>b.width?-1:0});this._classLogic();this._resizeAuto();c=this.c.details;!1!==c.type&&(a._detailsInit(),b.on("column-visibility.dtr",function(){a._timer&&
clearTimeout(a._timer);a._timer=setTimeout(function(){a._timer=null;a._classLogic();a._resizeAuto();a._resize();a._redrawChildren()},100)}),b.on("draw.dtr",function(){a._redrawChildren()}),d(b.table().node()).addClass("dtr-"+c.type));b.on("column-reorder.dtr",function(){a._classLogic();a._resizeAuto();a._resize()});b.on("column-sizing.dtr",function(){a._resizeAuto();a._resize()});b.on("preXhr.dtr",function(){var e=[];b.rows().every(function(){this.child.isShown()&&e.push(this.id(true))});b.one("draw.dtr",
function(){a._resizeAuto();a._resize();b.rows(e).every(function(){a._detailsDisplay(this,false)})})});b.on("init.dtr",function(){a._resizeAuto();a._resize();d.inArray(false,a.s.current)&&b.columns.adjust()});this._resize()},_columnsVisiblity:function(a){var b=this.s.dt,c=this.s.columns,e,f,g=c.map(function(a,b){return{columnIdx:b,priority:a.priority}}).sort(function(a,b){return a.priority!==b.priority?a.priority-b.priority:a.columnIdx-b.columnIdx}),h=d.map(c,function(e,c){return!1===b.column(c).visible()?
"not-visible":e.auto&&null===e.minWidth?!1:!0===e.auto?"-":-1!==d.inArray(a,e.includeIn)}),m=0;e=0;for(f=h.length;e<f;e++)!0===h[e]&&(m+=c[e].minWidth);e=b.settings()[0].oScroll;e=e.sY||e.sX?e.iBarWidth:0;m=b.table().container().offsetWidth-e-m;e=0;for(f=h.length;e<f;e++)c[e].control&&(m-=c[e].minWidth);var s=!1;e=0;for(f=g.length;e<f;e++){var k=g[e].columnIdx;"-"===h[k]&&(!c[k].control&&c[k].minWidth)&&(s||0>m-c[k].minWidth?(s=!0,h[k]=!1):h[k]=!0,m-=c[k].minWidth)}g=!1;e=0;for(f=c.length;e<f;e++)if(!c[e].control&&
!c[e].never&&!1===h[e]){g=!0;break}e=0;for(f=c.length;e<f;e++)c[e].control&&(h[e]=g),"not-visible"===h[e]&&(h[e]=!1);-1===d.inArray(!0,h)&&(h[0]=!0);return h},_classLogic:function(){var a=this,b=this.c.breakpoints,c=this.s.dt,e=c.columns().eq(0).map(function(a){var b=this.column(a),e=b.header().className,a=c.settings()[0].aoColumns[a].responsivePriority;a===q&&(b=d(b.header()).data("priority"),a=b!==q?1*b:1E4);return{className:e,includeIn:[],auto:!1,control:!1,never:e.match(/\bnever\b/)?!0:!1,priority:a}}),
f=function(a,b){var c=e[a].includeIn;-1===d.inArray(b,c)&&c.push(b)},g=function(d,c,g,k){if(g)if("max-"===g){k=a._find(c).width;c=0;for(g=b.length;c<g;c++)b[c].width<=k&&f(d,b[c].name)}else if("min-"===g){k=a._find(c).width;c=0;for(g=b.length;c<g;c++)b[c].width>=k&&f(d,b[c].name)}else{if("not-"===g){c=0;for(g=b.length;c<g;c++)-1===b[c].name.indexOf(k)&&f(d,b[c].name)}}else e[d].includeIn.push(c)};e.each(function(a,e){for(var c=a.className.split(" "),f=!1,i=0,l=c.length;i<l;i++){var j=d.trim(c[i]);
if("all"===j){f=!0;a.includeIn=d.map(b,function(a){return a.name});return}if("none"===j||a.never){f=!0;return}if("control"===j){f=!0;a.control=!0;return}d.each(b,function(a,b){var d=b.name.split("-"),c=j.match(RegExp("(min\\-|max\\-|not\\-)?("+d[0]+")(\\-[_a-zA-Z0-9])?"));c&&(f=!0,c[2]===d[0]&&c[3]==="-"+d[1]?g(e,b.name,c[1],c[2]+c[3]):c[2]===d[0]&&!c[3]&&g(e,b.name,c[1],c[2]))})}f||(a.auto=!0)});this.s.columns=e},_detailsDisplay:function(a,b){var c=this,e=this.s.dt,f=this.c.details;if(f&&!1!==f.type){var g=
f.display(a,b,function(){return f.renderer(e,a[0],c._detailsObj(a[0]))});(!0===g||!1===g)&&d(e.table().node()).triggerHandler("responsive-display.dt",[e,a,g,b])}},_detailsInit:function(){var a=this,b=this.s.dt,c=this.c.details;"inline"===c.type&&(c.target="td:first-child, th:first-child");b.on("draw.dtr",function(){a._tabIndexes()});a._tabIndexes();d(b.table().body()).on("keyup.dtr","td, th",function(a){a.keyCode===13&&d(this).data("dtr-keyboard")&&d(this).click()});var e=c.target;d(b.table().body()).on("click.dtr mousedown.dtr mouseup.dtr",
"string"===typeof e?e:"td, th",function(c){if(d(b.table().node()).hasClass("collapsed")&&d.inArray(d(this).closest("tr").get(0),b.rows().nodes().toArray())!==-1){if(typeof e==="number"){var g=e<0?b.columns().eq(0).length+e:e;if(b.cell(this).index().column!==g)return}g=b.row(d(this).closest("tr"));c.type==="click"?a._detailsDisplay(g,false):c.type==="mousedown"?d(this).css("outline","none"):c.type==="mouseup"&&d(this).blur().css("outline","")}})},_detailsObj:function(a){var b=this,c=this.s.dt;return d.map(this.s.columns,
function(e,d){if(!e.never&&!e.control)return{title:c.settings()[0].aoColumns[d].sTitle,data:c.cell(a,d).render(b.c.orthogonal),hidden:c.column(d).visible()&&!b.s.current[d],columnIndex:d,rowIndex:a}})},_find:function(a){for(var b=this.c.breakpoints,c=0,e=b.length;c<e;c++)if(b[c].name===a)return b[c]},_redrawChildren:function(){var a=this,b=this.s.dt;b.rows({page:"current"}).iterator("row",function(c,e){b.row(e);a._detailsDisplay(b.row(e),!0)})},_resize:function(){var a=this,b=this.s.dt,c=d(l).width(),
e=this.c.breakpoints,f=e[0].name,g=this.s.columns,h,m=this.s.current.slice();for(h=e.length-1;0<=h;h--)if(c<=e[h].width){f=e[h].name;break}var i=this._columnsVisiblity(f);this.s.current=i;e=!1;h=0;for(c=g.length;h<c;h++)if(!1===i[h]&&!g[h].never&&!g[h].control&&!1===!b.column(h).visible()){e=!0;break}d(b.table().node()).toggleClass("collapsed",e);var k=!1,j=0;b.columns().eq(0).each(function(b,c){!0===i[c]&&j++;i[c]!==m[c]&&(k=!0,a._setColumnVis(b,i[c]))});k&&(this._redrawChildren(),d(b.table().node()).trigger("responsive-resize.dt",
[b,this.s.current]),0===b.page.info().recordsDisplay&&d("td",b.table().body()).eq(0).attr("colspan",j))},_resizeAuto:function(){var a=this.s.dt,b=this.s.columns;if(this.c.auto&&-1!==d.inArray(!0,d.map(b,function(a){return a.auto}))){d.isEmptyObject(n)||d.each(n,function(b){b=b.split("-");r(a,1*b[0],1*b[1])});a.table().node();var c=a.table().node().cloneNode(!1),e=d(a.table().header().cloneNode(!1)).appendTo(c),f=d(a.table().body()).clone(!1,!1).empty().appendTo(c),g=a.columns().header().filter(function(b){return a.column(b).visible()}).to$().clone(!1).css("display",
"table-cell").css("min-width",0);d(f).append(d(a.rows({page:"current"}).nodes()).clone(!1)).find("th, td").css("display","");if(f=a.table().footer()){var f=d(f.cloneNode(!1)).appendTo(c),h=a.columns().footer().filter(function(b){return a.column(b).visible()}).to$().clone(!1).css("display","table-cell");d("<tr/>").append(h).appendTo(f)}d("<tr/>").append(g).appendTo(e);"inline"===this.c.details.type&&d(c).addClass("dtr-inline collapsed");d(c).find("[name]").removeAttr("name");d(c).css("position","relative");
c=d("<div/>").css({width:1,height:1,overflow:"hidden",clear:"both"}).append(c);c.insertBefore(a.table().node());g.each(function(c){c=a.column.index("fromVisible",c);b[c].minWidth=this.offsetWidth||0});c.remove()}},_setColumnVis:function(a,b){var c=this.s.dt,e=b?"":"none";d(c.column(a).header()).css("display",e);d(c.column(a).footer()).css("display",e);c.column(a).nodes().to$().css("display",e);d.isEmptyObject(n)||c.cells(null,a).indexes().each(function(a){r(c,a.row,a.column)})},_tabIndexes:function(){var a=
this.s.dt,b=a.cells({page:"current"}).nodes().to$(),c=a.settings()[0],e=this.c.details.target;b.filter("[data-dtr-keyboard]").removeData("[data-dtr-keyboard]");"number"===typeof e?a.cells(null,e,{page:"current"}).nodes().to$().attr("tabIndex",c.iTabIndex).data("dtr-keyboard",1):("td:first-child, th:first-child"===e&&(e=">td:first-child, >th:first-child"),d(e,a.rows({page:"current"}).nodes()).attr("tabIndex",c.iTabIndex).data("dtr-keyboard",1))}});i.breakpoints=[{name:"desktop",width:Infinity},{name:"tablet-l",
width:1024},{name:"tablet-p",width:768},{name:"mobile-l",width:480},{name:"mobile-p",width:320}];i.display={childRow:function(a,b,c){if(b){if(d(a.node()).hasClass("parent"))return a.child(c(),"child").show(),!0}else{if(a.child.isShown())return a.child(!1),d(a.node()).removeClass("parent"),!1;a.child(c(),"child").show();d(a.node()).addClass("parent");return!0}},childRowImmediate:function(a,b,c){if(!b&&a.child.isShown()||!a.responsive.hasHidden())return a.child(!1),d(a.node()).removeClass("parent"),
!1;a.child(c(),"child").show();d(a.node()).addClass("parent");return!0},modal:function(a){return function(b,c,e){if(c)d("div.dtr-modal-content").empty().append(e());else{var f=function(){g.remove();d(j).off("keypress.dtr")},g=d('<div class="dtr-modal"/>').append(d('<div class="dtr-modal-display"/>').append(d('<div class="dtr-modal-content"/>').append(e())).append(d('<div class="dtr-modal-close">&times;</div>').click(function(){f()}))).append(d('<div class="dtr-modal-background"/>').click(function(){f()})).appendTo("body");
d(j).on("keyup.dtr",function(a){27===a.keyCode&&(a.stopPropagation(),f())})}a&&a.header&&d("div.dtr-modal-content").prepend("<h2>"+a.header(b)+"</h2>")}}};var n={};i.renderer={listHiddenNodes:function(){return function(a,b,c){var e=d('<ul data-dtr-index="'+b+'" class="dtr-details"/>'),f=!1;d.each(c,function(b,c){c.hidden&&(d('<li data-dtr-index="'+c.columnIndex+'" data-dt-row="'+c.rowIndex+'" data-dt-column="'+c.columnIndex+'"><span class="dtr-title">'+c.title+"</span> </li>").append(d('<span class="dtr-data"/>').append(t(a,
c.rowIndex,c.columnIndex))).appendTo(e),f=!0)});return f?e:!1}},listHidden:function(){return function(a,b,c){return(a=d.map(c,function(a){return a.hidden?'<li data-dtr-index="'+a.columnIndex+'" data-dt-row="'+a.rowIndex+'" data-dt-column="'+a.columnIndex+'"><span class="dtr-title">'+a.title+'</span> <span class="dtr-data">'+a.data+"</span></li>":""}).join(""))?d('<ul data-dtr-index="'+b+'" class="dtr-details"/>').append(a):!1}},tableAll:function(a){a=d.extend({tableClass:""},a);return function(b,
c,e){b=d.map(e,function(a){return'<tr data-dt-row="'+a.rowIndex+'" data-dt-column="'+a.columnIndex+'"><td>'+a.title+":</td> <td>"+a.data+"</td></tr>"}).join("");return d('<table class="'+a.tableClass+' dtr-details" width="100%"/>').append(b)}}};i.defaults={breakpoints:i.breakpoints,auto:!0,details:{display:i.display.childRow,renderer:i.renderer.listHidden(),target:0,type:"inline"},orthogonal:"display"};var p=d.fn.dataTable.Api;p.register("responsive()",function(){return this});p.register("responsive.index()",
function(a){a=d(a);return{column:a.data("dtr-index"),row:a.parent().data("dtr-index")}});p.register("responsive.rebuild()",function(){return this.iterator("table",function(a){a._responsive&&a._responsive._classLogic()})});p.register("responsive.recalc()",function(){return this.iterator("table",function(a){a._responsive&&(a._responsive._resizeAuto(),a._responsive._resize())})});p.register("responsive.hasHidden()",function(){var a=this.context[0];return a._responsive?-1!==d.inArray(!1,a._responsive.s.current):
!1});p.registerPlural("columns().responsiveHidden()","column().responsiveHidden()",function(){return this.iterator("column",function(a,b){return a._responsive?a._responsive.s.current[b]:!1},1)});i.version="2.2.2";d.fn.dataTable.Responsive=i;d.fn.DataTable.Responsive=i;d(j).on("preInit.dt.dtr",function(a,b){if("dt"===a.namespace&&(d(b.nTable).hasClass("responsive")||d(b.nTable).hasClass("dt-responsive")||b.oInit.responsive||o.defaults.responsive)){var c=b.oInit.responsive;!1!==c&&new i(b,d.isPlainObject(c)?
c:{})}});return i});

View File

@@ -1,26 +0,0 @@
/*!
Select for DataTables 1.2.0
2015-2016 SpryMedia Ltd - datatables.net/license/mit
*/
(function(e){"function"===typeof define&&define.amd?define(["jquery","datatables.net"],function(i){return e(i,window,document)}):"object"===typeof exports?module.exports=function(i,l){i||(i=window);if(!l||!l.fn.dataTable)l=require("datatables.net")(i,l).$;return e(l,i,i.document)}:e(jQuery,window,document)})(function(e,i,l,h){function t(b,a,c){var d;d=function(c,a){if(c>a)var d=a,a=c,c=d;var f=!1;return b.columns(":visible").indexes().filter(function(b){b===c&&(f=!0);return b===a?(f=!1,!0):f})};var f=
function(c,a){var d=b.rows({search:"applied"}).indexes();if(d.indexOf(c)>d.indexOf(a))var f=a,a=c,c=f;var e=!1;return d.filter(function(b){b===c&&(e=!0);return b===a?(e=!1,!0):e})};!b.cells({selected:!0}).any()&&!c?(d=d(0,a.column),c=f(0,a.row)):(d=d(c.column,a.column),c=f(c.row,a.row));c=b.cells(c,d).flatten();b.cells(a,{selected:!0}).any()?b.cells(c).deselect():b.cells(c).select()}function r(b){var a=b.settings()[0]._select.selector;e(b.table().body()).off("mousedown.dtSelect",a).off("mouseup.dtSelect",
a).off("click.dtSelect",a);e("body").off("click.dtSelect")}function v(b){var a=e(b.table().body()),c=b.settings()[0],d=c._select.selector;a.on("mousedown.dtSelect",d,function(c){if(c.shiftKey||c.metaKey||c.ctrlKey)a.css("-moz-user-select","none").one("selectstart.dtSelect",d,function(){return!1})}).on("mouseup.dtSelect",d,function(){a.css("-moz-user-select","")}).on("click.dtSelect",d,function(c){var a=b.select.items();if(!i.getSelection||!i.getSelection().toString()){var d=b.settings()[0];if(e(c.target).closest("div.dataTables_wrapper")[0]==
b.table().container()){var g=b.cell(e(c.target).closest("td, th"));if(g.any()){var h=e.Event("user-select.dt");k(b,h,[a,g,c]);h.isDefaultPrevented()||(h=g.index(),"row"===a?(a=h.row,s(c,b,d,"row",a)):"column"===a?(a=g.index().column,s(c,b,d,"column",a)):"cell"===a&&(a=g.index(),s(c,b,d,"cell",a)),d._select_lastCell=h)}}}});e("body").on("click.dtSelect",function(a){c._select.blurable&&!e(a.target).parents().filter(b.table().container()).length&&(e(a.target).parents("div.DTE").length||p(c,!0))})}function k(b,
a,c,d){if(!d||b.flatten().length)"string"===typeof a&&(a+=".dt"),c.unshift(b),e(b.table().node()).triggerHandler(a,c)}function w(b){var a=b.settings()[0];if(a._select.info&&a.aanFeatures.i){var c=e('<span class="select-info"/>'),d=function(a,d){c.append(e('<span class="select-item"/>').append(b.i18n("select."+a+"s",{_:"%d "+a+"s selected","0":"",1:"1 "+a+" selected"},d)))};d("row",b.rows({selected:!0}).flatten().length);d("column",b.columns({selected:!0}).flatten().length);d("cell",b.cells({selected:!0}).flatten().length);
e.each(a.aanFeatures.i,function(a,b){var b=e(b),d=b.children("span.select-info");d.length&&d.remove();""!==c.text()&&b.append(c)})}}function x(b,a,c,d){var f=b[a+"s"]({search:"applied"}).indexes(),d=e.inArray(d,f),m=e.inArray(c,f);if(!b[a+"s"]({selected:!0}).any()&&-1===d)f.splice(e.inArray(c,f)+1,f.length);else{if(d>m)var j=m,m=d,d=j;f.splice(m+1,f.length);f.splice(0,d)}b[a](c,{selected:!0}).any()?(f.splice(e.inArray(c,f),1),b[a+"s"](f).deselect()):b[a+"s"](f).select()}function p(b,a){if(a||"single"===
b._select.style){var c=new g.Api(b);c.rows({selected:!0}).deselect();c.columns({selected:!0}).deselect();c.cells({selected:!0}).deselect()}}function s(b,a,c,d,f){var e=a.select.style(),j=a[d](f,{selected:!0}).any();"os"===e?b.ctrlKey||b.metaKey?a[d](f).select(!j):b.shiftKey?"cell"===d?t(a,f,c._select_lastCell||null):x(a,d,f,c._select_lastCell?c._select_lastCell[d]:null):(b=a[d+"s"]({selected:!0}),j&&1===b.flatten().length?a[d](f).deselect():(b.deselect(),a[d](f).select())):"multi+shift"==e?b.shiftKey?
"cell"===d?t(a,f,c._select_lastCell||null):x(a,d,f,c._select_lastCell?c._select_lastCell[d]:null):a[d](f).select(!j):a[d](f).select(!j)}function q(b,a){return function(c){return c.i18n("buttons."+b,a)}}var g=e.fn.dataTable;g.select={};g.select.version="1.2.0";g.select.init=function(b){var a=b.settings()[0],c=a.oInit.select,d=g.defaults.select,c=c===h?d:c,d="row",f="api",m=!1,j=!0,u="td, th",i="selected";a._select={};if(!0===c)f="os";else if("string"===typeof c)f=c;else if(e.isPlainObject(c)&&(c.blurable!==
h&&(m=c.blurable),c.info!==h&&(j=c.info),c.items!==h&&(d=c.items),c.style!==h&&(f=c.style),c.selector!==h&&(u=c.selector),c.className!==h))i=c.className;b.select.selector(u);b.select.items(d);b.select.style(f);b.select.blurable(m);b.select.info(j);a._select.className=i;e.fn.dataTable.ext.order["select-checkbox"]=function(a,c){return this.api().column(c,{order:"index"}).nodes().map(function(c){return"row"===a._select.items?e(c).parent().hasClass(a._select.className):"cell"===a._select.items?e(c).hasClass(a._select.className):
!1})};e(b.table().node()).hasClass("selectable")&&b.select.style("os")};e.each([{type:"row",prop:"aoData"},{type:"column",prop:"aoColumns"}],function(b,a){g.ext.selector[a.type].push(function(c,b,f){var b=b.selected,e,j=[];if(b===h)return f;for(var g=0,i=f.length;g<i;g++)e=c[a.prop][f[g]],(!0===b&&!0===e._select_selected||!1===b&&!e._select_selected)&&j.push(f[g]);return j})});g.ext.selector.cell.push(function(b,a,c){var a=a.selected,d,f=[];if(a===h)return c;for(var e=0,g=c.length;e<g;e++)d=b.aoData[c[e].row],
(!0===a&&d._selected_cells&&!0===d._selected_cells[c[e].column]||!1===a&&(!d._selected_cells||!d._selected_cells[c[e].column]))&&f.push(c[e]);return f});var n=g.Api.register,o=g.Api.registerPlural;n("select()",function(){return this.iterator("table",function(b){g.select.init(new g.Api(b))})});n("select.blurable()",function(b){return b===h?this.context[0]._select.blurable:this.iterator("table",function(a){a._select.blurable=b})});n("select.info()",function(b){return w===h?this.context[0]._select.info:
this.iterator("table",function(a){a._select.info=b})});n("select.items()",function(b){return b===h?this.context[0]._select.items:this.iterator("table",function(a){a._select.items=b;k(new g.Api(a),"selectItems",[b])})});n("select.style()",function(b){return b===h?this.context[0]._select.style:this.iterator("table",function(a){a._select.style=b;if(!a._select_init){var c=new g.Api(a);a.aoRowCreatedCallback.push({fn:function(c,b,d){b=a.aoData[d];b._select_selected&&e(c).addClass(a._select.className);
c=0;for(d=a.aoColumns.length;c<d;c++)(a.aoColumns[c]._select_selected||b._selected_cells&&b._selected_cells[c])&&e(b.anCells[c]).addClass(a._select.className)},sName:"select-deferRender"});c.on("preXhr.dt.dtSelect",function(){var a=c.rows({selected:!0}).ids(!0).filter(function(c){return c!==h}),b=c.cells({selected:!0}).eq(0).map(function(a){var b=c.row(a.row).id(!0);return b?{row:b,column:a.column}:h}).filter(function(c){return c!==h});c.one("draw.dt.dtSelect",function(){c.rows(a).select();b.any()&&
b.each(function(a){c.cells(a.row,a.column).select()})})});c.on("draw.dtSelect.dt select.dtSelect.dt deselect.dtSelect.dt info.dt",function(){w(c)});c.on("destroy.dtSelect",function(){r(c);c.off(".dtSelect")})}var d=new g.Api(a);r(d);"api"!==b&&v(d);k(new g.Api(a),"selectStyle",[b])})});n("select.selector()",function(b){return b===h?this.context[0]._select.selector:this.iterator("table",function(a){r(new g.Api(a));a._select.selector=b;"api"!==a._select.style&&v(new g.Api(a))})});o("rows().select()",
"row().select()",function(b){var a=this;if(!1===b)return this.deselect();this.iterator("row",function(c,a){p(c);c.aoData[a]._select_selected=!0;e(c.aoData[a].nTr).addClass(c._select.className)});this.iterator("table",function(c,b){k(a,"select",["row",a[b]],!0)});return this});o("columns().select()","column().select()",function(b){var a=this;if(!1===b)return this.deselect();this.iterator("column",function(a,b){p(a);a.aoColumns[b]._select_selected=!0;var f=(new g.Api(a)).column(b);e(f.header()).addClass(a._select.className);
e(f.footer()).addClass(a._select.className);f.nodes().to$().addClass(a._select.className)});this.iterator("table",function(c,b){k(a,"select",["column",a[b]],!0)});return this});o("cells().select()","cell().select()",function(b){var a=this;if(!1===b)return this.deselect();this.iterator("cell",function(a,b,f){p(a);b=a.aoData[b];b._selected_cells===h&&(b._selected_cells=[]);b._selected_cells[f]=!0;b.anCells&&e(b.anCells[f]).addClass(a._select.className)});this.iterator("table",function(b,d){k(a,"select",
["cell",a[d]],!0)});return this});o("rows().deselect()","row().deselect()",function(){var b=this;this.iterator("row",function(a,b){a.aoData[b]._select_selected=!1;e(a.aoData[b].nTr).removeClass(a._select.className)});this.iterator("table",function(a,c){k(b,"deselect",["row",b[c]],!0)});return this});o("columns().deselect()","column().deselect()",function(){var b=this;this.iterator("column",function(a,b){a.aoColumns[b]._select_selected=!1;var d=new g.Api(a),f=d.column(b);e(f.header()).removeClass(a._select.className);
e(f.footer()).removeClass(a._select.className);d.cells(null,b).indexes().each(function(b){var c=a.aoData[b.row],d=c._selected_cells;c.anCells&&(!d||!d[b.column])&&e(c.anCells[b.column]).removeClass(a._select.className)})});this.iterator("table",function(a,c){k(b,"deselect",["column",b[c]],!0)});return this});o("cells().deselect()","cell().deselect()",function(){var b=this;this.iterator("cell",function(a,b,d){b=a.aoData[b];b._selected_cells[d]=!1;b.anCells&&!a.aoColumns[d]._select_selected&&e(b.anCells[d]).removeClass(a._select.className)});
this.iterator("table",function(a,c){k(b,"deselect",["cell",b[c]],!0)});return this});e.extend(g.ext.buttons,{selected:{text:q("selected","Selected"),className:"buttons-selected",init:function(b){var a=this;b.on("draw.dt.DT select.dt.DT deselect.dt.DT",function(){var b=a.rows({selected:!0}).any()||a.columns({selected:!0}).any()||a.cells({selected:!0}).any();a.enable(b)});this.disable()}},selectedSingle:{text:q("selectedSingle","Selected single"),className:"buttons-selected-single",init:function(b){var a=
this;b.on("draw.dt.DT select.dt.DT deselect.dt.DT",function(){var c=b.rows({selected:!0}).flatten().length+b.columns({selected:!0}).flatten().length+b.cells({selected:!0}).flatten().length;a.enable(1===c)});this.disable()}},selectAll:{text:q("selectAll","Select all"),className:"buttons-select-all",action:function(){this[this.select.items()+"s"]().select()}},selectNone:{text:q("selectNone","Deselect all"),className:"buttons-select-none",action:function(){p(this.settings()[0],!0)},init:function(b){var a=
this;b.on("draw.dt.DT select.dt.DT deselect.dt.DT",function(){var c=b.rows({selected:!0}).flatten().length+b.columns({selected:!0}).flatten().length+b.cells({selected:!0}).flatten().length;a.enable(0<c)});this.disable()}}});e.each(["Row","Column","Cell"],function(b,a){var c=a.toLowerCase();g.ext.buttons["select"+a+"s"]={text:q("select"+a+"s","Select "+c+"s"),className:"buttons-select-"+c+"s",action:function(){this.select.items(c)},init:function(a){var b=this;a.on("selectItems.dt.DT",function(a,d,
e){b.active(e===c)})}}});e(l).on("preInit.dt.dtSelect",function(b,a){"dt"===b.namespace&&g.select.init(new g.Api(a))});return g.select});

View File

@@ -0,0 +1,37 @@
/*!
Copyright 2015-2018 SpryMedia Ltd.
This source file is free software, available under the following license:
MIT license - http://datatables.net/license/mit
This source file is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
For details please refer to: http://www.datatables.net/extensions/select
Select for DataTables 1.3.0
2015-2018 SpryMedia Ltd - datatables.net/license/mit
*/
(function(f){"function"===typeof define&&define.amd?define(["jquery","datatables.net"],function(k){return f(k,window,document)}):"object"===typeof exports?module.exports=function(k,m){k||(k=window);m&&m.fn.dataTable||(m=require("datatables.net")(k,m).$);return f(m,k,k.document)}:f(jQuery,window,document)})(function(f,k,m,h){function z(a,b,c){var d=function(c,b){if(c>b){var d=b;b=c;c=d}var e=!1;return a.columns(":visible").indexes().filter(function(a){a===c&&(e=!0);return a===b?(e=!1,!0):e})};var e=
function(c,b){var d=a.rows({search:"applied"}).indexes();if(d.indexOf(c)>d.indexOf(b)){var e=b;b=c;c=e}var f=!1;return d.filter(function(a){a===c&&(f=!0);return a===b?(f=!1,!0):f})};a.cells({selected:!0}).any()||c?(d=d(c.column,b.column),c=e(c.row,b.row)):(d=d(0,b.column),c=e(0,b.row));c=a.cells(c,d).flatten();a.cells(b,{selected:!0}).any()?a.cells(c).deselect():a.cells(c).select()}function v(a){var b=a.settings()[0]._select.selector;f(a.table().container()).off("mousedown.dtSelect",b).off("mouseup.dtSelect",
b).off("click.dtSelect",b);f("body").off("click.dtSelect"+a.table().node().id)}function A(a){var b=f(a.table().container()),c=a.settings()[0],d=c._select.selector,e;b.on("mousedown.dtSelect",d,function(a){if(a.shiftKey||a.metaKey||a.ctrlKey)b.css("-moz-user-select","none").one("selectstart.dtSelect",d,function(){return!1});k.getSelection&&(e=k.getSelection())}).on("mouseup.dtSelect",d,function(){b.css("-moz-user-select","")}).on("click.dtSelect",d,function(c){var b=a.select.items();if(e){var d=k.getSelection();
if((!d.anchorNode||f(d.anchorNode).closest("table")[0]===a.table().node())&&d!==e)return}d=a.settings()[0];var l=f.trim(a.settings()[0].oClasses.sWrapper).replace(/ +/g,".");if(f(c.target).closest("div."+l)[0]==a.table().container()&&(l=a.cell(f(c.target).closest("td, th")),l.any())){var g=f.Event("user-select.dt");n(a,g,[b,l,c]);g.isDefaultPrevented()||(g=l.index(),"row"===b?(b=g.row,w(c,a,d,"row",b)):"column"===b?(b=l.index().column,w(c,a,d,"column",b)):"cell"===b&&(b=l.index(),w(c,a,d,"cell",b)),
d._select_lastCell=g)}});f("body").on("click.dtSelect"+a.table().node().id,function(b){!c._select.blurable||f(b.target).parents().filter(a.table().container()).length||0===f(b.target).parents("html").length||f(b.target).parents("div.DTE").length||r(c,!0)})}function n(a,b,c,d){if(!d||a.flatten().length)"string"===typeof b&&(b+=".dt"),c.unshift(a),f(a.table().node()).trigger(b,c)}function B(a){var b=a.settings()[0];if(b._select.info&&b.aanFeatures.i&&"api"!==a.select.style()){var c=a.rows({selected:!0}).flatten().length,
d=a.columns({selected:!0}).flatten().length,e=a.cells({selected:!0}).flatten().length,l=function(b,c,d){b.append(f('<span class="select-item"/>').append(a.i18n("select."+c+"s",{_:"%d "+c+"s selected",0:"",1:"1 "+c+" selected"},d)))};f.each(b.aanFeatures.i,function(b,a){a=f(a);b=f('<span class="select-info"/>');l(b,"row",c);l(b,"column",d);l(b,"cell",e);var g=a.children("span.select-info");g.length&&g.remove();""!==b.text()&&a.append(b)})}}function D(a){var b=new g.Api(a);a.aoRowCreatedCallback.push({fn:function(b,
d,e){d=a.aoData[e];d._select_selected&&f(b).addClass(a._select.className);b=0;for(e=a.aoColumns.length;b<e;b++)(a.aoColumns[b]._select_selected||d._selected_cells&&d._selected_cells[b])&&f(d.anCells[b]).addClass(a._select.className)},sName:"select-deferRender"});b.on("preXhr.dt.dtSelect",function(){var a=b.rows({selected:!0}).ids(!0).filter(function(b){return b!==h}),d=b.cells({selected:!0}).eq(0).map(function(a){var c=b.row(a.row).id(!0);return c?{row:c,column:a.column}:h}).filter(function(b){return b!==
h});b.one("draw.dt.dtSelect",function(){b.rows(a).select();d.any()&&d.each(function(a){b.cells(a.row,a.column).select()})})});b.on("draw.dtSelect.dt select.dtSelect.dt deselect.dtSelect.dt info.dt",function(){B(b)});b.on("destroy.dtSelect",function(){v(b);b.off(".dtSelect")})}function C(a,b,c,d){var e=a[b+"s"]({search:"applied"}).indexes();d=f.inArray(d,e);var g=f.inArray(c,e);if(a[b+"s"]({selected:!0}).any()||-1!==d){if(d>g){var u=g;g=d;d=u}e.splice(g+1,e.length);e.splice(0,d)}else e.splice(f.inArray(c,
e)+1,e.length);a[b](c,{selected:!0}).any()?(e.splice(f.inArray(c,e),1),a[b+"s"](e).deselect()):a[b+"s"](e).select()}function r(a,b){if(b||"single"===a._select.style)a=new g.Api(a),a.rows({selected:!0}).deselect(),a.columns({selected:!0}).deselect(),a.cells({selected:!0}).deselect()}function w(a,b,c,d,e){var f=b.select.style(),g=b[d](e,{selected:!0}).any();"os"===f?a.ctrlKey||a.metaKey?b[d](e).select(!g):a.shiftKey?"cell"===d?z(b,e,c._select_lastCell||null):C(b,d,e,c._select_lastCell?c._select_lastCell[d]:
null):(a=b[d+"s"]({selected:!0}),g&&1===a.flatten().length?b[d](e).deselect():(a.deselect(),b[d](e).select())):"multi+shift"==f?a.shiftKey?"cell"===d?z(b,e,c._select_lastCell||null):C(b,d,e,c._select_lastCell?c._select_lastCell[d]:null):b[d](e).select(!g):b[d](e).select(!g)}function t(a,b){return function(c){return c.i18n("buttons."+a,b)}}function x(a){a=a._eventNamespace;return"draw.dt.DT"+a+" select.dt.DT"+a+" deselect.dt.DT"+a}function E(a,b){return-1!==f.inArray("rows",b.limitTo)&&a.rows({selected:!0}).any()||
-1!==f.inArray("columns",b.limitTo)&&a.columns({selected:!0}).any()||-1!==f.inArray("cells",b.limitTo)&&a.cells({selected:!0}).any()?!0:!1}var g=f.fn.dataTable;g.select={};g.select.version="1.3.0";g.select.init=function(a){var b=a.settings()[0],c=b.oInit.select,d=g.defaults.select;c=c===h?d:c;d="row";var e="api",l=!1,u=!0,k="td, th",n="selected",m=!1;b._select={};!0===c?(e="os",m=!0):"string"===typeof c?(e=c,m=!0):f.isPlainObject(c)&&(c.blurable!==h&&(l=c.blurable),c.info!==h&&(u=c.info),c.items!==
h&&(d=c.items),e=c.style!==h?c.style:"os",m=!0,c.selector!==h&&(k=c.selector),c.className!==h&&(n=c.className));a.select.selector(k);a.select.items(d);a.select.style(e);a.select.blurable(l);a.select.info(u);b._select.className=n;f.fn.dataTable.ext.order["select-checkbox"]=function(b,a){return this.api().column(a,{order:"index"}).nodes().map(function(a){return"row"===b._select.items?f(a).parent().hasClass(b._select.className):"cell"===b._select.items?f(a).hasClass(b._select.className):!1})};!m&&f(a.table().node()).hasClass("selectable")&&
a.select.style("os")};f.each([{type:"row",prop:"aoData"},{type:"column",prop:"aoColumns"}],function(a,b){g.ext.selector[b.type].push(function(a,d,e){d=d.selected;var c=[];if(!0!==d&&!1!==d)return e;for(var f=0,g=e.length;f<g;f++){var h=a[b.prop][e[f]];(!0===d&&!0===h._select_selected||!1===d&&!h._select_selected)&&c.push(e[f])}return c})});g.ext.selector.cell.push(function(a,b,c){b=b.selected;var d=[];if(b===h)return c;for(var e=0,f=c.length;e<f;e++){var g=a.aoData[c[e].row];(!0===b&&g._selected_cells&&
!0===g._selected_cells[c[e].column]||!(!1!==b||g._selected_cells&&g._selected_cells[c[e].column]))&&d.push(c[e])}return d});var p=g.Api.register,q=g.Api.registerPlural;p("select()",function(){return this.iterator("table",function(a){g.select.init(new g.Api(a))})});p("select.blurable()",function(a){return a===h?this.context[0]._select.blurable:this.iterator("table",function(b){b._select.blurable=a})});p("select.info()",function(a){return B===h?this.context[0]._select.info:this.iterator("table",function(b){b._select.info=
a})});p("select.items()",function(a){return a===h?this.context[0]._select.items:this.iterator("table",function(b){b._select.items=a;n(new g.Api(b),"selectItems",[a])})});p("select.style()",function(a){return a===h?this.context[0]._select.style:this.iterator("table",function(b){b._select.style=a;b._select_init||D(b);var c=new g.Api(b);v(c);"api"!==a&&A(c);n(new g.Api(b),"selectStyle",[a])})});p("select.selector()",function(a){return a===h?this.context[0]._select.selector:this.iterator("table",function(b){v(new g.Api(b));
b._select.selector=a;"api"!==b._select.style&&A(new g.Api(b))})});q("rows().select()","row().select()",function(a){var b=this;if(!1===a)return this.deselect();this.iterator("row",function(b,a){r(b);b.aoData[a]._select_selected=!0;f(b.aoData[a].nTr).addClass(b._select.className)});this.iterator("table",function(a,d){n(b,"select",["row",b[d]],!0)});return this});q("columns().select()","column().select()",function(a){var b=this;if(!1===a)return this.deselect();this.iterator("column",function(b,a){r(b);
b.aoColumns[a]._select_selected=!0;a=(new g.Api(b)).column(a);f(a.header()).addClass(b._select.className);f(a.footer()).addClass(b._select.className);a.nodes().to$().addClass(b._select.className)});this.iterator("table",function(a,d){n(b,"select",["column",b[d]],!0)});return this});q("cells().select()","cell().select()",function(a){var b=this;if(!1===a)return this.deselect();this.iterator("cell",function(b,a,e){r(b);a=b.aoData[a];a._selected_cells===h&&(a._selected_cells=[]);a._selected_cells[e]=
!0;a.anCells&&f(a.anCells[e]).addClass(b._select.className)});this.iterator("table",function(a,d){n(b,"select",["cell",b[d]],!0)});return this});q("rows().deselect()","row().deselect()",function(){var a=this;this.iterator("row",function(b,a){b.aoData[a]._select_selected=!1;f(b.aoData[a].nTr).removeClass(b._select.className)});this.iterator("table",function(b,c){n(a,"deselect",["row",a[c]],!0)});return this});q("columns().deselect()","column().deselect()",function(){var a=this;this.iterator("column",
function(a,c){a.aoColumns[c]._select_selected=!1;var b=new g.Api(a),e=b.column(c);f(e.header()).removeClass(a._select.className);f(e.footer()).removeClass(a._select.className);b.cells(null,c).indexes().each(function(b){var c=a.aoData[b.row],d=c._selected_cells;!c.anCells||d&&d[b.column]||f(c.anCells[b.column]).removeClass(a._select.className)})});this.iterator("table",function(b,c){n(a,"deselect",["column",a[c]],!0)});return this});q("cells().deselect()","cell().deselect()",function(){var a=this;
this.iterator("cell",function(a,c,d){c=a.aoData[c];c._selected_cells[d]=!1;c.anCells&&!a.aoColumns[d]._select_selected&&f(c.anCells[d]).removeClass(a._select.className)});this.iterator("table",function(b,c){n(a,"deselect",["cell",a[c]],!0)});return this});var y=0;f.extend(g.ext.buttons,{selected:{text:t("selected","Selected"),className:"buttons-selected",limitTo:["rows","columns","cells"],init:function(a,b,c){var d=this;c._eventNamespace=".select"+y++;a.on(x(c),function(){d.enable(E(a,c))});this.disable()},
destroy:function(a,b,c){a.off(c._eventNamespace)}},selectedSingle:{text:t("selectedSingle","Selected single"),className:"buttons-selected-single",init:function(a,b,c){var d=this;c._eventNamespace=".select"+y++;a.on(x(c),function(){var b=a.rows({selected:!0}).flatten().length+a.columns({selected:!0}).flatten().length+a.cells({selected:!0}).flatten().length;d.enable(1===b)});this.disable()},destroy:function(a,b,c){a.off(c._eventNamespace)}},selectAll:{text:t("selectAll","Select all"),className:"buttons-select-all",
action:function(){this[this.select.items()+"s"]().select()}},selectNone:{text:t("selectNone","Deselect all"),className:"buttons-select-none",action:function(){r(this.settings()[0],!0)},init:function(a,b,c){var d=this;c._eventNamespace=".select"+y++;a.on(x(c),function(){var b=a.rows({selected:!0}).flatten().length+a.columns({selected:!0}).flatten().length+a.cells({selected:!0}).flatten().length;d.enable(0<b)});this.disable()},destroy:function(a,b,c){a.off(c._eventNamespace)}}});f.each(["Row","Column",
"Cell"],function(a,b){var c=b.toLowerCase();g.ext.buttons["select"+b+"s"]={text:t("select"+b+"s","Select "+c+"s"),className:"buttons-select-"+c+"s",action:function(){this.select.items(c)},init:function(a){var b=this;a.on("selectItems.dt.DT",function(a,d,e){b.active(e===c)})}}});f(m).on("preInit.dt.dtSelect",function(a,b){"dt"===a.namespace&&g.select.init(new g.Api(b))});return g.select});

File diff suppressed because it is too large Load Diff

View File

@@ -1,350 +0,0 @@
;(function() {
var root = this;
var Farahey;
if (typeof exports !== 'undefined') {
Farahey = exports;
} else {
Farahey = root.Farahey = {};
}
var findInsertionPoint = function(sortedArr, val, comparator) {
var low = 0, high = sortedArr.length;
var mid = -1, c = 0;
while(low < high) {
mid = parseInt((low + high)/2);
c = comparator(sortedArr[mid], val);
if(c < 0) {
low = mid + 1;
}else if(c > 0) {
high = mid;
}else {
return mid;
}
}
return low;
},
geomSupport = typeof jsPlumbGeom !== "undefined" ? jsPlumbGeom : Biltong,
insertSorted = function(array, value, comparator) {
var ip = findInsertionPoint(array, value, comparator);
array.splice(ip, 0, value);
},
distanceFromOriginComparator = function(r1, r2, origin) {
var d1 = geomSupport.lineLength(origin, [ r1.x + (r1.w / 2), r1.y + (r1.h / 2)]),
d2 = geomSupport.lineLength(origin, [ r2.x + (r2.w / 2), r2.y + (r2.h / 2)]);
return d1 < d2 ? -1 : d1 == d2 ? 0 : 1;
},
EntryComparator = function(origin, getSize) {
var _origin = origin,
_cache = {},
_get = function(entry) {
if (!_cache[entry[1]]) {
var s = getSize(entry[2]);
_cache[entry[1]] = {
l:entry[0][0],
t:entry[0][1],
w:s[0],
h:s[1],
center:[entry[0][0] + (s[0] / 2), entry[0][1] + (s[1] / 2) ]
};
}
return _cache[entry[1]];
}
this.setOrigin = function(o) {
_origin = o;
_cache = {};
};
this.compare = function(e1, e2) {
var d1 = geomSupport.lineLength(_origin, _get(e1).center),
d2 = geomSupport.lineLength(_origin, _get(e2).center);
return d1 < d2 ? -1 : d1 == d2 ? 0 : 1;
};
};
var _isOnEdge = function(r, axis, dim, v) { return (r[axis] <= v && v <= r[axis] + r[dim]); },
_xAdj = [ function(r1, r2) { return r1.x + r1.w - r2.x; }, function(r1, r2) { return r1.x - (r2.x + r2.w); } ],
_yAdj = [ function(r1, r2) { return r1.y + r1.h - r2.y; }, function(r1, r2) { return r1.y - (r2.y + r2.h); } ],
_adj = [ null, [ _xAdj[0], _yAdj[1] ], [ _xAdj[0], _yAdj[0] ], [ _xAdj[1], _yAdj[0] ], [ _xAdj[1], _yAdj[1] ] ],
_genAdj = function(r1, r2, m, b, s) {
if (isNaN(m)) m = 0;
var y = r2.y + r2.h,
x = (m == Infinity || m == -Infinity) ? r2.x + (r2.w / 2) : (y - b) / m,
theta = Math.atan(m);
if (_isOnEdge(r2, "x", "w", x)) {
var rise = _adj[s][1](r1, r2),
hyp = rise / Math.sin(theta),
run = hyp * Math.cos(theta);
return { left:run, top:rise };
}
else {
var run = _adj[s][0](r1, r2),
hyp = run / Math.cos(theta),
rise = hyp * Math.sin(theta);
return { left:run, top:rise };
}
},
/*
* Calculates how far to move r2 from r1 so that it no longer overlaps.
* if origin is supplied, then it means we want r2 to move along a vector joining r2's center to that point.
* otherwise we want it to move along a vector joining the two rectangle centers.
*/
_calculateSpacingAdjustment = Farahey.calculateSpacingAdjustment = function(r1, r2) {
var c1 = r1.center || [ r1.x + (r1.w / 2), r1.y + (r1.h / 2) ],
c2 = r2.center || [ r2.x + (r2.w / 2), r2.y + (r2.h / 2) ],
m = geomSupport.gradient(c1, c2),
s = geomSupport.quadrant(c1, c2),
b = (m == Infinity || m == -Infinity || isNaN(m)) ? 0 : c1[1] - (m * c1[0]);
return _genAdj(r1, r2, m, b, s);
},
// calculate a padded rectangle for the given element with offset & size, and desired padding.
_paddedRectangle = Farahey.paddedRectangle = function(o, s, p) {
return { x:o[0] - p[0], y: o[1] - p[1], w:s[0] + (2 * p[0]), h:s[1] + (2 * p[1]) };
},
_magnetize = function(positionArray, positions, sizes, padding,
constrain, origin, filter,
updateOnStep, stepInterval, stepCallback)
{
origin = origin || [0,0];
stepCallback = stepCallback || function() { };
var focus = _paddedRectangle(origin, [1,1], padding),
iterations = 100, iteration = 1, uncleanRun = true, adjustBy, constrainedAdjustment,
_movedElements = {},
_move = function(id, o, x, y) {
_movedElements[id] = true;
o[0] += x;
o[1] += y;
},
step = function() {
for (var i = 0; i < positionArray.length; i++) {
var o1 = positions[positionArray[i][1]],
oid = positionArray[i][1],
a1 = positionArray[i][2], // angle to node from magnet origin
s1 = sizes[positionArray[i][1]],
// create a rectangle for first element: this encompasses the element and padding on each
//side
r1 = _paddedRectangle(o1, s1, padding);
if (filter(positionArray[i][1]) && geomSupport.intersects(focus, r1)) {
adjustBy = _calculateSpacingAdjustment(focus, r1);
constrainedAdjustment = constrain(positionArray[i][1], o1, adjustBy);
_move(oid, o1, constrainedAdjustment.left, constrainedAdjustment.top);
}
// now move others to account for this one, if necessary.
// reset rectangle for node
r1 = _paddedRectangle(o1, s1, padding);
for (var j = 0; j < positionArray.length; j++) {
if (i != j) {
var o2 = positions[positionArray[j][1]],
a2 = positionArray[j][2], // angle to node from magnet origin
s2 = sizes[positionArray[j][1]],
// create a rectangle for the second element, again by putting padding of the desired
// amount around the bounds of the element.
r2 = _paddedRectangle(o2, s2, padding);
// if the two rectangles intersect then figure out how much to move the second one by.
if (geomSupport.intersects(r1, r2)) {
// TODO in 0.3, instead of moving neither, the other node should move.
if (filter(positionArray[j][1])) {
uncleanRun = true;
adjustBy = _calculateSpacingAdjustment(r1, r2),
constrainedAdjustment = constrain(positionArray[j][1], o2, adjustBy);
_move(positionArray[j][1], o2, constrainedAdjustment.left, constrainedAdjustment.top);
}
}
}
}
}
if (updateOnStep)
stepCallback();
if (uncleanRun && iteration < iterations) {
uncleanRun = false;
iteration++;
if (updateOnStep) {
window.setTimeout(step, stepInterval);
}
else
step();
}
};
step();
return _movedElements;
};
/**
* @name Magnetizer
* @classdesc Applies repulsive magnetism to a set of elements relative to a given point, with a specified
* amount of padding around the point.
*/
/**
* @name Magnetizer#constructor
* @function
* @param {Selector|Element} [container] Element that contains the elements to magnetize. Only required if you intend to use the `executeAtEvent` method.
* @param {Function} [getContainerPosition] Function that returns the position of the container (as an object of the form `{left:.., top:..}`) when requested. Only required if you intend to use the `executeAtEvent` method.
* @param {Function} getPosition A function that takes an element id and returns its position. It does not matter to which element this position is computed as long as you remain consistent with this method, `setPosition` and the `origin` property.
* @param {Function} setPosition A function that takes an element id and position, and sets it. See note about offset parent above.
* @param {Function} getSize A function that takes an element id and returns its size, in pixels.
* @param {Integer[]} [padding] Optional padding for x and y directions. Defaults to 20 pixels in each direction.
* @param {Function} [constrain] Optional function that takes an id and a proposed amount of movement in each axis, and returns the allowed amount of movement in each axis. You can use this to constrain your elements to a grid, for instance, or a path, etc.
* @param {Integer[]} [origin] The origin of magnetization, in pixels. Defaults to 0,0. You can also supply this to the `execute` call.
* @param {Selector|String[]|Element[]} elements List of elements on which to operate.
* @param {Boolean} [executeNow=false] Whether or not to execute the routine immediately.
* @param {Function} [filter] Optional function that takes an element id and returns whether or not that element can be moved.
* @param {Boolean} [orderByDistanceFromOrigin=false] Whether or not to sort elements first by distance from origin. Can have better results but takes more time.
*/
root.Magnetizer = function(params) {
var getPosition = params.getPosition,
getSize = params.getSize,
getId = params.getId,
setPosition = params.setPosition,
padding = params.padding || [20, 20],
// expects a { left:.., top:... } object. returns how far it can actually go.
constrain = params.constrain || function(id, current, delta) { return delta; },
positionArray = [],
positions = {},
sizes = {},
elements = params.elements || [],
origin = params.origin || [0,0],
executeNow = params.executeNow,
minx, miny, maxx, maxy,
getOrigin = this.getOrigin = function() { return origin; },
filter = params.filter || function(_) { return true; },
orderByDistanceFromOrigin = params.orderByDistanceFromOrigin,
comparator = new EntryComparator(origin, getSize),
updateOnStep = params.updateOnStep,
stepInterval = params.stepInterval || 350,
originDebugMarker,
debug = params.debug,
createOriginDebugger = function() {
var d = document.createElement("div");
d.style.position = "absolute";
d.style.width = "10px";
d.style.height = "10px";
d.style.backgroundColor = "red";
document.body.appendChild(d);
originDebugMarker = d;
},
_addToPositionArray = function(p) {
if (!orderByDistanceFromOrigin || positionArray.length == 0)
positionArray.push(p);
else {
insertSorted(positionArray, p, comparator.compare);
}
},
_updatePositions = function() {
comparator.setOrigin(origin);
positionArray = []; positions = {}; sizes = {};
minx = miny = Infinity;
maxx = maxy = -Infinity;
for (var i = 0; i < elements.length; i++) {
var p = getPosition(elements[i]),
s = getSize(elements[i]),
id = getId(elements[i]);
positions[id] = [p.left, p.top];
_addToPositionArray([ [p.left, p.top], id, elements[i]]);
sizes[id] = s;
minx = Math.min(minx, p.left);
miny = Math.min(miny, p.top);
maxx = Math.max(maxx, p.left + s[0]);
maxy = Math.max(maxy, p.top + s[1]);
}
},
_run = function() {
if (elements.length > 1) {
var _movedElements = _magnetize(positionArray, positions, sizes, padding, constrain, origin, filter, updateOnStep, stepInterval, _positionElements);
_positionElements(_movedElements);
}
},
_positionElements = function(_movedElements) {
for (var i = 0; i < elements.length; i++) {
var id = getId(elements[i]);
if (_movedElements[id])
setPosition(elements[i], { left:positions[id][0], top:positions[id][1] });
}
},
setOrigin = function(o) {
if (o != null) {
origin = o;
comparator.setOrigin(o);
}
};
/**
* @name Magnetizer#execute
* @function
* @desc Runs the magnetize routine.
* @param {Integer[]} [o] Optional origin to use. You may have set this in the constructor and do not wish to supply it, or you may be happy with the default of [0,0].
*/
this.execute = function(o) {
setOrigin(o);
_updatePositions();
_run();
};
/**
* @name Magnetizer#executeAtCenter
* @function
* @desc Computes the center of all the nodes and then uses that as the magnetization origin when it runs the routine.
*/
this.executeAtCenter = function() {
_updatePositions();
setOrigin([
(minx + maxx) / 2,
(miny + maxy) / 2
]);
_run();
};
/**
* @name Magnetizer#executeAtEvent
* @function
* @desc Runs the magnetize routine using the location of the given event as the origin. To use this
* method you need to have provided a `container`, and a `getContainerPosition` function to the
* constructor.
* @param {Event} e Event to get origin location from.
*/
this.executeAtEvent = function(e) {
var c = params.container,
o = params.getContainerPosition(c),
x = e.pageX - o.left + c[0].scrollLeft,
y = e.pageY - o.top + c[0].scrollTop;
if (debug) {
originDebugMarker.style.left = e.pageX + "px";
originDebugMarker.style.top = e.pageY + "px";
}
this.execute([x,y]);
};
/**
* @name Magnetize#setElements
* @function
* @desc Sets the current list of elements.
* @param {Object[]} _els List of elements, in whatever format the magnetizer is setup to use.
*/
this.setElements = function(_els) {
elements = _els;
};
if (debug)
createOriginDebugger();
if (executeNow) this.execute();
};
}).call(this);

518
js/lib/farahey.js Normal file
View File

@@ -0,0 +1,518 @@
;(function() {
"use strict";
var root = this;
var Farahey = root.Farahey = {};
if (typeof exports !== 'undefined') {
exports.Farahey = Farahey;
}
var findInsertionPoint = function(sortedArr, val, comparator) {
var low = 0, high = sortedArr.length;
var mid = -1, c = 0;
while(low < high) {
mid = parseInt((low + high)/2);
c = comparator(sortedArr[mid], val);
if(c < 0) {
low = mid + 1;
}else if(c > 0) {
high = mid;
}else {
return mid;
}
}
return low;
},
geomSupport = root.Biltong,
insertSorted = function(array, value, comparator) {
var ip = findInsertionPoint(array, value, comparator);
array.splice(ip, 0, value);
},
EntryComparator = function(origin, getSize) {
var _origin = origin,
_cache = {},
_get = function(entry) {
if (!_cache[entry[1]]) {
var s = getSize(entry[2]);
_cache[entry[1]] = {
l:entry[0][0],
t:entry[0][1],
w:s[0],
h:s[1],
center:[entry[0][0] + (s[0] / 2), entry[0][1] + (s[1] / 2) ]
};
}
return _cache[entry[1]];
};
this.setOrigin = function(o) {
_origin = o;
_cache = {};
};
this.compare = function(e1, e2) {
var d1 = geomSupport.lineLength(_origin, _get(e1).center),
d2 = geomSupport.lineLength(_origin, _get(e2).center);
return d1 < d2 ? -1 : d1 == d2 ? 0 : 1;
};
};
var _isOnEdge = function(r, axis, dim, v) { return (r[axis] <= v && v <= r[axis] + r[dim]); },
_xAdj = [ function(r1, r2) { return r1.x + r1.w - r2.x; }, function(r1, r2) { return r1.x - (r2.x + r2.w); } ],
_yAdj = [ function(r1, r2) { return r1.y + r1.h - r2.y; }, function(r1, r2) { return r1.y - (r2.y + r2.h); } ],
_adj = [ null, [ _xAdj[0], _yAdj[1] ], [ _xAdj[0], _yAdj[0] ], [ _xAdj[1], _yAdj[0] ], [ _xAdj[1], _yAdj[1] ] ],
_genAdj = function(r1, r2, m, b, s) {
if (isNaN(m)) m = 0;
var y = r2.y + r2.h,
x = (m == Infinity || m == -Infinity) ? r2.x + (r2.w / 2) : (y - b) / m,
theta = Math.atan(m),
rise, hyp, run;
if (_isOnEdge(r2, "x", "w", x)) {
rise = _adj[s][1](r1, r2);
hyp = rise / Math.sin(theta);
run = hyp * Math.cos(theta);
return { left:run, top:rise };
}
else {
run = _adj[s][0](r1, r2);
hyp = run / Math.cos(theta);
rise = hyp * Math.sin(theta);
return { left:run, top:rise };
}
},
/*
* Calculates how far to move r2 from r1 so that it no longer overlaps.
* if origin is supplied, then it means we want r2 to move along a vector joining r2's center to that point.
* otherwise we want it to move along a vector joining the two rectangle centers.
*/
_calculateSpacingAdjustment = Farahey.calculateSpacingAdjustment = function(r1, r2) {
var c1 = r1.center || [ r1.x + (r1.w / 2), r1.y + (r1.h / 2) ],
c2 = r2.center || [ r2.x + (r2.w / 2), r2.y + (r2.h / 2) ],
m = geomSupport.gradient(c1, c2),
s = geomSupport.quadrant(c1, c2),
b = (m == Infinity || m == -Infinity || isNaN(m)) ? 0 : c1[1] - (m * c1[0]);
return _genAdj(r1, r2, m, b, s);
},
// calculate a padded rectangle for the given element with offset & size, and desired padding.
_paddedRectangle = Farahey.paddedRectangle = function(o, s, p) {
return { x:o[0] - p[0], y: o[1] - p[1], w:s[0] + (2 * p[0]), h:s[1] + (2 * p[1]) };
},
_magnetize = function(positionArray, positions, sizes, padding,
constrain, origin, filter,
updateOnStep, stepInterval, stepCallback, iterations,
exclude, excludeFocus)
{
origin = origin || [0,0];
stepCallback = stepCallback || function() { };
iterations = iterations || 2;
var focus = _paddedRectangle(origin, [1,1], padding),
iteration = 1, uncleanRun = true, adjustBy, constrainedAdjustment,
_movedElements = {},
_move = function(id, o, x, y) {
_movedElements[id] = true;
o[0] += x;
o[1] += y;
},
step = function() {
for (var i = 0; i < positionArray.length; i++) {
if (exclude(positionArray[i][1], positionArray[i][2])) {
continue;
}
var o1 = positions[positionArray[i][1]],
oid = positionArray[i][1],
a1 = positionArray[i][2], // angle to node from magnet origin
s1 = sizes[positionArray[i][1]],
// create a rectangle for first element: this encompasses the element and padding on each
//side
r1 = _paddedRectangle(o1, s1, padding);
if (!excludeFocus && filter(positionArray[i][1], positionArray[i][2]) && geomSupport.intersects(focus, r1)) {
adjustBy = _calculateSpacingAdjustment(focus, r1);
constrainedAdjustment = constrain(positionArray[i][1], o1, adjustBy);
_move(oid, o1, constrainedAdjustment.left, constrainedAdjustment.top);
}
// now move others to account for this one, if necessary.
// reset rectangle for node
r1 = _paddedRectangle(o1, s1, padding);
for (var j = 0; j < positionArray.length; j++) {
if (i != j) {
if (exclude(positionArray[j][1], positionArray[j][2])) {
continue;
}
if (filter(positionArray[j][1], positionArray[j][2])) {
var o2 = positions[positionArray[j][1]],
s2 = sizes[positionArray[j][1]],
// create a rectangle for the second element, again by putting padding of the desired
// amount around the bounds of the element.
r2 = _paddedRectangle(o2, s2, padding);
// if the two rectangles intersect then figure out how much to move the second one by.
if (geomSupport.intersects(r1, r2)) {
// TODO (?), instead of moving neither, the other node should move.
uncleanRun = true;
adjustBy = _calculateSpacingAdjustment(r1, r2);
constrainedAdjustment = constrain(positionArray[j][1], o2, adjustBy);
_move(positionArray[j][1], o2, constrainedAdjustment.left, constrainedAdjustment.top);
}
}
}
}
}
if (updateOnStep)
stepCallback();
if (uncleanRun && iteration < iterations) {
uncleanRun = false;
iteration++;
if (updateOnStep) {
window.setTimeout(step, stepInterval);
}
else
step();
}
};
step();
return _movedElements;
};
var _convertElements = function(l) {
if (l == null) return null;
else if (Object.prototype.toString.call(l) === "[object Array]") {
var a = [];
a.push.apply(a, l);
return a;
}
else {
var o = [];
for (var i in l) o.push(l[i]);
}
return o;
};
/**
* Applies repulsive magnetism to a set of elements relative to a given point, with a specified
* amount of padding around the point.
* @class FaraheyInstance
* @constructor
* @param {Object} params Constructor parameters.
* @param {Selector|Element} [params.container] Element that contains the elements to magnetize. Only required if you intend to use the `executeAtEvent` method.
* @param {Function} [params.getContainerPosition] Function that returns the position of the container (as an object of the form `{left:.., top:..}`) when requested. Only required if you intend to use the `executeAtEvent` method.
* @param {Function} params.getPosition A function that takes an element and returns its position. It does not matter to which element this position is computed as long as you remain consistent with this method, `setPosition` and the `origin` property.
* @param {Function} params.setPosition A function that takes an element and position, and sets it. See note about offset parent above.
* @param {Function} params.getSize A function that takes an element and returns its size, in pixels.
* @param {Number[]} [params.padding] Optional padding for x and y directions. Defaults to 20 pixels in each direction.
* @param {Function} [params.constrain] Optional function that takes an id and a proposed amount of movement in each axis, and returns the allowed amount of movement in each axis. You can use this to constrain your elements to a grid, for instance, or a path, etc.
* @param {Number[]} [params.origin] The origin of magnetization, in pixels. Defaults to 0,0. You can also supply this to the `execute` call.
* @param {Selector|String[]|Element[]} params.elements List, or object hash, of elements on which to operate.
* @param {Boolean} [params.executeNow=false] Whether or not to execute the routine immediately.
* @param {Function} [params.filter] Optional function that takes an element id and returns whether or not that element can be moved.
* @param {Boolean} [params.orderByDistanceFromOrigin=false] Whether or not to sort elements first by distance from origin. Can have better results but takes more time.
*/
var FaraheyInstance = function(params) {
var getPosition = params.getPosition,
getSize = params.getSize,
getId = params.getId,
setPosition = params.setPosition,
padding = params.padding || [20, 20],
// expects a { left:.., top:... } object. returns how far it can actually go.
constrain = params.constrain || function(id, current, delta) { return delta; },
positionArray = [],
positions = {},
sizes = {},
elements = _convertElements(params.elements || []),
origin = params.origin || [0,0],
executeNow = params.executeNow,
//minx, miny, maxx, maxy,
getOrigin = this.getOrigin = function() { return origin; },
filter = params.filter || function(_) { return true; },
exclude = params.exclude || function(_) { return false;},
orderByDistanceFromOrigin = params.orderByDistanceFromOrigin,
comparator = new EntryComparator(origin, getSize),
updateOnStep = params.updateOnStep,
stepInterval = params.stepInterval || 350,
originDebugMarker,
debug = params.debug,
createOriginDebugger = function() {
var d = document.createElement("div");
d.style.position = "absolute";
d.style.width = "10px";
d.style.height = "10px";
d.style.backgroundColor = "red";
document.body.appendChild(d);
originDebugMarker = d;
},
_addToPositionArray = function(p) {
if (!orderByDistanceFromOrigin || positionArray.length == 0)
positionArray.push(p);
else {
insertSorted(positionArray, p, comparator.compare);
}
},
_computeExtents = function(els) {
var minx, miny, maxx, maxy;
minx = miny = Infinity;
maxx = maxy = -Infinity;
for (var i = 0; i < els.length; i++) {
var p = getPosition(els[i]),
s = getSize(els[i]),
id = getId(els[i]);
positions[id] = [p.left, p.top];
_addToPositionArray([ [p.left, p.top], id, els[i]]);
sizes[id] = s;
minx = Math.min(minx, p.left);
miny = Math.min(miny, p.top);
maxx = Math.max(maxx, p.left + s[0]);
maxy = Math.max(maxy, p.top + s[1]);
}
return [ minx, maxx, miny, maxy ];
},
_updatePositions = function() {
comparator.setOrigin(origin);
positionArray = []; positions = {}; sizes = {};
return _computeExtents(elements);
},
_run = function(options) {
if (elements.length > 1) {
options = options || {};
var f = options.filter || filter;
var p = options.padding || padding;
var i = options.iterations;
var e = options.exclude || exclude;
var ef = options.excludeFocus;
var _movedElements = _magnetize(positionArray, positions, sizes, p, constrain, origin, f, updateOnStep, stepInterval, _positionElements, i, e, ef);
_positionElements(_movedElements);
}
},
_positionElements = function(_movedElements) {
for (var i = 0; i < elements.length; i++) {
var id = getId(elements[i]);
if (_movedElements[id])
setPosition(elements[i], { left:positions[id][0], top:positions[id][1] });
}
},
setOrigin = function(o) {
if (o != null) {
origin = o;
comparator.setOrigin(o);
}
};
/**
* Runs the magnetize routine.
* @method execute
* @param {Number[]} [o] Optional origin to use. You may have set this in the constructor and do not wish to supply it, or you may be happy with the default of [0,0].
* @param {Function} [options] Options to override defaults.
* @param {Function} [options.filter] Optional function to indicate whether a given element may be moved or not. Returning boolean false indicates it may not.
* @param {Number[]} [options.padding] Optional [x,y] padding values for elements.
* @param {Number} [options.iterations] Optional max number of iterations to run. The greater this number, the more comprehensive the magnetisation,
* but the slower it runs. The default is 2.
* @param {Function} [options.exclude] Optional function to return whether or not a given element should be completely excluded from the magnetisation: it neither
* moves, nor has any bearing on the movement of other elements.
* @param {Boolean} [options.excludeFocus=false] If true, do not pad any elements around the focus point.
*/
this.execute = function(o, options) {
setOrigin(o);
_updatePositions();
_run(options);
};
/**
* Computes the center of all the nodes and then uses that as the magnetization origin when it runs the routine.
* @method executeAtCenter
* @param {Function} [options] Options to override defaults.
* @param {Function} [options.filter] Optional function to indicate whether a given element may be moved or not. Returning boolean false indicates it may not.
* @param {Number[]} [options.padding] Optional [x,y] padding values for elements.
* @param {Number} [options.iterations] Optional max number of iterations to run. The greater this number, the more comprehensive the magnetisation,
* but the slower it runs. The default is 2.
* @param {Function} [options.exclude] Optional function to return whether or not a given element should be completely excluded from the magnetisation: it neither
* moves, nor has any bearing on the movement of other elements.
* @param {Boolean} [options.excludeFocus=false] If true, do not pad any elements around the focus point.
*/
this.executeAtCenter = function(options) {
var extents = _updatePositions();
setOrigin([
(extents[0] + extents[1]) / 2,
(extents[2] + extents[3]) / 2
]);
_run(options);
};
/**
* Runs the magnetize routine using the location of the given event as the origin. To use this
* method you need to have provided a `container`, and a `getContainerPosition` function to the
* constructor.
* @method executeAtEvent
* @param {Event} e Event to get origin location from.
* @param {Function} [options] Options to override defaults.
* @param {Function} [options.filter] Optional function to indicate whether a given element may be moved or not. Returning boolean false indicates it may not.
* @param {Number[]} [options.padding] Optional [x,y] padding values for elements.
* @param {Number} [options.iterations] Optional max number of iterations to run. The greater this number, the more comprehensive the magnetisation,
* but the slower it runs. The default is 2.
* @param {Function} [options.exclude] Optional function to return whether or not a given element should be completely excluded from the magnetisation: it neither
* moves, nor has any bearing on the movement of other elements.
* @param {Boolean} [options.excludeFocus=false] If true, do not pad any elements around the focus point.
*/
this.executeAtEvent = function(e, options) {
var c = params.container,
o = params.getContainerPosition(c),
x = e.pageX - o.left + c.scrollLeft,
y = e.pageY - o.top + c.scrollTop;
if (debug) {
originDebugMarker.style.left = e.pageX + "px";
originDebugMarker.style.top = e.pageY + "px";
}
this.execute([x,y], options);
};
/**
* Sets the current set of elements on which to operate.
* @method setElements
* @param {Object[]|Object} _els List, or object hash, of elements, in whatever format the Magnetizer is setup to use. If you supply an object hash then a list is generated from the hash's values (the keys are ignored).
*/
this.setElements = function(_els) {
elements = _convertElements(_els);
return this;
};
/**
* Adds the given element to the set of elements on which to operate.
* @method addElement
* @param el {Object} Element to add.
* @param {Boolean} [doNotTestForDuplicates=false] If true, we skip the check for duplicates. This makes
* for a much faster call when there are lots of elements, just use it with care.
*/
this.addElement = function(el, doNotTestForDuplicates) {
if (el != null && (doNotTestForDuplicates || elements.indexOf(el) === -1)) {
elements.push(el);
}
return this;
};
/**
* Adds the given elements to the set of elements on which to operate.
* @method addElements
* @param els {Object[]} Elements to add.
* @param {Boolean} [doNotTestForDuplicates=false] If true, we skip the check for duplicates. This makes
* for a much faster call when there are lots of elements, just use it with care.
*/
this.addElements = function(els, doNotTestForDuplicates) {
if (doNotTestForDuplicates) {
Array.prototype.push.apply(elements, els);
}
else {
for (var i = 0; i < els.length; i++) {
this.addElement(els[i]);
}
}
return this;
};
/**
* Gets the list of elements currently being managed.
* @method getElements
*/
this.getElements = function() {
return elements;
};
/**
* Removes the given element from the set of elements on which to operate.
* @method removeElement
* @param el {Object} Element to remove.
*/
this.removeElement = function(el) {
var idx = -1;
for (var i = 0; i < elements.length; i++) {
if (elements[i] == el) {
idx = i; break;
}
}
if (idx != -1) elements.splice(idx, 1);
return this;
};
/**
* Sets the padding to insert between magnetized elements.
* @method setPadding
* @param {Number[]} p Array of padding for each axis.
*/
this.setPadding = function(p) {
padding = p;
};
/**
* Sets the function used to constrain the movement of some element that the magnetizer wishes to relocate.
* The function is given an element ID and an array of [x,y] values, where each value indicates the proposed amount
* of movement in the given axis. The function is expected to return an array of [x,y] that indicates the allowed
* amount of movement in each axis.
* @method setConstrain
* @param {Function} c
*/
this.setConstrain = function(c) {
constrain = c;
};
/**
* Sets the function used to determine whether or not a given element should be considered during the magnetization process.
* @method setFilter
* @param {Function} f Filter function to use. Takes an element ID and returns whether or not that element can be moved.
*/
this.setFilter = function(f) {
filter = f;
};
/**
* Reset the Farahey instance. Use this to avoid memory leaks.
* @method reset
*/
this.reset = function() {
elements.length = 0;
};
if (debug)
createOriginDebugger();
if (executeNow) this.execute();
return this;
};
/**
* Gets a new FaraheyInstance
* @method
* @param {Object} params Method parameters.
* @param {Selector|Element} [params.container] Element that contains the elements to magnetize. Only required if you intend to use the `executeAtEvent` method.
* @param {Function} [params.getContainerPosition] Function that returns the position of the container (as an object of the form `{left:.., top:..}`) when requested. Only required if you intend to use the `executeAtEvent` method.
* @param {Function} params.getPosition A function that takes an element and returns its position. It does not matter to which element this position is computed as long as you remain consistent with this method, `setPosition` and the `origin` property.
* @param {Function} params.setPosition A function that takes an element and position, and sets it. See note about offset parent above.
* @param {Function} params.getSize A function that takes an element and returns its size, in pixels.
* @param {Number[]} [params.padding] Optional padding for x and y directions. Defaults to 20 pixels in each direction.
* @param {Function} [params.constrain] Optional function that takes an id and a proposed amount of movement in each axis, and returns the allowed amount of movement in each axis. You can use this to constrain your elements to a grid, for instance, or a path, etc.
* @param {Number[]} [params.origin] The origin of magnetization, in pixels. Defaults to 0,0. You can also supply this to the `execute` call.
* @param {Selector|String[]|Element[]} params.elements List, or object hash, of elements on which to operate.
* @param {Boolean} [params.executeNow=false] Whether or not to execute the routine immediately.
* @param {Function} [params.filter] Optional function that takes an element id and returns whether or not that element can be moved.
* @param {Boolean} [params.orderByDistanceFromOrigin=false] Whether or not to sort elements first by distance from origin. Can have better results but takes more time.
*/
Farahey.getInstance = function(params) {
return new FaraheyInstance(params);
};
}).call(typeof window !== 'undefined' ? window : this);

View File

@@ -67,8 +67,12 @@ $.fn.dragToSelect = function (conf) {
onRefresh: function () {return true;}
}, c);
var realParent = $(this);
var parent = realParent;
var realParent = $(this);
var parent = realParent;
// container for lasso element
// -> the only reason for NOT using the .pf-map is because of the zoom [scale()] feature or .pf-map
var lassoContainer = realParent.parent();
var animationFrameId;
var mouseIsDown = false;
@@ -77,13 +81,14 @@ $.fn.dragToSelect = function (conf) {
// deselected items
var deselectedItems = $();
/*
do {
if (/auto|scroll|hidden/.test(parent.css('overflow'))) {
break;
}
parent = parent.parent();
} while (parent[0].parentNode);
*/
// Does user want to disable dragToSelect
if (conf == 'disable') {
parent.addClass(config.disabledClass);
@@ -123,7 +128,7 @@ $.fn.dragToSelect = function (conf) {
// Create select box
var selectBox = $('<div>')
.appendTo(parent)
.appendTo(lassoContainer)
.attr('class', config.className)
.css('position', 'absolute');
@@ -133,8 +138,8 @@ $.fn.dragToSelect = function (conf) {
return;
}
selectBoxOrigin.left = e.pageX - parentDim.left + parent[0].scrollLeft - 5;
selectBoxOrigin.top = e.pageY - parentDim.top + parent[0].scrollTop - 5;
selectBoxOrigin.left = e.pageX - parentDim.left + parent[0].scrollLeft;
selectBoxOrigin.top = e.pageY - parentDim.top + parent[0].scrollTop;
var css = {
left: selectBoxOrigin.left + 'px',
@@ -155,20 +160,6 @@ $.fn.dragToSelect = function (conf) {
return refreshed;
}
// get scroll position
/*
var leftScroll = 0;
var topScroll = 0;
if(realParent.attr('data-scroll-left')){
leftScroll = parseInt(realParent.attr('data-scroll-left'));
}
if(realParent.attr('data-scroll-top')){
topScroll = parseInt(realParent.attr('data-scroll-top'));
}
*/
var left = lastMousePosition.x - parentDim.left + parent[0].scrollLeft;
var top = lastMousePosition.y - parentDim.top + parent[0].scrollTop;
var tempWidth = selectBoxOrigin.left - left;
@@ -219,30 +210,6 @@ $.fn.dragToSelect = function (conf) {
}
};
// Scrolls parent if needed
var scrollPerhaps = function (e) {
if (!selectBox.is('.' + config.activeClass) || parent.is('.' + config.disabledClass)) {
return;
}
// Scroll down
if ((e.pageY + config.scrollTH) > (parentDim.top + parentDim.height)) {
parent[0].scrollTop += config.scrollTH;
}
// Scroll up
if ((e.pageY - config.scrollTH) < parentDim.top) {
parent[0].scrollTop -= config.scrollTH;
}
// Scroll right
if ((e.pageX + config.scrollTH) > (parentDim.left + parentDim.width)) {
parent[0].scrollLeft += config.scrollTH;
}
// Scroll left
if ((e.pageX - config.scrollTH) < parentDim.left) {
parent[0].scrollLeft -= config.scrollTH;
}
};
// Selects all the elements in the select box's range
var selectElementsInRange = function () {
if (!selectBox.is('.' + config.activeClass) || parent.is('.' + config.disabledClass)) {
@@ -342,7 +309,7 @@ $.fn.dragToSelect = function (conf) {
}
var mouseupCallback = function(){
if (config.selectables){
if(config.selectables){
selectElementsInRange();
}
hideSelectBox();
@@ -364,10 +331,10 @@ $.fn.dragToSelect = function (conf) {
}).mouseup(mouseupCallback);
parent.mousedown(function(e){
if (
if(
e.which === 1 && // left mouse down
e.target === realParent[0] // prevent while dragging a system :)
) {
){
// Make sure user isn't clicking scrollbar (or disallow clicks far to the right actually)
if ((e.pageX + 20) > $(document.body).width()) {
return;
@@ -386,7 +353,6 @@ $.fn.dragToSelect = function (conf) {
e.preventDefault();
}).mouseup(mouseupCallback);
// Be nice
return this;
};

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

1
js/lib/raphael.min.js vendored Normal file

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More