landing page pricing table, map bug fixes, signature module improvement
This commit is contained in:
5366
.idea/dataSources.ids
generated
5366
.idea/dataSources.ids
generated
File diff suppressed because it is too large
Load Diff
2
.idea/dataSources.xml
generated
2
.idea/dataSources.xml
generated
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DataSourceManagerImpl" format="xml" hash="1236303993">
|
||||
<component name="DataSourceManagerImpl" format="xml" hash="629353432">
|
||||
<data-source source="LOCAL" name="Pathfinder" uuid="da3cf616-be39-4091-94bd-76d70f41765d">
|
||||
<driver-ref>mysql</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
|
||||
1
.idea/dictionaries/exodus4d.xml
generated
1
.idea/dictionaries/exodus4d.xml
generated
@@ -39,6 +39,7 @@
|
||||
<w>tbody</w>
|
||||
<w>textarea</w>
|
||||
<w>timelimit</w>
|
||||
<w>viewport</w>
|
||||
<w>waypoint</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
|
||||
6
.idea/sqldialects.xml
generated
Normal file
6
.idea/sqldialects.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="SqlDialectMappings">
|
||||
<file url="file://$PROJECT_DIR$/app" dialect="MySQL" />
|
||||
</component>
|
||||
</project>
|
||||
1497
.idea/workspace.xml
generated
1497
.idea/workspace.xml
generated
File diff suppressed because it is too large
Load Diff
@@ -56,6 +56,16 @@ NAME = "PATHFINDER"
|
||||
VERSION = "v0.10"
|
||||
CONTACT = "https://github.com/exodus4d"
|
||||
|
||||
; Max number of maps an entity can create
|
||||
MAX_MAPS_PRIVATE = 3
|
||||
MAX_MAPS_CORPORATION = 3
|
||||
MAX_MAPS_ALLIANCE = 3
|
||||
|
||||
; Max number of shared entities per map
|
||||
MAX_SHARED_USER = 10
|
||||
MAX_SHARED_CORPORATION = 3
|
||||
MAX_SHARED_ALLIANCE = 2
|
||||
|
||||
; ======================================================================================================
|
||||
[api_path]
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
* https://github.com/ikkez/F3-Sugar/
|
||||
*
|
||||
* @package DB
|
||||
* @version 1.3.0
|
||||
* @version 1.3.1-dev
|
||||
* @since 24.04.2012
|
||||
* @date 19.01.2015
|
||||
*/
|
||||
@@ -44,7 +44,7 @@ class Cortex extends Cursor {
|
||||
$dbsType, // mapper engine type [jig, sql, mongo]
|
||||
$fieldsCache, // relation field cache
|
||||
$saveCsd, // mm rel save cascade
|
||||
$collectionID, // collection set identifier
|
||||
$collection, // collection
|
||||
$relFilter, // filter for loading related models
|
||||
$hasCond, // IDs of records the next find should have
|
||||
$whitelist, // restrict to these fields
|
||||
@@ -107,7 +107,9 @@ class Cortex extends Cursor {
|
||||
$this->dbsType = 'mongo';
|
||||
if ($table)
|
||||
$this->table = $table;
|
||||
if (!$this->primary || $this->dbsType != 'sql')
|
||||
if ($this->dbsType != 'sql')
|
||||
$this->primary = '_id';
|
||||
elseif (!$this->primary)
|
||||
$this->primary = 'id';
|
||||
if (!$this->table && !$this->fluid)
|
||||
trigger_error(self::E_NO_TABLE);
|
||||
@@ -149,8 +151,10 @@ class Cortex extends Cursor {
|
||||
$this->standardiseID = $f3->exists('CORTEX.standardiseID') ?
|
||||
$f3->get('CORTEX.standardiseID') : TRUE;
|
||||
if(!empty($this->fieldConf))
|
||||
foreach($this->fieldConf as &$conf)
|
||||
foreach($this->fieldConf as &$conf) {
|
||||
$conf=static::resolveRelationConf($conf);
|
||||
unset($conf);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -236,8 +240,22 @@ class Cortex extends Cursor {
|
||||
return $conf;
|
||||
}
|
||||
|
||||
public function addToCollection($cID) {
|
||||
$this->collectionID = $cID;
|
||||
/**
|
||||
* give this model a reference to the collection it is part of
|
||||
* @param CortexCollection $cx
|
||||
*/
|
||||
public function addToCollection($cx) {
|
||||
$this->collection = $cx;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the collection where this model lives in
|
||||
* @return CortexCollection
|
||||
*/
|
||||
protected function getCollection()
|
||||
{
|
||||
return ($this->collection && $this->smartLoading)
|
||||
? $this->collection : false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -303,8 +321,8 @@ class Cortex extends Cursor {
|
||||
$rel['fieldConf'][$relConf[1]]['has-many']);
|
||||
if (!in_array($mmTable,$schema->getTables())) {
|
||||
$mmt = $schema->createTable($mmTable);
|
||||
$mmt->addColumn($relConf[1])->type_int();
|
||||
$mmt->addColumn($key)->type_int();
|
||||
$mmt->addColumn($relConf[1])->type($relConf['relFieldType']);
|
||||
$mmt->addColumn($key)->type($field['type']);
|
||||
$index = array($relConf[1],$key);
|
||||
sort($index);
|
||||
$mmt->addIndex($index);
|
||||
@@ -321,7 +339,9 @@ class Cortex extends Cursor {
|
||||
if (in_array($field['type'], array(self::DT_JSON, self::DT_SERIALIZED)))
|
||||
$field['type']=$schema::DT_TEXT;
|
||||
// defaults values
|
||||
if (!array_key_exists('nullable', $field)) $field['nullable'] = true;
|
||||
if (!array_key_exists('nullable', $field))
|
||||
$field['nullable'] = true;
|
||||
unset($field);
|
||||
}
|
||||
if (!in_array($table, $schema->getTables())) {
|
||||
// create table
|
||||
@@ -435,6 +455,26 @@ class Cortex extends Cursor {
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* get mm table name from config
|
||||
* @param array $conf own relation config
|
||||
* @param string $key relation field
|
||||
* @param null|array $fConf optional foreign config
|
||||
* @return string
|
||||
*/
|
||||
protected function mmTable($conf, $key, $fConf=null)
|
||||
{
|
||||
if (!isset($conf['refTable'])) {
|
||||
// compute mm table name
|
||||
$mmTable = isset($conf[2]) ? $conf[2] :
|
||||
static::getMMTableName($conf['relTable'],
|
||||
$conf['relField'], $this->getTable(), $key, $fConf);
|
||||
$this->fieldConf[$key]['has-many']['refTable'] = $mmTable;
|
||||
} else
|
||||
$mmTable = $conf['refTable'];
|
||||
return $mmTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* resolve relation field types
|
||||
* @param $field
|
||||
@@ -448,7 +488,7 @@ class Cortex extends Cursor {
|
||||
$relConf = array($relConf, '_id');
|
||||
// set field type
|
||||
if ($relConf[1] == '_id')
|
||||
$field['type'] = Schema::DT_INT8;
|
||||
$field['type'] = Schema::DT_INT4;
|
||||
else {
|
||||
// find foreign field type
|
||||
$fc = $relConf[0]::resolveConfiguration();
|
||||
@@ -465,6 +505,8 @@ class Cortex extends Cursor {
|
||||
}
|
||||
elseif (array_key_exists('has-many', $field)){
|
||||
$field['relType'] = 'has-many';
|
||||
if (!isset($field['type']))
|
||||
$field['type'] = Schema::DT_INT;
|
||||
$relConf = $field['has-many'];
|
||||
if(!is_array($relConf))
|
||||
return $field;
|
||||
@@ -473,7 +515,9 @@ class Cortex extends Cursor {
|
||||
$field['has-many']['hasRel'] = 'has-many';
|
||||
$field['has-many']['relTable'] = $rel['table'];
|
||||
$field['has-many']['relField'] = $relConf[1];
|
||||
$field['has-many']['relPK'] = $rel['primary'];
|
||||
$field['has-many']['relFieldType'] = isset($rel['fieldConf'][$relConf[1]]['type']) ?
|
||||
$rel['fieldConf'][$relConf[1]]['type'] : Schema::DT_INT;
|
||||
$field['has-many']['relPK'] = isset($relConf[3])?$relConf[3]:$rel['primary'];
|
||||
} else {
|
||||
$field['has-many']['hasRel'] = 'belongs-to-one';
|
||||
$toConf=$rel['fieldConf'][$relConf[1]]['belongs-to-one'];
|
||||
@@ -543,8 +587,9 @@ class Cortex extends Cursor {
|
||||
foreach($result as &$mapper) {
|
||||
$cr=$mapper->get($counter);
|
||||
$mapper->virtual('count_'.$counter,$cr?count($cr):null);
|
||||
unset($mapper);
|
||||
}
|
||||
$cc = new \DB\CortexCollection();
|
||||
$cc = new CortexCollection();
|
||||
$cc->setModels($result);
|
||||
if($sort) {
|
||||
$cc->orderBy($options['order']);
|
||||
@@ -604,6 +649,10 @@ class Cortex extends Cursor {
|
||||
if ($this->hasCond) {
|
||||
foreach($this->hasCond as $key => $hasCond) {
|
||||
$addToFilter = null;
|
||||
if ($deep = is_int(strpos($key,'.'))) {
|
||||
$key = rtrim($key,'.');
|
||||
$hasCond = array(null,null);
|
||||
}
|
||||
list($has_filter,$has_options) = $hasCond;
|
||||
$type = $this->fieldConf[$key]['relType'];
|
||||
$fromConf = $this->fieldConf[$key][$type];
|
||||
@@ -618,7 +667,7 @@ class Cortex extends Cursor {
|
||||
$id=$fromConf['relField'];
|
||||
// many-to-many
|
||||
if ($type == 'has-many' && $fromConf['hasRel'] == 'has-many') {
|
||||
if ($this->dbsType == 'sql'
|
||||
if (!$deep && $this->dbsType == 'sql'
|
||||
&& !isset($has_options['limit']) && !isset($has_options['offset'])) {
|
||||
$hasJoin = array_merge($hasJoin,
|
||||
$this->_hasJoinMM_sql($key,$hasCond,$filter,$options));
|
||||
@@ -639,7 +688,7 @@ class Cortex extends Cursor {
|
||||
break;
|
||||
// one-to-*
|
||||
case 'belongs-to-one':
|
||||
if ($this->dbsType == 'sql'
|
||||
if (!$deep && $this->dbsType == 'sql'
|
||||
&& !isset($has_options['limit']) && !isset($has_options['offset'])) {
|
||||
if (!is_array($fromConf))
|
||||
$fromConf = array($fromConf, '_id');
|
||||
@@ -660,7 +709,10 @@ class Cortex extends Cursor {
|
||||
$filter = array('');
|
||||
if (!empty($filter[0]))
|
||||
$filter[0] .= ' and ';
|
||||
$filter[0] .= '('.array_shift($addToFilter).')';
|
||||
$cond = array_shift($addToFilter);
|
||||
if ($this->dbsType=='sql')
|
||||
$cond = $this->_sql_quoteCondition($cond,$this->db->quotekey($this->getTable()));
|
||||
$filter[0] .= '('.$cond.')';
|
||||
$filter = array_merge($filter, $addToFilter);
|
||||
}
|
||||
}
|
||||
@@ -726,6 +778,8 @@ class Cortex extends Cursor {
|
||||
// factory new mappers
|
||||
$mapper = clone($this->mapper);
|
||||
$mapper->reset();
|
||||
// TODO: refactor this. Reflection can be removed for F3 >= v3.4.1
|
||||
$mapper->query= array($record);
|
||||
$m_adhoc = empty($adhoc) ? array() : $m_refl_adhoc;
|
||||
foreach ($record as $key=>$val)
|
||||
if (isset($m_refl_adhoc[$key]))
|
||||
@@ -787,13 +841,20 @@ class Cortex extends Cursor {
|
||||
* @return $this
|
||||
*/
|
||||
public function has($key, $filter, $options = null) {
|
||||
if (!isset($this->fieldConf[$key]))
|
||||
trigger_error(sprintf(self::E_UNKNOWN_FIELD,$key,get_called_class()));
|
||||
if (!isset($this->fieldConf[$key]['relType']))
|
||||
trigger_error(self::E_HAS_COND);
|
||||
if (is_string($filter))
|
||||
$filter=array($filter);
|
||||
$this->hasCond[$key] = array($filter,$options);
|
||||
if (is_int(strpos($key,'.'))) {
|
||||
list($key,$fkey) = explode('.',$key,2);
|
||||
if (!isset($this->hasCond[$key.'.']))
|
||||
$this->hasCond[$key.'.'] = array();
|
||||
$this->hasCond[$key.'.'][$fkey] = array($filter,$options);
|
||||
} else {
|
||||
if (!isset($this->fieldConf[$key]))
|
||||
trigger_error(sprintf(self::E_UNKNOWN_FIELD,$key,get_called_class()));
|
||||
if (!isset($this->fieldConf[$key]['relType']))
|
||||
trigger_error(self::E_HAS_COND);
|
||||
$this->hasCond[$key] = array($filter,$options);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -809,12 +870,8 @@ class Cortex extends Cursor {
|
||||
{
|
||||
$type = $this->fieldConf[$key]['relType'];
|
||||
$fieldConf = $this->fieldConf[$key][$type];
|
||||
if (!is_array($fieldConf))
|
||||
// one-to-many shortcut
|
||||
$fieldConf = array($fieldConf, '_id');
|
||||
$rel = $this->getRelInstance($fieldConf[0],null,$key);
|
||||
if($this->dbsType=='sql' && $fieldConf[1] == '_id')
|
||||
$fieldConf[1] = $rel->primary;
|
||||
// one-to-many shortcut
|
||||
$rel = $this->getRelFromConf($fieldConf,$key);
|
||||
$hasSet = $rel->find($filter, $options, $ttl);
|
||||
if (!$hasSet)
|
||||
return false;
|
||||
@@ -833,18 +890,12 @@ class Cortex extends Cursor {
|
||||
protected function _hasRefsInMM($key, $filter, $options, $ttl=0)
|
||||
{
|
||||
$fieldConf = $this->fieldConf[$key]['has-many'];
|
||||
$rel = $this->getRelInstance($fieldConf[0],null,$key);
|
||||
$rel = $this->getRelInstance($fieldConf[0],null,$key,true);
|
||||
$hasSet = $rel->find($filter,$options,$ttl);
|
||||
$result = false;
|
||||
if ($hasSet) {
|
||||
$hasIDs = $hasSet->getAll('_id',true);
|
||||
if (!array_key_exists('refTable', $fieldConf)) {
|
||||
$mmTable = isset($fieldConf[2]) ? $fieldConf[2] :
|
||||
static::getMMTableName($fieldConf['relTable'],
|
||||
$fieldConf['relField'], $this->getTable(), $key);
|
||||
$this->fieldConf[$key]['has-many']['refTable'] = $mmTable;
|
||||
} else
|
||||
$mmTable = $fieldConf['refTable'];
|
||||
$mmTable = $this->mmTable($fieldConf,$key);
|
||||
$pivot = $this->getRelInstance(null,array('db'=>$this->db,'table'=>$mmTable));
|
||||
$pivotSet = $pivot->find(array($key.' IN ?',$hasIDs),null,$ttl);
|
||||
if ($pivotSet)
|
||||
@@ -860,14 +911,7 @@ class Cortex extends Cursor {
|
||||
{
|
||||
$fieldConf = $this->fieldConf[$key]['has-many'];
|
||||
$hasJoin = array();
|
||||
if (!array_key_exists('refTable', $fieldConf)) {
|
||||
// compute mm table name
|
||||
$mmTable = isset($fieldConf[2]) ? $fieldConf[2] :
|
||||
static::getMMTableName($fieldConf['relTable'],
|
||||
$fieldConf['relField'], $this->getTable(), $key);
|
||||
$this->fieldConf[$key]['has-many']['refTable'] = $mmTable;
|
||||
} else
|
||||
$mmTable = $fieldConf['refTable'];
|
||||
$mmTable = $this->mmTable($fieldConf,$key);
|
||||
$hasJoin[] = $this->_sql_left_join($this->primary,$this->table,$fieldConf['relField'],$mmTable);
|
||||
$hasJoin[] = $this->_sql_left_join($key,$mmTable,$fieldConf['relPK'],$fieldConf['relTable']);
|
||||
$this->_sql_mergeRelCondition($hasCond,$fieldConf['relTable'],$filter,$options);
|
||||
@@ -948,7 +992,13 @@ class Cortex extends Cursor {
|
||||
*/
|
||||
public function filter($key,$filter=null,$option=null)
|
||||
{
|
||||
$this->relFilter[$key] = array($filter,$option);
|
||||
if (is_int(strpos($key,'.'))) {
|
||||
list($key,$fkey) = explode('.',$key,2);
|
||||
if (!isset($this->relFilter[$key.'.']))
|
||||
$this->relFilter[$key.'.'] = array();
|
||||
$this->relFilter[$key.'.'][$fkey] = array($filter,$option);
|
||||
} else
|
||||
$this->relFilter[$key] = array($filter,$option);
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -1002,7 +1052,7 @@ class Cortex extends Cursor {
|
||||
public function erase($filter = null)
|
||||
{
|
||||
$filter = $this->queryParser->prepareFilter($filter, $this->dbsType);
|
||||
if ((!$filter && $this->emit('beforeerase')!==false) || $filter) {
|
||||
if (!$filter && $this->emit('beforeerase')!==false) {
|
||||
if ($this->fieldConf) {
|
||||
foreach($this->fieldConf as $field => $conf)
|
||||
if (isset($conf['has-many']) &&
|
||||
@@ -1010,10 +1060,10 @@ class Cortex extends Cursor {
|
||||
$this->set($field,null);
|
||||
$this->save();
|
||||
}
|
||||
$this->mapper->erase();
|
||||
$this->emit('aftererase');
|
||||
} elseif($filter)
|
||||
$this->mapper->erase($filter);
|
||||
if (!$filter)
|
||||
$this->emit('aftererase');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1031,22 +1081,22 @@ class Cortex extends Cursor {
|
||||
return false;
|
||||
$result=$this->update();
|
||||
}
|
||||
// update changed collections
|
||||
$fields = $this->fieldConf;
|
||||
if ($fields)
|
||||
foreach($fields as $key=>$conf)
|
||||
if (!empty($this->fieldsCache[$key]) && $this->fieldsCache[$key] instanceof CortexCollection
|
||||
&& $this->fieldsCache[$key]->hasChanged())
|
||||
$this->set($key,$this->fieldsCache[$key]->getAll('_id',true));
|
||||
|
||||
// m:m save cascade
|
||||
if (!empty($this->saveCsd)) {
|
||||
$fields = $this->fieldConf;
|
||||
foreach($this->saveCsd as $key => $val) {
|
||||
if($fields[$key]['relType'] == 'has-many') {
|
||||
$relConf = $fields[$key]['has-many'];
|
||||
if (!isset($relConf['refTable'])) {
|
||||
// compute mm table name
|
||||
$mmTable = isset($relConf[2]) ? $relConf[2] :
|
||||
static::getMMTableName($relConf['relTable'],
|
||||
$relConf['relField'], $this->getTable(), $key);
|
||||
$this->fieldConf[$key]['has-many']['refTable'] = $mmTable;
|
||||
} else
|
||||
$mmTable = $relConf['refTable'];
|
||||
$mmTable = $this->mmTable($relConf,$key);
|
||||
$rel = $this->getRelInstance(null, array('db'=>$this->db, 'table'=>$mmTable));
|
||||
$id = $this->get('_id',true);
|
||||
$id = $this->get($relConf['relPK'],true);
|
||||
// delete all refs
|
||||
if (is_null($val))
|
||||
$rel->erase(array($relConf['relField'].' = ?', $id));
|
||||
@@ -1065,6 +1115,7 @@ class Cortex extends Cursor {
|
||||
$val->save();
|
||||
}
|
||||
}
|
||||
$this->saveCsd = array();
|
||||
}
|
||||
$this->emit($new?'afterinsert':'afterupdate');
|
||||
return $result;
|
||||
@@ -1116,14 +1167,7 @@ class Cortex extends Cursor {
|
||||
if ($relConf['hasRel']=='has-many') {
|
||||
// many-to-many
|
||||
if ($this->dbsType == 'sql') {
|
||||
if (!isset($relConf['refTable'])) {
|
||||
// compute mm table name
|
||||
$mmTable = isset($relConf[2]) ? $relConf[2] :
|
||||
static::getMMTableName($relConf['relTable'],
|
||||
$relConf['relField'], $this->getTable(), $key);
|
||||
$this->fieldConf[$key]['has-many']['refTable'] = $mmTable;
|
||||
} else
|
||||
$mmTable = $relConf['refTable'];
|
||||
$mmTable = $this->mmTable($relConf,$key);
|
||||
$filter = array($this->db->quotekey($mmTable).'.'.$this->db->quotekey($relConf['relField'])
|
||||
.' = '.$this->db->quotekey($this->getTable()).'.'.$this->db->quotekey($this->primary));
|
||||
$from=$mmTable;
|
||||
@@ -1187,6 +1231,23 @@ class Cortex extends Cursor {
|
||||
$this->grp_stack['finalize'].=$opt['finalize'];
|
||||
}
|
||||
|
||||
/**
|
||||
* update a given date or time field with the current time
|
||||
* @param string $key
|
||||
*/
|
||||
public function touch($key) {
|
||||
if (isset($this->fieldConf[$key])
|
||||
&& isset($this->fieldConf[$key]['type'])) {
|
||||
$type = $this->fieldConf[$key]['type'];
|
||||
$date = ($this->dbsType=='sql' && preg_match('/mssql|sybase|dblib|odbc|sqlsrv/',
|
||||
$this->db->driver())) ? 'Ymd' : 'Y-m-d';
|
||||
if ($type == Schema::DT_DATETIME || Schema::DT_TIMESTAMP)
|
||||
$this->set($key,date($date.' H:i:s'));
|
||||
elseif ($type == Schema::DT_DATE)
|
||||
$this->set($key,date($date));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind value to key
|
||||
* @return mixed
|
||||
@@ -1283,9 +1344,11 @@ class Cortex extends Cursor {
|
||||
$schema = new Schema($this->db);
|
||||
$table = $schema->alterTable($this->table);
|
||||
// add missing field
|
||||
if(!in_array($key,$table->getCols())) {
|
||||
if (!in_array($key,$table->getCols())) {
|
||||
// determine data type
|
||||
if (is_int($val)) $type = $schema::DT_INT;
|
||||
if (isset($this->fieldConf[$key]) && isset($this->fieldConf[$key]['type']))
|
||||
$type = $this->fieldConf[$key]['type'];
|
||||
elseif (is_int($val)) $type = $schema::DT_INT;
|
||||
elseif (is_double($val)) $type = $schema::DT_DOUBLE;
|
||||
elseif (is_float($val)) $type = $schema::DT_FLOAT;
|
||||
elseif (is_bool($val)) $type = $schema::DT_BOOLEAN;
|
||||
@@ -1377,7 +1440,7 @@ class Cortex extends Cursor {
|
||||
return $out;
|
||||
}
|
||||
$fields = $this->fieldConf;
|
||||
$id = ($this->dbsType == 'sql') ? $this->primary : '_id';
|
||||
$id = $this->primary;
|
||||
if ($key == '_id' && $this->dbsType == 'sql')
|
||||
$key = $id;
|
||||
if ($this->whitelist && !in_array($key,$this->whitelist)) {
|
||||
@@ -1398,15 +1461,10 @@ class Cortex extends Cursor {
|
||||
else {
|
||||
// get config for this field
|
||||
$relConf = $fields[$key]['belongs-to-one'];
|
||||
if (!is_array($relConf))
|
||||
$relConf = array($relConf, '_id');
|
||||
// fetch related model
|
||||
$rel = $this->getRelInstance($relConf[0],null,$key);
|
||||
if ($this->dbsType == 'sql' && $relConf[1] == '_id')
|
||||
$relConf[1] = $rel->primary;
|
||||
$rel = $this->getRelFromConf($relConf,$key);
|
||||
// am i part of a result collection?
|
||||
if ($this->collectionID && $this->smartLoading) {
|
||||
$cx = CortexCollection::instance($this->collectionID);
|
||||
if ($cx = $this->getCollection()) {
|
||||
// does the collection has cached results for this key?
|
||||
if (!$cx->hasRelSet($key)) {
|
||||
// build the cache, find all values of current key
|
||||
@@ -1435,7 +1493,7 @@ class Cortex extends Cursor {
|
||||
$fromConf = $fields[$key][$type];
|
||||
if (!is_array($fromConf))
|
||||
trigger_error(sprintf(self::E_REL_CONF_INC, $key));
|
||||
$rel = $this->getRelInstance($fromConf[0],null,$key);
|
||||
$rel = $this->getRelInstance($fromConf[0],null,$key,true);
|
||||
$relFieldConf = $rel->getFieldConfiguration();
|
||||
$relType = key($relFieldConf[$fromConf[1]]);
|
||||
// one-to-*, bidirectional, inverse way
|
||||
@@ -1446,9 +1504,8 @@ class Cortex extends Cursor {
|
||||
if ($toConf[1] != $id && (!$this->exists($toConf[1])
|
||||
|| is_null($this->mapper->get($toConf[1]))))
|
||||
$this->fieldsCache[$key] = null;
|
||||
elseif($this->collectionID && $this->smartLoading) {
|
||||
elseif($cx = $this->getCollection()) {
|
||||
// part of a result set
|
||||
$cx = CortexCollection::instance($this->collectionID);
|
||||
if(!$cx->hasRelSet($key)) {
|
||||
// emit eager loading
|
||||
$relKeys = $cx->getAll($toConf[1],true);
|
||||
@@ -1459,7 +1516,7 @@ class Cortex extends Cursor {
|
||||
}
|
||||
$result = $cx->getSubset($key, array($this->get($toConf[1])));
|
||||
$this->fieldsCache[$key] = $result ? (($type == 'has-one')
|
||||
? $result[0][0] : $result[0]) : NULL;
|
||||
? $result[0][0] : CortexCollection::factory($result[0])) : NULL;
|
||||
} else {
|
||||
$crit = array($fromConf[1].' = ?', $this->get($toConf[1],true));
|
||||
$crit = $this->mergeWithRelFilter($key, $crit);
|
||||
@@ -1471,19 +1528,16 @@ class Cortex extends Cursor {
|
||||
}
|
||||
// many-to-many, bidirectional
|
||||
elseif ($relType == 'has-many') {
|
||||
if (!array_key_exists('refTable', $fromConf)) {
|
||||
// compute mm table name
|
||||
$toConf = $relFieldConf[$fromConf[1]]['has-many'];
|
||||
$mmTable = isset($fromConf[2]) ? $fromConf[2] :
|
||||
static::getMMTableName($fromConf['relTable'],
|
||||
$fromConf['relField'], $this->getTable(), $key, $toConf);
|
||||
$this->fieldConf[$key]['has-many']['refTable'] = $mmTable;
|
||||
} else
|
||||
$mmTable = $fromConf['refTable'];
|
||||
$toConf = $relFieldConf[$fromConf[1]]['has-many'];
|
||||
$mmTable = $this->mmTable($fromConf,$key,$toConf);
|
||||
// create mm table mapper
|
||||
if (!$this->get($id,true)) {
|
||||
$this->fieldsCache[$key] = null;
|
||||
return $this->fieldsCache[$key];
|
||||
}
|
||||
$id = $toConf['relPK'];
|
||||
$rel = $this->getRelInstance(null,array('db'=>$this->db,'table'=>$mmTable));
|
||||
if ($this->collectionID && $this->smartLoading) {
|
||||
$cx = CortexCollection::instance($this->collectionID);
|
||||
if ($cx = $this->getCollection()) {
|
||||
if (!$cx->hasRelSet($key)) {
|
||||
// get IDs of all results
|
||||
$relKeys = $cx->getAll($id,true);
|
||||
@@ -1503,8 +1557,8 @@ class Cortex extends Cursor {
|
||||
$cx->setRelSet($key.'_pivot', $pivotRel);
|
||||
// preload all rels
|
||||
$pivotKeys = array_unique($pivotKeys);
|
||||
$fRel = $this->getRelInstance($fromConf[0],null,$key);
|
||||
$crit = array(($fRel->primary!='id' ? $fRel->primary : '_id').' IN ?', $pivotKeys);
|
||||
$fRel = $this->getRelInstance($fromConf[0],null,$key,true);
|
||||
$crit = array($toConf['relPK'].' IN ?', $pivotKeys);
|
||||
$relSet = $fRel->find($this->mergeWithRelFilter($key, $crit),
|
||||
$this->getRelFilterOption($key),$this->_ttl);
|
||||
$cx->setRelSet($key, $relSet ? $relSet->getBy($id) : NULL);
|
||||
@@ -1513,21 +1567,22 @@ class Cortex extends Cursor {
|
||||
}
|
||||
// fetch subset from preloaded rels using cached pivot keys
|
||||
$fkeys = $cx->getSubset($key.'_pivot', array($this->get($id)));
|
||||
$this->fieldsCache[$key] = $fkeys ? $cx->getSubset($key, $fkeys[0]) : NULL;
|
||||
$this->fieldsCache[$key] = $fkeys ?
|
||||
CortexCollection::factory($cx->getSubset($key, $fkeys[0])) : NULL;
|
||||
} // no collection
|
||||
else {
|
||||
// find foreign keys
|
||||
$results = $rel->find(
|
||||
array($fromConf['relField'].' = ?', $this->get($id,true)),null,$this->_ttl);
|
||||
array($fromConf['relField'].' = ?', $this->get($fromConf['relPK'],true)),null,$this->_ttl);
|
||||
if(!$results)
|
||||
$this->fieldsCache[$key] = NULL;
|
||||
else {
|
||||
$fkeys = $results->getAll($key,true);
|
||||
// create foreign table mapper
|
||||
unset($rel);
|
||||
$rel = $this->getRelInstance($fromConf[0],null,$key);
|
||||
$rel = $this->getRelInstance($fromConf[0],null,$key,true);
|
||||
// load foreign models
|
||||
$filter = array(($rel->primary!='id' ? $rel->primary : '_id').' IN ?', $fkeys);
|
||||
$filter = array($toConf['relPK'].' IN ?', $fkeys);
|
||||
$filter = $this->mergeWithRelFilter($key, $filter);
|
||||
$this->fieldsCache[$key] = $rel->find($filter,
|
||||
$this->getRelFilterOption($key),$this->_ttl);
|
||||
@@ -1546,17 +1601,12 @@ class Cortex extends Cursor {
|
||||
else {
|
||||
// create foreign table mapper
|
||||
$relConf = $fields[$key]['belongs-to-many'];
|
||||
if (!is_array($relConf))
|
||||
$relConf = array($relConf, '_id');
|
||||
$rel = $this->getRelInstance($relConf[0],null,$key);
|
||||
if ($this->dbsType == 'sql' && $relConf[1] == '_id')
|
||||
$relConf[1] = $rel->primary;
|
||||
$rel = $this->getRelFromConf($relConf,$key);
|
||||
$fkeys = array();
|
||||
foreach ($result as $el)
|
||||
$fkeys[] = is_int($el)||ctype_digit($el)?(int)$el:(string)$el;
|
||||
// if part of a result set
|
||||
if ($this->collectionID && $this->smartLoading) {
|
||||
$cx = CortexCollection::instance($this->collectionID);
|
||||
if ($cx = $this->getCollection()) {
|
||||
if (!$cx->hasRelSet($key)) {
|
||||
// find all keys
|
||||
$relKeys = ($cx->getAll($key,true));
|
||||
@@ -1576,7 +1626,7 @@ class Cortex extends Cursor {
|
||||
$cx->setRelSet($key, $relSet ? $relSet->getBy($relConf[1]) : NULL);
|
||||
}
|
||||
// get a subset of the preloaded set
|
||||
$this->fieldsCache[$key] = $cx->getSubset($key, $fkeys);
|
||||
$this->fieldsCache[$key] = CortexCollection::factory($cx->getSubset($key, $fkeys));
|
||||
} else {
|
||||
// load foreign models
|
||||
$filter = array($relConf[1].' IN ?', $fkeys);
|
||||
@@ -1664,14 +1714,16 @@ class Cortex extends Cursor {
|
||||
* @param string $model
|
||||
* @param array $relConf
|
||||
* @param string $key
|
||||
* @param bool $pushFilter
|
||||
* @return Cortex
|
||||
*/
|
||||
protected function getRelInstance($model=null,$relConf=null,$key='')
|
||||
protected function getRelInstance($model=null,$relConf=null,$key='',$pushFilter=false)
|
||||
{
|
||||
if (!$model && !$relConf)
|
||||
trigger_error(self::E_MISSING_REL_CONF);
|
||||
$relConf = $model ? $model::resolveConfiguration() : $relConf;
|
||||
$relName = ($model?:'Cortex').'\\'.$relConf['db']->uuid().'\\'.$relConf['table'];
|
||||
$relName = ($model?:'Cortex').'\\'.$relConf['db']->uuid().
|
||||
'\\'.$relConf['table'].'\\'.$key;
|
||||
if (\Registry::exists($relName)) {
|
||||
$rel = \Registry::get($relName);
|
||||
$rel->reset();
|
||||
@@ -1688,14 +1740,53 @@ class Cortex extends Cursor {
|
||||
if (isset($this->relWhitelist[$key][1]))
|
||||
$rel->fields($this->relWhitelist[$key][1],true);
|
||||
}
|
||||
if ($pushFilter && !empty($key)) {
|
||||
if (isset($this->relFilter[$key.'.'])) {
|
||||
foreach($this->relFilter[$key.'.'] as $fkey=>$conf)
|
||||
$rel->filter($fkey,$conf[0],$conf[1]);
|
||||
}
|
||||
if (isset($this->hasCond[$key.'.'])) {
|
||||
foreach($this->hasCond[$key.'.'] as $fkey=>$conf)
|
||||
$rel->has($fkey,$conf[0],$conf[1]);
|
||||
}
|
||||
}
|
||||
return $rel;
|
||||
}
|
||||
|
||||
/**
|
||||
* get relation model from config
|
||||
* @param $fieldConf
|
||||
* @param $key
|
||||
* @return Cortex
|
||||
*/
|
||||
protected function getRelFromConf(&$fieldConf, $key) {
|
||||
if (!is_array($fieldConf))
|
||||
$fieldConf = array($fieldConf, '_id');
|
||||
$rel = $this->getRelInstance($fieldConf[0],null,$key,true);
|
||||
if($this->dbsType=='sql' && $fieldConf[1] == '_id')
|
||||
$fieldConf[1] = $rel->primary;
|
||||
return $rel;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a clean/dry model from a relation
|
||||
* @param string $key
|
||||
* @return Cortex
|
||||
*/
|
||||
public function rel($key)
|
||||
{
|
||||
$rt = $this->fieldConf[$key]['relType'];
|
||||
$rc = $this->fieldConf[$key][$rt];
|
||||
if (!is_array($rc))
|
||||
$rc = array($rc,'_id');
|
||||
return $this->getRelInstance($rc[0],null,$key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return fields of mapper object as an associative array
|
||||
* @return array
|
||||
* @param bool|Cortex $obj
|
||||
* @param bool|int $rel_depths depths to resolve relations
|
||||
* @param int|array $rel_depths depths to resolve relations
|
||||
*/
|
||||
public function cast($obj = NULL, $rel_depths = 1)
|
||||
{
|
||||
@@ -1704,7 +1795,9 @@ class Cortex extends Cursor {
|
||||
foreach(array_keys($this->vFields) as $key)
|
||||
$fields[$key]=$this->get($key);
|
||||
if (is_int($rel_depths))
|
||||
$rel_depths--;
|
||||
$rel_depths = array('*'=>$rel_depths-1);
|
||||
elseif (is_array($rel_depths))
|
||||
$rel_depths['*'] = isset($rel_depths['*'])?--$rel_depths['*']:-1;
|
||||
if (!empty($this->fieldConf)) {
|
||||
$fields += array_fill_keys(array_keys($this->fieldConf),NULL);
|
||||
if($this->whitelist)
|
||||
@@ -1714,36 +1807,29 @@ class Cortex extends Cursor {
|
||||
// post process configured fields
|
||||
if (isset($this->fieldConf[$key]) && is_array($this->fieldConf[$key])) {
|
||||
// handle relations
|
||||
if (($rel_depths === TRUE || (is_int($rel_depths) && $rel_depths >= 0))
|
||||
&& $type=preg_grep('/[belongs|has]-(to-)*[one|many]/',
|
||||
$rd = isset($rel_depths[$key]) ? $rel_depths[$key] : $rel_depths['*'];
|
||||
if ((is_array($rd) || $rd >= 0) && $type=preg_grep('/[belongs|has]-(to-)*[one|many]/',
|
||||
array_keys($this->fieldConf[$key]))) {
|
||||
$relType=$type[0];
|
||||
// cast relations
|
||||
$val = (($relType == 'belongs-to-one' || $relType == 'belongs-to-many')
|
||||
&& !$mp->exists($key)) ? NULL : $mp->get($key);
|
||||
if (is_array($val) || is_object($val)) {
|
||||
if ($relType == 'belongs-to-one' || $relType == 'has-one')
|
||||
// single object
|
||||
$val = $val->cast(null, $rel_depths);
|
||||
elseif ($relType == 'belongs-to-many' || $relType == 'has-many')
|
||||
// multiple objects
|
||||
foreach ($val as $k => $item)
|
||||
$val[$k] = is_object($item) ? $item->cast(null, $rel_depths) : null;
|
||||
}
|
||||
if ($val instanceof CortexCollection)
|
||||
$val = $val->expose();
|
||||
if ($val instanceof Cortex)
|
||||
$val = $val->cast(null, $rd);
|
||||
elseif ($val instanceof CortexCollection)
|
||||
$val = $val->castAll($rd);
|
||||
}
|
||||
// decode array fields
|
||||
// extract array fields
|
||||
elseif (isset($this->fieldConf[$key]['type'])) {
|
||||
if ($this->dbsType == 'sql') {
|
||||
if ($this->fieldConf[$key]['type'] == self::DT_SERIALIZED)
|
||||
$val=unserialize($this->mapper->{$key});
|
||||
$val=unserialize($mp->mapper->{$key});
|
||||
elseif ($this->fieldConf[$key]['type'] == self::DT_JSON)
|
||||
$val=json_decode($this->mapper->{$key}, true);
|
||||
$val=json_decode($mp->mapper->{$key}, true);
|
||||
}
|
||||
if ($this->exists($key)
|
||||
&& preg_match('/BOOL/i',$this->fieldConf[$key]['type'])) {
|
||||
$val = (bool) $this->mapper->{$key};
|
||||
$val = (bool) $mp->mapper->{$key};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2043,6 +2129,7 @@ class CortexQueryParser extends \Prefab {
|
||||
} else
|
||||
$ncond[] = $val;
|
||||
}
|
||||
unset($part);
|
||||
}
|
||||
array_unshift($ncond, implode(' ', $parts));
|
||||
break;
|
||||
@@ -2089,6 +2176,7 @@ class CortexQueryParser extends \Prefab {
|
||||
$params[] = $args[$match[0]];
|
||||
} elseif (is_int(strpos($part, '?')))
|
||||
$params[] = $args[$pos++];
|
||||
unset($part);
|
||||
}
|
||||
return array($parts, $params);
|
||||
}
|
||||
@@ -2140,6 +2228,7 @@ class CortexQueryParser extends \Prefab {
|
||||
$chks[] = 'isset('.$field.')';
|
||||
$part = '('.implode(' && ',$chks).' && ('.$part.'))';
|
||||
}
|
||||
unset($part);
|
||||
}
|
||||
array_unshift($ncond, implode(' ', $parts));
|
||||
return $ncond;
|
||||
@@ -2302,7 +2391,8 @@ class CortexQueryParser extends \Prefab {
|
||||
}
|
||||
if (array_key_exists('group', $options) && is_string($options['group'])) {
|
||||
$keys = explode(',',$options['group']);
|
||||
$options['group']=array('keys'=>array(),'initial'=>array(),'reduce'=>'function (obj, prev) {}','finalize'=>'');
|
||||
$options['group']=array('keys'=>array(),'initial'=>array(),
|
||||
'reduce'=>'function (obj, prev) {}','finalize'=>'');
|
||||
$keys = array_combine($keys,array_fill(0,count($keys),1));
|
||||
$options['group']['keys']=$keys;
|
||||
$options['group']['initial']=$keys;
|
||||
@@ -2318,6 +2408,7 @@ class CortexCollection extends \ArrayIterator {
|
||||
protected
|
||||
$relSets = array(),
|
||||
$pointer = 0,
|
||||
$changed = false,
|
||||
$cid;
|
||||
|
||||
const
|
||||
@@ -2326,15 +2417,9 @@ class CortexCollection extends \ArrayIterator {
|
||||
|
||||
public function __construct() {
|
||||
$this->cid = uniqid('cortex_collection_');
|
||||
\Registry::set($this->cid,$this);
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function __destruct() {
|
||||
// free embedded relation cache from memory
|
||||
\Registry::clear($this->cid);
|
||||
}
|
||||
|
||||
//! Prohibit cloning to ensure an existing relation cache
|
||||
private function __clone() { }
|
||||
|
||||
@@ -2342,20 +2427,30 @@ class CortexCollection extends \ArrayIterator {
|
||||
* set a collection of models
|
||||
* @param $models
|
||||
*/
|
||||
function setModels($models) {
|
||||
function setModels($models,$init=true) {
|
||||
array_map(array($this,'add'),$models);
|
||||
if ($init)
|
||||
$this->changed = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* add single model to collection
|
||||
* @param $model
|
||||
*/
|
||||
function add(Cortex $model)
|
||||
{
|
||||
$model->addToCollection($this->cid);
|
||||
function add(Cortex $model) {
|
||||
$model->addToCollection($this);
|
||||
$this->append($model);
|
||||
}
|
||||
|
||||
public function offsetSet($i, $val) {
|
||||
$this->changed=true;
|
||||
parent::offsetSet($i,$val);
|
||||
}
|
||||
|
||||
public function hasChanged() {
|
||||
return $this->changed;
|
||||
}
|
||||
|
||||
/**
|
||||
* get a related collection
|
||||
* @param $key
|
||||
@@ -2400,9 +2495,11 @@ class CortexCollection extends \ArrayIterator {
|
||||
trigger_error(sprintf(self::E_SubsetKeysValue,gettype($keys)));
|
||||
if (!$this->hasRelSet($prop) || !($relSet = $this->getRelSet($prop)))
|
||||
return null;
|
||||
foreach ($keys as &$key)
|
||||
foreach ($keys as &$key) {
|
||||
if ($key instanceof \MongoId)
|
||||
$key = (string) $key;
|
||||
unset($key);
|
||||
}
|
||||
return array_values(array_intersect_key($relSet, array_flip($keys)));
|
||||
}
|
||||
|
||||
@@ -2415,18 +2512,19 @@ class CortexCollection extends \ArrayIterator {
|
||||
public function getAll($prop, $raw = false)
|
||||
{
|
||||
$out = array();
|
||||
foreach ($this->getArrayCopy() as $model)
|
||||
foreach ($this->getArrayCopy() as $model) {
|
||||
if ($model->exists($prop,true)) {
|
||||
$val = $model->get($prop, $raw);
|
||||
if (!empty($val))
|
||||
$out[] = $val;
|
||||
}
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* cast all contained mappers to a nested array
|
||||
* @param int $rel_depths depths to resolve relations
|
||||
* @param int|array $rel_depths depths to resolve relations
|
||||
* @return array
|
||||
*/
|
||||
public function castAll($rel_depths=1) {
|
||||
@@ -2496,14 +2594,10 @@ class CortexCollection extends \ArrayIterator {
|
||||
unset($this[$ii]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $cid
|
||||
* @return CortexCollection
|
||||
*/
|
||||
static public function instance($cid) {
|
||||
if (!\Registry::exists($cid))
|
||||
trigger_error(sprintf(self::E_UnknownCID, $cid));
|
||||
return \Registry::get($cid);
|
||||
static public function factory($records) {
|
||||
$cc = new self();
|
||||
$cc->setModels($records);
|
||||
return $cc;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,25 +22,6 @@ class AccessController extends Controller {
|
||||
|
||||
$accessRoute = $this->_isLoggedIn();
|
||||
|
||||
/*
|
||||
$userName = 'user_exodus';
|
||||
$password = '1234567';
|
||||
|
||||
// try to verify user
|
||||
$accessRoute = $this->_verifyUser($userName, $password);
|
||||
|
||||
if(!$accessRoute){
|
||||
// add new User
|
||||
try{
|
||||
$this->_registerUser($userName, $password);
|
||||
}catch(\Exception\ValidationException $e){
|
||||
// registration failed
|
||||
$this->f3->error($e->getCode(), $e->getMessage());
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
if(
|
||||
!$this->f3->get('AJAX') &&
|
||||
!$accessRoute
|
||||
@@ -108,6 +89,17 @@ class AccessController extends Controller {
|
||||
return $loggedIn;
|
||||
}
|
||||
|
||||
/**
|
||||
* get error object is a user is not found/logged of
|
||||
* @return object
|
||||
*/
|
||||
protected function getUserLoggedOffError(){
|
||||
$userError = (object) [];
|
||||
$userError->type = 'error';
|
||||
$userError->message = 'User not found';
|
||||
|
||||
return $userError;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ class Controller {
|
||||
* set/change DB connection
|
||||
* @param $type
|
||||
*/
|
||||
protected function setDB($type){
|
||||
protected function setDB($type = ''){
|
||||
|
||||
if($type === 'CCP'){
|
||||
// CCP DB
|
||||
@@ -84,14 +84,20 @@ class Controller {
|
||||
/**
|
||||
* get current user model
|
||||
* @return bool|null
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function _getUser(){
|
||||
|
||||
$user = Model\BasicModel::getNew('UserModel', 5);
|
||||
$user->getById($this->f3->get('SESSION.user.id'));
|
||||
$user = false;
|
||||
$userId = $this->f3->get('SESSION.user.id');
|
||||
|
||||
if($user->dry()){
|
||||
$user = false;
|
||||
if($userId > 0){
|
||||
$userModel = Model\BasicModel::getNew('UserModel', 5);
|
||||
$userModel->getById($userId);
|
||||
|
||||
if( !$userModel->dry() ){
|
||||
$user = $userModel;
|
||||
}
|
||||
}
|
||||
|
||||
return $user;
|
||||
|
||||
@@ -52,6 +52,11 @@ class MapController extends \Controller\AccessController {
|
||||
'text' => $f3->get('ERROR.text')
|
||||
];
|
||||
|
||||
// append stack trace for greater debug level
|
||||
if( $f3->get('DEBUG') === 3){
|
||||
$errorData['trace'] = $f3->get('ERROR.trace');
|
||||
}
|
||||
|
||||
echo json_encode($errorData);
|
||||
}else{
|
||||
echo $f3->get('ERROR.text');
|
||||
|
||||
75
app/main/controller/api/Access.php
Normal file
75
app/main/controller/api/Access.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: exodus4d
|
||||
* Date: 24.05.2015
|
||||
* Time: 17:42
|
||||
*/
|
||||
|
||||
namespace controller\api;
|
||||
use Model;
|
||||
|
||||
class Access extends \Controller\AccessController {
|
||||
|
||||
/**
|
||||
* event handler
|
||||
*/
|
||||
function beforeroute() {
|
||||
|
||||
parent::beforeroute();
|
||||
|
||||
// set header for all routes
|
||||
header('Content-type: application/json');
|
||||
}
|
||||
|
||||
/**
|
||||
* search user/corporation or alliance by name
|
||||
* @param $f3
|
||||
* @param $params
|
||||
*/
|
||||
public function search($f3, $params){
|
||||
|
||||
$accessData = [];
|
||||
|
||||
if(
|
||||
array_key_exists( 'arg1', $params) &&
|
||||
array_key_exists( 'arg2', $params)
|
||||
){
|
||||
$searchType = strtolower( $params['arg1'] );
|
||||
$searchToken = strtolower( $params['arg2'] );
|
||||
|
||||
$accessModel = null;
|
||||
switch($searchType){
|
||||
case 'user':
|
||||
$accessModel = Model\BasicModel::getNew('UserModel');
|
||||
break;
|
||||
case 'corporation':
|
||||
$accessModel = Model\BasicModel::getNew('CorporationModel');
|
||||
break;
|
||||
case 'alliance':
|
||||
$accessModel = Model\BasicModel::getNew('AllianceModel');
|
||||
break;
|
||||
}
|
||||
|
||||
if( is_object($accessModel) ){
|
||||
$accessList = $accessModel->find( array(
|
||||
"LOWER(name) LIKE :token AND active = 1",
|
||||
':token' => '%' . $searchToken . '%'
|
||||
));
|
||||
|
||||
if($accessList){
|
||||
foreach($accessList as $accessObject){
|
||||
$accessData[] = $accessObject->getData();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
echo json_encode($accessData);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -125,6 +125,14 @@ class Map extends \Controller\AccessController {
|
||||
}
|
||||
$initData['characterStatus'] = $characterStatusData;
|
||||
|
||||
// get max number of shared entities per map --------------------------
|
||||
$maxSharedCount = [
|
||||
'user' => $f3->get('PATHFINDER.MAX_SHARED_USER'),
|
||||
'corporation' => $f3->get('PATHFINDER.MAX_SHARED_CORPORATION'),
|
||||
'alliance' => $f3->get('PATHFINDER.MAX_SHARED_ALLIANCE'),
|
||||
];
|
||||
$initData['maxSharedCount'] = $maxSharedCount;
|
||||
|
||||
echo json_encode($initData);
|
||||
}
|
||||
|
||||
@@ -133,45 +141,138 @@ class Map extends \Controller\AccessController {
|
||||
* @param $f3
|
||||
*/
|
||||
public function save($f3){
|
||||
$mapData = (array)$f3->get('POST.mapData');
|
||||
$formData = (array)$f3->get('POST.formData');
|
||||
|
||||
$user = $this->_getUser();
|
||||
$return = (object) [];
|
||||
$return->error = [];
|
||||
|
||||
$map = Model\BasicModel::getNew('MapModel');
|
||||
$map->getById($mapData['id']);
|
||||
$map->setData($mapData);
|
||||
$map->save();
|
||||
if(array_key_exists( 'id', $formData)){
|
||||
|
||||
if($map->isPrivate()){
|
||||
$map->clearAccess(['corporation', 'alliance']);
|
||||
$map->setAccess($user);
|
||||
}elseif($map->isCorporation()){
|
||||
$activeCharacter = $user->getActiveUserCharacter();
|
||||
$user = $this->_getUser();
|
||||
|
||||
if($activeCharacter){
|
||||
$corporation = $activeCharacter->getCharacter()->getCorporation();
|
||||
$map = Model\BasicModel::getNew('MapModel');
|
||||
$map->getById($formData['id']);
|
||||
|
||||
if($corporation){
|
||||
$map->clearAccess(['user', 'alliance']);
|
||||
$map->setAccess($corporation);
|
||||
}
|
||||
// check if the user has access to this map
|
||||
$mapAccess = true;
|
||||
if(! $map->dry() ){
|
||||
$mapAccess = $map->hasAccess($user);
|
||||
}
|
||||
}elseif($map->isAlliance()){
|
||||
$activeCharacter = $user->getActiveUserCharacter();
|
||||
|
||||
if($activeCharacter){
|
||||
$alliance = $activeCharacter->getCharacter()->getAlliance();
|
||||
if($mapAccess){
|
||||
$map->setData($formData);
|
||||
$map = $map->save();
|
||||
|
||||
if($alliance){
|
||||
$map->clearAccess(['user', 'corporation']);
|
||||
$map->setAccess($alliance);
|
||||
// save global map access. Depends on map "type"
|
||||
if($map->isPrivate()){
|
||||
|
||||
// share map between users -> set access
|
||||
if(array_key_exists('mapUsers', $formData)){
|
||||
// clear map access. In case something has removed from access list
|
||||
$map->clearAccess();
|
||||
|
||||
$tempUser = Model\BasicModel::getNew('UserModel');
|
||||
|
||||
foreach((array)$formData['mapUsers'] as $userId){
|
||||
$tempUser->getById( $userId );
|
||||
|
||||
if( !$tempUser->dry() ){
|
||||
$map->setAccess($tempUser);
|
||||
}
|
||||
|
||||
$tempUser->reset();
|
||||
}
|
||||
}
|
||||
|
||||
// the current user itself should always have access
|
||||
// just in case he removed himself :)
|
||||
$map->setAccess($user);
|
||||
}elseif($map->isCorporation()){
|
||||
$activeCharacter = $user->getActiveUserCharacter();
|
||||
|
||||
if($activeCharacter){
|
||||
$corporation = $activeCharacter->getCharacter()->getCorporation();
|
||||
|
||||
if($corporation){
|
||||
// the current user has to have a corporation when
|
||||
// working on corporation maps!
|
||||
|
||||
// share map between corporations -> set access
|
||||
if(array_key_exists('mapCorporations', $formData)){
|
||||
// clear map access. In case something has removed from access list
|
||||
$map->clearAccess();
|
||||
|
||||
$tempCorporation = Model\BasicModel::getNew('CorporationModel');
|
||||
|
||||
foreach((array)$formData['mapCorporations'] as $corporationId){
|
||||
$tempCorporation->getById( $corporationId );
|
||||
|
||||
if( !$tempCorporation->dry() ){
|
||||
$map->setAccess($tempCorporation);
|
||||
}
|
||||
|
||||
$tempCorporation->reset();
|
||||
}
|
||||
}
|
||||
|
||||
// the corporation of the current user should always have access
|
||||
$map->setAccess($corporation);
|
||||
}
|
||||
}
|
||||
}elseif($map->isAlliance()){
|
||||
$activeCharacter = $user->getActiveUserCharacter();
|
||||
|
||||
if($activeCharacter){
|
||||
$alliance = $activeCharacter->getCharacter()->getAlliance();
|
||||
|
||||
if($alliance){
|
||||
// the current user has to have a alliance when
|
||||
// working on alliance maps!
|
||||
|
||||
// share map between alliances -> set access
|
||||
if(array_key_exists('mapAlliances', $formData)){
|
||||
// clear map access. In case something has removed from access list
|
||||
$map->clearAccess();
|
||||
|
||||
$tempAlliance = Model\BasicModel::getNew('AllianceModel');
|
||||
|
||||
foreach((array)$formData['mapAlliances'] as $allianceId){
|
||||
$tempAlliance->getById( $allianceId );
|
||||
|
||||
if( !$tempAlliance->dry() ){
|
||||
$map->setAccess($tempAlliance);
|
||||
}
|
||||
|
||||
$tempAlliance->reset();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// the alliance of the current user should always have access
|
||||
$map->setAccess($alliance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$return->mapData = $map->getData();
|
||||
}else{
|
||||
// map access denied
|
||||
$captchaError = new \stdClass();
|
||||
$captchaError->type = 'error';
|
||||
$captchaError->message = 'Access denied';
|
||||
$return->error[] = $captchaError;
|
||||
}
|
||||
}else{
|
||||
// map id field missing
|
||||
$idError = new \stdClass();
|
||||
$idError->type = 'error';
|
||||
$idError->message = 'Map id missing';
|
||||
$return->error[] = $idError;
|
||||
}
|
||||
|
||||
$mapData = $map->getData();
|
||||
|
||||
echo json_encode($mapData);
|
||||
|
||||
echo json_encode($return);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -202,92 +303,102 @@ class Map extends \Controller\AccessController {
|
||||
$responseTTL = 3;
|
||||
$user = $this->_getUser();
|
||||
|
||||
$cacheKey = 'user_map_data_' . $user->id;
|
||||
if($f3->exists($cacheKey) === false){
|
||||
$return = (object) [];
|
||||
$return->error = [];
|
||||
|
||||
$mapData = (array)$f3->get('POST.mapData');
|
||||
if($user){
|
||||
$cacheKey = 'user_map_data_' . $user->id;
|
||||
if($f3->exists($cacheKey) === false){
|
||||
|
||||
$mapData = (array)$f3->get('POST.mapData');
|
||||
|
||||
|
||||
$map = Model\BasicModel::getNew('MapModel');
|
||||
$system = Model\BasicModel::getNew('SystemModel');
|
||||
$connection = Model\BasicModel::getNew('ConnectionModel');
|
||||
$map = Model\BasicModel::getNew('MapModel');
|
||||
$system = Model\BasicModel::getNew('SystemModel');
|
||||
$connection = Model\BasicModel::getNew('ConnectionModel');
|
||||
|
||||
$activeCharacter = $user->getActiveUserCharacter();
|
||||
$activeCharacter = $user->getActiveUserCharacter();
|
||||
|
||||
foreach($mapData as $data){
|
||||
foreach($mapData as $data){
|
||||
|
||||
$config = $data['config'];
|
||||
$systems = [];
|
||||
$connections = [];
|
||||
$config = $data['config'];
|
||||
$systems = [];
|
||||
$connections = [];
|
||||
|
||||
// check whether system data and/or connection data is send
|
||||
// empty arrays are not included in ajax requests
|
||||
if(array_key_exists('data', $data)){
|
||||
if(array_key_exists('systems', $data['data'])){
|
||||
$systems = $data['data']['systems'];
|
||||
// check whether system data and/or connection data is send
|
||||
// empty arrays are not included in ajax requests
|
||||
if(array_key_exists('data', $data)){
|
||||
if(array_key_exists('systems', $data['data'])){
|
||||
$systems = $data['data']['systems'];
|
||||
}
|
||||
if(array_key_exists('connections', $data['data'])){
|
||||
$connections = $data['data']['connections'];
|
||||
}
|
||||
}
|
||||
if(array_key_exists('connections', $data['data'])){
|
||||
$connections = $data['data']['connections'];
|
||||
|
||||
// update map data ---------------------------------------------
|
||||
$map->getById($config['id']);
|
||||
|
||||
if(!$map->dry()){
|
||||
// update map on change
|
||||
if( (int)$config['updated'] > strtotime($map->updated)){
|
||||
$map->setData($config);
|
||||
$map->save();
|
||||
}
|
||||
}
|
||||
|
||||
// get system data -----------------------------------------------
|
||||
foreach($systems as $systemData){
|
||||
$system->getById($systemData['id']);
|
||||
|
||||
if(
|
||||
(int)$systemData['updated']['updated'] === 0 &&
|
||||
!$system->dry()
|
||||
){
|
||||
$system->setData($systemData);
|
||||
$system->mapId = $map;
|
||||
$system->updatedCharacterId = $activeCharacter->characterId;
|
||||
$system->save();
|
||||
}
|
||||
|
||||
$system->reset();
|
||||
}
|
||||
|
||||
// get connection data -------------------------------------------
|
||||
foreach($connections as $connectionData){
|
||||
$connection->getById($connectionData['id']);
|
||||
|
||||
if(
|
||||
(int)$connectionData['updated'] === 0 &&
|
||||
!$connection->dry()
|
||||
){
|
||||
$connectionData['mapId'] = $map;
|
||||
$connection->setData($connectionData);
|
||||
$connection->save($user);
|
||||
}
|
||||
|
||||
$connection->reset();
|
||||
}
|
||||
|
||||
$map->reset();
|
||||
}
|
||||
|
||||
// update map data ---------------------------------------------
|
||||
$map->getById($config['id']);
|
||||
// get map data ======================================================
|
||||
$activeMaps = $user->getMaps();
|
||||
|
||||
if(!$map->dry()){
|
||||
// update map on change
|
||||
if( (int)$config['updated'] > strtotime($map->updated)){
|
||||
$map->setData($config);
|
||||
$map->save();
|
||||
}
|
||||
}
|
||||
// format map Data for return
|
||||
$newData = self::getFormattedMapData($activeMaps);
|
||||
|
||||
// get system data -----------------------------------------------
|
||||
foreach($systems as $systemData){
|
||||
$system->getById($systemData['id']);
|
||||
|
||||
if(
|
||||
(int)$systemData['updated']['updated'] === 0 &&
|
||||
!$system->dry()
|
||||
){
|
||||
$system->setData($systemData);
|
||||
$system->mapId = $map;
|
||||
$system->updatedCharacterId = $activeCharacter->characterId;
|
||||
$system->save();
|
||||
}
|
||||
|
||||
$system->reset();
|
||||
}
|
||||
|
||||
// get connection data -------------------------------------------
|
||||
foreach($connections as $connectionData){
|
||||
$connection->getById($connectionData['id']);
|
||||
|
||||
if(
|
||||
(int)$connectionData['updated'] === 0 &&
|
||||
!$connection->dry()
|
||||
){
|
||||
$connectionData['mapId'] = $map;
|
||||
$connection->setData($connectionData);
|
||||
$connection->save($user);
|
||||
}
|
||||
|
||||
$connection->reset();
|
||||
}
|
||||
|
||||
$map->reset();
|
||||
$f3->set($cacheKey, $newData, $responseTTL);
|
||||
}
|
||||
|
||||
// get map data ======================================================
|
||||
$activeMaps = $user->getMaps();
|
||||
|
||||
// format map Data for return
|
||||
$newData = self::getFormattedMapData($activeMaps);
|
||||
|
||||
$f3->set($cacheKey, $newData, $responseTTL);
|
||||
$return = $f3->get($cacheKey);
|
||||
}else{
|
||||
// user logged of
|
||||
$return->error[] = $this->getUserLoggedOffError();
|
||||
}
|
||||
|
||||
echo json_encode( $f3->get($cacheKey) );
|
||||
echo json_encode( $return );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -322,45 +433,55 @@ class Map extends \Controller\AccessController {
|
||||
$responseTTL = 2;
|
||||
$user = $this->_getUser();
|
||||
|
||||
$cacheKey = 'user_data_' . $user->id;
|
||||
if($f3->exists($cacheKey) === false){
|
||||
$return = (object) [];
|
||||
$return->error = [];
|
||||
|
||||
// check if data for specific system is requested
|
||||
$systemData = (array)$f3->get('POST.systemData');
|
||||
if($user){
|
||||
$cacheKey = 'user_data_' . $user->id;
|
||||
if($f3->exists($cacheKey) === false){
|
||||
|
||||
// update current location (IGB data)
|
||||
$user->updateCharacterLog();
|
||||
// check if data for specific system is requested
|
||||
$systemData = (array)$f3->get('POST.systemData');
|
||||
|
||||
$userData = (object) [];
|
||||
// data for the current user
|
||||
$userData->userData = $user->getData();
|
||||
// update current location (IGB data)
|
||||
$user->updateCharacterLog();
|
||||
|
||||
// get user Data for each map ========================================
|
||||
$activeMaps = $user->getMaps();
|
||||
// data for the current user
|
||||
$return->userData = $user->getData();
|
||||
|
||||
foreach($activeMaps as $mapModel){
|
||||
$userData->mapUserData[] = $mapModel->getUserData();
|
||||
// get user Data for each map ========================================
|
||||
$activeMaps = $user->getMaps();
|
||||
|
||||
// request signature data for a system if user has map access
|
||||
if(
|
||||
!empty($systemData) &&
|
||||
$systemData['mapId'] == $mapModel->id
|
||||
){
|
||||
$system = $mapModel->getSystem( (int)$systemData['systemData']['id']);
|
||||
foreach($activeMaps as $mapModel){
|
||||
$return->mapUserData[] = $mapModel->getUserData();
|
||||
|
||||
// request signature data for a system if user has map access
|
||||
if(
|
||||
!empty($systemData) &&
|
||||
$systemData['mapId'] == $mapModel->id
|
||||
){
|
||||
$system = $mapModel->getSystem( (int)$systemData['systemData']['id']);
|
||||
|
||||
if(! is_null($system)){
|
||||
// data for the current selected system
|
||||
$return->system = $system->getData();
|
||||
$return->system->signatures = $system->getSignaturesData();
|
||||
}
|
||||
|
||||
if(! is_null($system)){
|
||||
// data for the current selected system
|
||||
$userData->system = $system->getData();
|
||||
$userData->system->signatures = $system->getSignaturesData();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$f3->set($cacheKey, $return, $responseTTL);
|
||||
}
|
||||
|
||||
$f3->set($cacheKey, $userData, $responseTTL);
|
||||
$return = $f3->get($cacheKey);
|
||||
}else{
|
||||
// user logged of
|
||||
$return->error[] = $this->getUserLoggedOffError();
|
||||
}
|
||||
|
||||
echo json_encode( $f3->get($cacheKey) );
|
||||
|
||||
echo json_encode( $return );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
338
app/main/controller/api/Routes.php
Normal file
338
app/main/controller/api/Routes.php
Normal file
@@ -0,0 +1,338 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: exodus4d
|
||||
* Date: 06.06.15
|
||||
* Time: 03:34
|
||||
*/
|
||||
|
||||
namespace Controller\Api;
|
||||
use Model;
|
||||
|
||||
/**
|
||||
* Routes controller
|
||||
* Class Routes
|
||||
* @package Controller\Api
|
||||
*/
|
||||
class Routes extends \Controller\AccessController {
|
||||
|
||||
/**
|
||||
* cache time for static jump data
|
||||
* @var int
|
||||
*/
|
||||
private $jumpDataCacheTime = 0;
|
||||
|
||||
/**
|
||||
* array system information grouped by systemId
|
||||
* @var array
|
||||
*/
|
||||
private $nameArray = [];
|
||||
|
||||
/**
|
||||
* array neighbour systems grouped by systemName
|
||||
* @var array
|
||||
*/
|
||||
private $jumpArray = [];
|
||||
|
||||
/**
|
||||
* array withh systemName => systemId matching
|
||||
* @var array
|
||||
*/
|
||||
private $idArray = [];
|
||||
|
||||
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
|
||||
// set cache time for static jump data
|
||||
$this->jumpDataCacheTime = 60 * 60 * 24;
|
||||
}
|
||||
|
||||
/**
|
||||
* set static system jump data for this instance
|
||||
* the data is fixed and should not change
|
||||
*/
|
||||
private function setSystemJumpData(){
|
||||
$query = "SELECT * FROM system_neighbour";
|
||||
|
||||
$rows = $this->f3->get('DB')->exec($query, null, $this->jumpDataCacheTime);
|
||||
|
||||
|
||||
foreach($rows as $row){
|
||||
$regionId = trim($row['regionId']);
|
||||
$constId = trim($row['constellationId']);
|
||||
$systemName = strtoupper(trim($row['systemName']));
|
||||
$systemId = trim($row['systemId']);
|
||||
$secStatus = trim($row['trueSec']);
|
||||
|
||||
$this->nameArray[$systemId][0] = $systemName;
|
||||
$this->nameArray[$systemId][1] = $regionId;
|
||||
$this->nameArray[$systemId][2] = $constId;
|
||||
$this->nameArray[$systemId][3] = $secStatus;
|
||||
|
||||
$this->idArray[strtoupper($systemName)] = $systemId;
|
||||
|
||||
$this->jumpArray[$systemName]= explode(":", strtoupper($row['jumpNodes']));
|
||||
array_push($this->jumpArray[$systemName],$systemId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get system data by systemId and dataName
|
||||
* @param $systemId
|
||||
* @param $option
|
||||
* @return null
|
||||
*/
|
||||
private function getSystemInfoBySystemId($systemId, $option){
|
||||
|
||||
$info = null;
|
||||
|
||||
switch($option){
|
||||
case 'systemName':
|
||||
$info = $this->nameArray[ $systemId ][0];
|
||||
break;
|
||||
case 'regionId':
|
||||
$info = $this->nameArray[ $systemId ][1];
|
||||
break;
|
||||
case 'constellationId':
|
||||
$info = $this->nameArray[ $systemId ][2];
|
||||
break;
|
||||
case 'trueSec':
|
||||
$info = $this->nameArray[ $systemId ][3];
|
||||
break;
|
||||
}
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
/**
|
||||
* find a route between two systems
|
||||
* @param $f3
|
||||
* @return array
|
||||
*/
|
||||
public function findRoute($f3){
|
||||
$parameter = $f3->get('GET');
|
||||
|
||||
$routeData = [
|
||||
'routePossible' => false,
|
||||
'routeJumps' => 0,
|
||||
'route' => []
|
||||
];
|
||||
|
||||
if(
|
||||
array_key_exists('from', $parameter) &&
|
||||
array_key_exists('to', $parameter)
|
||||
){
|
||||
$from = strtoupper( $parameter['from'] );
|
||||
$to = strtoupper( $parameter['to'] );
|
||||
|
||||
// set static system jump data
|
||||
$this->setSystemJumpData();
|
||||
|
||||
// jump counter
|
||||
$jumpNum = 0;
|
||||
|
||||
// check if the system we are looking for is a direct neighbour
|
||||
foreach( $this->jumpArray[$from] as $n ) {
|
||||
|
||||
if ($n == $to) {
|
||||
$jumpNum = 2;
|
||||
|
||||
$jumpNode = [
|
||||
'system' => $n,
|
||||
'security' => $this->getSystemInfoBySystemId($this->idArray[$n], 'trueSec')
|
||||
];
|
||||
|
||||
$routeData['route'][] = $jumpNode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// system is not a direct neighbour -> search recursive its neighbours
|
||||
if ($jumpNum == 0) {
|
||||
foreach( $this->graph_find_path( $this->jumpArray, $from, $to ) as $n ) {
|
||||
if ($jumpNum > 0) {
|
||||
|
||||
$jumpNode = [
|
||||
'system' => $n,
|
||||
'security' => $this->getSystemInfoBySystemId($this->idArray[$n], 'trueSec')
|
||||
];
|
||||
|
||||
$routeData['route'][] = $jumpNode;
|
||||
}
|
||||
$jumpNum++;
|
||||
}
|
||||
}
|
||||
|
||||
if ($jumpNum > 0) {
|
||||
// route found
|
||||
$routeData['routePossible'] = true;
|
||||
|
||||
$jumpNode = [
|
||||
'system' => $from,
|
||||
'security' => $this->getSystemInfoBySystemId($this->idArray[$from], 'trueSec')
|
||||
];
|
||||
|
||||
// insert "from" system on top
|
||||
array_unshift($routeData['route'], $jumpNode);
|
||||
} else {
|
||||
// route not found
|
||||
$routeData['routePossible'] = true;
|
||||
}
|
||||
|
||||
// route jumps
|
||||
$routeData['routeJumps'] = $jumpNum - 1;
|
||||
}
|
||||
|
||||
return $routeData;
|
||||
}
|
||||
|
||||
/**
|
||||
* recursive search function within a undirected graph
|
||||
* @param $G
|
||||
* @param $A
|
||||
* @param $B
|
||||
* @param int $M
|
||||
* @return array
|
||||
*/
|
||||
private function graph_find_path(&$G, $A, $B, $M = 50000){
|
||||
// $P will hold the result path at the end.
|
||||
// Remains empty if no path was found.
|
||||
$P = array();
|
||||
|
||||
// For each Node ID create a "visit information",
|
||||
// initially set as 0 (meaning not yet visited)
|
||||
// as soon as we visit a node we will tag it with the "source"
|
||||
// so we can track the path when we reach the search target
|
||||
|
||||
$V = array();
|
||||
|
||||
// We are going to keep a list of nodes that are "within reach",
|
||||
// initially this list will only contain the start node,
|
||||
// then gradually expand (almost like a flood fill)
|
||||
$R = array(trim($A));
|
||||
|
||||
$A = trim($A);
|
||||
$B = trim($B);
|
||||
|
||||
while(count($R) > 0 && $M > 0){
|
||||
$M--;
|
||||
|
||||
$X = trim(array_shift($R));
|
||||
|
||||
if( array_key_exists($X, $G) ){
|
||||
foreach($G[$X] as $Y){
|
||||
$Y = trim($Y);
|
||||
// See if we got a solution
|
||||
if($Y == $B){
|
||||
// We did? Construct a result path then
|
||||
array_push($P, $B);
|
||||
array_push($P, $X);
|
||||
while($V[$X] != $A){
|
||||
array_push($P, trim($V[$X]));
|
||||
$X = $V[$X];
|
||||
}
|
||||
array_push($P, $A);
|
||||
return array_reverse($P);
|
||||
}
|
||||
// First time we visit this node?
|
||||
if(!array_key_exists($Y, $V)){
|
||||
// Store the path so we can track it back,
|
||||
$V[$Y] = $X;
|
||||
// and add it to the "within reach" list
|
||||
array_push($R, $Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $P;
|
||||
}
|
||||
|
||||
/**
|
||||
* this funcion is just for setting up the cache table 'system_neighbour' which is used
|
||||
* for system jump calculation. Call this function manually if CCP adds Systems/Stargates
|
||||
*/
|
||||
private function setupSystemJumpTable(){
|
||||
|
||||
// switch DB
|
||||
$this->setDB('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, 2) 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 = $this->f3->get('DB')->exec($query);
|
||||
|
||||
if(count($rows) > 0){
|
||||
// switch DB back to pathfinder DB
|
||||
$this->setDB();
|
||||
|
||||
// clear cache table
|
||||
$query = "TRUNCATE system_neighbour";
|
||||
$this->f3->get('DB')->exec($query);
|
||||
|
||||
foreach($rows as $row){
|
||||
$this->f3->get('DB')->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']
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -135,14 +135,12 @@ class System extends \Controller\AccessController {
|
||||
|
||||
$rows = $this->f3->get('DB')->exec($query, null, 60 * 60 * 24);
|
||||
|
||||
|
||||
// format result
|
||||
$mapper = new Mapper\CcpSystemsMapper($rows);
|
||||
|
||||
return $mapper->getData();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* search systems by name
|
||||
* @param $f3
|
||||
@@ -244,14 +242,17 @@ class System extends \Controller\AccessController {
|
||||
$systemIds = $f3->get('POST.systemIds');
|
||||
|
||||
$user = $this->_getUser();
|
||||
$system = Model\BasicModel::getNew('SystemModel');
|
||||
|
||||
foreach($systemIds as $systemId){
|
||||
if($user){
|
||||
$system = Model\BasicModel::getNew('SystemModel');
|
||||
|
||||
$system->getById($systemId);
|
||||
$system->delete($user);
|
||||
foreach((array)$systemIds as $systemId){
|
||||
|
||||
$system->reset();
|
||||
$system->getById($systemId);
|
||||
$system->delete($user);
|
||||
|
||||
$system->reset();
|
||||
}
|
||||
}
|
||||
|
||||
echo json_encode([]);
|
||||
|
||||
@@ -119,6 +119,22 @@ class BasicModel extends \DB\Cortex{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* set "updated" field to current timestamp
|
||||
* this is useful to mark a row as "changed"
|
||||
*/
|
||||
protected function setUpdated(){
|
||||
if($this->_id > 0){
|
||||
$f3 = \Base::instance();
|
||||
$f3->get('DB')->exec(
|
||||
["UPDATE " . $this->table . " SET updated=NOW() WHERE id=:id"],
|
||||
[
|
||||
[':id' => $this->_id]
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get single dataSet by id
|
||||
* @param $id
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
namespace Model;
|
||||
|
||||
|
||||
class MapModel extends BasicModel{
|
||||
class MapModel extends BasicModel {
|
||||
|
||||
protected $table = 'map';
|
||||
protected $ttl = 5;
|
||||
@@ -31,8 +31,8 @@ class MapModel extends BasicModel{
|
||||
'mapCorporations' => array(
|
||||
'has-many' => array('Model\CorporationMapModel', 'mapId')
|
||||
),
|
||||
'mapAlliances' => array(
|
||||
'has-many' => array('Model\AllianceMapModel', 'mapId')
|
||||
'mapAlliances' => array('has-many' => array(
|
||||
'Model\AllianceMapModel', 'mapId')
|
||||
)
|
||||
);
|
||||
|
||||
@@ -52,7 +52,7 @@ class MapModel extends BasicModel{
|
||||
],
|
||||
'typeId' => [
|
||||
'regex' => '/^[1-9]+$/'
|
||||
],
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -67,11 +67,11 @@ class MapModel extends BasicModel{
|
||||
if($this->exists($key)){
|
||||
$this->$key = $value;
|
||||
}
|
||||
}else{
|
||||
} else{
|
||||
// special array data
|
||||
if($key == 'scope'){
|
||||
$this->scopeId = $value['id'];
|
||||
}elseif($key == 'type'){
|
||||
} elseif($key == 'type'){
|
||||
$this->typeId = $value['id'];
|
||||
}
|
||||
}
|
||||
@@ -85,24 +85,34 @@ class MapModel extends BasicModel{
|
||||
*/
|
||||
public function getData(){
|
||||
|
||||
$mapData = [
|
||||
'id' => $this->id,
|
||||
'name' => $this->name,
|
||||
'scope' => [
|
||||
'id' => $this->scopeId->id,
|
||||
'name' => $this->scopeId->name,
|
||||
'label' => $this->scopeId->label
|
||||
],
|
||||
'type' => [
|
||||
'id' => $this->typeId->id,
|
||||
'name' => $this->typeId->name,
|
||||
'classTab' => $this->typeId->classTab
|
||||
],
|
||||
'icon' => $this->icon,
|
||||
'updated' => strtotime($this->updated)
|
||||
$mapData = ['id' => $this->id, 'name' => $this->name, 'scope' => ['id' => $this->scopeId->id, 'name' => $this->scopeId->name, 'label' => $this->scopeId->label], 'type' => ['id' => $this->typeId->id, 'name' => $this->typeId->name, 'classTab' => $this->typeId->classTab], 'icon' => $this->icon, 'updated' => strtotime($this->updated), 'access' => ['user' => [], 'corporation' => [], 'alliance' => []]];
|
||||
|
||||
// get access object data -------------
|
||||
if($this->isPrivate()){
|
||||
$users = $this->getUsers();
|
||||
$userData = [];
|
||||
|
||||
];
|
||||
foreach($users as $user){
|
||||
$userData[] = $user->getSimpleData();
|
||||
}
|
||||
$mapData['access']['user'] = $userData;
|
||||
} elseif($this->isCorporation()){
|
||||
$corporations = $this->getCorporations();
|
||||
$corporationData = [];
|
||||
|
||||
foreach($corporations as $corporation){
|
||||
$corporationData[] = $corporation->getData();
|
||||
}
|
||||
$mapData['access']['corporation'] = $corporationData;
|
||||
} elseif($this->isAlliance()){
|
||||
$alliances = $this->getAlliances();
|
||||
$allianceData = [];
|
||||
|
||||
foreach($alliances as $alliance){
|
||||
$allianceData[] = $alliance->getData();
|
||||
}
|
||||
$mapData['access']['alliance'] = $allianceData;
|
||||
}
|
||||
|
||||
return $mapData;
|
||||
}
|
||||
@@ -127,7 +137,7 @@ class MapModel extends BasicModel{
|
||||
* @param $systemId
|
||||
* @return null
|
||||
*/
|
||||
public function getSystem( $systemId ){
|
||||
public function getSystem($systemId){
|
||||
$systems = $this->getSystems();
|
||||
$searchSystem = null;
|
||||
foreach($systems as $system){
|
||||
@@ -180,48 +190,68 @@ class MapModel extends BasicModel{
|
||||
*/
|
||||
public function setAccess($obj){
|
||||
|
||||
$newAccessGranted = false;
|
||||
|
||||
if($obj instanceof UserModel){
|
||||
// private map
|
||||
// get all userModels who have map access
|
||||
$userMaps = $this->getRelatedModels('UserMapModel', 'mapId');
|
||||
|
||||
$userFound = false;
|
||||
if($userMaps){
|
||||
foreach($userMaps as $userMap){
|
||||
if($userMap->userId->id !== $obj->id){
|
||||
// remove map access
|
||||
$userMap->erase();
|
||||
}else{
|
||||
$userFound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// check whether the user already has map access
|
||||
$this->has('mapUsers', array('active = 1 AND userId = :userId', ':userId' => $obj->id));
|
||||
$result = $this->findone(array('id = :id', ':id' => $this->id));
|
||||
|
||||
if(!$userFound){
|
||||
// set user who has access to this map
|
||||
if($result === false){
|
||||
// grant access for the user
|
||||
$userMap = self::getNew('UserMapModel');
|
||||
$userMap->userId = $obj;
|
||||
$userMap->mapId = $this;
|
||||
$userMap->save();
|
||||
|
||||
$newAccessGranted = true;
|
||||
}
|
||||
} elseif($obj instanceof CorporationModel){
|
||||
|
||||
// check whether the corporation already has map access
|
||||
$this->has('mapCorporations', array('active = 1 AND corporationId = :corporationId', ':corporationId' => $obj->id));
|
||||
$result = $this->findone(array('id = :id', ':id' => $this->id));
|
||||
|
||||
if($result === false){
|
||||
// grant access for this corporation
|
||||
$corporationMap = self::getNew('CorporationMapModel');
|
||||
$corporationMap->corporationId = $obj;
|
||||
$corporationMap->mapId = $this;
|
||||
$corporationMap->save();
|
||||
|
||||
$newAccessGranted = true;
|
||||
}
|
||||
} elseif($obj instanceof AllianceModel){
|
||||
|
||||
// check whether the corporation already has map access
|
||||
$this->has('mapAlliances', array('active = 1 AND allianceId = :allianceId', ':allianceId' => $obj->id));
|
||||
$result = $this->findone(array('id = :id', ':id' => $this->id));
|
||||
|
||||
if($result === false){
|
||||
$allianceMap = self::getNew('AllianceMapModel');
|
||||
$allianceMap->allianceId = $obj;
|
||||
$allianceMap->mapId = $this;
|
||||
$allianceMap->save();
|
||||
|
||||
$newAccessGranted = true;
|
||||
}
|
||||
}elseif($obj instanceof CorporationModel){
|
||||
$corporationMap = self::getNew('CorporationMapModel');
|
||||
$corporationMap->corporationId = $obj;
|
||||
$corporationMap->mapId = $this;
|
||||
$corporationMap->save();
|
||||
}elseif($obj instanceof AllianceModel){
|
||||
$allianceMap = self::getNew('AllianceMapModel');
|
||||
$allianceMap->allianceId = $obj;
|
||||
$allianceMap->mapId = $this;
|
||||
$allianceMap->save();
|
||||
}
|
||||
|
||||
|
||||
if($newAccessGranted){
|
||||
// mark this map as updated
|
||||
$this->setUpdated();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* clear access for a given type of objects
|
||||
* @param $clearKeys
|
||||
*/
|
||||
public function clearAccess($clearKeys){
|
||||
public function clearAccess($clearKeys = ['user', 'corporation', 'alliance']){
|
||||
|
||||
foreach($clearKeys as $key){
|
||||
switch($key){
|
||||
@@ -245,22 +275,23 @@ class MapModel extends BasicModel{
|
||||
}
|
||||
|
||||
/**
|
||||
* checks weather an object (user or alliance) has
|
||||
* @param $accessObject
|
||||
* checks weather a user has access to this map or not
|
||||
* @param $user
|
||||
* @return bool
|
||||
*/
|
||||
public function hasAccess($accessObject){
|
||||
public function hasAccess($user){
|
||||
$hasAccess = false;
|
||||
|
||||
if($accessObject instanceof UserModel){
|
||||
// get all userModels who have map access
|
||||
$userMaps = $this->getRelatedModels('UserMapModel', 'mapId');
|
||||
if($userMaps){
|
||||
foreach($userMaps as $userMap){
|
||||
if($userMap->userId->id === $accessObject->id){
|
||||
$hasAccess = true;
|
||||
break;
|
||||
}
|
||||
if($user instanceof UserModel){
|
||||
|
||||
// get all maps the user has access to
|
||||
// this includes corporation and alliance maps
|
||||
$maps = $user->getMaps();
|
||||
|
||||
foreach($maps as $map){
|
||||
if($map->id === $this->id){
|
||||
$hasAccess = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -269,22 +300,66 @@ class MapModel extends BasicModel{
|
||||
}
|
||||
|
||||
/**
|
||||
* get all user models with access to this map model
|
||||
* get all user models that have access to this map
|
||||
* @return array
|
||||
*/
|
||||
public function getUsers(){
|
||||
$this->filter('mapUsers', array('active = ?', 1));
|
||||
|
||||
$users = [];
|
||||
if($this->mapUsers){
|
||||
foreach($this->mapUsers as $mapUser){
|
||||
$users[] = $mapUser->userId;
|
||||
|
||||
if($this->isPrivate()){
|
||||
$this->filter('mapUsers', array('active = ?', 1));
|
||||
|
||||
if($this->mapUsers){
|
||||
foreach($this->mapUsers as $mapUser){
|
||||
$users[] = $mapUser->userId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $users;
|
||||
}
|
||||
|
||||
/**
|
||||
* get all corporations that have access to this map
|
||||
* @return array
|
||||
*/
|
||||
public function getCorporations(){
|
||||
$corporations = [];
|
||||
|
||||
if($this->isCorporation()){
|
||||
$this->filter('mapCorporations', array('active = ?', 1));
|
||||
|
||||
if($this->mapCorporations){
|
||||
foreach($this->mapCorporations as $mapCorporation){
|
||||
$corporations[] = $mapCorporation->corporationId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $corporations;
|
||||
}
|
||||
|
||||
/**
|
||||
* get all alliances that have access to this map
|
||||
* @return array
|
||||
*/
|
||||
public function getAlliances(){
|
||||
$alliances = [];
|
||||
|
||||
if($this->isAlliance()){
|
||||
$this->filter('mapAlliances', array('active = ?', 1));
|
||||
|
||||
if($this->mapAlliances){
|
||||
foreach($this->mapAlliances as $mapAlliance){
|
||||
$alliances[] = $mapAlliance->allianceId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $alliances;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* delete this map and all dependencies
|
||||
*/
|
||||
@@ -387,13 +462,13 @@ class MapModel extends BasicModel{
|
||||
}
|
||||
}
|
||||
|
||||
$mapUserData = (object) [];
|
||||
$mapUserData->config = (object) [];
|
||||
$mapUserData = (object)[];
|
||||
$mapUserData->config = (object)[];
|
||||
$mapUserData->config->id = $this->id;
|
||||
$mapUserData->data = (object) [];
|
||||
$mapUserData->data = (object)[];
|
||||
$mapUserData->data->systems = [];
|
||||
foreach($systems as $system){
|
||||
$systemUserData = (object) [];
|
||||
$systemUserData = (object)[];
|
||||
$systemUserData->id = $system->id;
|
||||
$systemUserData->user = [];
|
||||
|
||||
@@ -417,6 +492,26 @@ class MapModel extends BasicModel{
|
||||
return $mapUserData;
|
||||
}
|
||||
|
||||
/**
|
||||
* save a map
|
||||
* @return mixed
|
||||
*/
|
||||
public function save(){
|
||||
|
||||
$mapModel = parent::save();
|
||||
|
||||
}
|
||||
// check if map type has changed and clear access objects
|
||||
if( !$mapModel->dry() ){
|
||||
if( $mapModel->isPrivate() ){
|
||||
$mapModel->clearAccess(['corporation', 'alliance']);
|
||||
}elseif( $mapModel->isCorporation() ){
|
||||
$mapModel->clearAccess(['user', 'alliance']);
|
||||
}elseif( $mapModel->isAlliance() ){
|
||||
$mapModel->clearAccess(['user', 'corporation']);
|
||||
}
|
||||
}
|
||||
|
||||
return $mapModel;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ class SystemModel extends BasicModel {
|
||||
|
||||
/**
|
||||
* delete a system from a map
|
||||
* hint: signatures will be deleted on cascade
|
||||
* hint: signatures and connections will be deleted on cascade
|
||||
* @param $accessObject
|
||||
*/
|
||||
public function delete($accessObject){
|
||||
@@ -140,46 +140,11 @@ class SystemModel extends BasicModel {
|
||||
if(! $this->dry()){
|
||||
// check if user has access
|
||||
if($this->hasAccess($accessObject)){
|
||||
// delete all system connections
|
||||
$connections = $this->getConnections();
|
||||
|
||||
if(is_object($connections)){
|
||||
foreach($connections as $connection){
|
||||
$connection->erase();
|
||||
}
|
||||
}
|
||||
$this->erase();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get all connections for this system
|
||||
* @return array
|
||||
*/
|
||||
public function getConnections(){
|
||||
$connections = false;
|
||||
|
||||
// connections where system is source
|
||||
$sourceConnections = $this->getRelatedModels('ConnectionModel', 'source');
|
||||
$targetConnections = $this->getRelatedModels('ConnectionModel', 'target');
|
||||
|
||||
if(is_object($sourceConnections)){
|
||||
$connections = $sourceConnections;
|
||||
}
|
||||
|
||||
if(is_object($targetConnections)){
|
||||
if(is_object($connections)){
|
||||
$connections->append($targetConnections);
|
||||
}else{
|
||||
$connections = $targetConnections;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return $connections;
|
||||
}
|
||||
|
||||
/**
|
||||
* get all signatures of this system
|
||||
* @return array
|
||||
|
||||
@@ -62,6 +62,7 @@ class SystemSignatureModel extends BasicModel {
|
||||
'groupId' => $this->groupId,
|
||||
'typeId' => $this->typeId,
|
||||
'name' => $this->name,
|
||||
'description' => $this->description,
|
||||
'created' => [
|
||||
'character' => $this->createdCharacterId->getData(),
|
||||
'created' => strtotime($this->created)
|
||||
|
||||
@@ -45,13 +45,16 @@ class UserModel extends BasicModel {
|
||||
|
||||
/**
|
||||
* get all data for this user
|
||||
* ! caution ! this function returns sensitive data!
|
||||
* -> user getSimpleData() for faster performance and public user data
|
||||
* @return object
|
||||
*/
|
||||
public function getData(){
|
||||
|
||||
$userData = (object) [];
|
||||
$userData->id = $this->id;
|
||||
$userData->name = $this->name;
|
||||
// get public user data for this user
|
||||
$userData = $this->getSimpleData();
|
||||
|
||||
// add sensitive user data
|
||||
$userData->email = $this->email;
|
||||
|
||||
// api data
|
||||
@@ -76,6 +79,19 @@ class UserModel extends BasicModel {
|
||||
return $userData;
|
||||
}
|
||||
|
||||
/**
|
||||
* get public user data
|
||||
* - check out getData() for all user data
|
||||
* @return object
|
||||
*/
|
||||
public function getSimpleData(){
|
||||
$userData = (object) [];
|
||||
$userData->id = $this->id;
|
||||
$userData->name = $this->name;
|
||||
|
||||
return $userData;
|
||||
}
|
||||
|
||||
/**
|
||||
* validate and set a email address for this user
|
||||
* @param $email
|
||||
|
||||
@@ -7,6 +7,7 @@ GET|POST @map: /map= Controller\MapController->showMap, 86400
|
||||
; APIs
|
||||
GET|POST /api/@controller/@action = Controller\Api\@controller->@action, 0, 512
|
||||
GET|POST /api/@controller/@action/@arg1 = Controller\Api\@controller->@action, 0, 512
|
||||
GET|POST /api/@controller/@action/@arg1/@arg2 = Controller\Api\@controller->@action, 0, 512
|
||||
|
||||
; cronjob APIs
|
||||
GET /cron/@controller/@action = Controller\Cron\@controller->@action
|
||||
|
||||
13
js/app.js
13
js/app.js
@@ -13,11 +13,13 @@ requirejs.config({
|
||||
velocityUI: 'lib/velocity.ui.min', // v5.0.3 plugin for velocity - http://julian.com/research/velocity/#uiPack
|
||||
templates: '../public/templates', // template dir
|
||||
slidebars: 'lib/slidebars', // v0.10 Slidebars - side menu plugin http://plugins.adchsm.me/slidebars/
|
||||
jsPlumb: 'lib/dom.jsPlumb-1.7.2-min', // v1.7.2 jsPlumb (Vanilla)- main map draw plugin http://www.jsplumb.org/
|
||||
jsPlumb: 'lib/dom.jsPlumb-1.7.5-min', // v1.7.5 jsPlumb (Vanilla)- main map draw plugin http://www.jsplumb.org/
|
||||
customScrollbar: 'lib/jquery.mCustomScrollbar.concat.min', // v3.1.11 Custom scroll bars - http://manos.malihu.gr/
|
||||
datatables: 'lib/datatables/jquery.dataTables.min', // v1.10.7 DataTables - https://datatables.net/
|
||||
datatablesBootstrap: 'lib/datatables/dataTables.bootstrap', // DataTables - not used (bootstrap style)
|
||||
datatablesTableTools: 'lib/datatables/extensions/TableTools/js/dataTables.tableTools', // v2.2.3 TableTools (PlugIn) - https://datatables.net/extensions/tabletools/
|
||||
datatablesResponsive: 'lib/datatables/extensions/responsive/dataTables.responsive', // v1.0.6 TableTools (PlugIn) - https://datatables.net/extensions/responsive/
|
||||
|
||||
datatablesTableTools: 'lib/datatables/extensions/tabletools/js/dataTables.tableTools', // v2.2.3 TableTools (PlugIn) - https://datatables.net/extensions/tabletools/
|
||||
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)
|
||||
@@ -68,10 +70,13 @@ requirejs.config({
|
||||
datatables: {
|
||||
deps: ['jquery']
|
||||
},
|
||||
datatablesTableTools: {
|
||||
datatablesBootstrap: {
|
||||
deps: ['datatables']
|
||||
},
|
||||
datatablesBootstrap: {
|
||||
datatablesResponsive: {
|
||||
deps: ['datatables']
|
||||
},
|
||||
datatablesTableTools: {
|
||||
deps: ['datatables']
|
||||
},
|
||||
xEditable: {
|
||||
|
||||
@@ -8,6 +8,7 @@ define(['jquery'], function($) {
|
||||
|
||||
var Config = {
|
||||
timer: {
|
||||
dblClickTimer: 250, // ms: double click timer
|
||||
programStatusVisible: 5000, // ms: timer for status change visibility in head
|
||||
mapUpdate: {
|
||||
delay: 3000, // ms: delay between ping calls
|
||||
@@ -23,11 +24,14 @@ define(['jquery'], function($) {
|
||||
},
|
||||
path: {
|
||||
img: 'public/img/', // path for images
|
||||
// map init and trigger
|
||||
// user API
|
||||
getCaptcha: 'api/user/getCaptcha', // ajax URL - get captcha image
|
||||
logIn: 'api/user/logIn', // ajax URL - login
|
||||
logOut: 'api/user/logOut', // ajax URL - logout
|
||||
saveUserConfig: 'api/user/saveConfig', // ajax URL - saves custom configuration
|
||||
// access API
|
||||
searchAccess: 'api/access/search', // ajax URL - search corporation by name
|
||||
// main config/map ping API
|
||||
initMap: 'api/map/init', // ajax URL - get static data
|
||||
updateMapData: 'api/map/updateData', // ajax URL - main map update trigger
|
||||
updateUserData: 'api/map/updateUserData', // ajax URL - main map user data trigger
|
||||
|
||||
@@ -34,7 +34,10 @@ define([
|
||||
|
||||
// gallery
|
||||
galleryId: 'pf-gallery', // id for gallery container
|
||||
galleryThumbContainerId: 'pf-landing-gallery-thumb-container' // id for gallery thumb images
|
||||
galleryThumbContainerId: 'pf-landing-gallery-thumb-container', // id for gallery thumb images
|
||||
|
||||
// animation
|
||||
animateElementClass: 'pf-animate-on-visible' // class for elements that will be animated to show
|
||||
};
|
||||
|
||||
|
||||
@@ -164,7 +167,7 @@ define([
|
||||
var showGallery = function(){
|
||||
// thumb links
|
||||
var thumbLinks = $('#' + config.galleryThumbContainerId + ' a');
|
||||
|
||||
/*
|
||||
// show thumbs
|
||||
thumbLinks.velocity('transition.slideRightBigIn', {
|
||||
duration: 1200,
|
||||
@@ -173,6 +176,7 @@ define([
|
||||
visibility: 'visible'
|
||||
|
||||
});
|
||||
*/
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -180,12 +184,36 @@ define([
|
||||
*/
|
||||
var initScrollspy = function(){
|
||||
// init scrollspy
|
||||
$('body').scrollspy({ target: '#' + config.navigationElementId });
|
||||
|
||||
$('#' + config.navigationElementId).on('activate.bs.scrollspy', function (e) {
|
||||
$( window ).scroll(function() {
|
||||
|
||||
var ancorTag = $(e.target).find('a').attr('href');
|
||||
console.log(ancorTag);
|
||||
// find all elements that should be animated
|
||||
var visibleElements = $('.' + config.animateElementClass).isInViewport();
|
||||
|
||||
$(visibleElements).removeClass( config.animateElementClass );
|
||||
|
||||
$(visibleElements).velocity('transition.flipXIn', {
|
||||
duration: 600,
|
||||
stagger: 60,
|
||||
delay: 500,
|
||||
complete: function(element){
|
||||
$(element).find('.fade').addClass('in');
|
||||
},
|
||||
visibility: 'visible'
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// event listener for navigation links
|
||||
$('.page-scroll').on('click', function(){
|
||||
// get element to scroll
|
||||
var anchorTag = $(this).attr('data-anchor');
|
||||
|
||||
// scroll to container
|
||||
$(anchorTag).velocity('scroll', {
|
||||
duration: 300,
|
||||
easing: 'swing'
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -16,11 +16,6 @@ define([
|
||||
|
||||
'use strict';
|
||||
|
||||
var config = {
|
||||
mapModuleId: 'pf-map-module'
|
||||
};
|
||||
|
||||
|
||||
$(function(){
|
||||
// load page
|
||||
$('body').loadPageStructure();
|
||||
@@ -29,7 +24,7 @@ define([
|
||||
Logging.init();
|
||||
|
||||
// page initialized event ==============================================================
|
||||
$('#' + config.mapModuleId).on('pf:initModule', function(){
|
||||
$('#' + Util.config.mapModuleId).on('pf:initModule', function(){
|
||||
|
||||
if(! CCP.isTrusted()){
|
||||
// show trust message
|
||||
@@ -50,6 +45,7 @@ define([
|
||||
Init.systemStatus = initData.systemStatus;
|
||||
Init.systemType = initData.systemType;
|
||||
Init.characterStatus = initData.characterStatus;
|
||||
Init.maxSharedCount = initData.maxSharedCount;
|
||||
|
||||
// init map module
|
||||
mapModule.initMapModule();
|
||||
@@ -110,25 +106,35 @@ define([
|
||||
dataType: 'json'
|
||||
}).done(function(mapData){
|
||||
|
||||
$(document).setProgramStatus('online');
|
||||
|
||||
if(mapData.length === 0){
|
||||
// no map data available -> show "new map" dialog
|
||||
$(document).trigger('pf:menuShowMapSettings');
|
||||
if(
|
||||
mapData.error &&
|
||||
mapData.error.length > 0
|
||||
){
|
||||
// anny error in the main trigger functions result in a user log-off
|
||||
$(document).trigger('pf:menuLogout');
|
||||
}else{
|
||||
// map data found
|
||||
|
||||
// load map module
|
||||
mapModule.updateMapModule(mapData);
|
||||
$(document).setProgramStatus('online');
|
||||
|
||||
// log execution time
|
||||
var duration = Util.timeStop(mapUpdateKey);
|
||||
Util.log(mapUpdateKey, {duration: duration, description: 'updateMapModule'});
|
||||
if(mapData.length === 0){
|
||||
// no map data available -> show "new map" dialog
|
||||
$(document).trigger('pf:menuShowMapSettings', {tab: 'new'});
|
||||
}else{
|
||||
// map data found
|
||||
|
||||
// load map module
|
||||
mapModule.updateMapModule(mapData);
|
||||
|
||||
// log execution time
|
||||
var duration = Util.timeStop(mapUpdateKey);
|
||||
Util.log(mapUpdateKey, {duration: duration, description: 'updateMapModule'});
|
||||
}
|
||||
// init new trigger
|
||||
setTimeout(function(){
|
||||
triggerMapUpdatePing();
|
||||
}, mapUpdateDelay);
|
||||
}
|
||||
// init new trigger
|
||||
setTimeout(function(){
|
||||
triggerMapUpdatePing();
|
||||
}, mapUpdateDelay);
|
||||
|
||||
|
||||
}).fail(function( jqXHR, status, error) {
|
||||
var reason = status + ' ' + jqXHR.status + ': ' + error;
|
||||
@@ -155,31 +161,36 @@ define([
|
||||
dataType: 'json'
|
||||
}).done(function(data){
|
||||
|
||||
$(document).setProgramStatus('online');
|
||||
if(data.error.length > 0){
|
||||
// anny error in the main trigger functions result in a user log-off
|
||||
$(document).trigger('pf:menuLogout');
|
||||
}else{
|
||||
|
||||
if(data.userData !== undefined){
|
||||
// store current user data global (cache)
|
||||
var userData = Util.setCurrentUserData(data.userData);
|
||||
$(document).setProgramStatus('online');
|
||||
|
||||
if(userData.character === undefined){
|
||||
// no active character found -> show settings dialog
|
||||
$(document).triggerMenuEvent('ShowSettingsDialog');
|
||||
}else{
|
||||
// active character data found
|
||||
if(data.userData !== undefined){
|
||||
// store current user data global (cache)
|
||||
var userData = Util.setCurrentUserData(data.userData);
|
||||
|
||||
mapModule.updateMapModuleData(data);
|
||||
var duration = Util.timeStop(mapUserUpdateKey);
|
||||
if(userData.character === undefined){
|
||||
// no active character found -> show settings dialog
|
||||
$(document).triggerMenuEvent('ShowSettingsDialog');
|
||||
}else{
|
||||
// active character data found
|
||||
|
||||
// log execution time
|
||||
Util.log(mapUserUpdateKey, {duration: duration, description:'updateMapModuleData'});
|
||||
mapModule.updateMapModuleData(data);
|
||||
var duration = Util.timeStop(mapUserUpdateKey);
|
||||
|
||||
// log execution time
|
||||
Util.log(mapUserUpdateKey, {duration: duration, description:'updateMapModuleData'});
|
||||
|
||||
|
||||
// init new trigger
|
||||
setTimeout(function(){
|
||||
triggerUserUpdatePing();
|
||||
}, mapUserUpdateDelay);
|
||||
// init new trigger
|
||||
setTimeout(function(){
|
||||
triggerUserUpdatePing();
|
||||
}, mapUserUpdateDelay);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}).fail(function( jqXHR, status, error) {
|
||||
|
||||
@@ -619,166 +619,170 @@ define([
|
||||
|
||||
var mapContainer = mapConfig.map.getContainer();
|
||||
|
||||
// prevent jsPlumb from re-painting during main-map update -> performance boost :)
|
||||
mapConfig.map.doWhileSuspended(function() {
|
||||
|
||||
if(mapContainer === undefined){
|
||||
// add new map
|
||||
if(mapContainer === undefined){
|
||||
// add new map
|
||||
|
||||
// create map wrapper
|
||||
var mapWrapper = $('<div>', {
|
||||
class: config.mapWrapperClass
|
||||
});
|
||||
// create map wrapper
|
||||
var mapWrapper = $('<div>', {
|
||||
class: config.mapWrapperClass
|
||||
});
|
||||
|
||||
// create new map container
|
||||
mapContainer = $('<div>', {
|
||||
id: config.mapIdPrefix + mapConfig.config.id,
|
||||
class: [config.mapClass].join(' ')
|
||||
});
|
||||
// create new map container
|
||||
mapContainer = $('<div>', {
|
||||
id: config.mapIdPrefix + mapConfig.config.id,
|
||||
class: [config.mapClass].join(' ')
|
||||
});
|
||||
|
||||
// add additional information
|
||||
mapContainer.data('id', mapConfig.config.id);
|
||||
// add additional information
|
||||
mapContainer.data('id', mapConfig.config.id);
|
||||
|
||||
mapWrapper.append(mapContainer);
|
||||
mapWrapper.append(mapContainer);
|
||||
|
||||
// append mapWrapper to parent element (at the top)
|
||||
$(parentElement).prepend(mapWrapper);
|
||||
// append mapWrapper to parent element (at the top)
|
||||
$(parentElement).prepend(mapWrapper);
|
||||
|
||||
// set main Container for current map -> the container exists now in DOM !! very important
|
||||
mapConfig.map.setContainer($('#' + config.mapIdPrefix + mapConfig.config.id));
|
||||
// set main Container for current map -> the container exists now in DOM !! very important
|
||||
mapConfig.map.setContainer($('#' + config.mapIdPrefix + mapConfig.config.id));
|
||||
|
||||
// set map observer
|
||||
setMapObserver(mapConfig.map);
|
||||
// set map observer
|
||||
setMapObserver(mapConfig.map);
|
||||
}
|
||||
|
||||
mapContainer = $(mapContainer);
|
||||
|
||||
// add additional information for this map
|
||||
if(mapContainer.data('updated') !== mapConfig.config.updated){
|
||||
mapContainer.data('name', mapConfig.config.name);
|
||||
mapContainer.data('scopeId', mapConfig.config.scope.id);
|
||||
mapContainer.data('typeId', mapConfig.config.type.id);
|
||||
mapContainer.data('icon', mapConfig.config.icon);
|
||||
mapContainer.data('updated', mapConfig.config.updated);
|
||||
}
|
||||
|
||||
|
||||
// get map data
|
||||
var mapData = mapContainer.getMapDataFromClient();
|
||||
|
||||
if(mapData !== false){
|
||||
// map data available -> map not locked by update counter :)
|
||||
var currentSystemData = mapData.data.systems;
|
||||
var currentConnectionData = mapData.data.connections;
|
||||
|
||||
// update systems ===========================================================
|
||||
|
||||
for(var i = 0; i < mapConfig.data.systems.length; i++){
|
||||
var systemData = mapConfig.data.systems[i];
|
||||
|
||||
// add system
|
||||
var addNewSystem = true;
|
||||
|
||||
for(var k = 0; k < currentSystemData.length; k++){
|
||||
if(currentSystemData[k].id === systemData.id){
|
||||
if( currentSystemData[k].updated.updated < systemData.updated.updated ){
|
||||
// system changed -> update
|
||||
mapContainer.getSystem(mapConfig.map, systemData);
|
||||
}
|
||||
|
||||
addNewSystem = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( addNewSystem === true){
|
||||
drawSystem(mapConfig.map, systemData);
|
||||
}
|
||||
}
|
||||
|
||||
mapContainer = $(mapContainer);
|
||||
// check for systems that are gone -> delete system
|
||||
for(var a = 0; a < currentSystemData.length; a++){
|
||||
|
||||
// add additional information for this map
|
||||
if(mapContainer.data('updated') !== mapConfig.config.updated){
|
||||
mapContainer.data('name', mapConfig.config.name);
|
||||
mapContainer.data('scopeId', mapConfig.config.scope.id);
|
||||
mapContainer.data('typeId', mapConfig.config.type.id);
|
||||
mapContainer.data('icon', mapConfig.config.icon);
|
||||
mapContainer.data('updated', mapConfig.config.updated);
|
||||
var deleteThisSystem = true;
|
||||
|
||||
for(var b = 0; b < mapConfig.data.systems.length; b++){
|
||||
var deleteSystemData = mapConfig.data.systems[b];
|
||||
|
||||
if(deleteSystemData.id === currentSystemData[a].id){
|
||||
deleteThisSystem = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(deleteThisSystem === true){
|
||||
var deleteSystem = $('#' + config.systemIdPrefix + mapContainer.data('id') + '-' + currentSystemData[a].id);
|
||||
|
||||
// system not found -> delete system
|
||||
removeSystem(mapConfig.map, deleteSystem);
|
||||
}
|
||||
}
|
||||
|
||||
// update connections =========================================================
|
||||
|
||||
// get map data
|
||||
var mapData = mapContainer.getMapData();
|
||||
// set up default connections
|
||||
for(var j = 0; j < mapConfig.data.connections.length; j++){
|
||||
var connectionData = mapConfig.data.connections[j];
|
||||
|
||||
if(mapData !== false){
|
||||
// map data available -> map not locked by update counter :)
|
||||
var currentSystemData = mapData.data.systems;
|
||||
var currentConnectionData = mapData.data.connections;
|
||||
|
||||
// update systems ===========================================================
|
||||
|
||||
for(var i = 0; i < mapConfig.data.systems.length; i++){
|
||||
var systemData = mapConfig.data.systems[i];
|
||||
|
||||
// add system
|
||||
var addNewSystem = true;
|
||||
|
||||
for(var k = 0; k < currentSystemData.length; k++){
|
||||
if(currentSystemData[k].id === systemData.id){
|
||||
if( currentSystemData[k].updated.updated < systemData.updated.updated ){
|
||||
// system changed -> update
|
||||
mapContainer.getSystem(mapConfig.map, systemData);
|
||||
}
|
||||
|
||||
addNewSystem = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if( addNewSystem === true){
|
||||
drawSystem(mapConfig.map, systemData);
|
||||
}
|
||||
}
|
||||
|
||||
// check for systems that are gone -> delete system
|
||||
for(var a = 0; a < currentSystemData.length; a++){
|
||||
|
||||
var deleteThisSystem = true;
|
||||
|
||||
for(var b = 0; b < mapConfig.data.systems.length; b++){
|
||||
var deleteSystemData = mapConfig.data.systems[b];
|
||||
|
||||
if(deleteSystemData.id === currentSystemData[a].id){
|
||||
deleteThisSystem = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(deleteThisSystem === true){
|
||||
var deleteSystem = $('#' + config.systemIdPrefix + mapContainer.data('id') + '-' + currentSystemData[a].id);
|
||||
|
||||
// system not found -> delete system
|
||||
removeSystem(mapConfig.map, deleteSystem);
|
||||
}
|
||||
}
|
||||
|
||||
// update connections =========================================================
|
||||
|
||||
// set up default connections
|
||||
for(var j = 0; j < mapConfig.data.connections.length; j++){
|
||||
var connectionData = mapConfig.data.connections[j];
|
||||
|
||||
// add connection
|
||||
var addNewConnection= true;
|
||||
|
||||
for(var c = 0; c < currentConnectionData.length; c++){
|
||||
if(
|
||||
currentConnectionData[c].id === connectionData.id
|
||||
){
|
||||
// connection already exists -> check for updates
|
||||
if(
|
||||
currentConnectionData[c].updated < connectionData.updated
|
||||
){
|
||||
// connection changed -> update
|
||||
var tempConnection = ativeConnections[mapData.config.id][connectionData.id];
|
||||
updateConnection(tempConnection, currentConnectionData[c], connectionData);
|
||||
}
|
||||
|
||||
addNewConnection = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(addNewConnection === true){
|
||||
drawConnection(mapConfig.map, connectionData);
|
||||
}
|
||||
}
|
||||
|
||||
// check for connections that are gone -> delete connection
|
||||
for(var d = 0; d < currentConnectionData.length; d++){
|
||||
|
||||
var deleteThisConnection = true;
|
||||
|
||||
for(var e = 0; e < mapConfig.data.connections.length;e++){
|
||||
var deleteConnectionData = mapConfig.data.connections[e];
|
||||
|
||||
if(deleteConnectionData.id === currentConnectionData[d].id){
|
||||
deleteThisConnection = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// add connection
|
||||
var addNewConnection= true;
|
||||
|
||||
for(var c = 0; c < currentConnectionData.length; c++){
|
||||
if(
|
||||
deleteThisConnection === true &&
|
||||
ativeConnections[mapData.config.id][currentConnectionData[d].id] !== undefined
|
||||
currentConnectionData[c].id === connectionData.id
|
||||
){
|
||||
// connection already exists -> check for updates
|
||||
if(
|
||||
currentConnectionData[c].updated < connectionData.updated
|
||||
){
|
||||
// connection changed -> update
|
||||
var tempConnection = ativeConnections[mapData.config.id][connectionData.id];
|
||||
updateConnection(tempConnection, currentConnectionData[c], connectionData);
|
||||
}
|
||||
|
||||
addNewConnection = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(addNewConnection === true){
|
||||
drawConnection(mapConfig.map, connectionData);
|
||||
}
|
||||
}
|
||||
|
||||
// check for connections that are gone -> delete connection
|
||||
for(var d = 0; d < currentConnectionData.length; d++){
|
||||
|
||||
var deleteThisConnection = true;
|
||||
|
||||
for(var e = 0; e < mapConfig.data.connections.length;e++){
|
||||
var deleteConnectionData = mapConfig.data.connections[e];
|
||||
|
||||
if(deleteConnectionData.id === currentConnectionData[d].id){
|
||||
deleteThisConnection = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(
|
||||
deleteThisConnection === true &&
|
||||
ativeConnections[mapData.config.id][currentConnectionData[d].id] !== undefined
|
||||
){
|
||||
// connection not found -> delete connection
|
||||
var deleteConnection = ativeConnections[mapData.config.id][currentConnectionData[d].id];
|
||||
|
||||
// check if "source" and "target" still exist before remove
|
||||
// this is NOT the case if the system was removed previous
|
||||
if(
|
||||
deleteConnection.source &&
|
||||
deleteConnection.target
|
||||
){
|
||||
// connection not found -> delete connection
|
||||
var deleteConnection = ativeConnections[mapData.config.id][currentConnectionData[d].id];
|
||||
mapConfig.map.detach(deleteConnection, {fireEvent: false});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// repaint all connections because of some strange visual bugs -_-
|
||||
mapConfig.map.repaintEverything();
|
||||
}
|
||||
});
|
||||
|
||||
// repaint all connections because of some strange visual bugs -_-
|
||||
mapConfig.map.repaintEverything();
|
||||
}
|
||||
|
||||
|
||||
return mapContainer;
|
||||
@@ -804,6 +808,7 @@ define([
|
||||
// no visual effects in IGB (glitches)
|
||||
if(
|
||||
systemElements.length === 0 ||
|
||||
endpointElements.length === 0 ||
|
||||
CCP.isInGameBrowser() === true
|
||||
){
|
||||
callback();
|
||||
@@ -827,20 +832,17 @@ define([
|
||||
// show connections
|
||||
endpointElements.velocity('transition.fadeIn', {
|
||||
stagger: 50,
|
||||
drag: true,
|
||||
duration: 50,
|
||||
duration: 50
|
||||
});
|
||||
|
||||
connectorElements.velocity('transition.flipBounceXIn', {
|
||||
connectorElements.velocity('transition.fadeIn', {
|
||||
stagger: 50,
|
||||
drag: true,
|
||||
duration: 1000,
|
||||
duration: 180
|
||||
});
|
||||
|
||||
overlayElements.delay(500).velocity('transition.fadeIn', {
|
||||
stagger: 50,
|
||||
drag: true,
|
||||
duration: 200,
|
||||
duration: 180,
|
||||
display: 'auto',
|
||||
complete: function(){
|
||||
callback();
|
||||
@@ -854,15 +856,15 @@ define([
|
||||
$('.mCSB_container').velocity('callout.shake', {
|
||||
stagger: 0,
|
||||
drag: false,
|
||||
duration: 200,
|
||||
display: 'auto',
|
||||
duration: 180,
|
||||
display: 'auto'
|
||||
});
|
||||
|
||||
overlayElements.velocity('transition.fadeOut', {
|
||||
stagger: 50,
|
||||
drag: true,
|
||||
duration: 200,
|
||||
display: 'auto',
|
||||
duration: 180,
|
||||
display: 'auto'
|
||||
});
|
||||
|
||||
endpointElements.velocity('transition.fadeOut', {
|
||||
@@ -876,13 +878,13 @@ define([
|
||||
stagger: 0,
|
||||
drag: true,
|
||||
duration: 20,
|
||||
display: 'block',
|
||||
display: 'block'
|
||||
});
|
||||
|
||||
systemElements.delay(100).velocity('transition.slideUpOut', {
|
||||
stagger: 50,
|
||||
drag: true,
|
||||
duration: 200,
|
||||
duration: 180,
|
||||
display: 'block',
|
||||
complete: function(){
|
||||
callback();
|
||||
@@ -999,6 +1001,8 @@ define([
|
||||
|
||||
var mapContainer = $( map.getContainer() );
|
||||
|
||||
mapContainer.getMapOverlay().startMapUpdateCounter();
|
||||
|
||||
var systemIds = [];
|
||||
// systemIds for delete request
|
||||
for(var i = 0; i < systems.length; i++){
|
||||
@@ -1024,7 +1028,7 @@ define([
|
||||
for(var i = 0; i < systems.length; i++){
|
||||
var system = $(systems[i]);
|
||||
triggerData.systemIds.push( system.data('id') );
|
||||
removeSystem(map, system);
|
||||
removeSystem(map, system );
|
||||
}
|
||||
|
||||
// trigger "system deleted" on Tab Content Element
|
||||
@@ -1048,11 +1052,8 @@ define([
|
||||
var removeSystem = function(map, system){
|
||||
system = $(system);
|
||||
|
||||
// detach all connections
|
||||
map.detachAllConnections(system);
|
||||
|
||||
// delete all endpoints
|
||||
map.removeAllEndpoints(system);
|
||||
// remove endpoints and their connections
|
||||
map.removeAllEndpoints (system);
|
||||
|
||||
// hide tooltip
|
||||
system.toggleSystemTooltip('hide', {});
|
||||
@@ -1061,7 +1062,7 @@ define([
|
||||
system.velocity('transition.whirlOut', {
|
||||
duration: Init.animationSpeed.mapDeleteSystem,
|
||||
complete: function(){
|
||||
$(this).remove() ;
|
||||
map.remove(this);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1069,26 +1070,26 @@ define([
|
||||
|
||||
|
||||
/**
|
||||
* make a system name editable by x-editable
|
||||
* make a system name/alias editable by x-editable
|
||||
* @param system
|
||||
*/
|
||||
var makeEditable = function(system){
|
||||
|
||||
system = $(system);
|
||||
var headElement = $(system).find('.' + config.systemHeadNameClass);
|
||||
|
||||
$(headElement).editable({
|
||||
headElement.editable({
|
||||
mode: 'popup',
|
||||
type: 'text',
|
||||
title: 'system name',
|
||||
title: 'System alias',
|
||||
placement: 'top',
|
||||
onblur: 'submit',
|
||||
toggle: 'dblclick',
|
||||
toggle: 'manual', // is triggered manually on dblclick
|
||||
showbuttons: false
|
||||
});
|
||||
|
||||
// update z-index for system, editable field should be on top
|
||||
$(headElement).on('shown', function(e, editable) {
|
||||
updateZIndex(system);
|
||||
headElement.on('save', function(e, params) {
|
||||
// system alias changed -> mark system as updated
|
||||
system.markAsChanged();
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1161,29 +1162,29 @@ define([
|
||||
var seconds = config.logTimerCount;
|
||||
var fadeEffectDuration = 200;
|
||||
|
||||
// get counter interval (in case there is an active one)
|
||||
var interval = counterChart.data('interval');
|
||||
|
||||
if(interval){
|
||||
clearInterval(interval);
|
||||
}
|
||||
|
||||
mapOverlay.velocity('stop').velocity('transition.whirlIn', { duration: fadeEffectDuration });
|
||||
|
||||
var counterChartLabel = counterChart.find('span');
|
||||
|
||||
var percentPerCount = 100 / seconds;
|
||||
|
||||
// update counter
|
||||
var updateChart = function(tempSeconds){
|
||||
var 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
|
||||
var timer = function(){
|
||||
seconds--;
|
||||
|
||||
var pieChart = counterChart.data('easyPieChart');
|
||||
// check if chart is available
|
||||
if(pieChart !== undefined){
|
||||
counterChart.data('easyPieChart').update( percentPerCount * seconds);
|
||||
}
|
||||
counterChartLabel.text(seconds);
|
||||
if(seconds <= 0){
|
||||
if(seconds >= 0){
|
||||
// update counter
|
||||
updateChart(seconds);
|
||||
}else{
|
||||
// hide counter and reset
|
||||
clearInterval(mapUpdateCounter);
|
||||
|
||||
mapOverlay.velocity('transition.whirlOut', {
|
||||
@@ -1195,17 +1196,26 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
// start timer
|
||||
var mapUpdateCounter = setInterval(timer, 1000);
|
||||
var pieChart = counterChart.data('easyPieChart');
|
||||
if(pieChart !== undefined){
|
||||
pieChart.update( percentPerCount * seconds);
|
||||
}
|
||||
counterChartLabel.text(seconds);
|
||||
// get counter interval (in case there is an active one) ---------------------------
|
||||
var interval = counterChart.data('interval');
|
||||
|
||||
// store counter
|
||||
if(interval){
|
||||
clearInterval(interval);
|
||||
}
|
||||
|
||||
// start timer ---------------------------------------------------------------------
|
||||
var mapUpdateCounter = setInterval(timer, 1000);
|
||||
updateChart(seconds);
|
||||
|
||||
// store counter -------------------------------------------------------------------
|
||||
counterChart.data('interval', mapUpdateCounter);
|
||||
|
||||
// show overlay -------------------------------------------------------------------
|
||||
if(mapOverlay.is(':hidden')){
|
||||
mapOverlay.velocity('stop').velocity('transition.whirlIn', { duration: fadeEffectDuration });
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1321,6 +1331,10 @@ define([
|
||||
*/
|
||||
var saveConnection = function(connection){
|
||||
|
||||
var map = connection._jsPlumb.instance;
|
||||
var mapContainer = $( map.getContainer() );
|
||||
mapContainer.getMapOverlay().startMapUpdateCounter();
|
||||
|
||||
var connectionData = getDataByConnection(connection);
|
||||
|
||||
var requestData = {
|
||||
@@ -1358,45 +1372,68 @@ define([
|
||||
/**
|
||||
* Programmatically delete a connection and all related data
|
||||
* @param connections
|
||||
* @param deleteOnServer
|
||||
*/
|
||||
var deleteConnections = function(connections){
|
||||
var deleteConnections = function(connections, deleteOnServer){
|
||||
|
||||
var connectionIds = [];
|
||||
// systemIds for delete request
|
||||
for(var i = 0; i < connections.length; i++){
|
||||
var connectionId = connections[i].getParameter('connectionId');
|
||||
// drag&drop a new connection does not have an id yet, if connection is not established correct
|
||||
if(connectionId !== undefined){
|
||||
connectionIds[i] = connections[i].getParameter('connectionId');
|
||||
if(connections.length > 0){
|
||||
|
||||
// remove connections from map
|
||||
var removeConnections = function(tempConnections){
|
||||
for(var i = 0; i < tempConnections.length; i++){
|
||||
// if a connection is manually (drag&drop) detached, the jsPlumb instance does not exist any more
|
||||
// connection is already deleted!
|
||||
if(tempConnections[i]._jsPlumb){
|
||||
tempConnections[i]._jsPlumb.instance.detach(tempConnections[i], {fireEvent: false});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if(deleteOnServer === true){
|
||||
// prepare delete request
|
||||
|
||||
var map = connections[0]._jsPlumb.instance;
|
||||
var mapContainer = $( map.getContainer() );
|
||||
mapContainer.getMapOverlay().startMapUpdateCounter();
|
||||
|
||||
|
||||
var connectionIds = [];
|
||||
// systemIds for delete request
|
||||
for(var i = 0; i < connections.length; i++){
|
||||
var connectionId = connections[i].getParameter('connectionId');
|
||||
// drag&drop a new connection does not have an id yet, if connection is not established correct
|
||||
if(connectionId !== undefined){
|
||||
connectionIds[i] = connections[i].getParameter('connectionId');
|
||||
}
|
||||
}
|
||||
|
||||
if(connectionIds.length > 0){
|
||||
var requestData = {
|
||||
connectionIds: connectionIds
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: Init.path.deleteConnection,
|
||||
data: requestData,
|
||||
dataType: 'json'
|
||||
}).done(function(data){
|
||||
|
||||
// remove connections from map
|
||||
removeConnections(connections);
|
||||
|
||||
}).fail(function( jqXHR, status, error) {
|
||||
var reason = status + ' ' + error;
|
||||
Util.showNotify({title: jqXHR.status + ': deleteSystem', text: reason, type: 'warning'});
|
||||
$(document).setProgramStatus('problem');
|
||||
});
|
||||
}
|
||||
}else{
|
||||
// remove connections from map (no request)
|
||||
removeConnections(connections);
|
||||
}
|
||||
}
|
||||
|
||||
if(connectionIds.length > 0){
|
||||
var requestData = {
|
||||
connectionIds: connectionIds
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: Init.path.deleteConnection,
|
||||
data: requestData,
|
||||
dataType: 'json'
|
||||
}).done(function(data){
|
||||
|
||||
// remove systems from map
|
||||
for(var i = 0; i < connections.length; i++){
|
||||
// if a connection is manually (drag&drop) detached, the jsPlumb instance does not exist any more
|
||||
// connection is already deleted!
|
||||
if(connections[i]._jsPlumb){
|
||||
connections[i]._jsPlumb.instance.detach(connections[i], {fireEvent: false});
|
||||
}
|
||||
}
|
||||
}).fail(function( jqXHR, status, error) {
|
||||
var reason = status + ' ' + error;
|
||||
Util.showNotify({title: jqXHR.status + ': deleteSystem', text: reason, type: 'warning'});
|
||||
$(document).setProgramStatus('problem');
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
@@ -1644,19 +1681,24 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
* set up context menu for all Systems within a given map
|
||||
* @param endpoints
|
||||
* set up all actions that can be preformed on a system
|
||||
* @param map
|
||||
* @param system
|
||||
*/
|
||||
var setSystemObserver = function(map, system){
|
||||
|
||||
system = $(system);
|
||||
|
||||
|
||||
// get map container
|
||||
var mapContainer = $( map.getContainer() );
|
||||
|
||||
var systemHeadExpand = $( system.find('.' + config.systemHeadExpandClass) );
|
||||
var systemBody = $( system.find('.' + config.systemBodyClass) );
|
||||
|
||||
// map overlay will be set on "drag" start
|
||||
var mapOverlay = null;
|
||||
|
||||
|
||||
// make system draggable
|
||||
map.draggable(system, {
|
||||
containment: 'parent',
|
||||
@@ -1666,8 +1708,10 @@ define([
|
||||
start: function(params){
|
||||
var dragSystem = $(params.el);
|
||||
|
||||
mapOverlay = dragSystem.getMapOverlay();
|
||||
|
||||
// start map update timer
|
||||
dragSystem.getMapOverlay().startMapUpdateCounter();
|
||||
mapOverlay.startMapUpdateCounter();
|
||||
|
||||
// check if grid-snap is enable
|
||||
if(config.mapSnapToGrid){
|
||||
@@ -1688,16 +1732,18 @@ define([
|
||||
$(selectedSystems).toggleSystemTooltip('hide', {});
|
||||
},
|
||||
drag: function(){
|
||||
// start map update timer
|
||||
mapOverlay.startMapUpdateCounter();
|
||||
},
|
||||
stop: function(params){
|
||||
var dragSystem = $(params.el);
|
||||
|
||||
// start map update timer
|
||||
dragSystem.getMapOverlay().startMapUpdateCounter();
|
||||
mapOverlay.startMapUpdateCounter();
|
||||
|
||||
setTimeout(function(){
|
||||
dragSystem.removeClass('no-click');
|
||||
}, 200);
|
||||
}, Init.timer.dblClickTimer + 50);
|
||||
|
||||
// render tooltip
|
||||
dragSystem.toggleSystemTooltip('show', {show: true});
|
||||
@@ -1736,7 +1782,7 @@ define([
|
||||
map.setDraggable(system, false);
|
||||
}
|
||||
|
||||
// init system tooltips ================================================================
|
||||
// init system tooltips =============================================================================
|
||||
var systemTooltipOptions = {
|
||||
toggle: 'tooltip',
|
||||
placement: 'right',
|
||||
@@ -1745,7 +1791,7 @@ define([
|
||||
|
||||
system.find('.fa').tooltip(systemTooltipOptions);
|
||||
|
||||
// init system body expand ============================================================
|
||||
// init system body expand ==========================================================================
|
||||
systemHeadExpand.hoverIntent(function(e){
|
||||
// hover in
|
||||
var hoverSystem = $(this).parents('.' + config.systemClass);
|
||||
@@ -1804,7 +1850,7 @@ define([
|
||||
|
||||
});
|
||||
|
||||
// context menu ==================================================================
|
||||
// context menu =====================================================================================
|
||||
|
||||
// trigger context menu
|
||||
system.on('contextmenu', function(e){
|
||||
@@ -1940,22 +1986,47 @@ define([
|
||||
}
|
||||
});
|
||||
|
||||
// load system data =================================================================================
|
||||
system.on('click', function(e){
|
||||
// system click events ==============================================================================
|
||||
var double = function(e){
|
||||
var system = $(this);
|
||||
var headElement = $(system).find('.' + config.systemHeadNameClass);
|
||||
|
||||
// left mouse button
|
||||
if(e.which === 1){
|
||||
if(! system.hasClass('no-click')){
|
||||
if(e.ctrlKey === true){
|
||||
// select system
|
||||
system.toggleSelectSystem(map);
|
||||
}else{
|
||||
system.showSystemInfo(map);
|
||||
// update z-index for system, editable field should be on top
|
||||
updateZIndex(system);
|
||||
|
||||
// show "set alias" input (x-editable)
|
||||
headElement.editable('show');
|
||||
};
|
||||
|
||||
var single = function(e){
|
||||
|
||||
// check if click was performed on "popover" (x-editable
|
||||
var popoverClick = false;
|
||||
if( $(e.target).parents('.popover').length ){
|
||||
popoverClick = true;
|
||||
}
|
||||
|
||||
// continue if click was *not* on a popover dialog of a system
|
||||
if( !popoverClick ){
|
||||
var system = $(this);
|
||||
|
||||
// left mouse button
|
||||
if(e.which === 1){
|
||||
if(! system.hasClass('no-click')){
|
||||
if(e.ctrlKey === true){
|
||||
// select system
|
||||
system.toggleSelectSystem(map);
|
||||
}else{
|
||||
system.showSystemInfo(map);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
system.singleDoubleClick(single, double);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -2507,7 +2578,7 @@ define([
|
||||
// confirm dialog
|
||||
bootbox.confirm('Is this connection really gone?', function(result) {
|
||||
if(result){
|
||||
deleteConnections([params.component]);
|
||||
deleteConnections([params.component], true);
|
||||
}
|
||||
});
|
||||
break;
|
||||
@@ -2635,7 +2706,7 @@ define([
|
||||
selectClass: config.systemDialogSelectClass
|
||||
};
|
||||
|
||||
requirejs(['text!templates/modules/system_dialog.html', 'mustache'], function(template, Mustache) {
|
||||
requirejs(['text!templates/dialog/system.html', 'mustache'], function(template, Mustache) {
|
||||
|
||||
var content = Mustache.render(template, data);
|
||||
|
||||
@@ -2673,6 +2744,8 @@ define([
|
||||
return false;
|
||||
}
|
||||
|
||||
mapContainer.getMapOverlay().startMapUpdateCounter();
|
||||
|
||||
// calculate new system position -----------------------------------------------
|
||||
var currentX = 0;
|
||||
var currentY = 0;
|
||||
@@ -2750,7 +2823,7 @@ define([
|
||||
|
||||
var modalContent = $('#' + config.systemDialogId);
|
||||
|
||||
// init system select live search
|
||||
// init system select live search
|
||||
var selectElement = modalContent.find('.' + config.systemDialogSelectClass);
|
||||
selectElement.initSystemSelect({key: 'systemId'});
|
||||
});
|
||||
@@ -2862,10 +2935,11 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
* collect all data for export/save for a map
|
||||
* collect all map data for export/save for a map
|
||||
* this function returns the "client" data NOT the "server" data for a map
|
||||
* @returns {*}
|
||||
*/
|
||||
$.fn.getMapData = function(forceData){
|
||||
$.fn.getMapDataFromClient = function(forceData){
|
||||
|
||||
var mapElement = $(this);
|
||||
|
||||
@@ -2971,7 +3045,7 @@ define([
|
||||
};
|
||||
systemData.locked = system.data('locked') ? 1 : 0;
|
||||
systemData.rally = system.data('rally') ? 1 : 0;
|
||||
systemData.currentUser = system.data('currentUser');
|
||||
systemData.currentUser = system.data('currentUser'); // if user is currently in this system
|
||||
systemData.updated = {
|
||||
updated: parseInt( system.data('updated') )
|
||||
};
|
||||
@@ -3049,10 +3123,9 @@ define([
|
||||
setConnectionObserver(newJsPlumbInstance, info.connection);
|
||||
});
|
||||
|
||||
newJsPlumbInstance.bind('connectionDetached', function(info, e){
|
||||
// a connection is manually (drag&drop) detached! otherwise this event should not be send!
|
||||
var connection = info.connection;
|
||||
deleteConnections([connection]);
|
||||
// event after connection moved
|
||||
newJsPlumbInstance.bind('connectionMoved', function(info, e) {
|
||||
|
||||
});
|
||||
|
||||
// event after DragStop a connection or new connection
|
||||
@@ -3084,12 +3157,19 @@ define([
|
||||
|
||||
// event before Detach connection
|
||||
newJsPlumbInstance.bind('beforeDetach', function(info) {
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
newJsPlumbInstance.bind('connectionDetached', function(info, e){
|
||||
// a connection is manually (drag&drop) detached! otherwise this event should not be send!
|
||||
var connection = info.connection;
|
||||
deleteConnections([connection], true);
|
||||
});
|
||||
|
||||
activeInstances[mapId] = newJsPlumbInstance;
|
||||
|
||||
console.log('new jsPlumbInstance: ' + mapId);
|
||||
//console.log('new jsPlumbInstance: ' + mapId);
|
||||
}
|
||||
|
||||
return activeInstances[mapId];
|
||||
@@ -3164,7 +3244,7 @@ define([
|
||||
|
||||
|
||||
// reset map update timer
|
||||
mapOverlay.setMapUpdateCounter(100, '5');
|
||||
mapOverlay.setMapUpdateCounter(100, config.logTimerCount);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,8 +15,6 @@ define([
|
||||
|
||||
'use strict';
|
||||
|
||||
var currentMapData = []; // current map data
|
||||
|
||||
var config = {
|
||||
dynamicElementWrapperId: 'pf-dialog-wrapper', // parent Element for dynamic content (dialogs,..)
|
||||
mapTabElementId: 'pf-map-tab-element', // id for map tab element (tabs + content)
|
||||
@@ -24,6 +22,8 @@ define([
|
||||
mapTabIdPrefix: 'pf-map-tab-', // id prefix for a map tab
|
||||
mapTabClass: 'pf-map-tab', // class for a map tab
|
||||
mapTabLinkTextClass: 'nav-tabs-link', // class for span elements in a tab
|
||||
mapTabIconClass: 'pf-map-tab-icon', // class for map icon
|
||||
mapTabSharedIconClass: 'pf-map-tab-shared-icon', // class for map shared icon
|
||||
mapTabContentClass: 'pf-map-tab-content', // class for tab content container
|
||||
mapTabContentSystemInfoClass: 'pf-map-tab-content-system',
|
||||
mapWrapperClass: 'pf-map-wrapper', // scrollable
|
||||
@@ -101,11 +101,6 @@ define([
|
||||
drawSystemModules($( e.target ));
|
||||
});
|
||||
|
||||
$(this).on('pf:deleteSystemData', function(e, systemData){
|
||||
console.log(systemData);
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
@@ -302,39 +297,63 @@ define([
|
||||
$.fn.updateTabData = function(options){
|
||||
var tabElement = $(this);
|
||||
|
||||
// set main data
|
||||
// set "main" data
|
||||
tabElement.data('map-id', options.id).data('updated', options.updated);
|
||||
|
||||
// change tab link
|
||||
// change "tab" link
|
||||
tabElement.attr('href', '#' + config.mapTabIdPrefix + options.id);
|
||||
|
||||
// change map icon
|
||||
tabElement.find('i').removeClass().addClass(['fa', 'fa-fw', options.icon].join(' '));
|
||||
// change "map" icon
|
||||
var mapIconElement = tabElement.find('.' + config.mapTabIconClass);
|
||||
mapIconElement.removeClass().addClass([config.mapTabIconClass, 'fa', 'fa-fw', options.icon].join(' '));
|
||||
|
||||
// change "shared" icon
|
||||
var mapSharedIconElement = tabElement.find('.' + config.mapTabSharedIconClass);
|
||||
mapSharedIconElement.hide();
|
||||
|
||||
// check if the map is a "shared" map
|
||||
if(options.access){
|
||||
if(
|
||||
options.access.user.length > 1 ||
|
||||
options.access.corporation.length > 1 ||
|
||||
options.access.alliance.length > 1
|
||||
){
|
||||
mapSharedIconElement.show();
|
||||
}
|
||||
}
|
||||
|
||||
// change map name label
|
||||
tabElement.find('.' + config.mapTabLinkTextClass).text(options.name);
|
||||
var tabLinkTextElement = tabElement.find('.' + config.mapTabLinkTextClass);
|
||||
tabLinkTextElement.text(options.name);
|
||||
|
||||
// change tabClass
|
||||
var listElement = tabElement.parent();
|
||||
|
||||
listElement.removeClass().addClass([config.mapTabClass, options.type.classTab ].join(' '));
|
||||
// new tab classes
|
||||
var tabClasses = [config.mapTabClass, options.type.classTab ];
|
||||
|
||||
// check if tab was "active" before
|
||||
if( listElement.hasClass('active') ){
|
||||
tabClasses.push('active');
|
||||
}
|
||||
|
||||
listElement.removeClass().addClass( tabClasses.join(' ') );
|
||||
|
||||
// set title for tooltip
|
||||
if(options.type.name !== undefined){ console.log(options.type.name)
|
||||
if(options.type.name !== undefined){
|
||||
|
||||
listElement.tooltip('destroy');
|
||||
|
||||
var mapTooltipOptions = {
|
||||
placement: 'bottom',
|
||||
container: 'body',
|
||||
title: options.type.name + ' map',
|
||||
trigger: 'hover',
|
||||
delay: 200
|
||||
};
|
||||
|
||||
$(listElement).tooltip(mapTooltipOptions);
|
||||
tabLinkTextElement.attr('title', options.type.name + ' map');
|
||||
}
|
||||
|
||||
var mapTooltipOptions = {
|
||||
placement: 'bottom',
|
||||
container: 'body',
|
||||
trigger: 'hover',
|
||||
delay: 150
|
||||
};
|
||||
|
||||
listElement.find('[title]').tooltip(mapTooltipOptions).tooltip('fixTitle');
|
||||
|
||||
if(options.right === true){
|
||||
listElement.addClass('pull-right');
|
||||
}
|
||||
@@ -358,19 +377,27 @@ define([
|
||||
listElement.addClass('pull-right');
|
||||
}
|
||||
|
||||
// link element -------
|
||||
// link element
|
||||
var linkElement = $('<a>').attr('role', 'tab');
|
||||
|
||||
// icon element ------
|
||||
var iconElement = $('<i>');
|
||||
// map icon element
|
||||
var mapIconElement = $('<i>', {
|
||||
class: config.mapTabIconClass
|
||||
});
|
||||
|
||||
// text element -----
|
||||
// map shared icon element
|
||||
var mapSharedIconElement = $('<i>', {
|
||||
class: [config.mapTabSharedIconClass, 'fa', 'fa-fw', 'fa-share-alt'].join(' '),
|
||||
title: 'shared map'
|
||||
});
|
||||
|
||||
// text element
|
||||
var textElement = $('<span>', {
|
||||
class: config.mapTabLinkTextClass
|
||||
});
|
||||
|
||||
var newListElement = listElement.append(
|
||||
linkElement.append(iconElement).append(textElement)
|
||||
linkElement.append(mapIconElement).append(textElement).append(mapSharedIconElement)
|
||||
);
|
||||
|
||||
tabBar.append( newListElement );
|
||||
@@ -380,9 +407,9 @@ define([
|
||||
|
||||
// tabs content ====================================
|
||||
var contentElement = $('<div>', {
|
||||
id: config.mapTabIdPrefix + options.id,
|
||||
class: options.contentClasses.join(' ')
|
||||
});
|
||||
id: config.mapTabIdPrefix + parseInt( options.id ),
|
||||
class: [config.mapTabContentClass].join(' ')
|
||||
})
|
||||
|
||||
contentElement.addClass('tab-pane');
|
||||
|
||||
@@ -473,25 +500,6 @@ define([
|
||||
return deletedTabName;
|
||||
};
|
||||
|
||||
/**
|
||||
* get current map data for a map id
|
||||
* @param mapId
|
||||
* @returns {boolean}
|
||||
*/
|
||||
var getMapDataById = function(mapId){
|
||||
|
||||
var mapData = false;
|
||||
|
||||
for(var i = 0; i < currentMapData.length; i++){
|
||||
if(currentMapData[i].config.id === mapId){
|
||||
mapData = currentMapData[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return mapData;
|
||||
};
|
||||
|
||||
/**
|
||||
* load/update map module into element (all maps)
|
||||
* @param mapData
|
||||
@@ -503,12 +511,9 @@ define([
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// update current map data
|
||||
currentMapData = mapData;
|
||||
|
||||
// store current map data global (cache)
|
||||
// temp store current map data to prevent data-change while function execution!
|
||||
var tempMapData = currentMapData;
|
||||
var tempMapData = Util.setCurrentMapData(mapData);
|
||||
|
||||
var mapModuleElement = $(this);
|
||||
|
||||
@@ -531,7 +536,7 @@ define([
|
||||
var mapId = tabElement.data('map-id');
|
||||
|
||||
if(mapId > 0){
|
||||
var tabMapData = getMapDataById(mapId);
|
||||
var tabMapData = Util.getCurrentMapData(mapId);
|
||||
|
||||
if(tabMapData !== false){
|
||||
// map data available ->
|
||||
@@ -561,18 +566,7 @@ define([
|
||||
if( activeMapIds.indexOf( data.config.id ) === -1 ){
|
||||
// add new map tab
|
||||
|
||||
var tabOptions = {
|
||||
id: parseInt( data.config.id ),
|
||||
type: data.config.type,
|
||||
contentClasses: [config.mapTabContentClass],
|
||||
active: false,
|
||||
icon: data.config.icon,
|
||||
name: data.config.name,
|
||||
right: false,
|
||||
updated: data.config.updated
|
||||
};
|
||||
|
||||
var newTabElements = tabMapElement.addTab(tabOptions);
|
||||
var newTabElements = tabMapElement.addTab(data.config);
|
||||
|
||||
// set observer for manually triggered map events
|
||||
newTabElements.contentElement.setTabContentObserver();
|
||||
@@ -589,7 +583,7 @@ define([
|
||||
|
||||
// get current active map
|
||||
var activeMapId = Util.getMapModule().getActiveMap().data('id');
|
||||
var activeMapData = getMapDataById(activeMapId);
|
||||
var activeMapData = Util.getCurrentMapData(activeMapId);
|
||||
|
||||
if(activeMapData !== false){
|
||||
// update active map with new mapData
|
||||
@@ -611,19 +605,7 @@ define([
|
||||
for(var j = 0; j < tempMapData.length; j++){
|
||||
|
||||
var data = tempMapData[j];
|
||||
|
||||
var tabOptions = {
|
||||
id: parseInt( data.config.id ),
|
||||
type: data.config.type,
|
||||
contentClasses: [config.mapTabContentClass],
|
||||
icon: data.config.icon,
|
||||
name: data.config.name,
|
||||
right: false,
|
||||
updated: data.config.updated
|
||||
};
|
||||
|
||||
tabMapElement.addTab(tabOptions);
|
||||
|
||||
tabMapElement.addTab(data.config);
|
||||
}
|
||||
|
||||
// add "add" button
|
||||
@@ -632,7 +614,6 @@ define([
|
||||
type: {
|
||||
classTab: Util.getInfoForMap( 'standard', 'classTab')
|
||||
},
|
||||
contentClasses: [config.mapTabContentClass],
|
||||
icon: 'fa-plus',
|
||||
name: 'add',
|
||||
right: true
|
||||
@@ -676,15 +657,15 @@ define([
|
||||
|
||||
if(mapId === 0){
|
||||
// add new Tab selected
|
||||
$(document).trigger('pf:menuShowMapSettings');
|
||||
$(document).trigger('pf:menuShowMapSettings', {tab: 'new'});
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
// load new map right after tab-change
|
||||
allTabElements.on('shown.bs.tab', function (e) {
|
||||
allTabElements.on('shown.bs.tab', function (e) { console.log('switch')
|
||||
var mapId = $(e.target).data('map-id');
|
||||
var tabMapData = getMapDataById(mapId);
|
||||
var tabMapData = Util.getCurrentMapData(mapId);
|
||||
|
||||
if(tabMapData !== false){
|
||||
// load map
|
||||
@@ -733,7 +714,7 @@ define([
|
||||
var data = [];
|
||||
for(var i = 0; i < mapElements.length; i++){
|
||||
|
||||
var mapData = $(mapElements[i]).getMapData(false);
|
||||
var mapData = $(mapElements[i]).getMapDataFromClient(false);
|
||||
|
||||
if(mapData !== false){
|
||||
data.push(mapData);
|
||||
|
||||
@@ -168,7 +168,6 @@ define([
|
||||
var timeoutId;
|
||||
var blink = function(){
|
||||
document.title = document.title === blinkTitle ? currentTitle : blinkTitle;
|
||||
console.log(document.title)
|
||||
};
|
||||
|
||||
var clear = function() {
|
||||
|
||||
@@ -252,7 +252,7 @@ define([
|
||||
class: 'fa fa-gears fa-fw'
|
||||
})
|
||||
).on('click', function(){
|
||||
$(document).triggerMenuEvent('ShowMapSettings', {newMap: false});
|
||||
$(document).triggerMenuEvent('ShowMapSettings', {tab: 'settings'});
|
||||
})
|
||||
).append(
|
||||
$('<a>', {
|
||||
@@ -454,17 +454,17 @@ define([
|
||||
return false;
|
||||
});
|
||||
|
||||
$(document).on('pf:menuShowMapSettings', function(e){
|
||||
$(document).on('pf:menuShowMapSettings', function(e, data){
|
||||
// show map edit dialog or edit map
|
||||
var mapData = false;
|
||||
|
||||
var activeMap = Util.getMapModule().getActiveMap();
|
||||
|
||||
if(activeMap){
|
||||
mapData = activeMap.getMapData(true);
|
||||
mapData = Util.getCurrentMapData( activeMap.data('id') );
|
||||
}
|
||||
|
||||
$.fn.showMapSettingsDialog(mapData);
|
||||
$.fn.showMapSettingsDialog(mapData, data);
|
||||
return false;
|
||||
});
|
||||
|
||||
@@ -475,7 +475,7 @@ define([
|
||||
var activeMap = Util.getMapModule().getActiveMap();
|
||||
|
||||
if(activeMap){
|
||||
mapData = activeMap.getMapData(true);
|
||||
mapData = activeMap.getMapDataFromClient(true);
|
||||
}
|
||||
|
||||
$.fn.showDeleteMapDialog(mapData);
|
||||
@@ -652,7 +652,7 @@ define([
|
||||
}
|
||||
|
||||
// update user ship data --------------------------------------------------------
|
||||
if(currentShipId !== newShipId){ console.log('update ship ');
|
||||
if(currentShipId !== newShipId){
|
||||
|
||||
var showShipElement = true;
|
||||
if(newShipId === 0){
|
||||
@@ -683,7 +683,7 @@ define([
|
||||
}).done(function(data){
|
||||
|
||||
if(data.reroute !== undefined){
|
||||
window.location = Util.buildUrl(data.reroute);
|
||||
window.location = Util.buildUrl(data.reroute) + '?logout';
|
||||
}
|
||||
|
||||
}).fail(function( jqXHR, status, error) {
|
||||
|
||||
@@ -339,7 +339,7 @@ define([
|
||||
$.fn.showMapInfoDialog = function(){
|
||||
|
||||
var activeMap = Util.getMapModule().getActiveMap();
|
||||
var mapData = activeMap.getMapData(true);
|
||||
var mapData = activeMap.getMapDataFromClient(true);
|
||||
|
||||
if(mapData !== false){
|
||||
requirejs(['text!templates/dialog/map_info.html', 'mustache'], function(template, Mustache) {
|
||||
@@ -384,7 +384,7 @@ define([
|
||||
|
||||
if(menuAction === 'refresh'){
|
||||
// get new map data
|
||||
var mapData = activeMap.getMapData(true);
|
||||
var mapData = activeMap.getMapDataFromClient(true);
|
||||
|
||||
mapElement.loadMapInfoData(mapData);
|
||||
systemsElement.loadSystemInfoTable(mapData);
|
||||
|
||||
@@ -13,20 +13,25 @@ define([
|
||||
|
||||
var config = {
|
||||
// map dialog
|
||||
newMapDialogId: 'pf-map-new-dialog', // id for edit/update map dialog
|
||||
newMapDialogId: 'pf-map-dialog', // id for map settings dialog
|
||||
dialogMapCreateContainerId: 'pf-map-dialog-create', // id for the "new map" container
|
||||
dialogMapEditContainerId: 'pf-map-dialog-edit', // id for the "edit" container
|
||||
dialogMapSettingsContainerId: 'pf-map-dialog-settings', // id for the "settings" container
|
||||
|
||||
dialogMessageContainerId: 'pf-map-dialog-message-container' // id for dialog form message container
|
||||
dialogMessageContainerId: 'pf-map-dialog-message-container', // id for dialog form message container
|
||||
|
||||
userSelectId: 'pf-map-dialog-user-select', // id for "user" select
|
||||
corporationSelectId: 'pf-map-dialog-corporation-select', // id for "corporation" select
|
||||
allianceSelectId: 'pf-map-dialog-alliance-select' // id for "alliance" select
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* shows the add/edit map dialog
|
||||
* @param mapData
|
||||
* @param options
|
||||
*/
|
||||
$.fn.showMapSettingsDialog = function(mapData){
|
||||
$.fn.showMapSettingsDialog = function(mapData, options){
|
||||
|
||||
// check if dialog is already open
|
||||
var mapInfoDialogElement = $('#' + config.newMapDialogId);
|
||||
@@ -52,7 +57,9 @@ define([
|
||||
var data = {
|
||||
scope: Util.getMapScopes(),
|
||||
type: Util.getMapTypes(true),
|
||||
icon: Util.getMapIcons()
|
||||
icon: Util.getMapIcons(),
|
||||
formErrorContainerClass: Util.config.formErrorContainerClass,
|
||||
formWarningContainerClass: Util.config.formWarningContainerClass
|
||||
};
|
||||
|
||||
// render "new map" tab content -------------------------------------------
|
||||
@@ -62,32 +69,73 @@ define([
|
||||
var contentEditMap = Mustache.render(templateMapSettings, data);
|
||||
contentEditMap = $(contentEditMap);
|
||||
|
||||
// current map access info
|
||||
var accessUser = [];
|
||||
var accessCorporation = [];
|
||||
var accessAlliance = [];
|
||||
|
||||
if(mapData !== false){
|
||||
// set current map information
|
||||
contentEditMap.find('input[name="id"]').val( mapData.config.id );
|
||||
contentEditMap.find('select[name="icon"]').val( mapData.config.icon );
|
||||
contentEditMap.find('input[name="name"]').val( mapData.config.name );
|
||||
contentEditMap.find('select[name="scopeId"]').val( mapData.config.scope.id );
|
||||
contentEditMap.find('select[name="typeId"]').val( mapData.config.type.id );
|
||||
|
||||
accessUser = mapData.config.access.user;
|
||||
accessCorporation = mapData.config.access.corporation;
|
||||
accessAlliance = mapData.config.access.alliance;
|
||||
}
|
||||
|
||||
// render main dialog -----------------------------------------------------
|
||||
data = {
|
||||
id: config.newMapDialogId,
|
||||
|
||||
// default open tab ----------
|
||||
openTabNew: options.tab === 'new',
|
||||
openTabEdit: options.tab === 'edit',
|
||||
openTabSettings: options.tab === 'settings',
|
||||
|
||||
dialogMapCreateContainerId: config.dialogMapCreateContainerId,
|
||||
dialogMapEditContainerId: config.dialogMapEditContainerId,
|
||||
dialogMapSettingsContainerId: config.dialogMapSettingsContainerId,
|
||||
dialogMessageContainerId: config.dialogMessageContainerId,
|
||||
|
||||
hideEditTab: hideEditTab,
|
||||
hideSettingsTab: hideSettingsTab
|
||||
hideSettingsTab: hideSettingsTab,
|
||||
|
||||
// settings tab --------------
|
||||
userSelectId: config.userSelectId,
|
||||
corporationSelectId: config.corporationSelectId,
|
||||
allianceSelectId: config.allianceSelectId,
|
||||
|
||||
// map access objects --------
|
||||
accessUser: accessUser,
|
||||
accessCorporation: accessCorporation,
|
||||
accessAlliance: accessAlliance,
|
||||
|
||||
// access limitations --------
|
||||
maxUser: Init.maxSharedCount.user,
|
||||
maxCorporation: Init.maxSharedCount.corporation,
|
||||
maxAlliance: Init.maxSharedCount.alliance
|
||||
};
|
||||
|
||||
var contentDialog = Mustache.render(templateMapDialog, data);
|
||||
contentDialog = $(contentDialog);
|
||||
|
||||
// set mapId for "settings" tab
|
||||
if(mapData !== false){
|
||||
contentDialog.find('input[name="id"]').val( mapData.config.id );
|
||||
}
|
||||
|
||||
|
||||
// set tab content
|
||||
$('#' + config.dialogMapCreateContainerId, contentDialog).html(contentNewMap);
|
||||
$('#' + config.dialogMapEditContainerId, contentDialog).html(contentEditMap);
|
||||
|
||||
// disable modal focus event -> otherwise select2 is not working! -> quick fix
|
||||
$.fn.modal.Constructor.prototype.enforceFocus = function() {};
|
||||
|
||||
var mapInfoDialog = bootbox.dialog({
|
||||
title: dialogTitle,
|
||||
message: contentDialog,
|
||||
@@ -103,33 +151,58 @@ define([
|
||||
|
||||
// get the current active form
|
||||
var form = $('#' + config.newMapDialogId).find('form').filter(':visible');
|
||||
console.log(form)
|
||||
|
||||
// validate form
|
||||
form.validator('validate');
|
||||
|
||||
// validate select2 fields (settings tab)
|
||||
form.find('select').each(function(){
|
||||
var selectField = $(this);
|
||||
var selectValues = selectField.val();
|
||||
|
||||
if(selectValues === null){
|
||||
selectField.parents('.form-group').addClass('has-error');
|
||||
}else{
|
||||
selectField.parents('.form-group').removeClass('has-error');
|
||||
}
|
||||
});
|
||||
|
||||
// check weather the form is valid
|
||||
var formValid = form.isValidForm();
|
||||
|
||||
if(formValid === true){
|
||||
|
||||
var newMapData = {mapData: form.getFormValues()};
|
||||
// lock dialog
|
||||
var dialogContent = mapInfoDialog.find('.modal-content');
|
||||
dialogContent.showLoadingAnimation();
|
||||
|
||||
var newMapData = {formData: form.getFormValues()};
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: Init.path.saveMap,
|
||||
data: newMapData,
|
||||
dataType: 'json'
|
||||
}).done(function(data){
|
||||
Util.showNotify({title: dialogTitle, text: 'Map: ' + data.name, type: 'success'});
|
||||
}).done(function(responseData){
|
||||
|
||||
dialogContent.hideLoadingAnimation();
|
||||
|
||||
if(responseData.error.length > 0){
|
||||
form.showFormMessage(responseData.error);
|
||||
}else{
|
||||
// success
|
||||
Util.showNotify({title: dialogTitle, text: 'Map: ' + responseData.name, type: 'success'});
|
||||
|
||||
$(mapInfoDialog).modal('hide');
|
||||
$(document).trigger('pf:closeMenu', [{}]);
|
||||
}
|
||||
|
||||
$(mapInfoDialog).modal('hide');
|
||||
$(document).trigger('pf:closeMenu', [{}]);
|
||||
}).fail(function( jqXHR, status, error) {
|
||||
var reason = status + ' ' + error;
|
||||
Util.showNotify({title: jqXHR.status + ': saveMap', text: reason, type: 'warning'});
|
||||
$(document).setProgramStatus('problem');
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -145,7 +218,37 @@ console.log(form)
|
||||
mapInfoDialog.initTooltips();
|
||||
|
||||
// set form validator
|
||||
mapInfoDialog.find('form').validator();
|
||||
mapInfoDialog.find('form').initFormValidation();
|
||||
|
||||
// events for tab change
|
||||
mapInfoDialog.find('.navbar a').on('shown.bs.tab', function (e) {
|
||||
|
||||
var selectElementUser = mapInfoDialog.find('#' + config.userSelectId);
|
||||
var selectElementCorporation = mapInfoDialog.find('#' + config.corporationSelectId);
|
||||
var selectElementAlliance = mapInfoDialog.find('#' + config.allianceSelectId);
|
||||
|
||||
if($(e.target).attr('href') === '#' + config.dialogMapSettingsContainerId){
|
||||
// "settings" tab
|
||||
|
||||
initSettingsSelectFields(mapInfoDialog);
|
||||
}else{
|
||||
|
||||
if( $(selectElementUser).data('select2') !== undefined ){
|
||||
$(selectElementUser).select2('destroy');
|
||||
}
|
||||
|
||||
if( $(selectElementCorporation).data('select2') !== undefined ){
|
||||
$(selectElementCorporation).select2('destroy');
|
||||
}
|
||||
|
||||
if( $(selectElementAlliance).data('select2') !== undefined ){
|
||||
$(selectElementAlliance).select2('destroy');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// show form messages -------------------------------------
|
||||
$('#' + config.dialogMessageContainerId).showMessage({type: 'info', title: 'Hint', text: 'Creating new maps or change settings may take a few seconds'});
|
||||
|
||||
if(mapData === false){
|
||||
// no map data found (probably new user
|
||||
@@ -153,11 +256,45 @@ console.log(form)
|
||||
}
|
||||
});
|
||||
|
||||
// init select fields in case "settings" tab is open by default
|
||||
if(options.tab === 'settings'){
|
||||
initSettingsSelectFields(mapInfoDialog);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* init select2 fields within the settings dialog
|
||||
* @param mapInfoDialog
|
||||
*/
|
||||
var initSettingsSelectFields = function(mapInfoDialog){
|
||||
|
||||
var selectElementUser = mapInfoDialog.find('#' + config.userSelectId);
|
||||
var selectElementCorporation = mapInfoDialog.find('#' + config.corporationSelectId);
|
||||
var selectElementAlliance = mapInfoDialog.find('#' + config.allianceSelectId);
|
||||
|
||||
// init corporation select live search
|
||||
selectElementUser.initAccessSelect({
|
||||
type: 'user',
|
||||
maxSelectionLength: Init.maxSharedCount.user
|
||||
});
|
||||
|
||||
// init corporation select live search
|
||||
selectElementCorporation.initAccessSelect({
|
||||
type: 'corporation',
|
||||
maxSelectionLength: Init.maxSharedCount.corporation
|
||||
});
|
||||
|
||||
// init alliance select live search
|
||||
selectElementAlliance.initAccessSelect({
|
||||
type: 'alliance',
|
||||
maxSelectionLength: Init.maxSharedCount.alliance
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* shows the delete map Dialog
|
||||
* @param mapElement
|
||||
|
||||
@@ -27,13 +27,6 @@ define([
|
||||
settingsCloneRowButtonClass: 'pf-dialog-clone-button', // class for clone button (api row)
|
||||
settingsDeleteRowButtonClass: 'pf-dialog-delete-button', // class for delete button (api row)
|
||||
|
||||
// form messages
|
||||
settingsErrorId: 'pf-dialog-error-id', // id for "error" form element
|
||||
settingsWarningId: 'pf-dialog-warning-id', // id for "warning" form element
|
||||
settingsMessageVelocityOptions: {
|
||||
duration: 180
|
||||
},
|
||||
|
||||
// captcha
|
||||
captchaImageWrapperId: 'pf-dialog-captcha-wrapper', // id for "captcha image" wrapper
|
||||
captchaImageId: 'pf-dialog-captcha-image', // id for "captcha image"
|
||||
@@ -107,80 +100,6 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* show form messages
|
||||
* @param errors
|
||||
*/
|
||||
var showFormMessage = function(errors){
|
||||
|
||||
var errorMessage = [];
|
||||
var warningMessage = [];
|
||||
for(var i = 0; i < errors.length; i++){
|
||||
if(errors[i].type === 'error'){
|
||||
errorMessage.push( errors[i].message );
|
||||
}else if(errors[i].type === 'warning'){
|
||||
warningMessage.push( errors[i].message );
|
||||
}
|
||||
}
|
||||
|
||||
if(errorMessage.length > 0){
|
||||
hideFormMessage('error', function(element){
|
||||
$(element).find('small').text( errorMessage.join('<br>') );
|
||||
$(element).velocity('transition.slideUpIn', config.settingsMessageVelocityOptions);
|
||||
});
|
||||
}
|
||||
|
||||
if(warningMessage.length > 0){
|
||||
hideFormMessage('warning', function(element){
|
||||
$(element).find('small').text( warningMessage.join('<br>') );
|
||||
$(element).velocity('transition.slideUpIn', config.settingsMessageVelocityOptions);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* ide all form messages
|
||||
* @param type
|
||||
* @param callback
|
||||
*/
|
||||
var hideFormMessage = function(type, callback){
|
||||
|
||||
var settingsMessageVelocityOptions = $.extend({}, config.settingsMessageVelocityOptions);
|
||||
|
||||
|
||||
// check if callback exists
|
||||
if(callback !== undefined){
|
||||
settingsMessageVelocityOptions.complete = callback;
|
||||
|
||||
// new error will be shown afterwards -> keep display
|
||||
settingsMessageVelocityOptions.display = 'block';
|
||||
}
|
||||
|
||||
if(type === 'error'){
|
||||
var errorMessageElement = $('#' + config.settingsErrorId);
|
||||
|
||||
// check if element is visible
|
||||
if(errorMessageElement.is(':visible')){
|
||||
errorMessageElement.velocity('transition.slideDownOut', settingsMessageVelocityOptions);
|
||||
}else if(callback){
|
||||
// skip hide animation
|
||||
callback(errorMessageElement);
|
||||
}
|
||||
}
|
||||
|
||||
if(type === 'warning'){
|
||||
var warningMessageElement = $('#' + config.settingsWarningId);
|
||||
|
||||
// check if element is visible
|
||||
if(warningMessageElement.is(':visible')){
|
||||
warningMessageElement.velocity('transition.slideDownOut', settingsMessageVelocityOptions);
|
||||
}else if(callback){
|
||||
// skip hide animation
|
||||
callback(warningMessageElement);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* init popovers in dialog
|
||||
* @param dialogElement
|
||||
@@ -272,7 +191,6 @@ define([
|
||||
}];
|
||||
}
|
||||
|
||||
|
||||
var data = {
|
||||
id: config.settingsDialogId,
|
||||
register: register,
|
||||
@@ -283,8 +201,8 @@ define([
|
||||
deleteRowButtonClass: config.settingsDeleteRowButtonClass,
|
||||
captchaImageWrapperId: config.captchaImageWrapperId,
|
||||
captchaImageId: config.captchaImageId,
|
||||
settingsErrorId: config.settingsErrorId,
|
||||
settingsWarningId: config.settingsWarningId
|
||||
formErrorContainerClass: Util.config.formErrorContainerClass,
|
||||
formWarningContainerClass: Util.config.formWarningContainerClass
|
||||
};
|
||||
|
||||
var content = Mustache.render(template, data);
|
||||
@@ -376,7 +294,7 @@ define([
|
||||
responseData.error &&
|
||||
responseData.error.length > 0
|
||||
){
|
||||
showFormMessage(responseData.error);
|
||||
form.showFormMessage(responseData.error);
|
||||
|
||||
showCaptchaImage();
|
||||
}else{
|
||||
@@ -479,19 +397,7 @@ define([
|
||||
initPopover( dialogElement );
|
||||
|
||||
// init form validation
|
||||
form.validator();
|
||||
|
||||
// validation event listener
|
||||
form.on('valid.bs.validator', function(validatorObj){
|
||||
var inputGroup = $(validatorObj.relatedTarget).parents('.form-group');
|
||||
inputGroup.removeClass('has-error').addClass('has-success');
|
||||
});
|
||||
|
||||
form.on('invalid.bs.validator', function(validatorObj){
|
||||
var field = $(validatorObj.relatedTarget);
|
||||
var inputGroup = field.parents('.form-group');
|
||||
inputGroup.removeClass('has-success').addClass('has-error');
|
||||
});
|
||||
form.initFormValidation();
|
||||
|
||||
// on Tab switch ======================================================================
|
||||
tabLinkElements.on('shown.bs.tab', function (e) {
|
||||
|
||||
@@ -7,10 +7,10 @@ define([
|
||||
'app/init',
|
||||
'app/util'
|
||||
], function($, Init, Util) {
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* init a select element as an ajax based "select2" object
|
||||
* init a select element as an ajax based "select2" object for system search
|
||||
* @param options
|
||||
*/
|
||||
$.fn.initSystemSelect = function(options){
|
||||
@@ -50,7 +50,7 @@ define([
|
||||
};
|
||||
},
|
||||
error: function (jqXHR, status, error) {
|
||||
if(!Util.isXHRAborted){
|
||||
if( !Util.isXHRAborted(jqXHR) ){
|
||||
// close select
|
||||
selectElement.select2('destroy');
|
||||
|
||||
@@ -60,17 +60,162 @@ define([
|
||||
|
||||
}
|
||||
},
|
||||
theme: 'pathfinder',
|
||||
minimumInputLength: 2,
|
||||
placeholder: 'Jita',
|
||||
allowClear: true
|
||||
allowClear: true,
|
||||
escapeMarkup: function (markup) {
|
||||
// let our custom formatter work
|
||||
return markup;
|
||||
}
|
||||
})
|
||||
).done(function(){
|
||||
// open select
|
||||
selectElement.select2('open');
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* init a select element as an ajax based "select2" object for Access resources
|
||||
* user (private map), corporation (corp map), alliance (ally map)
|
||||
* @param options
|
||||
*/
|
||||
$.fn.initAccessSelect = function(options){
|
||||
|
||||
return this.each(function(){
|
||||
|
||||
var selectElement = $(this);
|
||||
|
||||
// format result data
|
||||
function formatResultData (data) {
|
||||
|
||||
if (data.loading){
|
||||
return data.text;
|
||||
}
|
||||
|
||||
// check if an option is already selected
|
||||
// do not show the same result twice
|
||||
var currentValues = selectElement.val();
|
||||
|
||||
if(
|
||||
currentValues &&
|
||||
currentValues.indexOf( data.id.toString() ) !== -1
|
||||
){
|
||||
return ;
|
||||
}
|
||||
|
||||
var imagePath = '';
|
||||
var previewContent = '';
|
||||
|
||||
switch(options.type){
|
||||
case 'user':
|
||||
previewContent = '<i class="fa fa-lg fa-user"></i>';
|
||||
break;
|
||||
case 'corporation':
|
||||
imagePath = Init.url.ccpImageServer + 'Corporation/' + data.id + '_32.png';
|
||||
previewContent = '<img src="' + imagePath + '" style="max-width: 100%" />';
|
||||
break;
|
||||
case 'alliance':
|
||||
imagePath = Init.url.ccpImageServer + 'Alliance/' + data.id + '_32.png';
|
||||
previewContent = '<img src="' + imagePath + '" style="max-width: 100%" />';
|
||||
break;
|
||||
}
|
||||
|
||||
var markup = '<div class="clearfix">';
|
||||
markup += '<div class="col-sm-2">' + previewContent + '</div>';
|
||||
markup += '<div class="col-sm-10">' + data.text + '</div></div>';
|
||||
|
||||
return markup;
|
||||
}
|
||||
|
||||
// format selection data
|
||||
function formatSelectionData (data){
|
||||
|
||||
if (data.loading){
|
||||
return data.text;
|
||||
}
|
||||
|
||||
var markup = '<div class="clearfix">';
|
||||
markup += '<div class="col-sm-10">' + data.text + '</div></div>';
|
||||
|
||||
return markup;
|
||||
}
|
||||
|
||||
$.when(
|
||||
selectElement.select2({
|
||||
ajax: {
|
||||
url: function(params){
|
||||
// add params to URL
|
||||
return Init.path.searchAccess + '/' + options.type + '/' + params.term;
|
||||
},
|
||||
dataType: 'json',
|
||||
delay: 250,
|
||||
timeout: 5000,
|
||||
cache: true,
|
||||
data: function(params) {
|
||||
// no url params here
|
||||
return;
|
||||
},
|
||||
processResults: function(data, page) {
|
||||
// parse the results into the format expected by Select2.
|
||||
return {
|
||||
results: data.map( function(item){
|
||||
return {
|
||||
id: item.id,
|
||||
text: item.name
|
||||
};
|
||||
})
|
||||
};
|
||||
},
|
||||
error: function (jqXHR, status, error) {
|
||||
if( !Util.isXHRAborted(jqXHR) ){
|
||||
|
||||
var reason = status + ' ' + jqXHR.status + ': ' + error;
|
||||
Util.showNotify({title: 'Access select error', text: reason + ' deleted', type: 'warning'});
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
theme: 'pathfinder',
|
||||
minimumInputLength: 2,
|
||||
placeholder: '',
|
||||
allowClear: false,
|
||||
maximumSelectionLength: options.maxSelectionLength,
|
||||
templateResult: formatResultData,
|
||||
templateSelection: formatSelectionData,
|
||||
escapeMarkup: function (markup) {
|
||||
// let our custom formatter work
|
||||
return markup;
|
||||
}
|
||||
}).on('change', function(e){
|
||||
// select changed
|
||||
|
||||
})
|
||||
).done(function(){
|
||||
// after init finish
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,8 @@ define([
|
||||
'app/util',
|
||||
'app/render',
|
||||
'bootbox',
|
||||
'app/counter'
|
||||
'app/counter',
|
||||
'datatablesResponsive'
|
||||
], function($, Init, Util, Render, bootbox) {
|
||||
'use strict';
|
||||
|
||||
@@ -29,6 +30,9 @@ define([
|
||||
// signature progress bar
|
||||
signatureScannedProgressBarClass: 'pf-system-progress-scanned', // class for signature progress bar
|
||||
|
||||
// toolbar
|
||||
sigTableClearButtonClass: 'pf-sig-table-clear-button', // class for "clear" signatures button
|
||||
|
||||
// signature table
|
||||
sigTableClass: 'pf-sig-table', // Table class for all Signature Tables
|
||||
sigTablePrimaryClass: 'pf-sig-table-primary', // class for primary sig table
|
||||
@@ -38,11 +42,15 @@ define([
|
||||
sigTableEditSigNameInput: 'pf-sig-table-edit-name-input', // class for editable fields (input)
|
||||
sigTableEditSigGroupSelect: 'pf-sig-table-edit-group-select', // class for editable fields (sig group)
|
||||
sigTableEditSigTypeSelect: 'pf-sig-table-edit-type-select', // class for editable fields (sig type)
|
||||
sigTableEditSigDescriptionTextarea: 'pf-sig-table-edit-desc-text', // class for editable fields (sig description)
|
||||
sigTableCounterClass: 'pf-sig-table-counter', // class for signature table counter
|
||||
sigTableCreatedCellClass: 'pf-sig-table-created', // class for "created" cells
|
||||
sigTableUpdatedCellClass: 'pf-sig-table-updated', // class for "updated" cells
|
||||
sigTableActionCellClass: 'pf-sig-table-action-cell', // class for "action" cells
|
||||
sigTableActionButtonClass: 'pf-sig-table-action-button' // class for row action button
|
||||
sigTableActionButtonClass: 'pf-sig-table-action-button', // class for row action button
|
||||
|
||||
// xEditable
|
||||
editableDiscriptionInputClass: 'pf-editable-description' // class for "description" textarea
|
||||
};
|
||||
|
||||
// disable Signature Table update temporary (until. some requests/animations) are finished
|
||||
@@ -55,8 +63,9 @@ define([
|
||||
var emptySignatureData = {
|
||||
id: 0,
|
||||
name: '',
|
||||
typeId: 0,
|
||||
groupId: 0,
|
||||
typeId: 0,
|
||||
description: '',
|
||||
created: {
|
||||
created: null
|
||||
},
|
||||
@@ -65,8 +74,14 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
var fullSignatureOptions = {
|
||||
action: 'delete',
|
||||
actionClass: ['fa-close', 'txt-color', 'txt-color-redDarker'].join(' ')
|
||||
};
|
||||
|
||||
// empty signatureData row Options
|
||||
var emptySignatureOptions = {
|
||||
action: 'add',
|
||||
actionClass: ['fa-plus', 'txt-color', 'txt-color-grayLighter'].join(' ')
|
||||
};
|
||||
|
||||
@@ -403,6 +418,62 @@ define([
|
||||
return signatureData;
|
||||
};
|
||||
|
||||
/**
|
||||
* get a labeled button
|
||||
* @param options
|
||||
* @returns {*|jQuery}
|
||||
*/
|
||||
var getLabledButton = function(options){
|
||||
|
||||
var buttonClasses = ['btn', 'btn-sm', 'btn-labeled'];
|
||||
|
||||
switch(options.type){
|
||||
case 'default':
|
||||
buttonClasses.push('btn-default');
|
||||
break;
|
||||
case 'primary':
|
||||
buttonClasses.push('btn-primary');
|
||||
break;
|
||||
case 'danger':
|
||||
buttonClasses.push('btn-danger');
|
||||
break;
|
||||
}
|
||||
|
||||
// add optional classes
|
||||
if(options.classes){
|
||||
buttonClasses = buttonClasses.concat(options.classes);
|
||||
}
|
||||
|
||||
|
||||
var buttonElement = $('<button>', {
|
||||
class: buttonClasses.join(' '),
|
||||
type: 'button',
|
||||
html: ' ' + options.label + ' '
|
||||
}).on('click', function(e){
|
||||
options.onClick(e);
|
||||
}).prepend(
|
||||
$('<span>', {
|
||||
class: 'btn-label'
|
||||
}).prepend(
|
||||
$('<i>', {
|
||||
class: ['fa', options.icon, 'fa-fw'].join(' ')
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
// add optional badge
|
||||
if(options.badge){
|
||||
buttonElement.append(
|
||||
$('<span>', {
|
||||
class: ['badge'].join(' '),
|
||||
text: options.badge.label
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return buttonElement;
|
||||
};
|
||||
|
||||
/**
|
||||
* draw signature table toolbar (add signature button, scan progress bar
|
||||
* @param systemData
|
||||
@@ -415,11 +486,11 @@ define([
|
||||
var tableToolbar = $('<div>', {
|
||||
class: config.tableToolsClass
|
||||
}).append(
|
||||
$('<button>', {
|
||||
class: ['btn', 'btn-primary', 'btn-sm'].join(' '),
|
||||
text: ' add signature',
|
||||
type: 'button'
|
||||
}).on('click', function(e){
|
||||
getLabledButton({
|
||||
type: 'primary',
|
||||
label: 'add',
|
||||
icon: 'fa-plus',
|
||||
onClick: function(e){
|
||||
// show "add sig" div
|
||||
var toolsElement = $(e.target).parents('.' + config.moduleClass).find('.' + config.tableToolsActionClass);
|
||||
|
||||
@@ -436,47 +507,59 @@ define([
|
||||
visibility: 'visible'
|
||||
});
|
||||
}
|
||||
|
||||
}).prepend(
|
||||
$('<i>', {
|
||||
class: ['fa', 'fa-plus', 'fa-fw'].join(' ')
|
||||
})
|
||||
)
|
||||
).append(
|
||||
$('<button>', {
|
||||
class: ['btn', 'btn-primary', 'btn-sm'].join(' '),
|
||||
text: ' signature reader',
|
||||
type: 'button'
|
||||
}).on('click', function(){
|
||||
// show signature reader dialog
|
||||
}
|
||||
})
|
||||
).append(
|
||||
getLabledButton({
|
||||
type: 'primary',
|
||||
label: 'signature reader',
|
||||
icon: 'fa-clipboard',
|
||||
onClick: function(){
|
||||
moduleElement.showSignatureReaderDialog(systemData);
|
||||
}).prepend(
|
||||
$('<i>', {
|
||||
class: ['fa', 'fa-clipboard', 'fa-fw'].join(' ')
|
||||
})
|
||||
)
|
||||
).append(
|
||||
$('<button>', {
|
||||
class: ['btn', 'btn-danger', 'btn-sm', 'pull-right'].join(' '),
|
||||
text: ' clear signatures',
|
||||
type: 'button'
|
||||
}).on('click', function(){
|
||||
}
|
||||
})
|
||||
).append(
|
||||
getLabledButton({
|
||||
type: 'default',
|
||||
label: 'select all',
|
||||
icon: 'fa-check-square-o',
|
||||
onClick: function(){
|
||||
var allRows = getRows(signatureTable);
|
||||
var selectedRows = getSelectedRows(signatureTable);
|
||||
var allRowElements = allRows.nodes().to$();
|
||||
|
||||
if(allRows.data().length === selectedRows.data().length){
|
||||
allRowElements.removeClass('selected');
|
||||
}else{
|
||||
allRowElements.addClass('selected');
|
||||
}
|
||||
|
||||
// check delete button
|
||||
checkDeleteSignaturesButton();
|
||||
}
|
||||
})
|
||||
).append(
|
||||
getLabledButton({
|
||||
type: 'danger',
|
||||
classes: [config.sigTableClearButtonClass, 'pull-right'],
|
||||
label: 'delete',
|
||||
icon: 'fa-close',
|
||||
badge: {
|
||||
label: '0'
|
||||
},
|
||||
onClick: function(){
|
||||
// delete all rows
|
||||
bootbox.confirm('Delete all signature?', function(result) {
|
||||
|
||||
var selectedRows = getSelectedRows(signatureTable);
|
||||
|
||||
bootbox.confirm('Delete ' + selectedRows.length + ' signature?', function(result) {
|
||||
if(result){
|
||||
var signatureTableApi = signatureTable.api();
|
||||
|
||||
var rows = signatureTableApi.rows();
|
||||
|
||||
deleteSignatures(rows);
|
||||
deleteSignatures(selectedRows);
|
||||
}
|
||||
});
|
||||
}).prepend(
|
||||
$('<i>', {
|
||||
class: ['fa', 'fa-close', 'fa-fw'].join(' ')
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
moduleElement.append(tableToolbar);
|
||||
|
||||
@@ -487,7 +570,7 @@ define([
|
||||
|
||||
// create "empty table for new signature
|
||||
var table = $('<table>', {
|
||||
class: ['display', 'compact', config.sigTableClass, config.sigTableSecondaryClass].join(' ')
|
||||
class: ['display', 'compact', 'nowrap', config.sigTableClass, config.sigTableSecondaryClass].join(' ')
|
||||
});
|
||||
|
||||
tableToolbarAction.append(table);
|
||||
@@ -495,7 +578,6 @@ define([
|
||||
tableToolbar.after(tableToolbarAction);
|
||||
|
||||
var signatureData = formatSignatureData(systemData, [emptySignatureData], emptySignatureOptions);
|
||||
|
||||
table.dataTable( {
|
||||
data: signatureData,
|
||||
paging: false,
|
||||
@@ -503,7 +585,6 @@ define([
|
||||
info: false,
|
||||
searching: false
|
||||
} );
|
||||
|
||||
table.makeEditable(systemData);
|
||||
|
||||
// scanned signatures progress bar =============================================================================
|
||||
@@ -551,6 +632,7 @@ define([
|
||||
var sigNameFields = tableElement.find('.' + config.sigTableEditSigNameInput);
|
||||
var sigGroupFields = tableElement.find('.' + config.sigTableEditSigGroupSelect);
|
||||
var sigTypeFields = tableElement.find('.' + config.sigTableEditSigTypeSelect);
|
||||
var sigDescriptionFields = tableElement.find('.' + config.sigTableEditSigDescriptionTextarea);
|
||||
|
||||
// jump to "next" editable field on save
|
||||
var openNextEditDialogOnSave = function(fields){
|
||||
@@ -586,7 +668,7 @@ define([
|
||||
return params;
|
||||
};
|
||||
|
||||
// set xEditable options for all following fields
|
||||
// set global xEditable options for all table fields
|
||||
$.extend($.fn.editable.defaults, {
|
||||
url: Init.path.saveSignatureData,
|
||||
dataType: 'json',
|
||||
@@ -730,49 +812,24 @@ define([
|
||||
}
|
||||
});
|
||||
|
||||
// open next field dialog
|
||||
// Textarea sig description -------------------------------------------------------------
|
||||
sigDescriptionFields.editable({
|
||||
type: 'textarea',
|
||||
title: 'description',
|
||||
name: 'description',
|
||||
emptytext: '<i class="fa fa-fw fa-lg fa-pencil"></i>',
|
||||
onblur: 'submit',
|
||||
mode: 'inline',
|
||||
showbuttons: false,
|
||||
inputclass: config.editableDiscriptionInputClass,
|
||||
params: modifyFieldParamsOnSend
|
||||
});
|
||||
|
||||
// open next field dialog ---------------------------------------------------------------
|
||||
openNextEditDialogOnSave(sigNameFields);
|
||||
openNextEditDialogOnSave(sigGroupFields);
|
||||
|
||||
// set save button observer (new signature) ====================================================================
|
||||
tableElement.find('.fa-plus').on('click', {systemData: systemData}, function(e){
|
||||
// submit all fields within a table row
|
||||
var addRowElement = $(e.target).parents('tr');
|
||||
var formFields = addRowElement.find('.editable');
|
||||
|
||||
var tempSystemData = e.data.systemData;
|
||||
|
||||
// submit all xEditable fields
|
||||
formFields.editable('submit', {
|
||||
url: Init.path.saveSignatureData,
|
||||
ajaxOptions: {
|
||||
dataType: 'json' //assuming json response
|
||||
},
|
||||
data: {
|
||||
systemId: tempSystemData.id, // additional data to submit
|
||||
pk: 0 // new data no primary key
|
||||
},
|
||||
error: $.fn.editable.defaults.error, // user default xEditable error function
|
||||
success: function(data, editableConfig){
|
||||
|
||||
addSignatureRow(systemData, data, true);
|
||||
|
||||
|
||||
// prepare "add signature" table for new entry -> reset --------------------------------------------
|
||||
var signatureData = formatSignatureData(systemData, [emptySignatureData], emptySignatureOptions);
|
||||
|
||||
var dataSecondaryElement = $('.' + config.sigTableSecondaryClass);
|
||||
var dataTableSecondary = dataSecondaryElement.DataTable();
|
||||
var newAddRowElement = dataTableSecondary.clear().row.add(signatureData.shift()).draw().nodes();
|
||||
|
||||
newAddRowElement.to$().makeEditable(tempSystemData);
|
||||
|
||||
Util.showNotify({title: 'Signature added', text: 'Name: ' + data.name, type: 'success'});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// init signature counter
|
||||
// init signature counter ---------------------------------------------------------------
|
||||
tableElement.find('.' + config.sigTableCounterClass + '[data-counter!="init"]').initSignatureCounter();
|
||||
};
|
||||
|
||||
@@ -818,9 +875,6 @@ define([
|
||||
// enable signature Table update
|
||||
disableTableUpdate = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
@@ -851,7 +905,7 @@ define([
|
||||
*/
|
||||
var addSignatureRow = function(systemData, signatureData, animate){
|
||||
|
||||
var newSignatureData = formatSignatureData(systemData, [signatureData], {});
|
||||
var newSignatureData = formatSignatureData(systemData, [signatureData], fullSignatureOptions);
|
||||
|
||||
// insert new row in main signature table
|
||||
var tablePrimaryElement = $('.' + config.sigTablePrimaryClass);
|
||||
@@ -985,7 +1039,7 @@ define([
|
||||
|
||||
// create new signature table -------------------------------------------
|
||||
var table = $('<table>', {
|
||||
class: ['display', 'compact', config.sigTableClass, config.sigTablePrimaryClass].join(' ')
|
||||
class: ['display', 'compact', 'nowrap', config.sigTableClass, config.sigTablePrimaryClass].join(' ')
|
||||
});
|
||||
|
||||
moduleElement.append(table);
|
||||
@@ -1026,22 +1080,32 @@ define([
|
||||
// areaId is required as a key for signature names
|
||||
if(areaId){
|
||||
|
||||
// action button class
|
||||
var actionButtonClass = ['fa-close', 'txt-color', 'txt-color-redDarker'].join(' ');
|
||||
|
||||
for(var i = 0; i < signatureData.length; i++){
|
||||
var data = signatureData[i];
|
||||
|
||||
var tempData = {};
|
||||
|
||||
// set signature id --------------------------------------------------------------------------------
|
||||
// set id ------------------------------------------------------------------------------------------
|
||||
var sigId = 0;
|
||||
if(data.id > 0){
|
||||
sigId = data.id;
|
||||
}
|
||||
tempData.id = sigId;
|
||||
|
||||
// set signature name ------------------------------------------------------------------------------
|
||||
// set status --------------------------------------------------------------------------------------
|
||||
var status = '';
|
||||
var statusClass = '';
|
||||
if(data.updated.character !== undefined){
|
||||
statusClass = Util.getStatusInfoForCharacter(data.updated.character, 'class');
|
||||
status = '<i class="fa fa-fw fa-circle pf-user-status ' + statusClass + '"></i>';
|
||||
}
|
||||
|
||||
tempData.status = {
|
||||
status: status,
|
||||
status_sort: statusClass
|
||||
};
|
||||
|
||||
// set name ----------------------------------------------------------------------------------------
|
||||
var sigName = '<a href="#" class="' + config.sigTableEditSigNameInput + '" ';
|
||||
if(data.id > 0){
|
||||
sigName += 'data-pk="' + data.id + '" ';
|
||||
@@ -1050,7 +1114,7 @@ define([
|
||||
|
||||
tempData.name = sigName;
|
||||
|
||||
// set signature group id --------------------------------------------------------------------------
|
||||
// set group id ------------------------------------------------------------------------------------
|
||||
var sigGroup = '<a href="#" class="' + config.sigTableEditSigGroupSelect + '" ';
|
||||
if(data.id > 0){
|
||||
sigGroup += 'data-pk="' + data.id + '" ';
|
||||
@@ -1062,7 +1126,7 @@ define([
|
||||
|
||||
tempData.group = sigGroup;
|
||||
|
||||
// set signature type id ---------------------------------------------------------------------------
|
||||
// set type id -------------------------------------------------------------------------------------
|
||||
var sigType = '<a href="#" class="' + config.sigTableEditSigTypeSelect + '" ';
|
||||
if(data.id > 0){
|
||||
sigType += 'data-pk="' + data.id + '" ';
|
||||
@@ -1081,22 +1145,19 @@ define([
|
||||
|
||||
tempData.type = sigType;
|
||||
|
||||
// status ------------------------------------------------------------------------------------------
|
||||
var status = '';
|
||||
if(data.updated.character !== undefined){
|
||||
var statusClass = Util.getStatusInfoForCharacter(data.updated.character, 'class');
|
||||
status = '<i class="fa fa-fw fa-circle pf-user-status ' + statusClass + '"></i>';
|
||||
// set description ---------------------------------------------------------------------------------
|
||||
var sigDescription = '<a href="#" class="' + config.sigTableEditSigDescriptionTextarea + '" ';
|
||||
if(data.id > 0){
|
||||
sigDescription += 'data-pk="' + data.id + '" ';
|
||||
}
|
||||
sigDescription += '>' + data.description + '</a>';
|
||||
|
||||
tempData.status = {
|
||||
status: status,
|
||||
status_sort: statusClass
|
||||
};
|
||||
tempData.description = sigDescription;
|
||||
|
||||
// set Sig created ---------------------------------------------------------------------------------
|
||||
// set created -------------------------------------------------------------------------------------
|
||||
tempData.created = data.created;
|
||||
|
||||
// set Sig updated ---------------------------------------------------------------------------------
|
||||
// set updated -------------------------------------------------------------------------------------
|
||||
tempData.updated = data.updated;
|
||||
|
||||
// info icon ---------------------------------------------------------------------------------------
|
||||
@@ -1107,13 +1168,12 @@ define([
|
||||
tempData.info = infoButton;
|
||||
|
||||
// action icon -------------------------------------------------------------------------------------
|
||||
if(options.actionClass){
|
||||
actionButtonClass = options.actionClass;
|
||||
}
|
||||
|
||||
var actionButton = '<i class="fa ' + actionButtonClass + ' ' + config.sigTableActionButtonClass + '"></i>';
|
||||
tempData.action = actionButton;
|
||||
|
||||
var actionButton = '<i class="fa ' + options.actionClass + ' ' + config.sigTableActionButtonClass + '"></i>';
|
||||
tempData.action = {
|
||||
action: options.action,
|
||||
button: actionButton
|
||||
};
|
||||
|
||||
formattedData.push(tempData);
|
||||
|
||||
@@ -1126,14 +1186,18 @@ define([
|
||||
|
||||
/**
|
||||
* setup dataTable options for all signatureTables
|
||||
* @param systemData
|
||||
*/
|
||||
var initSignatureDataTable = function(){
|
||||
var initSignatureDataTable = function(systemData){
|
||||
|
||||
$.extend( $.fn.dataTable.defaults, {
|
||||
pageLength: -1,
|
||||
lengthMenu: [[5, 10, 25, 50, -1], [5, 10, 25, 50, 'All']],
|
||||
order: [1, 'asc'],
|
||||
autoWidth: false,
|
||||
responsive: {
|
||||
details: false
|
||||
},
|
||||
language: {
|
||||
emptyTable: 'No signatures added',
|
||||
zeroRecords: 'No signatures found',
|
||||
@@ -1147,7 +1211,7 @@ define([
|
||||
searchable: false,
|
||||
title: '',
|
||||
width: '10px',
|
||||
class: 'text-center',
|
||||
class: ['text-center', 'min-tablet-l'].join(' '),
|
||||
data: 'status',
|
||||
type: 'html',
|
||||
render: {
|
||||
@@ -1159,6 +1223,7 @@ define([
|
||||
orderable: true,
|
||||
searchable: true,
|
||||
title: 'id',
|
||||
type: 'html',
|
||||
width: '30px',
|
||||
data: 'name'
|
||||
},{
|
||||
@@ -1166,38 +1231,48 @@ define([
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
title: 'group',
|
||||
type: 'html',
|
||||
width: '50px',
|
||||
data: 'group'
|
||||
},{
|
||||
targets: 3,
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
title: 'type/description',
|
||||
title: 'type',
|
||||
type: 'html',
|
||||
width: '180px',
|
||||
data: 'type'
|
||||
},{
|
||||
targets: 4,
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
title: 'description',
|
||||
type: 'html',
|
||||
data: 'description'
|
||||
},{
|
||||
targets: 5,
|
||||
title: 'created',
|
||||
width: '90px',
|
||||
searchable: false,
|
||||
className: [config.sigTableCounterClass, config.sigTableCreatedCellClass].join(' '),
|
||||
className: [config.sigTableCounterClass, config.sigTableCreatedCellClass, 'min-tablet-l'].join(' '),
|
||||
data: 'created',
|
||||
render: {
|
||||
_: 'created',
|
||||
sort: 'created'
|
||||
}
|
||||
},{
|
||||
targets: 5,
|
||||
targets: 6,
|
||||
title: 'updated',
|
||||
width: '90px',
|
||||
searchable: false,
|
||||
className: [config.sigTableCounterClass, config.sigTableUpdatedCellClass].join(' '),
|
||||
className: [config.sigTableCounterClass, config.sigTableUpdatedCellClass, 'min-tablet-l'].join(' '),
|
||||
data: 'updated',
|
||||
render: {
|
||||
_: 'updated',
|
||||
sort: 'updated'
|
||||
}
|
||||
},{
|
||||
targets: 6,
|
||||
targets: 7,
|
||||
title: '',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
@@ -1218,27 +1293,89 @@ define([
|
||||
}
|
||||
}
|
||||
},{
|
||||
targets: 7,
|
||||
targets: 8,
|
||||
title: '',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
width: '10px',
|
||||
class: ['text-center', config.sigTableActionCellClass].join(' '),
|
||||
data: 'action',
|
||||
render: {
|
||||
_: 'button',
|
||||
sort: 'action'
|
||||
},
|
||||
createdCell: function(cell, cellData, rowData, rowIndex, colIndex){
|
||||
|
||||
var tempTableElement = this;
|
||||
$(cell).on('click', function(e){
|
||||
e.preventDefault();
|
||||
var rowElement = $(cell).parents('tr');
|
||||
|
||||
switch(cellData.action){
|
||||
case 'add':
|
||||
// add new signature ---------------------------------------------------------------
|
||||
$(cell).on('click', function(e) {
|
||||
// submit all fields within a table row
|
||||
var formFields = rowElement.find('.editable');
|
||||
|
||||
// submit all xEditable fields
|
||||
formFields.editable('submit', {
|
||||
url: Init.path.saveSignatureData,
|
||||
ajaxOptions: {
|
||||
dataType: 'json' //assuming json response
|
||||
},
|
||||
data: {
|
||||
systemId: systemData.id, // additional data to submit
|
||||
pk: 0 // new data no primary key
|
||||
},
|
||||
error: $.fn.editable.defaults.error, // user default xEditable error function
|
||||
success: function (data, editableConfig) {
|
||||
|
||||
addSignatureRow(systemData, data, true);
|
||||
|
||||
|
||||
// prepare "add signature" table for new entry -> reset --------------------------------------------
|
||||
var signatureData = formatSignatureData(systemData, [emptySignatureData], emptySignatureOptions);
|
||||
|
||||
var dataSecondaryElement = $('.' + config.sigTableSecondaryClass);
|
||||
var dataTableSecondary = dataSecondaryElement.DataTable();
|
||||
var newAddRowElement = dataTableSecondary.clear().row.add(signatureData.shift()).draw().nodes();
|
||||
|
||||
newAddRowElement.to$().makeEditable(systemData);
|
||||
|
||||
Util.showNotify({
|
||||
title: 'Signature added',
|
||||
text: 'Name: ' + data.name,
|
||||
type: 'success'
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
break;
|
||||
case 'delete':
|
||||
// delete signature ----------------------------------------------------------------
|
||||
var confirmationSettings = {
|
||||
container: 'body',
|
||||
placement: 'left',
|
||||
btnCancelClass: 'btn btn-sm btn-default',
|
||||
btnCancelLabel: 'cancel',
|
||||
btnCancelIcon: 'fa fa-fw fa-ban',
|
||||
title: 'Delete signature',
|
||||
btnOkClass: 'btn btn-sm btn-danger',
|
||||
btnOkLabel: 'delete',
|
||||
btnOkIcon: 'fa fa-fw fa-close',
|
||||
onConfirm : function(e, target){
|
||||
var deleteRowElement = $(target).parents('tr');
|
||||
var row = tempTableElement.DataTable().rows(deleteRowElement);
|
||||
deleteSignatures(row);
|
||||
}
|
||||
};
|
||||
|
||||
// init confirmation dialog
|
||||
$(cell).confirmation(confirmationSettings);
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
bootbox.confirm('Delete signature?', function(result) {
|
||||
if(result){
|
||||
var rowElement = $(cell).parents('tr');
|
||||
var row = tempTableElement.DataTable().rows(rowElement);
|
||||
deleteSignatures(row);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -1254,14 +1391,101 @@ define([
|
||||
|
||||
/**
|
||||
* set module observer and look for relevant signature data to update
|
||||
* @param moduleElement
|
||||
*/
|
||||
var setModuleObserver = function(moduleElement){
|
||||
var tablePrimaryElement = $('.' + config.sigTablePrimaryClass);
|
||||
var dataTablePrimary = signatureTable.DataTable();
|
||||
var signatureTableApi = signatureTable.api();
|
||||
|
||||
$(document).off('pf:updateSystemModules').on('pf:updateSystemModules', function(e, data){
|
||||
if(data.signatures){
|
||||
moduleElement.updateSignatureTable(data.signatures);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// set multi row select -----------------------------------------------------------------
|
||||
tablePrimaryElement.on('click', 'tr', function(e){
|
||||
if(event.ctrlKey) {
|
||||
$(this).toggleClass('selected');
|
||||
|
||||
// check delete button
|
||||
checkDeleteSignaturesButton();
|
||||
}
|
||||
});
|
||||
|
||||
// draw event for signature table -------------------------------------------------------
|
||||
signatureTableApi.on('draw.dt', function(){
|
||||
// check delete button
|
||||
checkDeleteSignaturesButton();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* check the "delete signature" button. show/hide the button if a signature is selected
|
||||
*/
|
||||
var checkDeleteSignaturesButton = function(){
|
||||
|
||||
var selectedRows = getSelectedRows(signatureTable);
|
||||
var selectedRowCount = selectedRows.data().length;
|
||||
var clearButton = $('.' + config.sigTableClearButtonClass);
|
||||
|
||||
|
||||
if(selectedRowCount > 0){
|
||||
var allRows = getRows(signatureTable);
|
||||
var rowCount = allRows.data().length;
|
||||
|
||||
var badgetText = selectedRowCount;
|
||||
if(selectedRowCount >= rowCount){
|
||||
badgetText = 'all';
|
||||
}
|
||||
clearButton.find('.badge').text( badgetText );
|
||||
|
||||
// update clear signatures button text
|
||||
clearButton.velocity('stop');
|
||||
|
||||
if( clearButton.is(':hidden') ){
|
||||
// show button
|
||||
clearButton.velocity('transition.bounceIn', {
|
||||
duration: 200
|
||||
});
|
||||
}else{
|
||||
// highlight button
|
||||
clearButton.velocity('callout.pulse', {
|
||||
duration: 250
|
||||
});
|
||||
}
|
||||
}else{
|
||||
// hide button
|
||||
clearButton.velocity('transition.bounceOut', {
|
||||
duration: 200
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* get all rows of a table
|
||||
* @param table
|
||||
* @returns {*}
|
||||
*/
|
||||
var getRows = function(table){
|
||||
var tableApi = table.api();
|
||||
var rows = tableApi.rows();
|
||||
|
||||
return rows;
|
||||
};
|
||||
|
||||
/**
|
||||
* get all selected rows of a table
|
||||
* @param table
|
||||
* @returns {*}
|
||||
*/
|
||||
var getSelectedRows = function(table){
|
||||
var tableApi = table.api();
|
||||
var selectedRows = tableApi.rows('.selected');
|
||||
|
||||
return selectedRows;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1288,7 +1512,7 @@ define([
|
||||
$(parentElement).append(moduleElement);
|
||||
|
||||
// init dataTables
|
||||
initSignatureDataTable();
|
||||
initSignatureDataTable(systemData);
|
||||
|
||||
// draw "new signature" add table --------------------------------------------
|
||||
|
||||
@@ -1307,7 +1531,7 @@ define([
|
||||
dataType: 'json'
|
||||
}).done(function(signatureData){
|
||||
|
||||
var signatureTableData = formatSignatureData(systemData, signatureData, {});
|
||||
var signatureTableData = formatSignatureData(systemData, signatureData, fullSignatureOptions);
|
||||
|
||||
// draw signature table
|
||||
moduleElement.drawSignatureTable(signatureTableData, systemData);
|
||||
|
||||
720
js/app/util.js
720
js/app/util.js
@@ -20,7 +20,14 @@ define([
|
||||
ajaxOverlayClass: 'pf-loading-overlay',
|
||||
ajaxOverlayWrapperClass: 'pf-loading-overlay-wrapper',
|
||||
|
||||
formEditableFieldClass: 'pf-editable', // Class for all xEditable fields
|
||||
// form
|
||||
formEditableFieldClass: 'pf-editable', // class for all xEditable fields
|
||||
formErrorContainerClass: 'pf-dialog-error-container', // class for "error" containers in dialogs
|
||||
formWarningContainerClass: 'pf-dialog-warning-container', // class for "warning" containers in dialogs
|
||||
|
||||
settingsMessageVelocityOptions: {
|
||||
duration: 180
|
||||
},
|
||||
|
||||
// map module
|
||||
mapModuleId: 'pf-map-module', // main map module
|
||||
@@ -62,86 +69,12 @@ define([
|
||||
|
||||
var stopTimerCache = {}; // cache for stopwatch timer
|
||||
|
||||
/**
|
||||
* get date obj with current EVE Server Time.
|
||||
* @returns {Date}
|
||||
|
||||
/*
|
||||
* ===========================================================================================================
|
||||
* Global jQuery plugins for some common and frequently used functions
|
||||
* ==========================================================================================================
|
||||
*/
|
||||
var getServerTime = function(){
|
||||
|
||||
// Server is running with GMT/UTC (EVE Time)
|
||||
var localDate = new Date();
|
||||
|
||||
var serverDate= new Date(
|
||||
localDate.getUTCFullYear(),
|
||||
localDate.getUTCMonth(),
|
||||
localDate.getUTCDate(),
|
||||
localDate.getUTCHours(),
|
||||
localDate.getUTCMinutes(),
|
||||
localDate.getUTCSeconds()
|
||||
);
|
||||
|
||||
return serverDate;
|
||||
};
|
||||
|
||||
/**
|
||||
* start time measurement by a unique string identifier
|
||||
* @param timerName
|
||||
*/
|
||||
var timeStart = function(timerName){
|
||||
|
||||
if(typeof performance === 'object'){
|
||||
stopTimerCache[timerName] = performance.now();
|
||||
}else{
|
||||
stopTimerCache[timerName] = new Date().getTime();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* get time delta between timeStart() and timeStop() by a unique string identifier
|
||||
* @param timerName
|
||||
* @returns {number}
|
||||
*/
|
||||
var timeStop = function(timerName){
|
||||
|
||||
var duration = 0;
|
||||
|
||||
if( stopTimerCache.hasOwnProperty(timerName) ){
|
||||
// check browser support for performance API
|
||||
var timeNow = 0;
|
||||
|
||||
if(typeof performance === 'object'){
|
||||
timeNow = performance.now();
|
||||
}else{
|
||||
timeNow = new Date();
|
||||
}
|
||||
|
||||
// format ms time duration
|
||||
duration = Number( (timeNow - stopTimerCache[timerName] ).toFixed(2) );
|
||||
|
||||
// delete key
|
||||
delete( stopTimerCache[timerName]);
|
||||
}
|
||||
|
||||
return duration;
|
||||
};
|
||||
|
||||
/**
|
||||
* build a program URL by a given path
|
||||
* @param path
|
||||
* @returns {string}
|
||||
*/
|
||||
var buildUrl = function(path){
|
||||
return document.location.protocol + '//' + document.location.host + path;
|
||||
};
|
||||
|
||||
/**
|
||||
* trigger main logging event with log information
|
||||
* @param message
|
||||
* @param options
|
||||
*/
|
||||
var log = function(logKey, options){
|
||||
$(window).trigger('pf:log', [logKey, options]);
|
||||
};
|
||||
|
||||
/**
|
||||
* displays a loading indicator on an element
|
||||
@@ -230,6 +163,116 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* show form messages
|
||||
* check: showMessage() for en other way of showing messages
|
||||
* @param errors
|
||||
*/
|
||||
$.fn.showFormMessage = function(errors){
|
||||
|
||||
var formElement = $(this);
|
||||
|
||||
var errorMessage = [];
|
||||
var warningMessage = [];
|
||||
for(var i = 0; i < errors.length; i++){
|
||||
if(errors[i].type === 'error'){
|
||||
errorMessage.push( errors[i].message );
|
||||
}else if(errors[i].type === 'warning'){
|
||||
warningMessage.push( errors[i].message );
|
||||
}
|
||||
}
|
||||
|
||||
if(errorMessage.length > 0){
|
||||
formElement.hideFormMessage('error', function(element){
|
||||
$(element).find('small').text( errorMessage.join('<br>') );
|
||||
$(element).velocity('transition.slideUpIn', config.settingsMessageVelocityOptions);
|
||||
});
|
||||
}
|
||||
|
||||
if(warningMessage.length > 0){
|
||||
formElement.hideFormMessage('warning', function(element){
|
||||
$(element).find('small').text( warningMessage.join('<br>') );
|
||||
$(element).velocity('transition.slideUpIn', config.settingsMessageVelocityOptions);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* hide all form messages
|
||||
* @param type
|
||||
* @param callback
|
||||
*/
|
||||
$.fn.hideFormMessage = function(type, callback){
|
||||
|
||||
var formElement = $(this);
|
||||
|
||||
var settingsMessageVelocityOptions = $.extend({}, config.settingsMessageVelocityOptions);
|
||||
|
||||
// check if callback exists
|
||||
if(callback !== undefined){
|
||||
settingsMessageVelocityOptions.complete = callback;
|
||||
|
||||
// new error will be shown afterwards -> keep display
|
||||
settingsMessageVelocityOptions.display = 'block';
|
||||
}
|
||||
|
||||
if(type === 'error'){
|
||||
// find error container
|
||||
var errorMessageElement = formElement.find('.' + config.formErrorContainerClass);
|
||||
|
||||
// check if element is visible
|
||||
if(errorMessageElement.is(':visible')){
|
||||
errorMessageElement.velocity('transition.slideDownOut', settingsMessageVelocityOptions);
|
||||
}else if(callback){
|
||||
// skip hide animation
|
||||
callback(errorMessageElement);
|
||||
}
|
||||
}
|
||||
|
||||
if(type === 'warning'){
|
||||
var warningMessageElement = formElement.find('.' + config.formWarningContainerClass);
|
||||
|
||||
// check if element is visible
|
||||
if(warningMessageElement.is(':visible')){
|
||||
warningMessageElement.velocity('transition.slideDownOut', settingsMessageVelocityOptions);
|
||||
}else if(callback){
|
||||
// skip hide animation
|
||||
callback(warningMessageElement);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* init form elements for validation (bootstrap3 validation)
|
||||
* @returns {any|JQuery|*}
|
||||
*/
|
||||
$.fn.initFormValidation = function(){
|
||||
|
||||
return this.each(function(){
|
||||
var form = $(this);
|
||||
|
||||
// init form validation
|
||||
form.validator();
|
||||
|
||||
// validation event listener
|
||||
form.on('valid.bs.validator', function(validatorObj){
|
||||
var inputGroup = $(validatorObj.relatedTarget).parents('.form-group');
|
||||
if(inputGroup){
|
||||
inputGroup.removeClass('has-error').addClass('has-success');
|
||||
}
|
||||
});
|
||||
|
||||
form.on('invalid.bs.validator', function(validatorObj){
|
||||
var field = $(validatorObj.relatedTarget);
|
||||
var inputGroup = field.parents('.form-group');
|
||||
if(inputGroup){
|
||||
inputGroup.removeClass('has-success').addClass('has-error');
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* checks weather a bootstrap form is valid or not
|
||||
* validation plugin does not provide a proper function for this
|
||||
@@ -282,30 +325,311 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
* checks if an element is currently visible in viewport
|
||||
* @returns {boolean}
|
||||
* check multiple element if they arecurrently visible in viewport
|
||||
* @returns {Array}
|
||||
*/
|
||||
$.fn.isInViewport = function(){
|
||||
|
||||
var element = $(this)[0];
|
||||
var top = element.offsetTop;
|
||||
var left = element.offsetLeft;
|
||||
var width = element.offsetWidth;
|
||||
var height = element.offsetHeight;
|
||||
var visibleElement = [];
|
||||
|
||||
this.each(function(){
|
||||
var element = $(this)[0];
|
||||
|
||||
while(element.offsetParent) {
|
||||
element = element.offsetParent;
|
||||
top += element.offsetTop;
|
||||
left += element.offsetLeft;
|
||||
}
|
||||
var top = element.offsetTop;
|
||||
var left = element.offsetLeft;
|
||||
var width = element.offsetWidth;
|
||||
var height = element.offsetHeight;
|
||||
|
||||
return (
|
||||
top < (window.pageYOffset + window.innerHeight) &&
|
||||
while(element.offsetParent) {
|
||||
element = element.offsetParent;
|
||||
top += element.offsetTop;
|
||||
left += element.offsetLeft;
|
||||
}
|
||||
|
||||
if(
|
||||
top < (window.pageYOffset + window.innerHeight) &&
|
||||
left < (window.pageXOffset + window.innerWidth) &&
|
||||
(top + height) > window.pageYOffset &&
|
||||
(left + width) > window.pageXOffset
|
||||
);
|
||||
){
|
||||
visibleElement.push( this );
|
||||
}
|
||||
});
|
||||
|
||||
return visibleElement;
|
||||
};
|
||||
|
||||
/**
|
||||
* init the map-update-counter as "easy-pie-chart"
|
||||
*/
|
||||
$.fn.initMapUpdateCounter = function(){
|
||||
|
||||
var counterChart = $(this);
|
||||
|
||||
counterChart.easyPieChart({
|
||||
barColor: function(percent){
|
||||
|
||||
var color = '#568a89';
|
||||
if(percent <= 30){
|
||||
color = '#d9534f';
|
||||
}else if(percent <= 50){
|
||||
color = '#f0ad4e';
|
||||
}
|
||||
|
||||
return color;
|
||||
|
||||
},
|
||||
trackColor: '#2b2b2b',
|
||||
size: 30,
|
||||
scaleColor: false,
|
||||
lineWidth: 2,
|
||||
animate: 1000
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* init tooltips on an element
|
||||
* @returns {any|JQuery|*}
|
||||
*/
|
||||
$.fn.initTooltips = function(){
|
||||
|
||||
return this.each(function(){
|
||||
|
||||
var tooltipElements = $(this).find('[title]');
|
||||
tooltipElements.tooltip({
|
||||
container: this,
|
||||
delay: 100
|
||||
});
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* adds a popup tooltip with character information (created/updated)
|
||||
* @param tooltipData
|
||||
*/
|
||||
$.fn.addCharacterInfoTooltip = function(tooltipData){
|
||||
var element = $(this);
|
||||
|
||||
if(
|
||||
tooltipData.created.character &&
|
||||
tooltipData.updated.character
|
||||
){
|
||||
|
||||
var createdData = tooltipData.created;
|
||||
var updatedData = tooltipData.updated;
|
||||
|
||||
// check if data has changed
|
||||
if(
|
||||
element.data('created') !== createdData.created ||
|
||||
element.data('updated') !== updatedData.updated
|
||||
){
|
||||
// data changed
|
||||
// set new data for next check
|
||||
element.data('created', createdData.created);
|
||||
element.data('updated', updatedData.updated);
|
||||
|
||||
var statusCreatedClass = getStatusInfoForCharacter(createdData.character, 'class');
|
||||
var statusUpdatedClass = getStatusInfoForCharacter(updatedData.character, 'class');
|
||||
|
||||
// convert timestamps
|
||||
var dateCreated = new Date(createdData.created * 1000);
|
||||
var dateUpdated = new Date(updatedData.updated * 1000);
|
||||
var dateCreatedUTC = convertDateToUTC(dateCreated);
|
||||
var dateUpdatedUTC = convertDateToUTC(dateUpdated);
|
||||
|
||||
var data = {
|
||||
created: createdData,
|
||||
updated: updatedData,
|
||||
createdTime: convertDateToString(dateCreatedUTC),
|
||||
updatedTime: convertDateToString(dateUpdatedUTC),
|
||||
createdStatusClass: statusCreatedClass,
|
||||
updatedStatusClass: statusUpdatedClass
|
||||
};
|
||||
|
||||
requirejs(['text!templates/tooltip/character_info.html', 'mustache'], function(template, Mustache) {
|
||||
|
||||
var content = Mustache.render(template, data);
|
||||
|
||||
element.popover({
|
||||
placement: 'top',
|
||||
html: true,
|
||||
trigger: 'hover',
|
||||
content: '',
|
||||
container: 'body',
|
||||
title: 'Created / Updated',
|
||||
delay: {
|
||||
show: 250,
|
||||
hide: 0
|
||||
}
|
||||
});
|
||||
|
||||
// set new popover content
|
||||
var popover = element.data('bs.popover');
|
||||
popover.options.content = content;
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* display a custom message (info/warning/error) to a container element
|
||||
* check: $.fn.showFormMessage() for an other way of showing messages
|
||||
* @param config
|
||||
*/
|
||||
$.fn.showMessage = function(config){
|
||||
var containerElement = $(this);
|
||||
|
||||
requirejs(['text!templates/form/message.html', 'mustache'], function(template, Mustache) {
|
||||
|
||||
var messageTypeClass = 'alert-danger';
|
||||
var messageTextClass = 'txt-color-danger';
|
||||
|
||||
switch(config.type){
|
||||
case 'info':
|
||||
messageTypeClass = 'alert-info';
|
||||
messageTextClass = 'txt-color-information';
|
||||
break;
|
||||
case 'success':
|
||||
messageTypeClass = 'alert-success';
|
||||
messageTextClass = 'txt-color-success';
|
||||
break;
|
||||
case 'warning':
|
||||
messageTypeClass = 'alert-warning';
|
||||
messageTextClass = 'txt-color-warning';
|
||||
break;
|
||||
}
|
||||
|
||||
var data = {
|
||||
title: config.title,
|
||||
text: config.text,
|
||||
messageTypeClass: messageTypeClass,
|
||||
messageTextClass: messageTextClass
|
||||
};
|
||||
|
||||
var content = Mustache.render(template, data);
|
||||
|
||||
containerElement.html(content);
|
||||
|
||||
containerElement.children().first().velocity('stop').velocity('fadeIn');
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* wrapper function for onClick() || onDblClick() events in order to distinguish between this two types of events
|
||||
* @param singleClickCallback
|
||||
* @param doubleClickCallback
|
||||
* @param timeout
|
||||
* @returns {any|JQuery|*}
|
||||
*/
|
||||
$.fn.singleDoubleClick = function(singleClickCallback, doubleClickCallback, timeout) {
|
||||
return this.each(function(){
|
||||
var clicks = 0, self = this;
|
||||
$(this).on('mouseup', function(e){
|
||||
clicks++;
|
||||
if (clicks === 1) {
|
||||
setTimeout(function(){
|
||||
if(clicks === 1) {
|
||||
singleClickCallback.call(self, e);
|
||||
} else {
|
||||
doubleClickCallback.call(self, e);
|
||||
}
|
||||
clicks = 0;
|
||||
}, timeout || Init.timer.dblClickTimer);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* ===========================================================================================================
|
||||
* Util functions that are global available for all modules
|
||||
* ==========================================================================================================
|
||||
*/
|
||||
|
||||
/**
|
||||
* get date obj with current EVE Server Time.
|
||||
* @returns {Date}
|
||||
*/
|
||||
var getServerTime = function(){
|
||||
|
||||
// Server is running with GMT/UTC (EVE Time)
|
||||
var localDate = new Date();
|
||||
|
||||
var serverDate= new Date(
|
||||
localDate.getUTCFullYear(),
|
||||
localDate.getUTCMonth(),
|
||||
localDate.getUTCDate(),
|
||||
localDate.getUTCHours(),
|
||||
localDate.getUTCMinutes(),
|
||||
localDate.getUTCSeconds()
|
||||
);
|
||||
|
||||
return serverDate;
|
||||
};
|
||||
|
||||
/**
|
||||
* start time measurement by a unique string identifier
|
||||
* @param timerName
|
||||
*/
|
||||
var timeStart = function(timerName){
|
||||
|
||||
if(typeof performance === 'object'){
|
||||
stopTimerCache[timerName] = performance.now();
|
||||
}else{
|
||||
stopTimerCache[timerName] = new Date().getTime();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* get time delta between timeStart() and timeStop() by a unique string identifier
|
||||
* @param timerName
|
||||
* @returns {number}
|
||||
*/
|
||||
var timeStop = function(timerName){
|
||||
|
||||
var duration = 0;
|
||||
|
||||
if( stopTimerCache.hasOwnProperty(timerName) ){
|
||||
// check browser support for performance API
|
||||
var timeNow = 0;
|
||||
|
||||
if(typeof performance === 'object'){
|
||||
timeNow = performance.now();
|
||||
}else{
|
||||
timeNow = new Date();
|
||||
}
|
||||
|
||||
// format ms time duration
|
||||
duration = Number( (timeNow - stopTimerCache[timerName] ).toFixed(2) );
|
||||
|
||||
// delete key
|
||||
delete( stopTimerCache[timerName]);
|
||||
}
|
||||
|
||||
return duration;
|
||||
};
|
||||
|
||||
/**
|
||||
* build a program URL by a given path
|
||||
* @param path
|
||||
* @returns {string}
|
||||
*/
|
||||
var buildUrl = function(path){
|
||||
return document.location.protocol + '//' + document.location.host + path;
|
||||
};
|
||||
|
||||
/**
|
||||
* trigger main logging event with log information
|
||||
* @param message
|
||||
* @param options
|
||||
*/
|
||||
var log = function(logKey, options){
|
||||
$(window).trigger('pf:log', [logKey, options]);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -350,39 +674,6 @@ define([
|
||||
return !jqXHR.getAllResponseHeaders();
|
||||
};
|
||||
|
||||
// ==================================================================================================
|
||||
// ==================================================================================================
|
||||
// ==================================================================================================
|
||||
|
||||
/**
|
||||
* init the map-update-counter as "easy-pie-chart"
|
||||
*/
|
||||
$.fn.initMapUpdateCounter = function(){
|
||||
|
||||
var counterChart = $(this);
|
||||
|
||||
counterChart.easyPieChart({
|
||||
barColor: function(percent){
|
||||
|
||||
var color = '#568a89';
|
||||
if(percent <= 30){
|
||||
color = '#d9534f';
|
||||
}else if(percent <= 50){
|
||||
color = '#f0ad4e';
|
||||
}
|
||||
|
||||
return color;
|
||||
|
||||
},
|
||||
trackColor: '#2b2b2b',
|
||||
size: 30,
|
||||
scaleColor: false,
|
||||
lineWidth: 2,
|
||||
animate: 1000
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* get the map module object or create a new module
|
||||
* @returns {*|HTMLElement}
|
||||
@@ -451,7 +742,6 @@ define([
|
||||
for(var i = 0; i < mapTypes.length; i++){
|
||||
for(var j = 0; j < authorizedMapTypes.length; j++){
|
||||
if(mapTypes[i].name === authorizedMapTypes[j]){
|
||||
console.log('OK')
|
||||
tempMapTypes.push(mapTypes[i]);
|
||||
break;
|
||||
}
|
||||
@@ -850,8 +1140,47 @@ define([
|
||||
return areaId;
|
||||
};
|
||||
|
||||
/**
|
||||
* set currentMapData as "global" variable
|
||||
* this function should be called continuously after data change
|
||||
* to keep the data always up2data
|
||||
* @param mapData
|
||||
*/
|
||||
var setCurrentMapData = function(mapData){
|
||||
Init.currentMapData = mapData;
|
||||
|
||||
return getCurrentMapData();
|
||||
};
|
||||
|
||||
/**
|
||||
* get currentMapData from "global" variable for a specific map or all maps
|
||||
* @param mapId
|
||||
* @returns {boolean}
|
||||
*/
|
||||
var getCurrentMapData = function(mapId){
|
||||
|
||||
var currentMapData = false;
|
||||
|
||||
if( mapId === parseInt(mapId, 10) ){
|
||||
// search for a specific map
|
||||
for(var i = 0; i < Init.currentMapData.length; i++){
|
||||
if(Init.currentMapData[i].config.id === mapId){
|
||||
currentMapData = Init.currentMapData[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
// get data for all maps
|
||||
currentMapData = Init.currentMapData;
|
||||
}
|
||||
|
||||
return currentMapData;
|
||||
};
|
||||
|
||||
/**
|
||||
* set currentUserData as "global" variable
|
||||
* this function should be called continuously after data change
|
||||
* to keep the data always up2data
|
||||
* @param userData
|
||||
*/
|
||||
var setCurrentUserData = function(userData){
|
||||
@@ -968,137 +1297,8 @@ define([
|
||||
return dateString + ' ' + timeString;
|
||||
};
|
||||
|
||||
/**
|
||||
* init tooltips on an element
|
||||
* @returns {any|JQuery|*}
|
||||
*/
|
||||
$.fn.initTooltips = function(){
|
||||
|
||||
return this.each(function(){
|
||||
|
||||
var tooltipElements = $(this).find('[title]');
|
||||
tooltipElements.tooltip({
|
||||
container: this,
|
||||
delay: 100
|
||||
});
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* adds a popup tooltip with character information (created/updated)
|
||||
* @param tooltipData
|
||||
*/
|
||||
$.fn.addCharacterInfoTooltip = function(tooltipData){
|
||||
var element = $(this);
|
||||
|
||||
if(
|
||||
tooltipData.created.character &&
|
||||
tooltipData.updated.character
|
||||
){
|
||||
|
||||
var createdData = tooltipData.created;
|
||||
var updatedData = tooltipData.updated;
|
||||
|
||||
// check if data has changed
|
||||
if(
|
||||
element.data('created') !== createdData.created ||
|
||||
element.data('updated') !== updatedData.updated
|
||||
){
|
||||
// data changed
|
||||
// set new data for next check
|
||||
element.data('created', createdData.created);
|
||||
element.data('updated', updatedData.updated);
|
||||
|
||||
var statusCreatedClass = getStatusInfoForCharacter(createdData.character, 'class');
|
||||
var statusUpdatedClass = getStatusInfoForCharacter(updatedData.character, 'class');
|
||||
|
||||
// convert timestamps
|
||||
var dateCreated = new Date(createdData.created * 1000);
|
||||
var dateUpdated = new Date(updatedData.updated * 1000);
|
||||
var dateCreatedUTC = convertDateToUTC(dateCreated);
|
||||
var dateUpdatedUTC = convertDateToUTC(dateUpdated);
|
||||
|
||||
var data = {
|
||||
created: createdData,
|
||||
updated: updatedData,
|
||||
createdTime: convertDateToString(dateCreatedUTC),
|
||||
updatedTime: convertDateToString(dateUpdatedUTC),
|
||||
createdStatusClass: statusCreatedClass,
|
||||
updatedStatusClass: statusUpdatedClass
|
||||
};
|
||||
|
||||
requirejs(['text!templates/tooltip/character_info.html', 'mustache'], function(template, Mustache) {
|
||||
|
||||
var content = Mustache.render(template, data);
|
||||
|
||||
element.popover({
|
||||
placement: 'top',
|
||||
html: true,
|
||||
trigger: 'hover',
|
||||
content: '',
|
||||
container: 'body',
|
||||
title: 'Created / Updated',
|
||||
delay: {
|
||||
show: 250,
|
||||
hide: 0
|
||||
}
|
||||
});
|
||||
|
||||
// set new popover content
|
||||
var popover = element.data('bs.popover');
|
||||
popover.options.content = content;
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* display a custom message (info/warning/error) to a container element
|
||||
* @param config
|
||||
*/
|
||||
$.fn.showMessage = function(config){
|
||||
var containerElement = $(this);
|
||||
|
||||
requirejs(['text!templates/form/message.html', 'mustache'], function(template, Mustache) {
|
||||
|
||||
var messageTypeClass = 'alert-danger';
|
||||
var messageTextClass = 'txt-color-danger';
|
||||
|
||||
switch(config.type){
|
||||
case 'info':
|
||||
messageTypeClass = 'alert-info';
|
||||
messageTextClass = 'txt-color-information';
|
||||
break;
|
||||
case 'success':
|
||||
messageTypeClass = 'alert-success';
|
||||
messageTextClass = 'txt-color-success';
|
||||
break;
|
||||
case 'warning':
|
||||
messageTypeClass = 'alert-warning';
|
||||
messageTextClass = 'txt-color-warning';
|
||||
break;
|
||||
}
|
||||
|
||||
var data = {
|
||||
title: config.title,
|
||||
text: config.text,
|
||||
messageTypeClass: messageTypeClass,
|
||||
messageTextClass: messageTextClass
|
||||
};
|
||||
|
||||
var content = Mustache.render(template, data);
|
||||
|
||||
containerElement.html(content);
|
||||
|
||||
containerElement.children().first().velocity('stop').velocity('fadeIn');
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
config: config,
|
||||
getServerTime: getServerTime,
|
||||
timeStart: timeStart,
|
||||
timeStop: timeStop,
|
||||
@@ -1128,6 +1328,8 @@ define([
|
||||
getAllSignatureNames: getAllSignatureNames,
|
||||
getSignatureTypeIdByName: getSignatureTypeIdByName,
|
||||
getAreaIdBySecurity: getAreaIdBySecurity,
|
||||
setCurrentMapData: setCurrentMapData,
|
||||
getCurrentMapData: getCurrentMapData,
|
||||
setCurrentUserData: setCurrentUserData,
|
||||
getCurrentUserData: getCurrentUserData,
|
||||
setCurrentSystemData: setCurrentSystemData,
|
||||
|
||||
873
js/lib/datatables/extensions/responsive/dataTables.responsive.js
Normal file
873
js/lib/datatables/extensions/responsive/dataTables.responsive.js
Normal file
@@ -0,0 +1,873 @@
|
||||
/*! Responsive 1.0.6
|
||||
* 2014-2015 SpryMedia Ltd - datatables.net/license
|
||||
*/
|
||||
|
||||
/**
|
||||
* @summary Responsive
|
||||
* @description Responsive tables plug-in for DataTables
|
||||
* @version 1.0.6
|
||||
* @file dataTables.responsive.js
|
||||
* @author SpryMedia Ltd (www.sprymedia.co.uk)
|
||||
* @contact www.sprymedia.co.uk/contact
|
||||
* @copyright Copyright 2014-2015 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(window, document, undefined) {
|
||||
|
||||
|
||||
var factory = function( $, DataTable ) {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Responsive is a plug-in for the DataTables library that makes use of
|
||||
* DataTables' ability to change the visibility of columns, changing the
|
||||
* visibility of columns so the displayed columns fit into the table container.
|
||||
* The end result is that complex tables will be dynamically adjusted to fit
|
||||
* into the viewport, be it on a desktop, tablet or mobile browser.
|
||||
*
|
||||
* Responsive for DataTables has two modes of operation, which can used
|
||||
* individually or combined:
|
||||
*
|
||||
* * Class name based control - columns assigned class names that match the
|
||||
* breakpoint logic can be shown / hidden as required for each breakpoint.
|
||||
* * Automatic control - columns are automatically hidden when there is no
|
||||
* room left to display them. Columns removed from the right.
|
||||
*
|
||||
* In additional to column visibility control, Responsive also has built into
|
||||
* options to use DataTables' child row display to show / hide the information
|
||||
* from the table that has been hidden. There are also two modes of operation
|
||||
* for this child row display:
|
||||
*
|
||||
* * Inline - when the control element that the user can use to show / hide
|
||||
* child rows is displayed inside the first column of the table.
|
||||
* * Column - where a whole column is dedicated to be the show / hide control.
|
||||
*
|
||||
* Initialisation of Responsive is performed by:
|
||||
*
|
||||
* * Adding the class `responsive` or `dt-responsive` to the table. In this case
|
||||
* Responsive will automatically be initialised with the default configuration
|
||||
* options when the DataTable is created.
|
||||
* * Using the `responsive` option in the DataTables configuration options. This
|
||||
* can also be used to specify the configuration options, or simply set to
|
||||
* `true` to use the defaults.
|
||||
*
|
||||
* @class
|
||||
* @param {object} settings DataTables settings object for the host table
|
||||
* @param {object} [opts] Configuration options
|
||||
* @requires jQuery 1.7+
|
||||
* @requires DataTables 1.10.1+
|
||||
*
|
||||
* @example
|
||||
* $('#example').DataTable( {
|
||||
* responsive: true
|
||||
* } );
|
||||
* } );
|
||||
*/
|
||||
var Responsive = function ( settings, opts ) {
|
||||
// Sanity check that we are using DataTables 1.10 or newer
|
||||
if ( ! DataTable.versionCheck || ! DataTable.versionCheck( '1.10.1' ) ) {
|
||||
throw 'DataTables Responsive requires DataTables 1.10.1 or newer';
|
||||
}
|
||||
|
||||
this.s = {
|
||||
dt: new DataTable.Api( settings ),
|
||||
columns: []
|
||||
};
|
||||
|
||||
// Check if responsive has already been initialised on this table
|
||||
if ( this.s.dt.settings()[0].responsive ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// details is an object, but for simplicity the user can give it as a string
|
||||
if ( opts && typeof opts.details === 'string' ) {
|
||||
opts.details = { type: opts.details };
|
||||
}
|
||||
|
||||
this.c = $.extend( true, {}, Responsive.defaults, DataTable.defaults.responsive, opts );
|
||||
settings.responsive = this;
|
||||
this._constructor();
|
||||
};
|
||||
|
||||
Responsive.prototype = {
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* Constructor
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initialise the Responsive instance
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_constructor: function ()
|
||||
{
|
||||
var that = this;
|
||||
var dt = this.s.dt;
|
||||
|
||||
dt.settings()[0]._responsive = this;
|
||||
|
||||
// Use DataTables' private throttle function to avoid processor thrashing
|
||||
$(window).on( 'resize.dtr orientationchange.dtr', dt.settings()[0].oApi._fnThrottle( function () {
|
||||
that._resize();
|
||||
} ) );
|
||||
|
||||
// Destroy event handler
|
||||
dt.on( 'destroy.dtr', function () {
|
||||
$(window).off( 'resize.dtr orientationchange.dtr draw.dtr' );
|
||||
} );
|
||||
|
||||
// Reorder the breakpoints array here in case they have been added out
|
||||
// of order
|
||||
this.c.breakpoints.sort( function (a, b) {
|
||||
return a.width < b.width ? 1 :
|
||||
a.width > b.width ? -1 : 0;
|
||||
} );
|
||||
|
||||
// Determine which columns are already hidden, and should therefore
|
||||
// remain hidden. todo - should this be done? See thread 22677
|
||||
//
|
||||
// this.s.alwaysHidden = dt.columns(':hidden').indexes();
|
||||
|
||||
this._classLogic();
|
||||
this._resizeAuto();
|
||||
|
||||
// Details handler
|
||||
var details = this.c.details;
|
||||
if ( details.type ) {
|
||||
that._detailsInit();
|
||||
this._detailsVis();
|
||||
|
||||
dt.on( 'column-visibility.dtr', function () {
|
||||
that._detailsVis();
|
||||
} );
|
||||
|
||||
// Redraw the details box on each draw. This is used until
|
||||
// DataTables implements a native `updated` event for rows
|
||||
dt.on( 'draw.dtr', function () {
|
||||
dt.rows( {page: 'current'} ).iterator( 'row', function ( settings, idx ) {
|
||||
var row = dt.row( idx );
|
||||
|
||||
if ( row.child.isShown() ) {
|
||||
var info = that.c.details.renderer( dt, idx );
|
||||
row.child( info, 'child' ).show();
|
||||
}
|
||||
} );
|
||||
} );
|
||||
|
||||
$(dt.table().node()).addClass( 'dtr-'+details.type );
|
||||
}
|
||||
|
||||
// First pass - draw the table for the current viewport size
|
||||
this._resize();
|
||||
},
|
||||
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* Private methods
|
||||
*/
|
||||
|
||||
/**
|
||||
* Calculate the visibility for the columns in a table for a given
|
||||
* breakpoint. The result is pre-determined based on the class logic if
|
||||
* class names are used to control all columns, but the width of the table
|
||||
* is also used if there are columns which are to be automatically shown
|
||||
* and hidden.
|
||||
*
|
||||
* @param {string} breakpoint Breakpoint name to use for the calculation
|
||||
* @return {array} Array of boolean values initiating the visibility of each
|
||||
* column.
|
||||
* @private
|
||||
*/
|
||||
_columnsVisiblity: function ( breakpoint )
|
||||
{
|
||||
var dt = this.s.dt;
|
||||
var columns = this.s.columns;
|
||||
var i, ien;
|
||||
|
||||
// Class logic - determine which columns are in this breakpoint based
|
||||
// on the classes. If no class control (i.e. `auto`) then `-` is used
|
||||
// to indicate this to the rest of the function
|
||||
var display = $.map( columns, function ( col ) {
|
||||
return col.auto && col.minWidth === null ?
|
||||
false :
|
||||
col.auto === true ?
|
||||
'-' :
|
||||
$.inArray( breakpoint, col.includeIn ) !== -1;
|
||||
} );
|
||||
|
||||
// Auto column control - first pass: how much width is taken by the
|
||||
// ones that must be included from the non-auto columns
|
||||
var requiredWidth = 0;
|
||||
for ( i=0, ien=display.length ; i<ien ; i++ ) {
|
||||
if ( display[i] === true ) {
|
||||
requiredWidth += columns[i].minWidth;
|
||||
}
|
||||
}
|
||||
|
||||
// Second pass, use up any remaining width for other columns. For
|
||||
// scrolling tables we need to subtract the width of the scrollbar. It
|
||||
// may not be requires which makes this sub-optimal, but it would
|
||||
// require another full redraw to make complete use of those extra few
|
||||
// pixels
|
||||
var scrolling = dt.settings()[0].oScroll;
|
||||
var bar = scrolling.sY || scrolling.sX ? scrolling.iBarWidth : 0;
|
||||
var widthAvailable = dt.table().container().offsetWidth - bar;
|
||||
var usedWidth = widthAvailable - requiredWidth;
|
||||
|
||||
// Control column needs to always be included. This makes it sub-
|
||||
// optimal in terms of using the available with, but to stop layout
|
||||
// thrashing or overflow. Also we need to account for the control column
|
||||
// width first so we know how much width is available for the other
|
||||
// columns, since the control column might not be the first one shown
|
||||
for ( i=0, ien=display.length ; i<ien ; i++ ) {
|
||||
if ( columns[i].control ) {
|
||||
usedWidth -= columns[i].minWidth;
|
||||
}
|
||||
}
|
||||
|
||||
// Allow columns to be shown (counting from the left) until we run out
|
||||
// of room
|
||||
var empty = false;
|
||||
for ( i=0, ien=display.length ; i<ien ; i++ ) {
|
||||
if ( display[i] === '-' && ! columns[i].control ) {
|
||||
// Once we've found a column that won't fit we don't let any
|
||||
// others display either, or columns might disappear in the
|
||||
// middle of the table
|
||||
if ( empty || usedWidth - columns[i].minWidth < 0 ) {
|
||||
empty = true;
|
||||
display[i] = false;
|
||||
}
|
||||
else {
|
||||
display[i] = true;
|
||||
}
|
||||
|
||||
usedWidth -= columns[i].minWidth;
|
||||
}
|
||||
}
|
||||
|
||||
// Determine if the 'control' column should be shown (if there is one).
|
||||
// This is the case when there is a hidden column (that is not the
|
||||
// control column). The two loops look inefficient here, but they are
|
||||
// trivial and will fly through. We need to know the outcome from the
|
||||
// first , before the action in the second can be taken
|
||||
var showControl = false;
|
||||
|
||||
for ( i=0, ien=columns.length ; i<ien ; i++ ) {
|
||||
if ( ! columns[i].control && ! columns[i].never && ! display[i] ) {
|
||||
showControl = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for ( i=0, ien=columns.length ; i<ien ; i++ ) {
|
||||
if ( columns[i].control ) {
|
||||
display[i] = showControl;
|
||||
}
|
||||
}
|
||||
|
||||
// Finally we need to make sure that there is at least one column that
|
||||
// is visible
|
||||
if ( $.inArray( true, display ) === -1 ) {
|
||||
display[0] = true;
|
||||
}
|
||||
|
||||
return display;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Create the internal `columns` array with information about the columns
|
||||
* for the table. This includes determining which breakpoints the column
|
||||
* will appear in, based upon class names in the column, which makes up the
|
||||
* vast majority of this method.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_classLogic: function ()
|
||||
{
|
||||
var that = this;
|
||||
var calc = {};
|
||||
var breakpoints = this.c.breakpoints;
|
||||
var columns = this.s.dt.columns().eq(0).map( function (i) {
|
||||
var className = this.column(i).header().className;
|
||||
|
||||
return {
|
||||
className: className,
|
||||
includeIn: [],
|
||||
auto: false,
|
||||
control: false,
|
||||
never: className.match(/\bnever\b/) ? true : false
|
||||
};
|
||||
} );
|
||||
|
||||
// Simply add a breakpoint to `includeIn` array, ensuring that there are
|
||||
// no duplicates
|
||||
var add = function ( colIdx, name ) {
|
||||
var includeIn = columns[ colIdx ].includeIn;
|
||||
|
||||
if ( $.inArray( name, includeIn ) === -1 ) {
|
||||
includeIn.push( name );
|
||||
}
|
||||
};
|
||||
|
||||
var column = function ( colIdx, name, operator, matched ) {
|
||||
var size, i, ien;
|
||||
|
||||
if ( ! operator ) {
|
||||
columns[ colIdx ].includeIn.push( name );
|
||||
}
|
||||
else if ( operator === 'max-' ) {
|
||||
// Add this breakpoint and all smaller
|
||||
size = that._find( name ).width;
|
||||
|
||||
for ( i=0, ien=breakpoints.length ; i<ien ; i++ ) {
|
||||
if ( breakpoints[i].width <= size ) {
|
||||
add( colIdx, breakpoints[i].name );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( operator === 'min-' ) {
|
||||
// Add this breakpoint and all larger
|
||||
size = that._find( name ).width;
|
||||
|
||||
for ( i=0, ien=breakpoints.length ; i<ien ; i++ ) {
|
||||
if ( breakpoints[i].width >= size ) {
|
||||
add( colIdx, breakpoints[i].name );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( operator === 'not-' ) {
|
||||
// Add all but this breakpoint (xxx need extra information)
|
||||
|
||||
for ( i=0, ien=breakpoints.length ; i<ien ; i++ ) {
|
||||
if ( breakpoints[i].name.indexOf( matched ) === -1 ) {
|
||||
add( colIdx, breakpoints[i].name );
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Loop over each column and determine if it has a responsive control
|
||||
// class
|
||||
columns.each( function ( col, i ) {
|
||||
var classNames = col.className.split(' ');
|
||||
var hasClass = false;
|
||||
|
||||
// Split the class name up so multiple rules can be applied if needed
|
||||
for ( var k=0, ken=classNames.length ; k<ken ; k++ ) {
|
||||
var className = $.trim( classNames[k] );
|
||||
|
||||
if ( className === 'all' ) {
|
||||
// Include in all
|
||||
hasClass = true;
|
||||
col.includeIn = $.map( breakpoints, function (a) {
|
||||
return a.name;
|
||||
} );
|
||||
return;
|
||||
}
|
||||
else if ( className === 'none' || className === 'never' ) {
|
||||
// Include in none (default) and no auto
|
||||
hasClass = true;
|
||||
return;
|
||||
}
|
||||
else if ( className === 'control' ) {
|
||||
// Special column that is only visible, when one of the other
|
||||
// columns is hidden. This is used for the details control
|
||||
hasClass = true;
|
||||
col.control = true;
|
||||
return;
|
||||
}
|
||||
|
||||
$.each( breakpoints, function ( j, breakpoint ) {
|
||||
// Does this column have a class that matches this breakpoint?
|
||||
var brokenPoint = breakpoint.name.split('-');
|
||||
var re = new RegExp( '(min\\-|max\\-|not\\-)?('+brokenPoint[0]+')(\\-[_a-zA-Z0-9])?' );
|
||||
var match = className.match( re );
|
||||
|
||||
if ( match ) {
|
||||
hasClass = true;
|
||||
|
||||
if ( match[2] === brokenPoint[0] && match[3] === '-'+brokenPoint[1] ) {
|
||||
// Class name matches breakpoint name fully
|
||||
column( i, breakpoint.name, match[1], match[2]+match[3] );
|
||||
}
|
||||
else if ( match[2] === brokenPoint[0] && ! match[3] ) {
|
||||
// Class name matched primary breakpoint name with no qualifier
|
||||
column( i, breakpoint.name, match[1], match[2] );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
// If there was no control class, then automatic sizing is used
|
||||
if ( ! hasClass ) {
|
||||
col.auto = true;
|
||||
}
|
||||
} );
|
||||
|
||||
this.s.columns = columns;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Initialisation for the details handler
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_detailsInit: function ()
|
||||
{
|
||||
var that = this;
|
||||
var dt = this.s.dt;
|
||||
var details = this.c.details;
|
||||
|
||||
// The inline type always uses the first child as the target
|
||||
if ( details.type === 'inline' ) {
|
||||
details.target = 'td:first-child';
|
||||
}
|
||||
|
||||
// type.target can be a string jQuery selector or a column index
|
||||
var target = details.target;
|
||||
var selector = typeof target === 'string' ? target : 'td';
|
||||
|
||||
// Click handler to show / hide the details rows when they are available
|
||||
$( dt.table().body() ).on( 'click', selector, function (e) {
|
||||
// If the table is not collapsed (i.e. there is no hidden columns)
|
||||
// then take no action
|
||||
if ( ! $(dt.table().node()).hasClass('collapsed' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check that the row is actually a DataTable's controlled node
|
||||
if ( ! dt.row( $(this).closest('tr') ).length ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// For column index, we determine if we should act or not in the
|
||||
// handler - otherwise it is already okay
|
||||
if ( typeof target === 'number' ) {
|
||||
var targetIdx = target < 0 ?
|
||||
dt.columns().eq(0).length + target :
|
||||
target;
|
||||
|
||||
if ( dt.cell( this ).index().column !== targetIdx ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// $().closest() includes itself in its check
|
||||
var row = dt.row( $(this).closest('tr') );
|
||||
|
||||
if ( row.child.isShown() ) {
|
||||
row.child( false );
|
||||
$( row.node() ).removeClass( 'parent' );
|
||||
}
|
||||
else {
|
||||
var info = that.c.details.renderer( dt, row[0] );
|
||||
row.child( info, 'child' ).show();
|
||||
$( row.node() ).addClass( 'parent' );
|
||||
}
|
||||
} );
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Update the child rows in the table whenever the column visibility changes
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_detailsVis: function ()
|
||||
{
|
||||
var that = this;
|
||||
var dt = this.s.dt;
|
||||
|
||||
// Find how many columns are hidden
|
||||
var hiddenColumns = dt.columns().indexes().filter( function ( idx ) {
|
||||
var col = dt.column( idx );
|
||||
|
||||
if ( col.visible() ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Only counts as hidden if it doesn't have the `never` class
|
||||
return $( col.header() ).hasClass( 'never' ) ? null : idx;
|
||||
} );
|
||||
var haveHidden = true;
|
||||
|
||||
if ( hiddenColumns.length === 0 || ( hiddenColumns.length === 1 && this.s.columns[ hiddenColumns[0] ].control ) ) {
|
||||
haveHidden = false;
|
||||
}
|
||||
|
||||
if ( haveHidden ) {
|
||||
// Show all existing child rows
|
||||
dt.rows( { page: 'current' } ).eq(0).each( function (idx) {
|
||||
var row = dt.row( idx );
|
||||
|
||||
if ( row.child() ) {
|
||||
var info = that.c.details.renderer( dt, row[0] );
|
||||
|
||||
// The renderer can return false to have no child row
|
||||
if ( info === false ) {
|
||||
row.child.hide();
|
||||
}
|
||||
else {
|
||||
row.child( info, 'child' ).show();
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
else {
|
||||
// Hide all existing child rows
|
||||
dt.rows( { page: 'current' } ).eq(0).each( function (idx) {
|
||||
dt.row( idx ).child.hide();
|
||||
} );
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Find a breakpoint object from a name
|
||||
* @param {string} name Breakpoint name to find
|
||||
* @return {object} Breakpoint description object
|
||||
*/
|
||||
_find: function ( name )
|
||||
{
|
||||
var breakpoints = this.c.breakpoints;
|
||||
|
||||
for ( var i=0, ien=breakpoints.length ; i<ien ; i++ ) {
|
||||
if ( breakpoints[i].name === name ) {
|
||||
return breakpoints[i];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Alter the table display for a resized viewport. This involves first
|
||||
* determining what breakpoint the window currently is in, getting the
|
||||
* column visibilities to apply and then setting them.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_resize: function ()
|
||||
{
|
||||
var dt = this.s.dt;
|
||||
var width = $(window).width();
|
||||
var breakpoints = this.c.breakpoints;
|
||||
var breakpoint = breakpoints[0].name;
|
||||
var columns = this.s.columns;
|
||||
var i, ien;
|
||||
|
||||
// Determine what breakpoint we are currently at
|
||||
for ( i=breakpoints.length-1 ; i>=0 ; i-- ) {
|
||||
if ( width <= breakpoints[i].width ) {
|
||||
breakpoint = breakpoints[i].name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Show the columns for that break point
|
||||
var columnsVis = this._columnsVisiblity( breakpoint );
|
||||
|
||||
// Set the class before the column visibility is changed so event
|
||||
// listeners know what the state is. Need to determine if there are
|
||||
// any columns that are not visible but can be shown
|
||||
var collapsedClass = false;
|
||||
for ( i=0, ien=columns.length ; i<ien ; i++ ) {
|
||||
if ( columnsVis[i] === false && ! columns[i].never ) {
|
||||
collapsedClass = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$( dt.table().node() ).toggleClass('collapsed', collapsedClass );
|
||||
|
||||
dt.columns().eq(0).each( function ( colIdx, i ) {
|
||||
dt.column( colIdx ).visible( columnsVis[i] );
|
||||
} );
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Determine the width of each column in the table so the auto column hiding
|
||||
* has that information to work with. This method is never going to be 100%
|
||||
* perfect since column widths can change slightly per page, but without
|
||||
* seriously compromising performance this is quite effective.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_resizeAuto: function ()
|
||||
{
|
||||
var dt = this.s.dt;
|
||||
var columns = this.s.columns;
|
||||
|
||||
// Are we allowed to do auto sizing?
|
||||
if ( ! this.c.auto ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Are there any columns that actually need auto-sizing, or do they all
|
||||
// have classes defined
|
||||
if ( $.inArray( true, $.map( columns, function (c) { return c.auto; } ) ) === -1 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Clone the table with the current data in it
|
||||
var tableWidth = dt.table().node().offsetWidth;
|
||||
var columnWidths = dt.columns;
|
||||
var clonedTable = dt.table().node().cloneNode( false );
|
||||
var clonedHeader = $( dt.table().header().cloneNode( false ) ).appendTo( clonedTable );
|
||||
var clonedBody = $( dt.table().body().cloneNode( false ) ).appendTo( clonedTable );
|
||||
|
||||
$( dt.table().footer() ).clone( false ).appendTo( clonedTable );
|
||||
|
||||
// This is a bit slow, but we need to get a clone of each row that
|
||||
// includes all columns. As such, try to do this as little as possible.
|
||||
dt.rows( { page: 'current' } ).indexes().flatten().each( function ( idx ) {
|
||||
var clone = dt.row( idx ).node().cloneNode( true );
|
||||
|
||||
if ( dt.columns( ':hidden' ).flatten().length ) {
|
||||
$(clone).append( dt.cells( idx, ':hidden' ).nodes().to$().clone() );
|
||||
}
|
||||
|
||||
$(clone).appendTo( clonedBody );
|
||||
} );
|
||||
|
||||
var cells = dt.columns().header().to$().clone( false );
|
||||
$('<tr/>')
|
||||
.append( cells )
|
||||
.appendTo( clonedHeader );
|
||||
|
||||
// In the inline case extra padding is applied to the first column to
|
||||
// give space for the show / hide icon. We need to use this in the
|
||||
// calculation
|
||||
if ( this.c.details.type === 'inline' ) {
|
||||
$(clonedTable).addClass( 'dtr-inline collapsed' );
|
||||
}
|
||||
|
||||
var inserted = $('<div/>')
|
||||
.css( {
|
||||
width: 1,
|
||||
height: 1,
|
||||
overflow: 'hidden'
|
||||
} )
|
||||
.append( clonedTable );
|
||||
|
||||
// Remove columns which are not to be included
|
||||
inserted.find('th.never, td.never').remove();
|
||||
|
||||
inserted.insertBefore( dt.table().node() );
|
||||
|
||||
// The cloned header now contains the smallest that each column can be
|
||||
dt.columns().eq(0).each( function ( idx ) {
|
||||
columns[idx].minWidth = cells[ idx ].offsetWidth || 0;
|
||||
} );
|
||||
|
||||
inserted.remove();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* List of default breakpoints. Each item in the array is an object with two
|
||||
* properties:
|
||||
*
|
||||
* * `name` - the breakpoint name.
|
||||
* * `width` - the breakpoint width
|
||||
*
|
||||
* @name Responsive.breakpoints
|
||||
* @static
|
||||
*/
|
||||
Responsive.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 }
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Responsive default settings for initialisation
|
||||
*
|
||||
* @namespace
|
||||
* @name Responsive.defaults
|
||||
* @static
|
||||
*/
|
||||
Responsive.defaults = {
|
||||
/**
|
||||
* List of breakpoints for the instance. Note that this means that each
|
||||
* instance can have its own breakpoints. Additionally, the breakpoints
|
||||
* cannot be changed once an instance has been creased.
|
||||
*
|
||||
* @type {Array}
|
||||
* @default Takes the value of `Responsive.breakpoints`
|
||||
*/
|
||||
breakpoints: Responsive.breakpoints,
|
||||
|
||||
/**
|
||||
* Enable / disable auto hiding calculations. It can help to increase
|
||||
* performance slightly if you disable this option, but all columns would
|
||||
* need to have breakpoint classes assigned to them
|
||||
*
|
||||
* @type {Boolean}
|
||||
* @default `true`
|
||||
*/
|
||||
auto: true,
|
||||
|
||||
/**
|
||||
* Details control. If given as a string value, the `type` property of the
|
||||
* default object is set to that value, and the defaults used for the rest
|
||||
* of the object - this is for ease of implementation.
|
||||
*
|
||||
* The object consists of the following properties:
|
||||
*
|
||||
* * `renderer` - function that is called for display of the child row data.
|
||||
* The default function will show the data from the hidden columns
|
||||
* * `target` - Used as the selector for what objects to attach the child
|
||||
* open / close to
|
||||
* * `type` - `false` to disable the details display, `inline` or `column`
|
||||
* for the two control types
|
||||
*
|
||||
* @type {Object|string}
|
||||
*/
|
||||
details: {
|
||||
renderer: function ( api, rowIdx ) {
|
||||
var data = api.cells( rowIdx, ':hidden' ).eq(0).map( function ( cell ) {
|
||||
var header = $( api.column( cell.column ).header() );
|
||||
var idx = api.cell( cell ).index();
|
||||
|
||||
if ( header.hasClass( 'control' ) || header.hasClass( 'never' ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Use a non-public DT API method to render the data for display
|
||||
// This needs to be updated when DT adds a suitable method for
|
||||
// this type of data retrieval
|
||||
var dtPrivate = api.settings()[0];
|
||||
var cellData = dtPrivate.oApi._fnGetCellData(
|
||||
dtPrivate, idx.row, idx.column, 'display'
|
||||
);
|
||||
var title = header.text();
|
||||
if ( title ) {
|
||||
title = title + ':';
|
||||
}
|
||||
|
||||
return '<li data-dtr-index="'+idx.column+'">'+
|
||||
'<span class="dtr-title">'+
|
||||
title+
|
||||
'</span> '+
|
||||
'<span class="dtr-data">'+
|
||||
cellData+
|
||||
'</span>'+
|
||||
'</li>';
|
||||
} ).toArray().join('');
|
||||
|
||||
return data ?
|
||||
$('<ul data-dtr-index="'+rowIdx+'"/>').append( data ) :
|
||||
false;
|
||||
},
|
||||
|
||||
target: 0,
|
||||
|
||||
type: 'inline'
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* API
|
||||
*/
|
||||
var Api = $.fn.dataTable.Api;
|
||||
|
||||
// Doesn't do anything - work around for a bug in DT... Not documented
|
||||
Api.register( 'responsive()', function () {
|
||||
return this;
|
||||
} );
|
||||
|
||||
Api.register( 'responsive.index()', function ( li ) {
|
||||
li = $(li);
|
||||
|
||||
return {
|
||||
column: li.data('dtr-index'),
|
||||
row: li.parent().data('dtr-index')
|
||||
};
|
||||
} );
|
||||
|
||||
Api.register( 'responsive.rebuild()', function () {
|
||||
return this.iterator( 'table', function ( ctx ) {
|
||||
if ( ctx._responsive ) {
|
||||
ctx._responsive._classLogic();
|
||||
}
|
||||
} );
|
||||
} );
|
||||
|
||||
Api.register( 'responsive.recalc()', function () {
|
||||
return this.iterator( 'table', function ( ctx ) {
|
||||
if ( ctx._responsive ) {
|
||||
ctx._responsive._resizeAuto();
|
||||
ctx._responsive._resize();
|
||||
}
|
||||
} );
|
||||
} );
|
||||
|
||||
|
||||
/**
|
||||
* Version information
|
||||
*
|
||||
* @name Responsive.version
|
||||
* @static
|
||||
*/
|
||||
Responsive.version = '1.0.6';
|
||||
|
||||
|
||||
$.fn.dataTable.Responsive = Responsive;
|
||||
$.fn.DataTable.Responsive = Responsive;
|
||||
|
||||
// Attach a listener to the document which listens for DataTables initialisation
|
||||
// events so we can automatically initialise
|
||||
$(document).on( 'init.dt.dtr', function (e, settings, json) {
|
||||
if ( e.namespace !== 'dt' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( $(settings.nTable).hasClass( 'responsive' ) ||
|
||||
$(settings.nTable).hasClass( 'dt-responsive' ) ||
|
||||
settings.oInit.responsive ||
|
||||
DataTable.defaults.responsive
|
||||
) {
|
||||
var init = settings.oInit.responsive;
|
||||
|
||||
if ( init !== false ) {
|
||||
new Responsive( settings, $.isPlainObject( init ) ? init : {} );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
return Responsive;
|
||||
}; // /factory
|
||||
|
||||
|
||||
// Define as an AMD module if possible
|
||||
if ( typeof define === 'function' && define.amd ) {
|
||||
define( ['jquery', 'datatables'], factory );
|
||||
}
|
||||
else if ( typeof exports === 'object' ) {
|
||||
// Node/CommonJS
|
||||
factory( require('jquery'), require('datatables') );
|
||||
}
|
||||
else if ( jQuery && !jQuery.fn.dataTable.Responsive ) {
|
||||
// Otherwise simply initialise as normal, stopping multiple evaluation
|
||||
factory( jQuery, jQuery.fn.dataTable );
|
||||
}
|
||||
|
||||
|
||||
})(window, document);
|
||||
6
js/lib/dom.jsPlumb-1.7.5-min.js
vendored
Normal file
6
js/lib/dom.jsPlumb-1.7.5-min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
/*
|
||||
@title:
|
||||
Drag to Select
|
||||
|
||||
@@ -45,7 +45,7 @@ $('#jquery-drag-to-select-example').dragToSelect({
|
||||
alert($('#jquery-drag-to-select-example li.selected').length + ' selected');
|
||||
}
|
||||
});
|
||||
**/
|
||||
*/
|
||||
jQuery.fn.dragToSelect = function (conf) {
|
||||
var c = typeof(conf) == 'object' ? conf : {};
|
||||
|
||||
@@ -328,10 +328,6 @@ jQuery.fn.dragToSelect = function (conf) {
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
if (jQuery.fn.disableTextSelect) {
|
||||
parent.disableTextSelect();
|
||||
}
|
||||
|
||||
parent.mousedown(function (e) {
|
||||
|
||||
if(
|
||||
|
||||
4
js/lib/select2.min.js
vendored
4
js/lib/select2.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -3,23 +3,116 @@
|
||||
<nav class="navbar navbar-default" role="navigation">
|
||||
<div class="navbar-header pull-left">
|
||||
<ul class="nav navbar-nav {{dialogNavigationClass}}" role="tablist">
|
||||
<li class="active"><a role="tab" data-toggle="tab" href="#{{dialogMapCreateContainerId}}"><i class="fa fa-plus fa-lg fa-fw"></i> New map</a></li>
|
||||
<li class="{{#openTabNew}}active{{/openTabNew}}"><a role="tab" data-toggle="tab" data-name="newMap" href="#{{dialogMapCreateContainerId}}"><i class="fa fa-plus fa-lg fa-fw"></i> New map</a></li>
|
||||
{{^hideEditTab}}
|
||||
<li class=""><a role="tab" data-toggle="tab" href="#{{dialogMapEditContainerId}}"><i class="fa fa-edit fa-lg fa-fw"></i> Edit map</a></li>
|
||||
<li class="{{#openTabEdit}}active{{/openTabEdit}}"><a role="tab" data-toggle="tab" data-name="editMap" href="#{{dialogMapEditContainerId}}"><i class="fa fa-edit fa-lg fa-fw"></i> Edit map</a></li>
|
||||
{{/hideEditTab}}
|
||||
{{^hideSettingsTab}}
|
||||
<li class=""><a role="tab" data-toggle="tab" href="#{{dialogMapSettingsContainerId}}"><i class="fa fa-gears fa-lg fa-fw"></i> Settings</a></li>
|
||||
<li class="{{#openTabSettings}}active{{/openTabSettings}}"><a role="tab" data-toggle="tab" data-name="settings" href="#{{dialogMapSettingsContainerId}}"><i class="fa fa-gears fa-lg fa-fw"></i> Settings</a></li>
|
||||
{{/hideSettingsTab}}
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div id="{{dialogMessageContainerId}}"></div>
|
||||
|
||||
<div class="tab-content">
|
||||
<div role="tabpanel" class="tab-pane fade in active" id="{{dialogMapCreateContainerId}}"></div>
|
||||
<div role="tabpanel" class="tab-pane fade" id="{{dialogMapEditContainerId}}"></div>
|
||||
<div role="tabpanel" class="tab-pane fade" id="{{dialogMapSettingsContainerId}}">sett</div>
|
||||
<div role="tabpanel" class="tab-pane fade {{#openTabNew}}in active{{/openTabNew}}" id="{{dialogMapCreateContainerId}}"></div>
|
||||
<div role="tabpanel" class="tab-pane fade {{#openTabEdit}}in active{{/openTabEdit}}" id="{{dialogMapEditContainerId}}"></div>
|
||||
<div role="tabpanel" class="tab-pane fade {{#openTabSettings}}in active{{/openTabSettings}}" id="{{dialogMapSettingsContainerId}}">
|
||||
<form role="form" class="form-horizontal">
|
||||
<h4><i class="fa fa-share-alt fa-fw"></i> Share this map and grant access</h4>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-11">
|
||||
<blockquote>
|
||||
<p>
|
||||
Use this feature with caution! - Shared map entities have full access.
|
||||
They even can take over map control by removing other entities from this list.
|
||||
</p>
|
||||
<small>Reduce this risk by creating a new map for joined OPs.
|
||||
</small>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{! user search ----------------------------------------------------- }}
|
||||
{{#accessUser.length}}
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label" for="{{userSelectId}}">Username</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group" title="add/remove user">
|
||||
<label for="{{userSelectId}}"></label>
|
||||
<select id="{{userSelectId}}" name="mapUsers[]" multiple="multiple">
|
||||
{{#accessUser}}
|
||||
<option value="{{id}}" selected>{{name}}</option>
|
||||
{{/accessUser}}
|
||||
</select>
|
||||
<span class="help-block with-errors">Search user name (max {{maxUser}})</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/accessUser.length}}
|
||||
|
||||
{{! corporation search ---------------------------------------------- }}
|
||||
{{#accessCorporation.length}}
|
||||
<div class="row">
|
||||
<div class="col-sm-9">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-3 control-label" for="{{corporationSelectId}}">Corporations</label>
|
||||
<div class="col-sm-9">
|
||||
<div class="input-group" title="add/remove corporations">
|
||||
<label for="{{corporationSelectId}}"></label>
|
||||
<select id="{{corporationSelectId}}" name="mapCorporations[]" multiple="multiple">
|
||||
{{#accessCorporation}}
|
||||
<option value="{{id}}" selected="selected" >{{name}}</option>
|
||||
{{/accessCorporation}}
|
||||
</select>
|
||||
<span class="help-block with-errors">Search corporation name (max {{maxCorporation}})</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/accessCorporation.length}}
|
||||
|
||||
{{! alliance search ------------------------------------------------- }}
|
||||
{{#accessAlliance.length}}
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label" for="{{allianceSelectId}}">Alliances</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group" title="add/remove alliances">
|
||||
<label for="{{allianceSelectId}}"></label>
|
||||
<select id="{{allianceSelectId}}" name="mapAlliances[]" multiple="multiple" >
|
||||
{{#accessAlliance}}
|
||||
<option value="{{id}}" selected="selected" >{{name}}</option>
|
||||
{{/accessAlliance}}
|
||||
</select>
|
||||
<span class="help-block with-errors">Search alliance name (max {{maxAlliance}})</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/accessAlliance.length}}
|
||||
|
||||
<input type="hidden" name="id" value="0" />
|
||||
</form>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="{{dialogMessageContainerId}}"></div>
|
||||
|
||||
|
||||
|
||||
<div class="{{formWarningContainerClass}}" class="alert alert-warning" style="display: none;">
|
||||
<span class="txt-color txt-color-warning">Warning</span>
|
||||
<small> (important non-critical information)</small>
|
||||
</div>
|
||||
</div>
|
||||
@@ -80,7 +80,7 @@
|
||||
<label for="email" class="col-sm-3 control-label">New Email</label>
|
||||
<div class="col-sm-6">
|
||||
<div class="input-group" title="Enter your email. It will be kept private!" data-placement="right">
|
||||
<input name="email" type="email" class="form-control" id="email" value="" placeholder="my@mail.com" data-error="Email required" autocomplete="off" {{#register}}required{{/register}} >
|
||||
<input name="email" type="email" class="form-control" id="email" value="" placeholder="your@email.com" data-error="Email required" autocomplete="off" {{#register}}required{{/register}} >
|
||||
<span class="input-group-addon"><i class="fa fa-envelope"></i></span>
|
||||
</div>
|
||||
<div class="help-block with-errors"></div>
|
||||
@@ -95,7 +95,7 @@
|
||||
<label for="email_confirm" class="col-sm-3 control-label">Confirm Email</label>
|
||||
<div class="col-sm-6">
|
||||
<div class="input-group" title="Confirm your email" data-placement="right">
|
||||
<input name="email_confirm" type="email" class="form-control" id="email_confirm" value="" placeholder="my@mail.com" data-error="Email required" data-match="#email" data-match-error="Email fields do not match" autocomplete="off" {{#register}}required{{/register}}>
|
||||
<input name="email_confirm" type="email" class="form-control" id="email_confirm" value="" placeholder="your@email.com" data-error="Email required" data-match="#email" data-match-error="Email fields do not match" autocomplete="off" {{#register}}required{{/register}}>
|
||||
<span class="input-group-addon"><i class="fa fa-envelope"></i></span>
|
||||
</div>
|
||||
<div class="help-block with-errors"></div>
|
||||
@@ -183,6 +183,11 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="{{formErrorContainerClass}} alert alert-danger" style="display: none;">
|
||||
<span class="txt-color txt-color-danger">Error</span>
|
||||
<small> (important non-critical information)</small>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -192,7 +197,6 @@
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-11">
|
||||
|
||||
<blockquote>
|
||||
<p>
|
||||
API Key(s) are required to use <em class="pf-brand">pathfinder</em>.
|
||||
@@ -207,7 +211,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{{#userData.api}}
|
||||
<div class="row {{cloneApiRowClass}}">
|
||||
<div class="col-sm-4">
|
||||
@@ -260,15 +263,9 @@
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="{{settingsErrorId}}" class="alert alert-danger" style="display: none;">
|
||||
<span class="txt-color txt-color-danger">Error</span>
|
||||
<small> (important non-critical information)</small>
|
||||
</div>
|
||||
|
||||
<div id="{{settingsWarningId}}" class="alert alert-warning" style="display: none;">
|
||||
<span class="txt-color txt-color-warning">Warning</span>
|
||||
<small> (important non-critical information)</small>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group">
|
||||
<label for="form_system"></label>
|
||||
<select id="form_system" name="systemId" class="form-control {{selectClass}}" data-error="Choose a valid system" required/>
|
||||
<select id="form_system" name="systemId" class="{{selectClass}}" data-error="Choose a valid system" required/>
|
||||
<span class="help-block with-errors">Search system name</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -50,4 +50,9 @@
|
||||
{{/charactersData}}
|
||||
</div>
|
||||
|
||||
<div class="{{formWarningContainerClass}} alert alert-warning" style="display: none;">
|
||||
<span class="txt-color txt-color-warning">Warning</span>
|
||||
<small> (important non-critical information)</small>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="mainCharacterId" value="{{mainCharacter}}">
|
||||
@@ -53,4 +53,9 @@
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="id" value="0" />
|
||||
|
||||
<div class="{{formErrorContainerClass}} alert alert-danger" style="display: none;">
|
||||
<span class="txt-color txt-color-danger">Error</span>
|
||||
<small> (important non-critical information)</small>
|
||||
</div>
|
||||
</form>
|
||||
@@ -26,21 +26,12 @@
|
||||
</div>
|
||||
<div class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav navbar-right" role="tablist">
|
||||
<li>
|
||||
<a class="page-scroll" href="#page-top">Home</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="page-scroll" href="#pf-landing-login">Login</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="page-scroll" href="#pf-landing-map">Map</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="page-scroll" href="#pf-landing-gallery">Gallery</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="page-scroll" href="#pf-landing-contact">Contact</a>
|
||||
</li>
|
||||
<li><a class="page-scroll" data-anchor="#page-top">Home</a></li>
|
||||
<li> <a class="page-scroll" data-anchor="#pf-landing-login">Login</a></li>
|
||||
<li><a class="page-scroll" data-anchor="#pf-landing-map">Map</a></li>
|
||||
<li> <a class="page-scroll" data-anchor="#pf-landing-gallery">Gallery</a></li>
|
||||
<li> <a class="page-scroll" data-anchor="#pf-landing-pricing">Pricing</a></li>
|
||||
<li><a class="page-scroll" data-anchor="#pf-landing-contact">Contact</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -75,23 +66,25 @@
|
||||
<h2><span class="text-primary">Please</span> log in</h2>
|
||||
</div>
|
||||
</div>
|
||||
<form id="pf-login-form" class="form-horizontal" role="form" method="post" action="#">
|
||||
<form id="pf-login-form" class="" role="form" method="post" action="#">
|
||||
|
||||
<div class="row text-center m-t-lg">
|
||||
<div class="col-md-4 col-md-offset-2">
|
||||
<div class="form-group">
|
||||
<label for="userName" class="col-sm-3 control-label">Name</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text" class="form-control" id="userName" name="userName" placeholder="Your username" value="" tabindex="1" data-error="Username required" autocomplete="off" required>
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-sm-offset-3">
|
||||
<div class="form-grouppf-animate-on-visible">
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon"><i class="fa fa-fw fa-user"></i></div>
|
||||
<input type="text" class="form-control" name="userName" id="userName" placeholder="Username" autocomplete="off" tabindex="1" data-error="Username required" required>
|
||||
</div>
|
||||
<div class="help-block with-errors text-left"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="form-group">
|
||||
<label for="userPassword" class="col-sm-3 control-label">Password</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="password" class="form-control" id="userPassword" name="userPassword" placeholder="Your password" value="" tabindex="2" data-error="Password required" autocomplete="off" required>
|
||||
<div class="col-sm-3">
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-addon"><i class="fa fa-fw fa-lock"></i></div>
|
||||
<input type="password" class="form-control" name="userPassword" id="userPassword" placeholder="Password" autocomplete="off" tabindex="2" data-error="Password required" required>
|
||||
</div>
|
||||
<div class="help-block with-errors text-left"></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -99,16 +92,16 @@
|
||||
</div>
|
||||
|
||||
{* login message container*}
|
||||
<div class="row text-left m-t-lg">
|
||||
<div id="pf-login-message-container" class="col-md-8 col-md-offset-2"></div>
|
||||
<div class="row text-left">
|
||||
<div id="pf-login-message-container" class="col-sm-8 col-sm-offset-2"></div>
|
||||
</div>
|
||||
|
||||
<div class="row text-center m-t-lg">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<div class="col-sm-3 col-sm-offset-3">
|
||||
<div class="row text-center">
|
||||
<div class="col-sm-6 col-sm-offset-3">
|
||||
<div class="col-sm-4 col-sm-offset-2">
|
||||
<button class="pf-register-button btn-block btn btn-primary" tabindex="4"><i class="fa fa-fw fa-user-plus"></i> Register</button>
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
<div class="col-sm-4">
|
||||
<button class="pf-login-button btn-block btn btn-success" tabindex="3"><i class="fa fa-fw fa-sign-in"></i> Login</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -133,7 +126,7 @@
|
||||
|
||||
{* gallery *}
|
||||
<section id="pf-landing-gallery">
|
||||
<div class="container">
|
||||
<div id="pf-landing-gallery-thumb-container" class="container">
|
||||
<div class="row text-center">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<h2><span class="text-primary">Impressions and</span> Screenshots</h2>
|
||||
@@ -143,45 +136,193 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="row" id="pf-landing-gallery-thumb-container">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2 col-md-offset-2">
|
||||
<div class="form-group">
|
||||
<label for="userName" class="col-sm-2 control-label">General</label>
|
||||
<label for="userName" class="col-sm-2 control-label">Interface</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a href="http://i.imgur.com/z2jv77L.png" data-description="Logo" data-gallery="#pf-gallery">
|
||||
<a class="pf-animate-on-visible pf-animate" href="http://i.imgur.com/z2jv77L.png" data-description="Logo" data-gallery="#pf-gallery">
|
||||
<img src="http://i.imgur.com/z2jv77Ls.jpg" alt="Logo">
|
||||
</a>
|
||||
<a href="http://i.imgur.com/Cv6pXZS.png" data-description="Add system dialog" data-gallery="#pf-gallery">
|
||||
<img src="http://i.imgur.com/Cv6pXZSs.jpg" alt="Add system dialog">
|
||||
</a>
|
||||
<a href="http://i.imgur.com/6jZrIUv.png" data-description="Signature reader dialog" data-gallery="#pf-gallery">
|
||||
<img src="http://i.imgur.com/6jZrIUvs.jpg" alt="Signature reader dialog">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="row" id="pf-landing-gallery-thumb-container">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2 col-md-offset-2">
|
||||
<div class="form-group">
|
||||
<label for="userName" class="col-sm-2 control-label">Map</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a href="http://i.imgur.com/z2jv77L.png" data-description="Logo" data-gallery="#pf-gallery">
|
||||
<a class="pf-animate-on-visible pf-animate" href="http://i.imgur.com/z2jv77L.png" data-description="Logo" data-gallery="#pf-gallery">
|
||||
<img src="http://i.imgur.com/z2jv77Ls.jpg" alt="Logo">
|
||||
</a>
|
||||
<a href="http://i.imgur.com/Cv6pXZS.png" data-description="Add system dialog" data-gallery="#pf-gallery">
|
||||
<img src="http://i.imgur.com/Cv6pXZSs.jpg" alt="Add system dialog">
|
||||
</a>
|
||||
<a href="http://i.imgur.com/6jZrIUv.png" data-description="Signature reader dialog" data-gallery="#pf-gallery">
|
||||
<img src="http://i.imgur.com/6jZrIUvs.jpg" alt="Signature reader dialog">
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2 col-md-offset-2">
|
||||
<div class="form-group">
|
||||
<label for="userName" class="col-sm-2 control-label">System module</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a class="pf-animate-on-visible pf-animate" href="http://i.imgur.com/z2jv77L.png" data-description="Logo" data-gallery="#pf-gallery">
|
||||
<img src="http://i.imgur.com/z2jv77Ls.jpg" alt="Logo">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2 col-md-offset-2">
|
||||
<div class="form-group">
|
||||
<label for="userName" class="col-sm-2 control-label">Statistics module</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a class="pf-animate-on-visible pf-animate" href="http://i.imgur.com/z2jv77L.png" data-description="Logo" data-gallery="#pf-gallery">
|
||||
<img src="http://i.imgur.com/z2jv77Ls.jpg" alt="Logo">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2 col-md-offset-2">
|
||||
<div class="form-group">
|
||||
<label for="userName" class="col-sm-2 control-label">Signature module</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a class="pf-animate-on-visible pf-animate" href="http://i.imgur.com/z2jv77L.png" data-description="Logo" data-gallery="#pf-gallery">
|
||||
<img src="http://i.imgur.com/z2jv77Ls.jpg" alt="Logo">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2 col-md-offset-2">
|
||||
<div class="form-group">
|
||||
<label for="userName" class="col-sm-2 control-label">Route module</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a class="pf-animate-on-visible pf-animate" href="http://i.imgur.com/z2jv77L.png" data-description="Logo" data-gallery="#pf-gallery">
|
||||
<img src="http://i.imgur.com/z2jv77Ls.jpg" alt="Logo">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-2 col-md-offset-2">
|
||||
<div class="form-group">
|
||||
<label for="userName" class="col-sm-2 control-label">Killboard module</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a class="pf-animate-on-visible pf-animate" href="http://i.imgur.com/z2jv77L.png" data-description="Logo" data-gallery="#pf-gallery">
|
||||
<img src="http://i.imgur.com/z2jv77Ls.jpg" alt="Logo">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{* pricing *}
|
||||
<section id="pf-landing-pricing">
|
||||
<div class="container">
|
||||
<div class="row text-center">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<h2><span class="text-primary">Pricing and</span> Bundles</h2>
|
||||
<p>
|
||||
Choose the bundle that meets the requirements you need. If you just want to try out <em>PATHFINDER</em>, start with the <em>Private</em> bundle.
|
||||
This bundle will always be free of charge and is the most suitable for solo players or smaller groups.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row text-center">
|
||||
<div class="col-xs-12 col-sm-6 col-md-4 pf-landing-pricing-panel">
|
||||
<div class="panel panel-default pricing-big pf-animate pf-animate-on-visible">
|
||||
<div class="ribbon-wrapper fade"><div class="ribbon ribbon-orange">BETA</div></div>
|
||||
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Basic</h3>
|
||||
</div>
|
||||
<div class="panel-body no-padding text-align-center">
|
||||
<div class="the-price">
|
||||
<h6 class="txt-color txt-color-green">FREE</h6>
|
||||
</div>
|
||||
<div class="price-features">
|
||||
<ul class="list-unstyled text-left">
|
||||
<li><i class="fa fa-fw fa-check txt-color txt-color-green"></i> Create up to <span class="badge">3</span> private maps</li>
|
||||
<li><i class="fa fa-fw fa-check txt-color txt-color-green"></i> Share maps between up to <span class="badge">10</span> users</li>
|
||||
<li><i class="fa fa-fw fa-check txt-color txt-color-green"></i> System information module</li>
|
||||
<li><i class="fa fa-fw fa-check txt-color txt-color-green"></i> System statistics module</li>
|
||||
<li><i class="fa fa-fw fa-check txt-color txt-color-green"></i> System signature module</li>
|
||||
<li><i class="fa fa-fw fa-check txt-color txt-color-green"></i> System route module</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-footer text-align-center">
|
||||
<button class="btn btn-primary btn-block pf-register-button" role="button">Register</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-sm-6 col-md-4 pf-landing-pricing-panel">
|
||||
<div class="panel panel-primary pricing-big pf-animate pf-animate-on-visible">
|
||||
<div class="ribbon-wrapper fade"><div class="ribbon ribbon-orange">BETA</div></div>
|
||||
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Corporation</h3>
|
||||
</div>
|
||||
<div class="panel-body no-padding text-align-center">
|
||||
<div class="the-price">
|
||||
<h6 class="txt-color txt-color-tealLighter"><span class="subscript">ISK</span> 100m <span class="subscript">/mo</span></h6>
|
||||
</div>
|
||||
<div class="price-features">
|
||||
<ul class="list-unstyled text-left">
|
||||
<li><i class="fa fa-fw fa-angle-double-right"></i> All <em>public</em> features for corporation members</li>
|
||||
<li><i class="fa fa-fw fa-check txt-color txt-color-green"></i> Create up to <span class="badge">3</span> corporation maps</li>
|
||||
<li><i class="fa fa-fw fa-check txt-color txt-color-green"></i> Share corp maps between up to <span class="badge">3</span> corps</li>
|
||||
<li><i class="fa fa-fw fa-check txt-color txt-color-green"></i> System killboard module</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-footer text-align-center">
|
||||
<a href="javascript:void(0);" class="btn btn-default btn-block disabled" role="button">Apply for</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-sm-6 col-sm-offset-3 col-md-4 col-md-offset-0 pf-landing-pricing-panel">
|
||||
<div class="panel panel-primary pricing-big pf-animate pf-animate-on-visible">
|
||||
<div class="ribbon-wrapper fade"><div class="ribbon ribbon-orange">BETA</div></div>
|
||||
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Alliance</h3>
|
||||
</div>
|
||||
<div class="panel-body no-padding text-align-center">
|
||||
<div class="the-price">
|
||||
<h6 class="txt-color txt-color-tealLighter"><span class="subscript">ISK</span> 500m <span class="subscript">/mo</span></h6>
|
||||
</div>
|
||||
<div class="price-features">
|
||||
<ul class="list-unstyled text-left">
|
||||
<li><i class="fa fa-fw fa-angle-double-right"></i> All <em>public</em> features for alliance members</li>
|
||||
<li><i class="fa fa-fw fa-angle-double-right"></i> All <em>corporation</em> features for corporations</li>
|
||||
<li><i class="fa fa-fw fa-check txt-color txt-color-green"></i> Create up to <span class="badge">3</span> alliance maps</li>
|
||||
<li><i class="fa fa-fw fa-check txt-color txt-color-green"></i> Share corp maps between up to <span class="badge">2</span> alliances</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-footer text-align-center">
|
||||
<a href="javascript:void(0);" class="btn btn-default btn-block disabled" role="button">Apply for</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-info fade">
|
||||
<span class="txt-color txt-color-info">Hint</span>
|
||||
<small> During beta testing, all bundles are activated for any pilot! Enjoy testing and don´t forget to give feedback.</small>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -196,7 +337,7 @@
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row text-center m-t-lg">
|
||||
<div class="row text-center">
|
||||
<div class="col-md-4 col-md-offset-3">
|
||||
|
||||
<form class="form-horizontal" role="form" method="post" action="#">
|
||||
|
||||
@@ -20,11 +20,12 @@ $blue: #428bca;
|
||||
$blue-dark: #316490;
|
||||
|
||||
// teal
|
||||
$teal-light: #6caead;
|
||||
$teal: #568a89;
|
||||
$teal-dark: #477372;
|
||||
$teal-darker: #375959;
|
||||
$teal-darkest: #212C30;
|
||||
$teal-lightest: #6caead;
|
||||
$teal-lighter: #568a89;
|
||||
$teal: #477372;
|
||||
$teal-dark: #375959;
|
||||
$teal-darker: #212C30;
|
||||
$teal-darkest: #1b2326;
|
||||
|
||||
// green
|
||||
$green-light: #66c84f;
|
||||
@@ -80,7 +81,7 @@ $system-color-sec-0-9: #39bf99;
|
||||
$system-color-sec-1-0: #28c0bf;
|
||||
|
||||
// brand colors
|
||||
$brand-primary: $teal-darker !default;
|
||||
$brand-primary: $teal-dark !default;
|
||||
$brand-success: $green-dark !default;
|
||||
$brand-info: $blue-dark !default;
|
||||
$brand-warning: $orange !default;
|
||||
|
||||
@@ -221,7 +221,7 @@ $input-bg-disabled: $gray-lighter;
|
||||
$input-color: $gray-lighter;
|
||||
$input-border: $gray-light;
|
||||
$input-border-radius: 0px;
|
||||
$input-border-focus: $teal;
|
||||
$input-border-focus: $teal-lighter;
|
||||
|
||||
$input-color-placeholder: $gray-light;
|
||||
|
||||
@@ -362,16 +362,16 @@ $navbar-default-border: none;
|
||||
|
||||
// Navbar links
|
||||
$navbar-default-link-color: #777;
|
||||
$navbar-default-link-hover-color: $teal-light;
|
||||
$navbar-default-link-hover-color: $teal-lightest;
|
||||
$navbar-default-link-hover-bg: transparent;
|
||||
$navbar-default-link-active-color: $teal;
|
||||
$navbar-default-link-active-color: $teal-lighter;
|
||||
$navbar-default-link-active-bg: transparent;
|
||||
$navbar-default-link-disabled-color: #ccc;
|
||||
$navbar-default-link-disabled-bg: transparent;
|
||||
|
||||
// Navbar brand label
|
||||
$navbar-default-brand-color: $navbar-default-link-color;
|
||||
$navbar-default-brand-hover-color: $teal;
|
||||
$navbar-default-brand-hover-color: $teal-lighter;
|
||||
$navbar-default-brand-hover-bg: transparent;
|
||||
|
||||
// Navbar toggle
|
||||
@@ -637,19 +637,19 @@ $list-group-link-heading-color: #333;
|
||||
//
|
||||
//##
|
||||
|
||||
$panel-bg: #fff;
|
||||
$panel-bg: $gray;
|
||||
$panel-body-padding: 15px;
|
||||
$panel-border-radius: $border-radius-base;
|
||||
$panel-border-radius: 5px;
|
||||
|
||||
$panel-inner-border: #ddd;
|
||||
$panel-footer-bg: #f5f5f5;
|
||||
$panel-inner-border: $gray-dark;
|
||||
$panel-footer-bg: darken($modal-content-bg, 3%);
|
||||
|
||||
$panel-default-text: $gray-dark;
|
||||
$panel-default-border: #ddd;
|
||||
$panel-default-heading-bg: #f5f5f5;
|
||||
$panel-default-text: $gray-light;
|
||||
$panel-default-border: $gray-darkest;
|
||||
$panel-default-heading-bg: darken($modal-content-bg, 3%);
|
||||
|
||||
$panel-primary-text: #fff;
|
||||
$panel-primary-border: $brand-primary;
|
||||
$panel-primary-text: $gray-darkest;
|
||||
$panel-primary-border: $gray-darkest;
|
||||
$panel-primary-heading-bg: $brand-primary;
|
||||
|
||||
$panel-success-text: $state-success-text;
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
// Quick fix for badges in buttons
|
||||
.btn & {
|
||||
position: relative;
|
||||
top: -1px;
|
||||
top: 1px;
|
||||
}
|
||||
.btn-xs & {
|
||||
top: 0;
|
||||
|
||||
@@ -38,7 +38,8 @@
|
||||
&.active {
|
||||
outline: 0;
|
||||
background-image: none;
|
||||
@include box-shadow(inset 0 3px 5px rgba(0,0,0,.125));
|
||||
@include box-shadow(0 5px 11px 0 rgba(0, 0, 0, 0.18),0 4px 15px 0 rgba(0, 0, 0, 0.15) );
|
||||
//@include box-shadow(inset 0 3px 5px rgba(0,0,0,.125));
|
||||
}
|
||||
|
||||
&.disabled,
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
// When fading in the modal, animate it to slide down
|
||||
&.fade .modal-dialog {
|
||||
@include translate(0, -25%);
|
||||
@include transition-transform(0.3s ease-out);
|
||||
@include transition-transform(0.24s ease-out);
|
||||
}
|
||||
&.in .modal-dialog { @include translate(0, 0)}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
}
|
||||
|
||||
a {
|
||||
color: $teal-light;
|
||||
color: $teal-lightest;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,4 +7,5 @@
|
||||
@import "_images";
|
||||
@import "_dialogs";
|
||||
@import "_log";
|
||||
@import "_animation";
|
||||
@import "_animation";
|
||||
@import "_ribbon";
|
||||
@@ -150,11 +150,11 @@
|
||||
}
|
||||
|
||||
&:hover{
|
||||
border-color: $teal-darker;
|
||||
border-color: $teal-dark;
|
||||
@include box-shadow(0 6px 12px rgba(0,0,0, 0.3));
|
||||
|
||||
.pf-dialog-character-name{
|
||||
color: $teal;
|
||||
color: $teal-lighter;
|
||||
}
|
||||
|
||||
.pf-dialog-character-image{
|
||||
@@ -206,6 +206,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
// map settings dialog ====================================
|
||||
#pf-map-dialog{
|
||||
|
||||
#pf-map-dialog-user-select,
|
||||
#pf-map-dialog-corporation-select,
|
||||
#pf-map-dialog-alliance-select,{
|
||||
width: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
// map manual dialog ======================================
|
||||
#pf-manual-scrollspy{
|
||||
position: relative;
|
||||
|
||||
@@ -5,7 +5,7 @@ input, select{
|
||||
font-family: $font-family-bold;
|
||||
|
||||
&:focus{
|
||||
border-color: $teal;
|
||||
border-color: $teal-lighter;
|
||||
}
|
||||
|
||||
&:-webkit-autofill {
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
.pf-animate{
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
|
||||
// splash loading animation ============================================================================
|
||||
|
||||
.pf-color-line{
|
||||
@@ -213,10 +219,6 @@
|
||||
// Gallery --------------------------------------------------------------------
|
||||
a[data-gallery] {
|
||||
position: relative;
|
||||
margin: 5px;
|
||||
//display: none; // triggered by js
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
|
||||
img{
|
||||
border: {
|
||||
@@ -224,7 +226,8 @@ a[data-gallery] {
|
||||
style: solid;
|
||||
color: $gray-darker
|
||||
}
|
||||
width: 90px;
|
||||
margin: 5px;
|
||||
display: inline-block;
|
||||
height: 90px;
|
||||
will-change: all;
|
||||
@include border-radius(4px);
|
||||
@@ -243,7 +246,7 @@ a[data-gallery] {
|
||||
left: 0;
|
||||
height: 18px;
|
||||
width: 92px;
|
||||
margin-top: 35px;
|
||||
margin-top: 45px;
|
||||
z-index: 10;
|
||||
text-align: center;
|
||||
@include transition(transform 0.1s 0.06s ease-in, opacity 0.1s ease-out);
|
||||
@@ -254,7 +257,7 @@ a[data-gallery] {
|
||||
|
||||
&:hover{
|
||||
img{
|
||||
border-color: $teal-light;
|
||||
border-color: $teal-lightest;
|
||||
@include filter(brightness( 50% ));
|
||||
@include box-shadow(0 6px 12px rgba(0,0,0, 0.3));
|
||||
}
|
||||
@@ -269,6 +272,36 @@ a[data-gallery] {
|
||||
}
|
||||
}
|
||||
|
||||
// pricing --------------------------------------------------------------------
|
||||
.pf-landing-pricing-panel{
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.pricing-big{
|
||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.4);
|
||||
|
||||
.panel-heading{
|
||||
border-color: $gray;
|
||||
}
|
||||
.the-price {
|
||||
padding: 1px 0;
|
||||
background: darken($modal-content-bg, 6%);
|
||||
text-align: center;
|
||||
|
||||
.subscript{
|
||||
font-size: 12px;
|
||||
color: $gray-light;
|
||||
}
|
||||
}
|
||||
|
||||
.price-features {
|
||||
background: $gray;
|
||||
color: $gray-lighter;
|
||||
padding: 20px 15px;
|
||||
min-height: 182px;
|
||||
line-height: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
// content
|
||||
.pf-landing{
|
||||
@@ -277,4 +310,40 @@ a[data-gallery] {
|
||||
padding: 20px 0 40px 0;
|
||||
border-bottom: 1px solid $gray-darker;
|
||||
}
|
||||
}
|
||||
|
||||
.alert {
|
||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// TEST ---
|
||||
/*
|
||||
.form-control {
|
||||
border: 0;
|
||||
background-image: linear-gradient(#568A89,#568A89),linear-gradient(#63676A,#63676A);
|
||||
background-size: 0 2px,100% 1px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center bottom,center calc(100% - 1px);
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
.form-control:focus, .form-control.focus {
|
||||
outline: none;
|
||||
background-image: linear-gradient(#568A89,#568A89),linear-gradient(#63676A,#63676A);
|
||||
-webkit-animation: input-highlight .5s forwards;
|
||||
animation: input-highlight .5s forwards;
|
||||
box-shadow: none;
|
||||
background-size: 0 2px,100% 1px;
|
||||
}
|
||||
|
||||
@keyframes input-highlight {
|
||||
0% {
|
||||
background-size: 0 2px, 100% 1px;
|
||||
}
|
||||
100% {
|
||||
background-size: 100% 2px, 100% 1px;
|
||||
}
|
||||
}
|
||||
*/
|
||||
@@ -16,9 +16,9 @@ $logo-stroke-width: 0px;
|
||||
}
|
||||
|
||||
.logo-ploygon-top-right{
|
||||
fill: $teal-dark;
|
||||
fill: $teal;
|
||||
fill-rule: evenodd;
|
||||
stroke: $teal-dark;
|
||||
stroke: $teal;
|
||||
stroke-width: $logo-stroke-width;
|
||||
stroke-linecap: butt;
|
||||
stroke-linejoin: miter;
|
||||
@@ -38,9 +38,9 @@ $logo-stroke-width: 0px;
|
||||
}
|
||||
|
||||
.logo-ploygon-bottom-right{
|
||||
fill: $teal-darker;
|
||||
fill: $teal-dark;
|
||||
fill-rule: evenodd;
|
||||
stroke: $teal-darker;
|
||||
stroke: $teal-dark;
|
||||
stroke-width: $logo-stroke-width;
|
||||
stroke-linecap: butt;
|
||||
stroke-linejoin: miter;
|
||||
|
||||
@@ -14,13 +14,13 @@ body{
|
||||
|
||||
|
||||
a{
|
||||
color: $teal-dark;
|
||||
color: $teal;
|
||||
will-change: color;
|
||||
text-decoration: none;
|
||||
@include transition( color 0.08s ease-out );
|
||||
|
||||
&:hover{
|
||||
color: $teal-light;
|
||||
color: $teal-lightest;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,10 @@ em{
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.no-padding{
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
// help elements ====================================================
|
||||
.pf-help{
|
||||
cursor: pointer; // fallback
|
||||
@@ -78,6 +82,35 @@ em{
|
||||
will-change: opacity, transform;
|
||||
}
|
||||
|
||||
// select2 custom template ==========================================
|
||||
|
||||
.select2-results{
|
||||
[class*="col-"]{
|
||||
line-height: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
.select2{
|
||||
::-webkit-search-cancel-button{
|
||||
-webkit-appearance: none !important;
|
||||
}
|
||||
|
||||
.select2-selection__choice__remove{
|
||||
float: left;
|
||||
}
|
||||
|
||||
.select2-selection--multiple{
|
||||
input{
|
||||
box-shadow: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
::-moz-placeholder { color: $gray-light; // Firefox
|
||||
opacity: 1; } // See https://github.com/twbs/bootstrap/pull/11526
|
||||
:-ms-input-placeholder { color: $gray-light; } // Internet Explorer 10+
|
||||
::-webkit-input-placeholder { color: $gray-light; } // Safari and Chrome
|
||||
|
||||
// table styles =====================================================
|
||||
|
||||
// table icon toolbar
|
||||
@@ -226,7 +259,7 @@ em{
|
||||
}
|
||||
|
||||
.pf-map-type-global{
|
||||
color: $teal;
|
||||
color: $teal-lighter;
|
||||
}
|
||||
|
||||
// maps module ===================================================
|
||||
@@ -253,12 +286,16 @@ em{
|
||||
}
|
||||
|
||||
.pf-map-type-tab-global{
|
||||
border-top: 2px solid $teal;
|
||||
border-top: 2px solid $teal-lighter;
|
||||
}
|
||||
|
||||
.fa{
|
||||
.pf-map-tab-icon{
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.pf-map-tab-shared-icon{
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -479,8 +516,8 @@ em{
|
||||
}
|
||||
|
||||
.pf-system-status-unscanned{
|
||||
border-color: $teal !important;
|
||||
color: $teal;
|
||||
border-color: $teal-lighter !important;
|
||||
color: $teal-lighter;
|
||||
}
|
||||
|
||||
// system status within label
|
||||
@@ -507,7 +544,7 @@ em{
|
||||
}
|
||||
|
||||
&.pf-system-status-unscanned{
|
||||
background-color: $teal;
|
||||
background-color: $teal-lighter;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -541,12 +578,12 @@ em{
|
||||
}
|
||||
|
||||
&.pf-map-connection-jumpbridge{
|
||||
background-color: $teal-light;
|
||||
background-color: $teal-lightest;
|
||||
border-color: $gray;
|
||||
background: repeating-linear-gradient(
|
||||
to right,
|
||||
$teal-light,
|
||||
$teal-light 10px,
|
||||
$teal-lightest,
|
||||
$teal-lightest 10px,
|
||||
$gray 10px,
|
||||
$gray 20px
|
||||
);
|
||||
@@ -689,7 +726,7 @@ em{
|
||||
will-change: color;
|
||||
|
||||
&:focus{
|
||||
color: $teal-dark;
|
||||
color: $teal;
|
||||
|
||||
img{
|
||||
border-color: $gray;
|
||||
@@ -700,11 +737,11 @@ em{
|
||||
text-decoration: none;
|
||||
|
||||
.badge{
|
||||
color: $teal-light;
|
||||
color: $teal-lightest;
|
||||
}
|
||||
|
||||
img{
|
||||
border-color: $teal;
|
||||
border-color: $teal-lighter;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -792,10 +829,10 @@ em{
|
||||
|
||||
a{
|
||||
font-family: $font-family-bold;
|
||||
color: $teal-darker;
|
||||
color: $teal-dark;
|
||||
|
||||
&:hover{
|
||||
color: $teal-dark;
|
||||
color: $teal;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@ $mapWidth: 2500px ;
|
||||
.pf-system-body-right{
|
||||
text-overflow: ellipsis;
|
||||
float: right;
|
||||
color: $teal;
|
||||
color: $teal-lighter;
|
||||
display: none; // hover effect
|
||||
}
|
||||
// user status ===============================================
|
||||
@@ -337,7 +337,7 @@ $mapWidth: 2500px ;
|
||||
}
|
||||
|
||||
path:not(:first-child){
|
||||
stroke: $teal;
|
||||
stroke: $teal-lighter;
|
||||
}
|
||||
|
||||
&:hover{
|
||||
|
||||
58
sass/layout/_ribbon.scss
Normal file
58
sass/layout/_ribbon.scss
Normal file
@@ -0,0 +1,58 @@
|
||||
|
||||
.ribbon-wrapper {
|
||||
width: 72px;
|
||||
height: 88px;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: -3px;
|
||||
right: 7px;
|
||||
}
|
||||
|
||||
.ribbon {
|
||||
font: bold 12px $font-family-bold;
|
||||
color: $gray-darker;
|
||||
text-align: center;
|
||||
text-shadow: rgba(255,255,255,0.2) 0px 1px 0px;
|
||||
position: relative;
|
||||
padding: 3px 0;
|
||||
left: -4px;
|
||||
top: 16px;
|
||||
width: 99px;
|
||||
@include box-shadow(2px 3px 3px rgba(0,0,0,0.2));
|
||||
@include transform(rotate(45deg));
|
||||
|
||||
|
||||
&:before, &:after{
|
||||
content: "";
|
||||
border-left: 3px solid transparent;
|
||||
border-right: 3px solid transparent;
|
||||
position:absolute;
|
||||
bottom: -3px;
|
||||
}
|
||||
|
||||
|
||||
&.ribbon-green{
|
||||
background-color: $green;
|
||||
@include background-image(linear-gradient(top, darken($green, 3%), darken($green-dark, 3%)));
|
||||
|
||||
&:before, &:after{
|
||||
border-top: 3px solid darken($green-dark, 23%);
|
||||
}
|
||||
}
|
||||
|
||||
&.ribbon-orange{
|
||||
background-color: $orange;
|
||||
@include background-image(linear-gradient(top, darken($orange, 3%), darken($orange-dark, 3%)));
|
||||
|
||||
&:before, &:after{
|
||||
border-top: 3px solid darken($orange-dark, 18%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ribbon:before {
|
||||
left: 0;
|
||||
}
|
||||
.ribbon:after {
|
||||
right: 0;
|
||||
}
|
||||
@@ -45,9 +45,30 @@
|
||||
// signature table module ===================================================
|
||||
.pf-sig-table-module{
|
||||
|
||||
// delete signature button
|
||||
.pf-sig-table-clear-button{
|
||||
will-change: opacity, transform;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.pf-sig-table{
|
||||
font-size: 10px;
|
||||
|
||||
.pf-sig-table-edit-desc-text{
|
||||
white-space: normal;
|
||||
|
||||
&.editable-empty{
|
||||
border-bottom: none;
|
||||
@extend .pf-dialog-icon-button;
|
||||
}
|
||||
}
|
||||
|
||||
// textarea field
|
||||
.pf-editable-description{
|
||||
background-color: $gray-darker;
|
||||
max-height: 50px;
|
||||
}
|
||||
|
||||
.pf-sig-table-action-cell{
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -182,7 +203,7 @@
|
||||
z-index: 10;
|
||||
left: -25px;
|
||||
top: 15px;
|
||||
color: $teal-dark;
|
||||
color: $teal;
|
||||
opacity: 0;
|
||||
will-change: opacity, left;
|
||||
@include transition(all 0.12s ease-out);
|
||||
@@ -192,7 +213,7 @@
|
||||
margin-left: 20px;
|
||||
|
||||
.pf-system-killboard-img-ship{
|
||||
border-color: $teal;
|
||||
border-color: $teal-lighter;
|
||||
}
|
||||
|
||||
&:before{
|
||||
|
||||
@@ -67,6 +67,7 @@
|
||||
float: left;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
will-change: all;
|
||||
-webkit-transition-timing-function: cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
||||
-moz-transition-timing-function: cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
||||
-ms-transition-timing-function: cubic-bezier(0.645, 0.045, 0.355, 1.000);
|
||||
|
||||
@@ -23,7 +23,7 @@ table.dataTable thead th.sorting_desc:after {
|
||||
}
|
||||
|
||||
table.dataTable thead th:after {
|
||||
color: $teal;
|
||||
color: $teal-lighter;
|
||||
}
|
||||
|
||||
table.dataTable thead th.sorting:after {
|
||||
|
||||
106
sass/library/data-tables/_dataTables-responsive.scss
Normal file
106
sass/library/data-tables/_dataTables-responsive.scss
Normal file
@@ -0,0 +1,106 @@
|
||||
table.dataTable.dtr-inline.collapsed > tbody > tr > td:first-child,
|
||||
table.dataTable.dtr-inline.collapsed > tbody > tr > th:first-child {
|
||||
position: relative;
|
||||
padding-left: 30px;
|
||||
cursor: pointer;
|
||||
}
|
||||
table.dataTable.dtr-inline.collapsed > tbody > tr > td:first-child:before,
|
||||
table.dataTable.dtr-inline.collapsed > tbody > tr > th:first-child:before {
|
||||
top: 8px;
|
||||
left: 4px;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
display: block;
|
||||
position: absolute;
|
||||
color: white;
|
||||
border: 2px solid white;
|
||||
border-radius: 16px;
|
||||
text-align: center;
|
||||
line-height: 14px;
|
||||
box-shadow: 0 0 3px #444;
|
||||
box-sizing: content-box;
|
||||
content: '+';
|
||||
background-color: #31b131;
|
||||
}
|
||||
table.dataTable.dtr-inline.collapsed > tbody > tr > td:first-child.dataTables_empty:before,
|
||||
table.dataTable.dtr-inline.collapsed > tbody > tr > th:first-child.dataTables_empty:before {
|
||||
display: none;
|
||||
}
|
||||
table.dataTable.dtr-inline.collapsed > tbody > tr.parent > td:first-child:before,
|
||||
table.dataTable.dtr-inline.collapsed > tbody > tr.parent > th:first-child:before {
|
||||
content: '-';
|
||||
background-color: #d33333;
|
||||
}
|
||||
table.dataTable.dtr-inline.collapsed > tbody > tr.child td:before {
|
||||
display: none;
|
||||
}
|
||||
table.dataTable.dtr-inline.collapsed.compact > tbody > tr > td:first-child,
|
||||
table.dataTable.dtr-inline.collapsed.compact > tbody > tr > th:first-child {
|
||||
padding-left: 27px;
|
||||
}
|
||||
table.dataTable.dtr-inline.collapsed.compact > tbody > tr > td:first-child:before,
|
||||
table.dataTable.dtr-inline.collapsed.compact > tbody > tr > th:first-child:before {
|
||||
top: 5px;
|
||||
left: 4px;
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
border-radius: 14px;
|
||||
line-height: 12px;
|
||||
}
|
||||
table.dataTable.dtr-column > tbody > tr > td.control,
|
||||
table.dataTable.dtr-column > tbody > tr > th.control {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
}
|
||||
table.dataTable.dtr-column > tbody > tr > td.control:before,
|
||||
table.dataTable.dtr-column > tbody > tr > th.control:before {
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
margin-top: -10px;
|
||||
margin-left: -10px;
|
||||
display: block;
|
||||
position: absolute;
|
||||
color: white;
|
||||
border: 2px solid white;
|
||||
border-radius: 16px;
|
||||
text-align: center;
|
||||
line-height: 14px;
|
||||
box-shadow: 0 0 3px #444;
|
||||
box-sizing: content-box;
|
||||
content: '+';
|
||||
background-color: #31b131;
|
||||
}
|
||||
table.dataTable.dtr-column > tbody > tr.parent td.control:before,
|
||||
table.dataTable.dtr-column > tbody > tr.parent th.control:before {
|
||||
content: '-';
|
||||
background-color: #d33333;
|
||||
}
|
||||
table.dataTable > tbody > tr.child {
|
||||
padding: 0.5em 1em;
|
||||
}
|
||||
table.dataTable > tbody > tr.child:hover {
|
||||
background: transparent !important;
|
||||
}
|
||||
table.dataTable > tbody > tr.child ul {
|
||||
display: inline-block;
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
table.dataTable > tbody > tr.child ul li {
|
||||
border-bottom: 1px solid #efefef;
|
||||
padding: 0.5em 0;
|
||||
}
|
||||
table.dataTable > tbody > tr.child ul li:first-child {
|
||||
padding-top: 0;
|
||||
}
|
||||
table.dataTable > tbody > tr.child ul li:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
table.dataTable > tbody > tr.child span.dtr-title {
|
||||
display: inline-block;
|
||||
min-width: 75px;
|
||||
font-weight: bold;
|
||||
}
|
||||
@@ -57,7 +57,7 @@ table.dataTable tbody tr {
|
||||
background-color: darken($gray-darker, 4%);
|
||||
}
|
||||
table.dataTable tbody tr.selected {
|
||||
background-color: #b0bed9;
|
||||
background-color: $teal-darkest;
|
||||
}
|
||||
table.dataTable tbody th,
|
||||
table.dataTable tbody td {
|
||||
@@ -87,7 +87,7 @@ table.dataTable.stripe tbody tr.odd, table.dataTable.display tbody tr.odd {
|
||||
background-color: $gray-darker;
|
||||
}
|
||||
table.dataTable.stripe tbody tr.odd.selected, table.dataTable.display tbody tr.odd.selected {
|
||||
background-color: #abb9d3;
|
||||
background-color: $teal-darkest;
|
||||
}
|
||||
table.dataTable.hover tbody tr:hover,
|
||||
table.dataTable.hover tbody tr.odd:hover,
|
||||
@@ -111,7 +111,7 @@ table.dataTable.hover tbody tr.odd:hover.selected,
|
||||
table.dataTable.hover tbody tr.even:hover.selected, table.dataTable.display tbody tr:hover.selected,
|
||||
table.dataTable.display tbody tr.odd:hover.selected,
|
||||
table.dataTable.display tbody tr.even:hover.selected {
|
||||
background-color: #a9b7d1;
|
||||
background-color: $orange-dark;
|
||||
}
|
||||
table.dataTable.order-column tbody tr > .sorting_1,
|
||||
table.dataTable.order-column tbody tr > .sorting_2,
|
||||
@@ -128,7 +128,7 @@ table.dataTable.display tbody tr.selected > .sorting_3 {
|
||||
background-color: #acbad4;
|
||||
}
|
||||
table.dataTable.display tbody tr.odd > .sorting_1, table.dataTable.order-column.stripe tbody tr.odd > .sorting_1 {
|
||||
background-color: $teal-darkest;
|
||||
background-color: $teal-darker;
|
||||
}
|
||||
table.dataTable.display tbody tr.odd > .sorting_2, table.dataTable.order-column.stripe tbody tr.odd > .sorting_2 {
|
||||
background-color: #f3f3f3;
|
||||
@@ -137,7 +137,7 @@ table.dataTable.display tbody tr.odd > .sorting_3, table.dataTable.order-column.
|
||||
background-color: whitesmoke;
|
||||
}
|
||||
table.dataTable.display tbody tr.odd.selected > .sorting_1, table.dataTable.order-column.stripe tbody tr.odd.selected > .sorting_1 {
|
||||
background-color: #a6b3cd;
|
||||
background-color: darken($teal-darkest, 2%);
|
||||
}
|
||||
table.dataTable.display tbody tr.odd.selected > .sorting_2, table.dataTable.order-column.stripe tbody tr.odd.selected > .sorting_2 {
|
||||
background-color: #a7b5ce;
|
||||
@@ -146,7 +146,7 @@ table.dataTable.display tbody tr.odd.selected > .sorting_3, table.dataTable.orde
|
||||
background-color: #a9b6d0;
|
||||
}
|
||||
table.dataTable.display tbody tr.even > .sorting_1, table.dataTable.order-column.stripe tbody tr.even > .sorting_1 {
|
||||
background-color: $teal-darkest;
|
||||
background-color: $teal-darker;
|
||||
}
|
||||
table.dataTable.display tbody tr.even > .sorting_2, table.dataTable.order-column.stripe tbody tr.even > .sorting_2 {
|
||||
background-color: #fbfbfb;
|
||||
@@ -155,7 +155,7 @@ table.dataTable.display tbody tr.even > .sorting_3, table.dataTable.order-column
|
||||
background-color: #fdfdfd;
|
||||
}
|
||||
table.dataTable.display tbody tr.even.selected > .sorting_1, table.dataTable.order-column.stripe tbody tr.even.selected > .sorting_1 {
|
||||
background-color: #acbad4;
|
||||
background-color: darken($teal-darkest, 2%);
|
||||
}
|
||||
table.dataTable.display tbody tr.even.selected > .sorting_2, table.dataTable.order-column.stripe tbody tr.even.selected > .sorting_2 {
|
||||
background-color: #adbbd6;
|
||||
@@ -189,7 +189,7 @@ table.dataTable.display tbody tr.odd:hover.selected > .sorting_1,
|
||||
table.dataTable.display tbody tr.even:hover.selected > .sorting_1, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_1,
|
||||
table.dataTable.order-column.hover tbody tr.odd:hover.selected > .sorting_1,
|
||||
table.dataTable.order-column.hover tbody tr.even:hover.selected > .sorting_1 {
|
||||
background-color: #a1aec7;
|
||||
background-color: darken($orange-dark, 2%);
|
||||
}
|
||||
table.dataTable.display tbody tr:hover.selected > .sorting_2,
|
||||
table.dataTable.display tbody tr.odd:hover.selected > .sorting_2,
|
||||
|
||||
@@ -2,14 +2,19 @@
|
||||
// styles for drag-select
|
||||
|
||||
div.pf-map-drag-to-select {
|
||||
background: $teal-darker;
|
||||
display: none; // triggered by js
|
||||
opacity: 0.3;
|
||||
background: $teal-dark !important;
|
||||
display: block;
|
||||
visibility: hidden; // triggered by js
|
||||
opacity: 0; // triggered by js
|
||||
z-index: 9000;
|
||||
border: 1px dashed $gray-lighter;
|
||||
will-change: opacity, visibility;
|
||||
@include border-radius(5px);
|
||||
@include transition(opacity 0.15s linear, visibility 0.15s linear);
|
||||
|
||||
&.active {
|
||||
display: block;
|
||||
visibility: visible;
|
||||
opacity: 0.3;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
14
sass/library/select2/_core.scss
vendored
14
sass/library/select2/_core.scss
vendored
@@ -33,5 +33,15 @@
|
||||
filter: alpha(opacity=0);
|
||||
}
|
||||
|
||||
@import "theme/default/_layout";
|
||||
@import "theme/classic/_layout";
|
||||
.select2-hidden-accessible {
|
||||
border: 0;
|
||||
clip: rect(0 0 0 0);
|
||||
height: 1px;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
@import "theme/pathfinder/_layout";
|
||||
|
||||
22
sass/library/select2/_dropdown.scss
vendored
22
sass/library/select2/_dropdown.scss
vendored
@@ -1,14 +1,19 @@
|
||||
.select2-dropdown {
|
||||
background-color: $gray-dark;
|
||||
border: 1px solid $gray-light;
|
||||
background-color: white;
|
||||
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
|
||||
box-sizing: border-box;
|
||||
|
||||
display: block;
|
||||
|
||||
position: absolute;
|
||||
left: -100000px;
|
||||
|
||||
width: 100%;
|
||||
z-index: 1500;
|
||||
@include box-shadow(0 6px 12px rgba(0,0,0, 0.3));
|
||||
|
||||
z-index: 1051;
|
||||
}
|
||||
|
||||
.select2-results {
|
||||
@@ -23,8 +28,7 @@
|
||||
|
||||
.select2-results__option {
|
||||
padding: 6px;
|
||||
font-family: $font-family-bold;
|
||||
font-size: 10px;
|
||||
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
|
||||
@@ -47,7 +51,6 @@
|
||||
border-top: none;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
border-color: $teal;
|
||||
}
|
||||
|
||||
.select2-search--dropdown {
|
||||
@@ -57,6 +60,11 @@
|
||||
.select2-search__field {
|
||||
padding: 4px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
&::-webkit-search-cancel-button {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.select2-search--hide {
|
||||
|
||||
6
sass/library/select2/_multiple.scss
vendored
6
sass/library/select2/_multiple.scss
vendored
@@ -14,6 +14,7 @@
|
||||
overflow: hidden;
|
||||
padding-left: 8px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +22,13 @@
|
||||
float: left;
|
||||
|
||||
.select2-search__field {
|
||||
box-sizing: border-box;
|
||||
border: none;
|
||||
font-size: 100%;
|
||||
margin-top: 5px;
|
||||
|
||||
&::-webkit-search-cancel-button {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
4
sass/library/select2/_single.scss
vendored
4
sass/library/select2/_single.scss
vendored
@@ -11,10 +11,12 @@
|
||||
|
||||
.select2-selection__rendered {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
padding-left: 8px;
|
||||
padding-right: 20px;
|
||||
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
98
sass/library/select2/theme/default/_layout.scss
vendored
98
sass/library/select2/theme/default/_layout.scss
vendored
@@ -1,98 +0,0 @@
|
||||
.select2-container--default {
|
||||
@import "single";
|
||||
@import "multiple";
|
||||
|
||||
&.select2-container--open.select2-container--above {
|
||||
.select2-selection--single, .select2-selection--multiple {
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.select2-container--open.select2-container--below {
|
||||
.select2-selection--single, .select2-selection--multiple {
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
@include transition( border-color 0.3s ease-out );
|
||||
border-color: $teal;
|
||||
}
|
||||
}
|
||||
|
||||
.select2-search--dropdown {
|
||||
.select2-search__field {
|
||||
border: 1px solid $gray-light;
|
||||
}
|
||||
}
|
||||
|
||||
.select2-search--inline {
|
||||
.select2-search__field {
|
||||
background: transparent;
|
||||
border: none;
|
||||
outline: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.select2-results > .select2-results__options {
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.select2-results__option {
|
||||
&[role=group] {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&[aria-disabled=true] {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
&[aria-selected=true] {
|
||||
background-color: $teal-darker;
|
||||
color: $gray-lightest;
|
||||
}
|
||||
|
||||
.select2-results__option {
|
||||
padding-left: 1em;
|
||||
|
||||
.select2-results__group {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.select2-results__option {
|
||||
margin-left: -1em;
|
||||
padding-left: 2em;
|
||||
|
||||
.select2-results__option {
|
||||
margin-left: -2em;
|
||||
padding-left: 3em;
|
||||
|
||||
.select2-results__option {
|
||||
margin-left: -3em;
|
||||
padding-left: 4em;
|
||||
|
||||
.select2-results__option {
|
||||
margin-left: -4em;
|
||||
padding-left: 5em;
|
||||
|
||||
.select2-results__option {
|
||||
margin-left: -5em;
|
||||
padding-left: 6em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.select2-results__option--highlighted[aria-selected] {
|
||||
background-color: $gray-lighter;
|
||||
color: $gray-darker;
|
||||
}
|
||||
|
||||
.select2-results__group {
|
||||
cursor: default;
|
||||
display: block;
|
||||
padding: 6px;
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
.select2-selection--multiple {
|
||||
background-color: $gray-dark;
|
||||
border: 1px solid $gray-light;
|
||||
border-radius: 4px;
|
||||
cursor: text;
|
||||
|
||||
.select2-selection__rendered {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0 5px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.select2-selection__placeholder {
|
||||
color: $gray-light;
|
||||
|
||||
margin-top: 5px;
|
||||
|
||||
float: left;
|
||||
}
|
||||
|
||||
.select2-selection__clear {
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
font-weight: bold;
|
||||
margin-top: 5px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.select2-selection__choice {
|
||||
background-color: $gray-lighter;
|
||||
color: $gray-darker;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
cursor: default;
|
||||
|
||||
float: left;
|
||||
|
||||
margin-right: 5px;
|
||||
margin-top: 5px;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.select2-selection__choice__remove {
|
||||
color: $red-darker;
|
||||
cursor: pointer;
|
||||
|
||||
display: inline-block;
|
||||
font-weight: bold;
|
||||
|
||||
margin-right: 2px;
|
||||
|
||||
&:hover {
|
||||
color: #333;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&[dir="rtl"] {
|
||||
.select2-selection--multiple {
|
||||
.select2-selection__choice, .select2-selection__placeholder {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.select2-selection__choice {
|
||||
margin-left: 5px;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.select2-selection__choice__remove {
|
||||
margin-left: 2px;
|
||||
margin-right: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.select2-container--disabled {
|
||||
.select2-selection--multiple {
|
||||
background-color: #eee;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.select2-selection__choice__remove {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
85
sass/library/select2/theme/default/_single.scss
vendored
85
sass/library/select2/theme/default/_single.scss
vendored
@@ -1,85 +0,0 @@
|
||||
.select2-selection--single {
|
||||
background-color: $gray-dark;
|
||||
border: 1px solid $gray-light;
|
||||
border-radius: 0px;
|
||||
|
||||
.select2-selection__rendered {
|
||||
color: $gray-lighter;
|
||||
line-height: 28px;
|
||||
font-family: $font-family-bold;
|
||||
}
|
||||
|
||||
.select2-selection__clear {
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
font-weight: bold;
|
||||
color: $red-darker;
|
||||
}
|
||||
|
||||
.select2-selection__placeholder {
|
||||
color: $gray-light;
|
||||
}
|
||||
|
||||
.select2-selection__arrow {
|
||||
height: 26px;
|
||||
|
||||
position: absolute;
|
||||
|
||||
top: 1px;
|
||||
right: 1px;
|
||||
|
||||
width: 20px;
|
||||
|
||||
b {
|
||||
border-color: #888 transparent transparent transparent;
|
||||
border-style: solid;
|
||||
border-width: 5px 4px 0 4px;
|
||||
|
||||
height: 0;
|
||||
left: 50%;
|
||||
|
||||
margin-left: -4px;
|
||||
margin-top: -2px;
|
||||
|
||||
position: absolute;
|
||||
|
||||
top: 50%;
|
||||
width: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&[dir="rtl"] {
|
||||
.select2-selection--single {
|
||||
.select2-selection__clear {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.select2-selection__arrow {
|
||||
left: 1px;
|
||||
right: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.select2-container--disabled {
|
||||
.select2-selection--single {
|
||||
background-color: #eee;
|
||||
cursor: default;
|
||||
|
||||
.select2-selection__clear {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.select2-container--open {
|
||||
.select2-selection--single {
|
||||
.select2-selection__arrow {
|
||||
b {
|
||||
border-color: transparent transparent #888 transparent;
|
||||
border-width: 0 4px 5px 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,18 @@
|
||||
$remove-color: #888 !default;
|
||||
$remove-hover-color: #555 !default;
|
||||
$remove-color: $red-darker !default;
|
||||
$remove-hover-color: $red-darkest !default;
|
||||
$remove-width: 20px !default;
|
||||
|
||||
$selection-color: #444 !default;
|
||||
|
||||
$border-color: #aaa !default;
|
||||
$border-radius: 4px !default;
|
||||
$border-color: $gray-light !default;
|
||||
$border-radius: 0px !default;
|
||||
$border-radius-choice: 4px !default;
|
||||
|
||||
$focus-border-color: $gray-lighter !default;
|
||||
$focus-border-color: $teal-lighter !default;
|
||||
|
||||
$container-height: 28px !default;
|
||||
|
||||
$selection-bg-top-color: white !default;
|
||||
$selection-bg-top-color: $gray-dark !default;
|
||||
$selection-bg-bottom-color: #eeeeee !default;
|
||||
|
||||
$container-placeholder-color: #999 !default;
|
||||
@@ -28,7 +29,7 @@ $dropdown-bg-color: $selection-bg-top-color !default;
|
||||
$results-max-height: 200px !default;
|
||||
$results-nested-padding: 20px !default;
|
||||
|
||||
$results-choice-bg-hover-color: #3875d7 !default;
|
||||
$results-choice-fg-hover-color: $gray-darker !default;
|
||||
$results-choice-bg-hover-color: $gray-lighter !default;
|
||||
$results-choice-fg-hover-color: $gray-dark !default;
|
||||
|
||||
$results-choice-fg-unselectable-color: grey !default;
|
||||
@@ -1,7 +1,7 @@
|
||||
@import "defaults";
|
||||
@import "../../mixins/gradients";
|
||||
|
||||
.select2-container--classic {
|
||||
.select2-container--pathfinder {
|
||||
@import "single";
|
||||
@import "multiple";
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
.select2-dropdown {
|
||||
background-color: $dropdown-bg-color;
|
||||
border: 1px solid transparent;
|
||||
overflow: hidden;
|
||||
@include box-shadow(0 6px 12px rgba(0,0,0, 0.3));
|
||||
}
|
||||
|
||||
.select2-dropdown--above {
|
||||
@@ -61,3 +63,8 @@
|
||||
border-color: $focus-border-color;
|
||||
}
|
||||
}
|
||||
|
||||
// hide small "arrow" for hidden select elements
|
||||
select.select2-hidden-accessible{
|
||||
@include appearance( none );
|
||||
}
|
||||
@@ -1,11 +1,9 @@
|
||||
.select2-selection--multiple {
|
||||
background-color: white;
|
||||
|
||||
background-color: $gray-dark;
|
||||
color: $gray-dark;
|
||||
border: 1px solid $border-color;
|
||||
border-radius: $border-radius;
|
||||
|
||||
cursor: text;
|
||||
|
||||
outline: 0;
|
||||
|
||||
&:focus {
|
||||
@@ -24,14 +22,10 @@
|
||||
|
||||
.select2-selection__choice {
|
||||
background-color: $gray-lighter;
|
||||
|
||||
border: 1px solid $border-color;
|
||||
border-radius: $border-radius;
|
||||
|
||||
border-radius: $border-radius-choice;
|
||||
cursor: default;
|
||||
|
||||
float: left;
|
||||
|
||||
margin-right: 5px;
|
||||
margin-top: 5px;
|
||||
padding: 0 5px;
|
||||
@@ -40,10 +34,8 @@
|
||||
.select2-selection__choice__remove {
|
||||
color: $remove-color;
|
||||
cursor: pointer;
|
||||
|
||||
display: inline-block;
|
||||
font-weight: bold;
|
||||
|
||||
margin-right: 2px;
|
||||
|
||||
&:hover {
|
||||
@@ -1,51 +1,48 @@
|
||||
.select2-selection--single {
|
||||
background-color: $gray-dark;
|
||||
|
||||
border: 1px solid $border-color;
|
||||
border-radius: $border-radius;
|
||||
|
||||
outline: 0;
|
||||
|
||||
@include gradient-vertical($selection-bg-top-color, $selection-bg-bottom-color, 50%, 100%);
|
||||
|
||||
&:focus {
|
||||
border: 1px solid $focus-border-color;
|
||||
}
|
||||
|
||||
.select2-selection__rendered {
|
||||
color: #444;
|
||||
color: $gray-lighter;
|
||||
line-height: 28px;
|
||||
}
|
||||
|
||||
.select2-selection__clear {
|
||||
color: $remove-color;
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
font-weight: bold;
|
||||
margin-right: 10px;
|
||||
margin-right: 3px;
|
||||
margin-left: 10px;
|
||||
|
||||
&:hover {
|
||||
color: $remove-hover-color;
|
||||
}
|
||||
}
|
||||
|
||||
.select2-selection__placeholder {
|
||||
color: $gray-light;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.select2-selection__arrow {
|
||||
background-color: #ddd;
|
||||
|
||||
background-color: $gray-dark;
|
||||
border: none;
|
||||
border-left: 1px solid $border-color;
|
||||
border-left: none;
|
||||
border-top-right-radius: $border-radius;
|
||||
border-bottom-right-radius: $border-radius;
|
||||
|
||||
height: 26px;
|
||||
|
||||
position: absolute;
|
||||
|
||||
top: 1px;
|
||||
right: 1px;
|
||||
|
||||
width: 20px;
|
||||
|
||||
@include gradient-vertical(#eeeeee, #cccccc, 50%, 100%);
|
||||
|
||||
b {
|
||||
border-color: #888 transparent transparent transparent;
|
||||
@@ -107,8 +104,6 @@
|
||||
border-top: none;
|
||||
border-top-left-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
|
||||
@include gradient-vertical($selection-opened-bg-bottom-color, $selection-opened-bg-top-color, 0%, 50%);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,8 +112,6 @@
|
||||
border-bottom: none;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
|
||||
@include gradient-vertical($selection-opened-bg-top-color, $selection-opened-bg-bottom-color, 50%, 100%);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,7 +167,7 @@
|
||||
a.editable-click,
|
||||
a.editable-click:hover {
|
||||
text-decoration: none;
|
||||
border-bottom: dashed 1px $teal;
|
||||
border-bottom: dashed 1px $teal-lighter;
|
||||
}
|
||||
|
||||
.editable-click.editable-disabled,
|
||||
|
||||
@@ -30,13 +30,15 @@
|
||||
@import "library/data-tables/_dataTables-tableTools"; // DataTables 1.10.3 tableTools extension
|
||||
//@import "library/data-tables/_dataTables-bootstrap"; // DataTables 1.10.3 bootsrap integration
|
||||
@import "library/data-tables/_dataTables-fontAwesome"; // DataTables 1.10.3 fontAwesome support (sort icons)
|
||||
@import "library/data-tables/_dataTables-responsive"; // DataTables 1.10.3 fontAwesome support (sort icons)
|
||||
|
||||
|
||||
@import "library/x-editable/_bootstrap-editable"; // X-editable - v1.5.0
|
||||
@import "library/pnotify/_pnotify.core"; // PNotify styles
|
||||
@import "library/slidebars/_slidebars"; // Slidebars Navigation
|
||||
@import "library/easy-pie-chart/_easyPieChart"; // Easy Pie Chart 2.1.6
|
||||
@import "library/drag-to-select/_dragToSelect"; // Drag to Select 1.1
|
||||
@import "library/select2/_core"; // Select2 4.0.0 Beta2
|
||||
@import "library/select2/_core"; // Select2 4.0.0
|
||||
@import "library/blue-imp-gallery/_blueimp-gallery"; // Blue Imp Gallery
|
||||
@import "library/blue-imp-gallery/_bootstrap-image-gallery"; // Blue Imp Gallery Bootstrap
|
||||
|
||||
@@ -45,6 +47,8 @@
|
||||
@import "smartadmin/main";
|
||||
@import "smartadmin/main-colorpallet";
|
||||
|
||||
|
||||
|
||||
// my modules
|
||||
@import "layout/all";
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
&.txt-color-lighten { color: $lighten !important; }
|
||||
&.txt-color-white { color: $white !important; }
|
||||
&.txt-color-magenta { color: $magenta !important; }
|
||||
&.txt-color-teal { color: $teal !important; }
|
||||
&.txt-color-tealLighter { color: $teal-lighter !important; }
|
||||
|
||||
&.txt-color-primary { color: $brand-primary !important; }
|
||||
&.txt-color-success { color: $brand-success !important; }
|
||||
@@ -57,6 +57,6 @@
|
||||
&.bg-color-white { background-color: $white !important; }
|
||||
&.bg-color-grayDark { background-color: $greyDark !important; }
|
||||
&.bg-color-magenta { background-color: $magenta !important; }
|
||||
&.bg-color-teal { background-color: $teal !important; }
|
||||
&.bg-color-tealLighter{ background-color: $teal-lighter !important; }
|
||||
&.bg-color-redLight { background-color: $redLight !important; }
|
||||
}
|
||||
|
||||
@@ -556,9 +556,9 @@ input[type="text"],
|
||||
input[type="password"],
|
||||
input[type="email"]{
|
||||
&:focus + .input-group-addon {
|
||||
border-color: $teal;
|
||||
border-color: $teal-lighter;
|
||||
//background-color: lighten($state-info-text, 23%);
|
||||
color: $teal;
|
||||
color: $teal-lighter;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1288,13 +1288,13 @@ input[type="email"]{
|
||||
*/
|
||||
will-change: all;
|
||||
@include border-radius(2px);
|
||||
@include transition( all 0.06s ease-out );
|
||||
@include box-shadow(0 1px 3px 0 rgba(red($black), green($black), blue($black), 0.12), 0 1px 2px 0 rgba(red($black), green($black), blue($black), 0.24));
|
||||
@include transition( all 0.06s linear );
|
||||
//@include box-shadow(0 1px 3px 0 rgba(red($black), green($black), blue($black), 0.12), 0 1px 2px 0 rgba(red($black), green($black), blue($black), 0.24));
|
||||
}
|
||||
.btn:active {
|
||||
position:relative;
|
||||
top:1px;
|
||||
left:1px;
|
||||
//top:1px;
|
||||
//left:1px;
|
||||
}
|
||||
|
||||
.btn.btn-ribbon {
|
||||
@@ -1416,11 +1416,11 @@ input[type="email"]{
|
||||
}
|
||||
}
|
||||
.panel-teal {
|
||||
border-color: $teal;
|
||||
border-color: $teal-lighter;
|
||||
& > .panel-heading {
|
||||
color: $white;
|
||||
background-color: $teal;
|
||||
border-color: $teal;
|
||||
background-color: $teal-lighter;
|
||||
border-color: $teal-lighter;
|
||||
}
|
||||
}
|
||||
.panel-orange {
|
||||
@@ -1480,7 +1480,7 @@ input[type="email"]{
|
||||
border-radius: 50%;
|
||||
-moz-border-radius: 50%;
|
||||
-webkit-border-radius: 50%;
|
||||
@include box-shadow(none !important);
|
||||
@include box-shadow(0 1px 6px 0 rgba(0, 0, 0, 0.12),0 1px 6px 0 rgba(0, 0, 0, 0.12));
|
||||
}
|
||||
.btn-circle.btn-sm {
|
||||
width: 22px;
|
||||
@@ -1541,8 +1541,19 @@ input[type="email"]{
|
||||
* buttons with labels
|
||||
*/
|
||||
|
||||
.btn-label {position: relative;left: -12px;display: inline-block;padding: 6px 12px;background: rgba(red($black), green($black), blue($black),0.15);border-radius: 3px 0 0 3px;}
|
||||
.btn-labeled {padding-top: 0;padding-bottom: 0;}
|
||||
.btn-label {
|
||||
position: relative;
|
||||
left: -8px;
|
||||
display: inline-block;
|
||||
padding: 5px 8px;
|
||||
background: rgba(red($black), green($black), blue($black), 0.15);
|
||||
border-radius: 3px 0 0 3px;
|
||||
}
|
||||
|
||||
.btn-labeled {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.btn-link {
|
||||
box-shadow: none;
|
||||
@@ -1560,7 +1571,7 @@ input[type="email"]{
|
||||
padding: 5px;
|
||||
color: #666;
|
||||
background: rgba(red( $gray-darkest), green($gray-darkest), blue($gray-darkest), 0.9);
|
||||
border: solid 2px $teal-darker;
|
||||
border: solid 2px $teal-dark;
|
||||
font-family: 'Oxygen Bold';
|
||||
font-size: 10px;
|
||||
text-align: left;
|
||||
|
||||
Reference in New Issue
Block a user