From fbda0e733b243cda48660f6789f1c4a3198d766e Mon Sep 17 00:00:00 2001 From: Naomi Aro Date: Tue, 31 Jan 2012 18:59:27 +0100 Subject: [PATCH] CC-3174 : showbuilder check into issue that propel doesn't return DateTime object in UTC. using table tools to keep track of selected rows. --- .../controllers/LibraryController.php | 4 + .../controllers/ShowbuilderController.php | 36 +- airtime_mvc/application/models/Schedule.php | 3 +- airtime_mvc/application/models/Scheduler.php | 191 +- .../application/models/ShowBuilder.php | 10 +- airtime_mvc/application/models/StoredFile.php | 14 - airtime_mvc/application/models/User.php | 18 + airtime_mvc/public/css/TableTools.css | 265 ++ airtime_mvc/public/css/TableTools_JUI.css | 183 ++ .../library/events/library_playlistbuilder.js | 15 +- .../library/events/library_showbuilder.js | 33 +- .../public/js/airtime/library/library.js | 311 +- .../public/js/airtime/showbuilder/builder.js | 413 +-- .../plugin/dataTables.TableTools.js | 2569 +++++++++++++++++ .../plugin/dataTables.ZeroClipboard.js | 367 +++ .../public/js/libs/jquery-1.7.1.min.js | 4 + 16 files changed, 3999 insertions(+), 437 deletions(-) create mode 100755 airtime_mvc/public/css/TableTools.css create mode 100755 airtime_mvc/public/css/TableTools_JUI.css create mode 100755 airtime_mvc/public/js/datatables/plugin/dataTables.TableTools.js create mode 100755 airtime_mvc/public/js/datatables/plugin/dataTables.ZeroClipboard.js create mode 100644 airtime_mvc/public/js/libs/jquery-1.7.1.min.js diff --git a/airtime_mvc/application/controllers/LibraryController.php b/airtime_mvc/application/controllers/LibraryController.php index 2e52ca019..4acb26ee8 100644 --- a/airtime_mvc/application/controllers/LibraryController.php +++ b/airtime_mvc/application/controllers/LibraryController.php @@ -39,12 +39,15 @@ class LibraryController extends Zend_Controller_Action $baseUrl = $request->getBaseUrl(); $this->view->headScript()->appendFile($baseUrl.'/js/contextmenu/jjmenu.js','text/javascript'); + $this->view->headScript()->appendFile($baseUrl.'/js/datatables/js/jquery.dataTables.js','text/javascript'); $this->view->headScript()->appendFile($baseUrl.'/js/datatables/plugin/dataTables.pluginAPI.js','text/javascript'); $this->view->headScript()->appendFile($baseUrl.'/js/datatables/plugin/dataTables.fnSetFilteringDelay.js','text/javascript'); $this->view->headScript()->appendFile($baseUrl.'/js/datatables/plugin/dataTables.ColVis.js','text/javascript'); $this->view->headScript()->appendFile($baseUrl.'/js/datatables/plugin/dataTables.ColReorderResize.js','text/javascript'); $this->view->headScript()->appendFile($baseUrl.'/js/datatables/plugin/dataTables.FixedColumns.js','text/javascript'); + $this->view->headScript()->appendFile($baseUrl.'/js/datatables/plugin/dataTables.TableTools.js','text/javascript'); + $this->view->headScript()->appendFile($baseUrl.'/js/airtime/library/library.js','text/javascript'); $this->view->headScript()->appendFile($baseUrl.'/js/airtime/library/advancedsearch.js','text/javascript'); @@ -52,6 +55,7 @@ class LibraryController extends Zend_Controller_Action $this->view->headLink()->appendStylesheet($baseUrl.'/css/contextmenu.css'); $this->view->headLink()->appendStylesheet($baseUrl.'/css/datatables/css/ColVis.css'); $this->view->headLink()->appendStylesheet($baseUrl.'/css/datatables/css/ColReorder.css'); + $this->view->headLink()->appendStylesheet($baseUrl.'/css/TableTools.css'); $this->_helper->viewRenderer->setResponseSegment('library'); diff --git a/airtime_mvc/application/controllers/ShowbuilderController.php b/airtime_mvc/application/controllers/ShowbuilderController.php index 89f36eeac..39dfc4f99 100644 --- a/airtime_mvc/application/controllers/ShowbuilderController.php +++ b/airtime_mvc/application/controllers/ShowbuilderController.php @@ -6,7 +6,9 @@ class ShowbuilderController extends Zend_Controller_Action public function init() { $ajaxContext = $this->_helper->getHelper('AjaxContext'); - $ajaxContext->addActionContext('schedule', 'json') + $ajaxContext->addActionContext('schedule-update', 'json') + ->addActionContext('schedule-add', 'json') + ->addActionContext('schedule-remove', 'json') ->addActionContext('builder-feed', 'json') ->initContext(); } @@ -55,6 +57,38 @@ class ShowbuilderController extends Zend_Controller_Action $this->view->schedule = $showBuilder->GetItems(); } + public function scheduleAddAction() { + + $request = $this->getRequest(); + + $id = $request->getParam("id", null); + $instance = $request->getParam("instance", null); + + $items = $request->getParam("items", array()); + } + + public function scheduleRemoveAction() + { + $request = $this->getRequest(); + + $ids = $request->getParam("ids", null); + + Logging::log($ids); + + $json = array(); + + try { + Application_Model_Scheduler::removeItems($ids); + $json["message"]="success... maybe"; + } + catch (Exception $e) { + $json["message"]=$e->getMessage(); + Logging::log($e->getMessage()); + } + + $this->view->data = $json; + } + public function scheduleAction() { $request = $this->getRequest(); diff --git a/airtime_mvc/application/models/Schedule.php b/airtime_mvc/application/models/Schedule.php index c3e655b53..13f268cf6 100644 --- a/airtime_mvc/application/models/Schedule.php +++ b/airtime_mvc/application/models/Schedule.php @@ -309,7 +309,8 @@ class Application_Model_Schedule { $sql = "SELECT DISTINCT - showt.name AS show_name, showt.color AS show_color, showt.background_color AS show_background_colour, + showt.name AS show_name, showt.color AS show_color, + showt.background_color AS show_background_colour, showt.id AS show_id, si.starts AS si_starts, si.ends AS si_ends, si.time_filled AS si_time_filled, si.record AS si_record, si.rebroadcast AS si_rebroadcast, si.id AS si_id, diff --git a/airtime_mvc/application/models/Scheduler.php b/airtime_mvc/application/models/Scheduler.php index 3a3391eb1..b25b7e7c6 100644 --- a/airtime_mvc/application/models/Scheduler.php +++ b/airtime_mvc/application/models/Scheduler.php @@ -3,6 +3,7 @@ class Application_Model_Scheduler { private $propSched; + private $con; public function __construct($id = null) { @@ -15,13 +16,193 @@ class Application_Model_Scheduler { } /* - public function findScheduledItems($starts, $ends) { + * @param $id + * @param $type + * + * @return $files + */ + private static function retrieveMediaFiles($id, $type) { - CcScheduleQuery::create() - ->filterByDbStarts(array('min' => $starts->format('Y-m-d H:i:s'), 'max' => $ends->format('Y-m-d H:i:s'))) - ->find(); + $fileInfo = array( + "id" => "", + "cliplength" => "", + "cuein" => "00:00:00", + "cueout" => "00:00:00", + "fadein" => "00:00:00", + "fadeout" => "00:00:00" + ); + + $files = array(); + + if ($type === "file") { + $file = CcFilesQuery::create()->findByPK($id); + + $data = $fileInfo; + $data["id"] = $id; + $data["cliplength"] = $file->getDbLength(); + + $files[] = $data; + } + else if ($type === "playlist") { + + } + + return $files; + } + + /* + * @param array $scheduledIds + * @param array $fileIds + * @param array $playlistIds + */ + public static function scheduleAfter($scheduledIds, $mediaIds, $adjustSched = true) { + + $con = Propel::getConnection(CcSchedulePeer::DATABASE_NAME); + + $con->beginTransaction(); + + try { + + $schedFiles = array(); + foreach($mediaIds as $id => $type) { + $schedFiles = array_merge($schedFiles, self::retrieveMediaFiles($id, $type)); + } + + foreach ($scheduledIds as $id) { + + $schedItem = CcScheduleQuery::create()->findByPK($id); + + if ($adjustSched === true) { + $followingSchedItems = CcScheduleQuery::create() + ->filterByDBStarts($schedItem->getDbStarts("Y-m-d H:i:s.u"), Criteria::GREATER_THAN) + ->filterByDbInstanceId($instance) + ->orderByDbStarts() + ->find(); + } + + $nextItemDT = $schedItem->getDbEnds(null); + $instance = $schedItem->getDbInstanceId(); + + foreach($schedFiles as $file) { + + $durationDT = DateTime::createFromFormat("Y-m-d H:i:s.u", "1970-01-01 {$file['cliplength']}", new DateTimeZone("UTC")); + $endTimeEpoch = $nextItemDT->format("U.u") + $durationDT->format("U.u"); + $endTimeDT = DateTime::createFromFormat("U.u", $endTimeEpoch, new DateTimeZone("UTC")); + + $newItem = new CcSchedule(); + $newItem->setDbStarts($nextItemDT); + $newItem->setDbEnds($endTimeDT); + $newItem->setDbFileId($file['id']); + $newItem->setDbCueIn($file['cuein']); + $newItem->setDbCueOut($file['cueout']); + $newItem->setDbFadeIn($file['fadein']); + $newItem->setDbFadeOut($file['fadeout']); + $newItem->setDbInstanceId($instance); + $newItem->save($con); + + $nextItemDT = $endTimeDT; + } + + if ($adjustSched === true) { + + //recalculate the start/end times after the inserted items. + foreach($followingSchedItems as $followingItem) { + + $durationDT = DateTime::createFromFormat("Y-m-d H:i:s.u", "1970-01-01 {$file['cliplength']}", new DateTimeZone("UTC")); + $endTimeEpoch = $nextItemDT->format("U.u") + $durationDT->format("U.u"); + $endTimeDT = DateTime::createFromFormat("U.u", $endTimeEpoch, new DateTimeZone("UTC")); + + $followingItem->setDbStarts($nextItemDT); + $followingItem->setDbEnds($endTimeDT); + $followingItem->save($con); + + $nextItemDT = $endTimeDT; + } + } + } + } + catch (Exception $e) { + $con->rollback(); + throw $e; + } + } + + public function removeItems($scheduledIds, $adjustSched = true) { + + $showInstances = array(); + + $this->con = Propel::getConnection(CcSchedulePeer::DATABASE_NAME); + + $this->con->beginTransaction(); + + try { + + $removedItems = CcScheduleQuery::create()->findPks($scheduledIds); + $removedItems->delete($this->con); + + if ($adjustSched === true) { + //get the show instances of the shows we must adjust times for. + foreach ($removedItems as $item) { + + $instance = $item->getDBInstanceId(); + if (!in_array($instance, $showInstances)) { + $showInstances[] = $instance; + } + } + + foreach($showInstances as $instance) { + self::removeGaps($instance); + } + } + } + catch (Exception $e) { + $this->con->rollback(); + throw $e; + } + } + + public function removeGaps($showInstance) { + + Logging::log("removing gaps from show instance #".$showInstance); + + $instance = CcShowInstancesQuery::create()->findPK($showInstance); + $itemStartDT = $instance->getDbStarts(null); + + $schedule = CcScheduleQuery::create() + ->filterByDbInstanceId($showInstance) + ->orderByDbStarts() + ->find(); + + + foreach ($schedule as $item) { + + Logging::log("adjusting item #".$item->getDbId()); + + if (!$item->isDeleted()) { + Logging::log("item #".$item->getDbId()." is not deleted"); + + $durationDT = new DateTime("1970-01-01 {$item->getDbClipLength()}", new DateTimeZone("UTC")); + $startEpoch = $itemStartDT->format("U"); + Logging::log("new start time"); + Logging::log($itemStartDT->format("Y-m-d H:i:s")); + + Logging::log("duration"); + Logging::log($durationDT->format("Y-m-d H:i:s")); + Logging::log($durationDT->format("U"). "seconds"); + + $endEpoch = $itemStartDT->format("U") + $durationDT->format("U"); + $itemEndDT = DateTime::createFromFormat("U", $endEpoch, new DateTimeZone("UTC")); + Logging::log("new end time"); + Logging::log($itemEndDT->format("Y-m-d H:i:s")); + + $item->setDbStarts($itemStartDT); + $item->setDbEnds($itemEndDT); + $item->save($this->con); + + $itemStartDT = $itemEndDT; + } + } } - */ public function addScheduledItem($starts, $duration, $adjustSched = true) { diff --git a/airtime_mvc/application/models/ShowBuilder.php b/airtime_mvc/application/models/ShowBuilder.php index 8724b6e50..34aaa7d75 100644 --- a/airtime_mvc/application/models/ShowBuilder.php +++ b/airtime_mvc/application/models/ShowBuilder.php @@ -5,6 +5,7 @@ class Application_Model_ShowBuilder { private $timezone; private $startDT; private $endDT; + private $user; private $defaultRowArray = array( "header" => false, @@ -32,6 +33,7 @@ class Application_Model_ShowBuilder { $this->startDT = $p_startDT; $this->endDT = $p_endDT; $this->timezone = date_default_timezone_get(); + $this->user = Application_Model_User::GetCurrentUser(); } /* @@ -96,8 +98,8 @@ class Application_Model_ShowBuilder { $runtime = $schedStartDT->diff($schedEndDT); - $row["id"] = $p_item["sched_id"]; - $row["instance"] = $p_item["si_id"]; + $row["id"] = intval($p_item["sched_id"]); + $row["instance"] = intval($p_item["si_id"]); $row["starts"] = $schedStartDT->format("H:i:s"); $row["startsUnix"] = $schedStartDT->format("U"); $row["ends"] = $schedEndDT->format("H:i:s"); @@ -107,6 +109,10 @@ class Application_Model_ShowBuilder { $row["title"] = $p_item["file_track_title"]; $row["creator"] = $p_item["file_artist_name"]; $row["album"] = $p_item["file_album_title"]; + + if ($this->user->canSchedule($item["show_id"]) === true) { + $row["checkbox"] = true; + } } //show is empty else { diff --git a/airtime_mvc/application/models/StoredFile.php b/airtime_mvc/application/models/StoredFile.php index 1963738af..5ddcc08c3 100644 --- a/airtime_mvc/application/models/StoredFile.php +++ b/airtime_mvc/application/models/StoredFile.php @@ -687,20 +687,6 @@ class Application_Model_StoredFile { $results = Application_Model_StoredFile::searchFiles($fromTable, $datatables); - /* - type = aData["ftype"].substring(0,2); - id = aData["id"]; - - if(type == "au") { - $('td.library_type', nRow).html( '' ); - } else if(type == "pl") { - $('td.library_type', nRow).html( '' ); - } - - - $(nRow).attr("id", type+'_'+id); - */ - foreach($results['aaData'] as &$row){ // add checkbox row $row['checkbox'] = ""; diff --git a/airtime_mvc/application/models/User.php b/airtime_mvc/application/models/User.php index ad0a4306e..aa79e71bf 100644 --- a/airtime_mvc/application/models/User.php +++ b/airtime_mvc/application/models/User.php @@ -35,6 +35,19 @@ class Application_Model_User { return $this->isUserType(UTYPE_ADMIN); } + public function canSchedule($p_showId) { + $type = $this->getType(); + + if ( $type === UTYPE_ADMIN || + $type === UTYPE_PROGRAM_MANAGER || + CcShowHostsQuery::create()->filterByDbShow($p_showId)->filterByDbHost($this->getId())->count() > 0 ) + { + return true; + } + + return false; + } + public function isUserType($type, $showId=''){ if(is_array($type)){ $result = false; @@ -270,4 +283,9 @@ class Application_Model_User { } } + public static function GetCurrentUser() { + $userinfo = Zend_Auth::getInstance()->getStorage()->read(); + + return new self($userinfo->id); + } } diff --git a/airtime_mvc/public/css/TableTools.css b/airtime_mvc/public/css/TableTools.css new file mode 100755 index 000000000..2b8812a3b --- /dev/null +++ b/airtime_mvc/public/css/TableTools.css @@ -0,0 +1,265 @@ +/* + * File: TableTools.css + * Description: Styles for TableTools 2 + * Author: Allan Jardine (www.sprymedia.co.uk) + * Language: Javascript + * License: LGPL / 3 point BSD + * Project: DataTables + * + * Copyright 2010 Allan Jardine, all rights reserved. + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * CSS name space: + * DTTT DataTables TableTools + * + * Colour dictionary: + * Button border #d0d0d0 + * Button border hover #999999 + * Hover background #f0f0f0 + * Action blue #4b66d9 + * + * Style sheet provides: + * CONTAINER TableTools container element and styles applying to all components + * BUTTON_STYLES Action specific button styles + * SELECTING Row selection styles + * COLLECTIONS Drop down list (collection) styles + * PRINTING Print display styles + * MISC Minor misc styles + */ + + +/* + * CONTAINER + * TableTools container element and styles applying to all components + */ +div.DTTT_container { + position: relative; + float: left; + margin-bottom: 1em; +} + +button.DTTT_button { + position: relative; + float: left; + height: 30px; + margin-right: 3px; + padding: 3px 5px; + border: 1px solid #d0d0d0; + background-color: #fff; + cursor: pointer; + *cursor: hand; +} + +button.DTTT_button::-moz-focus-inner { + border: none !important; + padding: 0; +} + + +/* + * BUTTON_STYLES + * Action specific button styles + */ + +button.DTTT_button_csv { + padding-right: 30px; + background: url(../images/csv.png) no-repeat center right; +} + +button.DTTT_button_csv_hover { + padding-right: 30px; + border: 1px solid #999; + background: #f0f0f0 url(../images/csv_hover.png) no-repeat center right; +} + + +button.DTTT_button_xls { + padding-right: 30px; + background: url(../images/xls.png) no-repeat center right; +} + +button.DTTT_button_xls_hover { + padding-right: 30px; + border: 1px solid #999; + background: #f0f0f0 url(../images/xls_hover.png) no-repeat center right; +} + + +button.DTTT_button_copy { + padding-right: 30px; + background: url(../images/copy.png) no-repeat center right; +} + +button.DTTT_button_copy_hover { + padding-right: 30px; + border: 1px solid #999; + background: #f0f0f0 url(../images/copy_hover.png) no-repeat center right; +} + + +button.DTTT_button_pdf { + padding-right: 30px; + background: url(../images/pdf.png) no-repeat center right; +} + +button.DTTT_button_pdf_hover { + padding-right: 30px; + border: 1px solid #999; + background: #f0f0f0 url(../images/pdf_hover.png) no-repeat center right; +} + + +button.DTTT_button_print { + padding-right: 30px; + background: url(../images/print.png) no-repeat center right; +} + +button.DTTT_button_print_hover { + padding-right: 30px; + border: 1px solid #999; + background: #f0f0f0 url(../images/print_hover.png) no-repeat center right; +} + + +button.DTTT_button_text { +} + +button.DTTT_button_text_hover { + border: 1px solid #999; + background-color: #f0f0f0; +} + + +button.DTTT_button_collection { + padding-right: 17px; + background: url(../images/collection.png) no-repeat center right; +} + +button.DTTT_button_collection_hover { + padding-right: 17px; + border: 1px solid #999; + background: #f0f0f0 url(../images/collection_hover.png) no-repeat center right; +} + + +/* + * SELECTING + * Row selection styles + */ +table.DTTT_selectable tbody tr { + cursor: pointer; + *cursor: hand; +} + +tr.DTTT_selected.odd { + background-color: #9FAFD1; +} + +tr.DTTT_selected.odd td.sorting_1 { + background-color: #9FAFD1; +} + +tr.DTTT_selected.odd td.sorting_2 { + background-color: #9FAFD1; +} + +tr.DTTT_selected.odd td.sorting_3 { + background-color: #9FAFD1; +} + + +tr.DTTT_selected.even { + background-color: #B0BED9; +} + +tr.DTTT_selected.even td.sorting_1 { + background-color: #B0BED9; +} + +tr.DTTT_selected.even td.sorting_2 { + background-color: #B0BED9; +} + +tr.DTTT_selected.even td.sorting_3 { + background-color: #B0BED9; +} + + +/* + * COLLECTIONS + * Drop down list (collection) styles + */ + +div.DTTT_collection { + width: 150px; + padding: 3px; + border: 1px solid #ccc; + background-color: #f3f3f3; + overflow: hidden; + z-index: 2002; +} + +div.DTTT_collection_background { + background: transparent url(../images/background.png) repeat top left; + z-index: 2001; +} + +div.DTTT_collection button.DTTT_button { + float: none; + width: 100%; + margin-bottom: 2px; + background-color: white; +} + + +/* + * PRINTING + * Print display styles + */ + +.DTTT_print_info { + position: absolute; + top: 50%; + left: 50%; + width: 400px; + height: 150px; + margin-left: -200px; + margin-top: -75px; + text-align: center; + background-color: #3f3f3f; + color: white; + padding: 10px 30px; + + opacity: 0.9; + + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.5); + -moz-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.5); + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.5); +} + +.DTTT_print_info h6 { + font-weight: normal; + font-size: 28px; + line-height: 28px; + margin: 1em; +} + +.DTTT_print_info p { + font-size: 14px; + line-height: 20px; +} + + +/* + * MISC + * Minor misc styles + */ + +.DTTT_disabled { + color: #999; +} diff --git a/airtime_mvc/public/css/TableTools_JUI.css b/airtime_mvc/public/css/TableTools_JUI.css new file mode 100755 index 000000000..95996ed2b --- /dev/null +++ b/airtime_mvc/public/css/TableTools_JUI.css @@ -0,0 +1,183 @@ +/* + * File: TableTools.css + * Description: Styles for TableTools 2 with JUI theming + * Author: Allan Jardine (www.sprymedia.co.uk) + * Language: Javascript + * License: LGPL / 3 point BSD + * Project: DataTables + * + * Copyright 2010 Allan Jardine, all rights reserved. + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * Notes: + * Generally speaking, please refer to the TableTools.css file - this file contains basic + * modifications to that 'master' stylesheet for ThemeRoller. + * + * CSS name space: + * DTTT DataTables TableTools + * + * Colour dictionary: + * Button border #d0d0d0 + * Button border hover #999999 + * Hover background #f0f0f0 + * Action blue #4b66d9 + * + * Style sheet provides: + * CONTAINER TableTools container element and styles applying to all components + * SELECTING Row selection styles + * COLLECTIONS Drop down list (collection) styles + * PRINTING Print display styles + * MISC Minor misc styles + */ + + +/* + * CONTAINER + * TableTools container element and styles applying to all components + */ +div.DTTT_container { + position: relative; + float: left; +} + +button.DTTT_button { + position: relative; + float: left; + height: 24px; + margin-right: 3px; + padding: 3px 10px; + border: 1px solid #d0d0d0; + background-color: #fff; + cursor: pointer; + *cursor: hand; +} + +button.DTTT_button::-moz-focus-inner { + border: none !important; + padding: 0; +} + + + +/* + * SELECTING + * Row selection styles + */ +table.DTTT_selectable tbody tr { + cursor: pointer; + *cursor: hand; +} + +tr.DTTT_selected.odd { + background-color: #9FAFD1; +} + +tr.DTTT_selected.odd td.sorting_1 { + background-color: #9FAFD1; +} + +tr.DTTT_selected.odd td.sorting_2 { + background-color: #9FAFD1; +} + +tr.DTTT_selected.odd td.sorting_3 { + background-color: #9FAFD1; +} + + +tr.DTTT_selected.even { + background-color: #B0BED9; +} + +tr.DTTT_selected.even td.sorting_1 { + background-color: #B0BED9; +} + +tr.DTTT_selected.even td.sorting_2 { + background-color: #B0BED9; +} + +tr.DTTT_selected.even td.sorting_3 { + background-color: #B0BED9; +} + + +/* + * COLLECTIONS + * Drop down list (collection) styles + */ + +div.DTTT_collection { + width: 150px; + background-color: #f3f3f3; + overflow: hidden; + z-index: 2002; + + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.5); + -moz-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.5); + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.5); +} + +div.DTTT_collection_background { + background: url(../images/background.png) repeat top left; + z-index: 2001; +} + +div.DTTT_collection button.DTTT_button { + float: none; + width: 100%; + margin-bottom: -0.1em; +} + + +/* + * PRINTING + * Print display styles + */ + +.DTTT_print_info { + position: absolute; + top: 50%; + left: 50%; + width: 400px; + height: 150px; + margin-left: -200px; + margin-top: -75px; + text-align: center; + background-color: #3f3f3f; + color: white; + padding: 10px 30px; + + opacity: 0.9; + + border-radius: 5px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.5); + -moz-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.5); + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.5); +} + +.DTTT_print_info h6 { + font-weight: normal; + font-size: 28px; + line-height: 28px; + margin: 1em; +} + +.DTTT_print_info p { + font-size: 14px; + line-height: 20px; +} + + +/* + * MISC + * Minor misc styles + */ + +.DTTT_disabled { + color: #999; +} diff --git a/airtime_mvc/public/js/airtime/library/events/library_playlistbuilder.js b/airtime_mvc/public/js/airtime/library/events/library_playlistbuilder.js index 2fcec1285..956eb2477 100644 --- a/airtime_mvc/public/js/airtime/library/events/library_playlistbuilder.js +++ b/airtime_mvc/public/js/airtime/library/events/library_playlistbuilder.js @@ -9,7 +9,7 @@ function fnLibraryTableDrawCallback() { addLibraryItemEvents(); addMetadataQtip(); //saveNumEntriesSetting(); - setupGroupActions(); + //setupGroupActions(); } function addLibraryItemEvents() { @@ -20,16 +20,23 @@ function addLibraryItemEvents() { cursor: 'pointer' }); + /* $('#library_display tbody tr td').not('[class=library_checkbox]') .jjmenu("click", [{get:"/Library/context-menu/format/json/id/#id#/type/#type#"}], {id: getId, type: getType}, {xposition: "mouse", yposition: "mouse"}); + */ } function setupLibraryToolbar() { - $("div.library_toolbar").html('Reset Order' + - 'Delete' + - 'Add'); + //[0] = button text + //[1] = id + //[2] = enabled + var aButtons = [["Reset Order", "library_order_reset", true], + ["Delete", "library_group_delete", false], + ["Add", "library_group_add", false]]; + + addToolBarButtonsLibrary(aButtons); } diff --git a/airtime_mvc/public/js/airtime/library/events/library_showbuilder.js b/airtime_mvc/public/js/airtime/library/events/library_showbuilder.js index d380578a0..e2c46ad85 100644 --- a/airtime_mvc/public/js/airtime/library/events/library_showbuilder.js +++ b/airtime_mvc/public/js/airtime/library/events/library_showbuilder.js @@ -21,14 +21,33 @@ function addLibraryItemEvents() { cursor: 'pointer', connectToSortable: '#show_builder_table' }); - - $('#library_display tbody tr td').not('[class=library_checkbox]') - .jjmenu("click", - [{get:"/Library/context-menu/format/json/id/#id#/type/#type#"}], - {id: getId, type: getType}, - {xposition: "mouse", yposition: "mouse"}); - } function setupLibraryToolbar() { + var aButtons, + fnTest, + fnAddSelectedItems; + + fnTest = function() { + alert("hi"); + }; + + fnAddSelectedItems = function() { + var oTT = TableTools.fnGetInstance('show_builder_table'), + aData = oTT.fnGetSelectedData(), + i, + length = aData.length; + + for (i=0, i'; + libToolBar.append(html); + libToolBar.find("#"+aButtons[i][1]).click(aButtons[i][3]); + } +} + +function enableGroupBtn(btnId, func) { + btnId = '#' + btnId; + if ($(btnId).hasClass('ui-state-disabled')) { + $(btnId).removeClass('ui-state-disabled'); + } +} + +function disableGroupBtn(btnId) { + btnId = '#' + btnId; + if (!$(btnId).hasClass('ui-state-disabled')) { + $(btnId).addClass('ui-state-disabled'); + } +} + function deleteItem(type, id) { var tr_id, tr, dt; @@ -34,14 +71,15 @@ function deleteAudioClip(json) { return; } - if (json.ids != undefined) { - for (var i = json.ids.length - 1; i >= 0; i--) { - deleteItem("au", json.ids[i]); - } - } else if (json.id != undefined) { - deleteItem("au", json.id); + if (json.ids != undefined) { + for (var i = json.ids.length - 1; i >= 0; i--) { + deleteItem("au", json.ids[i]); } - location.reload(true); + } + else if (json.id != undefined) { + deleteItem("au", json.id); + } + location.reload(true); } function confirmDeleteGroup() { @@ -50,28 +88,6 @@ function confirmDeleteGroup() { } } -//callbacks called by jjmenu -function confirmDeleteAudioClip(params){ - if(confirm('The file will be deleted from disk, are you sure you want to delete?')){ - var url = '/Library/delete' + params; - $.ajax({ - url: url, - success: deleteAudioClip - }); - } -} - -//callbacks called by jjmenu -function confirmDeletePlaylist(params){ - if(confirm('Are you sure you want to delete?')){ - var url = '/Playlist/delete' + params; - $.ajax({ - url: url, - success: deletePlaylist - }); - } -} - function openFileOnSoundCloud(link){ window.open(link); } @@ -102,7 +118,6 @@ function deletePlaylist(json) { } window.location.reload(); } -//end callbacks called by jjmenu function addProgressIcon(id) { if($("#au_"+id).find("td.library_title").find("span").length > 0){ @@ -277,184 +292,17 @@ function getNumEntriesPreference(data) { } function groupAdd() { - if (checkedPLCount > 0) { - alert("Can't add playlist to another playlist"); - return; - } - disableGroupBtn('library_group_add'); - - var ids = new Array(); - var addGroupUrl = '/Playlist/add-group'; - var newSPLUrl = '/Playlist/new/format/json'; - var dirty = true; - $('#library_display tbody tr').each(function() { - var idSplit = $(this).attr('id').split("_"); - var id = idSplit.pop(); - var type = idSplit.pop(); - if (dirty && $(this).find(":checkbox").attr("checked")) { - if (type == "au") { - ids.push(id); - } else if (type == "pl") { - alert("Can't add playlist to another playlist"); - dirty = false; - } - } - }); - - if (dirty && ids.length > 0) { - stopAudioPreview(); - - if ($('#spl_sortable').length == 0) { - $.post(newSPLUrl, function(json) { - openDiffSPL(json); - redrawDataTablePage(); - - $.post(addGroupUrl, {format: "json", ids: ids}, setSPLContent); - }); - } else { - $.post(addGroupUrl, {format: "json", ids: ids}, setSPLContent); - } - } + } function groupDelete() { - disableGroupBtn('library_group_delete'); - - var auIds = new Array(); - var plIds = new Array(); - var auUrl = '/Library/delete-group'; - var plUrl = '/Playlist/delete-group'; - var dirty = true; - $('#library_display tbody tr').each(function() { - var idSplit = $(this).attr('id').split("_"); - var id = idSplit.pop(); - var type = idSplit.pop(); - if (dirty && $(this).find(":checkbox").attr("checked")) { - if (type == "au") { - auIds.push(id); - } else if (type == "pl") { - plIds.push(id); - } - } - }); - - if (dirty && (auIds.length > 0 || plIds.length > 0)) { - stopAudioPreview(); - - if (auIds.length > 0) { - $.post(auUrl, {format: "json", ids: auIds}, deleteAudioClip); - } - if (plIds.length > 0) { - $.post(plUrl, {format: "json", ids: plIds}, deletePlaylist); - } - } -} - -function toggleAll() { - var checked = $(this).attr("checked"); - $('#library_display tr').each(function() { - var idSplit = $(this).attr('id').split("_"); - var type = idSplit[0]; - $(this).find(":checkbox").attr("checked", checked); - if (checked) { - if (type == "pl") { - checkedPLCount++; - } - $(this).addClass('selected'); - } else { - $(this).removeClass('selected'); - } - }); - - if (checked) { - checkedCount = $('#library_display tbody tr').size(); - enableGroupBtn('library_group_add', groupAdd); - enableGroupBtn('library_group_delete', confirmDeleteGroup); - } else { - checkedCount = 0; - checkedPLCount = 0; - disableGroupBtn('library_group_add'); - disableGroupBtn('library_group_delete'); - } -} - -function enableGroupBtn(btnId, func) { - btnId = '#' + btnId; - if ($(btnId).hasClass('ui-state-disabled')) { - $(btnId).removeClass('ui-state-disabled'); - $(btnId).unbind("click").click(func); - } -} - -function disableGroupBtn(btnId) { - btnId = '#' + btnId; - if (!$(btnId).hasClass('ui-state-disabled')) { - $(btnId).addClass('ui-state-disabled'); - $(btnId).unbind("click"); - } -} - -function checkBoxChanged() { - var cbAll = $('#library_display thead').find(":checkbox"); - var cbAllChecked = cbAll.attr("checked"); - var checked = $(this).attr("checked"); - var size = $('#library_display tbody tr').size(); - var idSplit = $(this).parent().parent().attr('id').split("_"); - var type = idSplit[0]; - if (checked) { - if (checkedCount < size) { - checkedCount++; - } - if (type == "pl" && checkedPLCount < size) { - checkedPLCount++; - } - enableGroupBtn('library_group_add', groupAdd); - enableGroupBtn('library_group_delete', confirmDeleteGroup); - $(this).parent().parent().addClass('selected'); - } else { - if (checkedCount > 0) { - checkedCount--; - } - if (type == "pl" && checkedPLCount > 0) { - checkedPLCount--; - } - if (checkedCount == 0) { - disableGroupBtn('library_group_add'); - disableGroupBtn('library_group_delete'); - } - $(this).parent().parent().removeClass('selected'); - } - - if (cbAllChecked && checkedCount < size) { - cbAll.attr("checked", false); - } else if (!cbAllChecked && checkedCount == size) { - cbAll.attr("checked", true); - } -} - -function setupGroupActions() { - checkedCount = 0; - checkedPLCount = 0; - $('#library_display tr:nth-child(1)').find(":checkbox").attr("checked", false); - $('#library_display thead').find(":checkbox").unbind('change').change(toggleAll); - $('#library_display tbody tr').each(function() { - $(this).find(":checkbox").unbind('change').change(checkBoxChanged); - }); - - disableGroupBtn('library_group_add'); - disableGroupBtn('library_group_delete'); -} - -function fnShowHide(iCol) { - /* Get the DataTables object again - this is not a recreation, just a get of the object */ - var oTable = dTable; - - var bVis = oTable.fnSettings().aoColumns[iCol].bVisible; - oTable.fnSetColumnVis( iCol, bVis ? false : true ); + } function createDataTable(data) { - dTable = $('#library_display').dataTable( { + var oTable; + + oTable = $('#library_display').dataTable( { "bProcessing": true, "bServerSide": true, "sAjaxSource": "/Library/contents", @@ -471,7 +319,7 @@ function createDataTable(data) { "fnRowCallback": fnLibraryTableRowCallback, "fnDrawCallback": fnLibraryTableDrawCallback, "aoColumns": [ - /* Checkbox */ {"sTitle": "", "bSortable": false, "bSearchable": false, "mDataProp": "checkbox", "sWidth": "25px", "sClass": "library_checkbox"}, + /* Checkbox */ {"sTitle": "", "bSortable": false, "bSearchable": false, "mDataProp": "checkbox", "sWidth": "25px", "sClass": "library_checkbox"}, /* Id */ {"sName": "id", "bSearchable": false, "bVisible": false, "mDataProp": "id", "sClass": "library_id"}, /* Title */ {"sTitle": "Title", "sName": "track_title", "mDataProp": "track_title", "sClass": "library_title"}, /* Creator */ {"sTitle": "Creator", "sName": "artist_name", "mDataProp": "artist_name", "sClass": "library_creator"}, @@ -493,7 +341,35 @@ function createDataTable(data) { "iDisplayLength": getNumEntriesPreference(data), // R = ColReorder, C = ColVis, see datatables doc for others - "sDom": 'Rlfr<"H"C<"library_toolbar">>t<"F"ip>', + "sDom": 'Rlfr<"H"T<"library_toolbar"C>>t<"F"ip>', + + "oTableTools": { + "sRowSelect": "multi", + "aButtons": [], + "fnRowSelected": function ( node ) { + var x; + + //seems to happen if everything is selected + if ( node === null) { + oTable.find("input[type=checkbox]").attr("checked", true); + } + else { + $(node).find("input[type=checkbox]").attr("checked", true); + } + }, + "fnRowDeselected": function ( node ) { + var x; + + //seems to happen if everything is deselected + if ( node === null) { + oTable.find("input[type=checkbox]").attr("checked", false); + } + else { + $(node).find("input[type=checkbox]").attr("checked", false); + } + } + }, + "oColVis": { "buttonText": "Show/Hide Columns", "sAlign": "right", @@ -502,14 +378,25 @@ function createDataTable(data) { "bShowAll": true } }); - dTable.fnSetFilteringDelay(350); + oTable.fnSetFilteringDelay(350); setupLibraryToolbar(); $('#library_order_reset').click(function() { - ColReorder.fnReset( dTable ); + ColReorder.fnReset( oTable ); return false; }); + + $('[name="pl_cb_all"]').click(function(){ + var oTT = TableTools.fnGetInstance('library_display'); + + if ($(this).is(":checked")) { + oTT.fnSelectAll(); + } + else { + oTT.fnSelectNone(); + } + }); } $(document).ready(function() { @@ -519,8 +406,8 @@ $(document).ready(function() { error:function(jqXHR, textStatus, errorThrown){}}); checkImportStatus(); - setInterval( "checkImportStatus()", 5000 ); - setInterval( "checkSCUploadStatus()", 5000 ); + //setInterval( "checkImportStatus()", 5000 ); + //setInterval( "checkSCUploadStatus()", 5000 ); addQtipToSCIcons(); }); diff --git a/airtime_mvc/public/js/airtime/showbuilder/builder.js b/airtime_mvc/public/js/airtime/showbuilder/builder.js index c0fc7f0a2..c294b25e5 100644 --- a/airtime_mvc/public/js/airtime/showbuilder/builder.js +++ b/airtime_mvc/public/js/airtime/showbuilder/builder.js @@ -1,189 +1,10 @@ -/* -function tpStartOnHourShowCallback(hour) { - var tpEndHour = $('#show_builder_timepicker_end').timepicker('getHour'); - - // Check if proposed hour is prior or equal to selected end time hour - if (hour <= tpEndHour) { return true; } - // if hour did not match, it can not be selected - return false; -} - -function tpStartOnMinuteShowCallback(hour, minute) { - var tpEndHour = $('#show_builder_timepicker_end').timepicker('getHour'), - tpEndMinute = $('#show_builder_timepicker_end').timepicker('getMinute'); - - // Check if proposed hour is prior to selected end time hour - if (hour < tpEndHour) { return true; } - // Check if proposed hour is equal to selected end time hour and minutes is prior - if ( (hour == tpEndHour) && (minute < tpEndMinute) ) { return true; } - // if minute did not match, it can not be selected - return false; -} - -function tpEndOnHourShowCallback(hour) { - var tpStartHour = $('#show_builder_timepicker_start').timepicker('getHour'); - - // Check if proposed hour is after or equal to selected start time hour - if (hour >= tpStartHour) { return true; } - // if hour did not match, it can not be selected - return false; -} - -function tpEndOnMinuteShowCallback(hour, minute) { - var tpStartHour = $('#show_builder_timepicker_start').timepicker('getHour'), - tpStartMinute = $('#show_builder_timepicker_start').timepicker('getMinute'); - - // Check if proposed hour is after selected start time hour - if (hour > tpStartHour) { return true; } - // Check if proposed hour is equal to selected start time hour and minutes is after - if ( (hour == tpStartHour) && (minute > tpStartMinute) ) { return true; } - // if minute did not match, it can not be selected - return false; -} -*/ - -/* - * Get the schedule range start in unix timestamp form (in seconds). - * defaults to NOW if nothing is selected. - * - * @param String sDatePickerId - * - * @param String sTimePickerId - * - * @return Number iTime - */ -function fnGetUIPickerUnixTimestamp(sDatePickerId, sTimePickerId) { - var oDate, - oTimePicker = $( sTimePickerId ), - iTime, - iHour, - iMin, - iServerOffset, - iClientOffset; - - oDate = $( sDatePickerId ).datepicker( "getDate" ); - - //nothing has been selected from this datepicker. - if (oDate === null) { - oDate = new Date(); - } - else { - iHour = oTimePicker.timepicker('getHour'); - iMin = oTimePicker.timepicker('getMinute'); - - oDate.setHours(iHour, iMin); - } - - iTime = oDate.getTime(); //value is in millisec. - iTime = Math.round(iTime / 1000); - iServerOffset = serverTimezoneOffset; - iClientOffset = oDate.getTimezoneOffset() * 60;//function returns minutes - - //adjust for the fact the the Date object is - iTime = iTime + iServerOffset + iClientOffset; - - return iTime; -} -/* - * Returns an object containing a unix timestamp in seconds for the start/end range - * - * @return Object {"start", "end", "range"} - */ -function fnGetScheduleRange() { - var iStart, - iEnd, - iRange, - MIN_RANGE = 60*60*24; - - iStart = fnGetUIPickerUnixTimestamp("#show_builder_datepicker_start", "#show_builder_timepicker_start"); - iEnd = fnGetUIPickerUnixTimestamp("#show_builder_datepicker_end", "#show_builder_timepicker_end"); - - iRange = iEnd - iStart; - - //return min range - if (iRange < MIN_RANGE){ - iEnd = iStart + MIN_RANGE; - iRange = MIN_RANGE; - } - - return { - start: iStart, - end: iEnd, - range: iRange - }; -} - -var fnServerData = function fnServerData( sSource, aoData, fnCallback ) { - aoData.push( { name: "format", value: "json"} ); - - if (fnServerData.hasOwnProperty("start")) { - aoData.push( { name: "start", value: fnServerData.start} ); - } - if (fnServerData.hasOwnProperty("end")) { - aoData.push( { name: "end", value: fnServerData.end} ); - } - - $.ajax( { - "dataType": "json", - "type": "GET", - "url": sSource, - "data": aoData, - "success": fnCallback - } ); -}; - -var fnShowBuilderRowCallback = function ( nRow, aData, iDisplayIndex, iDisplayIndexFull ){ - var i, - sSeparatorHTML, - fnPrepareSeparatorRow, - node; - - //save some info for reordering purposes. - $(nRow).data({aData: aData}); - - fnPrepareSeparatorRow = function(sRowContent, sClass) { - - node = nRow.children[1]; - node.innerHTML = sRowContent; - node.setAttribute('colspan',100); - for (i = 2; i < nRow.children.length; i = i+1) { - node = nRow.children[i]; - node.innerHTML = ""; - node.setAttribute("style", "display : none"); - } - - nRow.className = sClass; - }; - - if (aData.header === true) { - node = nRow.children[0]; - node.innerHTML = ''; - - sSeparatorHTML = ''+aData.title+''+aData.starts+''+aData.ends+''; - fnPrepareSeparatorRow(sSeparatorHTML, "show-builder-header"); - } - else if (aData.footer === true) { - - node = nRow.children[0]; - node.innerHTML = ''; - - sSeparatorHTML = 'Show Footer'; - fnPrepareSeparatorRow(sSeparatorHTML, "show-builder-footer"); - } - else if (aData.empty === true) { - - } - else { - $(nRow).attr("id", "sched_"+aData.id); - } - - return nRow; -}; - $(document).ready(function() { - var oTable, + var tableDiv = $('#show_builder_table'), + oTable, oBaseDatePickerSettings, - oBaseTimePickerSettings; + oBaseTimePickerSettings, + fnAddSelectedItems, + fnRemoveSelectedItems; oBaseDatePickerSettings = { dateFormat: 'yy-mm-dd', @@ -203,9 +24,178 @@ $(document).ready(function() { defaultTime: '0:00' }; - oTable = $('#show_builder_table').dataTable( { + /* + * Get the schedule range start in unix timestamp form (in seconds). + * defaults to NOW if nothing is selected. + * + * @param String sDatePickerId + * + * @param String sTimePickerId + * + * @return Number iTime + */ + function fnGetUIPickerUnixTimestamp(sDatePickerId, sTimePickerId) { + var oDate, + oTimePicker = $( sTimePickerId ), + iTime, + iHour, + iMin, + iServerOffset, + iClientOffset; + + oDate = $( sDatePickerId ).datepicker( "getDate" ); + + //nothing has been selected from this datepicker. + if (oDate === null) { + oDate = new Date(); + } + else { + iHour = oTimePicker.timepicker('getHour'); + iMin = oTimePicker.timepicker('getMinute'); + + oDate.setHours(iHour, iMin); + } + + iTime = oDate.getTime(); //value is in millisec. + iTime = Math.round(iTime / 1000); + iServerOffset = serverTimezoneOffset; + iClientOffset = oDate.getTimezoneOffset() * 60;//function returns minutes + + //adjust for the fact the the Date object is + iTime = iTime + iServerOffset + iClientOffset; + + return iTime; + } + /* + * Returns an object containing a unix timestamp in seconds for the start/end range + * + * @return Object {"start", "end", "range"} + */ + function fnGetScheduleRange() { + var iStart, + iEnd, + iRange, + MIN_RANGE = 60*60*24; + + iStart = fnGetUIPickerUnixTimestamp("#show_builder_datepicker_start", "#show_builder_timepicker_start"); + iEnd = fnGetUIPickerUnixTimestamp("#show_builder_datepicker_end", "#show_builder_timepicker_end"); + + iRange = iEnd - iStart; + + //return min range + if (iRange < MIN_RANGE){ + iEnd = iStart + MIN_RANGE; + iRange = MIN_RANGE; + } + + return { + start: iStart, + end: iEnd, + range: iRange + }; + } + + var fnServerData = function ( sSource, aoData, fnCallback ) { + aoData.push( { name: "format", value: "json"} ); + + if (fnServerData.hasOwnProperty("start")) { + aoData.push( { name: "start", value: fnServerData.start} ); + } + if (fnServerData.hasOwnProperty("end")) { + aoData.push( { name: "end", value: fnServerData.end} ); + } + + $.ajax( { + "dataType": "json", + "type": "GET", + "url": sSource, + "data": aoData, + "success": fnCallback + } ); + }; + + var fnShowBuilderRowCallback = function ( nRow, aData, iDisplayIndex, iDisplayIndexFull ){ + var i, + sSeparatorHTML, + fnPrepareSeparatorRow, + node; + + //save some info for reordering purposes. + $(nRow).data({aData: aData}); + + fnPrepareSeparatorRow = function(sRowContent, sClass) { + + node = nRow.children[1]; + node.innerHTML = sRowContent; + node.setAttribute('colspan',100); + for (i = 2; i < nRow.children.length; i = i+1) { + node = nRow.children[i]; + node.innerHTML = ""; + node.setAttribute("style", "display : none"); + } + + nRow.className = sClass; + }; + + if (aData.header === true) { + node = nRow.children[0]; + node.innerHTML = ''; + + sSeparatorHTML = ''+aData.title+''+aData.starts+''+aData.ends+''; + fnPrepareSeparatorRow(sSeparatorHTML, "show-builder-header"); + } + else if (aData.footer === true) { + + node = nRow.children[0]; + node.innerHTML = ''; + + sSeparatorHTML = 'Show Footer'; + fnPrepareSeparatorRow(sSeparatorHTML, "show-builder-footer"); + } + else if (aData.empty === true) { + + } + else { + $(nRow).attr("id", "sched_"+aData.id); + + node = nRow.children[0]; + if (aData.checkbox === true) { + node.innerHTML = ''; + } + else { + node.innerHTML = ''; + + $(nRow).addClass("show-builder-not-allowed"); + } + } + + return nRow; + }; + + fnRemoveSelectedItems = function() { + var oTT = TableTools.fnGetInstance('show_builder_table'), + aData = oTT.fnGetSelectedData(), + item, + temp, + ids = []; + + for (item in aData) { + temp = aData[item]; + if (temp !== null && temp.hasOwnProperty('id')) { + ids.push(temp.id); + } + } + + $.post( "/showbuilder/schedule-remove", + {"ids": ids, "format": "json"}, + function(data) { + var x; + }); + }; + + oTable = tableDiv.dataTable( { "aoColumns": [ - /* checkbox */ {"mDataProp": "checkbox", "sTitle": "", "sWidth": "25px"}, + /* checkbox */ {"mDataProp": "checkbox", "sTitle": "", "sWidth": "15px"}, // /* scheduled id */{"mDataProp": "id", "sTitle": "id"}, // /* instance */{"mDataProp": "instance", "sTitle": "si_id"}, /* starts */{"mDataProp": "starts", "sTitle": "Airtime"}, @@ -233,8 +223,35 @@ $(document).ready(function() { "aiExclude": [ 0, 1 ] }, + "oTableTools": { + "sRowSelect": "multi", + "aButtons": [], + "fnRowSelected": function ( node ) { + var x; + + //seems to happen if everything is selected + if ( node === null) { + oTable.find("input[type=checkbox]").attr("checked", true); + } + else { + $(node).find("input[type=checkbox]").attr("checked", true); + } + }, + "fnRowDeselected": function ( node ) { + var x; + + //seems to happen if everything is deselected + if ( node === null) { + oTable.find("input[type=checkbox]").attr("checked", false); + } + else { + $(node).find("input[type=checkbox]").attr("checked", false); + } + } + }, + // R = ColReorder, C = ColVis, see datatables doc for others - "sDom": 'Rr<"H"C>t<"F">', + "sDom": 'Rr<"H"CT<"#show_builder_toolbar">>t<"F">', //options for infinite scrolling //"bScrollInfinite": true, @@ -246,6 +263,17 @@ $(document).ready(function() { }); + $('[name="sb_cb_all"]').click(function(){ + var oTT = TableTools.fnGetInstance('show_builder_table'); + + if ($(this).is(":checked")) { + oTT.fnSelectAll(); + } + else { + oTT.fnSelectNone(); + } + }); + $( "#show_builder_datepicker_start" ).datepicker(oBaseDatePickerSettings); $( "#show_builder_timepicker_start" ).timepicker(oBaseTimePickerSettings); @@ -255,13 +283,11 @@ $(document).ready(function() { $( "#show_builder_timepicker_end" ).timepicker(oBaseTimePickerSettings); $( "#show_builder_timerange_button" ).click(function(ev){ - var oTable, - oSettings, + var oSettings, oRange; oRange = fnGetScheduleRange(); - oTable = $('#show_builder_table').dataTable({"bRetrieve": true}); oSettings = oTable.fnSettings(); oSettings.fnServerData.start = oRange.start; oSettings.fnServerData.end = oRange.end; @@ -269,7 +295,7 @@ $(document).ready(function() { oTable.fnDraw(); }); - $( "#show_builder_table" ).sortable({ + tableDiv.sortable({ placeholder: "placeholder show-builder-placeholder", forceHelperSize: true, forcePlaceholderSize: true, @@ -307,4 +333,9 @@ $(document).ready(function() { } }); + $("#show_builder_toolbar") + .append('') + .find(".ui-icon-trash") + .click(fnRemoveSelectedItems); + }); diff --git a/airtime_mvc/public/js/datatables/plugin/dataTables.TableTools.js b/airtime_mvc/public/js/datatables/plugin/dataTables.TableTools.js new file mode 100755 index 000000000..3e02c2c08 --- /dev/null +++ b/airtime_mvc/public/js/datatables/plugin/dataTables.TableTools.js @@ -0,0 +1,2569 @@ +/* + * File: TableTools.js + * Version: 2.0.2 + * Description: Tools and buttons for DataTables + * Author: Allan Jardine (www.sprymedia.co.uk) + * Language: Javascript + * License: GPL v2 or BSD 3 point style + * Project: DataTables + * + * Copyright 2009-2012 Allan Jardine, all rights reserved. + * + * This source file is free software, under either the GPL v2 license or a + * BSD style license, available at: + * http://datatables.net/license_gpl2 + * http://datatables.net/license_bsd + */ + +/* Global scope for TableTools */ +var TableTools; + +(function($, window, document) { + +/** + * TableTools provides flexible buttons and other tools for a DataTables enhanced table + * @class TableTools + * @constructor + * @param {Object} oDT DataTables instance + * @param {Object} oOpts TableTools options + * @param {String} oOpts.sSwfPath ZeroClipboard SWF path + * @param {String} oOpts.sRowSelect Row selection options - 'none', 'single' or 'multi' + * @param {Function} oOpts.fnPreRowSelect Callback function just prior to row selection + * @param {Function} oOpts.fnRowSelected Callback function just after row selection + * @param {Function} oOpts.fnRowDeselected Callback function when row is deselected + * @param {Array} oOpts.aButtons List of buttons to be used + */ +TableTools = function( oDT, oOpts ) +{ + /* Santiy check that we are a new instance */ + if ( !this.CLASS || this.CLASS != "TableTools" ) + { + alert( "Warning: TableTools must be initialised with the keyword 'new'" ); + } + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Public class variables + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + /** + * @namespace Settings object which contains customisable information for TableTools instance + */ + this.s = { + /** + * Store 'this' so the instance can be retreieved from the settings object + * @property that + * @type object + * @default this + */ + "that": this, + + /** + * DataTables settings objects + * @property dt + * @type object + * @default null + */ + "dt": null, + + /** + * @namespace Print specific information + */ + "print": { + /** + * DataTables draw 'start' point before the printing display was shown + * @property saveStart + * @type int + * @default -1 + */ + "saveStart": -1, + + /** + * DataTables draw 'length' point before the printing display was shown + * @property saveLength + * @type int + * @default -1 + */ + "saveLength": -1, + + /** + * Page scrolling point before the printing display was shown so it can be restored + * @property saveScroll + * @type int + * @default -1 + */ + "saveScroll": -1, + + /** + * Wrapped function to end the print display (to maintain scope) + * @property funcEnd + * @type Function + * @default function () {} + */ + "funcEnd": function () {} + }, + + /** + * A unique ID is assigned to each button in each instance + * @property buttonCounter + * @type int + * @default 0 + */ + "buttonCounter": 0, + + /** + * @namespace Select rows specific information + */ + "select": { + /** + * Select type - can be 'none', 'single' or 'multi' + * @property type + * @type string + * @default "" + */ + "type": "", + + /** + * Array of nodes which are currently selected + * @property selected + * @type array + * @default [] + */ + "selected": [], + + /** + * Function to run before the selection can take place. Will cancel the select if the + * function returns false + * @property preRowSelect + * @type Function + * @default null + */ + "preRowSelect": null, + + /** + * Function to run when a row is selected + * @property postSelected + * @type Function + * @default null + */ + "postSelected": null, + + /** + * Function to run when a row is deselected + * @property postDeselected + * @type Function + * @default null + */ + "postDeselected": null, + + /** + * Indicate if all rows are selected (needed for server-side processing) + * @property all + * @type boolean + * @default false + */ + "all": false, + + /** + * Class name to add to selected TR nodes + * @property selectedClass + * @type String + * @default "" + */ + "selectedClass": "" + }, + + /** + * Store of the user input customisation object + * @property custom + * @type object + * @default {} + */ + "custom": {}, + + /** + * SWF movie path + * @property swfPath + * @type string + * @default "" + */ + "swfPath": "", + + /** + * Default button set + * @property buttonSet + * @type array + * @default [] + */ + "buttonSet": [], + + /** + * When there is more than one TableTools instance for a DataTable, there must be a + * master which controls events (row selection etc) + * @property master + * @type boolean + * @default false + */ + "master": false + }; + + + /** + * @namespace Common and useful DOM elements for the class instance + */ + this.dom = { + /** + * DIV element that is create and all TableTools buttons (and their children) put into + * @property container + * @type node + * @default null + */ + "container": null, + + /** + * The table node to which TableTools will be applied + * @property table + * @type node + * @default null + */ + "table": null, + + /** + * @namespace Nodes used for the print display + */ + "print": { + /** + * Nodes which have been removed from the display by setting them to display none + * @property hidden + * @type array + * @default [] + */ + "hidden": [], + + /** + * The information display saying tellng the user about the print display + * @property message + * @type node + * @default null + */ + "message": null + }, + + /** + * @namespace Nodes used for a collection display. This contains the currently used collection + */ + "collection": { + /** + * The div wrapper containing the buttons in the collection (i.e. the menu) + * @property collection + * @type node + * @default null + */ + "collection": null, + + /** + * Background display to provide focus and capture events + * @property background + * @type node + * @default null + */ + "background": null + } + }; + + + + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Public class methods + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + /** + * Retreieve the settings object from an instance + * @method fnSettings + * @returns {object} TableTools settings object + */ + this.fnSettings = function () { + return this.s; + }; + + + /* Constructor logic */ + if ( typeof oOpts == 'undefined' ) + { + oOpts = {}; + } + + this.s.dt = oDT.fnSettings(); + this._fnConstruct( oOpts ); + + return this; +}; + + + +TableTools.prototype = { + /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Public methods + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + /** + * Retreieve the settings object from an instance + * @method fnGetSelected + * @returns {array} List of TR nodes which are currently selected + */ + "fnGetSelected": function () + { + var masterS = this._fnGetMasterSettings(); + return masterS.select.selected; + }, + + + /** + * Get the data source objects/arrays from DataTables for the selected rows (same as + * fnGetSelected followed by fnGetData on each row from the table) + * @method fnGetSelectedData + * @returns {array} Data from the TR nodes which are currently selected + */ + "fnGetSelectedData": function () + { + var masterS = this._fnGetMasterSettings(); + var selected = masterS.select.selected; + var out = []; + + for ( var i=0, iLen=selected.length ; i 0 ) + { + sTitle = anTitle[0].innerHTML; + } + } + + /* Strip characters which the OS will object to - checking for UTF8 support in the scripting + * engine + */ + if ( "\u00A1".toString().length < 4 ) { + return sTitle.replace(/[^a-zA-Z0-9_\u00A1-\uFFFF\.,\-_ !\(\)]/g, ""); + } else { + return sTitle.replace(/[^a-zA-Z0-9_\.,\-_ !\(\)]/g, ""); + } + }, + + + /** + * Calculate a unity array with the column width by proportion for a set of columns to be + * included for a button. This is particularly useful for PDF creation, where we can use the + * column widths calculated by the browser to size the columns in the PDF. + * @method fnCalcColRations + * @param {Object} oConfig Button configuration object + * @returns {Array} Unity array of column ratios + */ + "fnCalcColRatios": function ( oConfig ) + { + var + aoCols = this.s.dt.aoColumns, + aColumnsInc = this._fnColumnTargets( oConfig.mColumns ), + aColWidths = [], + iWidth = 0, iTotal = 0, i, iLen; + + for ( i=0, iLen=aColumnsInc.length ; i