adaptive.js 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. $axure.internal(function($ax) {
  2. $ax.adaptive = {};
  3. $axure.utils.makeBindable($ax.adaptive, ["viewChanged"]);
  4. var _auto = true;
  5. var _autoIsHandledBySidebar = false;
  6. var _views;
  7. var _idToView;
  8. var _enabledViews = [];
  9. var _initialViewToLoad;
  10. var _initialViewSizeToLoad;
  11. var _loadFinished = false;
  12. $ax.adaptive.loadFinished = function() {
  13. if(_loadFinished) return;
  14. _loadFinished = true;
  15. if($ax.adaptive.currentViewId) $ax.viewChangePageAndMasters();
  16. else $ax.postAdaptiveViewChanged();
  17. };
  18. var _handleResize = function(forceSwitchTo) {
  19. if(!_auto) return;
  20. if(_auto && _autoIsHandledBySidebar && !forceSwitchTo) return;
  21. var $window = $(window);
  22. var height = $window.height();
  23. var width = $window.width();
  24. var toView = _getAdaptiveView(width, height);
  25. var toViewId = toView && toView.id;
  26. _switchView(toViewId, forceSwitchTo);
  27. };
  28. var _setAuto = $ax.adaptive.setAuto = function(val) {
  29. if(_auto != val) {
  30. _auto = Boolean(val);
  31. }
  32. };
  33. var _setLineImage = function(id, imageUrl) {
  34. $jobj(id).attr('src', imageUrl);
  35. };
  36. var _switchView = function (viewId, forceSwitchTo) {
  37. //if(!$ax.pageData.isAdaptiveEnabled) return;
  38. var previousViewId = $ax.adaptive.currentViewId;
  39. if(typeof previousViewId == 'undefined') previousViewId = '';
  40. if(typeof viewId == 'undefined') viewId = '';
  41. if (viewId == previousViewId) {
  42. if(forceSwitchTo) $ax.postAdaptiveViewChanged(forceSwitchTo);
  43. return;
  44. }
  45. $ax('*').each(function(obj, elementId) {
  46. if (!$ax.public.fn.IsTreeNodeObject(obj.type)) return;
  47. if(!obj.hasOwnProperty('isExpanded')) return;
  48. var query = $ax('#' + elementId);
  49. var defaultExpanded = obj.isExpanded;
  50. query.expanded(defaultExpanded);
  51. });
  52. // reset all the inline positioning from move and rotate actions including size and transformation
  53. $axure('*').each(function (diagramObject, elementId) {
  54. if(diagramObject.isContained) return;
  55. if($ax.getParentRepeaterFromElementIdExcludeSelf(elementId)) return;
  56. var element = document.getElementById(elementId);
  57. if(element) {
  58. var resetCss = {
  59. top: "", left: "", width: "", height: "", opacity: "",
  60. transform: "", webkitTransform: "", MozTransform: "", msTransform: "", OTransform: ""
  61. };
  62. var query = $(element);
  63. query.css(resetCss);
  64. var isPanel = $ax.public.fn.IsDynamicPanel(diagramObject.type);
  65. if(!isPanel || diagramObject.fitToContent) { //keeps size on the panel states when switching adaptive views to optimize fit to panel
  66. if(diagramObject.fitToContent) $ax.dynamicPanelManager.setFitToContentCss(elementId, true);
  67. var children = query.children();
  68. if(children.length) children.css(resetCss);
  69. }
  70. $ax.dynamicPanelManager.resetFixedPanel(diagramObject, element);
  71. $ax.dynamicPanelManager.resetAdaptivePercentPanel(diagramObject, element);
  72. }
  73. });
  74. $ax.adaptive.currentViewId = viewId; // we need to set this so the enabled and selected styles will apply properly
  75. if(previousViewId) {
  76. $ax.style.clearAdaptiveStyles();
  77. $('*').removeClass(previousViewId);
  78. } else {
  79. $ax.style.reselectElements();
  80. }
  81. $axure('*').each(function (obj, elementId) {
  82. if($ax.getParentRepeaterFromElementIdExcludeSelf(elementId)) return;
  83. $ax.style.updateElementIdImageStyle(elementId); // When image override exists, fix styling/borders
  84. });
  85. //$ax.style.startSuspendTextAlignment();
  86. // reset all the images only if we're going back to the default view
  87. if(!viewId) {
  88. $axure('*').each(function (diagramObject, elementId) {
  89. if($ax.getParentRepeaterFromElementIdExcludeSelf(elementId)) return;
  90. $ax.placeholderManager.refreshPlaceholder(elementId);
  91. var images = diagramObject.images;
  92. if(diagramObject.type == 'horizontalLine' || diagramObject.type == 'verticalLine') {
  93. var startImg = images['start~'];
  94. _setLineImage(elementId + "_start", startImg);
  95. var endImg = images['end~'];
  96. _setLineImage(elementId + "_end", endImg);
  97. var lineImg = images['line~'];
  98. _setLineImage(elementId + "_line", lineImg);
  99. } else if(diagramObject.type == $ax.constants.CONNECTOR_TYPE) {
  100. _setAdaptiveConnectorImages(elementId, images, '');
  101. } else if(images) {
  102. if (diagramObject.generateCompound) {
  103. if($ax.style.IsWidgetDisabled(elementId)) {
  104. disabledImage = _getImageWithTag(images, 'disabled~');
  105. if(disabledImage) $ax.style.applyImage(elementId, disabledImage, 'disabled');
  106. return;
  107. }
  108. if($ax.style.IsWidgetSelected(elementId)) {
  109. selectedImage = _getImageWithTag(images, 'selected~');
  110. if(selectedImage) $ax.style.applyImage(elementId, selectedImage, 'selected');
  111. return;
  112. }
  113. $ax.style.applyImage(elementId, _getImageWithTag(images, 'normal~'), 'normal');
  114. } else {
  115. if ($ax.style.IsWidgetDisabled(elementId)) {
  116. var disabledImage = _matchImage(elementId, images, [], 'disabled', true);
  117. if (disabledImage) $ax.style.applyImage(elementId, disabledImage, 'disabled');
  118. return;
  119. }
  120. if ($ax.style.IsWidgetSelected(elementId)) {
  121. var selectedImage = _matchImage(elementId, images, [], 'selected', true);
  122. if (selectedImage) $ax.style.applyImage(elementId, selectedImage, 'selected');
  123. return;
  124. }
  125. var normalImage = _matchImage(elementId, images, [], 'normal', true);
  126. $ax.style.applyImage(elementId, normalImage, 'normal');
  127. }
  128. }
  129. //align all text
  130. var child = $jobj(elementId).children('.text');
  131. if(child.length) $ax.style.transformTextWithVerticalAlignment(child[0].id, function() { });
  132. });
  133. // we have to reset visibility if we aren't applying a new view
  134. $ax.visibility.resetLimboAndHiddenToDefaults();
  135. $ax.visibility.clearMovedAndResized();
  136. $ax.repeater.refreshAllRepeaters();
  137. $ax.dynamicPanelManager.updateParentsOfNonDefaultFitPanels();
  138. $ax.dynamicPanelManager.updatePercentPanelCache($ax('*'));
  139. } else {
  140. $ax.visibility.clearLimboAndHidden();
  141. $ax.visibility.clearMovedAndResized();
  142. _applyView(viewId);
  143. $ax.repeater.refreshAllRepeaters();
  144. $ax.dynamicPanelManager.updateAllLayerSizeCaches();
  145. $ax.dynamicPanelManager.updateParentsOfNonDefaultFitPanels();
  146. }
  147. $ax.annotation.updateAllFootnotes();
  148. //$ax.style.resumeSuspendTextAlignment();
  149. $ax.adaptive.triggerEvent('viewChanged', {});
  150. if(_loadFinished) $ax.viewChangePageAndMasters(forceSwitchTo);
  151. };
  152. var _getImageWithTag = function(image, tag) {
  153. var flattened = {};
  154. for (var component in image) {
  155. var componentImage = image[component][tag];
  156. if(componentImage) flattened[component] = componentImage;
  157. }
  158. return flattened;
  159. }
  160. // gets the inheritance chain of a particular view.
  161. var _getAdaptiveIdChain = $ax.adaptive.getAdaptiveIdChain = function(viewId) {
  162. if(!viewId) return [];
  163. var view = _idToView[viewId];
  164. var chain = [];
  165. var current = view;
  166. while(current) {
  167. chain[chain.length] = current.id;
  168. current = _idToView[current.baseViewId];
  169. }
  170. return chain.reverse();
  171. };
  172. var _getMasterAdaptiveIdChain = $ax.adaptive.getMasterAdaptiveIdChain = function (masterId, viewId) {
  173. if (!viewId) return [];
  174. var master = $ax.pageData.masters[masterId];
  175. var masterViews = master.adaptiveViews;
  176. var idToMasterView = {};
  177. if (masterViews && masterViews.length > 0) {
  178. for (var i = 0; i < masterViews.length; i++) {
  179. var view = masterViews[i];
  180. idToMasterView[view.id] = view;
  181. }
  182. }
  183. if (!idToMasterView) return [];
  184. var view = idToMasterView[viewId];
  185. var chain = [];
  186. var current = view;
  187. while (current) {
  188. chain[chain.length] = current.id;
  189. current = idToMasterView[current.baseViewId];
  190. }
  191. return chain.reverse();
  192. };
  193. var _getPageStyle = $ax.adaptive.getPageStyle = function() {
  194. var currentViewId = $ax.adaptive.currentViewId;
  195. var adaptiveChain = _getAdaptiveIdChain(currentViewId);
  196. var currentStyle = $.extend({}, $ax.pageData.page.style);
  197. for(var i = 0; i < adaptiveChain.length; i++) {
  198. var viewId = adaptiveChain[i];
  199. $.extend(currentStyle, $ax.pageData.page.adaptiveStyles[viewId]);
  200. }
  201. return currentStyle;
  202. };
  203. var _setAdaptiveLineImages = function(elementId, images, viewIdChain) {
  204. for(var i = viewIdChain.length - 1; i >= 0; i--) {
  205. var viewId = viewIdChain[i];
  206. var startImg = images['start~' + viewId];
  207. if(startImg) {
  208. _setLineImage(elementId + "_start", startImg);
  209. var endImg = images['end~' + viewId];
  210. _setLineImage(elementId + "_end", endImg);
  211. var lineImg = images['line~' + viewId];
  212. _setLineImage(elementId + "_line", lineImg);
  213. break;
  214. }
  215. }
  216. };
  217. var _setAdaptiveConnectorImages = function (elementId, images, view) {
  218. var conn = $jobj(elementId);
  219. var count = conn.children().length-1; // -1 for rich text panel
  220. for(var i = 0; i < count; i++) {
  221. var img = images['' + i + '~' + view];
  222. $jobj(elementId + '_seg' + i).attr('src', img);
  223. }
  224. };
  225. var _applyView = $ax.adaptive.applyView = function(viewId, query) {
  226. var limboIds = {};
  227. var hiddenIds = {};
  228. var jquery;
  229. if(query) {
  230. jquery = query.jQuery();
  231. jquery = jquery.add(jquery.find('*'));
  232. var jqueryAnn = $ax.annotation.jQueryAnn(query);
  233. jquery = jquery.add(jqueryAnn);
  234. } else {
  235. jquery = $('*').not('#ios-safari-fixed');
  236. query = $ax('*');
  237. }
  238. jquery.addClass(viewId);
  239. var viewIdChain = _getAdaptiveIdChain(viewId);
  240. // this could be made more efficient by computing it only once per object
  241. query.each(function(diagramObject, elementId) {
  242. _applyAdaptiveViewOnObject(diagramObject, elementId, viewIdChain, viewId, limboIds, hiddenIds);
  243. });
  244. $ax.visibility.addLimboAndHiddenIds(limboIds, hiddenIds, query);
  245. //$ax.dynamicPanelManager.updateAllFitPanelsAndLayerSizeCaches();
  246. $ax.dynamicPanelManager.updatePercentPanelCache(query);
  247. };
  248. var _applyAdaptiveViewOnObject = function(diagramObject, elementId, viewIdChain, viewId, limboIds, hiddenIds) {
  249. var adaptiveChain = [];
  250. for(var i = 0; i < viewIdChain.length; i++) {
  251. var viewId = viewIdChain[i];
  252. var viewStyle = diagramObject.adaptiveStyles[viewId];
  253. if(viewStyle) {
  254. adaptiveChain[adaptiveChain.length] = viewStyle;
  255. if (viewStyle.size) $ax.public.fn.convertToSingleImage($jobj(elementId));
  256. }
  257. }
  258. var state = $ax.style.generateState(elementId);
  259. // set the image
  260. var images = diagramObject.images;
  261. if(images) {
  262. if(diagramObject.type == 'horizontalLine' || diagramObject.type == 'verticalLine') {
  263. _setAdaptiveLineImages(elementId, images, viewIdChain);
  264. } else if (diagramObject.type == $ax.constants.CONNECTOR_TYPE) {
  265. _setAdaptiveConnectorImages(elementId, images, viewId);
  266. } else if (diagramObject.generateCompound) {
  267. var compoundUrl = _matchImageCompound(diagramObject, elementId, viewIdChain, state);
  268. if (compoundUrl) $ax.style.applyImage(elementId, compoundUrl, state);
  269. }else {
  270. var imgUrl = _matchImage(elementId, images, viewIdChain, state);
  271. if(imgUrl) $ax.style.applyImage(elementId, imgUrl, state);
  272. }
  273. }
  274. // addaptive override style (not including default style props)
  275. var adaptiveStyle = $ax.style.computeAllOverrides(elementId, undefined, state, viewId);
  276. // this style INCLUDES the object's my style
  277. var compoundStyle = $.extend({}, diagramObject.style, adaptiveStyle);
  278. // if (diagramObject.owner.type == 'Axure:Master' && diagramObject.adaptiveStyles) {
  279. // adaptiveStyle = $ax.style.computeFullStyle(elementId, state, viewId);
  280. // }
  281. if(!diagramObject.isContained) {
  282. $ax.style.setAdaptiveStyle(elementId, adaptiveStyle);
  283. }
  284. var scriptId = $ax.repeater.getScriptIdFromElementId(elementId);
  285. if(compoundStyle.limbo && !diagramObject.isContained) limboIds[scriptId] = true;
  286. // sigh, javascript. we need the === here because undefined means not overriden
  287. if(compoundStyle.visible === false) hiddenIds[scriptId] = true;
  288. };
  289. var _matchImage = function(id, images, viewIdChain, state, doNotProgress) {
  290. var override = $ax.style.getElementImageOverride(id, state);
  291. if(override) return override;
  292. if(!images) return undefined;
  293. let scriptId = $ax.repeater.getScriptIdFromElementId(id);
  294. if(state == 'disabled' && $ax.style.IsWidgetSelected(id) || state == 'selected' && $ax.style.IsWidgetDisabled(id)) {
  295. let diagramObject = $ax.getObjectFromElementId(id);
  296. if(diagramObject && $ax.public.fn.IsSelectionButton(diagramObject.type)) {
  297. var selectedDisabled = $ax.constants.SELECTED_DISABLED;
  298. }
  299. }
  300. // first check all the images for this state
  301. for(let i = viewIdChain.length - 1; i >= 0; i--) {
  302. let viewId = viewIdChain[i];
  303. if(selectedDisabled) {
  304. let img = findImage(images, scriptId, selectedDisabled, viewId)
  305. if(img) return img;
  306. } else {
  307. let img = findImage(images, scriptId, state, viewId);
  308. if (img) return img;
  309. }
  310. }
  311. // check for the default state style
  312. if(selectedDisabled) {
  313. let defaultStateImage = findImage(images, scriptId, selectedDisabled)
  314. if(defaultStateImage) return defaultStateImage;
  315. } else {
  316. let defaultStateImage = findImage(images, scriptId, state);
  317. if (defaultStateImage) return defaultStateImage;
  318. }
  319. if(doNotProgress) return undefined;
  320. state = $ax.style.progessState(state);
  321. if (state) return _matchImage(scriptId, images, viewIdChain, state);
  322. // SHOULD NOT REACH HERE! NORMAL SHOULD ALWAYS CATCH AT THE DEFAULT!
  323. return images['normal~']; // this is the default
  324. };
  325. let findImage = function(images, scriptId, state, viewId) {
  326. if(!images) return undefined;
  327. if(!viewId) viewId = "";
  328. let withScript = scriptId + "~" + state + "~" + viewId;
  329. let img = images[withScript];
  330. if(!img) img = images[state + "~" + viewId];
  331. return img;
  332. }
  333. var _matchImageCompound = function(diagramObject, id, viewIdChain, state) {
  334. var images = [];
  335. for(var i = 0; i < diagramObject.compoundChildren.length; i++) {
  336. var component = diagramObject.compoundChildren[i];
  337. images[component] = _matchImage(id, diagramObject.images[component], viewIdChain, state);
  338. }
  339. return images;
  340. };
  341. $ax.adaptive.getImageForStateAndView = function(id, state) {
  342. var viewIdChain = _getAdaptiveIdChain($ax.adaptive.currentViewId);
  343. var diagramObject = $ax.getObjectFromElementId(id);
  344. if (diagramObject.generateCompound) return _matchImageCompound(diagramObject, id, viewIdChain, state);
  345. else return _matchImage(id, diagramObject.images, viewIdChain, state);
  346. };
  347. var _getAdaptiveView = function(winWidth, winHeight) {
  348. var _isViewOneGreaterThanTwo = function (view1, view2, winHeight) {
  349. if (view1.size.width > view2.size.width) return true;
  350. if (view1.size.width == view2.size.width) {
  351. if (view2.size.height <= winHeight) return view1.size.height > view2.size.height && view1.size.height <= winHeight;
  352. else return view1.size.height < view2.size.height;
  353. }
  354. return false;
  355. };
  356. var _isViewOneLessThanTwo = function(view1, view2) {
  357. var width2 = view2.size.width || 1000000; // artificially large number
  358. var height2 = view2.size.height || 1000000;
  359. var width1 = view1.size.width || 1000000;
  360. var height1 = view1.size.height || 1000000;
  361. return width1 < width2 || (width1 == width2 && height1 < height2);
  362. };
  363. var _isWindowWidthGreaterThanViewWidth = function(view, width) {
  364. return width >= view.size.width;
  365. };
  366. var _isWindowWidthLessThanViewWidth = function(view1, width) {
  367. var viewWidth = view1.size.width || 1000000;
  368. return width <= viewWidth;
  369. };
  370. var greater = undefined;
  371. var less = undefined;
  372. var defaultView = $ax.pageData.defaultAdaptiveView;
  373. if (_isWindowWidthGreaterThanViewWidth(defaultView, winWidth, winHeight)) greater = defaultView;
  374. less = defaultView;
  375. for(var i = 0; i < _enabledViews.length; i++) {
  376. var view = _enabledViews[i];
  377. if(_isWindowWidthGreaterThanViewWidth(view, winWidth, winHeight)) {
  378. if(!greater || _isViewOneGreaterThanTwo(view, greater, winHeight)) greater = view;
  379. }
  380. if(_isWindowWidthLessThanViewWidth(view, winWidth, winHeight)) {
  381. if(!less || _isViewOneLessThanTwo(view, less)) less = view;
  382. }
  383. }
  384. return greater || less;
  385. };
  386. var _isAdaptiveInitialized = function() {
  387. return typeof _idToView != 'undefined';
  388. };
  389. $ax.messageCenter.addMessageListener(function(message, data) {
  390. //If the adaptive plugin hasn't been initialized yet then
  391. //save the view to load so that it can get set when initialize occurs
  392. if (message == 'switchAdaptiveView') {
  393. if (!$axure.utils.isInPlayer()) return;
  394. var href = window.location.href.split('#')[0];
  395. var lastSlash = href.lastIndexOf('/');
  396. href = href.substring(lastSlash + 1);
  397. if(href != data.src) return;
  398. var view = data.view == 'auto' ? undefined : (data.view == 'default' ? '' : data.view);
  399. if(!_isAdaptiveInitialized()) {
  400. _initialViewToLoad = view;
  401. } else _handleLoadViewId(view);
  402. } else if (message == 'setAdaptiveViewForSize') {
  403. if (!$axure.utils.isInPlayer()) return;
  404. _autoIsHandledBySidebar = true;
  405. if(!_isAdaptiveInitialized()) {
  406. _initialViewSizeToLoad = data;
  407. } else _handleSetViewForSize(data.width, data.height);
  408. } else if (message == 'getScale') {
  409. if (!$axure.utils.isInPlayer()) return;
  410. var prevScaleN = data.prevScaleN;
  411. var newScaleN = 1;
  412. var contentOriginOffset = 0;
  413. var $body = $('body');
  414. $body.css('height', '');
  415. if (data.scale != 0) {
  416. var adjustScrollScale = false;
  417. if ($('html').getNiceScroll().length == 0 && !MOBILE_DEVICE) {
  418. //adding nicescroll so width is correct when getting scale
  419. _addNiceScroll($('html'), { emulatetouch: false, horizrailenabled: false });
  420. adjustScrollScale = true;
  421. }
  422. $('html').css('overflow-x', 'hidden');
  423. var bodyWidth = $body.width();
  424. var isCentered = $body.css('position') == 'relative';
  425. // screen width does not adjust on screen rotation for iOS (width is always shorter screen measurement)
  426. var isLandscape = window.orientation != 0 && window.orientation != 180;
  427. var mobileWidth = (IOS ? (isLandscape ? window.screen.height : window.screen.width) : window.screen.width) - data.panelWidthOffset;
  428. var scaleN = newScaleN = (MOBILE_DEVICE ? mobileWidth : $(window).width()) / bodyWidth;
  429. if (data.scale == 2) {
  430. var pageSize = $ax.public.fn.getPageSize();
  431. var hScaleN = (MOBILE_DEVICE ? data.viewportHeight : $(window).height()) / Math.max(1, pageSize.bottom);
  432. if (hScaleN < scaleN) {
  433. scaleN = newScaleN = hScaleN;
  434. }
  435. if (isCentered) contentOriginOffset = scaleN * (bodyWidth / 2);
  436. }
  437. if ((SAFARI && IOS) || SHARE_APP) {
  438. var pageSize = $ax.public.fn.getPageSize();
  439. $body.first().css('height', pageSize.bottom + 'px');
  440. } //else $body.css('height', $body.height() + 'px');
  441. if (adjustScrollScale) {
  442. _removeNiceScroll($('html'));
  443. _addNiceScroll($('html'), { emulatetouch: false, horizrailenabled: false, cursorwidth: Math.ceil(6 / newScaleN) + 'px', cursorborder: 1 / newScaleN + 'px solid #fff', cursorborderradius: 5 / newScaleN + 'px' });
  444. }
  445. }
  446. var contentScale = {
  447. scaleN: newScaleN,
  448. prevScaleN: prevScaleN,
  449. contentOriginOffset: contentOriginOffset,
  450. clipToView: data.clipToView,
  451. viewportHeight: data.viewportHeight,
  452. viewportWidth: data.viewportWidth,
  453. panelWidthOffset: data.panelWidthOffset,
  454. scale: data.scale
  455. };
  456. $axure.messageCenter.postMessage('setContentScale', contentScale);
  457. } else if (message == 'setDeviceMode') {
  458. if (!$axure.utils.isInPlayer()) return;
  459. _isDeviceMode = data.device;
  460. if (data.device) {
  461. // FIXES firefox cursor not staying outside initial device frame border
  462. // SAFARI needs entire content height so that trackpad can be disabled
  463. //if (FIREFOX || (SAFARI && !IOS)) {
  464. // var pageSize = $ax.public.fn.getPageSize();
  465. // $('html').css('height', pageSize.bottom + 'px');
  466. //}
  467. _removeNiceScroll($('html'), true);
  468. if (!MOBILE_DEVICE) {
  469. _addNiceScroll($('html'), { emulatetouch: true, horizrailenabled: false }, true);
  470. $('html').addClass('mobileFrameCursor');
  471. $('html').css('cursor', 'url(resources/css/images/touch.cur), auto');
  472. $('html').css('cursor', 'url(resources/css/images/touch.svg) 32 32, auto');
  473. $('html').css('overflow-x', 'hidden');
  474. if (IE) {
  475. document.addEventListener("click", function () {
  476. // IE still sometimes wants an argument here
  477. this.activeElement.releasePointerCapture();
  478. }, false);
  479. }
  480. if ($axure.browser.isEdge) {
  481. document.addEventListener("pointerdown", function (e) {
  482. this.activeElement.releasePointerCapture(e.pointerId);
  483. }, false);
  484. }
  485. $ax.dynamicPanelManager.initMobileScroll();
  486. }
  487. // Gives horizontal scroll to android in 100% (handled outside of iframe)
  488. $('html').css('overflow-x', 'hidden');
  489. $('body').css('margin', '0px');
  490. $(function () { _setHorizontalScroll(false); });
  491. } else {
  492. _removeNiceScroll($('html'), true);
  493. $('html').css('overflow-x', '');
  494. $('html').css('cursor', '');
  495. //$('html').removeAttr('style');
  496. $('body').css('margin', '');
  497. $('html').removeClass('mobileFrameCursor');
  498. $(function () { _setHorizontalScroll(!data.scaleToWidth); });
  499. $ax.dynamicPanelManager.initMobileScroll();
  500. }
  501. }
  502. });
  503. var _isDeviceMode = false;
  504. $ax.adaptive.isDeviceMode = function () {
  505. return _isDeviceMode;
  506. }
  507. var _isHtmlQuery = function ($container) { return $container.length > 0 && $container[0] == $('html')[0]; }
  508. var _removeNiceScroll = $ax.adaptive.removeNiceScroll = function ($container, blockResetScroll) {
  509. if (!blockResetScroll) {
  510. $container.scrollLeft(0);
  511. $container.scrollTop(0);
  512. }
  513. var nS = $container.getNiceScroll();
  514. var emulateTouch = nS.length > 0 && nS[0].opt.emulateTouch;
  515. nS.remove();
  516. //clean up nicescroll css
  517. if (IE) $container.css({ '-ms-overflow-y': '', 'overflow-y': '', '-ms-overflow-style': '', '-ms-touch-action': '' });
  518. if (!emulateTouch) return;
  519. if (_isHtmlQuery($container)) {
  520. $('#scrollContainer').remove();
  521. $('#base').off('mouseleave.ax');
  522. } else {
  523. $container.off('mouseleave.ax');
  524. }
  525. }
  526. var _addNiceScrollExitDetector = function ($container) {
  527. if (_isHtmlQuery($container)) {
  528. // add a fixed div the size of the frame that will not move as we scroll like html,body,#base,children
  529. // so we are able to detect when the mouse leaves that frame area if there is no existing DOM element
  530. var $scrollContainer = $("<div id='scrollContainer'></div>");
  531. var $body = $('body');
  532. $scrollContainer.css({
  533. 'position': 'fixed',
  534. 'width': $body.width(),
  535. 'height': $body.height()
  536. });
  537. // we want #base div to handle the event so that it bubbles up from the scrollContainer div which
  538. // handles the bounds of the frame in case there was no previously exisiting child to bubble up the
  539. // event or if the user has clicked on an existing child node to start the emulated touch scroll
  540. var $base = $('#base');
  541. $base.on('mouseleave.ax', function (e) {
  542. var nS = $container.getNiceScroll();
  543. for (var i = 0; i < nS.length; ++i)
  544. nS[i].ontouchend(e);
  545. });
  546. // need to prepend so it is first child in DOM and doesn't block mouse events to other children which
  547. // would make them unable to scroll
  548. $base.prepend($scrollContainer);
  549. } else {
  550. $container.on('mouseleave.ax', function (e) {
  551. var nS = $container.getNiceScroll();
  552. for (var i = 0; i < nS.length; ++i)
  553. nS[i].ontouchend(e);
  554. });
  555. }
  556. }
  557. var _addNiceScroll = $ax.adaptive.addNiceScroll = function ($container, options, blockResetScroll) {
  558. if (!blockResetScroll) {
  559. $container.scrollLeft(0);
  560. $container.scrollTop(0);
  561. }
  562. $container.niceScroll(options);
  563. // RP-581 add handling to stop scroll on mouse leave if enable cursor-drag scrolling like touch devices in desktop computer
  564. if (options.emulatetouch) _addNiceScrollExitDetector($container);
  565. //clean up nicescroll css so child scroll containers show scrollbars in IE
  566. if (IE) $container.css({ '-ms-overflow-y': '', '-ms-overflow-style': '' });
  567. if(IOS) $container.css({ 'overflow-y': ''});
  568. }
  569. //given the element, find the container that's using nice scroll (including the element itself)
  570. $ax.adaptive.getNiceScrollContainer = function(element) {
  571. var parent = element;
  572. while(parent) {
  573. if($(parent).getNiceScroll().length > 0) return parent;
  574. parent = parent.parentElement;
  575. }
  576. return undefined;
  577. }
  578. $ax.adaptive.updateMobileScrollOnBody = function () {
  579. var niceScroll = $('html').getNiceScroll();
  580. if (niceScroll.length == 0) return;
  581. niceScroll.resize();
  582. }
  583. var _setTrackpadHorizontalScroll = function (active) {
  584. var preventScroll = function (e) {
  585. if (Math.abs(e.wheelDeltaX) != 0) {
  586. e.preventDefault();
  587. }
  588. }
  589. if (!active) {
  590. document.body.addEventListener("mousewheel", preventScroll, { passive: false });
  591. document.getElementById('html').addEventListener("mousewheel", preventScroll, { passive: false });
  592. } else {
  593. document.body.removeEventListener("mousewheel", preventScroll, { passive: false });
  594. document.getElementById('html').removeEventListener("mousewheel", preventScroll, { passive: false });
  595. }
  596. }
  597. var _setHorizontalScroll = function (active) {
  598. var $body = $(document);
  599. if (!active) {
  600. $body.bind('scroll', function () {
  601. if ($body.scrollLeft() !== 0) {
  602. $body.scrollLeft(0);
  603. }
  604. });
  605. } else {
  606. $body.unbind('scroll');
  607. }
  608. }
  609. $ax.adaptive.setAdaptiveView = function(view) {
  610. var viewIdForSitemapToUnderstand = view == 'auto' ? undefined : (view == 'default' ? '' : view);
  611. if(!_isAdaptiveInitialized()) {
  612. _initialViewToLoad = viewIdForSitemapToUnderstand;
  613. } else _handleLoadViewId(viewIdForSitemapToUnderstand);
  614. };
  615. $ax.adaptive.initialize = function() {
  616. _views = $ax.pageData.adaptiveViews;
  617. _idToView = {};
  618. var useViews = $ax.document.configuration.useViews;
  619. if(_views && _views.length > 0) {
  620. for(var i = 0; i < _views.length; i++) {
  621. var view = _views[i];
  622. _idToView[view.id] = view;
  623. if(useViews) _enabledViews[_enabledViews.length] = view;
  624. }
  625. if(_autoIsHandledBySidebar && _initialViewSizeToLoad) _handleSetViewForSize(_initialViewSizeToLoad.width, _initialViewSizeToLoad.height);
  626. else _handleLoadViewId(_initialViewToLoad);
  627. }
  628. $axure.resize(function(e) {
  629. _handleResize();
  630. $ax.postResize(e); //window resize fires after view changed
  631. });
  632. };
  633. var _handleLoadViewId = function (loadViewId, forceSwitchTo) {
  634. if(typeof loadViewId != 'undefined') {
  635. _setAuto(false);
  636. _switchView(loadViewId != 'default' ? loadViewId : '', forceSwitchTo);
  637. } else {
  638. _setAuto(true);
  639. _handleResize(forceSwitchTo);
  640. }
  641. };
  642. var _handleSetViewForSize = function (width, height) {
  643. var toView = _getAdaptiveView(width, height);
  644. var toViewId = toView && toView.id;
  645. _switchView(toViewId, "auto");
  646. };
  647. $ax.adaptive.getSketchKey = function() {
  648. return $ax.pageData.sketchKeys[$ax.adaptive.currentViewId || ''];
  649. }
  650. });