您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
A right-click popup menu for editing segments. Currently integrates with WME Speedhelper and Road Selector to help make it even easier and faster to edit the map.
当前为
// ==UserScript== // @name WME Context Menu // @namespace https://greasyfork.org/users/30701-justins83-waze // @version 2018.08.24.01 // @description A right-click popup menu for editing segments. Currently integrates with WME Speedhelper and Road Selector to help make it even easier and faster to edit the map. // @author TheLastTaterTot // @include https://beta.waze.com/*editor* // @include https://www.waze.com/*editor* // @exclude https://www.waze.com/*user/editor/* // @grant none // @run-at document-end // ==/UserScript== /* jshint -W097 */ //--------------- DEBUG ---------------- var DEBUG = false; function cmlog() { if (DEBUG) { var debugStyle, debugCode, args = arguments, argArray = Object.keys(args).map(function(key) { return args[key]; }); if (argArray[0].constructor === Array) { debugStyle = argArray[0][1]; debugCode = parseInt(argArray[0][0]); } if (debugCode === DEBUG) { argArray = argArray.splice(1); switch (debugStyle) { case 1: // examine functions logCss = 'background: #444; color: #6FF'; break; case 2: // examine eventListeners logCss = 'background: #CCC; color: #048'; break; default: logCss = 'background: #EEE; color: #000; font-weight: bold;'; } console.debug('%cWMECM: %s', logCss, argArray.join(' ')); } } } //------------------------------------------------------------------------------ var SL = { forceBuildNewMenu: true, menuResetEvent: true, imperial: { mphCountries: ['UK', 'US', 'MU', 'AR', 'IC', 'JE', 'GQ', 'CJ', 'BM', 'LI'], mph2kph: 1.609344, kph2mph: 0.621371192, useMPH: null, convertUnits: null, currentCountry: null }, slSavedMaxElementTotal: 0, slSavedMenuElementFlags: false, cmMenuContentHTML: null, signsContainerHTML: null, speedhelperIsPresent: null, signsContainerHeight: null }; var 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, contextMenuSettings, changeEvent = new Event('change', { 'bubbles': true }), focusOut = new Event('focusout', {'bubbles':true}), isFirefox = !!~navigator.userAgent.indexOf('irefox'), minVersion = '0.3.6'; try { if (isFirefox && localStorage.WME_ContextMenuFF) { window.alert('WME Context Menu has been updated to be fully functional in FireFox.\n\nThank you for your patience!'); localStorage.removeItem('WME_ContextMenuFF'); } } catch(err) {} //------------------------------------------------------------------------------ if (localStorage.WME_ContextMenu) { contextMenuSettings = JSON.parse(localStorage.WME_ContextMenu); if (contextMenuSettings.hidden === undefined) { contextMenuSettings.hidden = {}; localStorage.WME_ContextMenu = JSON.stringify(contextMenuSettings); } } else { contextMenuSettings = { clipboard: 0, position: 0, pin: false, countries: [], speedSigns: {default: { speeds: [10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100, 105, 110, 115, 120, 125, 130], signShape: 'Circle', signBorderColor: '#34444B' }}, speedhelper: {}, version: 0, hidden: {} }; 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('WMECM:', '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; } }; //------------------------------------------------------------------------------ if (!CMenuVersion.isUpToDate(minVersion)) { if (contextMenuSettings.speedSigns === undefined) { contextMenuSettings.speedSigns = {default: { speeds: [10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100, 105, 110, 115, 120, 125, 130], signShape: 'Circle', signBorderColor: '#34444B' }}; contextMenuSettings.speedhelper = {}; localStorage.WME_ContextMenu = JSON.stringify(contextMenuSettings); //---------- TEMP ------------- if (localStorage.contextMenuSettings) localStorage.removeItem('contextMenuSettings'); } //CMenuVersion.updateVersionString(minVersion); } //------------------------------------------------------------------------------ //////////////////////////////////////////////////////////////////////////////////////////////// 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 addPasteItems = function(attrName) { if (/primaryStreet|primaryCity/.test(attrName)) { clipboard = document.getElementById('input_' + attrName); if (clipboard) { pasteOption = document.createElement('dd'); pasteOption.className = 'cm-paste'; pasteOption.innerHTML = clipboard.value; pasteOption.name = clipboard.value; //$('#'+attrName+'>dt').after('<dd class="cm-paste" name="' + clipboard.value + '">' + clipboard.value +'</dd>'); $('#' + attrName + ' .cm-paste').remove(); if (document.querySelector('#' + attrName + '>dd')){ document.getElementById(attrName).insertBefore(pasteOption, document.querySelector('#' + attrName + '>dd')); } else { document.getElementById(attrName).appendChild(pasteOption); } pasteOption.addEventListener('click', function(e) { pasteTo(e, this.parentNode.id, this.name); }, false); } } }; var pasteTo = function (e, opt, val) { try { // (temporary) really dumb way via DOM nodes: switch (opt) { case 'cm_primaryStreet': $('.full-address').click(); $('#emptyStreet').prop('checked',false).change(); $('.form-control.streetName').val(val).change(); if (!$('.form-control[name=cityName]').val().length) $('#emptyCity').prop('checked',true).change(); if ($('.form-control[name=stateID]').length) $('.form-control[name=stateID]').val(W.model.states.top.id); if ($('.form-control[name=countryID]').length) $('.form-control[name=countryID]').val(W.model.countries.top.id); $('.action-buttons>.save-button').click(); break; case 'cm_primaryCity': $('.full-address').click(); $('#emptyCity').prop('checked',false).change(); $('.form-control[name=cityName]').val(val).change(); if (!$('.form-control.streetName').val().length) $('#emptyStreet').prop('checked',true).change(); if ($('.form-control[name=stateID]').length) $('.form-control[name=stateID]').val(W.model.states.top.id); if ($('.form-control[name=countryID]').length) $('.form-control[name=countryID]').val(W.model.countries.top.id); $('.action-buttons>.save-button').click(); break; /*case 'cm_state': var $selState = $('.form-control[name=stateID]>option'); $selState.map(function(i,opt){ console.info(opt.text); if (opt.text === val) opt.prop('selected','') }); break;*/ } } catch(err) { console.error(err); } }; var getTopCityName = function() { return W.model.cities.objects[W.model.segments.topCityID].name; }; //---------------------------------------------------------------------- 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, s; switch (caseSelection ^ 0) { case 'primaryStreet': case 0: if (segIds.primaryStreet.length !== 0) { for (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 (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 copyToClipboard = function(id,str) { var $hiddenText; if (!document.getElementById('input_' + id)) { $hiddenText = $('<input>'); $hiddenText.prop('id','input_' + id); $hiddenText.css('position','fixed'); $hiddenText.css('top','-100px'); $hiddenText.css('left','-1000px'); $hiddenText.css('opacity',0); $("body").append($hiddenText); } else { $hiddenText = $('#input_' + id); } $hiddenText.val(str).select(); document.execCommand("copy"); //$temp.remove(); }; var copyTo = function (e, opt, val) { if (document.getElementById('cmPinMenu').value) e.stopPropagation(); if (document.getElementById('cmClipboard').value) { copyToClipboard(opt,val); if (document.getElementById('cmPinMenu').value) addPasteItems(opt); } 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_toCrossroads': 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) { cmlog([1,1], 'getSegmentProperties()'); 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, segments = selectedStuff.segments, s_altStObjKeys, s_altSt, s_toConnObjKeys, a, numAlts, k, numKeys; var s_ids = { ids: {}, primaryStreet: {}, altStreets: {}, altCities: {}, roadType: {}, createdBy: {}, updatedBy: {}, toCrossroads: {}, primaryCity: {}, state: {}, country: {} }; for (s = segments.length; s--;) { if (segments[s].model.attributes.id) s_ids.ids[segments[s].model.attributes.id] = null; if (segments[s].model.attributes.primaryStreetID) { s_ids.primaryStreet[segments[s].model.attributes.primaryStreetID] = null; if (W.model.streets.objects[segments[s].model.attributes.primaryStreetID].cityID) { s_ids.primaryCity[W.model.streets.objects[segments[s].model.attributes.primaryStreetID].cityID] = null; if (W.model.cities.objects[W.model.streets.objects[segments[s].model.attributes.primaryStreetID].cityID].stateID) s_ids.state[W.model.cities.objects[W.model.streets.objects[segments[s].model.attributes.primaryStreetID].cityID].stateID] = null; s_ids.country[W.model.cities.objects[W.model.streets.objects[segments[s].model.attributes.primaryStreetID].cityID].countryID] = null; } } s_ids.roadType[segments[s].model.attributes.roadType] = null; s_ids.createdBy[segments[s].model.attributes.createdBy] = null; if (segments[s].model.attributes.updatedBy) s_ids.updatedBy[segments[s].model.attributes.updatedBy] = null; s_altSt = segments[s].model.attributes.streetIDs; numAlts = s_altSt.length; for (a = 0; a < numAlts; a++) { try { s_ids.altStreets[s_altSt[a]] = null; s_ids.altCities[W.model.streets.objects[s_altSt[a]].cityID] = null; } catch(err) {} } s_toConnObjKeys = Object.keys(segments[s].model.attributes.toCrossroads); numKeys = s_toConnObjKeys.length; for (k = 0; k < numKeys; k++) { try { if (s_toConnObjKeys[k] !== '') { s_ids.toCrossroads[s_toConnObjKeys[k]] = segments[s].model.attributes.toCrossroads[s_toConnObjKeys[k]]; } } catch(err) {} } } var seg_ids = {}, seg_names = { ids: [], primaryStreet: [], altStreets: [], altCities: [], roadType: [], createdBy: [], updatedBy: [], toCrossroads: [], primaryCity: [], state: [], country: [] }; for (var idKey in s_ids) { seg_ids[idKey] = Object.keys(s_ids[idKey]); numKeys = seg_ids[idKey].length; for (k = 0; k < numKeys; k++) { try { 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; } } } catch(err) {} } } return { ids: seg_ids, names: seg_names }; } catch (err) { console.error(err); } }; var addHotkeyListener = function() { cmlog([1,1], 'addHotkeyListener()'); window.addEventListener('keydown', menuShortcutKeys, true); cmlog([2,2],'Adding global hotkey listener due to mouseenter'); }; var removeHotkeyListener = function() { cmlog([1,1], 'removeHotkeyListener()'); window.removeEventListener('keydown', menuShortcutKeys, true); cmlog([2,2],'Removing global hotkey listener due to mouseleave'); }; var closeContextMenu = function () { cmlog([1,1], 'closeContextMenu()'); try { // remove unnecessary hotkey listeners window.removeEventListener('keydown', menuShortcutKeys, true); document.getElementById('cmContextMenu').removeEventListener('mouseenter', addHotkeyListener, false); document.getElementById('cmContextMenu').removeEventListener('mouseleave', removeHotkeyListener, false); cmlog([2,2],'Closing menu, so removing all hotkey listeners'); // remove unnecessary close contextmenu listeners window.removeEventListener('click', closeContextMenu, false); document.getElementById('toolbar').removeEventListener('mouseenter', closeContextMenu, false); W.selectionManager.events.unregister("selectionchanged", null, setupSegmentContextMenu); // close the menu document.getElementById('cmContextMenu').style.display = 'none'; SL.menuResetEvent = true; } catch (err) {} }; var addSpecialMenuListeners = function () { cmlog([1,1], 'addSpecialMenuListeners()'); if (document.getElementById('cmPinMenu').value) { window.removeEventListener('click', closeContextMenu, false); document.getElementById('toolbar').removeEventListener('mouseenter', closeContextMenu, false); } else { window.addEventListener('keydown', menuShortcutKeys, true); cmlog([2,2],'Adding just global hotkey listener via addSpecialMenuListeners()'); window.addEventListener('click', closeContextMenu, false); document.getElementById('toolbar').addEventListener('mouseenter', closeContextMenu, false); } }; var adjustContextMenubar = function(pos) { if (pos === 1) { document.getElementById('cmFooterCaret').classList.add('fa-angle-down'); document.getElementById('cmFooterCaret').classList.remove('fa-angle-up'); document.getElementById('cmFooter').classList.add('cm-top'); document.getElementById('cmFooter').classList.remove('cm-bottom'); document.getElementById('cmFooter').style.marginBottom = '-1px'; document.getElementById('cmContextMenu').insertBefore(document.getElementById('cmFooter'), document.getElementById('cmContextMenu').children[0]); } else { document.getElementById('cmFooterCaret').classList.add('fa-angle-up'); document.getElementById('cmFooterCaret').classList.remove('fa-angle-down'); document.getElementById('cmFooter').classList.remove('cm-top'); document.getElementById('cmFooter').classList.add('cm-bottom'); document.getElementById('cmFooter').style.marginBottom = '0'; document.getElementById('cmContextMenu').appendChild(document.getElementById('cmFooter')); } }; var hideMenuSection = function(evt, sectionName) { var that; if (evt) { that = evt.target; evt.stopPropagation(); } else if (sectionName) { that = document.querySelector('.cm-menu-section[name=' + sectionName + ']>.cm-hide'); } that.classList.toggle('fa-caret-down'); that.classList.toggle('fa-caret-up'); if (that.classList.contains('fa-caret-up')) { //hidden section that.parentNode.classList.add('cm-hidden'); contextMenuSettings.hidden[that.parentNode.getAttribute('name')] = true; } else { //revealed section that.parentNode.classList.remove('cm-hidden'); contextMenuSettings.hidden[that.parentNode.getAttribute('name')] = false; } localStorage.WME_ContextMenu = JSON.stringify(contextMenuSettings); }; var resetContextMenu = function (contextMenuSettings) { cmlog([1,1], 'resetContextMenu()'); var menuHTML; 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); if (contextMenuSettings.clipboard === 1) { //RSel 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>'; } else { document.getElementById('cmContainer').innerHTML = ''; } menuHTML = '<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 valid segment(s) selected</dd></div>' + '<div id="cmMenuContent">' + '<div id="cm_street" name="street" class="cm-menu-section">' + '<span class="fa fa-caret-down cm-hide"></span><span class="fa fa-caret-up cm-hide"></span>' + '<dl id="cm_primaryStreet"><dt>Street</dt></dl>' + '<dl id="cm_altStreets"><dt>Alt street</dt></dl>' + '</div>' + '<div id="cm_city" name="city" class="cm-menu-section">' + '<span class="fa fa-caret-down cm-hide"></span><span class="fa fa-caret-up cm-hide"></span>' + '<dl id="cm_primaryCity"><dt>City</dt></dl>' + '<dl id="cm_altCities"><dt>Alt city</dt></dl>' + '</div>' + '<div name="state" class="cm-menu-section">' + '<span class="fa fa-caret-down cm-hide"></span><span class="fa fa-caret-up cm-hide"></span>' + '<dl id="cm_state"><dt>State</dt></dl>' + '</div>' + '<div name="roadtype" class="cm-menu-section">' + '<span class="fa fa-caret-down cm-hide"></span><span class="fa fa-caret-up cm-hide"></span>' + '<dl id="cm_roadType"><dt>Road type</dt></dl>' + '</div>' + '<div name="by" class="cm-menu-section">' + '<span class="fa fa-caret-down cm-hide"></span><span class="fa fa-caret-up cm-hide"></span>' + '<dl id="cm_updatedBy"><dt>Updated by</dt></dl>' + '<dl id="cm_createdBy"><dt>Created by</dt></dl>' + '</div>' + '<div name="id" class="cm-menu-section">' + '<dl><dd id="cm_ids">Segment IDs</dd></dl>' + '</div></div>'; for (var h in contextMenuSettings.hidden) { if (contextMenuSettings.hidden[h]) //hideMenuSection(null, h); menuHTML = menuHTML.replace(new RegExp('(name="' + h + '" class=")','m'),'$1cm-hidden '); } document.getElementById('cmContainer').innerHTML += menuHTML; $('.cm-hide').click(hideMenuSection); // if menu is not pinned if (!document.getElementById('cmPinMenu').value) { setTimeout(addSpecialMenuListeners, 250); } adjustContextMenubar(contextMenuSettings.position); }; var hidePasteMenu = function(bit) { if (bit === undefined) bit = !document.getElementById('cmClipboard').value; if ($('.cm-paste').length) { $('.cm-paste').each(function(i, node) { if (bit) node.style.display = 'none'; else node.style.display = ''; }); } }; var populateCopyMenu = function (segInfo, contextMenuSettings) { cmlog([1,1], 'populateCopyMenu()'); document.getElementById('cmMenuNoContent').style.display = 'none'; document.getElementById('cmMenuContent').style.display = 'block'; try { resetContextMenu(contextMenuSettings); var updateNames = Object.keys(segInfo.ids), numNames = updateNames.length, n, selOption, emptyArr, s_names = {}, s_ids = {}, clipboard, pasteOption, sectionElement; for (n = numNames; n--;) { sectionElement = document.getElementById('cm_' + updateNames[n]); if (sectionElement && 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++) { try { selOption = document.createElement('dd'); if (s_names[updateNames[n]][a]) { if (s_names[updateNames[n]][a] === '') { //no city or no street if (/city/i.test(updateNames[n])) { selOption.innerHTML = 'No City'; } else if (/street/i.test(updateNames[n])) { selOption.innerHTML = 'No Street'; } //selOption.name = ''; } else { //add the property value to the menu selOption.innerHTML = s_names[updateNames[n]][a]; //selOption.name = s_names[updateNames[n]][a]; } sectionElement.appendChild(selOption); switch (updateNames[n]) { case 'roadType': selOption.name = s_ids[updateNames[n]][a]; 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.name = s_names[updateNames[n]][a]; selOption.onclick = function (e) { //if (document.getElementById('cmPinMenu').value) e.stopPropagation(); copyTo(e, this.parentNode.id, this.name); }; } } else { emptyArr++; } } catch(err) { console.error(err); } } // Check if something has been copied into clipboard for pasting... if (document.getElementById('cmClipboard').value) addPasteItems('cm_' + updateNames[n]); // Hide section if nothing to copy if (emptyArr === aLength && !$('#input_cm_' + updateNames[n]).length) { sectionElement.style.display = "none"; //sectionElement.parentNode.children[0].style.display = "none"; } else if ($('#input_cm_' + updateNames[n]).length) { //show if something to paste selOption = document.createElement('dd'); selOption.innerHTML = ' '; sectionElement.appendChild(selOption); } } else { // Segment IDs 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 (sectionElement && !$('#input_cm_' + updateNames[n]).length) { // Hide section if nothing to copy //sectionElement.parentNode.style.display = "none"; sectionElement.style.display = "none"; sectionElement.parentNode.children[0].style.display = "none"; //caret-down sectionElement.parentNode.children[1].style.display = "none"; //caret-up } else if (sectionElement && $('#input_cm_' + updateNames[n]).length) { //show if something to paste selOption = document.createElement('dd'); if (/city/i.test(updateNames[n])) { selOption.innerHTML = 'No City'; } else if (/street/i.test(updateNames[n])) { selOption.innerHTML = 'No Street'; } /*else { selOption.innerHTML = ' '; }*/ if (selOption.innerHTML.length) { selOption.name = ''; sectionElement.appendChild(selOption); selOption.onclick = function (e) { //if (document.getElementById('cmPinMenu').value) e.stopPropagation(); copyTo(e, this.parentNode.id, this.name); }; sectionElement.appendChild(selOption); } } } // Hide sections if nothing to copy if (!s_names.primaryStreet.length && !s_names.altStreets.length && !$('#input_cm_primaryStreet').length) { document.getElementById('cm_primaryStreet').parentNode.style.display = 'none'; } if (!s_names.primaryCity.length && !s_names.altCities.length && !$('#input_cm_primaryCity').length) { document.getElementById('cm_primaryCity').parentNode.style.display = 'none'; } if (!s_names.state.length) document.getElementById('cm_state').parentNode.style.display = 'none'; var numSegments = getSelectedSegmentCount(); if (!numSegments || numSegments === 0) numSegments = '0 Segment IDs'; else if (numSegments === 1) numSegments = '1 Segment ID'; else numSegments = numSegments + ' Segment IDs'; document.getElementById('cm_ids').innerHTML = numSegments; //================================================================================= // RSEL-specific menu items //================================================================================= if (document.getElementById('cmRSel').value) { document.getElementById('cmMenuHeaderTitle').innerHTML = 'Send 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) { cmlog([1,1], err); //console.error(err); } }; //=============================================================================================== SL.checkCountry = function () { cmlog([1,1], 'SL.checkCountry()'); //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.mphCountries.length; ic < icLength; ic++) { if (currentCountries[0] === SL.imperial.mphCountries[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 SL.imperial.useMPH = isImperialCountry; SL.imperial.convertUnits = convertUnits; SL.currentCountry = currentCountries[0]; if (matchCount !== currentNumCountries) { contextMenuSettings.countries = currentCountries; localStorage.WME_ContextMenu = JSON.stringify(contextMenuSettings); SL.forceBuildNewMenu = true; return true; //saved for later for implementing a check without having to refresh browser } else { return false; } }; SL.highlightSpeedSigns = function () { cmlog([1,1], 'SL.highlightSpeedSigns()'); //$('#signsholder_cm>div').removeAttr('style'); //reset styles $('#signsholder_cm>div:not(#btnCMClearSLs)').removeAttr('class'); //reset classes //if (SL.imperial.convertUnits === null) SL.checkCountry(); // Highlight the current speed limit var fwdSL = document.querySelector('input[name="fwdMaxSpeed"]'), fwdSpeedVal, revSL = document.querySelector('input[name="revMaxSpeed"]'), revSpeedVal, numSegments = getSelectedSegmentCount(), fwdSLMenu = document.querySelector('input[name="fwdMaxSpeed_cm'), revSLMenu = document.querySelector('input[name="revMaxSpeed_cm'), unverFwdChkBox = document.getElementById('fwdMaxSpeedUnverifiedCheckbox'), unverRevChkBox = document.getElementById('revMaxSpeedUnverifiedCheckbox'), signFwd, signRev; if (fwdSL !== null) fwdSpeedVal = fwdSL.valueAsNumber; if (revSL !== null) revSpeedVal = revSL.valueAsNumber; if ((fwdSpeedVal+revSpeedVal) === 0) { return; } else if ((revSLMenu && revSLMenu.parentNode.style.display === 'none') || revSpeedVal===0) { revSpeedVal = false; } else if ((fwdSLMenu && fwdSLMenu.parentNode.style.display === 'none') || fwdSpeedVal===0) { fwdSpeedVal = false; } if (SL.imperial.convertUnits === 1) { if (fwdSpeedVal) fwdSpeedVal = Math.round(fwdSpeedVal * SL.imperial.kph2mph); if (revSpeedVal) revSpeedVal = Math.round(revSpeedVal * SL.imperial.kph2mph); } else if (SL.imperial.convertUnits === 2) { if (fwdSpeedVal) fwdSpeedVal = Math.round(fwdSpeedVal * SL.imperial.mph2kph); if (revSpeedVal) revSpeedVal = Math.round(revSpeedVal * SL.imperial.mph2kph); } signFwd = document.querySelector('#signsholder_cm>div[id="sign' + fwdSpeedVal + '"]'); signRev = document.querySelector('#signsholder_cm>div[id="sign' + revSpeedVal + '"]'); if ((fwdSpeedVal && revSpeedVal) && (fwdSpeedVal === revSpeedVal)) { if ((unverFwdChkBox === null && unverRevChkBox === null) || // if both have been verified (unverFwdChkBox && unverRevChkBox && unverFwdChkBox.checked === true && unverRevChkBox.checked === true)) { if (signFwd) signFwd.className ='cm-sl-verified cm-both'; } else if ((unverFwdChkBox === null || unverFwdChkBox.checked === true) || (unverRevChkBox === null || unverRevChkBox.checked === true)) { // only one has been verified if (signFwd) signFwd.className ='cm-sl-unverified cm-one'; } else if (unverFwdChkBox.checked === false && unverRevChkBox.checked === false) { // neither have been verified if (signFwd) signFwd.className ='cm-sl-unverified cm-both'; } } else if ((fwdSpeedVal && revSpeedVal) && (fwdSpeedVal !== revSpeedVal)) { if ((unverFwdChkBox === null && unverRevChkBox === null) || // if both have been verified -- no checkboxes (unverFwdChkBox && unverRevChkBox && unverFwdChkBox.checked === true && unverRevChkBox.checked === true)) { // or both checked if (signFwd) signFwd.className ='cm-sl-verified cm-a'; if (signRev) signRev.className ='cm-sl-verified cm-b'; } else if (unverFwdChkBox === null || unverFwdChkBox.checked === true) { //fwdSpeedVal checked or no checkbox if (signFwd) signFwd.className ='cm-sl-verified cm-a'; if (signRev)signRev.className ='cm-sl-unverified cm-b'; } else if (unverRevChkBox === null || unverRevChkBox.checked === true) { //revSpeedVal checked or no checkbox if (signFwd) signFwd.className ='cm-sl-unverified cm-a'; if (signRev)signRev.className ='cm-sl-verified cm-b'; } else if (unverFwdChkBox.checked === false && unverRevChkBox.checked === false) { //both unchecked if (signFwd) signFwd.className ='cm-sl-unverified cm-a'; if (signRev)signRev.className ='cm-sl-unverified cm-b'; } } else if (fwdSpeedVal && !revSpeedVal) { // no reverse speed has been inputted if (document.querySelector('input[name="revMaxSpeed"]') === null) { // if revSpeedVal input does not exist bc this is a oneway road if (unverFwdChkBox === null || unverFwdChkBox.checked === true) { // if fwdSpeedVal has been verified if (signFwd) signFwd.className ='cm-sl-verified'; } else if (unverFwdChkBox.checked === false) { //unverified speed on oneway road if (signFwd) signFwd.className ='cm-sl-unverified'; } } else { //revSpeedVal input box does exist but is empty if (unverFwdChkBox === null || unverFwdChkBox.checked === true) { // if fwdSpeedVal has been verified, then draw green box if (signFwd) signFwd.className ='cm-sl-verified cm-a'; } else if (unverFwdChkBox.checked === false) { //unverified speed on oneway road if (signFwd) signFwd.className ='cm-sl-unverified cm-a'; } } } else if (revSpeedVal && !fwdSpeedVal) { if (document.querySelector('input[name="fwdMaxSpeed"]') === null) { // if fwdSpeedVal input does not exist bc this is a oneway road if (unverRevChkBox === null || unverRevChkBox.checked === true) { //revSpeedVal has been verified if (signRev)signRev.className ='cm-sl-verified'; } else if (unverRevChkBox.checked === false) { //unverified speed on oneway road if (signRev)signRev.className ='cm-sl-unverified'; } } else { //fwdSpeedVal does exist, but has not been inputted if (unverRevChkBox === null || unverRevChkBox.checked === true) { //revSpeedVal has been verified signRev.className ='cm-sl-verified cm-b'; } else if (unverRevChkBox.checked === false) { //unverified speed on oneway road if (signRev) signRev.className ='cm-sl-unverified cm-b'; } } } if (numSegments > 1) $('#signsholder_cm>div.cm-sl-verified').addClass('cm-sl-multisegs'); }; SL.getSpeedLimits = function() { var origSignsEl = document.querySelectorAll('#signsholder>div[id^="sign"]'), signsEls = document.querySelectorAll('#signsholder_cm>div[id^="sign"]'), speedLimits = []; if (origSignsEl.length !== 0) signsEls = origSignsEl; for (var s = 0, nSigns = signsEls.length; s < nSigns; s++) { speedLimits.push(signsEls[s].children[0].innerHTML); } return speedLimits; }; SL.createSpeedSigns = function() { if (!SL.currentCountry) SL.checkCountry(); var signsHTML = '<div id="btnCMClearSLs" class="fa fa-ban"><div>0</div></div>', signsCSSEl, signsCSS, speedLimits, speedSignSettings, country = SL.currentCountry, signsHolderEl = document.getElementById('signsholder_cm'); if (document.getElementById('cmSignsWait') !== null ) document.getElementById('cmSignsWait').remove(); if (SL.speedhelperIsPresent === true || document.getElementById('cmSpeedhelperCSS') !== null) { if (document.getElementById('cmSpeedSignsCSS')) { document.getElementById('cmSpeedSignsCSS').remove(); if (document.getElementById('signsholder_cm') !== null) document.getElementById('signsholder_cm').className = ''; } if (contextMenuSettings.speedhelper && contextMenuSettings.speedhelper[country] && contextMenuSettings.speedhelper[country].speeds) { speedLimits = contextMenuSettings.speedhelper[country].speeds; } else { speedLimits = SL.getSpeedLimits(); contextMenuSettings.speedhelper[country] = {speeds: speedLimits}; localStorage.WME_ContextMenu = JSON.stringify(contextMenuSettings); } } else { if (contextMenuSettings.speedSigns[country] !== undefined && contextMenuSettings.speedSigns[country].speeds !== undefined && contextMenuSettings.speedSigns[country].speeds.length !== 0) { if (contextMenuSettings.speedSigns[country].signShape === undefined) contextMenuSettings.speedSigns[country].signShape = contextMenuSettings.speedSigns.default.signShape; if (contextMenuSettings.speedSigns[country].signBorderColor === undefined) contextMenuSettings.speedSigns[country].signBorderColor = contextMenuSettings.speedSigns.default.signBorderColor; speedSignSettings = contextMenuSettings.speedSigns[country]; speedLimits = speedSignSettings.speeds; } else { speedSignSettings = contextMenuSettings.speedSigns.default; speedLimits = speedSignSettings.speeds; if (SL.imperial.useMPH) { speedLimits = speedLimits.slice(0,15); } else { speedLimits = speedLimits.filter((a,i) => (Number.isInteger(a/10)) ? i : false); } contextMenuSettings.speedSigns[country] = { speeds: speedLimits, signShape: speedSignSettings.signShape, signBorderColor: speedSignSettings.signBorderColor}; } localStorage.WME_ContextMenu = JSON.stringify(contextMenuSettings); if (signsHolderEl === null) { signsHolderEl = document.createElement('div'); signsHolderEl.id = 'signsholder_cm'; document.getElementById('signsContainer').appendChild(signsHolderEl); } signsCSSEl = document.getElementById('cmSpeedSignsCSS'); if (signsCSSEl !== null) signsCSSEl.remove(); signsCSSEl = document.createElement('style'); signsCSSEl.type = 'text/css'; signsCSSEl.id = 'cmSpeedSignsCSS'; signsCSS = '#signsholder_cm>div[id^="sign"] { cursor: pointer; float: left; border-color: ' + speedSignSettings.signBorderColor + '; border-style: solid; background-color: #F5FCFF; position: relative; }\n' + '#signsholder_cm.cm-sl-circ>div[id^="sign"] { line-height: 1.8; letter-spacing: -0.9px; border-width: 3px; width: 30px; height: 30px; margin: 0px 0px 4px 3px; border-radius: 50%; font-family: helvetica, arial, "open sans"; }\n' + '#signsholder_cm.cm-sl-sqr>div[id^="sign"] { line-height: 1.9; letter-spacing: 0.5px; border-width: 2px; width: 30px; height: 30px; margin: 0px 1px 4px 2px; border-radius: 3px; opacity: 0.95; }\n' + '#signsholder_cm.cm-sl-circ>#btnCMClearSLs { border: 3px solid transparent; width: 30px; height: 30px; margin: -4px 0px 4px 3px; }\n' + '#signsholder_cm.cm-sl-sqr>#btnCMClearSLs { border: 2px solid transparent; width: 30px; height: 30px; margin: -3px 1px 4px 2px; }\n' + '#signsholder_cm>div>* { opacity: 1; position: relative; text-align: center; vertical-align: middle; color: #000; font-weight: bold; font-size: 14px; margin-left: -1px; }\n' + '#signsholder_cm.cm-sl-sqr>div>* { margin-left: 0; padding-top: 1px; }\n'; signsCSSEl.innerHTML = signsCSS; document.body.appendChild(signsCSSEl); switch (speedSignSettings.signShape) { case 'Square': signsHolderEl.classList.remove('cm-sl-circ'); signsHolderEl.classList.add('cm-sl-sqr'); break; case 'Circle': signsHolderEl.classList.add('cm-sl-circ'); signsHolderEl.classList.remove('cm-sl-sqr'); break; } } for (var sl=0, slLength = speedLimits.length; sl < slLength; sl++) { signsHTML += '<div id="sign' + speedLimits[sl] + '"><div>' + speedLimits[sl] + '</div></div>'; } signsHolderEl.innerHTML = signsHTML; SL.signsContainerHTML = document.getElementById('signsContainer').innerHTML; }; SL.removeSpeedSign = function(evt) { var speedVal = evt.target.firstElementChild.innerHTML, speedLimits = SL.getSpeedLimits(); if (/\d+/.test(speedVal)) { speedLimits = speedLimits.join().replace(speedVal,'').match(/\d+/g); if (SL.speedhelperIsPresent === false) contextMenuSettings.speedSigns[SL.currentCountry].speeds = speedLimits; else contextMenuSettings.speedhelper[SL.currentCountry].speeds = speedLimits; localStorage.WME_ContextMenu = JSON.stringify(contextMenuSettings); evt.target.remove(); SL.signsContainerHTML = document.getElementById('signsContainer').innerHTML; } }; SL.closeSpeedSignsEditor = function () { //document.querySelector('#cmMenuHeaderTitle>.fa-pencil').onclick = SL.editSpeedSigns; document.getElementById('cmContextMenu').addEventListener('mouseenter', addHotkeyListener, false); window.addEventListener('keydown', menuShortcutKeys, true); cmlog([2,2],'Removed focus from speed limit edit, so adding global hotkey listener again'); if (!document.getElementById('cmPinMenu').value) { cmlog([2,2], 'Adding event listners to allow menu to close'); addSpecialMenuListeners(); } document.getElementById('cmMenuSLEdit').remove(); document.getElementById('btnCMSLEditDone').previousElementSibling.style.color = ''; document.getElementById('btnCMSLEditDone').remove(); }; SL.saveSpeedSignEdits = function(e) { e.stopPropagation(); var editedSpeedLimits = document.querySelector('#cmMenuSLEdit textarea').value, country = SL.currentCountry; if (editedSpeedLimits.length !== 0) { editedSpeedLimits = editedSpeedLimits.match(/\d+/g); contextMenuSettings.speedSigns[country] = {}; if (SL.speedhelperIsPresent === false) { contextMenuSettings.speedSigns[country].speeds = editedSpeedLimits; contextMenuSettings.speedSigns[country].signShape = document.querySelector('#cmMenuSLEdit select').value; contextMenuSettings.speedSigns[country].signBorderColor = document.querySelector('#cmMenuSLEdit input[name="signBorderColor"]').value; } else { contextMenuSettings.speedhelper[country] = {speeds: editedSpeedLimits}; } } localStorage.WME_ContextMenu = JSON.stringify(contextMenuSettings); SL.createSpeedSigns(); SL.addListenersToSigns(false); //document.querySelector('#cmMenuHeaderTitle>.fa-pencil').onclick = SL.editSpeedSigns; setTimeout(SL.closeSpeedSignsEditor,150); }; SL.editSpeedSigns = function(evt) { evt.stopPropagation(); if (document.getElementById('cmMenuSLEdit') !== null) { SL.closeSpeedSignsEditor(); } else { try { document.getElementById('cmContextMenu').removeEventListener('mouseenter', addHotkeyListener, false); window.removeEventListener('keydown', menuShortcutKeys, true); cmlog([2,2],'removing global hotkey listener'); if (!document.getElementById('cmPinMenu').value) { cmlog([2,2],'Preventing menu from closing by removing event listeners'); window.removeEventListener('click', closeContextMenu, false); document.getElementById('toolbar').removeEventListener('mouseenter', closeContextMenu, false); } evt.target.style.color = '#FFF'; SL.checkCountry(); var speedLimits, editSLEl = document.createElement('div'), country = SL.currentCountry; editSLEl.id = 'cmMenuSLEdit'; editSLEl.className = 'cm-menu-section'; editSLEl.style.display = 'block'; editSLEl.style.padding = '5px 10px'; editSLEl.style.position = 'relative'; editSLEl.style.color = '#234350'; editSLEl.style.fontSize = '10px'; editSLEl.style.textTransform = 'uppercase'; editSLEl.style.letterSpacing = '-0.3px'; editSLEl.style.fontWeight = 'bold'; if (SL.speedhelperIsPresent !== true && document.getElementById('cmSpeedhelperCSS') === null) { if (contextMenuSettings.speedSigns[country] !== undefined && contextMenuSettings.speedSigns[country].speeds !== undefined && contextMenuSettings.speedSigns[country].speeds.length !== 0) { speedSignSettings = contextMenuSettings.speedSigns[country]; speedLimits = speedSignSettings.speeds.join(' '); } else { speedSignSettings = contextMenuSettings.speedSigns.default; speedLimits = SL.getSpeedLimits().join(' '); } editSLEl.innerHTML = '<div style="display: flex; position: relative">' + '<p style="min-width: 50%"> Shape <select style="margin: 3px 0 0; padding: 0px 3px; border-radius: 5px; height: 20px; width: 70px; display: block;"><option selected>Circle</option><option>Square</option></select></p>' + '<p style="min-width: 30%;"> Border <input type="color" value="' + speedSignSettings.signBorderColor + '" name="signBorderColor" list="signBorderColorList" style="margin: 3px 0 0; display: block; border-radius: 5px; padding: 3px 2px; height: 20px; border-color: transparent; width: 50px; background-color: rgba(255, 255, 255, 0.3);"></input>' + '<datalist id="signBorderColorList"><option>#34444B</option><option>#DC0F00</option><option>#03A9F4</option><option>#416B7C</option><option>#888888</option></datalist></p></div>' + '<p> Add/Remove Speed Limits<textarea class="form-control" style="max-width: 100%; height: auto; margin: 3px 0px 0px; word-spacing: 2px; font-weight: 600; padding: 2px 8px;">' + speedLimits + '</textarea></p>'; document.getElementById('cmMenuContent').insertBefore(editSLEl, document.getElementById('cmSpeedLimit')); document.querySelector('#cmMenuSLEdit select').value = speedSignSettings.signShape; } else { if (contextMenuSettings.speedhelper[country] !== undefined) speedLimits = contextMenuSettings.speedhelper[country].speeds.join(' '); else speedLimits = SL.getSpeedLimits().join(' '); editSLEl.innerHTML = '<p> Add/Remove Speed Limits<textarea class="form-control" style="max-width: 100%; height: auto; margin: 3px 0px 0px; word-spacing: 2px; font-weight: 600; padding: 2px 8px;">' + speedLimits + '</textarea></p>'; document.getElementById('cmMenuContent').insertBefore(editSLEl, document.getElementById('cmSpeedLimit')); } document.getElementById('cmMenuHeaderTitle').innerHTML += '<span id="btnCMSLEditDone" style="float: right; padding-right: 8px; margin-right: 2px; display: inline-flex; color: greenyellow; border-right: 1px solid #D8E9EF; cursor: pointer;"><i class="fa fa-check fa-fw"></i> DONE</span>'; document.getElementById('btnCMSLEditDone').onclick = SL.saveSpeedSignEdits; document.querySelector('#cmMenuHeaderTitle>.fa-pencil').onclick = SL.editSpeedSigns; } catch(err) { console.error(err); } } }; //------------------------------------------------------------------------------ SL.reduceSpeedhelperOverhead = function () { cmlog([1,1], 'SL.reduceSpeedhelperOverhead()'); if (document.getElementById('cmSpeedhelperCSS')) document.getElementById('cmSpeedhelperCSS').remove(); if (document.getElementById('cmSpeedSignsCSS')) { document.getElementById('cmSpeedSignsCSS').remove(); if (document.getElementById('signsholder_cm') !== null) document.getElementById('signsholder_cm').className = ''; } var speedhelperCSSEl = document.createElement('style'); speedhelperCSSEl.type = 'text/css'; speedhelperCSSEl.id = 'cmSpeedhelperCSS'; speedhelperCSSEl.innerHTML = '#signsholder_cm>div[id^="sign"], #btnCMClearSLs {margin-bottom: 1px; ' + 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'); SL.signsContainerHTML = document.getElementById('signsContainer').innerHTML; //return document.getElementById('cmMenuContent').innerHTML; }; //=============================================================================== SL.checkUnits = function(speedVal) { speedVal = Number(speedVal); if (SL.imperial.convertUnits === 1) { return Math.round(speedVal * SL.imperial.mph2kph); } else if (SL.imperial.convertUnits === 2) { return Math.round(speedVal * SL.imperial.kph2mph); } else { return speedVal; } }; SL.addSpeedSignAB = function(speedVal) { var fwdSLMenu = document.querySelector('input[name="fwdMaxSpeed_cm'), fwdSL = document.querySelector('input[name="fwdMaxSpeed"]'), fwdChkBox = document.getElementById('fwdMaxSpeedUnverifiedCheckbox'), prevFwdSpeedVal = fwdSLMenu.value, numSegsSelected = getSelectedSegmentCount(), pauseTime = (numSegsSelected > 10) ? (50+numSegsSelected) : 0; cmlog([5,3],speedVal); if (fwdSL.disabled === false) { document.getElementById('cmWaitCover').style.display = 'block'; speedVal = SL.checkUnits(speedVal); requestAnimationFrame(function(){ var fwdChkBoxMenu = document.getElementById('fwdMaxSpeedUnverifiedCheckbox_cm'); if (fwdChkBoxMenu !== null) fwdChkBoxMenu.checked = true; fwdSLMenu.value = speedVal; }); setTimeout(function(){ if (fwdChkBox !== null && speedVal === prevFwdSpeedVal) { fwdChkBox.checked = true; fwdChkBox.dispatchEvent(changeEvent); fwdChkBox.dispatchEvent(focusOut); } else if (fwdSL !== null) { fwdSL.value = speedVal; fwdSL.dispatchEvent(changeEvent); fwdSL.dispatchEvent(focusOut); $('input[name="fwdMaxSpeed"]').val(speedVal).change().focusout(); //$(fwdSL).val(speedVal).change(); if (fwdChkBox !== null) setTimeout(function(){fwdChkBox.checked = true;},20); } if (!document.getElementById('cmPinMenu').value) setTimeout(closeContextMenu, 150); else setTimeout(SL.highlightSpeedSigns,50); document.getElementById('cmWaitCover').style.display = 'none'; },pauseTime); } }; SL.addSpeedSignBA = function(speedVal) { var revSLMenu = document.querySelector('input[name="revMaxSpeed_cm'), revSL = document.querySelector('input[name="revMaxSpeed"]'), revChkBox = document.getElementById('revMaxSpeedUnverifiedCheckbox'), prevRevSpeedVal = revSLMenu.value, numSegsSelected = getSelectedSegmentCount(), pauseTime = (numSegsSelected > 10) ? (50+numSegsSelected) : 0; cmlog([5,3],speedVal); if (revSL.disabled === false) { document.getElementById('cmWaitCover').style.display = 'block'; speedVal = SL.checkUnits(speedVal); requestAnimationFrame(function(){ var revChkBoxMenu = document.getElementById('revMaxSpeedUnverifiedCheckbox_cm'); if (revChkBoxMenu !== null) revChkBoxMenu.checked = true; revSLMenu.value = speedVal; }); setTimeout(function(){ if (revChkBox !== null && speedVal === prevRevSpeedVal) { revChkBox.checked = true; revChkBox.dispatchEvent(changeEvent); revChkBox.dispatchEvent(focusOut); } else if (revSL !== null) { revSL.value = speedVal; revSL.dispatchEvent(changeEvent); revSL.dispatchEvent(focusOut); //$(revSL).val(speedVal).change(); $('input[name="revMaxSpeed"]').val(speedVal).change().focusout(); if (revChkBox !== null) setTimeout(function(){revChkBox.checked = true;},20); } if (!document.getElementById('cmPinMenu').value) setTimeout(closeContextMenu, 150); else setTimeout(SL.highlightSpeedSigns,50); document.getElementById('cmWaitCover').style.display = 'none'; },pauseTime); } }; SL.addSpeedSignBoth = function(speedVal) { var fwdSLMenu = document.querySelector('input[name="fwdMaxSpeed_cm'), revSLMenu = document.querySelector('input[name="revMaxSpeed_cm'), fwdSL = document.querySelector('input[name="fwdMaxSpeed"]'), revSL = document.querySelector('input[name="revMaxSpeed"]'), fwdChkBox = document.getElementById('fwdMaxSpeedUnverifiedCheckbox'), revChkBox = document.getElementById('revMaxSpeedUnverifiedCheckbox'), prevFwdSpeedVal, prevRevSpeedVal, numSegsSelected = getSelectedSegmentCount(), pauseTime = (numSegsSelected > 10) ? 60 : 0; cmlog([5,3],speedVal); if ((revSLMenu && revSLMenu.parentNode.style.display === 'none') || revSLMenu === null) { SL.addSpeedSignAB(speedVal); } else if ((fwdSLMenu && fwdSLMenu.parentNode.style.display === 'none') || fwdSLMenu === null) { SL.addSpeedSignBA(speedVal); } else if (fwdSL.disabled === false && revSL.disabled === false) { document.getElementById('cmWaitCover').style.display = 'block'; speedVal = SL.checkUnits(speedVal); prevFwdSpeedVal = fwdSLMenu.value; prevRevSpeedVal = revSLMenu.value; requestAnimationFrame(function(){ var fwdChkBoxMenu = document.getElementById('fwdMaxSpeedUnverifiedCheckbox_cm'), revChkBoxMenu = document.getElementById('revMaxSpeedUnverifiedCheckbox_cm'); if (fwdChkBoxMenu !== null) fwdChkBoxMenu.checked = true; if (revChkBoxMenu !== null) revChkBoxMenu.checked = true; fwdSLMenu.value = speedVal; //$('#cmSpeedLimit input[type="number"]').val(speedVal); revSLMenu.value = speedVal; }); setTimeout(function(){ if (fwdChkBox !== null && speedVal === prevFwdSpeedVal) { fwdChkBox.checked = true; fwdChkBox.dispatchEvent(changeEvent); fwdChkBox.dispatchEvent(focusOut); //$('#fwdMaxSpeedUnverifiedCheckbox').prop('checked', true).change(); } else if (fwdSL !== null) { fwdSL.value = speedVal; fwdSL.dispatchEvent(changeEvent); fwdSL.dispatchEvent(focusOut); $('input[name="fwdMaxSpeed"]').val(speedVal).change().focusout(); } if (revChkBox !== null && speedVal === prevRevSpeedVal) { revChkBox.checked = true; revChkBox.dispatchEvent(changeEvent); revChkBox.dispatchEvent(focusOut); //$('#revMaxSpeedUnverifiedCheckbox').prop('checked', true).change(); } else if (revSL !== null) { //revSL.value = speedVal; //revSL.dispatchEvent(changeEvent); $('input[name="revMaxSpeed"]').val(speedVal).change().focusout(); if (fwdChkBox !== null) setTimeout(function(){fwdChkBox.checked = true;},20); if (revChkBox !== null) setTimeout(function(){revChkBox.checked = true;},40); } if (fwdSL && parseInt(fwdSL.value) !== parseInt(speedVal)) fwdSL.value = speedVal; if (revSL && parseInt(revSL.value) !== parseInt(speedVal)) revSL.value = speedVal; if (!document.getElementById('cmPinMenu').value) setTimeout(closeContextMenu, 150); else setTimeout(SL.highlightSpeedSigns,50); /*setTimeout(function(){ try { //do it again just in case... sometimes necessary... $('input[name="revMaxSpeed"]').val(speedVal).change(); } catch(err) {} }, 150);*/ document.getElementById('cmWaitCover').style.display = 'none'; }, pauseTime); } }; SL.addListenersToSigns = function (forceBuildNewMenu) { // Add clear SL button: /*if (document.getElementById('btnCMClearSLs') === null) { document.getElementById('signsholder_cm').innerHTML = '<div id="btnCMClearSLs" class="fa fa-ban"><div id="spd_0">0</div></div>' + document.getElementById('signsholder_cm').innerHTML; }*/ var cmSpeedSigns = document.getElementById('signsholder_cm').children; for (var ss = cmSpeedSigns.length; ss--;) { //-------------------------------------------------------------- cmSpeedSigns[ss].addEventListener('click', function (e) { e.preventDefault(); var speedVal; if (!this.classList.length || !this.classList.contains('cm-sl-verified')) { speedVal = this.firstElementChild.innerHTML; } else { speedVal = 0; } if (e.shiftKey) { //AB - fwd requestAnimationFrame(function(){ SL.addSpeedSignAB(speedVal); }); } else if (e.ctrlKey || e.altKey || e.metaKey ) { //BA - rev requestAnimationFrame(function(){ SL.addSpeedSignBA(speedVal); }); } else { requestAnimationFrame(function(){ SL.addSpeedSignBoth(speedVal); }); } }, false); //-------------------------------------------------------------- cmSpeedSigns[ss].addEventListener('mousedown', function (ev) { //console.info(this); this.draggable = true; if (document.getElementById('cmPinMenu').value) { document.getElementById('cmContextMenu').removeEventListener('dragstart', allowMenuDrag, false); document.getElementById('cmContextMenu').draggable = false; window.addEventListener('mouseup', resetDrag, false); } }, false); cmSpeedSigns[ss].addEventListener('dragstart', function (ev) { //console.info(this); this.style.opacity = 0.3; this.children[0].opacity = 0.7; ev.dataTransfer.setData('text', this.children[0].innerHTML); ev.dataTransfer.setDragImage(this, ev.offsetX, ev.offsetY); }, false); cmSpeedSigns[ss].addEventListener('dragend', function (ev) { this.style.opacity = ''; this.children[0].opacity = ''; this.draggable = false; resetDrag(); window.removeEventListener('mouseup', resetDrag, false); }, false); } //----------------------------------------------- var slCurrentElementStatus = [!!document.getElementById('fwdMaxSpeedUnverifiedCheckbox'), !!document.getElementById('revMaxSpeedUnverifiedCheckbox'), !!document.getElementsByName('fwdMaxSpeed').length, !!document.getElementsByName('revMaxSpeed').length], slMenuElementFlags = [!!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, slCurrentElementTotal=0; cc--;) { slCurrentElementTotal += slCurrentElementStatus[cc]; } if (forceBuildNewMenu === null || SL.speedhelperIsPresent === null) { /*SL.signsContainerHTML = null;*/ } else { if (forceBuildNewMenu === true && SL.speedhelperIsPresent === true) SL.reduceSpeedhelperOverhead(); if (forceBuildNewMenu === true || slCurrentElementTotal >= SL.slSavedMaxElementTotal) { SL.cmMenuContentHTML = document.getElementById('cmMenuContent').innerHTML; SL.slSavedMaxElementTotal = slCurrentElementTotal; SL.slSavedMenuElementFlags = slMenuElementFlags; cmlog([4,4],'*** SL.cmMenuContentHTML replaced ***'); } } SL.highlightSpeedSigns(); // this is necessarily at the end to play catchup bc of the slower initialization times of Speedhelper elements }; //-------------------------------------------------------------------------- SL.populateSpeedMenu = function (contextMenuSettings, nodeLabel) { cmlog([1,1], 'SL.populateSpeedMenu(contextMenuSettings, ' + nodeLabel + ')'); document.getElementById('cmMenuNoContent').style.display = 'none'; document.getElementById('cmMenuContent').style.display = 'block'; if (SL.menuResetEvent === true) SL.checkCountry(); var slCurrentElementStatus = [!!document.getElementById('fwdMaxSpeedUnverifiedCheckbox'), !!document.getElementById('revMaxSpeedUnverifiedCheckbox'), !!document.getElementsByName('fwdMaxSpeed').length, !!document.getElementsByName('revMaxSpeed').length], signholderEl, forceBuildNewMenu = SL.forceBuildNewMenu, slMenuElementFlags = [!!document.getElementById('fwdMaxSpeedUnverifiedCheckbox_cm')+1, !!document.getElementById('revMaxSpeedUnverifiedCheckbox_cm')+1, document.getElementsByName('fwdMaxSpeed_cm').length+1, document.getElementsByName('revMaxSpeed_cm').length+1]; if (forceBuildNewMenu === true) { SL.forceBuildNewMenu = false; SL.menuResetEvent = true; SL.slSavedMenuElementFlags = false; SL.slSavedMaxElementTotal = 0; SL.cmMenuContentHTML = null; SL.signsContainerHTML = null; } if (SL.slSavedMenuElementFlags === false) SL.slSavedMenuElementFlags = slMenuElementFlags; for (var cc = 4, slNumSavedElementsMatched = 0, slNumElementsMatched = 0, slCurrentElementTotal=0; cc--;) { slNumElementsMatched += (((slMenuElementFlags[cc]*slCurrentElementStatus[cc]-1)>0)===slCurrentElementStatus[cc]); slNumSavedElementsMatched += (((SL.slSavedMenuElementFlags[cc]*slCurrentElementStatus[cc]-1)>0)===slCurrentElementStatus[cc]); slCurrentElementTotal += slCurrentElementStatus[cc]; } cmlog([4,3], 'SL.slSavedMaxElementTotal', SL.slSavedMaxElementTotal, '| slCurrentElementTotal', slCurrentElementTotal); cmlog([4,3], 'slNumSavedElementsMatched', slNumSavedElementsMatched, '| slNumElementsMatched', slNumElementsMatched); cmlog([4,3], 'SL.slSavedMenuElementFlags', SL.slSavedMenuElementFlags, '| slMenuElementFlags', slMenuElementFlags); if ( forceBuildNewMenu === true || SL.cmMenuContentHTML === null || slNumElementsMatched !== 4 || (SL.menuResetEvent === true && slNumElementsMatched !== 4) || (slCurrentElementTotal === 4 && SL.slSavedMaxElementTotal !== 4) ) { resetContextMenu(contextMenuSettings); document.getElementById('cmMenuHeaderTitle').innerHTML = 'Edit Speed Limits <i class="fa fa-pencil fa-pull-right" style="font-size: 12px; cursor: pointer;"></i>'; if (SL.cmMenuContentHTML && slNumSavedElementsMatched === 4) { cmlog([4,1],'Replace - Copy Saved and Rebuild'); document.getElementById('cmMenuContent').innerHTML = SL.cmMenuContentHTML; SL.menuResetEvent = false; } else { //TODO: I think slNumElementsMatched !== 4 is redundant with slNumSavedElementsMatched /*(document.getElementsByName('fwdMaxSpeed').length && !document.getElementsByName('fwdMaxSpeed_cm').length) || (document.getElementsByName('revMaxSpeed').length && !document.getElementsByName('revMaxSpeed_cm').length)) {*/ SL.menuResetEvent = true; try { cmlog([4,1],'Replace - Overwrite with Source and Rebuild'); document.getElementById('cmMenuContent').innerHTML = document.querySelector('#segment-edit-general div.speed-limit').outerHTML; speedLimit = document.getElementById('cmMenuContent').children[0]; speedLimit.innerHTML = '<div id="signsContainer" style="min-height: ' + ((SL.signsContainerHeight) ? (SL.signsContainerHeight + 'px; ') : 'auto; ') + 'margin-bottom: 10px; opacity: 0.9;"></div><div class="form-inline">' + speedLimit.innerHTML + '</div>'; speedLimit.id = 'cmSpeedLimit'; speedLimit.className = 'cm-speed-limit cm-menu-section'; signholderEl = document.querySelector('#cmSpeedLimit #signsholder'); if (SL.speedhelperIsPresent !== null && SL.signsContainerHTML !== null) { document.getElementById('signsContainer').innerHTML = SL.signsContainerHTML; } else if (signholderEl !== null) { signholderEl.id = 'signsholder_cm'; document.getElementById('signsContainer').appendChild(document.getElementById('signsholder_cm')); // Move the signs to its own container SL.reduceSpeedhelperOverhead(); SL.createSpeedSigns(); } else if (document.getElementById('cmSignsWait') === null) { document.getElementById('cmSpeedLimit').innerHTML = '<div id="cmSignsWait"><p><i class="fa fa-spinner fa-pulse fa-lg"></i></p><p>Looking for WME Speedhelper...<br>Please wait a moment.</p></div>' + document.getElementById('cmSpeedLimit').innerHTML; } } catch (err) { cmlog([4,2],'Replace - Caught. No SpeedHelper or SpeedHelper is not ready.', err); } } //-------------------------------------------------------------------------- try { var wazeVerifyChkBoxLabel = document.querySelectorAll('#segment-edit-general div.speed-limit input[type="checkbox"]+label'), wazeChkbox, wazeChkboxSelector; // Add event listeners for verified SL checkbox in menu for (var cb = 0; cb < wazeVerifyChkBoxLabel.length; cb++) { wazeChkbox = wazeVerifyChkBoxLabel[cb].parentNode.children[0]; cmChkboxSelector = '#cmSpeedLimit ' + '#' + wazeChkbox.id; if (SL.menuResetEvent) document.querySelector(cmChkboxSelector).id = wazeChkbox.id + '_cm'; document.querySelector(cmChkboxSelector + '_cm').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) {cmlog([4,2], 'wazeVerifyChkBoxLabel', err);} //-------------------------------------------------------------------------- try { var wazeSpeedInput = document.querySelectorAll('#segment-edit-general div.speed-limit input[type="number"]'), wazeSpeedInputLength = wazeSpeedInput.length, cmSpeedInput, cmSpeedInputSelector_orig, cmSpeedInputSelector, nm; for (nm = 0; nm < wazeSpeedInputLength; nm++) { cmSpeedInputSelector_orig = '#cmSpeedLimit input[name="' + wazeSpeedInput[nm].name + '"]'; cmSpeedInputSelector = '#cmSpeedLimit input[name="' + wazeSpeedInput[nm].name + '_cm' + '"]'; if (SL.menuResetEvent) { document.querySelector(cmSpeedInputSelector_orig).setAttribute('name', wazeSpeedInput[nm].name + '_cm'); } cmSpeedInput = document.querySelector(cmSpeedInputSelector); cmSpeedInput.addEventListener('click', function (e) { e.stopPropagation(); this.select(); document.getElementById('cmContextMenu').removeEventListener('mouseenter', addHotkeyListener, false); window.removeEventListener('keydown', menuShortcutKeys, true); cmlog([2,2],'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); cmlog([2,2],'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) {cmlog([4,2], 'cmSpeedInput', err);} //-------------------------------------------------------------------------- //-------------------------------------------------------------------------- try { // Try adding some event listeners for closing the menu if not pinned: if (!document.getElementById('cmPinMenu').value) { document.getElementById('cmContextMenu').addEventListener( 'mouseleave', function () { cmlog([2,2], 'Adding event listners to allow menu to close'); addSpecialMenuListeners(); //$('input[name="fwdMaxSpeed_cm"]').val($('input[name="fwdMaxSpeed"]').val()); //$('input[name="revMaxSpeed_cm"]').val($('input[name="revMaxSpeed"]').val()); }, false); document.getElementById('cmContextMenu').addEventListener( 'mouseenter', function () { //prevent menu from closing cmlog([2,2],'Preventing menu from closing by removing event listeners'); window.removeEventListener('click', closeContextMenu, false); document.getElementById('toolbar').removeEventListener('mouseenter', closeContextMenu, false); }, false); } } catch (err) { cmlog([4,2], 'addSpecialMenuListeners', err); } //-------------------------------------------------------------------------- document.querySelector('#cmMenuHeaderTitle>.fa-pencil').onclick = SL.editSpeedSigns; //-------------------------------------------------------------------------- // Add event listener for clearing SLs of each direction var fwdSpeedEl = document.querySelector('input[name="fwdMaxSpeed_cm"]'); if (fwdSpeedEl) { if (fwdSpeedEl.parentNode.querySelector('.fa-ban') === null) { var clearSignFwd = document.createElement('span'); clearSignFwd.className = 'fa fa-ban'; fwdSpeedEl.parentNode.insertBefore(clearSignFwd, fwdSpeedEl.parentNode.children[0]); clearSignFwd.addEventListener('click', function() { requestAnimationFrame(function(){ SL.addSpeedSignAB(0); }); }, false); } } var revSpeedEl = document.querySelector('input[name="revMaxSpeed_cm"]'); if (revSpeedEl) { if (revSpeedEl.parentNode.querySelector('.fa-ban') === null) { var clearSignRev = document.createElement('span'); clearSignRev.className = 'fa fa-ban'; revSpeedEl.parentNode.insertBefore(clearSignRev, revSpeedEl.parentNode.children[0]); clearSignRev.addEventListener('click', function() { requestAnimationFrame(function(){ SL.addSpeedSignBA(0); }); }, false); } } // Add event listener for the checkbox if (document.getElementById('fwdMaxSpeedUnverifiedCheckbox_cm') !== null) { document.getElementById('fwdMaxSpeedUnverifiedCheckbox_cm').parentNode.addEventListener('click', function(e) { this.children[0].checked = !this.children[0].checked; }, false); } if (document.getElementById('revMaxSpeedUnverifiedCheckbox_cm') !== null) { document.getElementById('revMaxSpeedUnverifiedCheckbox_cm').parentNode.addEventListener('click', function(e) { this.children[0].checked = !this.children[0].checked; }, false); } // Add event listeners for drag-drop events var fwdSpeedEl = document.querySelector('input[name="fwdMaxSpeed_cm"]'); if (fwdSpeedEl) { // Allow drop event fwdSpeedEl.addEventListener('dragover', function(ev) { if (ev.preventDefault()) ev.preventDefault(); this.style.border = '1px solid cyan'; return false; }, false); fwdSpeedEl.addEventListener('dragleave', function(ev) { this.style.border = ''; }, false); // Drop event fwdSpeedEl.addEventListener('drop', function(ev) { if (ev.preventDefault()) ev.preventDefault(); var speedVal = ev.dataTransfer.getData('text'); requestAnimationFrame(function(){ SL.addSpeedSignAB(speedVal); }); this.style.border = ''; }, false); } var revSpeedEl = document.querySelector('input[name="revMaxSpeed_cm"]'); if (revSpeedEl) { // Allow drop event revSpeedEl.addEventListener('dragover', function(ev) { if (ev.preventDefault()) ev.preventDefault(); this.style.border = '1px solid cyan'; return false; }, false); revSpeedEl.addEventListener('dragleave', function(ev) { this.style.border = ''; }, false); // Drop event revSpeedEl.addEventListener('drop', function(ev) { if (ev.preventDefault()) ev.preventDefault(); var speedVal = ev.dataTransfer.getData('text'); requestAnimationFrame(function(){ SL.addSpeedSignBA(speedVal); }); this.style.border = ''; }, false); } //-------------------------------------------------------------------------- var waitCount = 0, maxWait = 19, //~5 seconds signsContainerEl = document.getElementById('signsContainer'); var waitForSpeedhelper = function () { var originalSpeedhelperEl = document.querySelector('#segment-edit-general div.speed-limit #signsholder'); if (signsContainerEl.children.length === 0 || SL.speedhelperIsPresent === null) { if (originalSpeedhelperEl !== null) { SL.menuResetEvent = false; SL.speedhelperIsPresent = true; signsContainerEl.innerHTML = originalSpeedhelperEl.outerHTML; document.querySelector('#signsContainer>#signsholder').id = 'signsholder_cm'; setTimeout(function(){SL.signsContainerHeight = $('#signsholder_cm').height();},200); SL.reduceSpeedhelperOverhead(); SL.createSpeedSigns(); SL.addListenersToSigns(forceBuildNewMenu); } else if (waitCount++ < maxWait) { setTimeout(waitForSpeedhelper, 30*waitCount); if (waitCount===10 && SL.speedhelperIsPresent === null) { //~1.5seconds ? SL.createSpeedSigns(); SL.addListenersToSigns(null); } } else { SL.menuResetEvent = false; SL.signsContainerHeight = false; SL.speedhelperIsPresent = false; SL.createSpeedSigns(); SL.addListenersToSigns(forceBuildNewMenu); } } return; }; //------------------------------------------------------ setTimeout(function () { if (signsContainerEl && signsContainerEl.children.length) { SL.menuResetEvent = false; setTimeout(function(){SL.signsContainerHeight = $('#signsholder_cm').height();},200); SL.addListenersToSigns(forceBuildNewMenu); } else if (SL.speedhelperIsPresent !== false) { setTimeout(waitForSpeedhelper, 30); } else { // SL.speedhelperIsPresent === false SL.menuResetEvent = false; SL.createSpeedSigns(); SL.addListenersToSigns(forceBuildNewMenu); } }, 30); //timeout may be needed for countries with many speedlimit signs loaded by Speedhelper //------------------------------------------------------ } var $fwdSL = $('input[name="fwdMaxSpeed"]'), hasFwdSL = ($fwdSL.length && !$fwdSL.prop('disabled')), $revSL = $('input[name="revMaxSpeed"]'), hasRevSL = ($revSL.length && !$revSL.prop('disabled')), hasOnlyOneSL = !(hasFwdSL && hasRevSL), fwdSLMenu = document.querySelector('input[name="fwdMaxSpeed_cm"]'), revSLMenu = document.querySelector('input[name="revMaxSpeed_cm"]'), fwdChkBox, revChkBox, fwdMenuChkBox, revMenuChkBox; cmlog([5,3], 'hasFwdSL', hasFwdSL, 'hasRevSL', hasRevSL, 'hasOnlyOneSL', hasOnlyOneSL, 'nodeLabel', nodeLabel); if (hasFwdSL || hasRevSL) { fwdMenuChkBox = document.getElementById('fwdMaxSpeedUnverifiedCheckbox_cm'); fwdChkBox = document.getElementById('fwdMaxSpeedUnverifiedCheckbox'); revMenuChkBox = document.getElementById('revMaxSpeedUnverifiedCheckbox_cm'); revChkBox = document.getElementById('revMaxSpeedUnverifiedCheckbox'); // Update values of the context menu // Hide input fields that aren't relevant for selected segment(s) if (fwdSLMenu !== null) { fwdSLMenu.disabled = false; if (hasOnlyOneSL || nodeLabel !== 'B') { if (hasFwdSL) { fwdSLMenu.value = $fwdSL.val(); fwdSLMenu.parentNode.style.display = 'inline-block'; if (fwdMenuChkBox !== null) { fwdMenuChkBox.disabled = false; if (fwdChkBox !== null) { fwdMenuChkBox.checked = fwdChkBox.checked; fwdMenuChkBox.parentNode.style.visibility = 'visible'; fwdMenuChkBox.parentNode.style.display = 'inline-block'; } else { fwdMenuChkBox.parentNode.style.visibility = 'hidden'; fwdMenuChkBox.parentNode.style.display = 'inline-block'; } } } else { fwdSLMenu.parentNode.style.display = 'none'; if (fwdMenuChkBox !== null) fwdMenuChkBox.parentNode.style.display = 'none'; } } else { fwdSLMenu.parentNode.style.display = 'none'; if (fwdMenuChkBox !== null) fwdMenuChkBox.parentNode.style.display = 'none'; } } if (revSLMenu !== null) { revSLMenu.disabled = false; if (hasOnlyOneSL || nodeLabel !== 'A') { if (hasRevSL) { revSLMenu.value = $revSL.val(); revSLMenu.parentNode.style.display = 'inline-block'; if (revMenuChkBox !== null) { revMenuChkBox.disabled = false; if (revChkBox !== null) { revMenuChkBox.checked = revChkBox.checked; revMenuChkBox.parentNode.style.visibility = 'visible'; revMenuChkBox.parentNode.style.display = 'inline-block'; } else { revMenuChkBox.parentNode.style.visibility = 'hidden'; revMenuChkBox.parentNode.style.display = 'inline-block'; } } } else { revSLMenu.parentNode.style.display = 'none'; if (revMenuChkBox !== null) revMenuChkBox.parentNode.style.display = 'none'; } } else { revSLMenu.parentNode.style.display = 'none'; if (revMenuChkBox !== null) revMenuChkBox.parentNode.style.display = 'none'; } } SL.highlightSpeedSigns(); } else { cmlog([4,2],'No SL. Hiding...'); document.getElementById('cmMenuNoContent').style.display = 'block'; document.getElementById('cmMenuContent').style.display = 'none'; } //-------------------------------------------------------------------------- }; //============================================================================================== var selectedItemsIsSegment = function () { var sel = W.selectionManager.getSelectedFeatures(), //returns empty array if nothing selLength = sel.length, s, segments = []; cmlog([1,1], 'selectedItemsIsSegment()'); for (s = 0; s < selLength; s++) { if (sel[s].model.type === 'segment') segments.push(sel[s]); } return (segments.length) ? {nodeLabel: false, segments: segments} : false; }; //---------------------------------------------------------------------------------------------- var selectionIsSegment = function (e) { cmlog([1,1], 'selectionIsSegment(e)'); var sel, selLength, s, segments = [], numSelected, eventFeatures, evTarget, nodeLabel = false; // First check for segments under cursor (hover/mouseover) if (e && e.target) { evTarget = $(e.target).get(0); //normalization by jQuery is necessary for FF compatibility } else { evTarget = false; } if (evTarget && evTarget._featureId && (evTarget._geometryClass === "OpenLayers.Geometry.LineString" || evTarget._geometryClass === "OpenLayers.Geometry.Point")) { e.preventDefault(); if (evTarget._geometryClass === "OpenLayers.Geometry.Point" && evTarget._style) { cmlog([1,3], evTarget._featureId, evTarget._geometryClass, evTarget._style.label); if (evTarget._style.label === 'A') { nodeLabel = 'A'; } else if (evTarget._style.label === 'B') { nodeLabel = 'B'; } } sel = W.selectionManager.getSelectedFeatures(); //returns empty array if nothing selLength = sel.length; eventFeatures = W.map.segmentLayer.getFeatureById(evTarget._featureId); //segment layer -- returns null if nothing //cmlog([1,0], 'eventFeatures =') //console.debug(eventFeatures); if (eventFeatures && eventFeatures.model.type === 'segment') { segments[0] = eventFeatures; //return result from W.map.segmentLayer.getFeatureById(._featureId) is the same as individual objects within the array returned by W.selectionManager.selectedItems try { //cmlog([1,0],'SegID:',eventFeatures.model.attributes.id); W.selectionManager.setSelectedModels([eventFeatures.model]); // [eventFeatures.model] is the same as the return result for one seg from W.model.segments.getByIds([id]) } catch(err) { cmlog([1,0], '<tantrum>'); console.error(err); } } //Now check for any selected segments... any duplicates of the hovered //segment will be dealt with in the next steps using object literals try { for (s = 0; s < selLength; s++) { if (sel[s].model.type === 'segment') segments.push(sel[s]); } } catch(err) { if (e.type === 'selectionchanged') { sel = e.selected; selLength = sel.length; for (s = 0; s < selLength; s++) { if (sel[s] && sel[s].model.type === 'segment') segments.push(sel[s]); } } } //console.info(segments); document.getElementById('cmMenuNoContent').style.display = 'none'; document.getElementById('cmMenuContent').style.display = 'block'; return (segments.length) ? {nodeLabel: nodeLabel, segments: 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] && sel[s].model.type === 'segment') segments.push(sel[s]); } return (segments.length) ? {nodeLabel: false, segments: segments} : false; //no segments near cursor } else { return false; } }; //---------------------------------------------------------------------------------------------- var setupSegmentContextMenu = function (e) { cmlog([1,0],'------------------------------------------------------------'); cmlog([1,1], 'setupSegmentContextMenu()'); if (document.getElementById('cmContextMenu') && document.getElementById('cmContextMenu').style.display !== 'none') { var selectedStuff = selectionIsSegment(e); if (selectedStuff) { if (document.getElementById('cmRSel').value && document.getElementById('cmRSelAutoAdd')) document.getElementById('cmRSelAutoAdd').style.display = 'block'; switch (contextMenuSettings.clipboard) { case 2: SL.populateSpeedMenu(contextMenuSettings, selectedStuff.nodeLabel); break; case 1: case 0: var segInfo = getSegmentProperties(selectedStuff); populateCopyMenu(segInfo, contextMenuSettings); break; } } else if (document.getElementById('cmPinMenu').value) { if (document.getElementById('cmRSelAutoAdd')) document.getElementById('cmRSelAutoAdd').style.display = 'none'; document.getElementById('cmMenuNoContent').style.display = 'block'; document.getElementById('cmMenuContent').style.display = 'none'; return false; } else { cmlog([1,1],'No segment detected.'); return false; } } else { return false; } }; //======================================================================================= //var pressedKeys = []; var menuShortcutKeys = function (e) { cmlog([1,1], 'menuShortcutKeys()'); 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 cursorOffsetX, cursorOffsetY; var moveMenu = function (evt) { //cmlog([1],'moveMenu()'); try { evt.preventDefault(); evt.stopPropagation(); //evt.dataTransfer.effectAllowed = 'move'; requestAnimationFrame( function() { document.getElementById('cmContextMenu').classList.add('cm-drag'); document.getElementById('cmContextMenu').style.top = evt.clientY - cursorOffsetY + 'px'; document.getElementById('cmContextMenu').style.left = evt.clientX - cursorOffsetX + 'px'; }); } catch (err) { console.error(err); } }; var placeMenu = function (endevt) { cmlog([1,1], 'placeMenu()'); endevt.preventDefault(); //endevt.dataTransfer.dropEffect = 'move'; try { //document.getElementById('cmContextMenu').style.display = 'block'; setTimeout(function(){document.getElementById('cmContextMenu').classList.remove('cm-drag');},50); if (!isFirefox) { document.getElementById('cmContextMenu').style.display = 'block'; document.getElementById('cmContextMenu').removeEventListener('drag', moveMenu, false); } else { window.removeEventListener('mousemove', moveMenu, true); window.removeEventListener('mouseup', placeMenu, true); } } catch (err) { console.error(err); } }; var allowMenuDrag = function (startevt) { cmlog([1,1], 'allowMenuDrag()'); //console.info(startevt); try { if (document.getElementById('cmContextMenu').draggable) { document.getElementById('cmContextMenu').classList.add('cm-drag'); if (!isFirefox) { setTimeout(function(){document.getElementById('cmContextMenu').style.display = 'none';},20); cursorOffsetX = startevt.offsetX; cursorOffsetY = startevt.offsetY; document.getElementById('cmContextMenu').addEventListener('drag', moveMenu, false); } else { startevt.preventDefault(); startevt.stopPropagation(); cursorOffsetX = startevt.layerX; cursorOffsetY = startevt.layerY; window.addEventListener('mousemove', moveMenu, true); window.addEventListener('mouseup', placeMenu, true); } } } catch (err) { console.error(err); } }; // Setup dragging for when menu is pinned to page var dragMenuSetup = function(pinState) { if (pinState === undefined) pinState = document.getElementById('cmPinMenu').value; var contextMenu = document.getElementById('cmContextMenu'), mapDiv = document.getElementById('map'); if (pinState && contextMenu.draggable === false) { contextMenu.draggable = true; contextMenu.addEventListener('dragstart', allowMenuDrag, false); if (!isFirefox) { mapDiv.addEventListener('drop', placeMenu, false); mapDiv.ondragover = function (e) { e.preventDefault(); e.dataTransfer.effectAllowed = 'move'; e.dataTransfer.dropEffect = 'move'; }; } } else if (!pinState && contextMenu.draggable === true) { contextMenu.draggable = false; contextMenu.removeEventListener('dragstart', allowMenuDrag); if (!isFirefox) { mapDiv.removeEventListener('drop', placeMenu); } } }; //for preventing conflicts with SL sign drags var resetDrag = function() { window.removeEventListener('mouseup', resetDrag, false); dragMenuSetup(); }; //======================================================================================= 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 25px; 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 16px 10px 8px; 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: 80px; font-size: 32px; 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 = 5001; popPanelHTML.innerHTML = '<div class="cm-panel">' + '<div margin-bottom: 20px; margin-top: 20px;>' + '<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 details and screenshots 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 switchPanelTo = function(panelName) { switch (panelName) { case 'clipboard': 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 = '210px'; break; case 'rsel': 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'; break; case 'speed': 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 = '220px'; SL.signsContainerHeight = null; break; } }; var showEmptyPanel = function(panelName) { switch (panelName) { case 'clipboard': document.getElementById('cmMenuHeaderTitle').innerHTML = 'Copy To Clipboard'; document.getElementById('cmMenuNoContent').style.display = 'block'; document.getElementById('cmMenuContent').style.display = 'none'; break; case 'rsel': if (document.getElementById('cmRSelAutoAdd')) document.getElementById('cmRSelAutoAdd').style.display = 'none'; document.getElementById('cmMenuHeaderTitle').innerHTML = 'Send To Road Selector'; document.getElementById('cmMenuNoContent').style.display = 'block'; document.getElementById('cmMenuContent').style.display = 'none'; break; case 'speed': document.getElementById('cmMenuHeaderTitle').innerHTML = 'Edit Speed Limits'; document.getElementById('cmMenuNoContent').style.display = 'block'; document.getElementById('cmMenuContent').style.display = 'none'; break; } }; //======================================================================================= var initContextMenu = function () { cmlog([1,1], 'initContextMenu()'); var contextMenuActiveArea = document.createElement('div'), contextMenu = document.createElement('div'), contextMenuCSS = document.createElement('style'), menuCSS; try {//opacity: 0.5; contextMenuCSS.type = 'text/css'; menuCSS = '#cmContextMenu { display: block; opacity: 1; }\n' + '#cmContextMenu.cm-drag { cursor: move; opacity: 0.75 !important; transition: opacity .1s linear 0s; }\n' + '.cm-top { border-top-right-radius: 3px; border-top-left-radius: 3px; }\n' + '.cm-bottom { border-bottom-left-radius: 3px; border-bottom-right-radius: 3px; }\n' + '#cmFooter+#cmContainer .cm-menu-header>dl, #cmFooter+#cmContainer .cm-menu-header>dl>dt, #cmFooter+#cmContainer .cm-rsel>dl, #cmFooter+#cmContainer .cm-rsel>dl>dt, .cm-rsel+.cm-menu-header>dl, .cm-rsel+.cm-menu-header>dl>dt { border-radius: 0; }\n' + '#cmFooter+#cmContainer #cmMenuContent > div:last-child { border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; }\n' + '.cm-footer-icns { font-size: 13px; margin: 0px 4px 0px 2px; cursor: pointer; display: inline-table; line-height: 1; }\n' + '.cm-footer-icns:active, .cm-footer-icns:focus, .cm-footer-icns.toggle-off:active, .cm-footer-icns.toggle-off:focus { color: #64D8EA; }\n' + '.cm-footer-icns.toggle-off, .cm-footer-text.toggle-off { color: #8CBBCC; }\n' + '.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; }\n' + '.cm-update-note.cm-unread { color: crimson; }\n' + 'div.cm-menu-header { padding: 0px; border: 0; height: 20px; }\n' + '.cm-menu-header dl { background-color: rgba(147, 196, 211, 0.92); padding: 0; border-top-right-radius: 4px; border-top-left-radius: 4px; }\n' + '.cm-menu-header dt { padding: 4px 11px; text-transform: uppercase; line-height: 1.3; background-color: rgba(111, 167, 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 #9ACCDC; }\n' + 'div.cm-menu-section { z-index: 2; border-bottom: 1px solid #416B7C; padding: 2px 0px 3px; background-color: rgba(147, 196, 211, 0.92); }\n' + '.cm-menu-section dl { margin: 0; padding: 0; display: block; }\n' + '.cm-menu-section dt { font-size: 9px; padding: 0px 6px 0px 20px; margin-top: 2px; text-transform: uppercase; line-height: 1.2; }\n' + '.cm-menu-section dd { display: inherit; padding: 0px 14px 0px 20px; font-size: 11px; color: #234350; font-weight: 600; line-height: 1.3; word-break: break-all;}\n' + '.cm-menu-section dd:hover, .cm-menu-section dd:active, .cm-menu-section dd:focus { cursor: default; background-color: #BEDCE5; color: #416B7C; }\n' + '.cm-menu-section dd:active { color: #64D8EA; }\n'; menuCSS += '.cm-menu-section .cm-hide.fa-caret-down, .cm-menu-section .cm-hide.fa-caret-up { position: absolute; left: 8px; width: 90%; cursor: pointer; }\n' + '.cm-menu-section .cm-hide.fa-caret-down { display: block; }\n' + '.cm-menu-section .cm-hide.fa-caret-up { display: none; }\n' + '.cm-menu-section.cm-hidden .cm-hide.fa-caret-down { display: none; }\n' + '.cm-menu-section.cm-hidden .cm-hide.fa-caret-up { display: block; }\n' + '.cm-hidden { height: 19px; }\n' + '.cm-hidden dd { display: none; }\n' + '.cm-hidden dt, .cm-hidden dl {float: left; margin-right: -12px; color: rgba(255, 255, 255, 0.7); }\n' + '.cm-hidden dl:nth-of-type(2)>dt:before { content: "/ "; }\n' + 'dd.cm-paste { font-style: italic; text-align: right; max-width: 50%; float: right; padding: 0px 10px 0px 5px;}\n' + '.cm-paste:before { content: ""; font-style: normal; font-weight: 400; color: black; font-size: 11px; margin-right: 2px; }\n'; menuCSS += 'dd.cm-rsel-goselect { padding-right: 12px; padding-left: 12px; cursor: pointer; }\n' + '.cm-menu-section .cm-rsel-goselect:hover { background-color: transparent; color: #d4e7ed; }\n' + '.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; }\n' + '.cm-rsel>dl { padding-top: 1px; border-top-right-radius: 4px; border-top-left-radius: 4px; }\n' + '.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: 4px 10px; color: #d8e9ef; font-size: 10px; }\n' + '.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); }\n' + '.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; }\n' + '.cm-rsel-options:hover { background-color: rgba(89, 137, 158, 0.7); color: white; }\n' + '.cm-rsel-options.active:hover { background-color: #274B5A }\n' + '.cm-rsel-options.active, .cm-rsel-options:active, .cm-rsel-options:active:focus { color: white; background-color: #3F6271; }\n' + '.cm-rsel-options:focus { color: white; }\n' + '.cm-rsel-options.and { background-color: #EEE; color: #59899E; border-right: 1px solid #AAA;}\n' + '.cm-rsel-options.cm-badge-right { border-left: 1px solid #59899E; }\n'; menuCSS += '.cm-speed-limit.cm-menu-section { z-index: 3; width: 100%; font-size: 11px; text-align: center; display: inline-block; padding: 10px 8px; }\n' + '.cm-speed-limit input[type="number"] { height: 28px; width: 50px; font-size: 12px; padding: 4px 5px; line-height: 1; margin: 0px 2px; }\n' + '.cm-speed-limit input[type="checkbox"]+label { color: transparent; width: 10px; margin-left: 5px; vertical-align: middle; }\n' + '.cm-speed-limit .controls-container { margin-left: 5px; }\n' + '.cm-speed-limit div { border-radius: 3px; display: inline-block; }\n' + 'div#signsholder_cm>div#btnCMClearSLs { float: left; display: inline-block; cursor: pointer; background-image: none; color: #134C65; font-size: 28px; }\n' + 'div#signsholder_cm>div#btnCMClearSLs>div {display: none;}\n' + 'div#signsholder_cm>div#btnCMClearSLs:before { vertical-align: middle; }\n' + 'div#signsholder_cm>div:not(#btnCMClearSLs):before { position: absolute; background-color: white; color: black; border: 2px solid #00ECE3; font-weight: 400; border-radius: 50%; font-size: 9px; width: 16px; height: 16px; line-height: 12px; text-align: center; margin-left: -10px; margin-top: -3px; box-shadow: 0px 1px 1px gray; z-index: 1; }\n' + 'div#signsholder_cm>.cm-a:before { content: "A"; }\n' + 'div#signsholder_cm>.cm-b:before { content: "B"; }\n' + '.cm-speed-limit>.form-inline .fa-ban { cursor: pointer; color: #1F576E; padding-right: 8px; font-size: 1.5em; font-weight: bold; vertical-align: middle; margin-bottom: 2px; }\n' + '.cm-sl-edit>.fa-pencil:hover, .cm-speed-limit>.form-inline .fa-ban:hover { color: #00ECE3; }\n' + '.cm-sl-verified { box-shadow: inset 0px 0px 0px 2px lime; }\n' + '.cm-sl-unverified { box-shadow: inset 0px 0px 0px 2px gold; }\n' + '.cm-sl-multisegs { box-shadow: inset 0px 0px 0px 3px #333 !important; }\n' + '.cm-sl-verified.cm-both { box-shadow: 0px 0px 0px 1px lime, inset 0px 0px 0px 2px greenyellow; }\n' + '.cm-sl-unverified.cm-one { box-shadow: 0px 0px 0px 1px lime, inset 0px 0px 0px 2px rgba(255, 235, 59, 1); }\n' + '.cm-sl-unverified.cm-both { box-shadow: 0px 0px 0px 1px orange, inset 0px 0px 0px 2px rgba(255, 235, 59, 1); }\n' + '#signsholder_cm>#signsError { float: initial; width: 100%; height: initial; padding: 5px 5px 5px 45px !important; text-align: left; }\n'; contextMenuCSS.innerHTML = menuCSS; document.head.appendChild(contextMenuCSS); //#btnCMAddSL {float: left; display: inline-block; cursor: pointer; color: #134C65; font-size: 24px; padding: 2px; width: 32px; line-height: 1;} //#signsContainer.cm-sl-edit>#signsholder_cm>div:not(#btnCMclearSLs):after {content: "x"; position: absolute; background-color: #E53935; color: #FFF; font-weight: 600; border-radius: 50%; font-size: 11px; width: 14px; height: 14px; line-height: 12px; text-align: center; right: -3px; top: -4px; box-shadow: 0px 1px 1px gray;} // 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 = '210px'; contextMenu.style.margin = '0px'; contextMenu.style.padding = '0px'; contextMenu.style.borderRadius = '4px'; contextMenu.style.boxShadow = '0px 5px 12px rgba(0, 0, 0, 0.5)'; contextMenu.style.border = '1px solid rgb(89, 137, 150)'; contextMenu.style.borderBottom = '1px solid #2D505F'; contextMenu.style.color = 'white'; contextMenu.style.zIndex = '5000'; contextMenu.style.display = 'none'; contextMenu.style.opacity = 0; contextMenu.innerHTML = '<div id="cmContainer" style="z-index: 2; 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" class="cm-bottom" style="color: #DDEDF3; height: 24px; background-color: rgba(75, 125, 148, 0.85); ' + 'z-index: 3; 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: 0 0 0 -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-angle-up cm-footer-icns pull-right" style="position: relative; top: 3px; margin: auto -1px auto 7px; font-weight: bold;"></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; height: 100%; 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; height: 100%; border-right: 1px solid #6EA1B7;">' + '<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: 0; opacity: 0.84;">' + '<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>'; resetContextMenu(contextMenuSettings); hidePasteMenu(); setTimeout(function () { if (contextMenuSettings.clipboard === 0 || (contextMenuSettings.clipboard === 1 && document.getElementById('tabRSel') === null)) switchPanelTo('clipboard'); }, 2000); if (contextMenuSettings.clipboard === 1) switchPanelTo('rsel'); else if (contextMenuSettings.clipboard === 2) switchPanelTo('speed'); 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 = 'Hello there! Your friendly right-click WME popup has been recently updated! Within the popup panel, you can now:' + '</div><div class="cm-panel-section"><ul>' + '<li>Drag-and-drop speed limit signs to input box</li>' + '<li>Right-click node A/B to edit speed limit starting from that direction</li>' + '<li>Add or remove speed limit signs</li>' + '<li>When WME Speedhelper is not running, the popup will create its own customizable speed limit signs</li>' + '<li>Some previous bugs were found and squashed</li>' + '</ul>' + '<p>Enjoy!</p><p>Coming soonish – A better copy-and-paste menu for segment attributes (and maybe Places... who knows.)</p>'; document.getElementById('cmUpdateNote').onclick = function(e){ e.stopPropagation(); showPopupPanel(minVersion, updateNotes, forumURL); }; document.getElementById('cmClipboard').onclick = function (e) { try { e.stopPropagation(); switchPanelTo('clipboard'); contextMenuSettings.clipboard = 0; localStorage.WME_ContextMenu = JSON.stringify(contextMenuSettings); var selectedStuff = selectedItemsIsSegment(); if (selectedStuff) { var segInfo = getSegmentProperties(selectedStuff); populateCopyMenu(segInfo, contextMenuSettings); } else { showEmptyPanel('clipboard'); } hidePasteMenu(false); } catch (err) { console.error(err); } }; document.getElementById('cmRSel').onclick = function (e) { try { e.stopPropagation(); if (document.getElementById('tabRSel') !== null) { switchPanelTo('rsel'); contextMenuSettings.clipboard = 1; localStorage.WME_ContextMenu = JSON.stringify(contextMenuSettings); var selectedStuff = selectedItemsIsSegment(); if (selectedStuff) { var segInfo = getSegmentProperties(selectedStuff); if (document.getElementById('cmRSelAutoAdd')) document.getElementById('cmRSelAutoAdd').style.display = 'block'; populateCopyMenu(segInfo, contextMenuSettings); } else { showEmptyPanel('rsel'); } hidePasteMenu(true); } } catch (err) { console.error(err); } }; document.getElementById('cmSpeed').onclick = function (e) { try { e.stopPropagation(); switchPanelTo('speed'); contextMenuSettings.clipboard = 2; localStorage.WME_ContextMenu = JSON.stringify(contextMenuSettings); var selectedStuff = selectedItemsIsSegment(); if (selectedStuff) { SL.menuResetEvent = true; SL.populateSpeedMenu(contextMenuSettings); window.removeEventListener('click', closeContextMenu, false); document.getElementById('toolbar').removeEventListener('mouseenter', closeContextMenu, false); } else { showEmptyPanel('speed'); } } catch (err) { console.error(err); } }; document.getElementById('map').addEventListener( 'contextmenu', function (e) { cmlog([1,0],'------------------------------------------------------------'); cmlog([1,1], 'contextmenu'); //console.info(e); var selectedStuff = selectionIsSegment(e), contextMenu = document.getElementById('cmContextMenu'); if (selectedStuff) { try { e.stopPropagation(); contextMenu.style.display = 'block'; contextMenu.style.top = e.clientY - 10 + 'px'; contextMenu.style.left = e.clientX + 'px'; contextMenu.classList.remove('cm-drag'); SL.menuResetEvent = 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'); contextMenu.addEventListener('mouseenter', addHotkeyListener, false); contextMenu.addEventListener('mouseleave', removeHotkeyListener, false); W.selectionManager.events.register("selectionchanged", null, setupSegmentContextMenu); } } catch (err) { console.error(err); } } else { // No segment detected... Decide whether to keep the menu open. if (document.getElementById('cmPinMenu').value) { return true; } else { contextMenu.style.display = 'none'; return false; } } }, true); 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 dragMenuSetup(false); // 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 dragMenuSetup(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(); if (this.classList.contains('fa-angle-up')) { //switch to top menubar contextMenuSettings.position = 1; localStorage.WME_ContextMenu = JSON.stringify(contextMenuSettings); adjustContextMenubar(1); } else if (this.classList.contains('fa-angle-down')) { //switch to bottom menubar contextMenuSettings.position = 0; localStorage.WME_ContextMenu = JSON.stringify(contextMenuSettings); adjustContextMenubar(0); } }, false); } catch (err) { console.error(err); } dragMenuSetup(); var cmWaitCover = document.createElement('div'); cmWaitCover.id = 'cmWaitCover'; cmWaitCover.style.display = 'none'; cmWaitCover.style.position = 'fixed'; cmWaitCover.style.top = 0; cmWaitCover.style.bottom = '25px'; cmWaitCover.style.left = 0; cmWaitCover.style.right = 0; cmWaitCover.style.background = 'transparent'; cmWaitCover.style.cursor = 'wait'; cmWaitCover.style.zIndex = '5001'; document.body.appendChild(cmWaitCover); 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 getSelectedSegmentCount = function(){ let count = _.countBy(W.selectionManager.getSelectedFeatures().map(function(e){return e.model.type}), _.identity).segment; if( !count) return 0; else return count; } var waitCount = 0, maxWaitCount = 50; var waitForWaze = function () { try { if (document.getElementById('cmContextMenu')) { return true; } else if (typeof(Waze) !== "undefined" && W.model && W.selectionManager && W.model.segments && W.model.cities && W.map && W.map.layers) { //cmlog([1],'starting...'); setTimeout(initContextMenu, 1000); //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. Major fail. Please let TheLastTaterTot know about this...'); console.error(err); } }; waitForWaze();