TISWAS

Lists all turn instructions defined within the current map view

K instalaci tototo skriptu si budete muset nainstalovat rozšíření jako Tampermonkey, Greasemonkey nebo Violentmonkey.

You will need to install an extension such as Tampermonkey to install this script.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Userscripts.

You will need to install an extension such as Tampermonkey to install this script.

K instalaci tohoto skriptu si budete muset nainstalovat manažer uživatelských skriptů.

(Už mám manažer uživatelských skriptů, nechte mě ho nainstalovat!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Už mám manažer uživatelských stylů, nechte mě ho nainstalovat!)

// ==UserScript==
// @name                TISWAS
// @namespace           http://greasemonkey.chizzum.com
// @description         Lists all turn instructions defined within the current map view
// @include             https://*.waze.com/*editor*
// @include             https://editor-beta.waze.com/*
// @include             https://beta.waze.com/*
// @exclude             https://www.waze.com/user/*editor/*
// @exclude             https://www.waze.com/*/user/*editor/*
// @grant               none
// @version             0.9
// ==/UserScript==

const TISWAS =
{
   graphEntries: [],

   ModifyHTML: function(htmlIn)
   {
      if(typeof trustedTypes === "undefined")
      {
         return htmlIn;
      }
      else
      {
         const escapeHTMLPolicy = trustedTypes.createPolicy("forceInner", {createHTML: (to_escape) => to_escape});
         return escapeHTMLPolicy.createHTML(htmlIn);
      }
   },
   AddEventListener: function(elm,eventType,eventFn,eventBool)
   {
      try
      {
         document.getElementById(elm).addEventListener(eventType, eventFn, eventBool);
      }
      catch(err)
      {
         TISWAS.AddLog('AddEventListener() - '+elm+' not found!');
      }
   },
   AddLog: function(logtext)
   {
      console.log('TISWAS: '+Date()+' '+logtext);
   },
   RegexContains: function(text, contains)
   {
      let retval = false;
      if(text !== null)
      {
         let re = RegExp(contains, 'i');
         if(text.search(re) != -1)
         {
            retval = true;
         }
      }
      return retval;
   },

   GraphEntry: function(segID, es, rs, t, tts, vi, ioc)
   {
      this.segID = segID;
      this.es = es;
      this.rs = rs;
      this.t = t;
      this.tts = tts;
      this.vi = vi;
      this.ioc = ioc;
   },
   PushGraphEntry: function(e)
   {
      for(let i in e)
      {
         if(e.hasOwnProperty(i))
         {
            let tg = e[i].turnGuidance;
            let ioc = e[i].instructionOpcode;
            if((tg !== null) || (ioc !== null))
            {
               let segID = i;
               let entry = null;
               segID = segID.replace("f","");
               segID = segID.replace("r","");

               let es = [];
               let rs = [];

               entry = new TISWAS.GraphEntry(segID, es, rs, "", null, null, ioc);

               if(tg !== null)
               {
                  if(tg.exitSigns !== null)
                  {
                     for(let j = 0; j < tg.exitSigns.length; ++j)
                     {
                        es.push(tg.exitSigns[j]);
                     }
                     entry.es = es;
                  }
                  if(tg.roadShields !== null)
                  {
                     for(let j in tg.roadShields)
                     {
                        if(tg.roadShields.hasOwnProperty(j))
                        {
                           rs.push(tg.roadShields[j]);
                        }
                        entry.rs = rs;
                     }
                  }
                  entry.t = tg.towards;
                  if(tg.tts !== "")
                  {
                     entry.tts = tg.tts;
                  }
               }
               
               TISWAS.graphEntries.push(entry);
            }
         }
      }
   },
   SegSelect: function(e)
   {
      let segID = e.currentTarget.attributes.tag.value;
      let segObj = W.model.segments.objects[segID];
      let segCenter = segObj.attributes.geometry.getBounds().getCenterLonLat();
      W.selectionManager.setSelectedModels(segObj);
      W.map.setCenter(segCenter);
   },
   ReplaceShieldIDs: function(textIn, rs)
   {
      while(textIn.indexOf("$RS") !== -1)
      {
         let start = textIn.indexOf("$RS");
         let end = textIn.indexOf(" ", start);
         let rsID = null;
         if(end === -1)
         {
            rsID = parseInt(textIn.slice(start + 4));
         }
         else
         {
            rsID = parseInt(textIn.slice(start + 4, end));
         }

         let rsImg = "";
         if(rsID !== null)
         {
            rsImg = '<img src="https://renderer-row.waze.com/renderer/v1/signs/' + rs[rsID].type + '?text=' + rs[rsID].text + '" height="40px" style="margin-top:-8px;margin-bottom:-8px;">';
            if(rs[rsID].direction !== null)
            {
               rsImg += rs[rsID].direction;
            }
         }

         if(end === -1)
         {
            textIn = textIn.slice(0, start) + rsImg;
         }
         else
         {
            textIn = textIn.slice(0, start) + rsImg + textIn.slice(end + 1);
         }
      }
      return textIn;
   },
   FormatTI: function(ge, idx, useFilter, contains)
   {
      let showTI;
      if(useFilter === false)
      {
         showTI = true;
      }
      else
      {
         showTI = false;
      }

      let innerHTML = '<div style="background-color: yellow;"><i class="fa fa-road" style="scale:150%;;padding-right:10px;"></i><b>' + ge.segID + '</b></div>';
      
      innerHTML += '<div style="padding-left:10px;padding-top:4px;">';
      if(ge.es.length !== 0)
      {
         innerHTML += '<i class="fa fa-sign-out" style="scale:150%;;padding-right:10px;"></i>';         
         for(let j = 0; j < ge.es.length; ++j)
         {
            innerHTML += '<img src="https://renderer-row.waze.com/renderer/v1/signs/' + ge.es[j].type + '?text=' + ge.es[j].text + '" height="25px" style="padding-right:10px;">';
         }
         innerHTML += '<br>';
      }
      if(ge.vi !== null)
      {
         innerHTML += '<i class="fa fa-eye" style="scale:150%;;padding-right:10px;"></i>';
         innerHTML += TISWAS.ReplaceShieldIDs(ge.vi, ge.rs);
         innerHTML += '<br>';

         if(useFilter === true)
         {
            showTI = showTI || TISWAS.RegexContains(ge.vi, contains);
         }
      }
      if(ge.rs.length > 0)
      {
         for(let j = 0; j < ge.rs.length; ++j)
         {
            if(useFilter === true)
            {
               showTI = showTI || TISWAS.RegexContains(ge.rs[j].text, contains);
               showTI = showTI || TISWAS.RegexContains(ge.rs[j].direction, contains);
            }
         }
      }
      if(ge.t !== "")
      {
         innerHTML += '<i class="fa fa-reply" style="scale:150%;;padding-right:10px;"></i>';
         innerHTML += TISWAS.ReplaceShieldIDs(ge.t, ge.rs);
         innerHTML += '<br>';

         if(useFilter === true)
         {
            showTI = showTI || TISWAS.RegexContains(ge.t, contains);
         }
      }
      if(ge.tts !== null)
      {
         innerHTML += '<i class="fa fa-comment" style="scale:150%;;padding-right:10px;"></i>';
         innerHTML += ge.tts + '<br>';
         if(useFilter === true)
         {
            showTI = showTI || TISWAS.RegexContains(ge.tts, contains);
         }
      }
      if(ge.ioc !== null)
      {
         innerHTML += '<div';
         if(ge.tts !== null)
         {
            innerHTML += ' style="color: gray; text-decoration: line-through;"';
         }
         innerHTML += '><i class="fa fa-comment" style="scale:150%;;padding-right:10px;"></i>';
         let localisedIOC = I18n.lookup('turn_tooltip.instruction_override.opcodes')[ge.ioc];
         innerHTML += localisedIOC + '</div>';
         if(useFilter === true)
         {
            showTI = showTI || TISWAS.RegexContains(localisedIOC, contains);
         }
      }
      innerHTML += '</div>';

      let resHTML = '<div id="_tdiv-' + idx + '" tag="' + ge.segID + '" style="padding:2px; margin:6px; cursor:pointer;';
      if(showTI === false)
      {
         resHTML += ' display:none;';
      }
      resHTML += '">';
      resHTML += innerHTML;
      resHTML += '</div>';

      return resHTML;
   },
   DisplayTIs: function()
   {
      let resHTML = '';
      let filterEnabled = document.querySelector('#_tisEnableFilter').checked;
      let filterContains = document.querySelector('#_tisContains').value;

      for(let i = 0; i < TISWAS.graphEntries.length; ++i)
      {
         let ge = TISWAS.graphEntries[i];
         resHTML += TISWAS.FormatTI(ge, i, filterEnabled, filterContains);
      }
      return resHTML;
   },
   UpdateList: function()
   {
      let outPane = document.querySelector('#_tisOutput');
      if(outPane !== null)
      {
         let resHTML = '';
         let nEntries = 0;

         if(W.map.getZoom() >= 17)
         {
            nEntries = TISWAS.graphEntries.length;

            if(nEntries > 0)
            {
               resHTML += TISWAS.DisplayTIs();
            }
            else
            {
               resHTML += "No TIs here...";
            }
         }
         else
         {
            resHTML += "TIs only available at zoom 17+";
         }
         outPane.innerHTML = TISWAS.ModifyHTML(resHTML);

         if(nEntries > 0)
         {
            for(let i = 0; i < nEntries; ++i)
            {
               let linkID = "_tdiv-" + i;
               TISWAS.AddEventListener(linkID, "click", TISWAS.SegSelect, true);
            }
         }
      }
   },
   SurfaceTIs: function()
   {
      TISWAS.graphEntries = [];

      if(W.map.getZoom() >= 17)
      {
         W.model.turnGraph.reverseAdjacencyList.forEach(TISWAS.PushGraphEntry);
      }

      TISWAS.UpdateList();
   },

   PopulateUI: function()
   {
      var iHTML = '';
      iHTML += '<div id="_tisControl">';
      iHTML += '<i class="fa fa-filter" style="scale:150%;padding-right:10px;"></i><input type="checkbox" id="_tisEnableFilter" />&nbsp;';
      iHTML += '<input type="text" style="font-size:14px; line-height:16px; height:22px; margin-bottom:4px;" id="_tisContains">';
      iHTML += '</div>';

      iHTML += '<div id="_tisOutput" />';
   
      return iHTML;
   },
   Initialise: function()
   {
      TISWAS.AddLog("Initialise");
      if(document.getElementsByClassName("sandbox").length > 0)
      {
         TISWAS.AddLog('WME practice mode detected, script is disabled...');
         return;
      }
      if(document.location.href.indexOf('user/') !== -1)
      {
         TISWAS.AddLog('User profile page detected, script is disabled...');
         return;
      }
   
      TISWAS.WaitForW();
   },
   WaitForW: function()
   {
      if(window.W === undefined)
      {
         window.setTimeout(TISWAS.WaitForW, 100);
         return;
      }
   
      if (W.userscripts?.state?.isReady)
      {
         TISWAS.AddTab_API();
      } 
      else 
      {
         document.addEventListener("wme-ready", TISWAS.AddTab_API, {once: true});
      }
   },
   AddTab_API: async function()
   {
      TISWAS.AddLog("Registering with sidepanel...");
      let {tabLabel, tabPane} = W.userscripts.registerSidebarTab("TISWAS");
      tabLabel.innerText = "TISWAS";
      tabPane.innerHTML = TISWAS.ModifyHTML(TISWAS.PopulateUI());
      await W.userscripts.waitForElementConnected(tabPane);
      TISWAS.CompleteUISetup();
   },
   CompleteUISetup: function()
   {
      W.map.events.register("moveend", null, TISWAS.SurfaceTIs);
      W.map.events.register("zoomend", null, TISWAS.SurfaceTIs);
      TISWAS.AddEventListener("_tisEnableFilter", "change", TISWAS.UpdateList, true);
      TISWAS.AddEventListener("_tisContains", "keyup", TISWAS.UpdateList, true);
   }
};
TISWAS.Initialise();