WME Mobile Support

A userscript that makes the WME more useable on mobile devices

当前为 2018-03-18 提交的版本,查看 最新版本

  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.0
  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, performScript);
  27. W.loginManager.events.register("loginStatus", null, performScript);
  28. }
  29. var viewportMeta = document.createElement('meta');
  30. viewportMeta.name = 'viewport';
  31. viewportMeta.content = 'width=device-width, initial-scale=1';
  32. document.head.appendChild(viewportMeta);
  33.  
  34. setModeChangeListener();
  35. performScript();
  36. }
  37.  
  38. // Attempt to hook into the controller that can notify us whenever the editor's mode changes
  39. function setModeChangeListener() {
  40. if (!W.app || !W.app.modeController) {
  41. setTimeout(setModeChangeListener, 400);
  42. return;
  43. }
  44. W.app.modeController.model.bind('change:mode', function(model, modeId) {
  45. if (modeId == 0) { // 0 = Default, 1 = Events
  46. performScript();
  47. }
  48. });
  49. }
  50.  
  51. function performScript() {
  52. if (!styleElement) {
  53. styleElement = document.createElement('style');
  54. styleElement.textContent = `@media screen and (max-width: 1000px) {
  55. /* Login dialog modifications */
  56. .modal-dialog-login { width: 100%; margin: 0 }
  57. .modal-dialog-login .modal-content { width: 350px }
  58. #login-popup { padding: 10px; width: auto }
  59. #login-popup .login-popup-content { display: block }
  60. #login-popup .login-form { padding: 15px; height: auto }
  61. .modal-dialog-login .login-title { font-size: 19px }
  62. .modal-open .edit-area > .fluid-fixed { width: 100%; height: 100vh }
  63. .modal-open #editor-container #WazeMap { height: calc(100vh - 46px) !important }
  64.  
  65. /* Hide a lot of stuff */
  66. .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 { display: none !important }
  67.  
  68. /* Set the default width to several objects so they don't stretch the page */
  69. #editor-container, #editor-container #map { min-width: auto }
  70.  
  71. /* Adjust the sidebar and map so they appear on top of eachother */
  72. @media (orientation: portrait) {
  73. .show-sidebar .row-fluid .fluid-fixed { width: 100%; margin-left: 0 }
  74. .row-fluid #sidebar { width: auto }
  75. .edit-area { display: flex; flex-direction: column-reverse }
  76. #editor-container #WazeMap { height: 40vh !important }
  77. #editor-container:before, .show-sidebar #map, .show-sidebar #map:after { border-radius: 0 }
  78. .toolbar .toolbar-icon { width: 30px }
  79. #edit-buttons .toolbar-button { padding: 0 5px }
  80. }
  81.  
  82. /* Adjust the sidebar and map so they share the space horizontally */
  83. @media (orientation: landscape) {
  84. .show-sidebar .row-fluid .fluid-fixed { width: calc(100% - 330px); min-width: 50%; margin-left: 0 }
  85. .row-fluid #sidebar { max-width: 50% }
  86. #sidebar .tab-scroll-gradient { width: 100%; margin-left: -15px }
  87. .edit-area { display: flex }
  88. }
  89.  
  90. /* Adjust toolbar */
  91. .toolbar #search { width: 50px; min-width: auto }
  92. #app-head aside #brand, .group-title { display: none }
  93. .toolbar .toolbar-icon { position: relative }
  94. #edit-buttons .toolbar-button .item-icon { display: block; top: 8px; position: relative }
  95. #edit-buttons .toolbar-button .menu-title { display: none }
  96. #edit-buttons { flex-grow: 1 }
  97. #edit-buttons .toolbar-submenu { margin-right: 0 }
  98. #toolbar .toolbar, #edit-buttons { min-width: auto }
  99.  
  100. /* Adjust map controls */
  101. #WazeMap .zoom-controls { position: absolute; bottom: 35px; right: 5px; z-index: 1000 }
  102. #WazeMap .zoom-controls button:first-child { position: absolute; bottom: 33px }
  103. #WazeMap .zoom-controls button { font-size: 1.3em }
  104. #WazeMap .full-screen { position: absolute; bottom: 115px; 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 zoomControls = document.createElement('div');
  133. zoomControls.classList.add('zoom-controls');
  134. var zoomInButton = document.createElement('button');
  135. zoomInButton.classList.add('fa', 'fa-plus');
  136. zoomInButton.addEventListener('click', function() {
  137. W.map.zoomIn();
  138. });
  139. zoomControls.appendChild(zoomInButton);
  140. var zoomOutButton = document.createElement('button');
  141. zoomOutButton.classList.add('fa', 'fa-minus');
  142. zoomOutButton.addEventListener('click', function() {
  143. W.map.zoomOut();
  144. });
  145. zoomControls.appendChild(zoomOutButton);
  146. document.querySelector('#WazeMap').appendChild(zoomControls);
  147.  
  148. var fullScreenButton = document.createElement('button');
  149. fullScreenButton.classList.add('full-screen', 'fa', 'fa-arrows-alt');
  150. fullScreenButton.addEventListener('click', function() {
  151. var docEl = window.document.documentElement;
  152. var requestFullScreen = docEl.requestFullscreen || docEl.mozRequestFullScreen || docEl.webkitRequestFullScreen || docEl.msRequestFullscreen;
  153. requestFullScreen.call(docEl);
  154. });
  155. document.querySelector('#WazeMap').appendChild(fullScreenButton);
  156. }
  157.  
  158. init();