Merge branch 'saas-dev-publishing' of github.com:sourcefabric/airtime into saas-dev-publishing

This commit is contained in:
Duncan Sommerville 2015-09-15 14:21:27 -04:00
commit a444751397
13 changed files with 543 additions and 37 deletions

View File

@ -0,0 +1,30 @@
<?php
/**
* Created by PhpStorm.
* User: asantoni
* Date: 11/09/15
* Time: 2:47 PM
*/
class AirtimeTableView {
private static function _getTableJavaScriptDependencies() {
return ['js/airtime/widgets/table.js',
'js/datatables/js/jquery.dataTables.js',
'js/datatables/plugin/dataTables.pluginAPI.js',
'js/datatables/plugin/dataTables.fnSetFilteringDelay.js',
'js/datatables/plugin/dataTables.ColVis.js',
'js/datatables/plugin/dataTables.colReorder.min.js?',
'js/datatables/plugin/dataTables.FixedColumns.js',
'js/datatables/plugin/dataTables.FixedHeader.js',
'js/datatables/plugin/dataTables.columnFilter.js?'];
}
public static function injectTableJavaScriptDependencies(&$headScript, $baseUrl, $airtimeVersion)
{
$deps = self::_getTableJavaScriptDependencies();
for ($i = 0; $i < count($deps); $i++) {
$headScript->appendFile($baseUrl . $deps[$i] .'?'. $airtimeVersion, 'text/javascript');
}
}
}

View File

@ -1,5 +1,7 @@
<?php
require_once(__DIR__.'/../common/widgets/Table.php');
class DashboardController extends Zend_Controller_Action
{
@ -117,4 +119,17 @@ class DashboardController extends Zend_Controller_Action
$this->view->airtime_version = Application_Model_Preference::GetAirtimeVersion();
}
public function tableTestAction()
{
Zend_Layout::getMvcInstance()->assign('parent_page', 'Help');
$CC_CONFIG = Config::getConfig();
$baseUrl = Application_Common_OsPath::getBaseDir();
$headScript = $this->view->headScript();
AirtimeTableView::injectTableJavaScriptDependencies($headScript, $baseUrl, $CC_CONFIG['airtime_version']);
$this->view->headScript()->appendFile($baseUrl.'js/airtime/widgets/table-example.js?'.$CC_CONFIG['airtime_version']);
}
}

View File

@ -46,6 +46,7 @@ class PodcastTableMap extends TableMap
$this->addColumn('description', 'DbDescription', 'VARCHAR', false, 512, null);
$this->addColumn('auto_ingest', 'DbAutoIngest', 'BOOLEAN', true, null, false);
$this->addForeignKey('owner', 'DbOwner', 'INTEGER', 'cc_subjs', 'id', false, null, null);
$this->addColumn('type', 'DbType', 'INTEGER', true, null, 1);
// validators
} // initialize()

View File

