diff --git a/airtime_mvc/application/Bootstrap.php b/airtime_mvc/application/Bootstrap.php
index 4a5157f1e..f16183157 100644
--- a/airtime_mvc/application/Bootstrap.php
+++ b/airtime_mvc/application/Bootstrap.php
@@ -130,9 +130,9 @@ class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
protected function _initTasks() {
/* We need to wrap this here so that we aren't checking when we're running the unit test suite
*/
- $taskManager = TaskManager::getInstance();
- $taskManager->runTask(AirtimeTask::UPGRADE); // Run the upgrade on each request (if it needs to be run)
if (getenv("AIRTIME_UNIT_TEST") != 1) {
+ $taskManager = TaskManager::getInstance();
+ $taskManager->runTask(AirtimeTask::UPGRADE); // Run the upgrade on each request (if it needs to be run)
//This will do the upgrade too if it's needed...
$taskManager->runTasks();
}
diff --git a/airtime_mvc/application/configs/ACL.php b/airtime_mvc/application/configs/ACL.php
index 07ca7d822..39bba31ae 100644
--- a/airtime_mvc/application/configs/ACL.php
+++ b/airtime_mvc/application/configs/ACL.php
@@ -24,6 +24,7 @@ $ccAcl->add(new Zend_Acl_Resource('library'))
->add(new Zend_Acl_Resource('dashboard'))
->add(new Zend_Acl_Resource('preference'))
->add(new Zend_Acl_Resource('showbuilder'))
+ ->add(new Zend_Acl_Resource('show-builder'))
->add(new Zend_Acl_Resource('playouthistory'))
->add(new Zend_Acl_Resource('playouthistorytemplate'))
->add(new Zend_Acl_Resource('listenerstat'))
@@ -49,6 +50,7 @@ $ccAcl->allow('G', 'index')
->allow('G', 'error')
->allow('G', 'user', 'edit-user')
->allow('G', 'showbuilder')
+ ->allow('G', 'show-builder')
->allow('G', 'api')
->allow('G', 'schedule')
->allow('G', 'dashboard')
diff --git a/airtime_mvc/application/controllers/LibraryController.php b/airtime_mvc/application/controllers/LibraryController.php
index 2ad032973..d0f7f0f09 100644
--- a/airtime_mvc/application/controllers/LibraryController.php
+++ b/airtime_mvc/application/controllers/LibraryController.php
@@ -11,6 +11,7 @@ class LibraryController extends Zend_Controller_Action
{
$ajaxContext = $this->_helper->getHelper('AjaxContext');
$ajaxContext->addActionContext('contents-feed', 'json')
+ ->addActionContext('contents-feed-test', 'json')
->addActionContext('delete', 'json')
->addActionContext('duplicate', 'json')
->addActionContext('delete-group', 'json')
@@ -425,6 +426,19 @@ class LibraryController extends Zend_Controller_Action
$this->view->files = SecurityHelper::htmlescape_recursive($r["aaData"]);
}
+ public function contentsFeedTestAction()
+ {
+ $params = $this->getRequest()->getParams();
+
+ # terrible name for the method below. it does not only search files.
+ $r = Application_Model_StoredFile::searchLibraryFiles($params);
+
+ $this->view->sEcho = $r["sEcho"];
+ $this->view->iTotalDisplayRecords = $r["iTotalDisplayRecords"];
+ $this->view->iTotalRecords = $r["iTotalRecords"];
+ $this->view->files = SecurityHelper::htmlescape_recursive($r["aaData"]);
+ }
+
public function editFileMdAction()
{
$user = Application_Model_User::getCurrentUser();
diff --git a/airtime_mvc/application/controllers/ShowBuilderController.php b/airtime_mvc/application/controllers/ShowBuilderController.php
new file mode 100644
index 000000000..c5cd87818
--- /dev/null
+++ b/airtime_mvc/application/controllers/ShowBuilderController.php
@@ -0,0 +1,52 @@
+getType();
+
+ $this->view->headScript()->appendScript("localStorage.setItem( 'user-type', '$userType' );");
+ $this->view->headScript()->appendScript(Application_Common_GoogleAnalytics::generateGoogleTagManagerDataLayerJavaScript());
+
+ $this->view->headScript()->appendFile($baseUrl.'js/contextmenu/jquery.contextMenu.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
+ $this->view->headScript()->appendFile($baseUrl.'js/datatables/js/jquery.dataTables.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
+ $this->view->headScript()->appendFile($baseUrl.'js/datatables/plugin/dataTables.pluginAPI.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
+ $this->view->headScript()->appendFile($baseUrl.'js/datatables/plugin/dataTables.fnSetFilteringDelay.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
+ $this->view->headScript()->appendFile($baseUrl.'js/datatables/plugin/dataTables.ColVis.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
+ $this->view->headScript()->appendFile($baseUrl.'js/datatables/plugin/dataTables.FixedColumns.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
+ $this->view->headScript()->appendFile($baseUrl.'js/datatables/plugin/dataTables.columnFilter.js?'.$CC_CONFIG['airtime_version'], 'text/javascript');
+
+ $this->view->headScript()->appendFile($baseUrl.'js/blockui/jquery.blockUI.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
+ $this->view->headScript()->appendFile($baseUrl.'js/airtime/buttons/buttons.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
+ $this->view->headScript()->appendFile($baseUrl.'js/airtime/utilities/utilities.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
+
+ $this->view->headLink()->appendStylesheet($baseUrl.'css/media_library.css?'.$CC_CONFIG['airtime_version']);
+ $this->view->headLink()->appendStylesheet($baseUrl.'css/jquery.contextMenu.css?'.$CC_CONFIG['airtime_version']);
+ $this->view->headLink()->appendStylesheet($baseUrl.'css/datatables/css/ColVis.css?'.$CC_CONFIG['airtime_version']);
+ $this->view->headLink()->appendStylesheet($baseUrl.'css/datatables/css/ColReorder.css?'.$CC_CONFIG['airtime_version']);
+ $this->view->headScript()->appendFile($baseUrl.'js/airtime/library/library-test.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
+ $this->view->headScript()->appendFile($baseUrl.'js/airtime/library/events/library_showbuilder.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
+
+ // PLUPLOAD
+ $this->view->headScript()->appendFile($baseUrl.'js/libs/dropzone.min.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
+ $this->view->headLink()->appendStylesheet($baseUrl.'css/dropzone/dropzone.min.css?'.$CC_CONFIG['airtime_version']);
+
+ $this->view->headScript()->appendFile($baseUrl.'js/timepicker/jquery.ui.timepicker.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
+ $this->view->headScript()->appendFile($baseUrl.'js/airtime/showbuilder/builder_test.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
+ $this->view->headScript()->appendFile($baseUrl.'js/airtime/showbuilder/main_builder_test.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
+
+ $this->view->headLink()->appendStylesheet($baseUrl.'css/jquery.ui.timepicker.css?'.$CC_CONFIG['airtime_version']);
+ $this->view->headLink()->appendStylesheet($baseUrl.'css/showbuilder.css?'.$CC_CONFIG['airtime_version']);
+
+ $csrf_namespace = new Zend_Session_Namespace('csrf_namespace');
+ $csrf_element = new Zend_Form_Element_Hidden('csrf');
+ $csrf_element->setValue($csrf_namespace->authtoken)->setRequired('true')->removeDecorator('HtmlTag')->removeDecorator('Label');
+ $this->view->csrf = $csrf_element;
+ }
+
+}
diff --git a/airtime_mvc/application/models/StoredFile.php b/airtime_mvc/application/models/StoredFile.php
index e975ccd8c..5d92dd54d 100644
--- a/airtime_mvc/application/models/StoredFile.php
+++ b/airtime_mvc/application/models/StoredFile.php
@@ -907,6 +907,112 @@ SQL;
return $results;
}
+ public static function searchLibraryFilesTest($datatables)
+ {
+ $con = Propel::getConnection(CcFilesPeer::DATABASE_NAME);
+ $displayColumns = self::getLibraryColumns();
+
+ $fileSelect = array();
+ foreach ($displayColumns as $key) {
+ if ($key === "id") {
+ $fileSelect[] = "FILES.id AS $key";
+ } elseif ($key === "owner_id") {
+ $fileSelect[] = "sub.login AS $key";
+ } //file length is displayed based on cueout - cuein.
+ else if ($key === "length") {
+ $fileSelect[] = "(cueout - cuein)::INTERVAL AS length";
+ } elseif ($key === "year") {
+ $fileSelect[] = "year AS ".$key;
+ } else {
+ $fileSelect[] = $key;
+ }
+ }
+
+ $fileSelect = "SELECT ". join(",", $fileSelect);
+ $fileTable = "({$fileSelect} FROM cc_files AS FILES LEFT JOIN cc_subjs AS sub ON (sub.id = FILES.owner_id) WHERE file_exists = 'TRUE' AND hidden='FALSE')";
+ $fromTable = $fileTable." AS File"; //need an alias for the table if it's standalone.
+
+ // update is_scheduled to false for tracks that
+ // have already played out
+ self::updatePastFilesIsScheduled();
+ $results = Application_Model_Datatables::findEntries($con, $displayColumns, $fromTable, $datatables);
+
+ $displayTimezone = new DateTimeZone(Application_Model_Preference::GetUserTimezone());
+ $utcTimezone = new DateTimeZone("UTC");
+
+ foreach ($results['aaData'] as &$row) {
+ $row['id'] = intval($row['id']);
+
+ //taken from Datatables.php, needs to be cleaned up there.
+ if (isset($r['ftype'])) {
+ if ($r['ftype'] == 'playlist') {
+ $pl = new Application_Model_Playlist($r['id']);
+ $r['length'] = $pl->getLength();
+ } elseif ($r['ftype'] == "block") {
+ $bl = new Application_Model_Block($r['id']);
+ $r['bl_type'] = $bl->isStatic() ? 'static' : 'dynamic';
+ $r['length'] = $bl->getLength();
+ }
+ }
+
+ if ($row['ftype'] === "audioclip") {
+
+ $cuein_formatter = new LengthFormatter($row["cuein"]);
+ $row["cuein"] = $cuein_formatter->format();
+
+ $cueout_formatter = new LengthFormatter($row["cueout"]);
+ $row["cueout"] = $cueout_formatter->format();
+
+ $cuein = Application_Common_DateHelper::playlistTimeToSeconds($row["cuein"]);
+ $cueout = Application_Common_DateHelper::playlistTimeToSeconds($row["cueout"]);
+ $row_length = Application_Common_DateHelper::secondsToPlaylistTime($cueout - $cuein);
+
+ $formatter = new SamplerateFormatter($row['sample_rate']);
+ $row['sample_rate'] = $formatter->format();
+
+ $formatter = new BitrateFormatter($row['bit_rate']);
+ $row['bit_rate'] = $formatter->format();
+
+ // for audio preview
+ $row['audioFile'] = $row['id'].".".pathinfo($row['filepath'], PATHINFO_EXTENSION);
+
+ }
+ else {
+
+ $row['audioFile'] = $row['id'];
+ $row_length = $row['length'];
+ }
+
+ $len_formatter = new LengthFormatter($row_length);
+ $row['length'] = $len_formatter->format();
+
+ //convert mtime and utime to localtime
+ $row['mtime'] = new DateTime($row['mtime'], $utcTimezone);
+ $row['mtime']->setTimeZone($displayTimezone);
+ $row['mtime'] = $row['mtime']->format(DEFAULT_TIMESTAMP_FORMAT);
+ $row['utime'] = new DateTime($row['utime'], $utcTimezone);
+ $row['utime']->setTimeZone($displayTimezone);
+ $row['utime'] = $row['utime']->format(DEFAULT_TIMESTAMP_FORMAT);
+
+ //need to convert last played to localtime if it exists.
+ if (isset($row['lptime'])) {
+ $row['lptime'] = new DateTime($row['lptime'], $utcTimezone);
+ $row['lptime']->setTimeZone($displayTimezone);
+ $row['lptime'] = $row['lptime']->format(DEFAULT_TIMESTAMP_FORMAT);
+ }
+
+ // we need to initalize the checkbox and image row because we do not retrieve
+ // any data from the db for these and datatables will complain
+ $row['checkbox'] = "";
+ $row['image'] = "";
+
+ $type = substr($row['ftype'], 0, 2);
+ $row['tr_id'] = "{$type}_{$row['id']}";
+ }
+
+ return $results;
+ }
+
/**
* Copy a newly uploaded audio file from its temporary upload directory
* on the local disk (like /tmp) over to Airtime's "stor" directory,
diff --git a/airtime_mvc/application/views/scripts/show-builder/index.phtml b/airtime_mvc/application/views/scripts/show-builder/index.phtml
new file mode 100644
index 000000000..5d4b7abd1
--- /dev/null
+++ b/airtime_mvc/application/views/scripts/show-builder/index.phtml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+ render('widgets/lib-table.phtml') ?>
+
+
+
+dialog ?>
diff --git a/airtime_mvc/application/views/scripts/widgets/lib-table.phtml b/airtime_mvc/application/views/scripts/widgets/lib-table.phtml
new file mode 100644
index 000000000..894620a71
--- /dev/null
+++ b/airtime_mvc/application/views/scripts/widgets/lib-table.phtml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
diff --git a/airtime_mvc/build/sql/defaultdata.sql b/airtime_mvc/build/sql/defaultdata.sql
index 30fd8d765..bed25b869 100644
--- a/airtime_mvc/build/sql/defaultdata.sql
+++ b/airtime_mvc/build/sql/defaultdata.sql
@@ -378,7 +378,6 @@ INSERT INTO cc_stream_setting (keyname, value, type) VALUES ('s4_channels', 'ste
-- added in 2.5.14 - this can't be set up in Propel's XML schema, so we need to do it here -- Duncan
-ALTER TABLE cc_pref ALTER COLUMN subjid SET NULL;
ALTER TABLE cc_pref ALTER COLUMN subjid SET DEFAULT NULL;
CREATE UNIQUE INDEX cc_pref_key_idx ON cc_pref (keystr) WHERE subjid IS NULL;
ANALYZE cc_pref; -- this validates the new partial index
diff --git a/airtime_mvc/public/css/dropzone/dropzone.min.css b/airtime_mvc/public/css/dropzone/dropzone.min.css
new file mode 100644
index 000000000..d04515e27
--- /dev/null
+++ b/airtime_mvc/public/css/dropzone/dropzone.min.css
@@ -0,0 +1 @@
+@-webkit-keyframes passing-through{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%, 70%{opacity:1;-webkit-transform:translateY(0px);-moz-transform:translateY(0px);-ms-transform:translateY(0px);-o-transform:translateY(0px);transform:translateY(0px)}100%{opacity:0;-webkit-transform:translateY(-40px);-moz-transform:translateY(-40px);-ms-transform:translateY(-40px);-o-transform:translateY(-40px);transform:translateY(-40px)}}@-moz-keyframes passing-through{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%, 70%{opacity:1;-webkit-transform:translateY(0px);-moz-transform:translateY(0px);-ms-transform:translateY(0px);-o-transform:translateY(0px);transform:translateY(0px)}100%{opacity:0;-webkit-transform:translateY(-40px);-moz-transform:translateY(-40px);-ms-transform:translateY(-40px);-o-transform:translateY(-40px);transform:translateY(-40px)}}@keyframes passing-through{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%, 70%{opacity:1;-webkit-transform:translateY(0px);-moz-transform:translateY(0px);-ms-transform:translateY(0px);-o-transform:translateY(0px);transform:translateY(0px)}100%{opacity:0;-webkit-transform:translateY(-40px);-moz-transform:translateY(-40px);-ms-transform:translateY(-40px);-o-transform:translateY(-40px);transform:translateY(-40px)}}@-webkit-keyframes slide-in{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%{opacity:1;-webkit-transform:translateY(0px);-moz-transform:translateY(0px);-ms-transform:translateY(0px);-o-transform:translateY(0px);transform:translateY(0px)}}@-moz-keyframes slide-in{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%{opacity:1;-webkit-transform:translateY(0px);-moz-transform:translateY(0px);-ms-transform:translateY(0px);-o-transform:translateY(0px);transform:translateY(0px)}}@keyframes slide-in{0%{opacity:0;-webkit-transform:translateY(40px);-moz-transform:translateY(40px);-ms-transform:translateY(40px);-o-transform:translateY(40px);transform:translateY(40px)}30%{opacity:1;-webkit-transform:translateY(0px);-moz-transform:translateY(0px);-ms-transform:translateY(0px);-o-transform:translateY(0px);transform:translateY(0px)}}@-webkit-keyframes pulse{0%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}10%{-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-ms-transform:scale(1.1);-o-transform:scale(1.1);transform:scale(1.1)}20%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}}@-moz-keyframes pulse{0%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}10%{-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-ms-transform:scale(1.1);-o-transform:scale(1.1);transform:scale(1.1)}20%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}}@keyframes pulse{0%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}10%{-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-ms-transform:scale(1.1);-o-transform:scale(1.1);transform:scale(1.1)}20%{-webkit-transform:scale(1);-moz-transform:scale(1);-ms-transform:scale(1);-o-transform:scale(1);transform:scale(1)}}.dropzone,.dropzone *{box-sizing:border-box}.dropzone{min-height:150px;border:2px solid rgba(0,0,0,0.3);background:white;padding:20px 20px}.dropzone.dz-clickable{cursor:pointer}.dropzone.dz-clickable *{cursor:default}.dropzone.dz-clickable .dz-message,.dropzone.dz-clickable .dz-message *{cursor:pointer}.dropzone.dz-started .dz-message{display:none}.dropzone.dz-drag-hover{border-style:solid}.dropzone.dz-drag-hover .dz-message{opacity:0.5}.dropzone .dz-message{text-align:center;margin:2em 0}.dropzone .dz-preview{position:relative;display:inline-block;vertical-align:top;margin:16px;min-height:100px}.dropzone .dz-preview:hover{z-index:1000}.dropzone .dz-preview:hover .dz-details{opacity:1}.dropzone .dz-preview.dz-file-preview .dz-image{border-radius:20px;background:#999;background:linear-gradient(to bottom, #eee, #ddd)}.dropzone .dz-preview.dz-file-preview .dz-details{opacity:1}.dropzone .dz-preview.dz-image-preview{background:white}.dropzone .dz-preview.dz-image-preview .dz-details{-webkit-transition:opacity 0.2s linear;-moz-transition:opacity 0.2s linear;-ms-transition:opacity 0.2s linear;-o-transition:opacity 0.2s linear;transition:opacity 0.2s linear}.dropzone .dz-preview .dz-remove{font-size:14px;text-align:center;display:block;cursor:pointer;border:none}.dropzone .dz-preview .dz-remove:hover{text-decoration:underline}.dropzone .dz-preview:hover .dz-details{opacity:1}.dropzone .dz-preview .dz-details{z-index:20;position:absolute;top:0;left:0;opacity:0;font-size:13px;min-width:100%;max-width:100%;padding:2em 1em;text-align:center;color:rgba(0,0,0,0.9);line-height:150%}.dropzone .dz-preview .dz-details .dz-size{margin-bottom:1em;font-size:16px}.dropzone .dz-preview .dz-details .dz-filename{white-space:nowrap}.dropzone .dz-preview .dz-details .dz-filename:hover span{border:1px solid rgba(200,200,200,0.8);background-color:rgba(255,255,255,0.8)}.dropzone .dz-preview .dz-details .dz-filename:not(:hover){overflow:hidden;text-overflow:ellipsis}.dropzone .dz-preview .dz-details .dz-filename:not(:hover) span{border:1px solid transparent}.dropzone .dz-preview .dz-details .dz-filename span,.dropzone .dz-preview .dz-details .dz-size span{background-color:rgba(255,255,255,0.4);padding:0 0.4em;border-radius:3px}.dropzone .dz-preview:hover .dz-image img{-webkit-transform:scale(1.05, 1.05);-moz-transform:scale(1.05, 1.05);-ms-transform:scale(1.05, 1.05);-o-transform:scale(1.05, 1.05);transform:scale(1.05, 1.05);-webkit-filter:blur(8px);filter:blur(8px)}.dropzone .dz-preview .dz-image{border-radius:20px;overflow:hidden;width:120px;height:120px;position:relative;display:block;z-index:10}.dropzone .dz-preview .dz-image img{display:block}.dropzone .dz-preview.dz-success .dz-success-mark{-webkit-animation:passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);-moz-animation:passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);-ms-animation:passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);-o-animation:passing-through 3s cubic-bezier(0.77, 0, 0.175, 1);animation:passing-through 3s cubic-bezier(0.77, 0, 0.175, 1)}.dropzone .dz-preview.dz-error .dz-error-mark{opacity:1;-webkit-animation:slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);-moz-animation:slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);-ms-animation:slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);-o-animation:slide-in 3s cubic-bezier(0.77, 0, 0.175, 1);animation:slide-in 3s cubic-bezier(0.77, 0, 0.175, 1)}.dropzone .dz-preview .dz-success-mark,.dropzone .dz-preview .dz-error-mark{pointer-events:none;opacity:0;z-index:500;position:absolute;display:block;top:50%;left:50%;margin-left:-27px;margin-top:-27px}.dropzone .dz-preview .dz-success-mark svg,.dropzone .dz-preview .dz-error-mark svg{display:block;width:54px;height:54px}.dropzone .dz-preview.dz-processing .dz-progress{opacity:1;-webkit-transition:all 0.2s linear;-moz-transition:all 0.2s linear;-ms-transition:all 0.2s linear;-o-transition:all 0.2s linear;transition:all 0.2s linear}.dropzone .dz-preview.dz-complete .dz-progress{opacity:0;-webkit-transition:opacity 0.4s ease-in;-moz-transition:opacity 0.4s ease-in;-ms-transition:opacity 0.4s ease-in;-o-transition:opacity 0.4s ease-in;transition:opacity 0.4s ease-in}.dropzone .dz-preview:not(.dz-processing) .dz-progress{-webkit-animation:pulse 6s ease infinite;-moz-animation:pulse 6s ease infinite;-ms-animation:pulse 6s ease infinite;-o-animation:pulse 6s ease infinite;animation:pulse 6s ease infinite}.dropzone .dz-preview .dz-progress{opacity:1;z-index:1000;pointer-events:none;position:absolute;height:16px;left:50%;top:50%;margin-top:-8px;width:80px;margin-left:-40px;background:rgba(255,255,255,0.9);-webkit-transform:scale(1);border-radius:8px;overflow:hidden}.dropzone .dz-preview .dz-progress .dz-upload{background:#333;background:linear-gradient(to bottom, #666, #444);position:absolute;top:0;left:0;bottom:0;width:0;-webkit-transition:width 300ms ease-in-out;-moz-transition:width 300ms ease-in-out;-ms-transition:width 300ms ease-in-out;-o-transition:width 300ms ease-in-out;transition:width 300ms ease-in-out}.dropzone .dz-preview.dz-error .dz-error-message{display:block}.dropzone .dz-preview.dz-error:hover .dz-error-message{opacity:1;pointer-events:auto}.dropzone .dz-preview .dz-error-message{pointer-events:none;z-index:1000;position:absolute;display:block;display:none;opacity:0;-webkit-transition:opacity 0.3s ease;-moz-transition:opacity 0.3s ease;-ms-transition:opacity 0.3s ease;-o-transition:opacity 0.3s ease;transition:opacity 0.3s ease;border-radius:8px;font-size:13px;top:130px;left:-10px;width:140px;background:#be2626;background:linear-gradient(to bottom, #be2626, #a92222);padding:0.5em 1.2em;color:white}.dropzone .dz-preview .dz-error-message:after{content:'';position:absolute;top:-6px;left:64px;width:0;height:0;border-left:6px solid transparent;border-right:6px solid transparent;border-bottom:6px solid #be2626}
diff --git a/airtime_mvc/public/css/media_library.css b/airtime_mvc/public/css/media_library.css
index ef078fd55..446cc62b3 100644
--- a/airtime_mvc/public/css/media_library.css
+++ b/airtime_mvc/public/css/media_library.css
@@ -37,7 +37,6 @@
#library_content {
float: left;
- width: 50%;
overflow: auto;
}
diff --git a/airtime_mvc/public/css/showbuilder.css b/airtime_mvc/public/css/showbuilder.css
index e9d1380b7..869148bf9 100644
--- a/airtime_mvc/public/css/showbuilder.css
+++ b/airtime_mvc/public/css/showbuilder.css
@@ -180,8 +180,8 @@ table.datatable tr.cursor-selected-row td, table.datatable tr.cursor-selected-ro
background-color: rgba(255, 0, 0, 0.5);
}
-.sb-now-playing td {
- background-color: rgba(23, 235, 37, 1) !important;
+.sb-now-playing {
+ background-color: rgba(23, 235, 37, 1);
}
.sb-content.padded {
diff --git a/airtime_mvc/public/css/styles.css b/airtime_mvc/public/css/styles.css
index fad4eff17..d6ec22ad3 100644
--- a/airtime_mvc/public/css/styles.css
+++ b/airtime_mvc/public/css/styles.css
@@ -830,9 +830,9 @@ dl.inline-list dd {
.datatable tr.odd.selected td {
background-color: #c5deeb;
}
-.datatable tr.odd:hover td, .datatable tr.even:hover td {
- background-color: #95d5f7 !important;
-}
+/*.datatable tr.odd:hover td, .datatable tr.even:hover td {*/
+ /*background-color: #95d5f7 !important;*/
+/*}*/
.datatable tr td:first-child, .datatable tr th:first-child, .datatable tr th.ui-state-default:first-child {
border-left-width:0 !important;
@@ -3291,3 +3291,82 @@ dd .stream-status {
#schedule_iframe {
margin: 0 auto;
}
+
+/* Show Builder*/
+
+@media screen and (max-width: 1015px) {
+ .lib-test, .sb-test {
+ width: 100% !important;
+ }
+}
+
+.lib-test legend, .lib-test label, .lib-test span {
+ color: #efefef;
+}
+
+.lib-test {
+ margin: 2em 2em 2em 0;
+ overflow: hidden !important;
+}
+
+.sb-test {
+ margin-top: 2em;
+}
+
+.lib-test, .sb-test {
+ /* 1em for the middle margin, 6 for half the width of the left pane */
+ width: calc(50% - 8em);
+ min-width: 470px;
+}
+
+#media_type_nav {
+ float: left;
+ margin: 2em 0 0 0;
+
+ width: 12em;
+
+ background: none;
+ padding: 0 2em 0 0;
+}
+
+#new_media_selector {
+ width: 100%;
+}
+
+.media_type_selector {
+ cursor: pointer;
+ color: #cecece;
+ font-family: Roboto, "Open Sans", sans-serif;
+ font-size: 16px;
+ font-weight: 400;
+ width: 100%;
+ margin: 1em 1em 0 0;
+}
+
+.media_type_selector.selected {
+ color: #fff;
+}
+
+.media_type_selector:hover {
+ color: #fff;
+ -webkit-transition: color 0.2s linear;
+ -moz-transition: color 0.2s linear;
+ -o-transition: color 0.2s linear;
+ transition: color 0.2s linear;
+}
+
+/* Uploads */
+
+#upload_form {
+ width: 100%;
+ min-width: 470px;
+
+ background: none;
+ border: 2px dashed #efefef;
+
+ color: #efefef;
+ font-family: Roboto, "Open Sans", sans-serif;
+ font-size: 20px;
+ font-weight: 300;
+ line-height: 1.4rem;
+}
\ No newline at end of file
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 d44cd1707..8dcfd651b 100644
--- a/airtime_mvc/public/js/airtime/library/events/library_showbuilder.js
+++ b/airtime_mvc/public/js/airtime/library/events/library_showbuilder.js
@@ -125,7 +125,9 @@ var AIRTIME = (function(AIRTIME) {
}
if (aSchedIds.length == 0) {
- addToCurrentOrNext(aSchedIds);
+ if (!addToCurrentOrNext(aSchedIds)) {
+ return;
+ }
}
AIRTIME.showbuilder.fnAdd(aMediaIds, aSchedIds);
@@ -139,6 +141,12 @@ var AIRTIME = (function(AIRTIME) {
// the Now Playing screen if multiple shows are in view).
el = $("[si_id="+$("#0").attr("si_id")+"]");
var temp = el.eq(-2).data("aData");
+
+ if (temp === undefined) {
+ alert($.i18n._("Cannot schedule outside a show."));
+ return false;
+ }
+
arr.push({
"id" : temp.id,
"instance" : temp.instance,
diff --git a/airtime_mvc/public/js/airtime/library/library-test.js b/airtime_mvc/public/js/airtime/library/library-test.js
new file mode 100644
index 000000000..ebfc80279
--- /dev/null
+++ b/airtime_mvc/public/js/airtime/library/library-test.js
@@ -0,0 +1,978 @@
+var AIRTIME = (function(AIRTIME) {
+ var mod,
+ libraryInit,
+ oTable,
+ $libContent,
+ $libTable,
+ LIB_SELECTED_CLASS = "lib-selected",
+ chosenItems = {},
+ visibleChosenItems = {},
+ $previouslySelected;
+
+
+ // we need to know whether the criteria value is string or
+ // numeric in order to provide a single textbox or range textboxes
+ // in the advanced search
+ // s => string
+ // n => numberic
+ var libraryColumnTypes = {
+ 0 : "",
+ "album_title" : "s",
+ "artist_name" : "s",
+ "bit_rate" : "n",
+ "bpm" : "n",
+ "comments" : "s",
+ "composer" : "s",
+ "conductor" : "s",
+ "copyright" : "s",
+ "cuein" : "n",
+ "cueout" : "n",
+ "utime" : "n",
+ "mtime" : "n",
+ "lptime" : "n",
+ "disc_number" : "n",
+ "encoded_by" : "s",
+ "genre" : "s",
+ "isrc_number" : "s",
+ "label" : "s",
+ "language" : "s",
+ "length" : "n",
+ "lyricist" : "s",
+ "mime" : "s",
+ "mood" : "s",
+ "name" : "s",
+ "orchestra" : "s",
+ "rating" : "n",
+ "sample_rate" : "n",
+ "track_title" : "s",
+ "track_num" : "n",
+ "year" : "n",
+ "owner_id" : "s",
+ "info_url" : "s",
+ "replay_gain" : "n"
+ };
+
+ if (AIRTIME.library === undefined) {
+ AIRTIME.library = {};
+ }
+ mod = AIRTIME.library;
+
+ mod.getChosenItemsLength = function(){
+ var cItem,
+ selected,
+ $trs;
+
+ // Get visible items and check if any chosenItems are visible
+ $trs = $libTable.find("tr");
+ $trs.each(function(i){
+ for (cItem in chosenItems) {
+ if (cItem === $(this).attr("id")) {
+ visibleChosenItems[cItem] = $(this).data('aData');
+ }
+ }
+ });
+
+ selected = Object.keys(visibleChosenItems).length;
+ visibleChosenItems = {};
+ return selected;
+ };
+
+ mod.getChosenAudioFilesLength = function(){
+ // var files = Object.keys(chosenItems),
+ var files,
+ $trs,
+ cItem,
+ i, length,
+ count = 0,
+ reAudio=/^(au|st|pl|bl)/ ;
+
+ // Get visible items and check if any chosenItems are visible
+ $trs = $libTable.find("tr");
+ $trs.each(function(i){
+ for (cItem in chosenItems) {
+ if (cItem === $(this).attr("id")) {
+ visibleChosenItems[cItem] = $(this).data('aData');
+ }
+ }
+ });
+
+ files = Object.keys(visibleChosenItems);
+
+ for (i = 0, length = files.length; i < length; i++) {
+
+ if (files[i].search(reAudio) !== -1) {
+ count++;
+ }
+ }
+ visibleChosenItems = {};
+ return count;
+ };
+
+ mod.changeAddButtonText = function($button, btnText) {
+ $button.text(btnText);
+ };
+
+ mod.createToolbarButtons = function() {
+ $menu = $("
");
+ $menu
+ .append("" +
+ "" +
+ $.i18n._("Select")+" " +
+ " " +
+ "" +
+ "
")
+ .append("" +
+ "" +
+ " " +
+ " " +
+ " " +
+ "
")
+ .append("" +
+ "" +
+ " " +
+ " " +
+ "
");
+ };
+
+ mod.createToolbarDropDown = function() {
+ $('#sb-select-page').click(function(){mod.selectCurrentPage();});
+ $('#sb-dselect-page').click(function(){mod.deselectCurrentPage();});
+ $('#sb-dselect-all').click(function(){mod.selectNone();});
+ };
+
+ mod.checkDeleteButton = function() {
+ var selected = mod.getChosenItemsLength(),
+ check = false;
+
+ if (selected !== 0) {
+ check = true;
+ }
+
+ if (check === true) {
+ AIRTIME.button.enableButton("btn-group #sb-trash", false);
+ }
+ else {
+ AIRTIME.button.disableButton("btn-group #sb-trash", false);
+ }
+ };
+
+ mod.checkToolBarIcons = function() {
+
+ AIRTIME.library.checkAddButton();
+ AIRTIME.library.checkDeleteButton();
+ };
+
+ mod.getSelectedData = function() {
+ var id,
+ data = [],
+ cItem,
+ $trs;
+
+ $.fn.reverse = [].reverse;
+
+ // Get visible items and check if any chosenItems are visible
+ $trs = $libTable.find("tr").reverse();
+ $trs.each(function(i){
+ for (cItem in chosenItems) {
+ if (cItem === $(this).attr("id")) {
+ visibleChosenItems[cItem] = $(this).data('aData');
+ }
+ }
+ });
+
+ for (id in visibleChosenItems) {
+ if (visibleChosenItems.hasOwnProperty(id)) {
+ data.push(visibleChosenItems[id]);
+ }
+ }
+ visibleChosenItems = {};
+ return data;
+ };
+
+ mod.redrawChosen = function() {
+ var ids = Object.keys(chosenItems),
+ i, length,
+ $el;
+
+ for (i = 0, length = ids.length; i < length; i++) {
+ $el = $libTable.find("#"+ids[i]);
+
+ if ($el.length !== 0) {
+ mod.highlightItem($el);
+ }
+ }
+ };
+
+ mod.isChosenItem = function($el) {
+ var id = $el.attr("id"),
+ item = chosenItems[id];
+
+ return item !== undefined;
+ };
+
+ mod.addToChosen = function($el) {
+ var id = $el.attr("id");
+
+ chosenItems[id] = $el.data('aData');
+ };
+
+ mod.removeFromChosen = function($el) {
+ var id = $el.attr("id");
+
+ // used to not keep dragged items selected.
+ if (!$el.hasClass(LIB_SELECTED_CLASS)) {
+ delete chosenItems[id];
+ }
+ };
+
+ mod.highlightItem = function($el) {
+ $el.addClass(LIB_SELECTED_CLASS);
+ };
+
+ mod.unHighlightItem = function($el) {
+ $el.removeClass(LIB_SELECTED_CLASS);
+ };
+
+ mod.selectItem = function($el) {
+ mod.highlightItem($el);
+ mod.addToChosen($el);
+
+ mod.checkToolBarIcons();
+ };
+
+ mod.deselectItem = function($el) {
+ mod.unHighlightItem($el);
+ mod.removeFromChosen($el);
+ mod.checkToolBarIcons();
+ };
+
+ /*
+ * selects all items which the user can currently see. (behaviour taken from
+ * gmail)
+ *
+ * by default the items are selected in reverse order so we need to reverse
+ * it back
+ */
+ mod.selectCurrentPage = function() {
+ $.fn.reverse = [].reverse;
+ var $trs = $libTable.find("tbody").find("tr").reverse();
+ $trs.addClass(LIB_SELECTED_CLASS);
+
+ $trs.each(function(i, el){
+ $el = $(this);
+ mod.addToChosen($el);
+ });
+
+ mod.checkToolBarIcons();
+
+ };
+
+ /*
+ * deselects all items that the user can currently see. (behaviour taken
+ * from gmail)
+ */
+ mod.deselectCurrentPage = function() {
+ var $trs = $libTable.find("tr"), id;
+ $trs.removeClass(LIB_SELECTED_CLASS);
+
+ $trs.each(function(i, el){
+ $el = $(this);
+ id = $el.attr("id");
+ delete chosenItems[id];
+ });
+
+ mod.checkToolBarIcons();
+ };
+
+ mod.selectNone = function() {
+ var $trs = $libTable.find("tr");
+ $trs.removeClass(LIB_SELECTED_CLASS);
+
+ chosenItems = {};
+
+ mod.checkToolBarIcons();
+ };
+
+ mod.fnDeleteItems = function(aMedia) {
+
+ //Prevent the user from spamming the delete button while the AJAX request is in progress
+ AIRTIME.button.disableButton("btn-group #sb-trash", false);
+ //Hack to immediately show the "Processing" div in DataTables to give the user some sort of feedback.
+ $(".dataTables_processing").css('visibility','visible');
+
+ $.post(baseUrl+"library/delete",
+ {"format": "json", "media": aMedia},
+ function(json){
+ if (json.message !== undefined) {
+ alert(json.message);
+ }
+
+ chosenItems = {};
+ oTable.fnStandingRedraw();
+
+ //Re-enable the delete button
+ AIRTIME.button.enableButton("btn-group #sb-trash", false);
+ });
+ };
+
+ mod.fnDeleteSelectedItems = function() {
+ if (confirm($.i18n._('Are you sure you want to delete the selected item(s)?'))) {
+ var aData = AIRTIME.library.getSelectedData(),
+ item,
+ temp,
+ aMedia = [],
+ currentObjId = $("#side_playlist").find("#obj_id").val(),
+ currentObjType = $("#side_playlist").find("#obj_type").val(),
+ closeObj = false;
+
+ // process selected files/playlists.
+ for (item in aData) {
+ temp = aData[item];
+ if (temp !== null && temp.hasOwnProperty('id') ) {
+ aMedia.push({"id": temp.id, "type": temp.ftype});
+ if ( (temp.id == currentObjId && temp.ftype === currentObjType) ||
+ temp.id == currentObjId && temp.ftype === "stream" && currentObjType === "webstream") {
+ closeObj = true;
+ }
+ }
+ }
+
+ AIRTIME.library.fnDeleteItems(aMedia);
+
+ // close the object (playlist/block/webstream)
+ // on the right side if it was just deleted
+ // from the library
+ if (closeObj) {
+ $.post(baseUrl+"playlist/close-playlist",
+ {"format": "json", "type": currentObjType},
+ function(json) {
+ $("#side_playlist").empty().append(json.html);
+ });
+ }
+ }
+ };
+
+ libraryInit = function() {
+
+ $libContent = $("#library_content");
+
+ /*
+ * Icon hover states in the toolbar.
+ */
+ $libContent.on("mouseenter", ".fg-toolbar ul li", function(ev) {
+ $el = $(this);
+
+ if (!$el.hasClass("ui-state-disabled")) {
+ $el.addClass("ui-state-hover");
+ }
+ });
+ $libContent.on("mouseleave", ".fg-toolbar ul li", function(ev) {
+ $el = $(this);
+
+ if (!$el.hasClass("ui-state-disabled")) {
+ $el.removeClass("ui-state-hover");
+ }
+ });
+
+ var colReorderMap = new Array();
+
+ $libTable = $libContent.find("table");
+
+ function getTableHeight() {
+ return $libContent.height() - 175;
+ }
+
+ function setColumnFilter(oTable){
+ // TODO : remove this dirty hack once js is refactored
+ if (!oTable.fnSettings()) { return ; }
+ var aoCols = oTable.fnSettings().aoColumns;
+ var colsForAdvancedSearch = new Array();
+ var advanceSearchDiv = $("div#advanced_search");
+ advanceSearchDiv.empty();
+ $.each(aoCols, function(i,ele){
+ if (ele.bSearchable) {
+ var currentColId = ele._ColReorder_iOrigCol;
+
+ var inputClass = 'filter_column filter_number_text';
+ var labelStyle = "style='margin-right:35px;'";
+ if (libraryColumnTypes[ele.mDataProp] != "s") {
+ inputClass = 'filterColumn filter_number_range';
+ labelStyle = "";
+ }
+
+ if (ele.bVisible) {
+ advanceSearchDiv.append(
+ "" +
+ "
"+ele.sTitle+" : " +
+ "
" +
+ "
");
+ } else {
+ advanceSearchDiv.append(
+ "" +
+ "
"+ele.sTitle+" " +
+ "
" +
+ "
");
+ }
+
+ if (libraryColumnTypes[ele.mDataProp] == "s") {
+ var obj = { sSelector: "#"+ele.mDataProp }
+ } else {
+ var obj = { sSelector: "#"+ele.mDataProp, type: "number-range" }
+ }
+ colsForAdvancedSearch.push(obj);
+ } else {
+ colsForAdvancedSearch.push(null);
+ }
+ });
+
+ oTable.columnFilter({
+ aoColumns: colsForAdvancedSearch,
+ bUseColVis: true,
+ sPlaceHolder: "head:before"
+ }
+ );
+ }
+
+ function setFilterElement(iColumn, bVisible){
+ var actualId = colReorderMap[iColumn];
+ var selector = "div#advanced_search_col_"+actualId;
+ var $el = $(selector);
+
+ if (bVisible) {
+ $el.show();
+ } else {
+ $el.hide();
+ }
+
+ //resize to prevent double scroll bars.
+ var $fs = $el.parents("fieldset"),
+ tableHeight = getTableHeight(),
+ searchHeight = $fs.height();
+
+ $libContent.find(".dataTables_scrolling").css("max-height", tableHeight - searchHeight);
+ }
+
+ oTable = $libTable.dataTable( {
+
+ // put hidden columns at the top to insure they can never be visible
+ // on the table through column reordering.
+
+ //IMPORTANT: WHEN ADDING A NEW COLUMN PLEASE CONSULT WITH THE WIKI
+ // https://wiki.sourcefabric.org/display/CC/Adding+a+new+library+datatable+column
+ "aoColumns": [
+ /* ftype */ { "sTitle" : "" , "mDataProp" : "ftype" , "bSearchable" : false , "bVisible" : false } ,
+ /* Type */ { "sTitle" : "" , "mDataProp" : "image" , "bSearchable" : false , "sWidth" : "16px" , "sClass" : "library_type" , "iDataSort" : 0 } ,
+ ///* Is Scheduled */ { "sTitle" : $.i18n._("Scheduled") , "mDataProp" : "is_scheduled" , "bVisible" : false , "bSearchable" : false , "sWidth" : "90px" , "sClass" : "library_is_scheduled"} ,
+ /* Is Playlist */ { "sTitle" : $.i18n._("Playlist / Block") , "mDataProp" : "is_playlist" , "bSearchable" : false , "sWidth" : "110px" , "sClass" : "library_is_playlist"} ,
+ /* Title */ { "sTitle" : $.i18n._("Title") , "mDataProp" : "track_title" , "sClass" : "library_title" , "sWidth" : "170px" } ,
+ /* Creator */ { "sTitle" : $.i18n._("Creator") , "mDataProp" : "artist_name" , "sClass" : "library_creator" , "sWidth" : "160px" } ,
+ /* Album */ { "sTitle" : $.i18n._("Album") , "mDataProp" : "album_title" , "sClass" : "library_album" , "sWidth" : "150px" } ,
+ /* Bit Rate */ { "sTitle" : $.i18n._("Bit Rate") , "mDataProp" : "bit_rate" , "bVisible" : false , "sClass" : "library_bitrate" , "sWidth" : "80px" },
+ /* BPM */ { "sTitle" : $.i18n._("BPM") , "mDataProp" : "bpm" , "bVisible" : false , "sClass" : "library_bpm" , "sWidth" : "50px" },
+ /* Composer */ { "sTitle" : $.i18n._("Composer") , "mDataProp" : "composer" , "bVisible" : false , "sClass" : "library_composer" , "sWidth" : "150px" },
+ /* Conductor */ { "sTitle" : $.i18n._("Conductor") , "mDataProp" : "conductor" , "bVisible" : false , "sClass" : "library_conductor" , "sWidth" : "125px" },
+ /* Copyright */ { "sTitle" : $.i18n._("Copyright") , "mDataProp" : "copyright" , "bVisible" : false , "sClass" : "library_copyright" , "sWidth" : "125px" },
+ /* Cue In */ { "sTitle" : $.i18n._("Cue In") , "mDataProp" : "cuein" , "bVisible" : false , "sClass" : "library_length" , "sWidth" : "80px" },
+ /* Cue Out */ { "sTitle" : $.i18n._("Cue Out") , "mDataProp" : "cueout" , "bVisible" : false , "sClass" : "library_length" , "sWidth" : "80px" },
+ /* Encoded */ { "sTitle" : $.i18n._("Encoded By") , "mDataProp" : "encoded_by" , "bVisible" : false , "sClass" : "library_encoded" , "sWidth" : "150px" },
+ /* Genre */ { "sTitle" : $.i18n._("Genre") , "mDataProp" : "genre" , "bVisible" : false , "sClass" : "library_genre" , "sWidth" : "100px" },
+ /* ISRC Number */ { "sTitle" : $.i18n._("ISRC") , "mDataProp" : "isrc_number" , "bVisible" : false , "sClass" : "library_isrc" , "sWidth" : "150px" },
+ /* Label */ { "sTitle" : $.i18n._("Label") , "mDataProp" : "label" , "bVisible" : false , "sClass" : "library_label" , "sWidth" : "125px" },
+ /* Language */ { "sTitle" : $.i18n._("Language") , "mDataProp" : "language" , "bVisible" : false , "sClass" : "library_language" , "sWidth" : "125px" },
+ /* Last Modified */ { "sTitle" : $.i18n._("Last Modified") , "mDataProp" : "mtime" , "bVisible" : false , "sClass" : "library_modified_time" , "sWidth" : "125px" },
+ /* Last Played */ { "sTitle" : $.i18n._("Last Played") , "mDataProp" : "lptime" , "bVisible" : false , "sClass" : "library_modified_time" , "sWidth" : "125px" },
+ /* Length */ { "sTitle" : $.i18n._("Length") , "mDataProp" : "length" , "sClass" : "library_length" , "sWidth" : "80px" } ,
+ /* Mime */ { "sTitle" : $.i18n._("Mime") , "mDataProp" : "mime" , "bVisible" : false , "sClass" : "library_mime" , "sWidth" : "80px" },
+ /* Mood */ { "sTitle" : $.i18n._("Mood") , "mDataProp" : "mood" , "bVisible" : false , "sClass" : "library_mood" , "sWidth" : "70px" },
+ /* Owner */ { "sTitle" : $.i18n._("Owner") , "mDataProp" : "owner_id" , "bVisible" : false , "sClass" : "library_language" , "sWidth" : "125px" },
+ /* Replay Gain */ { "sTitle" : $.i18n._("Replay Gain") , "mDataProp" : "replay_gain" , "bVisible" : false , "sClass" : "library_replay_gain" , "sWidth" : "80px" },
+ /* Sample Rate */ { "sTitle" : $.i18n._("Sample Rate") , "mDataProp" : "sample_rate" , "bVisible" : false , "sClass" : "library_sr" , "sWidth" : "80px" },
+ /* Track Number */ { "sTitle" : $.i18n._("Track Number") , "mDataProp" : "track_number" , "bVisible" : false , "sClass" : "library_track" , "sWidth" : "65px" },
+ /* Upload Time */ { "sTitle" : $.i18n._("Uploaded") , "mDataProp" : "utime" , "bVisible" : false , "sClass" : "library_upload_time" , "sWidth" : "125px" } ,
+ /* 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" }
+ ],
+
+ "bProcessing": true,
+ "bServerSide": true,
+
+ "aLengthMenu": [[5, 10, 15, 20, 25, 50, 100], [5, 10, 15, 20, 25, 50, 100]],
+
+ "bStateSave": true,
+ "fnStateSaveParams": function (oSettings, oData) {
+ // remove oData components we don't want to save.
+ delete oData.oSearch;
+ delete oData.aoSearchCols;
+ },
+ "fnStateSave": function (oSettings, oData) {
+ localStorage.setItem('datatables-library', JSON.stringify(oData));
+ /*
+ $.ajax({
+ url: baseUrl+"usersettings/set-library-datatable",
+ type: "POST",
+ data: {settings : oData, format: "json"},
+ dataType: "json"
+ });
+ */
+
+ colReorderMap = oData.ColReorder;
+ },
+ "fnStateLoad": function fnLibStateLoad(oSettings) {
+ var settings = localStorage.getItem('datatables-library');
+
+ try {
+ return JSON.parse(settings);
+ } catch (e) {
+ return null;
+ }
+ },
+ "fnStateLoadParams": function (oSettings, oData) {
+ var i,
+ length,
+ a = oData.abVisCols;
+
+ if (a) {
+ // putting serialized data back into the correct js type to make
+ // sure everything works properly.
+ for (i = 0, length = a.length; i < length; i++) {
+ if (typeof(a[i]) === "string") {
+ a[i] = (a[i] === "true") ? true : false;
+ }
+ }
+ }
+
+ a = oData.ColReorder;
+ if (a) {
+ for (i = 0, length = a.length; i < length; i++) {
+ if (typeof(a[i]) === "string") {
+ a[i] = parseInt(a[i], 10);
+ }
+ }
+ }
+
+ oData.iEnd = parseInt(oData.iEnd, 10);
+ oData.iLength = parseInt(oData.iLength, 10);
+ oData.iStart = parseInt(oData.iStart, 10);
+ oData.iCreate = parseInt(oData.iCreate, 10);
+ },
+
+ "sAjaxSource": baseUrl+"Library/contents-feed-test",
+ "sAjaxDataProp": "files",
+
+ "fnServerData": function ( sSource, aoData, fnCallback ) {
+ /*
+ * The real validation check is done in
+ * dataTables.columnFilter.js We also need to check it here
+ * because datatable is redrawn everytime an action is performed
+ * in the Library page. In order for datatable to redraw the
+ * advanced search fields MUST all be valid.
+ */
+ var advSearchFields = $("div#advanced_search").children(':visible');
+ var advSearchValid = validateAdvancedSearch(advSearchFields);
+ var type;
+ aoData.push( { name: "format", value: "json"} );
+ aoData.push( { name: "advSearch", value: advSearchValid} );
+
+ // push whether to search files/playlists or all.
+ type = $(".media_type_selector.selected").attr("selection_id");
+ type = (type === undefined) ? 1 : type;
+ aoData.push( { name: "type", value: type} );
+
+ $.ajax( {
+ "dataType": 'json',
+ "type": "POST",
+ "url": sSource,
+ "data": aoData,
+ "success": fnCallback
+ } );
+ },
+ "fnRowCallback": AIRTIME.library.fnRowCallback,
+ "fnCreatedRow": function( nRow, aData, iDataIndex ) {
+ // add audio preview image/button
+ if (aData.ftype === "audioclip") {
+ $(nRow).find('td.library_type').html(' ');
+ } else if (aData.ftype === "playlist") {
+ $(nRow).find('td.library_type').html(' ');
+ } else if (aData.ftype === "block") {
+ $(nRow).find('td.library_type').html(' ');
+ } else if (aData.ftype === "stream") {
+ $(nRow).find('td.library_type').html(' ');
+ }
+
+ if (aData.is_scheduled) {
+ $(nRow).find("td.library_is_scheduled").html(' ');
+ } else if (!aData.is_scheduled) {
+ $(nRow).find("td.library_is_scheduled").html('');
+ }
+ if (aData.is_playlist) {
+ $(nRow).find("td.library_is_playlist").html(' ');
+ } else if (!aData.is_playlist) {
+ $(nRow).find("td.library_is_playlist").html('');
+ }
+
+ // add the play function to the library_type td
+ $(nRow).find('td.library_type').click(function(){
+ if (aData.ftype === 'playlist' && aData.length !== '0.0'){
+ open_playlist_preview(aData.audioFile, 0);
+ } else if (aData.ftype === 'audioclip') {
+ if (isAudioSupported(aData.mime)) {
+ open_audio_preview(aData.ftype, aData.id);
+ }
+ } else if (aData.ftype == 'stream') {
+ if (isAudioSupported(aData.mime)) {
+ open_audio_preview(aData.ftype, aData.id);
+ }
+ } else if (aData.ftype == 'block' && aData.bl_type == 'static') {
+ open_block_preview(aData.audioFile, 0);
+ }
+ return false;
+ });
+ },
+ // remove any selected nodes before the draw.
+ "fnPreDrawCallback": function( oSettings ) {
+
+ // make sure any dragging helpers are removed or else they'll be
+ // stranded on the screen.
+ $("#draggingContainer").remove();
+ },
+ "fnDrawCallback": AIRTIME.library.fnDrawCallback,
+
+ "aaSorting": [[5, 'asc']],
+ "sPaginationType": "full_numbers",
+ "bJQueryUI": true,
+ "bAutoWidth": false,
+ "oLanguage": datatables_dict,
+
+ // R = ColReorder, C = ColVis
+ "sDom": 'Rl<"#library_display_type">f<"dt-process-rel"r><"H"<"library_toolbar"C>><"dataTables_scrolling"t><"F"ip>',
+
+ "oColVis": {
+ "sAlign": "right",
+ "aiExclude": [0, 1, 2],
+ "sSize": "css",
+ "fnStateChange": setFilterElement,
+ "buttonText": $.i18n._("Show / hide columns")
+ },
+
+ "oColReorder": {
+ "iFixedColumns": 3
+ }
+
+ });
+
+ setColumnFilter(oTable);
+ oTable.fnSetFilteringDelay(350);
+
+ var simpleSearchText;
+
+ $libContent.on("click", "legend", function(){
+ $simpleSearch = $libContent.find("#library_display_filter label");
+ var $fs = $(this).parents("fieldset"),
+ searchHeight,
+ tableHeight = getTableHeight(),
+ height;
+
+ if ($fs.hasClass("closed")) {
+ $fs.removeClass("closed");
+ searchHeight = $fs.height();
+
+ //keep value of simple search for when user switches back to it
+ simpleSearchText = $simpleSearch.find('input').val();
+
+ // clear the simple search text field and reset datatable
+ $(".dataTables_filter input").val("").keyup();
+
+ $simpleSearch.addClass("sp-invisible");
+
+ //resize the library table to avoid a double scroll bar. CC-4504
+ height = tableHeight - searchHeight;
+ $libContent.find(".dataTables_scrolling").css("max-height", height);
+ }
+ else {
+ // clear the advanced search fields
+ var divs = $("div#advanced_search").children(':visible');
+ $.each(divs, function(i, div){
+ fields = $(div).children().find('input');
+ $.each(fields, function(i, field){
+ if ($(field).val() !== "") {
+ $(field).val("");
+ // we need to reset the results when removing
+ // an advanced search field
+ $(field).keyup();
+ }
+ });
+ });
+
+ //reset datatable with previous simple search results (if any)
+ $(".dataTables_filter input").val(simpleSearchText).keyup();
+
+ $simpleSearch.removeClass("sp-invisible");
+ $fs.addClass("closed");
+
+ //resize the library table to avoid a double scroll bar. CC-4504
+ $libContent.find(".dataTables_scrolling").css("max-height", tableHeight);
+ }
+ });
+
+ var tableHeight = getTableHeight();
+ $libContent.find(".dataTables_scrolling").css("max-height", tableHeight);
+
+ AIRTIME.library.setupLibraryToolbar(oTable);
+
+ $libTable.find("tbody").on("dblclick", "tr", function(ev) {
+ var $tr = $(this),
+ data = $tr.data("aData");
+ AIRTIME.library.dblClickAdd(data, data.ftype);
+ });
+
+ $libTable.find("tbody").on("click", "tr", function(ev) {
+ var $tr = $(this),
+ // Get the ID of the selected row
+ $rowId = $tr.attr("id");
+
+ if (ev.shiftKey && $previouslySelected !== undefined) {
+ if ($previouslySelected.attr("id") == $rowId) {
+ return;
+ }
+
+ // If the selected row comes before the previously selected row,
+ // we want to select previous rows, otherwise we select next
+ if ($previouslySelected.prevAll("#"+$rowId).length !== 0) {
+ $previouslySelected.prevUntil($tr).each(function(i, el){
+ mod.selectItem($(el));
+ });
+ } else {
+ $previouslySelected.nextUntil($tr).each(function(i, el){
+ mod.selectItem($(el));
+ });
+ }
+
+ mod.selectItem($tr);
+ } else if (ev.ctrlKey && $previouslySelected !== undefined) {
+ mod.selectItem($tr);
+ } else {
+ $("."+LIB_SELECTED_CLASS).each(function(i, el) {
+ mod.deselectItem($(el))
+ });
+ mod.selectItem($tr);
+ }
+
+ // Remember this row so we can properly multiselect
+ $previouslySelected = $tr;
+ });
+ };
+ mod.libraryInit = libraryInit;
+
+ return 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
+ */
+function validateAdvancedSearch(divs) {
+ var valid,
+ allValid = true,
+ fieldName,
+ fields,
+ searchTerm = Array(),
+ searchTermType,
+ regExpr,
+ timeRegEx = "\\d{2}[:]([0-5]){1}([0-9]){1}[:]([0-5]){1}([0-9]){1}([.]\\d{1,6})?",
+ dateRegEx = "\\d{4}[-]\\d{2}[-]\\d{2}?",
+ integerRegEx = "^\\d+$",
+ numericRegEx = "^\\d+[.]?\\d*$";
+
+ searchTerm[0] = "";
+ searchTerm[1] = "";
+ $.each(divs, function(i, div){
+ fieldName = $(div).children(':nth-child(2)').attr('id');
+ fields = $(div).children().find('input');
+ searchTermType = validationTypes[fieldName];
+ valid = true;
+
+ $.each(fields, function(i, field){
+ searchTerm[i] = $(field).val();
+
+ if (searchTerm[i] !== "") {
+
+ if (searchTermType === "l") {
+ regExpr = new RegExp("^" +timeRegEx+ "$");
+ } else if (searchTermType === "t") {
+ var pieces = searchTerm[i].split(" ");
+ if (pieces.length === 2) {
+ regExpr = new RegExp("^" +dateRegEx+ " " +timeRegEx+ "$");
+ } else if (pieces.length === 1) {
+ regExpr = new RegExp("^" +dateRegEx+ "$");
+ }
+ } else if (searchTermType === "i") {
+ regExpr = new RegExp(integerRegEx);
+ } else if (searchTermType === "n") {
+ regExpr = new RegExp(numericRegEx);
+ if (searchTerm[i].charAt(0) === "-") {
+ searchTerm[i] = searchTerm[i].substr(1);
+ }
+ }
+
+ // string fields do not need validation
+ if (searchTermType !== "s") {
+ valid = regExpr.test(searchTerm[i]);
+ if (!valid) allValid = false;
+ }
+
+ addRemoveValidationIcons(valid, $(field), searchTermType);
+
+ /*
+ * Empty fields should not have valid/invalid indicator Range values
+ * are considered valid even if only the 'From' value is provided.
+ * Therefore, if the 'To' value is empty but the 'From' value is not
+ * empty we need to keep the validation icon on screen.
+ */
+ } else if (searchTerm[0] === "" && searchTerm[1] !== "" ||
+ searchTerm[0] === "" && searchTerm[1] === ""){
+ if ($(field).closest('div').children(':last-child').hasClass('checked-icon') ||
+ $(field).closest('div').children(':last-child').hasClass('not-available-icon')) {
+ $(field).closest('div').children(':last-child').remove();
+ }
+ }
+
+ if (!valid) {
+ return false;
+ }
+ });
+ });
+
+ return allValid;
+}
+
+function addRemoveValidationIcons(valid, field, searchTermType) {
+ var title = '';
+ if (searchTermType === 'i') {
+ title = $.i18n._('Input must be a positive number');
+ } else if (searchTermType === 'n') {
+ title = $.i18n._('Input must be a number');
+ } else if (searchTermType === 't') {
+ title = $.i18n._('Input must be in the format: yyyy-mm-dd');
+ } else if (searchTermType === 'l') {
+ title = $.i18n._('Input must be in the format: hh:mm:ss.t');
+ }
+
+ var validIndicator = " ",
+ invalidIndicator = " ";
+
+ if (valid) {
+ if (!field.closest('div').children(':last-child').hasClass('checked-icon')) {
+ // remove invalid icon before adding valid icon
+ if (field.closest('div').children(':last-child').hasClass('not-available-icon')) {
+ field.closest('div').children(':last-child').remove();
+ }
+ field.closest('div').append(validIndicator);
+ }
+ } else {
+ if (!field.closest('div').children(':last-child').hasClass('not-available-icon')) {
+ // remove valid icon before adding invalid icon
+ if (field.closest('div').children(':last-child').hasClass('checked-icon')) {
+ field.closest('div').children(':last-child').remove();
+ }
+ field.closest('div').append(invalidIndicator);
+ }
+ }
+}
+
+/*
+ * Validation types: s => string i => integer n => numeric (positive/negative,
+ * whole/decimals) t => timestamp l => length
+ */
+var validationTypes = {
+ "album_title" : "s",
+ "artist_name" : "s",
+ "bit_rate" : "i",
+ "bpm" : "i",
+ "comments" : "s",
+ "composer" : "s",
+ "conductor" : "s",
+ "copyright" : "s",
+ "cuein" : "l",
+ "cueout" : "l",
+ "encoded_by" : "s",
+ "utime" : "t",
+ "mtime" : "t",
+ "lptime" : "t",
+ "disc_number" : "i",
+ "genre" : "s",
+ "isrc_number" : "s",
+ "label" : "s",
+ "language" : "s",
+ "length" : "l",
+ "lyricist" : "s",
+ "mood" : "s",
+ "mime" : "s",
+ "name" : "s",
+ "orchestra" : "s",
+ "owner_id" : "s",
+ "rating" : "i",
+ "replay_gain" : "n",
+ "sample_rate" : "n",
+ "track_title" : "s",
+ "track_number" : "i",
+ "info_url" : "s",
+ "year" : "i"
+};
+
+$(document).ready(function() {
+ $('#editmdsave').live("click", function() {
+ var file_id = $('#file_id').val(),
+ data = $("#edit-md-dialog form").serializeArray();
+ $.post(baseUrl+'library/edit-file-md', {format: "json", id: file_id, data: data}, function() {
+ $("#edit-md-dialog").dialog().remove();
+
+ // don't redraw the library table if we are on calendar page
+ // we would be on calendar if viewing recorded file metadata
+ if ($("#schedule_calendar").length === 0) {
+ oTable.fnStandingRedraw();
+ }
+ });
+ });
+
+ $('#editmdcancel').live("click", function() {
+ $("#edit-md-dialog").dialog().remove();
+ });
+
+ $('#edit-md-dialog').live("keyup", function(event) {
+ if (event.keyCode === 13) {
+ $('#editmdsave').click();
+ }
+ });
+
+ $(".media_type_selector").on("click", function() {
+ $(".media_type_selector").each(function() {
+ $(this).removeClass("selected");
+ });
+ $(this).addClass("selected");
+ oTable.fnDraw();
+ });
+});
+
diff --git a/airtime_mvc/public/js/airtime/library/library.js b/airtime_mvc/public/js/airtime/library/library.js
index 0e4d97723..b752b3e87 100644
--- a/airtime_mvc/public/js/airtime/library/library.js
+++ b/airtime_mvc/public/js/airtime/library/library.js
@@ -484,35 +484,35 @@ var AIRTIME = (function(AIRTIME) {
//IMPORTANT: WHEN ADDING A NEW COLUMN PLEASE CONSULT WITH THE WIKI
// https://wiki.sourcefabric.org/display/CC/Adding+a+new+library+datatable+column
"aoColumns": [
- /* ftype */ { "sTitle" : "" , "mDataProp" : "ftype" , "bSearchable" : false , "bVisible" : false } ,
- /* Checkbox */ { "sTitle" : "" , "mDataProp" : "checkbox" , "bSortable" : false , "bSearchable" : false , "sWidth" : "25px" , "sClass" : "library_checkbox" } ,
+ /* ftype */ { "sTitle" : "" , "mDataProp" : "ftype" , "bSearchable" : false , "bVisible" : false } ,
+ /* Checkbox */ { "sTitle" : "" , "mDataProp" : "checkbox" , "bSortable" : false , "bSearchable" : false , "sWidth" : "25px" , "sClass" : "library_checkbox" } ,
/* Type */ { "sTitle" : "" , "mDataProp" : "image" , "bSearchable" : false , "sWidth" : "25px" , "sClass" : "library_type" , "iDataSort" : 0 } ,
/* Is Scheduled */ { "sTitle" : $.i18n._("Scheduled") , "mDataProp" : "is_scheduled" , "bSearchable" : false , "sWidth" : "90px" , "sClass" : "library_is_scheduled"} ,
/* Is Playlist */ { "sTitle" : $.i18n._("Playlist / Block") , "mDataProp" : "is_playlist" , "bSearchable" : false , "sWidth" : "110px" , "sClass" : "library_is_playlist"} ,
- /* Title */ { "sTitle" : $.i18n._("Title") , "mDataProp" : "track_title" , "sClass" : "library_title" , "sWidth" : "170px" } ,
- /* Creator */ { "sTitle" : $.i18n._("Creator") , "mDataProp" : "artist_name" , "sClass" : "library_creator" , "sWidth" : "160px" } ,
- /* Album */ { "sTitle" : $.i18n._("Album") , "mDataProp" : "album_title" , "sClass" : "library_album" , "sWidth" : "150px" } ,
- /* Bit Rate */ { "sTitle" : $.i18n._("Bit Rate") , "mDataProp" : "bit_rate" , "bVisible" : false , "sClass" : "library_bitrate" , "sWidth" : "80px" },
+ /* Title */ { "sTitle" : $.i18n._("Title") , "mDataProp" : "track_title" , "sClass" : "library_title" , "sWidth" : "170px" } ,
+ /* Creator */ { "sTitle" : $.i18n._("Creator") , "mDataProp" : "artist_name" , "sClass" : "library_creator" , "sWidth" : "160px" } ,
+ /* Album */ { "sTitle" : $.i18n._("Album") , "mDataProp" : "album_title" , "sClass" : "library_album" , "sWidth" : "150px" } ,
+ /* Bit Rate */ { "sTitle" : $.i18n._("Bit Rate") , "mDataProp" : "bit_rate" , "bVisible" : false , "sClass" : "library_bitrate" , "sWidth" : "80px" },
/* BPM */ { "sTitle" : $.i18n._("BPM") , "mDataProp" : "bpm" , "bVisible" : false , "sClass" : "library_bpm" , "sWidth" : "50px" },
- /* Composer */ { "sTitle" : $.i18n._("Composer") , "mDataProp" : "composer" , "bVisible" : false , "sClass" : "library_composer" , "sWidth" : "150px" },
+ /* Composer */ { "sTitle" : $.i18n._("Composer") , "mDataProp" : "composer" , "bVisible" : false , "sClass" : "library_composer" , "sWidth" : "150px" },
/* Conductor */ { "sTitle" : $.i18n._("Conductor") , "mDataProp" : "conductor" , "bVisible" : false , "sClass" : "library_conductor" , "sWidth" : "125px" },
/* Copyright */ { "sTitle" : $.i18n._("Copyright") , "mDataProp" : "copyright" , "bVisible" : false , "sClass" : "library_copyright" , "sWidth" : "125px" },
/* Cue In */ { "sTitle" : $.i18n._("Cue In") , "mDataProp" : "cuein" , "bVisible" : false , "sClass" : "library_length" , "sWidth" : "80px" },
/* Cue Out */ { "sTitle" : $.i18n._("Cue Out") , "mDataProp" : "cueout" , "bVisible" : false , "sClass" : "library_length" , "sWidth" : "80px" },
- /* Encoded */ { "sTitle" : $.i18n._("Encoded By") , "mDataProp" : "encoded_by" , "bVisible" : false , "sClass" : "library_encoded" , "sWidth" : "150px" },
- /* Genre */ { "sTitle" : $.i18n._("Genre") , "mDataProp" : "genre" , "bVisible" : false , "sClass" : "library_genre" , "sWidth" : "100px" },
- /* ISRC Number */ { "sTitle" : $.i18n._("ISRC") , "mDataProp" : "isrc_number" , "bVisible" : false , "sClass" : "library_isrc" , "sWidth" : "150px" },
- /* Label */ { "sTitle" : $.i18n._("Label") , "mDataProp" : "label" , "bVisible" : false , "sClass" : "library_label" , "sWidth" : "125px" },
- /* Language */ { "sTitle" : $.i18n._("Language") , "mDataProp" : "language" , "bVisible" : false , "sClass" : "library_language" , "sWidth" : "125px" },
+ /* Encoded */ { "sTitle" : $.i18n._("Encoded By") , "mDataProp" : "encoded_by" , "bVisible" : false , "sClass" : "library_encoded" , "sWidth" : "150px" },
+ /* Genre */ { "sTitle" : $.i18n._("Genre") , "mDataProp" : "genre" , "bVisible" : false , "sClass" : "library_genre" , "sWidth" : "100px" },
+ /* ISRC Number */ { "sTitle" : $.i18n._("ISRC") , "mDataProp" : "isrc_number" , "bVisible" : false , "sClass" : "library_isrc" , "sWidth" : "150px" },
+ /* Label */ { "sTitle" : $.i18n._("Label") , "mDataProp" : "label" , "bVisible" : false , "sClass" : "library_label" , "sWidth" : "125px" },
+ /* Language */ { "sTitle" : $.i18n._("Language") , "mDataProp" : "language" , "bVisible" : false , "sClass" : "library_language" , "sWidth" : "125px" },
/* Last Modified */ { "sTitle" : $.i18n._("Last Modified") , "mDataProp" : "mtime" , "bVisible" : false , "sClass" : "library_modified_time" , "sWidth" : "125px" },
- /* Last Played */ { "sTitle" : $.i18n._("Last Played") , "mDataProp" : "lptime" , "bVisible" : false , "sClass" : "library_modified_time" , "sWidth" : "125px" },
- /* Length */ { "sTitle" : $.i18n._("Length") , "mDataProp" : "length" , "sClass" : "library_length" , "sWidth" : "80px" } ,
- /* Mime */ { "sTitle" : $.i18n._("Mime") , "mDataProp" : "mime" , "bVisible" : false , "sClass" : "library_mime" , "sWidth" : "80px" },
+ /* Last Played */ { "sTitle" : $.i18n._("Last Played") , "mDataProp" : "lptime" , "bVisible" : false , "sClass" : "library_modified_time" , "sWidth" : "125px" },
+ /* Length */ { "sTitle" : $.i18n._("Length") , "mDataProp" : "length" , "sClass" : "library_length" , "sWidth" : "80px" } ,
+ /* Mime */ { "sTitle" : $.i18n._("Mime") , "mDataProp" : "mime" , "bVisible" : false , "sClass" : "library_mime" , "sWidth" : "80px" },
/* Mood */ { "sTitle" : $.i18n._("Mood") , "mDataProp" : "mood" , "bVisible" : false , "sClass" : "library_mood" , "sWidth" : "70px" },
- /* Owner */ { "sTitle" : $.i18n._("Owner") , "mDataProp" : "owner_id" , "bVisible" : false , "sClass" : "library_language" , "sWidth" : "125px" },
- /* Replay Gain */ { "sTitle" : $.i18n._("Replay Gain") , "mDataProp" : "replay_gain" , "bVisible" : false , "sClass" : "library_replay_gain" , "sWidth" : "80px" },
- /* Sample Rate */ { "sTitle" : $.i18n._("Sample Rate") , "mDataProp" : "sample_rate" , "bVisible" : false , "sClass" : "library_sr" , "sWidth" : "80px" },
- /* Track Number */ { "sTitle" : $.i18n._("Track Number") , "mDataProp" : "track_number" , "bVisible" : false , "sClass" : "library_track" , "sWidth" : "65px" },
+ /* Owner */ { "sTitle" : $.i18n._("Owner") , "mDataProp" : "owner_id" , "bVisible" : false , "sClass" : "library_language" , "sWidth" : "125px" },
+ /* Replay Gain */ { "sTitle" : $.i18n._("Replay Gain") , "mDataProp" : "replay_gain" , "bVisible" : false , "sClass" : "library_replay_gain" , "sWidth" : "80px" },
+ /* Sample Rate */ { "sTitle" : $.i18n._("Sample Rate") , "mDataProp" : "sample_rate" , "bVisible" : false , "sClass" : "library_sr" , "sWidth" : "80px" },
+ /* Track Number */ { "sTitle" : $.i18n._("Track Number") , "mDataProp" : "track_number" , "bVisible" : false , "sClass" : "library_track" , "sWidth" : "65px" },
/* Upload Time */ { "sTitle" : $.i18n._("Uploaded") , "mDataProp" : "utime" , "sClass" : "library_upload_time" , "sWidth" : "125px" } ,
/* 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" }
diff --git a/airtime_mvc/public/js/airtime/showbuilder/builder.js b/airtime_mvc/public/js/airtime/showbuilder/builder.js
index d46d0aade..bb55faec7 100644
--- a/airtime_mvc/public/js/airtime/showbuilder/builder.js
+++ b/airtime_mvc/public/js/airtime/showbuilder/builder.js
@@ -214,7 +214,7 @@ var AIRTIME = (function(AIRTIME){
aData = [],
i, length,
$item;
-
+
if (sNot !== undefined) {
$selected = $selected.not("."+sNot);
}
@@ -1065,6 +1065,10 @@ var AIRTIME = (function(AIRTIME){
var elements = $sbTable.find('tr input:checked').parents('tr').not("."+NOW_PLAYING_CLASS);
elements.hide();
+ },
+ stop: function() {
+ var elements = $sbTable.find('tr.'+SB_SELECTED_CLASS).not("."+NOW_PLAYING_CLASS);
+ elements.show();
}
};
}());
diff --git a/airtime_mvc/public/js/airtime/showbuilder/builder_test.js b/airtime_mvc/public/js/airtime/showbuilder/builder_test.js
new file mode 100644
index 000000000..38d521396
--- /dev/null
+++ b/airtime_mvc/public/js/airtime/showbuilder/builder_test.js
@@ -0,0 +1,1112 @@
+var AIRTIME = (function(AIRTIME){
+ var mod,
+ oSchedTable,
+ SB_SELECTED_CLASS = "sb-selected",
+ CURSOR_SELECTED_CLASS = "cursor-selected-row",
+ NOW_PLAYING_CLASS = "sb-now-playing",
+ $sbContent,
+ $sbTable,
+ $toolbar,
+ $lib,
+ cursors = [],
+ cursorIds = [],
+ showInstanceIds = [],
+ headerFooter = [],
+ DISABLED_CLASS = 'ui-state-disabled',
+ $previouslySelected;
+
+ if (AIRTIME.showbuilder === undefined) {
+ AIRTIME.showbuilder = {};
+ }
+ mod = AIRTIME.showbuilder;
+
+ function checkError(json) {
+ if (json.error !== undefined) {
+ alert(json.error);
+ }
+ }
+
+ mod.timeout = undefined;
+ mod.timestamp = -1;
+ mod.showInstances = [];
+
+ mod.resetTimestamp = function() {
+
+ mod.timestamp = -1;
+ };
+
+ mod.setTimestamp = function(timestamp) {
+
+ mod.timestamp = timestamp;
+ };
+
+ mod.updateCalendarStatusIcon = function(json) {
+ //make sure we are only executing this code on the calendar view, not
+ //the Now Playing view.
+ if (window.location.pathname.toLowerCase().indexOf("schedule") < 0) {
+ return;
+ }
+
+
+ var instance_id = json.schedule[0].instance;
+
+ var lastElem = json.schedule[json.schedule.length-1];
+ var $elem = $("#fc-show-instance-"+instance_id);
+
+ //if the show is linked, then replace $elem to reference all linked
+ //instances
+ if ($elem.data("show-linked") == "1") {
+ var show_id = $elem.data("show-id");
+ $elem = $('*[data-show-id="'+show_id+'"]');
+ }
+
+ $elem.find(".show-empty, .show-partial-filled").remove();
+ if (json.schedule[1].empty) {
+ $elem
+ .find(".fc-event-inner")
+ .append(' ');
+ } else if (lastElem["fRuntime"][0] == "-") {
+ $elem
+ .find(".fc-event-inner")
+ .append(' ');
+ }
+ };
+
+ mod.getTimestamp = function() {
+
+ if (mod.timestamp !== undefined) {
+ return mod.timestamp;
+ }
+ else {
+ return -1;
+ }
+ };
+
+ mod.setShowInstances = function(showInstances) {
+ mod.showInstances = showInstances;
+ };
+
+ mod.getShowInstances = function() {
+ return mod.showInstances;
+ };
+
+ mod.refresh = function(schedId) {
+ mod.resetTimestamp();
+
+ // once a track plays out we need to check if we can update
+ // the is_scheduled flag in cc_files
+ if (schedId > 0) {
+ $.post(baseUrl+"schedule/update-future-is-scheduled",
+ {"format": "json", "schedId": schedId}, function(data) {
+ if (data.redrawLibTable !== undefined && data.redrawLibTable) {
+ $("#library_content").find("#library_display").dataTable().fnStandingRedraw();
+ }
+ });
+ oSchedTable.fnDraw();
+ }
+ };
+
+ mod.checkSelectButton = function() {
+ var $selectable = $sbTable.find("tr");
+
+ if ($selectable.length !== 0) {
+ AIRTIME.button.enableButton("btn-group #timeline-select", false);
+ } else {
+ AIRTIME.button.disableButton("btn-group #timeline-select", false);
+ }
+
+ //need to check if the 'Select' button is disabled
+ var select = $(".btn-group #timeline-select");
+ if (select.is(":disabled")) {
+ select.removeAttr("disabled");
+ }
+ };
+
+ mod.checkTrimButton = function() {
+ var $over = $sbTable.find(".sb-over.sb-allowed");
+
+ if ($over.length !== 0) {
+ AIRTIME.button.enableButton("icon-cut", true);
+ }
+ else {
+ AIRTIME.button.disableButton("icon-cut", true);
+ }
+ };
+
+ mod.checkDeleteButton = function() {
+ var $selected = $sbTable.find("tr."+SB_SELECTED_CLASS);
+
+ var button = $("#show_builder").find(".icon-trash").parent();
+ if ($selected.length !== 0) {
+ button.removeClass(DISABLED_CLASS);
+ button.removeAttr('disabled');
+ } else {
+ button.addClass(DISABLED_CLASS);
+ button.attr('disabled', 'disabled');
+ }
+ };
+
+ mod.checkJumpToCurrentButton = function() {
+ var $current = $sbTable.find("."+NOW_PLAYING_CLASS);
+
+ if ($current.length !== 0) {
+ AIRTIME.button.enableButton("icon-step-forward", true);
+ }
+ else {
+ AIRTIME.button.disableButton("icon-step-forward", true);
+ }
+ };
+
+ mod.checkCancelButton = function() {
+
+ var $current = $sbTable.find(".sb-current-show"),
+ //this user type should be refactored into a separate users module later
+ //when there's more time and more JS will need to know user data.
+ userType = localStorage.getItem('user-type'),
+ canCancel = false;
+
+ if ($current.length !== 0 && $current.hasClass("sb-allowed")) {
+ canCancel = true;
+ }
+ else if ($current.length !== 0 && (userType === 'A' || userType === 'P')) {
+ canCancel = true;
+ }
+
+ if (canCancel === true) {
+ AIRTIME.button.enableButton("icon-ban-circle", true);
+ }
+ else {
+ AIRTIME.button.disableButton("icon-ban-circle", true);
+ }
+ };
+
+ mod.checkToolBarIcons = function() {
+
+ //library may not be on the page.
+ if (AIRTIME.library !== undefined) {
+ AIRTIME.library.checkAddButton();
+ }
+
+ mod.checkSelectButton();
+ mod.checkTrimButton();
+ mod.checkDeleteButton();
+ mod.checkJumpToCurrentButton();
+ mod.checkCancelButton();
+ };
+
+ mod.selectCursor = function($el) {
+
+ $el.addClass(CURSOR_SELECTED_CLASS);
+ mod.checkToolBarIcons();
+ };
+
+ mod.removeCursor = function($el) {
+
+ $el.removeClass(CURSOR_SELECTED_CLASS);
+ mod.checkToolBarIcons();
+ };
+
+ /*
+ * sNot is an optional string to filter selected elements by. (ex removing the currently playing item)
+ */
+ mod.getSelectedData = function(sNot) {
+ var $selected = $sbTable.find("tr."+SB_SELECTED_CLASS),
+ aData = [],
+ i, length,
+ $item;
+
+ if (sNot !== undefined) {
+ $selected = $selected.not("."+sNot);
+ }
+
+ for (i = 0, length = $selected.length; i < length; i++) {
+ $item = $($selected.get(i));
+ aData.push($item.data('aData'));
+ }
+
+ return aData.reverse();
+ };
+
+ mod.selectAll = function () {
+ var $trs = $sbTable.find("tr.lib-audio").not(".sb-past");
+ $trs.addClass(SB_SELECTED_CLASS);
+
+ mod.checkToolBarIcons();
+ };
+
+ mod.selectNone = function () {
+ var $trs = $sbTable.find("tr.lib-audio");
+ $trs.removeClass(SB_SELECTED_CLASS);
+
+ mod.checkToolBarIcons();
+ };
+
+ mod.disableUI = function() {
+
+ $lib.block({
+ message: "",
+ theme: true,
+ applyPlatformOpacityRules: false
+ });
+
+ $sbContent.block({
+ message: "",
+ theme: true,
+ applyPlatformOpacityRules: false
+ });
+ };
+
+ mod.enableUI = function() {
+ $lib.unblock();
+ $sbContent.unblock();
+
+ //Block UI changes the postion to relative to display the messages.
+ $lib.css("position", "static");
+ $sbContent.css("position", "static");
+ };
+
+ mod.fnItemCallback = function(json) {
+ checkError(json);
+
+ mod.getSelectedCursors();
+ oSchedTable.fnDraw();
+
+ mod.enableUI();
+ //Unneccessary reload of the library pane after moving tracks in the showbuilder pane.
+ //$("#library_content").find("#library_display").dataTable().fnStandingRedraw();
+ };
+
+ mod.getSelectedCursors = function() {
+ cursorIds = [];
+
+ /* We need to keep record of which show the cursor belongs to
+ * in the case where more than one show is displayed in the show builder
+ * because header and footer rows have the same id
+ */
+ showInstanceIds = [];
+
+ /* Keeps track if the row is a footer. We need to do this because
+ * header and footer rows have the save cursorIds and showInstanceId
+ * so both will be selected in the draw callback
+ */
+ headerFooter = [];
+
+ cursors = $(".cursor-selected-row");
+ for (i = 0; i < cursors.length; i++) {
+ cursorIds.push(($(cursors.get(i)).attr("id")));
+ showInstanceIds.push(($(cursors.get(i)).attr("si_id")));
+ if ($(cursors.get(i)).hasClass("sb-footer")) {
+ headerFooter.push("f");
+ } else {
+ headerFooter.push("n");
+ }
+ }
+ };
+
+ mod.fnAdd = function(aMediaIds, aSchedIds) {
+ mod.disableUI();
+ for (var i in aSchedIds) {
+ if ($("#"+aSchedIds[i].id).hasClass("sb-past")) {
+ alert($.i18n._("Cannot add media before currently playing track."));
+ mod.enableUI();
+ return;
+ }
+ }
+
+ $.post(baseUrl+"showbuilder/schedule-add",
+ {"format": "json", "mediaIds": aMediaIds, "schedIds": aSchedIds},
+ mod.fnItemCallback
+ );
+ };
+
+ mod.fnMove = function(aSelect, aAfter) {
+
+ mod.disableUI();
+
+ $.post(baseUrl+"showbuilder/schedule-move",
+ {"format": "json", "selectedItem": aSelect, "afterItem": aAfter},
+ mod.fnItemCallback
+ );
+ };
+
+ mod.fnRemove = function(aItems) {
+
+ mod.disableUI();
+ if (confirm($.i18n._("Delete selected item(s)?"))) {
+ $.post( baseUrl+"showbuilder/schedule-remove",
+ {"items": aItems, "format": "json"},
+ mod.fnItemCallback
+ );
+ }else{
+ mod.enableUI();
+ }
+ };
+
+ mod.fnRemoveSelectedItems = function() {
+ var aData = mod.getSelectedData(),
+ i,
+ length,
+ temp,
+ aItems = [];
+
+ for (i=0, length = aData.length; i < length; i++) {
+ temp = aData[i];
+ aItems.push({"id": temp.id, "instance": temp.instance, "timestamp": temp.timestamp});
+ }
+
+ mod.fnRemove(aItems);
+ };
+
+ mod.fnServerData = function fnBuilderServerData( sSource, aoData, fnCallback ) {
+
+ aoData.push( { name: "timestamp", value: mod.getTimestamp()} );
+ aoData.push( { name: "instances", value: mod.getShowInstances()} );
+ aoData.push( { name: "format", value: "json"} );
+
+ if (mod.fnServerData.hasOwnProperty("start")) {
+ aoData.push( { name: "start", value: mod.fnServerData.start} );
+ }
+ if (mod.fnServerData.hasOwnProperty("end")) {
+ aoData.push( { name: "end", value: mod.fnServerData.end} );
+ }
+ if (mod.fnServerData.hasOwnProperty("ops")) {
+ aoData.push( { name: "myShows", value: mod.fnServerData.ops.myShows} );
+ aoData.push( { name: "showFilter", value: mod.fnServerData.ops.showFilter} );
+ aoData.push( { name: "showInstanceFilter", value: mod.fnServerData.ops.showInstanceFilter} );
+ }
+
+ $.ajax({
+ "dataType": "json",
+ "type": "POST",
+ "url": sSource,
+ "data": aoData,
+ "success": function(json) {
+ mod.updateCalendarStatusIcon(json)
+ mod.setTimestamp(json.timestamp);
+ mod.setShowInstances(json.instances);
+ mod.getSelectedCursors();
+ fnCallback(json);
+ }
+ });
+ };
+
+ mod.jumpToCurrentTrack = function() {
+ var $scroll = $sbContent.find(".dataTables_scrolling");
+ var scrolled = $scroll.scrollTop();
+ var scrollingTop = $scroll.offset().top;
+ var current = $sbTable.find("."+NOW_PLAYING_CLASS);
+ var currentTop = current.offset().top;
+
+ $scroll.scrollTop(currentTop - scrollingTop + scrolled);
+ };
+
+ mod.builderDataTable = function() {
+ $sbContent = $('#show_builder');
+ $lib = $("#library_content"),
+ $sbTable = $sbContent.find('table');
+ var isInitialized = false;
+
+ var lockedPreviewIcon = document.createElement('span');
+ lockedPreviewIcon.setAttribute('class', 'ui-icon ui-icon-locked');
+ var previewIcon = document.createElement('img');
+ previewIcon.setAttribute('src', baseUrl+'css/images/icon_audioclip.png');
+ previewIcon.setAttribute('title', $.i18n._("Track preview"));
+
+ oSchedTable = $sbTable.dataTable( {
+ "aoColumns": [
+ /* Type */ {"mDataProp": "image", "sTitle": "", "sClass": "library_image sb-image", "sWidth": "16px"},
+ /* starts */ {"mDataProp": "starts", "sTitle": $.i18n._("Start"), "sClass": "sb-starts", "sWidth": "60px"},
+ /* ends */ {"mDataProp": "ends", "sTitle": $.i18n._("End"), "sClass": "sb-ends", "sWidth": "60px"},
+ /* runtime */ {"mDataProp": "runtime", "sTitle": $.i18n._("Duration"), "sClass": "library_length sb-length", "sWidth": "65px"},
+ /* title */ {"mDataProp": "title", "sTitle": $.i18n._("Title"), "sClass": "sb-title"},
+ /* creator */ {"mDataProp": "creator", "sTitle": $.i18n._("Creator"), "sClass": "sb-creator"},
+ /* album */ {"mDataProp": "album", "sTitle": $.i18n._("Album"), "sClass": "sb-album"},
+ /* cue in */ {"mDataProp": "cuein", "sTitle": $.i18n._("Cue In"), "bVisible": false, "sClass": "sb-cue-in"},
+ /* cue out */ {"mDataProp": "cueout", "sTitle": $.i18n._("Cue Out"), "bVisible": false, "sClass": "sb-cue-out"},
+ /* fade in */ {"mDataProp": "fadein", "sTitle": $.i18n._("Fade In"), "bVisible": false, "sClass": "sb-fade-in"},
+ /* fade out */ {"mDataProp": "fadeout", "sTitle": $.i18n._("Fade Out"), "bVisible": false, "sClass": "sb-fade-out"},
+ /* Mime */ {"mDataProp" : "mime", "sTitle" : $.i18n._("Mime"), "bVisible": false, "sClass": "sb-mime"}
+ ],
+
+ "bJQueryUI": true,
+ "bSort": false,
+ "bFilter": false,
+ "bProcessing": true,
+ "bServerSide": true,
+ "bInfo": false,
+ "bAutoWidth": false,
+ "bDeferRender": true,
+
+ "bStateSave": true,
+ "fnStateSaveParams": function (oSettings, oData) {
+ //remove oData components we don't want to save.
+ delete oData.oSearch;
+ delete oData.aoSearchCols;
+ },
+ "fnStateSave": function fnStateSave(oSettings, oData) {
+ localStorage.setItem('datatables-timeline', JSON.stringify(oData));
+ },
+ "fnStateLoad": function fnBuilderStateLoad(oSettings) {
+ var settings = localStorage.getItem('datatables-timeline');
+
+ if (settings !== "") {
+ return JSON.parse(settings);
+ }
+ },
+ "fnStateLoadParams": function (oSettings, oData) {
+ var i,
+ length,
+ a = oData.abVisCols;
+
+ //putting serialized data back into the correct js type to make
+ //sure everything works properly.
+ for (i = 0, length = a.length; i < length; i++) {
+ if (typeof(a[i]) === "string") {
+ a[i] = (a[i] === "true") ? true : false;
+ }
+ }
+
+ oData.iCreate = parseInt(oData.iCreate, 10);
+ },
+
+ "fnServerData": mod.fnServerData,
+ "fnRowCallback": function fnRowCallback( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
+ var i, length,
+ sSeparatorHTML,
+ fnPrepareSeparatorRow,
+ $node,
+ cl="",
+ //background-color to imitate calendar color.
+ r,g,b,a,
+ $nRow = $(nRow),
+ $image,
+ $div,
+ headerIcon;
+
+ fnPrepareSeparatorRow = function fnPrepareSeparatorRow(sRowContent, sClass, iNodeIndex) {
+ //Albert:
+ //$(nRow.children[iNodeIndex]).replaceWith(emptyNode);
+
+ $node = $(nRow.children[iNodeIndex]);
+ $node.html(sRowContent);
+
+ $node.attr('colspan',100);
+ for (i = iNodeIndex + 1, length = nRow.children.length; i < length; i = i+1) {
+ $node = $(nRow.children[i]);
+ $node.html("");
+ $node.attr("style", "display : none");
+ }
+
+ $nRow.addClass(sClass);
+
+ };
+
+ if (aData.header === true) {
+ //remove the column classes from all tds.
+ $nRow.find('td').removeClass();
+
+ $node = $(nRow.children[0]);
+ $node.html("");
+ cl = 'sb-header';
+
+ if (aData.record === true) {
+ $div = $("
", {
+ "class": "small-icon " + headerIcon
+ });
+ $node.append($div);
+ }
+ else if (aData.rebroadcast === true) {
+ $div = $("
", {
+ "class": "small-icon rebroadcast"
+ });
+ $node.append($div);
+ }
+
+ sSeparatorHTML = ''+aData.title+' ';
+
+ if (aData.rebroadcast === true) {
+ sSeparatorHTML += ''+aData.rebroadcast_title+' ';
+ }
+
+ sSeparatorHTML += '';
+
+ if (aData.startDate === aData.endDate) {
+ sSeparatorHTML += ''+aData.startDate+' '+aData.startTime+' ';
+ sSeparatorHTML +='-'+aData.endTime+' ';
+ }
+ else {
+ sSeparatorHTML += ''+aData.startDate+' '+aData.startTime+' ';
+ sSeparatorHTML +='-'+aData.endDate+' '+aData.endTime+' ';
+ }
+
+ sSeparatorHTML += ' ';
+
+ fnPrepareSeparatorRow(sSeparatorHTML, cl, 1);
+ }
+ else if (aData.footer === true) {
+ //remove the column classes from all tds.
+ $nRow.find('td').removeClass();
+
+ $node = $(nRow.children[0]);
+ cl = 'sb-footer';
+
+ //check the show's content status.
+ if (aData.runtime >= 0) {
+ $node.html(' ');
+ cl = cl + ' ui-state-highlight';
+ }
+ else {
+ $node.html(' ');
+ cl = cl + ' ui-state-error';
+ }
+
+ sSeparatorHTML = ''+aData.fRuntime+' ';
+ fnPrepareSeparatorRow(sSeparatorHTML, cl, 1);
+ }
+ else if (aData.empty === true) {
+ //remove the column classes from all tds.
+ $nRow.find('td').removeClass();
+
+ $node = $(nRow.children[0]);
+ if ($node) {
+ $node.empty();
+ }
+
+ sSeparatorHTML = ''+$.i18n._("Show Empty")+' ';
+ cl = cl + " sb-empty odd";
+
+ fnPrepareSeparatorRow(sSeparatorHTML, cl, 1);
+ }
+ else if (aData.record === true) {
+ //remove the column classes from all tds.
+ $nRow.find('td').removeClass();
+
+ $node = $(nRow.children[0]);
+ $node.html('');
+
+ sSeparatorHTML = ''+$.i18n._("Recording From Line In")+' ';
+ cl = cl + " sb-record odd";
+ fnPrepareSeparatorRow(sSeparatorHTML, cl, 1);
+ }
+ else {
+
+ //add the play function if the file exists on disk.
+ $image = $nRow.find('td.sb-image');
+ $image.empty();
+ //check if the file exists.
+ if (aData.image === true) {
+ $nRow.addClass("lib-audio");
+ if (!isAudioSupported(aData.mime)) {
+ //$image.html(' ');
+ $image.append(lockedPreviewIcon);
+ } else {
+ $image.append(previewIcon.cloneNode(false));
+ $image.click(function() {
+ open_show_preview(aData.instance, aData.pos);
+ return false;
+ });
+
+ }
+ }
+ else {
+ $image.html(' ');
+ $image.find(".ui-icon-alert").qtip({
+ content: {
+ text: $.i18n._("Airtime is unsure about the status of this file. This can happen when the file is on a remote drive that is unaccessible or the file is in a directory that isn't \"watched\" anymore.")
+ },
+ style: {
+ classes: "ui-tooltip-dark"
+ },
+ show: 'mouseover',
+ hide: 'mouseout'
+ });
+ }
+ }
+
+ //add the show colour to the leftmost td
+ if (aData.footer !== true) {
+
+ if ($nRow.hasClass('sb-header')) {
+ a = 1;
+ }
+ else if ($nRow.hasClass('odd')) {
+ a = 0.3;
+ }
+ else if ($nRow.hasClass('even')) {
+ a = 0.4;
+ }
+
+ //convert from hex to rgb.
+ r = parseInt((aData.backgroundColor).substring(0,2), 16);
+ g = parseInt((aData.backgroundColor).substring(2,4), 16);
+ b = parseInt((aData.backgroundColor).substring(4,6), 16);
+
+ $nRow.find('td:first').css('background', 'rgba('+r+', '+g+', '+b+', '+a+')');
+ }
+
+ //save some info for reordering purposes.
+ $nRow.data({"aData": aData});
+
+ if (aData.scheduled === 1) {
+ $nRow.addClass(NOW_PLAYING_CLASS);
+ }
+ else if (aData.scheduled === 0) {
+ $nRow.addClass("sb-past");
+ }
+ else {
+ $nRow.addClass("sb-future");
+ }
+
+ if (aData.allowed !== true || aData.linked_allowed === false) {
+ $nRow.addClass("sb-not-allowed");
+ }
+ else {
+ $nRow.addClass("sb-allowed");
+ $nRow.attr("id", aData.id);
+ $nRow.attr("si_id", aData.instance);
+ }
+
+ //status used to colour tracks.
+ if (aData.status === 2) {
+ $nRow.addClass("sb-boundry");
+ }
+ else if (aData.status === 0) {
+ $nRow.addClass("sb-over");
+ }
+
+ if (aData.currentShow === true) {
+ $nRow.addClass("sb-current-show");
+ }
+ },
+ //remove any selected nodes before the draw.
+ "fnPreDrawCallback": function( oSettings ) {
+
+ //make sure any dragging helpers are removed or else they'll be stranded on the screen.
+ $("#draggingContainer").remove();
+ },
+ "fnDrawCallback": function fnBuilderDrawCallback(oSettings, json) {
+
+ if (!isInitialized) {
+ //when coming to 'Now Playing' page we want the page
+ //to jump to the current track
+ if ($(this).find("."+NOW_PLAYING_CLASS).length > 0) {
+ mod.jumpToCurrentTrack();
+ }
+ }
+
+ isInitialized = true;
+ var aData,
+ elements,
+ i, length, temp;
+
+ clearTimeout(mod.timeout);
+
+ //order of importance of elements for setting the next timeout.
+ elements = [
+ $sbTable.find("tr."+NOW_PLAYING_CLASS),
+ $sbTable.find("tbody").find("tr.sb-future.sb-footer, tr.sb-future.sb-header").filter(":first")
+ ];
+
+ //check which element we should set a timeout relative to.
+ for (i = 0, length = elements.length; i < length; i++) {
+ temp = elements[i];
+
+ if (temp.length > 0) {
+ aData = temp.data("aData");
+ // max time interval
+ // setTimeout allows only up to (2^31)-1 millisecs timeout value
+ maxRefreshInterval = Math.pow(2, 31) - 1;
+ refreshInterval = aData.refresh * 1000;
+ if(refreshInterval > maxRefreshInterval){
+ refreshInterval = maxRefreshInterval;
+ }
+ mod.timeout = setTimeout(function() {mod.refresh(aData.id)}, refreshInterval); //need refresh in milliseconds
+ break;
+ }
+ }
+
+
+ mod.checkToolBarIcons();
+ },
+
+ // R = ColReorder, C = ColVis
+ "sDom": 'R<"dt-process-rel"r><"sb-padded"<"H"C>><"dataTables_scrolling sb-padded"t>',
+
+ "oColVis": {
+ "aiExclude": [ 0, 1 ],
+ "buttonText": $.i18n._("Show / hide columns"),
+ },
+
+ "oColReorder": {
+ "iFixedColumns": 2
+ },
+
+ "sAjaxDataProp": "schedule",
+ "oLanguage": datatables_dict,
+ "sAjaxSource": baseUrl+"showbuilder/builder-feed"
+ });
+
+ $sbTable.find("tbody").on("click", "tr:not(.sb-past)", function(ev) {
+
+ var $tr = $(this),
+ // Get the ID of the selected row
+ $rowId = $tr.attr("id");
+
+ if (ev.shiftKey && $previouslySelected !== undefined) {
+ if ($previouslySelected.attr("id") == $rowId) {
+ return;
+ }
+
+ // If the selected row comes before the previously selected row,
+ // we want to select previous rows, otherwise we select next
+ if ($previouslySelected.prevAll("#"+$rowId).length !== 0) {
+ $previouslySelected.prevUntil($tr).each(function(i, el){
+ $(el).addClass(SB_SELECTED_CLASS);
+ });
+ } else {
+ $previouslySelected.nextUntil($tr).each(function(i, el){
+ $(el).addClass(SB_SELECTED_CLASS);
+ });
+ }
+ $tr.addClass(SB_SELECTED_CLASS);
+ } else if (ev.ctrlKey && $previouslySelected !== undefined) {
+ $tr.addClass(SB_SELECTED_CLASS);
+ } else {
+ $("."+SB_SELECTED_CLASS).removeClass(SB_SELECTED_CLASS);
+ $tr.addClass(SB_SELECTED_CLASS);
+ }
+
+ // Remember this row so we can properly multiselect
+ $previouslySelected = $tr;
+
+ mod.checkToolBarIcons();
+ });
+
+ var sortableConf = (function(){
+ var origTrs,
+ aItemData = [],
+ oPrevData,
+ fnAdd,
+ fnMove,
+ fnReceive,
+ fnUpdate,
+ i,
+ html,
+ helperData,
+ draggingContainer;
+
+ fnAdd = function() {
+ var aMediaIds = [],
+ aSchedIds = [];
+
+ for(i = 0; i < aItemData.length; i++) {
+ aMediaIds.push({"id": aItemData[i].id, "type": aItemData[i].ftype});
+ }
+ aSchedIds.push({"id": oPrevData.id, "instance": oPrevData.instance, "timestamp": oPrevData.timestamp});
+
+ mod.fnAdd(aMediaIds, aSchedIds);
+ };
+
+ fnMove = function() {
+ var aSelect = [],
+ aAfter = [];
+
+ for(i = 0; i < helperData.length; i++) {
+ aSelect.push({"id": helperData[i].id, "instance": helperData[i].instance, "timestamp": helperData[i].timestamp});
+ }
+
+ aAfter.push({"id": oPrevData.id, "instance": oPrevData.instance, "timestamp": oPrevData.timestamp});
+
+ mod.fnMove(aSelect, aAfter);
+ };
+
+ fnReceive = function(event, ui) {
+ var aItems = [];
+
+ AIRTIME.library.addToChosen(ui.item);
+
+ aItems = AIRTIME.library.getSelectedData();
+ origTrs = aItems;
+ html = ui.helper.html();
+
+ AIRTIME.library.removeFromChosen(ui.item);
+ };
+
+ fnUpdate = function(event, ui) {
+ var prev = ui.item.prev();
+
+ //can't add items outside of shows.
+ if (prev.find("td:first").hasClass("dataTables_empty")
+ || prev.length === 0) {
+ alert($.i18n._("Cannot schedule outside a show."));
+ ui.item.remove();
+ return;
+ }
+
+ //if item is added after a footer, add the item after the last item in the show.
+ if (prev.hasClass("sb-footer")) {
+ prev = prev.prev();
+ }
+
+ aItemData = [];
+ oPrevData = prev.data("aData");
+
+ //item was dragged in
+ if (origTrs !== undefined) {
+
+ $sbTable.find("tr.ui-draggable")
+ .empty()
+ .after(html);
+
+ aItemData = origTrs;
+ origTrs = undefined;
+ fnAdd();
+ }
+ //item was reordered.
+ else {
+
+ //ui.item
+ // .empty()
+ // .after(draggingContainer.html());
+
+ aItemData.push(ui.item.data("aData"));
+ fnMove();
+ }
+ };
+
+ return {
+ placeholder: "sb-placeholder ui-state-highlight",
+ //forcePlaceholderSize: true,
+ distance: 10,
+ helper:
+ function(event, item) {
+ var selected = mod.getSelectedData(NOW_PLAYING_CLASS),
+ thead = $("#show_builder_table thead"),
+ colspan = thead.find("th").length,
+ trfirst = thead.find("tr:first"),
+ width = trfirst.width(),
+ height = trfirst.height(),
+ message;
+
+ //if nothing is checked select the dragged item.
+ if (selected.length === 0) {
+ selected = [item.data("aData")];
+ }
+
+ if (selected.length === 1) {
+ message = sprintf($.i18n._("Moving %s"), selected[0].title);
+ //draggingContainer = item; //Default DataTables drag and drop
+ draggingContainer = $(' ')
+ .addClass('sb-helper')
+ .append(' ')
+ .find("td")
+ .attr("colspan", colspan)
+ .width(width)
+ .height(height)
+ .addClass("ui-state-highlight")
+ .append(message)
+ .end();
+ }
+ else {
+ message = sprintf($.i18n._("Moving %s Items"), selected.length);
+ draggingContainer = $(' ')
+ .addClass('sb-helper')
+ .append(' ')
+ .find("td")
+ .attr("colspan", colspan)
+ .width(width)
+ .height(height)
+ .addClass("ui-state-highlight")
+ .append(message)
+ .end();
+
+ }
+
+ helperData = selected;
+
+ return draggingContainer;
+ },
+ items: 'tr:not(:first, :last, .sb-header, .sb-not-allowed, .sb-past, .sb-now-playing, .sb-empty)',
+ cancel: '.sb-footer',
+ receive: fnReceive,
+ update: fnUpdate,
+ start: function(event, ui) {
+ var elements = $sbTable.find('tr.'+SB_SELECTED_CLASS).not("."+NOW_PLAYING_CLASS);
+ elements.hide();
+ },
+ stop: function() {
+ var elements = $sbTable.find('tr.'+SB_SELECTED_CLASS).not("."+NOW_PLAYING_CLASS);
+ elements.show();
+ }
+ };
+ }());
+
+ $sbTable.sortable(sortableConf);
+
+ //start setup of the builder toolbar.
+ $toolbar = $(".sb-content .fg-toolbar");
+
+ $menu = $("
");
+ $menu.append("" +
+ "" +
+ $.i18n._("Select")+" " +
+ " " +
+ "" +
+ "
")
+ .append("" +
+ "" +
+ "
")
+ .append("" +
+ "" +
+ "
");
+
+ //if 'Add/Remove content' was chosen from the context menu
+ //in the Calendar do not append these buttons
+ if ($(".ui-dialog-content").length === 0) {
+ $menu.append("" +
+ "" +
+ "
")
+ .append("" +
+ "" +
+ "
");
+ }
+
+ if (localStorage.getItem('user-type') != 'G') {
+ $toolbar.append($menu);
+ }
+
+ $menu = undefined;
+
+ $('#timeline-sa').click(function(){mod.selectAll();});
+ $('#timeline-sn').click(function(){mod.selectNone();});
+
+ //cancel current show
+ $toolbar.find('.icon-ban-circle').parent()
+ .click(function() {
+ var $tr,
+ data,
+ msg = $.i18n._('Cancel Current Show?');
+
+ if (AIRTIME.button.isDisabled('icon-ban-circle', true) === true) {
+ return;
+ }
+
+ $tr = $sbTable.find('tr.sb-future:first');
+
+ if ($tr.hasClass('sb-current-show')) {
+ data = $tr.data("aData");
+
+ if (data.record === true) {
+ msg = $.i18n._('Stop recording current show?');
+ }
+
+ if (confirm(msg)) {
+ var url = baseUrl+"Schedule/cancel-current-show";
+ $.ajax({
+ url: url,
+ data: {format: "json", id: data.instance},
+ success: function(data){
+ $("#library_content").find("#library_display").dataTable().fnStandingRedraw();
+ var oTable = $sbTable.dataTable();
+ oTable.fnDraw();
+ }
+ });
+ }
+ }
+ });
+
+ //jump to current
+ $toolbar.find('.icon-step-forward').parent()
+ .click(function() {
+
+ if (AIRTIME.button.isDisabled('icon-step-forward', true) === true) {
+ return;
+ }
+ /*
+ var $scroll = $sbContent.find(".dataTables_scrolling"),
+ scrolled = $scroll.scrollTop(),
+ scrollingTop = $scroll.offset().top,
+ current = $sbTable.find("."+NOW_PLAYING_CLASS),
+ currentTop = current.offset().top;
+
+ $scroll.scrollTop(currentTop - scrollingTop + scrolled);
+ */
+ mod.jumpToCurrentTrack();
+ });
+
+ //delete overbooked tracks.
+ $toolbar.find('.icon-cut', true).parent()
+ .click(function() {
+
+ if (AIRTIME.button.isDisabled('icon-cut', true) === true) {
+ return;
+ }
+
+ var temp,
+ aItems = [],
+ trs = $sbTable.find(".sb-over.sb-future.sb-allowed");
+
+ trs.each(function(){
+ temp = $(this).data("aData");
+ aItems.push({"id": temp.id, "instance": temp.instance, "timestamp": temp.timestamp});
+ });
+
+ mod.fnRemove(aItems);
+ });
+
+ //delete selected tracks
+ $toolbar.find('.icon-trash').parent()
+ .click(function() {
+
+ var button = $("#show_builder").find(".icon-trash").parent();
+
+ if (button.hasClass(DISABLED_CLASS)) {
+ return;
+ }
+
+ mod.fnRemoveSelectedItems();
+ });
+
+ //add events to cursors.
+ $sbTable.find("tbody").on("click", "div.marker", function(event) {
+ var $tr = $(this).parents("tr"),
+ $trs;
+
+ if ($tr.hasClass(CURSOR_SELECTED_CLASS)) {
+ mod.removeCursor($tr);
+ }
+ else {
+ mod.selectCursor($tr);
+ }
+
+ if (event.ctrlKey === false) {
+ $trs = $sbTable.find('.'+CURSOR_SELECTED_CLASS).not($tr);
+ mod.removeCursor($trs);
+ }
+
+ return false;
+ });
+
+ /*
+ * Select button dropdown state in the toolbar.
+ * The button has to be disabled to prevent the dropdown
+ * from opening
+ */
+ $sbContent.on("mouseenter", ".btn-group #timeline-select", function(ev) {
+ $el = $(this);
+
+ if ($el.hasClass("ui-state-disabled")) {
+ $el.attr("disabled", "disabled");
+ }
+ else {
+ $el.removeAttr("disabled");
+ }
+ });
+ };
+
+ return AIRTIME;
+
+}(AIRTIME || {}));
diff --git a/airtime_mvc/public/js/airtime/showbuilder/main_builder_test.js b/airtime_mvc/public/js/airtime/showbuilder/main_builder_test.js
new file mode 100644
index 000000000..1da573d13
--- /dev/null
+++ b/airtime_mvc/public/js/airtime/showbuilder/main_builder_test.js
@@ -0,0 +1,347 @@
+AIRTIME = (function(AIRTIME) {
+
+ var viewport,
+ $lib,
+ $libWrapper,
+ $builder,
+ $fs,
+ widgetHeight,
+ screenWidth,
+ resizeTimeout,
+ oBaseDatePickerSettings,
+ oBaseTimePickerSettings,
+ oRange,
+ dateStartId = "#sb_date_start",
+ timeStartId = "#sb_time_start",
+ dateEndId = "#sb_date_end",
+ timeEndId = "#sb_time_end",
+ mod;
+
+ if (AIRTIME.builderMain === undefined) {
+ AIRTIME.builderMain = {};
+ }
+ mod = AIRTIME.builderMain;
+
+ oBaseDatePickerSettings = {
+ dateFormat: 'yy-mm-dd',
+ //i18n_months, i18n_days_short are in common.js
+ monthNames: i18n_months,
+ dayNamesMin: i18n_days_short,
+ onClick: function(sDate, oDatePicker) {
+ $(this).datepicker( "setDate", sDate );
+ },
+ onClose: validateTimeRange
+ };
+
+ oBaseTimePickerSettings = {
+ showPeriodLabels: false,
+ showCloseButton: true,
+ closeButtonText: $.i18n._("Done"),
+ showLeadingZero: false,
+ defaultTime: '0:00',
+ hourText: $.i18n._("Hour"),
+ minuteText: $.i18n._("Minute"),
+ onClose: validateTimeRange
+ };
+
+ function setWidgetSize() {
+ viewport = AIRTIME.utilities.findViewportDimensions();
+ widgetHeight = viewport.height - 180;
+ screenWidth = Math.floor(viewport.width - 50);
+
+ var libTableHeight = widgetHeight - 175,
+ builderTableHeight = widgetHeight - 95,
+ oTable;
+
+ if ($fs.is(':visible')) {
+ builderTableHeight = builderTableHeight - 40;
+ }
+
+ //set the heights of the main widgets.
+ $builder//.height(widgetHeight)
+ .find(".dataTables_scrolling")
+ .css("max-height", builderTableHeight)
+ .end();
+ //.width(screenWidth);
+
+ $lib//.height(widgetHeight)
+ .find(".dataTables_scrolling")
+ .css("max-height", libTableHeight)
+ .end();
+
+ if ($lib.filter(':visible').length > 0) {
+
+ //$lib.width(Math.floor(screenWidth * 0.47));
+
+ $builder//.width(Math.floor(screenWidth * 0.47))
+ .find("#sb_edit")
+ .remove()
+ .end()
+ .find("#sb_date_start")
+ .css("margin-left", 0)
+ .end();
+
+ oTable = $('#show_builder_table').dataTable();
+ //oTable.fnDraw();
+ }
+ }
+
+ function validateTimeRange() {
+ var oRange,
+ inputs = $('.sb-timerange > input'),
+ start, end;
+
+ oRange = AIRTIME.utilities.fnGetScheduleRange(dateStartId, timeStartId, dateEndId, timeEndId);
+
+ start = oRange.start;
+ end = oRange.end;
+
+ if (end >= start) {
+ inputs.removeClass('error');
+ }
+ else {
+ if (!inputs.hasClass('error')) {
+ inputs.addClass('error');
+ }
+ }
+
+ return {
+ start: start,
+ end: end,
+ isValid: end >= start
+ };
+ }
+
+ function showSearchSubmit() {
+ var fn,
+ op,
+ oTable = $('#show_builder_table').dataTable(),
+ check;
+
+ check = validateTimeRange();
+
+ if (check.isValid) {
+
+ //reset timestamp value since input values could have changed.
+ AIRTIME.showbuilder.resetTimestamp();
+
+ fn = oTable.fnSettings().fnServerData;
+ fn.start = check.start;
+ fn.end = check.end;
+
+ op = $("div.sb-advanced-options");
+ if (op.is(":visible")) {
+
+ if (fn.ops === undefined) {
+ fn.ops = {};
+ }
+ fn.ops.showFilter = op.find("#sb_show_filter").val();
+ fn.ops.myShows = op.find("#sb_my_shows").is(":checked") ? 1 : 0;
+ }
+
+ oTable.fnDraw();
+ }
+ }
+
+ mod.onReady = function() {
+
+ Dropzone.options.uploadForm = {
+ init: function () {
+ this.on("sending", function (file, xhr, data) {
+ data.append("csrf_token", $("#csrf").val());
+ });
+ }
+ };
+
+ // define module vars.
+ $lib = $("#library_content");
+ $builder = $("#show_builder");
+ $fs = $builder.find('fieldset');
+
+ /*
+ * Icon hover states for search.
+ */
+ $builder.on("mouseenter", ".sb-timerange .ui-button", function(ev) {
+ $(this).addClass("ui-state-hover");
+ });
+ $builder.on("mouseleave", ".sb-timerange .ui-button", function(ev) {
+ $(this).removeClass("ui-state-hover");
+ });
+
+ $builder.find(dateStartId)
+ .datepicker(oBaseDatePickerSettings)
+ .blur(validateTimeRange);
+
+ $builder.find(timeStartId)
+ .timepicker(oBaseTimePickerSettings)
+ .blur(validateTimeRange);
+
+ $builder.find(dateEndId)
+ .datepicker(oBaseDatePickerSettings)
+ .blur(validateTimeRange);
+
+ $builder.find(timeEndId)
+ .timepicker(oBaseTimePickerSettings)
+ .blur(validateTimeRange);
+
+
+ oRange = AIRTIME.utilities.fnGetScheduleRange(dateStartId, timeStartId,
+ dateEndId, timeEndId);
+ AIRTIME.showbuilder.fnServerData.start = oRange.start;
+ AIRTIME.showbuilder.fnServerData.end = oRange.end;
+
+ //the user might not have the library on the page (guest user)
+ if (AIRTIME.library !== undefined) {
+ AIRTIME.library.libraryInit();
+ }
+
+ AIRTIME.showbuilder.builderDataTable();
+ setWidgetSize();
+
+ $libWrapper = $lib.find("#library_display_wrapper");
+ $builder.find('.dataTables_scrolling').css("max-height",
+ widgetHeight - 95);
+
+ $builder.on("click", "#sb_submit", showSearchSubmit);
+
+ $builder.on("click", "#sb_edit", function(ev) {
+ var schedTable = $("#show_builder_table").dataTable();
+
+ // reset timestamp to redraw the cursors.
+ AIRTIME.showbuilder.resetTimestamp();
+
+ $lib.show().width(Math.floor(screenWidth * 0.48));
+
+ $builder.width(Math.floor(screenWidth * 0.48)).find("#sb_edit")
+ .remove().end().find("#sb_date_start")
+ .css("margin-left", 0).end();
+
+ schedTable.fnDraw();
+
+ $.ajax( {
+ url : baseUrl+"usersettings/set-now-playing-screen-settings",
+ type : "POST",
+ data : {
+ settings : {
+ library : true
+ },
+ format : "json"
+ },
+ dataType : "json",
+ success : function() {
+ }
+ });
+ });
+
+ $lib.on("click", "#sb_lib_close", function() {
+ var schedTable = $("#show_builder_table").dataTable();
+
+ $lib.hide();
+ $builder.width(screenWidth).find(".sb-timerange").find("#sb_date_start").css("margin-left", 30)
+ .end().end();
+
+ schedTable.fnDraw();
+
+ $.ajax( {
+ url : baseUrl+"usersettings/set-now-playing-screen-settings",
+ type : "POST",
+ data : {
+ settings : {
+ library : false
+ },
+ format : "json"
+ },
+ dataType : "json",
+ success : function() {
+ }
+ });
+ });
+
+ $builder.find('legend').click(
+ function(ev, item) {
+
+ if ($fs.hasClass("closed")) {
+
+ $fs.removeClass("closed");
+ $builder.find('.dataTables_scrolling').css(
+ "max-height", widgetHeight - 150);
+ } else {
+ $fs.addClass("closed");
+
+ // set defaults for the options.
+ $fs.find('select').val(0);
+ $fs.find('input[type="checkbox"]').attr("checked",
+ false);
+ $builder.find('.dataTables_scrolling').css(
+ "max-height", widgetHeight - 110);
+ }
+ });
+
+ // set click event for all my shows checkbox.
+ $builder.on("click", "#sb_my_shows", function(ev) {
+
+ if ($(this).is(':checked')) {
+ $(ev.delegateTarget).find('#sb_show_filter').val(0);
+ }
+
+ showSearchSubmit();
+ });
+
+ //set select event for choosing a show.
+ $builder.on("change", '#sb_show_filter', function(ev) {
+
+ if ($(this).val() !== 0) {
+ $(ev.delegateTarget).find('#sb_my_shows')
+ .attr("checked", false);
+ }
+
+ showSearchSubmit();
+
+ });
+
+ function checkScheduleUpdates() {
+ var data = {}, oTable = $('#show_builder_table').dataTable(), fn = oTable
+ .fnSettings().fnServerData, start = fn.start, end = fn.end;
+
+ data["format"] = "json";
+ data["start"] = start;
+ data["end"] = end;
+ data["timestamp"] = AIRTIME.showbuilder.getTimestamp();
+ data["instances"] = AIRTIME.showbuilder.getShowInstances();
+
+ if (fn.hasOwnProperty("ops")) {
+ data["myShows"] = fn.ops.myShows;
+ data["showFilter"] = fn.ops.showFilter;
+ data["showInstanceFilter"] = fn.ops.showInstanceFilter;
+ }
+
+ $.ajax( {
+ "dataType" : "json",
+ "type" : "GET",
+ "url" : baseUrl+"showbuilder/check-builder-feed",
+ "data" : data,
+ "success" : function(json) {
+ if (json.update === true) {
+ oTable.fnDraw();
+ }
+ setTimeout(checkScheduleUpdates, 5000);
+ }
+ });
+
+ //check if the timeline view needs updating.
+ setTimeout(checkScheduleUpdates, 5000);
+ }
+ };
+
+ mod.onResize = function() {
+
+ clearTimeout(resizeTimeout);
+ resizeTimeout = setTimeout(setWidgetSize, 100);
+ };
+
+ return AIRTIME;
+
+} (AIRTIME || {}));
+
+$(document).ready(AIRTIME.builderMain.onReady);
+$(window).resize(AIRTIME.builderMain.onResize);
diff --git a/airtime_mvc/public/js/libs/dropzone.min.js b/airtime_mvc/public/js/libs/dropzone.min.js
new file mode 100644
index 000000000..56f769591
--- /dev/null
+++ b/airtime_mvc/public/js/libs/dropzone.min.js
@@ -0,0 +1,2 @@
+(function(){var a,b,c,d,e,f,g,h,i=[].slice,j={}.hasOwnProperty,k=function(a,b){function c(){this.constructor=a}for(var d in b)j.call(b,d)&&(a[d]=b[d]);return c.prototype=b.prototype,a.prototype=new c,a.__super__=b.prototype,a};g=function(){},b=function(){function a(){}return a.prototype.addEventListener=a.prototype.on,a.prototype.on=function(a,b){return this._callbacks=this._callbacks||{},this._callbacks[a]||(this._callbacks[a]=[]),this._callbacks[a].push(b),this},a.prototype.emit=function(){var a,b,c,d,e,f;if(d=arguments[0],a=2<=arguments.length?i.call(arguments,1):[],this._callbacks=this._callbacks||{},c=this._callbacks[d])for(e=0,f=c.length;f>e;e++)b=c[e],b.apply(this,a);return this},a.prototype.removeListener=a.prototype.off,a.prototype.removeAllListeners=a.prototype.off,a.prototype.removeEventListener=a.prototype.off,a.prototype.off=function(a,b){var c,d,e,f,g;if(!this._callbacks||0===arguments.length)return this._callbacks={},this;if(d=this._callbacks[a],!d)return this;if(1===arguments.length)return delete this._callbacks[a],this;for(e=f=0,g=d.length;g>f;e=++f)if(c=d[e],c===b){d.splice(e,1);break}return this},a}(),a=function(a){function c(a,b){var e,f,g;if(this.element=a,this.version=c.version,this.defaultOptions.previewTemplate=this.defaultOptions.previewTemplate.replace(/\n*/g,""),this.clickableElements=[],this.listeners=[],this.files=[],"string"==typeof this.element&&(this.element=document.querySelector(this.element)),!this.element||null==this.element.nodeType)throw new Error("Invalid dropzone element.");if(this.element.dropzone)throw new Error("Dropzone already attached.");if(c.instances.push(this),this.element.dropzone=this,e=null!=(g=c.optionsForElement(this.element))?g:{},this.options=d({},this.defaultOptions,e,null!=b?b:{}),this.options.forceFallback||!c.isBrowserSupported())return this.options.fallback.call(this);if(null==this.options.url&&(this.options.url=this.element.getAttribute("action")),!this.options.url)throw new Error("No URL provided.");if(this.options.acceptedFiles&&this.options.acceptedMimeTypes)throw new Error("You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated.");this.options.acceptedMimeTypes&&(this.options.acceptedFiles=this.options.acceptedMimeTypes,delete this.options.acceptedMimeTypes),this.options.method=this.options.method.toUpperCase(),(f=this.getExistingFallback())&&f.parentNode&&f.parentNode.removeChild(f),this.options.previewsContainer!==!1&&(this.previewsContainer=this.options.previewsContainer?c.getElement(this.options.previewsContainer,"previewsContainer"):this.element),this.options.clickable&&(this.clickableElements=this.options.clickable===!0?[this.element]:c.getElements(this.options.clickable,"clickable")),this.init()}var d,e;return k(c,a),c.prototype.Emitter=b,c.prototype.events=["drop","dragstart","dragend","dragenter","dragover","dragleave","addedfile","removedfile","thumbnail","error","errormultiple","processing","processingmultiple","uploadprogress","totaluploadprogress","sending","sendingmultiple","success","successmultiple","canceled","canceledmultiple","complete","completemultiple","reset","maxfilesexceeded","maxfilesreached","queuecomplete"],c.prototype.defaultOptions={url:null,method:"post",withCredentials:!1,parallelUploads:2,uploadMultiple:!1,maxFilesize:256,paramName:"file",createImageThumbnails:!0,maxThumbnailFilesize:10,thumbnailWidth:120,thumbnailHeight:120,filesizeBase:1e3,maxFiles:null,filesizeBase:1e3,params:{},clickable:!0,ignoreHiddenFiles:!0,acceptedFiles:null,acceptedMimeTypes:null,autoProcessQueue:!0,autoQueue:!0,addRemoveLinks:!1,previewsContainer:null,capture:null,dictDefaultMessage:"Drop files here to upload",dictFallbackMessage:"Your browser does not support drag'n'drop file uploads.",dictFallbackText:"Please use the fallback form below to upload your files like in the olden days.",dictFileTooBig:"File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB.",dictInvalidFileType:"You can't upload files of this type.",dictResponseError:"Server responded with {{statusCode}} code.",dictCancelUpload:"Cancel upload",dictCancelUploadConfirmation:"Are you sure you want to cancel this upload?",dictRemoveFile:"Remove file",dictRemoveFileConfirmation:null,dictMaxFilesExceeded:"You can not upload any more files.",accept:function(a,b){return b()},init:function(){return g},forceFallback:!1,fallback:function(){var a,b,d,e,f,g;for(this.element.className=""+this.element.className+" dz-browser-not-supported",g=this.element.getElementsByTagName("div"),e=0,f=g.length;f>e;e++)a=g[e],/(^| )dz-message($| )/.test(a.className)&&(b=a,a.className="dz-message");return b||(b=c.createElement('
'),this.element.appendChild(b)),d=b.getElementsByTagName("span")[0],d&&(d.textContent=this.options.dictFallbackMessage),this.element.appendChild(this.getFallbackForm())},resize:function(a){var b,c,d;return b={srcX:0,srcY:0,srcWidth:a.width,srcHeight:a.height},c=a.width/a.height,b.optWidth=this.options.thumbnailWidth,b.optHeight=this.options.thumbnailHeight,null==b.optWidth&&null==b.optHeight?(b.optWidth=b.srcWidth,b.optHeight=b.srcHeight):null==b.optWidth?b.optWidth=c*b.optHeight:null==b.optHeight&&(b.optHeight=1/c*b.optWidth),d=b.optWidth/b.optHeight,a.heightd?(b.srcHeight=a.height,b.srcWidth=b.srcHeight*d):(b.srcWidth=a.width,b.srcHeight=b.srcWidth/d),b.srcX=(a.width-b.srcWidth)/2,b.srcY=(a.height-b.srcHeight)/2,b},drop:function(){return this.element.classList.remove("dz-drag-hover")},dragstart:g,dragend:function(){return this.element.classList.remove("dz-drag-hover")},dragenter:function(){return this.element.classList.add("dz-drag-hover")},dragover:function(){return this.element.classList.add("dz-drag-hover")},dragleave:function(){return this.element.classList.remove("dz-drag-hover")},paste:g,reset:function(){return this.element.classList.remove("dz-started")},addedfile:function(a){var b,d,e,f,g,h,i,j,k,l,m,n,o;if(this.element===this.previewsContainer&&this.element.classList.add("dz-started"),this.previewsContainer){for(a.previewElement=c.createElement(this.options.previewTemplate.trim()),a.previewTemplate=a.previewElement,this.previewsContainer.appendChild(a.previewElement),l=a.previewElement.querySelectorAll("[data-dz-name]"),f=0,i=l.length;i>f;f++)b=l[f],b.textContent=a.name;for(m=a.previewElement.querySelectorAll("[data-dz-size]"),g=0,j=m.length;j>g;g++)b=m[g],b.innerHTML=this.filesize(a.size);for(this.options.addRemoveLinks&&(a._removeLink=c.createElement(''+this.options.dictRemoveFile+" "),a.previewElement.appendChild(a._removeLink)),d=function(b){return function(d){return d.preventDefault(),d.stopPropagation(),a.status===c.UPLOADING?c.confirm(b.options.dictCancelUploadConfirmation,function(){return b.removeFile(a)}):b.options.dictRemoveFileConfirmation?c.confirm(b.options.dictRemoveFileConfirmation,function(){return b.removeFile(a)}):b.removeFile(a)}}(this),n=a.previewElement.querySelectorAll("[data-dz-remove]"),o=[],h=0,k=n.length;k>h;h++)e=n[h],o.push(e.addEventListener("click",d));return o}},removedfile:function(a){var b;return a.previewElement&&null!=(b=a.previewElement)&&b.parentNode.removeChild(a.previewElement),this._updateMaxFilesReachedClass()},thumbnail:function(a,b){var c,d,e,f;if(a.previewElement){for(a.previewElement.classList.remove("dz-file-preview"),f=a.previewElement.querySelectorAll("[data-dz-thumbnail]"),d=0,e=f.length;e>d;d++)c=f[d],c.alt=a.name,c.src=b;return setTimeout(function(){return function(){return a.previewElement.classList.add("dz-image-preview")}}(this),1)}},error:function(a,b){var c,d,e,f,g;if(a.previewElement){for(a.previewElement.classList.add("dz-error"),"String"!=typeof b&&b.error&&(b=b.error),f=a.previewElement.querySelectorAll("[data-dz-errormessage]"),g=[],d=0,e=f.length;e>d;d++)c=f[d],g.push(c.textContent=b);return g}},errormultiple:g,processing:function(a){return a.previewElement&&(a.previewElement.classList.add("dz-processing"),a._removeLink)?a._removeLink.textContent=this.options.dictCancelUpload:void 0},processingmultiple:g,uploadprogress:function(a,b){var c,d,e,f,g;if(a.previewElement){for(f=a.previewElement.querySelectorAll("[data-dz-uploadprogress]"),g=[],d=0,e=f.length;e>d;d++)c=f[d],g.push("PROGRESS"===c.nodeName?c.value=b:c.style.width=""+b+"%");return g}},totaluploadprogress:g,sending:g,sendingmultiple:g,success:function(a){return a.previewElement?a.previewElement.classList.add("dz-success"):void 0},successmultiple:g,canceled:function(a){return this.emit("error",a,"Upload canceled.")},canceledmultiple:g,complete:function(a){return a._removeLink&&(a._removeLink.textContent=this.options.dictRemoveFile),a.previewElement?a.previewElement.classList.add("dz-complete"):void 0},completemultiple:g,maxfilesexceeded:g,maxfilesreached:g,queuecomplete:g,previewTemplate:'\n
\n
\n
\n
\n
\n
\n Check \n \n \n \n \n \n
\n
\n
\n Error \n \n \n \n \n \n \n \n
\n
'},d=function(){var a,b,c,d,e,f,g;for(d=arguments[0],c=2<=arguments.length?i.call(arguments,1):[],f=0,g=c.length;g>f;f++){b=c[f];for(a in b)e=b[a],d[a]=e}return d},c.prototype.getAcceptedFiles=function(){var a,b,c,d,e;for(d=this.files,e=[],b=0,c=d.length;c>b;b++)a=d[b],a.accepted&&e.push(a);return e},c.prototype.getRejectedFiles=function(){var a,b,c,d,e;for(d=this.files,e=[],b=0,c=d.length;c>b;b++)a=d[b],a.accepted||e.push(a);return e},c.prototype.getFilesWithStatus=function(a){var b,c,d,e,f;for(e=this.files,f=[],c=0,d=e.length;d>c;c++)b=e[c],b.status===a&&f.push(b);return f},c.prototype.getQueuedFiles=function(){return this.getFilesWithStatus(c.QUEUED)},c.prototype.getUploadingFiles=function(){return this.getFilesWithStatus(c.UPLOADING)},c.prototype.getActiveFiles=function(){var a,b,d,e,f;for(e=this.files,f=[],b=0,d=e.length;d>b;b++)a=e[b],(a.status===c.UPLOADING||a.status===c.QUEUED)&&f.push(a);return f},c.prototype.init=function(){var a,b,d,e,f,g,h;for("form"===this.element.tagName&&this.element.setAttribute("enctype","multipart/form-data"),this.element.classList.contains("dropzone")&&!this.element.querySelector(".dz-message")&&this.element.appendChild(c.createElement(''+this.options.dictDefaultMessage+"
")),this.clickableElements.length&&(d=function(a){return function(){return a.hiddenFileInput&&document.body.removeChild(a.hiddenFileInput),a.hiddenFileInput=document.createElement("input"),a.hiddenFileInput.setAttribute("type","file"),(null==a.options.maxFiles||a.options.maxFiles>1)&&a.hiddenFileInput.setAttribute("multiple","multiple"),a.hiddenFileInput.className="dz-hidden-input",null!=a.options.acceptedFiles&&a.hiddenFileInput.setAttribute("accept",a.options.acceptedFiles),null!=a.options.capture&&a.hiddenFileInput.setAttribute("capture",a.options.capture),a.hiddenFileInput.style.visibility="hidden",a.hiddenFileInput.style.position="absolute",a.hiddenFileInput.style.top="0",a.hiddenFileInput.style.left="0",a.hiddenFileInput.style.height="0",a.hiddenFileInput.style.width="0",document.body.appendChild(a.hiddenFileInput),a.hiddenFileInput.addEventListener("change",function(){var b,c,e,f;if(c=a.hiddenFileInput.files,c.length)for(e=0,f=c.length;f>e;e++)b=c[e],a.addFile(b);return d()})}}(this))(),this.URL=null!=(g=window.URL)?g:window.webkitURL,h=this.events,e=0,f=h.length;f>e;e++)a=h[e],this.on(a,this.options[a]);return this.on("uploadprogress",function(a){return function(){return a.updateTotalUploadProgress()}}(this)),this.on("removedfile",function(a){return function(){return a.updateTotalUploadProgress()}}(this)),this.on("canceled",function(a){return function(b){return a.emit("complete",b)}}(this)),this.on("complete",function(a){return function(){return 0===a.getUploadingFiles().length&&0===a.getQueuedFiles().length?setTimeout(function(){return a.emit("queuecomplete")},0):void 0}}(this)),b=function(a){return a.stopPropagation(),a.preventDefault?a.preventDefault():a.returnValue=!1},this.listeners=[{element:this.element,events:{dragstart:function(a){return function(b){return a.emit("dragstart",b)}}(this),dragenter:function(a){return function(c){return b(c),a.emit("dragenter",c)}}(this),dragover:function(a){return function(c){var d;try{d=c.dataTransfer.effectAllowed}catch(e){}return c.dataTransfer.dropEffect="move"===d||"linkMove"===d?"move":"copy",b(c),a.emit("dragover",c)}}(this),dragleave:function(a){return function(b){return a.emit("dragleave",b)}}(this),drop:function(a){return function(c){return b(c),a.drop(c)}}(this),dragend:function(a){return function(b){return a.emit("dragend",b)}}(this)}}],this.clickableElements.forEach(function(a){return function(b){return a.listeners.push({element:b,events:{click:function(d){return b!==a.element||d.target===a.element||c.elementInside(d.target,a.element.querySelector(".dz-message"))?a.hiddenFileInput.click():void 0}}})}}(this)),this.enable(),this.options.init.call(this)},c.prototype.destroy=function(){var a;return this.disable(),this.removeAllFiles(!0),(null!=(a=this.hiddenFileInput)?a.parentNode:void 0)&&(this.hiddenFileInput.parentNode.removeChild(this.hiddenFileInput),this.hiddenFileInput=null),delete this.element.dropzone,c.instances.splice(c.instances.indexOf(this),1)},c.prototype.updateTotalUploadProgress=function(){var a,b,c,d,e,f,g,h;if(d=0,c=0,a=this.getActiveFiles(),a.length){for(h=this.getActiveFiles(),f=0,g=h.length;g>f;f++)b=h[f],d+=b.upload.bytesSent,c+=b.upload.total;e=100*d/c}else e=100;return this.emit("totaluploadprogress",e,c,d)},c.prototype._getParamName=function(a){return"function"==typeof this.options.paramName?this.options.paramName(a):""+this.options.paramName+(this.options.uploadMultiple?"["+a+"]":"")},c.prototype.getFallbackForm=function(){var a,b,d,e;return(a=this.getExistingFallback())?a:(d='',b=c.createElement(d),"FORM"!==this.element.tagName?(e=c.createElement(''),e.appendChild(b)):(this.element.setAttribute("enctype","multipart/form-data"),this.element.setAttribute("method",this.options.method)),null!=e?e:b)},c.prototype.getExistingFallback=function(){var a,b,c,d,e,f;for(b=function(a){var b,c,d;for(c=0,d=a.length;d>c;c++)if(b=a[c],/(^| )fallback($| )/.test(b.className))return b},f=["div","form"],d=0,e=f.length;e>d;d++)if(c=f[d],a=b(this.element.getElementsByTagName(c)))return a},c.prototype.setupEventListeners=function(){var a,b,c,d,e,f,g;for(f=this.listeners,g=[],d=0,e=f.length;e>d;d++)a=f[d],g.push(function(){var d,e;d=a.events,e=[];for(b in d)c=d[b],e.push(a.element.addEventListener(b,c,!1));return e}());return g},c.prototype.removeEventListeners=function(){var a,b,c,d,e,f,g;for(f=this.listeners,g=[],d=0,e=f.length;e>d;d++)a=f[d],g.push(function(){var d,e;d=a.events,e=[];for(b in d)c=d[b],e.push(a.element.removeEventListener(b,c,!1));return e}());return g},c.prototype.disable=function(){var a,b,c,d,e;for(this.clickableElements.forEach(function(a){return a.classList.remove("dz-clickable")}),this.removeEventListeners(),d=this.files,e=[],b=0,c=d.length;c>b;b++)a=d[b],e.push(this.cancelUpload(a));return e},c.prototype.enable=function(){return this.clickableElements.forEach(function(a){return a.classList.add("dz-clickable")}),this.setupEventListeners()},c.prototype.filesize=function(a){var b,c,d,e,f,g,h,i;for(g=["TB","GB","MB","KB","b"],d=e=null,c=h=0,i=g.length;i>h;c=++h)if(f=g[c],b=Math.pow(this.options.filesizeBase,4-c)/10,a>=b){d=a/Math.pow(this.options.filesizeBase,4-c),e=f;break}return d=Math.round(10*d)/10,""+d+" "+e},c.prototype._updateMaxFilesReachedClass=function(){return null!=this.options.maxFiles&&this.getAcceptedFiles().length>=this.options.maxFiles?(this.getAcceptedFiles().length===this.options.maxFiles&&this.emit("maxfilesreached",this.files),this.element.classList.add("dz-max-files-reached")):this.element.classList.remove("dz-max-files-reached")},c.prototype.drop=function(a){var b,c;a.dataTransfer&&(this.emit("drop",a),b=a.dataTransfer.files,b.length&&(c=a.dataTransfer.items,c&&c.length&&null!=c[0].webkitGetAsEntry?this._addFilesFromItems(c):this.handleFiles(b)))},c.prototype.paste=function(a){var b,c;if(null!=(null!=a&&null!=(c=a.clipboardData)?c.items:void 0))return this.emit("paste",a),b=a.clipboardData.items,b.length?this._addFilesFromItems(b):void 0},c.prototype.handleFiles=function(a){var b,c,d,e;for(e=[],c=0,d=a.length;d>c;c++)b=a[c],e.push(this.addFile(b));return e},c.prototype._addFilesFromItems=function(a){var b,c,d,e,f;for(f=[],d=0,e=a.length;e>d;d++)c=a[d],f.push(null!=c.webkitGetAsEntry&&(b=c.webkitGetAsEntry())?b.isFile?this.addFile(c.getAsFile()):b.isDirectory?this._addFilesFromDirectory(b,b.name):void 0:null!=c.getAsFile?null==c.kind||"file"===c.kind?this.addFile(c.getAsFile()):void 0:void 0);return f},c.prototype._addFilesFromDirectory=function(a,b){var c,d;return c=a.createReader(),d=function(a){return function(c){var d,e,f;for(e=0,f=c.length;f>e;e++)d=c[e],d.isFile?d.file(function(c){return a.options.ignoreHiddenFiles&&"."===c.name.substring(0,1)?void 0:(c.fullPath=""+b+"/"+c.name,a.addFile(c))}):d.isDirectory&&a._addFilesFromDirectory(d,""+b+"/"+d.name)}}(this),c.readEntries(d,function(a){return"undefined"!=typeof console&&null!==console&&"function"==typeof console.log?console.log(a):void 0})},c.prototype.accept=function(a,b){return a.size>1024*this.options.maxFilesize*1024?b(this.options.dictFileTooBig.replace("{{filesize}}",Math.round(a.size/1024/10.24)/100).replace("{{maxFilesize}}",this.options.maxFilesize)):c.isValidFile(a,this.options.acceptedFiles)?null!=this.options.maxFiles&&this.getAcceptedFiles().length>=this.options.maxFiles?(b(this.options.dictMaxFilesExceeded.replace("{{maxFiles}}",this.options.maxFiles)),this.emit("maxfilesexceeded",a)):this.options.accept.call(this,a,b):b(this.options.dictInvalidFileType)},c.prototype.addFile=function(a){return a.upload={progress:0,total:a.size,bytesSent:0},this.files.push(a),a.status=c.ADDED,this.emit("addedfile",a),this._enqueueThumbnail(a),this.accept(a,function(b){return function(c){return c?(a.accepted=!1,b._errorProcessing([a],c)):(a.accepted=!0,b.options.autoQueue&&b.enqueueFile(a)),b._updateMaxFilesReachedClass()}}(this))},c.prototype.enqueueFiles=function(a){var b,c,d;for(c=0,d=a.length;d>c;c++)b=a[c],this.enqueueFile(b);return null},c.prototype.enqueueFile=function(a){if(a.status!==c.ADDED||a.accepted!==!0)throw new Error("This file can't be queued because it has already been processed or was rejected.");return a.status=c.QUEUED,this.options.autoProcessQueue?setTimeout(function(a){return function(){return a.processQueue()}}(this),0):void 0},c.prototype._thumbnailQueue=[],c.prototype._processingThumbnail=!1,c.prototype._enqueueThumbnail=function(a){return this.options.createImageThumbnails&&a.type.match(/image.*/)&&a.size<=1024*this.options.maxThumbnailFilesize*1024?(this._thumbnailQueue.push(a),setTimeout(function(a){return function(){return a._processThumbnailQueue()}}(this),0)):void 0},c.prototype._processThumbnailQueue=function(){return this._processingThumbnail||0===this._thumbnailQueue.length?void 0:(this._processingThumbnail=!0,this.createThumbnail(this._thumbnailQueue.shift(),function(a){return function(){return a._processingThumbnail=!1,a._processThumbnailQueue()}}(this)))},c.prototype.removeFile=function(a){return a.status===c.UPLOADING&&this.cancelUpload(a),this.files=h(this.files,a),this.emit("removedfile",a),0===this.files.length?this.emit("reset"):void 0},c.prototype.removeAllFiles=function(a){var b,d,e,f;for(null==a&&(a=!1),f=this.files.slice(),d=0,e=f.length;e>d;d++)b=f[d],(b.status!==c.UPLOADING||a)&&this.removeFile(b);return null},c.prototype.createThumbnail=function(a,b){var c;return c=new FileReader,c.onload=function(d){return function(){var e;return"image/svg+xml"===a.type?(d.emit("thumbnail",a,c.result),void(null!=b&&b())):(e=document.createElement("img"),e.onload=function(){var c,g,h,i,j,k,l,m;return a.width=e.width,a.height=e.height,h=d.options.resize.call(d,a),null==h.trgWidth&&(h.trgWidth=h.optWidth),null==h.trgHeight&&(h.trgHeight=h.optHeight),c=document.createElement("canvas"),g=c.getContext("2d"),c.width=h.trgWidth,c.height=h.trgHeight,f(g,e,null!=(j=h.srcX)?j:0,null!=(k=h.srcY)?k:0,h.srcWidth,h.srcHeight,null!=(l=h.trgX)?l:0,null!=(m=h.trgY)?m:0,h.trgWidth,h.trgHeight),i=c.toDataURL("image/png"),d.emit("thumbnail",a,i),null!=b?b():void 0},e.onerror=b,e.src=c.result)}}(this),c.readAsDataURL(a)},c.prototype.processQueue=function(){var a,b,c,d;if(b=this.options.parallelUploads,c=this.getUploadingFiles().length,a=c,!(c>=b)&&(d=this.getQueuedFiles(),d.length>0)){if(this.options.uploadMultiple)return this.processFiles(d.slice(0,b-c));for(;b>a;){if(!d.length)return;this.processFile(d.shift()),a++}}},c.prototype.processFile=function(a){return this.processFiles([a])},c.prototype.processFiles=function(a){var b,d,e;for(d=0,e=a.length;e>d;d++)b=a[d],b.processing=!0,b.status=c.UPLOADING,this.emit("processing",b);return this.options.uploadMultiple&&this.emit("processingmultiple",a),this.uploadFiles(a)},c.prototype._getFilesWithXhr=function(a){var b,c;return c=function(){var c,d,e,f;for(e=this.files,f=[],c=0,d=e.length;d>c;c++)b=e[c],b.xhr===a&&f.push(b);return f}.call(this)},c.prototype.cancelUpload=function(a){var b,d,e,f,g,h,i;if(a.status===c.UPLOADING){for(d=this._getFilesWithXhr(a.xhr),e=0,g=d.length;g>e;e++)b=d[e],b.status=c.CANCELED;for(a.xhr.abort(),f=0,h=d.length;h>f;f++)b=d[f],this.emit("canceled",b);this.options.uploadMultiple&&this.emit("canceledmultiple",d)}else((i=a.status)===c.ADDED||i===c.QUEUED)&&(a.status=c.CANCELED,this.emit("canceled",a),this.options.uploadMultiple&&this.emit("canceledmultiple",[a]));return this.options.autoProcessQueue?this.processQueue():void 0},e=function(){var a,b;return b=arguments[0],a=2<=arguments.length?i.call(arguments,1):[],"function"==typeof b?b.apply(this,a):b},c.prototype.uploadFile=function(a){return this.uploadFiles([a])},c.prototype.uploadFiles=function(a){var b,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L;for(w=new XMLHttpRequest,x=0,B=a.length;B>x;x++)b=a[x],b.xhr=w;p=e(this.options.method,a),u=e(this.options.url,a),w.open(p,u,!0),w.withCredentials=!!this.options.withCredentials,s=null,g=function(c){return function(){var d,e,f;for(f=[],d=0,e=a.length;e>d;d++)b=a[d],f.push(c._errorProcessing(a,s||c.options.dictResponseError.replace("{{statusCode}}",w.status),w));return f}}(this),t=function(c){return function(d){var e,f,g,h,i,j,k,l,m;if(null!=d)for(f=100*d.loaded/d.total,g=0,j=a.length;j>g;g++)b=a[g],b.upload={progress:f,total:d.total,bytesSent:d.loaded};else{for(e=!0,f=100,h=0,k=a.length;k>h;h++)b=a[h],(100!==b.upload.progress||b.upload.bytesSent!==b.upload.total)&&(e=!1),b.upload.progress=f,b.upload.bytesSent=b.upload.total;if(e)return}for(m=[],i=0,l=a.length;l>i;i++)b=a[i],m.push(c.emit("uploadprogress",b,f,b.upload.bytesSent));return m}}(this),w.onload=function(b){return function(d){var e;if(a[0].status!==c.CANCELED&&4===w.readyState){if(s=w.responseText,w.getResponseHeader("content-type")&&~w.getResponseHeader("content-type").indexOf("application/json"))try{s=JSON.parse(s)}catch(f){d=f,s="Invalid JSON response from server."}return t(),200<=(e=w.status)&&300>e?b._finished(a,s,d):g()}}}(this),w.onerror=function(){return function(){return a[0].status!==c.CANCELED?g():void 0}}(this),r=null!=(G=w.upload)?G:w,r.onprogress=t,j={Accept:"application/json","Cache-Control":"no-cache","X-Requested-With":"XMLHttpRequest"},this.options.headers&&d(j,this.options.headers);for(h in j)i=j[h],w.setRequestHeader(h,i);if(f=new FormData,this.options.params){H=this.options.params;for(o in H)v=H[o],f.append(o,v)}for(y=0,C=a.length;C>y;y++)b=a[y],this.emit("sending",b,w,f);if(this.options.uploadMultiple&&this.emit("sendingmultiple",a,w,f),"FORM"===this.element.tagName)for(I=this.element.querySelectorAll("input, textarea, select, button"),z=0,D=I.length;D>z;z++)if(l=I[z],m=l.getAttribute("name"),n=l.getAttribute("type"),"SELECT"===l.tagName&&l.hasAttribute("multiple"))for(J=l.options,A=0,E=J.length;E>A;A++)q=J[A],q.selected&&f.append(m,q.value);else(!n||"checkbox"!==(K=n.toLowerCase())&&"radio"!==K||l.checked)&&f.append(m,l.value);for(k=F=0,L=a.length-1;L>=0?L>=F:F>=L;k=L>=0?++F:--F)f.append(this._getParamName(k),a[k],a[k].name);return w.send(f)},c.prototype._finished=function(a,b,d){var e,f,g;for(f=0,g=a.length;g>f;f++)e=a[f],e.status=c.SUCCESS,this.emit("success",e,b,d),this.emit("complete",e);return this.options.uploadMultiple&&(this.emit("successmultiple",a,b,d),this.emit("completemultiple",a)),this.options.autoProcessQueue?this.processQueue():void 0},c.prototype._errorProcessing=function(a,b,d){var e,f,g;for(f=0,g=a.length;g>f;f++)e=a[f],e.status=c.ERROR,this.emit("error",e,b,d),this.emit("complete",e);return this.options.uploadMultiple&&(this.emit("errormultiple",a,b,d),this.emit("completemultiple",a)),this.options.autoProcessQueue?this.processQueue():void 0},c}(b),a.version="4.0.1",a.options={},a.optionsForElement=function(b){return b.getAttribute("id")?a.options[c(b.getAttribute("id"))]:void 0},a.instances=[],a.forElement=function(a){if("string"==typeof a&&(a=document.querySelector(a)),null==(null!=a?a.dropzone:void 0))throw new Error("No Dropzone found for given element. This is probably because you're trying to access it before Dropzone had the time to initialize. Use the `init` option to setup any additional observers on your Dropzone.");return a.dropzone},a.autoDiscover=!0,a.discover=function(){var b,c,d,e,f,g;for(document.querySelectorAll?d=document.querySelectorAll(".dropzone"):(d=[],b=function(a){var b,c,e,f;for(f=[],c=0,e=a.length;e>c;c++)b=a[c],f.push(/(^| )dropzone($| )/.test(b.className)?d.push(b):void 0);return f},b(document.getElementsByTagName("div")),b(document.getElementsByTagName("form"))),g=[],e=0,f=d.length;f>e;e++)c=d[e],g.push(a.optionsForElement(c)!==!1?new a(c):void 0);return g},a.blacklistedBrowsers=[/opera.*Macintosh.*version\/12/i],a.isBrowserSupported=function(){var b,c,d,e,f;if(b=!0,window.File&&window.FileReader&&window.FileList&&window.Blob&&window.FormData&&document.querySelector)if("classList"in document.createElement("a"))for(f=a.blacklistedBrowsers,d=0,e=f.length;e>d;d++)c=f[d],c.test(navigator.userAgent)&&(b=!1);else b=!1;else b=!1;return b},h=function(a,b){var c,d,e,f;for(f=[],d=0,e=a.length;e>d;d++)c=a[d],c!==b&&f.push(c);return f},c=function(a){return a.replace(/[\-_](\w)/g,function(a){return a.charAt(1).toUpperCase()})},a.createElement=function(a){var b;return b=document.createElement("div"),b.innerHTML=a,b.childNodes[0]},a.elementInside=function(a,b){if(a===b)return!0;for(;a=a.parentNode;)if(a===b)return!0;return!1},a.getElement=function(a,b){var c;if("string"==typeof a?c=document.querySelector(a):null!=a.nodeType&&(c=a),null==c)throw new Error("Invalid `"+b+"` option provided. Please provide a CSS selector or a plain HTML element.");return c},a.getElements=function(a,b){var c,d,e,f,g,h,i,j;if(a instanceof Array){e=[];try{for(f=0,h=a.length;h>f;f++)d=a[f],e.push(this.getElement(d,b))}catch(k){c=k,e=null}}else if("string"==typeof a)for(e=[],j=document.querySelectorAll(a),g=0,i=j.length;i>g;g++)d=j[g],e.push(d);else null!=a.nodeType&&(e=[a]);if(null==e||!e.length)throw new Error("Invalid `"+b+"` option provided. Please provide a CSS selector, a plain HTML element or a list of those.");return e},a.confirm=function(a,b,c){return window.confirm(a)?b():null!=c?c():void 0},a.isValidFile=function(a,b){var c,d,e,f,g;if(!b)return!0;for(b=b.split(","),d=a.type,c=d.replace(/\/.*$/,""),f=0,g=b.length;g>f;f++)if(e=b[f],e=e.trim(),"."===e.charAt(0)){if(-1!==a.name.toLowerCase().indexOf(e.toLowerCase(),a.name.length-e.length))return!0}else if(/\/\*$/.test(e)){if(c===e.replace(/\/.*$/,""))return!0}else if(d===e)return!0;return!1},"undefined"!=typeof jQuery&&null!==jQuery&&(jQuery.fn.dropzone=function(b){return this.each(function(){return new a(this,b)})}),"undefined"!=typeof module&&null!==module?module.exports=a:window.Dropzone=a,a.ADDED="added",a.QUEUED="queued",a.ACCEPTED=a.QUEUED,a.UPLOADING="uploading",a.PROCESSING=a.UPLOADING,a.CANCELED="canceled",a.ERROR="error",a.SUCCESS="success",e=function(a){var b,c,d,e,f,g,h,i,j,k;for(h=a.naturalWidth,g=a.naturalHeight,c=document.createElement("canvas"),c.width=1,c.height=g,d=c.getContext("2d"),d.drawImage(a,0,0),e=d.getImageData(0,0,1,g).data,k=0,f=g,i=g;i>k;)b=e[4*(i-1)+3],0===b?f=i:k=i,i=f+k>>1;return j=i/g,0===j?1:j},f=function(a,b,c,d,f,g,h,i,j,k){var l;return l=e(b),a.drawImage(b,c,d,f,g,h,i,j,k/l)},d=function(a,b){var c,d,e,f,g,h,i,j,k;if(e=!1,k=!0,d=a.document,j=d.documentElement,c=d.addEventListener?"addEventListener":"attachEvent",i=d.addEventListener?"removeEventListener":"detachEvent",h=d.addEventListener?"":"on",f=function(c){return"readystatechange"!==c.type||"complete"===d.readyState?(("load"===c.type?a:d)[i](h+c.type,f,!1),!e&&(e=!0)?b.call(a,c.type||c):void 0):void 0
+},g=function(){var a;try{j.doScroll("left")}catch(b){return a=b,void setTimeout(g,50)}return f("poll")},"complete"!==d.readyState){if(d.createEventObject&&j.doScroll){try{k=!a.frameElement}catch(l){}k&&g()}return d[c](h+"DOMContentLoaded",f,!1),d[c](h+"readystatechange",f,!1),a[c](h+"load",f,!1)}},a._autoDiscoverFunction=function(){return a.autoDiscover?a.discover():void 0},d(window,a._autoDiscoverFunction)}).call(this);
\ No newline at end of file