WME Advanced Closures

Recurrent and imported closures in the Waze Map Editor

目前為 2020-12-01 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name WME Advanced Closures
  3. // @version 2020.12.01.01
  4. // @description Recurrent and imported closures in the Waze Map Editor
  5. // @namespace WMEAC
  6. // @include https://www.waze.com/editor*
  7. // @include https://www.waze.com/*/editor*
  8. // @include https://beta.waze.com/editor*
  9. // @include https://beta.waze.com/*/editor*
  10. // @exclude https://www.waze.com/user/*
  11. // @exclude https://www.waze.com/*/user/*
  12. // @icon data:image/png;base64,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
  13. // @grant unsafeWindow
  14. // @grant GM_xmlhttpRequest
  15. // @connect holidayapi.com
  16. // @copyright 2018, dummyd2, seb-d59, WazeDev
  17. // @author dummyd2, seb-d59, WazeDev
  18. // ==/UserScript==
  19.  
  20.  
  21. /*******
  22. *
  23. * You are free to:
  24. * Share, copy, and redistribute the script in any medium or format
  25. * under the following terms:
  26. * Attribution - You must give appropriate credit. You may do so in any
  27. * reasonable manner, but not in any way that suggests the licensor
  28. * endorses you or your use.
  29. *
  30. * NonCommercial - You may not use the script for commercial purposes.
  31. *
  32. * NoModifications - You may NOT MODIFY the script.
  33. *
  34. * You are invited to contact authors on waze forum for more details.
  35. *
  36. ********/
  37.  
  38. /* global $ */
  39. /* global W */
  40. /* global OpenLayers */
  41. /* global require */
  42. /* global _ */
  43. /* global I18n */
  44. /*jshint multistr: true */
  45.  
  46.  
  47. /***********************************************
  48. *** IN INCLUDED FILE : ***
  49. *** include/downloadHelper.js ***
  50. ***********************************************/
  51.  
  52. /**** DOWNLOAD HELPER **********************/
  53. /******** AUTO INJECTED PART ***************/
  54. function WMEAC_downloadHelperInjected()
  55. {
  56. window.WMEAC_downloadHelper = {
  57. jobs: [],
  58. _waitForData: function (id)
  59. {
  60. if (this.jobs.length<=id)
  61. {
  62. this.jobs[id].callback({url: null, data: null, callback: this.jobs[id].callback, status: "error", error: "Request not found"});
  63. }
  64. else
  65. {
  66. if (this.jobs[id].status=="success" || this.jobs[id].status=="error")
  67. this.jobs[id].callback(this.jobs[id]);
  68. else
  69. {
  70. if (this.jobs[id].status=="downloading" && this.jobs[id].progressCallback)
  71. {
  72. this.jobs[id].progressCallback(this.jobs[id]);
  73. }
  74. var _this=this;
  75. window.setTimeout(function () { _this._waitForData(id); }, 500);
  76. }
  77. }
  78. },
  79. add: function (url, callback, progressCallback)
  80. {
  81. this.jobs.push({url: url, data: null, callback: callback, progressCallback: progressCallback, status: "added", progression: 0, error: ""});
  82. var _this=this;
  83. window.setTimeout(function () { _this._waitForData(_this.jobs.length-1); }, 500);
  84. }
  85. };
  86. }
  87. var WMEAC_downloadHelperInjectedScript = document.createElement("script");
  88. WMEAC_downloadHelperInjectedScript.textContent = '' + WMEAC_downloadHelperInjected.toString() + ' \n' + 'WMEAC_downloadHelperInjected();';
  89. WMEAC_downloadHelperInjectedScript.setAttribute("type", "application/javascript");
  90. document.body.appendChild(WMEAC_downloadHelperInjectedScript);
  91.  
  92. /******** SANDBOX PART ***************/
  93.  
  94. function lookFordownloadHelperJob()
  95. {
  96. for (var i=0; i<unsafeWindow.WMEAC_downloadHelper.jobs.length; i++)
  97. {
  98. if (unsafeWindow.WMEAC_downloadHelper.jobs[i].status=="added")
  99. {
  100. unsafeWindow.WMEAC_downloadHelper.jobs[i].status = cloneInto( "downloading", unsafeWindow.WMEAC_downloadHelper.jobs[i]);
  101. var f = function () {
  102. var job=i;
  103. GM_xmlhttpRequest ( {
  104. method: 'GET',
  105. headers: {"User-Agent": "Mozilla/5.0", "Accept": "text/plain"},
  106. synchronous: false,
  107. timeout: 10000,
  108. url: unsafeWindow.WMEAC_downloadHelper.jobs[job].url,
  109. onerror: function(r) {
  110. unsafeWindow.WMEAC_downloadHelper.jobs[job].status = cloneInto( "error", unsafeWindow.WMEAC_downloadHelper.jobs[job]);
  111. },
  112. ontimeout: function(r) {
  113. console.debug("TOTO Timeout while getting area from server: " , r);
  114. unsafeWindow.WMEAC_downloadHelper.jobs[job].status = cloneInto( "error", unsafeWindow.WMEAC_downloadHelper.jobs[job]);
  115. },
  116. onload: function(r) {
  117. unsafeWindow.WMEAC_downloadHelper.jobs[job].status = cloneInto( "success", unsafeWindow.WMEAC_downloadHelper.jobs[job]);
  118. unsafeWindow.WMEAC_downloadHelper.jobs[job].data = cloneInto( r.responseText, unsafeWindow.WMEAC_downloadHelper.jobs[job]);
  119. },
  120. onprogress: function (r) {
  121. unsafeWindow.WMEAC_downloadHelper.jobs[job].progression = cloneInto( r.total==0?0:(r.loaded/r.total), unsafeWindow.WMEAC_downloadHelper.jobs[job]);
  122. }
  123. } );
  124. }();
  125. }
  126. }
  127. window.setTimeout(lookFordownloadHelperJob, 2000);
  128. }
  129. window.setTimeout(lookFordownloadHelperJob);
  130.  
  131.  
  132. /***********************************************
  133. *** END OF INCLUDED FILE : ***
  134. *** include/downloadHelper.js ***
  135. ***********************************************/
  136.  
  137.  
  138.  
  139. function WMEAC_Injected()
  140. {
  141. // WMEAC object and members:
  142. /***********************************************
  143. *** IN INCLUDED FILE : ***
  144. *** include/globalDeclarations.js ***
  145. ***********************************************/
  146.  
  147.  
  148. var WMEAC={};
  149.  
  150. WMEAC.isDebug=false;
  151.  
  152. WMEAC.ac_version="2020.12.01.01";
  153.  
  154. WMEAC.closureTabTimeout=null;
  155.  
  156. WMEAC.csv=[];
  157.  
  158. WMEAC.csvCurrentClosureList=null;
  159.  
  160. WMEAC.csvCurrentBatchClosureList=null;
  161.  
  162. WMEAC.pendingOps=false;
  163.  
  164. WMEAC.pb = null;
  165.  
  166. WMEAC.daysOfWeek=[ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
  167.  
  168. WMEAC.lastGeneratedHolidays = [];
  169.  
  170. WMEAC.presets=[];
  171.  
  172. /***********************************************
  173. *** END OF INCLUDED FILE : ***
  174. *** include/globalDeclarations.js ***
  175. ***********************************************/
  176.  
  177.  
  178.  
  179. // WMEAC usefull function member
  180. /***********************************************
  181. *** IN INCLUDED FILE : ***
  182. *** include/util.js ***
  183. ***********************************************/
  184.  
  185. WMEAC.getElementsByClassName=function (classname, node) {
  186. if(!node) node = document.getElementsByTagName("body")[0];
  187. var a = [];
  188. var re = new RegExp('\\b' + classname + '\\b');
  189. var els = node.getElementsByTagName("*");
  190. for (var i=0,j=els.length; i<j; i++)
  191. if (re.test(els[i].className)) a.push(els[i]);
  192. return a;
  193. };
  194.  
  195.  
  196. WMEAC.removeChildElements = function (node)
  197. {
  198. while (node.firstChild)
  199. {
  200. WMEAC.removeChildElements(node.firstChild);
  201. node.removeChild(node.firstChild);
  202. }
  203. };
  204.  
  205. WMEAC.createElement = function (options)
  206. {
  207. if (options.hasOwnProperty('type')==false)
  208. return null;
  209. var el=document.createElement(options.type);
  210.  
  211. if (options.hasOwnProperty('id')==true)
  212. el.id=options.id;
  213.  
  214. if (options.hasOwnProperty('className')==true)
  215. el.className=options.className;
  216.  
  217. return el;
  218. };
  219.  
  220. WMEAC.getId = function (node) {
  221. var el = document.getElementById(node);
  222. return el;
  223. };
  224.  
  225. WMEAC.logBeta = function (msg, obj)
  226. {
  227. //log("Beta - " + msg, obj);
  228. };
  229.  
  230. WMEAC.logDebug = function (msg, obj)
  231. {
  232. if (WMEAC.isDebug) WMEAC.log("DEBUG - " + msg, obj);
  233. };
  234.  
  235. WMEAC.logError = function (msg, obj)
  236. {
  237. console.error("Advanced closures v" + WMEAC.ac_version + " - " + msg, obj);
  238. };
  239.  
  240.  
  241. WMEAC.log = function (msg, obj)
  242. {
  243. if (obj==null)
  244. console.log("Advanced closures v" + WMEAC.ac_version + " - " + msg);
  245. else
  246. console.debug("Advanced closures v" + WMEAC.ac_version + " - " + msg + " " ,obj);
  247. };
  248.  
  249. WMEAC.isValidDate = function(d) // http://stackoverflow.com/questions/1353684/detecting-an-invalid-date-date-instance-in-javascript
  250. {
  251. if ( Object.prototype.toString.call(d) === "[object Date]" ) {
  252. // it is a date
  253. if ( isNaN( d.getTime() ) ) { // d.valueOf() could also work
  254. return false;
  255. }
  256. else {
  257. return true;
  258. }
  259. }
  260. else {
  261. return false;
  262. }
  263. };
  264.  
  265. WMEAC.dateToClosureStr = function(d) {
  266. var yyyy = d.getUTCFullYear().toString();
  267. var MM = (d.getUTCMonth()+1).toString(); // getMonth() is zero-based
  268. var dd = d.getUTCDate().toString();
  269. var hh = d.getUTCHours().toString();
  270. var mm = d.getUTCMinutes().toString();
  271. return yyyy + '-' + (MM[1]?MM:"0"+MM[0]) + '-' + (dd[1]?dd:"0"+dd[0]) + ' ' + (hh[1]?hh:"0"+hh[0]) + ':' + (mm[1]?mm:"0"+mm[0]); // padding
  272. };
  273.  
  274.  
  275. // http://stackoverflow.com/questions/8493195/how-can-i-parse-a-csv-string-with-javascript
  276. WMEAC.CSVtoArray = function (text) {
  277. var b = [];
  278. var re_valid = /^\s*(?:'[^'\\]*(?:\\[\S\s][^'\\]*)*'|"[^"\\]*(?:\\[\S\s][^"\\]*)*"|[^,'"\s\\]*(?:\s+[^,'"\s\\]+)*)\s*(?:,\s*(?:'[^'\\]*(?:\\[\S\s][^'\\]*)*'|"[^"\\]*(?:\\[\S\s][^"\\]*)*"|[^,'"\s\\]*(?:\s+[^,'"\s\\]+)*)\s*)*$/;
  279. var re_value = /(?!\s*$)\s*(?:'([^'\\]*(?:\\[\S\s][^'\\]*)*)'|"([^"\\]*(?:\\[\S\s][^"\\]*)*)"|([^,'"\s\\]*(?:\s+[^,'"\s\\]+)*))\s*(?:,|$)/g;
  280. var lines = text.split('\n');
  281. lines.forEach(function (line) {
  282. if (!re_valid.test(line)) return;
  283. var a = []; // Initialize array to receive values.
  284. line.replace(re_value, // "Walk" the string using replace with callback.
  285. function(m0, m1, m2, m3) {
  286. // Remove backslash from \' in single quoted values.
  287. if (m1 !== undefined) a.push(m1.replace(/\\'/g, "'"));
  288. // Remove backslash from \" in double quoted values.
  289. else if (m2 !== undefined) a.push(m2.replace(/\\"/g, '"'));
  290. else if (m3 !== undefined) a.push(m3);
  291. return ''; // Return empty string.
  292. });
  293. // Handle special case of empty last value.
  294. if (/,\s*$/.test(line)) a.push('');
  295. b.push(a);
  296. });
  297. return b;
  298. };
  299.  
  300. WMEAC.segmentsIDsToSegments = function (ids)
  301. {
  302. return ids.filter(function (e) {
  303. return (W.model.segments.objects.hasOwnProperty(e));
  304. }).map (function (e) {
  305. return (W.model.segments.objects[e]);
  306. });
  307. };
  308.  
  309. WMEAC.reloadRoadLayer = function ()
  310. {
  311. var l=W.map.getLayersBy("uniqueName","roads")[0];
  312. l.redraw({force:!0});
  313. l.removeBackBuffer();
  314. W.controller.reloadData();
  315. };
  316.  
  317. WMEAC.reloadClosuresLayer = function (endHandler)
  318. {
  319. var l=W.map.getLayersBy("uniqueName","closures")[0];
  320. l.redraw({force:!0});
  321. W.controller.reloadData();
  322. if (endHandler)
  323. {
  324. var tmp = function reloaded() {
  325. WMEAC.log("Test if reloaded...");
  326. if (WMEAC.pendingOps==true)
  327. {
  328. WMEAC.log("Not yet. Waiting for WME...");
  329. window.setTimeout(reloaded, 500);
  330. }
  331. else
  332. {
  333. endHandler();
  334. }
  335. };
  336. window.setTimeout(tmp, 500);
  337. }
  338. };
  339.  
  340.  
  341. WMEAC.showClosuresLayer = function(show)
  342. {
  343. var l = W.map.getLayersBy("uniqueName", "closures");
  344. if (l.length==1) l[0].setVisibility(show);
  345. };
  346.  
  347. WMEAC.setDraggable = function (element, options)
  348. {
  349. if (!options.hasOwnProperty('controller'))
  350. options.controller=element;
  351. if (!options.hasOwnProperty('container'))
  352. options.container=[$('body')];
  353. options.controller.css({cursor: 'move'});
  354.  
  355. options.controller.on("mousedown", function(e) {
  356. var x = e.pageX-element.offset().left;
  357. var y = e.pageY-element.offset().top;
  358.  
  359. $('body').on("mouseup", function(e) {
  360. options.container.forEach(function (c) {
  361. c.off("mousemove", elemmousemove);
  362. });
  363. });
  364. function elemmousemove (e) {
  365. e.preventDefault();
  366. element.offset({
  367. top: e.pageY - y,
  368. left: e.pageX - x
  369. });
  370. }
  371. options.container.forEach(function (c) {
  372. c.on("mousemove", elemmousemove);
  373. });
  374.  
  375. });
  376. };
  377.  
  378. WMEAC.dateTimeOverlaps = function ( dt1, dt2 )
  379. {
  380. return (dt1.startDate < dt2.endDate && dt1.endDate > dt2.startDate );
  381. };
  382.  
  383. WMEAC.solveOverlaps = function (closureToAdd, existingClosureList, mode)
  384. {
  385. // sort existing closures:
  386. var ecs = existingClosureList.map(function (e) {
  387. return { isNew: false, ref: e, startDate: e.startDate, endDate: e.endDate};
  388. });
  389. // append new
  390. closureToAdd.isNew=true;
  391. ecs.push(closureToAdd);
  392. var changes=true;
  393. while (changes)
  394. {
  395. changes=false;
  396. ecs.sort(function (a, b) {
  397. return (new Date(a.startDate) - new Date(b.startDate));
  398. });
  399.  
  400. for (var i=1; i<ecs.length; i++)
  401. {
  402. if (WMEAC.dateTimeOverlaps(ecs[i-1], ecs[i]))
  403. {
  404. var indexOfNew = i-1;
  405. var indexOfExisting = i;
  406. if (ecs[i].isNew)
  407. {
  408. indexOfNew=i;
  409. indexOfExisting=i-1;
  410. }
  411. var r1 = ecs[indexOfNew];
  412. var r2 = ecs[indexOfExisting];
  413. var range1={};
  414. var range2={};
  415. switch (mode)
  416. {
  417. case 0: // keep existing. return empty
  418. return [];
  419. break;
  420. case 1: // delete existing.
  421. ecs.splice(indexOfExisting, 1);
  422. changes=true;
  423. break;
  424. case 2: // fill: keep all existing and cut/split new
  425. range1.start=new Date(r1.startDate);
  426. range1.end=new Date(r1.endDate);
  427. range2.start=new Date(r2.startDate);
  428. range2.end=new Date(r2.endDate);
  429. changes=true;
  430. if (range1.start>=range2.start && range1.end<=range2.end)
  431. {
  432. ecs.splice(indexOfNew, 1);
  433. }
  434. else if (range1.start<range2.start && range1.end>range2.end)
  435. {
  436. ecs.push({isNew: true, startDate: r2.endDate, endDate: r1.endDate});
  437. r1.endDate=r2.startDate;
  438. }
  439. else if (range1.start<range2.start)
  440. {
  441. r1.endDate=r2.startDate;
  442. }
  443. else //if (range1.end>range2.end)
  444. {
  445. r1.startDate = r2.endDate;
  446. }
  447. break;
  448. case 3: // force: cut/split/delete existing and keep new
  449. range1.start=new Date(r1.startDate);
  450. range1.end=new Date(r1.endDate);
  451. range2.start=new Date(r2.startDate);
  452. range2.end=new Date(r2.endDate);
  453. changes=true;
  454. if (range1.start>range2.start && range1.end<range2.end)
  455. {
  456. ecs.push({isNew: false, startDate: r1.endDate, endDate: r2.endDate, ref: r2.ref});
  457. r2.endDate=r1.startDate;
  458. }
  459. else if (range1.start<=range2.start && range1.end>=range2.end)
  460. {
  461. ecs.splice(indexOfExisting, 1);
  462. }
  463. else if (range1.start<range2.start)
  464. {
  465. r2.startDate=r1.endDate;
  466. }
  467. else //if (range1.end>range2.end)
  468. {
  469. r2.endDate = r1.startDate;
  470. }
  471. break;
  472. }
  473. }
  474. }
  475. }
  476. return ecs;
  477. };
  478.  
  479. // tests:
  480. // WMEAC.solveOverlaps({startDate: '2016-01-10 00:00', endDate: '2016-01-20 00:00'},
  481. // [ {startDate: '2016-01-05 00:00', endDate: '2016-01-15 00:00', reason: 'bla bla'}], 0);
  482. // WMEAC.solveOverlaps({startDate: '2016-01-10 00:00', endDate: '2016-01-20 00:00'},
  483. // [ {startDate: '2016-01-15 00:00', endDate: '2016-01-25 00:00', reason: 'bla bla'}], 0);
  484. // WMEAC.solveOverlaps({startDate: '2016-01-10 00:00', endDate: '2016-01-20 00:00'},
  485. // [ {startDate: '2016-01-05 00:00', endDate: '2016-01-25 00:00', reason: 'bla bla'}], 0);
  486. // WMEAC.solveOverlaps({startDate: '2016-01-10 00:00', endDate: '2016-01-20 00:00'},
  487. // [ {startDate: '2016-01-12 00:00', endDate: '2016-01-18 00:00', reason: 'bla bla'}], 0);
  488. // WMEAC.solveOverlaps({startDate: '2016-01-10 00:00', endDate: '2016-01-20 00:00'},
  489. // [ {startDate: '2016-01-10 00:00', endDate: '2016-01-20 00:00', reason: 'bla bla'}], 0);
  490. // WMEAC.solveOverlaps({startDate: '2016-01-10 00:00', endDate: '2016-01-20 00:00'},
  491. // [ {startDate: '2016-01-05 00:00', endDate: '2016-01-10 00:00', reason: 'bla bla'},
  492. // {startDate: '2016-01-20 00:00', endDate: '2016-01-25 00:00', reason: 'bla bla'}], 0);
  493. // WMEAC.solveOverlaps({startDate: '2016-01-10 00:00', endDate: '2016-01-20 00:00'},
  494. // [ {startDate: '2016-01-05 00:00', endDate: '2016-01-15 00:00', reason: 'bla bla'},
  495. // {startDate: '2016-01-16 00:00', endDate: '2016-01-25 00:00', reason: 'bla bla'}], 0);
  496.  
  497.  
  498. WMEAC.getCountriesFromSegmentSet = function (segs)
  499. {
  500. var cids = segs.map(function (s) {
  501. if (s.attributes.hasOwnProperty('primaryStreetID') && s.attributes.primaryStreetID!=null)
  502. {
  503. var stid = s.attributes.primaryStreetID;
  504. if (W.model.streets.objects.hasOwnProperty(stid))
  505. {
  506. var st = W.model.streets.objects[stid];
  507. if (st.hasOwnProperty('cityID') && st.cityID!=null && typeof st.cityID != 'undefined')
  508. {
  509. var ctid = st.cityID;
  510. if (W.model.cities.objects.hasOwnProperty(ctid))
  511. return W.model.cities.objects[ctid].countryID;
  512. }
  513. }
  514. }
  515. return null;
  516. }).filter(function (cid) {
  517. return (cid!=null);
  518. });
  519. return (W.model.countries.getObjectArray(function (c) {
  520. return cids.indexOf(c.id)!=-1;
  521. }));
  522. };
  523.  
  524. WMEAC.getOppositeClosure = function (closure)
  525. {
  526. return W.model.roadClosures.getObjectArray(function (c) {
  527. return (closure.reason == c.reason &&
  528. closure.startDate == c.startDate &&
  529. closure.endDate == c.endDate &&
  530. closure.segID == c.segID &&
  531. closure.forward != c.forward);
  532. });
  533. };
  534.  
  535. WMEAC.getCityStreetsFromSegmentSet = function (segs)
  536. {
  537. var r={};
  538. function add(city, street)
  539. {
  540. if (!r.hasOwnProperty(city))
  541. r[city]={};
  542. if (!r[city].hasOwnProperty(street))
  543. r[city][street]=0;
  544. r[city][street]++;
  545. }
  546. segs.forEach(function (s) {
  547. var city='noCity';
  548. if (s.attributes.primaryStreetID!=null &&
  549. W.model.streets.objects.hasOwnProperty(s.attributes.primaryStreetID))
  550. {
  551. var st = W.model.streets.objects[s.attributes.primaryStreetID];
  552. if (st.hasOwnProperty('cityID') && st.cityID!=null && typeof st.cityID != 'undefined')
  553. {
  554. var ctid = st.cityID;
  555. if (W.model.cities.objects.hasOwnProperty(ctid))
  556. {
  557. if (!W.model.cities.objects[ctid].isEmpty)
  558. city=W.model.cities.objects[ctid].name;
  559. }
  560. }
  561. if (W.model.streets.objects[s.attributes.primaryStreetID].isEmpty)
  562. add(city, 'noStreet');
  563. else
  564. add(city, W.model.streets.objects[s.attributes.primaryStreetID].name);
  565. }
  566. });
  567. return r;
  568. };
  569.  
  570. WMEAC.download = function (data, filename)
  571. {
  572. var element = document.createElement('a');
  573. element.style.display = 'none';
  574. element.setAttribute('href', encodeURI('data:text/plain,' + data));
  575. element.setAttribute('download', filename);
  576. document.body.appendChild(element);
  577. element.click();
  578. document.body.removeChild(element);
  579. };
  580.  
  581. WMEAC.buildPermalink = function (data)
  582. {
  583. var getvars = [];
  584. for (var m in data)
  585. {
  586. if (data.hasOwnProperty(m))
  587. {
  588. getvars.push('' + m + '=' + data[m]);
  589. }
  590. }
  591. return document.location.protocol + '//' + document.location.host + document.location.pathname + '?' + getvars.join('&amp;');
  592. };
  593.  
  594. WMEAC.sharedClosureDirection = {
  595. A_TO_B: 1,
  596. B_TO_A: 2,
  597. TWO_WAY: 3
  598. };
  599.  
  600. WMEAC.zoomToRoadType = function(e) {
  601. let allRoadTypes = [1,2,3,4,5,6,7,8,9,10,15,16,17,18,19,20,22];
  602. switch (e) {
  603. case 0:
  604. case 1:
  605. return [];
  606. case 2:
  607. return [2, 3, 4, 6, 7, 14];
  608. case 3:
  609. return [2, 3, 4, 6, 7, 8, 9, 10, 14, 16,17, 18, 19, 20, 22];
  610. case 4:
  611. case 5:
  612. case 6:
  613. case 7:
  614. case 8:
  615. case 9:
  616. case 10:
  617. default:
  618. return allRoadTypes;
  619. }
  620. }
  621.  
  622.  
  623.  
  624. /***********************************************
  625. *** END OF INCLUDED FILE : ***
  626. *** include/util.js ***
  627. ***********************************************/
  628.  
  629.  
  630.  
  631. /***********************************************
  632. *** IN INCLUDED FILE : ***
  633. *** include/css.js ***
  634. ***********************************************/
  635.  
  636. var cssElt = WMEAC.createElement({type: "style"});
  637. cssElt.type = "text/css";
  638. var css="";
  639. css += ".slashed:after { content: ''; position: relative; width: 140%; height: 1px; display: block; background: red; transform: rotate(-30deg); margin-top: -50%; margin-left: -20%; }";
  640. css += ".wmeac-sidepanel button { border: none; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; border-top-left-radius: 5px; border-top-right-radius: 5px; background-color: #F1DDDB }";
  641.  
  642. css += "#wmeac-progressBarInfo { display: none; width: 90%; float: left; position: absolute; border-top-left-radius: 5px; border-top-right-radius: 5px; border-bottom-right-radius: 5px; border-bottom-left-radius: 5px; margin-bottom: -100%; background-color: #c9e1e9; z-index: 999; margin: 5px; margin-right: 20px; }";
  643. css += ".wmeac-progressBarBG { margin-top: 2px; margin-bottom: 2px; margin-left: 2px; margin-right: 2px; padding-bottom: 0px; padding-top: 0px; padding-left: 0px; padding-right: 0px; width: 33%; background-color: #93c4d3; border: 3px rgb(147, 196, 211); border-top-left-radius: 5px; border-top-right-radius: 5px; border-bottom-right-radius: 5px; border-bottom-left-radius: 5px; height: 22px;}";
  644. css += ".wmeac-progressBarFG { float: left; position: relative; bottom: 22px; height: 0px; text-align: center; width: 100% }";
  645. css += ".wmeac-button { border: none; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; border-top-left-radius: 5px; border-top-right-radius: 5px; background-color: #F1DDDB; display: inline-block; padding: 6px 12px; cursor: pointer; text-align: center; font-weight: bold; }";
  646. css += ".wmeac-closuredialog { border: 2px solid #F1DDDB; width: 100%; float: left; display: none; position: absolute; padding: 0 0px; border-bottom-left-radius: 10px; border-bottom-right-radius: 10px; border-top-left-radius: 10px; border-top-right-radius: 10px; background-color: #FDEDEB; width: 500px; z-index: 9999; left: 80px; top: 10px;}";
  647. css += ".wmeac-closuredialog button { border: none; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; border-top-left-radius: 5px; border-top-right-radius: 5px; background-color: #F1DDDB; margin: 3px; }";
  648. css += ".wmeac-closuredialog h1 { background-color: #F1DDDB; text-align: center; font-size: medium; margin-top: 0px; padding: 10px;}";
  649. css += ".wmeac-closuredialog .content { padding: 10px;}";
  650. css += ".wmeac-closuredialog .content table { witdh: 100%; border: none; font-size: 10px; text-transform: uppercase;}";
  651. css += ".wmeac-closuredialog .content table tbody tr { vertical-align: top;}";
  652. css += ".wmeac-closuredialog .content table tbody tr td { padding-right: 2px; padding-left: 2px;}";
  653. css += ".wmeac-closuredialog-fromgroup { display: inline-block; }";
  654. css += ".wmeac-nav-tabs>ul { border-bottom: 1px solid #F6C3BE }";
  655. css += ".wmeac-nav-tabs>li { float: left; margin-bottom: -1px; }";
  656. css += ".wmeac-nav-tabs>li>a { border: 1px solid #F6C3BE; border-top-left-radius: 5px; border-top-right-radius: 5px; margin-right: 2px;}";
  657. css += ".wmeac-nav-tabs>li.active>a { background-color: rgba(0, 0, 0, 0); border-bottom: 1px solid #FDEDEB}";
  658. css += ".wmeac-nav-tabs>li:not(.active)>a { background-color: #DADBDC}";
  659. //css += ".wmeac-nav-tabs>li:not(.active)>a:hover { background-color: #DADBDC}";
  660. css += ".wmeac-tab-pane {border: 1px solid #F6C3BE; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; border-top-left-radius: 0px; border-top-right-radius: 0px; padding: 5px;}";
  661. css += ".wmeac-closuredialog .footer { height: 40px; padding: 0 10px;}";
  662. css += "#wmeac-csv-closures-list ul { list-style-type: none; padding: 0px;}";
  663. css += "#wmeac-csv-closures-list ul li { width: 100%; height: 42px; border-radius: 4px; margin-top: 1px; }";
  664. css += "#wmeac-csv-closures-list ul li > * { display: table-cell; vertical-align: middle;}";
  665. css += ".wmeac-csv-closures-list-add { background-color: #C6DFFF; }";
  666. css += ".wmeac-csv-closures-list-remove { background-color: #FFC65F; }";
  667. css += ".wmeac-csv-closures-list-failed { background-color: #FF8585; }";
  668. css += ".wmeac-csv-closures-list-done { background-color: #B9FAB1; }";
  669. css += ".wmeac-csv-closures-list-col-action { width: 14px; min-width: 14px; }";
  670. css += ".wmeac-csv-closures-list-col-lr { font-size: xx-small; width: 100%; }";
  671. css += ".wmeac-csv-closures-list-col-lr > * { height: 14px; overflow-y: hidden; vertical-align: middle; }";
  672. css += ".wmeac-csv-closures-list-col-dates { width: 75px; min-width: 75px; font-size: xx-small; text-align: center; }";
  673. css += ".wmeac-csv-closures-list-col-dates > * { height: 14px; overflow-y: hidden; vertical-align: center; }";
  674. css += ".wmeac-csv-closures-list-col-dir { width: 35px; min-width: 35px; text-align: center; }";
  675. css += ".wmeac-csv-closures-list-col-it { width: 15px; min-width: 15px; }";
  676. css += ".wmeac-csv-closures-list-col-target { width: 15px; min-width: 15px; }";
  677. css += ".wmeac-csv-closures-list-col-apply { width: 15px; min-width: 15px; }";
  678. css += ".wmeac-csv-closures-minilog { font-size: xx-small; font-family: monospace; border: 2px solid #F6C3BE; border-top: none; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; background-color: #FFFFFF; }";
  679. css += "#wmeac-csv-closures-log { font-size: xx-small; font-family: monospace; border: 2px solid #F6C3BE; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; border-top-left-radius: 5px; border-top-right-radius: 5px; padding-top: 8px; position: relative; margin-top: 10px; }";
  680. css += "#wmeac-csv-closures-log:before { content: \"Logs\"; position: absolute; top: -8px; left: 5px; float: left; background: #F6C3BE; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; border-top-left-radius: 5px; border-top-right-radius: 5px; padding: 2px; }";
  681. css += "#wmeac-csv-closures-preview { font-size: small; white-space: nowrap; font-family: monospace; border: 2px solid #F6C3BE; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; border-top-left-radius: 5px; border-top-right-radius: 5px; padding-top: 8px; position: relative; min-height: 20px; }";
  682. css += "#wmeac-csv-closures-preview:before { content: \"Preview\"; position: absolute; top: -8px; left: 5px; float: left; background: #F6C3BE; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; border-top-left-radius: 5px; border-top-right-radius: 5px; padding: 2px; }";
  683. css += ".wmeac-hl:after { content: \"\\f018\"; position: relative; display: block; margin-top: -100%; margin-left: 50%; font-family: FontAwesome; }";
  684. cssElt.innerHTML = css;
  685. document.body.appendChild(cssElt);
  686.  
  687.  
  688. /***********************************************
  689. *** END OF INCLUDED FILE : ***
  690. *** include/css.js ***
  691. ***********************************************/
  692.  
  693.  
  694.  
  695. // boostrap and init (wait for waze UI and objects)
  696. /***********************************************
  697. *** IN INCLUDED FILE : ***
  698. *** include/init.js ***
  699. ***********************************************/
  700.  
  701. WMEAC.bootstrapAC = function ()
  702. {
  703. window.setTimeout(WMEAC.initialize, 500);
  704. };
  705.  
  706.  
  707. WMEAC.initialize = function ()
  708. {
  709. WMEAC.log ("init");
  710. WMEAC.waitForWaze(function () {
  711. WMEAC.load();
  712. WMEAC.log("presets", WMEAC.presets);
  713. WMEAC.initUI();
  714. });
  715. WMEAC.log ("init done");
  716. };
  717.  
  718.  
  719. WMEAC.waitForWaze = function(handler)
  720. {
  721. var APIRequired=[{o: "W"},
  722. {o: "W.model"},
  723. {o: "W.map"},
  724. {o: "W.loginManager"},
  725. {o: "W.vent"},
  726. {o: "W.Config"},
  727. {o: "W.controller"}
  728. ];
  729. for (var i=0; i<APIRequired.length; i++)
  730. {
  731. var path=APIRequired[i].o.split('.');
  732. var object=window;
  733. for (var j=0; j<path.length; j++)
  734. {
  735. object=object[path[j]];
  736. if (typeof object == "undefined" || object == null)
  737. {
  738. window.setTimeout(function () { WMEAC.waitForWaze(handler); }, 500);
  739. return;
  740. }
  741. }
  742. }
  743. var userInfo = WMEAC.getId('user-info');
  744. if (userInfo==null)
  745. {
  746. window.setTimeout(function () { WMEAC.waitForWaze(handler); }, 500);
  747. return;
  748. }
  749.  
  750. var navTabs=userInfo.getElementsByTagName('ul');
  751. if (navTabs.length==0)
  752. {
  753. window.setTimeout(function () { WMEAC.waitForWaze(handler); }, 500);
  754. return;
  755. }
  756. if (typeof(navTabs[0])=='undefined')
  757. {
  758. window.setTimeout(function () { WMEAC.waitForWaze(handler); }, 500);
  759. return;
  760. }
  761.  
  762. var tabContents=userInfo.getElementsByTagName('div');
  763. if (tabContents.length==0)
  764. {
  765. window.setTimeout(function () { WMEAC.waitForWaze(handler); }, 500);
  766. return;
  767. }
  768. if (typeof(tabContents[0])=='undefined')
  769. {
  770. window.setTimeout(function () { WMEAC.waitForWaze(handler); }, 500);
  771. return;
  772. }
  773.  
  774. handler();
  775. };
  776.  
  777.  
  778.  
  779. /***********************************************
  780. *** END OF INCLUDED FILE : ***
  781. *** include/init.js ***
  782. ***********************************************/
  783.  
  784.  
  785.  
  786. // function to setup the UI dom
  787. /***********************************************
  788. *** IN INCLUDED FILE : ***
  789. *** include/setupUI.js ***
  790. ***********************************************/
  791.  
  792. WMEAC.initUI = function ()
  793. {
  794. var addon = WMEAC.createElement({type: 'section', id: 'wmeac-addon'});
  795. WMEAC.pb = new WMEAC.ProgressBar('wmeac-progressBarInfo');
  796. addon.appendChild(WMEAC.pb.divpbi);
  797. var section = WMEAC.createElement({type: 'p', id: 'wmeac-main-title'});
  798. section.style.paddingTop = "0px";
  799. section.style.marginTop = "0px";
  800. section.style.textIndent = "8px";
  801. var title='<b><a target="_blank" href="https://gf.qytechs.cn/scripts/370072-wme-advanced-closures"><u>Advanced Closures</u></a> <a target="_blank" href="https://www.waze.com/forum/viewtopic.php?f=1316&t=193462">Fr</a> <a target="_blank" href="https://www.waze.com/forum/viewtopic.php?f=819&t=261114">En</a> </b> v' + WMEAC.ac_version;
  802. section.innerHTML = title;
  803. addon.appendChild(section);
  804. var divAdvCl = WMEAC.createElement({type: 'div', className: 'wmeac-sidepanel', id:'wmeac-ac'});
  805. var addACBtn = WMEAC.createElement({type: 'div',
  806. id: 'wmeac-add-advanced-closure-button',
  807. className: 'wmeac-button'});
  808. addACBtn.style.width='100%';
  809. addACBtn.innerHTML='<i class="fa fa-clock-o"></i> Add advanced closure';
  810. addACBtn.addEventListener('click', WMEAC.showAddAdvancedClosure);
  811. divAdvCl.appendChild(addACBtn);
  812. var divCSV = WMEAC.createElement({type: 'div', className: 'wmeac-sidepanel', id:'wmeac-csv'});
  813. var csvHTML = '<label for="wmeac-csv-file" class="wmeac-button">Parse CSV</label>\
  814. <input id="wmeac-csv-file" type="file" name="files[]" style="display: none;" />';
  815. csvHTML += '\
  816. <div id="wmeac-csv-closures" style="display: none;">\
  817. <div id="wmeac-csv-closures-controls">\
  818. <input type="checkbox" id="wmeac-csv-closures-controls-check"> | \
  819. <a href="#" id="wmeac-csv-closures-controls-apply">Apply</a> | \
  820. <a href="#" id="wmeac-csv-closures-controls-segs">Check segments</a>\
  821. </div>\
  822. <div id="wmeac-csv-closures-list">\
  823. <ul id="wmeac-csv-closures-list-elts">\
  824. </ul>\
  825. </div>\
  826. </div>\
  827. <div id="wmeac-csv-closures-log">\
  828. </div>';
  829. divCSV.innerHTML = csvHTML;
  830. addon.appendChild(divAdvCl);
  831. addon.appendChild(WMEAC.createElement({type: 'hr'}));
  832. addon.appendChild(divCSV);
  833.  
  834. var userTabs = WMEAC.getId('user-tabs');
  835. var userInfo = WMEAC.getId('user-info');
  836. var sidePanelPrefs = WMEAC.getId('sidepanel-prefs');
  837. var navTabs = WMEAC.getElementsByClassName('nav-tabs', userTabs)[0];
  838. var tabContent = sidePanelPrefs.parentNode;
  839. newtab = WMEAC.createElement({type: 'li'});
  840. newtab.innerHTML = '<a title="Advanced closures" href="#sidepanel-wmeac" data-toggle="tab"><span class="fa fa-road slashed"></span></a>';
  841. navTabs.appendChild(newtab);
  842.  
  843. addon.id = "sidepanel-wmeac";
  844. addon.className = "tab-pane";
  845. addon.style.marginLeft = "-10px";
  846. tabContent.appendChild(addon);
  847.  
  848. var observer = new MutationObserver(function(mutations) {
  849. mutations.forEach(function(mutation) {
  850. function rescurse(node)
  851. {
  852. if (node.id=='segment-edit-closures')
  853. WMEAC.installButtonInClosureTab(node);
  854. else if (node.className=='closures-list')
  855. {
  856. var target = WMEAC.getId('segment-edit-closures');
  857. if (target)
  858. WMEAC.installButtonInClosureTab(target);
  859. }
  860. else
  861. {
  862. for (var j=0; j<node.childNodes.length; j++)
  863. rescurse(node.childNodes[j]);
  864. }
  865. }
  866. for (var i=0; i<mutation.addedNodes.length; i++)
  867. {
  868. rescurse(mutation.addedNodes[i]);
  869. }
  870. });
  871. });
  872. observer.observe(WMEAC.getId('edit-panel'), {childList: true, subtree: true});
  873. // test now if closure tab exists. It happens if WME is opened with a segment id in the url:
  874. WMEAC.installButtonInClosureTab();
  875. //W.selectionManager.events.register("selectionchanged", null, WMEAC.selectionChanged);
  876. W.vent.on("operationPending", function(e) {
  877. if (e.operation.id!="pending.road_data")
  878. return;
  879. WMEAC.pendingOps = true;
  880. });
  881.  
  882. W.vent.on("operationDone", function(e) {
  883. if (e.operation.id!="pending.road_data")
  884. return;
  885. WMEAC.pendingOps = false;
  886. });
  887.  
  888. W.model.events.register("mergeend", null, WMEAC.refreshHighlight);
  889. WMEAC.refreshHighlight();
  890. window.setTimeout(WMEAC.connectAdvancedClosureTabHandlers);
  891. };
  892.  
  893. WMEAC.installButtonInClosureTab = function (node)
  894. {
  895. if (!node)
  896. node=WMEAC.getId('segment-edit-closures');
  897. if (!node) return;
  898. // test if we already there
  899. if ($(node).find('#wmeac-closuretab-add-advanced-closure-button').length==0)
  900. {
  901. var addACBtn = WMEAC.createElement({type: 'div',
  902. id: 'wmeac-closuretab-add-advanced-closure-button',
  903. className: 'wmeac-button'});
  904. addACBtn.style.width='100%';
  905. addACBtn.style.marginBottom='10px';
  906. addACBtn.innerHTML='<i class="fa fa-clock-o"></i> Add advanced closure';
  907. addACBtn.addEventListener('click', WMEAC.showAddAdvancedClosure);
  908. $(node).find('.closures-list').prepend(addACBtn);
  909. }
  910. };
  911.  
  912. WMEAC.showAddAdvancedClosure = function()
  913. {
  914. // init if needed and show modal dialog
  915. var ACDiv = WMEAC.getId('wmeac-add-advanced-closure-dialog');
  916. if (ACDiv==null)
  917. {
  918. ACDiv = WMEAC.createElement({type: 'div',
  919. id: 'wmeac-add-advanced-closure-dialog',
  920. className: 'wmeac-closuredialog'});
  921. ACDiv.innerHTML=WMEAC.HTMLTemplates.advancedClosureDialog;
  922. W.map.getOLMap().div.appendChild(ACDiv);
  923. window.setTimeout(WMEAC.connectAdvancedClosureDialogHandlers);
  924. ACDiv.style.display="none";
  925. //W.selectionManager.events.register("selectionchanged", null, WMEAC.refreshClosureList);
  926. }
  927. if (ACDiv.style.display=="block") // already shown => reset position
  928. {
  929. $(ACDiv).css({left: '80px', top: '20px'});
  930. }
  931. else
  932. {
  933. ACDiv.style.display="block";
  934. W.selectionManager.events.register("selectionchanged", null, WMEAC.refreshClosureList);
  935. W.selectionManager.events.register("selectionchanged", null, WMEAC.refreshClosureListFromSelection);
  936. WMEAC.refreshClosureListFromSelection();
  937. }
  938. //window.setTimeout(function () { $('#wmeac-add-advanced-closure-dialog').find('.input-group-addon').css({display:"table-cell"}); });
  939. $(ACDiv).find('.input-group-addon').css({display:"table-cell"});
  940. WMEAC.showClosuresLayer(true);
  941. };
  942.  
  943. WMEAC.HTMLTemplates={};
  944.  
  945. var rangeStartEndUI ='\
  946. <div class="form-group">\
  947. <label class="control-label" for="closure_rangestartDate">Range start (included)</label>\
  948. <div class="controls">\
  949. <div style="width: 58%" class="date date-input-group input-group pull-left">\
  950. <input id="wmeac-advanced-closure-dialog-rangestartdate" class="form-control start-date" type="text" name="closure_rangestartDate">\
  951. <span class="input-group-addon">\
  952. <i class="fa fa-calendar"></i>\
  953. </span>\
  954. </div>\
  955. </div>\
  956. </div>\
  957. <div class="form-group">\
  958. <label class="control-label" for="closure_rangeendDate">Range end (included)</label>\
  959. <div class="controls">\
  960. <div style="width: 58%" class="date date-input-group input-group pull-left">\
  961. <input id="wmeac-advanced-closure-dialog-rangeenddate" class="form-control end-date" type="text" name="closure_rangeendDate">\
  962. <span class="input-group-addon">\
  963. <i class="fa fa-calendar"></i>\
  964. </span>\
  965. </div>\
  966. </div>\
  967. </div>';
  968.  
  969. var startTimeAndDurationUI = '\
  970. <div class="wmeac-closuredialog-fromgroup">\
  971. <label class="control-label" for="closure_startTime">Start</label>\
  972. <div class="controls">\
  973. <div style="width: 58%;" class="bootstrap-timepicker input-group pull-left">\
  974. <input id="wmeac-advanced-closure-dialog-starttime" class="form-control start-time" type="text" name="closure_startTime">\
  975. <span class="input-group-addon">\
  976. <i class="fa fa-clock-o"></i>\
  977. </span>\
  978. </div>\
  979. </div>\
  980. </div>\
  981. <div class="wmeac-closuredialog-fromgroup">\
  982. <label class="control-label">Duration</label>\
  983. <div style="width: 58%;" class="bootstrap-timepicker input-group">\
  984. <div class="controls" style="display: flex;">\
  985. <span class="input-group-addon pull-left">\
  986. <i class="fa fa-step-forward"></i>\
  987. </span>\
  988. <span class="form-control" style="padding: 1px; display: flex">\
  989. <input id="wmeac-advanced-closure-dialog-duration-day" name="value" value=0 size=3/>\
  990. <span style="padding: 5px;">D</span>\
  991. </span>\
  992. </div>\
  993. <div class="bootstrap-timepicker input-group pull-left">\
  994. <input id="wmeac-advanced-closure-dialog-durationtime" class="form-control start-time" type="text" name="closure_durationTime">\
  995. <span class="input-group-addon">\
  996. <i class="fa fa-clock-o"></i>\
  997. </span>\
  998. </div>\
  999. </div>\
  1000. </div>\
  1001. ';
  1002. var descriptionUI = '\
  1003. <div class="form-group">\
  1004. <label class="control-label" for="closure_reason">Description</label>\
  1005. <div class="controls">\
  1006. <input id="wmeac-advanced-closure-dialog-reason" class="form-control" type="text" name="closure_reason">\
  1007. </div>\
  1008. </div>\
  1009. ';
  1010.  
  1011. var locationUI = '\
  1012. <div class="form-group">\
  1013. <label class="control-label" for="closure_location">Location</label>\
  1014. <div class="controls">\
  1015. <input id="wmeac-advanced-closure-dialog-location" class="form-control" type="text" name="closure_location">\
  1016. </div>\
  1017. </div>\
  1018. ';
  1019.  
  1020. var directionUI = '\
  1021. <div class="form-group">\
  1022. <label class="control-label" for="closure_direction">Direction</label>\
  1023. <div class="controls">\
  1024. <select id="wmeac-advanced-closure-dialog-direction" style="font-family:\'FontAwesome\', Arial;" class="form-control" name="closure_direction">\
  1025. <option value="3">Two way (&#xf0ec;)</option><option value="1">One way (A &#8594; B)</option><option value="2">One way (B &#8594; A)</option>\
  1026. </select>\
  1027. </div>\
  1028. </div>\
  1029. ';
  1030.  
  1031. var ignoreTrafficUI = '\
  1032. <div class="checkbox">\
  1033. <label class="control-label" style="font-weight: bold;">\
  1034. <input id="wmeac-advanced-closure-dialog-ignoretraffic" type="checkbox" name="closure_permanent">\
  1035. Ignore Traffic\
  1036. </label>\
  1037. </div>\
  1038. ';
  1039.  
  1040. var MTEUI = '\
  1041. <div class="form-group">\
  1042. <label class="control-label control-label-inline" for="closure_MTE">Link to MTE</label>\
  1043. <div class="controls">\
  1044. <select id="wmeac-advanced-closure-dialog-mteid" class="form-control" name="closure_MTE" disabled><option value="">None</option></select>\
  1045. </div>\
  1046. </div>\
  1047. ';
  1048.  
  1049.  
  1050. var overlapModeUI = '\
  1051. <div class="form-group">\
  1052. <label class="control-label" for="closure_overlap">Overlap action</label>\
  1053. <div class="controls">\
  1054. <select id="wmeac-advanced-closure-dialog-overlap" style="font-family:\'FontAwesome\', Arial;" class="form-control" name="closure_overlap">\
  1055. <option value="0">Keep existing</option><option value="1">Delete existing</option><option value="2">Fill with new</option><option value="3">Force new</option>\
  1056. </select>\
  1057. </div>\
  1058. </div>\
  1059. ';
  1060.  
  1061.  
  1062. var tabRepeatUI = '\
  1063. <div style="width: 150px;" class="input-group">\
  1064. <div class="controls">\
  1065. <div class="input-group pull-left">\
  1066. <input id="wmeac-advanced-closure-dialog-repeat-ntimes" class="form-control" type="text" name="closure_repeat_ntimes">\
  1067. <span class="input-group-addon" for="closure_repeat_ntimes">times</span>\
  1068. </div>\
  1069. </div>\
  1070. </div>\
  1071. <div style="width: 150px;" class="input-group">\
  1072. <div class="controls">\
  1073. <div style="width: 150px;" class="bootstrap-timepicker input-group">\
  1074. <span class="input-group-addon">\
  1075. every\
  1076. </span>\
  1077. <span class="form-control" style="padding: 1px; display: flex">\
  1078. <input id="wmeac-advanced-closure-dialog-repeat-every-day" name="value" value=0 size=3/>\
  1079. <span style="padding: 5px;">D</span>\
  1080. <input id="wmeac-advanced-closure-dialog-repeat-every-hour" name="value" value=0 size=3/>\
  1081. <span style="padding: 5px;">H</span>\
  1082. <input id="wmeac-advanced-closure-dialog-repeat-every-minute" name="value" value=0 size=2/>\
  1083. <span style="padding: 5px;">M</span>\
  1084. </span>\
  1085. </div>\
  1086. </div>\
  1087. </div>\
  1088. ';
  1089.  
  1090. var daysOfWeekUI = _(I18n.translations[I18n.locale].date.abbr_day_names).clone();
  1091. daysOfWeekUI.push(daysOfWeekUI.shift());
  1092. var tabEachUI = '<div class="box" style="display:flex; flex-wrap:wrap;">\
  1093. <div style="width:100%;">\
  1094. <label class="control-label" style="font-weight: bold;">\
  1095. <input id="wmeac-advanced-closure-dialog-each-dayall" type="checkbox" name="closure_each_dayall">\
  1096. All\
  1097. </label>\
  1098. </div>\
  1099. ' +
  1100. daysOfWeekUI.map(function (d, i) {
  1101. return '<div style="width:14%;">\
  1102. <label class="control-label" style="font-weight: bold;">\
  1103. <input id="wmeac-advanced-closure-dialog-each-' + ((i+1)%7) + '" type="checkbox" name="closure_each_' + d + '">\
  1104. ' + d + '\
  1105. </label>\
  1106. </div>\
  1107. ';
  1108. }).join('') + '</div>';
  1109.  
  1110. var tabHolidayUI = '\
  1111. <div class="content">\
  1112. <a id="wmeac-advanced-closure-dialog-holiday-refresh" href="#">Refresh holidays</a><br>\
  1113. <i id="wmeac-advanced-closure-dialog-holiday-refresh-spinner" class="fa fa-spinner fa-pulse fa-3x fa-fw" style="display: none;"></i>\
  1114. <div id="wmeac-advanced-closure-dialog-holiday-list" class="form-group" style="overflow-y: scroll; max-height: 200px;">\
  1115. </div>\
  1116. </div>\
  1117. ';
  1118.  
  1119. var tabPresetsUI = '\
  1120. <div class="content">\
  1121. <table><tr><td style="width: 50%; border-right: 1px solid #F6C3BE; padding-right: 5px;">\
  1122. <div class="form-group">\
  1123. <label class="control-label" for="presets_load">Load preset</label>\
  1124. <div class="controls">\
  1125. <div class="input-group">\
  1126. <select style="width: 100%;" id="wmeac-advanced-closure-dialog-presets-list" name="presets_load">\
  1127. </select>\
  1128. <span id="wmeac-advanced-closure-dialog-presets-load" class="input-group-addon">\
  1129. <i class="fa fa-folder-open-o"></i>\
  1130. </span>\
  1131. <span id="wmeac-advanced-closure-dialog-presets-delete" class="input-group-addon">\
  1132. <i class="fa fa-trash"></i>\
  1133. </span>\
  1134. </div>\
  1135. </div>\
  1136. <label class="control-label" for="seg_load">Load from segment</label>\
  1137. <div class="controls">\
  1138. <div class="input-group">\
  1139. <select style="width: 100%;" id="wmeac-advanced-closure-dialog-segclosure-list" name="presets_load">\
  1140. </select>\
  1141. <span id="wmeac-advanced-closure-dialog-presets-load-fromseg" class="input-group-addon">\
  1142. <i class="fa fa-share"></i>\
  1143. </span>\
  1144. </div>\
  1145. </div>\
  1146. </div>\
  1147. </td><td style="padding-left: 5px;">\
  1148. <div class="form-group">\
  1149. <label class="control-label" for="presets_save">Save preset</label>\
  1150. <div class="controls">\
  1151. <div class="input-group pull-left">\
  1152. <input id="wmeac-advanced-closure-dialog-presets-name" class="form-control" type="text" name="presets_save">\
  1153. <span id="wmeac-advanced-closure-dialog-presets-save" class="input-group-addon">\
  1154. <i class="fa fa-floppy-o"></i>\
  1155. </span>\
  1156. </div>\
  1157. </div>\
  1158. </div>\
  1159. </td></tr></table>\
  1160. </div>\
  1161. ';
  1162.  
  1163. var tabsUI ='\
  1164. <ul class="nav wmeac-nav-tabs">\
  1165. <li class="active">\
  1166. <a id="wmeac-advanced-closure-dialog-repeat" data-toggle="tab" href="#wmeac-advanced-closure-dialog-tabrepeat">Repeat</a>\
  1167. </li>\
  1168. <li>\
  1169. <a id="wmeac-advanced-closure-dialog-each" data-toggle="tab" href="#wmeac-advanced-closure-dialog-tabeach">Each</a>\
  1170. </li>\
  1171. <li>\
  1172. <a id="wmeac-advanced-closure-dialog-holiday" data-toggle="tab" href="#wmeac-advanced-closure-dialog-tabholiday">Holidays</a>\
  1173. </li>\
  1174. <li style="float: right;">\
  1175. <a id="wmeac-advanced-closure-dialog-presets" data-toggle="tab" href="#wmeac-advanced-closure-dialog-tabpresets"><i class="fa fa-floppy-o"></i></a>\
  1176. </li>\
  1177. </ul>\
  1178. <div class="tab-content">\
  1179. <div class="tab-pane active wmeac-tab-pane" id="wmeac-advanced-closure-dialog-tabrepeat">\
  1180. ' + tabRepeatUI + '\
  1181. </div>\
  1182. <div class="tab-pane wmeac-tab-pane" id="wmeac-advanced-closure-dialog-tabeach">\
  1183. ' + tabEachUI + '\
  1184. </div>\
  1185. <div class="tab-pane wmeac-tab-pane" id="wmeac-advanced-closure-dialog-tabholiday">\
  1186. ' + tabHolidayUI + '\
  1187. </div>\
  1188. <div class="tab-pane wmeac-tab-pane" id="wmeac-advanced-closure-dialog-tabpresets">\
  1189. ' + tabPresetsUI + '\
  1190. </div>\
  1191. </div>';
  1192. var footerUI = '\
  1193. <div class="footer">\
  1194. <div id="wmeac-csv-closures-preview"><div id="wmeac-csv-closures-preview-content" style="overflow: scroll; max-height: 100px;"></div></div>\
  1195. <button style="float: left;" id="wmeac-advanced-closure-dialog-exportCSV-button">Export CSV</button>\
  1196. <button style="float: right;" id="wmeac-advanced-closure-dialog-close-button">Close</button>\
  1197. <button style="float: right;" id="wmeac-advanced-closure-dialog-apply-button">Apply</button>\
  1198. </div>';
  1199.  
  1200. WMEAC.HTMLTemplates.advancedClosureDialog='\
  1201. <h1>Advanced closures</h1>\
  1202. <div class="content">\
  1203. <table>\
  1204. <tr>\
  1205. <td style="width: 50%;">' +
  1206. rangeStartEndUI + startTimeAndDurationUI +
  1207. '\
  1208. </td>\
  1209. <td>' +
  1210. descriptionUI + directionUI + ignoreTrafficUI + MTEUI +// overlapModeUI +
  1211. '\
  1212. </td>\
  1213. </tr>\
  1214. </table>' +
  1215. tabsUI +
  1216. '</div>' + footerUI;
  1217.  
  1218.  
  1219.  
  1220. WMEAC.connectAdvancedClosureDialogHandlers = function ()
  1221. {
  1222. var e = null;
  1223. e=WMEAC.getId('wmeac-advanced-closure-dialog-exportCSV-button');
  1224. if (e)
  1225. {
  1226. e.addEventListener('click', function() {
  1227. var rc = WMEAC.buildClosuresListFromRecurringUI();
  1228. if (rc.error!="")
  1229. {
  1230. alert("Can't apply closures.\nPlease, check all parameters.");
  1231. return;
  1232. }
  1233. if (W.selectionManager.getSelectedFeatures().length==0 || W.selectionManager.getSelectedFeatures()[0].model.type!="segment")
  1234. {
  1235. alert("Please, select segment(s) before.");
  1236. return;
  1237. }
  1238. var reason = $('#wmeac-advanced-closure-dialog-reason').val();
  1239. //var cllocation = $('#wmeac-advanced-closure-dialog-location').val();
  1240. var direction = $('#wmeac-advanced-closure-dialog-direction').val();
  1241. var isIT = $('#wmeac-advanced-closure-dialog-ignoretraffic').is(':checked');
  1242. var mteId = $("#wmeac-advanced-closure-dialog-mteid").val();
  1243. var mte = W.model.majorTrafficEvents.getObjectById(mteId);
  1244. closureList = rc.list.map(function (e) {
  1245. //return {reason: reason, direction: direction, startDate: e.start, endDate: e.end, location: cllocation, permanent: isIT};
  1246. var details = {reason: reason, direction: direction, startDate: e.start, endDate: e.end, location: "", permanent: isIT};
  1247. if (mte)
  1248. details.eventId = mte.id;
  1249. return details;
  1250. });
  1251. // save selection list
  1252. var selection = _.map(W.selectionManager.getSelectedFeatures(), 'model');
  1253. var selectionReversed=[];
  1254. if (direction!='3') // not two way
  1255. {
  1256. var rev = W.selectionManager.getReversedSegments();
  1257. selection=selection.filter(function (e) {
  1258. if (rev[e.attributes.id])
  1259. {
  1260. selectionReversed.push(e);
  1261. return false;
  1262. }
  1263. return true;
  1264. });
  1265. }
  1266. var lonlat=W.map.getCenter().transform(W.map.getProjectionObject(), "EPSG:4326");
  1267. var csv = 'header,reason,start date (yyyy-mm-dd hh:mm),end date (yyyy-mm-dd hh:mm),direction (A to B|B to A|TWO WAY),ignore trafic (Yes|No),segment IDs (id1;id2;...),lon/lat (like in a permalink: lon=xxx&lat=yyy),zoom (2 to 10),MTE id (empty cell if not),comment (optional)\n';
  1268. closureList.forEach(function (e) {
  1269. csv+='add,"' + e.reason + '","' + e.startDate + '","' + e.endDate + '","' + (direction==3?"TWO WAY":(direction==2?"B to A":"A to B")) + '",' + (isIT?"Yes":"No") + ',"' + selection.map(function (s) { return s.attributes.id;}).join(';') + '","lon=' + lonlat.lon + '&lat=' + lonlat.lat + '",' + W.map.zoom + ',' + mteId + ',"Generated by WMEAC"\n';
  1270. });
  1271. if (!selectionReversed.length==0)
  1272. {
  1273. closureList.forEach(function (e) {
  1274. csv+='add,"' + e.reason + '","' + e.startDate + '","' + e.endDate + '","' + (direction==3?"TWO WAY":(direction==2?"A to B":"B to A")) + '",' + (isIT?"Yes":"No") + ',"' + selectionReversed.map(function (s) { return s.attributes.id;}).join(';') + '","lon=' + lonlat.lon + '&lat=' + lonlat.lat + '",' + W.map.zoom + ',' + mteId + ',"Generated by WMEAC"\n';
  1275. });
  1276. }
  1277. WMEAC.download(csv, 'closures.csv');
  1278. });
  1279. }
  1280. e=WMEAC.getId('wmeac-advanced-closure-dialog-close-button');
  1281. if (e)
  1282. {
  1283. e.addEventListener('click', function() {
  1284. var d = WMEAC.getId('wmeac-add-advanced-closure-dialog');
  1285. if (d)
  1286. {
  1287. W.selectionManager.events.unregister("selectionchanged", null, WMEAC.refreshClosureList);
  1288. W.selectionManager.events.unregister("selectionchanged", null, WMEAC.refreshClosureListFromSelection);
  1289. d.style.display='none';
  1290. }
  1291. });
  1292. }
  1293.  
  1294. e=WMEAC.getId('wmeac-advanced-closure-dialog-apply-button');
  1295. if (e)
  1296. {
  1297. e.addEventListener('click', function() {
  1298. var rc = WMEAC.buildClosuresListFromRecurringUI();
  1299. if (rc.error!="")
  1300. {
  1301. alert("Can't apply closures.\nPlease, check all parameters.");
  1302. return;
  1303. }
  1304. if (W.selectionManager.getSelectedFeatures().length==0 || W.selectionManager.getSelectedFeatures()[0].model.type!="segment")
  1305. {
  1306. alert("Please, select segment(s) before.");
  1307. return;
  1308. }
  1309. if (W.selectionManager.getSelectedFeatures().every(function (e) {
  1310. return e.model.isAllowed(e.model.permissionFlags.EDIT_CLOSURES);
  1311. })==false)
  1312. {
  1313. alert("You don't have permission to edit closures on all those segments.");
  1314. return;
  1315. }
  1316. var reason = $('#wmeac-advanced-closure-dialog-reason').val();
  1317. //var cllocation = $('#wmeac-advanced-closure-dialog-location').val();
  1318. var direction = $('#wmeac-advanced-closure-dialog-direction').val();
  1319. var sc = WMEAC.WMEAPI.require("Waze/Modules/Closures/Models/SharedClosure");
  1320. direction=(direction=="1"?WMEAC.sharedClosureDirection.A_TO_B:(direction=="2"?WMEAC.sharedClosureDirection.B_TO_A:WMEAC.sharedClosureDirection.TWO_WAY));
  1321. var directionStr = direction==1?"(A &#8594; B)":(direction==2?"(B &#8594; A)":"(&#8646;)");
  1322. var isIT = $('#wmeac-advanced-closure-dialog-ignoretraffic').is(':checked');
  1323. var mte = W.model.majorTrafficEvents.getObjectById($("#wmeac-advanced-closure-dialog-mteid").val());
  1324. closureList = rc.list.map(function (e) {
  1325. //return {reason: reason, direction: direction, startDate: e.start, endDate: e.end, location: cllocation, permanent: isIT};
  1326. var details = {reason: reason, direction: direction, startDate: e.start, endDate: e.end, location: "", permanent: isIT};
  1327. if (mte)
  1328. details.eventId = mte.id;
  1329. return details;
  1330. });
  1331. // save selection list
  1332. var selection = _.map(W.selectionManager.getSelectedFeatures(), 'model');
  1333. W.selectionManager.events.unregister("selectionchanged", null, WMEAC.refreshClosureList);
  1334. WMEAC.addClosureListFromSelection(closureList, function (i, e) {
  1335. $('#wmeac-advanced-closure-dialog-preview-' + i).html(e).css({color: "#44D544"});
  1336. }, function (i, e) {
  1337. $('#wmeac-advanced-closure-dialog-preview-' + i).html(e).css({color: "#D5444F"});
  1338. }, function () {
  1339. W.selectionManager.setSelectedModels(selection);
  1340. //alert ('done');
  1341. var tmp = function selectionReady()
  1342. {
  1343. if (W.selectionManager.getSelectedFeatures().length==0)
  1344. window.setTimeout(selectionReady, 500);
  1345. else
  1346. {
  1347. W.selectionManager.events.register("selectionchanged", null, WMEAC.refreshClosureList);
  1348. $('a[href="#segment-edit-closures"]').click();
  1349. }
  1350. };
  1351. window.setTimeout(tmp, 500);
  1352. }, 0);
  1353. });
  1354. }
  1355. if (typeof $.fn.datepicker !== 'undefined')
  1356. $("#wmeac-advanced-closure-dialog-rangestartdate,#wmeac-advanced-closure-dialog-rangeenddate").datepicker({ format: "yyyy-mm-dd", todayHighlight: !0, autoclose: !0});
  1357. else if (typeof $.fn.daterangepicker !== 'undefined') // WME beta
  1358. $("#wmeac-advanced-closure-dialog-rangestartdate,#wmeac-advanced-closure-dialog-rangeenddate").daterangepicker({singleDatePicker: !0,
  1359. locale: {
  1360. format: "YYYY-MM-DD"
  1361. }});
  1362. $("#wmeac-advanced-closure-dialog-rangestartdate,#wmeac-advanced-closure-dialog-rangeenddate").on("change", function () { WMEAC.refreshMTEList(); });
  1363. $("#wmeac-advanced-closure-dialog-starttime,#wmeac-advanced-closure-dialog-durationtime").timepicker({ defaultTime: "00:00", showMeridian: !1, template: !1});
  1364. $("#wmeac-add-advanced-closure-dialog").find(".input-group").find(".input-group-addon").on("click", function (e) {
  1365. $(e.target).parent().find("input").focus();
  1366. }).find("i").on("click", function (e) {
  1367. $(e.target).parent().parent().find("input").focus();
  1368. });
  1369. $('#wmeac-advanced-closure-dialog-each-dayall').on('click', function () {
  1370. var atLeastOneChecked=false;
  1371. for (var i=0; i<7; i++)
  1372. atLeastOneChecked = atLeastOneChecked || $("#wmeac-advanced-closure-dialog-each-"+i).is(':checked');
  1373. for (var i=0; i<7; i++)
  1374. $("#wmeac-advanced-closure-dialog-each-"+i).prop('checked', !atLeastOneChecked);
  1375. $('#wmeac-advanced-closure-dialog-each-dayall').prop('checked', !atLeastOneChecked);
  1376. });
  1377. if (typeof $.fn.spinner !== 'undefined')
  1378. {
  1379. $('#wmeac-advanced-closure-dialog-repeat-every-day').spinner({
  1380. min: 0,
  1381. spin: function (event, ui) {
  1382. $(this).trigger('change');
  1383. }
  1384. });
  1385. $('#wmeac-advanced-closure-dialog-repeat-every-hour').spinner({
  1386. min: 0,
  1387. spin: function (event, ui) {
  1388. if (ui.value >= 24) {
  1389. $(this).spinner('value', ui.value - 24);
  1390. $('#wmeac-advanced-closure-dialog-repeat-every-day').spinner('stepUp');
  1391. return false;
  1392. } else if (ui.value < 0) {
  1393. $(this).spinner('value', ui.value + 24);
  1394. $('#wmeac-advanced-closure-dialog-repeat-every-day').spinner('stepDown');
  1395. return false;
  1396. }
  1397. $(this).trigger('change');
  1398. }
  1399. });
  1400. $('#wmeac-advanced-closure-dialog-repeat-every-minute').spinner({
  1401. spin: function (event, ui) {
  1402. if (ui.value >= 60) {
  1403. $(this).spinner('value', ui.value - 60);
  1404. $('#wmeac-advanced-closure-dialog-repeat-every-hour').spinner('stepUp');
  1405. return false;
  1406. } else if (ui.value < 0) {
  1407. $(this).spinner('value', ui.value + 60);
  1408. $('#wmeac-advanced-closure-dialog-repeat-every-hour').spinner('stepDown');
  1409. return false;
  1410. }
  1411. $(this).trigger('change');
  1412. },
  1413. change: function (event) {
  1414. if (event.target.value<0 || event.target.value>59)
  1415. $(this).spinner('value', 0);
  1416. }
  1417. });
  1418. $('#wmeac-advanced-closure-dialog-duration-day').spinner({
  1419. min: 0,
  1420. spin: function (event, ui) {
  1421. $(this).trigger('change');
  1422. }
  1423. });
  1424. // $('#wmeac-advanced-closure-dialog-duration-hour').spinner({
  1425. // min: 0,
  1426. // spin: function (event, ui) {
  1427. // $(this).trigger('change');
  1428. // }
  1429. // });
  1430. // $('#wmeac-advanced-closure-dialog-duration-minute').spinner({
  1431. // spin: function (event, ui) {
  1432. // if (ui.value >= 60) {
  1433. // $(this).spinner('value', ui.value - 60);
  1434. // $('#wmeac-advanced-closure-dialog-duration-hour').spinner('stepUp');
  1435. // return false;
  1436. // } else if (ui.value < 0) {
  1437. // $(this).spinner('value', ui.value + 60);
  1438. // $('#wmeac-advanced-closure-dialog-duration-hour').spinner('stepDown');
  1439. // return false;
  1440. // }
  1441. // $(this).trigger('change');
  1442. // },
  1443. // change: function (event) {
  1444. // if (event.target.value<0 || event.target.value>59)
  1445. // $(this).spinner('value', 0);
  1446. // }
  1447. // });
  1448. }
  1449. $('#wmeac-advanced-closure-dialog-repeat,#wmeac-advanced-closure-dialog-each,#wmeac-advanced-closure-dialog-holiday').on('click', function(e){
  1450. window.setTimeout(WMEAC.refreshClosureList);
  1451. });
  1452. $('#wmeac-advanced-closure-dialog-holiday-refresh').on('click', function (e) {
  1453. var hDiv = $('#wmeac-advanced-closure-dialog-holiday-list');
  1454. $('#wmeac-advanced-closure-dialog-holiday-refresh-spinner').css({display: 'block'});
  1455. WMEAC.removeChildElements(hDiv[0]);
  1456. window.setTimeout(function () {
  1457. WMEAC.getHolidays({
  1458. rangeStart: $('#wmeac-advanced-closure-dialog-rangestartdate').val(),
  1459. rangeEnd: $('#wmeac-advanced-closure-dialog-rangeenddate').val(),
  1460. countries: _.map(WMEAC.getCountriesFromSegmentSet(_.map(W.selectionManager.getSelectedFeatures(), 'model')), 'abbr'),
  1461. handlerFinished: function (holidays)
  1462. {
  1463. WMEAC.lastGeneratedHolidays = holidays;
  1464. if (holidays.length==0)
  1465. hDiv.html("No holiday found.");
  1466. else
  1467. {
  1468. holidays.forEach(function (h, i) {
  1469. var chkBx = WMEAC.createElement({type: "div", className: "checkbox"});
  1470. chkBx.innerHTML='<label class="control-label" style="font-weight: bold;">\
  1471. <input id="wmeac-advanced-closure-dialog-holidays-' + i + '" type="checkbox">\
  1472. ' + h.date + ': ' + h.name + ' (' + h.country + ')\
  1473. </label>\
  1474. ';
  1475. $(chkBx).on('click', function(e){
  1476. window.setTimeout(WMEAC.refreshClosureList);
  1477. });
  1478. hDiv.append(chkBx);
  1479. });
  1480. }
  1481. $('#wmeac-advanced-closure-dialog-holiday-refresh-spinner').css({display: 'none'});
  1482. }
  1483. });
  1484. });
  1485. });
  1486. $('#wmeac-add-advanced-closure-dialog').on('change', function(e){
  1487. window.setTimeout(WMEAC.refreshClosureList);
  1488. });
  1489. WMEAC.reloadPresets();
  1490. $('#wmeac-advanced-closure-dialog-presets-load').on('click', function(e){
  1491. var presetIndex = parseInt($("#wmeac-advanced-closure-dialog-presets-list").val());
  1492. $("#wmeac-advanced-closure-dialog-starttime").val(WMEAC.presets[presetIndex].values.starttime);
  1493. // $("#wmeac-advanced-closure-dialog-duration-hour").val(WMEAC.presets[presetIndex].values.duration.hour);
  1494. // $("#wmeac-advanced-closure-dialog-duration-minute").val(WMEAC.presets[presetIndex].values.duration.minute);
  1495. if (WMEAC.presets[presetIndex].values.duration.hasOwnProperty('day'))
  1496. $("#wmeac-advanced-closure-dialog-duration-day").val(WMEAC.presets[presetIndex].values.duration.day);
  1497. else
  1498. $("#wmeac-advanced-closure-dialog-duration-day").val(Math.floor(WMEAC.presets[presetIndex].values.duration.hour/24));
  1499. $("#wmeac-advanced-closure-dialog-durationtime").val('' + (WMEAC.presets[presetIndex].values.duration.hour%24) + ':' + WMEAC.presets[presetIndex].values.duration.minute);
  1500. $("#wmeac-advanced-closure-dialog-reason").val(WMEAC.presets[presetIndex].values.description);
  1501. //$("#wmeac-advanced-closure-dialog-location").val(WMEAC.presets[presetIndex].values.location);
  1502. $("#wmeac-advanced-closure-dialog-direction").val(WMEAC.presets[presetIndex].values.direction);
  1503. $("#wmeac-advanced-closure-dialog-ignoretraffic").prop('checked', WMEAC.presets[presetIndex].values.ignoretraffic);
  1504. $("#wmeac-advanced-closure-dialog-repeat-ntimes").val(WMEAC.presets[presetIndex].values.repeat.ntimes);
  1505. if (WMEAC.presets[presetIndex].values.repeat.hasOwnProperty('day'))
  1506. $("#wmeac-advanced-closure-dialog-repeat-every-day").val(WMEAC.presets[presetIndex].values.repeat.day);
  1507. else
  1508. $("#wmeac-advanced-closure-dialog-repeat-every-day").val(Math.floor(WMEAC.presets[presetIndex].values.repeat.hour/24));
  1509. $("#wmeac-advanced-closure-dialog-repeat-every-hour").val(WMEAC.presets[presetIndex].values.repeat.hour%24);
  1510. $("#wmeac-advanced-closure-dialog-repeat-every-minute").val(WMEAC.presets[presetIndex].values.repeat.minute);
  1511. for (var i=0; i<7; i++)
  1512. $("#wmeac-advanced-closure-dialog-each-"+i).prop('checked', WMEAC.presets[presetIndex].values.each[i]);
  1513. });
  1514.  
  1515. $('#wmeac-advanced-closure-dialog-presets-load-fromseg').on('click', function () {
  1516. closureId = $("#wmeac-advanced-closure-dialog-segclosure-list").val();
  1517. if (closureId)
  1518. {
  1519. var c = W.model.roadClosures.objects[closureId];
  1520. if (c)
  1521. {
  1522. $("#wmeac-advanced-closure-dialog-starttime").val(c.startDate.split(' ')[1]);
  1523. var duration=new Date(c.endDate) - new Date(c.startDate);
  1524. // $("#wmeac-advanced-closure-dialog-duration-hour").val(Math.floor(duration/3600000));
  1525. // $("#wmeac-advanced-closure-dialog-duration-minute").val(new Date(duration).getMinutes());
  1526. var days = Math.floor(duration/86400000);
  1527. $("#wmeac-advanced-closure-dialog-duration-day").val(days);
  1528. var hours = Math.floor((duration - days * 86400000)/3600000);
  1529. var minutes = Math.floor((duration - days * 86400000 - hours * 3600000)/60000);
  1530. $("#wmeac-advanced-closure-dialog-durationtime").val('' + hours + ':' + minutes);
  1531. $("#wmeac-advanced-closure-dialog-reason").val(c.reason.trim());
  1532. if (WMEAC.getOppositeClosure(c).length==0) // oneway
  1533. $("#wmeac-advanced-closure-dialog-direction").val(c.forward?1:2);
  1534. else
  1535. $("#wmeac-advanced-closure-dialog-direction").val(3);
  1536. $("#wmeac-advanced-closure-dialog-ignoretraffic").prop('checked', c.permanent);
  1537. // MTE
  1538. if (c.eventId!=null)
  1539. {
  1540. var options = [];
  1541. $("#wmeac-advanced-closure-dialog-mteid option").each(function () { options.push($(this).val()); });
  1542. if (options.indexOf(c.eventId)!=-1)
  1543. $("#wmeac-advanced-closure-dialog-mteid").val(c.eventId);
  1544. else
  1545. $("#wmeac-advanced-closure-dialog-mteid").val('');
  1546. }
  1547. }
  1548. }
  1549. });
  1550. $('#wmeac-advanced-closure-dialog-presets-delete').on('click', function(e){
  1551. var presetIndex = parseInt($("#wmeac-advanced-closure-dialog-presets-list").val());
  1552. WMEAC.presets.splice(presetIndex, 1);
  1553. WMEAC.save();
  1554. WMEAC.reloadPresets();
  1555. });
  1556.  
  1557. $('#wmeac-advanced-closure-dialog-presets-save').on('click', function(e){
  1558. var name = $("#wmeac-advanced-closure-dialog-presets-name").val();
  1559. var presetIndex = WMEAC.presets.findIndex(function (e) {
  1560. return e.name==name;
  1561. });
  1562. var preset = {name: name, values: { duration: {}, repeat: {}, each: []}};
  1563. if (presetIndex!=-1) // overwrite existing preset
  1564. preset=WMEAC.presets[presetIndex];
  1565. preset.values.starttime=$("#wmeac-advanced-closure-dialog-starttime").val();
  1566. preset.values.duration.day=$("#wmeac-advanced-closure-dialog-duration-day").val();
  1567. preset.values.duration.hour=parseInt($("#wmeac-advanced-closure-dialog-durationtime").val().split(':')[0]);
  1568. preset.values.duration.minute=parseInt($("#wmeac-advanced-closure-dialog-durationtime").val().split(':')[1]);
  1569. preset.values.description=$("#wmeac-advanced-closure-dialog-reason").val();
  1570. //preset.values.location=$("#wmeac-advanced-closure-dialog-location").val();
  1571. preset.values.direction=$("#wmeac-advanced-closure-dialog-direction").val();
  1572. preset.values.ignoretraffic=$("#wmeac-advanced-closure-dialog-ignoretraffic").is(':checked');
  1573. preset.values.repeat.ntimes=$("#wmeac-advanced-closure-dialog-repeat-ntimes").val();
  1574. preset.values.repeat.day=$("#wmeac-advanced-closure-dialog-repeat-every-day").val();
  1575. preset.values.repeat.hour=$("#wmeac-advanced-closure-dialog-repeat-every-hour").val();
  1576. preset.values.repeat.minute=$("#wmeac-advanced-closure-dialog-repeat-every-minute").val();
  1577. for (var i=0; i<7; i++)
  1578. preset.values.each[i]=$("#wmeac-advanced-closure-dialog-each-"+i).is(':checked');
  1579. if (presetIndex==-1)
  1580. WMEAC.presets.push(preset);
  1581. WMEAC.save();
  1582. WMEAC.reloadPresets();
  1583. });
  1584. WMEAC.setDraggable($('#wmeac-add-advanced-closure-dialog'), { controller: $('#wmeac-add-advanced-closure-dialog h1:first-child'), container: [$('#OpenLayers_Map_200_OpenLayers_ViewPort'), $('#WazeMap')] });
  1585. };
  1586.  
  1587.  
  1588. WMEAC.connectAdvancedClosureTabHandlers = function ()
  1589. {
  1590. var e = null;
  1591.  
  1592. e=WMEAC.getId('wmeac-csv-file');
  1593. if (e)
  1594. e.addEventListener('change', WMEAC.CSVFileChanged);
  1595.  
  1596. e=WMEAC.getId('wmeac-csv-closures-controls-check');
  1597. if (e)
  1598. e.addEventListener('change', function (e) { WMEAC.CSVCheckAll(e.target.checked); });
  1599.  
  1600. e=WMEAC.getId('wmeac-csv-closures-controls-apply');
  1601. if (e)
  1602. e.addEventListener('click', WMEAC.CSVApplyChecked);
  1603.  
  1604. e=WMEAC.getId('wmeac-csv-closures-controls-segs');
  1605. if (e)
  1606. e.addEventListener('click', WMEAC.CSVCheckSegsChecked);
  1607.  
  1608. };
  1609.  
  1610. WMEAC.reloadPresets = function ()
  1611. {
  1612. var optionList=WMEAC.presets.map(function (p, i) {
  1613. return '<option value="' + i + '">' + p.name + '</option>';
  1614. });
  1615. $("#wmeac-advanced-closure-dialog-presets-list").html(optionList.join(''));
  1616. };
  1617.  
  1618.  
  1619. /***********************************************
  1620. *** END OF INCLUDED FILE : ***
  1621. *** include/setupUI.js ***
  1622. ***********************************************/
  1623.  
  1624.  
  1625.  
  1626. /***********************************************
  1627. *** IN INCLUDED FILE : ***
  1628. *** include/class.progressBar.js ***
  1629. ***********************************************/
  1630.  
  1631. WMEAC.ProgressBar = function (id)
  1632. {
  1633. this.id=id;
  1634. this.divpbi = WMEAC.createElement({type: 'div', id: id, className: id});
  1635. var elt = WMEAC.createElement({type: 'div', id: 'wmeac-progressBar'});
  1636. elt.style.width="100%";
  1637. elt.style.display="none";
  1638. elt.innerHTML='<div class="wmeac-progressBarBG"></div><span class="wmeac-progressBarFG">100%</span>';
  1639. this.divpbi.appendChild(elt);
  1640. elt = WMEAC.createElement({type: 'div', id: 'wmeac-progressBar-info'});
  1641. //elt.innerHTML="&nbsp;";
  1642. this.divpbi.appendChild(elt);
  1643.  
  1644. this.isShown = function () {
  1645. return (this.divpbi.style.display != "none");
  1646. };
  1647. this.show = function(toShow)
  1648. {
  1649. this.divpbi.style.display = (toShow?"block":"none");
  1650. };
  1651. this.update = function(value)
  1652. {
  1653. if (value==-1)
  1654. {
  1655. this.divpbi.children[0].style.display='none';
  1656. this.divpbi.children[1].style.display='none';
  1657. return;
  1658. }
  1659. value = Math.round(value);
  1660. this.divpbi.children[0].style.display='block';
  1661. this.divpbi.children[1].style.display='block';
  1662. this.divpbi.children[0].children[0].style.width = value+"%";
  1663. this.divpbi.children[0].children[1].innerHTML = value+"%";
  1664. };
  1665. this.info = function(text)
  1666. {
  1667. this.divpbi.children[1].innerHTML=text;
  1668. };
  1669. };
  1670.  
  1671.  
  1672.  
  1673.  
  1674. /***********************************************
  1675. *** END OF INCLUDED FILE : ***
  1676. *** include/class.progressBar.js ***
  1677. ***********************************************/
  1678.  
  1679.  
  1680.  
  1681. /***********************************************
  1682. *** IN INCLUDED FILE : ***
  1683. *** include/class.closure.js ***
  1684. ***********************************************/
  1685.  
  1686. WMEAC.ClassClosure = function (options)
  1687. {
  1688. WMEAC.log("options", options);
  1689. this.isValid=false;
  1690. this.errorMessage='';
  1691. var validProperties=['reason', 'startDate', 'endDate', 'direction', 'segIDs', 'lonlat', 'permanent', 'id', 'zoom'];
  1692. var goodOptions=0;
  1693. validProperties.forEach(function (p) {
  1694. if (options.hasOwnProperty(p))
  1695. {
  1696. this[p]=options[p];
  1697. goodOptions++;
  1698. }
  1699. else
  1700. {
  1701. this.errorMessage+="Missing property " + p + "\n";
  1702. }
  1703. }, this);
  1704. if (goodOptions==validProperties.length)
  1705. {
  1706. this.isValid=true;
  1707. }
  1708. else
  1709. {
  1710. return;
  1711. }
  1712. // optional options:
  1713. this.comment="";
  1714. if (options.hasOwnProperty('comment')) this.comment=options.comment;
  1715. this.eventId=null;
  1716. if (options.hasOwnProperty('eventId') && options.eventId!='') this.eventId=options.eventId;
  1717. this.segIDs = this.segIDs.split(';');
  1718. var matches = this.lonlat.match(/lon=(-?\d+\.?\d*)&lat=(-?\d+\.?\d*)/);
  1719. if (matches && matches.length==3)
  1720. this.lonlat = {lon: parseFloat(matches[1]), lat: parseFloat(matches[2])};
  1721. else
  1722. {
  1723. matches = this.lonlat.match(/lat=(-?\d+\.?\d*)&lon=(-?\d+\.?\d*)/);
  1724. if (matches && matches.length==3)
  1725. this.lonlat = {lon: parseFloat(matches[2]), lat: parseFloat(matches[1])};
  1726. else
  1727. {
  1728. this.isValid=false;
  1729. this.errorMessage="Can't parse lonlat: " + this.lonlat + "\n";
  1730. return;
  1731. }
  1732. }
  1733. if (this.direction!="A to B" && this.direction!="B to A" && this.direction!="TWO WAY")
  1734. {
  1735. this.isValid=false;
  1736. this.errorMessage="Can't determine direction: " + this.direction + "\n";
  1737. return;
  1738. }
  1739. this.zoom = parseInt(this.zoom);
  1740. if (this.zoom<2||this.zoom>10)
  1741. {
  1742. this.isValid=false;
  1743. this.errorMessage="Wrong zoom (2 to 10): " + this.zoom + "\n";
  1744. return;
  1745. }
  1746. this.applyInWME = function(successHandler, failureHandler)
  1747. {
  1748. // check if segments are on screen
  1749. var segs = WMEAC.segmentsIDsToSegments(this.segIDs);
  1750. WMEAC.log("Segs: ", segs);
  1751.  
  1752. segs = segs.filter(function (seg) {
  1753. return seg.isAllowed(seg.permissionFlags.EDIT_CLOSURES);
  1754. });
  1755. if (segs.length==0)
  1756. {
  1757. failureHandler([{attributes: {details: "No segment. Check permissions or existence."}}]);
  1758. }
  1759. else
  1760. {
  1761. var cityStreets = WMEAC.getCityStreetsFromSegmentSet(segs);
  1762. var closureLocation = Object.keys(cityStreets).map(function (c) {
  1763. return (Object.keys(cityStreets[c]).map(function (s) {
  1764. if (s=='noStreet') return I18n.translations[I18n.locale].edit.address.no_street;
  1765. return s;
  1766. }).join(', ') + (c=='noCity'?'':' (' + c + ')'));
  1767. }).join(' ; ');
  1768. var sc = WMEAC.WMEAPI.require("Waze/Modules/Closures/Models/SharedClosure");
  1769. var closureDetails = {reason: this.reason, direction: (this.direction=="A to B"?WMEAC.sharedClosureDirection.A_TO_B:(this.direction=="B to A"?WMEAC.sharedClosureDirection.B_TO_A:WMEAC.sharedClosureDirection.TWO_WAY)), startDate: this.startDate, endDate: this.endDate, location: closureLocation, permanent: this.permanent=='Yes', segments: segs};
  1770. if (this.eventId!=null) closureDetails.eventId = this.eventId;
  1771. WMEAC.addClosure(closureDetails, successHandler, failureHandler);
  1772. }
  1773. };
  1774. this.removeInWME = function(successHandler, failureHandler)
  1775. {
  1776. var segs = WMEAC.segmentsIDsToSegments(this.segIDs);
  1777. segs = segs.filter(function (seg) {
  1778. return seg.isAllowed(seg.permissionFlags.EDIT_CLOSURES);
  1779. });
  1780. var allClosuresToRemove=[];
  1781. var countToMatch=this.segIDs.length*(this.direction=="TWO WAY"?2:1); // two way = 2 closures in WME
  1782. segs.forEach(function (s) {
  1783. // look for closure(s)
  1784. var that = this;
  1785. var closures = W.model.roadClosures.getObjectArray(function (c) {
  1786. return (c.startDate==that.startDate &&
  1787. c.endDate==that.endDate &&
  1788. c.reason.trim()==that.reason &&
  1789. c.segID==s.attributes.id &&
  1790. c.permanent == (that.permanent=='Yes'));
  1791. });
  1792. if ((this.direction=="TWO WAY") || // && closures.length==2 && closures[0].forward!=closures[1].forward) ||
  1793. (this.direction=="A to B" && closures.length==1 && closures[0].forward==true) ||
  1794. (this.direction=="B to A" && closures.length==1 && closures[0].forward==false))
  1795. {
  1796. allClosuresToRemove=allClosuresToRemove.concat(closures);
  1797. }
  1798. }, this);
  1799. if (allClosuresToRemove.length==0)
  1800. {
  1801. failureHandler([{attributes: {details: "No segment. Check permissions or existence."}}]);
  1802. }
  1803. else
  1804. WMEAC.removeClosure(allClosuresToRemove, successHandler, failureHandler);
  1805. };
  1806. };
  1807.  
  1808.  
  1809. /***********************************************
  1810. *** END OF INCLUDED FILE : ***
  1811. *** include/class.closure.js ***
  1812. ***********************************************/
  1813.  
  1814.  
  1815. /***********************************************
  1816. *** IN INCLUDED FILE : ***
  1817. *** include/recurringClosures.js ***
  1818. ***********************************************/
  1819.  
  1820. WMEAC.buildClosuresListFromRecurringUI = function ()
  1821. {
  1822. var list = [];
  1823. var rangeStartDate = new Date($('#wmeac-advanced-closure-dialog-rangestartdate').val());
  1824. if (!WMEAC.isValidDate(rangeStartDate)) return {list: list, error: "Range start date is not valid"};
  1825. var rangeEndDate = new Date($('#wmeac-advanced-closure-dialog-rangeenddate').val());
  1826. if (!WMEAC.isValidDate(rangeEndDate)) return {list: list, error: "Range end date is not valid"};
  1827. if (rangeEndDate<rangeStartDate) return {list: list, error: "Range end date is before range start date"};
  1828. var dD = parseInt($('#wmeac-advanced-closure-dialog-duration-day').val());
  1829. if (isNaN(dD) || dH<0) return {list: list, error: "Duration days is invalid"};
  1830. // var dM = parseInt($('#wmeac-advanced-closure-dialog-duration-minute').val());
  1831. // if (isNaN(dM) || dM<0 || dM>=60) return {list: list, error: "Duration minute is invalid"};
  1832. var dH = parseInt($('#wmeac-advanced-closure-dialog-durationtime').val().split(':')[0]);
  1833. var dM = parseInt($('#wmeac-advanced-closure-dialog-durationtime').val().split(':')[1]);
  1834. if (dD==0 && dH==0 && dM==0) return {list: list, error: "Duration is null"};
  1835. // var rangeStartTimeM = $('#wmeac-advanced-closure-dialog-rangestarttime').val().split(':').map(function (e) {
  1836. // return parseInt(e);
  1837. // }).reduce(function (p, c, i) {
  1838. // return (p*60+c);
  1839. // });
  1840. var rangeStartTimeM = 0;
  1841. // var rangeEndTimeM = $('#wmeac-advanced-closure-dialog-rangeendtime').val().split(':').map(function (e) {
  1842. // return parseInt(e);
  1843. // }).reduce(function (p, c, i) {
  1844. // return (p*60+c);
  1845. // });
  1846. var rangeEndTimeM = 1440;
  1847. var rangeEndDateTime = rangeEndDate.clone();
  1848. rangeEndDateTime.addMinutes(rangeEndTimeM);
  1849. var startTimeM = $('#wmeac-advanced-closure-dialog-starttime').val().split(':').map(function (e) {
  1850. return parseInt(e);
  1851. }).reduce(function (p, c, i) {
  1852. return (p*60+c);
  1853. });
  1854. // if mode is REPEAT
  1855. if ($('#wmeac-advanced-closure-dialog-tabrepeat').attr('class').indexOf('active')!=-1)
  1856. {
  1857. var ntimes = parseInt($('#wmeac-advanced-closure-dialog-repeat-ntimes').val());
  1858. if (isNaN(ntimes) || ntimes<1) return {list: list, error: "Repeat count is invalid"};
  1859. var evD = parseInt($('#wmeac-advanced-closure-dialog-repeat-every-day').val());
  1860. if (isNaN(evD) || evD<0) return {list: list, error: "Repeat every day is invalid"};
  1861. var evH = parseInt($('#wmeac-advanced-closure-dialog-repeat-every-hour').val());
  1862. if (isNaN(evH) || evH<0) return {list: list, error: "Repeat every hour is invalid"};
  1863. var evM = parseInt($('#wmeac-advanced-closure-dialog-repeat-every-minute').val());
  1864. if (isNaN(evM) || evM<0 || evM>=60) return {list: list, error: "Repeat every minute is invalid"};
  1865. // if repeat is smaller than duration
  1866. if (evD * 1440 + evH * 60 + evM < dD * 1440 + dH * 60 + dM) return {list: list, error: "Repeat must be greater than duration"};
  1867. var firstDateTimeStart = rangeStartDate.clone();
  1868. if (startTimeM<rangeStartTimeM) // starts the day after
  1869. firstDateTimeStart.addDays(1);
  1870. firstDateTimeStart.setMinutes(startTimeM);
  1871. var firstDateTimeEnd = firstDateTimeStart.clone();
  1872. firstDateTimeEnd.addMinutes(dD * 1440 + dH * 60 + dM);
  1873. // var now = new Date();
  1874. for (var i=0; i<ntimes; i++)
  1875. {
  1876. var start = firstDateTimeStart.clone();
  1877. start.addMinutes((evD * 1440 + evH * 60 + evM)*i);
  1878. var end = start.clone();
  1879. end.addMinutes(dD * 1440 + dH * 60 + dM);
  1880. if (end > rangeEndDateTime) // stop if after range end
  1881. break;
  1882. // WMEAC.log('end', end);
  1883. // WMEAC.log('now', now);
  1884. // if (end < now) // do not add closure that ends before now
  1885. // {
  1886. // ntimes++;
  1887. // continue;
  1888. // }
  1889. list.push({start: WMEAC.dateToClosureStr(start), end: WMEAC.dateToClosureStr(end)});
  1890. }
  1891. return {list: list, error: ""};
  1892. }
  1893. // if mode is EACH
  1894. else if ($('#wmeac-advanced-closure-dialog-tabeach').attr('class').indexOf('active')!=-1)
  1895. {
  1896. // build bits for a week:
  1897. var dow = WMEAC.daysOfWeek.map(function (e, i) {
  1898. return ($('#wmeac-advanced-closure-dialog-each-' + i)).is(':checked');
  1899. });
  1900. var dayCount = Math.ceil((rangeEndDate-rangeStartDate+1)/86400000);
  1901. var day0 = rangeStartDate.clone();
  1902. day0.addMinutes(startTimeM);
  1903. if (startTimeM<rangeStartTimeM) // starts the day after
  1904. day0.addDays(1);
  1905. for (var d=0; d<dayCount; d++)
  1906. {
  1907. var start = day0.clone();
  1908. start.addMinutes(d*1440);
  1909. if (dow[start.getUTCDay()])
  1910. {
  1911. var end = start.clone();
  1912. end.addMinutes(dD * 1440 + dH * 60 + dM);
  1913. if (end > rangeEndDateTime) // stop if after range end
  1914. break;
  1915. list.push({start: WMEAC.dateToClosureStr(start), end: WMEAC.dateToClosureStr(end)});
  1916. }
  1917. }
  1918. return {list: list, error: ""};
  1919. }
  1920. else if ($('#wmeac-advanced-closure-dialog-tabholiday').attr('class').indexOf('active')!=-1)
  1921. {
  1922. WMEAC.lastGeneratedHolidays.forEach(function (e, i) {
  1923. if (($('#wmeac-advanced-closure-dialog-holidays-' + i)).is(':checked'))
  1924. {
  1925. var start = new Date(e.date).addMinutes(startTimeM);
  1926. var end = start.clone();
  1927. end.addMinutes(dD * 1440 + dH * 60 + dM);
  1928. list.push({start: WMEAC.dateToClosureStr(start), end: WMEAC.dateToClosureStr(end)});
  1929. }
  1930. });
  1931. return {list: list, error: ""};
  1932. }
  1933. else
  1934. return {list: list, error: "Wrong tab active"};
  1935.  
  1936. };
  1937.  
  1938. WMEAC.refreshClosureList = function ()
  1939. {
  1940. try {
  1941. var rc = WMEAC.buildClosuresListFromRecurringUI();
  1942. if (rc.error!="")
  1943. $('#wmeac-csv-closures-preview-content').html(rc.error);
  1944. else
  1945. {
  1946. var reason = $('#wmeac-advanced-closure-dialog-reason').val();
  1947. //var cllocation = $('#wmeac-advanced-closure-dialog-location').val();
  1948. var direction = $('#wmeac-advanced-closure-dialog-direction').val();
  1949. var directionStr = direction==1?"(A &#8594; B)":(direction==2?"(B &#8594; A)":"(&#8646;)");
  1950. var isIT = $('#wmeac-advanced-closure-dialog-ignoretraffic').is(':checked');
  1951. var existingClosures = W.selectionManager.getSelectedFeatures().reduce(function (p, c, i) {
  1952. var revSegs = W.selectionManager.getReversedSegments();
  1953. var isReversed = revSegs.hasOwnProperty(c.model.attributes.id) && revSegs[c.model.attributes.id];
  1954. var realWay = isReversed?(direction==1?2:1):direction;
  1955. return p.concat(W.model.roadClosures.getObjectArray(function (e) {
  1956. return (e.segID==c.model.attributes.id &&
  1957. (direction==3 || (e.forward && realWay==1) || (!e.forward && realWay==2)));
  1958. }));
  1959. }, []);
  1960. var mte = W.model.majorTrafficEvents.getObjectById($("#wmeac-advanced-closure-dialog-mteid").val());
  1961. $('#wmeac-csv-closures-preview-content').html('' + rc.list.length + ' closure(s) to apply: <br>' +
  1962. rc.list.map(function (e, i) {
  1963. var overlap = existingClosures.filter(function (c) {
  1964. return WMEAC.dateTimeOverlaps({startDate: e.start, endDate: e.end}, c);
  1965. }).map(function (c) {
  1966. var msg = (c.reason?c.reason + ' ':'') + '(' + c.segID + ')';
  1967. if (W.model.segments.objects.hasOwnProperty(c.segID)==false) return msg;
  1968. if (W.model.segments.objects[c.segID].attributes.primaryStreetID==null) return msg;
  1969. if (W.model.streets.objects.hasOwnProperty(W.model.segments.objects[c.segID].attributes.primaryStreetID)==false) return msg;
  1970. var street = W.model.streets.objects[W.model.segments.objects[c.segID].attributes.primaryStreetID];
  1971. if (!street.isEmpty) msg = street.name + ': ' + msg;
  1972. return msg;
  1973. });
  1974. var mteOK=!(mte && (new Date(e.start) < new Date(mte.attributes.startDate) || new Date(e.end) > new Date(mte.attributes.endDate)));
  1975. return (reason +
  1976. //' (' + cllocation + '): ' +
  1977. ': ' +
  1978. e.start + ' &#8594; ' + e.end +
  1979. ' ' + directionStr +
  1980. ' <i class="fa fa-car' + (isIT?" slashed":"") + '"></i>' +
  1981. (overlap.length!=0?' <i title="Warning: overlap on existing closure!\n' + overlap.join('\n') + '" class="fa fa-exclamation-circle" style="color: orange"></i>':'') +
  1982. (mteOK?'':' <i title="Warning: closure dates not inside MTE date!" class="fa fa-exclamation-circle" style="color: orange"></i>') +
  1983. ' <span id="wmeac-advanced-closure-dialog-preview-' + i + '"></span>');
  1984. }).join('<br>'));
  1985. }
  1986. }
  1987. catch (e)
  1988. {
  1989. WMEAC.logError("Error while refreshing closure list: ", e);
  1990. }
  1991. };
  1992.  
  1993. WMEAC.refreshMTEList = function ()
  1994. {
  1995. var currentMTEid = $("#wmeac-advanced-closure-dialog-mteid").val();
  1996. var rangeStart = new Date($("#wmeac-advanced-closure-dialog-rangestartdate").val());
  1997. var rangeEnd = new Date($("#wmeac-advanced-closure-dialog-rangeenddate").val());
  1998. var options=[{name: 'none', value: ''}];
  1999. $("#wmeac-advanced-closure-dialog-mteid").empty();
  2000. if (WMEAC.isValidDate(rangeStart) && WMEAC.isValidDate(rangeEnd))
  2001. {
  2002. rangeEnd.addDays(1);
  2003. // filter MTE loaded in WME:
  2004. W.model.majorTrafficEvents.getObjectArray(function (mte) {
  2005. // check if ranges overlap
  2006. return (WMEAC.dateTimeOverlaps({startDate: rangeStart, endDate: rangeEnd}, {startDate: new Date(mte.attributes.startDate), endDate: new Date(mte.attributes.endDate)}));
  2007. }).forEach(function (mte) {
  2008. options.push({name: mte.attributes.names[0].value, value: mte.attributes.id});
  2009. });
  2010. }
  2011. options.forEach(function (o) {
  2012. var el = WMEAC.createElement({type: 'option'});
  2013. el.setAttribute('value', o.value);
  2014. if (currentMTEid==o.value)
  2015. el.setAttribute('selected', '');
  2016. el.innerHTML = o.name;
  2017. $("#wmeac-advanced-closure-dialog-mteid").append(el);
  2018. });
  2019. if (options.length>1)
  2020. $("#wmeac-advanced-closure-dialog-mteid").removeAttr('disabled');
  2021. else
  2022. $("#wmeac-advanced-closure-dialog-mteid").attr('disabled', '');
  2023. };
  2024.  
  2025. WMEAC.refreshClosureListFromSelection = function ()
  2026. {
  2027. try
  2028. {
  2029. var currentSegClosure = $("#wmeac-advanced-closure-dialog-segclosure-list").val();
  2030. $("#wmeac-advanced-closure-dialog-segclosure-list").empty();
  2031. if (W.selectionManager.getSelectedFeatures().length!=0)
  2032. {
  2033. var blackList=[];
  2034. W.model.roadClosures.getObjectArray(function (c) {
  2035. return c.segID==W.selectionManager.getSelectedFeatures()[0].model.attributes.id;
  2036. }).sort(function (a,b) {
  2037. return (new Date(a.startDate)-new Date(b.startDate));
  2038. }).forEach(function (c) {
  2039. if (blackList.indexOf(c.id)!=-1) return;
  2040. var direction = c.forward?"A to B":"B to A";
  2041. var oppositeClosure = WMEAC.getOppositeClosure(c);
  2042. if (!oppositeClosure.length==0)
  2043. {
  2044. direction = "Two way";
  2045. blackList.push(oppositeClosure[0].id);
  2046. }
  2047. var el = WMEAC.createElement({type: 'option'});
  2048. el.setAttribute('value', c.id);
  2049. if (currentSegClosure==c.id)
  2050. el.setAttribute('selected', '');
  2051. el.innerHTML = c.reason.trim() + ' ' + direction + ' ' + c.startDate + '&#8594;' + c.endDate;
  2052. $("#wmeac-advanced-closure-dialog-segclosure-list").append(el);
  2053. });
  2054. }
  2055. }
  2056. catch (e)
  2057. {
  2058. WMEAC.logError("Error while refreshing closure list from selection: ", e);
  2059. }
  2060. };
  2061.  
  2062. /***********************************************
  2063. *** IN INCLUDED FILE : ***
  2064. *** include/holidays.js ***
  2065. ***********************************************/
  2066.  
  2067. WMEAC.abbrToISO3166_1alpha2 = function (abbr)
  2068. {
  2069. switch(abbr)
  2070. {
  2071. case 'GM':
  2072. return 'DE';
  2073. break;
  2074. case 'BU':
  2075. return 'BG';
  2076. break;
  2077. case 'EZ':
  2078. return 'CZ';
  2079. break;
  2080. case 'SP':
  2081. return 'ES';
  2082. break;
  2083. case 'UK':
  2084. return 'GB';
  2085. break;
  2086. case 'LO':
  2087. return 'SK';
  2088. break;
  2089. default:
  2090. return abbr;
  2091. break;
  2092. }
  2093. return abbr;
  2094. };
  2095.  
  2096. WMEAC.getHolidays = function (options)
  2097. {
  2098. var holidays = [];
  2099. var currentCountryIndex = 0;
  2100. var rangeStart = new Date(options.rangeStart);
  2101. var rangeEnd = new Date(options.rangeEnd).addDays(1);
  2102. var years = [];
  2103. for (y=parseInt(options.rangeStart.substring(0,4)); y<=parseInt(options.rangeEnd.substring(0,4)); y++) years.push(y);
  2104. var currentYearIndex = 0;
  2105. var tmp1 = function downloadNext() {
  2106. if (currentCountryIndex>=options.countries.length)
  2107. if (options.handlerFinished)
  2108. {
  2109. holidays.sort(function (a, b) {
  2110. return (new Date(a.date)-new Date(b.date));
  2111. });
  2112. holidays=holidays.filter(function (h, i) {
  2113. if (i!=0)
  2114. {
  2115. if (holidays[i-1].date==h.date)
  2116. {
  2117. holidays[i-1].name += ' / ' + h.name;
  2118. holidays[i-1].country += ' / ' + h.country;
  2119. return false;
  2120. }
  2121. }
  2122. return true;
  2123. });
  2124. options.handlerFinished(holidays);
  2125. return;
  2126. }
  2127. window.WMEAC_downloadHelper.add(
  2128. //"https://holidayapi.com/v1/holidays?country=" + WMEAC.abbrToISO3166_1alpha2(options.countries[currentCountryIndex]) + "&year=" + dateToNext.substring(0, 4) + "&month=" + dateToNext.substring(5, 7) + "&day=" + dateToNext.substring(8) + "&upcoming",
  2129. "https://holidayapi.com/v1/holidays?key=ca1a7925-0045-47da-bcf6-ee0de583e384&country=" + WMEAC.abbrToISO3166_1alpha2(options.countries[currentCountryIndex]) + "&year=" + years[currentYearIndex],
  2130. function (data) {
  2131. if (data.status=='success')
  2132. {
  2133. try {
  2134. nextHoliday = JSON.parse(data.data);
  2135. if (nextHoliday.hasOwnProperty('holidays'))
  2136. {
  2137. for (var hd in nextHoliday.holidays) {
  2138. if (!nextHoliday.holidays.hasOwnProperty(hd)) continue;
  2139. if (nextHoliday.holidays[hd].length==0) continue;
  2140. var name = _.map(nextHoliday.holidays[hd], 'name').join(' / ');
  2141. var h = nextHoliday.holidays[hd][0];
  2142. var d = new Date(h.date);
  2143. if (d>=rangeStart && d<rangeEnd)
  2144. {
  2145. holidays.push({date: h.date, name: name, country: h.country});
  2146. }
  2147. }
  2148. currentYearIndex++;
  2149. if (currentYearIndex<years.length)
  2150. {
  2151. window.setTimeout(downloadNext);
  2152. return;
  2153. }
  2154. }
  2155. }
  2156. catch (e)
  2157. {
  2158. WMEAC.log ("Error while getting holiday from server!", e);
  2159. WMEAC.log ("data", data.data);
  2160. }
  2161. currentCountryIndex++;
  2162. currentYearIndex=0;
  2163. window.setTimeout(downloadNext);
  2164. }
  2165. }
  2166. );
  2167. };
  2168.  
  2169. tmp1();
  2170.  
  2171. };
  2172.  
  2173. /***********************************************
  2174. *** END OF INCLUDED FILE : ***
  2175. *** include/holidays.js ***
  2176. ***********************************************/
  2177.  
  2178.  
  2179.  
  2180.  
  2181. /***********************************************
  2182. *** END OF INCLUDED FILE : ***
  2183. *** include/recurringClosures.js ***
  2184. ***********************************************/
  2185.  
  2186.  
  2187. /***********************************************
  2188. *** IN INCLUDED FILE : ***
  2189. *** include/actionClosures.js ***
  2190. ***********************************************/
  2191.  
  2192. WMEAC.addClosure = function (options, successHandler, failureHandler)
  2193. {
  2194. if (options &&
  2195. options.hasOwnProperty('segments') &&
  2196. options.hasOwnProperty('reason') &&
  2197. options.hasOwnProperty('direction') &&
  2198. options.hasOwnProperty('startDate') &&
  2199. options.hasOwnProperty('endDate') &&
  2200. options.hasOwnProperty('location') &&
  2201. options.hasOwnProperty('permanent'))
  2202. {
  2203. WMEAC.log("Addinf closure: ", options);
  2204. var fail = function (e) {
  2205. return function (f) {
  2206. if (failureHandler)
  2207. failureHandler(f);
  2208. else
  2209. WMEAC.log("Failed to create closure:", f);
  2210. };
  2211. };
  2212. var done = function (e) {
  2213. return function (f) {
  2214. if (successHandler)
  2215. successHandler(f);
  2216. else
  2217. WMEAC.log("Closure successful:", f);
  2218. };
  2219. };
  2220. var cab = WMEAC.WMEAPI.require("Waze/Modules/Closures/Models/ClosureActionBuilder");
  2221. var sc = WMEAC.WMEAPI.require("Waze/Modules/Closures/Models/SharedClosure");
  2222. var t = {};
  2223. var closureDetails = {reason: options.reason + String.fromCharCode(160), direction: options.direction, startDate: options.startDate, endDate: options.endDate, location: options.location, permanent: options.permanent, segments: options.segments, reverseSegments: {}};
  2224. if (options.hasOwnProperty('eventId') && options.eventId!=null) closureDetails.eventId = options.eventId;
  2225. var c = new sc(closureDetails, {dataModel: W.model, segmentSelection: W.selectionManager.getSegmentSelection(), isNew: true});
  2226. t.actions=[cab.add(c)];
  2227. W.controller.save(t).then(done()).catch(fail());
  2228. return true;
  2229. }
  2230. return false;
  2231. };
  2232.  
  2233. WMEAC.addClosureListFromSelection = function (closureList, successHandler, failureHandler, endHandler, i)
  2234. {
  2235. if (i>=closureList.length)
  2236. {
  2237. WMEAC.reloadClosuresLayer(function () {
  2238. if (endHandler) endHandler();
  2239. });
  2240. return;
  2241. }
  2242. var c=closureList[i];
  2243. var fail = function (e) {
  2244. return function (f) {
  2245. if (failureHandler)
  2246. {
  2247. var details = [];
  2248. f.errors.forEach(function (err) {
  2249. if (err.hasOwnProperty('attributes') && err.attributes.hasOwnProperty('details'))
  2250. details.push(err.attributes.details);
  2251. });
  2252. failureHandler(i, details.join (' | '));
  2253. }
  2254. else
  2255. WMEAC.log("Failed to create closure:", f);
  2256. WMEAC.addClosureListFromSelection(closureList, successHandler, failureHandler, endHandler, i+1);
  2257. };
  2258. };
  2259. var done = function (e) {
  2260. return function (f) {
  2261. if (successHandler)
  2262. {
  2263. successHandler(i, "OK");
  2264. }
  2265. else
  2266. WMEAC.log("Closure successful:", f);
  2267. WMEAC.addClosureListFromSelection(closureList, successHandler, failureHandler, endHandler, i+1);
  2268. };
  2269. };
  2270.  
  2271. var cab = WMEAC.WMEAPI.require("Waze/Modules/Closures/Models/ClosureActionBuilder");
  2272. var sc = WMEAC.WMEAPI.require("Waze/Modules/Closures/Models/SharedClosure");
  2273. var t = {};
  2274. var segs = _.map(W.selectionManager.getSelectedFeatures(), 'model');
  2275. var cityStreets = WMEAC.getCityStreetsFromSegmentSet(segs);
  2276. var closureLocation = Object.keys(cityStreets).map(function (c) {
  2277. return (Object.keys(cityStreets[c]).map(function (s) {
  2278. if (s=='noStreet') return I18n.translations[I18n.locale].edit.address.no_street;
  2279. return s;
  2280. }).join(', ') + (c=='noCity'?'':' (' + c + ')'));
  2281. }).join(' ; ');
  2282. var closureDetails = {reason: closureList[i].reason + String.fromCharCode(160), direction: closureList[i].direction, startDate: closureList[i].startDate, endDate: closureList[i].endDate, location: closureLocation, permanent: closureList[i].permanent, segments: segs, reverseSegments: W.selectionManager.getReversedSegments()};
  2283. if (closureList[i].hasOwnProperty('eventId') && closureList[i].eventId!=null) closureDetails.eventId = closureList[i].eventId;
  2284. var c = new sc(closureDetails, {dataModel: W.model, segmentSelection: W.selectionManager.getSegmentSelection(), isNew: true});
  2285. t.actions=[cab.add(c)];
  2286. W.controller.save(t).then(done()).catch(fail());
  2287. };
  2288.  
  2289. WMEAC.addClosureFromSelection = function (options, successHandler, failureHandler)
  2290. {
  2291. if (options &&
  2292. options.hasOwnProperty('reason') &&
  2293. options.hasOwnProperty('direction') &&
  2294. options.hasOwnProperty('startDate') &&
  2295. options.hasOwnProperty('endDate') &&
  2296. options.hasOwnProperty('location') &&
  2297. options.hasOwnProperty('permanent'))
  2298. {
  2299. WMEAC.log("Addinf closure: ", options);
  2300. var fail = function (e) {
  2301. return function (f) {
  2302. if (failureHandler)
  2303. failureHandler(f);
  2304. else
  2305. WMEAC.log("Failed to create closure:", f);
  2306. };
  2307. };
  2308. var done = function (e) {
  2309. return function (f) {
  2310. if (successHandler)
  2311. successHandler(f);
  2312. else
  2313. WMEAC.log("Closure successful:", f);
  2314. };
  2315. };
  2316. var cab = WMEAC.WMEAPI.require("Waze/Modules/Closures/Models/ClosureActionBuilder");
  2317. var sc = WMEAC.WMEAPI.require("Waze/Modules/Closures/Models/SharedClosure");
  2318. var t = {};
  2319. var segs = _.map(W.selectionManager.getSelectedFeatures(), 'model');
  2320. var closureDetails = {reason: options.reason + String.fromCharCode(160), direction: options.direction, startDate: options.startDate, endDate: options.endDate, location: options.location, permanent: options.permanent, segments: segs, reverseSegments: W.selectionManager.getReversedSegments()};
  2321. if (options.hasOwnProperty('eventId') && options.eventId!=null) closureDetails.eventId = options.eventId;
  2322. var c = new sc(closureDetails, {dataModel: W.model, segmentSelection: W.selectionManager.getSegmentSelection(), isNew: true});
  2323. t.actions=[cab.add(c)];
  2324. W.controller.save(t).then(done()).catch(fail());
  2325. return true;
  2326. }
  2327. return false;
  2328. };
  2329.  
  2330. WMEAC.removeClosure = function (closures, successHandler, failureHandler)
  2331. {
  2332. var fail = function (e) {
  2333. return function (f) {
  2334. if (failureHandler)
  2335. failureHandler(f);
  2336. else
  2337. WMEAC.log("Failed to delete closure:", f);
  2338. };
  2339. };
  2340. var done = function (e) {
  2341. return function (f) {
  2342. if (successHandler)
  2343. successHandler(f);
  2344. else
  2345. WMEAC.log("Closure deletion successful:", f);
  2346. };
  2347. };
  2348.  
  2349. var cab = WMEAC.WMEAPI.require("Waze/Modules/Closures/Models/ClosureActionBuilder");
  2350. var sc = WMEAC.WMEAPI.require("Waze/Modules/Closures/Models/SharedClosure");
  2351. var t = {};
  2352. var c = new sc({closures: [].concat(closures)}, {dataModel: W.model, segmentSelection: W.selectionManager.getSegmentSelection(), isNew: true});
  2353. t.actions=[cab.delete(c)];
  2354. W.controller.save(t).then(done()).catch(fail());
  2355. return true;
  2356. };
  2357.  
  2358.  
  2359. /***********************************************
  2360. *** END OF INCLUDED FILE : ***
  2361. *** include/actionClosures.js ***
  2362. ***********************************************/
  2363.  
  2364.  
  2365. // functions to load and save settings
  2366. /***********************************************
  2367. *** IN INCLUDED FILE : ***
  2368. *** include/saveLoad.js ***
  2369. ***********************************************/
  2370.  
  2371. WMEAC.save = function ()
  2372. {
  2373. WMEAC.log("save data...");
  2374. localStorage.WMEAC = JSON.stringify({presets: WMEAC.presets});
  2375. };
  2376.  
  2377. WMEAC.load = function ()
  2378. {
  2379. try
  2380. {
  2381. var saved = JSON.parse(localStorage.WMEAC);
  2382. WMEAC.presets = saved.presets;
  2383. WMEAC.log("presets", WMEAC.presets);
  2384. }
  2385. catch (err)
  2386. {
  2387. WMEAC.log("Error while loading data from storage: " , err);
  2388. }
  2389. };
  2390.  
  2391.  
  2392. /***********************************************
  2393. *** END OF INCLUDED FILE : ***
  2394. *** include/saveLoad.js ***
  2395. ***********************************************/
  2396.  
  2397.  
  2398.  
  2399. /***********************************************
  2400. *** IN INCLUDED FILE : ***
  2401. *** include/csv.js ***
  2402. ***********************************************/
  2403.  
  2404. WMEAC.parseCSV = function (csvString)
  2405. {
  2406. if (csvString!=null)
  2407. {
  2408. var csvArray = WMEAC.CSVtoArray(csvString);
  2409. WMEAC.log("CSV as array:", csvArray);
  2410. var isValid = WMEAC.csv[0].validate(csvArray);
  2411. if (isValid.isValid)
  2412. {
  2413. WMEAC.log("CSV is valid!");
  2414. var closures = WMEAC.csv[0].filter(csvArray).map(function (e, i) {
  2415. return {action: e[0], closure: new WMEAC.ClassClosure({reason:e[1], startDate:e[2], endDate:e[3], direction:e[4], segIDs:e[6], lonlat:e[7], permanent:e[5], zoom: e[8], id: i, eventId: e[9], comment: (e.length==11?e[10]:'')}), UI: null};
  2416. });
  2417. WMEAC.log("Closure list:", closures);
  2418. WMEAC.csvCurrentClosureList = closures;
  2419. var listUI = WMEAC.getId('wmeac-csv-closures-list-elts');
  2420. // remove all closures before:
  2421. WMEAC.removeChildElements(listUI);
  2422. closures.forEach(function (c) {
  2423. c.UI = WMEAC.buildInlineClosureUI(c.closure, c.action);
  2424. listUI.appendChild(c.UI);
  2425. });
  2426. WMEAC.csvShowList(true);
  2427. WMEAC.csvAddLog("CSV parse successful\n");
  2428. return true;
  2429. // aply closures: TEST ONLY: this should not be done there!
  2430. /*closures.forEach(function (c) {
  2431. c.closure.applyInWME(function () { WMEAC.log("Closure success:", c);});
  2432. });*/
  2433. // END OF aply closures: TEST ONLY: this should not be done there!
  2434. }
  2435. else
  2436. {
  2437. WMEAC.log("CSV is NOT valid!:" + isValid.feedBack + "\n");
  2438. WMEAC.csvAddLog(isValid.feedBack + '\n');
  2439. WMEAC.csvShowList(false);
  2440. WMEAC.csvCurrentClosureList = null;
  2441. return false;
  2442. }
  2443. return false;
  2444. }
  2445. return false;
  2446. };
  2447.  
  2448. WMEAC.CSVFileChanged = function (evt)
  2449. {
  2450. var files = evt.target.files; // FileList object
  2451. for (var i = 0, f; f = files[i]; i++)
  2452. {
  2453. var reader = new FileReader();
  2454. reader.onload = (function(theFile) {
  2455. return function(e) {
  2456. WMEAC.log("import CSV file read");
  2457. WMEAC.csvClearLog();
  2458. if (WMEAC.parseCSV(e.target.result))
  2459. {
  2460. WMEAC.csvCurrentBatchClosureList=WMEAC.csvCurrentClosureList.slice();
  2461. // WMEAC.csvCheckAllSegments(-1);
  2462. }
  2463. };
  2464. })(f);
  2465.  
  2466. // Read in the image file as a data URL.
  2467. reader.readAsText(f);
  2468. }
  2469. this.value = null;
  2470. WMEAC.getId('wmeac-csv-closures-controls-check').checked=false;
  2471. };
  2472.  
  2473. WMEAC.ClassCSV = function (options)
  2474. {
  2475. this.isValid=false;
  2476. if (options.hasOwnProperty('version'))
  2477. this.version=options.version;
  2478. else return;
  2479. if (options.hasOwnProperty('regexpValidation'))
  2480. this.regexpValidation=options.regexpValidation;
  2481. else return;
  2482. this.isValid=true;
  2483. this.validate = function(data)
  2484. {
  2485. var regexps = this.regexpValidation;
  2486. var feedBack = "";
  2487. this.filter(data).forEach(function (line, l) {
  2488. var isLineValid = line.reduce(function (stillValid, cell, i) {
  2489. var isCellValid = cell.match(regexps[i])!=null;
  2490. if (!isCellValid)
  2491. feedBack+="Error while parsing line " + l + " cell " + i + ": \"" + cell + "\" in line " + line.join(',');
  2492. return (stillValid && isCellValid);
  2493. }, true);
  2494. }, this);
  2495. return {isValid: feedBack=="", feedBack: feedBack};
  2496. };
  2497. this.filter = function(data)
  2498. {
  2499. return data.filter(function (line) {
  2500. // return (line.length>=1 && line[0]!="header" && line[0]!="comment");
  2501. return (line.length>=1 && ['add','remove'].indexOf(line[0])!=-1);
  2502. });
  2503. };
  2504. };
  2505.  
  2506. WMEAC.csv.push(new WMEAC.ClassCSV({version: 1, regexpValidation: [/.*/, // 1st cell: action is free keyword. It will be filtered later
  2507. /.*/, // reason is free
  2508. // /.*/, // location is free
  2509. /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/, // start date
  2510. /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/, // end date
  2511. /(^A to B$)|(^B to A$)|(^TWO WAY$)/, // direction
  2512. /(Yes)|(No)/, // ignore trafic = permanent
  2513. /^(\d+(;|$))+/, // seg ID list
  2514. /(lon=(-?\d+\.?\d*)&lat=(-?\d+\.?\d*))|(lat=(-?\d+\.?\d*)&lon=(-?\d+\.?\d*))/, // lonlat
  2515. /^\d$/, // zoom
  2516. /(^$)|(^-?\d+\.-?\d+\.-?\d+$)/ // MTE ID is empty or digits.digits.digits
  2517. ]}));
  2518. WMEAC.buildInlineClosureUI = function (closure, action)
  2519. {
  2520. var liElt = WMEAC.createElement({type: 'li', className: 'wmeac-csv-closures-list-' + action});
  2521. liElt.setAttribute('closureID', closure.id);
  2522. liElt.innerHTML='<div class="wmeac-csv-closures-list-col-action"><input type="checkbox" /></div>\
  2523. <div class="wmeac-csv-closures-list-col-lr"><div title="' + closure.reason + '">' + closure.reason + '</div><div title="' + closure.comment + '">' + closure.comment + '</div></div>\
  2524. <div class="wmeac-csv-closures-list-col-dates"><div title="' + closure.startDate + '">' + closure.startDate + '</div><div title="' + closure.endDate + '">' + closure.endDate + '</div></div>\
  2525. <div class="wmeac-csv-closures-list-col-dir">' + (closure.direction=="A to B"?'A&#8594;B':(closure.direction=="B to A"?'B&#8594;A':'A&#8596;B')) + '</div>\
  2526. <div class="wmeac-csv-closures-list-col-it"><input type="checkbox" ' + (closure.permanent=="Yes"?'checked':'') + ' disabled/></div>\
  2527. <div class="wmeac-csv-closures-list-col-target"><a href="' + WMEAC.buildPermalink({lon: closure.lonlat.lon, lat: closure.lonlat.lat, segments: closure.segIDs.join(','), zoom: closure.zoom}) + '" title="Go there!"><i class="fa fa-crosshairs"></i></a></div>\
  2528. <div class="wmeac-csv-closures-list-col-apply"><a href="#" title="Apply action of this closure"><i class="fa fa-arrow-circle-right"></i></a></div>\
  2529. <div class="wmeac-csv-closures-minilog" style="display: block;">' + (action=='add'?'Ready to apply':(action=='remove'?'Ready to remove':'')) + '</div>';
  2530. // attach handlers
  2531. liElt.children[5].children[0].addEventListener('click', function (e) {
  2532. WMEAC.csvClearLog();
  2533. // get closure id:
  2534. var cid = parseInt(e.target.parentNode.parentNode.parentNode.getAttribute('closureID'));
  2535. var closure = WMEAC.csvCurrentClosureList.find(function (c) {
  2536. return (c.closure.id==cid);
  2537. });
  2538. WMEAC.log('Closure to target:', closure);
  2539. var xy = OpenLayers.Layer.SphericalMercator.forwardMercator(closure.closure.lonlat.lon, closure.closure.lonlat.lat);
  2540. W.map.setCenter(xy, closure.closure.zoom);
  2541. var tmp3 = function selectSegments()
  2542. {
  2543. WMEAC.log("Now select segments...");
  2544. var segs = WMEAC.segmentsIDsToSegments(closure.closure.segIDs);
  2545. if (segs.length!=closure.closure.segIDs.length)
  2546. {
  2547. if (segs.length==0)
  2548. {
  2549. WMEAC.csvAddLog("No segment found: " + closure.closure.comment + "(" + closure.closure.reason + ")\n");
  2550. WMEAC.setCSVMiniLog(closure, "Selection failed: no segment found", 3);
  2551. }
  2552. else
  2553. {
  2554. WMEAC.csvAddLog("Partial selection (" + segs.length + "/" + closure.closure.segIDs.length + "): " + closure.closure.comment + "(" + closure.closure.reason + ")\n");
  2555. WMEAC.setCSVMiniLog(closure, "Partial selection: " + segs.length + "/" + closure.closure.segIDs.length, 2);
  2556. }
  2557. alert ("Warning: missing segments.\nFound " + segs.length + "/" + closure.closure.segIDs.length + " segment(s)");
  2558. }
  2559. else
  2560. {
  2561. WMEAC.csvAddLog("Selection ok (" + segs.length + "): " + closure.closure.comment + "(" + closure.closure.reason + ")\n");
  2562. WMEAC.setCSVMiniLog(closure, "Selection OK: " + segs.length, 1);
  2563. }
  2564. if (segs.length!=0)
  2565. {
  2566. W.selectionManager.setSelectedModels(segs);
  2567. var tmp = function selectionReady()
  2568. {
  2569. if (W.selectionManager.getSelectedFeatures().length==0)
  2570. window.setTimeout(selectionReady, 500);
  2571. else
  2572. {
  2573. $('a[href="#segment-edit-closures"]').click();
  2574. }
  2575. };
  2576. window.setTimeout(tmp, 500);
  2577. }
  2578. };
  2579. var tmp2 = function readyToSelect() {
  2580. WMEAC.log("Test if ready to select...");
  2581. if (WMEAC.pendingOps==true)
  2582. {
  2583. WMEAC.log("Not yet. Waiting for WME...");
  2584. window.setTimeout(readyToSelect, 500);
  2585. }
  2586. else
  2587. {
  2588. tmp3();
  2589. }
  2590. };
  2591. var tmp1 = function mapMovedEnd() {
  2592. WMEAC.log("Test if roads are reloaded...");
  2593. if (WMEAC.pendingOps==true)
  2594. {
  2595. WMEAC.log("Not yet. Waiting for WME...");
  2596. window.setTimeout(mapMovedEnd, 500);
  2597. }
  2598. else
  2599. {
  2600. WMEAC.reloadRoadLayer();
  2601. tmp2();
  2602. }
  2603. };
  2604. window.setTimeout(tmp1, 500);
  2605. e.preventDefault();
  2606. });
  2607. liElt.children[6].children[0].addEventListener('click', function (e) {
  2608. // get closure id:
  2609. WMEAC.csvClearLog();
  2610. var liElt = e.target.parentNode.parentNode.parentNode;
  2611. var cid = parseInt(liElt.getAttribute('closureID'));
  2612. var closure = WMEAC.csvCurrentClosureList.find(function (c) {
  2613. return (c.closure.id==cid);
  2614. });
  2615. WMEAC.log('Closure to apply:', closure);
  2616. WMEAC.csvApplyClosure(closure, null);
  2617. });
  2618. return liElt;
  2619. };
  2620.  
  2621. WMEAC.csvApplyClosure = function(closure, handler)
  2622. {
  2623. var xy = OpenLayers.Layer.SphericalMercator.forwardMercator(closure.closure.lonlat.lon, closure.closure.lonlat.lat);
  2624. W.map.setCenter(xy, closure.closure.zoom);
  2625. function applySuccess(evt)
  2626. {
  2627. WMEAC.csvAddLog("Closure OK: " + closure.closure.comment + "(" + closure.closure.reason + ")\n");
  2628. closure.UI.className="wmeac-csv-closures-list-done";
  2629. WMEAC.setCSVMiniLog(closure, "OK", 1);
  2630. handler && handler(true);
  2631. };
  2632. function applyFailure(evt)
  2633. {
  2634. //WMEAC.log('evt', evt);
  2635. var details="";
  2636. evt.errors.forEach(function (err) {
  2637. if (err.hasOwnProperty('attributes') && err.attributes.hasOwnProperty('details'))
  2638. details += err.attributes.details + "\n";
  2639. });
  2640. WMEAC.csvAddLog("Closure KO: " + closure.closure.comment + " (" + closure.closure.reason + ")\n" + details + "\n");
  2641. WMEAC.setCSVMiniLog(closure, "KO: " + details, 3);
  2642. closure.UI.className="wmeac-csv-closures-list-failed";
  2643. handler && handler(false);
  2644. };
  2645. var tmp3 = function applyClosure()
  2646. {
  2647. WMEAC.log("Now apply closure...");
  2648. if (closure.action=="add")
  2649. closure.closure.applyInWME(applySuccess, applyFailure);
  2650. else if (closure.action=='remove')
  2651. closure.closure.removeInWME(applySuccess, applyFailure);
  2652. };
  2653. var tmp2 = function readyToApply() {
  2654. WMEAC.log("Test if ready to apply...");
  2655. if (WMEAC.pendingOps==true)
  2656. {
  2657. WMEAC.log("Not yet. Waiting for WME...");
  2658. window.setTimeout(readyToApply, 500);
  2659. }
  2660. else
  2661. {
  2662. tmp3();
  2663. }
  2664. };
  2665. var tmp1 = function mapMovedEnd() {
  2666. WMEAC.log("Test if roads are reloaded...");
  2667. if (WMEAC.pendingOps==true)
  2668. {
  2669. WMEAC.log("Not yet. Waiting for WME...");
  2670. window.setTimeout(mapMovedEnd, 500);
  2671. }
  2672. else
  2673. {
  2674. WMEAC.reloadRoadLayer();
  2675. tmp2();
  2676. }
  2677. };
  2678. window.setTimeout(tmp1, 1500);
  2679. };
  2680.  
  2681. WMEAC.csvAddLog = function(text)
  2682. {
  2683. var divLog = WMEAC.getId('wmeac-csv-closures-log');
  2684. divLog.innerHTML += text.replace(/\n/g, "<br>");
  2685. };
  2686.  
  2687. WMEAC.csvClearLog = function()
  2688. {
  2689. var divLog = WMEAC.getId('wmeac-csv-closures-log');
  2690. divLog.innerHTML = "";
  2691. };
  2692.  
  2693. WMEAC.csvShowList = function(show)
  2694. {
  2695. var divList = WMEAC.getId('wmeac-csv-closures');
  2696. divList.style.display=(show?"block":"none");
  2697. };
  2698.  
  2699. WMEAC.csvCheckAllSegments = function (i)
  2700. {
  2701. if (i==-1) // firt call: init progressbar
  2702. {
  2703. WMEAC.pb.update(0);
  2704. WMEAC.pb.show(true);
  2705. // and call the check on first closure
  2706. window.setTimeout(function () { WMEAC.csvCheckAllSegments(0); });
  2707. return;
  2708. }
  2709. var continueSegmentCheck = function()
  2710. {
  2711. window.setTimeout(function () { WMEAC.csvCheckAllSegments(i+1); });
  2712. };
  2713. if (i<WMEAC.csvCurrentBatchClosureList.length)
  2714. {
  2715. var currentClosure = WMEAC.csvCurrentBatchClosureList[i];
  2716. WMEAC.pb.update(i*100/WMEAC.csvCurrentBatchClosureList.length);
  2717. WMEAC.pb.info("Scanning segments. please wait...");
  2718. // check segments
  2719. // catch window tile
  2720. var c = OpenLayers.Layer.SphericalMercator.forwardMercator(currentClosure.closure.lonlat.lon, currentClosure.closure.lonlat.lat);
  2721. var b = W.map.calculateBounds();
  2722. var zoomRatio = Math.pow(2, W.map.zoom - currentClosure.closure.zoom);
  2723. var w = b.getWidth()*1.7*zoomRatio;
  2724. var h = b.getHeight()*1.7*zoomRatio;
  2725.  
  2726. var tileBounds = new OpenLayers.Bounds(c.lon - w / 2, c.lat - h / 2, c.lon + w / 2, c.lat + h / 2);
  2727. tileBounds=tileBounds.transform(W.map.getProjectionObject(), new OpenLayers.Projection("EPSG:4326")).toBBOX();
  2728. var roadTypes = (WMEAC.zoomToRoadType(currentClosure.closure.zoom)==-1?_.range(1, 22):WMEAC.zoomToRoadType(currentClosure.closure.zoom));
  2729. var WFVS = WMEAC.WMEAPI.require("Waze/Feature/Vector/Segment");
  2730. var aseg = new WFVS;
  2731. var req = new XMLHttpRequest();
  2732. req.open('GET', document.location.protocol + '//' + document.location.host + W.Config.api_base + '/Features?roadTypes=' + roadTypes.join('%2C') + '&problemFilter=0&mapUpdateRequestFilter=0&roadClosures=true&userAreas=false&managedAreas=false&majorTrafficEvents=false&bbox=' + encodeURIComponent(tileBounds) + '&language=en', true);
  2733. req.onreadystatechange = function (e) {
  2734. if (req.readyState == 4) {
  2735. if(req.status == 200)
  2736. {
  2737. //WMEAC.log(req.responseText);
  2738. try {
  2739. var data = JSON.parse(req.responseText);
  2740. WMEAC.log("data", data);
  2741. var existingSegs = currentClosure.closure.segIDs.filter(function (sid) {
  2742. return (data.segments.objects.find(function (seg) {
  2743. return (sid == seg.id);
  2744. })!=null);
  2745. });
  2746. var editableClosuresSegs = currentClosure.closure.segIDs.filter(function (sid) {
  2747. return (data.segments.objects.find(function (seg) {
  2748. return (sid == seg.id && (seg.permissions)&aseg.permissionFlags.EDIT_CLOSURES);
  2749. })!=null);
  2750. });
  2751. // look for closures on existing segs and build overlap list
  2752. var overlaps=[];
  2753. var existingClosures = existingSegs.forEach(function (sid) {
  2754. var cl = data.roadClosures.objects.filter(function (c) {
  2755. return (c.segID==sid);
  2756. });
  2757. console.log('cl', cl);
  2758. cl.forEach(function (c) {
  2759. var forwardMustBe = currentClosure.closure.direction=="A to B"?true:(currentClosure.closure.direction=="B to A"?false:null);
  2760. console.log('forwardMustBe', forwardMustBe);
  2761. console.log('dateTimeOverlaps', currentClosure.closure);
  2762. console.log('dateTimeOverlaps', c);
  2763. if (WMEAC.dateTimeOverlaps(currentClosure.closure, c))
  2764. {
  2765. if (forwardMustBe==null || forwardMustBe==c.forward)
  2766. {
  2767. var segment = data.segments.objects.find(function (seg) {
  2768. return seg.id==sid;
  2769. });
  2770. var streetName=null;
  2771. if (segment && segment.primaryStreetID!=null)
  2772. {
  2773. var street = data.streets.objects.find(function (st) {
  2774. return st.id==segment.primaryStreetID;
  2775. });
  2776. if (street && street.name!=null)
  2777. streetName=street.name;
  2778. }
  2779. overlaps.push('Overlap with ' + c.reason + (streetName!=null?' :'+streetName:'') + ' (' + sid + ')');
  2780. }
  2781. }
  2782. });
  2783. });
  2784. if (existingSegs.length == currentClosure.closure.segIDs.length &&
  2785. editableClosuresSegs.length == currentClosure.closure.segIDs.length &&
  2786. overlaps.length==0)
  2787. {
  2788. WMEAC.csvAddLog("Seg check OK: " + currentClosure.closure.comment + " (" + currentClosure.closure.reason + "):\n" + existingSegs.length + " editable seg(s) found\n");
  2789. WMEAC.setCSVMiniLog(currentClosure, "segs OK: " + existingSegs.length + " editable seg(s) found", 1);
  2790. }
  2791. else if (existingSegs.length == currentClosure.closure.segIDs.length &&
  2792. editableClosuresSegs.length == currentClosure.closure.segIDs.length &&
  2793. overlaps.length!=0)
  2794. {
  2795. WMEAC.csvAddLog("Seg check KO: " + currentClosure.closure.comment + " (" + currentClosure.closure.reason + "):\nOverlap detected on existing closures:\n" + overlaps.join('\n') + '\n');
  2796. WMEAC.setCSVMiniLog(currentClosure, "segs KO: " + overlaps.length + " overlap(s) detected", 2);
  2797. }
  2798. else if (existingSegs.length == currentClosure.closure.segIDs.length &&
  2799. editableClosuresSegs.length != currentClosure.closure.segIDs.length)
  2800. {
  2801. WMEAC.csvAddLog("Seg check KO: " + currentClosure.closure.comment + " (" + currentClosure.closure.reason + "):\n" + existingSegs.length + "/" + currentClosure.closure.segIDs.length + " seg(s) found but " + (currentClosure.closure.segIDs.length-editableClosuresSegs.length) + " are not editable\n");
  2802. WMEAC.setCSVMiniLog(currentClosure, "segs KO: " + existingSegs.length + "/" + currentClosure.closure.segIDs.length + " seg(s) found and " + (currentClosure.closure.segIDs.length-editableClosuresSegs.length) + " are not editable", 2);
  2803. }
  2804. else
  2805. {
  2806. WMEAC.csvAddLog("Seg check KO: " + currentClosure.closure.comment + " (" + currentClosure.closure.reason + "):\n" + existingSegs.length + "/" + currentClosure.closure.segIDs.length + " seg(s) found\n");
  2807. WMEAC.setCSVMiniLog(currentClosure, "segs KO: " + existingSegs.length + "/" + currentClosure.closure.segIDs.length + " seg(s) found", 3);
  2808. }
  2809. }
  2810. catch (err)
  2811. {
  2812. WMEAC.log("Failed to parse Waze's server response: " + req.responseText);
  2813. WMEAC.csvAddLog("Seg check KO: " + currentClosure.closure.comment + " (" + currentClosure.closure.reason + "):\nFailed to parse response from Waze\n");
  2814. WMEAC.setCSVMiniLog(currentClosure, "segs KO: Failed to parse response from Waze", 3);
  2815. }
  2816. }
  2817. else
  2818. {
  2819. WMEAC.log("Error on road tile: " + e.target.status);
  2820. WMEAC.csvAddLog("Seg check KO: " + currentClosure.closure.comment + " (" + currentClosure.closure.reason + "):\nCommunication failed with Waze\n");
  2821. WMEAC.setCSVMiniLog(currentClosure, "segs KO: Communication failed with Waze", 3);
  2822. }
  2823. continueSegmentCheck();
  2824. }
  2825. };
  2826. req.onError = function (e) {
  2827. WMEAC.log("Error on road tile: " + e.target.status);
  2828. WMEAC.csvAddLog("Seg check KO: " + currentClosure.closure.comment + " (" + currentClosure.closure.reason + "):\nCommunication failed with Waze's server\n");
  2829. WMEAC.setCSVMiniLog(currentClosure, "segs KO: Communication failed with Waze", 3);
  2830. continueSegmentCheck();
  2831. };
  2832. /* // Useless since waze server never send content length... :/
  2833. req.onprogress = function(e) {
  2834. WMEAC.pb.update((i+(e.position / e.totalSize))*100/WMEAC.csvCurrentClosureList.length);
  2835. };*/
  2836. req.send(null);
  2837. }
  2838. else // end of check
  2839. {
  2840. WMEAC.pb.show(false);
  2841. }
  2842.  
  2843. };
  2844.  
  2845. WMEAC.setCSVMiniLog = function(closure, text, level) // level=0: black 1: green, 2:orange, 3: red
  2846. {
  2847. var c=null;
  2848. if (closure.hasOwnProperty('UI'))
  2849. c=closure;
  2850. else
  2851. c = WMEAC.csvCurrentClosureList.find(function (e) {
  2852. return (e.closure.id == closure.id);
  2853. });
  2854.  
  2855. if (c!=null)
  2856. {
  2857. c.UI.children[7].innerHTML=text;
  2858. var colors = ["#000000", "#54C600", "#FFA000", "#FF0000"];
  2859. if (arguments.length==3)
  2860. c.UI.children[7].style.color=colors[level];
  2861. else
  2862. c.UI.children[7].style.color=colors[0];
  2863. }
  2864. };
  2865.  
  2866. WMEAC.CSVCheckAll = function (check)
  2867. {
  2868. WMEAC.csvCurrentClosureList.forEach(function (e) {
  2869. e.UI.children[0].children[0].checked = check;
  2870. });
  2871. };
  2872.  
  2873. WMEAC.CSVApplyChecked = function ()
  2874. {
  2875. WMEAC.csvCurrentBatchClosureList = WMEAC.csvCurrentClosureList.filter(function (e) {
  2876. return (e.UI.children[0].children[0].checked);
  2877. });
  2878. WMEAC.csvClearLog();
  2879. if (WMEAC.csvCurrentBatchClosureList.length==0)
  2880. {
  2881. WMEAC.csvAddLog("No closure checked!\n");
  2882. }
  2883. else
  2884. {
  2885. WMEAC.showClosuresLayer(true);
  2886. WMEAC.pb.update(0);
  2887. WMEAC.pb.info("Applying closures. please wait...");
  2888. WMEAC.pb.show(true);
  2889. WMEAC.csvAddLog("Start to apply selected closures\n");
  2890. window.setTimeout(function () { WMEAC.CSVBatchApply(0); });
  2891. }
  2892. };
  2893.  
  2894. WMEAC.CSVBatchApply = function(i)
  2895. {
  2896. WMEAC.pb.update(i*100/WMEAC.csvCurrentBatchClosureList.length);
  2897.  
  2898. if (i<WMEAC.csvCurrentBatchClosureList.length)
  2899. {
  2900. if (WMEAC.csvCurrentBatchClosureList[i].action!='add' &&
  2901. WMEAC.csvCurrentBatchClosureList[i].action!='remove')
  2902. {
  2903. WMEAC.csvAddLog("Closure KO: " + WMEAC.csvCurrentBatchClosureList[i].closure.comment + " (" + WMEAC.csvCurrentBatchClosureList[i].closure.reason + "): action " + WMEAC.csvCurrentBatchClosureList[i].action + " not supported yet\n");
  2904. WMEAC.setCSVMiniLog(WMEAC.csvCurrentBatchClosureList[i], "KO: action " + WMEAC.csvCurrentBatchClosureList[i].action + " not supported yet", 2);
  2905. WMEAC.CSVBatchApply(i+1);
  2906. }
  2907. else
  2908. {
  2909. WMEAC.csvApplyClosure(WMEAC.csvCurrentBatchClosureList[i], function (success) {
  2910. if (success)
  2911. WMEAC.csvAddLog("Closure OK: " + WMEAC.csvCurrentBatchClosureList[i].closure.comment + " (" + WMEAC.csvCurrentBatchClosureList[i].closure.reason + ")\n");
  2912. else
  2913. WMEAC.csvAddLog("Closure KO: " + WMEAC.csvCurrentBatchClosureList[i].closure.comment + " (" + WMEAC.csvCurrentBatchClosureList[i].closure.reason + ")\n");
  2914. WMEAC.CSVBatchApply(i+1);
  2915. });
  2916. }
  2917. }
  2918. else
  2919. {
  2920. WMEAC.csvAddLog("Apply selected closures ended\n");
  2921. WMEAC.reloadClosuresLayer();
  2922. WMEAC.pb.show(false);
  2923. }
  2924. };
  2925.  
  2926. WMEAC.CSVCheckSegsChecked = function ()
  2927. {
  2928. WMEAC.csvClearLog();
  2929. WMEAC.csvCurrentBatchClosureList = WMEAC.csvCurrentClosureList.filter(function (e) {
  2930. return (e.UI.children[0].children[0].checked);
  2931. });
  2932. if (WMEAC.csvCurrentBatchClosureList.length==0)
  2933. {
  2934. WMEAC.csvAddLog("No closure checked!\n");
  2935. }
  2936. else
  2937. {
  2938. WMEAC.csvCheckAllSegments(-1);
  2939. }
  2940. };
  2941.  
  2942.  
  2943. /***********************************************
  2944. *** END OF INCLUDED FILE : ***
  2945. *** include/csv.js ***
  2946. ***********************************************/
  2947.  
  2948.  
  2949. /***********************************************
  2950. *** IN INCLUDED FILE : ***
  2951. *** include/highlight.js ***
  2952. ***********************************************/
  2953.  
  2954. WMEAC.refreshHighlight = function ()
  2955. {
  2956. try
  2957. {
  2958. var l = W.map.getLayersBy("uniqueName", "closures");
  2959. if (l.length==1) l=l[0];
  2960. for (var m in l.markers)
  2961. {
  2962. if (!l.markers.hasOwnProperty(m)) continue;
  2963. var marker = l.markers[m];
  2964. if (marker.model.reason &&
  2965. marker.model.reason.length>=1 &&
  2966. marker.model.reason.charCodeAt(marker.model.reason.length-1)==160)
  2967. marker.icon.$div.addClass('wmeac-hl');
  2968. }
  2969. }
  2970. catch (e) {
  2971. WMEAC.log("Highlight error: ", e);
  2972. }
  2973. };
  2974.  
  2975. /***********************************************
  2976. *** END OF INCLUDED FILE : ***
  2977. *** include/highlight.js ***
  2978. ***********************************************/
  2979.  
  2980.  
  2981. if (typeof window.require != 'undefined' && typeof window.define == 'undefined') // that's the require provided by waze devs
  2982. {
  2983. WMEAC.WMEAPI={require: window.require};
  2984. // start normally
  2985. WMEAC.bootstrapAC();
  2986. }
  2987. else
  2988. {
  2989. // use the patch.
  2990. // the patch will call bootstrapAC to start the script
  2991. /***********************************************
  2992. *** IN INCLUDED FILE : ***
  2993. *** include/requirePatch.js ***
  2994. ***********************************************/
  2995.  
  2996. // setup one global var and put all in
  2997. var WMEAPI = {};
  2998.  
  2999.  
  3000. // detect URL of WME source code
  3001. WMEAPI.scripts = document.getElementsByTagName('script');
  3002. WMEAPI.url=null;
  3003. for (i=0;i<WMEAPI.scripts.length;i++)
  3004. {
  3005. if (WMEAPI.scripts[i].src.indexOf('/assets-editor/js/app')!=-1)
  3006. {
  3007. WMEAPI.url=WMEAPI.scripts[i].src;
  3008. break;
  3009. }
  3010. }
  3011. if (WMEAPI.url==null)
  3012. {
  3013. throw new Error("WME require patch: can't detect WME main JS");
  3014. }
  3015.  
  3016.  
  3017.  
  3018. // setup a fake require and require.define
  3019. WMEAPI.require=function (e) {
  3020. if (WMEAPI.require.define.modules.hasOwnProperty(e))
  3021. return WMEAPI.require.define.modules[e];
  3022. else
  3023. console.error('Require failed on ' + e, WMEAPI.require.define.modules);
  3024. return null;
  3025. };
  3026.  
  3027. WMEAPI.require.define=function (m) {
  3028. if (WMEAPI.require.define.hasOwnProperty('modules')==false)
  3029. WMEAPI.require.define.modules={};
  3030. for (var p in m)
  3031. {
  3032. WMEAPI.require.define.modules[p]=m[p];
  3033. }
  3034. };
  3035.  
  3036. // save the original webpackJsonp function
  3037. WMEAPI.tmp = window.webpackJsonp;
  3038.  
  3039. // taken from WME code: this function is a wrapper that setup the API and may call recursively other functions
  3040. WMEAPI.t = function (n) {
  3041. if (WMEAPI.s[n]) return WMEAPI.s[n].exports;
  3042. var r = WMEAPI.s[n] = {
  3043. exports: {},
  3044. id: n,
  3045. loaded: !1
  3046. };
  3047. return WMEAPI.e[n].call(r.exports, r, r.exports, WMEAPI.t), r.loaded = !0, r.exports;
  3048. };
  3049.  
  3050. // e is a copy of all WME funcs because function t need to access to this list
  3051. WMEAPI.e=[];
  3052.  
  3053. // the patch
  3054. window.webpackJsonp = function(a, i) {
  3055. // our API but we will use it only to build the require stuffs
  3056. var api={};
  3057. // taken from WME code. a is [1], so...
  3058. for (var o, d, u = 0, l = []; u < a.length; u++) d = a[u], WMEAPI.r[d] && l.push.apply(l, WMEAPI.r[d]), WMEAPI.r[d] = 0;
  3059. var unknownCount=0;
  3060. var classname, funcStr;
  3061. // copy i in e and keep a link from classname to index in e
  3062. for (o in i)
  3063. {
  3064. WMEAPI.e[o] = i[o];
  3065. funcStr = i[o].toString();
  3066. classname = funcStr.match(/CLASS_NAME:\"([^\"]*)\"/);
  3067. if (classname)
  3068. {
  3069. // keep the link.
  3070. api[classname[1].replace(/\./g,'/').replace(/^W\//, 'Waze/')]={index: o, func: WMEAPI.e[o]};
  3071. }
  3072. else
  3073. {
  3074. api['Waze/Unknown/' + unknownCount]={index: o, func: WMEAPI.e[o]};
  3075. unknownCount++;
  3076. }
  3077. }
  3078. // taken from WME code: it calls the original webpackJsonp and do something else, but I don't really know what.
  3079. // removed the call to the original webpackJsonp: still works...
  3080. //for (tmp && tmp(a, i); l.length;) l.shift().call(null, t);
  3081. for (; l.length;) l.shift().call(null, WMEAPI.t);
  3082. WMEAPI.s[0] = 0;
  3083. // run the first func of WME. This first func will call recusrsively all funcs needed to setup the API.
  3084. // After this call, s will contain all instanciables classes.
  3085. //var ret = WMEAPI.t(0);
  3086. // now, build the requires thanks to the link we've built in var api.
  3087. var module={};
  3088. var apiFuncName;
  3089. unknownCount=0;
  3090. for (o in i)
  3091. {
  3092. funcStr = i[o].toString();
  3093. classname = funcStr.match(/CLASS_NAME:\"([^\"]*)\"/);
  3094. if (classname)
  3095. {
  3096. module={};
  3097. apiFuncName = classname[1].replace(/\./g,'/').replace(/^W\//, 'Waze/');
  3098. module[apiFuncName]=WMEAPI.t(api[apiFuncName].index);
  3099. WMEAPI.require.define(module);
  3100. }
  3101. else
  3102. {
  3103. var matches = funcStr.match(/SEGMENT:"segment",/);
  3104. if (matches)
  3105. {
  3106. module={};
  3107. apiFuncName='Waze/Model/ObjectType';
  3108. module[apiFuncName]=WMEAPI.t(api['Waze/Unknown/' + unknownCount].index);
  3109. WMEAPI.require.define(module);
  3110. }
  3111. else if (matches = funcStr.match(/TWO_WAY:/))
  3112. {
  3113. module={};
  3114. apiFuncName='Waze/Modules/Closures/Models/SharedClosure';
  3115. module[apiFuncName]=WMEAPI.t(api['Waze/Unknown/' + unknownCount].index);
  3116. WMEAPI.require.define(module);
  3117. }
  3118. else if (matches = funcStr.match(/nextClosureID:/))
  3119. {
  3120. module={};
  3121. apiFuncName='Waze/Modules/Closures/Models/ClosureActionBuilder';
  3122. module[apiFuncName]=WMEAPI.t(api['Waze/Unknown/' + unknownCount].index);
  3123. WMEAPI.require.define(module);
  3124. }
  3125.  
  3126. unknownCount++;
  3127. }
  3128. }
  3129.  
  3130. // restore the original func
  3131. window.webpackJsonp=WMEAPI.tmp;
  3132.  
  3133. // set the require public if needed
  3134. // if so: others scripts must wait for the window.require to be available before using it.
  3135. // window.require=WMEAPI.require;
  3136. WMEAC.WMEAPI = WMEAPI;
  3137. // all available functions are in WMEAPI.require.define.modules
  3138. // console.debug this variable to read it:
  3139. // console.debug('Modules: ', WMEAPI.require.define.modules);
  3140. // run your script here:
  3141. setTimeout(WMEAC.bootstrapAC);
  3142. // again taken from WME code. Not sure about what it does.
  3143. //if (i[0]) return ret;
  3144. };
  3145.  
  3146. // some kind of global vars and init
  3147. WMEAPI.s = {};
  3148. WMEAPI.r = {
  3149. 0: 0
  3150. };
  3151.  
  3152. // hacking finished
  3153.  
  3154. // load again WME through our patched func
  3155. WMEAPI.WMEHACK_Injected_script = document.createElement("script");
  3156. WMEAPI.WMEHACK_Injected_script.setAttribute("type", "application/javascript");
  3157. WMEAPI.WMEHACK_Injected_script.src = WMEAPI.url;
  3158. document.body.appendChild(WMEAPI.WMEHACK_Injected_script);
  3159.  
  3160.  
  3161. /***********************************************
  3162. *** END OF INCLUDED FILE : ***
  3163. *** include/requirePatch.js ***
  3164. ***********************************************/
  3165.  
  3166.  
  3167. }
  3168. WMEAC.log("Ready");
  3169. }
  3170.  
  3171. function bootstrap(tries = 1) {
  3172. if (W &&
  3173. W.map &&
  3174. W.model &&
  3175. W.loginManager.user &&
  3176. $)
  3177. init();
  3178. else if (tries < 1000)
  3179. setTimeout(function () {bootstrap(tries++);}, 200);
  3180. }
  3181.  
  3182. bootstrap();
  3183.  
  3184. function init(){
  3185. var WMEAC_Injected_script = document.createElement("script");
  3186. WMEAC_Injected_script.textContent = '' + WMEAC_Injected.toString() + ' \n' + 'WMEAC_Injected();';
  3187. WMEAC_Injected_script.setAttribute("type", "application/javascript");
  3188. document.body.appendChild(WMEAC_Injected_script);
  3189. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址