@ -72,6 +72,13 @@ abstract class BasePodcast extends BaseObject implements Persistent
*/
protected $owner;
/**
* The value for the type field.
* Note: this column has a database default value of: 1
* @var int
*/
protected $type;
/**
* @var CcSubjs
*/
@ -118,6 +125,7 @@ abstract class BasePodcast extends BaseObject implements Persistent
public function applyDefaultValues()
{
$this->auto_ingest = false;
$this->type = 1;
}
/**
@ -207,6 +215,17 @@ abstract class BasePodcast extends BaseObject implements Persistent
return $this->owner;
}
/**
* Get the [type] column value.
*
* @return int
*/
public function getDbType()
{
return $this->type;
}
/**
* Set the value of [id] column.
*
@ -366,6 +385,27 @@ abstract class BasePodcast extends BaseObject implements Persistent
return $this;
} // setDbOwner()
/**
* Set the value of [type] column.
*
* @param int $v new value
* @return Podcast The current object (for fluent API support)
*/
public function setDbType($v)
{
if ($v !== null && is_numeric($v)) {
$v = (int) $v;
}
if ($this->type !== $v) {
$this->type = $v;
$this->modifiedColumns[] = PodcastPeer::TYPE;
}
return $this;
} // setDbType()
/**
* Indicates whether the columns in this object are only set to default values.
*
@ -380,6 +420,10 @@ abstract class BasePodcast extends BaseObject implements Persistent
return false;
}
if ($this->type !== 1) {
return false;
}
// otherwise, everything was equal, so return true
return true;
} // hasOnlyDefaultValues()
@ -409,6 +453,7 @@ abstract class BasePodcast extends BaseObject implements Persistent
$this->description = ($row[$startcol + 4] !== null) ? (string) $row[$startcol + 4] : null;
$this->auto_ingest = ($row[$startcol + 5] !== null) ? (boolean) $row[$startcol + 5] : null;
$this->owner = ($row[$startcol + 6] !== null) ? (int) $row[$startcol + 6] : null;
$this->type = ($row[$startcol + 7] !== null) ? (int) $row[$startcol + 7] : null;
$this->resetModified();
$this->setNew(false);
@ -418,7 +463,7 @@ abstract class BasePodcast extends BaseObject implements Persistent
}
$this->postHydrate($row, $startcol, $rehydrate);
return $startcol + 7; // 7 = PodcastPeer::NUM_HYDRATE_COLUMNS.
return $startcol + 8; // 8 = PodcastPeer::NUM_HYDRATE_COLUMNS.
} catch (Exception $e) {
throw new PropelException("Error populating Podcast object", $e);
@ -696,6 +741,9 @@ abstract class BasePodcast extends BaseObject implements Persistent
if ($this->isColumnModified(PodcastPeer::OWNER)) {
$modifiedColumns[':p' . $index++] = '"owner"';
}
if ($this->isColumnModified(PodcastPeer::TYPE)) {
$modifiedColumns[':p' . $index++] = '"type"';
}
$sql = sprintf(
'INSERT INTO "podcast" (%s) VALUES (%s)',
@ -728,6 +776,9 @@ abstract class BasePodcast extends BaseObject implements Persistent
case '"owner"':
$stmt->bindValue($identifier, $this->owner, PDO::PARAM_INT);
break;
case '"type"':
$stmt->bindValue($identifier, $this->type, PDO::PARAM_INT);
break;
}
}
$stmt->execute();
@ -896,6 +947,9 @@ abstract class BasePodcast extends BaseObject implements Persistent
case 6:
return $this->getDbOwner();
break;
case 7:
return $this->getDbType();
break;
default:
return null;
break;
@ -932,6 +986,7 @@ abstract class BasePodcast extends BaseObject implements Persistent
$keys[4] => $this->getDbDescription(),
$keys[5] => $this->getDbAutoIngest(),
$keys[6] => $this->getDbOwner(),
$keys[7] => $this->getDbType(),
);
$virtualColumns = $this->virtualColumns;
foreach ($virtualColumns as $key => $virtualColumn) {
@ -1000,6 +1055,9 @@ abstract class BasePodcast extends BaseObject implements Persistent
case 6:
$this->setDbOwner($value);
break;
case 7:
$this->setDbType($value);
break;
} // switch()
}
@ -1031,6 +1089,7 @@ abstract class BasePodcast extends BaseObject implements Persistent
if (array_key_exists($keys[4], $arr)) $this->setDbDescription($arr[$keys[4]]);
if (array_key_exists($keys[5], $arr)) $this->setDbAutoIngest($arr[$keys[5]]);
if (array_key_exists($keys[6], $arr)) $this->setDbOwner($arr[$keys[6]]);
if (array_key_exists($keys[7], $arr)) $this->setDbType($arr[$keys[7]]);
}
/**
@ -1049,6 +1108,7 @@ abstract class BasePodcast extends BaseObject implements Persistent
if ($this->isColumnModified(PodcastPeer::DESCRIPTION)) $criteria->add(PodcastPeer::DESCRIPTION, $this->description);
if ($this->isColumnModified(PodcastPeer::AUTO_INGEST)) $criteria->add(PodcastPeer::AUTO_INGEST, $this->auto_ingest);
if ($this->isColumnModified(PodcastPeer::OWNER)) $criteria->add(PodcastPeer::OWNER, $this->owner);
if ($this->isColumnModified(PodcastPeer::TYPE)) $criteria->add(PodcastPeer::TYPE, $this->type);
return $criteria;
}
@ -1118,6 +1178,7 @@ abstract class BasePodcast extends BaseObject implements Persistent
$copyObj->setDbDescription($this->getDbDescription());
$copyObj->setDbAutoIngest($this->getDbAutoIngest());
$copyObj->setDbOwner($this->getDbOwner());
$copyObj->setDbType($this->getDbType());
if ($deepCopy && !$this->startCopy) {
// important: temporarily setNew(false) because this affects the behavior of
@ -1512,6 +1573,7 @@ abstract class BasePodcast extends BaseObject implements Persistent
$this->description = null;
$this->auto_ingest = null;
$this->owner = null;
$this->type = null;
$this->alreadyInSave = false;
$this->alreadyInValidation = false;
$this->alreadyInClearAllReferencesDeep = false;

View File

@ -24,13 +24,13 @@ abstract class BasePodcastPeer
const TM_CLASS = 'PodcastTableMap';
/** The total number of columns. */
const NUM_COLUMNS = 7;
const NUM_COLUMNS = 8;
/** The number of lazy-loaded columns. */
const NUM_LAZY_LOAD_COLUMNS = 0;
/** The number of columns to hydrate (NUM_COLUMNS - NUM_LAZY_LOAD_COLUMNS) */
const NUM_HYDRATE_COLUMNS = 7;
const NUM_HYDRATE_COLUMNS = 8;
/** the column name for the id field */
const ID = 'podcast.id';
@ -53,6 +53,9 @@ abstract class BasePodcastPeer
/** the column name for the owner field */
const OWNER = 'podcast.owner';
/** the column name for the type field */
const TYPE = 'podcast.type';
/** The default string format for model objects of the related table **/
const DEFAULT_STRING_FORMAT = 'YAML';
@ -72,12 +75,12 @@ abstract class BasePodcastPeer
* e.g. PodcastPeer::$fieldNames[PodcastPeer::TYPE_PHPNAME][0] = 'Id'
*/
protected static $fieldNames = array (
BasePeer::TYPE_PHPNAME => array ('DbId', 'DbUrl', 'DbTitle', 'DbCreator', 'DbDescription', 'DbAutoIngest', 'DbOwner', ),
BasePeer::TYPE_STUDLYPHPNAME => array ('dbId', 'dbUrl', 'dbTitle', 'dbCreator', 'dbDescription', 'dbAutoIngest', 'dbOwner', ),
BasePeer::TYPE_COLNAME => array (PodcastPeer::ID, PodcastPeer::URL, PodcastPeer::TITLE, PodcastPeer::CREATOR, PodcastPeer::DESCRIPTION, PodcastPeer::AUTO_INGEST, PodcastPeer::OWNER, ),
BasePeer::TYPE_RAW_COLNAME => array ('ID', 'URL', 'TITLE', 'CREATOR', 'DESCRIPTION', 'AUTO_INGEST', 'OWNER', ),
BasePeer::TYPE_FIELDNAME => array ('id', 'url', 'title', 'creator', 'description', 'auto_ingest', 'owner', ),
BasePeer::TYPE_NUM => array (0, 1, 2, 3, 4, 5, 6, )
BasePeer::TYPE_PHPNAME => array ('DbId', 'DbUrl', 'DbTitle', 'DbCreator', 'DbDescription', 'DbAutoIngest', 'DbOwner', 'DbType', ),
BasePeer::TYPE_STUDLYPHPNAME => array ('dbId', 'dbUrl', 'dbTitle', 'dbCreator', 'dbDescription', 'dbAutoIngest', 'dbOwner', 'dbType', ),
BasePeer::TYPE_COLNAME => array (PodcastPeer::ID, PodcastPeer::URL, PodcastPeer::TITLE, PodcastPeer::CREATOR, PodcastPeer::DESCRIPTION, PodcastPeer::AUTO_INGEST, PodcastPeer::OWNER, PodcastPeer::TYPE, ),
BasePeer::TYPE_RAW_COLNAME => array ('ID', 'URL', 'TITLE', 'CREATOR', 'DESCRIPTION', 'AUTO_INGEST', 'OWNER', 'TYPE', ),
BasePeer::TYPE_FIELDNAME => array ('id', 'url', 'title', 'creator', 'description', 'auto_ingest', 'owner', 'type', ),
BasePeer::TYPE_NUM => array (0, 1, 2, 3, 4, 5, 6, 7, )
);
/**
@ -87,12 +90,12 @@ abstract class BasePodcastPeer
* e.g. PodcastPeer::$fieldNames[BasePeer::TYPE_PHPNAME]['Id'] = 0
*/
protected static $fieldKeys = array (
BasePeer::TYPE_PHPNAME => array ('DbId' => 0, 'DbUrl' => 1, 'DbTitle' => 2, 'DbCreator' => 3, 'DbDescription' => 4, 'DbAutoIngest' => 5, 'DbOwner' => 6, ),
BasePeer::TYPE_STUDLYPHPNAME => array ('dbId' => 0, 'dbUrl' => 1, 'dbTitle' => 2, 'dbCreator' => 3, 'dbDescription' => 4, 'dbAutoIngest' => 5, 'dbOwner' => 6, ),
BasePeer::TYPE_COLNAME => array (PodcastPeer::ID => 0, PodcastPeer::URL => 1, PodcastPeer::TITLE => 2, PodcastPeer::CREATOR => 3, PodcastPeer::DESCRIPTION => 4, PodcastPeer::AUTO_INGEST => 5, PodcastPeer::OWNER => 6, ),
BasePeer::TYPE_RAW_COLNAME => array ('ID' => 0, 'URL' => 1, 'TITLE' => 2, 'CREATOR' => 3, 'DESCRIPTION' => 4, 'AUTO_INGEST' => 5, 'OWNER' => 6, ),
BasePeer::TYPE_FIELDNAME => array ('id' => 0, 'url' => 1, 'title' => 2, 'creator' => 3, 'description' => 4, 'auto_ingest' => 5, 'owner' => 6, ),
BasePeer::TYPE_NUM => array (0, 1, 2, 3, 4, 5, 6, )
BasePeer::TYPE_PHPNAME => array ('DbId' => 0, 'DbUrl' => 1, 'DbTitle' => 2, 'DbCreator' => 3, 'DbDescription' => 4, 'DbAutoIngest' => 5, 'DbOwner' => 6, 'DbType' => 7, ),
BasePeer::TYPE_STUDLYPHPNAME => array ('dbId' => 0, 'dbUrl' => 1, 'dbTitle' => 2, 'dbCreator' => 3, 'dbDescription' => 4, 'dbAutoIngest' => 5, 'dbOwner' => 6, 'dbType' => 7, ),
BasePeer::TYPE_COLNAME => array (PodcastPeer::ID => 0, PodcastPeer::URL => 1, PodcastPeer::TITLE => 2, PodcastPeer::CREATOR => 3, PodcastPeer::DESCRIPTION => 4, PodcastPeer::AUTO_INGEST => 5, PodcastPeer::OWNER => 6, PodcastPeer::TYPE => 7, ),
BasePeer::TYPE_RAW_COLNAME => array ('ID' => 0, 'URL' => 1, 'TITLE' => 2, 'CREATOR' => 3, 'DESCRIPTION' => 4, 'AUTO_INGEST' => 5, 'OWNER' => 6, 'TYPE' => 7, ),
BasePeer::TYPE_FIELDNAME => array ('id' => 0, 'url' => 1, 'title' => 2, 'creator' => 3, 'description' => 4, 'auto_ingest' => 5, 'owner' => 6, 'type' => 7, ),
BasePeer::TYPE_NUM => array (0, 1, 2, 3, 4, 5, 6, 7, )
);
/**
@ -173,6 +176,7 @@ abstract class BasePodcastPeer
$criteria->addSelectColumn(PodcastPeer::DESCRIPTION);
$criteria->addSelectColumn(PodcastPeer::AUTO_INGEST);
$criteria->addSelectColumn(PodcastPeer::OWNER);
$criteria->addSelectColumn(PodcastPeer::TYPE);
} else {
$criteria->addSelectColumn($alias . '.id');
$criteria->addSelectColumn($alias . '.url');
@ -181,6 +185,7 @@ abstract class BasePodcastPeer
$criteria->addSelectColumn($alias . '.description');
$criteria->addSelectColumn($alias . '.auto_ingest');
$criteria->addSelectColumn($alias . '.owner');
$criteria->addSelectColumn($alias . '.type');
}
}

View File

@ -13,6 +13,7 @@
* @method PodcastQuery orderByDbDescription($order = Criteria::ASC) Order by the description column
* @method PodcastQuery orderByDbAutoIngest($order = Criteria::ASC) Order by the auto_ingest column
* @method PodcastQuery orderByDbOwner($order = Criteria::ASC) Order by the owner column
* @method PodcastQuery orderByDbType($order = Criteria::ASC) Order by the type column
*
* @method PodcastQuery groupByDbId() Group by the id column
* @method PodcastQuery groupByDbUrl() Group by the url column
@ -21,6 +22,7 @@
* @method PodcastQuery groupByDbDescription() Group by the description column
* @method PodcastQuery groupByDbAutoIngest() Group by the auto_ingest column
* @method PodcastQuery groupByDbOwner() Group by the owner column
* @method PodcastQuery groupByDbType() Group by the type column
*
* @method PodcastQuery leftJoin($relation) Adds a LEFT JOIN clause to the query
* @method PodcastQuery rightJoin($relation) Adds a RIGHT JOIN clause to the query
@ -43,6 +45,7 @@
* @method Podcast findOneByDbDescription(string $description) Return the first Podcast filtered by the description column
* @method Podcast findOneByDbAutoIngest(boolean $auto_ingest) Return the first Podcast filtered by the auto_ingest column
* @method Podcast findOneByDbOwner(int $owner) Return the first Podcast filtered by the owner column
* @method Podcast findOneByDbType(int $type) Return the first Podcast filtered by the type column
*
* @method array findByDbId(int $id) Return Podcast objects filtered by the id column
* @method array findByDbUrl(string $url) Return Podcast objects filtered by the url column
@ -51,6 +54,7 @@
* @method array findByDbDescription(string $description) Return Podcast objects filtered by the description column
* @method array findByDbAutoIngest(boolean $auto_ingest) Return Podcast objects filtered by the auto_ingest column
* @method array findByDbOwner(int $owner) Return Podcast objects filtered by the owner column
* @method array findByDbType(int $type) Return Podcast objects filtered by the type column
*
* @package propel.generator.airtime.om
*/
@ -158,7 +162,7 @@ abstract class BasePodcastQuery extends ModelCriteria
*/
protected function findPkSimple($key, $con)
{
$sql = 'SELECT "id", "url", "title", "creator", "description", "auto_ingest", "owner" FROM "podcast" WHERE "id" = :p0';
$sql = 'SELECT "id", "url", "title", "creator", "description", "auto_ingest", "owner", "type" FROM "podcast" WHERE "id" = :p0';
try {
$stmt = $con->prepare($sql);
$stmt->bindValue(':p0', $key, PDO::PARAM_INT);
@ -476,6 +480,48 @@ abstract class BasePodcastQuery extends ModelCriteria
return $this->addUsingAlias(PodcastPeer::OWNER, $dbOwner, $comparison);
}
/**
* Filter the query on the type column
*
* Example usage:
* <code>
* $query->filterByDbType(1234); // WHERE type = 1234
* $query->filterByDbType(array(12, 34)); // WHERE type IN (12, 34)
* $query->filterByDbType(array('min' => 12)); // WHERE type >= 12
* $query->filterByDbType(array('max' => 12)); // WHERE type <= 12
* </code>
*
* @param mixed $dbType The value to use as filter.
* Use scalar values for equality.
* Use array values for in_array() equivalent.
* Use associative array('min' => $minValue, 'max' => $maxValue) for intervals.
* @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL
*
* @return PodcastQuery The current query, for fluid interface
*/
public function filterByDbType($dbType = null, $comparison = null)
{
if (is_array($dbType)) {
$useMinMax = false;
if (isset($dbType['min'])) {
$this->addUsingAlias(PodcastPeer::TYPE, $dbType['min'], Criteria::GREATER_EQUAL);
$useMinMax = true;
}
if (isset($dbType['max'])) {
$this->addUsingAlias(PodcastPeer::TYPE, $dbType['max'], Criteria::LESS_EQUAL);
$useMinMax = true;
}
if ($useMinMax) {
return $this;
}
if (null === $comparison) {
$comparison = Criteria::IN;
}
}
return $this->addUsingAlias(PodcastPeer::TYPE, $dbType, $comparison);
}
/**
* Filter the query by a related CcSubjs object
*

View File

@ -21,13 +21,20 @@ class Rest_MediaController extends Zend_Rest_Controller
$offset = $this->_getParam('offset', 0);
$limit = $this->_getParam('limit', $totalFileCount);
//Sorting parameters
$sortColumn = $this->_getParam('sort', CcFilesPeer::ID);
$sortDir = $this->_getParam('sort_dir', Criteria::ASC);
$query = CcFilesQuery::create()
->filterByDbHidden(false)
->filterByDbFileExists(true)
->filterByDbImportStatus(0)
->setLimit($limit)
->setOffset($offset)
->orderByDbId();
->orderBy($sortColumn, $sortDir);
//->orderByDbId();
$queryCount = $query->count();
$queryResult = $query->find();
@ -39,7 +46,7 @@ class Rest_MediaController extends Zend_Rest_Controller
$this->getResponse()
->setHttpResponseCode(200)
->setHeader('X-TOTAL-COUNT', $queryCount)
->setHeader('X-TOTAL-COUNT', $totalFileCount)
->appendBody(json_encode($files_array));
/** TODO: Use this simpler code instead after we upgrade to Propel 1.7 (Airtime 2.6.x branch):

View File

@ -0,0 +1,7 @@
<div class="text-content">
<h2><?php echo _("Table Test") ?></h2>
<p>
Hello
</p>
<table id="example-table" cellpadding="0" cellspacing="0" class="datatable"></table>
</div>

View File

@ -571,6 +571,7 @@
<column name="description" phpName="DbDescription" type="VARCHAR" size="512" />
<column name="auto_ingest" phpName="DbAutoIngest" type="BOOLEAN" required="true" defaultValue="false"/>
<column name="owner" phpName="DbOwner" type="INTEGER" />
<column name="type" phpName="DbType" type="INTEGER" required="true" defaultValue="1"/>
<foreign-key foreignTable="cc_subjs" name="podcast_owner_fkey" onDelete="CASCADE">
<reference local="owner" foreign="id" />
</foreign-key>

View File

@ -722,6 +722,7 @@ CREATE TABLE "podcast"
"description" VARCHAR(512),
"auto_ingest" BOOLEAN DEFAULT 'f' NOT NULL,
"owner" INTEGER,
"type" INTEGER DEFAULT 1 NOT NULL,
PRIMARY KEY ("id")
);

View File

@ -1256,25 +1256,6 @@ var AIRTIME = (function(AIRTIME) {
}(AIRTIME || {}));
function buildEditMetadataDialog (json){
var dialog = $(json.dialog);
dialog.dialog({
autoOpen: false,
title: $.i18n._("Edit Metadata"),
width: 460,
height: 660,
modal: true,
close: closeDialogLibrary
});
dialog.dialog('open');
}
function closeDialogLibrary(event, ui) {
$(this).remove();
}
/*
* This function is called from dataTables.columnFilter.js
*/

View File

@ -0,0 +1,24 @@
/**
* Created by asantoni on 11/09/15.
*/
$(document).ready(function() {
var aoColumns = [
/* Title */ { "sTitle" : $.i18n._("Title") , "mDataProp" : "track_title" , "sClass" : "library_title" , "sWidth" : "170px" },
/* Creator */ { "sTitle" : $.i18n._("Creator") , "mDataProp" : "artist_name" , "sClass" : "library_creator" , "sWidth" : "160px" },
/* Upload Time */ { "sTitle" : $.i18n._("Uploaded") , "mDataProp" : "utime" , "bVisible" : false , "sClass" : "library_upload_time" , "sWidth" : "155px" },
/* Website */ { "sTitle" : $.i18n._("Website") , "mDataProp" : "info_url" , "bVisible" : false , "sClass" : "library_url" , "sWidth" : "150px" },
/* Year */ { "sTitle" : $.i18n._("Year") , "mDataProp" : "year" , "bVisible" : false , "sClass" : "library_year" , "sWidth" : "60px" },
];
var ajaxSourceURL = baseUrl+"rest/media";
//Set up the div with id "example-table" as a datatable.
var table = AIRTIME.widgets.table.init(
$('#example-table'), //DOM node to create the table inside.
true, //Enable item selection
{ //Datatables overrides.
'aoColumns' : aoColumns,
'sAjaxSource' : ajaxSourceURL
});
});

View File

@ -0,0 +1,326 @@
/**
* Created by asantoni on 11/09/15.
*/
var AIRTIME = (function(AIRTIME) {
//Module initialization
if (AIRTIME.widgets === undefined) {
AIRTIME.widgets = {};
}
if (AIRTIME.widgets.table === undefined) {
AIRTIME.widgets.table = {};
}
var self;
var self = AIRTIME.widgets.table;
//Constants
self.SELECTION_MODE = {
SINGLE : 0,
MULTI_SHIFT : 1,
MULTI_CTRL : 2
}
self.HUGE_INT = Math.pow(2, 53) - 1;
//Member variables
self._datatable = null;
self._selectedRows = []; //An array containing the underlying objects for each selected row. (Easy to use!)
//self._selectedRowVisualIdxMap = []; //A map of the visual index of a selected rows onto the actual row data.
self._selectedRowVisualIdxMin = self.HUGE_INT;
self._selectedRowVisualIdxMax = -1;
self._$wrapperDOMNode = null;
//Member functions
self.init = function(wrapperDOMNode, bItemSelection, dataTablesOptions) {
self._$wrapperDOMNode = $(wrapperDOMNode);
//TODO: If selection is enabled, add in the checkbox column.
if (bItemSelection) {
dataTablesOptions["aoColumns"].unshift(
/* Checkbox */ { "sTitle" : "", "mData" : self._datatablesCheckboxDataDelegate, "bSortable" : false , "bSearchable" : false , "sWidth" : "16px" , "sClass" : "library_checkbox" }
);
dataTablesOptions["fnRowCallback"] = self._rowCreatedCallback;
}
var options = {
"aoColumns": [
/* Title */ { "sTitle" : $.i18n._("Make sure to override me") , "mDataProp" : "track_title" , "sClass" : "library_title" , "sWidth" : "170px" },
],
"bProcessing": true,
"bServerSide": true,
"sAjaxSource": baseUrl+"rest/media", //Override me
"sAjaxDataProp": "aaData",
"bScrollCollapse": false,
"sPaginationType": "full_numbers",
"bJQueryUI": true,
"bAutoWidth": false,
"aaSorting": [],
"oLanguage" : getDatatablesStrings({
"sEmptyTable": $.i18n._(""),
"sZeroRecords": $.i18n._("No matching results found.")
}),
"oColVis": {
"sAlign": "right",
"buttonText": $.i18n._("Columns"),
"iOverlayFade": 0
},
// z = ColResize, R = ColReorder, C = ColVis
"sDom": 'Rf<"dt-process-rel"r><"H"<"library_toolbar"C>><"dataTables_scrolling"t<"#library_empty"<"#library_empty_image"><"#library_empty_text">>><"F"lip>>',
"fnServerData": self._fetchData,
"fnDrawCallback" : self._tableDrawCallback
};
//Override any options with those passed in as arguments to this constructor.
for (var key in dataTablesOptions)
{
options[key] = dataTablesOptions[key];
}
self._datatable = self._$wrapperDOMNode.dataTable(options);
};
self._handleAjaxError = function(r) {
// If the request was denied due to permissioning
if (r.status === 403) {
// Hide the processing div
/*
$("#library_display_wrapper").find(".dt-process-rel").hide();
$.getJSON( "ajax/library_placeholders.json", function( data ) {
$('#library_empty_text').text($.i18n._(data.unauthorized));
}) ;
$('#library_empty').show();
*/
}
};
//
self._fetchData = function ( sSource, aoData, fnCallback, oSettings ) {
var echo = aoData[0].value; //Datatables state tracking. Must be included.
//getUsabilityHint();
var sortColName = "";
var sortDir = "";
if (oSettings.aaSorting.length > 0) {
var sortColIdx = oSettings.aaSorting[0][0];
sortColName = oSettings.aoColumns[sortColIdx].mDataProp;
sortDir = oSettings.aaSorting[0][1].toUpperCase();
}
$.ajax({
"dataType": 'json',
"type": "GET",
"url": sSource,
"data": {
"limit": oSettings._iDisplayLength,
"offset": oSettings._iDisplayStart,
"sort": sortColName,
'sort_dir': sortDir,
},
"success": function (json, textStatus, jqXHR) {
var rawResponseJSON = json;
json = [];
json.aaData = rawResponseJSON;
json.iTotalRecords = jqXHR.getResponseHeader('X-TOTAL-COUNT');
json.iTotalDisplayRecords = json.iTotalRecords;//rawResponseJSON.length;
json.sEcho = echo;
//Pass it along to datatables.
fnCallback(json);
},
"error": self._handleAjaxError
}).done(function (data) {
/*
if (data.iTotalRecords > data.iTotalDisplayRecords) {
$('#filter_message').text(
$.i18n._("Filtering out ") + (data.iTotalRecords - data.iTotalDisplayRecords)
+ $.i18n._(" of ") + data.iTotalRecords
+ $.i18n._(" records")
);
$('#library_empty').hide();
$('#library_display').find('tr:has(td.dataTables_empty)').show();
} else {
$('#filter_message').text("");
}
$('#library_content').find('.dataTables_filter input[type="text"]')
.css('padding-right', $('#advanced-options').find('button').outerWidth());
*/
});
};
self._datatablesCheckboxDataDelegate = function(rowData, callType, dataToSave) {
if (callType == undefined) {
//Supposed to return the raw data for the type here.
return null;
} else if (callType == 'display') {
return "<input type='checkbox' class='airtime_table_checkbox'>";
} else if (callType == 'sort') {
return null;
} else if (callType == 'type') {
return "input";
} else if (callType == 'set') {
//The data to set is in dataToSave.
return;
} else if (callType == 'filter') {
return null;
}
//For all other calls, just return the data as this:
return "check";
};
self._rowCreatedCallback = function(nRow, aData, iDisplayIndex) {
// Bind click event
$(nRow).click(function(e) {
e.stopPropagation();
e.preventDefault();
document.getSelection().removeAllRanges();
//alert( 'You clicked on '+aData.track_title+'\'s row' + iDisplayIndex);
var selectionMode = self.SELECTION_MODE.SINGLE;
if (e.shiftKey) {
selectionMode = self.SELECTION_MODE.MULTI_SHIFT;
} else if (e.ctrlKey) {
selectionMode = self.SELECTION_MODE.MULTI_CTRL;
}
self.selectRow(nRow, aData, selectionMode, iDisplayIndex);
});
return nRow;
};
self._tableDrawCallback = function(oSettings) {
$('input.airtime_table_checkbox').click(function(e) {
$this = $(this);
var iVisualRowIdx = $this.parent().parent().index();
self.selectRow($this.parent().parent(), null, self.SELECTION_MODE.MULTI_CTRL, iVisualRowIdx); //Always multiselect for checkboxes
e.stopPropagation();
return true;
});
};
/** @param nRow is a tr DOM node (non-jQuery)
* @param aData is an array containing the raw data for the row. Can be null if you don't have it.
* @param selectionMode is an SELECT_MODE enum. Specify what selection mode you want to use for this action.
* @param iVisualRowIdx is an integer which corresponds to the index of the clicked row, as it appears to the user.
* eg. The 5th row in the table will have an iVisualRowIdx of 4 (0-based).
*/
self.selectRow = function(nRow, aData, selectionMode, iVisualRowIdx) {
//Default to single item selection.
if (selectionMode == undefined) {
selectionMode = self.SELECTION_MODE.SINGLE;
}
var $nRow = $(nRow);
/*
var foundAtIdx = $.inArray(aData, self._selectedRows)
if (foundAtIdx >= 0 && self._selectedRows.length > 1) {
self._selectedRows.splice(foundAtIdx, 1);
$nRow.removeClass('selected');
$nRow.find('input.airtime_table_checkbox').attr('checked', false);
*/
if (false) {
} else {
//Regular single left-click mode
if (selectionMode == self.SELECTION_MODE.SINGLE) {
self._clearSelection();
self._selectedRows.push(aData);
self._selectedRowVisualIdxMin = iVisualRowIdx;
self._selectedRowVisualIdxMax = iVisualRowIdx;
//self._selectedRowVisualIdxMap[iVisualRowIdx] = aData;
$nRow.addClass('selected');
$nRow.find('input.airtime_table_checkbox').attr('checked', true);
}
//Ctrl-click multi row selection mode
else if (selectionMode == self.SELECTION_MODE.MULTI_CTRL) {
var foundAtIdx = $.inArray(aData, self._selectedRows)
if (foundAtIdx >= 0 && self._selectedRows.length > 1) {
self._selectedRows.splice(foundAtIdx, 1);
$nRow.removeClass('selected');
$nRow.find('input.airtime_table_checkbox').attr('checked', false);
}
else {
self._selectedRows.push(aData);
self._selectedRowVisualIdxMin = iVisualRowIdx;
self._selectedRowVisualIdxMax = iVisualRowIdx;
$nRow.addClass('selected');
$nRow.find('input.airtime_table_checkbox').attr('checked', true);
}
}
//Shift-click multi row selection mode
else if (selectionMode == self.SELECTION_MODE.MULTI_SHIFT) {
//If there's no rows selected, just behave like single selection.
if (self._selectedRows.length == 0) {
return self.selectRow(nRow, aData, self.SELECTION_MODE.SINGLE, iVisualRowIdx);
}
if (iVisualRowIdx > self._selectedRowVisualIdxMax) {
self._selectedRowVisualIdxMax = iVisualRowIdx;
}
if (iVisualRowIdx < self._selectedRowVisualIdxMin) {
self._selectedRowVisualIdxMin = iVisualRowIdx;
}
var selectionStartRowIdx = Math.min(iVisualRowIdx, self._selectedRowVisualIdxMin);
var selectionEndRowIdx = Math.min(iVisualRowIdx, self._selectedRowVisualIdxMax);
//We can assume there's at least 1 row already selected now.
var allRows = self._datatable.fnGetData();
self._selectedRows = [];
for (var i = self._selectedRowVisualIdxMin; i <= self._selectedRowVisualIdxMax; i++)
{
self._selectedRows.push(allRows[i]);
$row = $($nRow.parent().children()[i]);
$row.addClass('selected');
$row.find('input.airtime_table_checkbox').attr('checked', true);
}
}
else {
console.log("Unimplemented selection mode");
}
}
};
self._clearSelection = function() {
self._selectedRows = [];
//self._selectedRowVisualIdxMap = [];
self._selectedRowVisualIdxMin = self.HUGE_INT;
self._selectedRowVisualIdxMax = -1;
self._$wrapperDOMNode.find('.selected').removeClass('selected');
self._$wrapperDOMNode.find('input.airtime_table_checkbox').attr('checked', false);
};
self.getSelectedRows = function() {
return self._selectedRows;
}
return AIRTIME;
}(AIRTIME || {}));