axQuery.js.orig 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  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. var now = new Date().getTime();
  37. if(now - _lastFiredResize > THRESHOLD) {
  38. _fireResize();
  39. } else if(!_lastTimeout) {
  40. _lastTimeout = window.setTimeout(_fireResize, THRESHOLD);
  41. }
  42. });
  43. window.$obj = function(id) {
  44. return $ax.getObjectFromElementId(id);
  45. };
  46. window.$id = function(obj) {
  47. return obj.scriptIds[0];
  48. };
  49. window.$jobj = function(id) {
  50. return $('#' + id);
  51. };
  52. $ax.INPUT = function(id) { return id + "_input"; };
  53. $ax.IsButtonShape = function(type) { return type == 'buttonShape'; };
  54. $ax.IsTreeNodeObject = function(type) { return type == 'treeNodeObject'; };
  55. $ax.IsSelectionButton = function(type) { return type == 'checkbox' || type == 'radioButton'; };
  56. var _fn = {};
  57. $axure.fn = _fn;
  58. $axure.fn.jQuery = function() {
  59. var elementIds = this.getElementIds();
  60. var elementIdSelectors = jQuery.map(elementIds, function(elementId) { return '#' + elementId; });
  61. var jQuerySelectorText = (elementIds.length > 0) ? elementIdSelectors.join(', ') : '';
  62. return $(jQuerySelectorText);
  63. };
  64. $axure.fn.$ = $axure.fn.jQuery;
  65. var _query = function(query, queryArg) {
  66. var returnVal = {};
  67. var _axQueryObject = returnVal.query = { };
  68. _axQueryObject.filterFunctions = [];
  69. if (query == '*') {
  70. _axQueryObject.filterFunctions[0] = function() { return true; };
  71. } else if (typeof(query) === 'function') {
  72. _axQueryObject.filterFunctions[0] = query;
  73. } else {
  74. var firstString = $.trim(query.toString());
  75. if (firstString.charAt(0) == '@') {
  76. _axQueryObject.filterFunctions[0] = function(diagramObject) {
  77. return diagramObject.label == firstString.substring(1);
  78. };
  79. } else if (firstString.charAt(0) == '#') {
  80. _axQueryObject.elementId = firstString.substring(1);
  81. } else {
  82. if (firstString == 'label') {
  83. _axQueryObject.filterFunctions[0] = function(diagramObject) {
  84. return queryArg instanceof Array && queryArg.indexOf(diagramObject.label) > 0 ||
  85. queryArg instanceof RegExp && queryArg.test(diagramObject.label) ||
  86. diagramObject.label == queryArg;
  87. };
  88. } else if(firstString == 'elementId') {
  89. _axQueryObject.filterFunctions[0] = function(diagramObject, elementId) {
  90. return queryArg instanceof Array && queryArg.indexOf(elementId) > 0 ||
  91. elementId == queryArg;
  92. };
  93. }
  94. }
  95. }
  96. var axureFn = $axure.fn;
  97. for (var key in axureFn) {
  98. returnVal[key] = axureFn[key];
  99. }
  100. return returnVal;
  101. };
  102. $axure.query = _query;
  103. var _getFilterFnFromQuery = function(query) {
  104. var filter = function(diagramObject, elementId) {
  105. // Non diagram objects are allowed to be queryed, such as text inputs.
  106. if(diagramObject && diagramObject.type != 'referenceDiagramObject' && $jobj(elementId).length == 0) return false;
  107. var retVal = true;
  108. for(var i = 0; i < query.filterFunctions.length && retVal; i++) {
  109. retVal = query.filterFunctions[i](diagramObject, elementId);
  110. }
  111. return retVal;
  112. };
  113. return filter;
  114. };
  115. $ax.public.fn.filter = function(query, queryArg) {
  116. var returnVal = _query(query, queryArg);
  117. if(this.query.elementId) returnVal.query.elementId = this.query.elementId;
  118. //If there is already a function, offset by 1 when copying other functions over.
  119. var offset = returnVal.query.filterFunctions[0] ? 1 : 0;
  120. //Copy all functions over to new array.
  121. for(var i = 0; i < this.query.filterFunctions.length; i++) returnVal.query.filterFunctions[i+offset] = this.query.filterFunctions[i];
  122. //Functions are in reverse order now
  123. returnVal.query.filterFunctions.reverse();
  124. return returnVal;
  125. };
  126. $ax.public.fn.each = function(fn) {
  127. var filter = _getFilterFnFromQuery(this.query);
  128. var elementIds = this.query.elementId ? [this.query.elementId] : $ax.getAllElementIds();
  129. for (var i = 0; i < elementIds.length; i++) {
  130. var elementId = elementIds[i];
  131. var diagramObject = $ax.getObjectFromElementId(elementId);
  132. if (filter(diagramObject, elementId)) {
  133. fn.apply(diagramObject, [diagramObject, elementId]);
  134. }
  135. }
  136. };
  137. $ax.public.fn.getElementIds = function() {
  138. var elementIds = [];
  139. this.each(function(dObj, elementId) { elementIds[elementIds.length] = elementId; });
  140. return elementIds;
  141. };
  142. // Deep means to keep getting parents parent until at the root parent. Parent is then an array instead of an id.
  143. $ax.public.fn.getParents = function(deep) {
  144. var elementIds = this.getElementIds();
  145. var parentIds = [];
  146. var getParent = function(elementId) {
  147. var parent = undefined;
  148. var scriptId = $ax.repeater.getScriptIdFromElementId(elementId);
  149. var itemNum = $ax.repeater.getItemIdFromElementId(elementId);
  150. var parentRepeater = $ax.getParentRepeaterFromScriptId(scriptId);
  151. // Repeater references self, constantly if it is treated as its own parent in this case infinite recursion occurs.
  152. if(parentRepeater == scriptId) parentRepeater = undefined;
  153. if(parentRepeater) {
  154. parentRepeater = $ax.repeater.createElementId(parentRepeater, itemNum);
  155. parent = parentRepeater;
  156. }
  157. var masterPath = $ax.getPathFromScriptId($ax.repeater.getScriptIdFromElementId(elementId));
  158. masterPath.pop();
  159. if(masterPath.length > 0) {
  160. var masterId = $ax.getElementIdFromPath(masterPath, {itemNum: itemNum});
  161. var masterRepeater = $ax.getParentRepeaterFromScriptId($ax.repeater.getScriptIdFromElementId(masterId));
  162. if(!parentRepeater || masterRepeater) parent = masterId;
  163. }
  164. var parentDynamicPanel = $obj(elementId).parentDynamicPanel;
  165. if(parentDynamicPanel) {
  166. // Make sure the parent if not parentRepeater, or dynamic panel is also in that repeater
  167. // If there is a parent master, the dynamic panel must be in it, otherwise parentDynamicPanel would be undefined.
  168. var panelPath = masterPath;
  169. panelPath[panelPath.length] = parentDynamicPanel;
  170. var panelId = $ax.getElementIdFromPath(panelPath, {itemNum: itemNum});
  171. var panelRepeater = $ax.getParentRepeaterFromScriptId($ax.repeater.getScriptIdFromElementId(panelId));
  172. if(!parentRepeater || panelRepeater) {
  173. var states = $obj(panelId).diagrams.length;
  174. for(var i = 0; i < states; i++) {
  175. var stateId = panelId + '_state' + i;
  176. if($jobj(stateId + '_content').find('#' + elementId).length) return stateId;
  177. }
  178. }
  179. }
  180. return parent;
  181. };
  182. for(var i = 0; i < elementIds.length; i++) {
  183. var parent = getParent(elementIds[i]);
  184. if(deep) {
  185. var parents = [];
  186. while(parent) {
  187. parents[parents.length] = parent;
  188. // If id is not a valid object, you are either repeater item or dynamic panel state.
  189. // Either way, get parents id in that case.
  190. if(!$obj(parent)) parent = $jobj(parent).parent().attr('id');
  191. parent = getParent(parent);
  192. }
  193. parent = parents;
  194. }
  195. parentIds[parentIds.length] = parent;
  196. }
  197. return parentIds;
  198. };
  199. // Get the path to the child, where non leaf nodes can be masters, dynamic panels, and repeaters.
  200. $ax.public.fn.getChildren = function(deep) {
  201. var elementIds = this.getElementIds();
  202. var children = [];
  203. var getChildren = function(elementId) {
  204. var obj = $obj(elementId);
  205. if(!obj) return undefined;
  206. var isRepeater = obj.type == 'repeater';
  207. var isDynamicPanel = obj.type == 'dynamicPanel';
  208. var isMaster = obj.type == 'master';
  209. var isMenu = obj.type == 'menuObject';
  210. var isTreeNode = obj.type == 'treeNodeObject';
  211. var isTable = obj.type == 'table';
  212. if(isRepeater || isDynamicPanel || isMaster || isMenu || isTreeNode || isTable) {
  213. // Find parent that children should be pulled from. Default is just the elementId query (used by table and master)
  214. var parent = $jobj(elementId);
  215. if(isRepeater) {
  216. parent = $();
  217. var itemIds = $ax.getItemIdsForRepeater(elementId);
  218. for(var itemIndex = 0; itemIndex < itemIds.length; itemIndex++) parent = parent.add($jobj($ax.repeater.createElementId(elementId, itemIds[itemIndex])));
  219. } else if(isDynamicPanel) {
  220. // Really only need to do active state probably...
  221. parent = $jobj(elementId).children().children();
  222. } else if(isTreeNode) parent = $jobj($ax.repeater.applySuffixToElementId(elementId, '_children'));
  223. // Menu doesn't want all children, only tables and menus, so it must be handled specially
  224. var children = isMenu ? parent.children('.ax_table').add(parent.children('.ax_menu')) : parent.children();
  225. // For tree nodes you want the the button shape contained by the elementQuery too
  226. if(isTreeNode) {
  227. var treeNodeChildren = $jobj(elementId).children();
  228. for(var treeNodeIndex = 0; treeNodeIndex < treeNodeChildren.length; treeNodeIndex++) {
  229. var treeNodeChild = $(treeNodeChildren[treeNodeIndex]);
  230. var childObj = $obj(treeNodeChild.attr('id'));
  231. if(childObj && childObj.type == 'buttonShape') children = children.add(treeNodeChild);
  232. }
  233. }
  234. var childrenIds = [];
  235. for(var childIndex = 0; childIndex < children.length; childIndex++) childrenIds.push($(children[childIndex]).attr('id'));
  236. if(deep) {
  237. var childObjs = [];
  238. for(var i = 0; i < childrenIds.length; i++) {
  239. var childId = childrenIds[i];
  240. childObjs[i] = { id: childId, children: getChildren(childId) };
  241. }
  242. childrenIds = childObjs;
  243. }
  244. return childrenIds;
  245. }
  246. return undefined;
  247. };
  248. for(var i = 0; i < elementIds.length; i++) {
  249. children[children.length] = { id : elementIds[i], children : getChildren(elementIds[i])};
  250. }
  251. return children;
  252. };
  253. })();