visibility.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. $axure.internal(function($ax) {
  2. var document = window.document;
  3. var _visibility = {};
  4. $ax.visibility = _visibility;
  5. var _defaultHidden = {};
  6. var _defaultLimbo = {};
  7. // ****************** Visibility and State Functions ****************** //
  8. var _isIdVisible = $ax.visibility.IsIdVisible = function(id) {
  9. return $ax.visibility.IsVisible(window.document.getElementById(id));
  10. };
  11. $ax.visibility.IsVisible = function(element) {
  12. //cannot use css('visibility') because that gets the effective visiblity
  13. //e.g. won't be able to set visibility on panels inside hidden panels
  14. return element.style.visibility != 'hidden';
  15. };
  16. $ax.visibility.SetIdVisible = function(id, visible) {
  17. $ax.visibility.SetVisible(window.document.getElementById(id), visible);
  18. // Hide lightbox if necessary
  19. if(!visible) {
  20. $jobj($ax.repeater.applySuffixToElementId(id, '_lightbox')).remove();
  21. $ax.flyoutManager.unregisterPanel(id, true);
  22. }
  23. };
  24. $ax.visibility.SetVisible = function(element, visible) {
  25. //todo -- ahhhh! I really don't want to add this, I don't know why it is necessary (right now sliding panel state out then in then out breaks
  26. //and doesn't go hidden on the second out if we do not set display here.
  27. element.style.display = visible ? '' : 'none';
  28. element.style.visibility = visible ? 'visible' : 'hidden';
  29. };
  30. var _setWidgetVisibility = $ax.visibility.SetWidgetVisibility = function(elementId, options) {
  31. // If limboed, just fire the next action then leave.
  32. if(_limboIds[elementId]) {
  33. $ax.action.fireAnimationFromQueue(elementId);
  34. return;
  35. }
  36. var parentId = $jobj(elementId).parent().attr('id');
  37. _setVisibility(parentId, elementId, options);
  38. //set the visibility of the annotation box as well if it exists
  39. var ann = document.getElementById(elementId + "_ann");
  40. if(ann) _visibility.SetVisible(ann, options.value);
  41. //set ref visibility for ref of flow shape, if that exists
  42. var ref = document.getElementById(elementId + '_ref');
  43. if(ref) _visibility.SetVisible(ref, options.value);
  44. };
  45. var _setVisibility = function(parentId, childId, options) {
  46. var widget = $jobj(childId);
  47. var visible = $ax.visibility.IsIdVisible(childId);
  48. if(visible == options.value) {
  49. $ax.action.fireAnimationFromQueue(childId);
  50. return;
  51. }
  52. var child = $jobj(childId);
  53. var parent = parentId ? $jobj(parentId) : child.parent();
  54. var needContainer = options.easing && options.easing != 'none';
  55. var cullPosition = options.cull ? options.cull.css('position') : '';
  56. if(needContainer) {
  57. var fixedInfo = $ax.dynamicPanelManager.getFixedInfo(childId);
  58. var containerId = childId + '_container';
  59. var container = _makeContainer(containerId, options.cull || child, fixedInfo);
  60. container.insertBefore(child);
  61. child.appendTo(container);
  62. if(!options.settingChild) {
  63. child.css({
  64. position: 'absolute',
  65. left: 0,
  66. top: 0,
  67. 'margin-left': 0,
  68. 'margin-top': 0
  69. });
  70. }
  71. }
  72. var onComplete = function() {
  73. if(needContainer) {
  74. var css = {};
  75. if(fixedInfo.fixed) {
  76. css.position = 'fixed';
  77. if(fixedInfo.horizontal == 'left') css.left = fixedInfo.x;
  78. else if(fixedInfo.horizontal == 'center') {
  79. css.left = '50%';
  80. css['margin-left'] = fixedInfo.x;
  81. } else if(fixedInfo.horizontal == 'right') {
  82. css.left = 'auto';
  83. css.right = fixedInfo.x;
  84. }
  85. if(fixedInfo.vertical == 'top') css.top = fixedInfo.y;
  86. else if(fixedInfo.vertical == 'middle') {
  87. css.top = '50%';
  88. css['margin-top'] = fixedInfo.y;
  89. } else if(fixedInfo.vertical == 'bottom') {
  90. css.top = 'auto';
  91. css.bottom = fixedInfo.y;
  92. }
  93. } else {
  94. css.top = Number(container.css('top').replace('px', '')) || 0;
  95. css.left = Number(container.css('left').replace('px', '')) || 0;
  96. }
  97. child.insertBefore(container);
  98. container.remove();
  99. child.css(css);
  100. if(options.cull) options.cull.css('position', cullPosition);
  101. }
  102. options.onComplete && options.onComplete();
  103. if(options.fire) {
  104. $ax.event.raiseSyntheticEvent(childId, options.value ? 'onShow' : 'onHide');
  105. $ax.action.fireAnimationFromQueue(childId);
  106. }
  107. };
  108. var size = options.size || (needContainer ? child : parent);
  109. if(!options.easing || options.easing == 'none') {
  110. $ax.visibility.SetIdVisible(childId, options.value);
  111. onComplete();
  112. } else if(options.easing == 'fade') {
  113. if(options.value) {
  114. // Can't use $ax.visibility.SetIdVisible, because we only want to set visible, we don't want to display, fadeIn will handle that.
  115. widget.css('visibility', 'visible');
  116. widget.fadeIn(options.duration, onComplete);
  117. } else {
  118. // Fading here is being retarded...
  119. widget.animate({ opacity: 0 }, options.duration, 'swing', function() {
  120. $ax.visibility.SetIdVisible(childId, false);
  121. widget.css('opacity', '');
  122. onComplete();
  123. });
  124. }
  125. } else {
  126. if(options.value) {
  127. _slideStateIn(childId, childId, options.easing, options.direction, options.duration, size, false, onComplete);
  128. } else {
  129. var top = child.css('top');
  130. var left = child.css('left');
  131. var onOutComplete = function() {
  132. $ax.visibility.SetIdVisible(childId, false);
  133. child.css('top', top);
  134. child.css('left', left);
  135. onComplete();
  136. };
  137. _slideStateOut(size, childId, options.easing, options.direction, options.duration, onOutComplete);
  138. }
  139. }
  140. // If showing, go through all rich text objects inside you, and try to redo alignment of them
  141. if(options.value) {
  142. var descendants = $jobj(childId).find('*');
  143. for(var i = 0; i < descendants.length; i++) {
  144. var decendantId = descendants[i].id;
  145. // This check is probably redundant? UpdateTextAlignment should ignore any text objects that haven't set the vAlign yet.
  146. if($ax.getTypeFromElementId(decendantId) != 'richTextPanel') continue;
  147. $ax.style.updateTextAlignmentForVisibility(decendantId);
  148. }
  149. }
  150. };
  151. $ax.visibility.GetPanelState = function(id) {
  152. var children = $jobj(id).children();
  153. for(var i = 0; i < children.length; i++) {
  154. if(children[i].style && $ax.visibility.IsVisible(children[i])) return children[i].id;
  155. }
  156. return '';
  157. };
  158. $ax.visibility.SetPanelState = function(id, stateId, easingOut, directionOut, durationOut, easingIn, directionIn, durationIn, showWhenSet) {
  159. var show = !$ax.visibility.IsIdVisible(id) && showWhenSet;
  160. if(show) $ax.visibility.SetIdVisible(id, true);
  161. // Exit here if already at desired state.
  162. if($ax.visibility.IsIdVisible(stateId)) {
  163. if(show) $ax.event.raiseSyntheticEvent(id, 'onShow');
  164. $ax.action.fireAnimationFromQueue(id);
  165. return;
  166. }
  167. var state = $jobj(stateId);
  168. var oldStateId = $ax.visibility.GetPanelState(id);
  169. var oldState = $jobj(oldStateId);
  170. $ax.dynamicPanelManager.adjustFixed(id, oldState.width(), oldState.height(), state.width(), state.height());
  171. _bringPanelStateToFront(id, oldStateId);
  172. var fitToContent = $ax.dynamicPanelManager.isIdFitToContent(id);
  173. var resized = false;
  174. if(fitToContent) {
  175. // Set resized
  176. resized = state.width() != oldState.width() || state.height() != oldState.height();
  177. }
  178. var movement = (directionOut == 'left' || directionOut == 'up' || state.children().length == 0) && oldState.children().length != 0 ? oldState : state;
  179. var onCompleteCount = 0;
  180. var onComplete = function() {
  181. $ax.dynamicPanelManager.fitParentPanel(id);
  182. $ax.dynamicPanelManager.updatePanelPercentWidth(id);
  183. $ax.dynamicPanelManager.updatePanelContentPercentWidth(id);
  184. $ax.action.fireAnimationFromQueue(id);
  185. $ax.event.raiseSyntheticEvent(id, "onPanelStateChange");
  186. $ax.event.leavingState(oldStateId);
  187. };
  188. // Must do state out first, so if we cull by new state, location is correct
  189. _setVisibility(id, oldStateId, {
  190. value: false,
  191. easing: easingOut,
  192. direction: directionOut,
  193. duration: durationOut,
  194. onComplete: function() { _bringPanelStateToFront(id, stateId); if(++onCompleteCount == 2) onComplete(); },
  195. settingChild: true,
  196. size: movement,
  197. cull: easingOut == 'none' || state.children().length == 0 ? oldState : state
  198. });
  199. _setVisibility(id, stateId, {
  200. value: true,
  201. easing: easingIn,
  202. direction: directionIn,
  203. duration: durationIn,
  204. onComplete: function() { if(++onCompleteCount == 2) onComplete(); },
  205. settingChild: true,
  206. size: movement
  207. });
  208. if(show) $ax.event.raiseSyntheticEvent(id, 'onShow');
  209. if(resized) $ax.event.raiseSyntheticEvent(id, 'onResize');
  210. };
  211. var _makeContainer = function(containerId, rect, fixedInfo) {
  212. var container = $('<div></div>');
  213. container.attr('id', containerId);
  214. var css = {
  215. position: 'absolute',
  216. width: rect.width(),
  217. height: rect.height(),
  218. overflow: 'hidden'
  219. };
  220. // todo: **mas** make sure tihs is ok
  221. if(fixedInfo.fixed) {
  222. css.position = 'fixed';
  223. if(fixedInfo.horizontal == 'left') css.left = fixedInfo.x;
  224. else if(fixedInfo.horizontal == 'center') {
  225. css.left = '50%';
  226. css['margin-left'] = fixedInfo.x;
  227. } else if(fixedInfo.horizontal = 'right') {
  228. css.left = 'auto';
  229. css.right = fixedInfo.x;
  230. }
  231. if(fixedInfo.vertical == 'top') css.top = fixedInfo.y;
  232. else if(fixedInfo.vertical == 'middle') {
  233. css.top = '50%';
  234. css['margin-top'] = fixedInfo.y;
  235. } else if(fixedInfo.vertical == 'bottom') {
  236. css.top = 'auto';
  237. css.bottom = fixedInfo.y;
  238. }
  239. } else {
  240. css.left = Number(rect.css('left').replace('px', '')) || 0;
  241. css.top = Number(rect.css('top').replace('px', '')) || 0;
  242. }
  243. container.css(css);
  244. return container;
  245. };
  246. var _slideStateOut = function(container, stateId, easingOut, directionOut, durationOut, onComplete) {
  247. var width = container.width();
  248. var height = container.height();
  249. if(directionOut == "right") {
  250. $ax.move.MoveWidget(stateId, width, 0, easingOut, durationOut, false, onComplete);
  251. } else if(directionOut == "left") {
  252. $ax.move.MoveWidget(stateId, -width, 0, easingOut, durationOut, false, onComplete);
  253. } else if(directionOut == "up") {
  254. $ax.move.MoveWidget(stateId, 0, -height, easingOut, durationOut, false, onComplete);
  255. } else if(directionOut == "down") {
  256. $ax.move.MoveWidget(stateId, 0, height, easingOut, durationOut, false, onComplete);
  257. }
  258. };
  259. var _slideStateIn = function(id, stateId, easingIn, directionIn, durationIn, container, makePanelVisible, onComplete) {
  260. var width = container.width();
  261. var height = container.height();
  262. var state = $jobj(stateId);
  263. var oldTop = 0;
  264. var oldLeft = 0;
  265. if(directionIn == "right") {
  266. state.css('left', oldLeft - width + 'px');
  267. } else if(directionIn == "left") {
  268. state.css('left', oldLeft + width + 'px');
  269. } else if(directionIn == "up") {
  270. state.css('top', oldTop + height + 'px');
  271. } else if(directionIn == "down") {
  272. state.css('top', oldTop - height + 'px');
  273. }
  274. if(makePanelVisible) $ax.visibility.SetIdVisible(id, true);
  275. $ax.visibility.SetIdVisible(stateId, true);
  276. if(directionIn == "right") {
  277. $ax.move.MoveWidget(stateId, width, 0, easingIn, durationIn, false, onComplete);
  278. } else if(directionIn == "left") {
  279. $ax.move.MoveWidget(stateId, -width, 0, easingIn, durationIn, false, onComplete);
  280. } else if(directionIn == "up") {
  281. $ax.move.MoveWidget(stateId, 0, -height, easingIn, durationIn, false, onComplete);
  282. } else if(directionIn == "down") {
  283. $ax.move.MoveWidget(stateId, 0, height, easingIn, durationIn, false, onComplete);
  284. }
  285. };
  286. $ax.visibility.GetPanelStateId = function(dpId, index) {
  287. var itemNum = $ax.repeater.getItemIdFromElementId(dpId);
  288. var panelStateId = $ax.repeater.getScriptIdFromElementId(dpId) + '_state' + index;
  289. return $ax.repeater.createElementId(panelStateId, itemNum);
  290. };
  291. var _bringPanelStateToFront = function(dpId, stateid) {
  292. $('#' + stateid).appendTo($('#' + dpId));
  293. };
  294. var _limboIds = _visibility.limboIds = {};
  295. // limboId's is a dictionary of id->true, essentially a set.
  296. var _addLimboAndHiddenIds = $ax.visibility.addLimboAndHiddenIds = function(newLimboIds, newHiddenIds, query) {
  297. var limboedByMaster = {};
  298. for(var key in newLimboIds) {
  299. if($ax.getObjectFromElementId(key).type != 'referenceDiagramObject') continue;
  300. var ids = $ax.model.idsInRdo(key);
  301. for(var i = 0; i < ids.length; i++) limboedByMaster[ids[i]] = true;
  302. }
  303. var hiddenByMaster = {};
  304. for(key in newHiddenIds) {
  305. if($ax.getObjectFromElementId(key).type != 'referenceDiagramObject') continue;
  306. ids = $ax.model.idsInRdo(key);
  307. for(i = 0; i < ids.length; i++) hiddenByMaster[ids[i]] = true;
  308. }
  309. // Extend with children of rdos
  310. newLimboIds = $.extend(newLimboIds, limboedByMaster);
  311. newHiddenIds = $.extend(newHiddenIds, hiddenByMaster);
  312. // something is only visible if it's not hidden and limboed
  313. //if(!skipSetting) {
  314. query.each(function(diagramObject, elementId) {
  315. // Rdos already handled, contained widgets are limboed by the parent, and sub menus should be ignored
  316. if(diagramObject.type == 'referenceDiagramObject' || diagramObject.type == 'tableCell' || diagramObject.isContained || $jobj(elementId).hasClass('sub_menu')) return;
  317. if(diagramObject.type == 'table' && $jobj(elementId).parent().hasClass('ax_menu')) return;
  318. var shouldBeVisible = Boolean(!newLimboIds[elementId] && !newHiddenIds[elementId]);
  319. var isVisible = Boolean(_isIdVisible(elementId));
  320. if(shouldBeVisible != isVisible) {
  321. _setWidgetVisibility(elementId, { value: shouldBeVisible });
  322. }
  323. });
  324. //}
  325. _limboIds = _visibility.limboIds = $.extend(_limboIds, newLimboIds);
  326. };
  327. var _clearLimboAndHidden = $ax.visibility.clearLimboAndHidden = function(ids) {
  328. _limboIds = _visibility.limboIds = {};
  329. };
  330. $ax.visibility.clearLimboAndHiddenIds = function(ids) {
  331. for(var i = 0; i < ids.length; i++) delete _limboIds[ids[i]];
  332. };
  333. $ax.visibility.resetLimboAndHiddenToDefaults = function() {
  334. _clearLimboAndHidden();
  335. _addLimboAndHiddenIds(_defaultLimbo, _defaultHidden, $ax('*'));
  336. };
  337. $ax.visibility.initialize = function() {
  338. // initialize initial visible states
  339. $axure('*').each(function(diagramObject, elementId) {
  340. // sigh, javascript. we need the === here because undefined means not overriden
  341. if(diagramObject.style.visible === false) _defaultHidden[elementId] = true;
  342. //todo: **mas** check if the limboed widgets are hidden by default by the generator
  343. if(diagramObject.style.limbo) _defaultLimbo[elementId] = true;
  344. });
  345. $ax.visibility.addLimboAndHiddenIds(_defaultLimbo, _defaultHidden, $ax('*'));
  346. };
  347. });