- UI changes to "build index" button on /setup
- updated `wormhole.csv` - upgrade SDE dump `eve_lifeblood.sql` -> `eve_abyss.sql` - upgrade endpoint "getUniverseSystemData()" `v3` -> `v4` - upgrade endpoint "getUniverseStructureData()" `v1` -> `v2` - some minor code improvements
This commit is contained in:
@@ -54,4 +54,7 @@ deleteAuthenticationData = Cron\CharacterUpdate->deleteAuthenticati
|
||||
deleteExpiredCacheData = Cron\Cache->deleteExpiredData, @downtime
|
||||
|
||||
; delete old statistics (activity log) data
|
||||
deleteStatisticsData = Cron\StatisticsUpdate->deleteStatisticsData, @weekly
|
||||
deleteStatisticsData = Cron\StatisticsUpdate->deleteStatisticsData, @weekly
|
||||
|
||||
; setup universe DB with static data from ESI
|
||||
; setup = Cron\Universe->setup, @instant
|
||||
@@ -91,6 +91,15 @@ class Setup extends Controller\Controller {
|
||||
$return->countBuildAll = $categoryUniverseModel->getById($categoryId, 0)->getTypesCount(false);
|
||||
$return->progress = $percent($return->countAll, $return->countBuildAll);
|
||||
break;
|
||||
case 'SystemNeighbourModel':
|
||||
// Becomes deprecated with new Universe DB!!!
|
||||
$this->setupSystemJumpTable();
|
||||
|
||||
$return->countAll = 5214;
|
||||
$return->countBuild = Database::instance()->getRowCount('system_neighbour');
|
||||
$return->countBuildAll = $return->countBuild;
|
||||
$return->progress = $percent($return->countAll, $return->countBuildAll);
|
||||
break;
|
||||
}
|
||||
|
||||
if($return->countBuildAll < $return->countAll){
|
||||
@@ -130,5 +139,74 @@ class Setup extends Controller\Controller {
|
||||
echo json_encode($return);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is just for setting up the cache table 'system_neighbour' which is used
|
||||
* for system jump calculation. Call this function manually when CCP adds Systems/Stargates
|
||||
*/
|
||||
protected function setupSystemJumpTable(){
|
||||
$pfDB = $this->getDB('PF');
|
||||
$ccpDB = $this->getDB('CCP');
|
||||
|
||||
$query = "SELECT
|
||||
map_sys.solarSystemID system_id,
|
||||
map_sys.regionID region_id,
|
||||
map_sys.constellationID constellation_id,
|
||||
map_sys.solarSystemName system_name,
|
||||
ROUND( map_sys.security, 4) system_security,
|
||||
(
|
||||
SELECT
|
||||
GROUP_CONCAT( NULLIF(map_sys_inner.solarSystemName, NULL) SEPARATOR ':')
|
||||
FROM
|
||||
mapSolarSystemJumps map_jump INNER JOIN
|
||||
mapSolarSystems map_sys_inner ON
|
||||
map_sys_inner.solarSystemID = map_jump.toSolarSystemID
|
||||
WHERE
|
||||
map_jump.fromSolarSystemID = map_sys.solarSystemID
|
||||
) system_neighbours
|
||||
FROM
|
||||
mapSolarSystems map_sys
|
||||
HAVING
|
||||
-- skip systems without neighbors (e.g. WHs)
|
||||
system_neighbours IS NOT NULL
|
||||
";
|
||||
|
||||
$rows = $ccpDB->exec($query);
|
||||
|
||||
if(count($rows) > 0){
|
||||
// switch DB back to pathfinder DB
|
||||
|
||||
// clear cache table
|
||||
$pfDB->exec("TRUNCATE system_neighbour");
|
||||
|
||||
foreach($rows as $row){
|
||||
$pfDB->exec("
|
||||
INSERT INTO
|
||||
system_neighbour(
|
||||
regionId,
|
||||
constellationId,
|
||||
systemName,
|
||||
systemId,
|
||||
jumpNodes,
|
||||
trueSec
|
||||
)
|
||||
VALUES(
|
||||
:regionId,
|
||||
:constellationId,
|
||||
:systemName,
|
||||
:systemId,
|
||||
:jumpNodes,
|
||||
:trueSec
|
||||
)",
|
||||
[
|
||||
':regionId' => $row['region_id'],
|
||||
':constellationId' => $row['constellation_id'],
|
||||
':systemName' => $row['system_name'],
|
||||
':systemId' => $row['system_id'],
|
||||
':jumpNodes' => $row['system_neighbours'],
|
||||
':trueSec' => $row['system_security']
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -112,14 +112,14 @@ class Setup extends Controller {
|
||||
'Model\Universe\GroupModel',
|
||||
'Model\Universe\CategoryModel',
|
||||
'Model\Universe\StructureModel',
|
||||
'Model\Universe\WormholeModel',
|
||||
'Model\Universe\StargateModel',
|
||||
'Model\Universe\StarModel',
|
||||
'Model\Universe\PlanetModel',
|
||||
'Model\Universe\SystemModel',
|
||||
'Model\Universe\ConstellationModel',
|
||||
'Model\Universe\RegionModel',
|
||||
'Model\Universe\SystemStaticModel'
|
||||
// 'Model\Universe\WormholeModel',
|
||||
// 'Model\Universe\StargateModel',
|
||||
// 'Model\Universe\StarModel',
|
||||
// 'Model\Universe\PlanetModel',
|
||||
// 'Model\Universe\SystemModel',
|
||||
// 'Model\Universe\ConstellationModel',
|
||||
// 'Model\Universe\RegionModel',
|
||||
// 'Model\Universe\SystemStaticModel'
|
||||
],
|
||||
'tables' => []
|
||||
],
|
||||
@@ -231,9 +231,6 @@ class Setup extends Controller {
|
||||
case 'fixCols':
|
||||
$fixColumns = true;
|
||||
break;
|
||||
case 'buildIndex':
|
||||
$this->setupSystemJumpTable();
|
||||
break;
|
||||
case 'importTable':
|
||||
$this->importTable($params['model']);
|
||||
break;
|
||||
@@ -1354,14 +1351,15 @@ class Setup extends Controller {
|
||||
protected function getIndexData(\Base $f3){
|
||||
// active DB and tables are required for obtain index data
|
||||
if(!$this->databaseHasError){
|
||||
$categoryUniverseModel = Model\Universe\BasicUniverseModel::getNew('CategoryModel');
|
||||
$systemUniverseModel = Model\Universe\BasicUniverseModel::getNew('SystemModel');
|
||||
//$categoryUniverseModel = Model\Universe\BasicUniverseModel::getNew('CategoryModel');
|
||||
//$systemUniverseModel = Model\Universe\BasicUniverseModel::getNew('SystemModel');
|
||||
$systemNeighbourModel = Model\BasicModel::getNew('SystemNeighbourModel');
|
||||
$wormholeModel = Model\BasicModel::getNew('WormholeModel');
|
||||
$systemWormholeModel = Model\BasicModel::getNew('SystemWormholeModel');
|
||||
$constellationWormholeModel = Model\BasicModel::getNew('ConstellationWormholeModel');
|
||||
|
||||
$indexInfo = [
|
||||
/*
|
||||
'Systems' => [
|
||||
'task' => [
|
||||
[
|
||||
@@ -1408,7 +1406,8 @@ class Setup extends Controller {
|
||||
'countBuild' => $categoryUniverseModel->getById(6, 0)->getTypesCount(false),
|
||||
'countAll' => (int)$f3->get('REQUIREMENTS.DATA.SHIPS'),
|
||||
'tooltip' => 'import all ships types from ESI. Runtime: ~2min'
|
||||
],
|
||||
], */
|
||||
// All following rows become deprecated
|
||||
'SystemNeighbourModel' => [
|
||||
'task' => [
|
||||
[
|
||||
@@ -1456,7 +1455,7 @@ class Setup extends Controller {
|
||||
],
|
||||
'label' => 'system_wormhole',
|
||||
'countBuild' => $this->dbLib->getRowCount($systemWormholeModel->getTable()),
|
||||
'countAll' => 233
|
||||
'countAll' => 234
|
||||
],
|
||||
'ConstellationWormholeModel' => [
|
||||
'task' => [
|
||||
@@ -1474,91 +1473,21 @@ class Setup extends Controller {
|
||||
],
|
||||
'label' => 'constellation_wormhole',
|
||||
'countBuild' => $this->dbLib->getRowCount( $constellationWormholeModel->getTable() ),
|
||||
'countAll' => 460
|
||||
'countAll' => 461
|
||||
]
|
||||
];
|
||||
}else{
|
||||
$indexInfo = [
|
||||
'SystemNeighbourModel' => [
|
||||
'task' => [],
|
||||
'table' => 'Fix database errors first!'
|
||||
'label' => 'Fix database errors first!'
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
//var_dump($indexInfo); die();
|
||||
return $indexInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is just for setting up the cache table 'system_neighbour' which is used
|
||||
* for system jump calculation. Call this function manually when CCP adds Systems/Stargates
|
||||
*/
|
||||
protected function setupSystemJumpTable(){
|
||||
$pfDB = $this->getDB('PF');
|
||||
$ccpDB = $this->getDB('CCP');
|
||||
|
||||
$query = "SELECT
|
||||
map_sys.solarSystemID system_id,
|
||||
map_sys.regionID region_id,
|
||||
map_sys.constellationID constellation_id,
|
||||
map_sys.solarSystemName system_name,
|
||||
ROUND( map_sys.security, 4) system_security,
|
||||
(
|
||||
SELECT
|
||||
GROUP_CONCAT( NULLIF(map_sys_inner.solarSystemName, NULL) SEPARATOR ':')
|
||||
FROM
|
||||
mapSolarSystemJumps map_jump INNER JOIN
|
||||
mapSolarSystems map_sys_inner ON
|
||||
map_sys_inner.solarSystemID = map_jump.toSolarSystemID
|
||||
WHERE
|
||||
map_jump.fromSolarSystemID = map_sys.solarSystemID
|
||||
) system_neighbours
|
||||
FROM
|
||||
mapSolarSystems map_sys
|
||||
HAVING
|
||||
-- skip systems without neighbors (e.g. WHs)
|
||||
system_neighbours IS NOT NULL
|
||||
";
|
||||
|
||||
$rows = $ccpDB->exec($query);
|
||||
|
||||
if(count($rows) > 0){
|
||||
// switch DB back to pathfinder DB
|
||||
|
||||
// clear cache table
|
||||
$pfDB->exec("TRUNCATE system_neighbour");
|
||||
|
||||
foreach($rows as $row){
|
||||
$pfDB->exec("
|
||||
INSERT INTO
|
||||
system_neighbour(
|
||||
regionId,
|
||||
constellationId,
|
||||
systemName,
|
||||
systemId,
|
||||
jumpNodes,
|
||||
trueSec
|
||||
)
|
||||
VALUES(
|
||||
:regionId,
|
||||
:constellationId,
|
||||
:systemName,
|
||||
:systemId,
|
||||
:jumpNodes,
|
||||
:trueSec
|
||||
)",
|
||||
[
|
||||
':regionId' => $row['region_id'],
|
||||
':constellationId' => $row['constellation_id'],
|
||||
':systemName' => $row['system_name'],
|
||||
':systemId' => $row['system_id'],
|
||||
':jumpNodes' => $row['system_neighbours'],
|
||||
':trueSec' => $row['system_security']
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* import table data from existing dump file (e.g *.csv)
|
||||
* @param string $modelClass
|
||||
|
||||
@@ -156,13 +156,13 @@ class Universe {
|
||||
|
||||
/**
|
||||
* imports static universe data from ESI
|
||||
* >> php index.php "/cron/setup?model=system&offset=0&length=5"
|
||||
* >> php index.php "/cron/setup?type=system&offset=0&length=5"
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
*/
|
||||
function setup(\Base $f3){
|
||||
$params = (array)$f3->get('GET');
|
||||
$type = (string)$params['model'];
|
||||
$type = (string)$params['type'];
|
||||
$paramOffset = (int)$params['offset'];
|
||||
$paramLength = (int)$params['length'];
|
||||
$timeTotalStart = microtime(true);
|
||||
|
||||
@@ -40,9 +40,6 @@ class AllianceModel extends BasicModel {
|
||||
'allianceCharacters' => [
|
||||
'has-many' => ['Model\CharacterModel', 'allianceId']
|
||||
],
|
||||
'alliancCorporations' => [
|
||||
'has-many' => ['Model\CharacterModel', 'allianceId']
|
||||
],
|
||||
'mapAlliances' => [
|
||||
'has-many' => ['Model\AllianceMapModel', 'allianceId']
|
||||
]
|
||||
|
||||
@@ -99,9 +99,7 @@ abstract class BasicUniverseModel extends BasicModel {
|
||||
* -> stores getData() result into Cache (RAM) for faster access
|
||||
*/
|
||||
public function buildIndex(){
|
||||
$hashKeyId = $this->getHashKey();
|
||||
$hashKeyName = $this->getHashKey('name');
|
||||
if($hashKeyId && $hashKeyName){
|
||||
if($hashKeyId = $this->getHashKey()){
|
||||
$f3 = self::getF3();
|
||||
$hashKeyTable = self::generateHashKeyTable($this->getTable());
|
||||
|
||||
@@ -109,18 +107,16 @@ abstract class BasicUniverseModel extends BasicModel {
|
||||
$cachedData = [];
|
||||
}
|
||||
|
||||
if( !in_array($hashKeyName, $cachedData) ){
|
||||
$cachedData[] = $hashKeyName;
|
||||
if( !in_array($hashKeyId, $cachedData) ){
|
||||
$cachedData[] = $hashKeyId;
|
||||
}
|
||||
|
||||
// value update does not update ttl -> delete key from cache and add again
|
||||
$f3->clear($hashKeyId);
|
||||
$f3->clear($hashKeyName);
|
||||
$f3->clear($hashKeyTable);
|
||||
|
||||
// straight into cache (no $f->set() ), no sync with hive here -> save ram
|
||||
self::setCacheValue($hashKeyId, $this->getData(), self::CACHE_INDEX_EXPIRE_KEY);
|
||||
self::setCacheValue($hashKeyName, $hashKeyId, self::CACHE_INDEX_EXPIRE_KEY);
|
||||
self::setCacheValue($hashKeyTable, $cachedData, self::CACHE_INDEX_EXPIRE_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,6 @@ class GroupModel extends BasicUniverseModel {
|
||||
$groupData->id = $this->id;
|
||||
$groupData->name = $this->name;
|
||||
|
||||
|
||||
if($typesData = $this->getTypesData()){
|
||||
$groupData->types = $typesData;
|
||||
}
|
||||
|
||||
@@ -8,10 +8,8 @@
|
||||
|
||||
namespace Model\Universe;
|
||||
|
||||
|
||||
use DB\SQL;
|
||||
use DB\SQL\Schema;
|
||||
use lib\Util;
|
||||
|
||||
class StructureModel extends BasicUniverseModel {
|
||||
|
||||
@@ -81,32 +79,25 @@ class StructureModel extends BasicUniverseModel {
|
||||
protected function loadData(int $id, string $accessToken = '', array $additionalOptions = []){
|
||||
$data = self::getF3()->ccpClient->getUniverseStructureData($id, $accessToken, $additionalOptions);
|
||||
if(!empty($data)){
|
||||
/**
|
||||
* @var $type TypeModel
|
||||
*/
|
||||
$type = $this->rel('typeId');
|
||||
$type->loadById($data['typeId'], $accessToken, $additionalOptions);
|
||||
$data['typeId'] = $type;
|
||||
|
||||
$this->copyfrom($data);
|
||||
$this->copyfrom($data, ['id', 'name', 'systemId', 'typeId', 'position']);
|
||||
$this->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|string $key
|
||||
* @param null $fields
|
||||
* @return NULL
|
||||
*/
|
||||
public function copyfrom($key, $fields = null){
|
||||
// flatten array (e.g. "position" key)
|
||||
$key = Util::arrayFlattenByKey((array)$key);
|
||||
parent::copyfrom($key, $fields);
|
||||
}
|
||||
|
||||
/**
|
||||
* overwrites parent
|
||||
* @param null|SQL $db
|
||||
* @param null $table
|
||||
* @param null $fields
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function setup($db=null, $table=null, $fields=null){
|
||||
if($status = parent::setup($db,$table,$fields)){
|
||||
|
||||
@@ -107,12 +107,15 @@ class SystemModel extends BasicUniverseModel {
|
||||
$systemData->id = $this->_id;
|
||||
$systemData->name = $this->name;
|
||||
$systemData->constellation = $this->constellationId->getData();
|
||||
$systemData->star = $this->starId->getData();
|
||||
$systemData->security = $this->security;
|
||||
$systemData->trueSec = $this->trueSec;
|
||||
$systemData->effect = $this->effect;
|
||||
$systemData->shattered = $this->shattered;
|
||||
|
||||
if($this->starId){
|
||||
$systemData->star = $this->starId->getData();
|
||||
}
|
||||
|
||||
if( !empty($planetsData = $this->getPlanetsData()) ){
|
||||
$systemData->planets = $planetsData;
|
||||
}
|
||||
@@ -128,6 +131,20 @@ class SystemModel extends BasicUniverseModel {
|
||||
return $systemData;
|
||||
}
|
||||
|
||||
/**
|
||||
* setter for system name
|
||||
* @param $name
|
||||
* @return mixed
|
||||
*/
|
||||
public function set_name($name){
|
||||
// name should never change
|
||||
// -> important for "Abyssal" systems where ESI don´t have correct system name
|
||||
if(!empty($this->name)){
|
||||
$name = $this->name;
|
||||
}
|
||||
return $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* setter for row (un-formatted) trueSec
|
||||
* @param $secStatus
|
||||
@@ -144,13 +161,24 @@ class SystemModel extends BasicUniverseModel {
|
||||
$this->trueSec = $trueSec;
|
||||
// set 'security' for NON wormhole systems! -> those get updated from csv import
|
||||
if(!preg_match('/^j\d+$/i', $this->name)){
|
||||
if($trueSec <= 0){
|
||||
$security = '0.0';
|
||||
}elseif($trueSec < 0.5){
|
||||
$security = 'L';
|
||||
// check for "Abyssal" system
|
||||
if(
|
||||
$this->get('constellationId', true) >= 22000001 &&
|
||||
$this->get('constellationId', true) <= 22000025
|
||||
){
|
||||
// "Abyssal" system
|
||||
$security = 'A';
|
||||
}else{
|
||||
$security = 'H';
|
||||
// k-space system
|
||||
if($trueSec <= 0){
|
||||
$security = '0.0';
|
||||
}elseif($trueSec < 0.5){
|
||||
$security = 'L';
|
||||
}else{
|
||||
$security = 'H';
|
||||
}
|
||||
}
|
||||
|
||||
$this->security = $security;
|
||||
}
|
||||
return $secStatus;
|
||||
@@ -297,6 +325,7 @@ class SystemModel extends BasicUniverseModel {
|
||||
*/
|
||||
protected function loadData(int $id, string $accessToken = '', array $additionalOptions = []){
|
||||
$data = self::getF3()->ccpClient->getUniverseSystemData($id);
|
||||
|
||||
if(!empty($data)){
|
||||
/**
|
||||
* @var $constellation ConstellationModel
|
||||
@@ -305,12 +334,15 @@ class SystemModel extends BasicUniverseModel {
|
||||
$constellation->loadById($data['constellationId'], $accessToken, $additionalOptions);
|
||||
$data['constellationId'] = $constellation;
|
||||
|
||||
/**
|
||||
* @var $star StarModel
|
||||
*/
|
||||
$star = $this->rel('starId');
|
||||
$star->loadById($data['starId'], $accessToken, $additionalOptions);
|
||||
$data['starId'] = $star;
|
||||
// starId is optional since ESI v4 (e.g. Abyssal systems)
|
||||
if($data['starId']){
|
||||
/**
|
||||
* @var $star StarModel
|
||||
*/
|
||||
$star = $this->rel('starId');
|
||||
$star->loadById($data['starId'], $accessToken, $additionalOptions);
|
||||
$data['starId'] = $star;
|
||||
}
|
||||
|
||||
$this->copyfrom($data, ['id', 'name', 'constellationId', 'starId', 'securityStatus', 'securityClass', 'position']);
|
||||
$this->save();
|
||||
@@ -323,7 +355,8 @@ class SystemModel extends BasicUniverseModel {
|
||||
public function loadPlanetsData(){
|
||||
if( !$this->dry() ){
|
||||
$data = self::getF3()->ccpClient->getUniverseSystemData($this->_id);
|
||||
if(!empty($data)){
|
||||
if($data['planets']){
|
||||
// planets are optional since ESI v4 (e.g. Abyssal systems)
|
||||
foreach((array)$data['planets'] as $planetData){
|
||||
/**
|
||||
* @var $planet PlanetModel
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
"37";"M609";"C4";"1000000000";"20000000";;"16";"4";
|
||||
"38";"N062";"C5";"3000000000";"300000000";;"24";"2.5";
|
||||
"39";"N110";"H";"1000000000";"20000000";;"24";"10";
|
||||
"40";"N290";"L";"3000000000";"1800000000";"500000000";"24";;
|
||||
"40";"N290";"L";"3000000000";"1350000000";"500000000";"24";;
|
||||
"41";"N432";"C5";"3000000000";"1350000000";;"24";"10";
|
||||
"42";"N766";"C2";"2000000000";"300000000";;"16";"4";
|
||||
"43";"N770";"C5";"3000000000";"300000000";;"24";"2.5";
|
||||
@@ -56,7 +56,7 @@
|
||||
"57";"S804";"C6";"1000000000";"20000000";;"24";"1.25";
|
||||
"58";"T405";"C4";"2000000000";"300000000";;"16";"6.67";
|
||||
"59";"U210";"L";"3000000000";"300000000";;"24";"10";
|
||||
"60";"U319";"C6";"3000000000";"1800000000";"500000000";"48";;
|
||||
"60";"U319";"C6";"3000000000";"1350000000";"500000000";"48";;
|
||||
"61";"U574";"C6";"3000000000";"300000000";;"24";"1.25";
|
||||
"62";"V283";"0.0";"3000000000";"1000000000";;"24";"2.5";
|
||||
"63";"V301";"C1";"500000000";"20000000";;"16";"5";
|
||||
|
||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -101,7 +101,7 @@ define(['jquery'], function($) {
|
||||
4: 'M609 - C4',
|
||||
5: 'L614 - C5',
|
||||
6: 'S804 - C6',
|
||||
7: 'F135 - Thera'
|
||||
7: 'F353 - Thera'
|
||||
},
|
||||
6: { // ORE
|
||||
1: 'Ordinary Perimeter Deposit', //*
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,414 +0,0 @@
|
||||
/*! RowGroup 1.0.3-dev
|
||||
* ©2017-2018 SpryMedia Ltd - datatables.net/license
|
||||
*/
|
||||
|
||||
/**
|
||||
* @summary RowGroup
|
||||
* @description RowGrouping for DataTables
|
||||
* @version 1.0.3-dev
|
||||
* @file dataTables.rowGroup.js
|
||||
* @author SpryMedia Ltd (www.sprymedia.co.uk)
|
||||
* @contact datatables.net
|
||||
* @copyright Copyright 2017-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
|
||||
*/
|
||||
|
||||
(function( factory ){
|
||||
if ( typeof define === 'function' && define.amd ) {
|
||||
// AMD
|
||||
define( ['jquery', 'datatables.net'], function ( $ ) {
|
||||
return factory( $, window, document );
|
||||
} );
|
||||
}
|
||||
else if ( typeof exports === 'object' ) {
|
||||
// CommonJS
|
||||
module.exports = function (root, $) {
|
||||
if ( ! root ) {
|
||||
root = window;
|
||||
}
|
||||
|
||||
if ( ! $ || ! $.fn.dataTable ) {
|
||||
$ = require('datatables.net')(root, $).$;
|
||||
}
|
||||
|
||||
return factory( $, root, root.document );
|
||||
};
|
||||
}
|
||||
else {
|
||||
// Browser
|
||||
factory( jQuery, window, document );
|
||||
}
|
||||
}(function( $, window, document, undefined ) {
|
||||
'use strict';
|
||||
var DataTable = $.fn.dataTable;
|
||||
|
||||
|
||||
var RowGroup = function ( dt, opts ) {
|
||||
// Sanity check that we are using DataTables 1.10 or newer
|
||||
if ( ! DataTable.versionCheck || ! DataTable.versionCheck( '1.10.8' ) ) {
|
||||
throw 'RowGroup requires DataTables 1.10.8 or newer';
|
||||
}
|
||||
|
||||
// User and defaults configuration object
|
||||
this.c = $.extend( true, {},
|
||||
DataTable.defaults.rowGroup,
|
||||
RowGroup.defaults,
|
||||
opts
|
||||
);
|
||||
|
||||
// Internal settings
|
||||
this.s = {
|
||||
dt: new DataTable.Api( dt ),
|
||||
|
||||
dataFn: DataTable.ext.oApi._fnGetObjectDataFn( this.c.dataSrc )
|
||||
};
|
||||
|
||||
// DOM items
|
||||
this.dom = {
|
||||
|
||||
};
|
||||
|
||||
// Check if row grouping has already been initialised on this table
|
||||
var settings = this.s.dt.settings()[0];
|
||||
var existing = settings.rowGroup;
|
||||
if ( existing ) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
settings.rowGroup = this;
|
||||
this._constructor();
|
||||
};
|
||||
|
||||
|
||||
$.extend( RowGroup.prototype, {
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* API methods for DataTables API interface
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get/set the grouping data source - need to call draw after this is
|
||||
* executed as a setter
|
||||
* @returns string~RowGroup
|
||||
*/
|
||||
dataSrc: function ( val )
|
||||
{
|
||||
if ( val === undefined ) {
|
||||
return this.c.dataSrc;
|
||||
}
|
||||
|
||||
var dt = this.s.dt;
|
||||
|
||||
this.c.dataSrc = val;
|
||||
this.s.dataFn = DataTable.ext.oApi._fnGetObjectDataFn( this.c.dataSrc );
|
||||
|
||||
$(dt.table().node()).triggerHandler( 'rowgroup-datasrc.dt', [ dt, val ] );
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Disable - need to call draw after this is executed
|
||||
* @returns RowGroup
|
||||
*/
|
||||
disable: function ()
|
||||
{
|
||||
this.c.enable = false;
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Enable - need to call draw after this is executed
|
||||
* @returns RowGroup
|
||||
*/
|
||||
enable: function ( flag )
|
||||
{
|
||||
if ( flag === false ) {
|
||||
return this.disable();
|
||||
}
|
||||
|
||||
this.c.enable = true;
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* Constructor
|
||||
*/
|
||||
_constructor: function ()
|
||||
{
|
||||
var that = this;
|
||||
var dt = this.s.dt;
|
||||
var rows = dt.rows();
|
||||
var groups = [];
|
||||
|
||||
rows.every( function () {
|
||||
var d = this.data();
|
||||
var group = that.s.dataFn( d );
|
||||
|
||||
if ( groups.indexOf(group) == -1 ) {
|
||||
groups.push( group );
|
||||
}
|
||||
} );
|
||||
|
||||
dt.on( 'draw.dtrg', function () {
|
||||
if ( that.c.enable ) {
|
||||
that._draw();
|
||||
}
|
||||
} );
|
||||
|
||||
dt.on( 'column-visibility.dt.dtrg responsive-resize.dt.dtrg', function () {
|
||||
that._adjustColspan();
|
||||
} );
|
||||
|
||||
dt.on( 'destroy', function () {
|
||||
dt.off( '.dtrg' );
|
||||
} );
|
||||
},
|
||||
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* Private methods
|
||||
*/
|
||||
|
||||
/**
|
||||
* Adjust column span when column visibility changes
|
||||
* @private
|
||||
*/
|
||||
_adjustColspan: function ()
|
||||
{
|
||||
$( 'tr.'+this.c.className, this.s.dt.table().body() )
|
||||
.attr( 'colspan', this._colspan() );
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the number of columns that a grouping row should span
|
||||
* @private
|
||||
*/
|
||||
_colspan: function ()
|
||||
{
|
||||
return this.s.dt.columns().visible().reduce( function (a, b) {
|
||||
return a + b;
|
||||
}, 0 );
|
||||
},
|
||||
|
||||
/**
|
||||
* Update function that is called whenever we need to draw the grouping rows
|
||||
* @private
|
||||
*/
|
||||
_draw: function ()
|
||||
{
|
||||
var that = this;
|
||||
var dt = this.s.dt;
|
||||
var rows = dt.rows( { page: 'current' } );
|
||||
var groupedRows = [];
|
||||
var last, display;
|
||||
|
||||
rows.every( function () {
|
||||
var d = this.data();
|
||||
var group = that.s.dataFn( d );
|
||||
|
||||
if ( group === null || group === undefined ) {
|
||||
group = that.c.emptyDataGroup;
|
||||
}
|
||||
|
||||
if ( last === undefined || group !== last ) {
|
||||
groupedRows.push( [] );
|
||||
last = group;
|
||||
}
|
||||
|
||||
groupedRows[ groupedRows.length - 1 ].push( this.index() );
|
||||
} );
|
||||
|
||||
for ( var i=0, ien=groupedRows.length ; i<ien ; i++ ) {
|
||||
var group = groupedRows[i];
|
||||
var firstRow = dt.row(group[0]);
|
||||
var groupName = this.s.dataFn( firstRow.data() );
|
||||
|
||||
if ( this.c.startRender ) {
|
||||
display = this.c.startRender.call( this, dt.rows(group), groupName );
|
||||
|
||||
this
|
||||
._rowWrap( display, this.c.startClassName )
|
||||
.insertBefore( firstRow.node() );
|
||||
}
|
||||
|
||||
if ( this.c.endRender ) {
|
||||
display = this.c.endRender.call( this, dt.rows(group), groupName );
|
||||
|
||||
this
|
||||
._rowWrap( display, this.c.endClassName )
|
||||
.insertAfter( dt.row( group[ group.length-1 ] ).node() );
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Take a rendered value from an end user and make it suitable for display
|
||||
* as a row, by wrapping it in a row, or detecting that it is a row.
|
||||
* @param [node|jQuery|string] display Display value
|
||||
* @param [string] className Class to add to the row
|
||||
* @private
|
||||
*/
|
||||
_rowWrap: function ( display, className )
|
||||
{
|
||||
var row;
|
||||
|
||||
if ( display === null || display === undefined ) {
|
||||
display = this.c.emptyDataGroup;
|
||||
}
|
||||
|
||||
if ( typeof display === 'object' && display.nodeName && display.nodeName.toLowerCase() === 'tr') {
|
||||
row = $(display);
|
||||
}
|
||||
else if (display instanceof $ && display.length && display[0].nodeName.toLowerCase() === 'tr') {
|
||||
row = display;
|
||||
}
|
||||
else {
|
||||
row = $('<tr/>')
|
||||
.append(
|
||||
$('<td/>')
|
||||
.attr( 'colspan', this._colspan() )
|
||||
.append( display )
|
||||
);
|
||||
}
|
||||
|
||||
return row
|
||||
.addClass( this.c.className )
|
||||
.addClass( className );
|
||||
}
|
||||
} );
|
||||
|
||||
|
||||
/**
|
||||
* RowGroup default settings for initialisation
|
||||
*
|
||||
* @namespace
|
||||
* @name RowGroup.defaults
|
||||
* @static
|
||||
*/
|
||||
RowGroup.defaults = {
|
||||
/**
|
||||
* Class to apply to grouping rows - applied to both the start and
|
||||
* end grouping rows.
|
||||
* @type string
|
||||
*/
|
||||
className: 'group',
|
||||
|
||||
/**
|
||||
* Data property from which to read the grouping information
|
||||
* @type string|integer
|
||||
*/
|
||||
dataSrc: 0,
|
||||
|
||||
/**
|
||||
* Text to show if no data is found for a group
|
||||
* @type string
|
||||
*/
|
||||
emptyDataGroup: 'No group',
|
||||
|
||||
/**
|
||||
* Initial enablement state
|
||||
* @boolean
|
||||
*/
|
||||
enable: true,
|
||||
|
||||
/**
|
||||
* Class name to give to the end grouping row
|
||||
* @type string
|
||||
*/
|
||||
endClassName: 'group-end',
|
||||
|
||||
/**
|
||||
* End grouping label function
|
||||
* @function
|
||||
*/
|
||||
endRender: null,
|
||||
|
||||
/**
|
||||
* Class name to give to the start grouping row
|
||||
* @type string
|
||||
*/
|
||||
startClassName: 'group-start',
|
||||
|
||||
/**
|
||||
* Start grouping label function
|
||||
* @function
|
||||
*/
|
||||
startRender: function ( rows, group ) {
|
||||
return group;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
RowGroup.version = "1.0.3-dev";
|
||||
|
||||
|
||||
$.fn.dataTable.RowGroup = RowGroup;
|
||||
$.fn.DataTable.RowGroup = RowGroup;
|
||||
|
||||
|
||||
DataTable.Api.register( 'rowGroup()', function () {
|
||||
return this;
|
||||
} );
|
||||
|
||||
DataTable.Api.register( 'rowGroup().disable()', function () {
|
||||
return this.iterator( 'table', function (ctx) {
|
||||
if ( ctx.rowGroup ) {
|
||||
ctx.rowGroup.enable( false );
|
||||
}
|
||||
} );
|
||||
} );
|
||||
|
||||
DataTable.Api.register( 'rowGroup().enable()', function ( opts ) {
|
||||
return this.iterator( 'table', function (ctx) {
|
||||
if ( ctx.rowGroup ) {
|
||||
ctx.rowGroup.enable( opts === undefined ? true : opts );
|
||||
}
|
||||
} );
|
||||
} );
|
||||
|
||||
DataTable.Api.register( 'rowGroup().dataSrc()', function ( val ) {
|
||||
if ( val === undefined ) {
|
||||
return this.context[0].rowGroup.dataSrc();
|
||||
}
|
||||
|
||||
return this.iterator( 'table', function (ctx) {
|
||||
if ( ctx.rowGroup ) {
|
||||
ctx.rowGroup.dataSrc( val );
|
||||
}
|
||||
} );
|
||||
} );
|
||||
|
||||
|
||||
// Attach a listener to the document which listens for DataTables initialisation
|
||||
// events so we can automatically initialise
|
||||
/*
|
||||
$(document).on( 'preInit.dt.dtrg', function (e, settings, json) {
|
||||
if ( e.namespace !== 'dt' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var init = settings.oInit.rowGroup;
|
||||
var defaults = DataTable.defaults.rowGroup;
|
||||
|
||||
if ( init || defaults ) {
|
||||
var opts = $.extend( {}, defaults, init );
|
||||
|
||||
if ( init !== false ) {
|
||||
new RowGroup( settings, opts );
|
||||
}
|
||||
}
|
||||
} );
|
||||
*/
|
||||
|
||||
return RowGroup;
|
||||
|
||||
}));
|
||||
@@ -1,55 +0,0 @@
|
||||
describe( 'rowGroup().dataSrc()', function() {
|
||||
var table;
|
||||
|
||||
dt.libs( {
|
||||
js: [ 'jquery', 'datatables', 'rowgroup' ],
|
||||
css: [ 'datatables', 'rowgroup' ]
|
||||
} );
|
||||
|
||||
dt.html( 'basic' );
|
||||
|
||||
it( 'A DataTable can be created with RowGrouping', function () {
|
||||
table = $('#example').DataTable( {
|
||||
order: [[2, 'asc']],
|
||||
rowGroup: {
|
||||
dataSrc: 2
|
||||
}
|
||||
} );
|
||||
|
||||
expect( $('#example tbody tr:eq(0) td:eq(0)').html() ).toBe( 'Edinburgh' );
|
||||
expect( $('#example tbody tr:eq(1) td:eq(0)').html() ).toBe( 'Tiger Nixon' );
|
||||
} );
|
||||
|
||||
it( 'Get the current data source', function () {
|
||||
expect( table.rowGroup().dataSrc() ).toBe( 2 );
|
||||
} );
|
||||
|
||||
it( 'Can change the data source', function () {
|
||||
table.rowGroup().dataSrc( 3 ).draw();
|
||||
|
||||
expect( $('#example tbody tr:eq(0) td:eq(0)').html() ).toBe( '61' );
|
||||
expect( $('#example tbody tr:eq(1) td:eq(0)').html() ).toBe( 'Tiger Nixon' );
|
||||
expect( $('#example tbody tr:eq(2) td:eq(0)').html() ).toBe( '22' );
|
||||
expect( $('#example tbody tr:eq(3) td:eq(0)').html() ).toBe( 'Cedric Kelly' );
|
||||
} );
|
||||
|
||||
it( 'Return as a setter is an API instance', function () {
|
||||
expect( table.rowGroup().dataSrc( 3 ) instanceof $.fn.dataTable.Api ).toBe( true );
|
||||
} );
|
||||
|
||||
it( 'Read the set value back', function () {
|
||||
expect( table.rowGroup().dataSrc() ).toBe( 3 );
|
||||
} );
|
||||
|
||||
it( 'Setting does not show any difference until redraw', function () {
|
||||
table.rowGroup().dataSrc( 0 );
|
||||
|
||||
expect( $('#example tbody tr:eq(0) td:eq(0)').html() ).toBe( '61' );
|
||||
} );
|
||||
|
||||
it( 'Setting does not show any difference until redraw', function () {
|
||||
table.draw();
|
||||
|
||||
expect( $('#example tbody tr:eq(0) td:eq(0)').html() ).toBe( 'Tiger Nixon' );
|
||||
} );
|
||||
} );
|
||||
@@ -1,35 +0,0 @@
|
||||
describe( 'rowGroup().disable()', function() {
|
||||
var table;
|
||||
|
||||
dt.libs( {
|
||||
js: [ 'jquery', 'datatables', 'rowgroup' ],
|
||||
css: [ 'datatables', 'rowgroup' ]
|
||||
} );
|
||||
|
||||
dt.html( 'basic' );
|
||||
|
||||
it( 'A DataTable can be created with RowGrouping', function () {
|
||||
table = $('#example').DataTable( {
|
||||
order: [[2, 'asc']],
|
||||
rowGroup: {
|
||||
dataSrc: 2
|
||||
}
|
||||
} );
|
||||
|
||||
expect( $('#example tbody tr:eq(0) td:eq(0)').html() ).toBe( 'Edinburgh' );
|
||||
expect( $('#example tbody tr:eq(1) td:eq(0)').html() ).toBe( 'Tiger Nixon' );
|
||||
} );
|
||||
|
||||
it( 'Does not redraw automatically', function () {
|
||||
table.rowGroup().disable();
|
||||
|
||||
expect( $('#example tbody tr:eq(0) td:eq(0)').html() ).toBe( 'Edinburgh' );
|
||||
expect( $('#example tbody tr:eq(1) td:eq(0)').html() ).toBe( 'Tiger Nixon' );
|
||||
} );
|
||||
|
||||
it( 'Disabled after a redraw', function () {
|
||||
table.draw();
|
||||
|
||||
expect( $('#example tbody tr:eq(0) td:eq(0)').html() ).toBe( 'Tiger Nixon' );
|
||||
} );
|
||||
} );
|
||||
@@ -1,48 +0,0 @@
|
||||
describe( 'rowGroup().enable()', function() {
|
||||
var table;
|
||||
|
||||
dt.libs( {
|
||||
js: [ 'jquery', 'datatables', 'rowgroup' ],
|
||||
css: [ 'datatables', 'rowgroup' ]
|
||||
} );
|
||||
|
||||
dt.html( 'basic' );
|
||||
|
||||
it( 'A DataTable can be created with RowGrouping', function () {
|
||||
table = $('#example').DataTable( {
|
||||
order: [[2, 'asc']],
|
||||
rowGroup: {
|
||||
dataSrc: 2
|
||||
}
|
||||
} );
|
||||
|
||||
expect( $('#example tbody tr:eq(0) td:eq(0)').html() ).toBe( 'Edinburgh' );
|
||||
expect( $('#example tbody tr:eq(1) td:eq(0)').html() ).toBe( 'Tiger Nixon' );
|
||||
} );
|
||||
|
||||
it( 'Disable', function () {
|
||||
table.rowGroup().disable().draw();
|
||||
|
||||
expect( $('#example tbody tr:eq(0) td:eq(0)').html() ).toBe( 'Tiger Nixon' );
|
||||
} );
|
||||
|
||||
it( 'Can be enabled', function () {
|
||||
table.rowGroup().enable().draw();
|
||||
|
||||
expect( $('#example tbody tr:eq(0) td:eq(0)').html() ).toBe( 'Edinburgh' );
|
||||
expect( $('#example tbody tr:eq(1) td:eq(0)').html() ).toBe( 'Tiger Nixon' );
|
||||
} );
|
||||
|
||||
it( 'Can be used as a toggle to disable', function () {
|
||||
table.rowGroup().enable( false ).draw();
|
||||
|
||||
expect( $('#example tbody tr:eq(0) td:eq(0)').html() ).toBe( 'Tiger Nixon' );
|
||||
} );
|
||||
|
||||
it( 'Can be used as a toggle to enable', function () {
|
||||
table.rowGroup().enable( true ).draw();
|
||||
|
||||
expect( $('#example tbody tr:eq(0) td:eq(0)').html() ).toBe( 'Edinburgh' );
|
||||
expect( $('#example tbody tr:eq(1) td:eq(0)').html() ).toBe( 'Tiger Nixon' );
|
||||
} );
|
||||
} );
|
||||
@@ -1,52 +0,0 @@
|
||||
describe( 'rowgroup-datasrc', function() {
|
||||
var table;
|
||||
var args;
|
||||
|
||||
dt.libs( {
|
||||
js: [ 'jquery', 'datatables', 'rowgroup' ],
|
||||
css: [ 'datatables', 'rowgroup' ]
|
||||
} );
|
||||
|
||||
dt.html( 'basic' );
|
||||
|
||||
it( 'A DataTable can be created with RowGrouping', function () {
|
||||
table = $('#example').DataTable( {
|
||||
order: [[2, 'asc']],
|
||||
rowGroup: {
|
||||
dataSrc: 2
|
||||
}
|
||||
} );
|
||||
|
||||
expect( $('#example tbody tr:eq(0) td:eq(0)').html() ).toBe( 'Edinburgh' );
|
||||
expect( $('#example tbody tr:eq(1) td:eq(0)').html() ).toBe( 'Tiger Nixon' );
|
||||
} );
|
||||
|
||||
it( 'Change in the data source will trigger rowgroup-datasrc', function ( done ) {
|
||||
table.on( 'rowgroup-datasrc', function () {
|
||||
args = arguments;
|
||||
done();
|
||||
} );
|
||||
|
||||
table.rowGroup().dataSrc( 3 ).draw();
|
||||
} );
|
||||
|
||||
it( 'Three arguments', function () {
|
||||
expect( args.length ).toBe( 3 );
|
||||
} );
|
||||
|
||||
it( 'First is jQuery object', function () {
|
||||
expect( args[0] instanceof $.Event ).toBe( true );
|
||||
} );
|
||||
|
||||
it( 'Second is DataTable API instance', function () {
|
||||
expect( args[1] instanceof $.fn.dataTable.Api ).toBe( true );
|
||||
} );
|
||||
|
||||
it( 'Third is the new data source value', function () {
|
||||
expect( args[2] ).toBe( 3 );
|
||||
} );
|
||||
|
||||
it( 'Event is triggered with .dt namespace', function () {
|
||||
expect( args[0].namespace ).toBe( 'dt' );
|
||||
} );
|
||||
} );
|
||||
@@ -1,26 +0,0 @@
|
||||
describe( 'RowGroup exists and can be initialised', function() {
|
||||
var table;
|
||||
|
||||
dt.libs( {
|
||||
js: [ 'jquery', 'datatables', 'rowgroup' ],
|
||||
css: [ 'datatables', 'rowgroup' ]
|
||||
} );
|
||||
|
||||
dt.html( 'basic' );
|
||||
|
||||
it( 'Exists', function () {
|
||||
expect( $.fn.dataTable.RowGroup ).toBeDefined();
|
||||
} );
|
||||
|
||||
it( 'A DataTable can be created with RowGrouping', function () {
|
||||
table = $('#example').DataTable( {
|
||||
order: [[2, 'asc']],
|
||||
rowGroup: {
|
||||
dataSrc: 2
|
||||
}
|
||||
} );
|
||||
|
||||
expect( $('#example tbody tr:eq(0) td:eq(0)').html() ).toBe( 'Edinburgh' );
|
||||
expect( $('#example tbody tr:eq(1) td:eq(0)').html() ).toBe( 'Tiger Nixon' );
|
||||
} );
|
||||
} );
|
||||
@@ -1,56 +0,0 @@
|
||||
describe( 'Class name', function() {
|
||||
var table;
|
||||
|
||||
dt.libs( {
|
||||
js: [ 'jquery', 'datatables', 'rowgroup' ],
|
||||
css: [ 'datatables', 'rowgroup' ]
|
||||
} );
|
||||
|
||||
dt.html( 'basic' );
|
||||
|
||||
it( 'Default is `group`', function () {
|
||||
expect( $.fn.dataTable.RowGroup.defaults.className ).toBe( 'group' );
|
||||
} );
|
||||
|
||||
it( 'Is used for header rows', function () {
|
||||
table = $('#example').DataTable( {
|
||||
order: [[2, 'asc']],
|
||||
rowGroup: {
|
||||
dataSrc: 2
|
||||
}
|
||||
} );
|
||||
|
||||
expect( $('#example tbody tr:eq(0)').hasClass('group') ).toBe( true );
|
||||
} );
|
||||
|
||||
dt.html( 'basic' );
|
||||
|
||||
it( 'Can be set to a different value', function () {
|
||||
table = $('#example').DataTable( {
|
||||
order: [[2, 'asc']],
|
||||
rowGroup: {
|
||||
dataSrc: 2,
|
||||
className: 'test'
|
||||
}
|
||||
} );
|
||||
|
||||
expect( $('#example tbody tr:eq(0)').hasClass('group') ).toBe( false );
|
||||
expect( $('#example tbody tr:eq(0)').hasClass('test') ).toBe( true );
|
||||
} );
|
||||
|
||||
dt.html( 'basic' );
|
||||
|
||||
it( 'Is applied to the footer grouping row', function () {
|
||||
table = $('#example').DataTable( {
|
||||
order: [[2, 'asc']],
|
||||
rowGroup: {
|
||||
dataSrc: 2,
|
||||
endRender: function () {
|
||||
return 'Test';
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
expect( $('#example tbody tr:eq(10)').hasClass('group') ).toBe( true );
|
||||
} );
|
||||
} );
|
||||
@@ -1,43 +0,0 @@
|
||||
describe( 'dataSrc', function() {
|
||||
var table;
|
||||
|
||||
dt.libs( {
|
||||
js: [ 'jquery', 'datatables', 'rowgroup' ],
|
||||
css: [ 'datatables', 'rowgroup' ]
|
||||
} );
|
||||
|
||||
dt.html( 'basic' );
|
||||
|
||||
it( 'Default is 0', function () {
|
||||
expect( $.fn.dataTable.RowGroup.defaults.dataSrc ).toBe( 0 );
|
||||
} );
|
||||
|
||||
it( 'Is indeed 0 when run', function () {
|
||||
table = $('#example').DataTable( {
|
||||
rowGroup: true
|
||||
} );
|
||||
|
||||
expect( $('#example tbody tr:eq(0)').text() ).toBe( 'Airi Satou' );
|
||||
} );
|
||||
|
||||
dt.html( 'basic' );
|
||||
|
||||
it( 'Can be used with object data', function () {
|
||||
table = $('#example').DataTable( {
|
||||
order: [[2, 'asc']],
|
||||
columns: [
|
||||
{ data: 'name' },
|
||||
{ data: 'position' },
|
||||
{ data: 'office' },
|
||||
{ data: 'age' },
|
||||
{ data: 'startDate' },
|
||||
{ data: 'salary' }
|
||||
],
|
||||
rowGroup: {
|
||||
dataSrc: 'office'
|
||||
}
|
||||
} );
|
||||
|
||||
expect( $('#example tbody tr:eq(0)').text() ).toBe( 'Edinburgh' );
|
||||
} );
|
||||
} );
|
||||
@@ -1,40 +0,0 @@
|
||||
describe( 'Enable', function() {
|
||||
var table;
|
||||
|
||||
dt.libs( {
|
||||
js: [ 'jquery', 'datatables', 'rowgroup' ],
|
||||
css: [ 'datatables', 'rowgroup' ]
|
||||
} );
|
||||
|
||||
dt.html( 'basic' );
|
||||
|
||||
it( 'Default is enable', function () {
|
||||
expect( $.fn.dataTable.RowGroup.defaults.enable ).toBe( true );
|
||||
} );
|
||||
|
||||
it( 'Is indeed enabled', function () {
|
||||
table = $('#example').DataTable( {
|
||||
order: [[2, 'asc']],
|
||||
rowGroup: {
|
||||
dataSrc: 2
|
||||
}
|
||||
} );
|
||||
|
||||
expect( $('#example tbody tr:eq(0)').hasClass('group') ).toBe( true );
|
||||
} );
|
||||
|
||||
dt.html( 'basic' );
|
||||
|
||||
it( 'Can be disabled', function () {
|
||||
table = $('#example').DataTable( {
|
||||
order: [[2, 'asc']],
|
||||
rowGroup: {
|
||||
dataSrc: 2,
|
||||
enable: false
|
||||
}
|
||||
} );
|
||||
|
||||
expect( $('#example tbody tr:eq(0)').hasClass('group') ).toBe( false );
|
||||
expect( $('#example tbody tr').length ).toBe( 10 );
|
||||
} );
|
||||
} );
|
||||
@@ -1,46 +0,0 @@
|
||||
describe( 'End class name', function() {
|
||||
var table;
|
||||
|
||||
dt.libs( {
|
||||
js: [ 'jquery', 'datatables', 'rowgroup' ],
|
||||
css: [ 'datatables', 'rowgroup' ]
|
||||
} );
|
||||
|
||||
dt.html( 'basic' );
|
||||
|
||||
it( 'Default is `group-end`', function () {
|
||||
expect( $.fn.dataTable.RowGroup.defaults.endClassName ).toBe( 'group-end' );
|
||||
} );
|
||||
|
||||
it( 'Is used', function () {
|
||||
table = $('#example').DataTable( {
|
||||
order: [[2, 'asc']],
|
||||
rowGroup: {
|
||||
dataSrc: 2,
|
||||
endRender: function () {
|
||||
return 'Test';
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
expect( $('#example tbody tr:eq(10)').hasClass('group-end') ).toBe( true );
|
||||
} );
|
||||
|
||||
dt.html( 'basic' );
|
||||
|
||||
it( 'Can be changed', function () {
|
||||
table = $('#example').DataTable( {
|
||||
order: [[2, 'asc']],
|
||||
rowGroup: {
|
||||
dataSrc: 2,
|
||||
endRender: function () {
|
||||
return 'Test';
|
||||
},
|
||||
endClassName: 'test'
|
||||
}
|
||||
} );
|
||||
|
||||
expect( $('#example tbody tr:eq(10)').hasClass('group-end') ).toBe( false );
|
||||
expect( $('#example tbody tr:eq(10)').hasClass('test') ).toBe( true );
|
||||
} );
|
||||
} );
|
||||
@@ -1,88 +0,0 @@
|
||||
describe( 'End render', function() {
|
||||
var table;
|
||||
|
||||
dt.libs( {
|
||||
js: [ 'jquery', 'datatables', 'rowgroup' ],
|
||||
css: [ 'datatables', 'rowgroup' ]
|
||||
} );
|
||||
|
||||
dt.html( 'basic' );
|
||||
|
||||
it( 'Default is null', function () {
|
||||
expect( $.fn.dataTable.RowGroup.defaults.endRender ).toBe( null );
|
||||
} );
|
||||
|
||||
it( 'Can be used to show the grouping data name', function () {
|
||||
table = $('#example').DataTable( {
|
||||
order: [[2, 'asc']],
|
||||
rowGroup: {
|
||||
dataSrc: 2,
|
||||
endRender: function ( rows, group ) {
|
||||
return group;
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
expect( $('#example tbody tr:eq(10)').text() ).toBe( 'Edinburgh' );
|
||||
expect( $('#example tbody tr:eq(13)').text() ).toBe( 'London' );
|
||||
} );
|
||||
|
||||
dt.html( 'basic' );
|
||||
|
||||
it( 'Will show a static value', function () {
|
||||
table = $('#example').DataTable( {
|
||||
order: [[2, 'asc']],
|
||||
rowGroup: {
|
||||
dataSrc: 2,
|
||||
endRender: function ( rows, group ) {
|
||||
return 'Test';
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
expect( $('#example tbody tr:eq(10)').text() ).toBe( 'Test' );
|
||||
expect( $('#example tbody tr:eq(13)').text() ).toBe( 'Test' );
|
||||
} );
|
||||
|
||||
dt.html( 'basic' );
|
||||
|
||||
var a1 = [];
|
||||
var a2 = [];
|
||||
|
||||
it( 'Renderer is called with two arguments', function () {
|
||||
var args;
|
||||
|
||||
table = $('#example').DataTable( {
|
||||
order: [[2, 'asc']],
|
||||
rowGroup: {
|
||||
dataSrc: 2,
|
||||
endRender: function ( rows, group ) {
|
||||
a1.push( rows );
|
||||
a2.push( group );
|
||||
args = arguments.length;
|
||||
return group;
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
expect( args ).toBe( 2 );
|
||||
} );
|
||||
|
||||
it( 'Is called once for each group on the page', function () {
|
||||
expect( a1.length ).toBe( 2 );
|
||||
} );
|
||||
|
||||
it( 'First argument is an API instance', function () {
|
||||
expect( a1[0] instanceof $.fn.dataTable.Api ).toBe( true );
|
||||
} );
|
||||
|
||||
it( 'First argument has the rows for the group in it', function () {
|
||||
expect( a1[0].count() ).toBe( 9 );
|
||||
expect( a1[1].count() ).toBe( 1 );
|
||||
} );
|
||||
|
||||
it( 'Second argument has the group name', function () {
|
||||
expect( a2[0] ).toBe( 'Edinburgh' );
|
||||
expect( a2[1] ).toBe( 'London' );
|
||||
} );
|
||||
} );
|
||||
@@ -1,40 +0,0 @@
|
||||
describe( 'Start class name', function() {
|
||||
var table;
|
||||
|
||||
dt.libs( {
|
||||
js: [ 'jquery', 'datatables', 'rowgroup' ],
|
||||
css: [ 'datatables', 'rowgroup' ]
|
||||
} );
|
||||
|
||||
dt.html( 'basic' );
|
||||
|
||||
it( 'Default is `group-start`', function () {
|
||||
expect( $.fn.dataTable.RowGroup.defaults.startClassName ).toBe( 'group-start' );
|
||||
} );
|
||||
|
||||
it( 'Is used', function () {
|
||||
table = $('#example').DataTable( {
|
||||
order: [[2, 'asc']],
|
||||
rowGroup: {
|
||||
dataSrc: 2
|
||||
}
|
||||
} );
|
||||
|
||||
expect( $('#example tbody tr:eq(0)').hasClass('group-start') ).toBe( true );
|
||||
} );
|
||||
|
||||
dt.html( 'basic' );
|
||||
|
||||
it( 'Can be changed', function () {
|
||||
table = $('#example').DataTable( {
|
||||
order: [[2, 'asc']],
|
||||
rowGroup: {
|
||||
dataSrc: 2,
|
||||
startClassName: 'test'
|
||||
}
|
||||
} );
|
||||
|
||||
expect( $('#example tbody tr:eq(0)').hasClass('group-start') ).toBe( false );
|
||||
expect( $('#example tbody tr:eq(0)').hasClass('test') ).toBe( true );
|
||||
} );
|
||||
} );
|
||||
@@ -1,121 +0,0 @@
|
||||
describe( 'Start render', function() {
|
||||
var table;
|
||||
|
||||
dt.libs( {
|
||||
js: [ 'jquery', 'datatables', 'rowgroup' ],
|
||||
css: [ 'datatables', 'rowgroup' ]
|
||||
} );
|
||||
|
||||
dt.html( 'basic' );
|
||||
|
||||
it( 'Default is defined as a function', function () {
|
||||
expect( typeof $.fn.dataTable.RowGroup.defaults.startRender ).toBe( 'function' );
|
||||
} );
|
||||
|
||||
it( 'Default is to show the grouping data name', function () {
|
||||
table = $('#example').DataTable( {
|
||||
order: [[2, 'asc']],
|
||||
rowGroup: {
|
||||
dataSrc: 2
|
||||
}
|
||||
} );
|
||||
|
||||
expect( $('#example tbody tr:eq(0)').text() ).toBe( 'Edinburgh' );
|
||||
expect( $('#example tbody tr:eq(10)').text() ).toBe( 'London' );
|
||||
} );
|
||||
|
||||
dt.html( 'basic' );
|
||||
|
||||
it( 'Will show a static value', function () {
|
||||
table = $('#example').DataTable( {
|
||||
order: [[2, 'asc']],
|
||||
rowGroup: {
|
||||
dataSrc: 2,
|
||||
startRender: function ( rows, group ) {
|
||||
return 'Test';
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
expect( $('#example tbody tr:eq(0)').text() ).toBe( 'Test' );
|
||||
expect( $('#example tbody tr:eq(10)').text() ).toBe( 'Test' );
|
||||
} );
|
||||
|
||||
dt.html( 'basic' );
|
||||
|
||||
var a1 = [];
|
||||
var a2 = [];
|
||||
|
||||
it( 'Renderer is called with two arguments', function () {
|
||||
var args;
|
||||
|
||||
table = $('#example').DataTable( {
|
||||
order: [[2, 'asc']],
|
||||
rowGroup: {
|
||||
dataSrc: 2,
|
||||
startRender: function ( rows, group ) {
|
||||
a1.push( rows );
|
||||
a2.push( group );
|
||||
args = arguments.length;
|
||||
return group;
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
expect( args ).toBe( 2 );
|
||||
} );
|
||||
|
||||
it( 'Is called once for each group on the page', function () {
|
||||
expect( a1.length ).toBe( 2 );
|
||||
} );
|
||||
|
||||
it( 'First argument is an API instance', function () {
|
||||
expect( a1[0] instanceof $.fn.dataTable.Api ).toBe( true );
|
||||
} );
|
||||
|
||||
it( 'First argument has the rows for the group in it', function () {
|
||||
expect( a1[0].count() ).toBe( 9 );
|
||||
expect( a1[1].count() ).toBe( 1 );
|
||||
} );
|
||||
|
||||
it( 'Second argument has the group name', function () {
|
||||
expect( a2[0] ).toBe( 'Edinburgh' );
|
||||
expect( a2[1] ).toBe( 'London' );
|
||||
} );
|
||||
|
||||
dt.html( 'basic' );
|
||||
|
||||
it( 'Can return a jQuery object', function () {
|
||||
var args;
|
||||
|
||||
table = $('#example').DataTable( {
|
||||
order: [[2, 'asc']],
|
||||
rowGroup: {
|
||||
dataSrc: 2,
|
||||
startRender: function ( rows, group ) {
|
||||
return $('<tr><td>Test jQuery</td></tr>');
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
expect( $('#example tbody tr:eq(0)').text() ).toBe( 'Test jQuery' );
|
||||
} );
|
||||
|
||||
dt.html( 'basic' );
|
||||
|
||||
it( 'Can return a node', function () {
|
||||
var args;
|
||||
|
||||
table = $('#example').DataTable( {
|
||||
order: [[2, 'asc']],
|
||||
rowGroup: {
|
||||
dataSrc: 2,
|
||||
startRender: function ( rows, group ) {
|
||||
return $('<tr><td>Test node</td></tr>')[0];
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
expect( $('#example tbody tr:eq(0)').text() ).toBe( 'Test node' );
|
||||
} );
|
||||
} );
|
||||
@@ -927,17 +927,19 @@
|
||||
<span class="btn disabled btn-fake">{{ @indexData.label }}</span>
|
||||
</div>
|
||||
<div class="col-xs-3 text-right">
|
||||
<check if="{{ @indexData.countBuild >= @indexData.countAll }}">
|
||||
<kbd class="txt-color txt-color-success">{{ @indexData.countBuild }}/{{ @indexData.countAll }}</kbd>
|
||||
</check>
|
||||
<check if="{{ @indexData.countBuild > 0 && @indexData.countBuild < @indexData.countAll}}">
|
||||
<kbd class="txt-color txt-color-warning">{{ @indexData.countBuild }}/{{ @indexData.countAll }}</kbd>
|
||||
</check>
|
||||
<check if="{{ @indexData.countBuild <= 0 }}">
|
||||
<kbd class="txt-color txt-color-danger">{{ @indexData.countBuild }}/{{ @indexData.countAll }}</kbd>
|
||||
</check>
|
||||
<check if="{{ @indexData.tooltip }}">
|
||||
<i class="fas fa-fw fa-sm fa-question-circle pf-help-light" title="{{ @indexData.tooltip }}"></i>
|
||||
<check if="{{ isset(@indexData.countAll) }}">
|
||||
<check if="{{ @indexData.countBuild >= @indexData.countAll }}">
|
||||
<kbd class="txt-color txt-color-success">{{ @indexData.countBuild }}/{{ @indexData.countAll }}</kbd>
|
||||
</check>
|
||||
<check if="{{ @indexData.countBuild > 0 && @indexData.countBuild < @indexData.countAll}}">
|
||||
<kbd class="txt-color txt-color-warning">{{ @indexData.countBuild }}/{{ @indexData.countAll }}</kbd>
|
||||
</check>
|
||||
<check if="{{ @indexData.countBuild <= 0 }}">
|
||||
<kbd class="txt-color txt-color-danger">{{ @indexData.countBuild }}/{{ @indexData.countAll }}</kbd>
|
||||
</check>
|
||||
<check if="{{ @indexData.tooltip }}">
|
||||
<i class="fas fa-fw fa-sm fa-question-circle pf-help-light" title="{{ @indexData.tooltip }}"></i>
|
||||
</check>
|
||||
</check>
|
||||
</div>
|
||||
<div class="col-xs-5">
|
||||
|
||||
@@ -124,6 +124,7 @@ fieldset[disabled]{
|
||||
display: block;
|
||||
height: 100%;
|
||||
background-color: rgba($green, .2 );
|
||||
max-width: 100%;
|
||||
width: 0;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
||||
Reference in New Issue
Block a user