您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Various UI changes to make editing faster and easier.
当前为
// ==UserScript== // @name WME ClickSaver // @namespace https://gf.qytechs.cn/users/45389 // @version 2018.07.06.001 // @description Various UI changes to make editing faster and easier. // @author MapOMatic // @include /^https:\/\/(www|beta)\.waze\.com\/(?!user\/)(.{2,6}\/)?editor\/?.*$/ // @license GNU GPLv3 // @connect google.com // @grant GM_xmlhttpRequest // ==/UserScript== /* global GM_info */ /* global W */ /* global Node */ /* global I18n */ (function() { function main(argsObject) { //'use strict'; let _debugLevel = 0; let _roadTypeDropDownSelector = 'select[name="roadType"]'; let _elevationDropDownSelector = 'select[name="level"]'; let _routingTypeDropDownSelector = 'select[name="routingRoadType"]'; let _parkingSpacesDropDownSelector = 'select[name="estimatedNumberOfSpots"]'; let _parkingCostDropDownSelector = 'select[name="costType"]'; let _alertUpdate = false; let _settings = {}; let _settingsStoreName = 'clicksaver_settings'; let _lastScriptVersion; let _trans; // Translation object let _scriptVersionChanges = [ argsObject.scriptName, 'v' + argsObject.scriptVersion, '', 'What\'s New', '------------------------------', '' // Add important changes here and set _alertUpdate=true ].join('\n'); let _roadTypes = { St:{val:1, wmeColor:'#ffffeb', svColor:'#ffffff', category:'streets', visible:true}, PS:{val:2, wmeColor:'#f0ea58', svColor:'#cba12e', category:'streets', visible:true}, mH:{val:7, wmeColor:'#69bf88', svColor:'#ece589', category:'highways', visible:true}, MH:{val:6, wmeColor:'#45b8d1', svColor:'#c13040', category:'highways', visible:true}, Fw:{val:3, wmeColor:'#c577d2', svColor:'#387fb8', category:'highways', visible:false}, Rmp:{val:4, wmeColor:'#b3bfb3', svColor:'#58c53b', category:'highways', visible:false}, OR:{val:8, wmeColor:'#867342', svColor:'#82614a', category:'otherDrivable', visible:false}, PLR:{val:20, wmeColor:'#ababab', svColor:'#2282ab', category:'otherDrivable', visible:true}, PR:{val:17, wmeColor:'#beba6c', svColor:'#00ffb3', category:'otherDrivable', visible:true}, Fer:{val:15, wmeColor:'#d7d8f8', svColor:'#ff8000', category:'otherDrivable', visible:false}, WT:{val:5, wmeColor:'#b0a790', svColor:'#00ff00', category:'nonDrivable', visible:false}, PB:{val:10, wmeColor:'#9a9a9a', svColor:'#0000ff', category:'nonDrivable', visible:false}, Sw:{val:16, wmeColor:'#999999', svColor:'#b700ff', category:'nonDrivable', visible:false}, RR:{val:18, wmeColor:'#c62925', svColor:'#ffffff', category:'nonDrivable', visible:false}, RT:{val:19, wmeColor:'#ffffff', svColor:'#00ff00', category:'nonDrivable', visible:false} }; let _directions = { twoWay: {val:3}, oneWayAB: {val:1}, oneWayBA: {val:2}, unknown: {val:0} }; let UpdateObject, AddOrGetCity, AddOrGetStreet, MultiAction; function log(message, level) { if (message && level <= _debugLevel) { console.log('ClickSaver: ' + message); } } function isChecked(checkboxId) { return $('#' + checkboxId).is(':checked'); } function setChecked(checkboxId, checked) { $('#' + checkboxId).prop('checked', checked); } function loadSettingsFromStorage() { let loadedSettings = $.parseJSON(localStorage.getItem(_settingsStoreName)); let defaultSettings = { lastVersion: null, roadButtons: true, roadTypeButtons: ['St','PS','mH','MH','Fw','Rmp','PLR','PR'], lockButtons: true, elevationButtons: true, directionButtons: true, routingTypeButtons: true, parkingCostButtons: true, parkingSpacesButtons: true, setNewPLRStreetToNone: true, setNewPLRCity: true, addAltCityButton: true, useOldRoadColors: false }; _settings = loadedSettings ? loadedSettings : defaultSettings; for (let prop in defaultSettings) { if (!_settings.hasOwnProperty(prop)) { _settings[prop] = defaultSettings[prop]; } } setChecked('csRoadTypeButtonsCheckBox', _settings.roadButtons); if (_settings.roadTypeButtons) { for (let roadTypeAbbr1 in _roadTypes) { setChecked('cs' + roadTypeAbbr1 + 'CheckBox', _settings.roadTypeButtons.indexOf(roadTypeAbbr1) !== -1); } } if (_settings.roadButtons) { $('.csRoadTypeButtonsCheckBoxContainer').show(); } else { $('.csRoadTypeButtonsCheckBoxContainer').hide(); } setChecked('csLockButtonsCheckBox', _settings.lockButtons); setChecked('csElevationButtonsCheckBox', _settings.elevationButtons); setChecked('csDirectionButtonsCheckBox', _settings.directionButtons); setChecked('csParkingSpacesButtonsCheckBox', _settings.parkingSpacesButtons); setChecked('csParkingCostButtonsCheckBox', _settings.parkingCostButtons); setChecked('csRoutingTypeCheckBox', _settings.routingTypeButtons); setChecked('csClearNewPLRCheckBox', _settings.setNewPLRStreetToNone); setChecked('csUseOldRoadColorsCheckBox', _settings.useOldRoadColors); setChecked('csSetNewPLRCityCheckBox', _settings.setNewPLRCity); setChecked('csAddAltCityButtonCheckBox', _settings.addAltCityButton); } function saveSettingsToStorage() { if (localStorage) { let settings = { lastVersion: argsObject.scriptVersion, roadButtons: _settings.roadButtons, lockButtons: _settings.lockButtons, elevationButtons: _settings.elevationButtons, directionButtons: _settings.directionButtons, parkingCostButtons: _settings.parkingCostButtons, parkingSpacesButtons: _settings.parkingSpacesButtons, setNewPLRStreetToNone: _settings.setNewPLRStreetToNone, useOldRoadColors: _settings.useOldRoadColors, setNewPLRCity: _settings.setNewPLRCity, addAltCityButton: _settings.addAltCityButton }; settings.roadTypeButtons = []; for (let roadTypeAbbr in _roadTypes) { if(_settings.roadTypeButtons.indexOf(roadTypeAbbr) !== -1) { settings.roadTypeButtons.push(roadTypeAbbr); } } localStorage.setItem(_settingsStoreName, JSON.stringify(settings)); log('Settings saved', 1); } } function getConnectedSegmentIDs(segmentID) { let IDs = []; let segment = W.model.segments.get(segmentID); [W.model.nodes.get(segment.attributes.fromNodeID), W.model.nodes.get(segment.attributes.toNodeID)].forEach(function(node) { if (node) { node.attributes.segIDs.forEach(function(segID) { if (segID !== segmentID) { IDs.push(segID); } }); } }); return IDs; } function getFirstConnectedStateID(startSegment) { let stateID = null; let nonMatches = []; let segmentIDsToSearch = [startSegment.attributes.id]; while (stateID === null && segmentIDsToSearch.length > 0) { let startSegmentID = segmentIDsToSearch.pop(); startSegment = W.model.segments.get(startSegmentID); let connectedSegmentIDs = getConnectedSegmentIDs(startSegmentID); for (let i=0;i<connectedSegmentIDs.length;i++) { let streetID = W.model.segments.get(connectedSegmentIDs[i]).attributes.primaryStreetID; if (streetID !== null && typeof(streetID) !== 'undefined') { let cityID = W.model.streets.get(streetID).cityID; stateID = W.model.cities.get(cityID).attributes.stateID; break; } } if (stateID === null) { nonMatches.push(startSegmentID); connectedSegmentIDs.forEach(function(segmentID) { if (nonMatches.indexOf(segmentID) === -1 && segmentIDsToSearch.indexOf(segmentID) === -1) { segmentIDsToSearch.push(segmentID); } }); } else { return stateID; } } return null; } function getFirstConnectedCityID(startSegment) { let cityID = null; let nonMatches = []; let segmentIDsToSearch = [startSegment.attributes.id]; while (cityID === null && segmentIDsToSearch.length > 0) { let startSegmentID = segmentIDsToSearch.pop(); startSegment = W.model.segments.get(startSegmentID); let connectedSegmentIDs = getConnectedSegmentIDs(startSegmentID); for (let i=0;i<connectedSegmentIDs.length;i++) { let streetID = W.model.segments.get(connectedSegmentIDs[i]).attributes.primaryStreetID; if (streetID !== null && typeof(streetID) !== 'undefined') { cityID = W.model.streets.get(streetID).cityID; break; } } if (cityID === null) { nonMatches.push(startSegmentID); connectedSegmentIDs.forEach(function(segmentID) { if (nonMatches.indexOf(segmentID) === -1 && segmentIDsToSearch.indexOf(segmentID) === -1) { segmentIDsToSearch.push(segmentID); } }); } else { return cityID; } } return null; } function getEmptyCity(stateID) { let emptyCity = null; W.model.cities.getObjectArray().forEach(function(city) { if (city.attributes.stateID === stateID && city.attributes.isEmpty) { emptyCity = city; } }); return emptyCity; } function getCity(cityID) { let cities = W.model.cities.getByIds([cityID]); return cities.length ? cities[0] : null; } function setStreetAndCity () { let segments = W.selectionManager.getSelectedFeatures(); let setCity = isChecked('csSetNewPLRCityCheckBox'); if (segments.length === 0 || segments[0].model.type !== 'segment') { return; } segments.forEach(function(segment) { let segModel = segment.model; if (segModel.attributes.primaryStreetID === null) { let stateID = getFirstConnectedStateID(segment.model); if (stateID) { let state = W.model.states.get(stateID); let country = W.model.countries.get(state.countryID); let m_action = new MultiAction(); let cityToSet; m_action.setModel(W.model); if (setCity) cityToSet = getCity(getFirstConnectedCityID(segment.model)); if (!cityToSet) cityToSet = getEmptyCity(state.id); if (!cityToSet) { let addCityAction = new AddOrGetCity(state, country, "", true); m_action.doSubAction(addCityAction); cityToSet = getEmptyCity(state.id); } let newStreet = {isEmpty:true, cityID:cityToSet.attributes.id}; let emptyStreet = W.model.streets.getByAttributes(newStreet)[0]; if (!emptyStreet) { let addStreetAction = new AddOrGetStreet("", cityToSet, true); m_action.doSubAction(addStreetAction); emptyStreet = W.model.streets.getByAttributes(newStreet)[0]; } let action3 = new UpdateObject(segModel, {primaryStreetID: emptyStreet.id}); m_action.doSubAction(action3); W.model.actionManager.add(m_action); } } }); } function onAddAltCityButtonClick() { $('.full-address').click(); $('.add-alt-street-btn').click(); $('.alt-street-block input.street-name').val($('input.street-name').first().val()).blur().change(); if ($('input.alt-address.empty-city').is(':checked')) $('input.alt-address.empty-city').click(); $('.alt-street-block input.city-name').last().val('').focus(); } function onRoadTypeButtonClick(roadTypeAbbr) { $(_roadTypeDropDownSelector).val(_roadTypes[roadTypeAbbr].val).change(); if (roadTypeAbbr === 'PLR' && isChecked('csClearNewPLRCheckBox') && require) { setStreetAndCity(); } } function addRoadTypeButtons() { let $dropDown = $(_roadTypeDropDownSelector); $('#csRoadTypeButtonsContainer').remove(); let $container = $('<div>',{id:'csRoadTypeButtonsContainer',class:'rth-btn-container'}); let $street = $('<div>', {id:'csStreetButtonContainer',class:'cs-rt-btn-container'}); let $highway = $('<div>', {id:'csHighwayButtonContainer',class:'cs-rt-btn-container'}); let $otherDrivable = $('<div>', {id:'csOtherDrivableButtonContainer',class:'cs-rt-btn-container'}); let $nonDrivable = $('<div>', {id:'csNonDrivableButtonContainer',class:'cs-rt-btn-container'}); let divs = {streets:$street, highways:$highway, otherDrivable:$otherDrivable, nonDrivable:$nonDrivable}; for (let roadTypeKey in _roadTypes) { if (_settings.roadTypeButtons.indexOf(roadTypeKey) !== -1) { let roadType = _roadTypes[roadTypeKey]; let $div = divs[roadType.category]; $div.append( $('<div>', {class:'btn btn-rth btn-rth-' + roadTypeKey + ($dropDown.attr('disabled') ? ' disabled' : '') + ' btn-positive',title:_trans.roadTypeButtons[roadTypeKey].title}) .text(_trans.roadTypeButtons[roadTypeKey].text) .prop('checked', roadType.visible) .data('key', roadTypeKey) .click(function() { onRoadTypeButtonClick($(this).data('key')); }) ); } } $container.append($street).append($highway).append($otherDrivable).append($nonDrivable); $dropDown.before($container); } function addRoutingTypeButtons() { let $dropDown = $(_routingTypeDropDownSelector); if ($dropDown.length > 0) { let options = $dropDown.children(); if (options.length === 3) { let buttonInfos = [ ['-1', options[0].value, options[0].text], [options[1].text, options[1].value, ''], ['+1', options[2].value, options[2].text] ]; $('#csRoutingTypeContainer').remove(); let $form = $('<div>', {id:'csRoutingTypeContainer',style:'height:30px;padding-top:0px'}); for (let i=0; i<buttonInfos.length; i++) { let btnInfo = buttonInfos[i]; let $input = $('<input>', {type:'radio', name:'routingRoadType', id:'routingRoadType' + i, value:btnInfo[1]}) .click(function() { $(_routingTypeDropDownSelector).val($(this).attr('value')).change(); }); if (String(btnInfo[1]) === String($dropDown.val())) $input.prop('checked', 'true'); $form.append( $('<div class="controls-container" style="float: left; margin-right: 10px;margin-left:0px">').append( $input, $('<label>', {for:'routingRoadType' + i, style:'padding-left: 20px;', title:btnInfo[2]}).text(btnInfo[0]) ) ); } $dropDown.before($form); $dropDown.hide(); } } } function isPLA(item) { return (item.model.type === 'venue') && item.model.attributes.categories.indexOf('PARKING_LOT') > -1; } function addParkingSpacesButtons() { let $dropDown = $(_parkingSpacesDropDownSelector); let selItems = W.selectionManager.getSelectedFeatures(); let item = selItems[0]; let attr = item.model.attributes; // If it's not a PLA, exit. if (!isPLA(item)) return; $('#csParkingSpacesContainer').remove(); let $div = $('<div>',{id:'csParkingSpacesContainer'}); let dropdownDisabled = $dropDown.attr('disabled') === 'disabled'; let optionNodes = $(_parkingSpacesDropDownSelector + ' option'); let optionValues = []; for (i=0; i<optionNodes.length; i++) { let $option = $(optionNodes[i]); let text = $option.text(); let selected = $option.val() === $dropDown.val(); $div.append( $('<div>', { class:'btn waze-btn waze-btn-white' + (selected ? ' waze-btn-blue':'') + (dropdownDisabled ? ' disabled' : ''), style: 'margin-bottom: 5px; height: 22px; padding: 2px 8px 0px 8px; margin-right: 3px;' }) .text(text) .data('val',$option.val()) .hover(function() {}) .click(function() { if(!dropdownDisabled) { $(_parkingSpacesDropDownSelector).val($(this).data('val')).change(); addParkingSpacesButtons(); } }) ); } $dropDown.before($div); $dropDown.hide(); } function addParkingCostButtons() { let $dropDown = $(_parkingCostDropDownSelector); let selItems = W.selectionManager.getSelectedFeatures(); let item = selItems[0]; let attr = item.model.attributes; // If it's not a PLA, exit. if (!isPLA(item)) return; $('#csParkingCostContainer').remove(); let $div = $('<div>',{id:'csParkingCostContainer'}); let dropdownDisabled = $dropDown.attr('disabled') === 'disabled'; let optionNodes = $(_parkingCostDropDownSelector + ' option'); let optionValues = []; for (i=0; i<optionNodes.length; i++) { let $option = $(optionNodes[i]); let text = $option.text(); let selected = $option.val() === $dropDown.val(); $div.append( $('<div>', { class:'btn waze-btn waze-btn-white' + (selected ? ' waze-btn-blue':'') + (dropdownDisabled ? ' disabled' : ''), style: 'margin-bottom: 5px; height: 22px; padding: 2px 8px 0px 8px; margin-right: 4px;' }) .text(text !== '' ? text : '?') .data('val',$option.val()) .hover(function() {}) .click(function() { if(!dropdownDisabled) { $(_parkingCostDropDownSelector).val($(this).data('val')).change(); addParkingCostButtons(); } }) ); } $dropDown.before($div); $dropDown.hide(); } function addElevationButtons() { let id = 'csElevationButtonsContainer'; if ($('#' + id).length===0) { let $dropDown = $(_elevationDropDownSelector); let baseClass = 'btn waze-btn waze-btn-white' + ($dropDown.attr('disabled') ? ' disabled' : ''); let style = 'height: 20px;padding-left: 8px;padding-right: 8px;margin-right: 4px;padding-top: 1px;'; let $div = $('<div>', {id:id, style:'margin-bottom: 5px;'}).append( $('<div>',{class:baseClass, style:style}).text('-').click(function() { let level = parseInt($(_elevationDropDownSelector).val()); if (level > -5) { $(_elevationDropDownSelector).val(level - 1).change(); } }) ).append( $('<div>',{class:baseClass, style:style}).text(_trans.groundButtonText) .click(function() { let level = parseInt($(_elevationDropDownSelector).val()); if (level !== 0) { $(_elevationDropDownSelector).val(0).change(); } }) ).append( $('<div>',{class:baseClass, style:style}).text('+').click(function() { let level = parseInt($(_elevationDropDownSelector).val()); if (level < 9) { $(_elevationDropDownSelector).val(level + 1).change(); } }) ); $dropDown.css({display:'inline-block',width:'120px',marginRight:'10px'}); $dropDown.before($div); $dropDown.detach(); $div.prepend($dropDown); } } function addAddAltCityButton() { let id = 'csAddAltCityButton'; if (W.selectionManager.getSelectedFeatures()[0].model.type === 'segment' && $('#' + id).length === 0) { $('label.control-label').filter(function() { return $(this).text() === 'Address'; }).append( $('<a>', {href:'#',style:'float: right;text-transform: none;font-family: "Helvetica Neue", Helvetica, "Open Sans", sans-serif;color: #26bae8;font-weight: normal;'}).text('Add alt city').click(onAddAltCityButtonClick) ); } } function showScriptInfoAlert() { /* Check version and alert on update */ if (_alertUpdate && argsObject.scriptVersion !== _lastScriptVersion) { alert(_scriptVersionChanges); } } function shadeColor2(color, percent) { let f=parseInt(color.slice(1),16),t=percent<0?0:255,p=percent<0?percent*-1:percent,R=f>>16,G=f>>8&0x00FF,B=f&0x0000FF; return '#'+(0x1000000+(Math.round((t-R)*p)+R)*0x10000+(Math.round((t-G)*p)+G)*0x100+(Math.round((t-B)*p)+B)).toString(16).slice(1); } function buildRoadTypeButtonCss() { let lines = []; let useOldColors = _settings.useOldRoadColors; for (let roadTypeAbbr in _roadTypes) { let roadType = _roadTypes[roadTypeAbbr]; let bgColor = useOldColors ? roadType.svColor : roadType.wmeColor; let output = '.rth-btn-container .btn-rth-' + roadTypeAbbr + ' {background-color:' + bgColor + ';box-shadow:0 2px ' + shadeColor2(bgColor, -0.5) + ';border-color:' + shadeColor2(bgColor,-0.15) + ';}'; output += ' .rth-btn-container .btn-rth-' + roadTypeAbbr + ':hover {background-color:' + shadeColor2(bgColor,0.2) + '}'; lines.push(output); } return lines.join(' '); } function injectCss() { let css = [ // Road type button formatting '.csRoadTypeButtonsCheckBoxContainer {margin-left:15px;}', '.rth-btn-container {margin-bottom:5px;}', '.rth-btn-container .btn-rth {font-size:11px;line-height:20px;color:black;padding:0px 4px;height:20px;margin-right:2px;border-style:solid;border-width:1px;}', buildRoadTypeButtonCss(), '.btn.btn-rth:active {box-shadow:none;transform:translateY(2px)}', 'div .cs-rt-btn-container {float:left; margin: 0px 5px 5px 0px;}', '#sidepanel-clicksaver .controls-container {padding:0px;}', // Lock button formatting '.btn-lh {cursor:pointer;padding:1px 6px;height:22px;border:solid 1px #c1c1c1;margin-right:3px;}', '.btn.btn-lh.btn-lh-selected {background-color:#6999ae;color:white}', '.btn.btn-lh.btn-lh-selected:hover {color:white}', '.btn.btn-lh.disabled {color:#909090;background-color:#f7f7f7;}', '.btn.btn-lh.btn-lh-selected.disabled {color:white;background-color:#6999ae;}', '.cs-group-label {font-size: 11px; width: 100%; font-family: Poppins, sans-serif; text-transform: uppercase; font-weight: 700; color: #354148; margin-bottom: 6px;}' ].join(' '); $('<style type="text/css">' + css + '</style>').appendTo('head'); } function onModeChanged(model, modeId, context) { if(!modeId || modeId === 1) { initUserPanel(); loadSettingsFromStorage(); } } // function createSettingRadio(settingName, groupName, groupLabel, buttonMetas) { // let $container = $('<div>',{class:'controls-container'}); // $('<input>', {type:'checkbox', class:'csSettingsCheckBox', id:groupName, 'data-setting-name':groupName}).appendTo($container); // $('<label>', {for:groupName}).text(groupLabel).css({marginRight:'10px'}).appendTo($container); // buttonMetas.forEach(function(meta) { // let $input = $('<input>', {type:'radio', class:'csSettingsCheckBox', name:groupName, id:meta.id, 'data-setting-name':groupName}).css({marginLeft:'5px'}).appendTo($container); // let $label = $('<label>', {for:meta.id}).text(meta.labelText).appendTo($container); // }); // return $container; // } function createSettingsCheckbox(id, settingName, labelText, titleText, divCss, labelCss, optionalAttributes) { let $container = $('<div>',{class:'controls-container'}); let $input = $('<input>', {type:'checkbox',class:'csSettingsCheckBox',name:id, id:id, 'data-setting-name':settingName}).appendTo($container); let $label = $('<label>', {for:id}).text(labelText).appendTo($container); if (divCss) $container.css(divCss); if (labelCss) $label.css(labelCss); if (titleText) $container.attr({title:titleText}); if (optionalAttributes) $input.attr(optionalAttributes); return $container; } function initUserPanel() { let $roadTypesDiv = $('<div>', {class:'csRoadTypeButtonsCheckBoxContainer'}); $roadTypesDiv.append( createSettingsCheckbox('csUseOldRoadColorsCheckBox', 'useOldRoadColors', _trans.prefs.useOldRoadColors) ); for (let roadTypeAbbr in _roadTypes) { let roadType = _roadTypes[roadTypeAbbr]; let id = 'cs' + roadTypeAbbr + 'CheckBox'; $roadTypesDiv.append( createSettingsCheckbox(id, 'roadType', roadType.title, null, null, null, {'data-road-type':roadTypeAbbr}) ); if (roadTypeAbbr === 'PLR') { $roadTypesDiv.append( createSettingsCheckbox('csClearNewPLRCheckBox', 'setNewPLRStreetToNone', _trans.prefs.setStreetCityToNone, _trans.prefs.setStreetCityToNone_Title, {paddingLeft:'20px', display:'inline', marginRight:'4px'}, {fontStyle:'italic'}), createSettingsCheckbox('csSetNewPLRCityCheckBox', 'setNewPLRCity', _trans.prefs.setCityToConnectedSegCity, '', {paddingLeft:'30px', marginRight:'4px'}, {fontStyle:'italic'}) //$('<select style="height:24px;" disabled><option>None</option><option>Closest Segmet</option></select>') ); } } let $tab = $('<li>',{title:argsObject.scriptName}).append( $('<a>', {'data-toggle':'tab', href:'#sidepanel-clicksaver'}).append($('<span>').text('CS')) ); let $panel = $('<div>', {class:'tab-pane', id:'sidepanel-clicksaver'}) .append( $('<div>', {class:'side-panel-section>'}).append( $('<div>', {style: 'margin-bottom:8px;'}).append( $('<div>', {class:'form-group'}).append( $('<label>', {class:'cs-group-label'}).text(_trans.prefs.dropdownHelperGroup), $('<div>').append( createSettingsCheckbox('csRoadTypeButtonsCheckBox', 'roadButtons', _trans.prefs.roadTypeButtons) ).append( $roadTypesDiv ), createSettingsCheckbox('csRoutingTypeCheckBox', 'routingTypeButtons', _trans.prefs.routingTypeButtons), createSettingsCheckbox('csElevationButtonsCheckBox', 'elevationButtons', _trans.prefs.elevationButtons), createSettingsCheckbox('csParkingCostButtonsCheckBox', 'parkingCostButtons', _trans.prefs.parkingCostButtons), createSettingsCheckbox('csParkingSpacesButtonsCheckBox', 'parkingSpacesButtons', _trans.prefs.parkingSpacesButtons) ), $('<label>', {class:'cs-group-label'}).text('Time Savers'), $('<div>', {style:'margin-bottom:8px;'}).append( createSettingsCheckbox('csAddAltCityButtonCheckBox', 'addAltCityButton', 'Show "Add Alt City" button') ) ) ) ); $panel.append( $('<div>',{style:'margin-top:20px;font-size:10px;color:#999999;'}) .append($('<div>').text('version ' + argsObject.scriptVersion + (argsObject.scriptName.toLowerCase().indexOf('beta') > -1 ? ' beta' : ''))) .append( $('<div>').append( $('<a>',{href:'https://www.waze.com/forum/viewtopic.php?f=819&t=199894', target:'__blank'}).text(_trans.prefs.discussionForumLinkText) ) ) ); $('#user-tabs > .nav-tabs').append($tab); $('#user-info > .flex-parent > .tab-content').append($panel); // Add change events $('#csRoadTypeButtonsCheckBox').change(function() { if(this.checked) { $('.csRoadTypeButtonsCheckBoxContainer').show(); } else { $('.csRoadTypeButtonsCheckBoxContainer').hide(); } saveSettingsToStorage(); }); $('.csSettingsCheckBox').change(function() { let checked = this.checked; let settingName = $(this).data('setting-name'); if (settingName === 'roadType') { let roadType = $(this).data('road-type'); let array = _settings.roadTypeButtons; let index = array.indexOf(roadType); if(checked && index === -1) { array.push(roadType); } else if (!checked && index !== -1) { array.splice(index, 1); } } else { _settings[settingName] = checked; } saveSettingsToStorage(); }); } function updateControls() { if($(_roadTypeDropDownSelector).length>0) { if(isChecked('csRoadTypeButtonsCheckBox')) addRoadTypeButtons(); } if($(_routingTypeDropDownSelector && isChecked('csRoutingTypeCheckBox')).length>0) { addRoutingTypeButtons(); } if ($(_elevationDropDownSelector).length>0 && isChecked('csElevationButtonsCheckBox')) { addElevationButtons(); } if ($(_parkingSpacesDropDownSelector).length>0 && isChecked('csParkingSpacesButtonsCheckBox')) { addParkingSpacesButtons(); // TODO - add option setting } if ($(_parkingCostDropDownSelector).length>0 && isChecked('csParkingCostButtonsCheckBox')) { addParkingCostButtons(); // TODO - add option setting } } function replaceWord(target, searchWord, replaceWithWord) { return target.replace(new RegExp('\\b' + searchWord + '\\b','g'), replaceWithWord); } function titleCase(word) { return word.charAt(0).toUpperCase() + word.substring(1).toLowerCase(); } function mcCase(word) { return word.charAt(0).toUpperCase() + word.charAt(1).toLowerCase() + word.charAt(2).toUpperCase() + word.substring(3).toLowerCase(); } function upperCase(word) { return word.toUpperCase(); } function processSubstring(target, substringRegex, processFunction) { let substrings = target.match(substringRegex); if (substrings) { for (let idx=0; idx<substrings.length; idx++) { let substring = substrings[idx]; let newSubstring = processFunction(substring); target = replaceWord(target, substring, newSubstring); } } return target; } function onPaste(e) { let targetNode = e.target; if (targetNode.name === 'streetName' || targetNode.className.indexOf('street-name') > -1) { // Get the text that's being pasted. let pastedText = e.clipboardData.getData('text/plain'); // If pasting text in ALL CAPS... if (/^[^a-z]*$/.test(pastedText)) { [ // Title case all words first. [/\b[a-zA-Z]+(?:'S)?\b/g, titleCase], // Then process special cases. [/\bMC\w+\b/ig, mcCase], // e.g. McCaulley [/\b(?:I|US|SH|SR|CH|CR|CS|PR|PS)\s*-?\s*\d+\w*\b/ig, upperCase], // e.g. US-25, US25 [/\b(?:AL|AK|AS|AZ|AR|CA|CO|CT|DE|DC|FM|FL|GA|GU|HI|ID|IL|IN|IA|KS|KY|LA|ME|MH|MD|MA|MI|MN|MS|MO|MT|NE|NV|NH|NJ|NM|NY|NC|ND|MP|OH|OK|OR|PW|PA|PR|RI|SC|SD|TN|TX|UT|VT|VI|VA|WA|WV|WI|WY)\s*-?\s*\d+\w*\b/ig, upperCase], // e.g. WV-52 [/\b(?:NE|NW|SE|SW)\b/ig, upperCase] ].forEach(function(item) { pastedText = processSubstring(pastedText,item[0],item[1]); }); // Insert new text in the focused node. document.execCommand('insertText', false, pastedText); // Prevent the default paste behavior. e.preventDefault(); return false; } } return true; } function getTranslationObject() { if (argsObject.useDefaultTranslation) { return DEFAULT_TRANSLATION; } else { let locale = I18n.currentLocale().toLowerCase(); if (!argsObject.translations.hasOwnProperty(locale)) { locale = 'en-us'; } return argsObject.translations[locale]; } } function errorHandler(callback) { try { callback(); } catch (ex) { console.error(argsObject.scriptName + ':', ex); } } function init() { _trans = getTranslationObject(); for (let rtName in _roadTypes) { _roadTypes[rtName].title = _trans.roadTypeButtons[rtName].title; _roadTypes[rtName].text = _trans.roadTypeButtons[rtName].text; } for (let d in _directions) { _directions[d].text = _trans.directionButtons[d].text; _directions[d].title = _trans.directionButtons[d].title; } document.addEventListener('paste', onPaste); _lastScriptVersion = localStorage.getItem('wmeClickSaver_lastVersion'); localStorage.setItem('wmeClickSaver_lastVersion', argsObject.scriptVersion); showScriptInfoAlert(); // check for changes in the edit-panel let observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { for (let i = 0; i < mutation.addedNodes.length; i++) { let addedNode = mutation.addedNodes[i]; if (addedNode.nodeType === Node.ELEMENT_NODE) { if(addedNode.querySelector(_roadTypeDropDownSelector)) { if(isChecked('csRoadTypeButtonsCheckBox')) addRoadTypeButtons(); } if(addedNode.querySelector(_routingTypeDropDownSelector) && isChecked('csRoutingTypeCheckBox')) { addRoutingTypeButtons(); } if (addedNode.querySelector(_elevationDropDownSelector) && isChecked('csElevationButtonsCheckBox')) { addElevationButtons(); } if (addedNode.querySelector(_parkingSpacesDropDownSelector) && isChecked('csParkingSpacesButtonsCheckBox')) { addParkingSpacesButtons(); // TODO - add option setting } if (addedNode.querySelector(_parkingCostDropDownSelector) && isChecked('csParkingCostButtonsCheckBox')) { addParkingCostButtons(); // TODO - add option setting } if ($(addedNode).find('label').filter(function() { return $(this).text() === 'Address'; }).length && isChecked('csAddAltCityButtonCheckBox')) { addAddAltCityButton(); } } } }); }); observer.observe(document.getElementById('edit-panel'), { childList: true, subtree: true }); initUserPanel(); loadSettingsFromStorage(); injectCss(); W.app.modeController.model.bind('change:mode', () => errorHandler(onModeChanged)); W.prefs.on('change:isImperial', () => errorHandler(function() {initUserPanel();loadSettingsFromStorage();})); updateControls(); // In case of PL w/ segments selected. W.selectionManager.events.register('selectionchanged', null, () => errorHandler(updateControls)); if (typeof(require) !== 'undefined') { UpdateObject = require('Waze/Action/UpdateObject'); AddOrGetCity = require('Waze/Action/AddOrGetCity'); AddOrGetStreet = require('Waze/Action/AddOrGetStreet'); MultiAction = require('Waze/Action/MultiAction'); } log('Initialized', 1); } function bootstrap() { if (window.require && W && W.loginManager && W.loginManager.events.register && W.map && W.loginManager.isLoggedIn()) { log('Initializing...', 1); init(); } else { log('Bootstrap failed. Trying again...', 1); setTimeout(function () { bootstrap(); }, 250); } } let DEFAULT_TRANSLATION = { "roadTypeButtons":{ "St":{"title":"Street","text":"St"}, "PS":{"title":"Primary Street","text":"PS"}, "mH":{"title":"Minor Highway","text":"mH"}, "MH":{"title":"Major Highway","text":"MH"}, "Fw":{"title":"Freeway","text":"Fw"}, "Rmp":{"title":"Ramp","text":"Rmp"}, "OR":{"title":"Off-road / Not Maintained","text":"OR"}, "PLR":{"title":"Parking Lot Road","text":"PLR"}, "PR":{"title":"Private Road","text":"PR"}, "Fer":{"title":"Ferry","text":"Fer"}, "WT":{"title":"Walking Trail (non-drivable)","text":"WT"}, "PB":{"title":"Pedestrian Boardwalk (non-drivable)","text":"PB"}, "Sw":{"title":"Stairway (non-drivable)","text":"Sw"}, "RR":{"title":"Railroad (non-drivable)","text":"RR"}, "RT":{"title":"Runway/Taxiway (non-drivable)","text":"RT"} }, "directionButtons":{ "twoWay":{"title":"Two way","text":"Two way"}, "oneWayAB":{"title":"One way (A → B)","text":"A → B"}, "oneWayBA":{"title":"One way (B → A)","text":"B → A"}, "unknown":{"title":"Unknown","text":"?"} }, "groundButtonText":"Ground", "autoLockButtonText":"Auto", "multiLockLevelWarning":"Multiple lock levels selected!", "prefs":{ "dropdownHelperGroup":"DROPDOWN HELPERS", "roadTypeButtons":"Add road type buttons", "useOldRoadColors":"Use old road colors (requires refresh)", "setStreetCityToNone":"Set Street/City to None (new PLR only)", "setStreetCityToNone_Title":"NOTE: Only works if connected directly or indirectly to a segment with State/Country already set.", "setCityToConnectedSegCity":"Set City to connected segment's City", "routingTypeButtons":"Add routing type buttons", "elevationButtons":"Add elevation buttons", "parkingCostButtons":"Add PLA cost buttons", "parkingSpacesButtons":"Add PLA estimated spaces buttons", "spaceSaversGroup":"SPACE SAVERS", "inlineRoadType":"Inline road type checkboxes", "avgSpeedCameras":"Hide Avg Speed Cameras", "inlineParkingStuff":"Inline parking/payment type checkboxes", "discussionForumLinkText":"Discussion Forum" } }; log('Bootstrap...', 1); bootstrap(); //--------------------------------------------------------------------------------------------- // ==UserScript== // @name WMEQuickAltDel // @namespace http://tampermonkey.net/ // @version 0.0.2 // @description try to take over the world! // @author Jonathan Angliss (modifications by MapOMatic) // @include /^https:\/\/(www|beta)\.waze\.com\/(?!user\/)(.{2,6}\/)?editor\/.*$/ // @grant none // ==/UserScript== (function() { 'use strict'; let UpdateObject; function WMEaltStreet_Remove( elemClicked ) { let altID = parseInt($(elemClicked.currentTarget).data('id')); let selectedObjs = W.selectionManager.getSelectedFeatures(); selectedObjs.forEach(function(element) { if (element.model.type === 'segment') { let segment = element.model; if (segment.attributes.streetIDs.indexOf(altID) !== -1) { let newStreets = []; segment.attributes.streetIDs.forEach(function(sID) { if (altID !== sID) { newStreets.push(sID); } }); let sUpdate = new UpdateObject(segment, {streetIDs: newStreets}); W.model.actionManager.add(sUpdate); updateAltStreetCtrls(); } } }); } function bootstrap_WMEQuickAltDel() { if (window.require && W && W.loginManager && W.loginManager.events.register && W.map && W.loginManager.isLoggedIn()) { init_WMEQuickAltDel(); } else { setTimeout(function () { bootstrap_WMEQuickAltDel(); }, 250); } } function init_WMEQuickAltDel() { W.selectionManager.events.register("selectionchanged", null, () => errorHandler(updateAltStreetCtrls)); W.model.actionManager.events.register("afterundoaction",null, () => errorHandler(updateAltStreetCtrls)); W.model.actionManager.events.register("hasActions",null, () => errorHandler(()=>setTimeout(updateAltStreetCtrls, 250))); W.model.actionManager.events.register("noActions",null, () => errorHandler(()=>setTimeout(updateAltStreetCtrls, 250))); W.model.actionManager.events.register("afteraction",null, () => errorHandler(updateAltStreetCtrls)); if (typeof(require) !== "undefined") { UpdateObject = require("Waze/Action/UpdateObject"); } let observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { if ($(mutation.target).hasClass('preview')) updateAltStreetCtrls(); }); }); observer.observe(document.getElementById('edit-panel'), { childList: true, subtree: true }); } function updateAltStreetCtrls() { if (W.selectionManager.getSelectedFeatures().length > 0) { let selItems = W.selectionManager.getSelectedFeatures(); if (selItems.length > 0 && selItems[0].model.type === 'segment') { let $idElements = $('.add-alt-street-form .alt-street'); let $liElements = $('li.alt-street'); for (let i = 0; i < $idElements.length; i++) { let $idElem = $idElements.eq(i); let $liElem = $liElements.eq(i); if($liElem.find('i').length === 0){//prevent duplicate entries $liElem.append( $('<i>', {class:'fa fa-times-circle'}).css({cursor:'pointer'}).data('id', $idElem.data('id')).click(WMEaltStreet_Remove) ); } } } } } bootstrap_WMEQuickAltDel(); })(); } function injectMain(argsObject) { let scriptElem = document.createElement("script"); scriptElem.textContent = '(function(){' + main.toString() + "\n main(" + JSON.stringify(argsObject).replace("'","\\'") + ")})();"; scriptElem.setAttribute("type", "application/javascript"); document.body.appendChild(scriptElem); } function setValue(object, path, value) { let pathParts = path.split('.'); for (let i = 0; i < pathParts.length - 1; i++) { let pathPart = pathParts[i]; if (pathPart in object) { object = object[pathPart]; } else { object[pathPart] = {}; object = object[pathPart]; } } object[pathParts[pathParts.length - 1]] = value; } function convertTranslationsArrayToObject(arrayIn) { let translations = {}; let iRow, iCol; let languages = arrayIn[0].map(function(lang) { return lang.toLowerCase(); }); for (iCol=1; iCol<languages.length; iCol++) { translations[languages[iCol]] = {}; } for (iRow=1; iRow<arrayIn.length; iRow++) { let row = arrayIn[iRow]; let propertyPath = row[0]; for (iCol=1; iCol<row.length; iCol++) { setValue(translations[languages[iCol]], propertyPath, row[iCol]); } } return translations; } GM_xmlhttpRequest({ url: 'https://docs.google.com/spreadsheets/d/1ZlE9yhNncP9iZrPzFFa-FCtYuK58wNOEcmKqng4sH1M/pub?gid=0&single=true&output=tsv', method: 'GET', overrideMimeType: 'text/csv', onload: function(res) { let args; if (res.status === 200) { let translationsArray = res.responseText.split(/\r?\n/).map(function(t) { return t.split(/\t/); }); args = { scriptName: GM_info.script.name, scriptVersion: GM_info.script.version, translations: convertTranslationsArrayToObject(translationsArray) }; } else { args = { scriptName: GM_info.script.name, scriptVersion: GM_info.script.version, useDefaultTranslation: true }; } injectMain(args); }, onerror: function() { injectMain({ scriptName: GM_info.script.name, scriptVersion: GM_info.script.version, useDefaultTranslation: true }); } }); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址