您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
WME Context Menu stores various editor elements in an easy-to-access right-click menu. It can copy properties of selected segments to clipboard and it integrates with WME Speedhelper and WME Road Selector to help make it even easier and faster to edit the map.
当前为
// ==UserScript== // @name WME Context Menu // @namespace https://greasyforks.org/users/11629-TheLastTaterTot // @version 0.3.2 // @description WME Context Menu stores various editor elements in an easy-to-access right-click menu. It can copy properties of selected segments to clipboard and it integrates with WME Speedhelper and WME Road Selector to help make it even easier and faster to edit the map. // @author TheLastTaterTot // @include https://editor-beta.waze.com/*editor/* // @include https://www.waze.com/*editor/* // @exclude https://www.waze.com/*user/editor/* // @grant GM_setClipboard // @run-at document-end // ==/UserScript== /* jshint -W097 */ var _W_, _$_, roadTypes = { 1: "Street", 2: "Primary Street", 3: "Freeway", 4: "Ramp", 5: "Walking Trail", 6: "Major Highway", 7: "Minor Highway", 8: "Dirt road / 4X4 Trail", 10: "Pedestrian Boardwalk", 15: "Ferry", 16: "Stairway", 17: "Private Road", 18: "Railroad", 19: "Runway/Taxiway", 20: "Parking Lot Road" }, menuResetEvent_RSel = false, menuResetEvent_SL = true, contextMenuSettings, slMaxElementCount = 0, speedhelperHTML = false, SL_imperial = { countries: ['UK', 'US', 'MU', 'AR', 'IC', 'JE', 'GQ', 'CJ', 'BM', 'LI'], mph2kph: 1.609344, kph2mph: 0.621371192, convertUnits: null }, minVersion = '0.3', isFirefox = !!~navigator.userAgent.indexOf('Firefox'); if (isFirefox && !localStorage.WME_ContextMenuFF) { window.alert('Hello, my Firefox-using friends! The new version (0.3) would have brought you lots of great enhancements for help with inputting speed limits, but unfortunately, Firefox is being a jerk and refuses to work properly. If you would like to see what you\'re missing, you could visit the forum post for the new version here: https://tiny.cc/wmecm \n\nI will try to fix it for FireFox as soon as I can, but for now it will only work in Chrome. Sorry!\n\nNOTE: You should feel free to leave this script enabled in GreaseMonkey if you would like it to update as soon as the fix is released. This script version will automatically quit running once it has detected a Firefox browser.\n\nAnd don\'t worry; you will only see this message pop up this one time.'); localStorage.WME_ContextMenuFF = true; return false; } else if (isFirefox) { return false } if (localStorage.WME_ContextMenu) { contextMenuSettings = JSON.parse(localStorage.WME_ContextMenu); } else { contextMenuSettings = { clipboard: 0, position: 0, pin: false, countries: [], version: 0 }; localStorage.WME_ContextMenu = JSON.stringify(contextMenuSettings); } CMenuVersion = { currentVersion: GM_info.script.version, lastVersionString: function(){return contextMenuSettings.version}, convertToNumericVersion: function(versionString) { var vMult = [8000, 400, 20, 1], versionNumeric = 0; if (versionString) { if (versionString.constructor === Array) { if (versionString.length === 1) { versionString = versionString[0]; } else { console.error('WMEKMLayers:', 'versionString is an array with more than 1 element.') } } return versionString.match(/(\d)+/g).map(function(d, i) { versionNumeric += d * vMult[i]; }), versionNumeric; } else { return null; } }, getLastVersionValue: function() { return this.convertToNumericVersion(this.lastVersionString()); }, updateVersionString: function() { contextMenuSettings.version = this.currentVersion; localStorage.WME_ContextMenu = JSON.stringify(contextMenuSettings); }, isUpToDate: function(minimumVersionString) { var minVersionVal = this.convertToNumericVersion(minimumVersionString), lastVersionVal = this.getLastVersionValue(); return (lastVersionVal >= minVersionVal) ? true : false; } }; var getUnique = function (objArray) { var isNotDuplicate = function (comparisonList, checkThisName) { var isNotDup = true; try { for (var c = 0, cLength = comparisonList.length; c < cLength; c++) { if (comparisonList[c] === checkThisName) isNotDup = false; } } catch (err) { console.error(err); } return isNotDup; }; try { var uniqObjs = []; for (var r = objArray.length; r--;) { if (isNotDuplicate(uniqObjs, objArray[r])) uniqObjs.push(objArray[r]); // && objArray[r] !== '' } return uniqObjs; } catch (err) { console.error(err); } }; var addStreetAndCityToRSel = function (segIds, caseSelection) { var opAndOr = parseInt(document.getElementById('cmOpAddOr').value), opNot = document.getElementById('cmOpNot').classList.contains('active'), addConjunction = !!document.getElementById('outRSExpr').innerHTML.length; switch (caseSelection ^ 0) { case 'primaryStreet': case 0: if (segIds.primaryStreet.length !== 0) { for (var s = segIds.primaryStreet.length; s--;) { if (addConjunction) { if (opAndOr) { document.getElementById('btnRSOr').click(); } else { document.getElementById('btnRSAnd').click(); } } if (opNot) document.getElementById('btnRSNot').click(); //set to primary document.getElementById('selRSAlttStreet').value = 0; document.getElementById('selRSAltCity').value = 0; document.getElementById('btnRSLBkt').click(); document.getElementById('inRSStreet').value = _W_.model.streets.objects[segIds.primaryStreet[s]].name; document.getElementById('btnRSAddStreet').click(); //document.getElementById('btnRSAnd').click(); document.getElementById('inRSCity').value = _W_.model.cities.objects[_W_.model.streets.objects[segIds.primaryStreet[s]].cityID].name; document.getElementById('btnRSAddCity').click(); document.getElementById('btnRSRBkt').click(); } } break; case 'altStreets': case 1: if (segIds.altStreets.length !== 0) { for (var s = segIds.primaryStreet.length; s--;) { if (addConjunction) { if (opAndOr) { document.getElementById('btnRSOr').click(); } else { document.getElementById('btnRSAnd').click(); } } if (opNot) document.getElementById('btnRSNot').click(); //set to alt document.getElementById('selRSAlttStreet').value = 1; document.getElementById('selRSAltCity').value = 1; document.getElementById('btnRSLBkt').click(); document.getElementById('inRSStreet').value = _W_.model.streets.objects[segIds.altStreets[s]].name; document.getElementById('btnRSAddStreet').click(); //document.getElementById('btnRSAnd').click(); document.getElementById('inRSCity').value = _W_.model.cities.objects[_W_.model.streets.objects[segIds.altStreets[s]].cityID].name; document.getElementById('btnRSAddCity').click(); document.getElementById('btnRSRBkt').click(); } } break; case 'anyStreet': case 2: addStreetAndCityToRSel(segIds, 0); //primary addStreetAndCityToRSel(segIds, 1); //alt break; } }; var addStreetNameToRSel = function (segNames, inputFieldId, altSelId, altVal, addBtnId) { var opAndOr = parseInt(document.getElementById('cmOpAddOr').value), opNot = document.getElementById('cmOpNot').classList.contains('active'), addConjunction = !!document.getElementById('outRSExpr').innerHTML.length; for (var n = 0, nLength = segNames.length; n < nLength; n++) { if (addConjunction) { if (opAndOr) { document.getElementById('btnRSOr').click(); } else { document.getElementById('btnRSAnd').click(); } } if (opNot) document.getElementById('btnRSNot').click(); document.getElementById(inputFieldId).value = segNames[n]; document.getElementById(altSelId).value = altVal ^ 0; document.getElementById(addBtnId).click(); addConjunction = true; } }; var addRoadTypeToRSel = function (ids, inputFieldId, addBtnId) { var opAndOr = parseInt(document.getElementById('cmOpAddOr').value), opNot = document.getElementById('cmOpNot').classList.contains('active'), addConjunction = !!document.getElementById('outRSExpr').innerHTML.length; document.getElementById('btnRSLBkt').click(); for (var n = 0, nLength = ids.length; n < nLength; n++) { if (addConjunction) { if (opAndOr) { document.getElementById('btnRSOr').click(); } else { document.getElementById('btnRSAnd').click(); } } if (opNot) document.getElementById('btnRSNot').click(); document.getElementById(inputFieldId).value = ids[n]; document.getElementById(addBtnId).click(); addConjunction = true; } document.getElementById('btnRSRBkt').click(); }; var copyTo = function (e, opt, val) { if (document.getElementById('cmPinMenu').value) e.stopPropagation(); if (document.getElementById('cmClipboard').value) { GM_setClipboard(val); } else { try { switch (opt) { case 'cm_priSC': if (document.getElementById('cmRoadType').classList.contains('active')) { addRoadTypeToRSel(getUnique(val.roadType), 'selRSRoadType', 'btnRSAddRoadType'); document.getElementById('btnRSAnd').click(); document.getElementById('btnRSLBkt').click(); addStreetAndCityToRSel(val, 0); document.getElementById('btnRSRBkt').click(); } else { addStreetAndCityToRSel(val, 0); } break; case 'cm_altSC': if (document.getElementById('cmRoadType').classList.contains('active')) { addRoadTypeToRSel(getUnique(val.roadType), 'selRSRoadType', 'btnRSAddRoadType'); document.getElementById('btnRSAnd').click(); document.getElementById('btnRSLBkt').click(); addStreetAndCityToRSel(val, 1); document.getElementById('btnRSRBkt').click(); } else { addStreetAndCityToRSel(val, 1); } break; case 'cm_anySC': if (document.getElementById('cmRoadType').classList.contains('active')) { addRoadTypeToRSel(getUnique(val.roadType), 'selRSRoadType', 'btnRSAddRoadType'); document.getElementById('btnRSAnd').click(); document.getElementById('btnRSLBkt').click(); addStreetAndCityToRSel(val, 2); document.getElementById('btnRSRBkt').click(); } else { addStreetAndCityToRSel(val, 2); } break; case 'cm_priS': if (document.getElementById('cmRoadType').classList.contains('active')) { addRoadTypeToRSel(getUnique(val.roadType), 'selRSRoadType', 'btnRSAddRoadType'); document.getElementById('btnRSAnd').click(); document.getElementById('btnRSLBkt').click(); addStreetNameToRSel(getUnique(val.primaryStreet), 'inRSStreet', 'selRSAlttStreet', 0, 'btnRSAddStreet'); document.getElementById('btnRSRBkt').click(); } else { addStreetNameToRSel(getUnique(val.primaryStreet), 'inRSStreet', 'selRSAlttStreet', 0, 'btnRSAddStreet'); } break; case 'cm_altS': if (document.getElementById('cmRoadType').classList.contains('active')) { addRoadTypeToRSel(getUnique(val.roadType), 'selRSRoadType', 'btnRSAddRoadType'); document.getElementById('btnRSAnd').click(); document.getElementById('btnRSLBkt').click(); addStreetNameToRSel(getUnique(val.altStreets), 'inRSStreet', 'selRSAlttStreet', 1, 'btnRSAddStreet'); document.getElementById('btnRSRBkt').click(); } else { addStreetNameToRSel(getUnique(val.altStreets), 'inRSStreet', 'selRSAlttStreet', 1, 'btnRSAddStreet'); } break; case 'cm_anyS': if (document.getElementById('cmRoadType').classList.contains('active')) { addRoadTypeToRSel(getUnique(val.roadType), 'selRSRoadType', 'btnRSAddRoadType'); document.getElementById('btnRSAnd').click(); document.getElementById('btnRSLBkt').click(); addStreetNameToRSel(getUnique(val.primaryStreet), 'inRSStreet', 'selRSAlttStreet', 0, 'btnRSAddStreet'); addStreetNameToRSel(getUnique(val.altStreets), 'inRSStreet', 'selRSAlttStreet', 1, 'btnRSAddStreet'); document.getElementById('btnRSRBkt').click(); } else { addStreetNameToRSel(getUnique(val.primaryStreet), 'inRSStreet', 'selRSAlttStreet', 0, 'btnRSAddStreet'); addStreetNameToRSel(getUnique(val.altStreets), 'inRSStreet', 'selRSAlttStreet', 1, 'btnRSAddStreet'); } break; case 'cm_ids': document.getElementById('inRSSegId').value = val; document.getElementById('btnRSAddSegId').classList.add('btn-info'); break; case 'cm_primaryStreet': document.getElementById('inRSStreet').value = val; document.getElementById('selRSAlttStreet').value = 0; document.getElementById('btnRSAddStreet').classList.add('btn-info'); break; case 'cm_altStreets': document.getElementById('inRSStreet').value = val; document.getElementById('selRSAlttStreet').value = 1; document.getElementById('btnRSAddStreet').classList.add('btn-info'); break; case 'cm_altStreetsAND': document.getElementById('inRSStreet').value = ''; break; case 'cm_altStreetsOR': document.getElementById('inRSStreet').value = ''; break; case 'cm_primaryCity': document.getElementById('inRSCity').value = val; document.getElementById('selRSAltCity').value = 0; document.getElementById('btnRSAddCity').classList.add('btn-info'); break; case 'cm_altCities': document.getElementById('inRSCity').value = val; document.getElementById('selRSAltCity').value = 1; document.getElementById('btnRSAddCity').classList.add('btn-info'); break; case 'cm_state': document.getElementById('inRSState').value = val; document.getElementById('btnRSAddState').classList.add('btn-info'); break; case 'cm_roadType': document.getElementById('selRSRoadType').value = val; document.getElementById('btnRSAddRoadType').classList.add('btn-info'); break; case 'cm_updatedBy': document.getElementById('inRSUpdtd').value = val; document.getElementById('btnRSAddUpdtd').classList.add('btn-info'); break; case 'cm_createdBy': document.getElementById('inRSCrtd').value = val; document.getElementById('btnRSAddCrtd').classList.add('btn-info'); break; case 'cm_toConnections': break; } } catch (err) { console.error(err); } // swap panel from selection panel try { document.getElementById('user-info').style.display = 'block'; document.getElementById('edit-panel').style.display = 'none'; } catch (err) { console.error(err); } // switch active tab-content try { document.querySelector('.tab-content>.active').classList.remove('active'); document.getElementById('sidepanel-roadselector').classList.add('active'); } catch (err) {} // switch active nav-tab try { document.querySelector('#user-tabs li.active').classList.remove('active'); document.getElementById('tabRSel').classList.add('active'); } catch (err) {} // switch to RSel editor tab try { document.getElementById('roadselector-tabs').children[1].classList.remove('active'); document.getElementById('roadselector-tabs').children[0].classList.add('active'); document.getElementById('roadselector-tab-content').children[1].classList.remove('active'); document.getElementById('roadselector-tab-content').children[0].classList.add('active'); } catch (err) { /* */ } } }; var getAutoAddToRSelCase = function (addType) { var nameClass = ((document.getElementById('cm_pri').checked * document.getElementById('cm_pri').value) + (document.getElementById('cm_alt').checked * document.getElementById('cm_alt').value)) - 1; switch (addType) { case 'cm_S': switch (nameClass) { case 0: //primary return 'cm_priS'; case 1: //alt return 'cm_altS'; case 2: //any return 'cm_anyS'; } break; case 'cm_SC': // cm_SC street and city switch (nameClass) { case 0: //primary return 'cm_priSC'; case 1: //alt return 'cm_altSC'; case 2: //any return 'cm_anySC'; } break; } }; var getSegmentProperties = function (selectedStuff) { try { /*var roadTypeOpts = document.querySelector('#segment-edit-general select[name="roadType"]'), numRoadTypes = roadTypeOpts.options.length, r, roadTypes = {}; for (r=0; r < numRoadTypes; r++) { roadTypes[roadTypeOpts[r].value] = roadTypeOpts[r].text; }*/ var s, s_ids = {}, s_altStObjKeys, s_altSt, s_toConnObjKeys; s_ids = { ids: {}, primaryStreet: {}, altStreets: {}, altCities: {}, roadType: {}, createdBy: {}, updatedBy: {}, toConnections: {}, primaryCity: {}, state: {}, country: {} }; for (s = selectedStuff.length; s--;) { s_ids.ids[selectedStuff[s].model.attributes.id] = null; s_ids.primaryStreet[selectedStuff[s].model.attributes.primaryStreetID] = null; s_ids.roadType[selectedStuff[s].model.attributes.roadType] = null; s_ids.createdBy[selectedStuff[s].model.attributes.createdBy] = null; s_ids.updatedBy[selectedStuff[s].model.attributes.updatedBy] = null; s_ids.primaryCity[_W_.model.streets.objects[selectedStuff[s].model.attributes.primaryStreetID].cityID] = null; s_ids.state[_W_.model.cities.objects[_W_.model.streets.objects[selectedStuff[s].model.attributes.primaryStreetID].cityID].stateID] = null; s_ids.country[_W_.model.cities.objects[_W_.model.streets.objects[selectedStuff[s].model.attributes.primaryStreetID].cityID].countryID] = null; s_altSt = selectedStuff[s].model.attributes.streetIDs; for (var a = 0, numAlts = s_altSt.length; a < numAlts; a++) { s_ids.altStreets[s_altSt[a]] = null; s_ids.altCities[_W_.model.streets.objects[s_altSt[a]].cityID] = null; } s_toConnObjKeys = Object.keys(selectedStuff[s].model.attributes.toConnections); for (var k = 0, numKeys = s_toConnObjKeys.length; k < numKeys; k++) { if (s_toConnObjKeys[k] !== '') { s_ids.toConnections[s_toConnObjKeys[k]] = selectedStuff[s].model.attributes.toConnections[s_toConnObjKeys[k]]; } } } var seg_ids = {}, seg_names = { ids: [], primaryStreet: [], altStreets: [], altCities: [], roadType: [], createdBy: [], updatedBy: [], toConnections: [], primaryCity: [], state: [], country: [] }; for (var idKey in s_ids) { seg_ids[idKey] = Object.keys(s_ids[idKey]); for (var k = 0, numKeys = seg_ids[idKey].length; k < numKeys; k++) { if (seg_ids[idKey][k] !== '') { switch (idKey) { case 'primaryStreet': seg_names[idKey][k] = _W_.model.streets.objects[seg_ids[idKey][k]].name; break; case 'primaryCity': seg_names[idKey][k] = _W_.model.cities.objects[seg_ids[idKey][k]].name; break; case 'altStreets': seg_names[idKey][k] = _W_.model.streets.objects[seg_ids[idKey][k]].name; break; case 'altCities': seg_names[idKey][k] = _W_.model.cities.objects[seg_ids[idKey][k]].name; break; case 'state': seg_names[idKey][k] = _W_.model.states.objects[seg_ids[idKey][k]].name; break; case 'roadType': seg_names[idKey][k] = roadTypes[String(seg_ids[idKey][k])]; break; case 'createdBy': seg_names[idKey][k] = _W_.model.users.objects[seg_ids[idKey][k]].userName; break; case 'updatedBy': seg_names[idKey][k] = _W_.model.users.objects[seg_ids[idKey][k]].userName; break; } } } } return { ids: seg_ids, names: seg_names }; } catch (err) { console.error(err); } }; var addHotkeyListener = function() { window.addEventListener('keydown', menuShortcutKeys, true); //console.info('WMECM:','Adding global hotkey listener due to mouseenter'); }; var removeHotkeyListener = function() { window.removeEventListener('keydown', menuShortcutKeys, true); //console.info('WMECM:','Removing global hotkey listener due to mouseleave'); }; var closeContextMenu = function () { try { // remove unnecessary hotkey listeners window.removeEventListener('keydown', menuShortcutKeys, true); document.getElementById('cmContextMenu').removeEventListener('mouseenter', addHotkeyListener, false); document.getElementById('cmContextMenu').removeEventListener('mouseleave', removeHotkeyListener, false); //console.info('WMECM:','Closing menu, so removing all hotkey listeners'); // remove unnecessary close contextmenu listeners window.removeEventListener('click', closeContextMenu, false); document.getElementById('toolbar').removeEventListener('mouseenter', closeContextMenu, false); // close the menu document.getElementById('cmContextMenu').style.display = 'none'; menuResetEvent_SL = true; } catch (err) {} }; var addSpecialMenuListeners = function () { if (document.getElementById('cmPinMenu').value) { window.removeEventListener('click', closeContextMenu, false); document.getElementById('toolbar').removeEventListener('mouseenter', closeContextMenu, false); } else { window.addEventListener('keydown', menuShortcutKeys, true); //console.info('WMECM:','Adding just global hotkey listener via addSpecialMenuListeners()'); window.addEventListener('click', closeContextMenu, false); document.getElementById('toolbar').addEventListener('mouseenter', closeContextMenu, false); } }; var resetContextMenu = function (contextMenuSettings) { if (menuResetEvent_RSel) document.getElementById('btnRSClear').click(); menuResetEvent_RSel = false; try { document.querySelector('#user-tabs a[href="#sidepanel-roadselector"]').parentNode.id = 'tabRSel'; } catch (err) {} // <label for="cm_any" class="btn cm-rsel-options badge cm-badge-right active"><input id="cm_any" type="radio" name="cmOptions" value=2 style="opacity: 0" checked>any</label> //dl - background-color: rgba(177, 210, 220, 0.75); document.getElementById('cmContainer').innerHTML = `<div id="cmRSelAutoAdd" class="cm-menu-section cm-rsel"> <dl><dt>RSel Auto-Add Names</dt> <dd><div class="btn-group pull-left" data-toggle="buttons"> <label for="cm_pri" class="btn cm-rsel-options cm-badge-left active"><input id="cm_pri" type="checkbox" value=1 checked> Primary</label> <label for="cm_alt" class="btn cm-rsel-options cm-badge-right active"><input id="cm_alt" type="checkbox" value=2 checked>Alternate </label> </div> <div class="pull-left btn-group" style="margin: 0px 2px"> <button type="button" id="cmRoadType" class="btn cm-rsel-options active">Type</button> </div> <div class="btn-group pull-right"> <button type="button" id="cmOpAddOr" class="btn cm-rsel-options cm-badge-left and" value="0" style="padding-right: 4px;">and</button> <button type="button" id="cmOpNot" class="btn cm-rsel-options cm-badge-right" style="padding-left: 4px;">!</button> </div></dd> <dd id="cm_SC">All <span id="cm_textSC">Primary/Alt. Street, City</span></dd> <dd id="cm_S">All <span id="cm_textS">Primary/Alt. Street</span></dd> </dl> </div> <div class="cm-menu-header"> <dl><dt id="cmMenuHeaderTitle">Copy To Clipboard</dt></dl> </div> <div id="cmMenuNoContent" class="cm-menu-section" style="display: none;"><dd>No segment selected</dd></div> <div id="cmMenuContent"> <div id="cm_street" class="cm-menu-section"> <dl id="cm_primaryStreet"> <dt>Street</dt> </dl> <dl id="cm_altStreets"> <dt>Alt street</dt> </dl> </div> <div id="cm_city" class="cm-menu-section"> <dl id="cm_primaryCity"> <dt>City</dt> </dl> <dl id="cm_altCities"> <dt>Alt city</dt> </dl> </div> <div class="cm-menu-section"> <dl id="cm_state"> <dt>State</dt> </dl> </div> <div class="cm-menu-section"> <dl id="cm_roadType"> <dt>Road type</dt> </dl> </div> <div class="cm-menu-section"> <dl id="cm_updatedBy"> <dt>Updated by</dt> </dl> <dl id="cm_createdBy"> <dt>Created by</dt> </dl> </div> <div class="cm-menu-section"> <dl> <dd id="cm_ids">Segment IDs</dd> </dl> </div></div>`; // if menu is not pinned if (!document.getElementById('cmPinMenu').value) { setTimeout(addSpecialMenuListeners, 250); } if (contextMenuSettings.position === 1) { document.getElementById('cmFooterCaret').classList.add('fa-caret-down'); document.getElementById('cmFooterCaret').classList.remove('fa-caret-up'); document.getElementById('cmFooter').style.marginBottom = '-2px'; document.getElementById('cmContextMenu').insertBefore(document.getElementById('cmFooter'), document.getElementById('cmContextMenu').children[0]); } else { document.getElementById('cmFooterCaret').classList.add('fa-caret-up'); document.getElementById('cmFooterCaret').classList.remove('fa-caret-down'); document.getElementById('cmFooter').style.marginBottom = '0'; document.getElementById('cmContextMenu').appendChild(document.getElementById('cmFooter')); } }; var populateCopyContextMenu = function (segInfo, contextMenuSettings) { try { resetContextMenu(contextMenuSettings); var updateNames = Object.keys(segInfo.ids), numNames = updateNames.length, n, selOption, emptyArr, s_names = {}, s_ids = {}; for (n = numNames; n--;) { if (document.getElementById('cm_' + updateNames[n]) && segInfo.ids[updateNames[n]] && segInfo.ids[updateNames[n]].length) { if (updateNames[n] !== 'ids') { emptyArr = 0; s_names[updateNames[n]] = getUnique(segInfo.names[updateNames[n]]) s_ids[updateNames[n]] = getUnique(segInfo.ids[updateNames[n]]) for (var a = 0, aLength = s_ids[updateNames[n]].length; a < aLength; a++) { if (s_names[updateNames[n]][a]) { selOption = document.createElement('dd'); if (s_names[updateNames[n]][a] === '') { if (~updateNames[n].indexOf('Cit')) { selOption.innerHTML = 'No City'; } else if (~updateNames[n].indexOf('Street')) { selOption.innerHTML = 'No Street'; } } else { selOption.innerHTML = s_names[updateNames[n]][a]; } selOption.name = s_ids[updateNames[n]][a]; document.getElementById('cm_' + updateNames[n]).appendChild(selOption); switch (updateNames[n]) { case 'roadType': if (document.getElementById('cmClipboard').value) selOption.name = s_names[updateNames[n]][a]; selOption.onclick = function (e) { //if (document.getElementById('cmPinMenu').value) e.stopPropagation(); copyTo(e, this.parentNode.id, this.name); }; break; default: selOption.onclick = function (e) { //if (document.getElementById('cmPinMenu').value) e.stopPropagation(); copyTo(e, this.parentNode.id, this.innerHTML); }; } } else { emptyArr++; } } if (emptyArr === aLength) { if (document.getElementById('cm_' + updateNames[n])) { document.getElementById('cm_' + updateNames[n]).style.display = "none"; } } } else { selOption = document.getElementById('cm_ids'); selOption.name = segInfo.ids[updateNames[n]].join(','); selOption.onclick = function (e) { //if (document.getElementById('cmPinMenu').value) e.stopPropagation(); copyTo(e, this.id, this.name); }; } } else if (document.getElementById('cm_' + updateNames[n])) { document.getElementById('cm_' + updateNames[n]).style.display = "none"; } } if (!s_names.primaryStreet.length && !s_names.altStreets.length) { document.getElementById('cm_primaryStreet').parentNode.style.display = 'none'; } if (!s_names.primaryCity.length && !s_names.altCities.length) { document.getElementById('cm_primaryCity').parentNode.style.display = 'none'; } if (!s_names.state.length) document.getElementById('cm_state').parentNode.style.display = 'none'; // RSEL menu items if (document.getElementById('cmRSel').value) { document.getElementById('cmMenuHeaderTitle').innerHTML = 'Copy To Road Selector'; var copyToRSelAndSelect = document.createElement('dd'); copyToRSelAndSelect.id = 'cm_SCgo'; copyToRSelAndSelect.zIndex = 1; copyToRSelAndSelect.className = 'fa fa-fast-forward pull-right cm-rsel-goselect'; document.getElementById('cm_SC').parentNode.insertBefore(copyToRSelAndSelect, document.getElementById('cm_SC')); var copyToRSelAndSelect2 = copyToRSelAndSelect.cloneNode(); copyToRSelAndSelect2.id = 'cm_Sgo'; copyToRSelAndSelect.zIndex = 1; document.getElementById('cm_S').parentNode.insertBefore(copyToRSelAndSelect2, document.getElementById('cm_S')); document.getElementById('cmRSelAutoAdd').style.display = 'block'; //name options document.getElementById('cm_pri').parentNode.addEventListener('click', function (e) { e.stopPropagation(); var numBtnDown = this.parentNode.getElementsByClassName('active').length; if (this.children[0].checked) { //currently checked... decide whether to uncheck this.classList.remove('active'); this.children[0].checked = false; if (numBtnDown === 0) { document.getElementById('cm_alt').parentNode.classList.add('active') document.getElementById('cm_alt').checked = true; } document.getElementById('cm_textSC').innerHTML = 'Alt. Street, City'; document.getElementById('cm_textS').innerHTML = 'Alt. Street'; } else { //unchecked this.classList.add('active'); this.children[0].checked = true; document.getElementById('cm_textSC').innerHTML = 'Primary/Alt. Street, City'; document.getElementById('cm_textS').innerHTML = 'Primary/Alt. Street'; } }, false); document.getElementById('cm_alt').parentNode.addEventListener('click', function (e) { e.stopPropagation(); var numBtnDown = this.parentNode.getElementsByClassName('active').length; if (this.children[0].checked) { //currently checked... decide whether to uncheck this.classList.remove('active'); this.children[0].checked = false; if (numBtnDown === 0) { document.getElementById('cm_pri').parentNode.classList.add('active'); document.getElementById('cm_pri').checked = true; } document.getElementById('cm_textSC').innerHTML = 'Primary Street, City'; document.getElementById('cm_textS').innerHTML = 'Primary Street'; } else { //unchecked this.classList.add('active'); this.children[0].checked = true; document.getElementById('cm_textSC').innerHTML = 'Primary/Alt. Street, City'; document.getElementById('cm_textS').innerHTML = 'Primary/Alt. Street'; } }, false); //road type document.getElementById('cmRoadType').addEventListener('click', function (e) { e.stopPropagation(); if (document.getElementById('cmRoadType').classList.contains('active')) { document.getElementById('cmRoadType').classList.remove('active') } else { document.getElementById('cmRoadType').classList.add('active') } }, false); //operations document.getElementById('cmOpAddOr').addEventListener('click', function (e) { e.stopPropagation(); var opToggleLabel = ['and', 'or'], newValue = this.value ^ 1; this.innerHTML = opToggleLabel[newValue]; this.value = newValue; //console.info(this.value); }, false); document.getElementById('cmOpNot').addEventListener('click', function (e) { e.stopPropagation(); if (document.getElementById('cmOpNot').classList.contains('active')) { document.getElementById('cmOpNot').classList.remove('active') } else { document.getElementById('cmOpNot').classList.add('active') } }, false); //menu selections document.getElementById('cm_SC').addEventListener('click', function (e) { copyTo(e, getAutoAddToRSelCase('cm_SC'), segInfo.ids); }, false); document.getElementById('cm_S').addEventListener('click', function (e) { copyTo(e, getAutoAddToRSelCase('cm_S'), segInfo.names); }, false); document.getElementById('cm_SCgo').addEventListener('click', function (e) { menuResetEvent_RSel = true; copyTo(e, getAutoAddToRSelCase('cm_SC'), segInfo.ids); document.getElementById('btnRSSelect').click(); }, false); document.getElementById('cm_Sgo').addEventListener('click', function (e) { menuResetEvent_RSel = true; copyTo(e, getAutoAddToRSelCase('cm_S'), segInfo.names); document.getElementById('btnRSSelect').click(); }, false); } } catch (err) { console.error(err); }; }; var SL_checkCountry = function () { // returns a boolean value for menuResetEvent_SL and implies whether to run // reduceSpeedhelperOverhead() again //for (i=1; i<17; i++) {kph=Math.round(i*5*SL_imperial.mph2kph); mph=Math.round(kph*SL_imperial.kph2mph); console.info('kph:',kph,'---','mph:',mph)} if (!contextMenuSettings.countries) contextMenuSettings.countries = []; var savedNumCountries = contextMenuSettings.countries.length, currentNumCountries, currentCountries, convertUnits = false, isImperialCountry = false; try { currentCountries = [_W_.model.countries.top.abbr]; currentNumCountries = 1; } catch (err) { console.warning('WMECM:', 'Could not find W.model.countries.top. Trying to use W.model.countries.objects instead.'); try { currentCountries = Object.keys(_W_.model.countries.objects); currentNumCountries = currentCountries.length; } catch (err) { console.warning('WMECM:', 'WME objects might have been changed by Waze. This could be a problem and should be examined.') currentCountries = false; currentNumCountries = 0; } } var matchCount = 0; for (var c = 0; c < currentNumCountries; c++) { for (var s = 0; s < savedNumCountries; s++) { if (currentCountries[c] === contextMenuSettings.countries[s]) matchCount++; } } for (var ic = 0, icLength = SL_imperial.countries.length; ic < icLength; ic++) { if (currentCountries[0] === SL_imperial.countries[ic]) { isImperialCountry = true; break; } } if (isImperialCountry && !_W_.prefs.attributes.isImperial) convertUnits = 1; //convert metric --> imperial else if (!isImperialCountry && _W_.prefs.attributes.isImperial) convertUnits = 2; //convert imperial --> metric if (matchCount !== currentNumCountries) { contextMenuSettings.countries = currentCountries; localStorage.contextMenuSettings = JSON.stringify(contextMenuSettings); return { menuResetEvent_SL: true, //saved for later for implementing a check without having to refresh browser convertUnits: convertUnits }; } else { return { menuResetEvent_SL: false, //saved for later for implementing a check without having to refresh browser convertUnits: convertUnits }; } }; var highlightSpeedSigns = function () { //_$_('#signsholder_cm>div').removeAttr('style'); //reset styles _$_('#signsholder_cm>div').removeAttr('class'); //reset classes if (SL_imperial.convertUnits === null) { var countryResults = SL_checkCountry(); SL_imperial.convertUnits = countryResults.convertUnits; SL = SL_imperial //debug } // Highlight the current speed limit var fwdSpeed = _$_('input[name="fwdMaxSpeed"]').val(), revSpeed = _$_('input[name="revMaxSpeed"]').val(); if (SL_imperial.convertUnits === 1) { fwdSpeed = Math.round(fwdSpeed * SL_imperial.kph2mph); revSpeed = Math.round(revSpeed * SL_imperial.kph2mph); } else if (SL_imperial.convertUnits === 2) { fwdSpeed = Math.round(fwdSpeed * SL_imperial.mph2kph); revSpeed = Math.round(revSpeed * SL_imperial.mph2kph); } if ((fwdSpeed && revSpeed) && (fwdSpeed === revSpeed)) { if ((!_$_('#fwdMaxSpeedUnverifiedCheckbox').length && !_$_('#revMaxSpeedUnverifiedCheckbox').length) || // if both have been verified (_$_('#fwdMaxSpeedUnverifiedCheckbox').prop('checked') && _$_('#revMaxSpeedUnverifiedCheckbox').prop('checked'))) { _$_('#signsholder_cm>div[id$="' + fwdSpeed + '"]').addClass('cm-sl-verified cm-both'); } else if (_$_('#fwdMaxSpeedUnverifiedCheckbox').prop('checked') || _$_('#revMaxSpeedUnverifiedCheckbox').prop('checked')) { // only one has been verified _$_('#signsholder_cm>div[id$="' + fwdSpeed + '"]').addClass('cm-sl-unverified cm-one'); } else if (!_$_('#fwdMaxSpeedUnverifiedCheckbox').prop('checked') && !_$_('#revMaxSpeedUnverifiedCheckbox').prop('checked')) { // neither have been verified _$_('#signsholder_cm>div[id$="' + fwdSpeed + '"]').addClass('cm-sl-unverified cm-both'); } } else if ((fwdSpeed && revSpeed) && (fwdSpeed !== revSpeed)) { if ((!_$_('#fwdMaxSpeedUnverifiedCheckbox').length && !_$_('#revMaxSpeedUnverifiedCheckbox').length) || // if both have been verified (_$_('#fwdMaxSpeedUnverifiedCheckbox').prop('checked') && _$_('#revMaxSpeedUnverifiedCheckbox').prop('checked'))) { _$_('#signsholder_cm>div[id$="' + fwdSpeed + '"]').addClass('cm-sl-verified cm-a'); _$_('#signsholder_cm>div[id$="' + revSpeed + '"]').addClass('cm-sl-verified cm-b'); } else if (_$_('#fwdMaxSpeedUnverifiedCheckbox').prop('checked')) { //fwdspeed verified _$_('#signsholder_cm>div[id$="' + fwdSpeed + '"]').addClass('cm-sl-verified cm-a'); _$_('#signsholder_cm>div[id$="' + revSpeed + '"]').addClass('cm-sl-unverified cm-b'); } else if (_$_('#revMaxSpeedUnverifiedCheckbox').prop('checked')) { //revspeed verified _$_('#signsholder_cm>div[id$="' + fwdSpeed + '"]').addClass('cm-sl-unverified cm-a'); _$_('#signsholder_cm>div[id$="' + revSpeed + '"]').addClass('cm-sl-verified cm-b'); } else if (!_$_('#fwdMaxSpeedUnverifiedCheckbox').prop('checked') && !_$_('#revMaxSpeedUnverifiedCheckbox').prop('checked')) { _$_('#signsholder_cm>div[id$="' + fwdSpeed + '"]').addClass('cm-sl-unverified cm-a'); _$_('#signsholder_cm>div[id$="' + revSpeed + '"]').addClass('cm-sl-unverified cm-b'); } } else if (fwdSpeed && !revSpeed) { // no reverse speed has been inputted if (!_$_('input[name="revMaxSpeed"]').length) { // if revspeed input does not exist bc this is a oneway road if (!_$_('#fwdMaxSpeedUnverifiedCheckbox').length || _$_('#fwdMaxSpeedUnverifiedCheckbox').prop('checked')) { // if fwdspeed has been verified _$_('#signsholder_cm>div[id$="' + fwdSpeed + '"]').addClass('cm-sl-verified'); } else if (!_$_('#fwdMaxSpeedUnverifiedCheckbox').prop('checked')) { //unverified speed on oneway road _$_('#signsholder_cm>div[id$="' + fwdSpeed + '"]').addClass('cm-sl-unverified'); } } else { //revspeed input box does exist but is empty if (!_$_('#fwdMaxSpeedUnverifiedCheckbox').length || _$_('#fwdMaxSpeedUnverifiedCheckbox').prop('checked')) { // if fwdspeed has been verified, then draw yellow box _$_('#signsholder_cm>div[id$="' + fwdSpeed + '"]').addClass('cm-sl-verified cm-a'); } } } else if (revSpeed && !fwdSpeed) { if (!_$_('input[name="fwdMaxSpeed"]').length) { // if fwdspeed input does not exist bc this is a oneway road if (!_$_('#revMaxSpeedUnverifiedCheckbox').length || _$_('#revMaxSpeedUnverifiedCheckbox').prop('checked')) { //revspeed has been verified _$_('#signsholder_cm>div[id$="' + revSpeed + '"]').addClass('cm-sl-verified'); } else if (!_$_('#revMaxSpeedUnverifiedCheckbox').prop('checked')) { //unverified speed on oneway road _$_('#signsholder_cm>div[id$="' + revSpeed + '"]').addClass('cm-sl-unverified'); } } else { //fwdspeed does exist, but has not been inputted if (!_$_('#revMaxSpeedUnverifiedCheckbox').length || _$_('#revMaxSpeedUnverifiedCheckbox').prop('checked')) { // nonetheless if revspeed has been verified, then draw yellow box _$_('#signsholder_cm>div[id$="' + revSpeed + '"]').addClass('cm-sl-verified cm-b'); } } } } var reduceSpeedhelperOverhead = function () { // returns the innerHTML for slimmed down cmMenuContent, to be assigned to speedhelperHTML if (document.getElementById('cmSpeedhelperCSS')) document.getElementById('cmSpeedhelperCSS').remove(); var speedhelperCSSEl = document.createElement('style'); speedhelperCSSEl.type = 'text/css'; speedhelperCSSEl.id = 'cmSpeedhelperCSS'; speedhelperCSSEl.innerHTML = '#signsholder_cm>div[id^="sign"] {' + document.getElementById('signsholder').children[0].getAttribute('style') + '}\n' + '#signsholder_cm>div[id^="sign"]>* {' + document.querySelector('#signsholder>div[id^="sign"]>*').getAttribute('style') + '}\n'; document.body.appendChild(speedhelperCSSEl); _$_('#signsholder_cm>div[id^="sign"]:not([id="signsError"]').removeAttr('style'); _$_('#signsholder_cm>div[id^="sign"]>div').removeAttr('style'); return document.getElementById('cmMenuContent').innerHTML; }; var populateSpeedMenu = function (contextMenuSettings) { var slCurrentElementCount = [!!document.getElementById('fwdMaxSpeedUnverifiedCheckbox'), !!document.getElementById('revMaxSpeedUnverifiedCheckbox'), !!document.getElementsByName('fwdMaxSpeed').length, !!document.getElementsByName('revMaxSpeed').length], slMenuElementCount = [!!document.getElementById('fwdMaxSpeedUnverifiedCheckbox_cm')+1, !!document.getElementById('revMaxSpeedUnverifiedCheckbox_cm')+1, document.getElementsByName('fwdMaxSpeed_cm').length+1, document.getElementsByName('revMaxSpeed_cm').length+1]; for (var cc = 4, slCompareElementCount = 0, sumElementCount=0; cc--;) { slCompareElementCount += (slMenuElementCount[cc]*slCurrentElementCount[cc]-1)==slCurrentElementCount[cc]; sumElementCount += slCurrentElementCount[cc]; } if (menuResetEvent_SL || !speedhelperHTML) { resetContextMenu(contextMenuSettings); try { document.getElementById('cmMenuHeaderTitle').innerHTML = 'Edit Speed Limits'; if ((slCompareElementCount !== 4 && slMaxElementCount !== 4) || !speedhelperHTML) { document.getElementById('cmMenuContent').innerHTML = ''; var speedLimit = document.querySelector('#segment-edit-general div.speed-limit').cloneNode(true); speedLimit.id = 'cmSpeedLimit'; speedLimit.className = 'cm-speed-limit cm-menu-section'; speedLimit.innerHTML = '<div id="signsContainer" style="margin-bottom: 15px; opacity: 0.9;"></div><div class="form-inline">' + speedLimit.innerHTML + '</div>'; document.getElementById('cmMenuContent').appendChild(speedLimit); document.querySelector('#cmSpeedLimit #signsholder').id = 'signsholder_cm'; // Move the signs to its own container document.getElementById('signsContainer').appendChild(document.getElementById('signsholder_cm')); } else { document.getElementById('cmMenuContent').innerHTML = speedhelperHTML; } } catch (err) {} //-------------------------------------------------------------------------- try { var wazeVerifyChkBoxLabel = document.querySelectorAll('#segment-edit-general div.speed-limit input[type="checkbox"]+label'), wazeChkbox; for (var cb = 0; cb < wazeVerifyChkBoxLabel.length; cb++) { wazeChkbox = wazeVerifyChkBoxLabel[cb].parentNode.children[0]; _$_('#cmSpeedLimit ' + '#' + wazeChkbox.id).prop('id', wazeChkbox.id + '_cm'); _$_('#cmSpeedLimit ' + '#' + wazeChkbox.id + '_cm').get(0).addEventListener( 'click', function (e) { e.stopPropagation(); this.parentNode.children[0].checked = !document.getElementById(this.parentNode.children[0].id.slice(0, -3)).checked; }, false); } } catch (err) {} //-------------------------------------------------------------------------- try { var wazeSpeedInput = document.querySelectorAll('#segment-edit-general div.speed-limit input[type="number"]'), wazeSpeedInputLength = wazeSpeedInput.length, cmSpeedInput, nm; for (nm = 0; nm < wazeSpeedInputLength; nm++) { _$_('#cmSpeedLimit input[name="' + wazeSpeedInput[nm].name + '"]').prop('name', wazeSpeedInput[nm].name + '_cm'); cmSpeedInput = _$_('#cmSpeedLimit input[name="' + wazeSpeedInput[nm].name + '_cm' + '"]').get(0); cmSpeedInput.addEventListener('click', function (e) { e.stopPropagation(); this.select(); document.getElementById('cmContextMenu').removeEventListener('mouseenter', addHotkeyListener, false); window.removeEventListener('keydown', menuShortcutKeys, true); //console.info('WMECM:','Editing speed value, so removing global hotkey listener'); }, false); cmSpeedInput.addEventListener('blur', function (e) { document.getElementById('cmContextMenu').addEventListener('mouseenter', addHotkeyListener, false); window.addEventListener('keydown', menuShortcutKeys, true); //console.info('WMECM:','Removed focus from speed input field, so adding global hotkey listener again'); _$_('input[name="' + this.name.slice(0, -3) + '"]').val(this.value).change(); }, false); cmSpeedInput.addEventListener('change', function (e) { //e.stopPropagation(); _$_('input[name="' + this.name.slice(0, -3) + '"]').val(this.value).change(); }, false); } } catch (err) {} //-------------------------------------------------------------------------- try { // Try adding some event listeners for closing the menu if not pinned: if (!document.getElementById('cmPinMenu').value) { document.getElementById('cmSpeedLimit').addEventListener( 'mouseleave', function () { addSpecialMenuListeners(); _$_('input[name="fwdMaxSpeed_cm"]').val(_$_('input[name="fwdMaxSpeed"]').val()); _$_('input[name="revMaxSpeed_cm"]').val(_$_('input[name="revMaxSpeed"]').val()); }, false); document.getElementById('cmSpeedLimit').addEventListener( 'mouseenter', function () { //prevent menu from closing window.removeEventListener('click', closeContextMenu, false); document.getElementById('toolbar').removeEventListener('mouseenter', closeContextMenu, false); }, false); } } catch (err) {} //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- var addListenersToSigns = function () { var cmSpeedSigns = document.getElementById('signsholder_cm').children; for (var ss = cmSpeedSigns.length; ss--;) { cmSpeedSigns[ss].addEventListener('click', function (e) { e.preventDefault(); var speedVal = this.firstElementChild.innerHTML; if (SL_imperial.convertUnits === 1) { speedVal = Math.round(speedVal * SL_imperial.mph2kph); } else if (SL_imperial.convertUnits === 2) { speedVal = Math.round(speedVal * SL_imperial.kph2mph); } if (e.shiftKey) { //AB - fwd if (!_$_('input[name="fwdMaxSpeed"]').prop('disabled')) { _$_('input[name="fwdMaxSpeed_cm"]').val(speedVal); _$_('#fwdMaxSpeedUnverifiedCheckbox_cm').prop('checked', true); _$_('#fwdMaxSpeedUnverifiedCheckbox').prop('checked', true).change(); _$_('input[name="fwdMaxSpeed"]').val(speedVal).change(); } } else if (e.ctrlKey || e.altKey || e.metaKey ) { //BA - rev if (!_$_('input[name="revMaxSpeed"]').prop('disabled')) { _$_('input[name="revMaxSpeed_cm"]').val(speedVal); _$_('#revMaxSpeedUnverifiedCheckbox_cm').prop('checked', true); _$_('#revMaxSpeedUnverifiedCheckbox').prop('checked', true).change(); _$_('input[name="revMaxSpeed"]').val(speedVal).change(); } } else { if (!$('#segment-edit-general div.speed-limit input[type="number"]').prop('disabled')) { //_$_('#segment-edit-general div.speed-limit input[type="number"]').val(speedVal).change(); _$_('#cmSpeedLimit input[type="number"]').val(speedVal); _$_('#fwdMaxSpeedUnverifiedCheckbox_cm').prop('checked', true); _$_('#fwdMaxSpeedUnverifiedCheckbox').prop('checked', true).change(); _$_('#revMaxSpeedUnverifiedCheckbox_cm').prop('checked', true); _$_('#revMaxSpeedUnverifiedCheckbox').prop('checked', true).change(); _$_('#segment-edit-general div.speed-limit input[type="number"]').val(speedVal).change(); } } highlightSpeedSigns(); if (!document.getElementById('cmPinMenu').value) { setTimeout(closeContextMenu, 100); } }, false); } if (sumElementCount > slMaxElementCount) { speedhelperHTML = reduceSpeedhelperOverhead(); slMaxElementCount = sumElementCount; } highlightSpeedSigns(); // this is necessary to play catchup bc of the slower initialization times of Speedhelper elements }; //-------------------------------------------------------------------------- var waitCount = 0, maxWait = 15; var waitForSpeedhelper = function () { var signsHolder = document.querySelector('#segment-edit-general div.speed-limit #signsholder'); if (signsHolder !== null && !document.getElementById('signsContainer').children.length) { menuResetEvent_SL = false; document.getElementById('signsContainer').innerHTML = signsHolder.outerHTML; document.querySelector('#signsContainer>#signsholder').id = 'signsholder_cm'; addListenersToSigns(); } else if (waitCount++ < maxWait) { setTimeout(waitForSpeedhelper, 50); } }; //------------------------------------------------------ setTimeout(function () { if (document.getElementById('signsContainer').children.length) { addListenersToSigns(); } else { setTimeout(waitForSpeedhelper, 50); } }, 50); //timeout may be needed for countries with many speedlimit signs loaded by Speedhelper //------------------------------------------------------ } else { //menuResetEvent_SL === false // if menu is pinned and has not been reset... if (slCompareElementCount !== 4 && slMaxElementCount !== 4) { menuResetEvent_SL = true; populateSpeedMenu(contextMenuSettings) return true; } } // menuResetEvent_SL === true // Update values of the context menu _$_('#fwdMaxSpeedUnverifiedCheckbox_cm').prop('checked', _$_('#fwdMaxSpeedUnverifiedCheckbox').prop('checked')); _$_('#revMaxSpeedUnverifiedCheckbox_cm').prop('checked', _$_('#revMaxSpeedUnverifiedCheckbox').prop('checked')); _$_('input[name="fwdMaxSpeed_cm"]').val(_$_('input[name="fwdMaxSpeed"]').val()).change(); _$_('input[name="revMaxSpeed_cm"]').val(_$_('input[name="revMaxSpeed"]').val()).change(); //-------------------------------------------------------------------------- //------------------------- extra beautifying stuff ------------------------ // Hide input fields that aren't relevant for selected segment(s) (_$_('#fwdMaxSpeedUnverifiedCheckbox').length) ? _$_('#fwdMaxSpeedUnverifiedCheckbox_cm').parent().css('display', 'inline-block'): _$_('#fwdMaxSpeedUnverifiedCheckbox_cm').parent().css('display', 'none'); (_$_('#revMaxSpeedUnverifiedCheckbox').length) ? _$_('#revMaxSpeedUnverifiedCheckbox_cm').parent().css('display', 'inline-block'): _$_('#revMaxSpeedUnverifiedCheckbox_cm').parent().css('display', 'none'); (_$_('input[name="fwdMaxSpeed"]').length) ? _$_('input[name="fwdMaxSpeed_cm"]').parent().css('display', 'inline-block'): _$_('input[name="fwdMaxSpeed_cm"]').parent().css('display', 'none'); (_$_('input[name="revMaxSpeed"]').length) ? _$_('input[name="revMaxSpeed_cm').parent().css('display', 'inline-block'): _$_('input[name="revMaxSpeed_cm').parent().css('display', 'none'); highlightSpeedSigns(); if (menuResetEvent_SL) menuResetEvent_SL = false; //redundant, but just to make sure :) }; var selectionIsSegment = function (e) { try { var sel, selLength, s, segments = [], numSelected, selectedFeatures; // First check for segments under cursor (hover/mouseover) if (e && e.target && e.target._featureId && (e.target._geometryClass === "OpenLayers.Geometry.LineString" || e.target._geometryClass === "OpenLayers.Geometry.Point")) { selectedFeatures = _W_.map.layers[9].getFeatureById(e.target._featureId); //segment layer -- returns null if nothing sel = _W_.selectionManager.selectedItems; //returns empty array if nothing selLength = sel.length if (selectedFeatures && selectedFeatures.model.type === 'segment') { segments[0] = selectedFeatures; _W_.selectionManager.select([selectedFeatures.model]); } //Now check for any selected segments... any duplicates of the hovered //segment will be dealt with in the next steps using object literals for (s = 0; s < selLength; s++) { if (sel[s].model.type === 'segment') segments.push(sel[s]); } document.getElementById('cmMenuNoContent').style.display = 'none'; document.getElementById('cmMenuContent').style.display = 'block'; return (segments.length) ? segments : false; //no segments near cursor } else if (e.type === 'selectionchanged') { sel = e.selected; selLength = sel.length; for (s = 0; s < selLength; s++) { if (sel[s].model.type === 'segment') segments.push(sel[s]); } return (segments.length) ? segments : false; //no segments near cursor } else { return false; } } catch (err) { console.error('WMECM:selectionIsSegment():',err); }; }; var preselectionIsSegment = function () { var sel = _W_.selectionManager.selectedItems, //returns empty array if nothing selLength = sel.length, s, segments = []; for (s = 0; s < selLength; s++) { if (sel[s].model.type === 'segment') segments.push(sel[s]); } return (segments.length) ? segments : false; }; //var pressedKeys = []; var menuShortcutKeys = function (e) { switch (e.which) { case 49: //81: //q e.preventDefault(); e.stopPropagation(); document.getElementById('cmClipboard').click(); break; case 50: //87: //w e.preventDefault(); e.stopPropagation(); document.getElementById('cmRSel').click(); break; case 51: //69: //e e.preventDefault(); e.stopPropagation(); document.getElementById('cmSpeed').click(); break; default: return false; } }; var setupSegmentContextMenu = function (e) { if (document.getElementById('cmContextMenu') && document.getElementById('cmContextMenu').style.display !== 'none') { var selectedStuff = selectionIsSegment(e); if (selectedStuff) { if (document.getElementById('cmRSel').value) document.getElementById('cmRSelAutoAdd').style.display = 'block'; document.getElementById('cmMenuNoContent').style.display = 'none'; document.getElementById('cmMenuContent').style.display = 'block'; switch (contextMenuSettings.clipboard) { case 2: populateSpeedMenu(contextMenuSettings); break; case 1: case 0: var segInfo = getSegmentProperties(selectedStuff); populateCopyContextMenu(segInfo, contextMenuSettings); break; } } else if (document.getElementById('cmPinMenu').value) { document.getElementById('cmRSelAutoAdd').style.display = 'none'; document.getElementById('cmMenuNoContent').style.display = 'block'; document.getElementById('cmMenuContent').style.display = 'none'; return false; } else {1 return false; } } else { return false; } }; var cursorOffsetX, cursorOffsetY; var moveMenu = function (evt) { evt.preventDefault(); evt.stopPropagation(); evt.dataTransfer.effectAllowed = 'move'; document.getElementById('cmContextMenu').style.opacity = 0.8; document.getElementById('cmContextMenu').style.display = 'none'; document.getElementById('cmContextMenu').style.top = evt.clientY - cursorOffsetY + 'px'; document.getElementById('cmContextMenu').style.left = evt.clientX - cursorOffsetX + 'px'; //10 to account for activeArea padding }; var placeMenu = function (endevt) { endevt.preventDefault(); endevt.dataTransfer.dropEffect = 'move'; document.getElementById('cmContextMenu').style.display = 'block'; setTimeout(function(){document.getElementById('cmContextMenu').style.opacity = 1;},50); }; var allowMenuDrag = function (startevt) { if (document.getElementById('cmContextMenu').draggable) { cursorOffsetX = startevt.offsetX; cursorOffsetY = startevt.offsetY; document.getElementById('cmContextMenu').addEventListener('drag', moveMenu, true); //document.getElementById('cmContextMenu').addEventListener('dragend', placeMenu, true); document.getElementById('map').ondrop = placeMenu; document.getElementById('map').ondragover = function (e) { e.preventDefault(); e.dataTransfer.effectAllowed = 'move'; e.dataTransfer.dropEffect = 'move'; }; } }; var showPopupPanel = function(updateVersion, updateText, forumURL) { var popPanelWidth = 600, popPanelCSS = document.createElement('style'), popPanelHTML = document.createElement('div'); popPanelCSS.type = 'text/css'; popPanelCSS.id = 'cssCMupdate'; popPanelCSS.innerHTML = '.cm-panel { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);' + ' width: ' + popPanelWidth + 'px; padding: 10px 20px; margin: 0; overflow-y: auto; overflow-x: auto; word-wrap: break-word;' + ' background-color: white; box-shadow: 0px 5px 20px #555555; border: 1px solid #858585; border-radius: 10px; }\n' + '.cm-panel .fa-exclamation-circle { margin: -5px 8px 10px 0px; line-height: .9; font-size: 56px;}\n' + '.cm-panel-inner { padding: 0px 5px; }\n' + '.cm-panel-section {display: block; font-size: 14px; margin-bottom: 10px; text-align: left; padding: 0px; }\n' + '.cm-panel h2 { margin-top: 15px; margin-left: 64px; font-size: 30px; font-weight: bold; text-align: left; color: #C0C0C0 }\n' + '.cm-panel-hr { display: block; border: 0; height: 0; border-top: 1px solid rgba(0, 0, 0, 0.1);' + ' border-bottom: 1px solid rgba(255, 255, 255, 0.3); margin-top: 8px; margin-bottom: 15px; }\n' + '.cm-panel .cm-btn-container { position: relative; display: table; margin: 0px auto 8px; vertical-align: middle; padding: 0}\n' + '.cm-panel .btn { margin: 0px 5px; padding: 0px 15px; display: inline-block; height: 32px; }\n'; document.body.appendChild(popPanelCSS); popPanelHTML.id = 'divCMupdate'; popPanelHTML.style.backgroundColor = 'rgba(0,0,0,0.5)'; popPanelHTML.style.position = 'fixed'; popPanelHTML.style.top = 0; popPanelHTML.style.right = 0; popPanelHTML.style.bottom = 0; popPanelHTML.style.left = 0; popPanelHTML.style.zIndex = 9999; popPanelHTML.innerHTML = '<div class="cm-panel">' + '<div>' + '<i class="fa fa-exclamation-circle fa-pull-left"></i>' + '<h2>WMECM Update Notes</h2>' + '<hr class="cm-panel-hr"></div>' + '<div class="cm-panel-inner"><div class="cm-panel-section">' + updateText + '</div>' + '<div style="margin-top: 10px; font-size: 10.1pt">' + 'For more details on the new features or to report a bug, please visit the forum post: <a href="' + forumURL + '" target="_blank"><i class="fa fa-external-link"></i></a>' + '</div>' + '<div style="margin-top: 10px; font-style: italic; font-size: 10px;"> ' + 'WME Context Menu update for min. version ' + updateVersion + '</div></div>' + '<hr class="cm-panel-hr">' + '<div class="cm-btn-container">' + '<button id="btnCMokay" class="btn btn-default">OK</button>' + '</div></div>'; document.body.appendChild(popPanelHTML); document.getElementById('btnCMokay').onclick = function() { document.getElementById('divCMupdate').remove(); document.getElementById('cmUpdateNote').classList.remove('cm-unread'); document.getElementById('cssCMupdate').remove(); requestAnimationFrame(function(){CMenuVersion.updateVersionString(minVersion)}); }; }; var initContextMenu = function () { var contextMenuActiveArea = document.createElement('div'), contextMenu = document.createElement('div'), contextMenuCSS = document.createElement('style'); try { contextMenuCSS.type = 'text/css'; contextMenuCSS.innerHTML = ` div#cmContextMenu { visibility: visible; opacity: 1; transition: opacity .2s linear 0s; } div.cm-menu-header { padding: 0px; border: 0; height: 20px; } .cm-menu-header dl { background-color: rgba(147, 196, 211, 0.90); padding: 0; border-top-right-radius: 4px; border-top-left-radius: 4px; } .cm-menu-header dt { padding: 4px 12px; text-transform: uppercase; line-height: 1.2; background-color: rgba(113, 168, 185, 0.7); color: #D8E9EF; font-size: 10px; border-top-right-radius: 3px; border-top-left-radius: 3px; height: 22px; margin-top: 1px; box-shadow: 0px -1px 0px rgba(154, 204, 220, 0.9); } div.cm-menu-section { z-index: 2; border-bottom: 1px solid #416B7C; padding: 2px 0px 3px; background-color: rgba(147, 196, 211, 0.92); } .cm-menu-section dl { margin: 0; padding: 0; display: block; } .cm-menu-section dt { font-size: 9px; padding: 0px 12px; margin-top: 3px; text-transform: uppercase; line-height: 1.2; } .cm-menu-section dd { display: inherit; padding: 0px 12px; font-size: 11px; color: #234350; font-weight: 600; line-height: 1.3;} .cm-menu-section dd:hover, .cm-menu-section dd:active, .cm-menu-section dd:focus { background-color: #BEDCE5; color: #416B7C; } .cm-menu-section dd:active { color: #64D8EA; } .cm-footer-icns { font-size: 13px; margin: 0px 4px 0px 2px; cursor: pointer; display: inline-table; line-height: 1; } .cm-footer-icns:active, .cm-footer-icns:focus, .cm-footer-icns.toggle-off:active, .cm-footer-icns.toggle-off:focus { color: #64D8EA; } .cm-footer-icns.toggle-off, .cm-footer-text.toggle-off { color: #8CBBCC; } .cm-update-note { z-index: 3; cursor: pointer; color: #59899E; margin-top: -15px; position: relative; float: right; right: 5px; bottom: 2px; opacity: .8; line-height: 1; font-size: 14px; } .cm-update-note.cm-unread { color: crimson; } dd.cm-rsel-goselect { padding-right: 14px 3px; cursor: pointer; } .cm-menu-section .cm-rsel-goselect:hover { background-color: transparent; color: #d4e7ed; } .cm-rsel { display: none; border: 0; background-color: rgba(154, 204, 220, 0.9); border-top-right-radius: 3px; border-top-left-radius: 3px; margin-bottom: -1px; } .cm-rsel>dl { padding-top: 1px; border-top-right-radius: 4px; border-top-left-radius: 4px; } .cm-rsel>dl>dt { background-color: rgba(111, 167, 185, 0.7); height: 20px; margin-top: -2px; border-top-right-radius: 3px; border-top-left-radius: 3px; padding-top: 4px; padding-bottom: 4px; color: #d8e9ef; font-size: 10px; } .cm-rsel>dl>dt+dd { height: 24px; margin: 0px 0px 3px; padding: 5px 10px 5px 9px; background-color: rgba(228, 248, 255, 0.3); box-shadow: 0px 1px 0px rgba(0,0,0,0.1); } .cm-rsel-options, cm-rsel-options:focus:hover, cm-rsel-options+input:not(checked) { z-index: 2; background-color: rgba(89, 137, 158, 0.60); color: #D4E7ED; font-weight: bold !important; height: 14px !important; line-height: 1; padding: 3px 6px; font-size: 8px !important; border-radius: 15px; } .cm-rsel-options:hover { background-color: rgba(89, 137, 158, 0.7); color: white; } .cm-rsel-options.active:hover { background-color: #274B5A } .cm-rsel-options.active, .cm-rsel-options:active, .cm-rsel-options:active:focus { color: white; background-color: #3F6271; }\ .cm-rsel-options:focus { color: white; } .cm-rsel-options.and { background-color: #EEE; color: #59899E; border-right: 1px solid #AAA;} .cm-rsel-options.cm-badge-right { border-left: 1px solid #59899E; } div#cmSpeedLimit { z-index: 3; width: 100%; font-size: 10px; text-align: center; display: inline-block; padding: 10px; } div#cmSpeedLimit input[type="number"] { height: 28px; width: 50px; font-size: 11px; padding: 4px 5px; line-height: 1; margin: 0px 2px; } div#cmSpeedLimit input[type="checkbox"]+label { padding-left: 22px; line-height: 1.8; } div#cmSpeedLimit .controls-container { margin-left: 5px; } div#cmSpeedLimit div { border-radius: 3px; display: inline-block; } div#signsholder_cm :before { opacity: .9; position: absolute; background-color: white; color: black; border: 3px solid #00ECE3; font-weight: 400; border-radius: 50%; font-size: 10px; width: 20px; height: 20px; line-height: 14px; text-align: center; margin-left: -12px; margin-top: -5px; box-shadow: 0px 1px 1px gray; } div#signsholder_cm .cm-a:before { content: "A"; } div#signsholder_cm .cm-b:before { content: "B"; } .cm-sl-verified { background-color: rgba(173, 255, 47, 0.8); } .cm-sl-unverified { background-color: rgba(255, 235, 59, 0.8); } .cm-sl-verified.cm-both, .cm-sl-unverified.cm-one { box-shadow: 0px 0px 0px 1px greenyellow; } .cm-sl-unverified.cm-both { box-shadow: 0px 0px 0px 1px rgba(255, 235, 59, 1); } #signsholder_cm>#signsError { float: initial; width: 100%; height: initial; padding: 5px 5px 5px 45px !important; text-align: left; }`; document.head.appendChild(contextMenuCSS); // reminder to self: no need to declare CSS here since this is put into DOM once and does not get destroyed contextMenu.id = 'cmContextMenu'; contextMenu.style.position = 'fixed'; contextMenu.style.top = '0px'; contextMenu.style.left = '0px'; contextMenu.style.width = '200px'; //contextMenu.style.minHeight = '100px'; contextMenu.style.margin = '0px'; contextMenu.style.padding = '0px'; contextMenu.style.borderRadius = '4px'; contextMenu.style.boxShadow = '0px 1px 12px rgba(0,0,0,0.7)'; contextMenu.style.border = '1px solid rgb(89, 137, 150)'; contextMenu.style.borderBottom = '1px solid #2D505F'; contextMenu.style.color = 'white'; contextMenu.style.zIndex = '9999'; contextMenu.style.display = 'none'; contextMenu.style.opacity = 0; contextMenu.innerHTML = '<div id="cmContainer" style="z-index: 2; border-radius: 2px; color: white; padding:0; margin:0; position: relative; width: 100%; display: block;"></div>' + '<div id="cmUpdateNote" class="fa fa-exclamation-circle cm-update-note"></div>' + '<div id="cmFooter" style="color: #DDEDF3; z-index: 3; height: 24px; background-color: rgba(75, 125, 148, 0.85); ' + 'padding: 1px 7px 1px; margin: 0; position: relative; width: 100%; display: block;"></div>'; document.getElementById('map').appendChild(contextMenu); document.getElementById('cmFooter').innerHTML = ` <div style="position: relative; float: left; vertical-align: middle;"> <i id="cmPinMenu" class="fa fa-thumb-tack cm-footer-icns toggle-off" style="margin: 0px -3px 0px -3px; padding: 3px 6px;" value=true title="Pin menu" data-toggle="tooltips"></i> <span id="cmPinClose" class="cm-footer-text toggle-off" style="cursor: pointer; font-weight: 600; border-left: 1px solid #D4E7ED; padding-left: 8px; text-transform: uppercase; font-size: 10px; letter-spacing: .7px;">Close</span> </div> <div id="cmFooterCaret" class="fa fa-caret-up cm-footer-icns pull-right" style="position: relative; top: 3px; margin: auto 0px auto 7px;"></div> <div style="position: relative; height: 21px; border-radius: 20px; border: 1px solid #6EA1B7; padding: 0px 1px 0px 5px;" class="btn-group pull-right"> <div style="position: relative; display: inline-block; border-right: 1px solid #6EA1B7; padding-left: 2px; width: 22px;" class=""> <i id="cmClipboard" value="false" style="font-size: 13px;" class="fa fa-clipboard cm-footer-icns toggle-off" title="Copy to Clipboard" data-toggle="tooltips"></i> </div> <div style="position: relative; display: inline-block; border-right: 1px solid #6EA1B7;" class=""> <i id="cmRSel" style="font-size: 14px;" value="false" class="fa fa-road cm-footer-icns toggle-off" title="Copy to WME Road Selector" data-toggle="tooltips"></i> </div> <div style="position: relative; display: inline-block; width: 20px; margin: 0px 0px 0px -2px; opacity: 0.84;" class=""> <span id="cmSpeed" style="height: 16px" value="false" title="Edit Speed Limits" class="fa fa-stack"> <i class="fa fa-circle cm-footer-icns" style="font-size: 15px; width: 15px; color: #EEE; line-height: 14px; position: absolute; left: 0; text-align: center;"></i> <i class="fa fa-circle-o cm-footer-icns" style="font-size: 15px; width: 15px; font-weight: 500; color: crimson; line-height: 14px; position: absolute; left: 0; text-align: center;"></i> <i class="fa cm-footer-icns" style="font-size: 8px; font-style: normal; width: 15px; color: black; line-height: 14px; position: absolute; left: 0; text-align: center;">S</i> </span> </div> </div>`; /* contextMenuActiveArea.id = 'cmActiveArea'; contextMenuActiveArea.style.position = 'absolute'; contextMenuActiveArea.style.padding = '10px'; contextMenuActiveArea.style.top = '-10px'; contextMenuActiveArea.style.right = '-10px'; contextMenuActiveArea.style.bottom = '-10px'; contextMenuActiveArea.style.left = '-10px'; contextMenuActiveArea.style.zIndex = 0; contextMenuActiveArea.style.visibility = 'visible'; contextMenu.appendChild(contextMenuActiveArea); */ resetContextMenu(contextMenuSettings); setTimeout(function () { if (contextMenuSettings.clipboard === 0 || document.getElementById('tabRSel') === null) { document.getElementById('cmClipboard').value = true; document.getElementById('cmClipboard').classList.remove('toggle-off'); document.getElementById('cmRSel').value = false; document.getElementById('cmRSel').classList.add('toggle-off'); document.getElementById('cmSpeed').value = false; document.getElementById('cmSpeed').parentNode.style.opacity = 0.4; document.getElementById('cmContextMenu').style.width = '200px'; } }, 2000); if (contextMenuSettings.clipboard === 1) { document.getElementById('cmClipboard').value = false; document.getElementById('cmClipboard').classList.add('toggle-off'); document.getElementById('cmRSel').value = true; document.getElementById('cmRSel').classList.remove('toggle-off'); document.getElementById('cmSpeed').value = false; document.getElementById('cmSpeed').parentNode.style.opacity = 0.4; document.getElementById('cmContextMenu').style.width = '210px'; } else if (contextMenuSettings.clipboard === 2) { document.getElementById('cmClipboard').value = false; document.getElementById('cmClipboard').classList.add('toggle-off'); document.getElementById('cmRSel').value = false; document.getElementById('cmRSel').classList.add('toggle-off'); document.getElementById('cmSpeed').value = true; document.getElementById('cmSpeed').parentNode.style.opacity = 0.84; document.getElementById('cmContextMenu').style.width = '226px'; } if (contextMenuSettings.pin) { document.getElementById('cmPinMenu').value = true; document.getElementById('cmPinMenu').classList.remove('toggle-off'); document.getElementById('cmPinClose').classList.remove('toggle-off'); } else { document.getElementById('cmPinMenu').value = false; document.getElementById('cmPinMenu').classList.add('toggle-off'); document.getElementById('cmPinClose').classList.add('toggle-off'); } // VERSION CHECK if (!CMenuVersion.isUpToDate(minVersion)) { document.getElementById('cmUpdateNote').classList.add('cm-unread'); } var forumURL = 'https://www.waze.com/forum/viewtopic.php?f=819&t=178371'; updateNotes_0_2_2 = 'Hello there! Thanks for trying out WME Context Menu. Given the big push by Waze to add speed limits (SLs) to the map, this most recent update provides a few enhancements that I hope you\'ll find helpful in getting the job done:' + '</div><div class="cm-panel-section"><ul>' + '<li>Right-clicking on an unselected segment will now also open the menu.</li>' + '<li>When pinned, the menu becomes draggable.</li>' + '<li>When pinned, numeric hotkeys (1-3) for switching panels of the context menu will only work when your cursor is on the menu.' + '<li>Verified Speedhelper signs are highlighted with a green border. Unverified SLs are highlighted yellow.</li>' + '<li>Two-way roads with differing SL values for each direction are indicated by a badge on top of its sign.</li>' + '<li>Selectively assign SLs to either A-B or B-A direction: Use <b>shift+click for A-B</b> or <b>Alt+click for B-A</b>.</li>' + '<li>Speedhelper signs will automatically adjust the units to those used by the country</li>' + '</ul>' + 'As a reminder, these enhanced features currenly apply to only the Speedhelper panel within WME Context Menu.'; document.getElementById('cmUpdateNote').onclick = function(e){ e.stopPropagation(); showPopupPanel(minVersion, updateNotes_0_2_2, forumURL); }; document.getElementById('cmClipboard').onclick = function (e) { try { e.stopPropagation(); document.getElementById('cmRSel').value = false; document.getElementById('cmRSel').classList.add('toggle-off'); document.getElementById('cmSpeed').value = false; document.getElementById('cmSpeed').parentNode.style.opacity = 0.4; this.value = true; this.classList.remove('toggle-off'); document.getElementById('cmContextMenu').style.width = '200px'; contextMenuSettings.clipboard = 0; localStorage.WME_ContextMenu = JSON.stringify(contextMenuSettings); var selectedStuff = preselectionIsSegment(); if (selectedStuff) { var segInfo = getSegmentProperties(selectedStuff); document.getElementById('cmMenuNoContent').style.display = 'none'; document.getElementById('cmMenuContent').style.display = 'block'; populateCopyContextMenu(segInfo, contextMenuSettings); } else { document.getElementById('cmMenuHeaderTitle').innerHTML = 'Copy To Clipboard'; document.getElementById('cmMenuNoContent').style.display = 'block'; document.getElementById('cmMenuContent').style.display = 'none'; } } catch (err) { console.error(err); }; }; document.getElementById('cmRSel').onclick = function (e) { try { e.stopPropagation(); if (document.getElementById('tabRSel') !== null) { document.getElementById('cmClipboard').value = false; document.getElementById('cmClipboard').classList.add('toggle-off'); document.getElementById('cmSpeed').value = false; document.getElementById('cmSpeed').parentNode.style.opacity = 0.4; this.value = true; this.classList.remove('toggle-off'); document.getElementById('cmContextMenu').style.width = '210px'; contextMenuSettings.clipboard = 1; localStorage.WME_ContextMenu = JSON.stringify(contextMenuSettings); var selectedStuff = preselectionIsSegment(); if (selectedStuff) { var segInfo = getSegmentProperties(selectedStuff); document.getElementById('cmRSelAutoAdd').style.display = 'block'; document.getElementById('cmMenuNoContent').style.display = 'none'; document.getElementById('cmMenuContent').style.display = 'block'; populateCopyContextMenu(segInfo, contextMenuSettings); } else { document.getElementById('cmRSelAutoAdd').style.display = 'none'; document.getElementById('cmMenuHeaderTitle').innerHTML = 'Copy To Road Selector'; document.getElementById('cmMenuNoContent').style.display = 'block'; document.getElementById('cmMenuContent').style.display = 'none'; } } } catch (err) { console.error(err); } }; document.getElementById('cmSpeed').onclick = function (e) { try { e.stopPropagation(); document.getElementById('cmClipboard').value = false; document.getElementById('cmClipboard').classList.add('toggle-off'); document.getElementById('cmRSel').value = false; document.getElementById('cmRSel').classList.add('toggle-off'); this.value = true; this.parentNode.style.opacity = 0.84; document.getElementById('cmContextMenu').style.width = '226px'; contextMenuSettings.clipboard = 2; localStorage.WME_ContextMenu = JSON.stringify(contextMenuSettings); var selectedStuff = preselectionIsSegment(); if (selectedStuff) { document.getElementById('cmRSelAutoAdd').style.display = 'none'; document.getElementById('cmMenuNoContent').style.display = 'none'; document.getElementById('cmMenuContent').style.display = 'block'; menuResetEvent_SL = true; populateSpeedMenu(contextMenuSettings); window.removeEventListener('click', closeContextMenu, false); document.getElementById('toolbar').removeEventListener('mouseenter', closeContextMenu, false); } else { document.getElementById('cmMenuHeaderTitle').innerHTML = 'Edit Speed Limits'; document.getElementById('cmMenuNoContent').style.display = 'block'; document.getElementById('cmMenuContent').style.display = 'none'; } } catch (err) { console.error(err); } }; document.getElementById('map').addEventListener( 'contextmenu', function (e) { var selectedStuff; selectedStuff = selectionIsSegment(e); if (selectedStuff) { try { e.preventDefault(); var contextMenu = document.getElementById('cmContextMenu'); contextMenu.style.display = 'block'; contextMenu.style.top = e.clientY - 10 + 'px'; contextMenu.style.left = e.clientX + 'px'; menuResetEvent_SL = true; setupSegmentContextMenu(e); contextMenu.style.opacity = 1; window.addEventListener('keydown', menuShortcutKeys, true); //console.info('WMECM:','Added initial global hotkey listener upon menu open'); if (document.getElementById('cmPinMenu').value) { // use a more selective hotkey listener //console.info('WMECM:','Menu is pinned, so adding selective hotkey listeners too'); document.getElementById('cmContextMenu').addEventListener('mouseenter', addHotkeyListener, false); document.getElementById('cmContextMenu').addEventListener('mouseleave', removeHotkeyListener, false); } } catch (err) { console.error(err); } } else { if (document.getElementById('cmPinMenu').value) { return false; } else { document.getElementById('cmContextMenu').style.display = 'none'; return false; } } }, false); if (!isFirefox) { _W_.selectionManager.events.register("selectionchanged", null, setupSegmentContextMenu); } else { document.getElementById('WazeMap').addEventListener('click', setupSegmentContextMenu, false); } if (document.getElementById('cmPinMenu').value) { document.getElementById('cmContextMenu').draggable = true; document.getElementById('cmContextMenu').addEventListener('dragstart', allowMenuDrag, true); } else { document.getElementById('cmContextMenu').draggable = false; } document.getElementById('cmPinMenu').onclick = function (e) { try { e.stopPropagation(); if (this.value) { // no pinning this.value = false; this.classList.add('toggle-off'); document.getElementById('cmPinClose').classList.add('toggle-off'); // remove drag menu listeners document.getElementById('cmContextMenu').draggable = false; document.getElementById('cmContextMenu').removeEventListener('dragstart', allowMenuDrag, true); // closing context menu will remove hotkey listeners & closing contextmenu listeners // they will be reinstated if appropriate upon reopening the menu closeContextMenu(); } else { // pin menu this.value = true; this.classList.remove('toggle-off'); document.getElementById('cmPinClose').classList.remove('toggle-off'); // remove listeners that close the menu without clicking close window.removeEventListener('click', closeContextMenu, false); document.getElementById('toolbar').removeEventListener('mouseenter', closeContextMenu, false); // Add dragging menu listeners document.getElementById('cmContextMenu').draggable = true; document.getElementById('cmContextMenu').addEventListener('dragstart', allowMenuDrag, true); // use a more selective hotkey listener //console.info('WMECM:','Switch to menu pinning, so adding selective hotkey listener'); document.getElementById('cmContextMenu').addEventListener('mouseenter', addHotkeyListener, false); document.getElementById('cmContextMenu').addEventListener('mouseleave', removeHotkeyListener, false); } contextMenuSettings.pin = !contextMenuSettings.pin; localStorage.WME_ContextMenu = JSON.stringify(contextMenuSettings); } catch (err) { console.error(err); } }; document.getElementById('cmPinClose').onclick = closeContextMenu; document.getElementById('cmFooterCaret').addEventListener('click', function (e) { e.stopPropagation(); try { if (this.classList.contains('fa-caret-up')) { contextMenuSettings.position = 1; localStorage.WME_ContextMenu = JSON.stringify(contextMenuSettings); this.classList.add('fa-caret-down'); this.classList.remove('fa-caret-up'); document.getElementById('cmFooter').style.marginBottom = '-1px'; document.getElementById('cmContextMenu').insertBefore(document.getElementById('cmFooter'), document.getElementById('cmContextMenu').children[0]); } else if (this.classList.contains('fa-caret-down')) { contextMenuSettings.position = 0; localStorage.WME_ContextMenu = JSON.stringify(contextMenuSettings); this.classList.add('fa-caret-up'); this.classList.remove('fa-caret-down'); document.getElementById('cmFooter').style.marginBottom = '0'; document.getElementById('cmContextMenu').appendChild(document.getElementById('cmFooter')); } } catch (err) { console.error(err); } }, false); } catch (err) { console.error(err); } setTimeout(function () { try { var rselBtnEls = document.querySelectorAll('#RSconditions button'); for (var b = rselBtnEls.length; b--;) { rselBtnEls[b].addEventListener('click', function () { this.classList.remove('btn-info') }, false); } } catch (err) { console.error(err) } }, 1200) }; var waitCount = 0, maxWaitCount = 50; var waitForWaze = function () { try { if (document.getElementById('cmContextMenu')) { return true; } else if (typeof (unsafeWindow) !== "undefined" && unsafeWindow.Waze && unsafeWindow.Waze.model && unsafeWindow.Waze.selectionManager && unsafeWindow.Waze.selectionManager.selectedItems && unsafeWindow.Waze.model.segments && unsafeWindow.Waze.model.cities && unsafeWindow.Waze.map && unsafeWindow.Waze.map.layers) { _W_ = unsafeWindow.Waze; _$_ = unsafeWindow.$; //console.info('starting...'); setTimeout(initContextMenu, 2000); //console.info('WMECM:', 'Something may have went wrong... not sure.'); } else if (waitCount++ < maxWaitCount) { //console.info('waiting...'); setTimeout(waitForWaze, 1000); } else { console.error('WMECM:', 'Failed to start'); } } catch (err) { console.error('WMECM:', 'Whoa. Big failure.'); console.error(err); } }; waitForWaze();