APIs

Show:
  1. /**
  2. This class manages the UI of all blocks within a channel as well as the ability to sort and reorder the content of a channel
  3. @class ChannelListView
  4. @constructor
  5. @return {Object} instantiated CompCampaignNavigator
  6. **/
  7. define(['jquery', 'backbone', 'jqueryui', 'TouchPunch', 'Timeline', 'SequencerView', 'StorylineView', 'Draggable'], function ($, Backbone, jqueryui, TouchPunch, Timeline, SequencerView, StorylineView, Draggable) {
  8.  
  9. BB.SERVICES.CHANNEL_LIST_VIEW = 'ChannelListView';
  10.  
  11. var ChannelListView = BB.View.extend({
  12.  
  13. /**
  14. Init the ChannelList component and enable sortable channels UI via drag and drop operations.
  15. @method initialize
  16. **/
  17. initialize: function () {
  18. var self = this;
  19.  
  20. self.m_property = BB.comBroker.getService(BB.SERVICES.PROPERTIES_VIEW);
  21. self.selected_block_id = undefined;
  22. self.selected_campaign_timeline_chanel_id = undefined;
  23. self.selected_campaign_timeline_id = undefined;
  24. self.selected_campaign_timeline_board_viewer_id = undefined;
  25.  
  26. self._listenAddRemoveBlocks();
  27. self._listenTimelineSelected();
  28. self._listenResourceRemoved();
  29. self._listenSceneRemoved();
  30. self._listenBlockLengthChanged();
  31. self._listenStorylineBlockSelected();
  32. self._listenStorylineChannelSelected();
  33. self._listenReset();
  34. self._listenContextMenu();
  35. pepper.listen(Pepper.TIMELINE_DELETED, $.proxy(self._onTimelineDeleted, self));
  36.  
  37. },
  38.  
  39. /**
  40. Listen to reset of when switching to different campaign so we forget current state
  41. @method _listenReset
  42. **/
  43. _listenReset: function () {
  44. var self = this;
  45. BB.comBroker.listen(BB.EVENTS.CAMPAIGN_RESET, function () {
  46. self.selected_block_id = undefined;
  47. self.selected_campaign_timeline_chanel_id = undefined;
  48. self.selected_campaign_timeline_id = undefined;
  49. self.selected_campaign_timeline_board_viewer_id = undefined;
  50. });
  51. },
  52.  
  53. /**
  54. Wire the UI and listen to channel remove and channel add button events.
  55. @method _listenAddRemoveBlocks
  56. @return none
  57. **/
  58. _listenAddRemoveBlocks: function () {
  59. var self = this;
  60. $(Elements.REMOVE_BLOCK_BUTTON).on('click', function (e) {
  61. if (_.isUndefined(self.selected_block_id)) {
  62. bootbox.alert($(Elements.MSG_BOOTBOX_SELECT_RESOURCE).text());
  63. return;
  64. }
  65. self._deleteChannelBlock(self.selected_block_id);
  66. });
  67. $(Elements.ADD_BLOCK_BUTTON).on('click', function (e) {
  68. if (_.isUndefined(self.selected_campaign_timeline_id)) {
  69. bootbox.alert($(Elements.MSG_BOOTBOX_SELECT_CHANNEL).text());
  70. return;
  71. }
  72. self._openAddBlockWizard(e);
  73. });
  74. },
  75.  
  76. /**
  77. Wire the UI for timeline deletion.
  78. @method _onTimelineDeleted
  79. @return none
  80. **/
  81. _onTimelineDeleted: function () {
  82. var self = this;
  83. $(Elements.ADD_BLOCK_BUTTON).fadeOut();
  84. $(Elements.REMOVE_BLOCK_BUTTON).fadeOut();
  85. $(Elements.TIMELIME_PREVIEW).fadeOut();
  86. self._resetChannel();
  87. },
  88.  
  89. /**
  90. Update the blocks offset times according to current order of LI elements and reorder accordingly in msdb.
  91. @method _reOrderChannelBlocks
  92. @return none
  93. **/
  94. _reOrderChannelBlocks: function () {
  95. var self = this
  96. var blocks = $(Elements.SORTABLE).children();
  97. var playerOffsetTime = 0;
  98. $(blocks).each(function (i) {
  99. var block_id = $(this).data('block_id');
  100. var recBlock = pepper.getBlockRecord(block_id);
  101. var playerDuration = recBlock['player_duration']
  102. pepper.setBlockRecord(block_id, 'player_offset_time', playerOffsetTime);
  103. log('player ' + block_id + ' offset ' + playerOffsetTime + ' playerDuration ' + playerDuration);
  104. playerOffsetTime = parseFloat(playerOffsetTime) + parseFloat(playerDuration);
  105. });
  106. pepper.calcTimelineTotalDuration(this.selected_campaign_timeline_id);
  107. BB.comBroker.fire(BB.EVENTS.CAMPAIGN_TIMELINE_CHANGED, self);
  108. BB.comBroker.fire(BB.EVENTS.BLOCK_SELECTED, this, null, self.selected_block_id);
  109. },
  110.  
  111. /**
  112. Get the total duration in seconds of the channel
  113. @method _getTotalDurationChannel
  114. @return {Number} totalChannelLength
  115. **/
  116. _getTotalDurationChannel: function () {
  117. var self = this
  118. var blocks = $(Elements.SORTABLE).children();
  119. var blocksIDs = [];
  120. $(blocks).each(function (i) {
  121. var block_id = $(this).data('block_id');
  122. blocksIDs.push(block_id);
  123. });
  124. var totalChannelLength = pepper.getTotalDurationOfBlocks(blocksIDs);
  125. return totalChannelLength;
  126. },
  127.  
  128. /**
  129. Launch the add new block wizard UI component.
  130. @method _openAddBlockWizard
  131. @return none
  132. **/
  133. _openAddBlockWizard: function (e) {
  134. var self = this;
  135. var addBlockView = BB.comBroker.getService(BB.SERVICES.ADD_BLOCK_VIEW);
  136. addBlockView.setPlacement(BB.CONSTS.PLACEMENT_CHANNEL);
  137. addBlockView.selectView();
  138. BB.comBroker.listenOnce(BB.EVENTS.ADD_NEW_BLOCK_CHANNEL, function (e) {
  139. self._createNewChannelBlock(e.edata.blockCode, e.edata.resourceID, e.edata.sceneID);
  140. e.stopImmediatePropagation();
  141. e.preventDefault();
  142. });
  143. },
  144.  
  145. /**
  146. Create a new block (player) on the current channel and refresh UI bindings such as properties open events.
  147. @method _createNewChannelBlock
  148. @param {Number} i_blockID
  149. @param {Number} i_resourceID optional param used when creating a block with embedded resource (i.e.: video / image / swf)
  150. @param {Number} i_sceneID optional param used when creating a block with embedded scene
  151. @return {Boolean} false
  152. **/
  153. _createNewChannelBlock: function (i_blockID, i_resourceID, i_sceneID) {
  154. var self = this;
  155. var totalChannelLength = self._getTotalDurationChannel();
  156. var jData = pepper.createNewChannelPlayer(self.selected_campaign_timeline_chanel_id, i_blockID, totalChannelLength, i_resourceID, i_sceneID);
  157. var campaign_timeline_chanel_player_id = jData['campaign_timeline_chanel_player_id'];
  158. var campaign_timeline_chanel_player_data = jData['campaign_timeline_chanel_player_data'];
  159.  
  160. var timeline = BB.comBroker.getService(BB.SERVICES.CAMPAIGN_VIEW).getTimelineInstance(self.selected_campaign_timeline_id);
  161. var channel = timeline.getChannelInstance(self.selected_campaign_timeline_chanel_id);
  162. channel.createChannelBlock(campaign_timeline_chanel_player_id, campaign_timeline_chanel_player_data);
  163.  
  164. var campaign_timeline_board_viewer_id = self.selected_campaign_timeline_board_viewer_id;
  165. var campaign_timeline_id = self.selected_campaign_timeline_id;
  166. var campaign_timeline_chanel_id = self.selected_campaign_timeline_chanel_id;
  167.  
  168. // self._resetChannel();
  169. $(Elements.SORTABLE).empty();
  170. self._loadChannelBlocks(campaign_timeline_id, campaign_timeline_chanel_id);
  171. self._listenBlockSelected();
  172. // self._deselectBlocksFromChannel();
  173. self._selectLastBlockOnChannel();
  174. self._reOrderChannelBlocks();
  175. return false;
  176. },
  177.  
  178. /**
  179. Listen to when a resource has been deleted so we can delete the associated block and re calc channel length
  180. @method _listenResourceRemoved
  181. @return none
  182. **/
  183. _listenResourceRemoved: function () {
  184. var self = this;
  185. BB.comBroker.listen(BB.EVENTS.REMOVED_RESOURCE, function (e) {
  186. if (self.selected_campaign_timeline_id != undefined && self.selected_campaign_timeline_chanel_id != undefined) {
  187. $(Elements.SORTABLE).empty();
  188. self._loadChannelBlocks(self.selected_campaign_timeline_id, self.selected_campaign_timeline_chanel_id);
  189. self._reOrderChannelBlocks();
  190. }
  191. });
  192. },
  193.  
  194. /**
  195. Listen to when a resource has been deleted so we can delete the associated block and re calc channel length
  196. @method _listenSceneRemoved
  197. @return none
  198. **/
  199. _listenSceneRemoved: function () {
  200. var self = this;
  201. BB.comBroker.listen(BB.EVENTS.REMOVED_SCENE, function () {
  202. if (self.selected_campaign_timeline_id != undefined && self.selected_campaign_timeline_chanel_id != undefined) {
  203. $(Elements.SORTABLE).empty();
  204. self._loadChannelBlocks(self.selected_campaign_timeline_id, self.selected_campaign_timeline_chanel_id);
  205. self._reOrderChannelBlocks();
  206. }
  207. });
  208. },
  209.  
  210. /**
  211. Listen to the BB.EVENTS.ON_VIEWER_SELECTED so we know when a timeline has been selected.
  212. Once a timeline selection was done we check if the event if one of a timeline owner or other; if of timeline
  213. we populate channel list, if latter reset list.
  214. @method _listenTimelineSelected
  215. @return none
  216. **/
  217. _listenTimelineSelected: function () {
  218. var self = this;
  219.  
  220. BB.comBroker.listen(BB.EVENTS.ON_VIEWER_SELECTED, function (e) {
  221.  
  222. self._resetChannel();
  223. self.selected_campaign_timeline_board_viewer_id = e.caller.campaign_timeline_board_viewer_id;
  224. self.selected_campaign_timeline_id = e.caller.campaign_timeline_id;
  225.  
  226. if (e.context.m_owner instanceof Timeline || e.context.m_owner instanceof StorylineView) {
  227.  
  228. var recCampaignTimelineViewerChanels = pepper.getChannelIdFromCampaignTimelineBoardViewer(self.selected_campaign_timeline_board_viewer_id, self.selected_campaign_timeline_id);
  229. self._loadChannelBlocks(self.selected_campaign_timeline_id, recCampaignTimelineViewerChanels['campaign_timeline_chanel_id']);
  230. $(Elements.ADD_BLOCK_BUTTON).fadeIn();
  231. $(Elements.REMOVE_BLOCK_BUTTON).fadeIn();
  232. $(Elements.TIMELIME_PREVIEW).fadeIn();
  233. }
  234.  
  235. if (e.context.m_owner instanceof SequencerView) {
  236. self._resetChannel();
  237. $(Elements.ADD_BLOCK_BUTTON).fadeOut();
  238. $(Elements.REMOVE_BLOCK_BUTTON).fadeOut();
  239. $(Elements.TIMELIME_PREVIEW).fadeOut();
  240. }
  241. });
  242. },
  243.  
  244. /**
  245. Load the channel list with its own blocks and refresh the UI.
  246. @method _loadChannelBlocks
  247. @param {Number} i_campaign_timeline_id
  248. @param {Number} i_campaign_timeline_chanel_id
  249. @return none
  250. **/
  251. _loadChannelBlocks: function (i_campaign_timeline_id, i_campaign_timeline_chanel_id) {
  252. var self = this;
  253.  
  254. self.selected_campaign_timeline_chanel_id = i_campaign_timeline_chanel_id;
  255.  
  256. var timeline = BB.comBroker.getService(BB.SERVICES['CAMPAIGN_VIEW']).getTimelineInstance(i_campaign_timeline_id);
  257. var channel = timeline.getChannelInstance(i_campaign_timeline_chanel_id);
  258. var blocks = channel.getBlocks();
  259. var xdate = BB.comBroker.getService('XDATE');
  260.  
  261. for (var block in blocks) {
  262. var blockData = blocks[block].getBlockData();
  263. var duration = pepper.getBlockTimelineChannelBlockLength(blockData.blockID).totalInSeconds;
  264. var durationFormatted = xdate.clearTime().addSeconds(duration).toString('HH:mm:ss');
  265. $(Elements.SORTABLE).append($('<li class="' + BB.lib.unclass(Elements.CLASS_CHANNEL_LIST_ITEMS) + ' list-group-item" data-block_id="' + blockData.blockID + '">' +
  266. '<a href="#">' +
  267. //'<img class="img-responsive" src="' + blockData.blockIcon + '"/>' +
  268. '<i class="fa ' + blockData.blockFontAwesome + '"></i>' +
  269. '<span>' + blockData.blockName + '</span>' +
  270. '<i style="padding: 0; margin: 0" class="dragch fa fa-arrows-v"></i>' +
  271. '<span class="' + BB.lib.unclass(Elements.CLASS_BLOCK_LENGTH_TIMER) + ' hidden-xs">' + durationFormatted + '</span>' +
  272. '</a>' +
  273. '</li>'));
  274. }
  275. self._listenBlockSelected();
  276. self._createSortable(Elements.SORTABLE);
  277. },
  278.  
  279. /**
  280. Listen when a block is selected, if its properties need to be open than open panel.
  281. Also, reference the selected block internally and fire event announcing it was selected.
  282. We also load required AMD moduels if this is the first time a block was selected (i.e.: modules
  283. were never loaded yet) and when they finish loaded we continue with thread execution.
  284. @method _listenBlockSelected
  285. @return none
  286. **/
  287. _listenBlockSelected: function () {
  288. var self = this;
  289. // clear previous listeners
  290. $(Elements.CLASS_CHANNEL_LIST_ITEMS).off('mousedown');
  291. $(Elements.CLASS_CHANNEL_LIST_ITEMS).on('mousedown contextmenu', function (e) {
  292. $.proxy(self._listenChannelBlockSelected(e), self);
  293. });
  294.  
  295. },
  296.  
  297. /**
  298. When block is selected within a channel, get the resource element so we can select it and fire
  299. the BLOCK_SELECTED event
  300. @method _listenChannelBlockSelected
  301. @param {Event} e
  302. **/
  303. _listenChannelBlockSelected: function (e) {
  304. var self = this;
  305. var resourceElem = $(e.target).closest('li');
  306. self.selected_block_id = $(resourceElem).data('block_id');
  307. BB.comBroker.fire(BB.EVENTS.BLOCK_SELECTED, this, null, self.selected_block_id);
  308. $(Elements.CLASS_CHANNEL_LIST_ITEMS).removeClass('activated').find('a').removeClass('whiteFont');
  309. $(resourceElem).addClass('activated').find('a').addClass('whiteFont');
  310. return false;
  311. },
  312.  
  313. /**
  314. Listen to when a channel is selected, but through the storyline so we can re-select appropriate block in channel list
  315. @method _listenStorylineChannelSelected
  316. **/
  317. _listenStorylineChannelSelected: function () {
  318. var self = this;
  319. BB.comBroker.listen(BB.EVENTS['STORYLINE_CHANNEL_SELECTED'], function (e) {
  320. self.selected_block_id = e.edata;
  321. var resourceElem = $(Elements.CHANNEL_LIST_ELEM_VIEW).find('[data-block_id="' + self.selected_block_id + '"]');
  322. BB.comBroker.fire(BB.EVENTS.BLOCK_SELECTED, this, null, self.selected_block_id);
  323. $(Elements.CLASS_CHANNEL_LIST_ITEMS).removeClass('activated').find('a').removeClass('whiteFont');
  324. $(resourceElem).addClass('activated').find('a').addClass('whiteFont');
  325. return false;
  326. });
  327. },
  328.  
  329. /**
  330. When a block is selected within a storyline get the resource element so we can select it and fire global block selection event
  331. @method _listenStorylineBlockSelected
  332. @param {Event} e
  333. **/
  334. _listenStorylineBlockSelected: function (e) {
  335. var self = this;
  336. BB.comBroker.listen(BB.EVENTS['STORYLINE_BLOCK_SELECTED'], function (e) {
  337. self.selected_block_id = e.edata;
  338. var resourceElem = $(Elements.CHANNEL_LIST_ELEM_VIEW).find('[data-block_id="' + self.selected_block_id + '"]');
  339. BB.comBroker.fire(BB.EVENTS.BLOCK_SELECTED, this, null, self.selected_block_id);
  340. $(Elements.CLASS_CHANNEL_LIST_ITEMS).removeClass('activated').find('a').removeClass('whiteFont');
  341. $(resourceElem).addClass('activated').find('a').addClass('whiteFont');
  342. return false;
  343. });
  344. },
  345.  
  346. /**
  347. Forget the selected channel and reset channel member references
  348. @method _resetChannel
  349. **/
  350. _resetChannel: function () {
  351. var self = this;
  352. $(Elements.SORTABLE).empty();
  353. self.selected_block_id = undefined;
  354. self.selected_campaign_timeline_board_viewer_id = undefined;
  355. self.selected_campaign_timeline_id = undefined;
  356. self.selected_campaign_timeline_chanel_id = undefined;
  357. },
  358.  
  359. /**
  360. Reset the UI when no block on channel is selected.
  361. @method _deselectBlocksFromChannel
  362. **/
  363. _deselectBlocksFromChannel: function () {
  364. var self = this;
  365. self.selected_block_id = undefined;
  366. self.m_property.resetPropertiesView();
  367. },
  368.  
  369. /**
  370. Listen to when a block length has changed so we can update all other blocks offset respectively
  371. @method _listenBlockLengthChanged
  372. @return none
  373. **/
  374. _listenBlockLengthChanged: function () {
  375. var self = this;
  376. pepper.listen(Pepper.BLOCK_LENGTH_CHANGED, $.proxy(self._onBlockLengthChanged, self));
  377. },
  378.  
  379. /**
  380. Listen to when a block on channel is modified with respect to its length
  381. @method _onBlockLengthChanged
  382. @param {Event} e block changed data
  383. **/
  384. _onBlockLengthChanged: function (e) {
  385. var self = this;
  386. var block_id = e.edata.campaignTimelineChanelPlayerID;
  387. var duration = e.edata.totalSeconds;
  388. var selectedLI = $(Elements.SORTABLE).find('[data-block_id="' + block_id + '"]');
  389. self.m_xdate = BB.comBroker.getService('XDATE');
  390. var durationFormated = self.m_xdate.clearTime().addSeconds(duration).toString('HH:mm:ss');
  391. $(Elements.CLASS_BLOCK_LENGTH_TIMER, selectedLI).text(durationFormated);
  392. self._reOrderChannelBlocks();
  393. },
  394.  
  395. /**
  396. Select the last block on the channel (last LI element) and fire a click event on it.
  397. @method _selectLastBlockOnChannel
  398. @return none
  399. **/
  400. _selectLastBlockOnChannel: function () {
  401. var self = this
  402. var blocks = $(Elements.SORTABLE).children();
  403. var block = undefined;
  404. $(blocks).each(function (i) {
  405. block = this;
  406. });
  407. if (block)
  408. $(block).click();
  409. },
  410.  
  411. /**
  412. Delete the selected block from the channel
  413. @method _deleteChannelBlock
  414. @return none
  415. **/
  416. _deleteChannelBlock: function (i_block_id) {
  417. var self = this;
  418. var selectedLI = $(Elements.SORTABLE).find('[data-block_id="' + i_block_id + '"]');
  419. selectedLI.remove();
  420. var timeline = BB.comBroker.getService(BB.SERVICES.CAMPAIGN_VIEW).getTimelineInstance(self.selected_campaign_timeline_id);
  421. var channel = timeline.getChannelInstance(self.selected_campaign_timeline_chanel_id);
  422. channel.deleteBlock(i_block_id);
  423. self._deselectBlocksFromChannel();
  424. self._reOrderChannelBlocks();
  425. },
  426.  
  427. /**
  428. Listen to any canvas right click
  429. @method _listenContextMenu
  430. **/
  431. _listenContextMenu: function () {
  432. var self = this;
  433. $(Elements.SORTABLE).contextmenu({
  434. target: Elements.CHANNEL_LIST_CONTEXT_MENU,
  435. before: function (e, element, target) {
  436. e.preventDefault();
  437. //self.m_mouseX = e.offsetX;
  438. //self.m_mouseY = e.offsetY;
  439. if (_.isUndefined(self.selected_block_id))
  440. return false;
  441. return true;
  442. },
  443. onItem: function (context, e) {
  444. self._onContentMenuSelection($(e.target).attr('name'))
  445. }
  446. });
  447. },
  448.  
  449. /**
  450. On Scene right click context menu selection command
  451. @method _onContentMenuSelection
  452. @param {String} i_command
  453. **/
  454. _onContentMenuSelection: function (i_command) {
  455. var self = this;
  456. var campaign_timeline_id = BB.comBroker.getService(BB.SERVICES.CAMPAIGN_VIEW).getSelectedTimeline();
  457. if (campaign_timeline_id == -1 || _.isUndefined(campaign_timeline_id))
  458. return;
  459.  
  460. switch (i_command) {
  461. case 'remove':
  462. {
  463. $(Elements.REMOVE_BLOCK_BUTTON).trigger('click');
  464. break;
  465. }
  466. case 'first':
  467. {
  468. self.moveBlockFirst();
  469. break;
  470. }
  471. case 'last':
  472. {
  473. self.moveBlockLast();
  474. break;
  475. }
  476. }
  477. return true;
  478. },
  479.  
  480. /**
  481. Create a draggable sortable channel list
  482. @method _createSortable
  483. @param {String} i_selector
  484. **/
  485. _createSortable: function (i_selector) {
  486. var self = this;
  487. if ($(i_selector).children().length==0) return;
  488. var sortable = document.querySelector(i_selector);
  489. self.m_draggables = Draggable.create(sortable.children, {
  490. type: "y",
  491. bounds: sortable,
  492. dragClickables: true,
  493. edgeResistance: 1,
  494. onPress: self._sortablePress,
  495. onDragStart: self._sortableDragStart,
  496. onDrag: self._sortableDrag,
  497. liveSnap: self._sortableSnap,
  498. onDragEnd: function () {
  499. var t = this.target,
  500. max = t.kids.length - 1,
  501. newIndex = Math.round(this.y / t.currentHeight);
  502. newIndex += (newIndex < 0 ? -1 : 0) + t.currentIndex;
  503. if (newIndex === max) {
  504. t.parentNode.appendChild(t);
  505. } else {
  506. t.parentNode.insertBefore(t, t.kids[newIndex + 1]);
  507. }
  508. TweenLite.set(t.kids, { yPercent: 0, overwrite: "all" });
  509. TweenLite.set(t, { y: 0, color: "" });
  510. self._reOrderChannelBlocks();
  511.  
  512. //_.each(self.m_draggables, function(i){
  513. // this.enabled(false);
  514. //});
  515. }
  516. });
  517. },
  518.  
  519. /**
  520. Sortable channel list on press
  521. @method _sortablePress
  522. **/
  523. _sortablePress: function () {
  524. var t = this.target,
  525. i = 0,
  526. child = t;
  527. while (child = child.previousSibling)
  528. if (child.nodeType === 1) i++;
  529. t.currentIndex = i;
  530. t.currentHeight = t.offsetHeight;
  531. t.kids = [].slice.call(t.parentNode.children); // convert to array
  532. },
  533.  
  534. /**
  535. Sortable drag channel list on press
  536. @method _sortableDragStart
  537. **/
  538. _sortableDragStart: function () {
  539. TweenLite.set(this.target, { color: "#88CE02" });
  540. },
  541.  
  542. /**
  543. Sortable drag channel list
  544. @method _sortableDrag
  545. **/
  546. _sortableDrag: function () {
  547. var t = this.target,
  548. elements = t.kids.slice(), // clone
  549. indexChange = Math.round(this.y / t.currentHeight),
  550. bound1 = t.currentIndex,
  551. bound2 = bound1 + indexChange;
  552. if (bound1 < bound2) { // moved down
  553. TweenLite.to(elements.splice(bound1 + 1, bound2 - bound1), 0.15, { yPercent: -100 });
  554. TweenLite.to(elements, 0.15, { yPercent: 0 });
  555. } else if (bound1 === bound2) {
  556. elements.splice(bound1, 1);
  557. TweenLite.to(elements, 0.15, { yPercent: 0 });
  558. } else { // moved up
  559. TweenLite.to(elements.splice(bound2, bound1 - bound2), 0.15, { yPercent: 100 });
  560. TweenLite.to(elements, 0.15, { yPercent: 0 });
  561. }
  562. },
  563.  
  564. /**
  565. snap channels to set rounder values
  566. @method _sortableSnap
  567. **/
  568. _sortableSnap: function (y) {
  569. return y;
  570. // enable code below to enable snapinnes on dragging
  571. // var h = this.target.currentHeight;
  572. // return Math.round(y / h) * h;
  573. },
  574.  
  575. /**
  576. Move current selected block to be the first to play within the channel
  577. @method moveBlockFirst
  578. **/
  579. moveBlockFirst: function () {
  580. var self = this;
  581. var resourceElem = $('.activated', self.$el);
  582. $(Elements.SORTABLE).prepend($(resourceElem));
  583. self._reOrderChannelBlocks();
  584. },
  585.  
  586. /**
  587. Move current selected block to be the last to play within the channel
  588. @method moveBlockLast
  589. **/
  590. moveBlockLast: function () {
  591. var self = this;
  592. var resourceElem = $('.activated', self.$el);
  593. $(Elements.SORTABLE).append($(resourceElem));
  594. self._reOrderChannelBlocks();
  595. }
  596. });
  597.  
  598. return ChannelListView;
  599.  
  600. });