- /**
- The sequencer module is responsible for management and order of playback of each timeline within each campaign
- @class SequencerView
- @constructor
- @param {String} i_container element that CompCampaignNavigator inserts itself into
- @return {Object} instantiated CompCampaignNavigator
- **/
- define(['jquery', 'backbone', 'ScreenTemplateFactory', 'contextmenu'], function ($, Backbone, ScreenTemplateFactory, contextmenu) {
-
- BB.SERVICES.SEQUENCER_VIEW = 'SequencerView';
-
- var SequencerView = BB.View.extend({
-
- /**
- Constructor
- Init the instance and enable drag and drop operation.
- We also wire the open properties UI so we can populate a selected timeline through the properties panel.
- @method initialize
- **/
- initialize: function () {
- var self = this;
- this.m_thumbsContainer = this.$el;
- this.m_timelines = {};
- this.m_screenTemplates = {};
-
- self._listenContextMenu();
- self._listenReset();
- pepper.listen(Pepper.TIMELINE_DELETED, $.proxy(self._deleteSequencedTimeline, self));
- },
-
- /**
- Listen to any canvas right click
- @method _listenContextMenu
- **/
- _listenContextMenu: function () {
- var self = this;
- $(Elements.SCREEN_SELECTOR_CONTAINER).contextmenu({
- target: Elements.SEQUENCER_CONTEXT_MENU,
- before: function (e, element, target) {
- e.preventDefault();
- //self.m_mouseX = e.offsetX;
- //self.m_mouseY = e.offsetY;
- return true;
- },
- onItem: function (context, e) {
- self._onContentMenuSelection($(e.target).attr('name'))
- }
- });
- },
-
- /**
- On Scene right click context menu selection command
- @method _onContentMenuSelection
- @param {String} i_command
- **/
- _onContentMenuSelection: function (i_command) {
- var self = this;
- var campaign_timeline_id = BB.comBroker.getService(BB.SERVICES.CAMPAIGN_VIEW).getSelectedTimeline();
- if (campaign_timeline_id == -1 || _.isUndefined(campaign_timeline_id))
- return;
-
- switch (i_command) {
- case 'firstChannel':
- {
- $(Elements.SELECT_NEXT_CHANNEL).trigger('click');
- break;
- }
- case 'editLayout':
- {
- $(Elements.EDIT_SCREEN_LAYOUT).trigger('click');
- break;
- }
- case 'duplicate':
- {
- BB.comBroker.getService(BB.SERVICES.CAMPAIGN_VIEW).duplicateTimeline(campaign_timeline_id, {});
- break;
- }
- case 'remove':
- {
- $(Elements.REMOVE_TIMELINE_BUTTON).trigger('click');
- break;
- }
- case 'first':
- {
- var elem = $(self.m_thumbsContainer).find('[data-campaign_timeline_id="' + campaign_timeline_id + '"]').eq(0).closest('svg');
- $(self.m_thumbsContainer).prepend(elem);
- self.reSequenceTimelines();
- break;
- }
- case 'last':
- {
- var elem = $(self.m_thumbsContainer).find('[data-campaign_timeline_id="' + campaign_timeline_id + '"]').eq(0).closest('svg');
- $(self.m_thumbsContainer).append(elem);
- self.reSequenceTimelines();
- break;
- }
- }
- return true;
- },
-
- /**
- Delete a timeline from the Sequencer UI, as well as from the local member m_timelines.
- @method _deleteSequencedTimeline
- @param {Number} i_campaign_timeline_id
- @return none
- **/
- _deleteSequencedTimeline: function (e) {
- var self = this;
- var campaign_timeline_id = e.edata;
- self._deleteTimelineThumbUI(campaign_timeline_id);
- delete self.m_timelines[campaign_timeline_id];
- pepper.removeTimelineFromSequences(campaign_timeline_id);
- self.reSequenceTimelines();
- },
-
- /**
- Remove the element's UI thumb of a template layout
- @method _deleteTimelineThumbUI
- @param {Number} i_campaign_timeline_id
- **/
- _deleteTimelineThumbUI: function (i_campaign_timeline_id) {
- var self = this;
- var elementID = self.m_timelines[i_campaign_timeline_id];
- $('#' + elementID).remove();
- if (self.m_screenTemplates[i_campaign_timeline_id])
- self.m_screenTemplates[i_campaign_timeline_id].destroy();
- },
-
- /**
- Listen to reset of when switching to different campaign so we forget current state
- @method _listenReset
- **/
- _listenReset: function () {
- var self = this;
- BB.comBroker.listen(BB.EVENTS.CAMPAIGN_RESET, function () {
- self.m_timelines = {};
- self.m_screenTemplates = {};
- $(self.m_thumbsContainer).empty();
- });
- },
-
- /**
- Create a sortable channel list
- @method _createSortable
- @param {Element} i_selector
- **/
- _createSortable: function (i_selector) {
- var self = this;
- if ($(i_selector).children().length == 0) return;
- var sortable = document.querySelector(i_selector);
- self.m_draggables = Draggable.create(sortable.children, {
- type: "x",
- bounds: sortable,
- edgeResistance: 1,
- dragResistance: 0,
- onPress: self._sortablePress,
- onDragStart: self._sortableDragStart,
- onDrag: self._sortableDrag,
- liveSnap: self._sortableSnap,
- zIndexBoost: true,
- onDragEnd: function () {
- var t = this.target,
- max = t.kids.length - 1,
- //newIndex = Math.round(this.x / t.currentWidth);
- newIndex = Math.ceil(this.x / t.currentWidth);
- newIndex += (newIndex < 0 ? -1 : 0) + t.originalIndex;
- if (newIndex === max) {
- t.parentNode.appendChild(t);
- } else {
- t.parentNode.insertBefore(t, t.kids[newIndex + 1]);
- }
- TweenLite.set(t.kids, { xPercent: 0, overwrite: "all" });
- TweenLite.set(t, { y: 0, color: "" });
- var orderedTimelines = self.reSequenceTimelines();
- $(self.m_thumbsContainer).empty();
- BB.comBroker.getService(BB.SERVICES.CAMPAIGN_VIEW).populateTimelines(orderedTimelines);
- var campaign_timeline_id = BB.comBroker.getService(BB.SERVICES.CAMPAIGN_VIEW).getSelectedTimeline();
- self.selectTimeline(campaign_timeline_id);
-
- }
- });
- },
-
- /**
- Sortable channel list on press
- @method _sortablePress
- **/
- _sortablePress: function () {
- var t = this.target,
- i = 0,
- child = t;
- while (child = child.previousSibling)
- if (child.nodeType === 1) i++;
- t.originalIndex = i;
- t.currentWidth = $(t).outerWidth();
- t.kids = [].slice.call(t.parentNode.children); // convert to array
- },
-
- /**
- Sortable drag channel list on press
- @method _sortableDragStart
- **/
- _sortableDragStart: function () {
- TweenLite.set(this.target, { color: "#88CE02" });
- },
-
- /**
- Sortable drag channel list
- @method _sortableDrag
- **/
- _sortableDrag: function () {
- var t = this.target,
- elements = t.kids.slice(), // clone
- // indexChange = Math.round(this.x / t.currentWidth), // round flawed on large values
- indexChange = Math.ceil(this.x / t.currentWidth),
- srcIndex = t.originalIndex,
- dstIndex = srcIndex + indexChange;
-
- // console.log('k ' + t.kids.length + ' s:' + srcIndex + ' d:' + indexChange + ' t:' + (dstIndex - srcIndex));
-
- if (srcIndex < dstIndex) { // moved right
- TweenLite.to(elements.splice(srcIndex + 1, dstIndex - srcIndex), 0.15, { xPercent: -140 }); // 140 = width of screen layout widget
- TweenLite.to(elements, 0.15, { xPercent: 0 });
- } else if (srcIndex === dstIndex) {
- elements.splice(srcIndex, 1);
- TweenLite.to(elements, 0.15, { xPercent: 0 });
- } else { // moved left
- // ignore if destination > source index
- if ( (indexChange < 0 ? indexChange * -1 : indexChange) > srcIndex)
- return;
- TweenLite.to(elements.splice(dstIndex, srcIndex - dstIndex), 0.15, { xPercent: 140 }); // 140 = width of screen layout widget
- TweenLite.to(elements, 0.15, { xPercent: -10 });
- }
- },
-
- /**
- snap channels to set rounder values
- @method _sortableSnap
- **/
- _sortableSnap: function (y) {
- return y;
- /* enable code below to use live drag snapping */
- // var h = this.target.currentHeight;
- // return Math.round(y / h) * h;
- },
-
- /**
- Select the first timeline in the Sequencer
- @method selectFirstTimeline
- **/
- selectFirstTimeline: function () {
- var self = this;
- var timeline;
- for (timeline in self.m_timelines) {
- self.selectTimeline(timeline);
- break;
- }
- },
-
- /**
- Select a viewer
- @method selectViewer
- @param {Number} i_timeline_id
- @param {Number} i_viewer_id
- **/
- selectViewer: function (i_timeline_id, i_viewer_id) {
- var self = this;
- self.m_screenTemplates[i_timeline_id].selectDivison(i_viewer_id);
- },
-
- /**
- Create the timeline template (a.k.a timeline thumbnail) via the ScreenTemplateFactory
- and insert it into the sequencer UI. We proceed by activating the newly created timeline thumbnail
- via the ScreenTemplateFactory public methods.
- @method createTimelineThumbnailUI
- @param {Object} i_screenProps
- **/
- createTimelineThumbnailUI: function (i_screenProps) {
- var self = this;
- var index = -1;
- var elem = undefined;
-
- // Get the timeline id for current timeline creating
- for (var screenProp in i_screenProps) {
- var campaign_timeline_id = i_screenProps[screenProp]['campaign_timeline_id']
- break;
- }
-
- // if timeline_id already exists, it means this is an update from ScreenLayoutEditorView so we
- // must first delete previous UI as well as it's matching instance
- if (self.m_timelines[campaign_timeline_id] != undefined) {
- var elementID = '#' + self.m_timelines[campaign_timeline_id];
- index = $(elementID).index();
- self._deleteTimelineThumbUI(campaign_timeline_id);
- }
-
- var screenTemplateData = {
- orientation: BB.comBroker.getService(BB.SERVICES.ORIENTATION_SELECTOR_VIEW).getOrientation(),
- resolution: BB.comBroker.getService(BB.SERVICES.RESOLUTION_SELECTOR_VIEW).getResolution(),
- screenProps: i_screenProps,
- scale: '14'
- };
-
- var screenTemplate = new ScreenTemplateFactory({
- i_screenTemplateData: screenTemplateData,
- i_selfDestruct: false,
- i_owner: this
- });
-
- var snippet = screenTemplate.create();
- var elementID = $(snippet).attr('id');
-
- self.m_timelines[campaign_timeline_id] = elementID;
- self.m_screenTemplates[campaign_timeline_id] = screenTemplate;
-
- //screenTemplate.selectablelDivision();
- //screenTemplate.activate();
-
- switch (index) {
- case -1:
- {
- // position thumbnail in beginning (first creation)
- self.m_thumbsContainer.append(snippet);
- screenTemplate.selectableFrame();
- break;
- }
-
- case 0:
- {
- // position thumbnail index in beginning (append if no other thumbnails)
- elem = self.m_thumbsContainer.children().eq(0);
- if (elem.length > 0) {
- $(snippet).insertBefore(elem)
- } else {
- self.m_thumbsContainer.append(snippet);
- }
- screenTemplate.selectableFrame();
- break;
- }
-
- default:
- {
- // position thumbnail as previous index position
- elem = self.m_thumbsContainer.children().eq(index - 1);
- $(snippet).insertAfter(elem)
- screenTemplate.selectableFrame();
- break;
- }
- }
-
- self._createSortable(Elements.SCREEN_LAYOUTS_UL);
- },
-
- /**
- Reorder the timeline in the local msdb to match the UI order of the timeline thumbnails in the Sequencer
- @method reSequenceTimelines
- @return {Array} order of timelines ids
- **/
- reSequenceTimelines: function () {
- var self = this;
- var order = [];
- var timelines = $(self.m_thumbsContainer).children().each(function (sequenceIndex) {
- var element = $(this).find('[data-campaign_timeline_id]').eq(0);
- var campaign_timeline_id = $(element).data('campaign_timeline_id');
- order.push(campaign_timeline_id);
- var selectedCampaign = BB.comBroker.getService(BB.SERVICES.CAMPAIGN_VIEW).getSelectedCampaign();
- pepper.setCampaignTimelineSequencerIndex(selectedCampaign, campaign_timeline_id, sequenceIndex);
- });
- return order;
- },
-
- /**
- Return this instance.
- @method getOwner
- @return {Object} this
- **/
- getOwner: function () {
- return this;
- },
-
- /**
- Find the campaign_timeline_id within the Sequencer and trigger a click event on it so it gets selected.
- @method selectTimeline
- @param {Number} i_campaign_timeline_id
- @return {Number} i_campaign_timeline_id or -1
- **/
- selectTimeline: function (i_campaign_timeline_id) {
- var self = this;
- BB.comBroker.fire(BB.EVENTS.CAMPAIGN_TIMELINE_SELECTED, this, null, i_campaign_timeline_id);
- var total = $(self.m_thumbsContainer).find('[data-campaign_timeline_id="' + i_campaign_timeline_id + '"]').eq(0).mouseup();;
- if (total.length == 0)
- return -1;
- return i_campaign_timeline_id;
- }
- });
-
- return SequencerView;
-
- });
-