APIs

Show:
  1. /**
  2. This base class for all the Blocks / players which reside on the timeline_channel or inside scenes.
  3. The base class implements basic timeline and scene interfaces including the management the properties UI.
  4. @class Block
  5. @constructor
  6. @param {string} i_placement indicates if the block is set to exist inside a timeline or inside a scene
  7. @param {string} i_block_id block / player id, only required if block inserted onto channel_timeline
  8. @return none
  9. **/
  10. define(['jquery', 'backbone'], function ($) {
  11.  
  12. /**
  13. Quiet mode, don't announce
  14. @property BB.CONSTS.NO_NOTIFICATION
  15. @static
  16. @final
  17. @type String
  18. */
  19. BB.CONSTS.NO_NOTIFICATION = true;
  20.  
  21. /**
  22. event fires when scene block was changed so scene needs to be re-rendered
  23. @event Block.SCENE_BLOCK_CHANGE
  24. @param {this} caller
  25. @param {String} selected block_id
  26. **/
  27. BB.EVENTS.SCENE_BLOCK_CHANGE = 'SCENE_BLOCK_CHANGE';
  28.  
  29. /**
  30. event fires when block border changed so scene needs to be re-rendered
  31. @event Block.BLOCK_BORDER_CHANGE
  32. @param {this} caller
  33. @param {String} selected block_id
  34. **/
  35. BB.EVENTS.BLOCK_BORDER_CHANGE = 'BLOCK_BORDER_CHANGE';
  36.  
  37. /**
  38. event fires when scene blocks freshly re-rendered onto the scene canvas so we need to update the UI of ALL blocks
  39. normally occurs after a Block.SCENE_BLOCK_CHANGE event
  40. @event Block.SCENE_BLOCKS_RENDERED
  41. @param {this} caller
  42. @param {String} selected block_id
  43. **/
  44. BB.EVENTS.SCENE_BLOCKS_RENDERED = 'SCENE_BLOCKS_RENDERED';
  45.  
  46. /**
  47. event fires when block is selected
  48. @event Block.BLOCK_SELECTED
  49. @param {this} caller
  50. @param {String} selected block_id
  51. **/
  52. BB.EVENTS.BLOCK_SELECTED = 'BLOCK_SELECTED';
  53.  
  54. /**
  55. Custom event fired when a block state changes
  56. @event LOCK_CHANGED
  57. @param {This} caller
  58. @param {Self} context caller
  59. @param {Event}
  60. @static
  61. @final
  62. **/
  63. BB.EVENTS.LOCK_CHANGED = 'LOCK_CHANGED';
  64.  
  65. var Block = BB.Controller.extend({
  66.  
  67. /**
  68. Constructor
  69. @method initialize
  70. **/
  71. initialize: function (options) {
  72. var self = this;
  73. self.m_placement = options.i_placement;
  74. self.m_block_id = options.i_block_id;
  75. self.m_sceneID = options.i_scene_player_data_id;
  76. self.m_blockType = options.blockType;
  77. self.m_selected = false;
  78. self.m_zIndex = -1;
  79. self.m_minSize = {w: 50, h: 50};
  80. self.m_blockName = BB.PepperHelper.getBlockBoilerplate(self.m_blockType).name;
  81. self.m_blockAcronym = BB.PepperHelper.getBlockBoilerplate(self.m_blockType).acronym;
  82. self.m_blockDescription = BB.PepperHelper.getBlockBoilerplate(self.m_blockType).description;
  83. self.m_blockIcon = BB.PepperHelper.getBlockBoilerplate(self.m_blockType).icon;
  84. self.m_blockFontAwesome = BB.PepperHelper.getBlockBoilerplate(self.m_blockType).fontAwesome;
  85. self.m_blockSvg = BB.PepperHelper.getBlockBoilerplate(self.m_blockType).svg;
  86. self.m_resourceID = undefined;
  87. self.m_blockProperty = BB.comBroker.getService(BB.SERVICES['BLOCK_PROPERTIES']);
  88.  
  89. self._listenAlphaChange();
  90. self._listenToggleLock();
  91. self._listenGradientChange();
  92. self._listenGradientColorPickerClosed();
  93. self._listenBackgroundStateChange();
  94. self._listenBorderStateChange();
  95. self._listenBorderColorChange();
  96. self._listenBlockSelected();
  97. self._onBlockLengthChanged();
  98. },
  99.  
  100. /**
  101. Init the sub properties panel for a block
  102. @method _initSubPanel
  103. @param {String} i_panel
  104. **/
  105. _initSubPanel: function (i_panel) {
  106. var self = this;
  107. self.m_blockProperty.initSubPanel(i_panel);
  108. },
  109.  
  110. /**
  111. Bring into view a sub properties panel of this block
  112. @method _viewSubPanel
  113. @param {String} i_panel
  114. **/
  115. _viewSubPanel: function (i_panel) {
  116. var self = this;
  117. self.m_blockProperty.viewSubPanel(i_panel);
  118. },
  119.  
  120. /**
  121. On changes in msdb model updated UI common lock properties
  122. @method _fabricLock
  123. **/
  124. _fabricLock: function () {
  125. var self = this;
  126. var domPlayerData = self._getBlockPlayerData();
  127. var locked = $(domPlayerData).attr('locked');
  128. if (_.isUndefined(locked) || locked == '0') {
  129. locked = false;
  130. } else {
  131. locked = true;
  132. }
  133. self.lockMovementX = locked;
  134. self.lockMovementY = locked;
  135. //self.lockScalingX = locked; self.lockScalingY = locked; self.lockUniScaling = locked; self.lockRotation = locked;
  136. if (!self.m_selected)
  137. return;
  138. var dimensionProps = BB.comBroker.getService(BB.SERVICES['DIMENSION_PROPS_LAYOUT']);
  139. if (_.isUndefined(dimensionProps))
  140. return;
  141. dimensionProps.setLock(locked);
  142. },
  143.  
  144. /**
  145. Toggle lock status
  146. @method _toggleLock
  147. **/
  148. _listenToggleLock: function () {
  149. var self = this;
  150. self._toggleLock = function (e) {
  151. if (!self.m_selected)
  152. return;
  153. self.lockMovementX = e.edata;
  154. self.lockMovementY = e.edata;
  155. //self.lockScalingX = e.edata; self.lockScalingY = e.edata; self.lockUniScaling = e.edata; self.lockRotation = e.edata;
  156. var v = e.edata == true ? 1 : 0;
  157. var domPlayerData = self._getBlockPlayerData();
  158. $(domPlayerData).attr('locked', v);
  159. self._setBlockPlayerData(domPlayerData, BB.CONSTS.NO_NOTIFICATION);
  160. };
  161. BB.comBroker.listenWithNamespace(BB.EVENTS.LOCK_CHANGED, self, self._toggleLock);
  162. },
  163.  
  164.  
  165. /**
  166. Listen to changes in Alpha UI properties selection and update msdb
  167. @method _listenAlphaChange
  168. **/
  169. _listenAlphaChange: function () {
  170. var self = this;
  171. self._alphaChanged = _.debounce(function (e) {
  172. if (!self.m_selected)
  173. return;
  174. var alpha = e.edata;
  175. var domPlayerData = self._getBlockPlayerData();
  176. var data = $(domPlayerData).find('Data').eq(0);
  177. var xSnippet = $(data).find('Appearance').eq(0);
  178. $(xSnippet).attr('alpha', alpha);
  179. self._setBlockPlayerData(domPlayerData);
  180. }, 100);
  181. BB.comBroker.listenWithNamespace(BB.EVENTS.ALPHA_CHANGED, self, self._alphaChanged);
  182. },
  183.  
  184. /**
  185. On changes in msdb model updated UI common alpha properties
  186. @method _alphaPopulate
  187. **/
  188. _alphaPopulate: function () {
  189. var self = this;
  190. var domPlayerData = self._getBlockPlayerData();
  191. var data = $(domPlayerData).find('Data').eq(0);
  192. var xSnippet = $(data).find('Appearance').eq(0);
  193. var alpha = $(xSnippet).attr('alpha');
  194. alpha = parseFloat(alpha) * 100;
  195. $(Elements.BLOCK_ALPHA_SLIDER).val(alpha);
  196. },
  197.  
  198. /**
  199. Enable gradient background UI
  200. @method _enableBgSelection
  201. **/
  202. _enableBgSelection: function () {
  203. var self = this;
  204. $(Elements.SHOW_BACKGROUND).prop('checked', true);
  205. $(Elements.BG_COLOR_SOLID_SELECTOR).hide();
  206. $(Elements.BG_COLOR_GRADIENT_SELECTOR).show();
  207. },
  208.  
  209. /**
  210. Enable gradient background UI
  211. @method _enableBgSelection
  212. **/
  213. _enableBorderSelection: function () {
  214. var self = this;
  215. $(Elements.SHOW_BORDER).prop('checked', true);
  216. $(Elements.BLOCK_BORDER_WRAP).show();
  217. },
  218.  
  219. /**
  220. On changes in msdb model updated UI common gradient background properties
  221. @method _bgPropsPopulate
  222. **/
  223. _bgPropsPopulate: function () {
  224. var self = this;
  225. var gradient = $(Elements.BG_COLOR_GRADIENT_SELECTOR).data("gradientPicker-sel");
  226. // gradient.changeFillDirection("top"); /* change direction future support */
  227. gradient.removeAllPoints();
  228. var domPlayerData = self._getBlockPlayerData();
  229. var xSnippet = self._findGradientPoints(domPlayerData);
  230. if (xSnippet.length > 0) {
  231. self._enableBgSelection();
  232. var points = $(xSnippet).find('Point');
  233. $.each(points, function (i, point) {
  234. var pointColor = BB.lib.decimalToHex($(point).attr('color'));
  235. var pointMidpoint = (parseInt($(point).attr('midpoint')) / 250);
  236. gradient.addPoint(pointMidpoint, pointColor, true);
  237. });
  238. } else {
  239. self._bgPropsUnpopulate();
  240. }
  241. },
  242.  
  243. /**
  244. On changes in msdb model updated UI common border properties
  245. @method _borderPropsPopulate
  246. **/
  247. _borderPropsPopulate: function () {
  248. var self = this;
  249. var domPlayerData = self._getBlockPlayerData();
  250. var xSnippet = self._findBorder(domPlayerData);
  251. if (xSnippet.length > 0) {
  252. self._enableBorderSelection();
  253. var color = $(xSnippet).attr('borderColor');
  254. color = '#' + BB.lib.decimalToHex(color);
  255. self.m_blockProperty.setBorderBlockPropColorPicker(color);
  256. } else {
  257. self._borderPropsUnpopulate();
  258. }
  259. },
  260.  
  261. /**
  262. Disable the gradient background UI
  263. @method _bgPropsUnpopulate
  264. **/
  265. _bgPropsUnpopulate: function () {
  266. var self = this;
  267. $(Elements.SHOW_BACKGROUND).prop('checked', false);
  268. $(Elements.BG_COLOR_GRADIENT_SELECTOR).hide();
  269. $(Elements.BG_COLOR_SOLID_SELECTOR).hide();
  270. var domPlayerData = self._getBlockPlayerData();
  271. var gradientPoints = self._findGradientPoints(domPlayerData);
  272. $(gradientPoints).empty();
  273. },
  274.  
  275. /**
  276. Disable the border UI
  277. @method _borderPropsUnpopulate
  278. **/
  279. _borderPropsUnpopulate: function () {
  280. var self = this;
  281. $(Elements.SHOW_BORDER).prop('checked', false);
  282. $(Elements.BLOCK_BORDER_WRAP).hide();
  283. var domPlayerData = self._getBlockPlayerData();
  284. var border = self._findBorder(domPlayerData);
  285. $(border).empty();
  286. },
  287.  
  288. /**
  289. Toggle block background on UI checkbox selection
  290. @method _toggleBackgroundColorHandler
  291. @param {event} e
  292. **/
  293. _toggleBackgroundColorHandler: function (e) {
  294. var self = this;
  295. if (!self.m_selected)
  296. return;
  297.  
  298. var xBgSnippet = undefined;
  299. var domPlayerData = self._getBlockPlayerData();
  300. var checked = $(e.target).prop('checked') == true ? 1 : 0;
  301. if (checked) {
  302. self._enableBgSelection();
  303. xBgSnippet = BB.PepperHelper.getCommonBackgroundXML();
  304. var data = $(domPlayerData).find('Data').eq(0);
  305. var bgData = $(data).find('Background');
  306. if (bgData.length > 0 && !_.isUndefined(bgData.replace)) { // ie bug workaround
  307. bgData.replace($(xBgSnippet));
  308. } else {
  309. $(data).append($(xBgSnippet));
  310. }
  311. var player_data = pepper.xmlToStringIEfix(domPlayerData);
  312. domPlayerData = $.parseXML(player_data);
  313. self._setBlockPlayerData(domPlayerData, BB.CONSTS.NO_NOTIFICATION);
  314. self._bgPropsPopulate();
  315. //self._announceBlockChanged();
  316. } else {
  317. var xSnippet = self._findBackground(domPlayerData);
  318. $(xSnippet).remove();
  319. self._bgPropsUnpopulate();
  320. self._setBlockPlayerData(domPlayerData);
  321. }
  322. },
  323.  
  324. /**
  325. Toggle block background on UI checkbox selection
  326. @method _toggleBackgroundColorHandler
  327. @param {event} e
  328. **/
  329. _toggleBorderHandler: function (e) {
  330. var self = this;
  331. if (!self.m_selected)
  332. return;
  333.  
  334. var xBgSnippet = undefined;
  335. var domPlayerData = self._getBlockPlayerData();
  336. var checked = $(e.target).prop('checked') == true ? 1 : 0;
  337. if (checked) {
  338. self._enableBorderSelection();
  339. xBgSnippet = BB.PepperHelper.getCommonBorderXML();
  340. var data = $(domPlayerData).find('Data').eq(0);
  341. var bgData = self._findBorder(data);
  342. if (bgData.length > 0 && !_.isUndefined(bgData.replace)) { // ie bug workaround
  343. bgData.replace($(xBgSnippet));
  344. } else {
  345. $(data).append($(xBgSnippet));
  346. }
  347. var player_data = pepper.xmlToStringIEfix(domPlayerData);
  348. domPlayerData = $.parseXML(player_data);
  349. self._setBlockPlayerData(domPlayerData, BB.CONSTS.NO_NOTIFICATION);
  350. self._borderPropsPopulate();
  351. //self._announceBlockChanged();
  352. } else {
  353. var xSnippet = self._findBorder(domPlayerData);
  354. $(xSnippet).remove();
  355. self._borderPropsUnpopulate();
  356. self._setBlockPlayerData(domPlayerData);
  357. }
  358. },
  359.  
  360. /**
  361. Listen to change in background enable / disable states
  362. @method _listenBackgroundStateChange
  363. **/
  364. _listenBackgroundStateChange: function () {
  365. var self = this;
  366. self.m_proxyToggleBg = $.proxy(self._toggleBackgroundColorHandler, self);
  367. self.m_proxyToggleBgKey = _.uniqueId('click.');
  368. $(Elements.SHOW_BACKGROUND).on(self.m_proxyToggleBgKey, self.m_proxyToggleBg);
  369. },
  370.  
  371. /**
  372. Listen to change in background enable / disable states
  373. @method _listenBackgroundStateChange
  374. **/
  375. _listenBorderStateChange: function () {
  376. var self = this;
  377. self.m_proxyToggleBorder = $.proxy(self._toggleBorderHandler, self);
  378. self.m_proxyToggleBorderKey = _.uniqueId('click.');
  379. $(Elements.SHOW_BORDER).on(self.m_proxyToggleBorderKey, self.m_proxyToggleBorder);
  380. },
  381.  
  382. /**
  383. Update a block's player_data with new gradient background
  384. @method _listenGradientChange
  385. **/
  386. _listenGradientChange: function () {
  387. var self = this;
  388. BB.comBroker.listenWithNamespace(BB.EVENTS.GRADIENT_COLOR_CHANGED, self, function (e) {
  389. if (!self.m_selected)
  390. return;
  391. var points = e.edata.points;
  392. var styles = e.edata.styles;
  393. if (points.length == 0)
  394. return;
  395. var domPlayerData = self._getBlockPlayerData();
  396. var gradientPoints = self._findGradientPoints(domPlayerData);
  397. $(gradientPoints).empty();
  398. var pointsXML = "";
  399. for (var i = 0; i < points.length; ++i) {
  400. var pointMidpoint = (parseInt(points[i].position * 250));
  401. var color = BB.lib.colorToDecimal(points[i].color);
  402. var xPoint = '<Point color="' + color + '" opacity="1" midpoint="' + pointMidpoint + '" />';
  403. // log(xPoint);
  404. // $(gradientPoints).append(xPoint);
  405. pointsXML += xPoint;
  406. }
  407. // $(domPlayerData).find('GradientPoints').html(pointsXML);
  408. var xmlString = (new XMLSerializer()).serializeToString(domPlayerData);
  409. xmlString = xmlString.replace(/<GradientPoints[ ]*\/>/, '<GradientPoints>' + pointsXML + '</GradientPoints>');
  410. domPlayerData = $.parseXML(xmlString);
  411. self._setBlockPlayerData(domPlayerData, BB.CONSTS.NO_NOTIFICATION);
  412. });
  413. },
  414.  
  415. /**
  416. Update a block's player_data with new border background
  417. @method _listenBorderColorChange
  418. **/
  419. _listenBorderColorChange: function () {
  420. var self = this;
  421. BB.comBroker.listenWithNamespace(BB.EVENTS.BLOCK_BORDER_CHANGE, self, function (e) {
  422. if (!self.m_selected)
  423. return;
  424. var color = e.edata;
  425. var domPlayerData = self._getBlockPlayerData();
  426. var border = self._findBorder(domPlayerData);
  427. $(border).attr('borderColor', BB.lib.hexToDecimal(color));
  428. self._setBlockPlayerData(domPlayerData);
  429. });
  430. },
  431.  
  432. /**
  433. Update a block's player_data with new gradient background
  434. @method _listenGradientChange
  435. **/
  436. _listenGradientColorPickerClosed: function () {
  437. var self = this;
  438. BB.comBroker.listenWithNamespace(BB.EVENTS.GRADIENT_COLOR_CLOSED, self, function (e) {
  439. if (!self.m_selected)
  440. return;
  441. var domPlayerData = self._getBlockPlayerData();
  442. self._setBlockPlayerData(domPlayerData);
  443. });
  444. },
  445.  
  446. /**
  447. Find the background section in player_data for selected block
  448. @method _findBackground
  449. @param {object} i_domPlayerData
  450. @return {Xml} xSnippet
  451. **/
  452. _findBackground: function (i_domPlayerData) {
  453. var self = this;
  454. var xSnippet = $(i_domPlayerData).find('Background');
  455. return xSnippet;
  456. },
  457.  
  458. /**
  459. Find the border section in player_data for selected block
  460. @method _findBorder
  461. @param {object} i_domPlayerData
  462. @return {Xml} xSnippet
  463. **/
  464. _findBorder: function (i_domPlayerData) {
  465. var self = this;
  466. return $(i_domPlayerData).find('Border');
  467. },
  468.  
  469. /**
  470. Find the gradient blocks in player_data for selected block
  471. @method _findGradientPoints
  472. @param {object} i_domPlayerData
  473. @return {Xml} xSnippet
  474. **/
  475. _findGradientPoints: function (i_domPlayerData) {
  476. var self = this;
  477. var xSnippet = $(i_domPlayerData).find('GradientPoints');
  478. return xSnippet;
  479. },
  480.  
  481. /**
  482. Notify this object that it has been selected so it can populate it's own the properties box etc
  483. The function triggers from the BLOCK_SELECTED event.
  484. @method _listenBlockSelected
  485. @return none
  486. **/
  487. _listenBlockSelected: function () {
  488. var self = this;
  489. BB.comBroker.listenWithNamespace(BB.EVENTS.BLOCK_SELECTED, self, function (e) {
  490. var blockID = e.edata;
  491. if (self.m_block_id != blockID) {
  492. self.m_selected = false;
  493. return;
  494. }
  495. self._onBlockSelected();
  496. });
  497. },
  498.  
  499. /**
  500. When a block is selected, find out where is it placed (scene/ channel) and change props accordingly
  501. @method _onBlockSelected
  502. **/
  503. _onBlockSelected: function () {
  504. var self = this;
  505. self.m_selected = true;
  506. self.m_blockProperty.viewPanel(Elements.BLOCK_PROPERTIES);
  507. self._updateTitle();
  508. self._updateTitleTab();
  509. self._alphaPopulate();
  510. self._fabricLock();
  511. self._borderPropsPopulate();
  512. self._bgPropsPopulate();
  513.  
  514. log('block selected ' + self.m_block_id);
  515.  
  516. switch (self.m_placement) {
  517. case BB.CONSTS.PLACEMENT_CHANNEL:
  518. {
  519. $(Elements.CHANNEL_BLOCK_PROPS).show();
  520. $(Elements.SCENE_BLOCK_PROPS).hide();
  521. self._updateBlockLength();
  522. break;
  523. }
  524.  
  525. case BB.CONSTS.PLACEMENT_SCENE:
  526. {
  527. $(Elements.CHANNEL_BLOCK_PROPS).hide();
  528. $(Elements.SCENE_BLOCK_PROPS).show();
  529. self._updateBlockDimensions();
  530. break;
  531. }
  532.  
  533. case BB.CONSTS.PLACEMENT_IS_SCENE:
  534. {
  535. $(Elements.CHANNEL_BLOCK_PROPS).hide();
  536. $(Elements.SCENE_BLOCK_PROPS).hide();
  537. self._updateBlockLength();
  538. break;
  539. }
  540. }
  541.  
  542. if (self._loadBlockSpecificProps)
  543. self._loadBlockSpecificProps();
  544. },
  545.  
  546. /**
  547. Update the title of the block inside the assigned element.
  548. @method _updateTitle
  549. @return none
  550. **/
  551. _updateTitle: function () {
  552. var self = this;
  553. $(Elements.SELECTED_CHANNEL_RESOURCE_NAME).text(self.m_blockName);
  554. },
  555.  
  556. /**
  557. Update the title of the selected tab properties element
  558. @method m_blockAcronym
  559. **/
  560. _updateTitleTab: function () {
  561. var self = this;
  562. var isVisible = $(Elements.BLOCK_COMMON_SETTINGS_TAB).is(':visible');
  563. if (isVisible){
  564. $(Elements.BLOCK_COMMON_SETTINGS_TAB).hide();
  565. $(Elements.BLOCK_PROPERTIES_TABBER).find('a').eq(0).trigger('click');
  566. }
  567. $(Elements.BLOCK_SUBPROPERTIES_TITLE).text(self.m_blockAcronym);
  568. },
  569.  
  570. /**
  571. Update the length properties of the block with respect to position on the timeline_channel
  572. @method _updateBlockLength
  573. @return none
  574. **/
  575. _updateBlockLength: function () {
  576. var self = this;
  577. var lengthData;
  578.  
  579. switch (self.m_placement) {
  580. case BB.CONSTS.PLACEMENT_CHANNEL:
  581. {
  582. lengthData = pepper.getBlockTimelineChannelBlockLength(self.m_block_id);
  583. break;
  584. }
  585. case BB.CONSTS.PLACEMENT_IS_SCENE:
  586. {
  587. lengthData = pepper.getSceneDuration(self.m_block_id);
  588. break;
  589. }
  590. }
  591. $(Elements.BLOCK_LENGTH_HOURS).val(lengthData.hours).trigger('change');
  592. $(Elements.BLOCK_LENGTH_MINUTES).val(lengthData.minutes).trigger('change');
  593. $(Elements.BLOCK_LENGTH_SECONDS).val(lengthData.seconds).trigger('change');
  594. },
  595.  
  596. /**
  597. Update the position of the block when placed inside a scene
  598. @method _updateBlockDimensions
  599. **/
  600. _updateBlockDimensions: function () {
  601. var self = this;
  602. var dimensionProps = BB.comBroker.getService(BB.SERVICES['DIMENSION_PROPS_LAYOUT']);
  603.  
  604. //var cW = self['canvasScale'] == 1 ? self.canvas.getWidth() : self.canvas.getWidth() * (1 / self['canvasScale']);
  605. //var cH = self['canvasScale'] == 1 ? self.canvas.getHeight() : self.canvas.getHeight() * (1 / self['canvasScale']);
  606.  
  607. var values = {
  608. y: self['canvasScale'] == 1 ? self.top : self.top * (1 / self['canvasScale']),
  609. x: self['canvasScale'] == 1 ? self.left : self.left * (1 / self['canvasScale']),
  610. w: self['canvasScale'] == 1 ? self.width : self.width * (1 / self['canvasScale']),
  611. h: self['canvasScale'] == 1 ? self.height : self.height * (1 / self['canvasScale']),
  612. a: self.angle
  613. };
  614. dimensionProps.setValues(values);
  615. },
  616.  
  617. /**
  618. Take action when block length has changed which is triggered by the BLOCK_LENGTH_CHANGING event
  619. @method _onBlockLengthChanged
  620. @return none
  621. **/
  622. _onBlockLengthChanged: function () {
  623. var self = this;
  624.  
  625. BB.comBroker.listenWithNamespace(BB.EVENTS.BLOCK_LENGTH_CHANGING, this, function (e) {
  626.  
  627. if (self.m_selected) {
  628.  
  629. var hours = $(Elements.BLOCK_LENGTH_HOURS).val();
  630. var minutes = $(Elements.BLOCK_LENGTH_MINUTES).val();
  631. var seconds = $(Elements.BLOCK_LENGTH_SECONDS).val();
  632.  
  633. switch (e.caller) {
  634. case 'blockLengthHours':
  635. {
  636. hours = e.edata;
  637. break;
  638. }
  639. case 'blockLengthMinutes':
  640. {
  641. minutes = e.edata;
  642. break;
  643. }
  644. case 'blockLengthSeconds':
  645. {
  646. seconds = e.edata;
  647. break;
  648. }
  649. }
  650. // log('upd: ' + self.m_block_id + ' ' + hours + ' ' + minutes + ' ' + seconds);
  651. if (parseInt(hours) == 0 && parseInt(minutes) == 0 && parseInt(seconds) < 5)
  652. return;
  653.  
  654. switch (self.m_placement) {
  655. case BB.CONSTS.PLACEMENT_CHANNEL:
  656. {
  657. pepper.setBlockTimelineChannelBlockLength(self.m_block_id, hours, minutes, seconds);
  658. break;
  659. }
  660. case BB.CONSTS.PLACEMENT_IS_SCENE:
  661. {
  662. log('upd: ' + self.m_block_id + ' ' + hours + ' ' + minutes + ' ' + seconds);
  663. pepper.setSceneDuration(self.m_block_id, hours, minutes, seconds);
  664. break;
  665. }
  666. }
  667. }
  668. });
  669. },
  670.  
  671. /**
  672. Announce that this block has changed
  673. @method _announceBlockChanged
  674. @param {Number} i_player_data
  675. **/
  676. _announceBlockChanged: function () {
  677. var self = this;
  678. BB.comBroker.fire(BB.EVENTS['SCENE_BLOCK_CHANGE'], self, null, [self.m_block_id]);
  679. },
  680.  
  681. /**
  682. Update the msdb for the block with new values inside its player_data
  683. @method _setBlockPlayerData
  684. @param {Object} i_xmlDoc the dom object to save to local msdb
  685. @param {String} [i_noNotify] if set, fire event announcing data saved
  686. @param {Boolean} [i_xmlIsString] if set, bypass serializeToString since already in string format
  687. **/
  688. _setBlockPlayerData: function (i_xmlDoc, i_noNotify, i_xmlIsString) {
  689. var self = this;
  690. var player_data;
  691. if (i_xmlIsString == true) {
  692. player_data = i_xmlDoc;
  693. } else {
  694. player_data = (new XMLSerializer()).serializeToString(i_xmlDoc);
  695. }
  696.  
  697. switch (self.m_placement) {
  698. case BB.CONSTS.PLACEMENT_CHANNEL:
  699. {
  700. pepper.setCampaignTimelineChannelPlayerRecord(self.m_block_id, 'player_data', player_data);
  701. break;
  702. }
  703. case BB.CONSTS.PLACEMENT_SCENE:
  704. {
  705. pepper.setScenePlayerdataBlock(self.m_sceneID, self.m_block_id, player_data);
  706. if (!i_noNotify)
  707. self._announceBlockChanged();
  708. break;
  709. }
  710. case BB.CONSTS.PLACEMENT_IS_SCENE:
  711. {
  712. pepper.setScenePlayerData(self.m_block_id, player_data);
  713. if (!i_noNotify)
  714. self._announceBlockChanged();
  715. break;
  716. }
  717. }
  718. },
  719.  
  720.  
  721. /**
  722. Get the XML player data of a block, depending where its placed
  723. If you like to view XML raw data, be sure to debug domPlayerData.children[0].outerHTML
  724. @method _getBlockPlayerData
  725. @return {Object} player data of block (aka player) parsed as DOM
  726. **/
  727. _getBlockPlayerData: function () {
  728. var self = this;
  729. var recBlock = undefined;
  730.  
  731. switch (self.m_placement) {
  732.  
  733. case BB.CONSTS.PLACEMENT_CHANNEL:
  734. {
  735. recBlock = pepper.getCampaignTimelineChannelPlayerRecord(self.m_block_id);
  736. return $.parseXML(recBlock['player_data']);
  737. // to view data debug domPlayerData.children[0].outerHTML
  738. break;
  739. }
  740.  
  741. case BB.CONSTS.PLACEMENT_SCENE:
  742. {
  743. return pepper.getScenePlayerdataBlock(self.m_sceneID, self.m_block_id);
  744. // to view data debug domPlayerData.children[0].outerHTML
  745. break;
  746. }
  747. }
  748. },
  749.  
  750. /**
  751. bug fix: backward comparability with player_data that includes deleted resources
  752. this was already fixed but we live _selfDestruct for backwards compatability
  753. @method _selfDestruct
  754. **/
  755. _selfDestruct: function () {
  756. var self = this;
  757. setTimeout(function () {
  758. var sceneEditView = BB.comBroker.getService(BB.SERVICES['SCENE_EDIT_VIEW']);
  759. if (!_.isUndefined(sceneEditView)) {
  760. var selectedSceneID = sceneEditView.getSelectedSceneID();
  761. pepper.removeScenePlayer(selectedSceneID, self.m_block_id);
  762. BB.comBroker.fire(BB.EVENTS.LOAD_SCENE, this, null, selectedSceneID);
  763. }
  764. }, 2000);
  765. },
  766.  
  767.  
  768. /**
  769. Delete block is a private method that is always called regardless if instance has
  770. been inherited or not. Used for releasing memory for garbage collector.
  771. @method _deleteBlock
  772. @params {Boolean} i_memoryOnly if true only remove from existance but not from msdb
  773. @return none
  774. **/
  775. _deleteBlock: function (i_memoryOnly) {
  776. var self = this;
  777. if (!i_memoryOnly)
  778. pepper.removeBlockFromTimelineChannel(self.m_block_id);
  779. BB.comBroker.stopListenWithNamespace(BB.EVENTS.BLOCK_SELECTED, self);
  780. BB.comBroker.stopListenWithNamespace(BB.EVENTS.BLOCK_LENGTH_CHANGING, self);
  781. BB.comBroker.stopListenWithNamespace(BB.EVENTS.GRADIENT_COLOR_CHANGED, self);
  782. BB.comBroker.stopListenWithNamespace(BB.EVENTS.GRADIENT_COLOR_CLOSED, self);
  783. BB.comBroker.stopListenWithNamespace(BB.EVENTS.BLOCK_BORDER_CHANGE, self);
  784. BB.comBroker.stopListenWithNamespace(BB.EVENTS.ALPHA_CHANGED, self);
  785. BB.comBroker.stopListenWithNamespace(BB.EVENTS.LOCK_CHANGED, self);
  786. $(Elements.SHOW_BACKGROUND).off(self.m_proxyToggleBgKey, self.m_proxyToggleBg);
  787. $(Elements.SHOW_BORDER).off(self.m_proxyToggleBorderKey, self.m_proxyToggleBorder);
  788.  
  789. if (self.off != undefined)
  790. self.off('modified');
  791.  
  792. if (self.m_sceneSelectedHandler)
  793. self.m_canvas.off('object:selected', self.m_sceneSelectedHandler);
  794.  
  795. $.each(self, function (k) {
  796. self[k] = undefined;
  797. });
  798. },
  799.  
  800. /**
  801. Fabricate alpha to canvas
  802. @method _fabricAlpha
  803. @param {Object} i_domPlayerData
  804. **/
  805. _fabricAlpha: function (i_domPlayerData) {
  806. var self = this;
  807. var appearance = $(i_domPlayerData).find('Appearance');
  808. var opacity = $(appearance).attr('alpha');
  809. self.setOpacity(opacity);
  810. },
  811.  
  812. /**
  813. Fabricate color points to canvas
  814. @method _fabricColorPoints
  815. @param {xml} i_domPlayerData
  816. **/
  817. _fabricColorPoints: function (i_domPlayerData) {
  818. var self = this;
  819. var gradientPoints = $(i_domPlayerData).find('GradientPoints');
  820. var points = $(gradientPoints).find('Point');
  821. var colorStops = {}
  822. _.each(points, function (point) {
  823. var color = '#' + BB.lib.decimalToHex($(point).attr('color'));
  824. var offset = $(point).attr('midpoint');
  825. offset = offset / 250;
  826. colorStops[offset] = color;
  827. });
  828. return colorStops;
  829. },
  830.  
  831. /**
  832. Config the fabric block border
  833. @method _fabricateBorder
  834. @param {i_options} i_options
  835. @return {object} object literal
  836. **/
  837. _fabricateBorder: function (i_options) {
  838. var self = this;
  839. var domPlayerData = self._getBlockPlayerData();
  840. var border = self._findBorder(domPlayerData);
  841. var color = border.length == 0 ? 'transparent' : '#' + BB.lib.decimalToHex($(border).attr('borderColor'));
  842. return _.extend({
  843. // borderColor: '#5d5d5d',
  844. stroke: color,
  845. strokeWidth: 1
  846. }, i_options);
  847. },
  848.  
  849. /**
  850. Build the options injected into a newly created fabric object
  851. @method _fabricateOptions
  852. @param {Number} i_top
  853. @param {Number} i_left
  854. @param {Number} i_width
  855. @param {Number} i_height
  856. @param {Number} i_angle
  857. @return {object} object literal
  858. **/
  859. _fabricateOptions: function (i_top, i_left, i_width, i_height, i_angle) {
  860. var self = this;
  861. var options = {
  862. top: i_top,
  863. left: i_left,
  864. width: i_width,
  865. height: i_height,
  866. angle: i_angle,
  867. fill: '#ececec',
  868. hasRotatingPoint: false,
  869. transparentCorners: false,
  870. cornerColor: 'black',
  871. cornerSize: 5,
  872. lockRotation: true,
  873. lineWidth: 1
  874. };
  875.  
  876. return self._fabricateBorder(options);
  877. },
  878.  
  879. /**
  880. Fabricate color points to canvas
  881. @method _fabricRect
  882. @param {number} i_width
  883. @param {number} i_height
  884. @param {xml} i_domPlayerData
  885. @return {object} r fabric js rectangular
  886. **/
  887. _fabricRect: function (i_width, i_height, i_domPlayerData) {
  888. var self = this;
  889. var options = self._fabricateOptions(0, 0, i_width, i_height, 0);
  890. var r = new fabric.Rect(options);
  891. r.setGradient('fill', {
  892. x1: 0 - (i_width / 2),
  893. y1: 0,
  894. x2: (i_width / 2),
  895. y2: 0,
  896. colorStops: self._fabricColorPoints(i_domPlayerData)
  897. });
  898. return r;
  899. },
  900.  
  901. /**
  902. Convert the block into a fabric js compatible object, called externally on creation of block
  903. @Override
  904. @method fabricateBlock
  905. **/
  906. fabricateBlock: function (i_canvasScale, i_callback) {
  907. var self = this;
  908.  
  909. var domPlayerData = self._getBlockPlayerData();
  910. var layout = $(domPlayerData).find('Layout');
  911.  
  912. var w = parseInt(layout.attr('width'));
  913. var h = parseInt(layout.attr('height'));
  914. var rec = self._fabricRect(w, h, domPlayerData);
  915.  
  916. fabric.loadSVGFromString(self.m_blockSvg, function (objects, options) {
  917. var groupSvg = fabric.util.groupSVGElements(objects, options);
  918. rec.originX = 'center';
  919. rec.originY = 'center';
  920. groupSvg.originX = 'center';
  921. groupSvg.originY = 'center';
  922.  
  923. var o = {
  924. left: parseInt(layout.attr('x')),
  925. top: parseInt(layout.attr('y')),
  926. width: parseInt(layout.attr('width')),
  927. height: parseInt(layout.attr('height')),
  928. angle: parseInt(layout.attr('rotation')),
  929. hasRotatingPoint: false,
  930. stroke: 'transparent',
  931. cornerColor: 'black',
  932. cornerSize: 5,
  933. lockRotation: true,
  934. transparentCorners: false
  935. };
  936. _.extend(self, o);
  937. self.add(rec);
  938. self.add(groupSvg);
  939. self._fabricAlpha(domPlayerData);
  940. self._fabricLock();
  941. self['canvasScale'] = i_canvasScale;
  942. i_callback();
  943. });
  944. },
  945.  
  946. /**
  947. Get block data as a json formatted object literal and return to caller
  948. @method getBlockData
  949. @return {object} data
  950. The entire block data members which can be made public
  951. **/
  952. getBlockData: function () {
  953. var self = this;
  954. var data = {
  955. blockID: self.m_block_id,
  956. blockType: self.m_blockType,
  957. blockName: self.m_blockName,
  958. blockDescription: self.m_blockDescription,
  959. blockIcon: self.m_blockIcon,
  960. blockFontAwesome: self.m_blockFontAwesome,
  961. blockAcronym: self.m_blockAcronym,
  962. blockMinWidth: self.m_minSize.w,
  963. blockMinHeight: self.m_minSize.h,
  964. blockData: self._getBlockPlayerData()
  965. };
  966. return data;
  967. },
  968.  
  969. /**
  970. Set a block's z-index in case we know it (i.e.: it is going to be a re-render of a previous block that
  971. was removed from the canvas)
  972. @method setZindex
  973. @param {Number} i_index
  974. **/
  975. setZindex: function (i_zIndex) {
  976. var self = this;
  977. self.m_zIndex = i_zIndex;
  978. },
  979.  
  980. /**
  981. Get a block's z-index
  982. @method getZindex
  983. @param {Number} i_index
  984. **/
  985. getZindex: function (i_zIndex) {
  986. var self = this;
  987. return self.m_zIndex;
  988. },
  989.  
  990. /**
  991. Delete block is a public method used as fall back method, if not overridden by inherited instance.
  992. It is also a semi abstract method, all implementations should go into _deleteBlock();
  993. @method deleteBlock
  994. @params {Boolean} i_memoryOnly if true only remove from existance but not from msdb
  995. @return none
  996. **/
  997. deleteBlock: function (i_memoryOnly) {
  998. /* semi-abstract, overridden, do not modify */
  999. var self = this;
  1000. self._deleteBlock(i_memoryOnly);
  1001. }
  1002. });
  1003.  
  1004. return Block;
  1005. });