您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds options to LiveMap to alter the Waze-suggested routes.
当前为
// ==UserScript== // @name Waze LiveMap Options // @namespace WazeDev // @version 2017.12.22.002 // @description Adds options to LiveMap to alter the Waze-suggested routes. // @author MapOMatic // @include /^https:\/\/www.waze.com\/livemap/ // @license GNU GPL v3 // ==/UserScript== /* global W */ /* global Node */ (function() { 'use strict'; var EXPANDED_MAX_HEIGHT = '200px'; var _settings = { 'lmo-tolls': {checked:false}, 'lmo-freeways': {checked:false}, 'lmo-ferries': {checked:false}, 'lmo-difficult-turns':{checked:false}, 'lmo-unpaved-roads': {checked:true}, 'lmo-long-unpaved-roads': {checked:false}, 'lmo-u-turns':{checked:false, opposite:true}, 'lmo-hov':{checked:false, opposite:true}, 'lmo-real-time-traffic':{checked:true}, 'lmo-hide-traffic':{checked:false}, 'lmo-day': 'today', 'lmo-hour': 'now', collapsed: false }; // Store the onAfterItemAdded function. It is removed and re-added, to prevent the // LiveMap api from moving the map to the boundaries of the routes every time // an option is checked. var _onAfterItemAdded = W.controller._routePaths.onAfterItemAdded; function checked(id, optionalSetTo) { var $elem = $('#' + id); if (typeof optionalSetTo !== 'undefined') { $elem.prop('checked', optionalSetTo); } else { return $elem.prop('checked'); } } function getDateTimeOffset() { var hour = $('#lmo-hour').val(); var day = $('#lmo-day').val(); if (hour === '---') hour = 'now'; if (day === '---') day = 'today'; if (hour === '') hour = 'now'; if (day === '') day = 'today'; var t = new Date(); var thour = (t.getHours() * 60) + t.getMinutes(); var tnow = (t.getDay() * 1440) + thour; var tsel = tnow; if (hour === 'now') { if (day === "0") tsel = (parseInt(day) * 1440) + thour; if (day === "1") tsel = (parseInt(day) * 1440) + thour; if (day === "2") tsel = (parseInt(day) * 1440) + thour; if (day === "3") tsel = (parseInt(day) * 1440) + thour; if (day === "4") tsel = (parseInt(day) * 1440) + thour; if (day === "5") tsel = (parseInt(day) * 1440) + thour; if (day === "6") tsel = (parseInt(day) * 1440) + thour; } else { if (day === "today") tsel = (t.getDay() * 1440) + parseInt(hour); if (day === "0") tsel = (parseInt(day) * 1440) + parseInt(hour); if (day === "1") tsel = (parseInt(day) * 1440) + parseInt(hour); if (day === "2") tsel = (parseInt(day) * 1440) + parseInt(hour); if (day === "3") tsel = (parseInt(day) * 1440) + parseInt(hour); if (day === "4") tsel = (parseInt(day) * 1440) + parseInt(hour); if (day === "5") tsel = (parseInt(day) * 1440) + parseInt(hour); if (day === "6") tsel = (parseInt(day) * 1440) + parseInt(hour); } var diff = tsel - tnow; if (diff < -3.5 * 1440) diff += 7 * 1440; else if (diff > 3.5 * 1440) diff -= 7 * 1440; return diff; } function updateTimes() { var realTimeTraffic = checked('lmo-real-time-traffic'); var $routeTimes = $('.routes .route-time'); for (var idx=0; idx<$routeTimes.length; idx++) { var time = getRouteTime(idx, realTimeTraffic); var $routeTime = $routeTimes.eq(idx); var contents = $routeTime.contents(); contents[contents.length-1].remove(); $routeTime.append(' ' + time); } } function fetchRoutes() { var routeSearch = W.controller._routeSearch; if (routeSearch.to.address.attributes.latlng && routeSearch.from.address.attributes.latlng) {//($('div#origin input.query').val() && $('div#destination input.query').val()) { $('.lmo-control').prop('disabled',true); // HACK - Temporarily remove the onAfterItemAdded function, to prevent map from moving. W.controller._routePaths.onAfterItemAdded = null; routeSearch.fetchRoutes(); } } function addOptions() { if (!$('#lmo-table').length) { $('.search-forms').after( $('<div>', {class:'lmo-options-header'}).append( $('<span>').text('Change routing options'), $('<i>', {class:'fa fa.fa-angle-down fa.fa-angle-up'}).addClass(_settings.collapsed ? 'fa-angle-down' : 'fa-angle-up') ), $('<div>', {class: 'lmo-options-container'}).css({maxHeight:_settings.collapsed ? '0px' : EXPANDED_MAX_HEIGHT}).append( $('<table>', {class: 'lmo-table'}).append( [['Avoid:',['Tolls','Freeways','Ferries','HOV','Unpaved roads','Long unpaved roads','Difficult turns','U-Turns']], ['Options:',['Real-time traffic','Hide traffic']]].map(rowItems => { var rowID = rowItems[0].toLowerCase().replace(/[ :]/g,''); return $('<tr>', {id:'lmo-row-' + rowID}).append( $('<td>').append($('<span>', {id:'lmo-header-' + rowID, class:'lmo-table-header-text'}).text(rowItems[0])), $('<td>', {class: 'lmo-settings-cell'}).append( rowItems[1].map((text) => { var idName = text.toLowerCase().replace(/ /g, '-'); var id = 'lmo-' + idName; return $('<span>', {class:'lmo-control-container'}).append( $('<input>', {id:id, type:'checkbox', class:'lmo-control'}).prop('checked',_settings[id].checked), $('<label>', {for:id}).text(text) ); }) ) ); }) ) ) ); $('#lmo-header-avoid').css({color:'#c55'}); $('label[for="lmo-u-turns"').attr('title','Note: this is not an available setting in the app'); var timeArray = [['Now','now']]; for (var i=0; i<48; i++) { var t = i * 30; var min = t % 60; var hr = Math.floor(t / 60); var str = (hr < 10 ? ('0') : '') + hr + ':' + (min === 0 ? '00' : min); timeArray.push([str, t.toString()]); } $('#lmo-row-options td.lmo-settings-cell').append( $('<div>').append( $('<label>', {for:'lmo-day', style:'font-weight: normal;'}).text('Day'), $('<select>', {id: 'lmo-day', class:'lmo-control', style:'margin-left: 4px; margin-right: 8px; padding: 0px; height: 22px;'}).append( [ ['Today','today'], ['Monday','1'], ['Tuesday','2'], ['Wednesday','3'], ['Thursday','4'], ['Friday','5'], ['Saturday','6'], ['Sunday','0'] ].map(val => $('<option>', {value:val[1]}).text(val[0])) ), $('<label>', {for:'lmo-hour', style:'font-weight: normal;'}).text('Time'), $('<select>', {id: 'lmo-hour', class:'lmo-control', style:'margin-left: 4px; margin-right: 8px; padding: 0px; height: 22px;'}).append( timeArray.map(val => $('<option>', {value:val[1]}).text(val[0])) ) ) ); // Set up events $('.lmo-options-header').click(function() { var $container = $('.lmo-options-container'); var collapsed = $container.css('max-height') === '0px'; $('.lmo-options-header i').removeClass(collapsed ? 'fa-angle-down' : 'fa-angle-up').addClass(collapsed ? 'fa-angle-up' : 'fa-angle-down'); $container.css({maxHeight: collapsed ? EXPANDED_MAX_HEIGHT : '0px'}); _settings.collapsed = !collapsed; }); $('.lmo-control').change(function() { var id = this.id; if (id === 'lmo-hour' || id === 'lmo-day') { fetchRoutes(); } else { var isChecked = checked(id); _settings[id].checked = isChecked; if (id === 'lmo-real-time-traffic') { updateTimes(); } else if (id === 'lmo-hide-traffic') { W.controller._mapModel.features.enableJams(!isChecked); } else { if (id === 'lmo-long-unpaved-roads') { if (isChecked) { checked('lmo-unpaved-roads', false); _settings['lmo-unpaved-roads'].checked = false; } } else if (id === 'lmo-unpaved-roads') { if (isChecked) { checked('lmo-long-unpaved-roads', false); _settings['lmo-long-unpaved-roads'].checked = false; } } fetchRoutes(); } } }); } } var observer = new MutationObserver(mutations => { mutations.forEach(mutation => { for (var i = 0; i < mutation.addedNodes.length; i++) { var addedNode = mutation.addedNodes[i]; if (addedNode.nodeType === Node.ELEMENT_NODE){ var $addedNode = $(addedNode); if (addedNode.className === 'search-forms') { addOptions(); } else if ($addedNode.hasClass('route-info')) { updateTimes(); } else if ($addedNode.is('div.routing-time')) { $addedNode.remove(); } } } mutation.removedNodes.forEach(nd => { if ($(nd).hasClass('s-loading')) { $('.lmo-control').prop("disabled", false); W.controller._routePaths.onAfterItemAdded = _onAfterItemAdded; } }); }); }); observer.observe($('.leaflet-top')[0], { childList: true, subtree: true }); $('div.routing-time').remove(); addOptions(); function getRouteTime(routeIdx, realTimeTraffic) { var sec = 0; W.controller._routes.models[routeIdx].attributes.results.forEach(result => { sec += realTimeTraffic ? result.crossTime : result.crossTimeWithoutRealTime; }); var hours = Math.floor(sec/3600); sec -= hours * 3600; var min = Math.floor(sec/60); sec -= min * 60; return (hours > 0 ? hours + 'h ' : '') + (min > 0 ? min + 'm ' : '') + sec + 's'; } $.ajaxPrefilter(function(request, originalRequest, jqXHR) { if (originalRequest.url === '/RoutingManager/routingRequest') { // Remove all options from the request (everything after '&options=') var baseData = request.data.replace(request.data.match(/&options=(.*)/)[1],''); var options = []; [['tolls','AVOID_TOLL_ROADS'],['freeways','AVOID_PRIMARIES'],['ferries','AVOID_FERRIES'],['difficult-turns','AVOID_DANGEROUS_TURNS'],['u-turns','ALLOW_UTURNS'],['hov','ADD_HOV_ROUTES']].forEach(optionInfo => { var id = 'lmo-' + optionInfo[0]; var enableOption = checked(id); if (_settings[id].opposite) enableOption = !enableOption; options.push(optionInfo[1] + ':' + (enableOption ? 't' : 'f')); }); if (checked('lmo-long-unpaved-roads')) { options.push('AVOID_LONG_TRAILS:t'); } else if (checked('lmo-unpaved-roads')) { options.push('AVOID_TRAILS:t'); } else { options.push('AVOID_LONG_TRAILS:f'); } baseData = baseData.replace(/&at=0/,'&at=' + getDateTimeOffset()); request.data = baseData + encodeURIComponent(options.join(',')); } }); var transTime = '0.2s'; var css = [ '.lmo-options-header { margin-top: 4px; cursor: pointer; color: #59899e; font-size: 11px; font-weight: 600; }', '.lmo-options-header i { margin-left: 5px; }', '.lmo-options-container { max-height: 500px; overflow: hidden; transition: max-height ' + transTime + '; -moz-transition: max-height ' + transTime + '; -webkit-transition: max-height ' + transTime + '; -o-transition: max-height ' + transTime + '; }', '.lmo-table { margin-top: 4px; font-size: 12px; }', '.lmo-table td { padding: 4px 10px 0px 10px; }', '.lmo-table-header-text { margin: 0px; font-weight: 600; }', '.lmo-control-container { margin-right: 8px; }' ].join('\n'); $('head').append( $('<style>', {type:'text/css'}).html(css) ); })();