ScalingAbsolute.js 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. 'use strict';
  2. /**
  3. * Licensed Materials - Property of IBM
  4. * IBM Cognos Products: BI Cloud (C) Copyright IBM Corp. 2013, 2019
  5. * US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  6. */
  7. define(['./Absolute', 'jquery', 'underscore', '../../../util/PxPercentUtil', '../../../../app/util/DeepClone'], function (BaseLayout, $, _, PxPercentUtil) {
  8. var PageLayout = null;
  9. var SQUARES_INFO = 60;
  10. var SQUARES = 100;
  11. PageLayout = BaseLayout.extend({
  12. init: function init(options) {
  13. PageLayout.inherited('init', this, arguments);
  14. this.model.on('insert:item', this._onNewItem, this);
  15. if (this.model.items) {
  16. for (var i = 0; i < this.model.items.length; i++) {
  17. this._setChildMonitors(this.model.items[i]);
  18. }
  19. }
  20. //This is temporary until the property to change the aspect ratio gets up in. Then I'll use that to create the svg.
  21. this.specializeConsumeView(['setPreferredLocation']);
  22. this.dashboardApi = options.dashboardApi;
  23. },
  24. /**
  25. * Called when the view is destroyed
  26. */
  27. destroy: function destroy() {
  28. this.model.off('insert:item', this._onNewItem, this);
  29. this.$el.find('.relativeLayoutGrid').remove();
  30. if (this.model.items) {
  31. for (var i = 0; i < this.model.items.length; i++) {
  32. this._setChildMonitors(this.model.items[i], 'off');
  33. }
  34. }
  35. PageLayout.inherited('destroy', this, arguments);
  36. },
  37. /**
  38. * Set or Remove the event listeners to monitor when the layout model changes.
  39. * @param childModel
  40. * @param {String} sOff (Optional) Set to 'off' to remove listeners.
  41. */
  42. _setChildMonitors: function _setChildMonitors(childModel, sOff) {
  43. var sOnOrOff = sOff === 'off' ? 'off' : 'on';
  44. childModel[sOnOrOff]('change:style', this._onChildModelStyleChange, this);
  45. childModel[sOnOrOff]('prechange:style', this._onChildModelStylePreChange, this);
  46. childModel[sOnOrOff]('change:parent', this._onChildModelUpdateParent, this);
  47. },
  48. /**
  49. * Called when a new layout model is added to this layout.
  50. *
  51. */
  52. _onNewItem: function _onNewItem(payload) {
  53. var model = this.model.findModel(payload.value.parameter.model.id);
  54. this._setChildMonitors(model);
  55. this.updateStyleToPercent(model, payload.data);
  56. },
  57. /**
  58. * Called when the parent of a child model has changed.
  59. */
  60. _onChildModelUpdateParent: function _onChildModelUpdateParent(payload) {
  61. if (payload.value.parameter.parentId !== this.model.id) {
  62. var model = this.layoutController.topLayoutModel.findModel(payload.modelId);
  63. this._setChildMonitors(model, 'off');
  64. }
  65. },
  66. /**
  67. * Called when the layout style has changed
  68. */
  69. _onChildModelStyleChange: function _onChildModelStyleChange(payload) {
  70. // No need to do anything if the operation was caused by the 'updateStyleToPercent' method.
  71. // This means we already converted the pixels to percent
  72. if (payload.data && payload.data.hint !== 'updateStyleToPercent' && payload.sender !== 'UndoRedoController') {
  73. var model = this.layoutController.topLayoutModel.findModel(payload.modelId);
  74. this.updateStyleToPercent(model, payload.data);
  75. }
  76. },
  77. _onChildModelStylePreChange: function _onChildModelStylePreChange(payload) {
  78. if (payload.sender !== 'UndoRedoController') {
  79. var style = payload.value && payload.value.style;
  80. this._changePixelModelToPercent(style);
  81. }
  82. },
  83. /**
  84. * Modify the 'top,left,width, height' property in style object to use percent
  85. * @param {*} style
  86. */
  87. _changePixelModelToPercent: function _changePixelModelToPercent(style) {
  88. var $referenceView = this.$el;
  89. // this view could be hidden, so find a view that isn't hidden.
  90. if (!$referenceView.is(':visible')) {
  91. $referenceView = $(this.layoutController.getLastVisiblePage());
  92. }
  93. var referenceViewSize = { width: $referenceView.width(), height: $referenceView.height() };
  94. PxPercentUtil.changePixelPropertiesToPercent(style, referenceViewSize);
  95. },
  96. /**
  97. * Update the dimensions/positions in the model from pixel to percent
  98. *
  99. */
  100. updateStyleToPercent: function updateStyleToPercent(model, payloadData) {
  101. var _this = this;
  102. // TODO This should be changed to the way it is done in WA
  103. // https://github.ibm.com/WatsonAnalytics/wa-cardpage-client/pull/1760/files
  104. // insert:item needs to happen after add:item so currently a timeout is being used
  105. // Both events are triggered from add() of LayoutModel.js
  106. // We set the style once the layout is ready so that any pending layout view updates for the original change are complete.
  107. // We will only update the child model if it belongs to this layout
  108. return this.layoutController.layoutReady(model.id).then(function () {
  109. return new Promise(function (resolve, reject) {
  110. try {
  111. if (model.getParent() && model.getParent().id === _this.model.id) {
  112. if (model.style) {
  113. var newModelStyle = _.extend({}, model.style);
  114. _this._changePixelModelToPercent(newModelStyle);
  115. // Add a hint to the data that the operation is caused by updating the style to percent
  116. // This is to avoid doing an extra call to 'updateStyleToPercent' as a result of a layout style change
  117. var data = _.deepClone(payloadData);
  118. data.hint = 'updateStyleToPercent';
  119. data.triggerResize = false;
  120. model.updateModel({
  121. updateArray: [{
  122. style: newModelStyle,
  123. id: model.id
  124. }]
  125. }, null, data);
  126. }
  127. }
  128. resolve();
  129. } catch (error) {
  130. reject(error);
  131. }
  132. });
  133. });
  134. },
  135. _moveDrop: function _moveDrop(dragObject) {
  136. var nodeInfo = dragObject.data.nodeInfoList[0];
  137. var nodeModel = nodeInfo.node._layout.model;
  138. var currentParent = nodeModel.getParent();
  139. PageLayout.inherited('_moveDrop', this, arguments);
  140. if (currentParent.id !== this.model.id) {
  141. // Monitor the child for changes to get a chance to convert pixels to percent
  142. var childModel = this.model.findModel(nodeModel.id);
  143. this._setChildMonitors(childModel);
  144. currentParent.deselect(nodeModel.id);
  145. }
  146. },
  147. getMinimumTop: function getMinimumTop() {
  148. var parentMinimum = this.consumeView.parentLayout ? this.consumeView.parentLayout.getMinimumTop() : 0;
  149. var position = this.$el.position();
  150. return -1 * (position.top + this.$el.parent().scrollTop()) + parentMinimum;
  151. },
  152. getMinimumLeft: function getMinimumLeft() {
  153. var parentMinimum = this.consumeView.parentLayout ? this.consumeView.parentLayout.getMinimumLeft() : 0;
  154. var position = this.$el.position();
  155. return -1 * (position.left + this.$el.parent().scrollLeft()) + parentMinimum;
  156. },
  157. getScrollAreaNode: function getScrollAreaNode() {
  158. // the scaling layout does not provide a scrollable area. We use the parent view as scrollable area.
  159. return this.consumeView.parentLayout.$el;
  160. },
  161. renderGrid: function renderGrid() {
  162. var showGridProp = this.model.getValueFromSelfOrParent('showGrid');
  163. var showGrid = showGridProp === undefined ? false : showGridProp;
  164. var layoutPositioning = this.model.getValueFromSelfOrParent('layoutPositioning');
  165. if (showGrid && layoutPositioning === 'relative') {
  166. if (this.$el.hasClass('gridCapable')) {
  167. this.$el.find('.relativeLayoutGrid').remove();
  168. this.$el.prepend(this._createGridSvg(this.$el[0].id, this.$el.hasClass('infoGraphic')));
  169. }
  170. } else {
  171. this.$el.find('.relativeLayoutGrid').remove();
  172. }
  173. },
  174. _createGridSvg: function _createGridSvg(id, isInfographic) {
  175. var layoutPositioning = this.model.getValueFromSelfOrParent('layoutPositioning');
  176. var pageSize = this.getPhysicalPageSize(layoutPositioning, id);
  177. var gridSize = 0;
  178. if (isInfographic) {
  179. gridSize = pageSize.width / SQUARES_INFO;
  180. } else {
  181. gridSize = pageSize.width / SQUARES;
  182. }
  183. return '<div class="relativeLayoutGrid">\
  184. <svg viewBox="0 0 ' + pageSize.width + ' ' + pageSize.height + '" xmlns="http://www.w3.org/2000/svg">\
  185. <defs>\
  186. <pattern id="grid' + id + '" width="' + gridSize + '" height="' + gridSize + '" patternUnits="userSpaceOnUse">\
  187. <path d="M ' + gridSize + ' 0 L 0 0 0 ' + gridSize + '" fill="none" stroke-width="0.5"/>\
  188. </pattern>\
  189. </defs>\
  190. <rect width="100%" height="100%" fill="url(#grid' + id + ')" />\
  191. </svg>\
  192. </div>';
  193. }
  194. });
  195. return PageLayout;
  196. });
  197. //# sourceMappingURL=ScalingAbsolute.js.map