Greasy Fork is available in English.

RSel-ExprEditor-(Library)

Allows easier editing of the selection criteria by converting the expressions into editable text

Fra 04.03.2016. Se den seneste versjonen.

Dette scriptet burde ikke installeres direkte. Det er et bibliotek for andre script å inkludere med det nye metadirektivet // @require https://update.greatest.deepsurf.us/scripts/17641/111339/RSel-ExprEditor-%28Library%29.js

  1. // ==UserScript==
  2. // @name RSel-ExprEditor-(Library)
  3. // @namespace https://greatest.deepsurf.us/users/11629-TheLastTaterTot
  4. // @version 0.2.5
  5. // @description Allows easier editing of the selection criteria by converting the expressions into editable text
  6. // @author TheLastTaterTot
  7. // @include https://editor-beta.waze.com/*editor/*
  8. // @include https://www.waze.com/*editor/*
  9. // @exclude https://www.waze.com/*user/editor/*
  10. // @grant none
  11. // @run-at document-end
  12. // ==/UserScript==
  13.  
  14. var _rsel = {
  15. getSelectionIndex: function(selector, selText) {
  16. return selector.map(function(i) {
  17. if (new RegExp(selText, 'i').test(this.innerText)) return this.value
  18. }).get(0);
  19. },
  20. getSelectOptions: function(selector) {
  21. var opts = [];
  22. selector.map(function(i, a) {
  23. opts.push(a.innerText.toLowerCase());
  24. });
  25. return opts;
  26. },
  27. getNewExprBuild: function() {
  28. return {
  29. cond: null,
  30. op: null,
  31. op2: null,
  32. val: null,
  33. val2: null,
  34. condmod: null
  35. }
  36. }
  37. },
  38. /*Using RSel DOM elements rather than requesting dev to provide direct modifiction of RSel's expr object.
  39. This is so the RSel dev can feel free to significantly change his object storage structure if needed. */
  40. rselBtns = {
  41. lfParens: function() {
  42. try {
  43. $('#btnRSLBkt').click();
  44. } catch (err) {}
  45. },
  46. rtParens: function() {
  47. try {
  48. $('#btnRSRBkt').click();
  49. } catch (err) {}
  50. },
  51. and: function() {
  52. try {
  53. $('#btnRSAnd').click()
  54. } catch (err) {}
  55. },
  56. or: function() {
  57. try {
  58. $('#btnRSOr').click()
  59. } catch (err) {}
  60. },
  61. not: function() {
  62. try {
  63. $('#btnRSNot').click()
  64. } catch (err) {}
  65. },
  66. clear: function() {
  67. try {
  68. $('#btnRSClear').click()
  69. } catch (err) {}
  70. }
  71. },
  72. rselCond = {
  73. country: {
  74. op: function(selText) {
  75. $('#opRSCountry').val(_rsel.getSelectionIndex($('#opRSCountry option'), selText));
  76. },
  77. val: function(selText) {
  78. $('#selRSCountry').val(_rsel.getSelectionIndex($('#selRSCountry option'), selText));
  79. },
  80. add: function() {
  81. $('#btnRSAddCountry').click();
  82. }
  83. },
  84. state: {
  85. op: function(selText) {
  86. $('#opRSState').val(_rsel.getSelectionIndex($('#opRSState option'), selText));
  87. },
  88. val: function(val) {
  89. $('#inRSState').val(val);
  90. },
  91. add: function() {
  92. $('#btnRSAddState').click();
  93. }
  94. },
  95. city: {
  96. op: function(selText) {
  97. $('#opRSCity').val(_rsel.getSelectionIndex($('#opRSCity option'), selText));
  98. },
  99. val: function(val) {
  100. $('#inRSCity').val(val);
  101. },
  102. condmod: function(val) {
  103. $('#selRSAltCity').val(val);
  104. },
  105. add: function() {
  106. $('#btnRSAddCity').click();
  107. }
  108. },
  109. street: {
  110. op: function(selText) {
  111. $('#opRSStreet').val(_rsel.getSelectionIndex($('#opRSStreet option'), selText));
  112. },
  113. val: function(val) {
  114. $('#inRSStreet').val(val);
  115. },
  116. condmod: function(val) {
  117. $('#selRSAlttStreet').val(val);
  118. },
  119. add: function() {
  120. $('#btnRSAddStreet').click();
  121. }
  122. },
  123. unnamed: {
  124. op: function(chkVal) {
  125. $('#cbRSNoName').prop('checked', chkVal);
  126. }, //checked - has no name
  127. opAlt: function(chkVal) {
  128. $('#cbRSAltNoName').prop('checked', chkVal);
  129. }, //checked - alt name
  130. add: function() {
  131. $('#btnRSAddNoName').click();
  132. }
  133. },
  134. road: {
  135. op: function(selText) {
  136. $('#opRSRoadType').val(_rsel.getSelectionIndex($('#opRSRoadType option'), selText));
  137. },
  138. val: function(selText) {
  139. $('#selRSRoadType').val(_rsel.getSelectionIndex($('#selRSRoadType option'), selText));
  140. },
  141. add: function() {
  142. $('#btnRSAddRoadType').click();
  143. }
  144. },
  145. direction: {
  146. op: function(selText) {
  147. $('#opRSDirection').val(_rsel.getSelectionIndex($('#opRSDirection option'), selText));
  148. },
  149. val: function(selText) {
  150. $('#selRSDirection').val(_rsel.getSelectionIndex($('#selRSDirection option'), selText));
  151. },
  152. add: function() {
  153. $('#btnRSAddDirection').click();
  154. }
  155. },
  156. elevation: {
  157. op: function(selText) {
  158. $('#opRSElevation').val(_rsel.getSelectionIndex($('#opRSElevation option'), selText));
  159. },
  160. val: function(selText) {
  161. $('#selRSElevation').val(_rsel.getSelectionIndex($('#selRSElevation option'), selText));
  162. },
  163. add: function() {
  164. $('#btnRSAddElevation').click();
  165. }
  166. },
  167. manual: {
  168. op: function(selText) {
  169. $('#opRSManLock').val(_rsel.getSelectionIndex($('#opRSManLock option'), selText));
  170. },
  171. val: function(val) {
  172. $('#selRSManLock').val(val);
  173. },
  174. add: function() {
  175. $('#btnRSAddManLock').click();
  176. }
  177. },
  178. trafic: {
  179. op: function(selText) {
  180. $('#opRSTrLock').val(_rsel.getSelectionIndex($('#opRSTrLock option'), selText));
  181. },
  182. val: function(val) {
  183. $('#selRSTrLock').val(val);
  184. },
  185. add: function() {
  186. $('#btnRSAddTrLock').click();
  187. }
  188. },
  189. speed: {
  190. opOptNodes: $('#opRSSpeed option'),
  191. op: function(selText) {
  192. $('#opRSSpeed').val(_rsel.getSelectionIndex($('#opRSSpeed option'), selText));
  193. },
  194. val: function(val) {
  195. $('#inRSSpeed').val(val);
  196. },
  197. add: function() {
  198. $('#btnRSAddSpeed').click();
  199. }
  200. },
  201. closure: {
  202. op: function(checked) {
  203. $('#cbRSClsr').prop('checked', checked);
  204. },
  205. op2: function(selText) {
  206. $('#opRSClsrStrtEnd').val(_rsel.getSelectionIndex($('#opRSClsrStrtEnd option'), selText));
  207. },
  208. val: function(val) {
  209. $('#inRSClsrDays').val(val);
  210. },
  211. condmod: function(selText) {
  212. $('#opRSClsrBeforeAter').val(_rsel.getSelectionIndex($('#opRSClsrBeforeAter option'), selText));
  213. },
  214. add: function() {
  215. $('#btnRSAddClsr').click();
  216. }
  217. },
  218. updated: {
  219. op: function(selText) {
  220. $('#opRSUpdtd').val(_rsel.getSelectionIndex($('#opRSUpdtd option'), selText));
  221. },
  222. val: function(val) {
  223. $('#inRSUpdtd').val(val);
  224. },
  225. add: function() {
  226. $('#btnRSAddUpdtd').click();
  227. }
  228. },
  229. created: {
  230. op: function(selText) {
  231. $('#opRSCrtd').val(_rsel.getSelectionIndex($('#opRSCrtd option'), selText));
  232. },
  233. val: function(val) {
  234. $('#inRSCrtd').val(val);
  235. },
  236. add: function() {
  237. $('#btnRSAddCrtd').click();
  238. }
  239. },
  240. last: {
  241. op: function(selText) {
  242. $('#opRSLastU').val(_rsel.getSelectionIndex($('#opRSLastU option'), selText));
  243. },
  244. val: function(val) {
  245. $('#inRSLastU').val(val);
  246. },
  247. add: function() {
  248. $('#btnRSAddLastU').click();
  249. }
  250. },
  251. length: {
  252. op: function(selText) {
  253. $('#opRSLength').val(_rsel.getSelectionIndex($('#opRSLength option'), selText));
  254. },
  255. val: function(val) {
  256. $('#inRSLength').val(val);
  257. },
  258. condmod: function(selText) {
  259. $('#unitRSLength').val(_rsel.getSelectionIndex($('#unitRSLength option'), selText));
  260. },
  261. add: function() {
  262. $('#btnRSAddLength').click();
  263. }
  264. },
  265. id: {
  266. op: function(selText) {
  267. $('#opRSSegId').val(_rsel.getSelectionIndex($('#opRSSegId option'), selText));
  268. },
  269. val: function(val) {
  270. $('#inRSSegId').val(val);
  271. },
  272. add: function() {
  273. $('#btnRSAddSegId').click();
  274. }
  275. },
  276. roundabout: {
  277. op: function(checked) {
  278. $('#cbRSIsRound').prop('checked', checked);
  279. },
  280. add: function() {
  281. $('#btnRSAddIsRound').click();
  282. }
  283. },
  284. toll: {
  285. op: function(checked) {
  286. $('#cbRSIsToll').prop('checked', checked);
  287. },
  288. add: function() {
  289. $('#btnRSAddIsToll').click();
  290. }
  291. },
  292. tunnel: {
  293. op: function(checked) {
  294. $('#cbRSTunnel').prop('checked', checked);
  295. },
  296. add: function() {
  297. $('#btnRSAddTunnel').click();
  298. }
  299. },
  300. new: {
  301. op: function(checked) {
  302. $('#cbRSIsNew').prop('checked', checked);
  303. },
  304. add: function() {
  305. $('#btnRSAddIsNew').click();
  306. }
  307. },
  308. changed: {
  309. op: function(checked) {
  310. $('#cbRSIsChngd').prop('checked', checked);
  311. },
  312. add: function() {
  313. $('#btnRSAddIsChngd').click();
  314. }
  315. },
  316. screen: {
  317. op: function(checked) {
  318. $('#cbRSOnScr').prop('checked', checked);
  319. },
  320. add: function() {
  321. $('#btnRSAddOnScr').click();
  322. }
  323. },
  324. restriction: {
  325. op: function(checked) {
  326. $('#cbRSRestr').prop('checked', checked);
  327. },
  328. add: function() {
  329. $('#btnRSAddRestr').click();
  330. }
  331. },
  332. editable: {
  333. op: function(checked) {
  334. $('#cbRSEdtbl').prop('checked', checked);
  335. },
  336. add: function() {
  337. $('#btnRSAddEdtbl').click();
  338. }
  339. }
  340. };
  341.  
  342. //=============================================================================
  343. function updateExpr(parseThis) {
  344. var __EXPR_DEBUGINFO;
  345.  
  346. console.info('*** Begin parsing expression... ***');
  347. rselBtns.clear();
  348.  
  349. //---------------------------------------------------------------
  350. var addExpr = function(eb) {
  351. var checkKeys = false;
  352. Object.keys(rselCond).map(function(a, i) {
  353. if (a === eb.cond) checkKeys = true;
  354. });
  355. if (checkKeys) {
  356. try {
  357. rselCond[eb.cond].op(eb.op);
  358. if (eb.op2 !== null) rselCond[eb.cond].op2(eb.op2);
  359. if (eb.condmod !== null) rselCond[eb.cond].condmod(eb.condmod);
  360.  
  361. if (eb.val2 === null) {
  362. if (eb.val !== null) rselCond[eb.cond].val(eb.val);
  363. rselCond[eb.cond].add();
  364. } else {
  365. rselBtns.lfParens();
  366. rselCond[eb.cond].val(eb.val);
  367. rselCond[eb.cond].add();
  368. rselBtns.or();
  369. rselCond[eb.cond].val(eb.val2);
  370. rselCond[eb.cond].add();
  371. rselBtns.rtParens();
  372. }
  373.  
  374. } catch (err) {
  375. __EXPR_DEBUGINFO.eb = eb;
  376. return {
  377. errdebug: __EXPR_DEBUGINFO,
  378. err: err
  379. };
  380. }
  381. } else {
  382. __EXPR_DEBUGINFO.eb = eb;
  383. return {
  384. errdebug: __EXPR_DEBUGINFO,
  385. err: 'Selector condition was not recognized'
  386. };
  387. }
  388.  
  389. return true;
  390. };
  391. //---------------------------------------------------------------
  392. //parseThis = '(((Country="United States" AND State="Oregon") AND !(Prim name!="Somewhere") AND Name contains ("Somewhere")) OR (Alt name !contains ("Somewhere"))) AND Primary City ~("Some City") AND City="Big City" AND Alt. City!= "Big City" AND Prim. or Alt. City contains ("Big City") AND ((Has name OR Unnamed) AND (NO Alt. names OR Has Alt name(s))) AND Road Type = "Runway/Taxiway" AND !Roundabout AND Is NOT Toll Road AND != Unnamed & (Direction != "One way (A->B)" OR Direction = "Unknown") AND (Elevation != "Ground" AND Elevation > 1 AND Elevation <= 1) AND Is NOT Tunnel AND On Screen & OUT of Screen && Has restriction | Has NO restriction AND Has closure || Has NO closure AND Closure starts before 1 day AND Closure ends before 1 day AND Closure starts after 1 day AND Closure ends after 1 day AND Closure starts in 1 day AND Closure ends in 1 day AND Closure doesn\'t start in 1 day AND Closure doesn\'t end in 1 day';
  393. //parseThis.replace(/\bis(?:\s?n[o']t)\b/ig,'!=')
  394.  
  395. if (parseThis === undefined) parseThis = $('#cmEditExprBox').val();
  396.  
  397. var parseExprArray = parseThis.match(
  398. /\("(.*?)"\)|\('(.*?)'\)|"(.*?)"|'(.*?)'|\bpri?m?(?:ary|\.)?\s?(?:or|and|\|\||\||&|&&|\/)\s?alt(?:ern|s)?(?:\.)?|\bno[\s-]alt|\b(?:street[\s-]?)?name\(s\)|\bstreet(?:\snames?)\b|\b(?:un)?name[ds]?(?:[-\s]?seg[a-z]*)?\b|\b(?:road)(?:.?(?:type))?\b|\btoll(?:[-\s]?ro?a?d)?\b|\b(?:speed[\s-]?(?:limits?)?|sl)\b|\bman[ually]*[\s-]?(?:lock[eds]*)?\b|\btraf[fic]*[\s-]?(?:lock[eds]*)?\b|\bauto-?(?:matic[ally]*)?[\s-]?(?:lock[eds]*)?\b|\bcreated(?:[\s-]?by)?\b|\blast(?:[\s-]?(?:update[ds]?|edite?d?s?))?\b|\b(?:update[ds]?|edite?d?s?)(?:[\s-]?by)?\b|\b(?:in|on|off|out|outside)(?: of)?[- ]?screen\b|\bdoes(?:\s?n[o']t)\b|(?:!\s?)?contains?\b|!=|>=|<=|A->B|B->A|\w+(\(s\))?|&&|\|\||!=|[|&<>=()!~]/gi
  399. ),
  400. exprHistory = [],
  401. condMatches = [],
  402. condMatchPhrases = [],
  403. exprMatches = [],
  404. exprMatchPhrases = [],
  405. exprBuild, exprFragment, exprFragPhrase, exprFragPhraseStr, unwantedWordsSearch,
  406. closeParens, e, f, b, fLength, m, mLength,
  407. success = false;
  408.  
  409. // The following parses the expression text into unique chunks within separate array elements
  410. e = parseExprArray.length;
  411. while (e-- > 0) {
  412. try {
  413. exprFragment = parseExprArray.shift();
  414. //console.info(exprFragment);
  415.  
  416. // Find operators that join individual expressions (AND|OR|!|parenthesis)
  417. if (/^(?:and|or|&&|\|\||!=|[=&|()!])$/i.test(exprFragment)) {
  418. exprMatches.push(exprFragment.toLowerCase());
  419. exprMatchPhrases.push(exprFragment.toLowerCase());
  420. }
  421.  
  422. // Identify elements that contain selection condition names
  423. if (
  424. /^country|^state|^city|^street|^(?:un|street[\s-]?)?name.*|^(?:road)(?:.?(?:type))?|^type|^round[a-z]*|^rotary|^ra|^toll(?:[-\s]?ro?a?d)?|^(?:speed[\s-]?(?:limits?)?|sl)|^dir[a-z]*|^elevation|^tun[a-z]*|^man[ually]*[\s-]?(?:lock[eds]*)?|^traf[fic]*[\s-]?(?:lock[eds]*)?|^auto-?(?:matic[ally]*)?[\s-]?(?:lock[eds]*)?|^speed|^sls?|^new|^changed|^chg[a-z]*|^(?:in|on|off|out|outside)(?: of)?[- ]?screen|^restrict[a-z]*|^clos[a-z]+|^created(?:[\s-]?by)?|^last(?:[\s-]?(?:update[ds]?|edite?d?s?)[\s-]?(?:by)?)?|^(?:update[ds]?|edite?d?s?)(?:[\s-]?by)?|^length|^id|^editable/i
  425. .test(exprFragment)) {
  426. condMatches.push(exprFragment.toLowerCase()); // lists specific selection conditions
  427. exprMatches.push(exprFragment.toLowerCase()); //same as condMatches, but includes operations as separate array elements
  428.  
  429. try {
  430. //search phrase fowards
  431. fLength = parseExprArray.length;
  432. f = 0;
  433. while (!(/^(and|or|&&|\|\||[&|)])$/i.test(parseExprArray[f])) && (++f < fLength)) {}
  434. //search phrase backwards
  435. b = exprHistory.length;
  436. while (!(/^(and|or|&&|\|\||[&|(])$/i.test(exprHistory[b - 1])) && (--b > 0)) {}
  437.  
  438. condMatchPhrases.push(exprHistory.slice(b).concat(exprFragment, parseExprArray.slice(0, f))); //list specific selection conditions and its criteria
  439.  
  440. unwantedWordsSearch = exprHistory.slice(b);
  441. if (unwantedWordsSearch && unwantedWordsSearch.length) {
  442. spliceOut = [];
  443. for (m = unwantedWordsSearch.length; m--;) {
  444. if (/\b(has|have|is|=|are|does)\b/i.test(unwantedWordsSearch[m])) {
  445. unwantedWordsSearch.splice(m, 1);
  446. }
  447. }
  448. }
  449. if (/!|!=/.test(unwantedWordsSearch[0])) unwantedWordsSearch.splice(0, 1);
  450.  
  451. exprMatchPhrases.push(unwantedWordsSearch.concat(parseExprArray.slice(0, f))); //excludes the match cond
  452.  
  453. //exprHistory.push(exprFragment);
  454. exprHistory = exprHistory.concat(exprFragment, parseExprArray.slice(0, f));
  455. parseExprArray = parseExprArray.slice(f);
  456. e -= f;
  457. } catch (err) {
  458. return {
  459. errdebug: 'Error parsing expression at ' + exprFragment,
  460. err: err
  461. };
  462. }
  463. } else {
  464. exprHistory.push(exprFragment);
  465. }
  466. } catch (err) {
  467. return {
  468. errdebug: 'Error parsing expression at ' + exprFragment,
  469. err: err
  470. };
  471. }
  472. } //while
  473.  
  474.  
  475. //---------------------------------------------------------------
  476. // Quick crude check for unmatched parentheses
  477. var nOpenParens = exprMatches.toString().match(/\(/g),
  478. nCloseParens = exprMatches.toString().match(/\)/g);
  479. if (!nOpenParens) nOpenParens = [];
  480. if (!nCloseParens) nCloseParens = [];
  481. if (nOpenParens.length !== nCloseParens.length) return 1;
  482. //---------------------------------------------------------------
  483.  
  484. closeParens = 0;
  485. mLength = exprMatchPhrases.length;
  486. for (m = 0; m < mLength; m++) {
  487. __EXPR_DEBUGINFO = {
  488. m: m,
  489. exprMatches: exprMatches[m],
  490. exprMatchPhrases: exprMatchPhrases[m]
  491. }; //reset for error debugging
  492.  
  493. exprFragment = exprMatches[m];
  494. exprFragPhrase = exprMatchPhrases[m];
  495. if (exprFragPhrase.constructor !== Array) exprFragPhrase = [exprFragPhrase];
  496.  
  497. exprBuild = _rsel.getNewExprBuild();
  498. exprBuild.cond = exprFragment;
  499.  
  500. //if (m===10) debugger;
  501.  
  502. if (closeParens === 1) closeParens = 2;
  503.  
  504. //============================================================
  505. // Where the magic happens... sort of.
  506. //============================================================
  507. switch (true) {
  508. case (exprFragment === '('):
  509. rselBtns.lfParens();
  510. break;
  511. case (exprFragment === ')'):
  512. rselBtns.rtParens();
  513. break;
  514. case /^(&|&&|and)$/.test(exprFragment):
  515. rselBtns.and();
  516. //console.info(exprFragment.toLowerCase());
  517. break;
  518. case /^(\||\|\||or)$/.test(exprFragment):
  519. //console.info(exprFragment.toLowerCase());
  520. rselBtns.or();
  521. break;
  522. case /no[\s-]alt/i.test(exprFragPhrase):
  523. rselCond.unnamed.op(true);
  524. rselCond.unnamed.opAlt(true);
  525. rselCond.unnamed.add();
  526. success = true;
  527. break;
  528. case /^(!|!=|not)$/.test(exprFragment):
  529. rselBtns.not();
  530. if (exprMatches[m + 1] !== '(') {
  531. rselBtns.lfParens();
  532. closeParens = 1;
  533. }
  534. break;
  535. case /^unnamed/.test(exprBuild.cond):
  536. rselCond.unnamed.op(true);
  537. rselCond.unnamed.opAlt(false);
  538. rselCond.unnamed.add();
  539. success = true;
  540. break;
  541.  
  542. // SPEED LIMITS
  543. case /^speed.*|^sls?/.test(exprBuild.cond):
  544. exprBuild.cond = exprBuild.cond.replace(/^sls?|^speed.*/, 'speed');
  545.  
  546. try {
  547. if (exprFragPhrase.length < 2 && /\bnot?\b|!|!=/i.test(exprFragPhrase[0])) {
  548. exprBuild.op = 'none';
  549. } else {
  550. exprFragPhrase = exprFragPhrase.join(' ');
  551.  
  552. if (/\bnot?\b|!|!=/i.test(exprFragPhrase)) rselBtns.not();
  553.  
  554. var optionText = _rsel.getSelectOptions(rselCond.speed.opOptNodes);
  555. optionText = RegExp(optionText.join('|'), 'i').exec(exprFragPhrase);
  556. if (optionText) exprBuild.op = optionText[0];
  557. else exprBuild.op = 'any';
  558. }
  559.  
  560. var speedVal = exprFragPhrase.match(/(\d+)\s?mph|(\d+)\s?km/i);
  561. if (speedVal && speedVal.length === 2) exprBuild.val = speedVal[1];
  562. } catch (err) {
  563. __EXPR_DEBUGINFO.exprBuild = exprBuild;
  564. return {
  565. errdebug: __EXPR_DEBUGINFO,
  566. err: err
  567. };
  568. }
  569. success = addExpr(exprBuild);
  570. break;
  571.  
  572.  
  573. // BINARY CONDITIONS:
  574. case exprFragPhrase.length === 0 || //suggests binary
  575. /^(?:screen|roundabout|ra|toll|tun|new|changed|restr|editable)/.test(exprBuild.cond) || //binary selection conditions
  576. (/^(?:street[\s-]?)?name.*|^clos.*/i.test(exprBuild.cond) && exprFragPhrase.length <= 1): //selection conditions that have both binary and multiple options
  577.  
  578. exprFragPhrase = exprFragPhrase.join(' ');
  579.  
  580. exprBuild.cond = exprBuild.cond.replace(/^(?:street[\s-]?)?name.*/, 'name');
  581. exprBuild.cond = exprBuild.cond.replace(/^ra|^rotary|^round.*/, 'roundabout');
  582. exprBuild.cond = exprBuild.cond.replace(/^toll.*/, 'toll');
  583. exprBuild.cond = exprBuild.cond.replace(/^tun.*/, 'tunnel');
  584. exprBuild.cond = exprBuild.cond.replace(/^restr.*/, 'restriction');
  585. exprBuild.cond = exprBuild.cond.replace(/^(?:in|on)[- ]?screen/, 'onscreen');
  586. exprBuild.cond = exprBuild.cond.replace(/^(?:off|out|outside)(?: of)?[- ]?screen/, 'offscreen');
  587.  
  588. if (/\bnot?\b|!|!=/i.test(exprFragPhrase)) {
  589. exprBuild.op = false;
  590. } else {
  591. exprBuild.op = true;
  592. }
  593. try {
  594. switch (exprBuild.cond) {
  595. case 'name':
  596. try {
  597. if (/alt/i.test(exprFragPhrase)) {
  598. rselCond.unnamed.op(false);
  599. rselCond.unnamed.opAlt(true);
  600. rselCond.unnamed.add();
  601. } else {
  602. rselCond.unnamed.op(false);
  603. rselCond.unnamed.opAlt(false);
  604. rselCond.unnamed.add();
  605. }
  606. success = true;
  607. } catch (err) {
  608. return {
  609. errdebug: __EXPR_DEBUGINFO,
  610. err: err
  611. };
  612. }
  613. break;
  614. case 'closure':
  615. exprBuild.op2 = '---';
  616. success = addExpr(exprBuild);
  617. break;
  618. case 'onscreen':
  619. exprBuild.cond = 'screen';
  620. exprBuild.op = true;
  621. success = addExpr(exprBuild);
  622. break;
  623. case 'offscreen':
  624. exprBuild.cond = 'screen';
  625. exprBuild.op = false;
  626. success = addExpr(exprBuild);
  627. break;
  628. case 'roundabout':
  629. case 'toll':
  630. case 'tunnel':
  631. case 'new':
  632. case 'changed':
  633. case 'restriction':
  634. case 'editable':
  635. success = addExpr(exprBuild);
  636. break;
  637. } //switch
  638.  
  639. } catch (err) {
  640. __EXPR_DEBUGINFO.exprBuild = exprBuild;
  641. return {
  642. errdebug: __EXPR_DEBUGINFO,
  643. err: err
  644. };
  645. }
  646. break;
  647. //--------------------------------------------------------------------
  648.  
  649. case /^closure/.test(exprBuild.cond):
  650. try {
  651. exprFragPhrase = exprFragPhrase.join().toLowerCase();
  652. exprBuild.op = !(/does\s?n['o]t|!|!=/.test(exprFragPhrase)); //checkbox
  653. exprBuild.op2 = /start|end/.exec(exprFragPhrase) + 's'; //starts/ends
  654. exprBuild.condmod = /before|after|\bin\b/.exec(exprFragPhrase) + ''; //in/before/after
  655. exprBuild.val = /\d+/.exec(exprFragPhrase) + ''; //days ago
  656. } catch (err) {
  657. __EXPR_DEBUGINFO.exprBuild = exprBuild;
  658. return {
  659. errdebug: __EXPR_DEBUGINFO,
  660. err: err
  661. };
  662. }
  663. success = addExpr(exprBuild);
  664. break;
  665.  
  666. default:
  667. // CONDITION NAME MATCHING (TYPE OF SELECTION)
  668. try {
  669. if (/^(?:name.*|^str.*|^cit.*)/.test(exprBuild.cond)) {
  670. exprBuild.cond = exprBuild.cond.replace(/^name.*/, 'street');
  671. exprBuild.cond = exprBuild.cond.replace(/^str.*/, 'street');
  672. exprBuild.cond = exprBuild.cond.replace(/^cit.*/, 'city');
  673. var exprStart = exprFragPhrase.slice(0, -1), //don't include last element bc it should be the name itself
  674. prim, alt;
  675. if (exprStart) {
  676. exprStart = exprStart.toString().toLowerCase();
  677. prim = /\bpri?m?(?:ary|\.)?\b/i.test(exprStart);
  678. alt = /\balt(?:ern\w*|\.)?\b/i.test(exprStart);
  679. } else {
  680. prim = false;
  681. alt = false;
  682. }
  683. if (prim && alt) exprBuild.condmod = 2;
  684. else if (prim) exprBuild.condmod = 0;
  685. else if (alt) exprBuild.condmod = 1;
  686. else exprBuild.condmod = 0;
  687. } else {
  688. exprBuild.cond = exprBuild.cond.replace(/^traf.*|^auto.*/, 'trafic');
  689. exprBuild.cond = exprBuild.cond.replace(/^man.*/, 'manual');
  690. exprBuild.cond = exprBuild.cond.replace(/^dir.*/, 'direction');
  691. exprBuild.cond = exprBuild.cond.replace(/^(?:road)(?:.?(?:type))?|^type/, 'road');
  692. exprBuild.cond = exprBuild.cond.replace(/^last\s.*/, 'last');
  693. exprBuild.cond = exprBuild.cond.replace(/^create.*/, 'created');
  694. exprBuild.cond = exprBuild.cond.replace(/^update.*/, 'updated');
  695. }
  696. } catch (err) {
  697. __EXPR_DEBUGINFO.exprBuild = exprBuild;
  698. return {
  699. errdebug: __EXPR_DEBUGINFO,
  700. err: err
  701. };
  702. }
  703.  
  704. // COMPARATOR OPERATION MATCHING
  705. try {
  706. // Convert natural lang representation to standard comparator operations
  707. exprFragPhraseStr = exprFragPhrase.join(' ').replace(/is less than|is fewer than/i, '<');
  708. exprFragPhraseStr = exprFragPhraseStr.replace(/is greater than/i, '>');
  709. exprFragPhraseStr = exprFragPhraseStr.replace(/is less or equal to|is less than or equal to|is fewer than or equal to|is fewer or equal to/i, '<=');
  710. exprFragPhraseStr = exprFragPhraseStr.replace(/is greater than or equal to|is greater or equal to/i, '>=');
  711. exprFragPhraseStr = exprFragPhraseStr.replace(/(?:does|has|is|was|were|are)(?:\s?n[o']t)(?:\sequal)?/i, '!=');
  712. exprFragPhraseStr = exprFragPhraseStr.replace(/(?:has|have|is|was|were|are)(?:\sequal)?|==/i, '=');
  713. exprFragPhraseStr = exprFragPhraseStr.replace(/(?:do(?:es)?\s?n[o']t\s|!\s?)contains?/i, '! contains');
  714. exprFragPhraseStr = exprFragPhraseStr.replace(/contains?/i, 'contains');
  715.  
  716. // Comparator operations with standard representation
  717. exprBuild.op = /(?:! )?contains|[!<>=~]{1,2}/i.exec(exprFragPhraseStr) + '';
  718. //console.info(exprBuild.op);
  719. } catch (err) {
  720. __EXPR_DEBUGINFO.exprBuild = exprBuild;
  721. return {
  722. errdebug: __EXPR_DEBUGINFO,
  723. err: err
  724. };
  725. }
  726.  
  727. // SELECTION VALUE MATCHING
  728. try {
  729. if (/^length|^last/.test(exprBuild.cond)) {
  730. exprFragPhraseStr = exprFragPhraseStr.replace(/\btoday\b/, 0);
  731. exprFragPhraseStr = exprFragPhraseStr.replace(/\byesterday\b/, 1);
  732. exprBuild.val = exprFragPhraseStr.match(/\b\d+/) + ''
  733. } else {
  734. var exprCondVal = exprFragPhrase.slice(-1)[0];
  735. // Remove surrounding paretheses and quotations
  736. if (/^[('"]+(.*?)['")]+$/.test(exprCondVal)) {
  737. exprBuild.val = exprCondVal.replace(/^[('"\s]+(.*?)[\s'")]+$/, '$1'); //.replace(/["()]/g,'').replace(/^'(.*)'$/,'$1');
  738. } else {
  739. try {
  740. exprBuild.val = exprFragPhraseStr.replace(new RegExp('(?:' + exprBuild.op + ')\\s(\\b(?:\\w\\s?)*\\b)', 'i'), '$1');
  741. } catch (err) {
  742. __EXPR_DEBUGINFO.exprBuild = exprBuild;
  743. return {
  744. errdebug: 2,
  745. err: __EXPR_DEBUGINFO
  746. };
  747. }
  748. }
  749.  
  750.  
  751. // Add flexility to value specification for direction selection
  752. // Also allow user to specify 'oneway' without direction and auto add expr for both directions
  753. if (/^direction/.test(exprBuild.cond)) {
  754. exprBuild.val = exprBuild.val.match(/A[<>-\s]*B|B[<>-\s]*A|^one[\s-]?ways?$|unknown/i) + ''; //reduce to unique key words... last option will automatically input both one ways
  755. exprBuild.val = exprBuild.val.replace(/B[\s<-]*A/, 'A->B');
  756. exprBuild.val = exprBuild.val.replace(/A[\s<-]*B/, 'B->A');
  757. if (/^one[\s-]?ways?$/.test(exprBuild.val)) {
  758. exprBuild.val = 'A->B';
  759. exprBuild.val2 = 'B->A';
  760. }
  761. } else if (/^road/.test(exprBuild.cond)) {
  762. exprBuild.val = exprBuild.val.replace(/^fwy$/i, '^freeway');
  763. exprBuild.val = exprBuild.val.replace(/hwy/i, ''); //not important bc not a unique keyword
  764. exprBuild.val = exprBuild.val.replace(/^MH$/, '^major');
  765. exprBuild.val = exprBuild.val.replace(/^mH$/, '^minor');
  766. exprBuild.val = exprBuild.val.replace(/^ps$|^prim.*/i, '^primary');
  767. exprBuild.val = exprBuild.val.replace(/^st.*/i, '^street');
  768. exprBuild.val = exprBuild.val.replace(/^dirt.*|.*4[\s-]?x[\s-]?4.*/i, '^dirt');
  769. exprBuild.val = exprBuild.val.replace(/^plr$|^pl$|^park.*/i, '^parking');
  770. exprBuild.val = exprBuild.val.replace(/^pr$|^pvtr$|^pvr$|^priv.*/i, '^private');
  771. exprBuild.val = exprBuild.val.replace(/^wt$|^walk.*|.*trl/i, '^walking');
  772. exprBuild.val = exprBuild.val.replace(/^pb$|^ped.*|.*b(?:oard)?w(?:alk)?/i, '^pedestrian');
  773. exprBuild.val = exprBuild.val.replace(/^sw$|^stair.*/i, '^stairway');
  774. exprBuild.val = exprBuild.val.replace(/^rr$|^rail.*/i, '^railroad');
  775. exprBuild.val = exprBuild.val.replace(/^rw$|^tw$|.*run.*|.*taxi.*/i, '^runway');
  776. }
  777. }
  778. success = addExpr(exprBuild);
  779.  
  780. } catch (err) {
  781. __EXPR_DEBUGINFO.exprBuild = exprBuild;
  782. return {
  783. errdebug: __EXPR_DEBUGINFO,
  784. err: err
  785. };
  786. }
  787. } //switch
  788.  
  789. if (closeParens === 2) {
  790. rselBtns.rtParens();
  791. closeParens = 0;
  792. }
  793.  
  794. } //for each condition matched
  795. __EXPR_DEBUGINFO.exprBuild = exprBuild;
  796. if (!success) {
  797. return {
  798. errdebug: __EXPR_DEBUGINFO
  799. }
  800. }
  801. } //updateExpr()
  802.