产品原型
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.

578 lines
22 KiB

4 years ago
  1. // ******* Expr MANAGER ******** //
  2. $axure.internal(function($ax) {
  3. var _expr = $ax.expr = {};
  4. var _binOpHandlers = {
  5. '&&': function(left, right) { return _binOpOverride(left, right, function(left) { return $ax.getBool(left) && $ax.getBool(right()); }); },
  6. '||': function(left, right) { return _binOpOverride(left, right, function(left) { return $ax.getBool(left) || $ax.getBool(right()); }); },
  7. '==': function(left, right) { return isEqual(left, right, true); },
  8. '!=': function(left, right) { return !isEqual(left, right, true); },
  9. '>': function(left, right) { return _binOpNum(left, right, function(left, right) { return left > right; }); },
  10. '<': function(left, right) { return _binOpNum(left, right, function(left, right) { return left < right; }); },
  11. '>=': function(left, right) { return _binOpNum(left, right, function(left, right) { return left >= right; }); },
  12. '<=': function(left, right) { return _binOpNum(left, right, function(left, right) { return left <= right; }); }
  13. };
  14. var checkOps = function(left, right) {
  15. return left == undefined || right == undefined;
  16. };
  17. var isEqual = function (left, right, isFunction) {
  18. if (isFunction) {
  19. //if left and right is function, then get the value
  20. //otherwise left and right should be already the value we want
  21. left = left();
  22. right = right();
  23. }
  24. if(checkOps(left, right)) return false;
  25. if(left instanceof Date && right instanceof Date) {
  26. if(left.getMilliseconds() != right.getMilliseconds()) return false;
  27. if(left.getSeconds() != right.getSeconds()) return false;
  28. if(left.getMinutes() != right.getMinutes()) return false;
  29. if(left.getHours() != right.getHours()) return false;
  30. if(left.getDate() != right.getDate()) return false;
  31. if(left.getMonth() != right.getMonth()) return false;
  32. if(left.getYear() != right.getYear()) return false;
  33. return true;
  34. }
  35. if(left instanceof Object && right instanceof Object) {
  36. var prop;
  37. // Go through all of lefts properties and compare them to rights.
  38. for(prop in left) {
  39. if(!left.hasOwnProperty(prop)) continue;
  40. // If left has a property that the right doesn't they are not equal.
  41. if(!right.hasOwnProperty(prop)) return false;
  42. // If any of their properties are not equal, they are not equal.
  43. if(!isEqual(left[prop], right[prop], false)) return false;
  44. }
  45. for(prop in right) {
  46. // final check to make sure right doesn't have some extra properties that make them not equal.
  47. if(left.hasOwnProperty(prop) != right.hasOwnProperty(prop)) return false;
  48. }
  49. return true;
  50. }
  51. return $ax.getBool(left) == $ax.getBool(right);
  52. };
  53. var _binOpOverride = function(left, right, func) {
  54. left = left();
  55. if(left == undefined) return false;
  56. var res = func(left, right);
  57. return res == undefined ? false : res;
  58. };
  59. var _binOpNum = function(left, right, func) {
  60. var left = left();
  61. var right = right();
  62. if(checkOps(left, right)) return false;
  63. return func(left, Number(right));
  64. };
  65. var _exprHandlers = {};
  66. _exprHandlers.array = function(expr, eventInfo) {
  67. var returnVal = [];
  68. for(var i = 0; i < expr.items.length; i++) {
  69. returnVal[returnVal.length] = _evaluateExpr(expr.items[i], eventInfo);
  70. }
  71. return returnVal;
  72. };
  73. _exprHandlers.binaryOp = function(expr, eventInfo) {
  74. var left = function() { return expr.leftExpr && _evaluateExpr(expr.leftExpr, eventInfo); };
  75. var right = function() { return expr.rightExpr && _evaluateExpr(expr.rightExpr, eventInfo); };
  76. if(left == undefined || right == undefined) return false;
  77. return _binOpHandlers[expr.op](left, right);
  78. };
  79. _exprHandlers.block = function(expr, eventInfo) {
  80. var subExprs = expr.subExprs;
  81. for(var i = 0; i < subExprs.length; i++) {
  82. _evaluateExpr(subExprs[i], eventInfo); //ignore the result
  83. }
  84. };
  85. _exprHandlers.booleanLiteral = function(expr) {
  86. return expr.value;
  87. };
  88. _exprHandlers.nullLiteral = function() { return null; };
  89. _exprHandlers.pathLiteral = function(expr, eventInfo) {
  90. if(expr.isThis) return [eventInfo.srcElement];
  91. if(expr.isFocused && window.lastFocusedControl) {
  92. $ax('#' + window.lastFocusedControl).focus();
  93. return [window.lastFocusedControl];
  94. }
  95. if(expr.isTarget) return [eventInfo.targetElement];
  96. return $ax.getElementIdsFromPath(expr.value, eventInfo);
  97. };
  98. _exprHandlers.panelDiagramLiteral = function(expr, eventInfo) {
  99. var elementIds = $ax.getElementIdsFromPath(expr.panelPath, eventInfo);
  100. var elementIdsWithSuffix = [];
  101. var suffix = '_state' + expr.panelIndex;
  102. for(var i = 0; i < elementIds.length; i++) {
  103. elementIdsWithSuffix[i] = $ax.repeater.applySuffixToElementId(elementIds[i], suffix);
  104. }
  105. return String($jobj(elementIdsWithSuffix).data('label'));
  106. };
  107. _exprHandlers.fcall = function(expr, eventInfo) {
  108. var oldTarget = eventInfo.targetElement;
  109. var targets = [];
  110. var fcallArgs = [];
  111. var exprArgs = expr.arguments;
  112. for(var i = 0; i < expr.arguments.length; i++) {
  113. var exprArg = exprArgs[i];
  114. var fcallArg = '';
  115. if(targets.length) {
  116. for(var j = 0; j < targets.length; j++) {
  117. if(exprArg == null) {
  118. fcallArgs[j][i] = null;
  119. continue;
  120. }
  121. eventInfo.targetElement = targets[j];
  122. fcallArg = _evaluateExpr(exprArg, eventInfo);
  123. if(typeof (fcallArg) == 'undefined') return '';
  124. fcallArgs[j][i] = fcallArg;
  125. }
  126. } else {
  127. if(exprArg == null) {
  128. fcallArgs[i] = null;
  129. continue;
  130. }
  131. fcallArg = _evaluateExpr(exprArg, eventInfo);
  132. if(typeof (fcallArg) == 'undefined') return '';
  133. fcallArgs[i] = fcallArg;
  134. }
  135. // We do support null exprArgs...
  136. // TODO: This makes 2 assumptions that may change in the future. 1. The pathLiteral is the always the first arg. 2. there is always only 1 pathLiteral
  137. if(exprArg && exprArg.exprType == 'pathLiteral') {
  138. targets = fcallArg;
  139. // fcallArgs is now an array of an array of args
  140. for(j = 0; j < targets.length; j++) fcallArgs[j] = [[fcallArg[j]]];
  141. }
  142. }
  143. // we want to preserve the target element from outside this function.
  144. eventInfo.targetElement = oldTarget;
  145. var retval = '';
  146. if(targets.length) {
  147. // Go backwards so retval is the first item.
  148. for(i = targets.length - 1; i >= 0; i--) {
  149. var args = fcallArgs[i];
  150. // Add event info to the end
  151. args[args.length] = eventInfo;
  152. retval = _exprFunctions[expr.functionName].apply(this, args);
  153. }
  154. } else fcallArgs[fcallArgs.length] = eventInfo;
  155. return targets.length ? retval : _exprFunctions[expr.functionName].apply(this, fcallArgs);
  156. };
  157. _exprHandlers.globalVariableLiteral = function(expr) {
  158. return expr.variableName;
  159. };
  160. _exprHandlers.keyPressLiteral = function(expr) {
  161. var keyInfo = {};
  162. keyInfo.keyCode = expr.keyCode;
  163. keyInfo.ctrl = expr.ctrl;
  164. keyInfo.alt = expr.alt;
  165. keyInfo.shift = expr.shift;
  166. return keyInfo;
  167. };
  168. _exprHandlers.adaptiveViewLiteral = function(expr) {
  169. return expr.id;
  170. };
  171. _exprHandlers.optionLiteral = function(expr) {
  172. return expr.value;
  173. }
  174. var _substituteSTOs = function(expr, eventInfo) {
  175. //first evaluate the local variables
  176. var scope = {};
  177. for(var varName in expr.localVariables) {
  178. scope[varName] = $ax.expr.evaluateExpr(expr.localVariables[varName], eventInfo);
  179. }
  180. // TODO: [ben] Date and data object (obj with info for url or image) both need to return non-strings.
  181. var i = 0;
  182. var retval;
  183. var retvalString = expr.value.replace(/\[\[(?!\[)(.*?)\]\](?=\]*)/g, function(match) {
  184. var sto = expr.stos[i++];
  185. if(sto.sto == 'error') return match;
  186. try {
  187. var result = $ax.evaluateSTO(sto, scope, eventInfo);
  188. } catch(e) {
  189. return match;
  190. }
  191. if((result instanceof Object) && i == 1 && expr.value.substring(0, 2) == '[[' &&
  192. expr.value.substring(expr.value.length - 2) == ']]') {
  193. // If the result was an object, this was the first result, and the whole thing was this expresion.
  194. retval = result;
  195. }
  196. return ((result instanceof Object) && (result.label || result.text)) || result;
  197. });
  198. // If more than one group returned, the object is not valid
  199. if(i != 1) retval = false;
  200. return retval || retvalString;
  201. };
  202. _exprHandlers.htmlLiteral = function (expr, eventInfo) {
  203. eventInfo.htmlLiteral = true;
  204. var html = _substituteSTOs(expr, eventInfo);
  205. eventInfo.htmlLiteral = false
  206. return html;
  207. };
  208. _exprHandlers.stringLiteral = function(expr, eventInfo) {
  209. return _substituteSTOs(expr, eventInfo);
  210. };
  211. var _exprFunctions = {};
  212. _exprFunctions.SetCheckState = function(elementIds, value) {
  213. var toggle = value == 'toggle';
  214. var boolValue = Boolean(value) && value != 'false';
  215. for(var i = 0; i < elementIds.length; i++) {
  216. var query = $ax('#' + elementIds[i]);
  217. query.selected(toggle ? !query.selected() : boolValue);
  218. }
  219. };
  220. _exprFunctions.SetSelectedOption = function(elementIds, value) {
  221. for(var i = 0; i < elementIds.length; i++) {
  222. var elementId = elementIds[i];
  223. var obj = $jobj($ax.INPUT(elementId));
  224. if(obj.val() == value) return;
  225. obj.val(value);
  226. if($ax.event.HasSelectionChanged($ax.getObjectFromElementId(elementId))) $ax.event.raiseSyntheticEvent(elementId, 'onSelectionChange');
  227. }
  228. };
  229. _exprFunctions.SetGlobalVariableValue = function(varName, value) {
  230. $ax.globalVariableProvider.setVariableValue(varName, value);
  231. };
  232. _exprFunctions.SetWidgetFormText = function(elementIds, value) {
  233. for(var i = 0; i < elementIds.length; i++) {
  234. var elementId = elementIds[i];
  235. var inputId = $ax.repeater.applySuffixToElementId(elementId, '_input');
  236. var obj = $jobj(inputId);
  237. if(obj.val() == value || (value == '' && $ax.placeholderManager.isActive(elementId))) return;
  238. obj.val(value);
  239. $ax.placeholderManager.updatePlaceholder(elementId, !value);
  240. if($ax.event.HasTextChanged($ax.getObjectFromElementId(elementId))) $ax.event.TryFireTextChanged(elementId);
  241. }
  242. };
  243. _exprFunctions.SetFocusedWidgetText = function(elementId, value) {
  244. if(window.lastFocusedControl) {
  245. var elementId = window.lastFocusedControl;
  246. var type = $obj(elementId).type;
  247. if ($ax.public.fn.IsTextBox(type) || $ax.public.fn.IsTextArea(type)) _exprFunctions.SetWidgetFormText([elementId], value);
  248. else _exprFunctions.SetWidgetRichText([elementId], value, true);
  249. }
  250. };
  251. _exprFunctions.GetRtfElementHeight = function(rtfElement) {
  252. if(rtfElement.innerHTML == '') rtfElement.innerHTML = '&nbsp;';
  253. return rtfElement.offsetHeight;
  254. };
  255. _exprFunctions.SetWidgetRichText = function(ids, value, plain) {
  256. // Converts dates, widgetinfo, and the like to strings.
  257. value = _exprFunctions.ToString(value);
  258. //Replace any newlines with line breaks
  259. var finalValue = value.replace(/\r\n/g, '<br>').replace(/\n/g, '<br>');
  260. for(var i = 0; i < ids.length; i++) {
  261. var id = ids[i];
  262. // If calling this on button shape, get the id of the rich text panel inside instead
  263. if($obj(id).type !== $ax.constants.LINK_TYPE) id = $ax.GetTextPanelId(id, true);
  264. var element = window.document.getElementById(id);
  265. $ax.visibility.SetVisible(element, value != '');
  266. $ax.style.transformTextWithVerticalAlignment(id, function() {
  267. var spans = $jobj(id).find('span');
  268. if(plain) {
  269. // Can't set value as text because '<br/>' doesn't actually do a line break
  270. // Can't set vaule as html because it doesn't like '<' and ignores all after it
  271. // Create tags yourself
  272. var lines = value.split(/\r\n|\n/);
  273. //if we are dealing with only one line, just reuse the old one
  274. if(spans.length === 1 && lines.length === 1) {
  275. $(spans[0]).text(value);
  276. return;
  277. }
  278. // Wrap in span and p, style them accordingly.
  279. var span = $('<span></span>');
  280. if(spans.length > 0) {
  281. span.attr('style', $(spans[0]).attr('style'));
  282. span.attr('id', $(spans[0]).attr('id'));
  283. }
  284. if(lines.length == 1) span.text(value);
  285. else {
  286. for(var i = 0; i < lines.length; i++) {
  287. if(i != 0) span.append($('<br />'));
  288. var line = lines[i];
  289. if(line.length == 0) continue;
  290. var subSpan = $('<span />');
  291. subSpan.text(line);
  292. span.append(subSpan);
  293. }
  294. }
  295. var ps = $jobj(id).find('p');
  296. if(ps && ps.length) {
  297. ps[0].innerHTML = $('<div></div>').append(span).html();;
  298. if(ps.length > 1) {
  299. for(var i = 1; i < ps.length; i++) {
  300. $(ps[i]).remove();
  301. }
  302. }
  303. } else {
  304. var p = $('<p></p>');
  305. p.append(span);
  306. element.innerHTML = $('<div></div>').append(p).html();
  307. }
  308. } else element.innerHTML = finalValue;
  309. });
  310. if(!plain) $ax.style.CacheOriginalText(id, true);
  311. }
  312. };
  313. _exprFunctions.GetCheckState = function(ids) {
  314. return $ax('#' + ids[0]).selected();
  315. };
  316. _exprFunctions.GetDisabledState = function (ids) {
  317. return !$ax('#' + ids[0]).enabled();
  318. };
  319. _exprFunctions.GetSelectedOption = function (ids) {
  320. var inputs = $jobj($ax.INPUT(ids[0]));
  321. return inputs.length ? inputs[0].value : '';
  322. };
  323. _exprFunctions.GetNum = function(str) {
  324. //Setting a GlobalVariable to some blank text then setting a widget to the value of that variable would result in 0 not ""
  325. //I have fixed this another way so commenting this should be fine now
  326. //if (!str) return "";
  327. return isNaN(str) ? str : Number(str);
  328. };
  329. _exprFunctions.GetGlobalVariableValue = function(id) {
  330. return $ax.globalVariableProvider.getVariableValue(id);
  331. };
  332. _exprFunctions.GetGlobalVariableLength = function(id) {
  333. return _exprFunctions.GetGlobalVariableValue(id).length;
  334. };
  335. _exprFunctions.GetWidgetText = function(ids) {
  336. if($ax.placeholderManager.isActive(ids[0])) return '';
  337. var input = $ax.INPUT(ids[0]);
  338. return $ax('#' + ($jobj(input).length ? input : ids[0])).text();
  339. };
  340. _exprFunctions.GetFocusedWidgetText = function() {
  341. if(window.lastFocusedControl) {
  342. return $ax('#' + window.lastFocusedControl).text();
  343. } else {
  344. return "";
  345. }
  346. };
  347. _exprFunctions.GetWidgetValueLength = function(ids) {
  348. var id = ids[0];
  349. if(!id) return undefined;
  350. if($ax.placeholderManager.isActive(id)) return 0;
  351. var obj = $jobj($ax.INPUT(id));
  352. if(!obj.length) obj = $jobj(id);
  353. var val = obj[0].value || _exprFunctions.GetWidgetText([id]);
  354. return val.length;
  355. };
  356. _exprFunctions.GetPanelState = function(ids) {
  357. var id = ids[0];
  358. if(!id) return undefined;
  359. var stateId = $ax.visibility.GetPanelState(id);
  360. return stateId && String($jobj(stateId).data('label'));
  361. };
  362. _exprFunctions.GetWidgetVisibility = function(ids) {
  363. var id = ids[0];
  364. if(!id) return undefined;
  365. return $ax.visibility.IsIdVisible(id);
  366. };
  367. // ***************** Validation Functions ***************** //
  368. _exprFunctions.IsValueAlpha = function(val) {
  369. var isAlphaRegex = new RegExp("^[a-z\\s]+$", "gi");
  370. return isAlphaRegex.test(val);
  371. };
  372. _exprFunctions.IsValueNumeric = function(val) {
  373. var isNumericRegex = new RegExp("^[0-9,\\.\\s]+$", "gi");
  374. return isNumericRegex.test(val);
  375. };
  376. _exprFunctions.IsValueAlphaNumeric = function(val) {
  377. var isAlphaNumericRegex = new RegExp("^[0-9a-z\\s]+$", "gi");
  378. return isAlphaNumericRegex.test(val);
  379. };
  380. _exprFunctions.IsValueOneOf = function(val, values) {
  381. for(var i = 0; i < values.length; i++) {
  382. var option = values[i];
  383. if(val == option) return true;
  384. }
  385. //by default, return false
  386. return false;
  387. };
  388. _exprFunctions.IsValueNotAlpha = function(val) {
  389. return !_exprFunctions.IsValueAlpha(val);
  390. };
  391. _exprFunctions.IsValueNotNumeric = function(val) {
  392. return !_exprFunctions.IsValueNumeric(val);
  393. };
  394. _exprFunctions.IsValueNotAlphaNumeric = function(val) {
  395. return !_exprFunctions.IsValueAlphaNumeric(val);
  396. };
  397. _exprFunctions.IsValueNotOneOf = function(val, values) {
  398. return !_exprFunctions.IsValueOneOf(val, values);
  399. };
  400. _exprFunctions.GetKeyPressed = function(eventInfo) {
  401. return eventInfo.keyInfo;
  402. };
  403. _exprFunctions.GetCursorRectangles = function() {
  404. var rects = new Object();
  405. rects.lastRect = new $ax.drag.Rectangle($ax.lastMouseLocation.x, $ax.lastMouseLocation.y, 1, 1);
  406. rects.currentRect = new $ax.drag.Rectangle($ax.mouseLocation.x, $ax.mouseLocation.y, 1, 1);
  407. return rects;
  408. };
  409. _exprFunctions.GetWidgetRectangles = function (elementIds, eventInfo) {
  410. var elementId = elementIds[0];
  411. var rects = new Object();
  412. var jObj = $jobj(elementId);
  413. var invalid = jObj.length == 0;
  414. var parent = jObj;
  415. // Or are in valid if no obj can be found, or if it is not visible.
  416. while(parent.length != 0 && !parent.is('body')) {
  417. if(parent.css('display') == 'none') {
  418. invalid = true;
  419. break;
  420. }
  421. parent = parent.parent();
  422. }
  423. if(invalid) {
  424. rects.lastRect = rects.currentRect = new $ax.drag.Rectangle(-1, -1, -1, -1);
  425. return rects;
  426. }
  427. var axObj = $ax('#' + elementId);
  428. var boundingRect = axObj.viewportBoundingRect();
  429. rects.lastRect = new $ax.drag.Rectangle(
  430. boundingRect.left,
  431. boundingRect.top,
  432. boundingRect.width,
  433. boundingRect.height);
  434. //rects.lastRect = new $ax.drag.Rectangle(
  435. // axObj.left(),
  436. // axObj.top(),
  437. // axObj.width(),
  438. // axObj.height());
  439. rects.currentRect = rects.lastRect;
  440. return rects;
  441. };
  442. _exprFunctions.GetWidget = function(elementId) {
  443. return $ax.getWidgetInfo(elementId[0]);
  444. };
  445. _exprFunctions.GetAdaptiveView = function (eventInfo) {
  446. if (eventInfo && eventInfo.srcElement) {
  447. var id = eventInfo.srcElement;
  448. var diagramObject = $ax.getObjectFromElementId(id);
  449. if (diagramObject.owner.type == 'Axure:Master') {
  450. var viewIdChain = $ax.style.getViewIdChain($ax.adaptive.currentViewId || '', id, diagramObject);
  451. if (viewIdChain.length > 0) return viewIdChain[viewIdChain.length - 1];
  452. else return '19e82109f102476f933582835c373474';
  453. }
  454. }
  455. return $ax.adaptive.currentViewId || '';
  456. };
  457. _exprFunctions.IsEntering = function(movingRects, targetRects) {
  458. return !movingRects.lastRect.IntersectsWith(targetRects.currentRect) && movingRects.currentRect.IntersectsWith(targetRects.currentRect);
  459. };
  460. _exprFunctions.IsLeaving = function(movingRects, targetRects) {
  461. return movingRects.lastRect.IntersectsWith(targetRects.currentRect) && !movingRects.currentRect.IntersectsWith(targetRects.currentRect);
  462. };
  463. var _IsOver = _exprFunctions.IsOver = function(movingRects, targetRects) {
  464. return movingRects.currentRect.IntersectsWith(targetRects.currentRect);
  465. };
  466. _exprFunctions.IsNotOver = function(movingRects, targetRects) {
  467. return !_IsOver(movingRects, targetRects);
  468. };
  469. _exprFunctions.ValueContains = function(inputString, value) {
  470. return inputString.indexOf(value) > -1;
  471. };
  472. _exprFunctions.ValueNotContains = function(inputString, value) {
  473. return !_exprFunctions.ValueContains(inputString, value);
  474. };
  475. _exprFunctions.ToString = function(value) {
  476. if(value.isWidget) {
  477. return value.text;
  478. }
  479. return String(value);
  480. };
  481. var _evaluateExpr = $ax.expr.evaluateExpr = function(expr, eventInfo, toString) {
  482. if(expr === undefined || expr === null) return undefined;
  483. var result = _exprHandlers[expr.exprType](expr, eventInfo);
  484. return toString ? _exprFunctions.ToString(result) : result;
  485. };
  486. });