WME Mobile Support

A userscript that makes the WME more useable on mobile devices

  1. // ==UserScript==
  2. // @name WME Mobile Support
  3. // @author Tom 'Glodenox' Puttemans
  4. // @namespace http://tomputtemans.com/
  5. // @description A userscript that makes the WME more useable on mobile devices
  6. // @include /^https:\/\/(www|beta)\.waze\.com\/(?!user\/)(.{2,6}\/)?editor.*$/
  7. // @version 0.3.6
  8. // @supportURL https://github.com/Glodenox/wme-mobile-support/issues
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. // Style element to reuse whenever it gets removed by the WME (user login, for example)
  13. var styleElement;
  14.  
  15. // Initialisation of the script, this will only run completely one time
  16. function init(e) {
  17. if (e && e.user == null) {
  18. return;
  19. }
  20. // if you require certain features to be loaded, you can add them here
  21. if (typeof I18n === 'undefined' || typeof W === 'undefined' || typeof W.loginManager === 'undefined') {
  22. setTimeout(init, 200);
  23. return;
  24. }
  25. if (!W.loginManager.user) {
  26. W.loginManager.events.register("login", null, applyStyles);
  27. W.loginManager.events.register("loginStatus", null, applyStyles);
  28. }
  29. var viewportMeta = document.createElement('meta');
  30. viewportMeta.name = 'viewport';
  31. viewportMeta.content = 'width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=0';
  32. document.head.appendChild(viewportMeta);
  33.  
  34. enableTouchEvents();
  35. //fixSelection(); // disabled as it doesn't really work as hoped
  36. applyStyles();
  37. }
  38.  
  39. // Add the missing OpenLayers classes for touch navigation and enable them
  40. function enableTouchEvents() {
  41. if (!OpenLayers.Control.PinchZoom) {
  42. OpenLayers.Control.PinchZoom=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_TOOL,containerCenter:null,pinchOrigin:null,currentCenter:null,autoActivate:!0,initialize:function(a){OpenLayers.Control.prototype.initialize.apply(this,arguments);this.handler=new OpenLayers.Handler.Pinch(this,{start:this.pinchStart,move:this.pinchMove,done:this.pinchDone},this.handlerOptions)},activate:function(){var a=OpenLayers.Control.prototype.activate.apply(this,arguments);a&&(this.map.events.on({moveend:this.updateContainerCenter,scope:this}),this.updateContainerCenter());return a},deactivate:function(){var a=OpenLayers.Control.prototype.deactivate.apply(this,arguments);this.map&&this.map.events&&this.map.events.un({moveend:this.updateContainerCenter,scope:this});return a},updateContainerCenter:function(){var a=this.map.layerContainerDiv;this.containerCenter={x:parseInt(a.style.left,10)+50,y:parseInt(a.style.top,10)+50}},pinchStart:function(a){this.currentCenter=this.pinchOrigin=a.xy},pinchMove:function(a,b){var c=b.scale,d=this.containerCenter,e=this.pinchOrigin,f=a.xy,g=Math.round(f.x-e.x+(c-1)*(d.x-e.x)),d=Math.round(f.y-e.y+(c-1)*(d.y-e.y));this.applyTransform("translate("+g+"px, "+d+"px) scale("+c+")");this.currentCenter=f},applyTransform:function(a){var b=this.map.layerContainerDiv.style;b["-webkit-transform"]=a;b["-moz-transform"]=a},pinchDone:function(a,b,c){this.applyTransform("");a=this.map.getZoomForResolution(this.map.getResolution()/c.scale,!0);if(a!==this.map.getZoom()||!this.currentCenter.equals(this.pinchOrigin)){var b=this.map.getResolutionForZoom(a),c=this.map.getLonLatFromPixel(this.pinchOrigin),d=this.currentCenter,e=this.map.getSize();c.lon+=b*(e.w/2-d.x);c.lat-=b*(e.h/2-d.y);this.map.div.clientWidth=this.map.div.clientWidth;this.map.setCenter(c,a)}},CLASS_NAME:"OpenLayers.Control.PinchZoom"});
  43. }
  44. if (!OpenLayers.Handler.Pinch) {
  45. OpenLayers.Handler.Pinch=OpenLayers.Class(OpenLayers.Handler,{started:!1,stopDown:!1,pinching:!1,last:null,start:null,touchstart:function(a){var b=!0;this.pinching=!1;OpenLayers.Event.isMultiTouch(a)?(this.started=!0,this.last=this.start={distance:this.getDistance(a.touches),delta:0,scale:1},this.callback("start",[a,this.start]),b=!this.stopDown):(this.started=!1,this.last=this.start=null);OpenLayers.Event.stop(a);return b},touchmove:function(a){if(this.started&&OpenLayers.Event.isMultiTouch(a)){this.pinching=!0;var b=this.getPinchData(a);this.callback("move",[a,b]);this.last=b;OpenLayers.Event.stop(a)}return!0},touchend:function(a){this.started&&(this.pinching=this.started=!1,this.callback("done",[a,this.start,this.last]),this.last=this.start=null);return!0},activate:function(){var a=!1;OpenLayers.Handler.prototype.activate.apply(this,arguments)&&(this.pinching=!1,a=!0);return a},deactivate:function(){var a=!1;OpenLayers.Handler.prototype.deactivate.apply(this,arguments)&&(this.pinching=this.started=!1,this.last=this.start=null,a=!0);return a},getDistance:function(a){var b=a[0],a=a[1];return Math.sqrt(Math.pow(b.clientX-a.clientX,2)+Math.pow(b.clientY-a.clientY,2))},getPinchData:function(a){a=this.getDistance(a.touches);return{distance:a,delta:this.last.distance-a,scale:a/this.start.distance}},CLASS_NAME:"OpenLayers.Handler.Pinch"});
  46. }
  47. W.map.navigationControl.pinchZoom = new OpenLayers.Control.PinchZoom({
  48. map: W.map
  49. });
  50. W.map.navigationControl.pinchZoom.activate();
  51. }
  52.  
  53. function applyStyles() {
  54. if (!styleElement) {
  55. styleElement = document.createElement('style');
  56. styleElement.textContent = `@media screen and (max-width: 1000px) {
  57. /* Login dialog modifications */
  58. .modal-dialog-login { width: 100%; margin: 0 }
  59. .modal-dialog-login .modal-content { width: 350px }
  60. #login-popup { padding: 10px; width: auto }
  61. #login-popup .login-popup-content { display: block }
  62. #login-popup .login-form { padding: 15px; height: auto }
  63. .modal-dialog-login .login-title { font-size: 19px }
  64. .modal-open .edit-area > .fluid-fixed { width: 100%; height: 100vh }
  65. .modal-open #editor-container #WazeMap { height: calc(100vh - 46px) !important }
  66.  
  67. /* Hide a lot of stuff */
  68. .login-popup-links, .language-select, .welcome-message p, .title-text, .topbar .area-managers-region, .olControlPanZoomBar, #links, #advanced-tools, .WazeControlMousePosition, #user-box, #chat-overlay, .google-permalink, .WazeControlPermalink { display: none !important }
  69.  
  70. /* Set the default width to several objects so they don't stretch the page */
  71. #editor-container, #editor-container #map { min-width: auto }
  72.  
  73. /* Adjust the sidebar and map so they appear on top of eachother */
  74. @media (orientation: portrait) {
  75. .show-sidebar .row-fluid .fluid-fixed { width: 100%; margin-left: 0 }
  76. .row-fluid #sidebar { width: auto }
  77. .edit-area { display: flex; flex-direction: column-reverse }
  78. #editor-container #WazeMap { height: 40vh !important }
  79. #editor-container:before, .show-sidebar #map, .show-sidebar #map:after { border-radius: 0 }
  80. .toolbar .toolbar-icon { width: 30px }
  81. #edit-buttons .toolbar-button { padding: 0 5px }
  82. .toolbar #edit-buttons .toolbar-button .item-container { padding: 0 5px }
  83. }
  84.  
  85. /* Adjust the sidebar and map so they share the space horizontally */
  86. @media (orientation: landscape) {
  87. .show-sidebar .row-fluid .fluid-fixed { width: calc(100% - 330px); min-width: 50%; margin-left: 0 }
  88. .row-fluid #sidebar { max-width: 50% }
  89. #sidebar .tab-scroll-gradient { width: 100%; margin-left: -15px }
  90. .edit-area { display: flex }
  91. }
  92.  
  93. /* Adjust toolbar */
  94. .toolbar #search { width: 50px; min-width: auto }
  95. #app-head aside #brand, .group-title { display: none }
  96. .toolbar .toolbar-icon { position: relative }
  97. #edit-buttons .toolbar-button .item-icon { display: block; top: 8px; position: relative }
  98. #edit-buttons .toolbar-button .menu-title { display: none }
  99. #edit-buttons { flex-grow: 1 }
  100. #edit-buttons .toolbar-submenu { margin-right: 0 }
  101. #toolbar .toolbar, #edit-buttons { min-width: auto }
  102.  
  103. /* Adjust map controls */
  104. #WazeMap .full-screen { position: absolute; bottom: 35px; right: 5px; z-index: 1000; font-size: 1.3em }
  105. }`;
  106. }
  107. if (!styleElement.parentNode) {
  108. document.head.appendChild(styleElement);
  109. }
  110.  
  111. var adjustToolbar = function() {
  112. if (!document.querySelector('#mode-switcher') || !document.querySelector('#edit-buttons')) {
  113. setTimeout(adjustToolbar, 100);
  114. return;
  115. }
  116. document.querySelector('#mode-switcher .short-title').textContent = 'Mode';
  117. var addStickyClasses = function(el, classes) {
  118. var observer = new MutationObserver(function() {
  119. el.querySelector('.item-icon').classList.add(...classes);
  120. });
  121. observer.observe(el, {
  122. childList: true
  123. });
  124. el.querySelector('.item-icon').classList.add(...classes);
  125. };
  126. addStickyClasses(document.querySelector('#edit-buttons .toolbar-button.waze-icon-save'), ['fa', 'fa-save']);
  127. addStickyClasses(document.querySelector('#edit-buttons .toolbar-button.waze-icon-redo'), ['fa', 'fa-chevron-right']);
  128. addStickyClasses(document.querySelector('#edit-buttons .toolbar-button.waze-icon-undo'), ['fa', 'fa-chevron-left']);
  129. };
  130. adjustToolbar();
  131.  
  132. var fullScreenButton = document.createElement('button');
  133. fullScreenButton.classList.add('full-screen', 'fa', 'fa-arrows-alt');
  134. fullScreenButton.addEventListener('click', function() {
  135. var docEl = document.documentElement;
  136. var requestFullScreen = docEl.requestFullscreen || docEl.mozRequestFullScreen || docEl.webkitRequestFullScreen || docEl.msRequestFullscreen;
  137. var cancelFullScreen = document.exitFullscreen || document.mozCancelFullScreen || document.webkitExitFullscreen || document.msExitFullscreen;
  138. if (!document.fullscreenElement && !document.mozFullScreenElement && !document.webkitFullscreenElement && !document.msFullscreenElement) {
  139. requestFullScreen.call(docEl);
  140. } else {
  141. cancelFullScreen.call(document);
  142. }
  143. });
  144. document.querySelector('#WazeMap').appendChild(fullScreenButton);
  145. }
  146.  
  147. init();

QingJ © 2025

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