visibility.js 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103
  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. var _setAllVisible = function(query, visible) {
  25. for(var i = 0; i < query.length; i++) _visibility.SetVisible(query[i], visible);
  26. }
  27. $ax.visibility.SetVisible = function(element, visible) {
  28. //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
  29. //and doesn't go hidden on the second out if we do not set display here.
  30. if(visible) {
  31. //hmmm i will need to remove the class here cause display will not be overwriten by set to ''
  32. if($(element).hasClass(HIDDEN_CLASS)) $(element).removeClass(HIDDEN_CLASS);
  33. if($(element).hasClass(UNPLACED_CLASS)) $(element).removeClass(UNPLACED_CLASS);
  34. element.style.display = '';
  35. element.style.visibility = 'visible';
  36. } else {
  37. element.style.display = 'none';
  38. element.style.visibility = 'hidden';
  39. }
  40. };
  41. var _setWidgetVisibility = $ax.visibility.SetWidgetVisibility = function (elementId, options) {
  42. var visible = $ax.visibility.IsIdVisible(elementId);
  43. // If limboed, just fire the next action then leave.
  44. if(visible == options.value || _limboIds[elementId]) {
  45. if(!_limboIds[elementId]) options.onComplete && options.onComplete();
  46. $ax.action.fireAnimationFromQueue(elementId, $ax.action.queueTypes.fade);
  47. return;
  48. }
  49. options.containInner = true;
  50. var query = $jobj(elementId);
  51. var parentId = query.parent().attr('id');
  52. var axObj = $obj(elementId);
  53. var preserveScroll = false;
  54. var isPanel = $ax.public.fn.IsDynamicPanel(axObj.type);
  55. var isLayer = $ax.public.fn.IsLayer(axObj.type);
  56. if(isPanel || isLayer) {
  57. //if dp has scrollbar, save its scroll position
  58. if(isPanel && axObj.scrollbars != 'none') {
  59. var shownState = $ax.dynamicPanelManager.getShownState(elementId);
  60. preserveScroll = true;
  61. //before hiding, try to save scroll location
  62. if(!options.value && shownState) {
  63. DPStateAndScroll[elementId] = {
  64. shownId: shownState.attr('id'),
  65. left: shownState.scrollLeft(),
  66. top: shownState.scrollTop()
  67. }
  68. }
  69. }
  70. _pushContainer(elementId, isPanel);
  71. if(isPanel && !options.value) _tryResumeScrollForDP(elementId);
  72. var complete = options.onComplete;
  73. options.onComplete = function () {
  74. if(complete) complete();
  75. _popContainer(elementId, isPanel);
  76. //after showing dp, restore the scoll position
  77. if(isPanel && options.value) _tryResumeScrollForDP(elementId, true);
  78. }
  79. options.containerExists = true;
  80. }
  81. _setVisibility(parentId, elementId, options, preserveScroll);
  82. //set the visibility of the annotation box as well if it exists
  83. var ann = document.getElementById(elementId + "_ann");
  84. if(ann) _visibility.SetVisible(ann, options.value);
  85. //set ref visibility for ref of flow shape, if that exists
  86. var ref = document.getElementById(elementId + '_ref');
  87. if(ref) _visibility.SetVisible(ref, options.value);
  88. };
  89. var _setVisibility = function(parentId, childId, options, preserveScroll) {
  90. var wrapped = $jobj(childId);
  91. //easing: easingOut
  92. var completeTotal = 1;
  93. var visible = $ax.visibility.IsIdVisible(childId);
  94. if(visible == options.value) {
  95. options.onComplete && options.onComplete();
  96. $ax.action.fireAnimationFromQueue(childId, $ax.action.queueTypes.fade);
  97. return;
  98. }
  99. var child = $jobj(childId);
  100. var size = options.size || (options.containerExists ? $(child.children()[0]) : child);
  101. var isIdFitToContent = $ax.dynamicPanelManager.isIdFitToContent(parentId);
  102. //fade and resize won't work together when there is a container... but we still needs the container for fit to content DPs
  103. var needContainer = options.easing && options.easing != 'none' && (options.easing != 'fade' || isIdFitToContent);
  104. var cullPosition = options.cull ? options.cull.css('position') : '';
  105. var containerExists = options.containerExists;
  106. var isFullWidth = $ax.dynamicPanelManager.isPercentWidthPanel($obj(childId));
  107. // If fixed fit to content panel, then we must set size on it. It will be size of 0 otherwise, because container in it is absolute position.
  108. var needSetSize = false;
  109. var sizeObj = {};
  110. if(needContainer) {
  111. var sizeId = '';
  112. if($ax.dynamicPanelManager.isIdFitToContent(childId)) sizeId = childId;
  113. else {
  114. var panelId = $ax.repeater.removeSuffixFromElementId(childId)[0];
  115. if($ax.dynamicPanelManager.isIdFitToContent(panelId)) sizeId = panelId;
  116. }
  117. if (sizeId) {
  118. needSetSize = true;
  119. sizeObj = $jobj(sizeId);
  120. var newSize = options.cull || sizeObj;
  121. var newAxSize = $ax('#' + newSize.attr('id'));
  122. sizeObj.width(newAxSize.width());
  123. sizeObj.height(newAxSize.height());
  124. }
  125. }
  126. var wrappedOffset = { left: 0, top: 0 };
  127. var visibleWrapped = wrapped;
  128. if(needContainer) {
  129. var childObj = $obj(childId);
  130. if (options.cull) {
  131. var axCull = $ax('#' + options.cull.attr('id'));
  132. var containerWidth = axCull.width();
  133. var containerHeight = axCull.height();
  134. } else {
  135. if(childObj && ($ax.public.fn.IsLayer(childObj.type))) {// || childObj.generateCompound)) {
  136. var boundingRectangle = $ax.public.fn.getWidgetBoundingRect(childId);
  137. wrappedOffset.left = boundingRectangle.left;
  138. wrappedOffset.top = boundingRectangle.top;
  139. containerWidth = boundingRectangle.width;
  140. containerHeight = boundingRectangle.height;
  141. } else {
  142. containerWidth = $ax('#' + childId).width();
  143. containerHeight = $ax('#' + childId).height();
  144. }
  145. }
  146. var containerId = $ax.visibility.applyWidgetContainer(childId);
  147. // var container = _makeContainer(containerId, options.cull || boundingRectangle, isFullWidth, options.easing == 'flip', wrappedOffset, options.containerExists);
  148. var container = _makeContainer(containerId, containerWidth, containerHeight, isFullWidth, options.easing == 'flip', wrappedOffset, options.containerExists);
  149. if(options.containInner) {
  150. wrapped = _wrappedChildren(containerExists ? $(child.children()[0]) : child);
  151. // Filter for visibile wrapped children
  152. visibleWrapped = [];
  153. for (var i = 0; i < wrapped.length; i++) if($ax.visibility.IsVisible(wrapped[i])) visibleWrapped.push(wrapped[i]);
  154. visibleWrapped = $(visibleWrapped);
  155. completeTotal = visibleWrapped.length;
  156. if(!containerExists) container.prependTo(child);
  157. // Offset items if necessary
  158. if(!containerExists && (wrappedOffset.left != 0 || wrappedOffset.top != 0)) {
  159. for(var i = 0; i < wrapped.length; i++) {
  160. var inner = $(wrapped[i]);
  161. inner.css('left', $ax.getNumFromPx(inner.css('left')) - wrappedOffset.left);
  162. inner.css('top', $ax.getNumFromPx(inner.css('top')) - wrappedOffset.top);
  163. // Parent layer is now size 0, so have to have to use conatiner since it's the real size.
  164. // Should we use container all the time? This may make things easier for fit panels too.
  165. size = container;
  166. }
  167. }
  168. } else if(!containerExists) container.insertBefore(child);
  169. if(!containerExists) wrapped.appendTo(container);
  170. if (options.value && options.containInner) {
  171. //has to set children first because flip to show needs childerns invisible
  172. _setAllVisible(visibleWrapped, false);
  173. _updateChildAlignment(childId);
  174. _setAllVisible(child, true);
  175. }
  176. }
  177. var completeCount = 0;
  178. var onComplete = function () {
  179. completeCount++;
  180. if (needContainer && completeCount == completeTotal) {
  181. if ($ax.public.fn.isCompoundVectorHtml(container.parent()[0])) {
  182. wrappedOffset.left = $ax.getNumFromPx(container.css('left'));
  183. wrappedOffset.top = $ax.getNumFromPx(container.css('top'));
  184. }
  185. if (options.containInner && !containerExists && (wrappedOffset.left != 0 || wrappedOffset.top != 0)) {
  186. for (i = 0; i < wrapped.length; i++) {
  187. inner = $(wrapped[i]);
  188. //if ($ax.public.fn.isCompoundVectorComponentHtml(inner[0])) break;
  189. inner.css('left', $ax.getNumFromPx(inner.css('left')) + wrappedOffset.left);
  190. inner.css('top', $ax.getNumFromPx(inner.css('top')) + wrappedOffset.top);
  191. }
  192. }
  193. if(options.containInner && !options.value) {
  194. _setAllVisible(child, false);
  195. _setAllVisible(visibleWrapped, true);
  196. }
  197. if(containerExists) {
  198. if(!options.settingChild) container.css('position', 'relative;');
  199. } else {
  200. wrapped.insertBefore(container);
  201. container.remove();
  202. }
  203. //child.css(css);
  204. // Any text set or other things that triggered alignment updating during animation can happen now.
  205. if(options.containInner) {
  206. for(i = 0; i < wrapped.length; i++) $ax.style.checkAlignmentQueue($(wrapped[i]).attr('id'));
  207. }
  208. if(childObj && $ax.public.fn.IsDynamicPanel(childObj.type) && window.modifiedDynamicPanleParentOverflowProp) {
  209. child.css('overflow', 'hidden');
  210. window.modifiedDynamicPanleParentOverflowProp = false;
  211. }
  212. }
  213. if(!needContainer || completeTotal == completeCount) {
  214. if(options.cull) options.cull.css('position', cullPosition);
  215. if(needSetSize) {
  216. sizeObj.css('width', 'auto');
  217. sizeObj.css('height', 'auto');
  218. }
  219. options.onComplete && options.onComplete();
  220. if(options.fire) {
  221. $ax.event.raiseSyntheticEvent(childId, options.value ? 'onShow' : 'onHide');
  222. $ax.action.fireAnimationFromQueue(childId, $ax.action.queueTypes.fade);
  223. }
  224. }
  225. };
  226. // Nothing actually being animated, all wrapped elements invisible
  227. if(!visibleWrapped.length) {
  228. if(!options.easing || options.easing == 'none') {
  229. $ax.visibility.SetIdVisible(childId, options.value);
  230. completeTotal = 1;
  231. onComplete();
  232. } else {
  233. window.setTimeout(function() {
  234. completeCount = completeTotal - 1;
  235. onComplete();
  236. },options.duration);
  237. }
  238. return;
  239. }
  240. if(!options.easing || options.easing == 'none') {
  241. $ax.visibility.SetIdVisible(childId, options.value);
  242. completeTotal = 1;
  243. onComplete();
  244. } else if(options.easing == 'fade') {
  245. if(options.value) {
  246. if(preserveScroll) {
  247. visibleWrapped.css('opacity', 0);
  248. visibleWrapped.css('visibility', 'visible');
  249. visibleWrapped.css('display', 'block');
  250. //was hoping we could just use fadein here, but need to set display before set scroll position
  251. _tryResumeScrollForDP(childId);
  252. visibleWrapped.animate({ opacity: 1 }, {
  253. duration: options.duration,
  254. easing: 'swing',
  255. queue: false,
  256. complete: function() {
  257. $ax.visibility.SetIdVisible(childId, true);
  258. visibleWrapped.css('opacity', '');
  259. onComplete();
  260. }
  261. });
  262. } else {
  263. // Can't use $ax.visibility.SetIdVisible, because we only want to set visible, we don't want to display, fadeIn will handle that.
  264. visibleWrapped.css('visibility', 'visible');
  265. visibleWrapped.fadeIn({
  266. queue: false,
  267. duration: options.duration,
  268. complete: onComplete
  269. });
  270. }
  271. } else {
  272. // Fading here is being strange...
  273. visibleWrapped.animate({ opacity: 0 }, { duration: options.duration, easing: 'swing', queue: false, complete: function() {
  274. $ax.visibility.SetIdVisible(childId, false);
  275. visibleWrapped.css('opacity', '');
  276. onComplete();
  277. }});
  278. }
  279. } else if (options.easing == 'flip') {
  280. //this container will hold
  281. var innerContainer = $('<div></div>');
  282. innerContainer.attr('id', containerId + "_inner");
  283. innerContainer.data('flip', options.direction == 'left' || options.direction == 'right' ? 'y' : 'x');
  284. innerContainer.css({
  285. position: 'relative',
  286. 'width': containerWidth,
  287. 'height': containerHeight
  288. });
  289. innerContainer.appendTo(container);
  290. wrapped.appendTo(innerContainer);
  291. if(childObj && $ax.public.fn.IsDynamicPanel(childObj.type)) var containerDiv = child;
  292. else containerDiv = parentId ? $jobj(parentId) : child.parent();
  293. completeTotal = 1;
  294. var flipdegree;
  295. var requestAnimFrame = window.requestAnimationFrame ||
  296. window.webkitRequestAnimationFrame ||
  297. window.mozRequestAnimationFrame || window.msRequestAnimationFrame ||
  298. function (callback) {
  299. window.setTimeout(callback, 1000 / 60);
  300. };
  301. var originForUpOrDown = '100% ' + containerHeight / 2 + 'px';
  302. if(options.value) {
  303. //options.value == true means in or show, note to get here, the element must be currently hidden
  304. //to show, we need to first flip it 180deg without animation
  305. switch(options.direction) {
  306. case 'right':
  307. case 'left':
  308. _setRotateTransformation(innerContainer, 'rotateY(180deg)');
  309. flipdegree = options.direction === 'right' ? 'rotateY(360deg)' : 'rotateY(0deg)';
  310. break;
  311. case 'up':
  312. case 'down':
  313. innerContainer.css({
  314. '-webkit-transform-origin': originForUpOrDown,
  315. '-ms-transform-origin': originForUpOrDown,
  316. 'transform-origin': originForUpOrDown,
  317. });
  318. _setRotateTransformation(innerContainer, 'rotateX(180deg)');
  319. flipdegree = options.direction === 'up' ? 'rotateX(360deg)' : 'rotateX(0deg)';
  320. break;
  321. }
  322. var onFlipShowComplete = function() {
  323. $ax.visibility.SetIdVisible(childId, true);
  324. wrapped.insertBefore(innerContainer);
  325. innerContainer.remove();
  326. onComplete();
  327. };
  328. innerContainer.css({
  329. '-webkit-backface-visibility': 'hidden',
  330. 'backface-visibility': 'hidden'
  331. });
  332. child.css({
  333. 'display': '',
  334. 'visibility': 'visible'
  335. });
  336. visibleWrapped.css({
  337. 'display': '',
  338. 'visibility': 'visible'
  339. });
  340. innerContainer.css({
  341. '-webkit-transition-duration': options.duration + 'ms',
  342. 'transition-duration': options.duration + 'ms'
  343. });
  344. if(preserveScroll) _tryResumeScrollForDP(childId);
  345. requestAnimFrame(function () {
  346. _setRotateTransformation(innerContainer, flipdegree, containerDiv, onFlipShowComplete, options.duration);
  347. });
  348. } else { //hide or out
  349. switch(options.direction) {
  350. case 'right':
  351. case 'left':
  352. flipdegree = options.direction === 'right' ? 'rotateY(180deg)' : 'rotateY(-180deg)';
  353. break;
  354. case 'up':
  355. case 'down':
  356. //_setRotateTransformation(wrapped, 'rotateX(0deg)');
  357. innerContainer.css({
  358. '-webkit-transform-origin': originForUpOrDown,
  359. '-ms-transform-origin': originForUpOrDown,
  360. 'transform-origin': originForUpOrDown,
  361. });
  362. flipdegree = options.direction === 'up' ? 'rotateX(180deg)' : 'rotateX(-180deg)';
  363. break;
  364. }
  365. var onFlipHideComplete = function() {
  366. wrapped.insertBefore(innerContainer);
  367. $ax.visibility.SetIdVisible(childId, false);
  368. innerContainer.remove();
  369. onComplete();
  370. };
  371. innerContainer.css({
  372. '-webkit-backface-visibility': 'hidden',
  373. 'backface-visibility': 'hidden',
  374. '-webkit-transition-duration': options.duration + 'ms',
  375. 'transition-duration': options.duration + 'ms'
  376. });
  377. if(preserveScroll) _tryResumeScrollForDP(childId);
  378. requestAnimFrame(function () {
  379. _setRotateTransformation(innerContainer, flipdegree, containerDiv, onFlipHideComplete, options.duration);
  380. });
  381. }
  382. } else {
  383. // Because the move is gonna fire on annotation and ref too, need to update complete total
  384. completeTotal = $addAll(visibleWrapped, childId).length;
  385. if(options.value) {
  386. _slideStateIn(childId, childId, options, size, false, onComplete, visibleWrapped, preserveScroll);
  387. } else {
  388. var tops = [];
  389. var lefts = [];
  390. for(var i = 0; i < visibleWrapped.length; i++) {
  391. var currWrapped = $(visibleWrapped[i]);
  392. tops.push(currWrapped.css('top'));
  393. lefts.push(currWrapped.css('left'));
  394. }
  395. var onOutComplete = function () {
  396. //bring back SetIdVisible on childId for hiding lightbox
  397. $ax.visibility.SetIdVisible(childId, false);
  398. for(i = 0; i < visibleWrapped.length; i++) {
  399. currWrapped = $(visibleWrapped[i]);
  400. $ax.visibility.SetIdVisible(currWrapped.attr('id'), false);
  401. currWrapped.css('top', tops[i]);
  402. currWrapped.css('left', lefts[i]);
  403. }
  404. onComplete();
  405. };
  406. _slideStateOut(size, childId, options, onOutComplete, visibleWrapped);
  407. }
  408. }
  409. // If showing, go through all rich text objects inside you, and try to redo alignment of them
  410. if(options.value && !options.containInner) {
  411. _updateChildAlignment(childId);
  412. }
  413. };
  414. var _updateChildAlignment = function(childId) {
  415. var descendants = $jobj(childId).find('*');
  416. for(var i = 0; i < descendants.length; i++) {
  417. var decendantId = descendants[i].id;
  418. // This check is probably redundant? UpdateTextAlignment should ignore any text objects that haven't set the vAlign yet.
  419. if($ax.getTypeFromElementId(decendantId) != 'richTextPanel') continue;
  420. $ax.style.updateTextAlignmentForVisibility(decendantId);
  421. }
  422. };
  423. var _wrappedChildren = function (child) {
  424. return child.children();
  425. //var children = child.children();
  426. //var valid = [];
  427. //for(var i = 0; i < children.length; i++) if($ax.visibility.IsVisible(children[i])) valid.push(children[i]);
  428. //return $(valid);
  429. };
  430. var _setRotateTransformation = function(elementsToSet, transformValue, elementParent, flipCompleteCallback, flipDurationMs) {
  431. if(flipCompleteCallback) {
  432. //here we didn't use 'transitionend' event to fire callback
  433. //when show/hide on one element, changing transition property will stop the event from firing
  434. window.setTimeout(flipCompleteCallback, flipDurationMs);
  435. }
  436. elementsToSet.css({
  437. '-webkit-transform': transformValue,
  438. '-moz-transform': transformValue,
  439. '-ms-transform': transformValue,
  440. '-o-transform': transformValue,
  441. 'transform': transformValue
  442. });
  443. //when deal with dynamic panel, we need to set it's parent's overflow to visible to have the 3d effect
  444. //NOTE: we need to set this back when both flips finishes in DP, to prevents one animation finished first and set this back
  445. if(elementParent && elementParent.css('overflow') === 'hidden') {
  446. elementParent.css('overflow', 'visible');
  447. window.modifiedDynamicPanleParentOverflowProp = true;
  448. }
  449. };
  450. $ax.visibility.GetPanelState = function(id) {
  451. var children = $ax.visibility.getRealChildren($jobj(id).children());
  452. for(var i = 0; i < children.length; i++) {
  453. if(children[i].style && $ax.visibility.IsVisible(children[i])) return children[i].id;
  454. }
  455. return '';
  456. };
  457. var containerCount = {};
  458. $ax.visibility.SetPanelState = function(id, stateId, easingOut, directionOut, durationOut, easingIn, directionIn, durationIn, showWhenSet) {
  459. var show = !$ax.visibility.IsIdVisible(id) && showWhenSet;
  460. if(show) $ax.visibility.SetIdVisible(id, true);
  461. // Exit here if already at desired state.
  462. if($ax.visibility.IsIdVisible(stateId)) {
  463. if(show) $ax.event.raiseSyntheticEvent(id, 'onShow');
  464. $ax.action.fireAnimationFromQueue(id, $ax.action.queueTypes.setState);
  465. return;
  466. }
  467. _pushContainer(id, true);
  468. var state = $jobj(stateId);
  469. var oldStateId = $ax.visibility.GetPanelState(id);
  470. var oldState = $jobj(oldStateId);
  471. //pin to browser
  472. $ax.dynamicPanelManager.adjustFixed(id, oldState.width(), oldState.height(), state.width(), state.height());
  473. _bringPanelStateToFront(id, stateId);
  474. var fitToContent = $ax.dynamicPanelManager.isIdFitToContent(id);
  475. var resized = false;
  476. if(fitToContent) {
  477. // Set resized
  478. resized = state.width() != oldState.width() || state.height() != oldState.height();
  479. }
  480. //edge case for sliding
  481. var movement = (directionOut == 'left' || directionOut == 'up' || state.children().length == 0) && oldState.children().length != 0 ? oldState : state;
  482. var onCompleteCount = 0;
  483. var onComplete = function () {
  484. //move this call from _setVisibility() for animate out.
  485. //Because this will make the order of dp divs consistence: the showing panel is always in front after both animation finished
  486. //tested in the cases where one panel is out/show slower/faster/same time/instantly.
  487. _bringPanelStateToFront(id, stateId);
  488. if (window.modifiedDynamicPanleParentOverflowProp) {
  489. var parent = id ? $jobj(id) : child.parent();
  490. parent.css('overflow', 'hidden');
  491. window.modifiedDynamicPanleParentOverflowProp = false;
  492. }
  493. $ax.dynamicPanelManager.fitParentPanel(id);
  494. $ax.dynamicPanelManager.updatePanelPercentWidth(id);
  495. $ax.dynamicPanelManager.updatePanelContentPercentWidth(id);
  496. $ax.action.fireAnimationFromQueue(id, $ax.action.queueTypes.setState);
  497. $ax.event.raiseSyntheticEvent(id, "onPanelStateChange");
  498. $ax.event.leavingState(oldStateId);
  499. _popContainer(id, true);
  500. };
  501. // Must do state out first, so if we cull by new state, location is correct
  502. _setVisibility(id, oldStateId, {
  503. value: false,
  504. easing: easingOut,
  505. direction: directionOut,
  506. duration: durationOut,
  507. containerExists: true,
  508. onComplete: function() {
  509. // if(easingIn !== 'flip') _bringPanelStateToFront(id, stateId);
  510. if (++onCompleteCount == 2) onComplete();
  511. },
  512. settingChild: true,
  513. size: movement,
  514. //cull for
  515. cull: easingOut == 'none' || state.children().length == 0 ? oldState : state
  516. });
  517. _setVisibility(id, stateId, {
  518. value: true,
  519. easing: easingIn,
  520. direction: directionIn,
  521. duration: durationIn,
  522. containerExists: true,
  523. onComplete: function () {
  524. // if (easingIn === 'flip') _bringPanelStateToFront(id, stateId);
  525. if (++onCompleteCount == 2) onComplete();
  526. },
  527. settingChild: true,
  528. //size for offset
  529. size: movement
  530. });
  531. if(show) $ax.event.raiseSyntheticEvent(id, 'onShow');
  532. if(resized) $ax.event.raiseSyntheticEvent(id, 'onResize');
  533. };
  534. var containedFixed = {};
  535. var _pushContainer = _visibility.pushContainer = function(id, panel) {
  536. var count = containerCount[id];
  537. if(count) containerCount[id] = count + 1;
  538. else {
  539. var jobj = $jobj(id);
  540. var children = jobj.children();
  541. var css = {
  542. position: 'relative',
  543. top: 0,
  544. left: 0
  545. };
  546. if(!panel) {
  547. var boundingRect = $axure.fn.getWidgetBoundingRect(id);
  548. css.top = boundingRect.top;
  549. css.left = boundingRect.left;
  550. }
  551. var container = $('<div></div>');
  552. container.attr('id', $ax.visibility.applyWidgetContainer(id));
  553. container.css(css);
  554. //container.append(jobj.children());
  555. jobj.append(container);
  556. containerCount[id] = 1;
  557. // Panel needs to wrap children
  558. if(panel) {
  559. for(var i = 0; i < children.length; i++) {
  560. var child = $(children[i]);
  561. var childContainer = $('<div></div>');
  562. childContainer.attr('id', $ax.visibility.applyWidgetContainer(child.attr('id')));
  563. childContainer.css(css);
  564. child.after(childContainer);
  565. childContainer.append(child);
  566. container.append(childContainer);
  567. }
  568. } else {
  569. var focus = _getCurrFocus();
  570. // Layer needs to fix top left
  571. var childIds = $ax('#' + id).getChildren()[0].children;
  572. for(var i = 0; i < childIds.length; i++) {
  573. var childId = childIds[i];
  574. var childObj = $jobj(childId);
  575. var fixedInfo = $ax.dynamicPanelManager.getFixedInfo(childId);
  576. if(fixedInfo.fixed) {
  577. var axObj = $ax('#' + childId);
  578. var left = axObj.left();
  579. var top = axObj.top();
  580. containedFixed[childId] = { left: left, top: top, fixed: fixedInfo };
  581. childObj.css('left', left);
  582. childObj.css('top', top);
  583. childObj.css('margin-left', 0);
  584. childObj.css('margin-top', 0);
  585. childObj.css('right', 'auto');
  586. childObj.css('bottom', 'auto');
  587. childObj.css('position', 'absolute');
  588. }
  589. var cssChange = {
  590. left: '-=' + css.left,
  591. top: '-=' + css.top
  592. };
  593. if($ax.getTypeFromElementId(childId) == $ax.constants.LAYER_TYPE) {
  594. _pushContainer(childId, false);
  595. $ax.visibility.applyWidgetContainer(childId, true).css(cssChange);
  596. } else {
  597. //if ($ax.public.fn.isCompoundVectorHtml(jobj[0])) {
  598. // var grandChildren = jobj[0].children;
  599. // //while (grandChildren.length > 0 && grandChildren[0].id.indexOf('container') >= 0) grandChildren = grandChildren[0].children;
  600. // for (var j = 0; j < grandChildren.length; j++) {
  601. // var grandChildId = grandChildren[j].id;
  602. // if (grandChildId.indexOf(childId + 'p') >= 0 || grandChildId.indexOf('_container') >= 0) $jobj(grandChildId).css(cssChange);
  603. // }
  604. //} else
  605. // Need to include ann and ref in move.
  606. childObj = $addAll(childObj, childId);
  607. childObj.css(cssChange);
  608. }
  609. container.append(childObj);
  610. }
  611. _setCurrFocus(focus);
  612. }
  613. }
  614. };
  615. var _popContainer = _visibility.popContainer = function(id, panel) {
  616. var count = containerCount[id];
  617. if(!count) return;
  618. count--;
  619. containerCount[id] = count;
  620. if(count != 0) return;
  621. var jobj = $jobj(id);
  622. var container = $ax.visibility.applyWidgetContainer(id, true);
  623. // If layer is at bottom or right of page, unwrapping could change scroll by temporarily reducting page size.
  624. // To avoid this, we let container persist on page, with the size it is at this point, and don't remove container completely
  625. // until the children are back to their proper locations.
  626. var size = $ax('#' + id);
  627. container.css('width', size.width());
  628. container.css('height', size.height());
  629. var focus = _getCurrFocus();
  630. jobj.append(container.children());
  631. _setCurrFocus(focus);
  632. $('body').append(container);
  633. // Layer doesn't have children containers to clean up
  634. if(panel) {
  635. var children = jobj.children();
  636. for(var i = 0; i < children.length; i++) {
  637. var childContainer = $(children[i]);
  638. var child = $(childContainer.children()[0]);
  639. childContainer.after(child);
  640. childContainer.remove();
  641. }
  642. } else {
  643. var left = container.css('left');
  644. var top = container.css('top');
  645. var childIds = $ax('#' + id).getChildren()[0].children;
  646. for (var i = 0; i < childIds.length; i++) {
  647. var childId = childIds[i];
  648. var cssChange = {
  649. left: '+=' + left,
  650. top: '+=' + top
  651. };
  652. if($ax.getTypeFromElementId(childId) == $ax.constants.LAYER_TYPE) {
  653. $ax.visibility.applyWidgetContainer(childId, true).css(cssChange);
  654. _popContainer(childId, false);
  655. } else {
  656. var childObj = $jobj(childId);
  657. // if ($ax.public.fn.isCompoundVectorHtml(jobj[0])) {
  658. // var grandChildren = jobj[0].children;
  659. // //while (grandChildren.length > 0 && grandChildren[0].id.indexOf('container') >= 0) grandChildren = grandChildren[0].children;
  660. // for (var j = 0; j < grandChildren.length; j++) {
  661. // var grandChildId = grandChildren[j].id;
  662. // if (grandChildId.indexOf(childId + 'p') >= 0 || grandChildId.indexOf('_container') >= 0) $jobj(grandChildId).css(cssChange);
  663. // }
  664. //} else
  665. var allObjs = $addAll(childObj, childId); // Just include other objects for initial css. Fixed panels need to be dealt with separately.
  666. allObjs.css(cssChange);
  667. var fixedInfo = containedFixed[childId];
  668. if(fixedInfo) {
  669. delete containedFixed[childId];
  670. childObj.css('position', 'fixed');
  671. var deltaX = $ax.getNumFromPx(childObj.css('left')) - fixedInfo.left;
  672. var deltaY = $ax.getNumFromPx(childObj.css('top')) - fixedInfo.top;
  673. fixedInfo = fixedInfo.fixed;
  674. if(fixedInfo.horizontal == 'left') childObj.css('left', fixedInfo.x + deltaX);
  675. else if(fixedInfo.horizontal == 'center') {
  676. childObj.css('left', '50%');
  677. childObj.css('margin-left', fixedInfo.x + deltaX);
  678. } else {
  679. childObj.css('left', 'auto');
  680. childObj.css('right', fixedInfo.x - deltaX);
  681. }
  682. if(fixedInfo.vertical == 'top') childObj.css('top', fixedInfo.y + deltaY);
  683. else if(fixedInfo.vertical == 'middle') {
  684. childObj.css('top', '50%');
  685. childObj.css('margin-top', fixedInfo.y + deltaY);
  686. } else {
  687. childObj.css('top', 'auto');
  688. childObj.css('bottom', fixedInfo.y - deltaY);
  689. }
  690. $ax.dynamicPanelManager.updatePanelPercentWidth(childId);
  691. $ax.dynamicPanelManager.updatePanelContentPercentWidth(childId);
  692. }
  693. }
  694. }
  695. }
  696. container.remove();
  697. };
  698. var _getCurrFocus = function() {
  699. return window.lastFocusedClickable && window.lastFocusedClickable.id;
  700. }
  701. var _setCurrFocus = function(id) {
  702. if(id) {
  703. $jobj(id).focus();
  704. }
  705. }
  706. //use this to save & restore DP's scroll position when show/hide
  707. //key => dp's id (not state's id, because it seems we can change state while hiding)
  708. //value => first state's id & scroll position
  709. //we only need to store one scroll position for one DP, and remove the key after shown.
  710. var DPStateAndScroll = {}
  711. var _tryResumeScrollForDP = function (dpId, deleteId) {
  712. var scrollObj = DPStateAndScroll[dpId];
  713. if(scrollObj) {
  714. var shownState = document.getElementById(scrollObj.shownId);
  715. if(scrollObj.left) shownState.scrollLeft = scrollObj.left;
  716. if(scrollObj.top) shownState.scrollTop = scrollObj.top;
  717. if(deleteId) delete DPStateAndScroll[dpId];
  718. }
  719. };
  720. // var _makeContainer = function (containerId, rect, isFullWidth, isFlip, offset, containerExists) {
  721. var _makeContainer = function (containerId, width, height, isFullWidth, isFlip, offset, containerExists) {
  722. if(containerExists) var container = $jobj(containerId);
  723. else {
  724. container = $('<div></div>');
  725. container.attr('id', containerId);
  726. }
  727. var css = {
  728. position: 'absolute',
  729. width: width,
  730. height: height,
  731. };
  732. if(!containerExists) {
  733. // If container exists, may be busy updating location. Will init and update it correctly.
  734. css.top = offset.top;
  735. css.left = offset.left;
  736. }
  737. if(isFlip) {
  738. css.perspective = '800px';
  739. css.webkitPerspective = "800px";
  740. css.mozPerspective = "800px";
  741. } else css.overflow = 'hidden';
  742. //perspective on container will give us 3d effect when flip
  743. //if(!isFlip) css.overflow = 'hidden';
  744. // Rect should be a jquery not axquery obj
  745. //_getFixedCss(css, rect.$ ? rect.$() : rect, fixedInfo, isFullWidth);
  746. container.css(css);
  747. return container;
  748. };
  749. var CONTAINER_SUFFIX = _visibility.CONTAINER_SUFFIX = '_container';
  750. var CONTAINER_INNER = CONTAINER_SUFFIX + '_inner';
  751. _visibility.getWidgetFromContainer = function(id) {
  752. var containerIndex = id.indexOf(CONTAINER_SUFFIX);
  753. if(containerIndex == -1) return id;
  754. return id.substr(0, containerIndex) + id.substr(containerIndex + CONTAINER_SUFFIX.length);
  755. };
  756. // Apply container to widget id if necessary.
  757. // returnJobj: True if you want the jquery object rather than id returned
  758. // skipCheck: True if you want the query returned reguardless of container existing
  759. // checkInner: True if inner container should be checked
  760. _visibility.applyWidgetContainer = function (id, returnJobj, skipCheck, checkInner) {
  761. // If container exists, just return (return query if requested)
  762. if(id.indexOf(CONTAINER_SUFFIX) != -1) return returnJobj ? $jobj(id) : id;
  763. // Get desired id, and return it if query is not desired
  764. var containerId = $ax.repeater.applySuffixToElementId(id, checkInner ? CONTAINER_INNER : CONTAINER_SUFFIX);
  765. if(!returnJobj) return containerId;
  766. // If skipping check or container exists, just return innermost container requested
  767. var container = $jobj(containerId);
  768. if(skipCheck || container.length) return container;
  769. // If inner container was not checked, then no more to check, return query for widget
  770. if(!checkInner) return $jobj(id);
  771. // If inner container was checked, check for regular container still
  772. container = $jobj($ax.repeater.applySuffixToElementId(id, CONTAINER_SUFFIX));
  773. return container.length ? container : $jobj(id);
  774. };
  775. _visibility.isContainer = function(id) {
  776. return id.indexOf(CONTAINER_SUFFIX) != -1;
  777. };
  778. _visibility.getRealChildren = function(query) {
  779. while(query.length && $(query[0]).attr('id').indexOf(CONTAINER_SUFFIX) != -1) query = query.children();
  780. return query;
  781. };
  782. var _getFixedCss = function(css, rect, fixedInfo, isFullWidth) {
  783. // todo: **mas** make sure this is ok
  784. if(fixedInfo.fixed) {
  785. css.position = 'fixed';
  786. if(fixedInfo.horizontal == 'left') css.left = fixedInfo.x;
  787. else if(fixedInfo.horizontal == 'center') {
  788. css.left = isFullWidth ? '0px' : '50%';
  789. css['margin-left'] = fixedInfo.x;
  790. } else if(fixedInfo.horizontal == 'right') {
  791. css.left = 'auto';
  792. css.right = fixedInfo.x;
  793. }
  794. if(fixedInfo.vertical == 'top') css.top = fixedInfo.y;
  795. else if(fixedInfo.vertical == 'middle') {
  796. css.top = '50%';
  797. css['margin-top'] = fixedInfo.y;
  798. } else if(fixedInfo.vertical == 'bottom') {
  799. css.top = 'auto';
  800. css.bottom = fixedInfo.y;
  801. }
  802. } else {
  803. css.left = Number(rect.css('left').replace('px', '')) || 0;
  804. css.top = Number(rect.css('top').replace('px', '')) || 0;
  805. }
  806. };
  807. var _slideStateOut = function (container, stateId, options, onComplete, jobj) {
  808. var directionOut = options.direction;
  809. var axObject = $ax('#' + container.attr('id'));
  810. var width = axObject.width();
  811. var height = axObject.height();
  812. if(directionOut == "right") {
  813. $ax.move.MoveWidget(stateId, width, 0, options, false, onComplete, false, jobj);
  814. } else if(directionOut == "left") {
  815. $ax.move.MoveWidget(stateId, -width, 0, options, false, onComplete, false, jobj);
  816. } else if(directionOut == "up") {
  817. $ax.move.MoveWidget(stateId, 0, -height, options, false, onComplete, false, jobj);
  818. } else if(directionOut == "down") {
  819. $ax.move.MoveWidget(stateId, 0, height, options, false, onComplete, false, jobj);
  820. }
  821. };
  822. var _slideStateIn = function (id, stateId, options, container, makePanelVisible, onComplete, jobj, preserveScroll) {
  823. var directionIn = options.direction;
  824. var axObject = $ax('#' +container.attr('id'));
  825. var width = axObject.width();
  826. var height = axObject.height();
  827. for(var i = 0; i < jobj.length; i++) {
  828. var child = $(jobj[i]);
  829. var oldTop = $ax.getNumFromPx(child.css('top'));
  830. var oldLeft = $ax.getNumFromPx(child.css('left'));
  831. if (directionIn == "right") {
  832. child.css('left', oldLeft - width + 'px');
  833. } else if(directionIn == "left") {
  834. child.css('left', oldLeft + width + 'px');
  835. } else if(directionIn == "up") {
  836. child.css('top', oldTop + height + 'px');
  837. } else if(directionIn == "down") {
  838. child.css('top', oldTop - height + 'px');
  839. }
  840. }
  841. if (makePanelVisible) $ax.visibility.SetIdVisible(id, true);
  842. for(i = 0; i < jobj.length; i++) $ax.visibility.SetIdVisible($(jobj[i]).attr('id'), true);
  843. if(preserveScroll) _tryResumeScrollForDP(id);
  844. if(directionIn == "right") {
  845. $ax.move.MoveWidget(stateId, width, 0, options, false, onComplete, false, jobj);
  846. } else if(directionIn == "left") {
  847. $ax.move.MoveWidget(stateId, -width, 0, options, false, onComplete, false, jobj);
  848. } else if(directionIn == "up") {
  849. $ax.move.MoveWidget(stateId, 0, -height, options, false, onComplete, false, jobj);
  850. } else if(directionIn == "down") {
  851. $ax.move.MoveWidget(stateId, 0, height, options, false, onComplete, false, jobj);
  852. }
  853. };
  854. $ax.visibility.GetPanelStateId = function(dpId, index) {
  855. var itemNum = $ax.repeater.getItemIdFromElementId(dpId);
  856. var panelStateId = $ax.repeater.getScriptIdFromElementId(dpId) + '_state' + index;
  857. return $ax.repeater.createElementId(panelStateId, itemNum);
  858. };
  859. $ax.visibility.GetPanelStateCount = function(id) {
  860. return $ax.visibility.getRealChildren($jobj(id).children()).length;
  861. };
  862. var _bringPanelStateToFront = function (dpId, stateid) {
  863. var panel = $jobj(dpId);
  864. if(containerCount[dpId]) {
  865. stateid = $ax.visibility.applyWidgetContainer(stateid);
  866. panel = $ax.visibility.applyWidgetContainer(dpId, true, false, true);
  867. }
  868. $jobj(stateid).appendTo(panel);
  869. //when bring a panel to front, it will be focused, and the previous front panel should fire blur event if it's lastFocusedClickableSelector
  870. //ie(currently 11) and firefox(currently 34) doesn't fire blur event, this is the hack to fire it manually
  871. if((IE || FIREFOX) && window.lastFocusedClickable && $ax.event.getFocusableWidgetOrChildId(window.lastFocusedControl) == window.lastFocusedClickable.id) {
  872. $(window.lastFocusedClickable).triggerHandler('blur');
  873. }
  874. };
  875. var _limboIds = _visibility.limboIds = {};
  876. // limboId's is a dictionary of id->true, essentially a set.
  877. var _addLimboAndHiddenIds = $ax.visibility.addLimboAndHiddenIds = function(newLimboIds, newHiddenIds, query, skipRepeater) {
  878. var limboedByMaster = {};
  879. for(var key in newLimboIds) {
  880. if (!$ax.public.fn.IsReferenceDiagramObject($ax.getObjectFromElementId(key).type)) continue;
  881. var ids = $ax.model.idsInRdo(key);
  882. for(var i = 0; i < ids.length; i++) limboedByMaster[ids[i]] = true;
  883. }
  884. var hiddenByMaster = {};
  885. for(key in newHiddenIds) {
  886. if (!$ax.public.fn.IsReferenceDiagramObject($ax.getObjectFromElementId(key).type)) continue;
  887. ids = $ax.model.idsInRdo(key);
  888. for(i = 0; i < ids.length; i++) hiddenByMaster[ids[i]] = true;
  889. }
  890. // Extend with children of rdos
  891. newLimboIds = $.extend(newLimboIds, limboedByMaster);
  892. newHiddenIds = $.extend(newHiddenIds, hiddenByMaster);
  893. // something is only visible if it's not hidden and limboed
  894. //if(!skipSetting) {
  895. query.each(function(diagramObject, elementId) {
  896. // Rdos already handled, contained widgets are limboed by the parent, and sub menus should be ignored
  897. if($ax.public.fn.IsReferenceDiagramObject(diagramObject.type) || $ax.public.fn.IsTableCell(diagramObject.type) || diagramObject.isContained || $jobj(elementId).hasClass('sub_menu')) return;
  898. if(diagramObject.type == 'table' && $jobj(elementId).parent().hasClass('ax_menu')) return;
  899. if(skipRepeater) {
  900. // Any item in a repeater should return
  901. var repeater = $ax.getParentRepeaterFromElementId(elementId);
  902. if (repeater && repeater != elementId) return;
  903. }
  904. var scriptId = $ax.repeater.getScriptIdFromElementId(elementId);
  905. var shouldBeVisible = Boolean(!newLimboIds[scriptId] && !newHiddenIds[scriptId]);
  906. var isVisible = Boolean(_isIdVisible(elementId));
  907. if(shouldBeVisible != isVisible) {
  908. _setWidgetVisibility(elementId, { value: shouldBeVisible });
  909. }
  910. });
  911. //}
  912. _limboIds = _visibility.limboIds = $.extend(_limboIds, newLimboIds);
  913. };
  914. var _clearLimboAndHidden = $ax.visibility.clearLimboAndHidden = function(ids) {
  915. _limboIds = _visibility.limboIds = {};
  916. };
  917. $ax.visibility.clearLimboAndHiddenIds = function(ids) {
  918. for(var i = 0; i < ids.length; i++) {
  919. var scriptId = $ax.repeater.getScriptIdFromElementId(ids[i]);
  920. delete _limboIds[scriptId];
  921. }
  922. };
  923. $ax.visibility.resetLimboAndHiddenToDefaults = function (query) {
  924. if(!query) query = $ax('*');
  925. _clearLimboAndHidden();
  926. _addLimboAndHiddenIds(_defaultLimbo, _defaultHidden, query);
  927. };
  928. $ax.visibility.isScriptIdLimbo = function(scriptId) {
  929. if(_limboIds[scriptId]) return true;
  930. var repeater = $ax.getParentRepeaterFromScriptId(scriptId);
  931. if(!repeater) return false;
  932. var itemId = $ax.getItemIdsForRepeater(repeater)[0];
  933. return _limboIds[$ax.repeater.createElementId(scriptId, itemId)];
  934. }
  935. $ax.visibility.initialize = function() {
  936. // initialize initial visible states
  937. $('.' + HIDDEN_CLASS).each(function (index, diagramObject) {
  938. _defaultHidden[$ax.repeater.getScriptIdFromElementId(diagramObject.id)] = true;
  939. });
  940. $('.' + UNPLACED_CLASS).each(function (index, diagramObject) {
  941. _defaultLimbo[$ax.repeater.getScriptIdFromElementId(diagramObject.id)] = true;
  942. });
  943. _addLimboAndHiddenIds(_defaultLimbo, _defaultHidden, $ax('*'), true);
  944. };
  945. _visibility.initRepeater = function(repeaterId) {
  946. var html = $('<div></div>');
  947. html.append($jobj(repeaterId + '_script').html());
  948. html.find('.' + HIDDEN_CLASS).each(function (index, element) {
  949. _defaultHidden[$ax.repeater.getScriptIdFromElementId(element.id)] = true;
  950. });
  951. html.find('.' + UNPLACED_CLASS).each(function (index, element) {
  952. _defaultLimbo[$ax.repeater.getScriptIdFromElementId(element.id)] = true;
  953. });
  954. }
  955. var HIDDEN_CLASS = _visibility.HIDDEN_CLASS = 'ax_default_hidden';
  956. var UNPLACED_CLASS = _visibility.UNPLACED_CLASS = 'ax_default_unplaced';
  957. });