You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

403 lines
18 KiB

3 years ago
  1. $axure = function(query) {
  2. return $axure.query(query);
  3. };
  4. // ******* AxQuery and Page metadata ******** //
  5. (function() {
  6. var $ax = function() {
  7. var returnVal = $axure.apply(this, arguments);
  8. var axFn = $ax.fn;
  9. for (var key in axFn) {
  10. returnVal[key] = axFn[key];
  11. }
  12. return returnVal;
  13. };
  14. $ax.public = $axure;
  15. $ax.fn = {};
  16. $axure.internal = function(initFunction) {
  17. //Attach messagecenter to $ax object so that it can be used in viewer.js, etc in internal scope
  18. if(!$ax.messageCenter) $ax.messageCenter = $axure.messageCenter;
  19. return initFunction($ax);
  20. };
  21. var _lastFiredResize = 0;
  22. var _resizeFunctions = [];
  23. var _lastTimeout;
  24. var _fireResize = function() {
  25. if (_lastTimeout) window.clearTimeout(_lastTimeout);
  26. _lastTimeout = undefined;
  27. _lastFiredResize = new Date().getTime();
  28. for(var i = 0; i < _resizeFunctions.length; i++) _resizeFunctions[i]();
  29. };
  30. $axure.resize = function(fn) {
  31. if(fn) _resizeFunctions[_resizeFunctions.length] = fn;
  32. else $(window).resize();
  33. };
  34. $(window).resize(function() {
  35. var THRESHOLD = 50;
  36. _updateWindowInfo();
  37. var now = new Date().getTime();
  38. if(now - _lastFiredResize > THRESHOLD) {
  39. _fireResize();
  40. } else if(!_lastTimeout) {
  41. _lastTimeout = window.setTimeout(_fireResize, THRESHOLD);
  42. }
  43. });
  44. $(window).scroll(function () {
  45. _updateWindowInfo();
  46. });
  47. var _windowInfo;
  48. var _updateWindowInfo = $axure.updateWindowInfo = function () {
  49. var win = {};
  50. var jWin = $(window);
  51. var scrollWin = $('#ios-safari-html').length > 0 ? $('#ios-safari-html') : jWin;
  52. win.width = jWin.width();
  53. win.height = jWin.height();
  54. win.scrollx = scrollWin.scrollLeft();
  55. win.scrolly = scrollWin.scrollTop();
  56. _windowInfo = win;
  57. };
  58. $ax.getWindowInfo = function () {
  59. if(!_windowInfo) _updateWindowInfo();
  60. return _windowInfo;
  61. };
  62. window.$obj = function(id) {
  63. return $ax.getObjectFromElementId(id);
  64. };
  65. window.$id = function(obj) {
  66. return obj.scriptIds[0];
  67. };
  68. window.$jobj = function(id) {
  69. return $(document.getElementById(id));
  70. };
  71. window.$jobjAll = function(id) {
  72. return $addAll($jobj(id), id);
  73. };
  74. window.$addAll = function(jobj, id) {
  75. return jobj.add($jobj(id + '_ann')).add($jobj(id + '_ref'));
  76. };
  77. $ax.INPUT = function(id) { return id + "_input"; };
  78. $ax.IsImageFocusable = function (type) { return $ax.public.fn.IsImageBox(type) || $ax.public.fn.IsVector(type) || $ax.public.fn.IsTreeNodeObject(type) || $ax.public.fn.IsTableCell(type); };
  79. $ax.IsTreeNodeObject = function (type) { return $ax.public.fn.IsTreeNodeObject(type); };
  80. $ax.IsSelectionButton = function (type) { return $ax.public.fn.IsCheckBox(type) || $ax.public.fn.IsRadioButton(type); };
  81. var _fn = {};
  82. $axure.fn = _fn;
  83. $axure.fn.jQuery = function() {
  84. var elements = this.getElements();
  85. return $(elements);
  86. };
  87. $axure.fn.$ = $axure.fn.jQuery;
  88. var _query = function(query, queryArg) {
  89. var returnVal = {};
  90. var _axQueryObject = returnVal.query = { };
  91. _axQueryObject.filterFunctions = [];
  92. if (query == '*') {
  93. _axQueryObject.filterFunctions[0] = function() { return true; };
  94. } else if (typeof(query) === 'function') {
  95. _axQueryObject.filterFunctions[0] = query;
  96. } else {
  97. var firstString = $.trim(query.toString());
  98. if (firstString.charAt(0) == '@') {
  99. _axQueryObject.filterFunctions[0] = function(diagramObject) {
  100. return diagramObject.label == firstString.substring(1);
  101. };
  102. } else if (firstString.charAt(0) == '#') {
  103. _axQueryObject.elementId = firstString.substring(1);
  104. } else {
  105. if (firstString == 'label') {
  106. _axQueryObject.filterFunctions[0] = function(diagramObject) {
  107. return queryArg instanceof Array && queryArg.indexOf(diagramObject.label) > 0 ||
  108. queryArg instanceof RegExp && queryArg.test(diagramObject.label) ||
  109. diagramObject.label == queryArg;
  110. };
  111. } else if(firstString == 'elementId') {
  112. _axQueryObject.filterFunctions[0] = function(diagramObject, elementId) {
  113. return queryArg instanceof Array && queryArg.indexOf(elementId) > 0 ||
  114. elementId == queryArg;
  115. };
  116. }
  117. }
  118. }
  119. var axureFn = $axure.fn;
  120. for (var key in axureFn) {
  121. returnVal[key] = axureFn[key];
  122. }
  123. return returnVal;
  124. };
  125. $axure.query = _query;
  126. var _getFilterFnFromQuery = function(query) {
  127. var filter = function(diagramObject, elementId) {
  128. // Non diagram objects are allowed to be queryed, such as text inputs.
  129. if (diagramObject && !$ax.public.fn.IsReferenceDiagramObject(diagramObject.type) && !document.getElementById(elementId)) return false;
  130. var retVal = true;
  131. for(var i = 0; i < query.filterFunctions.length && retVal; i++) {
  132. retVal = query.filterFunctions[i](diagramObject, elementId);
  133. }
  134. return retVal;
  135. };
  136. return filter;
  137. };
  138. $ax.public.fn.filter = function(query, queryArg) {
  139. var returnVal = _query(query, queryArg);
  140. if(this.query.elementId) returnVal.query.elementId = this.query.elementId;
  141. //If there is already a function, offset by 1 when copying other functions over.
  142. var offset = returnVal.query.filterFunctions[0] ? 1 : 0;
  143. //Copy all functions over to new array.
  144. for(var i = 0; i < this.query.filterFunctions.length; i++) returnVal.query.filterFunctions[i+offset] = this.query.filterFunctions[i];
  145. //Functions are in reverse order now
  146. returnVal.query.filterFunctions.reverse();
  147. return returnVal;
  148. };
  149. $ax.public.fn.each = function(fn) {
  150. var filter = _getFilterFnFromQuery(this.query);
  151. var elementIds = this.query.elementId ? [this.query.elementId] : $ax.getAllElementIds();
  152. for (var i = 0; i < elementIds.length; i++) {
  153. var elementId = elementIds[i];
  154. var diagramObject = $ax.getObjectFromElementId(elementId);
  155. if (filter(diagramObject, elementId)) {
  156. fn.apply(diagramObject, [diagramObject, elementId]);
  157. }
  158. }
  159. };
  160. $ax.public.fn.getElements = function() {
  161. var elements = [];
  162. this.each(function(dObj, elementId) {
  163. var elementById = document.getElementById(elementId);
  164. if(elementById) elements[elements.length] = elementById;
  165. });
  166. return elements;
  167. };
  168. $ax.public.fn.getElementIds = function() {
  169. var elementIds = [];
  170. this.each(function(dObj, elementId) { elementIds[elementIds.length] = elementId; });
  171. return elementIds;
  172. };
  173. // Deep means to keep getting parents parent until at the root parent. Parent is then an array instead of an id.
  174. // Filter options: layer, rdo, repeater, item, dynamicPanel, state
  175. $ax.public.fn.getParents = function (deep, filter) {
  176. if(filter == '*') filter = ['layer', 'rdo', 'repeater', 'item', 'dynamicPanel', 'state'];
  177. var elementIds = this.getElementIds();
  178. var parentIds = [];
  179. var getParent = function(elementId) {
  180. var containerIndex = elementId.indexOf('_container');
  181. if(containerIndex !== -1) elementId = elementId.substring(0, containerIndex);
  182. if(elementId.indexOf('_text') !== -1) elementId = $ax.GetShapeIdFromText(elementId);
  183. // Check repeater item before layer, because repeater item detects it's parent layer, but wants to go directly to it's repeater first.
  184. // if repeater item, then just return repeater
  185. var scriptId = $ax.repeater.getScriptIdFromElementId(elementId);
  186. var itemNum = $ax.repeater.getItemIdFromElementId(elementId);
  187. var parentRepeater = $ax.getParentRepeaterFromScriptId(scriptId);
  188. // scriptId is item or repeater itself
  189. if (parentRepeater == scriptId) {
  190. // If you are repeater item, return your repeater
  191. if (itemNum) return filter.indexOf('repeater') != -1 ? scriptId : getParent(scriptId);
  192. // Otherwise you are actually at repeater, clean parentRepeater, or else you loop
  193. parentRepeater = undefined;
  194. }
  195. // Layer only references it if it is a direct layer to it
  196. var parent = $ax.getLayerParentFromElementId(elementId);
  197. // If layer is allowed we found parent, otherwise ignore and keep climbing
  198. if (parent) return filter.indexOf('layer') != -1 ? parent : getParent(parent);
  199. // if state, then just return panel
  200. if(scriptId.indexOf('_state') != -1) {
  201. var panelId = $ax.repeater.createElementId(scriptId.split('_')[0], itemNum);
  202. // If dynamic panel is allowed we found parent, otherwise ignore and keep climbing
  203. return filter.indexOf('dynamicPanel') != -1 ? panelId : getParent(panelId);
  204. }
  205. var parentType = '';
  206. if(parentRepeater) {
  207. parentType = 'item';
  208. parent = $ax.repeater.createElementId(parentRepeater, itemNum);
  209. }
  210. var masterPath = $ax.getPathFromScriptId($ax.repeater.getScriptIdFromElementId(elementId));
  211. masterPath.pop();
  212. if(masterPath.length > 0) {
  213. var masterId = $ax.getElementIdFromPath(masterPath, { itemNum: itemNum }, true);
  214. if(!masterId) return undefined;
  215. var masterRepeater = $ax.getParentRepeaterFromElementId($ax.repeater.getScriptIdFromElementId(masterId));
  216. if(!parentRepeater || masterRepeater) {
  217. parentType = 'rdo';
  218. parent = masterId;
  219. }
  220. }
  221. var obj = $obj(elementId);
  222. var parentDynamicPanel = obj.parentDynamicPanel;
  223. if(parentDynamicPanel) {
  224. // Make sure the parent if not parentRepeater, or dynamic panel is also in that repeater
  225. // If there is a parent master, the dynamic panel must be in it, otherwise parentDynamicPanel would be undefined.
  226. var panelPath = masterPath;
  227. panelPath[panelPath.length] = parentDynamicPanel;
  228. panelId = $ax.getElementIdFromPath(panelPath, { itemNum: itemNum }, true);
  229. if(!panelId) return undefined;
  230. var panelRepeater = $ax.getParentRepeaterFromElementId(panelId);
  231. if(!parentRepeater || panelRepeater) {
  232. parentType = 'state';
  233. parent = panelId + '_state' + obj.panelIndex;
  234. }
  235. }
  236. // If at top or parent type is desired, then return parent, otherwise keep climbing
  237. return !parent || filter.indexOf(parentType) != -1 ? parent : getParent(parent);
  238. };
  239. for(var i = 0; i < elementIds.length; i++) {
  240. var parent = getParent(elementIds[i]);
  241. if(deep) {
  242. var parents = [];
  243. while(parent) {
  244. parents[parents.length] = parent;
  245. // If id is not a valid object, you are either repeater item or dynamic panel state
  246. //if(!$obj(parent)) parent = $ax.visibility.getWidgetFromContainer($jobj(parent).parent().attr('id'));
  247. parent = getParent(parent);
  248. }
  249. parent = parents;
  250. }
  251. parentIds[parentIds.length] = parent;
  252. }
  253. return parentIds;
  254. };
  255. // Get the path to the child, where non leaf nodes can be masters, layers, dynamic panels, and repeaters.
  256. $ax.public.fn.getChildren = function(deep, ignoreUnplaced) { // ignoreUnplaced should probably be the default, but when that is done a full audit of usages should be done
  257. var elementIds = this.getElementIds();
  258. var children = [];
  259. var getChildren = function (elementId) {
  260. var obj = $obj(elementId);
  261. //if(!obj) return undefined;
  262. var isRepeater = obj && obj.type == $ax.constants.REPEATER_TYPE;
  263. if (isRepeater && $ax.repeater.getScriptIdFromElementId(elementId) != elementId) {
  264. //prevent repeater items from being marked as isRepeater
  265. //TODO: evaluate changing the naming convention to be more like panel states which don't seem to have this problem
  266. obj = undefined;
  267. isRepeater = false;
  268. }
  269. var isDynamicPanel = obj && obj.type == $ax.constants.DYNAMIC_PANEL_TYPE;
  270. //var isLayer = obj.type == $ax.constants.LAYER_TYPE;
  271. //var isMaster = obj.type == $ax.constants.MASTER_TYPE || obj.type == $ax.constants.REFERENCE_DIAGRAM_OBJECT_TYPE;
  272. var isMenu = obj && obj.type == $ax.constants.MENU_OBJECT_TYPE;
  273. var isTreeNode = obj && obj.type == $ax.constants.TREE_NODE_OBJECT_TYPE;
  274. //var isTable = obj.type == $ax.constants.TABLE_TYPE;
  275. //var isCompoundVector = obj.type == $ax.constants.VECTOR_SHAPE_TYPE && obj.generateCompound;
  276. //if (isRepeater || isDynamicPanel || isLayer || isMaster || isMenu || isTreeNode || isTable) {// || isCompoundVector) {
  277. // Find parent that children should be pulled from. Default is just the elementId query (used by table and master)
  278. var parent = $jobj(elementId);
  279. if(isRepeater) {
  280. parent = $();
  281. var itemIds = $ax.getItemIdsForRepeater(elementId);
  282. for(var itemIndex = 0; itemIndex < itemIds.length; itemIndex++) parent = parent.add($jobj($ax.repeater.createElementId(elementId, itemIds[itemIndex])));
  283. } else if(isDynamicPanel) {
  284. // Really only need to do active state probably...
  285. parent = $jobj(elementId).children();
  286. // Get through all containers
  287. while ($(parent[0]).attr('id').indexOf('container') != -1) parent = parent.children();
  288. // Now at states, but want states content
  289. parent = parent.children();
  290. } else if(isTreeNode) parent = $jobj($ax.repeater.applySuffixToElementId(elementId, '_children'));
  291. // Menu doesn't want all children, only tables and menus, so it must be handled specially
  292. var children = isMenu ? parent.children('.ax_table').add(parent.children('.ax_menu')) : parent.children();
  293. children = $ax.visibility.getRealChildren(_fixForBasicLinks(children));
  294. // For tree nodes you want the the button shape contained by the elementQuery too
  295. if(isTreeNode) {
  296. var treeNodeChildren = $jobj(elementId).children();
  297. for(var treeNodeIndex = 0; treeNodeIndex < treeNodeChildren.length; treeNodeIndex++) {
  298. var treeNodeChild = $(treeNodeChildren[treeNodeIndex]);
  299. var childObj = $obj(treeNodeChild.attr('id'));
  300. if (childObj && $ax.public.fn.IsVector(childObj.type)) children = children.add(treeNodeChild);
  301. }
  302. }
  303. var childrenIds = [];
  304. for(var childIndex = 0; childIndex < children.length; childIndex++) {
  305. var childObj = $(children[childIndex]);
  306. var id = childObj.attr('id');
  307. if(typeof(id) == 'undefined' && childObj.is('a')) id = $(childObj.children()[0]).attr('id');
  308. // Ignore annotations and any other children that are not elements
  309. if (id.split('_').length > 1) continue;
  310. // Ignore Unplaced
  311. if(ignoreUnplaced && $ax.visibility.isScriptIdLimbo($ax.repeater.getScriptIdFromElementId(id))) continue;
  312. childrenIds.push(id);
  313. }
  314. if(deep) {
  315. var childObjs = [];
  316. for(var i = 0; i < childrenIds.length; i++) {
  317. var childId = childrenIds[i];
  318. childObjs[i] = { id: childId, children: getChildren(childId) };
  319. }
  320. childrenIds = childObjs;
  321. }
  322. return childrenIds;
  323. //}
  324. //return undefined;
  325. };
  326. for(var i = 0; i < elementIds.length; i++) {
  327. var elementId = elementIds[i];
  328. //if the state is passed in, look for children in the content element
  329. if (elementId.indexOf('_state') > -1 && elementId.indexOf('_content') < 0) elementId = elementId + '_content';
  330. children[children.length] = { id: elementId, children: getChildren(elementId)};
  331. }
  332. return children;
  333. };
  334. var _fixForBasicLinks = function(query) {
  335. var hasBasicLinks = query.filter('.basiclink').length > 0;
  336. if(!hasBasicLinks) return query;
  337. var retval = $();
  338. for(var i = 0; i < query.length; i++) {
  339. var child = $(query[i]);
  340. if(child.hasClass('basiclink')) retval = retval.add(child.children());
  341. else retval = retval.add(child);
  342. }
  343. return retval;
  344. };
  345. })();