您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds filtering and pop-up infobox for UR, MP and camera markers
当前为
// ==UserScript== // @name UROverview Plus (URO+) // @namespace http://greasemonkey.chizzum.com // @description Adds filtering and pop-up infobox for UR, MP and camera markers // @include https://www.waze.com/*/editor/* // @include https://www.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 3.98 // ==/UserScript== /* TO-DO ITEMS ======================================================================================================================= Bug fixes - MUST BE CLEARED BEFORE RELEASE ======================================================================================================================= ======================================================================================================================= Things to be checked ======================================================================================================================= ======================================================================================================================= Proposed functionality ======================================================================================================================= Adjust default settings for places & MP tabs to account for dynamic nature of tab building Restore custom icon functionality Convert camera XHR code to async operation "Hide All" button for feed - automatically clicks the trashcan on all visible feed entries Allow custom alert box to be used as a confirm() replacement as well Improve reliability of yellow/green comment marker choice Implement some sort of UR "hotspot" marking to highlight areas of the map with significant clustering of URs Flush settings to localStorage whenever a change is made, or at least before opening a new tab via a popup User-defined setting presets Extend unstacking to cameras Place filtering - by last user to edit More localisation First-run information - show quickstart guide to URO features if no existing settings are present (i.e. new installation) ======================================================================================================================= New functionality in progress ======================================================================================================================= Addition of segment and place watchlist functionality */ /* JSHint Directives */ /* globals $: */ /* globals W: true */ /* globals I18n: */ /* globals OL: true */ /* globals OpenLayers: true */ /* globals Waze: true */ /* globals require: */ /* jshint bitwise: false */ /* jshint eqnull: true */ var uroVersion = "3.98"; var uroReleaseDate = "20170309"; // list of changes affecting all users var uroChanges = [ "Fix for missing segment popup in Firefox when certain segment address details were missing", "Fix for console errors when something other than a UR editing panel is opened", "Popups auto-hide when the map comments dropdown menu is accessed", "Inhibits speed limit validation on private and parking segments", "MP filter list now auto-generated based on whatever MP types are present in WME", "Popups now enabled for map comments" ]; // list of changes affecting only WME Beta users (at least until the next production release including these parts of the beta code...) var uroBetaChanges = [ "Compatibility fixes" ]; // true enables debug output during script startup var uroShowDebugOutput = true; // true keeps debug output enabled after script startup var uroPersistentDebugOutput = false; /* var uroRecentDebug = []; */ var uroCtrlsHidden = false; var uroCurrentTab = 1; var uroFID = -1; var uroShownFID = -1; var uroShownPopupType = null; var uroInhibitSave = true; var uroPopupTimer = -2; var uroPopupDwellTimer = -1; var uroPopupShown = false; var uroPopupSuppressed = false; var uroSetupListeners = true; var uroRootContainer = null; var uroPlacesRoot = null; var uroConfirmIntercepted = false; var uroCustomMarkerList = []; var uroPendingURSessionIDs = []; var uroRequestedURSessionIDs = []; var uroPlacesGroupsCollapsed = []; var uroKnownProblemTypeIDs = []; var uroKnownProblemTypeNames = []; var uroMouseInPopup = false; var uroURControlsIdx = null; var uroProblemControlsIdx = null; var uroTurnsLayerIdx = null; var uroMCLayerIdx = null; var uroNullCamLayer = false; var uroNullOpenLayers = false; var uroNullURLayer = false; var uroNullProblemLayer = false; var uroNullMapViewport = false; var uroURDialogIsOpen = false; var uroHoveredURID = null; var uroSelectedURID = null; var uroURReclickAttempts = 0; var uroPendingCommentDataRefresh = false; var uroWaitingCommentDataRefresh = false; var uroExpectedCommentCount = null; var uroCachedLastCommentID = null; var uroMCSelected = false; var uroPlaceSelected = false; var uroAutoCentreDisabledOn = []; var uroMouseIsDown = false; var uroBackfilling = false; var uroHidePopupOnPanelOpen = false; var uroUserID = -1; var uroURIDInURL = null; var uroDOMHasTurnProblems = false; var uroBetaEditor = false; var uroWazeBitsPresent = 0; var uroMTEMode = false; var uroFinalisingListenerSetup = false; var uroInitialised = false; var uroOWL = null; var uroDiv = null; var uroAlerts = null; var uroControls = null; var uroCtrlURs = null; var uroCtrlMPs = null; var uroCtrlPlaces = null; var uroCtrlCameras = null; var uroCtrlMisc = null; var uroCtrlHides = null; var uroAMList = []; var uroCWLGroups = []; var uroCamWatchObjects = []; var uroSegWatchObjects = []; var uroPlaceWatchObjects = []; var uroFriendlyAreaNames = []; var uroAreaNameHoverTime = -1; var uroAreaNameHoverObj = null; var uroAreaNameOverlayShown = false; var uroANEditHovered = false; var uroANEditBox = null; var uroPrevMouseX = -1; var uroPrevMouseY = -1; var dteControlsIdx = -1; var dteOldestFullDrive = new Date(0); var dteEpoch = new Date(0); var dteTopID = ''; var dteClearHighlightsOnPanelClose = false; var dteArmClearHighlightsOnPanelClose = false; var dteOffset = 0; var uroUserTabId = ''; var uroShowFeedFilter = false; var uroTBRObj = null; var uroBackfillQueue = []; var uroUnstackedMasterID = null; var uroStackList = []; var uroStackType = null; var uroMousedOverMarkerID = null; var uroMousedOverMarkerType = null; var uroClickedOnMarkerID = null; var uroClickedOnMarkerType = null; var uroAlertBoxStack = []; var uroAlertBoxTickAction = null; var uroAlertBoxCrossAction = null; var uroAlertBoxInUse = false; var uroNativeMarkerImage = 'problems-sc703e224cf.png'; var uroCustomURTags = ['[ROADWORKS]','[CONSTRUCTION]','[CLOSURE]','[EVENT]','[NOTE]','[WSLM]','[BOG]','[DIFFICULT]']; var uroAltMarkers = [ // 0 = closure "url('data:image/png;base64,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')", // 1 = cone "url('data:image/png;base64,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')", // 2 = custom text "url('data:image/png;base64,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')", // 3 = editor note "url('data:image/png;base64,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')", // 4 = event "url('data:image/png;base64,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')", // 5 = wslm & native SL URs "url('data:image/png;base64,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')", // 6 = Elgin "url('data:image/png;base64,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')", // 7 = TrafficCast "url('data:image/png;base64,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')", // 8 = TrafficMaster "url('data:image/png;base64,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')", // 9 = CalTrans "url('data:image/png;base64,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')", // 10 = TfL "url('data:image/png;base64,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')", // 11 = boots on ground "url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAKrCAYAAAB/UOT4AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4AgUFzoXiojUYAAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAABmJLR0QA/wD/AP+gvaeTAAAiFklEQVR42u1cCXBUxdZOSEggAZJAkkkmCcQskG0mM5lJJnsgxCh7niwSFoEE4bGFCYJgsSkoRoU8RFndBQtLwEJleSi4gOvTUhbFFRAVDaKPRSBs4f7na/oOdyaTDX31qv53DtV1597uPt/p06dPnz7pwsODiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJ6T9Arah4de/e3dtisbRWC97xXdb/5eQJxgCJjo5uQ892ubm5QQQcnJ2dHZqSkqLDE+/4jnrZzlsK5PmnwTFKnU7nn5WV1ZFKBL3HpqenJ1utVnNOTo6VvmXgiXd8Rz3aoT36of+NCuOJkRCjtmBGI+xMo02x2+29Pv744+rjx4/vPnfu3LG6urqLVBQ88Y7vqEc7tEc/KXxbqZlmC+IJ6Wl07ekZnpmZmbhw4cKSH374YfuVK1cuS1CFfivqb/X9/MWz6vtltF+4YEEJ+oOP5Ne6OYIIAWw2W4f8/PwoYpD2/vvvVxNArStg0+9X8Kx9/623qsEH/MC3KUHEFEBiqLG4uNh25MiRrVrmKFevXlVUchVAJbTR9jm8fv3W4p49beAL/o1NjZc0wAgYGgmwzVUAlPfee09ZsGCBsm7dOuXixYsOwc6dO6s89dRTCk2d8umnn9YT8PCuXdsyTSarzWKJAI5czs5a6NWrly+WWlpampGAlrmqGOW7775T/P39FWqv+Pr6Kg8//LD4fvnyZWXWrFmKt7e3qCMQpaampt50rV24cJkxKckIHOA5aUM6ngDSQtzs2bNLqdMFrRAY6cmTJ5UxY8YIkFatWoknMVL++OMP5d///rdC8+5UN336dNHHdWpmTp9eChzgyWlx+APf5OTkMPpo/f7773e52sBnn32mxMbGCuZeXl4OoN69e4spqa2tVfLy8hxCqPUJCQnKgQMHnOwH/IEDPOCq2vCSyyd22rRpg9UOaida/0r//v2dADw9PcUT6l+6dKnyyCOPONWp9egzcOBA5fz581r7uAIc4AFX2AZUkpGR0YlGAltYrVo3OoF27drlVgDtiNV6rQDqO+reffddRTs44AAPuOqU+MKZ0IesH3/88V9qY3Uuo6KiHEBNAWo1oC1xcXEOIc7WnlGAAzzgiimBSyVr7VJQUNCDjOxXtTFo5MiRgkm7du2UGTNmKCtWrBDGiG+NCTBgwABl9erVytSpUxU/Pz/x7c477xQDQwEO8IALfA9ySv5y07mFwC+pDmfbtm1K27ZthSa+/vprhTyn8tprr4m6NWvWuNUIvj3//PMYqfAjoK+++krR6/VCGEytHOQl4AEX+LCJduRO42mJ9dJ6wilTpgim69evV6qqqpSSkhLl6aefdnjFYcOGiXoYJ1YMfo8fP175/PPPFdpNlXvvvdfR9tlnn3UsW1XLwAMu8IUQVOLwkYxRaAIrAqDo+Ntvvyl9+vRRfvrpJ9FZNdhXXnlF1O/c+YbQEH7v3r1bmTBhgvLkk08qWtuCL0H9kCFDxHIGDvCAK4SAOsinx9AGU3z69OkadEbDoUOHio7Hjh1Tfv/9d+EV1WULeuKJJ+QSHKT069dP/H7hhReUU6dOKWfPnnVqe+jQIVF/xx13CL8CHOABV0wHDAMbC5Xuhw8f/vDCpfOiI6ZAVbF2UwKBUXx8vHDhcGL4DfuhKMsxBaoAoFGjRgle1dXVCvjTvvQB8GS80daxREk9tu3bt69SO/7yyy9KcHCw4uPjo1RWViqXLl2zWRgpRVGCKVR/4sQJ5ddff1XGjh0rvsF9Y+SqsJMnTxY8QkNDhUYxGOAAz7FEZQSF6MdQWlo6AvuGOuKPPvpICQoKcqz31q1bO1w3eTvlzJkzjnlX9w/VSNW2KJ06dVL2798veNK0XgAO8ICrOqtWMniNIS/Wc+/evf/UxgcUISlz5sxRbr31VgEM41q1apVD3dq2GDl8yaBBg0Rb+JT58+crP//8s2OKwB84wBNGKaNzsYEhakYERMZTduHChTOqr1dtAaOG0cFoVYbuoisQ9gq0xarQtgFf8AcO8LQbmGMTk9ooXLt27VJierVl4Vyd26Kpuwq+hNMDOI7NyyW8h4EGI2wnd9pn69atm5ctW+ZgAg00JQB+u77jSRG4smfPnk3gK48Fwa5acJysqNKP5imMGpqow4ANGzZsRKi2c+dOp/jCNd7Q/nZ9x5PCweMUW4wl/mbwB05DJzUR6MJY5OHFPHz48L4PPfRQNa3zWlKlI4BpiLRBMGjRokV1ZMRbaDX0Az/wlR7au8mIGw2xhmnnM5SVlRVVVFSU33XXXR8oLaB77rnnAO0/40aMGFGE5Qh+zRHASRCojBiE0JKMpy3ddsstt/SnJTeJIqVDjYHPnDnzFDkoO/UpoQ2KAmxTPBl7iJzqlp3C5Mm7DTEJJGaRN998s4H8fBFRGe2GP7sTgALbk+RTKrE5wa6oRKE/+MiV0CIBhBA4LcG3IzImLehJiJQePXoU0xzbyW+cUsNAaYh1dASopuXXDwJAcAiA/hTU+mjSBk1PxeDBg9HYFwcUHNvgWnFOAFMSJoFAcul9KAW3y0mIupNnf1Nj0R2kgVFUV4jDMKImOCTEkaS9APgFjUANCuOwBXQEKM4HONAiKCVsC22/2diC6TvODvY33njjLQhw9OjRI/R9JoQgsN5U8kiIdOqTCr9A/LpSXTTCfKlV34aWKD76ylRADFRK4Dnw85hjYtyfBBtIdcOozQxiXEW/V5AfOUrTs47el1D9XKorpz6D4GfgnOgbhC6AUBgQ8dE3dkL3kkFvKDXqBssmkCLMMcCJ8VAa7XBiNJre51FZTIyW03M1be0r6fdSet5P9RXEYyS0RX0HUz+kB3pR33zpBLuQxgMbEkJoAikfBBvSfadL1RZiRGCG0UEr9Ps2CTKUfg+BoBg9gfdFOwSy0CKVAoT3EADLFXZC04Ld0+1yFUaJ5YR5Q2PkFIxG401yThMhGAqcj5xvk0wTmfAO24FRog39TkI/RNQYPaYBtgYBNMbZeJ4KyS/pYNrJw2sgtCQDoI5g6FrUOhQsT/TD/MuUg1gZLXFYqq8Q6UKpIaeUYVNFTSnKJd/qr8jkaQnMfch9tyHn5YdC3tTvb3/7G7yij6z/6/OYNJpW48aN86a9pA0d7drRhhZEQW7wpEmTQinA1eGJd3xHPdqhPfr96TwmmNBO2JpiRv+JEyd2JLAIAoulDSqZ3s12u91K9Rl44h3fUY92aI9+6H+jwnhiJMSoLZjRCDtTSVm5cmWvb775ppr2qd0ULzrlMfGO76hHO7RHP/QHH/Br0QYG6WlE7aljOI0ukQ63JXS22I78ZEOxJMrFy7WOPCbaox/6gw/4gW+zNjA0JHV2IBVHEYO0gwcP1stjNreg38F9+6rBB/zAtylBxBRAYqhx1qxZtpqamibzmNrSUB6z5p13ts66+24b+EoNu5+agoICLxgSjAqGRgK4zWMi37Bx40ZxAlcPyQC9cKFWefPNN0UdnWnr9avZt29bxd//bp04fnwEcIBXTwt03vSVS81IU7DMnQA4nyJ7g1MY8hNID6ihPU7kOMmjDlkZpA9d++9av37ZuPJyI3CA56QNqIdKAM1d3DPPPFNKHS64TgGO+zjiAeT2228XT4qmRfSNk9bs2bOd6pCxQR/XqXlyzZpS4ABPTss1LdDm5DtmzJgwih2tx48fr5fHpKO8yNyoICrQgw8+KKYER4F58+bVq6dpRcDjZD/gDxzgAVdoA3MDY4GTWb169WBXg6P1r9DZox4AnlA/ndSUV1991alOq5ElS5Y4cuBqHhM4wAOusA05FZ1ojmALq10TIsjIuhOgIVDXtihffvmlkzaAAzzgiimBSuBMyFiyTpw4US+PiUSIyqw5gNrfasFUqnxrL55HYuVfwAOumBK4VPrQhU5YPehI75THfOyxxwQTrAgcA3fs2CGMsSkBkP2nIFghI1doM3PkNNSzKnCAB1zge9CJyR/zQ7ufUx4TB2E6iwpNIHmGNNEnn3wi6nBAdqcRPN955x2R8YMfAaEv8l4QRpNsvwQ84ALfA1svSRNP3swpj4mcJZgiL71582aRRIczUunRRx8V9TBOVQAkWZHZoXOo8tJLLznavv32245lq2oZeMAFvhCCjCQOH1VNYEUAFB2RocFSRNJLO1XIOaB+//59QkP4TQYnUouazK1QP3wJ6pG9kyvlEvCAK4SAOsh5xNAcFZ87d65GzT3hTwjoCHA4I9e/dalTgiWoLuE9e/aIRKyaUFHb4q9AqH/88ceFXwEO8IArpgOGgY2FpOpOjT+8dPmi6IgpUFXsumzBiPoIg4Xl4zfshxg7bW4qARy8tmzZooA/OawPgCfjjbaOJUofbKTWVZoTtlJeXq7Q6UrkpgGsGhr+3gWmUP3p06dFgfXjG9w3Rq4Kiz/OgQfynNAoBgMc4DmWqIygOtKIDLT8Rqj7Bujbb78Vf/dSVwCYqSth7ty5IkunzV9DANVI1bYoZWVlDveNPClwgAdc4awQ/8E4MD/Tpk3rSduwUx4TGdsXX3xReeCBBwQwjOv111931GvbYuTwJbATtIVPwSpBolVtC/7AAR5wZfx5bQND1IwIiFZF2aVLl864Jr8wahgdjNZdQOOaVHU1UBTwBX/gAM+xgakBDTYTSEcGU0j+YCnyjjcS0jVSroIv7aw9gOPYvLRBDaTC2QFhOxlNH/IDm/HXH0cQ67wTtqjgj7pffPHFJvCVx4JgJy2ohLkhA/IjTYRRIxNJPIC85UaEakiO/5k85oYNG46T+sfibAL+wFFtwW2gC2NBnElSm6uqqvoSg2pa57VqTKnaRHPymC+//HLd9u3bt5CB9gM/8AX/ps4gDkGwhsnKDYsXLy6isK6c9pIW5TFp1z2wfPnycTSQIixH8GuOAE6CQGU0gpD77rsvnhjZyEH1nzNnziTapg81AX6KhLaTK8fBJ5NmAZtUCPi1+BQGy6VYsA05q0CykcgZM2YYSJAiKmXPPfec2zwmBbYnqa4SmxPsimwgCv3BR66EluUx0QmnJXmODKDtWU+bTQoJU0yasZPfOOVipHV05qgmw+sHASA4BED/0aNH+4Bfcw/GnvPnz/fC8pEHoQ7yNI7zSCQFJwm0anKpDN20aZPIY+LPzqB9+/btILWPIi0U4jCMqAkOCXEkecgA+AVVoMaEcdgCOgIU5wMcaBGUEoCFmGVjC6bfpfTNvnfvXpHHpMPvEdLQTAhBAvamkkeCpNMzFX6BBOpKz2iE+dAqDj5ulyg+QgMYufRoJmqcAz+POSaG/Wl6BtK3YfR7BpWqu+++e8WhQ4eOkrGuo+9L6NtcEqScfg+Cn4FzolJM/QogFAZET32DJ3TMmQx6Q6lBN1g2MSrCHAOchBlKWhhOTEbT93n0fTEBLqfvq+l9Jf1eSuV++l1BZSS0hXsS1K5ERlH5GBimifgFuhVC1QRSPgg2pPtOl6rFPBeDGUYHrRDIbQCBcPRtCATF6Ol7X7RDIAst0rcChPcQAMsVdkJ2gYyg+zwmjBLLCfOGxsgpUGBzk5zTRAiGAueD+ZbL0CzdfCpsB0aJNiREEvrJ9FEXTANsDQJojLPxPBWSXzBS6eUCoEJoSaZ/OsrTk1NR61CwPNEP8y9zXmJltMRheaoCwVagIXSGcM0taK/2BZ+/IpP3Xye+j8n3Mfk+Jt/H5PuYfB+T72PyfUy+j8n3Mfk+Jt/H5PuYfB+T72PyfUy+j8n3Mfk+Jt/HbOl9TDoktyksLPRDIQfmh3e+j8n3Mfk+Jt/H5PuYfB+T72PyfUy+j8n3Mfk+Jt/H5PuYfB+T72PyfUy+j8n3Mfk+5v/EfUz1/iRURrbiQxrygYYgVHOLdFCiL/igNDZ6/v8x+T4m38fk+5h8H5PvY/J9TL6Pyfcx+T4m38fk+5h8H5PvY/J9TL6Pyfcx+T4m38fk+5j/r+5jqglWbXK1vLzcj05oInkqc9Z8H5PvY/J9TL6Pyfcx+T4m38fk+5h8H/N/+D5mz549OyxYsMBEVl/2X7uP+Y9//KMN38fk+5h8H5PvY/J9TL6Pyfcx+T4m38f8X/7/MUWCNbp7tHe4Jby1WvD+H7+PCZDA6MA2nbt3bheVGxUUZgkLjsiOCA1JCdHhiXd8Rz3aSaH+mvuYGKW/zt8/Iiuioz5LH6Gz6GLD0sOSdVadWZ+jt4ZnhWfgiXfxnerRDu3RD/1v+D4mRhKZFdkWzCJyIzrrs/UpRruxV/7H+dUpx1N2h54LPda6rvVFjzoPBU+84zvq0Q7t0Q/9wUdqpvkbGKSPzIlsTyoOD88MT0xfmF6S9kPadq8rXpcBKsoV+dS+X7z226vO6zLapy+wlqA/+ICf1IpnswTQ2/QdovKjosIyw9Jy38+t9r3iW1sPsBnv6Jf7VnY1+IAf+DYlyLUpIImhxs7FnW1pR9K2OjFHuUpF/ecqgPrvqnOftPXxWzv3jLKBL/g3NjVeMCQYFQzNfMS8rZ4AKO9RWUBl3XX1C9BzVJ6ispDKp/UFNO9K2hZmCrGGW8IigOP2PmZcrzhfLLXQtFBj9nvZy+qpGOU7Kv7yOpsvlYfl98tUZlHxlnU6KjX1p8e0sNuy4KRORuAAz0kbUA8ZTwBpIc4021Tqc8XngpMQGOlJKmMkSCv57EXlDyr/ppLpUjdd9nGZGuN0QylwgCen5foFjuDk4LDI7pFW4/fGXfVs4DMqsZK5lwaot5ySWip5GiHU+gQqB5ztB/yBAzyn+5gwFjgZwzTDYEcHVY2Y6/4uAJ7yCfUvpfKIS52nRpCBVM5fn5JWda2uAAd4wBW2AZXoM/SdIvIijJnvZa52WPcVOYJdDQigHbGHGwHUd9S9q9EGFeAAD7jqlPjCmegydFndfuz2L0djdS6jPOrdr2wQ0NNFMLXEaYSgqQMO8IArpkS45uyILvoCfY+Of3T81dEY/0ZKJu2ozKCyQhqjRxMCDKACnU6l4ie/3SkHRgU4wAMu8D1ii2P9MT+6LN0t3nXelxwOZxuVtlITX1N5n8prsm5NAxrBt+ep/Cj9CP59RUUvhdl17RtwgAdc4Htg6w23hcfrMnW9nDzhFMl0PZUqKiVUntZ4xWGy3luuGPweT+VzKulU7tW0fVazbKWWgQdc4AshorpHxeGj9xWpiXMSFB1/o9KHyk+SoWqwr8j6nVJD+L2bygQqT2oGc1X6EtQPuWYTwAEecIUQUAf59Bh9vr44+HRwjeiMdT9UdjxG5XfpFes0QjyhWYL95O8XqJyictal7SFZf8c1vwIc4AFXTIcwTNpYwnPDu3c73O1DD9UqqjQq1m5KinRQ8dKFx8rfsJ8UzRRc0fweJXlVUyH+CUcSPgCe2NBgmOoSpe3WZt1uXeXo+AuVYCo+VCqvdRb/YKRWyRSqP0EFa2qs/JYpR64KO1nyCJUapcEAB3iOJQpngeiHwjRDTGnMCLFvqCP+iEqQZr231rjuHCpnNPOu7h9eLm1ROlHZf42nz2WfC8ABHnBVZ9UKxoH5Cc8L72nYa/inU3zwA5U5VG6VwDCuVRp117lME3zJINkW620+lZ+vTxH4Awd4wii19zERNSMCir0jtsz/gv8Zxy6q2sIZaXS1mjl3F10pcq84JVeFpg34gj9wgFfvPqaMqKCNQvNa81JierWl4Zzbcr3uKviG54T3AI5j83K9j4mzA8L2sOywPslbkzd7LNMwqW2GAFfcvOP5sYeSuid1E/gK/oTT4H1MCkL9aJ7CdOk6ky5bNyBpQ9JGEartdIkv6hp4v+rmnZ5+C/yOByQEjA21hJrBHzgN3seEpcJYEGeS9Zrjh8f3TXooqbrVqFa1Hms1AUxD/646v3su8qyLWRWzJa40rh/4gS/4N3UGcQiCNWy402BILEssSqxILA++K/iDRuDr/Qu6J+hAwpSEcV1HdC3CcgS/5gjgJAhUljwiOaTbkG7xCSMTbFG3RPXX99JPajuw7aHGwH1m+pzqOrmrPX5kfAm5o8xQU2h8ZF5kCPi1+BQmT95tyDoCabeL7HJzF0NUcVRReFF4md90v5/dCdDhZIeTKXNSKrE5wa7C08Oj0B98bvg+pjgOkm9HZBzTK0bfpbhLSkSPiOLo0mh7+zPtTznCQDI+zzrPuqSHk6rDcsP6CQFIcAiA/iHJIS27j5k0OEncxxQHITq2iQMxnRMEU4suQZ+rz6WVMzThkYTlnlc968SOSf8SdiXsCMkMGUXLsFAchilqgkMScWRRdAD8gkaghvOYqi2gI0BxPsCBVgSluXpLRH5ENrbg0KzQ0uCsYHv8G/FvQYDwo+FHQvJDZgohcsJ6k0PKC88OT6c+qcIvZIR11WfqoxHmQ6vy4NPwfUyZCoiBSvV5erDriTkm5v1DbaEDdbm6YZ2yOs0IygiqCsoNWhHyachRXaluXWBG4JKOto5zQ7JCysPywgbBz8A56Wy64rCssAIIJQaUE6Fv7ITuJYPeUGrYDZZNe34R5hjgxHhoWH7YcBrtaAKbF2QLWtzB0mF5gC1gdYA1YGWAJWBpoDXw/uDM4IrQ7NCR0Bb1HUz9SjAI0mA+BoZpoqUa2JAQQhNI+SDYgBqF9KQLzDNGJDQC1wutZIbeJkGG0u8hQks0egpg+4rVQYEstEjaLEB4DwGwXGEnNC0N38eEUWI5Yd7QGDmFEGPITZhTkezA/EI4cj6Yb+HerTqzmDp6F7ZDRok29DsJ/RBRY/SYBtgaBNAYZ+N5KiS/5F4C7xkAFQotwWaQvyKGrkWtQ8HyRD/MP1aaujJa4rCc7mNKDTmlDJsqakpRLvm/9j4mMW3VpaCLl2WcxTtjSkZrteAd31H/H8ljgjFAjCOMbdKnprdLr0gPMk8wB6dNSgtNHZuqwxPv+I56tEN7KZDnnxoxqdXbXGb2SxqU5G+ZaOlIYBGmCaZY82RzcurEVLPZbraappgy8BTv9B31aIf26Act3ZAw6GSdZm1jnGDsaJhsiE2pSMk0V5hT8lfm9yr8prDacNKwO/SCSx6T3vEd9WiH9pYKS2cIkz4xvS0002xBIEDKmBQ/40RjeNL4JFPC5IQ+xheMD1p+tWxHfrLBWLLu+ikN7dC+cF1hiWmyKdE0zhSeNiGtPbTSpCCqAJZJlg5WuzWKGKT1ONijfh6zmQX9euzrXg0+4Ae+TQniCZVBYqjROstqs9ZYm85j1jWdx7S+k7zVerfFBr6Cf0NTI5YXGRKMCoZmqbG4z2Mi37BRnsAvawS7QOVNWXe4fj/LPuM2098NVvN4UwRwgFdPC5mVmb5iyU1INRYcLFjmVoBfZPZmiMxPvKIJ7V+QJ/khMitzsn7/zPXmZcbyFCNwgOekDajHPM4cQEssLv+Z/FKfOnke1U7BWXnEA8jt8rlIRt84ac12qXte9nGZmrw1uaXAAZ6clmtaiMyM9DWOMYZZplusqcdT6+cxj8jMjQqiAj0opwRHgXlu6u1UjjrbD/gDB3jAFdrA3MBY4GTyVucNrmdwmOuH3ADcLtW/lcqrLnVajSzR5MBlHhM4wqkRrrANORWdLJUWY97BvNX1EiIHGhCgIdAhbuq+dNYGcIAncDElUAmciXGSMSvhREL9POYEDbPmAN7upv0UjRCkFeAAD7hiSuBSzZPMXUx3mXp0PO+Sx3xMMsGKwDFwhzTGpgRA9v8NKs9QGaHJaah5TMIBHnCB75EzM8cf82OcanTOY+IgPFxq4phME30i63Y2oBE835EZv92y7TGZ9xpxPdkOHOABF/ge2HrNE83xhgqDcx7zackUeenNMon+psYrPirrh2oEWCMzO/dQeUnT9m3NspVaBh5wgS+EsFZa4/DRoYkLEnSIzNA8KJNe2qn6WNbvlxrC74MytbjLJY9ZK+urr9kEcIAHXCEE1EHOI4bmqDj4nMxjXpR/Qhgiwf9w87eunZolqC7hPTIRW+vStkbWP37NrwAHeMC9Nh3Y62ljMVWauifWJH4onI8ip0BVseuyRZsKabBT5G/Yz10um5v673HJa8u1vknHkz4AHnCFYapL1FRhsmV/kn09jwnfX06lVOamL2sMbZZkCtWflmWV/DZbjlwV9inJY6zUKA0GOMBzLFE4C0Q/5ilmg3WRdYRj38C/b+XfvdQVUKpZCXNllk6bv56tMdJSTb+y6+4beVLgAA+4wlkhkBErBHYxzdTTdNjknMdExvZFKg9IYBjX65r6Opdp2iHtZK70KS/JRKtsC/7AAR5w1ehcbGCImkUE9Ii1zP+S/5l6ibHz0uguNhDQuCZVXQ0UeUziC/7AAZ5jA1MDGmwmQhuVpsKsN7OWIu94IyFdI+Uq+KbaU3sAx7F5aYMaSIWzA8J2WsN9TB+bNou//tRd9/k3LMB3FOJ9Yd0EvuAPHCctaINcnDEyKjPCKLoyGeyGAaZ3TRtFqLb/z+Ux229ofzx+bPxYnE3AX5xlGjipiUAXxiLizAqz2VZl62vdYK32fty71hFTXmxBHvNlz7rE7YlbbIts/cAPfMG/qTOIQxCs4YIlBYacxTlFWSuyyiOfjmxRHlO3VnfAttw2LqsqqwjLEfyaI4CTIFBZwaKCkJz7cuJzqnJs5lnm/oY5hkmBDwc2msdss7bNqYwVGXbbQ7aS1MmpmcaxxnjrVGsI+LXoFIaGsNzs6dltKBYMJEOKtM6wGtJmpRUZZhnKOjzXwX0e82yHk1nPZVVic4JdpU1Mi0J/8JEroWV5THTCaUkEPRQZZ96TqU+fmZ5inmEuNlWZ7O3Pyzxm3fU8pnWjtdpYaewHASA4BEB/02iTjyZt0PRUFMwv8MLyESdxOrbJ0ziO/pGp41MTTHZTboo9ZWjaprRreUyZcDfsM+xImpo0ylhhLMRhGFETHBLiSNs0WwD8gipQY8I4bAEdAYrzAQ60IiidaraYp5mzsQUnT00uTahMsCfuTRR5TP2v+iMJMxJmCiHsxt4kaB5tUOlp9rRUkS6YZOqaNjktGmG+0CodfNwuUXyEBsRmRh4NKiXvmQM/jzkmv9E/eUrywJTKlGHd7N1mxNpjq2LujlkReij0aNzDcetiKmOWxNvj55Ig5YZKwyD4GTgn0kyxcYqxAEKJAVVY9A2e0DFnUJdQ/RRzN1g2udgizDHADdMMQw13GYYnVSSNJrB5sZWxi6OnRi+Pnha9OtoevfKmqTctjZsad3+CPaEi2Z48EtrCPQnqX4JB0IDyha3QNFmnWAPdCqFqAikfBBtCjZCeVIt5xoiERmh00IphquE2gEC45IrkIUJQjH6qoS/aiUCWtEgDKUB4DwGwXGEnhtGGdsgCuc1jwiixnDBvaIycgrHceBPmFKoUfh+FnA/mG4zhisVypHdhOzBKapM2NS1J9EN6iUaPaYCtQQCNcTacJIOqkPyCkYpYg4SCCoWWEIjAbmC8LkWtQxH+hfph/rHS1JXREoflqQoEW4GGXFOGTRU1pYi+4NPYsvw/+M5n8Ri3jeMAAAAASUVORK5CYII=')", // 12 = difficult turn "url('data:image/png;base64,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')", ]; var uroMarkers = [ // 0 = comment count circle ["data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAaCAYAAAA5WTUBAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB90LCxYGJyle3m4AAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAAv1JREFUSMfFls1r3EYYxn+zo9XsqjuSxpBQU5OCDy0Y3JODs2Z36W6P/YBCk159s+/5F9Z/QsHkUAruZZ344Jx7KPTSa2/NwSdDE1ISf8SWI63k6UVLN8ZuZFnQ56IZDYwevR/P+wguh7jieXF9Gewla3vJWeELAfA8b9ZxnFWl1P0kST7NsswDkFJGrus+i+P4cZqmP0VR9JyKIWq12owx5kff95PBYBCPRiN7EaPRyA4Gg9j3/cQY80hK6VdFwFFK3TXGvOx0OoktiE6nExtjXjSbzYUb/T3QqNfrvSAITofDob0uhsOhDcPwTVkiAmgCC8aYV2UITBMxxrwok5oGcEdr/XR5eXlsb4g8NY+uVQPAh0KIr7XW6f7+vq0Cvu8nnufNvu/jtak03FZKfbe4uGjn5uYqqe6lpSXrOM5qERIS8IEZz/O66+vrTlUttra25iql7hfSImAB+DIIgrd7e3u2KhwcHNggCE6LREIBGlBZlqn5+fnK1C4MQybqWiQdKi/O/wWTwpSAkFLGWZZVdnkURUgpoyIk/t3Uas93dnYqI7G9vY3rus+KkLBABtgoin7f3NxMqyKxtbWVxHH8uIhUG+AT4CMhxK1Wq/XD8fGxrIJEEATjNE0/ft+IrwEx8AaIrbWH1tpfV1ZWbhyNbrc7llL+XMRjyDwdTt6mzSRJ/jw5Ofkiy7JGr9crRWBjY4Pd3d3XR0dH31hrz4pOTw18BnwFPBBCPPR9/6zsKA+C4FQpdbeoc3tngAErwLfA90KIh2EYHrbb7cITtd1uj40xr+r1eq+s7jSAO0A3J/IAWG21Wr9ordN+vz++yt71+/2x1jrVWj/NR0DjukbmHVcF3ALmgJl8L4UQoeu6n3ued+/8/Hw2yzKVG91YSvlXFEW/xXH8xFr7B/A38PYqZ13EbYtcwkPgdk7kgylZF1PWPc076xR4DbwEDvN3tmwkLtZIMx/xwWTA5d1ELm6T1j4CjoGznFgpX/lfZxJwpwhMR2JCJJkobllN+QeQNNGuneopoQAAAABJRU5ErkJggg=="], // 1 = green comment marker ["data:image/png;base64,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"], // 2 = yellow (own) comment marker ["data:image/png;base64,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"] ]; var uroFeedFilterReloads = 0; var uroFeedFilterFilters = [ ['feed.issues.motivations.CAN_BE_SOLVED_BY_RANK', 'motivation'], ['feed.issues.motivations.CLOSE_TO_FAVORITES', 'motivation'], ['feed.issues.motivations.ISSUE_AGE', 'motivation'], ['feed.issues.motivations.ISSUE_REOPENED', 'motivation'], ['feed.issues.motivations.NEAR_DRIVES', 'motivation'], ['feed.issues.motivations.REPORTED_BY_USER', 'motivation'], ['feed.issues.motivations.USER_FOLLOWS_ISSUE', 'motivation'], ['feed.issues.motivations.USER_FOLLOWS_ISSUE_LAST_COMMENT', 'motivation'], ['venues.update_requests.panel.flag_title.IMAGE', 'title'], ['venues.update_requests.panel.flag_title.VENUE', 'title'], ['venues.update_requests.panel.title.ADD_IMAGE', 'title'], ['venues.update_requests.panel.title.ADD_VENUE', 'title'], ['venues.update_requests.panel.title.DELETE_VENUE', 'title'], ['venues.update_requests.panel.title.UPDATE_VENUE', 'title'] ]; /* function uroAddDebug(debugtext) { var ts = Math.round(performance.now()); if(uroRecentDebug.length == 100) { uroRecentDebug.shift(); } uroRecentDebug.push(ts+': '+debugtext); console.debug('URO+DBG '+ts+':'+debugtext); } function uroDumpDebug() { if(uroRecentDebug.length > 0) { document.getElementById('WazeMap').innerHTML = '<textarea id="uroDbgOutput" style="width:100%;height:100%">'; var dbgOutput = ''; for(var i=0; i<uroRecentDebug.length; i++) { dbgOutput += uroRecentDebug[i]+'\n'; } document.getElementById('uroDbgOutput').textContent = dbgOutput; } } */ function uroTempFixMTEDropDown() { // temporary fix for that bloody annoying bug in the closure event dropdown... sort it out devs! // also removes the "Choose Event" non-option from the list, so that it now always starts with "None" if(document.getElementsByName('closure_eventId').length > 0) { if(document.getElementsByName('closure_eventId')[0].selectedOptions.length > 0) { document.getElementsByName('closure_eventId')[0].required = false; if(document.getElementsByName('closure_eventId')[0].selectedOptions[0].text == I18n.lookup('closures.choose_event')) { document.getElementsByName('closure_eventId')[0].selectedOptions[0].remove(); } } } } function uroAddLog(logtext) { if(uroShowDebugOutput) console.log('URO+: '+logtext); } function uroGetCBChecked(cbID) { try { return(document.getElementById(cbID).checked); } catch(err) { return null; } } function uroSetCBChecked(cbID, state) { try { document.getElementById(cbID).checked = state; } catch(err) { } } function uroGetElmValue(elmID) { try { return(document.getElementById(elmID).value); } catch(err) { return null; } } function uroSetStyleDisplay(elm,style) { try { document.getElementById(elm).style.display = style; } catch(err) { } } function uroSetOnClick(elm,fn) { try { document.getElementById(elm).onclick = fn; } catch(err) { } } function uroAddEventListener(elm,eventType,eventFn,eventBool) { try { document.getElementById(elm).addEventListener(eventType, eventFn, eventBool); } catch(err) { } } function uroAlertBoxObj(headericon, title, content, hasCross, tickText, crossText, tickAction, crossAction) { this.headericon = headericon; this.title = title; this.content = content; this.hasCross = hasCross; this.tickText = tickText; this.crossText = crossText; this.tickAction = tickAction; this.crossAction = crossAction; } function uroCloseAlertBox() { document.getElementById('uroAlerts').childNodes[0].innerHTML = ''; document.getElementById('uroAlerts').childNodes[1].innerHTML = ''; document.getElementById('uroAlertTickBtnCaption').innerHTML = ''; document.getElementById('uroAlertCrossBtnCaption').innerHTML = ''; uroAlertBoxTickAction = null; uroAlertBoxCrossAction = null; document.getElementById('uroAlerts').style.visibility = "hidden"; document.getElementById('uroAlertCrossBtn').style.visibility = "hidden"; uroAlertBoxInUse = false; if(uroAlertBoxStack.length > 0) { uroBuildAlertBoxFromStack(); } } function uroCloseAlertBoxWithTick() { if(typeof uroAlertBoxTickAction === 'function') { uroAlertBoxTickAction(); } uroCloseAlertBox(); } function uroCloseAlertBoxWithCross() { if(typeof uroAlertBoxCrossAction === 'function') { uroAlertBoxCrossAction(); } uroCloseAlertBox(); } function uroShowAlertBox(headericon, title, content, hasCross, tickText, crossText, tickAction, crossAction) { uroAlertBoxStack.push(new uroAlertBoxObj(headericon, title, content, hasCross, tickText, crossText, tickAction, crossAction)); if(uroAlertBoxInUse === false) { uroBuildAlertBoxFromStack(); } } function uroBuildAlertBoxFromStack() { uroAlertBoxInUse = true; uroAlertBoxTickAction = null; uroAlertBoxCrossAction = null; var titleContent = '<span style="font-size:14px;padding:2px;">'; titleContent += '<i class="fa '+uroAlertBoxStack[0].headericon+'"> </i> '; titleContent += uroAlertBoxStack[0].title; titleContent += '</span>'; document.getElementById('uroAlerts').childNodes[0].innerHTML = titleContent; document.getElementById('uroAlerts').childNodes[1].innerHTML = uroAlertBoxStack[0].content; document.getElementById('uroAlertTickBtnCaption').innerHTML = uroAlertBoxStack[0].tickText; if(uroAlertBoxStack[0].hasCross) { document.getElementById('uroAlertCrossBtnCaption').innerHTML = uroAlertBoxStack[0].crossText; document.getElementById('uroAlertCrossBtn').style.visibility = "visible"; if(typeof uroAlertBoxStack[0].crossAction === "function") { uroAlertBoxCrossAction = uroAlertBoxStack[0].crossAction; } } else { document.getElementById('uroAlertCrossBtn').style.visibility = "hidden"; } if(typeof uroAlertBoxStack[0].tickAction === "function") { uroAlertBoxTickAction = uroAlertBoxStack[0].tickAction; } document.getElementById('uroAlerts').style.visibility = ""; uroAlertBoxStack.shift(); } function uroFirstTimerWelcomePack() { uroAddLog('welcome new users to Club URO...'); // for now, just show the update notes... uroShowUpdateNotes(); } function uroShowUpdateNotes() { uroAddLog('let existing users know what\'s new in this release'); var releaseNotes = ''; releaseNotes += '<p>Thanks for upgrading to URO+ '+uroVersion+' ('+uroReleaseDate+'). What\'s changed?</p>'; var loop; if(uroChanges.length > 0) { releaseNotes += '<ul>'; for(loop=0; loop < uroChanges.length; loop++) { releaseNotes += '<li>'+uroChanges[loop]; } releaseNotes += '</ul>'; } if((uroBetaEditor) && (uroBetaChanges.length > 0)) { releaseNotes += '<p>For WME Beta:<p>'; releaseNotes += '<ul>'; for(loop=0; loop < uroBetaChanges.length; loop++) { releaseNotes += '<li>'+uroBetaChanges[loop]; } releaseNotes += '</ul>'; } uroShowAlertBox('fa-info-circle', 'URO+ Release Notes', releaseNotes, false, "OK", "", null, null); } function uroAdvertiseCustomIcons() { /* //// TEMPORARY REMOVAL UNTIL CUSTOM ICON SUPPORT IS FIXED IN NEW WME uroAddLog('advertise the benefits of custom UR icons...'); var confirmMsg = ''; confirmMsg += '<p>Hi there. One of the features of URO+ that a lot of users find useful is the ability to use a custom marker for URs and MPs which have been tagged with a specific keyword in their description text.</p>'; confirmMsg += '<p>Markers are defined for <b>[ROADWORKS]</b>, <b>[CONSTRUCTION]</b>, <b>[CLOSURE]</b>, <b>[EVENT]</b>, <b>[NOTE]</b>, <b>[WSLM]</b>, <b>[BOG]</b> and <b>[DIFFICULT]</b> tags in URs, and <b>[TfL Open Data]</b>, <b>[Elgin]</b>, <b>[TM]</b>, <b>[TrafficCast]</b> and <b>[Caltrans]</b> in MPs.</p>'; confirmMsg += '<div style="background-image:'+uroAltMarkers[1]+';background-position:0 -523px;visibility:visible;height:40px;width:33px;float:left;"></div>'; confirmMsg += '<div style="background-image:'+uroAltMarkers[0]+';background-position:0 -523px;visibility:visible;height:40px;width:33px;float:left;"></div>'; confirmMsg += '<div style="background-image:'+uroAltMarkers[4]+';background-position:0 -523px;visibility:visible;height:40px;width:33px;float:left;"></div>'; confirmMsg += '<div style="background-image:'+uroAltMarkers[3]+';background-position:0 -523px;visibility:visible;height:40px;width:33px;float:left;"></div>'; confirmMsg += '<div style="background-image:'+uroAltMarkers[5]+';background-position:0 -523px;visibility:visible;height:40px;width:33px;float:left;"></div>'; confirmMsg += '<div style="background-image:'+uroAltMarkers[11]+';background-position:0 -523px;visibility:visible;height:40px;width:33px;float:left;"></div>'; confirmMsg += '<div style="background-image:'+uroAltMarkers[12]+';background-position:0 -523px;visibility:visible;height:40px;width:33px;float:left;"></div>'; confirmMsg += '<div style="background-image:'+uroAltMarkers[10]+';background-position:0 -25px;visibility:visible;height:40px;width:33px;float:left;"></div>'; confirmMsg += '<div style="background-image:'+uroAltMarkers[6]+';background-position:0 -25px;visibility:visible;height:40px;width:33px;float:left;"></div>'; confirmMsg += '<div style="background-image:'+uroAltMarkers[8]+';background-position:0 -25px;visibility:visible;height:40px;width:33px;float:left;"></div>'; confirmMsg += '<div style="background-image:'+uroAltMarkers[7]+';background-position:0 -25px;visibility:visible;height:40px;width:33px;float:left;"></div>'; confirmMsg += '<div style="background-image:'+uroAltMarkers[9]+';background-position:0 -25px;visibility:visible;height:40px;width:33px;float:left;"></div>'; confirmMsg += '<p style="clear:left;">Would you like me to automatically enable these custom markers?</p>'; confirmMsg += '<p>If you change your mind later on, they can be enabled/disabled via the Misc tab within the URO+ settings</p>'; uroShowAlertBox('fa-info-circle', 'URO+ Message to Users', confirmMsg, true, 'Yes please', 'No thanks', uroSetMarkerCBs, null); */ } function uroSetMarkerCBs() { uroSetCBChecked('_cbCustomRoadworksMarkers', true); uroSetCBChecked('_cbCustomConstructionMarkers', true); uroSetCBChecked('_cbCustomClosuresMarkers', true); uroSetCBChecked('_cbCustomEventsMarkers', true); uroSetCBChecked('_cbCustomNotesMarkers', true); uroSetCBChecked('_cbCustomBOGMarkers', true); uroSetCBChecked('_cbCustomDifficultMarkers', true); uroSetCBChecked('_cbCustomWSLMMarkers', true); uroSetCBChecked('_cbCustomNativeSLMarkers', true); uroSetCBChecked('_cbCustomElginMarkers', true); uroSetCBChecked('_cbCustomTrafficMasterMarkers', true); uroSetCBChecked('_cbCustomTrafficCastMarkers', true); uroSetCBChecked('_cbCustomCaltransMarkers', true); uroSetCBChecked('_cbCustomTFLMarkers', true); } function uroGatherSettings(container) { var options = ''; var urOptions = document.getElementById(container).getElementsByTagName('input'); for (var optIdx=0;optIdx<urOptions.length;optIdx++) { var id = urOptions[optIdx].id; if((id.indexOf('_cb') === 0)||(id.indexOf('_text') === 0)||(id.indexOf('_input') === 0)) { options += ':' + id; if(urOptions[optIdx].type == 'checkbox') options += ',' + urOptions[optIdx].checked.toString(); else if((urOptions[optIdx].type == 'text')||(urOptions[optIdx].type == 'number')) options += ',' + urOptions[optIdx].value.toString(); } } return options; } function uroGatherCamWatchList() { var liststr = ''; for(var loop=0;loop<uroCamWatchObjects.length;loop++) { var camObj = uroCamWatchObjects[loop]; if((camObj.fid != null) && (camObj.persistent === true)) { if(loop > 0) liststr += ':'; liststr += camObj.fid+','; liststr += camObj.watch.lon+','; liststr += camObj.watch.lat+','; liststr += camObj.watch.type+','; liststr += camObj.watch.azymuth+','; liststr += camObj.watch.speed+','; liststr += camObj.watch.validated+','; liststr += camObj.groupID+','; liststr += camObj.server; } } return liststr; } function uroGatherSegWatchList() { var liststr = ''; for(var loop=0;loop<uroSegWatchObjects.length;loop++) { var segObj = uroSegWatchObjects[loop]; if((segObj.fid != null) && (segObj.persistent === true)) { if(loop > 0) liststr += ':'; liststr += segObj.fid+','; liststr += segObj.watch.left+','; liststr += segObj.watch.right+','; liststr += segObj.watch.bottom+','; liststr += segObj.watch.top+','; liststr += segObj.watch.fromNode+','; liststr += segObj.watch.toNode+','; liststr += segObj.watch.fwdDir+','; liststr += segObj.watch.revDir+','; liststr += segObj.watch.length+','; liststr += segObj.watch.level+','; liststr += segObj.watch.rank+','; liststr += segObj.watch.roadType+','; liststr += segObj.watch.updatedOn+','; liststr += segObj.groupID+','; liststr += segObj.server; } } return liststr; } function uroGatherPlaceWatchList() { var liststr = ''; for(var loop=0;loop<uroPlaceWatchObjects.length;loop++) { var placeObj = uroPlaceWatchObjects[loop]; if((placeObj.fid != null) && (placeObj.persistent === true)) { if(loop > 0) liststr += ':'; liststr += placeObj.fid+','; liststr += placeObj.watch.left+','; liststr += placeObj.watch.right+','; liststr += placeObj.watch.bottom+','; liststr += placeObj.watch.top+','; liststr += placeObj.watch.name+','; liststr += placeObj.watch.imageCount+','; liststr += placeObj.watch.residential+','; liststr += placeObj.watch.updatedOn+','; liststr += placeObj.groupID+','; liststr += placeObj.server; } } return liststr; } function uroGatherCWLGroups() { var liststr = ''; for(var loop=0;loop<uroCWLGroups.length;loop++) { var groupObj = uroCWLGroups[loop]; if(groupObj.groupID != -1) { if(loop > 0) liststr += ':'; liststr += groupObj.groupID+','; liststr += groupObj.groupName+','; liststr += groupObj.groupCollapsed; } } return liststr; } function uroGatherPlacesGroups() { var liststr = ''; for(var loop=0;loop<uroPlacesGroupsCollapsed.length;loop++) { if(loop > 0) liststr += ':'; liststr += uroPlacesGroupsCollapsed[loop]; } return liststr; } function uroGatherFriendlyAreaNames() { var liststr = ''; for(var loop=0;loop<uroFriendlyAreaNames.length;loop++) { var fnObj = uroFriendlyAreaNames[loop]; if(loop > 0) liststr += ':'; liststr += fnObj.fName+','; liststr += fnObj.area+','; liststr += fnObj.server; } return liststr; } function uroSaveSettings() { if(uroInhibitSave) { uroAddLog('save inhibited'); return; } if (localStorage) { localStorage.UROverviewUROptions = uroGatherSettings('uroCtrlURs'); localStorage.UROverviewMPOptions = uroGatherSettings('uroCtrlMPs'); localStorage.UROverviewCameraOptions = uroGatherSettings('uroCtrlCameras'); localStorage.UROverviewMiscOptions = uroGatherSettings('uroCtrlMisc'); localStorage.UROverviewPlacesOptions = uroGatherSettings('uroCtrlPlaces'); localStorage.UROverviewCamWatchList = uroGatherCamWatchList(); localStorage.UROverviewSegWatchList = uroGatherSegWatchList(); localStorage.UROverviewPlaceWatchList = uroGatherPlaceWatchList(); localStorage.UROverviewCWLGroups = uroGatherCWLGroups(); localStorage.UROverviewFriendlyAreaNames = uroGatherFriendlyAreaNames(); localStorage.UROverviewPlacesGroups = uroGatherPlacesGroups(); localStorage.UROverviewMasterEnable = uroGetCBChecked('_cbMasterEnable'); localStorage.UROverviewCurrentVersion = uroVersion; uroAddLog('save complete'); } else { uroAddLog('no localStorage, save blocked'); } } function uroApplySettings(settings) { var options = settings.split(':'); for(var optIdx=0;optIdx<options.length;optIdx++) { var fields = options[optIdx].split(','); if(fields[0].indexOf('_cb') === 0) { if(document.getElementById(fields[0]) !== null) { uroSetCBChecked(fields[0], (fields[1] == 'true')); } } else if((fields[0].indexOf('_input') === 0)||(fields[0].indexOf('_text') === 0)) { if(document.getElementById(fields[0]) !== null) document.getElementById(fields[0]).value = fields[1]; } } } function uroApplyCamWatchList() { var objects = localStorage.UROverviewCamWatchList.split(':'); uroCamWatchObjects = []; if(objects.length > 0) { for(var objIdx=0;objIdx<objects.length;objIdx++) { var fields = objects[objIdx].split(','); if(fields.length >= 7) { // following two bits of code add in blank fields if the user has updated their copy of URO+ from an // older version which didn't include support for either of these field types // add default groupID field if(fields.length == 7) { fields.push(0); } // set default groupID value to 0 (no group) if(fields[7] == -1) { fields[7] = 0; } // add default server field if(fields.length == 8) { fields.push('??'); } // set default server value to unknown if(fields[8] === 0) { fields[8] = '??'; } uroCamWatchObjects.push(new uroCamWatchObj(true,fields[0],fields[1],fields[2],fields[3],fields[4],fields[5],fields[6],fields[7],fields[8])); } } } } /* function uroApplySegWatchList() { var objects = localStorage.UROverviewSegWatchList.split(':'); uroSegWatchObjects = []; for(var objIdx=0;objIdx<objects.length;objIdx++) { var fields = objects[objIdx].split(','); uroSegWatchObjects.push(new uroSegWatchObj(true,fields[0],fields[1],fields[2],fields[3],fields[4],fields[5],fields[6],fields[7],fields[8],fields[9],fields[10],fields[11],fields[12],fields[13],fields[14],fields[15])); } } function uroApplyPlaceWatchList() { var objects = localStorage.UROverviewPlaceWatchList.split(':'); uroPlaceWatchObjects = []; for(var objIdx=0;objIdx<objects.length;objIdx++) { var fields = objects[objIdx].split(','); uroPlaceWatchObjects.push(new uroPlaceWatchObj(true,fields[0],fields[1],fields[2],fields[3],fields[4],fields[5],fields[6],fields[7],fields[8],fields[9],fields[10])); } } */ function uroApplyCWLGroups() { var objects = localStorage.UROverviewCWLGroups.split(':'); uroCWLGroups = []; if(objects.length === 0) { uroCWLGroups.push(new uroOWLGroupObj(0,'No group',false)); } else { for(var objIdx=0;objIdx<objects.length;objIdx++) { var fields = objects[objIdx].split(','); if(fields.length < 2) { fields.push(false); } uroCWLGroups.push(new uroOWLGroupObj(fields[0],fields[1],(fields[2] == 'true'))); } } } /* function uroApplyPlacesGroups() { var t = localStorage.UROverviewPlacesGroups.split(':'); for(var i=0;i<t.length;i++) { uroPlacesGroupsCollapsed[i] = (t[i] == "true"); } } */ function uroApplyFriendlyAreaNames() { var objects = localStorage.UROverviewFriendlyAreaNames.split(':'); uroFriendlyAreaNames = []; for(var objIdx=0;objIdx<objects.length;objIdx++) { var fields = objects[objIdx].split(','); uroFriendlyAreaNames.push(new uroAFNObj(fields[0],parseFloat(fields[1]),fields[2])); } uroReplaceAreaNames(true); } function uroTranslateLegacyMPTabSettings() { var options = localStorage.UROverviewMPOptions.split(':'); for(var optIdx=0;optIdx<options.length;optIdx++) { var fields = options[optIdx].split(','); if(fields[0].indexOf('_cb') === 0) { if(fields[0] == '_cbMPFilterParkingLotInputAsPoint') uroSetCBChecked('_cbMPFilter_T50', (fields[1] == 'true')); if(fields[0] == '_cbMPMissingPLP_T70') uroSetCBChecked('_cbMPFilter_T70', (fields[1] == 'true')); if(fields[0] == '_cbMPMissingPLP_T71') uroSetCBChecked('_cbMPFilter_T71', (fields[1] == 'true')); if(fields[0] == '_cbMPFilterDrivingDirectionMismatch') uroSetCBChecked('_cbMPFilter_T101', (fields[1] == 'true')); if(fields[0] == '_cbMPFilterMissingJunction') uroSetCBChecked('_cbMPFilter_T102', (fields[1] == 'true')); if(fields[0] == '_cbMPFilterMissingRoad') uroSetCBChecked('_cbMPFilter_T103', (fields[1] == 'true')); if(fields[0] == '_cbMPFilterCrossroadsJunctionMissing') uroSetCBChecked('_cbMPFilter_T104', (fields[1] == 'true')); if(fields[0] == '_cbMPFilterRoadTypeMismatch') uroSetCBChecked('_cbMPFilter_T105', (fields[1] == 'true')); if(fields[0] == '_cbMPFilterRestrictedTurn') uroSetCBChecked('_cbMPFilter_T106', (fields[1] == 'true')); if(fields[0] == '_cbMPFilterTurnProblem') uroSetCBChecked('_cbMPFilter_T200', (fields[1] == 'true')); if(fields[0] == '_cbMPFilterRoadClosureProblem') uroSetCBChecked('_cbMPFilter_T300', (fields[1] == 'true')); } } } function uroLoadSettings() { var isNewInstall = true; var isUpgradeInstall = true; var notifyAboutCustomIcons = true; uroAddLog('loadSettings()'); if (localStorage.UROverviewUROptions != null) { uroAddLog('recover UR tab settings'); uroApplySettings(localStorage.UROverviewUROptions); isNewInstall = false; } if (localStorage.UROverviewCameraOptions != null) { uroAddLog('recover camera tab settings'); uroApplySettings(localStorage.UROverviewCameraOptions); isNewInstall = false; } if (localStorage.UROverviewMPOptions != null) { uroAddLog('recover MP tab settings'); uroTranslateLegacyMPTabSettings(); uroApplySettings(localStorage.UROverviewMPOptions); isNewInstall = false; } if (localStorage.UROverviewPlacesOptions != null) { uroAddLog('recover Places tab settings'); uroApplySettings(localStorage.UROverviewPlacesOptions); isNewInstall = false; } if (localStorage.UROverviewMiscOptions != null) { uroAddLog('recover misc tab settings'); uroApplySettings(localStorage.UROverviewMiscOptions); isNewInstall = false; if(localStorage.UROverviewCurrentVersion != null) { notifyAboutCustomIcons = false; } else { if(uroGetCBChecked('_cbCustomRoadworksMarkers') === true) notifyAboutCustomIcons = false; if(uroGetCBChecked('_cbCustomConstructionMarkers')=== true) notifyAboutCustomIcons = false; if(uroGetCBChecked('_cbCustomClosuresMarkers') === true) notifyAboutCustomIcons = false; if(uroGetCBChecked('_cbCustomEventsMarkers') === true) notifyAboutCustomIcons = false; if(uroGetCBChecked('_cbCustomNotesMarkers') === true) notifyAboutCustomIcons = false; if(uroGetCBChecked('_cbCustomWSLMMarkers') === true) notifyAboutCustomIcons = false; if(uroGetCBChecked('_cbCustomBOGMarkers') === true) notifyAboutCustomIcons = false; if(uroGetCBChecked('_cbCustomDifficultMarkers') === true) notifyAboutCustomIcons = false; if(uroGetCBChecked('_cbCustomNativeSLMarkers') === true) notifyAboutCustomIcons = false; } } if(localStorage.UROverviewCWLGroups != null) { uroAddLog('recover CWL groups'); uroApplyCWLGroups(); isNewInstall = false; } else { uroAddLog('set default CWL group'); uroCWLGroups.push(new uroOWLGroupObj(0,'No group',false)); } if(localStorage.UROverviewCamWatchList != null) { uroAddLog('recover camera watchlist'); uroApplyCamWatchList(); uroGetCurrentCamWatchListObjects(); isNewInstall = false; } /* if(localStorage.UROverviewSegWatchList != null) { uroAddLog('recover segment watchlist'); uroApplySegWatchList(); uroGetCurrentSegWatchListObjects(); isNewInstall = false; } if(localStorage.UROverviewPlaceWatchList != null) { uroAddLog('recover places watchlist'); uroApplyPlaceWatchList(); //uroGetCurrentPlaceWatchListObjects(); isNewInstall = false; } if(localStorage.UROverviewPlacesGroups != null) { uroAddLog('recover places groups'); uroApplyPlacesGroups(); isNewInstall = false; } */ if(localStorage.UROverviewCurrentVersion != null) { uroAddLog('comparing install versions'); if(localStorage.UROverviewCurrentVersion == uroVersion) { isUpgradeInstall = false; } } if(localStorage.UROverviewFriendlyAreaNames != null) { uroAddLog('recover friendly area names'); uroApplyFriendlyAreaNames(); isNewInstall = false; } if(localStorage.UROverviewMasterEnable != null) { uroAddLog('recover master enable state'); document.getElementById('_cbMasterEnable').checked = (localStorage.UROverviewMasterEnable == "true"); } if(isNewInstall) { uroFirstTimerWelcomePack(); } else if(isUpgradeInstall) { uroShowUpdateNotes(); } if(notifyAboutCustomIcons) { uroAdvertiseCustomIcons(); } uroInhibitSave = false; } function uroDefaultSettings() { uroShowAlertBox("fa-warning", "URO+ Warning", "Resetting URO+ settings <b>cannot</b> be undone.<br>Are you <i>sure</i> you want to do this?", true, "Reset settings", "Keep settings", uroDefaultSettingsAction, null); } function uroDefaultSettingsAction() { var defaultSettings = ''; defaultSettings += '[UROverviewMPOptions][len=788]:_cbMPFilterParkingLotInputAsPoint,false:_cbMPFilterMissingJunction,false:_cbMPFilterMissingRoad,false:_cbMPFilterCrossroadsJunctionMissing,false:_cbMPFilterDrivingDirectionMismatch,false:_cbMPFilterRoadTypeMismatch,false:_cbMPFilterRestrictedTurn,false:_cbMPFilterRoadClosureProblem,false:_cbMPFilterUnknownProblem,false:_cbMPFilterTurnProblem,false:_cbFilterElgin,false:_cbFilterTrafficCast,false:_cbFilterTrafficMaster,false:_cbFilterCaltrans,false:_cbFilterTFL,false:_cbMPFilterReopenedProblem,false:_cbInvertMPFilter,false:_cbMPFilterOutsideArea,false:_cbMPFilterClosed,false:_cbMPFilterSolved,false:_cbMPFilterUnidentified,false:_cbMPClosedUserIDFilter,false:_cbMPNotClosedUserIDFilter,false:_cbMPFilterLowSeverity,false:_cbMPFilterMediumSeverity,false:_cbMPFilterHighSeverity,false[END]'; defaultSettings += '[UROverviewPlaceWatchList][len=0][END]'; defaultSettings += '[UROverviewSegWatchList][len=0][END]'; defaultSettings += '[UROverviewPlacesGroups][len=65]false:false:false:false:false:false:false:false:false:false:false[END]'; defaultSettings += '[UROverviewMasterEnable][len=4]true[END]'; defaultSettings += '[UROverviewFriendlyAreaNames][len=0][END]'; defaultSettings += '[UROverviewMiscOptions][len=1337]:_cbNativeConvoMarkers,true:_cbNativeBetaConvoMarkers,true:_cbCommentCount,false:_cbURBackfill,false:_inputUnstackSensitivity,15:_inputUnstackZoomLevel,3:_cbCustomRoadworksMarkers,false:_cbCustomConstructionMarkers,false:_cbCustomClosuresMarkers,false:_cbCustomEventsMarkers,false:_cbCustomNotesMarkers,false:_cbCustomBOGMarkers,false:_cbCustomDifficultMarkers,false:_cbCustomWSLMMarkers,false:_cbCustomNativeSLMarkers,false:_cbCustomKeywordMarkers,false:_textCustomKeyword,:_cbCustomElginMarkers,false:_cbCustomTrafficMasterMarkers,false:_cbCustomTrafficCastMarkers,false:_cbCustomCaltransMarkers,false:_cbCustomTFLMarkers,false:_inputPopupDwellTimeout,2:_inputPopupEntryTimeout,2:_inputMaxJitter,2:_cbInhibitURPopup,false:_cbInhibitMPPopup,false:_cbInhibitCamPopup,false:_cbInhibitSegPopup,false:_cbInhibitSegGenericPopup,false:_cbInhibitTurnsPopup,false:_cbInhibitLandmarkPopup,false:_cbInhibitPUPopup,false:_cbDateFmtDDMMYY,true:_cbDateFmtMMDDYY,false:_cbDateFmtYYMMDD,false:_cbTimeFmt24H,true:_cbTimeFmt12H,false:_cbWhiteBackground,false:_inputCustomBackgroundRed,255:_inputCustomBackgroundGreen,255:_inputCustomBackgroundBlue,255:_cbInhibitNURButton,false:_cbInhibitNMPButton,false:_cbInhibitNPURButton,false:_cbHideAMLayer,false:_cbDisablePlacesFiltering,false:_cbDisableTabStyling,false:_cbHideEditorInfo,false:_cbEnableDTE,false[END]'; defaultSettings += '[UROverviewUROptions][len=1756]:_cbURFilterOutsideArea,false:_cbNoFilterForURInURL,false:_cbFilterWazeAuto,false:_cbFilterIncorrectTurn,false:_cbFilterIncorrectAddress,false:_cbFilterIncorrectRoute,false:_cbFilterMissingRoundabout,false:_cbFilterGeneralError,false:_cbFilterTurnNotAllowed,false:_cbFilterIncorrectJunction,false:_cbFilterMissingBridgeOverpass,false:_cbFilterWrongDrivingDirection,false:_cbFilterMissingExit,false:_cbFilterMissingRoad,false:_cbFilterBlockedRoad,false:_cbFilterMissingLandmark,false:_cbFilterSpeedLimits,false:_cbFilterUndefined,false:_cbFilterRoadworks,false:_cbFilterConstruction,false:_cbFilterClosure,false:_cbFilterEvent,false:_cbFilterNote,false:_cbFilterBOG,false:_cbFilterDifficult,false:_cbFilterWSLM,false:_cbInvertURFilter,false:_cbFilterOpenUR,false:_cbFilterClosedUR,false:_cbFilterSolved,false:_cbFilterUnidentified,false:_cbEnableMinAgeFilter,false:_inputFilterMinDays,:_cbEnableMaxAgeFilter,false:_inputFilterMaxDays,:_cbHideMyFollowed,false:_cbHideMyUnfollowed,false:_cbURDescriptionMustBePresent,false:_cbURDescriptionMustBeAbsent,false:_cbEnableKeywordMustBePresent,false:_textKeywordPresent,:_cbEnableKeywordMustBeAbsent,false:_textKeywordAbsent,:_cbCaseInsensitive,false:_cbHideMyComments,false:_cbHideAnyComments,false:_cbHideIfLastCommenter,false:_cbHideIfNotLastCommenter,false:_cbHideIfReporterLastCommenter,false:_cbHideIfReporterNotLastCommenter,false:_cbEnableMinCommentsFilter,false:_inputFilterMinComments,:_cbEnableMaxCommentsFilter,false:_inputFilterMaxComments,:_cbEnableCommentAgeFilter2,false:_inputFilterCommentDays2,:_cbEnableCommentAgeFilter,false:_inputFilterCommentDays,:_cbIgnoreOtherEditorComments,false:_cbURUserIDFilter,false:_cbURResolverIDFilter,false:_cbInvertURStateFilter,false:_cbNoFilterForTaggedURs,false[END]'; defaultSettings += '[UROverviewCameraOptions][len=878]:_cbShowWorldCams,true:_cbShowUSACams,true:_cbShowNonWorldCams,true:_cbShowOnlyCamsCreatedBy,false:_cbShowOnlyCamsEditedBy,false:_textCameraEditor,:_cbShowOnlyMyCams,false:_cbShowApprovedCams,true:_cbShowNonApprovedCams,true:_cbShowOlderCreatedNonApproved,false:_inputCameraMinCreatedDays,:_cbShowOlderUpdatedNonApproved,false:_inputCameraMinUpdatedDays,:_cbShowSpeedCams,true:_cbShowIfSpeedSet,true:_cbShowIfNoSpeedSet,true:_cbShowRedLightCams,true:_cbShowDummyCams,true:_cbHideCreatedByMe,false:_cbHideCreatedByRank0,false:_cbHideCreatedByRank1,false:_cbHideCreatedByRank2,false:_cbHideCreatedByRank3,false:_cbHideCreatedByRank4,false:_cbHideCreatedByRank5,false:_cbHideUpdatedByMe,false:_cbHideUpdatedByRank0,false:_cbHideUpdatedByRank1,false:_cbHideUpdatedByRank2,false:_cbHideUpdatedByRank3,false:_cbHideUpdatedByRank4,false:_cbHideUpdatedByRank5,false:_cbHideCWLCams,false[END]'; defaultSettings += '[UROverviewCamWatchList][len=0][END]'; defaultSettings += '[UROverviewPlacesOptions][len=5421]:_cbFilterUneditablePlaceUpdates,false:_cbFilterLockRankedPlaceUpdates,false:_cbFilterNewPlacePUR,false:_cbFilterUpdatedDetailsPUR,false:_cbFilterNewPhotoPUR,false:_cbFilterFlaggedPUR,false:_cbLeavePURGeos,false:_cbInvertPURFilters,false:_cbPURFilterLowSeverity,false:_cbPURFilterMediumSeverity,false:_cbPURFilterHighSeverity,false:_cbEnablePURMinAgeFilter,false:_inputPURFilterMinDays,:_cbEnablePURMaxAgeFilter,false:_inputPURFilterMaxDays,:_cbPlaceFilterEditedLessThan,false:_inputFilterPlaceEditMinDays,:_cbPlaceFilterEditedMoreThan,false:_inputFilterPlaceEditMaxDays,:_cbHidePlacesL0,false:_cbHidePlacesL1,false:_cbHidePlacesL2,false:_cbHidePlacesL3,false:_cbHidePlacesL4,false:_cbHidePlacesL5,false:_cbHidePlacesStaff,false:_cbHidePlacesAdLocked,false:_cbHideAreaPlaces,false:_cbHidePointPlaces,false:_cbHidePhotoPlaces,false:_cbHideNoPhotoPlaces,false:_cbHideLinkedPlaces,false:_cbHideNoLinkedPlaces,false:_cbHideKeywordPlaces,false:_cbHideNoKeywordPlaces,false:_textKeywordPlace,:_cbShowOnlyPlacesCreatedBy,false:_cbShowOnlyPlacesEditedBy,false:_textPlacesEditor,:_cbPlacesFilter-CAR_SERVICES,false:_cbPlacesFilter-GAS_STATION,false:_cbPlacesFilter-GARAGE_AUTOMOTIVE_SHOP,false:_cbPlacesFilter-CAR_WASH,false:_cbPlacesFilter-CHARGING_STATION,false:_cbPlacesFilter-TRANSPORTATION,false:_cbPlacesFilter-AIRPORT,false:_cbPlacesFilter-BUS_STATION,false:_cbPlacesFilter-FERRY_PIER,false:_cbPlacesFilter-SEAPORT_MARINA_HARBOR,false:_cbPlacesFilter-SUBWAY_STATION,false:_cbPlacesFilter-TRAIN_STATION,false:_cbPlacesFilter-BRIDGE,false:_cbPlacesFilter-TUNNEL,false:_cbPlacesFilter-TAXI_STATION,false:_cbPlacesFilter-JUNCTION_INTERCHANGE,false:_cbPlacesFilter-PROFESSIONAL_AND_PUBLIC,false:_cbPlacesFilter-COLLEGE_UNIVERSITY,false:_cbPlacesFilter-SCHOOL,false:_cbPlacesFilter-CONVENTIONS_EVENT_CENTER,false:_cbPlacesFilter-GOVERNMENT,false:_cbPlacesFilter-LIBRARY,false:_cbPlacesFilter-CITY_HALL,false:_cbPlacesFilter-ORGANIZATION_OR_ASSOCIATION,false:_cbPlacesFilter-PRISON_CORRECTIONAL_FACILITY,false:_cbPlacesFilter-COURTHOUSE,false:_cbPlacesFilter-CEMETERY,false:_cbPlacesFilter-FIRE_DEPARTMENT,false:_cbPlacesFilter-POLICE_STATION,false:_cbPlacesFilter-MILITARY,false:_cbPlacesFilter-HOSPITAL_MEDICAL_CARE,false:_cbPlacesFilter-OFFICES,false:_cbPlacesFilter-POST_OFFICE,false:_cbPlacesFilter-RELIGIOUS_CENTER,false:_cbPlacesFilter-KINDERGARDEN,false:_cbPlacesFilter-FACTORY_INDUSTRIAL,false:_cbPlacesFilter-EMBASSY_CONSULATE,false:_cbPlacesFilter-INFORMATION_POINT,false:_cbPlacesFilter-SHOPPING_AND_SERVICES,false:_cbPlacesFilter-ARTS_AND_CRAFTS,false:_cbPlacesFilter-BANK_FINANCIAL,false:_cbPlacesFilter-SPORTING_GOODS,false:_cbPlacesFilter-BOOKSTORE,false:_cbPlacesFilter-PHOTOGRAPHY,false:_cbPlacesFilter-CAR_DEALERSHIP,false:_cbPlacesFilter-FASHION_AND_CLOTHING,false:_cbPlacesFilter-CONVENIENCE_STORE,false:_cbPlacesFilter-PERSONAL_CARE,false:_cbPlacesFilter-DEPARTMENT_STORE,false:_cbPlacesFilter-PHARMACY,false:_cbPlacesFilter-ELECTRONICS,false:_cbPlacesFilter-FLOWERS,false:_cbPlacesFilter-FURNITURE_HOME_STORE,false:_cbPlacesFilter-GIFTS,false:_cbPlacesFilter-GYM_FITNESS,false:_cbPlacesFilter-SWIMMING_POOL,false:_cbPlacesFilter-HARDWARE_STORE,false:_cbPlacesFilter-MARKET,false:_cbPlacesFilter-SUPERMARKET_GROCERY,false:_cbPlacesFilter-JEWELRY,false:_cbPlacesFilter-LAUNDRY_DRY_CLEAN,false:_cbPlacesFilter-SHOPPING_CENTER,false:_cbPlacesFilter-MUSIC_STORE,false:_cbPlacesFilter-PET_STORE_VETERINARIAN_SERVICES,false:_cbPlacesFilter-TOY_STORE,false:_cbPlacesFilter-TRAVEL_AGENCY,false:_cbPlacesFilter-ATM,false:_cbPlacesFilter-CURRENCY_EXCHANGE,false:_cbPlacesFilter-CAR_RENTAL,false:_cbPlacesFilter-FOOD_AND_DRINK,false:_cbPlacesFilter-RESTAURANT,false:_cbPlacesFilter-BAKERY,false:_cbPlacesFilter-DESSERT,false:_cbPlacesFilter-CAFE,false:_cbPlacesFilter-FAST_FOOD,false:_cbPlacesFilter-FOOD_COURT,false:_cbPlacesFilter-BAR,false:_cbPlacesFilter-ICE_CREAM,false:_cbPlacesFilter-CULTURE_AND_ENTERTAINEMENT,false:_cbPlacesFilter-ART_GALLERY,false:_cbPlacesFilter-CASINO,false:_cbPlacesFilter-CLUB,false:_cbPlacesFilter-TOURIST_ATTRACTION_HISTORIC_SITE,false:_cbPlacesFilter-MOVIE_THEATER,false:_cbPlacesFilter-MUSEUM,false:_cbPlacesFilter-MUSIC_VENUE,false:_cbPlacesFilter-PERFORMING_ARTS_VENUE,false:_cbPlacesFilter-GAME_CLUB,false:_cbPlacesFilter-STADIUM_ARENA,false:_cbPlacesFilter-THEME_PARK,false:_cbPlacesFilter-ZOO_AQUARIUM,false:_cbPlacesFilter-RACING_TRACK,false:_cbPlacesFilter-THEATER,false:_cbPlacesFilter-OTHER,false:_cbPlacesFilter-CONSTRUCTION_SITE,false:_cbPlacesFilter-LODGING,false:_cbPlacesFilter-HOTEL,false:_cbPlacesFilter-HOSTEL,false:_cbPlacesFilter-CAMPING_TRAILER_PARK,false:_cbPlacesFilter-COTTAGE_CABIN,false:_cbPlacesFilter-BED_AND_BREAKFAST,false:_cbPlacesFilter-OUTDOORS,false:_cbPlacesFilter-PARK,false:_cbPlacesFilter-PLAYGROUND,false:_cbPlacesFilter-BEACH,false:_cbPlacesFilter-SPORTS_COURT,false:_cbPlacesFilter-GOLF_COURSE,false:_cbPlacesFilter-PLAZA,false:_cbPlacesFilter-PROMENADE,false:_cbPlacesFilter-POOL,false:_cbPlacesFilter-SCENIC_LOOKOUT_VIEWPOINT,false:_cbPlacesFilter-SKI_AREA,false:_cbPlacesFilter-NATURAL_FEATURES,false:_cbPlacesFilter-ISLAND,false:_cbPlacesFilter-SEA_LAKE_POOL,false:_cbPlacesFilter-RIVER_STREAM,false:_cbPlacesFilter-FOREST_GROVE,false:_cbPlacesFilter-FARM,false:_cbPlacesFilter-CANAL,false:_cbPlacesFilter-SWAMP_MARSH,false:_cbPlacesFilter-DAM,false:_cbPlacesFilter-PARKING_LOT,false:_cbFilterPrivatePlaces,false:_cbInvertPlacesFilter,false[END]'; defaultSettings += '[UROverviewCurrentVersion][len=0][END]'; defaultSettings += '[UROverviewCWLGroups][len=16]0,No group,false[END]'; document.getElementById('_txtSettings').value = defaultSettings; uroTextToSettings(); document.getElementById('_txtSettings').value = ''; } function uroSettingsToText() { var txtSettings = ''; uroSaveSettings(); for(var lsEntry in localStorage) { if(lsEntry.indexOf('UROverview') === 0) { txtSettings += '['+lsEntry+'][len=' + localStorage[lsEntry].length + ']' + localStorage[lsEntry] + '[END]\n'; } } document.getElementById('_txtSettings').value = txtSettings; document.getElementById('_txtSettings').focus(); document.getElementById('_txtSettings').select(); } function uroTextToSettings() { var txtSettings = ''; txtSettings = uroGetElmValue('_txtSettings'); if(txtSettings.indexOf('[END]') == -1) return; var subText = txtSettings.split('[END]'); for(var i=0;i<subText.length;i++) { var aPos = subText[i].indexOf('['); var bPos = subText[i].indexOf(']'); if((aPos != -1) && (bPos != -1)) { var settingID = subText[i].substr(aPos+1,bPos-1-aPos); subText[i] = subText[i].substr(bPos+1); bPos = subText[i].indexOf(']'); if(bPos != -1) { var settingLength = subText[i].substr(5,bPos-5); subText[i] = subText[i].substr(bPos+1); if(subText[i].length == settingLength) { localStorage[settingID] = subText[i]; } } } } uroLoadSettings(); } function uroClearSettingsText() { document.getElementById('_txtSettings').value = ''; } function uroDateToDays(dateToConvert) { var dateNow = new Date(); var elapsedSinceEpoch = dateNow.getTime(); var elapsedSinceEvent = elapsedSinceEpoch - dateToConvert; dateNow.setHours(0); dateNow.setMinutes(0); dateNow.setSeconds(0); dateNow.setMilliseconds(0); var elapsedSinceMidnight = elapsedSinceEpoch - dateNow.getTime(); if(elapsedSinceEvent < elapsedSinceMidnight) { // event occurred today... return 0; } else { // event occurred at some point prior to midnight this morning, so return a minimum value of 1... return 1 + Math.floor((elapsedSinceEvent - elapsedSinceMidnight) / 86400000); } } function uroGetURAge(urObj,ageType,getRaw) { if(ageType === 0) { if((urObj.attributes.driveDate === null)||(urObj.attributes.driveDate === 0)) return -1; if(getRaw) return urObj.attributes.driveDate; else return uroDateToDays(urObj.attributes.driveDate); } else if(ageType === 1) { if((urObj.attributes.resolvedOn === null)||(urObj.attributes.resolvedOn === 0)) return -1; if(getRaw) return urObj.attributes.resolvedOn; else return uroDateToDays(urObj.attributes.resolvedOn); } else { return -1; } } function uroGetMCAge(mcObj,ageType,getRaw) { if(ageType === 0) { if((mcObj.attributes.createdOn === null)||(mcObj.attributes.createdOn === 0)) return -1; if(getRaw) return mcObj.attributes.createdOn; else return uroDateToDays(mcObj.attributes.createdOn); } else if(ageType === 1) { if((mcObj.attributes.updatedOn === null)||(mcObj.attributes.updatedOn === 0)) return -1; if(getRaw) return mcObj.attributes.updatedOn; else return uroDateToDays(mcObj.attributes.updatedOn); } else { return -1; } } function uroGetPURAge(purObj) { if(purObj.attributes.venueUpdateRequests[0].attributes.dateAdded !== null) { return uroDateToDays(purObj.attributes.venueUpdateRequests[0].attributes.dateAdded); } else { return -1; } } function uroGetCameraAge(camObj, mode) { if(mode === 0) { if(camObj.attributes.updatedOn === null) return -1; return uroDateToDays(camObj.attributes.updatedOn); } if(mode === 1) { if(camObj.attributes.createdOn === null) return -1; return uroDateToDays(camObj.attributes.createdOn); } } function uroGetCommentAge(commentObj) { if(commentObj.createdOn === null) return -1; return uroDateToDays(commentObj.createdOn); } function uroParseDaysAgo(days) { if(days === 0) return 'today'; else if(days === 1) return '1 day ago'; else return days+' days ago'; } function uroGetLocalisedSpeedString(camSpeed, includeValidity) { if(camSpeed !== null) { var conversionFactor = 1; // default to metric var multipleFactor = 10; // default to limits being set in multiples of 10 var country; if(W.model.countries.top === undefined) { country = W.model.countries.additionalInfo[0].name; } else { country = W.model.countries.top.name; } if(country !== null) { // country-specific deviations from the above... if ( (country == "United Kingdom") || (country == "Jersey") || (country == "Guernsey") || (country == "United States") ) { // countries using MPH conversionFactor = 1.609; } if ( (country == "United States") || (country == "Guernsey") ) { // countries with speed limits set in multiples of 5 multipleFactor = 5; } } var speed = Math.round(camSpeed / conversionFactor); var retval = speed; if(conversionFactor == 1) retval += "KM/H"; else retval += "MPH"; if(includeValidity === true) { // special handling for the 7KM/H spielstrasse found in Germany... if(country == "Germany") { if(speed != 7) { if(speed % multipleFactor !== 0) retval += " (not valid?)"; } } else { if(speed % multipleFactor !== 0) retval += " (not valid?)"; } } return retval; } else return "not set"; } // -------------------------------------------------------------------------------------------------------------------- // AREA FRIENDLYNAME STUFF // -------------------------------------------------------------------------------------------------------------------- function uroAFNObj(fName, area, server) { this.fName = fName; this.area = area; this.server = server; } function uroUpdateAreaName(name, server, area) { var foundExisting = false; for(var i=0; i<uroFriendlyAreaNames.length; i++) { if((uroFriendlyAreaNames[i].server == server) && (uroFriendlyAreaNames[i].area == area)) { if(name === "") { uroFriendlyAreaNames.splice(i,1); foundExisting = true; } else { uroFriendlyAreaNames[i].fName = name; foundExisting = true; } } } if((foundExisting === false) && (name !== "")) { uroFriendlyAreaNames.push(new uroAFNObj(name,area,server)); } uroReplaceAreaNames(true); } function uroAreaNameHover() { if((uroAreaNameHoverObj === null) || (uroAreaNameHoverObj != this)) { uroAreaNameHoverTime = 0; } uroAreaNameHoverObj = this; } function uroAreaNameUnHover() { if(uroANEditHovered === true) { return false; } if(uroAreaNameOverlayShown) { uroAreaNameHoverObj.removeChild(uroANEditBox); } uroAreaNameHoverObj = null; uroAreaNameHoverTime = -1; uroAreaNameOverlayShown = false; } function uroANEditHover() { uroANEditHovered = true; uroAddEventListener('uroANEditBox','mouseout',uroANEditUnHover,false); uroAddEventListener('uroANEditBox','click',uroANEditClick,false); } function uroANEditUnHover() { var newName = document.getElementById('_textAreaName').value; // sanitise name to avoid conflicts with config storage delimiters... newName = newName.replace(',',''); newName = newName.replace(':',''); var server = W.location.code; var area = uroGetAreaArea(uroAreaNameHoverObj.parentNode.children[1]); uroAreaNameHoverObj.removeChild(uroANEditBox); uroAreaNameOverlayShown = false; uroANEditHovered = false; uroUpdateAreaName(newName, server, area); } function uroANEditClick(e) { // this traps the click to prevent it falling through to the underlying area name element and // potentially causing the map view to be relocated to that area... e.stopPropagation(); } function uroGetAreaArea(listObj) { var area = listObj.getElementsByTagName('span')[0].innerHTML; area = parseFloat(area.split(' ')[0]); return area; } function uroAreaNameOverlaySetup() { uroAreaNameOverlayShown = true; uroANEditBox = document.createElement('div'); uroANEditBox.id = "uroANEditBox"; uroANEditBox.style.position = "absolute"; uroANEditBox.style.top = '7px'; uroANEditBox.style.left = '2px'; uroANEditBox.style.width = "99%"; uroAreaNameHoverObj.appendChild(uroANEditBox); uroANEditBox.onmouseover = uroANEditHover(); var existingName = uroAreaNameHoverObj.innerHTML; var italicTagPos = existingName.indexOf(' <i>'); if(italicTagPos == -1) { existingName = ""; } else { existingName = existingName.substr(0,italicTagPos); } uroANEditBox.innerHTML = '<input type="text" style="font-size:14px; line-height:16px; height:22px; width:100%" id="_textAreaName" value="'+existingName+'">'; } function uroReplaceAreaNames(replaceAfterNameChange) { if(document.getElementById('sidepanel-areas') === undefined) { return; } if(replaceAfterNameChange === false) { if(document.getElementById('sidepanel-areas').getElementsByClassName('result-list')[0].id == "friendlyNamed") { return; } } var panelRootObj = document.getElementById('sidepanel-areas').getElementsByClassName('result-list')[0]; if(panelRootObj === undefined) { // we get here if the user doesn't have any areas defined... return; } var areaCount = panelRootObj.children.length; if(areaCount === 0) { return; } var localisedManagedArea = I18n.lookup("user.areas.managed_area"); for(var loop=0; loop < areaCount; loop++) { var childObjPElems = panelRootObj.children[loop].getElementsByTagName('p'); var title = childObjPElems[0].innerHTML; if(title.indexOf(localisedManagedArea) > -1) { var area = uroGetAreaArea(childObjPElems[1]); childObjPElems[0].innerHTML = localisedManagedArea; for(var fnIdx=0; fnIdx < uroFriendlyAreaNames.length; fnIdx++) { var fnObj = uroFriendlyAreaNames[fnIdx]; if((fnObj.area == area) && (fnObj.server == W.location.code)) { childObjPElems[0].innerHTML = fnObj.fName +' <i>('+localisedManagedArea+')</i>'; break; } } var titleObj = panelRootObj.getElementsByClassName('title')[loop]; titleObj.addEventListener("mouseover", uroAreaNameHover, false); titleObj.addEventListener("mouseout", uroAreaNameUnHover, false); titleObj.style.cursor = "text"; } } document.getElementById('sidepanel-areas').getElementsByClassName('result-list')[0].id = "friendlyNamed"; } // -------------------------------------------------------------------------------------------------------------------- // WATCHLIST STUFF // -------------------------------------------------------------------------------------------------------------------- // Generic Functions function uroTypeCast(varin) { if(varin == "null") return null; if(typeof varin == "string") return parseInt(varin); return varin; } function uroTruncate(val) { if(val === null) return val; if(val < 0) return Math.ceil(val); return Math.floor(val); } function uroOWLGroupObj(groupID, groupName, groupCollapsed) { groupID = uroTypeCast(groupID); this.groupID = groupID; this.groupName = groupName; this.groupCount = 0; this.groupCollapsed = groupCollapsed; } // Camera Functions function uroCamWatchObjCheckProps(type, azymuth, speed, validated, lat, lon) { if(type !== null) type = uroTypeCast(type); if(azymuth !== null) azymuth = uroTruncate(uroTypeCast(azymuth)%360); if(speed !== null) speed = uroTruncate(uroTypeCast(speed)); if(typeof validated == "string") validated = (validated == "true"); if(lat !== null) lat = uroTruncate(uroTypeCast(lat)); if(lon !== null) lon = uroTruncate(uroTypeCast(lon)); this.type = type; this.azymuth = azymuth; this.speed = speed; this.validated = validated; this.lat = lat; this.lon = lon; } function uroCamWatchObj(persistent, fid, lon, lat, type, azymuth, speed, validated, groupID, server) { fid = uroTypeCast(fid); groupID = uroTypeCast(groupID); if(typeof persistent == "string") persistent = (persistent == "true"); this.fid = fid; this.persistent = persistent; this.loaded = false; this.server = server; this.groupID = groupID; this.watch = new uroCamWatchObjCheckProps(type, azymuth, speed, validated, lat, lon); this.current = new uroCamWatchObjCheckProps(null, null, null, null, null, null); } function uroCamDataChanged(idx) { var camObj = uroCamWatchObjects[idx]; if(camObj.loaded === false) return false; if(camObj.current.type != camObj.watch.type) return true; if(camObj.current.azymuth != camObj.watch.azymuth) return true; if(camObj.current.speed != camObj.watch.speed) return true; if(camObj.current.validated != camObj.watch.validated) return true; if(camObj.current.lat != camObj.watch.lat) return true; if(camObj.current.lon != camObj.watch.lon) return true; return false; } function uroFindCWLGroupByIdx(groupIdx) { var groupName = ''; for(var loop=0;loop<uroCWLGroups.length;loop++) { if(uroCWLGroups[loop].groupID == groupIdx) { groupName = uroCWLGroups[loop].groupName; break; } } return groupName; } function uroIsCamOnWatchList(fid) { for(var loop=0;loop<uroCamWatchObjects.length;loop++) { if(uroCamWatchObjects[loop].fid == fid) return loop; } return -1; } function uroAddCurrentCamWatchData(idx, lat, lon, type, azymuth, speed, validated, server) { var camObj = uroCamWatchObjects[idx]; camObj.loaded = true; camObj.server = server; camObj.current = new uroCamWatchObjCheckProps(type, azymuth, speed, validated, lat, lon); return(uroCamDataChanged(idx)); } function uroAddCamToWatchList() { if(uroIsCamOnWatchList(uroShownFID) == -1) { var camObj = W.model.cameras.objects[uroShownFID]; uroCamWatchObjects.push(new uroCamWatchObj(true, uroShownFID, camObj.geometry.x, camObj.geometry.y, camObj.attributes.type, camObj.attributes.azymuth, camObj.attributes.speed, camObj.attributes.validated, 0, W.location.code)); uroAddCurrentCamWatchData(uroCamWatchObjects.length-1, camObj.geometry.y, camObj.geometry.x, camObj.attributes.type, camObj.attributes.azymuth, camObj.attributes.speed, camObj.attributes.validated, W.location.code); uroAddLog('added camera '+uroShownFID+' to watchlist'); uroOWLUpdateHTML(); } } function uroRemoveCamFromWatchList() { var camidx = uroIsCamOnWatchList(uroShownFID); if(camidx != -1) { uroCamWatchObjects.splice(camidx,1); uroAddLog('removed camera '+uroShownFID+' from watchlist'); uroOWLUpdateHTML(); } } function uroUpdateCamWatchList() { var camIdx = uroIsCamOnWatchList(uroShownFID); if(camIdx != -1) { var camObj = W.model.cameras.objects[uroShownFID]; uroCamWatchObjects[camIdx].watch = new uroCamWatchObjCheckProps(camObj.attributes.type, camObj.attributes.azymuth, camObj.attributes.speed, camObj.attributes.validated, camObj.geometry.y, camObj.geometry.x); } } function uroClearCamWatchList() { uroShowAlertBox("fa-warning", "URO+ Warning", "Removing all cameras from the OWL <b>cannot</b> be undone.<br>Are you <i>sure</i> you want to do this?", true, "Delete ALL Cameras", "Keep Cameras", uroClearCamWatchListAction, null); } function uroClearCamWatchListAction() { uroCamWatchObjects = []; uroOWLUpdateHTML(); } function uroRetrieveCameras(lat, lon) { var camPos = new OpenLayers.LonLat(); var camChanged = false; camPos.lon = lon; camPos.lat = lat; camPos.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326")); var camURL = 'https://' + document.location.host; camURL += Waze.Config.api_base; camURL += '/Features?language=en&cameras=true&bbox='; var latl = camPos.lat - 0.25; var latu = camPos.lat + 0.25; var lonl = camPos.lon - 0.25; var lonr = camPos.lon + 0.25; camURL += lonl+','+latl+','+lonr+','+latu; uroAddLog('retrieving camera data around '+camPos.lon+','+camPos.lat); var camReq = new XMLHttpRequest(); camReq.open('GET',camURL,false); try { camReq.send(); uroAddLog('response '+camReq.status+' received'); if (camReq.status === 200) { var camData = JSON.parse(camReq.responseText); for(var camIdx = 0; camIdx < camData.cameras.objects.length; camIdx++) { var camObj = camData.cameras.objects[camIdx]; var listIdx = uroIsCamOnWatchList(camObj.id); if(listIdx != -1) { camPos.lon = camObj.geometry.coordinates[0]; camPos.lat = camObj.geometry.coordinates[1]; camPos.transform(new OpenLayers.Projection("EPSG:4326"),new OpenLayers.Projection("EPSG:900913")); camPos.lon = uroTruncate(camPos.lon); camPos.lat = uroTruncate(camPos.lat); camChanged |= uroAddCurrentCamWatchData(listIdx, camPos.lat, camPos.lon, camObj.type, camObj.azymuth, camObj.speed, camObj.validated, W.location.code); } else if(camObj.validated === false) { } } } else { uroAddLog('request failed (status != 200)'); } } catch(err) { uroAddLog('camera load request failed (exception '+err+' caught)'); } return camChanged; } function uroGetCurrentCamWatchListObjects() { var camChanged = false; var camsChanged = []; var camsDeleted = []; var camidx; var camObj; for(camidx=0;camidx<uroCamWatchObjects.length;camidx++) { camObj = uroCamWatchObjects[camidx]; if((camObj.loaded === false) && ((camObj.server == W.location.code) || (camObj.server == '??'))) { if(typeof W.model.cameras.objects[camObj.fid] == 'object') { if(W.model.cameras.objects[camObj.fid].state != "Delete") { var wazeObj = W.model.cameras.objects[camObj.fid]; camChanged |= uroAddCurrentCamWatchData(camidx, wazeObj.geometry.y, wazeObj.geometry.x, wazeObj.attributes.type, wazeObj.attributes.azymuth, wazeObj.attributes.speed, wazeObj.attributes.validated); } else { camChanged |= uroRetrieveCameras(camObj.watch.lat, camObj.watch.lon); } } else { camChanged |= uroRetrieveCameras(camObj.watch.lat, camObj.watch.lon); } } } if(camChanged) { for(camidx=0;camidx<uroCamWatchObjects.length;camidx++) { if(uroCamDataChanged(camidx)) { camsChanged.push(uroCamWatchObjects[camidx]); } } } for(camidx=0;camidx<uroCamWatchObjects.length;camidx++) { camObj = uroCamWatchObjects[camidx]; if((camObj.loaded === false) && (camObj.server == W.location.code)) { camsDeleted.push(camObj); } } if((camsChanged.length > 0) || (camsDeleted.length > 0)) { var alertStr = ''; for(camidx=0;camidx<camsChanged.length;camidx++) { alertStr += 'Camera ID '+camsChanged[camidx].fid+' in group "'+uroFindCWLGroupByIdx(camsChanged[camidx].groupID)+'" has been changed<br>'; } alertStr += '<br>'; for(camidx=0;camidx<camsDeleted.length;camidx++) { alertStr += 'Camera ID '+camsDeleted[camidx].fid+' in group "'+uroFindCWLGroupByIdx(camsDeleted[camidx].groupID)+'" has been deleted<br>'; } uroShowAlertBox("fa-info-circle", "URO+ Camera Watchlist Alert", alertStr, false, "OK", null, null, null); } } function uroClearDeletedCameras() { for(var camidx=uroCamWatchObjects.length-1;camidx>=0;camidx--) { if(uroCamWatchObjects[camidx].loaded === false) { uroShownFID = uroCamWatchObjects[camidx].fid; uroRemoveCamFromWatchList(); } } } function uroClearUnknownServerCameras() { var confirmMsg = '<p>Cameras with an unknown server <i>cannot</i> be automatically verified by URO+</p>'; confirmMsg += 'It is recommended that you manually load WME from each server (World, USA/Canada and Israel) to give URO+ a chance of locating these cameras.<br>'; confirmMsg += 'If the cameras then continue to show up as an unknown server, it is safe to delete them...<br><br>'; confirmMsg += 'Do you still wish to proceed with deleting all unknown server cameras?'; uroShowAlertBox("fa-warning", "URO+ Warning", confirmMsg, true, "Delete unknown cameras", "Keep unknown cameras", uroClearUnknownServerCamerasAction, null); } function uroClearUnknownServerCamerasAction() { for(var camidx=uroCamWatchObjects.length-1;camidx>=0;camidx--) { if(uroCamWatchObjects[camidx].server == '??') { uroShownFID = uroCamWatchObjects[camidx].fid; uroRemoveCamFromWatchList(); } } } function uroRescanCamWatchList() { for(var camidx=0;camidx<uroCamWatchObjects.length;camidx++) { uroCamWatchObjects[camidx].loaded = false; } uroGetCurrentCamWatchListObjects(); uroOWLUpdateHTML(); } function uroGotoCam() { var camidx = this.id.substr(13); var camPos = new OpenLayers.LonLat(); camPos.lon = uroCamWatchObjects[camidx].watch.lon; camPos.lat = uroCamWatchObjects[camidx].watch.lat; W.map.setCenter(camPos,4); W.map.camerasLayer.setVisibility(true); return false; } // Segment Functions /* function uroSegWatchObjCheckProps(left, right, bottom, top, fromNode, toNode, fwdDir, revDir, length, level, rank, roadType, updatedOn) { if(left !== null) left = uroTruncate(uroTypeCast(left)); if(right !== null) right = uroTruncate(uroTypeCast(right)); if(bottom !== null) bottom = uroTruncate(uroTypeCast(bottom)); if(top !== null) top = uroTruncate(uroTypeCast(top)); if(fromNode !== null) fromNode = uroTypeCast(fromNode); if(toNode !== null) toNode = uroTypeCast(toNode); if(fwdDir !== null) fwdDir = uroTypeCast(fwdDir); if(revDir !== null) revDir = uroTypeCast(revDir); if(length !== null) length = uroTypeCast(length); if(level !== null) level = uroTypeCast(level); if(rank !== null) rank = uroTypeCast(rank); if(roadType !== null) roadType = uroTypeCast(roadType); if(updatedOn !== null) updatedOn = uroTypeCast(updatedOn); this.left = left; this.right = right; this.bottom = bottom; this.top = top; this.fromNode = fromNode; this.toNode = toNode; this.fwdDir = fwdDir; this.revDir = revDir; this.length = length; this.level = level; this.rank = rank; this.roadType = roadType; this.updatedOn = updatedOn; } function uroSegWatchObj(persistent, fid, left, right, bottom, top, fromNode, toNode, fwdDir, revDir, length, level, rank, roadType, updatedOn, groupID, server) { fid = uroTypeCast(fid); groupID = uroTypeCast(groupID); if(typeof persistent == "string") persistent = (persistent == "true"); this.fid = fid; this.persistent = persistent; this.loaded = false; this.server = server; this.groupID = groupID; this.watch = new uroSegWatchObjCheckProps(left, right, bottom, top, fromNode, toNode, fwdDir, revDir, length, level, rank, roadType, updatedOn); this.current = new uroSegWatchObjCheckProps(null, null, null, null, null, null, null, null, null, null, null, null, null); } function uroSegDataChanged(idx) { var segObj = uroSegWatchObjects[idx]; if(segObj.loaded === false) return false; if(segObj.current.left != segObj.watch.left) return true; if(segObj.current.right != segObj.watch.right) return true; if(segObj.current.bottom != segObj.watch.bottom) return true; if(segObj.current.top != segObj.watch.top) return true; if(segObj.current.fromNode != segObj.watch.fromNode) return true; if(segObj.current.toNode != segObj.watch.toNode) return true; if(segObj.current.fwdDir != segObj.watch.fwdDir) return true; if(segObj.current.revDir != segObj.watch.revDir) return true; if(segObj.current.length != segObj.watch.length) return true; if(segObj.current.level != segObj.watch.level) return true; if(segObj.current.rank != segObj.watch.rank) return true; if(segObj.current.roadType != segObj.watch.roadType) return true; if(segObj.current.updatedOn != segObj.watch.updatedOn) return true; return false; } function uroIsSegOnWatchList(fid) { for(var loop=0;loop<uroSegWatchObjects.length;loop++) { if(uroSegWatchObjects[loop].fid == fid) return loop; } return -1; } function uroAddCurrentSegWatchData(idx, left, right, bottom, top, fromNode, toNode, fwdDir, revDir, length, level, rank, roadType, updatedOn, server) { var segObj = uroSegWatchObjects[idx]; segObj.loaded = true; segObj.server = server; segObj.current = new uroSegWatchObjCheckProps(left, right, bottom, top, fromNode, toNode, fwdDir, revDir, length, level, rank, roadType, updatedOn); return(uroSegDataChanged(idx)); } function uroClearSegWatchList() { if(confirm('Removing all segments from the OWL cannot be undone\nAre you sure you want to do this?') === true) { uroSegWatchObjects = []; uroOWLUpdateHTML(); } } function uroAddUpdateSegWatchList() { var selectedCount = W.selectionManager.selectedItems.length; if(selectedCount === 0) { return; } for(var loop=0;loop < selectedCount; loop++) { var segObj = W.selectionManager.selectedItems[loop].model.attributes; var fid = segObj.id; var idx = uroIsSegOnWatchList(fid); if(idx != -1) { uroSegWatchObjects[idx].watch = new uroSegWatchObjCheckProps(segObj.geometry.bounds.left, segObj.geometry.bounds.right, segObj.geometry.bounds.bottom, segObj.geometry.bounds.top, segObj.fromNodeID, segObj.toNodeID, segObj.fwdDirection, segObj.revDirection, segObj.length, segObj.level, segObj.rank, segObj.roadType, segObj.updatedOn); uroAddLog('updated watchlist details for segment '+fid); } else { uroSegWatchObjects.push(new uroSegWatchObj(true, fid, segObj.geometry.bounds.left, segObj.geometry.bounds.right, segObj.geometry.bounds.bottom, segObj.geometry.bounds.top, segObj.fromNodeID, segObj.toNodeID, segObj.fwdDirection, segObj.revDirection, segObj.length, segObj.level, segObj.rank, segObj.roadType, segObj.updatedOn, 0, W.location.code)); uroAddCurrentSegWatchData(uroSegWatchObjects.length-1, segObj.geometry.bounds.left, segObj.geometry.bounds.right, segObj.geometry.bounds.bottom, segObj.geometry.bounds.top, segObj.fromNodeID, segObj.toNodeID, segObj.fwdDirection, segObj.revDirection, segObj.length, segObj.level, segObj.rank, segObj.roadType, segObj.updatedOn, W.location.code); uroAddLog('added segment '+fid+' to watchlist'); } } //uroOWLUpdateHTML(); } function uroRemoveSegFromWatchList() { var selectedCount = W.selectionManager.selectedItems.length; if(selectedCount === 0) { return; } for(var loop=0;loop < selectedCount; loop++) { var fid = W.selectionManager.selectedItems[loop].model.attributes.id; var idx = uroIsSegOnWatchList(fid); if(idx != -1) { uroSegWatchObjects.splice(idx,1); uroAddLog('removed segment '+fid+' from watchlist'); } } //uroOWLUpdateHTML(); } function uroRetrieveSegments(lat, lon) { var pos = new OpenLayers.LonLat(); var changed = false; pos.lon = lon; pos.lat = lat; pos.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326")); var URL = 'https://' + document.location.host; URL += Waze.Config.api_base; URL += '/Features?roadTypes=1%2C2%2C3%2C4%2C5%2C6%2C7%2C8%2C9%2C10%2C11%2C12%2C13%2C14%2C15%2C16%2C17%2C18%2C19%2C20%2C21'; URL += '&bbox='; var latl = pos.lat - 0.25; var latu = pos.lat + 0.25; var lonl = pos.lon - 0.25; var lonr = pos.lon + 0.25; URL += lonl+','+latl+','+lonr+','+latu; URL += '&language=en'; uroAddLog('retrieving segment data around '+pos.lon+','+pos.lat); var req = new XMLHttpRequest(); req.open('GET',URL,false); try { req.send(); uroAddLog('response '+req.status+' received'); if (req.status === 200) { var data = JSON.parse(req.responseText); for(var idx = 0; idx < data.segments.objects.length; idx++) { var obj = data.segments.objects[idx]; var listIdx = uroIsSegOnWatchList(obj.id); if(listIdx != -1) { //pos.lon = obj.geometry.coordinates[0]; //pos.lat = obj.geometry.coordinates[1]; //pos.transform(new OpenLayers.Projection("EPSG:4326"),new OpenLayers.Projection("EPSG:900913")); //camPos.lon = uroTruncate(camPos.lon); //camPos.lat = uroTruncate(camPos.lat); //camChanged |= uroAddCurrentCamWatchData(listIdx, camPos.lat, camPos.lon, camObj.type, camObj.azymuth, camObj.speed, camObj.validated, W.location.code); } else if(obj.validated === false) { } } } else { uroAddLog('request failed (status != 200)'); } } catch(err) { uroAddLog('segment load request failed (exception '+err+' caught)'); } return changed; } function uroGetCurrentSegWatchListObjects() { var segChanged = false; var segsChanged = []; var segsDeleted = []; var idx; var segObj; for(idx=0;idx<uroSegWatchObjects.length;idx++) { segObj = uroSegWatchObjects[idx]; if((segObj.loaded === false) && ((segObj.server == W.location.code) || (segObj.server == '??'))) { var segLat = (segObj.watch.top + segObj.watch.bottom) / 2; var segLon = (segObj.watch.right + segObj.watch.left) / 2; if(typeof W.model.segments.objects[segObj.fid] == 'object') { if(W.model.segments.objects[segObj.fid].state != "Delete") { var wazeObj = W.model.segments.objects[segObj.fid]; segChanged |= uroAddCurrentSegWatchData(idx, wazeObj.geometry.bounds.left, wazeObj.geometry.bounds.right, wazeObj.geometry.bounds.bottom, wazeObj.geometry.bounds.top, wazeObj.fromNodeID, wazeObj.toNodeID, wazeObj.fwdDirection, wazeObj.revDirection, wazeObj.length, wazeObj.level, wazeObj.rank, wazeObj.roadType, wazeObj.updatedOn, W.location.code); } else { segChanged |= uroRetrieveSegments(segLat, segLon); } } else { segChanged |= uroRetrieveSegments(segLat, segLon); } } } if(segChanged) { for(idx=0;idx<uroSegWatchObjects.length;idx++) { if(uroSegDataChanged(idx)) { segsChanged.push(uroSegWatchObjects[idx]); } } } for(idx=0;idx<uroSegWatchObjects.length;idx++) { segObj = uroSegWatchObjects[idx]; if((segObj.loaded === false) && (segObj.server == W.location.code)) { segsDeleted.push(segObj); } } if((segsChanged.length > 0) || (segsDeleted.length > 0)) { var alertStr = 'Segment WatchList Alert!!!\r\n'; for(idx=0;idx<segsChanged.length;idx++) { alertStr += 'Segment ID '+segsChanged[idx].fid+' in group "'+uroFindCWLGroupByIdx(segsChanged[idx].groupID)+'" has been changed\r\n'; } for(idx=0;idx<segsDeleted.length;idx++) { alertStr += 'Segment ID '+segsDeleted[idx].fid+' in group "'+uroFindCWLGroupByIdx(segsDeleted[idx].groupID)+'" has been deleted\r\n'; } alert(alertStr); } } // Places Functions function uroPlaceWatchObjCheckProps(left, right, bottom, top, name, imageCount, residential, updatedOn) { if(left !== null) left = uroTruncate(uroTypeCast(left)); if(right !== null) right = uroTruncate(uroTypeCast(right)); if(bottom !== null) bottom = uroTruncate(uroTypeCast(bottom)); if(top !== null) top = uroTruncate(uroTypeCast(top)); if(imageCount !== null) imageCount = uroTypeCast(imageCount); if(typeof residential == "string") residential = (residential == "true"); if(updatedOn !== null) updatedOn = uroTypeCast(updatedOn); this.left = left; this.right = right; this.bottom = bottom; this.top = top; this.name = name; this.imageCount = imageCount; this.residential = residential; this.updatedOn = updatedOn; } function uroPlaceWatchObj(persistent, fid, left, right, bottom, top, imageCount, name, residential, updatedOn, groupID, server) { groupID = uroTypeCast(groupID); if(typeof persistent == "string") persistent = (persistent == "true"); this.fid = fid; this.persistent = persistent; this.loaded = false; this.server = server; this.groupID = groupID; this.watch = new uroPlaceWatchObjCheckProps(left, right, bottom, top, name, imageCount, residential, updatedOn); this.current = new uroPlaceWatchObjCheckProps(null, null, null, null, null, null, null, null); } function uroPlaceDataChanged(idx) { var placeObj = uroPlaceWatchObjects[idx]; if(placeObj.loaded === false) return false; if(placeObj.current.left != placeObj.watch.left) return true; if(placeObj.current.right != placeObj.watch.right) return true; if(placeObj.current.bottom != placeObj.watch.bottom) return true; if(placeObj.current.top != placeObj.watch.top) return true; if(placeObj.current.name != placeObj.watch.name) return true; if(placeObj.current.imageCount != placeObj.watch.imageCount) return true; if(placeObj.current.residential != placeObj.watch.residential) return true; if(placeObj.current.updatedOn != placeObj.watch.updatedOn) return true; return false; } function uroIsPlaceOnWatchList(fid) { for(var loop=0;loop<uroPlaceWatchObjects.length;loop++) { if(uroPlaceWatchObjects[loop].fid == fid) return loop; } return -1; } function uroClearPlaceWatchList() { if(confirm('Removing all places from the OWL cannot be undone\nAre you sure you want to do this?') === true) { uroPlaceWatchObjects = []; uroOWLUpdateHTML(); } } */ function uroHighlightCWLEntry() { this.style.backgroundColor = '#FFFFAA'; return false; } function uroUnhighlightCWLEntry() { var camidx = this.id.substr(8); var changed = uroCamDataChanged(camidx); var deleted = (uroCamWatchObjects[camidx].loaded === false); if(uroCamWatchObjects[camidx].server != W.location.code) { if(uroCamWatchObjects[camidx].server == '??') this.style.backgroundColor = '#A0A0A0'; else this.style.backgroundColor = '#AAFFAA'; } else if(changed) this.style.backgroundColor = '#AAAAFF'; else if(deleted) this.style.backgroundColor = '#FFAAAA'; else this.style.backgroundColor = '#FFFFFF'; return false; } function uroCWLIconHighlight() { this.style.color="#0000ff"; return false; } function uroCWLIconLowlight() { this.style.color="#ccccff"; return false; } function uroPopulateCWLGroupSelect() { var selector = document.getElementById('_uroCWLGroupSelect'); while(selector.options.length > 0) { selector.options.remove(0); } for(var loop=0;loop<uroCWLGroups.length;loop++) { var groupObj = uroCWLGroups[loop]; if(groupObj.groupID != -1) { selector.options.add(new Option(groupObj.groupName,groupObj.groupID)); } } } function uroGetNextCWLGroupID() { var nextID = 1; for(var loop=0;loop<uroCWLGroups.length;loop++) { if(uroCWLGroups[loop].groupID >= nextID) { nextID = uroCWLGroups[loop].groupID + 1; } } return nextID; } function uroFindCWLGroupByName(groupName) { var groupID = -1; for(var loop=0;loop<uroCWLGroups.length;loop++) { if((uroCWLGroups[loop].groupName == groupName) && (uroCWLGroups[loop].groupID != -1)) { groupID = uroCWLGroups[loop].groupID; break; } } return groupID; } function uroAddCWLGroup() { var groupID = uroGetNextCWLGroupID(); var groupName = uroGetElmValue('_uroCWLGroupEntry'); if(uroFindCWLGroupByName(groupName) == -1) { uroCWLGroups.push(new uroOWLGroupObj(groupID,groupName,false)); uroPopulateCWLGroupSelect(); } } function uroRemoveCWLGroup() { var loop; var selector = document.getElementById('_uroCWLGroupSelect'); var groupID = parseInt(selector.selectedOptions[0].value); if(groupID === 0) return false; // prevent deletion of the default group for(loop=0;loop<uroCamWatchObjects.length;loop++) { var cwObj = uroCamWatchObjects[loop]; if(cwObj.groupID == groupID) { cwObj.groupID = 0; } } for(loop=0;loop<uroCWLGroups.length;loop++) { var groupObj = uroCWLGroups[loop]; if(groupObj.groupID == groupID) { groupObj.groupID = -1; } } uroOWLUpdateHTML(); } function uroAssignCameraToGroup() { var camidx = this.id.substr(13); var selector = document.getElementById('_uroCWLGroupSelect'); uroCamWatchObjects[camidx].groupID = parseInt(selector.selectedOptions[0].value); uroOWLUpdateHTML(); return false; } function uroAddBtnEvl(btnID, evlType, evlFunction) { var btnObj = document.getElementById(btnID); if(btnObj !== null) { btnObj.addEventListener(evlType, evlFunction, true); } } function uroCWLGroupCollapseExpand() { var groupidx = this.id.substr(18); if(uroCWLGroups[groupidx].groupCollapsed === true) uroCWLGroups[groupidx].groupCollapsed = false; else uroCWLGroups[groupidx].groupCollapsed = true; uroOWLUpdateHTML(); return false; } var uroSelectedOWLGroup = null; function uroOWLUpdateHTML(doFullUpdate) { var camTypes = new Array("","","Speed", "Dummy", "Red Light"); var iHTML = ''; if(document.getElementById('_uroCWLGroupSelect') !== null) { uroSelectedOWLGroup = document.getElementById('_uroCWLGroupSelect').selectedIndex; } iHTML = '<br><b>Camera Watchlist:</b><br><br>'; iHTML += '<div id="_uroCWLCamList" style="height:65%;overflow:auto;">'; if(uroCWLGroups.length > 0) { var camidx; for(var groupidx=0;groupidx<uroCWLGroups.length;groupidx++) { var groupObj = uroCWLGroups[groupidx]; iHTML += '<div id="_uroCWLGroup-'+groupidx+'">'; if(groupObj.groupCollapsed === true) { iHTML += '<i class="fa fa-plus-square-o" style="cursor:pointer;font-size:14px;" id="_uroCWLGroupState-'+groupidx+'"></i>'; } else { iHTML += '<i class="fa fa-minus-square-o" style="cursor:pointer;font-size:14px;" id="_uroCWLGroupState-'+groupidx+'"></i>'; } iHTML += '<b>'+groupObj.groupName+'</b><br>'; groupObj.groupCount = 0; if(uroCamWatchObjects.length > 0) { for(camidx=0;camidx<uroCamWatchObjects.length;camidx++) { var camObj = uroCamWatchObjects[camidx]; if(camObj.groupID == groupObj.groupID) { groupObj.groupCount++; var changed = uroCamDataChanged(camidx); var deleted = (camObj.loaded === false); iHTML += '<div id="_uroCWL-'+camidx+'" style="padding:3px;border-width:2px;border-style:solid;border-color:#FFFFFF;background-color:'; if(camObj.server != W.location.code) { if(camObj.server == '??') iHTML += '#A0A0A0;'; else iHTML += '#AAFFAA;'; } else if(changed) iHTML += '#AAAAFF;'; else if(deleted) iHTML += '#FFAAAA;'; else iHTML += '#FFFFFF;'; if(groupObj.groupCollapsed === true) iHTML += 'display:none;">'; else iHTML += 'display:block;">'; iHTML += 'ID: '+camObj.fid; iHTML += ' ('+camObj.server+')'; iHTML += ' Type: '+camTypes[camObj.watch.type]; if(camObj.server != W.location.code) { if(camObj.server == '??') { iHTML += '<br><i>Unknown server</i>'; } else { iHTML += '<br><i>Not on this server</i>'; } } else if(deleted) { iHTML += '<br>DELETED'; } else if(changed) { if(camObj.current.type != camObj.watch.type) { iHTML += '<br> Type changed'; iHTML += ' ('+camObj.watch.type+' to '+camObj.current.type+')'; } if(camObj.current.azymuth != camObj.watch.azymuth) { iHTML += '<br> Azimuth changed'; iHTML += ' ('+camObj.watch.azymuth+' to '+camObj.current.azymuth+')'; } if(camObj.current.speed != camObj.watch.speed) { iHTML += '<br> Speed changed'; iHTML += ' ('+camObj.watch.speed+' to '+camObj.current.speed+')'; } if(camObj.current.validated != camObj.watch.validated) { iHTML += '<br> Approval state changed'; iHTML += ' ('+camObj.watch.validated+' to '+camObj.current.validated+')'; } if(camObj.current.lat != camObj.watch.lat) { iHTML += '<br> Latitude changed'; iHTML += ' ('+camObj.watch.lat+' to '+camObj.current.lat+')'; } if(camObj.current.lon != camObj.watch.lon) { iHTML += '<br> Longitude changed'; iHTML += ' ('+camObj.watch.lon+' to '+camObj.current.lon+')'; } } if(camObj.server == W.location.code) { if(deleted === false) { iHTML += ' <i class="fa fa-group" style="cursor:pointer;font-size:14px;color:#ccccff;" id="_uroCWLIcon1-'+camidx+'"></i>'; } iHTML += ' <i class="fa fa-arrow-circle-right" style="cursor:pointer;font-size:14px;color:#ccccff;" id="_uroCWLIcon2-'+camidx+'"></i>'; } iHTML += '</div>'; } } } iHTML += '</div>'; } } iHTML += '</div><div id="_uroCWLControls">'; iHTML += '<hr>Group control:<br>'; iHTML += '<select id="_uroCWLGroupSelect" style="width:40%;height:22px;"></select> <input type="button" id="_btnCWLGroupDel" value="Delete group"><br>'; iHTML += '<input type="text" id="_uroCWLGroupEntry" style="width:40%;height:22px;"> <input type="button" id="_btnCWLGroupAdd" value="Add group">'; iHTML += '<br><input type="button" id="_btnRescanCamWatchList" value="Refresh Camera Data"><br><br>'; iHTML += '<b>Remove cameras from OWL:</b><br>'; iHTML += '<input type="button" id="_btnRemoveDeletedCameras" value="Deleted"> '; iHTML += '<input type="button" id="_btnRemoveUnknownServerCameras" value="Unknown Server"> '; iHTML += '<input type="button" id="_btnClearCamWatchList" value="ALL Cameras">'; iHTML += '</div>'; uroOWL.innerHTML = iHTML; uroFinaliseOWLHTMLUpdate(); } function uroFinaliseOWLHTMLUpdate() { if(uroCamWatchObjects.length > 0) { if(document.getElementById("_uroCWL-0") == null) { setTimeout(uroFinaliseOWLHTMLUpdate,100); return; } for(var camidx=0;camidx<uroCamWatchObjects.length;camidx++) { document.getElementById("_uroCWL-"+camidx).onmouseover = uroHighlightCWLEntry; document.getElementById("_uroCWL-"+camidx).onmouseleave = uroUnhighlightCWLEntry; if(uroCamWatchObjects[camidx].server == W.location.code) { var icon1 = document.getElementById("_uroCWLIcon1-"+camidx); var icon2 = document.getElementById("_uroCWLIcon2-"+camidx); if(icon1 !== null) { icon1.onmouseover = uroCWLIconHighlight; icon1.onmouseleave = uroCWLIconLowlight; icon1.onclick = uroAssignCameraToGroup; } if(icon2 !== null) { icon2.onmouseover = uroCWLIconHighlight; icon2.onmouseleave = uroCWLIconLowlight; icon2.onclick = uroGotoCam; } } } } if(document.getElementById('_btnClearCamWatchList') == null) { setTimeout(uroFinaliseOWLHTMLUpdate,100); return; } uroAddBtnEvl('_btnClearCamWatchList', 'click', uroClearCamWatchList); uroAddBtnEvl('_btnRemoveDeletedCameras', 'click', uroClearDeletedCameras); uroAddBtnEvl('_btnRemoveUnknownServerCameras', 'click', uroClearUnknownServerCameras); uroAddBtnEvl('_btnRescanCamWatchList', 'click', uroRescanCamWatchList); uroAddBtnEvl('_btnCWLGroupDel', 'click', uroRemoveCWLGroup); uroAddBtnEvl('_btnCWLGroupAdd', 'click', uroAddCWLGroup); if(document.getElementById('_uroCWLGroupSelect') !== null) { uroAddLog('populating CWL group list'); uroPopulateCWLGroupSelect(); var selector = document.getElementById('_uroCWLGroupSelect'); if(uroSelectedOWLGroup >= selector.length) { uroSelectedOWLGroup = 0; } selector.selectedIndex = uroSelectedOWLGroup; } if(uroCWLGroups.length > 0) { for(var groupidx=0;groupidx<uroCWLGroups.length;groupidx++) { if(uroCWLGroups[groupidx].groupCount === 0) { uroSetStyleDisplay('_uroCWLGroup-'+groupidx,'none'); } else { uroSetOnClick('_uroCWLGroupState-'+groupidx,uroCWLGroupCollapseExpand); } } } } // -------------------------------------------------------------------------------------------------------------------- // END OF WATCHLIST STUFF // -------------------------------------------------------------------------------------------------------------------- function uroIsOnIgnoreList(fid) { if(sessionStorage.UROverview_FID_IgnoreList.indexOf('fid:'+fid) == -1) return false; else return true; } function uroEnableIgnoreListControls() { var btnState = "visible"; if(sessionStorage.UROverview_FID_IgnoreList === '') { btnState = "hidden"; } document.getElementById('_btnUndoLastHide').style.visibility = btnState; document.getElementById('_btnClearSessionHides').style.visibility = btnState; uroFilterItems(); } function uroAddToIgnoreList() { if(!uroIsOnIgnoreList(uroShownFID)) { sessionStorage.UROverview_FID_IgnoreList += 'fid:'+uroShownFID; uroAddLog('added fid '+uroShownFID+' to ignore list'); uroAddLog(sessionStorage.UROverview_FID_IgnoreList); uroDiv.style.visibility = 'hidden'; uroEnableIgnoreListControls(); W.map.events.register("mousemove", null, uroFilterItemsOnMove); } return false; } function uroRemoveLastAddedIgnore() { var ignorelist = sessionStorage.UROverview_FID_IgnoreList; var fidpos = ignorelist.lastIndexOf('fid:'); if(fidpos != -1) { ignorelist = ignorelist.slice(0,fidpos); sessionStorage.UROverview_FID_IgnoreList = ignorelist; uroAddLog('removed last fid from ignore list'); uroAddLog(sessionStorage.UROverview_FID_IgnoreList); uroEnableIgnoreListControls(); } } function uroRemoveAllIgnores() { sessionStorage.UROverview_FID_IgnoreList = ''; uroEnableIgnoreListControls(); } function uroKeywordPresent(desc, keyword) { var re; if(uroGetCBChecked('_cbCaseInsensitive') === true) re = RegExp(keyword,'i'); else re = RegExp(keyword); if(desc.search(re) != -1) return true; else return false; } function uroClickify(desc) { var linkStartPos = desc.indexOf('http://'); if(linkStartPos == -1) linkStartPos = desc.indexOf('https://'); if(linkStartPos != -1) { var descPreLink = desc.slice(0,linkStartPos); var descURL = desc.slice(linkStartPos); var linkEndPos = descURL.indexOf(' '); var descPostLink = ''; if(linkEndPos != -1) { descPostLink = descURL.slice(linkEndPos); descURL = descURL.slice(0,linkEndPos); } var linkTarget = ''; if(descURL.indexOf('cryosphere') != -1) linkTarget = '_cryosphere'; else if(descURL.indexOf('waze.com') != -1) linkTarget = '_wazeUR'; desc = descPreLink + '<a target="'+linkTarget+'" href="'+descURL+'">here</a>' + descPostLink; } return desc; } function uroGetUpdateRequestSessions() { var idList = []; while((idList.length < 50) && (uroPendingURSessionIDs.length)) { var id = uroPendingURSessionIDs.shift(); idList.push(id); } if(idList.length > 0) { uroAddLog('grabbing '+idList.length+' updateRequestSessions, IDs: '+idList); W.model.updateRequestSessions.get(idList); } if((uroPendingURSessionIDs.length) || (uroRequestedURSessionIDs.length)) { setTimeout(uroGetUpdateRequestSessions,1000); } } function uroRefreshUpdateRequestSessions() { var urcount = 0; uroPendingURSessionIDs = []; uroRequestedURSessionIDs = []; for (var urID in W.model.mapUpdateRequests.objects) { if(W.model.mapUpdateRequests.objects.hasOwnProperty(urID)) { if(W.model.updateRequestSessions.objects[urID] === undefined) { uroPendingURSessionIDs.push(urID); } urcount++; } } uroGetUpdateRequestSessions(); } function uroURHasMyComments(fid) { if(uroUserID === -1) return false; var nComments = W.model.updateRequestSessions.objects[fid].comments.length; if(nComments === 0) return false; for(var cidx=0; cidx<nComments; cidx++) { if(W.model.updateRequestSessions.objects[fid].comments[cidx].userID == uroUserID) return true; } return false; } function uroACMObj(urID, markerType, customType, hasMyComments, nComments) { this.urID = urID; this.markerType = markerType; this.customType = customType; this.hasMyComments = hasMyComments; this.nComments = nComments; } function uroAddCustomMarkers(urID, markerType, customType, hasMyComments, nComments) { var useCustomMarker = false; if(uroGetCBChecked('_cbMasterEnable') === true) { if(customType === 0) useCustomMarker = (uroGetCBChecked('_cbCustomRoadworksMarkers')); else if(customType === 1) useCustomMarker = (uroGetCBChecked('_cbCustomConstructionMarkers')); else if(customType === 2) useCustomMarker = (uroGetCBChecked('_cbCustomClosuresMarkers')); else if(customType === 3) useCustomMarker = (uroGetCBChecked('_cbCustomEventsMarkers')); else if(customType === 4) useCustomMarker = (uroGetCBChecked('_cbCustomNotesMarkers')); else if(customType === 5) useCustomMarker = (uroGetCBChecked('_cbCustomWSLMMarkers')); else if(customType === 6) useCustomMarker = (uroGetCBChecked('_cbCustomBOGMarkers')); else if(customType === 7) useCustomMarker = (uroGetCBChecked('_cbCustomDifficultMarkers')); else if(customType === 98) useCustomMarker = (uroGetCBChecked('_cbCustomNativeSLMarkers')); else if(customType === 99) useCustomMarker = (uroGetCBChecked('_cbCustomKeywordMarkers')); else if(customType === 100) useCustomMarker = (uroGetCBChecked('_cbCustomElginMarkers')); else if(customType === 101) useCustomMarker = (uroGetCBChecked('_cbCustomTrafficCastMarkers')); else if(customType === 102) useCustomMarker = (uroGetCBChecked('_cbCustomTrafficMasterMarkers')); else if(customType === 103) useCustomMarker = (uroGetCBChecked('_cbCustomCaltransMarkers')); else if(customType === 104) useCustomMarker = (uroGetCBChecked('_cbCustomTFLMarkers')); } if(!useCustomMarker) customType = -1; uroCustomMarkerList.push(new uroACMObj(urID, markerType, customType, hasMyComments, nComments)); } function uroRenderCustomMarkers(markerType) { var urID; var elmID; var newSpan; var divElem; var objIdx; var customType; var cmlObj; var defaultMarkerURL = "url('"+document.location.origin + '/assets-editor/sprites/vectors/' + uroNativeMarkerImage+"')"; var touchedByURO = false; if(markerType == 'ur') { var useDefaultConvoMarker = false; var addCommentCount = false; if(uroGetCBChecked('_cbMasterEnable') === true) { if((uroGetCBChecked('_cbNativeConvoMarkers')) && (uroBetaEditor === false)) useDefaultConvoMarker = true; if((uroGetCBChecked('_cbNativeBetaConvoMarkers')) && (uroBetaEditor === true)) useDefaultConvoMarker = true; if(uroGetCBChecked('_cbCommentCount')) addCommentCount = true; } else { useDefaultConvoMarker = true; } var uRCM_masterEnable = uroGetCBChecked('_cbMasterEnable'); divElem = document.getElementById(W.map.updateRequestLayer.id); if(divElem.childNodes.length > 0) { for(objIdx = 0; objIdx < uroCustomMarkerList.length; objIdx++) { customType = -1; cmlObj = uroCustomMarkerList[objIdx]; if(cmlObj.markerType == 'ur') { if(uRCM_masterEnable === true) { customType = cmlObj.customType; } if(customType < 100) { urID = cmlObj.urID; var nComments = cmlObj.nComments; var iconObj = W.map.updateRequestLayer.markers[urID].icon; newSpan = ''; if(nComments !== 0) { var classList = iconObj.imageDiv.classList; elmID = "commentCount_"+urID; if(addCommentCount) { // add a new comment count bubble if the UR doesn't already have one if(document.getElementById(elmID) === null) { newSpan += '<span id="'+elmID+'" style="position:absolute;top:-9px;left:-11px;pointer-events:none;z-index:1">'; // define the comment-count holding span within the span used to hold the empty bubble image, and before the image is // added to the HTML, to avoid z-indexing issues when adjacent comment count bubbles are overlapped... newSpan += '<span id="'+elmID+"_inner"+'" style="position:absolute;top:4px;left:11px;font-size:11px;;pointer-events:none"></span>'; newSpan += '<img src="'+uroMarkers[0]+'">'; newSpan += '</span>'; } } else { // remove comment count bubble from this UR marker if one has previously been // added and the user has now disabled the option... if(document.getElementById(elmID) !== null) { document.getElementById(elmID).remove(); } if(document.getElementById(elmID+"_inner") !== null) { document.getElementById(elmID+"_inner").remove(); } } elmID = "convoMarker_"+urID; if(useDefaultConvoMarker === false) { if(document.getElementById(elmID) === null) { var hasMyComments = cmlObj.hasMyComments; // z-index needs to be set to 1 here so that when a new comment is added to a UR and WME re-renders the native // conversation marker, the custom marker remains on top... newSpan += '<span id="'+elmID+'" style="position:absolute;top:-9px;left:18px;pointer-events:none;z-index:1">'; if(hasMyComments) newSpan += '<img src="'+uroMarkers[2]+'">'; else newSpan += '<img src="'+uroMarkers[1]+'">'; newSpan += '</span>'; classList.remove("has-comments"); } } else { // remove custom conversation marker from this UR if one has previously been // added and the user has now disabled this option if(document.getElementById(elmID) !== null) { document.getElementById(elmID).remove(); } if(nComments > 0) { // only replace the native marker class if the UR has comments - if we're just clearing the custom // marker following a master enable switchoff, we don't then want to add native markers to URs which // didn't have them in the first place... classList.add("has-comments"); } } } // change main marker if required touchedByURO = W.map.updateRequestLayer.markers[urID].touchedByURO; /* //// TEMPORARY REMOVAL UNTIL CUSTOM ICON SUPPORT IS FIXED IN NEW WME if(customType != -1) { if((touchedByURO === undefined) || (touchedByURO === false)) { customType = uroGetCustomMarkerIdx(customType); W.map.updateRequestLayer.markers[urID].icon.imageDiv.style.backgroundImage = uroAltMarkers[customType]; W.map.updateRequestLayer.markers[urID].touchedByURO = true; } } else { if((touchedByURO === undefined) || (touchedByURO === true)) { W.map.updateRequestLayer.markers[urID].icon.imageDiv.style.backgroundImage = defaultMarkerURL; W.map.updateRequestLayer.markers[urID].touchedByURO = false; } } */ if(newSpan !== '') { iconObj.$div.prepend(newSpan); if(addCommentCount) { var styleLeft; if(nComments < 10) styleLeft = '11px'; else if(nComments < 100) styleLeft = '8px'; else styleLeft = '5px'; elmID = "commentCount_"+urID; if(document.getElementById(elmID+"_inner") !== null) { document.getElementById(elmID+"_inner").innerHTML = nComments; document.getElementById(elmID+"_inner").style.left = styleLeft; } } } } } } } } else if(markerType == 'mp') { divElem = document.getElementById(W.map.problemLayer.id); if(divElem.childNodes.length > 0) { for(objIdx = 0; objIdx < uroCustomMarkerList.length; objIdx++) { cmlObj = uroCustomMarkerList[objIdx]; if(cmlObj.markerType == 'mp') { customType = cmlObj.customType; if((customType >= 100) || (customType == -1)) { urID = cmlObj.urID; // change main marker if required touchedByURO = W.map.problemLayer.markers[urID].touchedByURO; /* //// TEMPORARY REMOVAL UNTIL CUSTOM ICON SUPPORT IS FIXED IN NEW WME if(customType != -1) { if((touchedByURO === undefined) || (touchedByURO === false)) { customType = uroGetCustomMarkerIdx(customType); W.map.problemLayer.markers[urID].icon.imageDiv.style.backgroundImage = uroAltMarkers[customType]; W.map.problemLayer.markers[urID].touchedByURO = true; } } else { if((touchedByURO === undefined) || (touchedByURO === true)) { W.map.problemLayer.markers[urID].icon.imageDiv.style.backgroundImage = defaultMarkerURL; W.map.problemLayer.markers[urID].touchedByURO = false; } } */ } } } } } } function uroFilterPlaces() { if(uroFilterPreamble() === false) return; if(uroPlaceSelected === true) return; if(uroGetCBChecked('_cbDisablePlacesFiltering') === true) return; uroUpdateVenueEditorList(); var filterNameID = null; var tbUserName = uroGetElmValue('_textPlacesEditor'); var selector = document.getElementById('_selectPlacesUserID'); if(selector.selectedIndex > 0) { var selUserName = document.getElementById('_selectPlacesUserID').selectedOptions[0].innerHTML; if(selUserName == tbUserName) { filterNameID = document.getElementById('_selectPlacesUserID').selectedOptions[0].value; } } if(filterNameID === null) { var userObj = W.model.users.getByAttributes({userName:tbUserName})[0]; if(userObj !== undefined) { filterNameID = userObj.id; } } var filterCats = []; for(var i=0; i<W.Config.venues.categories.length; i++) { var parentCategory = W.Config.venues.categories[i]; var subCategory; if(uroGetCBChecked('_cbPlacesFilter-'+parentCategory) === true) { filterCats.push(parentCategory); for(var i1=0; i1<W.Config.venues.subcategories[parentCategory].length; i1++) { subCategory = W.Config.venues.subcategories[parentCategory][i1]; filterCats.push(subCategory); } } else { for(var i2=0; i2<W.Config.venues.subcategories[parentCategory].length; i2++) { subCategory = W.Config.venues.subcategories[parentCategory][i2]; if(uroGetCBChecked('_cbPlacesFilter-'+subCategory) === true) { filterCats.push(subCategory); } } } } var placeStyle; var uFP_filterEditedLessThan = uroGetCBChecked('_cbPlaceFilterEditedLessThan'); var uFP_filterEditedMoreThan = uroGetCBChecked('_cbPlaceFilterEditedMoreThan'); var uFP_filterL0 = uroGetCBChecked('_cbHidePlacesL0'); var uFP_filterL1 = uroGetCBChecked('_cbHidePlacesL1'); var uFP_filterL2 = uroGetCBChecked('_cbHidePlacesL2'); var uFP_filterL3 = uroGetCBChecked('_cbHidePlacesL3'); var uFP_filterL4 = uroGetCBChecked('_cbHidePlacesL4'); var uFP_filterL5 = uroGetCBChecked('_cbHidePlacesL5'); var uFP_filterStaff = uroGetCBChecked('_cbHidePlacesStaff'); var uFP_filterAL = uroGetCBChecked('_cbHidePlacesAdLocked'); var uFP_filterOnLockLevel = (uFP_filterL0 || uFP_filterL1 || uFP_filterL2 || uFP_filterL3 || uFP_filterL4 || uFP_filterL5 || uFP_filterStaff); var uFP_filterNoPhotos = uroGetCBChecked('_cbHideNoPhotoPlaces'); var uFP_filterWithPhotos = uroGetCBChecked('_cbHidePhotoPlaces'); var uFP_filterNoLinks = uroGetCBChecked('_cbHideNoLinkedPlaces'); var uFP_filterWithLinks = uroGetCBChecked('_cbHideLinkedPlaces'); var uFP_filterNoKeyword = uroGetCBChecked('_cbHideKeywordPlaces'); var uFP_filterKeyword = uroGetCBChecked('_cbHideNoKeyeordPlaces'); var uFP_filterPrivate = uroGetCBChecked('_cbFilterPrivatePlaces'); var uFP_invertFilters = uroGetCBChecked('_cbInvertPlacesFilter'); var uFP_masterEnable = uroGetCBChecked('_cbMasterEnable'); var uFP_filterAreaPlaces = uroGetCBChecked('_cbHideAreaPlaces'); var uFP_filterPointPlaces = uroGetCBChecked('_cbHidePointPlaces'); var uFP_filterCreatedBy = uroGetCBChecked('_cbShowOnlyPlacesCreatedBy'); var uFP_filterEditedBy = uroGetCBChecked('_cbShowOnlyPlacesEditedBy'); var uFP_NameKeyword = document.getElementById('_textKeywordPlace').value.toLowerCase(); var uFP_thresholdMinDays = document.getElementById('_inputFilterPlaceEditMinDays').value; var uFP_thresholdMaxDays = document.getElementById('_inputFilterPlaceEditMaxDays').value; for(var v=0; v<W.map.landmarkLayer.features.length; v++) { placeStyle = 'visible'; if(uFP_masterEnable === true) { var lmObj = W.map.landmarkLayer.features[v]; // when an area place is selected, the drag points for editing the place outline now get added as objects into W.map.landmarkLayer.features, // however none of these objects have the .model property - we must therefore check each entry in features[] to see if it has .model before // attempting to filter it... if(lmObj.model != null) { if(lmObj.model.attributes.id < 0) { // don't apply filtering to newly-created places - this allows the user to leave their filtering settings unchanged whilst // adding a new place which, once saved, would then be hidden... break; } if(uFP_filterAreaPlaces) { if(lmObj.model.attributes.geometry.id.indexOf('Polygon') !== -1) { placeStyle = 'hidden'; } } if(uFP_filterPointPlaces) { if(lmObj.model.attributes.geometry.id.indexOf('Point') !== -1) { placeStyle = 'hidden'; } } if(placeStyle == 'visible') { if((uFP_filterEditedLessThan) || (uFP_filterEditedMoreThan)) { var editDate = lmObj.model.attributes.updatedOn; if(editDate === undefined) { // where a place has never been edited since its creation, use the creation date instead... editDate = lmObj.model.attributes.createdOn; } if(editDate != null) { var editDaysAgo = uroDateToDays(editDate); if(uFP_filterEditedLessThan) { if(editDaysAgo < uFP_thresholdMinDays) { placeStyle = 'hidden'; } } if(uFP_filterEditedMoreThan) { if(editDaysAgo > uFP_thresholdMaxDays) { placeStyle = 'hidden'; } } } } } if(placeStyle == 'visible') { if(uFP_filterOnLockLevel) { var lockLevel = lmObj.model.attributes.lockRank; if ((uFP_filterL0) && (lockLevel === 0)) placeStyle = 'hidden'; if ((uFP_filterL1) && (lockLevel === 1)) placeStyle = 'hidden'; if ((uFP_filterL2) && (lockLevel === 2)) placeStyle = 'hidden'; if ((uFP_filterL3) && (lockLevel === 3)) placeStyle = 'hidden'; if ((uFP_filterL4) && (lockLevel === 4)) placeStyle = 'hidden'; if ((uFP_filterL5) && (lockLevel === 5)) placeStyle = 'hidden'; if ((uFP_filterStaff) && (lockLevel === 6)) placeStyle = 'hidden'; } } if(placeStyle == 'visible') { if(uFP_filterAL) { if(lmObj.model.attributes.adLocked) placeStyle = 'hidden'; } } if(placeStyle == 'visible') { if(uFP_filterNoPhotos || uFP_filterWithPhotos) { var nPhotos = 0; for(var loop=0; loop<lmObj.model.attributes.images.length; loop++) { if(lmObj.model.attributes.images[loop].attributes.approved) nPhotos++; } if((uFP_filterNoPhotos) && (nPhotos === 0)) placeStyle = 'hidden'; if((uFP_filterWithPhotos) && (nPhotos !== 0)) placeStyle = 'hidden'; } } if(placeStyle == 'visible') { if(uFP_filterNoLinks || uFP_filterWithLinks) { var nLinks = lmObj.model.attributes.externalProviderIDs.length; if((uFP_filterNoLinks) && (nLinks === 0)) placeStyle = 'hidden'; if((uFP_filterWithLinks) && (nLinks !== 0)) placeStyle = 'hidden'; } } if(placeStyle == 'visible') { if((uFP_filterPrivate === true) && (lmObj.model.attributes.residential === true)) { placeStyle = 'hidden'; } else { for(var cat=0; cat<filterCats.length; cat++) { if(lmObj.model.attributes.categories.contains(filterCats[cat])) { placeStyle = 'hidden'; break; } } } } if(placeStyle == 'visible') { if(uFP_filterNoKeyword || uFP_filterKeyword) { var venueName = lmObj.model.attributes.name.toLowerCase(); var noKeywordMatch = true; if(uFP_NameKeyword === '') { noKeywordMatch = (venueName !== ''); } else { noKeywordMatch = (venueName.indexOf(uFP_NameKeyword) === -1); } if(!noKeywordMatch && uFP_filterNoKeyword) placeStyle = 'hidden'; if(noKeywordMatch && uFP_filterKeyword) placeStyle = 'hidden'; } } if(placeStyle == 'visible') { if(filterNameID != null) { if(uFP_filterCreatedBy === true) { if(filterNameID != lmObj.model.attributes.createdBy) placeStyle = 'hidden'; } if(uFP_filterEditedBy === true) { if(filterNameID != lmObj.model.attributes.updatedBy) placeStyle = 'hidden'; } } } } if(uFP_invertFilters === true) { if(placeStyle == 'hidden') placeStyle = 'visible'; else placeStyle = 'hidden'; } } var geoID = W.map.landmarkLayer.features[v].geometry.id; if(document.getElementById(geoID) !== null) { document.getElementById(geoID).style.visibility = placeStyle; } } var uFP_filterUneditable = uroGetCBChecked('_cbFilterUneditablePlaceUpdates'); var uFP_filterLockRanked = uroGetCBChecked('_cbFilterLockRankedPlaceUpdates'); var uFP_filterFlagged = uroGetCBChecked("_cbFilterFlaggedPUR"); var uFP_filterNewPlace = uroGetCBChecked("_cbFilterNewPlacePUR"); var uFP_filterUpdatedDetails = uroGetCBChecked("_cbFilterUpdatedDetailsPUR"); var uFP_filterNewPhoto = uroGetCBChecked("_cbFilterNewPhotoPUR"); var uFP_filterMinPURAge = uroGetCBChecked('_cbEnablePURMinAgeFilter'); var uFP_filterMaxPURAge = uroGetCBChecked('_cbEnablePURMaxAgeFilter'); var uFP_invertPURFilters = uroGetCBChecked('_cbInvertPURFilters'); var uFP_filterHighSeverity = uroGetCBChecked('_cbPURFilterHighSeverity'); var uFP_filterMedSeverity = uroGetCBChecked('_cbPURFilterMediumSeverity'); var uFP_filterLowSeverity = uroGetCBChecked('_cbPURFilterLowSeverity'); var uFP_leavePURGeos = uroGetCBChecked('_cbLeavePURGeos'); var uFP_thresholdMinPURDays = uroGetElmValue('_inputPURFilterMinDays'); var uFP_thresholdMaxPURDays = uroGetElmValue('_inputPURFilterMaxDays'); var uFP_isLoggedIn = W.loginManager.isLoggedIn(); var uFP_userRank = W.loginManager.user.rank; var purAge = null; for(var pu in W.map.placeUpdatesLayer.markers) { if(W.map.placeUpdatesLayer.markers.hasOwnProperty(pu)) { var puObj = W.map.placeUpdatesLayer.markers[pu]; if(W.map.placeUpdatesLayer.getVisibility() === true) { placeStyle = 'visible'; if(uFP_masterEnable === true) { if(uFP_masterEnable === true) { if(uFP_filterUneditable === true) { if(puObj.model.attributes.permissions === 0) { placeStyle = 'hidden'; } if((placeStyle == 'visible') && (uFP_isLoggedIn)) { if(uFP_userRank < puObj.model.attributes.lockRank) { placeStyle = 'hidden'; } } if((placeStyle == 'visible') && (puObj.model.attributes.adLocked)) { placeStyle = 'hidden'; } } if((placeStyle == 'visible') && (uFP_filterLockRanked === true)) { if(puObj.model.attributes.lockRank !== 0) { placeStyle = 'hidden'; } } if((placeStyle == 'visible') && (uFP_filterFlagged === true)) { if(puObj.icon.imageDiv.className.indexOf('flag') != -1) { placeStyle = 'hidden'; } } if((placeStyle == 'visible') && (uFP_filterNewPlace === true)) { if(puObj.icon.imageDiv.className.indexOf('add_venue') != -1) { placeStyle = 'hidden'; } } if((placeStyle == 'visible') && (uFP_filterUpdatedDetails === true)) { if((puObj.icon.imageDiv.className.indexOf('update_venue') != -1) || (puObj.icon.imageDiv.className.indexOf('multiple') != -1)) { placeStyle = 'hidden'; } } if((placeStyle == 'visible') && (uFP_filterNewPhoto === true)) { if(puObj.icon.imageDiv.className.indexOf('add_image') != -1) { placeStyle = 'hidden'; } } if(uFP_invertPURFilters === true) { if(placeStyle == 'hidden') placeStyle = 'visible'; else placeStyle = 'hidden'; } if(uFP_filterMinPURAge || uFP_filterMaxPURAge) { purAge = uroGetPURAge(puObj.model); if(uFP_filterMinPURAge === true) { if(purAge < uFP_thresholdMinPURDays) placeStyle = 'hidden'; } if(uFP_filterMaxPURAge === true) { if(purAge > uFP_thresholdMaxPURDays) placeStyle = 'hidden'; } } if(placeStyle == 'visible') { var purSeverity = puObj._getSeverity(); if((uFP_filterHighSeverity) && (purSeverity == "high")) placeStyle = 'hidden'; if((placeStyle == 'visible') && (uFP_filterMedSeverity) && (purSeverity == "medium")) placeStyle = 'hidden'; if((placeStyle == 'visible') && (uFP_filterLowSeverity) && (purSeverity == "low")) placeStyle = 'hidden'; } } } puObj.icon.imageDiv.style.visibility = placeStyle; if(uFP_leavePURGeos === false) { if(puObj.model != null) { if(puObj.model.geometry != null) { var puGeo = document.getElementById(puObj.model.geometry.id); if(puGeo !== null) { puGeo.style.visibility = placeStyle; } } } } } } } } function uroFilterCameras() { if(uroFilterPreamble() === false) return; var camLayer = document.getElementById(uroRootContainer+'_svgRoot'); if(camLayer === null) { if(uroNullCamLayer === false) { uroAddLog('caught null camLayer'); uroNullCamLayer = true; } return; } uroNullCamLayer = false; if(uroMouseIsDown === false) W.map.camerasLayer.redraw(); if(uroGetCBChecked('_cbMasterEnable') === true) { uroUpdateCamEditorList(); var filterNameID = null; var tbUserName = uroGetElmValue('_textCameraEditor'); var selector = document.getElementById('_selectCameraUserID'); if(selector.selectedIndex > 0) { var selUserName = document.getElementById('_selectCameraUserID').selectedOptions[0].innerHTML; if(selUserName == tbUserName) { filterNameID = document.getElementById('_selectCameraUserID').selectedOptions[0].value; } } if(filterNameID === null) { var userObj = W.model.users.getByAttributes({userName:tbUserName})[0]; if(userObj !== undefined) { filterNameID = userObj.id; } } for (var uroCamObj in W.model.cameras.objects) { if(W.model.cameras.objects.hasOwnProperty(uroCamObj)) { var uroCamUpdater = ''; var uroCamUpdaterRank = -1; var uroCamCreator = ''; var uroCamCreatorRank = -1; var uroCam = W.model.cameras.objects[uroCamObj]; var uroCamStyle = 'visible'; if(uroCam.attributes.createdBy !== null) { if(W.model.users.objects[uroCam.attributes.createdBy] != null) { uroCamCreator = W.model.users.objects[uroCam.attributes.createdBy].userName; uroCamCreatorRank = W.model.users.objects[uroCam.attributes.createdBy].rank; } } if(uroCam.attributes.updatedBy !== null) { if(W.model.users.objects[uroCam.attributes.updatedBy] != null) { uroCamUpdater = W.model.users.objects[uroCam.attributes.updatedBy].userName; uroCamUpdaterRank = W.model.users.objects[uroCam.attributes.updatedBy].rank; } } var uroCamApproved = uroCam.attributes.validated; var uroCamType = uroCam.attributes.type; if(filterNameID != null) { if(uroGetCBChecked('_cbShowOnlyCamsCreatedBy') === true) { if(filterNameID != uroCam.attributes.createdBy) uroCamStyle = 'hidden'; } if(uroGetCBChecked('_cbShowOnlyCamsEditedBy') === true) { if(filterNameID != uroCam.attributes.updatedBy) uroCamStyle = 'hidden'; } } if(uroGetCBChecked('_cbShowOnlyMyCams') === true) { if((uroUserID != uroCam.attributes.createdBy)&&(uroUserID != uroCam.attributes.updatedBy)) uroCamStyle = 'hidden'; } if((uroGetCBChecked('_cbShowWorldCams') === false) || (uroGetCBChecked('_cbShowUSACams') === false) || (uroGetCBChecked('_cbShowNonWorldCams') === false)) { var posWorld = uroCamCreator.indexOf('world_'); var posUSA = uroCamCreator.indexOf('usa_'); if((uroGetCBChecked('_cbShowWorldCams') === false) && (posWorld === 0)) uroCamStyle = 'hidden'; if((uroGetCBChecked('_cbShowUSACams') === false) && (posUSA === 0)) uroCamStyle = 'hidden'; if((uroGetCBChecked('_cbShowNonWorldCams') === false) && (posWorld !== 0) && (posUSA !== 0)) uroCamStyle = 'hidden'; } if((uroGetCBChecked('_cbShowApprovedCams') === false) || (uroGetCBChecked('_cbShowNonApprovedCams') === false)) { if((uroGetCBChecked('_cbShowApprovedCams') === false) && (uroCamApproved === true)) uroCamStyle = 'hidden'; if((uroGetCBChecked('_cbShowNonApprovedCams') === false) && (uroCamApproved === false)) uroCamStyle = 'hidden'; } if((uroGetCBChecked('_cbShowNonApprovedCams') === true) && (uroCamApproved === false)) { if(((uroGetCBChecked('_cbShowOlderCreatedNonApproved') === true)) && (uroGetCameraAge(uroCam,1) <= uroGetElmValue('_inputCameraMinCreatedDays'))) uroCamStyle = 'hidden'; if(((uroGetCBChecked('_cbShowOlderUpdatedNonApproved') === true)) && (uroGetCameraAge(uroCam,0) <= uroGetElmValue('_inputCameraMinUpdatedDays'))) uroCamStyle = 'hidden'; } if((uroGetCBChecked('_cbShowSpeedCams') === false) || (uroGetCBChecked('_cbShowRedLightCams') === false) || (uroGetCBChecked('_cbShowDummyCams') === false)) { if((uroGetCBChecked('_cbShowSpeedCams') === false) && (uroCamType == 2)) uroCamStyle = 'hidden'; if((uroGetCBChecked('_cbShowRedLightCams') === false) && (uroCamType == 4)) uroCamStyle = 'hidden'; if((uroGetCBChecked('_cbShowDummyCams') === false) && (uroCamType == 3)) uroCamStyle = 'hidden'; } if(uroGetCBChecked('_cbShowSpeedCams') === true) { if((uroGetCBChecked('_cbShowIfNoSpeedSet') === false) && (uroCam.attributes.speed === null)) uroCamStyle = 'hidden'; if((uroGetCBChecked('_cbShowIfSpeedSet') === false) && (uroCam.attributes.speed !== null)) uroCamStyle = 'hidden'; } if(uroGetCBChecked('_cbHideCreatedByMe') === true) { if(uroUserID == uroCam.attributes.createdBy) uroCamStyle = 'hidden'; } if((uroGetCBChecked('_cbHideCreatedByRank0') === true) && (uroCamCreatorRank === 0)) uroCamStyle = 'hidden'; if((uroGetCBChecked('_cbHideCreatedByRank1') === true) && (uroCamCreatorRank == 1)) uroCamStyle = 'hidden'; if((uroGetCBChecked('_cbHideCreatedByRank2') === true) && (uroCamCreatorRank == 2)) uroCamStyle = 'hidden'; if((uroGetCBChecked('_cbHideCreatedByRank3') === true) && (uroCamCreatorRank == 3)) uroCamStyle = 'hidden'; if((uroGetCBChecked('_cbHideCreatedByRank4') === true) && (uroCamCreatorRank == 4)) uroCamStyle = 'hidden'; if((uroGetCBChecked('_cbHideCreatedByRank5') === true) && (uroCamCreatorRank == 5)) uroCamStyle = 'hidden'; if(uroGetCBChecked('_cbHideUpdatedByMe') === true) { if(uroUserID == uroCam.attributes.updatedBy) uroCamStyle = 'hidden'; } if((uroGetCBChecked('_cbHideUpdatedByRank0') === true) && (uroCamUpdaterRank === 0)) uroCamStyle = 'hidden'; if((uroGetCBChecked('_cbHideUpdatedByRank1') === true) && (uroCamUpdaterRank == 1)) uroCamStyle = 'hidden'; if((uroGetCBChecked('_cbHideUpdatedByRank2') === true) && (uroCamUpdaterRank == 2)) uroCamStyle = 'hidden'; if((uroGetCBChecked('_cbHideUpdatedByRank3') === true) && (uroCamUpdaterRank == 3)) uroCamStyle = 'hidden'; if((uroGetCBChecked('_cbHideUpdatedByRank4') === true) && (uroCamUpdaterRank == 4)) uroCamStyle = 'hidden'; if((uroGetCBChecked('_cbHideUpdatedByRank5') === true) && (uroCamUpdaterRank == 5)) uroCamStyle = 'hidden'; if((uroGetCBChecked('_cbHideCWLCams') === true) && (uroIsCamOnWatchList(uroCam.attributes.id) != -1)) uroCamStyle = 'hidden'; var uroCamGeometryID = uroCam.geometry.id; if(camLayer.getElementById(uroCamGeometryID) !== null) { if(uroCamStyle == "hidden") { camLayer.getElementById(uroCamGeometryID).remove(); } } } } } } function uroFilterURs_onObjectsChanged() { if(uroFilterPreamble()) { if(uroBackfilling === false) { if(uroURDialogIsOpen === false) { uroURBackfill(); } else { uroFilterURs(); } } } } function uroFilterURs_onObjectsAdded() { if(uroFilterPreamble()) { if(uroBackfilling === false) { uroURBackfill(); } } } function uroFilterURs_onObjectsRemoved() { if(uroFilterPreamble()) { if(uroBackfilling === false) { uroURBackfill(); } } } function uroBackfillQueueObj(lon, lat, blockSize) { this.lon = lon; this.lat = lat; this.blockSize = blockSize; } function uroURBackfill_GetData() { if(uroBackfillQueue.length === 0) { uroBackfilling = false; uroFilterURs(); return; } var nextBFQueueObj = uroBackfillQueue.shift(); var lon = parseFloat(nextBFQueueObj.lon); var lat = parseFloat(nextBFQueueObj.lat); var blockSize = parseFloat(nextBFQueueObj.blockSize); uroAddLog('Backfill square '+lon+','+lat); var backfillReq = new XMLHttpRequest(); backfillReq.onreadystatechange = function () { if (backfillReq.readyState == 4) { uroAddLog('backfill data request, response '+backfillReq.status+' received'); if (backfillReq.status == 200) { var tResp = JSON.parse(backfillReq.responseText); var urCount = tResp.mapUpdateRequests.objects.length; uroAddLog(urCount+' URs loaded for backfill processing'); if(urCount == 500) { uroAddLog('WARNING - backfill data may have been pre-filtered by server'); } var backfilled = 0; for(var i=0; i<urCount; i++) { var urID = tResp.mapUpdateRequests.objects[i].id; if(W.model.mapUpdateRequests.objects[urID] === undefined) { var newUR = require('Waze/Feature/Vector/UpdateRequest'); var tUR = new newUR(tResp.mapUpdateRequests.objects[i]); var tPoint = new OpenLayers.Geometry.Point(); tPoint.x = tResp.mapUpdateRequests.objects[i].geometry.coordinates[0]; tPoint.y = tResp.mapUpdateRequests.objects[i].geometry.coordinates[1]; tPoint.transform(new OpenLayers.Projection("EPSG:4326"),new OpenLayers.Projection("EPSG:900913")); tUR.geometry = tPoint; var tReqBounds = new OpenLayers.Geometry.Polygon(); var tBounds = new OpenLayers.Bounds(); tBounds.left = tPoint.x; tBounds.right = tPoint.x; tBounds.top = tPoint.y; tBounds.bottom = tPoint.y; tReqBounds.bounds = tBounds; tUR.requestBounds = tReqBounds; W.model.mapUpdateRequests.put(tUR); backfilled++; } } uroAddLog(backfilled+' URs backfilled'); } uroURBackfill_GetData(); } }; var tURL = 'https://' + document.location.host; tURL += Waze.Config.api_base; tURL += '/Features?language=en&mapUpdateRequestFilter=0'; tURL += '&bbox='+(lon)+','+(lat)+','+(lon + blockSize)+','+(lat + blockSize); backfillReq.open('GET',tURL,true); backfillReq.send(); } function uroURBackfill() { if((uroGetCBChecked('_cbURBackfill') === false) || (uroGetCBChecked('_cbMasterEnable') === false)) { uroFilterURs(); return; } var nativeURCount = Object.keys(W.model.mapUpdateRequests.objects).length; if(nativeURCount < 500) { uroAddLog(nativeURCount+' URs loaded natively, no backfilling required'); uroFilterURs(); return; } uroAddLog('exactly 500 URs loaded, possible server-side filtering requiring backfill...'); var subSize = 0.1; var vpWidth = W.map.getExtent().getWidth(); var vpHeight = W.map.getExtent().getHeight(); var vpCentre = W.map.getCenter(); var vpLL = new OpenLayers.LonLat(); var vpUR = new OpenLayers.LonLat(); vpLL.lon = vpCentre.lon - (vpWidth / 2); vpLL.lat = vpCentre.lat - (vpHeight / 2); vpUR.lon = vpCentre.lon + (vpWidth / 2); vpUR.lat = vpCentre.lat + (vpHeight / 2); vpLL = vpLL.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326")); vpUR = vpUR.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326")); vpLL.lon -= (subSize / 2); vpLL.lat -= (subSize / 2); vpUR.lon += (subSize / 2); vpUR.lat += (subSize / 2); vpLL.lon = +vpLL.lon.toFixed(1); vpLL.lat = +vpLL.lat.toFixed(1); vpUR.lon = +vpUR.lon.toFixed(1); vpUR.lat = +vpUR.lat.toFixed(1); uroBackfilling = true; uroBackfillQueue = []; for(var bfLat = vpLL.lat; bfLat <= vpUR.lat; bfLat += subSize) { for(var bfLon = vpLL.lon; bfLon <= vpUR.lon; bfLon += subSize) { uroBackfillQueue.push(new uroBackfillQueueObj(bfLon, bfLat, subSize)); } } uroURBackfill_GetData(); } function uroFilterURs() { if(uroUserID === -1) return; // compatibility fix for URComments - based on code supplied by RickZabel var hasActiveURFilters = false; if(uroGetCBChecked('_cbMasterEnable') === true) { var urTabInputs = document.getElementById('uroCtrlURs').getElementsByTagName('input'); for(var loop = 0; loop < urTabInputs.length; loop++) { if(urTabInputs[loop].type == 'checkbox') { var ignoreCB = false; ignoreCB = ignoreCB || (urTabInputs[loop].id == '_cbCaseInsensitive'); ignoreCB = ignoreCB || (urTabInputs[loop].id == '_cbNoFilterForTaggedURs'); if((urTabInputs[loop].checked) && (ignoreCB === false)) { hasActiveURFilters = true; break; } } } } sessionStorage.UROverview_hasActiveURFilters = hasActiveURFilters; if(uroFilterPreamble() === false) return; uroRefreshUpdateRequestSessions(); var selectorResolver = document.getElementById('_selectURResolverID'); var selectorCommentUser = document.getElementById('_selectURUserID'); if(uroGetCBChecked('_cbURResolverIDFilter') === false) { while(selectorResolver.options.length > 0) { selectorResolver.options.remove(0); } } if(uroGetCBChecked('_cbURUserIDFilter') === false) { while(selectorCommentUser.options.length > 0) { selectorCommentUser.options.remove(0); } } if(Object.keys(W.model.updateRequestSessions.objects).length === 0) { return; } var commenterUser = null; if(uroGetCBChecked('_cbURUserIDFilter') === true) { if(selectorCommentUser.options.length === 0) { uroUpdateUserList(); } if(selectorCommentUser.selectedOptions[0] != null) { commenterUser = parseInt(selectorCommentUser.selectedOptions[0].value); } } var resolverUser = null; if(uroGetCBChecked('_cbURResolverIDFilter') === true) { if(selectorResolver.options.length === 0) { uroUpdateResolverList(); } if(selectorResolver.selectedOptions[0] != null) { resolverUser = parseInt(selectorResolver.selectedOptions[0].value); } } uroCustomMarkerList = []; var uFURs_masterEnable = uroGetCBChecked('_cbMasterEnable'); var filterOutsideEditableArea = uroGetCBChecked('_cbURFilterOutsideArea'); var filterSolved = uroGetCBChecked('_cbFilterSolved'); var filterUnidentified = uroGetCBChecked('_cbFilterUnidentified'); var filterClosed = uroGetCBChecked('_cbFilterClosedUR'); var filterOpen = uroGetCBChecked('_cbFilterOpenUR'); var filterDescMustBePresent = uroGetCBChecked('_cbURDescriptionMustBePresent'); var filterDescMustBeAbsent = uroGetCBChecked('_cbURDescriptionMustBeAbsent'); var filterKeywordMustBePresent = uroGetCBChecked('_cbEnableKeywordMustBePresent'); var filterKeywordMustBeAbsent = uroGetCBChecked('_cbEnableKeywordMustBeAbsent'); var filterMinURAge = uroGetCBChecked('_cbEnableMinAgeFilter'); var filterMaxURAge = uroGetCBChecked('_cbEnableMaxAgeFilter'); var filterMinComments = uroGetCBChecked('_cbEnableMinCommentsFilter'); var filterMaxComments = uroGetCBChecked('_cbEnableMaxCommentsFilter'); var filterReporterLastCommenter = uroGetCBChecked('_cbHideIfReporterLastCommenter'); var filterReporterNotLastCommenter = uroGetCBChecked('_cbHideIfReporterNotLastCommenter'); var filterHideAnyComments = uroGetCBChecked('_cbHideAnyComments'); var filterHideNotLastCommenter = uroGetCBChecked('_cbHideIfNotLastCommenter'); var filterHideMyComments = uroGetCBChecked('_cbHideMyComments'); var filterIfLastCommenter = uroGetCBChecked('_cbHideIfLastCommenter'); var filterIfNotLastCommenter = uroGetCBChecked('_cbHideIfNotLastCommenter'); var filterCommentMinAge = uroGetCBChecked('_cbEnableCommentAgeFilter2'); var filterCommentMaxAge = uroGetCBChecked('_cbEnableCommentAgeFilter'); var filterUserID = uroGetCBChecked('_cbURUserIDFilter'); var filterMyFollowed = uroGetCBChecked('_cbHideMyFollowed'); var filterMyUnfollowed = uroGetCBChecked('_cbHideMyUnfollowed'); var filterWazeAuto = uroGetCBChecked('_cbFilterWazeAuto'); var filterRoadworks = uroGetCBChecked('_cbFilterRoadworks'); var filterConstruction = uroGetCBChecked('_cbFilterConstruction'); var filterClosure = uroGetCBChecked('_cbFilterClosure'); var filterEvent = uroGetCBChecked('_cbFilterEvent'); var filterNote = uroGetCBChecked('_cbFilterNote'); var filterWSLM = uroGetCBChecked('_cbFilterWSLM'); var filterBOG = uroGetCBChecked('_cbFilterBOG'); var filterDifficult = uroGetCBChecked('_cbFilterDifficult'); var filterIncorrectTurn = uroGetCBChecked('_cbFilterIncorrectTurn'); var filterIncorrectAddress = uroGetCBChecked('_cbFilterIncorrectAddress'); var filterIncorrectRoute = uroGetCBChecked('_cbFilterIncorrectRoute'); var filterMissingRoundabout = uroGetCBChecked('_cbFilterMissingRoundabout'); var filterGeneralError = uroGetCBChecked('_cbFilterGeneralError'); var filterTurnNotAllowed = uroGetCBChecked('_cbFilterTurnNotAllowed'); var filterIncorrectJunction = uroGetCBChecked('_cbFilterIncorrectJunction'); var filterMissingBridgeOverpass = uroGetCBChecked('_cbFilterMissingBridgeOverpass'); var filterWrongDrivingDirection = uroGetCBChecked('_cbFilterWrongDrivingDirection'); var filterMissingExit = uroGetCBChecked('_cbFilterMissingExit'); var filterMissingRoad = uroGetCBChecked('_cbFilterMissingRoad'); var filterMissingLandmark = uroGetCBChecked('_cbFilterMissingLandmark'); var filterNativeSpeedLimit = uroGetCBChecked('_cbFilterSpeedLimits'); var filterBlockedRoad = uroGetCBChecked('_cbFilterBlockedRoad'); var filterUndefined = uroGetCBChecked('_cbFilterUndefined'); var invertURFilters = uroGetCBChecked('_cbInvertURFilter'); var invertURStateFilters = uroGetCBChecked('_cbInvertURStateFilter'); var noFilterTaggedURs = uroGetCBChecked('_cbNoFilterForTaggedURs'); var noFilterURInURL = uroGetCBChecked('_cbNoFilterForURInURL'); var keywordPresent = uroGetElmValue('_textKeywordPresent'); var keywordAbsent = uroGetElmValue('_textKeywordAbsent'); var thresholdMinAge = uroGetElmValue('_inputFilterMinDays'); var thresholdMaxAge = uroGetElmValue('_inputFilterMaxDays'); var thresholdMinComments = uroGetElmValue('_inputFilterMinComments'); var thresholdMaxComments = uroGetElmValue('_inputFilterMaxComments'); var thresholdMaxCommentAge = uroGetElmValue('_inputFilterCommentDays'); var thresholdMinCommentAge = uroGetElmValue('_inputFilterCommentDays2'); var ignoreOtherEditorComments = uroGetCBChecked('_cbIgnoreOtherEditorComments'); var urcFilteringIsActive = false; var urcCB = document.getElementById('URCommentsFilterEnabled'); if(urcCB !== null) { if(urcCB.checked) { urcFilteringIsActive = true; } } urcCB = document.getElementById('URCommentUROOnlyMyUR'); if(urcCB !== null) { if(urcCB.checked) { urcFilteringIsActive = true; } } urcCB = document.getElementById('URCommentUROHideTagged'); if(urcCB !== null) { if(urcCB.checked) { urcFilteringIsActive = true; } } for (var urobj in W.model.mapUpdateRequests.objects) { if(W.model.mapUpdateRequests.objects.hasOwnProperty(urobj)) { var ureq = W.model.mapUpdateRequests.objects[urobj]; var ureqID = null; if(ureq.fid === null) ureqID = ureq.attributes.id; else ureqID = ureq.fid; var urStyle = 'visible'; var inhibitFiltering = ((ureqID == uroURIDInURL) && (noFilterURInURL)); var hasMyComments = false; var nComments = 0; var customType = uroGetCustomType(ureqID, "ur"); if(W.model.updateRequestSessions.objects[ureqID] != null) { nComments = W.model.updateRequestSessions.objects[ureqID].comments.length; if((uFURs_masterEnable === false) && (nComments === 0)) { // when master enable is turned off, we want to make sure that all URs, including ones that were previously hidden, are correctly // displayed in their native form - i.e. no comment count or custom conversation bubbles. The easiest way to achieve this is to // force the uroRenderCustomMarkers code to test for the presence of these bubbles on each UR, which we do by setting a non-zero // comment count for each UR... For URs which genuinely do have no comments we use -1 to indicate that we're not really setting // a comment count, but that we still need to do something that wouldn't be achieved by using 0. nComments = -1; } } if((uFURs_masterEnable === true) && (inhibitFiltering === false)) { var wazeauto_ur = false; var ukroadworks_ur = false; var construction_ur = false; var closure_ur = false; var event_ur = false; var note_ur = false; var wslm_ur = false; var bog_ur = false; var difficult_ur = false; var filterByNotIncludedKeyword = false; var filterByIncludedKeyword = true; var desc = ''; if(ureq.attributes.description !== null) desc = ureq.attributes.description.replace(/<\/?[^>]+(>|$)/g, ""); if(customType === 0) ukroadworks_ur = true; else if(customType === 1) construction_ur = true; else if(customType === 2) closure_ur = true; else if(customType === 3) event_ur = true; else if(customType === 4) note_ur = true; else if(customType === 5) wslm_ur = true; else if(customType === 6) bog_ur = true; else if(customType === 7) difficult_ur = true; // check UR against editable area... if(filterOutsideEditableArea === true) { if(ureq.canEdit() === false) urStyle = 'hidden'; } // check UR against current session ignore list... if(uroIsOnIgnoreList(ureqID)) urStyle = 'hidden'; // state-age filtering if(urStyle == 'visible') { // check against closed/not identified filtering if enabled... if(filterSolved === true) { if(ureq.attributes.resolution === 0) urStyle = 'hidden'; } if(filterUnidentified === true) { if(ureq.attributes.resolution == 1) urStyle = 'hidden'; } if((ureq.attributes.resolvedOn !== null) && (filterClosed === true)) { urStyle = 'hidden'; } if((ureq.attributes.resolvedOn === null) && (filterOpen === true)) { urStyle = 'hidden'; } if(urStyle == 'visible') { // check UR against keyword filtering if enabled... if(filterDescMustBePresent === true) { if(desc === '') urStyle = 'hidden'; } if(filterDescMustBeAbsent === true) { if(desc !== '') urStyle = 'hidden'; } if(filterKeywordMustBePresent === true) { var keywordIsPresentInDesc = uroKeywordPresent(desc,keywordPresent); filterByIncludedKeyword &= (!keywordIsPresentInDesc); } if(filterKeywordMustBeAbsent === true) { var keywordIsAbsentInDesc = uroKeywordPresent(desc,keywordAbsent); filterByNotIncludedKeyword |= keywordIsAbsentInDesc; } } if(urStyle == 'visible') { // do age-based filtering if enabled if(filterMinURAge === true) { if(uroGetURAge(ureq,0,false) < thresholdMinAge) urStyle = 'hidden'; } if(filterMaxURAge === true) { if(uroGetURAge(ureq,0,false) > thresholdMaxAge) urStyle = 'hidden'; } } if(urStyle == 'visible') { if(resolverUser !== null) { if(ureq.attributes.resolvedBy != resolverUser) urStyle = 'hidden'; } } if(urStyle == 'visible') { // do comments/following filtering if(W.model.updateRequestSessions.objects[ureqID] != null) { nComments = W.model.updateRequestSessions.objects[ureqID].comments.length; var commentDaysOld = -1; if(filterMinComments === true) { if(nComments < thresholdMinComments) urStyle = 'hidden'; } if(filterMaxComments === true) { if(nComments > thresholdMaxComments) urStyle = 'hidden'; } if(nComments > 0) { var reporterIsLastCommenter = false; if(W.model.updateRequestSessions.objects[ureqID].comments[nComments-1].userID == -1) reporterIsLastCommenter = true; if(filterReporterLastCommenter === true) { if(reporterIsLastCommenter === true) urStyle = 'hidden'; } else if(filterReporterNotLastCommenter === true) { if(reporterIsLastCommenter === false) urStyle = 'hidden'; } hasMyComments = uroURHasMyComments(ureqID); if(hasMyComments === false) { if(filterHideAnyComments === true) urStyle = 'hidden'; if(filterHideNotLastCommenter === true) urStyle = 'hidden'; } else { if(filterHideMyComments === true) urStyle = 'hidden'; var userIsLastCommenter = false; if(W.model.updateRequestSessions.objects[ureqID].comments[nComments-1].userID == uroUserID) userIsLastCommenter = true; if(filterIfLastCommenter === true) { if(userIsLastCommenter === true) urStyle = 'hidden'; } else if(filterIfNotLastCommenter === true) { if(userIsLastCommenter === false) urStyle = 'hidden'; } } var cidx; if(ignoreOtherEditorComments === false) { commentDaysOld = uroGetCommentAge(W.model.updateRequestSessions.objects[ureqID].comments[nComments-1]); } else { for(cidx=0; cidx<nComments; cidx++) { var cObj = W.model.updateRequestSessions.objects[ureqID].comments[cidx]; if((cObj.userID == uroUserID) || (cObj.userID == -1)) { commentDaysOld = uroGetCommentAge(cObj); } } } if((filterCommentMinAge === true) && (commentDaysOld != -1)) { if(thresholdMinCommentAge > commentDaysOld) urStyle = 'hidden'; } if((filterCommentMaxAge === true) && (commentDaysOld != -1)) { if(thresholdMaxCommentAge < commentDaysOld) urStyle = 'hidden'; } if((commenterUser !== null) && (urStyle != 'hidden')) { urStyle = 'hidden'; for(cidx=0; cidx<nComments; cidx++) { if(W.model.updateRequestSessions.objects[ureqID].comments[cidx].userID == commenterUser) { urStyle = 'visible'; break; } } } var commentText = ''; for(cidx=0; cidx<nComments; cidx++) { commentText += W.model.updateRequestSessions.objects[ureqID].comments[cidx].text; } if(filterKeywordMustBePresent === true) { var keywordIsPresentInComments = uroKeywordPresent(commentText,keywordPresent); filterByIncludedKeyword &= (!keywordIsPresentInComments); } if(filterKeywordMustBeAbsent === true) { var keywordIsAbsentInComments = uroKeywordPresent(commentText,keywordAbsent); filterByNotIncludedKeyword |= keywordIsAbsentInComments; } } else { if(filterUserID === true) { urStyle = 'hidden'; } } filterByNotIncludedKeyword &= filterKeywordMustBeAbsent; filterByIncludedKeyword &= filterKeywordMustBePresent; if(filterByNotIncludedKeyword || filterByIncludedKeyword) { urStyle = 'hidden'; } if(W.model.updateRequestSessions.objects[ureqID].isFollowing === true) { if(filterMyFollowed === true) urStyle = 'hidden'; } else { if(filterMyUnfollowed === true) urStyle = 'hidden'; } } } if(invertURStateFilters === true) { if(urStyle == 'hidden') urStyle = 'visible'; else urStyle = 'hidden'; } } // type filtering if(urStyle == 'visible') { // Test for Waze automatic URs before any others - these always (?) get inserted as General Error URs, // so we can't filter them by type... if(desc.indexOf('Waze Automatic:') != -1) { wazeauto_ur = true; } if(wazeauto_ur === true) { if(filterWazeAuto === true) urStyle = 'hidden'; } else if(ukroadworks_ur === true) { if(filterRoadworks === true) urStyle = 'hidden'; } else if(construction_ur === true) { if(filterConstruction === true) urStyle = 'hidden'; } else if(closure_ur === true) { if(filterClosure === true) urStyle = 'hidden'; } else if(event_ur === true) { if(filterEvent === true) urStyle = 'hidden'; } else if(note_ur === true) { if(filterNote === true) urStyle = 'hidden'; } else if(wslm_ur === true) { if(filterWSLM === true) urStyle = 'hidden'; } else if(bog_ur === true) { if(filterBOG === true) urStyle = 'hidden'; } else if(difficult_ur === true) { if(filterDifficult === true) urStyle = 'hidden'; } else if(ureq.attributes.type == 6) { if(filterIncorrectTurn === true) urStyle = 'hidden'; } else if(ureq.attributes.type == 7) { if (filterIncorrectAddress === true) urStyle = 'hidden'; } else if(ureq.attributes.type == 8) { if(filterIncorrectRoute === true) urStyle = 'hidden'; } else if(ureq.attributes.type == 9) { if(filterMissingRoundabout === true) urStyle = 'hidden'; } else if(ureq.attributes.type == 10) { if(filterGeneralError === true) urStyle = 'hidden'; } else if(ureq.attributes.type == 11) { if(filterTurnNotAllowed === true) urStyle = 'hidden'; } else if(ureq.attributes.type == 12) { if(filterIncorrectJunction === true) urStyle = 'hidden'; } else if(ureq.attributes.type == 13) { if(filterMissingBridgeOverpass === true) urStyle = 'hidden'; } else if(ureq.attributes.type == 14) { if(filterWrongDrivingDirection === true) urStyle = 'hidden'; } else if(ureq.attributes.type == 15) { if(filterMissingExit === true) urStyle = 'hidden'; } else if(ureq.attributes.type == 16) { if(filterMissingRoad === true) urStyle = 'hidden'; } else if(ureq.attributes.type == 18) { if(filterMissingLandmark === true) urStyle = 'hidden'; } else if(ureq.attributes.type == 19) { if(filterBlockedRoad === true) urStyle = 'hidden'; } else if(ureq.attributes.type == 23) { if(filterNativeSpeedLimit === true) urStyle = 'hidden'; } else if(filterUndefined === true) urStyle = 'hidden'; if(invertURFilters === true) { if(urStyle == 'hidden') urStyle = 'visible'; else urStyle = 'hidden'; } } // stage-age filtering override for tagged URs if(noFilterTaggedURs === true) { if(ukroadworks_ur === true) { if(filterRoadworks === false) urStyle = 'visible'; } else if(construction_ur === true) { if(filterConstruction === false) urStyle = 'visible'; } else if(closure_ur === true) { if(filterClosure === false) urStyle = 'visible'; } else if(event_ur === true) { if(filterEvent === false) urStyle = 'visible'; } else if(note_ur === true) { if(filterNote === false) urStyle = 'visible'; } else if(wslm_ur === true) { if(filterWSLM === false) urStyle = 'visible'; } } } // only touch marker visibility if we've got active filter settings, or if URComments is not // doing any filtering of its own if((hasActiveURFilters === true) || (urcFilteringIsActive === false) || (uFURs_masterEnable === false)) { W.map.updateRequestLayer.markers[urobj].icon.imageDiv.style.visibility = urStyle; } if(urStyle != 'hidden') { uroAddCustomMarkers(ureqID,'ur',customType, hasMyComments, nComments); } } } uroRenderCustomMarkers('ur'); } function uroGetProblemTypes() { uroKnownProblemTypeIDs = []; uroKnownProblemTypeNames = []; var tProblemList = I18n.lookup("problems.types"); for(var tObj in tProblemList) { if(tObj !== undefined) { uroKnownProblemTypeIDs.push(parseInt(tObj)); uroKnownProblemTypeNames.push(tProblemList[tObj].title); } } } function uroFilterProblems() { if(uroFilterPreamble() === false) return; var selector; if((uroGetCBChecked('_cbMPNotClosedUserIDFilter') === false) && (uroGetCBChecked('_cbMPClosedUserIDFilter') === false)) { selector = document.getElementById('_selectMPUserID'); while(selector.options.length > 0) { selector.options.remove(0); } } var solverUser = null; if((uroGetCBChecked('_cbMPNotClosedUserIDFilter') === true) || (uroGetCBChecked('_cbMPClosedUserIDFilter') === true)) { selector = document.getElementById('_selectMPUserID'); if(selector.options.length === 0) { uroUpdateMPSolverList(); } if(selector.selectedOptions[0] != null) { solverUser = parseInt(selector.selectedOptions[0].value); } } var urobj; var problem; var problemStyle; var problem_marker_img; var uFP_masterEnable = uroGetCBChecked('_cbMasterEnable'); var filter_OutsideEditableArea = uroGetCBChecked('_cbMPFilterOutsideArea'); var filter_Solved = uroGetCBChecked('_cbMPFilterSolved'); var filter_Unidentified = uroGetCBChecked('_cbMPFilterUnidentified'); var filter_Closed = uroGetCBChecked('_cbMPFilterClosed'); var filter_NotClosedUserID = uroGetCBChecked('_cbMPNotClosedUserIDFilter'); var filter_ClosedUserID = uroGetCBChecked('_cbMPClosedUserIDFilter'); var filter_Reopened = uroGetCBChecked('_cbMPFilterReopenedProblem'); var filter_LowSeverity = uroGetCBChecked('_cbMPFilterLowSeverity'); var filter_MediumSeverity = uroGetCBChecked('_cbMPFilterMediumSeverity'); var filter_HighSeverity = uroGetCBChecked('_cbMPFilterHighSeverity'); var filter_TurnProblems = uroGetCBChecked('_cbMPFilterTurnProblem'); var filterTypes = []; var i; for(i=0; i<uroKnownProblemTypeIDs.length; i++) { if(uroGetCBChecked('_cbMPFilter_T'+uroKnownProblemTypeIDs[i])) filterTypes.push(uroKnownProblemTypeIDs[i]); } var filter_TypeUnknown = uroGetCBChecked('_cbMPFilterUnknownProblem'); var filter_TaggedElgin = uroGetCBChecked('_cbFilterElgin'); var filter_TaggedTrafficCast = uroGetCBChecked('_cbFilterTrafficCast'); var filter_TaggedTrafficMaster = uroGetCBChecked('_cbFilterTrafficMaster'); var filter_TaggedCaltrans = uroGetCBChecked('_cbFilterCaltrans'); var filter_TaggedTFL = uroGetCBChecked('_cbFilterTFL'); var filter_Invert = uroGetCBChecked('_cbInvertMPFilter'); for (urobj in W.model.problems.objects) { if(W.model.problems.objects.hasOwnProperty(urobj)) { problem = W.model.problems.objects[urobj]; problemStyle = 'visible'; var ureqID = null; var customType = null; if(uFP_masterEnable === true) { var elgin_mp = false; var trafficcast_mp = false; var trafficmaster_mp = false; var caltrans_mp = false; var tfl_mp = false; ureqID = problem.attributes.id; customType = uroGetCustomType(ureqID, "mp"); if(customType === 100) elgin_mp = true; else if(customType === 101) trafficcast_mp = true; else if(customType === 102) trafficmaster_mp = true; else if(customType === 103) caltrans_mp = true; else if(customType === 104) tfl_mp = true; // check problem against current session ignore list... if(uroIsOnIgnoreList(ureqID)) problemStyle = 'hidden'; if(filter_OutsideEditableArea === true) { if(problem.canEdit() === false) { problemStyle = 'hidden'; } } // check against closed/not identified filtering if enabled... problem_marker_img = ''; if(problem.geometry.id !== null) { if(document.getElementById(problem.geometry.id) !== null) { problem_marker_img = document.getElementById(problem.geometry.id).href.baseVal; if(filter_Solved === true) { if(problem_marker_img.indexOf('_solved') != -1) problemStyle = 'hidden'; } if(filter_Unidentified === true) { if(problem_marker_img.indexOf('_rejected') != -1) problemStyle = 'hidden'; } } } if(filter_Closed === true) { if(problem.attributes.open === false) { problemStyle = 'hidden'; } } if(problemStyle == 'visible') { if(solverUser !== null) { if((filter_NotClosedUserID === true) && (problem.attributes.resolvedBy == solverUser)) problemStyle = 'hidden'; if((filter_ClosedUserID === true) && (problem.attributes.resolvedBy != solverUser)) problemStyle = 'hidden'; } } if(problemStyle == 'visible') { var problemType = null; if(uroDOMHasTurnProblems) { problemType = problem.attributes.problemType; } else { problemType = problem.attributes.subType; } if(elgin_mp === true) { if(filter_TaggedElgin === true) problemStyle = 'hidden'; } else if(trafficcast_mp === true) { if(filter_TaggedTrafficCast === true) problemStyle = 'hidden'; } else if(trafficmaster_mp === true) { if(filter_TaggedTrafficMaster === true) problemStyle = 'hidden'; } else if(caltrans_mp === true) { if(filter_TaggedCaltrans === true) problemStyle = 'hidden'; } else if(tfl_mp === true) { if(filter_TaggedTFL === true) problemStyle = 'hidden'; } else if(uroKnownProblemTypeIDs.indexOf(problemType) !== -1) { if(filterTypes.indexOf(problemType) !== -1) { problemStyle = 'hidden'; } } else if(filter_TypeUnknown === true) problemStyle = 'hidden'; if(filter_Reopened === true) { if((problem.attributes.open === true) && (problem.attributes.resolvedOn !== null)) { problemStyle = 'hidden'; } } if(filter_Invert === true) { if(problemStyle == 'hidden') problemStyle = 'visible'; else problemStyle = 'hidden'; } if(problem.attributes.weight <= 3) { if(filter_LowSeverity === true) problemStyle = 'hidden'; } else if(problem.attributes.weight <= 7) { if(filter_MediumSeverity === true) problemStyle = 'hidden'; } else if(filter_HighSeverity === true) problemStyle = 'hidden'; } } W.map.problemLayer.markers[urobj].icon.imageDiv.style.visibility = problemStyle; if((problemStyle != 'hidden') && (ureqID !== null) && (customType !== null)) { uroAddCustomMarkers(ureqID,'mp',customType, false, 0); } } } if(uroDOMHasTurnProblems) { for (urobj in W.model.turnProblems.objects) { if(W.model.turnProblems.objects.hasOwnProperty(urobj)) { problem = W.model.turnProblems.objects[urobj]; problemStyle = 'visible'; if(uFP_masterEnable === true) { // check problem against current session ignore list... if(uroIsOnIgnoreList(problem.attributes.id)) problemStyle = 'hidden'; // check against closed/not identified filtering if enabled... problem_marker_img = ''; if(problem.geometry.id !== null) { if(document.getElementById(problem.geometry.id) !== null) { problem_marker_img = document.getElementById(problem.geometry.id).href.baseVal; if(filter_Solved === true) { if(problem_marker_img.indexOf('_solved') != -1) problemStyle = 'hidden'; } if(filter_Unidentified === true) { if(problem_marker_img.indexOf('_rejected') != -1) problemStyle = 'hidden'; } } } if(filter_Closed === true) { if(problem.attributes.open === false) { problemStyle = 'hidden'; } } if(problemStyle == 'visible') { if(filter_TurnProblems === true) problemStyle = 'hidden'; if(filter_Reopened === true) { if((problem.attributes.open === true) && (problem.attributes.resolvedOn !== null)) { problemStyle = 'hidden'; } } if(filter_Invert === true) { if(problemStyle == 'hidden') problemStyle = 'visible'; else problemStyle = 'hidden'; } } } W.map.problemLayer.markers[urobj].icon.imageDiv.style.visibility = problemStyle; } } } uroRenderCustomMarkers('mp'); } function uroToHex(decValue,digits) { var modifier = 1; for(var i=0; i<digits; i++) { modifier *= 16; } decValue = parseInt(decValue); decValue += modifier; var retval = decValue.toString(16); retval = retval.substr(-digits); retval = retval.toUpperCase(); return retval; } function uroFilterPreamble() { var mapviewport = document.getElementsByClassName("olMapViewport")[0]; if(mapviewport === null) { if(uroNullMapViewport === false) { uroAddLog('caught null mapviewport'); uroNullMapViewport = true; } return false; } var uiElms = document.getElementById('uroCtrlMisc'); if(uiElms == null) { uroAddLog('caught missing UI'); return false; } if(uiElms.innerHTML.length === 0) { uroAddLog('caught empty UI'); return false; } uroNullMapViewport = false; return true; } function uroFilterItems_URTabClick() { uroFilterURs(); } function uroFilterItems_MPTabClick() { uroFilterProblems(); } function uroFilterItems_PlacesTabClick() { uroFilterPlaces(); } function uroFilterItems_CamerasTabClick() { uroFilterCameras(); } function uroFilterItems_MiscTabClick() { uroFilterItems(); } function uroFilterItems_MasterEnableClick() { if(uroGetCBChecked('_cbMasterEnable') === false) { uroHidePopup(); } uroFilterItems(); } function uroScaleTheScaleBar() { // adjust the scale bar to more accurately reflect true distances at all latitudes var currLat = W.map.getCenter().transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326")).lat; if((currLat < 85) && (currLat > -85)) { var cosLat = Math.cos((currLat * Math.PI) / 180); var scaleElm; var elmWidth; scaleElm = document.getElementsByClassName('olControlScaleLineTop')[0]; if(scaleElm.innerHTML.indexOf(' ') !== -1) { elmWidth = Math.round((scaleElm.clientWidth + 2) / cosLat); scaleElm.innerHTML = scaleElm.innerHTML.replace(' ',''); scaleElm.style.width = elmWidth + 'px'; } scaleElm = document.getElementsByClassName('olControlScaleLineBottom')[0]; if(scaleElm.innerHTML.indexOf(' ') !== -1) { elmWidth = Math.round((scaleElm.clientWidth + 2) / cosLat); scaleElm.innerHTML = scaleElm.innerHTML.replace(' ',''); scaleElm.style.width = elmWidth + 'px'; } } } function uroFilterItems() { uroScaleTheScaleBar(); uroFilterProblems(); uroFilterPlaces(); uroFilterCameras(); uroFilterURs(); } function uroFilterItemsOnMove() { W.map.events.unregister('mousemove',null,uroFilterItemsOnMove); uroFilterItems(); } function uroDeleteObject() { uroAddLog('delete camera ID '+uroShownFID); if(W.model.cameras.objects[uroShownFID] === null) { uroAddLog('camera object not found...'); return false; } uroRemoveCamFromWatchList(); var actionObj = require('Waze/Action/DeleteObject'); var deleteAction = new actionObj(W.model.cameras.objects[uroShownFID], null); W.model.actionManager.add(deleteAction); uroExitPopup(); uroHidePopup(); return false; } function uroGetUserNameAndRank(userID) { var userName; var userLevel; if(W.model.users.objects[userID] != null) { userName = W.model.users.objects[userID].userName; if(userName === undefined) { userName = userID; } userLevel = W.model.users.objects[userID].rank + 1; } else { userName = userID; userLevel = '?'; } return userName + ' (' + userLevel + ')'; } function uroCheckCommentsForTag(idSrc, customText) { var ursObj = W.model.updateRequestSessions.objects[idSrc]; if(typeof(ursObj) == 'undefined') return -1; if(ursObj.comments.length === 0) return -1; for(var idx=ursObj.comments.length-1; idx>=0; idx--) { for(var tag=0; tag<uroCustomURTags.length; tag++) { var keyword = uroCustomURTags[tag]; if(ursObj.comments[idx].text.indexOf(keyword) != -1) { return tag; } } if(customText !== '') { if(ursObj.comments[idx].text.toLowerCase().indexOf(customText) != -1) { return 99; } } } return -1; } function uroGetCustomMarkerIdx(customType) { if(customType === 0) return 1; // ROADWORKS if(customType === 1) return 1; // CONSTRUCTION if(customType === 2) return 0; // CLOSURE if(customType === 3) return 4; // EVENT if(customType === 4) return 3; // NOTE if(customType === 5) return 5; // WSLM if(customType === 6) return 11; // BOG if(customType === 7) return 12; // DIFFICULT if(customType === 98) return 5; // Native speed limit URs if(customType === 99) return 2; // custom text if(customType === 100) return 6; // ELGIN if(customType === 101) return 7; // TRAFFICCAST if(customType === 102) return 8; // TRAFFICMASTER if(customType === 103) return 9; // CALTRANS if(customType === 104) return 10; // TFL return -1; } function uroGetCustomType(idSrc, markerType) { var desc = ''; var provider = ''; var customText = ''; if(uroGetCBChecked('_cbCustomKeywordMarkers')) customText = document.getElementById('_textCustomKeyword').value.toLowerCase(); if(markerType == "ur") { var ureq = W.model.mapUpdateRequests.objects[idSrc]; // early test for native speed limit URs if(ureq.attributes.type == 23) return 98; // UR objects always have a .description attribute, which is set to null if empty... if(ureq.attributes.description !== null) { desc = ureq.attributes.description; } } else if(markerType == "mp") { var mp = W.model.problems.objects[idSrc]; // ...whereas MP objects with a blank description don't even get the attribute if(mp.attributes.description != null) { desc = mp.attributes.description; } if(mp.attributes.provider != null) { provider = mp.attributes.provider; } } if(desc !== '') { if(markerType == 'ur') { for(var tag=0; tag<uroCustomURTags.length; tag++) { var keyword = uroCustomURTags[tag]; if(desc.indexOf(keyword) != -1) { return tag; } } } if((uroGetCBChecked('_cbCustomKeywordMarkers')) && (customText !== '')) { if(desc.toLowerCase().indexOf(customText) != -1) return 99; } if(markerType == 'mp') { if(desc.indexOf('[Elgin]') != -1) return 100; if(desc.indexOf('[TrafficCast]') != -1) return 101; if(desc.indexOf('[TM]') != -1) return 102; if(desc.indexOf('[Caltrans]') != -1) return 103; if(desc.indexOf('[TfL Open Data]') != -1) return 104; if(provider.indexOf('London TFL Closures') != -1) return 104; } } if(markerType == "ur") { return uroCheckCommentsForTag(idSrc, customText); } return -1; } function uroFormatRestriction(restObj) { var retval = '<tr>'; retval += '<td style="text-align:center;">'; if((restObj._days & 1) == 1) retval += 'S'; else retval += '-'; retval += '</td><td style="text-align:center;">'; if((restObj._days & 2) == 2) retval += 'M'; else retval += '-'; retval += '</td><td style="text-align:center;">'; if((restObj._days & 4) == 4) retval += 'T'; else retval += '-'; retval += '</td><td style="text-align:center;">'; if((restObj._days & 8) == 8) retval += 'W'; else retval += '-'; retval += '</td><td style="text-align:center;">'; if((restObj._days & 16) == 16) retval += 'T'; else retval += '-'; retval += '</td><td style="text-align:center;">'; if((restObj._days & 32) == 32) retval += 'F'; else retval += '-'; retval += '</td><td style="text-align:center;">'; if((restObj._days & 64) == 64) retval += 'S'; else retval += '-'; retval += '</td><td>'; if(restObj._fromDate === null) retval += 'All dates'; else retval += restObj._fromDate+' to '+restObj._toDate; retval += '</td><td>'; if(restObj._allDay === true) retval += 'All day'; else retval += restObj._fromTime+' to '+restObj._toTime; retval += '</td><td>'; if(restObj.allVehicleTypes == restObj._vehicleTypes) retval += 'All vehicles'; else retval += 'Some vehicles'; retval += '</td><td>'; if(restObj._description !== null) { var desc = restObj._description.replace(/<\/?[^>]+(>|$)/g, ""); desc = uroClickify(desc); retval += desc; } retval += '</td></tr>'; return retval; } function uroHidePopup() { if(uroPopupShown) { uroDiv.style.visibility = 'hidden'; uroPopupShown = false; uroPopupTimer = -2; uroShownFID = -1; } uroPopupSuppressed = false; } function uroSuppressPopup() { uroDiv.style.visibility = 'hidden'; window.getSelection().removeAllRanges(); uroPopupSuppressed = true; } function uroRecentreSessionOnUR() { W.map.updateRequestLayer.markers[uroShownFID].icon.imageDiv.click(); W.map.moveTo(W.map.updateRequestLayer.markers[uroShownFID].lonlat, 5); uroHidePopup(); return false; } function uroRecentreSessionOnMP() { W.map.problemLayer.markers[uroShownFID].icon.imageDiv.click(); W.map.moveTo(W.map.problemLayer.markers[uroShownFID].lonlat, 5); uroHidePopup(); return false; } function uroRecentreSessionOnPUR() { W.map.placeUpdatesLayer.markers[uroShownFID].icon.imageDiv.click(); W.map.moveTo(W.map.placeUpdatesLayer.markers[uroShownFID].lonlat, 5); uroHidePopup(); return false; } function uroRecentreSessionOnVenueNavPoint() { W.map.moveTo(uroGetVenueNavPoint(uroShownFID), 5); uroHidePopup(); return false; } function uroGetDateTimeString(ts) { var tDateObj = new Date(ts); var dateLocale; var timeLocale; if(uroGetCBChecked('_cbDateFmtDDMMYY')) dateLocale = 'en-gb'; if(uroGetCBChecked('_cbDateFmtMMDDYY')) dateLocale = 'en-us'; if(uroGetCBChecked('_cbDateFmtYYMMDD')) dateLocale = 'ja'; if(uroGetCBChecked('_cbTimeFmt24H')) timeLocale = 'en-gb'; if(uroGetCBChecked('_cbTimeFmt12H')) timeLocale = 'en-us'; return tDateObj.toLocaleDateString(dateLocale) + ' ' + tDateObj.toLocaleTimeString(timeLocale); } function uroParsePxString(pxString) { return parseInt(pxString.split("px")[0]); } function uroStackListObj(fid,x,y) { this.fid = fid; this.x = uroTypeCast(x); this.y = uroTypeCast(y); } function uroRestackMarkers() { if(uroStackList.length === 0) return; var markerCollection = null; if(uroStackType == 1) markerCollection = W.map.updateRequestLayer.markers; else if(uroStackType == 2) markerCollection = W.map.problemLayer.markers; else if(uroStackType == 3) markerCollection = W.map.placeUpdatesLayer.markers; if(markerCollection !== null) { uroAddLog('restacking markers...'); // strip off the .realX/realY attributes from any UR object we've previously added it to, to allow // the native recentering to work again... for(var marker in markerCollection) { if(markerCollection.hasOwnProperty(marker)) { var testMarkerObj = markerCollection[marker]; if(testMarkerObj.model.attributes.geometry.realX != null) { testMarkerObj.model.attributes.geometry.x = testMarkerObj.model.attributes.geometry.realX; testMarkerObj.model.attributes.geometry.y = testMarkerObj.model.attributes.geometry.realY; delete(testMarkerObj.model.attributes.geometry.realX); delete(testMarkerObj.model.attributes.geometry.realY); } } } // now restack any markers that were repositioned... for(var idx=0; idx<uroStackList.length; idx++) { var orig_x = uroStackList[idx].x + 'px'; var orig_y = uroStackList[idx].y + 'px'; var fid = uroStackList[idx].fid; if(markerCollection[fid] != null) { markerCollection[fid].icon.imageDiv.style.left = orig_x; markerCollection[fid].icon.imageDiv.style.top = orig_y; } } uroStackList = []; uroUnstackedMasterID = null; uroStackType = null; } } function uroIsIDAlreadyUnstacked(idSrc) { if(uroStackList.length === 0) return false; for(var idx=0; idx<uroStackList.length; idx++) { if(uroStackList[idx].fid == idSrc) return true; } return false; } function uroCheckStacking(stackType, masterID, unstackedX, unstackedY) { if(uroIsIDAlreadyUnstacked(masterID) === true) return; if(uroStackType !== null) return; if(uroPopupDwellTimer > 0) return; uroAddLog('checking for marker stack, masterID: '+masterID+', stackType: '+stackType); var stackList = []; stackList.push(masterID); var threshSquared = uroGetElmValue('_inputUnstackSensitivity'); threshSquared *= threshSquared; var markerCollection = null; var marker; if(stackType == 1) markerCollection = W.map.updateRequestLayer.markers; else if(stackType == 2) markerCollection = W.map.problemLayer.markers; else if(stackType == 3) markerCollection = W.map.placeUpdatesLayer.markers; var offset = 1000000000; if(markerCollection !== null) { for(marker in markerCollection) { if(markerCollection.hasOwnProperty(marker)) { var testMarkerObj = markerCollection[marker]; var includeInStack = (testMarkerObj.icon.imageDiv.style.visibility != 'hidden'); var suppressClosed = (testMarkerObj.icon.imageDiv.classList.contains("recently-closed") & (W.map.updateRequestLayer.showHidden === false)); // if multiple markers are stacked exactly on top of one another, WME will always open up the one which it would have rendered on the // top of the stack in the absence of any URO+ filtering, regardless of which UR pin actually receives the click event. To prevent // this, we give each pin in the stack a unique set of false coordinates, storing the original coordinates in newly created // properties so they can be restored later on // // originally this fix changed the x coordinate for each UR in the stack to be a unique value that ought to have been well out of the range // of any real coordinate and therefore unable to clash with any UR marker coordinates that weren't in the current stack. However it now // appears this could then cause WME to think a completely different UR was being opened - possibly as a result of some change in coordinate // handling allowing out of range values to be wrapped around back into the normal range? As a workaround for this new WME behaviour, both the // x and y coordinates are now set to valid values somewhere in the North Atlantic Ocean - the likelihood of there being any real URs in this // area is so vanishingly small as to be not worth worrying about... if(testMarkerObj.model.attributes.geometry.realX === undefined) { testMarkerObj.model.attributes.geometry.realX = testMarkerObj.model.attributes.geometry.x; testMarkerObj.model.attributes.geometry.x += offset; testMarkerObj.model.attributes.geometry.realY = testMarkerObj.model.attributes.geometry.y; testMarkerObj.model.attributes.geometry.y += offset; offset += 1000; } if((includeInStack) && (!suppressClosed)) { if(testMarkerObj.id != masterID) { var xdiff = unstackedX - uroParsePxString(markerCollection[testMarkerObj.id].icon.imageDiv.style.left); var ydiff = unstackedY - uroParsePxString(markerCollection[testMarkerObj.id].icon.imageDiv.style.top); var distSquared = ((xdiff * xdiff) + (ydiff * ydiff)); if(distSquared < threshSquared) { stackList.push(testMarkerObj.id); } } } } } } // as it's the fiddling with .geometry.x which seems to inhibit the autocentering behaviour when a UR/MP marker is clicked, we need to // allow this to occur even if unstacking isn't required at this zoom level. To then reenable recentering when clicking on the crosshairs // or feed entry, we need to reinstate the correct .x value once the marker is no longer being highlighted, which means we pretty much need // to do all of the unstacking *except* for actually unstacking the stack and hiding the other markers... var inhibitUnstacking = (W.map.getZoom() < uroGetElmValue('_inputUnstackZoomLevel')); // also inhibit unstacking if there's only a single marker in the list - this will be true if we're highlighting an isolated marker that // doesn't need to be unstacked, and where we're only using the .geometry.x fiddle to prevent autocentering... inhibitUnstacking |= (stackList.length == 1); uroStackType = stackType; if(stackList.length > 0) { if(inhibitUnstacking) uroAddLog('single marker highlighted, adjusting geometry properties to prevent recentering...'); else uroAddLog('markers are stacked!'); if(uroUnstackedMasterID != masterID) { uroAddLog('unstacked ID mismatch, relocating markers...'); uroRestackMarkers(); uroUnstackedMasterID = masterID; uroStackList = []; // push the highlighted marker onto the stacklist so uroIsIDAlreadyUnstacked() will return true uroStackList.push(new uroStackListObj(masterID,unstackedX,unstackedY)); for(var shoveIdx=0; shoveIdx < stackList.length; shoveIdx++) { var fid = stackList[shoveIdx]; var x = uroParsePxString(markerCollection[fid].icon.imageDiv.style.left); var y = uroParsePxString(markerCollection[fid].icon.imageDiv.style.top); // store the unstacked marker positions so they can be reinstated later uroStackList.push(new uroStackListObj(fid,x,y)); if(!inhibitUnstacking) { markerCollection[fid].icon.imageDiv.style.left = unstackedX + 'px'; markerCollection[fid].icon.imageDiv.style.top = unstackedY + 'px'; unstackedX += 10; unstackedY -= 30; } } if(!inhibitUnstacking) { // hide other markers to prevent confusion with the unstacked markers for(marker in markerCollection) { if(markerCollection.hasOwnProperty(marker)) { var toHideID = markerCollection[marker].id; if(uroIsIDAlreadyUnstacked(toHideID) === false) { markerCollection[toHideID].icon.imageDiv.style.visibility = 'hidden'; } } } } } } else { uroRestackMarkers(); } } function uroGetVenueNavPoint(uroFID) { for(var vObj in W.model.venues.objects) { if(W.model.venues.objects.hasOwnProperty(vObj)) { if(uroFID == vObj) { return W.model.venues.objects[vObj].getNavigationPoint().point.toLonLat(); } } } // just in case... return a safe value if the requested venue object wasn't found return W.map.getCenter(); } function uroOpenNewTab() { // flush the current settings into localStorage before the new tab opens, so that when its instance of // URO+ fires up it'll have the same settings as this one uroSaveSettings(); return true; } function uroEditTBR() { if(uroTBRObj === null) { return; } uroTBRObj.getElementsByClassName('waze-icon-clock')[0].click(); return false; } function uroKillCentering() { return W.map.getExtent(); } function uroRestoreCentering() { if(uroAutoCentreDisabledOn.length > 0) { if(uroAutoCentreDisabledOn[0] == 'PUR') { if(W.map.placeUpdatesLayer.markers[uroAutoCentreDisabledOn[1]] != null) { W.map.placeUpdatesLayer.markers[uroAutoCentreDisabledOn[1]].model.geometry.getBounds = W.map.placeUpdatesLayer.markers[uroAutoCentreDisabledOn[1]].model.geometry.origGetBounds; } } else if(uroAutoCentreDisabledOn[0] == 'MP') { if(W.map.problemLayer.markers[uroAutoCentreDisabledOn[1]] != null) { W.map.problemLayer.markers[uroAutoCentreDisabledOn[1]].model.getDisconnectBounds = W.map.problemLayer.markers[uroAutoCentreDisabledOn[1]].model.origGetDisconnectBounds; } } uroAutoCentreDisabledOn = []; } } function uroAddClosureRowToTable(rcObj) { var result = ''; if(rcObj.active === true) { result += '<tr>'; } else { result += '<tr bgcolor="#C0C0C0">'; } var startDate = rcObj.startDate; var endDate = "unknown"; if(rcObj.endDate !== null) { endDate = rcObj.endDate; } var provider = "---"; if(rcObj.provider !== null) { provider = rcObj.provider; } else if(rcObj.createdBy !== null) { provider = uroGetUserNameAndRank(rcObj.createdBy); } var reason = "---"; if(rcObj.reason !== null) { reason = rcObj.reason; } var mte = "---"; if(rcObj.eventId !== null) { try { mte = W.model.majorTrafficEvents.objects[rcObj.eventId].attributes.names[0].value; } catch(err) { } } result += '<td>' + startDate + ' to ' + endDate + '</td>'; result += '<td>' + provider + '</td>'; result += '<td>' + reason + '</td>'; result += '<td>' + mte + '</td>'; result += '</td></tr>'; return result; } function uroGetAddress(streetID, houseNumber, formatForSegmentPopup) { var result = ''; if((houseNumber !== undefined) && (houseNumber !== null)) { result += houseNumber + ' '; } if(streetID != null) { var streetName = I18n.lookup('edit.address.no_street'); var doesStreetIDExist = true; if(W.model.streets.objects[streetID] === undefined) { streetName = 'non-existent streetID'; doesStreetIDExist = false; } else { if((streetName !== null) && (W.model.streets.objects[streetID].isEmpty === false)) { streetName = W.model.streets.objects[streetID].name; } } if(formatForSegmentPopup === true) { result += '<b>'+streetName+'</b><br>'; } else { result += streetName + ', '; } if(doesStreetIDExist === true) { var cityName = I18n.lookup('edit.address.no_city'); var doesCityIDExist = true; var cityID = W.model.streets.objects[streetID].cityID; if(W.model.cities.objects[cityID] === undefined) { cityName = 'non-existent cityID'; doesCityIDExist = false; } else { if(W.model.cities.objects[cityID].attributes.name !== "") { cityName = W.model.cities.objects[cityID].attributes.name; } } result += cityName + ', '; if(doesCityIDExist === true) { var stateID = W.model.cities.objects[cityID].attributes.stateID; if(W.model.states.objects[stateID] === undefined) { result += 'non-existent stateID'; } else { result += W.model.states.objects[stateID].name; } } } } result += '<br>'; return result; } function uroNewLookHighlightedItemsCheck(e) { var result = ''; var rw; var rh; var objHasIgnoreLink = false; var objHasDeleteLink = false; var objHasAddWatchLink = false; var objHasRemoveWatchLink = false; var objHasUpdateWatchLink = false; var objHasRecentreSessionLink = false; var objHasOpenInNewTabLink = false; var objHasCloneLink = false; var isVenue = false; var isMapComment = false; var newPopupType = null; var markerObj; var markerPos; var markerImg; var ureq = null; var idx; var hovered = false; var targetTab = ''; var unstackedX; var unstackedY; var ureqID = null; var isUR = false; var isProblem = false; var isTurnProb = false; var isPlaceUpdate = false; var idSrc = null; var mouseX; var mouseY; var uroDaysResolved; var renderIntent; // function preamble... { if(uroMTEMode) return; if(!uroInitialised) return; if(e == 'dwellTimeout') { } else { if((uroMouseIsDown) && (e.buttons === 0)) { uroAddLog('trapped erroneous mousedown state'); uroMouseIsDown = false; } } if(uroMouseIsDown) { return; } if(OpenLayers === null) { if(uroNullOpenLayers === false) { uroAddLog('caught null OpenLayers'); uroNullOpenLayers = true; } return; } uroNullOpenLayers = false; if(W.map.updateRequestLayer === null) { if(uroNullURLayer === false) { uroAddLog('caught null UR layer'); uroNullURLayer = true; } return; } uroNullURLayer = false; if(W.map.problemLayer === null) { if(uroNullProblemLayer === false) { uroAddLog('caught null problem layer'); uroNullProblemLayer = true; } return; } uroNullProblemLayer = false; if(uroGetCBChecked('_cbMasterEnable') === false) { return; } if(e == 'dwellTimeout') { mouseX = uroPrevMouseX; mouseY = uroPrevMouseY; } else { mouseX = e.pageX - document.getElementById('map').getBoundingClientRect().left; mouseY = e.pageY - document.getElementById('map').getBoundingClientRect().top; var maxJitter = uroGetElmValue('_inputMaxJitter'); if((Math.abs(uroPrevMouseX - mouseX) > maxJitter) || (Math.abs(uroPrevMouseY - mouseY) > maxJitter)) { uroPopupDwellTimer = uroGetElmValue('_inputPopupDwellTimeout'); } uroPrevMouseX = mouseX; uroPrevMouseY = mouseY; } } var popupXOffset = uroParsePxString(window.getComputedStyle(document.getElementById('sidebar')).getPropertyValue("width")); var popupYOffset = $(document.getElementById("WazeMap")).offset().top - 80; var uroPopupX = mouseX + popupXOffset + 10; var uroPopupY = mouseY + popupYOffset - 10; // popup for segment restrictions if((uroMousedOverMarkerType === null) && (uroGetCBChecked('_cbInhibitSegPopup') === false)) { for(var slIdx=0; slIdx < W.map.segmentLayer.features.length; slIdx++) { if(W.map.segmentLayer.features[slIdx].renderIntent == 'highlight') { if(W.map.getExtent().intersectsBounds(W.map.segmentLayer.features[slIdx].geometry.getBounds())) { var doPopUp = false; var segObj; var restObj; if(W.map.segmentLayer.features[slIdx].fid === null) segObj = W.map.segmentLayer.features[slIdx].model; else segObj = W.map.segmentLayer.features[slIdx]; // generic segment data if(uroGetCBChecked('_cbInhibitSegGenericPopup') === false) { doPopUp = true; var streetID = segObj.attributes.primaryStreetID; uroAddLog('building popup for segment '+streetID); result += uroGetAddress(streetID, null, true); result += '<b>ID: </b>'+segObj.attributes.id+'<br>'; var fwdSpeed = segObj.attributes.fwdMaxSpeed; var revSpeed = segObj.attributes.revMaxSpeed; var fwdUnverified = segObj.attributes.fwdMaxSpeedUnverified; var revUnverified = segObj.attributes.revMaxSpeedUnverified; var roadType = segObj.attributes.roadType; var verifyLimits = true; if((roadType === 17) || (roadType === 20)) { verifyLimits = false; } if(segObj.attributes.fwdDirection) { result += '<b>A-B speed: </b>'+uroGetLocalisedSpeedString(fwdSpeed, verifyLimits); if(fwdUnverified) result += ' (unverified)'; result += '<br>'; } if(segObj.attributes.revDirection) { result += '<b>B-A speed: </b>'+uroGetLocalisedSpeedString(revSpeed, verifyLimits); if(revUnverified) result += ' (unverified)'; result += '<br>'; } if((segObj.attributes.fwdDirection) && (segObj.attributes.revDirection) && (fwdSpeed != revSpeed) && (!fwdUnverified) && (!revUnverified)) { result += 'Two-way segment has different verified speed limits...<br>'; } } // segment restrictions result += '<table cellpadding=4 border=1">'; if(segObj.attributes.fwdRestrictions.length > 0) { doPopUp = true; result += '<tr><td colspan=11><b>A-B restrictions:</b></td></tr>'; for(idx = 0; idx < segObj.attributes.fwdRestrictions.length; idx++) { restObj = segObj.attributes.fwdRestrictions[idx]; result += uroFormatRestriction(restObj); } } if (segObj.attributes.revRestrictions.length > 0) { doPopUp = true; result += '<tr><td colspan=11><b>B-A restrictions:</b></td></tr>'; for(idx = 0; idx < segObj.attributes.revRestrictions.length; idx++) { restObj = segObj.attributes.revRestrictions[idx]; result += uroFormatRestriction(restObj); } } result += '</table>'; if(W.map.closuresMarkerLayer.getVisibility() === true) { result += '<table cellpadding=4 border=1" width="100%">'; if(segObj.attributes.hasClosures === true) { var hasFwd = false; var hasRev = false; var rcObj; var roadClosure; for(roadClosure in W.model.roadClosures.objects) { if(W.model.roadClosures.objects.hasOwnProperty(roadClosure)) { rcObj = W.model.roadClosures.objects[roadClosure]; if(rcObj.segID == segObj.attributes.id) { if(rcObj.forward === true) { if(hasFwd === false) { result += '<tr><td colspan=4><b>A-B closures:</b></td></tr>'; hasFwd = true; } result += uroAddClosureRowToTable(rcObj); } else { hasRev = true; } } } } if(hasRev === true) { result += '<tr><td colspan=4><b>B-A closures:</b></td></tr>'; for(roadClosure in W.model.roadClosures.objects) { if(W.model.roadClosures.objects.hasOwnProperty(roadClosure)) { rcObj = W.model.roadClosures.objects[roadClosure]; if(rcObj.segID == segObj.attributes.id) { if(rcObj.forward === false) { result += uroAddClosureRowToTable(rcObj); } } } } } if((hasFwd === true) || (hasRev === true)) { doPopUp = true; } } result += '</table>'; } if(doPopUp === true) { if(segObj.attributes.id === null) uroFID = segObj.id; else uroFID = segObj.attributes.id; newPopupType = 'segment_restriction'; } break; } else { uroAddLog('segment '+uroFID+' has renderIntent==highlight but is offscreen... blocking popup'); } } } } // popup for restricted turns if((uroMousedOverMarkerType === null) && (newPopupType === null) && (uroGetCBChecked('_cbInhibitTurnsPopup') === false)) { var turnMarkerCount = W.map.layers[uroTurnsLayerIdx].markers.length; if(turnMarkerCount > 0) { for(idx=0; idx<turnMarkerCount; idx++) { markerObj = W.map.layers[uroTurnsLayerIdx].markers[idx]; var arrowElm = markerObj.icon.imageDiv.childNodes[0]; markerImg = window.getComputedStyle(arrowElm).getPropertyValue("background-image"); markerPos = window.getComputedStyle(arrowElm).getPropertyValue("background-position"); hovered = false; if(markerImg.indexOf('turns96765f551688fd5082b619129499bbb3.png') != -1) { if(markerPos == '-72px 0px') { hovered = true; } } if(hovered === true) { uroAddLog('hover over restricted turn marker'); uroTBRObj = arrowElm.childNodes[0]; var trObj = ($(arrowElm).data('model')); var Vertex = new require("Waze/Model/Graph/Vertex"); var turnGraph = W.model.getTurnGraph().getTurn(Vertex.forwardOf(trObj.fromSeg.attributes.id),Vertex.reverseOf(trObj.toSeg.attributes.id)); var resObj = turnGraph._turnData._restrictions; uroAddLog('building popup for turn restriction'); result += '<label id="_editTBR">Click to edit</label><br>'; result += '<table cellpadding=4 border=1">'; for(var resIdx=0; resIdx < resObj.length; resIdx++) { result += uroFormatRestriction(resObj[resIdx]); } result += '</table>'; uroFID = markerObj.icon.imageDiv._eventCacheID; newPopupType = 'turn_restriction'; break; } } } } // popup for landmarks if((uroMousedOverMarkerType === null) && (newPopupType === null) && (uroGetCBChecked('_cbInhibitLandmarkPopup') === false)) { uroPlaceSelected = false; var venueObj = null; renderIntent = null; var navpointPos=new OpenLayers.LonLat(); for(var llFeatureIdx=0; llFeatureIdx < W.map.landmarkLayer.features.length; llFeatureIdx++) { renderIntent = W.map.landmarkLayer.features[llFeatureIdx].renderIntent; if(renderIntent == 'highlight') { if(W.map.getExtent().intersectsBounds(W.map.landmarkLayer.features[llFeatureIdx].geometry.getBounds())) { if(W.map.landmarkLayer.features[llFeatureIdx].fid === null) venueObj = W.map.landmarkLayer.features[llFeatureIdx].model; else venueObj = W.map.landmarkLayer.features[llFeatureIdx]; if(newPopupType === null) { if(venueObj.attributes.id === null) uroFID = venueObj.id; else uroFID = venueObj.attributes.id; uroAddLog('building popup for place '+uroFID); navpointPos = uroGetVenueNavPoint(uroFID); navpointPos.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326")); result += '<b>'; if(venueObj.attributes.name === '') { if(venueObj.attributes.residential === true) result += '<i>Residential</i>'; else result += '<i>Unnamed</i>'; } else result += venueObj.attributes.name; if(venueObj.attributes.externalProviderIDs.length > 0) { result += ' <i>(linked)</i>'; } if(venueObj.attributes.adLocked) { result += ' <i>(AdLocked)</i>'; } result += '</b><br>'; result += uroGetAddress(venueObj.attributes.streetID, venueObj.attributes.houseNumber, false); result += '<ul>'; for(idx = 0; idx < venueObj.attributes.categories.length; idx++) { result += '<li>' + I18n.lookup("venues.categories." + venueObj.attributes.categories[idx]); } result += '</ul>'; if(venueObj.attributes.residential === true) { if(venueObj.geometry.CLASS_NAME == 'OpenLayers.Geometry.Point') { result += '<a href="#" id="_cloneRP">Clone place</a>'; objHasCloneLink = true; } } var npLink = document.location.href; ////var npLayers = '&layers='+... var npLayers = ''; npLink = npLink.substr(0,npLink.indexOf('?zoom')); npLink += '?zoom=5&lat='+navpointPos.lat+'&lon='+navpointPos.lon+npLayers; targetTab = "_uroTab_" + Math.round(Math.random()*1000000); result += '<hr>Jump to nav point: <a href="'+npLink+'" id="_openInNewTab" target="'+targetTab+'">in new tab</a> - '; objHasOpenInNewTabLink = true; result += '<a href="#" id="_recentreSession">in this tab</a>'; objHasRecentreSessionLink = true; newPopupType = 'venue'; isVenue = true; break; } else { var otherID; if(venueObj.attributes.id === null) otherID = venueObj.id; else otherID = venueObj.attributes.id; uroAddLog('venue '+otherID+' is also highlighted'); } } else { uroAddLog('landmark '+uroFID+' has renderIntent==highlight but is offscreen... blocking popup'); } } else if((renderIntent == 'select') || (renderIntent == 'highlightselected')) { uroPlaceSelected = true; } } } // popup for map comments if((uroMousedOverMarkerType === null) && (newPopupType === null) && (uroGetCBChecked('_cbInhibitMapCommentPopup') === false)) { uroMCSelected = false; var mcObj = null; renderIntent = null; for(var mcFeatureIdx=0; mcFeatureIdx < W.map.layers[uroMCLayerIdx].features.length; mcFeatureIdx++) { renderIntent = W.map.layers[uroMCLayerIdx].features[mcFeatureIdx].renderIntent; if(renderIntent == 'highlight') { if(W.map.getExtent().intersectsBounds(W.map.layers[uroMCLayerIdx].features[mcFeatureIdx].geometry.getBounds())) { mcObj = W.map.layers[uroMCLayerIdx].features[mcFeatureIdx].model; if(newPopupType === null) { uroFID = mcObj.attributes.id; uroAddLog('building popup for map comment '+uroFID); result += '<b>'; if(mcObj.attributes.subject === '') { result += '<i>No subject</i>'; } else result += mcObj.attributes.subject; result += '</b><br>'; if(mcObj.attributes.body !== '') { var mcDesc = mcObj.attributes.body.replace(/<\/?[^>]+(>|$)/g, ""); if(mcDesc != "null") { mcDesc = uroClickify(mcDesc); result += mcDesc + '<br>'; } } var mcDaysOld = uroGetMCAge(mcObj,0,false); var mcSubmittedTS = uroGetMCAge(mcObj,0,true); if(mcSubmittedTS != -1) { mcSubmittedTS = uroGetDateTimeString(mcSubmittedTS); } if(mcDaysOld != -1) { result += '<i>Submitted ' + uroParseDaysAgo(mcDaysOld) + ' '; if(mcSubmittedTS != -1) result += '(' + mcSubmittedTS + ') '; if(mcObj.attributes.createdBy != null) { result += ' by '+uroGetUserNameAndRank(mcObj.attributes.createdBy); } result += '</i><br>'; } mcDaysOld = uroGetMCAge(mcObj,1,false); mcSubmittedTS = uroGetMCAge(mcObj,1,true); if(mcSubmittedTS != -1) { mcSubmittedTS = uroGetDateTimeString(mcSubmittedTS); } if(mcDaysOld != -1) { result += '<i>Updated ' + uroParseDaysAgo(mcDaysOld) + ' '; if(mcSubmittedTS != -1) result += '(' + mcSubmittedTS + ') '; if(mcObj.attributes.createdBy != null) { result += ' by '+uroGetUserNameAndRank(mcObj.attributes.updatedBy); } result += '</i><br>'; } var mcHasMyComments = false; var mcNComments = mcObj.attributes.conversation.length; if(mcNComments > 0) { for(var i=0; i<mcNComments; i++) { if(mcObj.attributes.conversation[i].userID == uroUserID) { mcHasMyComments = true; break; } } } result += '<br>' + mcNComments +' comment'; if(mcNComments != 1) result += 's'; if((mcHasMyComments === false) && (mcNComments > 0)) result += ' (none by me)'; newPopupType = 'map_comment'; isMapComment = true; break; } else { var mcOtherID = mcObj.attributes.id; uroAddLog('map comment '+mcOtherID+' is also highlighted'); } } else { uroAddLog('map comment '+uroFID+' has renderIntent==highlight but is offscreen... blocking popup'); } } else if((renderIntent == 'select') || (renderIntent == 'highlightselected')) { uroMCSelected = true; } } } // look for URs, place updates and problems if(newPopupType === null) { if((uroMousedOverMarkerType == 'ur') && (newPopupType === null) && (uroGetCBChecked('_cbInhibitURPopup') === false)) { hovered = true; isUR = true; newPopupType = 'ur'; ureq = W.model.mapUpdateRequests.objects[uroMousedOverMarkerID]; unstackedX = uroParsePxString(W.map.updateRequestLayer.markers[uroMousedOverMarkerID].icon.imageDiv.style.left); unstackedY = uroParsePxString(W.map.updateRequestLayer.markers[uroMousedOverMarkerID].icon.imageDiv.style.top); // override popup base position uroPopupX = unstackedX + popupXOffset + 6; uroPopupY = unstackedY + popupYOffset + 66; uroPopupX -= uroParsePxString(W.map.segmentLayer.div.style.left); uroPopupY -= uroParsePxString(W.map.segmentLayer.div.style.top); // check for stacking... if(uroShownFID != uroMousedOverMarkerID) { uroCheckStacking(1,uroMousedOverMarkerID, unstackedX, unstackedY); } uroFID = uroMousedOverMarkerID; uroAddLog('building popup for UR '+uroMousedOverMarkerID); result = '<b>Update Request ('+uroMousedOverMarkerID+'): ' + I18n.lookup("update_requests.types." + ureq.attributes.type) + '</b><br>'; if(ureq.attributes.description !== null) { var desc = ureq.attributes.description.replace(/<\/?[^>]+(>|$)/g, ""); if(desc != "null") { desc = uroClickify(desc); result += desc + '<br>'; } } var uroDaysOld = uroGetURAge(ureq,0,false); var uroSubmittedTS = uroGetURAge(ureq,0,true); if(uroSubmittedTS != -1) { uroSubmittedTS = uroGetDateTimeString(uroSubmittedTS); } if(uroDaysOld != -1) { result += '<i>Submitted ' + uroParseDaysAgo(uroDaysOld) + ' '; if(uroSubmittedTS != -1) result += '(' + uroSubmittedTS + ') '; if(ureq.attributes.guestUserName != null) { result += 'via Livemap'; if(ureq.attributes.guestUserName !== '') { result += ' by '+ureq.attributes.guestUserName.replace(/<\/?[^>]+(>|$)/g, ""); } } result += '</i>'; } if(ureq.attributes.resolvedOn !== null) { uroDaysResolved = uroGetURAge(ureq,1,false); var uroResolvedTS = uroGetURAge(ureq,1,true); if(uroResolvedTS != -1) { uroResolvedTS = uroGetDateTimeString(uroResolvedTS); } if(uroDaysResolved != -1) { result += '<br><i>Closed ' + uroParseDaysAgo(uroDaysResolved) + ' '; if(uroResolvedTS != -1) result += '(' + uroResolvedTS + ')</i>'; result += '<br><i>Marked as '; if(ureq.attributes.resolution === 0) result += 'solved'; else if(ureq.attributes.resolution == 1) result += 'not identified'; else result += 'unknown'; if(ureq.attributes.resolvedBy !== null) { result += ' by '+uroGetUserNameAndRank(ureq.attributes.resolvedBy); } result += '</i>'; } } if(W.model.updateRequestSessions.objects[uroMousedOverMarkerID] != null) { var hasMyComments = uroURHasMyComments(uroMousedOverMarkerID); var nComments = W.model.updateRequestSessions.objects[uroMousedOverMarkerID].comments.length; result += '<br>' + nComments + ' comment'; if(nComments != 1) result += 's'; if((hasMyComments === false) && (nComments > 0)) result += ' (none by me)'; if(nComments > 0) { var commentDaysOld = uroGetCommentAge(W.model.updateRequestSessions.objects[uroMousedOverMarkerID].comments[nComments-1]); if(commentDaysOld != -1) { result += ', last update '+uroParseDaysAgo(commentDaysOld); } } } } if((uroMousedOverMarkerType == 'pur') && (newPopupType === null) && (uroGetCBChecked('_cbInhibitPUPopup') === false)) { hovered = true; isPlaceUpdate = true; newPopupType = 'pur'; ureq = W.map.placeUpdatesLayer.markers[uroMousedOverMarkerID].model; unstackedX = uroParsePxString(W.map.placeUpdatesLayer.markers[uroMousedOverMarkerID].icon.imageDiv.style.left); unstackedY = uroParsePxString(W.map.placeUpdatesLayer.markers[uroMousedOverMarkerID].icon.imageDiv.style.top); // override popup base position uroPopupX = unstackedX + popupXOffset + 6; uroPopupY = unstackedY + popupYOffset + 66; uroPopupX -= uroParsePxString(W.map.segmentLayer.div.style.left); uroPopupY -= uroParsePxString(W.map.segmentLayer.div.style.top); if(uroShownFID != uroMousedOverMarkerID) { // check for stacking... uroCheckStacking(3,uroMousedOverMarkerID, unstackedX, unstackedY); } uroFID = uroMousedOverMarkerID; // to inhibit auto-centering only when the PUR marker is clicked, we wait for the marker to get highlighted, then // make a copy of the original getBounds() function before replacing it with a call to W.map.getExtent(). Clicking // the marker causes a call to getBounds() which will then return the current map extent, and thus no change in the // map view will occur... uroRestoreCentering(); W.map.placeUpdatesLayer.markers[uroMousedOverMarkerID].model.geometry.origGetBounds = W.map.placeUpdatesLayer.markers[uroMousedOverMarkerID].model.geometry.getBounds; W.map.placeUpdatesLayer.markers[uroMousedOverMarkerID].model.geometry.getBounds = uroKillCentering; uroAutoCentreDisabledOn.push('PUR', uroMousedOverMarkerID); uroAddLog('building popup for placeUpdate '+uroMousedOverMarkerID); result = '<b>'; if(ureq.attributes.name === '') result += 'Unnamed landmark'; else result += ureq.attributes.name; result += '</b><br>'; result += '<ul>'; for(idx = 0; idx < ureq.attributes.categories.length; idx++) { result += '<li>' + I18n.lookup("venues.categories." + ureq.attributes.categories[idx]); } result += '</ul>'; if(ureq.attributes.residential === true) { result += '<i>Residential</i>'; } var daysOld = uroGetPURAge(ureq); if(daysOld != -1) { result += '<br><i>Submitted '+uroParseDaysAgo(daysOld)+'</i>'; } } if((uroMousedOverMarkerType == 'mp') && (newPopupType === null) && (uroGetCBChecked('_cbInhibitMPPopup') === false)) { hovered = true; isProblem = true; newPopupType = 'map_problem'; ureq = W.model.problems.objects[uroMousedOverMarkerID]; if(ureq === undefined) { if(uroDOMHasTurnProblems) { ureq = W.model.turnProblems.objects[uroMousedOverMarkerID]; if(ureq != null) isTurnProb = true; } } unstackedX = uroParsePxString(W.map.problemLayer.markers[uroMousedOverMarkerID].icon.imageDiv.style.left); unstackedY = uroParsePxString(W.map.problemLayer.markers[uroMousedOverMarkerID].icon.imageDiv.style.top); // override popup base position uroPopupX = unstackedX + popupXOffset + 6; uroPopupY = unstackedY + popupYOffset + 66; uroPopupX -= uroParsePxString(W.map.segmentLayer.div.style.left); uroPopupY -= uroParsePxString(W.map.segmentLayer.div.style.top); // check for stacking... if(uroShownFID != uroMousedOverMarkerID) { uroCheckStacking(2,uroMousedOverMarkerID, unstackedX, unstackedY); } uroFID = uroMousedOverMarkerID; // same method of disabling the on-click auto-centre behaviour as for PURs above... uroRestoreCentering(); W.map.problemLayer.markers[uroMousedOverMarkerID].model.origGetDisconnectBounds = W.map.problemLayer.markers[uroMousedOverMarkerID].model.getDisconnectBounds; W.map.problemLayer.markers[uroMousedOverMarkerID].model.getDisconnectBounds = uroKillCentering; uroAutoCentreDisabledOn.push('MP', uroMousedOverMarkerID); uroAddLog('building popup for problem '+uroMousedOverMarkerID); if(isTurnProb) result = '<b>Turn Problem ('+uroMousedOverMarkerID+'): ' + I18n.lookup("problems.types.turn.title"); else { result = '<b>Map Problem ('+uroMousedOverMarkerID+'): '; var problemType = null; if(uroDOMHasTurnProblems) { problemType = ureq.attributes.problemType; } else { problemType = ureq.attributes.subType; } if(problemType == 300) { result += I18n.lookup("problems.panel.closure.title"); } else { if(I18n.lookup("problems.types." + problemType) === undefined) result += 'Unknown problem type ('+problemType+')'; else result += I18n.lookup("problems.types." + problemType + ".title"); } } result += '</b><br>'; if(ureq.attributes.description != null) { result += 'Description: ' + ureq.attributes.description + '<br>'; } if(ureq.attributes.extraInfo != null) { result += 'ExtraInfo: ' + ureq.attributes.extraInfo + '<br>'; } if(ureq.attributes.provider != null) { result += 'Provider: ' + ureq.attributes.provider + '<br>'; } if(ureq.attributes.resolvedOn != null) { uroDaysResolved = uroGetURAge(ureq,1,false); if(uroDaysResolved != -1) { result += '<br><i>Closed ' + uroParseDaysAgo(uroDaysResolved) + ' '; if(ureq.attributes.resolvedBy != null) { result += ' by '+uroGetUserNameAndRank(ureq.attributes.resolvedBy); } if((ureq.attributes.open === true) && (ureq.attributes.resolvedOn != null)) { result += '<br>Reopened by Waze'; } result += '</i>'; } } } if(hovered === false) { uroFID = -1; if(uroStackType !== null) { var tStackType = uroStackType; uroRestackMarkers(); if(tStackType == 1) uroFilterURs(); else if(tStackType == 2) uroFilterProblems(); else if(tStackType == 3) uroFilterPlaces(); } } else { // add "open new WME tab" link var urPos=new OpenLayers.LonLat(); if(isPlaceUpdate) { urPos=ureq.geometry.bounds.centerLonLat.clone(); } else { if(ureq.geometry.realX === undefined) { urPos.lon = ureq.geometry.x; urPos.lat = ureq.geometry.y; } else { urPos.lon = ureq.geometry.realX; urPos.lat = ureq.geometry.realY; } } urPos.transform(new OpenLayers.Projection("EPSG:900913"),new OpenLayers.Projection("EPSG:4326")); var urLink = document.location.href; ////var urLayers = '&layers='+... var urLayers = ''; urLink = urLink.substr(0,urLink.indexOf('?zoom')); urLink += '?zoom=5&lat='+urPos.lat+'&lon='+urPos.lon+urLayers; if(isUR) urLink += '&mapUpdateRequest='+idSrc; else if(isTurnProb) urLink += '&showturn='+idSrc+'&endshow'; else if(isProblem) urLink += '&mapProblem='+idSrc; else if(isPlaceUpdate) urLink += '&showpur='+idSrc+'&endshow'; targetTab = "_uroTab_" + Math.round(Math.random()*1000000); result += '<hr><ul><li><a href="'+urLink+'" id="_openInNewTab" target="'+targetTab+'">Open in new tab</a> - '; objHasOpenInNewTabLink = true; result += '<a href="#" id="_recentreSession">centre in current tab</a>'; objHasRecentreSessionLink = true; // add "open new livemap tab" link var lmLink = null; if(document.getElementById("livemap-link") != null) { uroAddLog('Livemap link in livemap-link id element'); lmLink = document.getElementById("livemap-link").href; } else if(document.getElementsByClassName("livemap-link") != null) { uroAddLog('Livemap link in livemap-link class element'); lmLink = document.getElementsByClassName("livemap-link")[0].href; } else { uroAddLog('Livemap link not found...'); } if(lmLink !== null) { var zpos = lmLink.indexOf('?'); if(zpos > -1) lmLink = lmLink.substr(0,zpos); lmLink += '?zoom=17&lat='+urPos.lat+'&lon='+urPos.lon+'&layers=BTTTT'; result += '<li><a href="'+lmLink+'" target="_lmTab">Open in new livemap tab</a>'; } if(!isPlaceUpdate) { // add "ignore for this session" link result += '<li><a href="#" id="_addtoignore">Hide for this session</a></ul>'; objHasIgnoreLink = true; } } } if((newPopupType != 'map_problem') && (newPopupType != 'pur')) { uroRestoreCentering(); } // look for cameras if((newPopupType === null) && (uroGetCBChecked('_cbInhibitCamPopup') === false)) { for(var clFeature in W.map.camerasLayer._featureMap) { if(W.map.camerasLayer._featureMap[clFeature].renderIntent == 'highlight') { ureq = W.map.camerasLayer._featureMap[clFeature].model; ureqID = ureq.attributes.id; // test isSelected() so that we only do overview data on cameras that are being hovered over if(ureq.isSelected() === false) { uroPopupY -= 20; newPopupType = 'camera'; uroFID = ureqID; uroAddLog('building popup for camera '+uroFID); if(I18n.lookup("edit.camera.fields.type") === undefined) { result += '<b>Camera: ' + ureq.TYPES[ureq.attributes.type] + '</b><br>'; } else { result += '<b>Camera: ' + I18n.lookup("edit.camera.fields.type." + ureq.attributes.type) + '</b><br>'; } result += 'ID: '+uroFID+'<br>'; result += 'Created by '; var userID; if(W.model.users.get(ureq.attributes.createdBy) != null) { userID = ureq.attributes.createdBy; result += uroGetUserNameAndRank(userID); } else result += 'unknown'; result += ', '; var camAge = uroGetCameraAge(ureq,1); if(camAge != -1) { result += uroParseDaysAgo(camAge); } else result += 'unknown days ago'; result += '<br>Updated by '; if(W.model.users.get(ureq.attributes.updatedBy) != null) { userID = ureq.attributes.updatedBy; var userName = W.model.users.objects[userID].userName; var userLevel = W.model.users.objects[userID].rank + 1; result += userName + ' (' + userLevel + ')'; } else result += 'unknown'; result += ', '; camAge = uroGetCameraAge(ureq,0); if(camAge != -1) { result += uroParseDaysAgo(camAge); } else result += 'unknown days ago'; result += '<br>Speed data: '; result += uroGetLocalisedSpeedString(ureq.attributes.speed, true); result += '<hr><ul>'; if(uroIsCamOnWatchList(uroFID) != -1) { result += '<li><a href="#" id="_updatewatchlist">Update watchlist entry</a>'; result += '<li><a href="#" id="_removefromwatchlist">Remove from watchlist</a>'; objHasUpdateWatchLink = true; objHasRemoveWatchLink = true; } else { result += '<li><a href="#" id="_addtowatchlist">Add to watchlist</a>'; objHasAddWatchLink = true; } if(ureq.attributes.permissions !== 0) { result += '<li><a href="#" id="_deleteobject">Delete Camera</a>'; objHasDeleteLink = true; } result += '</ul>'; } break; } } } if((newPopupType !== null) && (uroPopupDwellTimer === 0) && (uroPopupSuppressed === false)) { if((uroFID != uroShownFID) || (newPopupType != uroShownPopupType)) { if(uroFID != uroShownFID) uroAddLog('FID mismatch, show popup: '+uroFID+'/'+uroShownFID); else uroAddLog('Popup type mismatch: '+newPopupType+'/'+uroShownPopupType); uroShownFID = uroFID; uroShownPopupType = newPopupType; uroPopupShown = false; } if(uroPopupShown === false) { uroAddLog('display popup at '+uroPopupX+','+uroPopupY); uroPopupShown = true; uroDiv.style.height = "auto"; uroDiv.style.width = "auto"; uroDiv.innerHTML = result; if((uroFID != -1) && (objHasIgnoreLink === true)) { uroAddEventListener('_addtoignore','click', uroAddToIgnoreList, true); } if(objHasDeleteLink === true) { uroAddEventListener('_deleteobject','click', uroDeleteObject, true); } if(objHasRemoveWatchLink === true) { uroAddEventListener('_removefromwatchlist','click', uroRemoveCamFromWatchList, true); } if(objHasAddWatchLink === true) { uroAddEventListener('_addtowatchlist','click', uroAddCamToWatchList, true); } if(objHasUpdateWatchLink === true) { uroAddEventListener('_updatewatchlist','click', uroUpdateCamWatchList, true); } if(objHasOpenInNewTabLink === true) { uroAddEventListener('_openInNewTab','mouseup', uroOpenNewTab, true); } if(objHasRecentreSessionLink === true) { if(isUR) uroAddEventListener('_recentreSession', 'click', uroRecentreSessionOnUR, true); else if((isProblem)||(isTurnProb)) uroAddEventListener('_recentreSession', 'click', uroRecentreSessionOnMP, true); else if(isPlaceUpdate) uroAddEventListener('_recentreSession', 'click', uroRecentreSessionOnPUR, true); else if(isVenue) uroAddEventListener('_recentreSession', 'click', uroRecentreSessionOnVenueNavPoint, true); } if(objHasCloneLink === true) { uroAddEventListener('_cloneRP', 'click', uroCloneResidentialPlace, true); } if(newPopupType == 'turn_restriction') { uroAddEventListener('_editTBR','click', uroEditTBR, true); } // restrict the popup width to be no wider than just under half the window width to avoid it // completely overlapping the marker it's associated with - by keeping it to just below half // the window width we guarantee that it'll fit either to the left or the right of the marker // no matter how far across the screen the marker is located... rw = parseInt(uroDiv.clientWidth); if(rw > (window.innerWidth * 0.45)) { rw = (window.innerWidth * 0.45); uroDiv.style.width = rw+'px'; } // get the div height after any adjustment of the width above, to account for whatever content // reflow may have occurred as a result of reducing the width... rh = parseInt(uroDiv.clientHeight); if((uroPopupX + rw) > window.innerWidth) { // where the popup would be off the right hand side of the screen, move it completely over to the // other side of the mouse pointer uroPopupX -= (rw + 20); if(uroPopupX < 0) uroPopupX = 0; } if((uroPopupY + rh) > window.innerHeight) { // where the popup would be off the bottom of the screen, shift it up just far enough to be // fully visible uroPopupY -= (((uroPopupY + rh) - window.innerHeight) + 30); if(uroPopupY < 0) uroPopupY = 0; } uroDiv.style.top = uroPopupY+'px'; uroDiv.style.left = uroPopupX+'px'; uroDiv.style.visibility = 'visible'; } uroPopupTimer = -1; } else if((newPopupType === null) && (uroPopupDwellTimer !== 0) && (uroPopupShown === true)) { uroHidePopup(); } else { if((uroPopupTimer == -1) && (uroFID != uroShownFID)) { uroPopupTimer = uroGetElmValue('_inputPopupEntryTimeout'); } } } function uroExclusiveCB() { var cbChecked = uroGetCBChecked(this.id); if(cbChecked === true) { var pairedList = this.attributes.pairedWith.value.split(','); for(var i=0; i<pairedList.length; i++) { uroSetCBChecked(pairedList[i], false); } } } function uroGetAMs(e) { if(uroMTEMode) return; if(!uroFilterPreamble) return; if(!uroInitialised) return; var amList = ''; if(W.map.managedAreasLayer.getVisibility() === true) { var mouseX = e.pageX - document.getElementById('map').getBoundingClientRect().left; var mouseY = e.pageY - document.getElementById('map').getBoundingClientRect().top - document.getElementById('toolbar').clientHeight; var mousePixel = new OL.Pixel(mouseX, mouseY); var mousePoint = W.map.getLonLatFromPixel(mousePixel).toPoint(); for(var amObj in W.model.managedAreas.objects) { if(W.model.managedAreas.objects[amObj].geometry.containsPoint(mousePoint)) { if(amList !== '') amList += ', '; amList += uroGetUserNameAndRank(W.model.managedAreas.objects[amObj].userID); } } if(amList === '') { amList = 'none'; } amList = "<b>Area Managers:</b> "+amList; } document.getElementById("uroAMList").innerHTML = amList; } function uroMouseDown() { uroMouseIsDown = true; } function uroMouseUp() { uroMouseIsDown = false; } function uroMouseOut() { //console.debug('Elvis has left the building...'); } function uroUREvent_onObjectsChanged() { } function uroUREvent_onObjectsAdded() { if(uroGetCBChecked('_cbURResolverIDFilter') === true) { uroUpdateResolverList(); } uroFilterURs(); } function uroUREvent_onObjectsRemoved() { } function uroGetSelectedURCommentCount() { if(W.model.updateRequestSessions.objects[uroSelectedURID] != null) { var cachedCommentCount = W.model.updateRequestSessions.objects[uroSelectedURID].comments.length; uroAddLog(uroSelectedURID+':'+cachedCommentCount+' '+uroExpectedCommentCount); // if there aren't the same number of cached comments as there are comments in the UR dialog list, initiate // a refresh of the comment data... if(cachedCommentCount != uroExpectedCommentCount) { if(uroPendingCommentDataRefresh === true) { if(cachedCommentCount > 0) { uroCachedLastCommentID = W.model.updateRequestSessions.objects[uroSelectedURID].comments[cachedCommentCount-1].id; } else { uroCachedLastCommentID = null; } uroAddLog('updateRequestSessions refresh required for UR '+uroSelectedURID); if(uroCachedLastCommentID !== null) { uroAddLog('last comment ID for this UR is '+uroCachedLastCommentID); } else { uroAddLog('first comment for this UR, no previous comment to ID'); } var idList = []; idList.push(uroSelectedURID); // need to delete the existing cache object first, as .get() is only capable of creating new objects, // it doesn't seem able to update an existing object with new data W.model.updateRequestSessions.remove(W.model.updateRequestSessions.objects[uroSelectedURID]); W.model.updateRequestSessions.get(idList); // the call to .get() initiates a XMLHttpRequest for the data, so we now need to switch modes - the // refresh process has started so we're no longer pending, but we are now waiting for the XMLHttpRequest // to return something... uroPendingCommentDataRefresh = false; uroWaitingCommentDataRefresh = true; } else { if(cachedCommentCount > 0) { var currentLastCommentID = W.model.updateRequestSessions.objects[uroSelectedURID].comments[cachedCommentCount-1].id; if(currentLastCommentID == uroCachedLastCommentID) { // most recent comment loaded for this UR is the same one that was present at the start of this // refresh process, so kick back into pending mode so we can retry the .get()... uroAddLog('latest comment ID still the same, reverting to pending mode...'); uroPendingCommentDataRefresh = true; } else { // something may have gone awry here - the most recent comment loaded for this UR doesn't have the // same ID as the one present at the start of the refresh process, yet the comment counts still don't // match up, which suggests either a comment got lost along the way or someone else has commented on // the same UR at almost the same time. To get out of the loop this would create, assume that a // mismatch in the IDs means the .get() has completed successfully no matter what the new comment // count is, and take this new count to be the count we were expecting all along... uroAddLog('latest comment ID different, but expected count not correct...'); uroExpectedCommentCount = cachedCommentCount; } } else { uroAddLog('first comment on this UR not received yet, reverting to pending mode...'); uroPendingCommentDataRefresh = true; } } } else { // if the WME session is loaded with a UR already selected, such that WME has opened the UR dialog as part // of the session startup process, adding new comments to the UR cause the cached data to be updated immediately. // This prevents URO+ from switching into waiting mode in the above block of code, so we have to instead do // it here by comparing the cached count against the expected count following the Send click event. if(cachedCommentCount >= uroExpectedCommentCount) { uroPendingCommentDataRefresh = false; uroWaitingCommentDataRefresh = true; uroExpectedCommentCount = null; } // once the cached data has been updated, refilter the URs so that the new comment count is taken into account // immediately for filtering and display purposes if(uroWaitingCommentDataRefresh === true) { uroWaitingCommentDataRefresh = false; uroFilterURs(); uroAddLog('refresh complete'); } } } } function uroAddedComment() { // when the user clicks the Send button to submit a new UR comment, this event handler fires before the new comment is // posted to the server and thus also before the comment list gets updated in the UR dialog. So we take the current // comment count and, if the new comment edit box isn't empty, increment it by 1 to get the expected count. Then we // set the pending flag true to initiate a session refresh on the next 100ms tick uroExpectedCommentCount = W.map.panelRegion.currentView.conversationView.viewModel.attributes.commentCount; if(document.getElementsByClassName('new-comment-text')[0].value !== '') { uroExpectedCommentCount++; uroAddLog('new comment added to UR '+uroSelectedURID+', cache refresh required...'); uroPendingCommentDataRefresh = true; } else { uroPendingCommentDataRefresh = false; } } function uroInhibitNextUpdateRequestButton(e) { var doClick = true; e.stopPropagation(); if(document.getElementsByClassName('form-control new-comment-text').length > 0) { if(document.getElementsByClassName('form-control new-comment-text')[0].textLength > 0) { doClick = (confirm('Comment not sent, close report panel anyway?')); } } if(doClick) { document.getElementsByClassName('close-panel')[0].click(); } } function uroAddLZ(valueToPad, newLength) { var padString = ''; for(var i=0; i<newLength; i++) { padString += '0'; } padString += valueToPad.toString(); return padString.slice(-newLength); } function uroIncrementClosureDate(oldDate, incByDays) { var dateBits = oldDate.split('-'); var year = parseInt(dateBits[0]); var month = parseInt(dateBits[1])-1; var date = parseInt(dateBits[2])+1; var incrementedDate = new Date(year, month, date); return (uroAddLZ(incrementedDate.getFullYear(),4) + '-' + uroAddLZ(incrementedDate.getMonth()+1,2) + '-' + uroAddLZ(incrementedDate.getDate(),2)); } function uroGetElementProperty(elmName, elmOffset, elmProperty) { var retval = null; if(document.getElementsByName(elmName).length !== 0) { retval = document.getElementsByName(elmName)[elmOffset][elmProperty]; } return retval; } // Residential Place Cloning //{ var uroCRPStreetID; var uroCRPHouseNumber; function uroCompleteRPClone() { // as with closure cloning, the place details edit form requires us to push the new value into the relevant // edit field and then generate a change event on that field, otherwise WME doesn't bother reading the value... // street name var streetObj = W.model.streets.get(uroCRPStreetID); if(streetObj !== undefined) { document.getElementsByClassName('street-name')[0].value = streetObj.name; document.getElementsByClassName('street-name')[0].dispatchEvent(new Event('change', { 'bubbles': true })); // city name var cityObj = W.model.cities.get(streetObj.cityID); if(cityObj !== undefined) { if(cityObj.attributes.isEmpty === true) { // The donor point place we create to take the cloned RPP properties may have been automatically given // a city name by WME, and thus the city name field will already be filled in and activated... If our // RPP doesn't however have a city name, we need to deactivate the city name field again, so that WME // doesn't complain about the user trying to save the new RPP with an empty city name if(document.getElementsByClassName("empty-city")[0].checked === false) { document.getElementsByClassName("empty-city")[0].click(); } } document.getElementsByClassName('city-name')[0].value = cityObj.attributes.name; document.getElementsByClassName('city-name')[0].dispatchEvent(new Event('change', { 'bubbles': true })); // county document.getElementsByClassName('state-id')[0].value = cityObj.attributes.stateID; document.getElementsByClassName('state-id')[0].dispatchEvent(new Event('change', { 'bubbles': true })); // country document.getElementsByClassName('country-id')[0].value = cityObj.attributes.countryID; document.getElementsByClassName('country-id')[0].dispatchEvent(new Event('change', { 'bubbles': true })); } } // house number document.getElementsByClassName('house-number')[0].value = uroCRPHouseNumber; document.getElementsByClassName('house-number')[0].dispatchEvent(new Event('change', { 'bubbles': true })); // now wait for the user to confirm everything and click Apply... } function uroConvertToRP() { // panel isn't open yet, which means the user either hasn't clicked yet or WME is still processing the // placement of the venue, so wait a while and then check again... if(document.getElementById('edit-panel').getElementsByClassName('landmark').length === 0) { setTimeout(uroConvertToRP, 100); return; } // panel is open, so move to the next step of the cloning procedure by converting the newly created // place to residential by generating a click event on the "convert to residential" link... document.getElementsByClassName("toggle-residential")[0].click(); // and then click on the address edit icon... document.getElementsByClassName('waze-icon-edit')[0].click(); // now click on the "none" checkbox for the street name edit field so we can enter the street name document.getElementById('empty-street').click(); // WME automatically clears the checkbox associated with the city name edit field if we set the street // name to be one that has a city associated with it, which is nice :-) // the click event seems to take a while to execute, and if we call dispatchEvent on the edit field whilst // it's still tagged as disabled then it gets ignored, causing the value in that field to be dropped when // we apply the changes to the place. Trying to programatically detect when the field has been activated // doesn't seem to be reliable, however a fixed delay of 1s seems to work nicely setTimeout(uroCompleteRPClone, 1000); } function uroCloneResidentialPlace() { // trying to clone a RPP when one is already selected causes the selected one to be changed back to // a non-residential, as uroConvertToRP() thinks the user has already clicked to place the new RPP... if(document.getElementById('edit-panel').getElementsByClassName('landmark').length === 0) { var venueObj = W.model.venues.objects[uroFID]; if(venueObj !== undefined) { // copy address from highlighted residential place uroCRPHouseNumber = venueObj.attributes.houseNumber; uroCRPStreetID = venueObj.attributes.streetID; // generate a click event on the first new point venue entry in the venues menu in order to generate a // new point venue object that we can manipulate... document.getElementsByClassName('toolbar-group-venues')[0].getElementsByClassName("drawing-control main-control point")[0].click(); // now wait for the user to click on the map to place the new point venue uroConvertToRP(); } } } //} // Closure Cloning //{ var uroConfirmClosureDelete = true; var uroClosuresToDelete = 0; var uroCLocation; var uroCReason; var uroCEvent; var uroCDirection; var uroCHasStartDate; var uroCStartDate; var uroCStartTime; var uroCEndDate; var uroCEndTime; var uroCIgnoreTraffic; function uroCompleteClosureCloning() { if(document.getElementsByClassName('edit-closure').length === 0) { window.setTimeout(uroCompleteClosureCloning,100); return; } // need to generate a change event on each of the form fields, because WME appears to be silently populating some hidden // closure object with the details as they're entered manually, and if we just set the form values without then forcing // the change event as well then WME will end up using its default values instead of the ones we've so lovingly copied... if(uroCLocation !== null) { document.getElementsByName('closure_location')[0].value = uroCLocation; document.getElementsByName('closure_location')[0].dispatchEvent(new Event('change', {'bubbles':true})); } if(uroCReason !== null) { document.getElementsByName('closure_reason')[0].value = uroCReason; document.getElementsByName('closure_reason')[0].dispatchEvent(new Event('change', {'bubbles':true})); } if(uroCDirection !== null) { document.getElementsByName('closure_direction')[0].selectedIndex = uroCDirection; document.getElementsByName('closure_direction')[0].dispatchEvent(new Event('change', {'bubbles':true})); } if(uroCHasStartDate !== null) { document.getElementsByName('closure_hasStartDate')[0].checked = uroCHasStartDate; document.getElementsByName('closure_hasStartDate')[0].dispatchEvent(new Event('change', {'bubbles':true})); } if(uroCStartDate !== null) { document.getElementsByName('closure_startDate')[0].value = uroCStartDate; document.getElementsByName('closure_startDate')[0].dispatchEvent(new Event('change', {'bubbles':true})); } if(uroCStartTime !== null) { document.getElementsByName('closure_startTime')[0].value = uroCStartTime; document.getElementsByName('closure_startTime')[0].dispatchEvent(new Event('change', {'bubbles':true})); } if(uroCIgnoreTraffic !== null) { document.getElementsByName('closure_permanent')[0].checked = uroCIgnoreTraffic; document.getElementsByName('closure_permanent')[0].dispatchEvent(new Event('change', {'bubbles':true})); } if(uroCEndTime !== null) { document.getElementsByName('closure_endTime')[0].value = uroCEndTime; // the cloning process doesn't alter the end time, which seems to confuse WME when it then receives the // change event - the MTE dropdown ends up being reset to just the "Choose event" and "None" entries // regardless of how many MTE entries there ought to be. The fix for this appears to simply be to then // submit a second change event... document.getElementsByName('closure_endTime')[0].dispatchEvent(new Event('change', {'bubbles':true})); document.getElementsByName('closure_endTime')[0].dispatchEvent(new Event('change', {'bubbles':true})); } // the current version of WME wipes any existing end date as soon as the end time is altered, so we now need // to set the date after the time instead of before as in earlier versions of this function... if(uroCEndDate !== null) { document.getElementsByName('closure_endDate')[0].value = uroCEndDate; document.getElementsByName('closure_endDate')[0].dispatchEvent(new Event('change', {'bubbles':true})); } uroTempFixMTEDropDown(); if(uroCEvent !== null) { if(document.getElementsByName('closure_eventId')[0].options.length > 1) { for(var loop=0; loop<document.getElementsByName('closure_eventId')[0].options.length; loop++) { if(document.getElementsByName('closure_eventId')[0].options[loop].value == uroCEvent) { document.getElementsByName('closure_eventId')[0].selectedIndex = loop; break; } } } else { document.getElementsByName('closure_eventId')[0].selectedIndex = 0; } document.getElementsByName('closure_eventId')[0].dispatchEvent(new Event('change', {'bubbles':true})); } } function uroCloneClosure() { var closureOffset = parseInt(this.id.split('-')[1]); // grab the current closure details from the UI... document.getElementsByClassName('closure-item')[closureOffset].children[0].children[0].children[1].click(); uroCLocation = uroGetElementProperty('closure_location', 0, 'value'); uroCReason = uroGetElementProperty('closure_reason', 0, 'value'); uroCEvent = uroGetElementProperty('closure_eventId', 0, 'value'); uroCDirection = uroGetElementProperty('closure_direction', 0, 'selectedIndex'); uroCHasStartDate = uroGetElementProperty('closure_hasStartDate', 0, 'checked'); uroCStartDate = uroGetElementProperty('closure_startDate', 0, 'value'); uroCStartTime = uroGetElementProperty('closure_startTime', 0, 'value'); uroCEndDate = uroGetElementProperty('closure_endDate', 0, 'value'); uroCEndTime = uroGetElementProperty('closure_endTime', 0, 'value'); uroCIgnoreTraffic = uroGetElementProperty('closure_permanent', 0, 'checked'); document.getElementsByClassName('closures')[0].getElementsByClassName('cancel-button')[0].click(); // auto-increment the start and end dates... uroCStartDate = uroIncrementClosureDate(uroCStartDate,1); uroCEndDate = uroIncrementClosureDate(uroCEndDate,1); // generate a click event on the Add a closure button to open up the closure editing UI, then // wait for the UI to finish opening... document.getElementsByClassName('add-closure-button')[0].click(); window.setTimeout(uroCompleteClosureCloning,100); } function uroDeleteNextClosureOnList() { var nClosures = document.getElementsByClassName('closure-item').length; if(nClosures > 0) { if (nClosures != uroClosuresToDelete) { uroClosuresToDelete = nClosures; document.getElementsByClassName('closure-item')[0].getElementsByClassName('delete')[0].click(); } setTimeout(uroDeleteNextClosureOnList,100); } else { uroConfirmClosureDelete = true; } } function uroDeleteAllClosures() { uroConfirmClosureDelete = true; if(window.confirm(I18n.lookup("closures.delete_confirm_no_reason")+' ('+I18n.lookup("closures.apply_to_all")+')')) { uroConfirmClosureDelete = false; var nClosures = document.getElementsByClassName('closure-item').length; if(nClosures > 0) { uroClosuresToDelete = -1; uroDeleteNextClosureOnList(); } else { uroConfirmClosureDelete = true; } } } //} // Feed Filtering //{ function uroToggleFFCtrls() { if(uroShowFeedFilter === false) { uroShowFeedFilter = true; document.getElementById('_uroFFCtrlVisibility').className = "fa fa-minus-square-o"; document.getElementById('uroFFCtrls').style.display = "block"; } else { uroShowFeedFilter = false; document.getElementById('_uroFFCtrlVisibility').className = "fa fa-plus-square-o"; document.getElementById('uroFFCtrls').style.display = "none"; } } function uroForceFeedRefresh() { uroFeedFilterReloads = 0; } function uroAddFeedFilterControls() { if(document.getElementById('sidepanel-feed') != null) { if(document.getElementById('sidepanel-feed').childNodes[0] != null) { var nDiv = document.createElement('div'); var iHTML = ''; nDiv.id = "uroFeedFilter"; iHTML += '<i class="fa fa-plus-square-o" style="cursor:pointer;font-size:14px;" id="_uroFFCtrlVisibility"> </i><b>Feed Filter Controls</b><br>'; iHTML += '<div id="uroFFCtrls">'; iHTML += '<b>Filter feed by listing type:</b><br>'; iHTML += '<input type="checkbox" id="_cbFeedFilter_TypeUR" />UR<br>'; iHTML += '<input type="checkbox" id="_cbFeedFilter_TypeMP" />MP<br>'; iHTML += '<input type="checkbox" id="_cbFeedFilter_TypePUR" />PUR<br>'; iHTML += '<input type="checkbox" id="_cbFeedFilter_TypePM" />PM notifications<br>'; iHTML += '<br><b>Filter feed by listing reason:</b><br>'; for(var loop=0; loop < uroFeedFilterFilters.length; loop++) { iHTML += '<input type="checkbox" id="_cbFeedFilter_'+loop+'" />'+I18n.lookup(uroFeedFilterFilters[loop][0])+'<br>'; } iHTML += '<input type="checkbox" id="_cbFeedFilter_MotNone" />None of the above...<br>'; iHTML += '<br><input type="checkbox" id="_cbFeedFilter_Invert" />Invert behaviour of above filters<br>'; iHTML += '<br><b>Filter feed by keyword/phrase:</b><br>'; iHTML += '<input type="checkbox" id="_cbFeedFilter_HideKeyword" pairedWith="_cbFeedFilter_ShowKeyword" />Hide or '; iHTML += '<input type="checkbox" id="_cbFeedFilter_ShowKeyword" pairedWith="_cbFeedFilter_HideKeyword" />show if keyword is present<br>'; iHTML += '<input type="text" id="_cbFeedFilter_Keyword" />'; iHTML += '</div>'; nDiv.innerHTML = iHTML; document.getElementById('sidepanel-feed').insertBefore(nDiv,document.getElementById('sidepanel-feed').childNodes[0]); uroAddEventListener('_uroFFCtrlVisibility','click',uroToggleFFCtrls, true); uroShowFeedFilter = true; uroToggleFFCtrls(); var nDiv2 = document.createElement('div'); nDiv2.id = "uroFeedRefresher"; nDiv2.style.display = 'none'; nDiv2.innerHTML = '<br><div id="_btnFeedRefresh" class="btn btn-block btn-default" style="display: block;"><i class="fa fa-refresh"></div>'; document.getElementById('sidepanel-feed').appendChild(nDiv2); uroAddEventListener('_btnFeedRefresh','click',uroForceFeedRefresh, true); } } } function uroTSTFeedFilter() { var feedEntries = document.getElementsByClassName('feed-item'); var feedLength = feedEntries.length; if(feedLength === 0) return; if(document.getElementById('uroFeedFilter') === null) return; var hideFI; var iHTML; var fClass; var ffKeyword = uroGetElmValue('_cbFeedFilter_Keyword'); var ffShowKW = uroGetCBChecked('_cbFeedFilter_ShowKeyword'); var ffHideKW = uroGetCBChecked('_cbFeedFilter_HideKeyword'); var kwPresent; var isChecked_cbFeedFilter_TypeUR = uroGetCBChecked('_cbFeedFilter_TypeUR'); var isChecked_cbFeedFilter_TypeMP = uroGetCBChecked('_cbFeedFilter_TypeMP'); var isChecked_cbFeedFilter_TypePUR = uroGetCBChecked('_cbFeedFilter_TypePUR'); var isChecked_cbFeedFilter_TypePM = uroGetCBChecked('_cbFeedFilter_TypePM'); var isChecked_cbFeedFilter_MotNone = uroGetCBChecked('_cbFeedFilter_MotNone'); var isChecked_cbFeedFilter_Invert = uroGetCBChecked('_cbFeedFilter_Invert'); var trans = []; var isChecked = []; var nFilters = uroFeedFilterFilters.length; for(var loop=0; loop < nFilters; loop++) { trans.push(I18n.lookup(uroFeedFilterFilters[loop][0])); isChecked.push(uroGetCBChecked('_cbFeedFilter_'+loop)); } for(var i=0; i<feedLength; i++) { hideFI = false; iHTML = feedEntries[i].innerHTML; fClass = feedEntries[i].className; if(isChecked_cbFeedFilter_TypeUR) { hideFI |= (fClass.indexOf('feed-issue-ur') != -1); } if(isChecked_cbFeedFilter_TypeMP) { hideFI |= (fClass.indexOf('feed-issue-mp') != -1); } if(isChecked_cbFeedFilter_TypePUR) { hideFI |= (fClass.indexOf('feed-issue-pu') != -1); } if(isChecked_cbFeedFilter_TypePM) { hideFI |= (fClass.indexOf('feed-notification-pm') != -1); } for(var filters=0; filters < nFilters; filters++) { if(isChecked[filters]) { hideFI |= (iHTML.indexOf(trans[filters]) != -1); } } if(isChecked_cbFeedFilter_MotNone) { hideFI |= (iHTML.indexOf('motivation') == -1); } if(isChecked_cbFeedFilter_Invert) { hideFI = !hideFI; } if((ffShowKW) || (ffHideKW)) { kwPresent = (iHTML.indexOf(ffKeyword) != -1); hideFI |= (kwPresent & ffHideKW); hideFI |= ((!kwPresent) & ffShowKW); } if(hideFI) feedEntries[i].style.display = 'none'; else feedEntries[i].style.display = 'block'; } var nFeedItems = document.getElementById('sidepanel-feed').getElementsByClassName('feed-item').length; var nVisibleItems = 0; for(var j=0; j < nFeedItems; j++) { if(document.getElementById('sidepanel-feed').getElementsByClassName('feed-item')[j].style.display == 'block') { nVisibleItems++; } } if(nVisibleItems < 5) { if(document.getElementById('sidepanel-feed').getElementsByClassName('feed-loading-more')[0].style.display == 'none') { if(uroFeedFilterReloads < 5) { document.getElementById('sidepanel-feed').getElementsByClassName('feed-load-more')[0].click(); uroFeedFilterReloads++; document.getElementById('uroFeedRefresher').style.display = 'none'; } else { document.getElementById('uroFeedRefresher').style.display = 'block'; } } } else { uroFeedFilterReloads = 0; document.getElementById('uroFeedRefresher').style.display = 'none'; } } //} function uroGetMarkerType(className) { var markerType = null; if(className.indexOf('user-generated') !== -1) markerType = 'ur'; else if(className.indexOf('map-problem') !== -1) markerType = 'mp'; else if(className.indexOf('place-update') !== -1) markerType = 'pur'; return markerType; } function uroMarkerMouseOver(e) { var markerType; markerType = uroGetMarkerType(this.className); if(markerType !== null) { var markerID = null; markerID = this.attributes["data-id"].value; uroAddLog('hover over '+markerType+' ID '+markerID); uroMousedOverMarkerID = markerID; uroMousedOverMarkerType = markerType; if(markerType == 'ur') uroHoveredURID = markerID; } else { uroAddLog('hover over unknown object...'); } } function uroMarkerMouseOut(e) { var markerType; markerType = uroGetMarkerType(this.className); if(markerType !== null) { var markerID = null; markerID = this.attributes["data-id"].value; uroAddLog('hover off '+markerType+' ID '+markerID); uroMousedOverMarkerID = null; uroMousedOverMarkerType = null; uroHoveredURID = null; } else { uroAddLog('hover off unknown object...'); } } function uroMarkerClick() { var markerType = uroGetMarkerType(this.className); if(markerType !== null) { var markerID = this.attributes["data-id"].value; uroAddLog('clicked on '+markerType+' marker '+markerID); uroClickedOnMarkerID = markerID; uroClickedOnMarkerType = markerType; } } function uroBlobMouseOver(e) { var blobType = this.attributes.uroBlobType; if(blobType !== undefined) { var blobID = this.attributes.uroBlobID; uroAddLog('hover over '+blobType+' ID '+blobID); //uroMousedOverMarkerID = markerID; //uroMousedOverMarkerType = markerType; } else { uroAddLog('hover over unknown blob...'); } } function uroBlobMouseOut(e) { var blobType = this.attributes.uroBlobType; if(blobType !== undefined) { var blobID = this.attributes.uroBlobID; uroAddLog('hover off '+blobType+' ID '+blobID); //uroMousedOverMarkerID = markerID; //uroMousedOverMarkerType = markerType; } else { uroAddLog('hover off unknown blob...'); } } function uroBlobClick() { var blobType = this.attributes.uroBlobType; if(blobType !== undefined) { var blobID = this.attributes.uroBlobID; uroAddLog('clicked on '+blobType+' blob '+blobID); } } function uroMCLayerChanged() { if(uroMCLayerIdx != null) { uroAddLog('adding MC blob event handlers'); for(var mObj=0; mObj<W.map.layers[uroMCLayerIdx].features.length; mObj++) { var mcBlobID = W.map.layers[uroMCLayerIdx].features[mObj].model.attributes.geometry.id; var mcID = W.map.layers[uroMCLayerIdx].features[mObj].model.attributes.id; var mcBlob = document.getElementById(mcBlobID); if(mcBlob !== null) { mcBlob.addEventListener("mouseover", uroBlobMouseOver, false); mcBlob.addEventListener("mouseout", uroBlobMouseOut, false); mcBlob.addEventListener("click", uroBlobClick, false); mcBlob.attributes.uroBlobID = mcID; mcBlob.attributes.uroBlobType = "map_comment"; } } } } function uroPlaceLayerChanged() { uroAddLog('adding place blob event handlers'); for(var mObj=0; mObj<W.map.landmarkLayer.features.length; mObj++) { var mcBlobID = W.map.landmarkLayer.features[mObj].model.attributes.geometry.id; var mcID = W.map.landmarkLayer.features[mObj].model.attributes.id; var mcBlob = document.getElementById(mcBlobID); if(mcBlob !== null) { mcBlob.addEventListener("mouseover", uroBlobMouseOver, false); mcBlob.addEventListener("mouseout", uroBlobMouseOut, false); mcBlob.addEventListener("click", uroBlobClick, false); mcBlob.attributes.uroBlobID = mcID; mcBlob.attributes.uroBlobType = "place"; } } } function uroURLayerChanged() { uroAddLog('adding UR marker event handlers'); for(var mObj in W.map.updateRequestLayer.markers) { var mIcon = W.map.updateRequestLayer.markers[mObj].icon.div; mIcon.addEventListener("mouseover",uroMarkerMouseOver, false); mIcon.addEventListener("mouseout",uroMarkerMouseOut, false); mIcon.addEventListener("click",uroMarkerClick, false); } } function uroMPLayerChanged() { uroAddLog('adding MP marker event handlers'); for(var mObj in W.map.problemLayer.markers) { var mIcon = W.map.problemLayer.markers[mObj].icon.div; mIcon.addEventListener("mouseover", uroMarkerMouseOver, false); mIcon.addEventListener("mouseout", uroMarkerMouseOut, false); mIcon.addEventListener("click", uroMarkerClick, false); } } function uroPURLayerChanged() { uroAddLog('adding PUR marker event handlers'); for(var mObj in W.map.placeUpdatesLayer.markers) { var mIcon = W.map.placeUpdatesLayer.markers[mObj].icon.div; mIcon.addEventListener("mouseover", uroMarkerMouseOver, false); mIcon.addEventListener("mouseout", uroMarkerMouseOut, false); mIcon.addEventListener("click", uroMarkerClick, false); } } function uroFinalizeListenerSetup() { uroFinalisingListenerSetup = true; // filter markers when the marker objects are modified (this happens whenever WME needs to load fresh marker data // due to having panned/zoomed the map beyond the extents of the previously loaded data) W.model.mapUpdateRequests.on("objectschanged", uroFilterURs_onObjectsChanged); W.model.mapUpdateRequests.on("objectsadded", uroFilterURs_onObjectsAdded); W.model.mapUpdateRequests.on("objectsremoved", uroFilterURs_onObjectsRemoved); W.model.updateRequestSessions.on("objectschanged", uroUREvent_onObjectsChanged); W.model.updateRequestSessions.on("objectsadded", uroUREvent_onObjectsAdded); W.model.updateRequestSessions.on("objectsremoved", uroUREvent_onObjectsRemoved); W.model.cameras.on("objectschanged", uroFilterCameras); W.model.cameras.on("objectsadded", uroFilterCameras); W.model.cameras.on("objectsremoved", uroFilterCameras); W.model.problems.on("objectschanged", uroFilterProblems); W.model.problems.on("objectsadded", uroFilterProblems); W.model.problems.on("objectsremoved", uroFilterProblems); W.model.venues.on("objectschanged", uroFilterPlaces); W.model.venues.on("objectsadded", uroFilterPlaces); W.model.venues.on("objectsremoved", uroFilterPlaces); ////var uroMO_MCLayer = new MutationObserver(uroMCLayerChanged); ////uroMO_MCLayer.observe(W.map.layers[uroMCLayerIdx].div,{childList: true, attributes : true, characterData: true, subtree: true}); ////var uroMO_PlaceLayer = new MutationObserver(uroPlaceLayerChanged); ////uroMO_PlaceLayer.observe(W.map.landmarkLayer.div,{childList: true, attributes : true, characterData : true, subtree: true}); var uroMO_URLayer = new MutationObserver(uroURLayerChanged); uroMO_URLayer.observe(W.map.updateRequestLayer.div,{childList : true}); var uroMO_MPLayer = new MutationObserver(uroMPLayerChanged); uroMO_MPLayer.observe(W.map.problemLayer.div,{childList : true}); var uroMO_PURLayer = new MutationObserver(uroPURLayerChanged); uroMO_PURLayer.observe(W.map.placeUpdatesLayer.div,{childList : true}); var userTabs = document.getElementById(uroUserTabId); var tabContent = null; var navTabs = userTabs.getElementsByClassName('nav-tabs')[0]; tabContent = document.getElementById('user-info').getElementsByClassName('tab-content')[0]; var newtabUR = document.createElement('li'); newtabUR.innerHTML = '<a href="#sidepanel-uroverview" data-toggle="tab">URO+</a>'; navTabs.appendChild(newtabUR); uroControls.id = "sidepanel-uroverview"; uroControls.className = "tab-pane"; tabContent.appendChild(uroControls); uroAddEventListener('_btnUndoLastHide',"click", uroRemoveLastAddedIgnore, true); uroAddEventListener('_btnClearSessionHides',"click", uroRemoveAllIgnores, true); uroEnableIgnoreListControls(); uroAddEventListener('_btnClearCamWatchList',"click", uroClearCamWatchList, true); uroAddEventListener('_btnSettingsToText',"click", uroSettingsToText, true); uroAddEventListener('_btnTextToSettings',"click", uroTextToSettings, true); uroAddEventListener('_btnResetSettings',"click", uroDefaultSettings, true); uroAddEventListener('_btnClearSettingsText',"click", uroClearSettingsText, true); uroAddEventListener('_cbMasterEnable',"click", uroFilterItems_MasterEnableClick, true); /* uroAddEventListener('_btnDebugToScreen',"click", uroDumpDebug, true); */ uroAddEventListener('uroDiv',"dblclick",uroSuppressPopup,true); uroAddEventListener('_selectCameraUserID',"change", uroCamEditorSelected, true); uroAddEventListener('_selectPlacesUserID',"change", uroPlacesEditorSelected, true); uroAddEventListener('uroAlertTickBtn','click',uroCloseAlertBoxWithTick,true); uroAddEventListener('uroAlertCrossBtn','click',uroCloseAlertBoxWithCross,true); uroSetOnClick("_linkSelectUserRequests",uroShowURTab); uroSetOnClick("_linkSelectMapProblems",uroShowMPTab); uroSetOnClick("_linkSelectPlaces",uroShowPlacesTab); uroSetOnClick("_linkSelectCameras",uroShowCameraTab); uroSetOnClick("_linkSelectMisc",uroShowMiscTab); uroSetOnClick("_linkSelectOWL",uroShowOWLTab); for(var idx=0;idx<W.Config.venues.categories.length;idx++) { uroSetOnClick('_uroPlacesGroupState-'+idx,uroPlacesGroupCollapseExpand); } uroAddLog('finalise onload'); uroLoadSettings(); uroNewLookCheckDetailsRequest(); if(uroGetCBChecked('_cbEnableDTE')) { if(dteControlsIdx != -1) { dteSetNewTabLength(); } else { uroAddLog('ERROR - archive panel not found!'); uroSetStyleDisplay(uroUserTabId,''); } } // filter markers as and when the map is moved W.map.events.register("moveend", null, uroFilterItems); W.map.events.register("mousemove", null, uroGetAMs); W.map.events.register("mousemove", null, uroNewLookHighlightedItemsCheck); W.map.events.registerPriority("mousedown", null, uroMouseDown); // trap mousedown on Streetview marker drag document.getElementsByClassName('street-view-control')[0].onmousedown = uroMouseDown; W.map.events.register("mouseup", null, uroMouseUp); W.map.events.register("mouseout", null, uroMouseOut); uroSetStyles(uroCtrlURs); uroSetStyles(uroCtrlMPs); uroSetStyles(uroCtrlPlaces); uroSetStyles(uroCtrlCameras); uroSetStyles(uroCtrlMisc); uroSetStyles(uroOWL); uroAddFeedFilterControls(); uroShowURTab(); uroUserID = W.loginManager.getLoggedInUser().id; uroFilterItems(); uroShowDebugOutput = uroPersistentDebugOutput; var dbgMode = "none"; if(uroShowDebugOutput) { dbgMode = "inline"; } document.getElementById('_uroDebugMode').style.display = dbgMode; uroAddEventListener('_uroVersion',"click", uroToggleDebug, true); // add exclusiveCB click handlers to all checkboxes with a pairedWith attribute var cbList = document.getElementsByTagName('input'); for (var optIdx=0;optIdx<cbList.length;optIdx++) { if((cbList[optIdx].id.indexOf('_cb') === 0) && (cbList[optIdx].attributes.pairedWith != null)) { uroSetOnClick(cbList[optIdx].id,uroExclusiveCB); } } // manually call the layer-change handlers on startup, since there's a good chance WME will already have // completed its own startup layer changes before our handlers get registered, preventing the marker handlers // from being set up as expected on any markers which are visible in the startup map view before the user forces // a layer update by panning/zooming/etc... ////uroMCLayerChanged(); ////uroPlaceLayerChanged(); uroURLayerChanged(); uroMPLayerChanged(); uroPURLayerChanged(); uroSetupListeners = false; uroInitialised = true; } function uroTSTPopupHandler() { if(document.getElementsByClassName('panel')[0] === undefined) { uroHidePopupOnPanelOpen = true; } if(uroPopupShown === true) { var hidePopup = false; if(document.getElementsByClassName('dropdown action open').length > 0.5) { hidePopup = true; } if(hidePopup === false) { if(document.getElementsByClassName('layer-switcher-container').length === 0) { if(document.getElementById('layer-switcher-list') !== null) { hidePopup = (window.getComputedStyle(document.getElementById('layer-switcher-list').parentNode).getPropertyValue('opacity') > 0.5); } else if(document.getElementsByClassName('layer-switcher').length !== 0) { hidePopup = (window.getComputedStyle(document.getElementsByClassName('layer-switcher')[0].getElementsByClassName('content')[0]).getPropertyValue('visibility') == 'visible'); } } } if(hidePopup === false) { hidePopup = (window.getComputedStyle(document.getElementsByClassName('toolbar-group-drawing')[0].childNodes[0]).getPropertyValue('opacity') > 0.5); } if(hidePopup === false) { hidePopup = (window.getComputedStyle(document.getElementsByClassName('toolbar-group-venues')[0].childNodes[0]).getPropertyValue('opacity') > 0.5); } if(hidePopup === false) { hidePopup = (window.getComputedStyle(document.getElementsByClassName('toolbar-group-map-comments')[0].childNodes[0]).getPropertyValue('opacity') > 0.5); } if(document.getElementsByClassName('panel')[0] != null) { if(uroHidePopupOnPanelOpen === true) { hidePopup = true; uroHidePopupOnPanelOpen = false; } } if(hidePopup === true) { uroHidePopup(); } } if((uroAreaNameHoverObj !== null) && (uroAreaNameHoverTime != -1) && (uroAreaNameOverlayShown === false)) { if(++uroAreaNameHoverTime > 5) { uroAreaNameOverlaySetup(); } } uroReplaceAreaNames(false); if(uroPopupTimer > 0) { if(uroMouseInPopup === false) { uroPopupTimer--; } } if(uroPopupTimer === 0) { uroHidePopup(); } if(uroPopupDwellTimer > 0) { uroPopupDwellTimer--; if(uroPopupDwellTimer === 0) { uroNewLookHighlightedItemsCheck('dwellTimeout'); } } } function uroTSTDTEHandler() { if(document.getElementsByClassName("archive-panel")[0] === undefined) { if(dteClearHighlightsOnPanelClose) { dteClearListHighlight(); dteClearHighlightsOnPanelClose = false; } } else { if(dteArmClearHighlightsOnPanelClose) { dteArmClearHighlightsOnPanelClose = false; dteClearHighlightsOnPanelClose = true; } } } function uroTSTNextBtnHandler() { // replace the "next xxx" button on UR, MP and PUR editing UIs if(W.map.panelRegion.hasView() === true) { var nurButton = W.map.panelRegion.$el[0].getElementsByClassName('btn btn-block')[0]; if(nurButton != null) { var doneString = I18n.lookup('problems.panel.done'); var nextURString = (nurButton.innerHTML.indexOf(I18n.lookup('update_requests.panel.next')) !== -1); var nextMPString = (nurButton.innerHTML.indexOf(I18n.lookup('problems.panel.next')) !== -1); var nextPURString = (nurButton.innerHTML.indexOf(I18n.lookup('venues.update_requests.panel.next_venue')) !== -1); var nextIssueString = (nurButton.innerHTML.indexOf(I18n.lookup('feed.issues.next')) !== -1); var updateButton = false; var panelClass = W.map.panelRegion.$el[0].childNodes[0].childNodes[0].className; var isURorMPPanel = (panelClass.indexOf('problem-edit') !== -1); var isPURPanel = (panelClass.indexOf('place-update') !== -1); // "next" button class used for UR and MP edit panel if(isURorMPPanel === true) { // user has enabled UR button mod? if(uroGetCBChecked('_cbInhibitNURButton') === true) { // mod the button if this is a UR/MP panel rather than a PUR panel, and if the "Next update request" or "Next issue" // text is currently being used on the button - WME uses the former text when a UR is selected directly from the map // pin, and the latter text when a UR is selected from the feed. However, it *also* uses the latter text for PURs // selected from the feed, hence the need to test the panel type here as well - having to work around odd // inconsistencies in WME behaviour, whatever next... updateButton = updateButton || ((nextURString === true) || (nextIssueString === true)); } // user has enabled MP button mod? if(uroGetCBChecked('_cbInhibitNMPButton') === true) { // although there's no easy way to determine whether the panel is opened for a UR or MP, since the feed doesn't yet seem // to provide a means of accessing MPs then we don't yet have to worry about finding the "Next issue" text in a MP panel, // which makes life slightly easier here... updateButton = updateButton || (nextMPString === true); } } else if(isPURPanel === true) { // "next-venue" class only used for PUR edit panel if(uroGetCBChecked('_cbInhibitNPURButton') === true) { // as noted above, PURs opened from the feed may also use the "Next issue" text, so we need to test for that as well, // knowing that in order to get this far we've already determined that the user really does want to mod the PUR // next button *and* that the currently open panel is a PUR panel... updateButton = updateButton || ((nextPURString === true) || (nextIssueString === true)); } } if(updateButton === true) { // if we need to change the button label back to "Done", do it here... nurButton.innerHTML = doneString; uroAddLog('inhibit Next UR/MP/PUR button'); } // if updateButton isn't already set here, it suggests the panel is using the native "Done" button... if(updateButton === false) { nurButton = W.map.panelRegion.$el[0].getElementsByClassName('btn btn-block done')[0]; if(nurButton != null) { updateButton = true; } } if(updateButton === true) { // Add a new click handler to override the native one - this acts both to prevent the normal action of the "Next UR/MP/PUR" button in // moving to the next UR/MP/PUR, and also allows us to warn about closing the UR panel if there's an unsent comment... nurButton.addEventListener("click", uroInhibitNextUpdateRequestButton, false); } } } } function uroTSTCommentAddedHandler() { // test for the opening or closing of the UR editing dialog so we can detect when a new comment is added var URDialogIsOpen = false; var panelOpen = (document.getElementById('panel-container').firstChild !== null); if(panelOpen) { if(document.getElementById('panel-container').firstChild.firstChild !== null) { var panelClass = document.getElementById('panel-container').firstChild.firstChild.className; if(panelClass === 'problem-edit severity-low') { URDialogIsOpen = true; } } } if(URDialogIsOpen) { var thisSelectedURID = document.getElementsByClassName('permalink')[0].href.split('&mapUpdateRequest='); if(thisSelectedURID.length > 1) { thisSelectedURID = thisSelectedURID[1].split('&')[0]; } else { thisSelectedURID = null; } if(thisSelectedURID != uroSelectedURID) { // if the user selects a new UR whilst the editing dialog is still open, treat it in the // same way as if the user had selected that UR with the dialog closed uroURDialogIsOpen = false; } if(uroURDialogIsOpen === false) { // user is editing a new UR uroSelectedURID = thisSelectedURID; // add our own click event handler to the Send button, so we can do stuff whenever a new comment is added document.getElementsByClassName('new-comment-form')[0].getElementsByClassName('btn')[0].addEventListener("click", uroAddedComment, false); uroAddLog('user is editing UR '+uroSelectedURID); uroExpectedCommentCount = W.model.updateRequestSessions.objects[uroSelectedURID].comments.length; ////if(uroShowDebugOutput === true) { if((uroHoveredURID !== null) && (uroSelectedURID !== null) && (parseInt(uroHoveredURID) !== parseInt(uroSelectedURID))) { if(uroURReclickAttempts === 0) { uroAddLog('DANGER, WILL ROBINSON! You clicked on UR ID '+uroHoveredURID+' but WME has loaded the details for UR ID '+uroSelectedURID+' instead, attempting to fix...'); } if(++uroURReclickAttempts < 3) { //uroRestackMarkers(); W.map.updateRequestLayer.markers[uroHoveredURID].model.attributes.geometry.x = W.map.updateRequestLayer.markers[uroHoveredURID].model.attributes.geometry.realX; W.map.updateRequestLayer.markers[uroHoveredURID].model.attributes.geometry.y = W.map.updateRequestLayer.markers[uroHoveredURID].model.attributes.geometry.realY; W.map.updateRequestLayer.markers[uroHoveredURID].icon.$div.click(); return; } else { uroAddLog('Woe is me, attempting to open UR ID '+uroHoveredURID+' has failed...'); uroShowAlertBox('fa-warning', 'URO+ Warning', 'WME may have opened the details panel for a different UR to the one you selected, proceed with caution', false, "OK", "", null, null); } } uroURReclickAttempts = 0; } } } else if(uroURDialogIsOpen === true) { // dialog was open and has now been closed uroSelectedURID = null; } uroURDialogIsOpen = URDialogIsOpen; if(((uroPendingCommentDataRefresh === true) || (uroWaitingCommentDataRefresh === true)) && (uroSelectedURID !== null)) { uroAddLog('check completion of comment data refresh for UR '+uroSelectedURID+' ('+uroPendingCommentDataRefresh+','+uroWaitingCommentDataRefresh+')'); uroGetSelectedURCommentCount(); } } function uroTSTOWLHandler() { /* var selectedTotal = W.selectionManager.selectedItems.length; if((selectedTotal > 0) && (document.getElementById('_uroDivOWLBtns') === null)) { var selectedClass = W.selectionManager.selectedItems[0].model.CLASS_NAME; var displayAddToOWLBtn = false; var displayUpdateOWLBtn = false; var displayRemoveFromOWLBtn = false; var selectedSegments = false; var selectedLandmarks = false; var fid; var loop; // WME only seems to allow multi-object selections for segments, so testing the class of the first object in the // selection list tells us the class of any other objects in the list too... if(selectedClass == "Waze.Feature.Vector.Segment") { selectedSegments = true; for(loop=0; loop<selectedTotal; loop++) { fid = W.selectionManager.selectedItems[loop].model.attributes.id; var segIdx = uroIsSegOnWatchList(fid); if(segIdx == -1) { displayAddToOWLBtn = true; } else { if(uroSegDataChanged(segIdx)) { displayUpdateOWLBtn = true; } displayRemoveFromOWLBtn = true; } } } else if(selectedClass == "Waze.Feature.Vector.Landmark") { selectedLandmarks = true; for(loop=0; loop<selectedTotal; loop++) { fid = W.selectionManager.selectedItems[loop].model.attributes.id; var placeIdx = uroIsPlaceOnWatchList(fid); if(placeIdx == -1) { displayAddToOWLBtn = true; } else { if(uroPlaceDataChanged(placeIdx)) { displayUpdateOWLBtn = true; } displayRemoveFromOWLBtn = true; } } } var btnHTML = '<div id="_uroDivOWLBtns">'; if((displayAddToOWLBtn === true) && (displayUpdateOWLBtn === false)) { btnHTML += '<button class="btn btn-default" id="_btnAddUpdateOWL">Add to OWL</button>'; } else if((displayUpdateOWLBtn === true) && (displayAddToOWLBtn === false)) { btnHTML += '<button class="btn btn-default" id="_btnAddUpdateOWL">Update OWL</button>'; } else if((displayAddToOWLBtn === true) && (displayUpdateOWLBtn === true)) { btnHTML += '<button class="btn btn-default" id="_btnAddUpdateOWL">Add to & Update OWL</button>'; } if(displayRemoveFromOWLBtn === true) { btnHTML += '<button class="btn btn-default" id="_btnRemoveOWL">Remove from OWL</button>'; } btnHTML += '</div>'; // note to self... altering the inner HTML of the segment-edit-general panel when the selected // segment is part of a roundabout always used to disable the onclick handler for the select // roundabout button. will need to see how this behaves in the current WME given the changes in // panel arrangement and the introduction of the native select roundabout button if(selectedSegments === true) { document.getElementById("segment-edit-general").innerHTML += btnHTML; } else if(selectedLandmarks === true) { document.getElementById("landmark-edit-general").innerHTML += btnHTML; } if((displayAddToOWLBtn === true)||(displayUpdateOWLBtn === true)) { if(selectedSegments === true) { uroAddEventListener('_btnAddUpdateOWL','click', uroAddUpdateSegWatchList, true); } else { uroAddEventListener('_btnAddUpdateOWL','click', uroAddUpdatePlaceWatchList, true); } } if(displayRemoveFromOWLBtn === true) { if(selectedSegments === true) { uroAddEventListener('_btnRemoveOWL','click', uroRemoveSegFromWatchList, true); } else { uroAddEventListener('_btnRemoveOWL','click', uroRemovePlaceFromWatchList, true); } } } */ } function uroTSTClosureCloningHandler() { // closure cloning support... // // has the closures tab been generated? if(document.getElementById('segment-edit-closures') !== null) { // and is it active? if(document.getElementById('segment-edit-closures').className === 'tab-pane active') { // and are there any closures defined for all of the selected segment(s)... if(document.getElementsByClassName('full-closures').length > 0) { var nClosures = document.getElementsByClassName('full-closures')[0].childNodes.length; if(nClosures > 0) { // and last but by no means least, have we already added the clone icon to this closure? for(var cLoop = 0; cLoop < nClosures; cLoop++) { var btnElm = document.getElementsByClassName('full-closures')[0].childNodes[cLoop].children[0].children[0]; if(btnElm.innerHTML.indexOf('_uroCloneClosure-') == -1) { var newAnchor = document.createElement('a'); var anchorID = '_uroCloneClosure-'+cLoop; newAnchor.href="#"; newAnchor.innerHTML = "<i class='fa fa-copy'></i>"; newAnchor.id = anchorID; btnElm.appendChild(newAnchor); uroAddEventListener(anchorID,"click",uroCloneClosure,false); } } } } // if there's more than one closure (full or partial) listed, also add the delete all button if not already present... if(document.getElementsByClassName('closure-item').length > 1) { if(document.getElementById('_btnDeleteAllClosures') === null) { var daDiv = document.createElement('div'); daDiv.className = 'delete-all-button btn btn-primary'; daDiv.id = '_btnDeleteAllClosures'; daDiv.innerHTML = '<i class="fa fa-trash"></i> '+I18n.lookup("closures.delete_confirm_no_reason")+' ('+I18n.lookup("closures.apply_to_all")+')'; daDiv.style.width = '100%'; daDiv.style.marginBottom = '10px'; var acBtn = document.getElementsByClassName('add-closure-button')[0]; acBtn.parentNode.insertBefore(daDiv, acBtn.nextSibling); uroAddEventListener('_btnDeleteAllClosures',"click", uroDeleteAllClosures, false); } } } } } function uroMiscUITweaksHandler() { if(uroFilterPreamble()) { // give user the option of setting their own background colour... { var mapviewport = document.getElementsByClassName("olMapViewport")[0]; if((uroGetCBChecked('_cbWhiteBackground') === true) && (uroGetCBChecked('_cbMasterEnable') === true)) { var customColour = '#' + uroToHex(uroGetElmValue('_inputCustomBackgroundRed'),2); customColour += uroToHex(uroGetElmValue('_inputCustomBackgroundGreen'),2); customColour += uroToHex(uroGetElmValue('_inputCustomBackgroundBlue'),2); mapviewport.style.backgroundColor = customColour; } else { mapviewport.style.backgroundColor = "#C2C2C2"; } } // allows user to hide the area managers layer without switching off the layer completely... { // ...if this sounds like a weird option - why not just switch off the layer from the layers menu? - then // remember that in order for URO+ to be able to display in its own tab the list of AMs under the current // mouse pointer location, which is somewhat more useful than the list given in the topbar, it needs the // AM layer to be activated so that the AM areas data is loaded into WME. It doesn't however need the layer // to then be visible, and since having a bunch of purple polygons covering the map can make for a rather // difficult editing experience, being able to hide the polys whilst retaining the area information is // of real benefit... if((uroGetCBChecked('_cbHideAMLayer')) && (uroGetCBChecked('_cbMasterEnable'))) { W.map.managedAreasLayer.setOpacity(0); } else { W.map.managedAreasLayer.setOpacity(1); } } // gives user the option of minimising the size of the sidebar tabs to save space { if(!uroGetCBChecked('_cbDisableTabStyling')) { // The nav-tabs class is now also used for the General/Closures tabs on the segment edit panel, so we have // to restrict the scope of this code to just those nav-tab classed elements within the user-tabs element. var navTabs = document.getElementById('user-tabs').getElementsByClassName("nav-tabs")[0].children; for(var loop = 0; loop<navTabs.length; loop++) { navTabs[loop].children[0].style.padding = "4px"; } } } // gives user the option of hiding the somewhat unnecessary editor info panel at the top of the sidebar { var panelDisplay = ''; if(uroGetCBChecked('_cbHideEditorInfo')) { panelDisplay = "none"; } document.getElementById("user-details").style.display = panelDisplay; } } } function uroTenthSecondTick() { if(uroMTEMode) return; if(uroSetupListeners) { if(uroFinalisingListenerSetup === false) { if(W.loginManager.isLoggedIn()) { uroFinalizeListenerSetup(); } } } else { uroTSTPopupHandler(); uroTSTDTEHandler(); uroTSTNextBtnHandler(); uroTSTCommentAddedHandler(); uroTSTOWLHandler(); uroTSTClosureCloningHandler(); uroTSTFeedFilter(); uroMiscUITweaksHandler(); uroTempFixMTEDropDown(); } } function uroActiveTab(_id) { var e = document.getElementById(_id); e.style.backgroundColor = "aliceblue"; e.style.borderTop = "1px solid"; e.style.borderLeft = "1px solid"; e.style.borderRight = "1px solid"; e.style.borderBottom = "0px solid"; } function uroInactiveTab(_id) { var e = document.getElementById(_id); e.style.backgroundColor = "white"; e.style.borderTop = "0px solid"; e.style.borderLeft = "0px solid"; e.style.borderRight = "0px solid"; e.style.borderBottom = "1px solid"; } function uroInactiveAllTabs() { uroInactiveTab("_tabSelectCameras"); uroInactiveTab("_tabSelectMapProblems"); uroInactiveTab("_tabSelectMisc"); uroInactiveTab("_tabSelectUserRequests"); uroInactiveTab("_tabSelectCWL"); uroInactiveTab("_tabSelectPlaces"); if(!uroCtrlsHidden) { uroSetStyleDisplay('uroCtrlURs','none'); uroSetStyleDisplay('uroCtrlMPs','none'); uroSetStyleDisplay('uroCtrlCameras','none'); uroSetStyleDisplay('uroCtrlMisc','none'); uroSetStyleDisplay('uroOWL','none'); uroSetStyleDisplay('uroCtrlPlaces','none'); } } function uroShowURTab() { uroInactiveAllTabs(); uroActiveTab("_tabSelectUserRequests"); uroCurrentTab = 1; if(!uroCtrlsHidden) uroSetStyleDisplay('uroCtrlURs','block'); return false; } function uroShowMPTab() { uroInactiveAllTabs(); uroActiveTab("_tabSelectMapProblems"); uroCurrentTab = 2; if(!uroCtrlsHidden) uroSetStyleDisplay('uroCtrlMPs','block'); return false; } function uroShowPlacesTab() { uroInactiveAllTabs(); uroActiveTab("_tabSelectPlaces"); uroCurrentTab = 3; if(!uroCtrlsHidden) uroSetStyleDisplay('uroCtrlPlaces','block'); for(var idx=0;idx<uroPlacesGroupsCollapsed.length;idx++) { uroPlacesGroupCEHandler(idx); } return false; } function uroShowCameraTab() { uroInactiveAllTabs(); uroActiveTab("_tabSelectCameras"); uroCurrentTab = 4; if(!uroCtrlsHidden) uroSetStyleDisplay('uroCtrlCameras','block'); return false; } function uroShowOWLTab() { uroInactiveAllTabs(); uroActiveTab("_tabSelectCWL"); uroCurrentTab = 5; if(!uroCtrlsHidden) uroSetStyleDisplay('uroOWL','block'); uroOWLUpdateHTML(); return false; } function uroShowMiscTab() { uroInactiveAllTabs(); uroActiveTab("_tabSelectMisc"); uroCurrentTab = 6; if(!uroCtrlsHidden) uroSetStyleDisplay('uroCtrlMisc','block'); return false; } function uroNewLookCheckDetailsRequest() { var thisurl = document.location.href; var doRetry = true; var urID; var endmarkerpos = thisurl.indexOf('&endshow'); var showmarkerpos = thisurl.indexOf('&showturn='); if((endmarkerpos != -1) && (showmarkerpos != -1)) { showmarkerpos += 10; uroAddLog('showturn tab opened'); urID = thisurl.substr(showmarkerpos,endmarkerpos-showmarkerpos); uroAddLog(' turn problem ID = '+urID); try { W.map.problemLayer.markers[urID].icon.imageDiv.click(); doRetry = false; } catch(err) { uroAddLog('problems not fully loaded, retrying...'); } if(doRetry) setTimeout(uroNewLookCheckDetailsRequest,500); } else { showmarkerpos = thisurl.indexOf('&showpur='); if((endmarkerpos != -1) && (showmarkerpos != -1)) { showmarkerpos += 9; uroAddLog('showPUR tab opened'); urID = thisurl.substr(showmarkerpos,endmarkerpos-showmarkerpos); uroAddLog(' PUR ID = '+urID); try { W.map.placeUpdatesLayer.markers[urID].icon.imageDiv.click(); doRetry = false; } catch(err) { uroAddLog('PURs not fully loaded, retrying...'); } if(doRetry) setTimeout(uroNewLookCheckDetailsRequest,500); } } } function uroUpdateVenueEditorList() { if(Object.keys(W.model.venues.objects).length === 0) return; var selector = document.getElementById('_selectPlacesUserID'); var selectedUser = null; if(selector.selectedOptions[0] != null) { selectedUser = parseInt(selector.selectedOptions[0].value); } while(selector.options.length > 0) { selector.options.remove(0); } var selectedIdx = null; var listedIDs = []; var idx; for(idx in W.model.venues.objects) { if(W.model.venues.objects.hasOwnProperty(idx)) { var obj = W.model.venues.objects[idx].attributes; var cbID = obj.createdBy; var ubID = obj.updatedBy; if((cbID !== null) && (listedIDs.indexOf(cbID) == -1)) { listedIDs.push(cbID); } if((ubID !== null) && (ubID !== cbID) && (listedIDs.indexOf(ubID) == -1)) { listedIDs.push(ubID); } } } selector.options.add(new Option('<select a user>', null)); if(listedIDs.length > 0) { var users = W.model.users.getByIds(listedIDs); var selectorEntry = ''; for(idx=0; idx<users.length; idx++) { if(users[idx].userName === undefined) { selectorEntry = users[idx].id; } else { selectorEntry = users[idx].userName; } selector.options.add(new Option(selectorEntry, users[idx].id)); if(users[idx].id == selectedUser) { selectedIdx = idx+1; } } } if(selectedIdx !== null) { selector.selectedIndex = selectedIdx; } } function uroPlacesEditorSelected() { var selector = document.getElementById('_selectPlacesUserID'); if(selector.selectedIndex > 0) { document.getElementById('_textPlacesEditor').value = document.getElementById('_selectPlacesUserID').selectedOptions[0].innerHTML; } } function uroUpdateMPSolverList() { if(Object.keys(W.model.problems.objects).length === 0) { return; } var resolverList = []; var selector = document.getElementById('_selectMPUserID'); var selectedUser = null; if(selector.selectedOptions[0] != null) { selectedUser = parseInt(selector.selectedOptions[0].value); } while(selector.options.length > 0) { selector.options.remove(0); } var selectedIdx = 0; var idx = 0; for (var mpobj in W.model.problems.objects) { if(W.model.problems.objects.hasOwnProperty(mpobj)) { var prob = W.model.problems.objects[mpobj]; if(prob.attributes.resolvedBy !== null) { var userID = prob.attributes.resolvedBy; var userName = W.model.users.objects[userID].userName; if(resolverList.indexOf(userName) == -1) { resolverList.push(userName); selector.options.add(new Option(userName, userID)); if(userID == selectedUser) { selectedIdx = idx; } idx++; } } } } if(selectedIdx !== null) { selector.selectedIndex = selectedIdx; } } function uroUpdateResolverList() { if(Object.keys(W.model.mapUpdateRequests.objects).length === 0) { return; } var resolverList = []; var selector = document.getElementById('_selectURResolverID'); var selectedUser = null; if(selector.selectedOptions[0] != null) { selectedUser = parseInt(selector.selectedOptions[0].value); } while(selector.options.length > 0) { selector.options.remove(0); } var selectedIdx = 0; var idx = 0; for (var urobj in W.model.mapUpdateRequests.objects) { if(W.model.mapUpdateRequests.objects.hasOwnProperty(urobj)) { var ureq = W.model.mapUpdateRequests.objects[urobj]; if(ureq.attributes.resolvedBy !== null) { var userID = ureq.attributes.resolvedBy; var userName = W.model.users.objects[userID].userName; if(resolverList.indexOf(userName) == -1) { resolverList.push(userName); selector.options.add(new Option(userName, userID)); if(userID == selectedUser) { selectedIdx = idx; } idx++; } } } } if(selectedIdx !== null) { selector.selectedIndex = selectedIdx; } } function uroUpdateUserList() { if(Object.keys(W.model.updateRequestSessions.objects).length === 0) return; var selector = document.getElementById('_selectURUserID'); var selectedUser = null; if(selector.selectedOptions[0] != null) { selectedUser = parseInt(selector.selectedOptions[0].value); } while(selector.options.length > 0) { selector.options.remove(0); } var selectedIdx = null; var listedIDs = []; for(var ursIdx in W.model.updateRequestSessions.objects) { if(W.model.updateRequestSessions.objects.hasOwnProperty(ursIdx)) { var ursObj = W.model.updateRequestSessions.objects[ursIdx]; if(ursObj.comments.length > 0) { for(var cidx=0; cidx < ursObj.comments.length; cidx++) { var userID = ursObj.comments[cidx].userID; if((listedIDs.indexOf(userID) == -1) && (userID != -1)) { listedIDs.push(userID); } } } } } if(listedIDs.length > 0) { var users = W.model.users.getByIds(listedIDs); for(var idx=0; idx<listedIDs.length; idx++) { selector.options.add(new Option(users[idx].userName, listedIDs[idx])); if(listedIDs[idx] == selectedUser) { selectedIdx = idx; } } } if(selectedIdx !== null) { selector.selectedIndex = selectedIdx; } } function uroUpdateCamEditorList() { if(Object.keys(W.model.cameras.objects).length === 0) return; var selector = document.getElementById('_selectCameraUserID'); var selectedUser = null; if(selector.selectedOptions[0] != null) { selectedUser = parseInt(selector.selectedOptions[0].value); } while(selector.options.length > 0) { selector.options.remove(0); } var selectedIdx = null; var listedIDs = []; for(var camIdx in W.model.cameras.objects) { if(W.model.cameras.objects.hasOwnProperty(camIdx)) { var camObj = W.model.cameras.objects[camIdx].attributes; var cbID = camObj.createdBy; var ubID = camObj.updatedBy; if((cbID !== null) && (listedIDs.indexOf(cbID) == -1)) { listedIDs.push(cbID); } if((ubID !== null) && (ubID !== cbID) && (listedIDs.indexOf(ubID) == -1)) { listedIDs.push(ubID); } } } selector.options.add(new Option('<select a user>', null)); if(listedIDs.length > 0) { var users = W.model.users.getByIds(listedIDs); var selectorEntry = ''; for(var idx=0; idx<users.length; idx++) { if(users[idx].userName === undefined) { selectorEntry = users[idx].id; } else { selectorEntry = users[idx].userName; } selector.options.add(new Option(selectorEntry, users[idx].id)); if(users[idx].id == selectedUser) { selectedIdx = idx+1; } } } if(selectedIdx !== null) { selector.selectedIndex = selectedIdx; } } function uroCamEditorSelected() { var selector = document.getElementById('_selectCameraUserID'); if(selector.selectedIndex > 0) { document.getElementById('_textCameraEditor').value = document.getElementById('_selectCameraUserID').selectedOptions[0].innerHTML; } } function uroSetStyles(obj) { obj.style.fontSize = '12px'; obj.style.lineHeight = '100%'; obj.style.overflow = 'auto'; obj.style.height = (window.innerHeight * 0.55) + 'px'; } function uroPlacesGroupCEHandler(groupidx) { if(uroPlacesGroupsCollapsed[groupidx] === false) { document.getElementById('_uroPlacesGroup-'+groupidx).style.display = "block"; document.getElementById('_uroPlacesGroupState-'+groupidx).className = "fa fa-minus-square-o"; } else { document.getElementById('_uroPlacesGroup-'+groupidx).style.display = "none"; document.getElementById('_uroPlacesGroupState-'+groupidx).className = "fa fa-plus-square-o"; } } function uroPlacesGroupCollapseExpand() { var groupidx = this.id.substr(21); if(uroPlacesGroupsCollapsed[groupidx] === true) uroPlacesGroupsCollapsed[groupidx] = false; else uroPlacesGroupsCollapsed[groupidx] = true; uroPlacesGroupCEHandler(groupidx); return false; } function uroPopulateProblemsTab() { var tHTML = ''; tHTML += '<input type="checkbox" id="_cbMPFilterOutsideArea">Hide MPs outside my editable area</input><br><br>'; tHTML += '<b>Filter MPs by type:</b><br>'; var i; for(i=0; i<uroKnownProblemTypeNames.length; i++) { tHTML += '<input type="checkbox" id="_cbMPFilter_T'+uroKnownProblemTypeIDs[i]+'">'+uroKnownProblemTypeNames[i]+'</input><br>'; } tHTML += '<br><input type="checkbox" id="_cbMPFilterUnknownProblem">Unknown problem type</input><br><br>'; tHTML += ' <i>Specially tagged types</i><br>'; tHTML += ' <input type="checkbox" id="_cbFilterElgin">[Elgin]</input><br>'; tHTML += ' <input type="checkbox" id="_cbFilterTrafficCast">[TrafficCast]</input><br>'; tHTML += ' <input type="checkbox" id="_cbFilterTrafficMaster">[TM]</input><br>'; tHTML += ' <input type="checkbox" id="_cbFilterCaltrans">[Caltrans]</input><br>'; tHTML += ' <input type="checkbox" id="_cbFilterTFL">TfL</input><br>'; tHTML += '<input type="checkbox" id="_cbMPFilterReopenedProblem">Reopened Problems</input><br><br>'; tHTML += '<input type="checkbox" id="_cbInvertMPFilter">Invert operation of type filters?</input><br>'; tHTML += '<br><b>Hide closed/solved/unidentified Problems:</b><br>'; tHTML += '<input type="checkbox" id="_cbMPFilterClosed">Closed</input><br>'; tHTML += '<input type="checkbox" id="_cbMPFilterSolved">Solved</input><br>'; tHTML += '<input type="checkbox" id="_cbMPFilterUnidentified">Not identified</input><br><br>'; tHTML += '<input type="checkbox" id="_cbMPClosedUserIDFilter" pairedWith="_cbMPNotClosedUserIDFilter">Closed</input> or '; tHTML += '<input type="checkbox" id="_cbMPNotClosedUserIDFilter" pairedWith="_cbMPClosedUserIDFilter">Not Closed</input> by user'; tHTML += '<select id="_selectMPUserID" style="width:80%; height:22px;"></select><br>'; tHTML += '<br><b>Hide problems (not turn) by severity:</b><br>'; tHTML += '<input type="checkbox" id="_cbMPFilterLowSeverity">Low</input> '; tHTML += '<input type="checkbox" id="_cbMPFilterMediumSeverity">Medium</input> '; tHTML += '<input type="checkbox" id="_cbMPFilterHighSeverity">High</input><br>'; uroCtrlMPs.innerHTML = tHTML; } function uroPopulatePlacesTab() { var tHTML = ''; tHTML += '<b>Filter PURs by category/status:</b><br>'; tHTML += '<input type="checkbox" id="_cbFilterUneditablePlaceUpdates">Ones I can\'t edit</input><br>'; tHTML += '<input type="checkbox" id="_cbFilterLockRankedPlaceUpdates">Ones with non-zero lockRanks</input><br>'; tHTML += '<input type="checkbox" id="_cbFilterNewPlacePUR">Ones for new places</input><br>'; tHTML += '<input type="checkbox" id="_cbFilterUpdatedDetailsPUR">Ones for updated place details</input><br>'; tHTML += '<input type="checkbox" id="_cbFilterNewPhotoPUR">Ones for new photos</input><br>'; tHTML += '<input type="checkbox" id="_cbFilterFlaggedPUR">Ones flagged for attention</input><br>'; tHTML += '<br><input type="checkbox" id="_cbLeavePURGeos">Don\'t hide place polygons/points</input><br>'; tHTML += '<br><input type="checkbox" id="_cbInvertPURFilters">Invert PUR filters</input><br>'; tHTML += '<br><b>Filter PURs by severity:</b><br>'; tHTML += '<input type="checkbox" id="_cbPURFilterLowSeverity">Low</input> '; tHTML += '<input type="checkbox" id="_cbPURFilterMediumSeverity">Medium</input> '; tHTML += '<input type="checkbox" id="_cbPURFilterHighSeverity">High</input>'; tHTML += '<br><b>Filter PURs by age of submission:</b><br>'; tHTML += '<input type="checkbox" id="_cbEnablePURMinAgeFilter">Hide PURs less than </input>'; tHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputPURFilterMinDays"> days old<br>'; tHTML += '<input type="checkbox" id="_cbEnablePURMaxAgeFilter">Hide PURs more than </input>'; tHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputPURFilterMaxDays"> days old<br>'; tHTML += '<hr>'; tHTML += '<br><b>Filter Places by state:</b><br>'; tHTML += 'Hide if last edited<br>'; tHTML += '<input type="checkbox" id="_cbPlaceFilterEditedLessThan"> less than </input>'; tHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputFilterPlaceEditMinDays"> days ago<br>'; tHTML += '<input type="checkbox" id="_cbPlaceFilterEditedMoreThan"> more than </input>'; tHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputFilterPlaceEditMaxDays"> days ago<br>'; tHTML += '<br>Hide if locked at level:<br>'; tHTML += ' <input type="checkbox" id="_cbHidePlacesL0">1</input>'; tHTML += ' <input type="checkbox" id="_cbHidePlacesL1">2</input>'; tHTML += ' <input type="checkbox" id="_cbHidePlacesL2">3</input>'; tHTML += ' <input type="checkbox" id="_cbHidePlacesL3">4</input>'; tHTML += ' <input type="checkbox" id="_cbHidePlacesL4">5</input>'; tHTML += ' <input type="checkbox" id="_cbHidePlacesL5">6</input>'; tHTML += ' <input type="checkbox" id="_cbHidePlacesStaff">Staff</input>'; tHTML += '<br> <input type="checkbox" id="_cbHidePlacesAdLocked">AdLocked</input><br>'; tHTML += '<br>Hide by geometry:<br>'; tHTML += ' <input type="checkbox" id="_cbHideAreaPlaces">Areas</input>'; tHTML += ' <input type="checkbox" id="_cbHidePointPlaces">Points</input>'; tHTML += '<br><br><input type="checkbox" id="_cbHidePhotoPlaces" pairedWith="_cbHideNoPhotoPlaces">Hide or </input>'; tHTML += '<input type="checkbox" id="_cbHideNoPhotoPlaces" pairedWith="_cbHidePhotoPlaces">show ones with photos</input><br>'; tHTML += '<input type="checkbox" id="_cbHideLinkedPlaces" pairedWith="_cbHideNoLinkedPlaces">Hide or </input>'; tHTML += '<input type="checkbox" id="_cbHideNoLinkedPlaces" pairedWith="_cbHideLinkedPlaces">show ones with external links</input><br>'; tHTML += '<input type="checkbox" id="_cbHideKeywordPlaces" pairedWith="_cbHideNoKeywordPlaces">Hide or </input>'; tHTML += '<input type="checkbox" id="_cbHideNoKeywordPlaces" pairedWith="_cbHideKeywordPlaces">show ones with a name including</input><br>'; tHTML += '<input type="text" style="font-size:14px; line-height:16px; height:22px; margin-bottom:4px;" id="_textKeywordPlace"><br>'; tHTML += '<br><b>Show Places touched by a specific editor:</b><br>'; tHTML += '<input type="checkbox" id="_cbShowOnlyPlacesCreatedBy">Created by</input> / '; tHTML += '<input type="checkbox" id="_cbShowOnlyPlacesEditedBy">edited by</input><br>'; tHTML += '<input type="text" style="font-size:14px; line-height:16px; height:22px; margin-bottom:4px;" id="_textPlacesEditor"><br>'; tHTML += '<select id="_selectPlacesUserID" style="width:80%; height:22px;"></select><br>'; tHTML += '<br><br><b>Filter Places by category:</b><br>'; var nCategories = W.Config.venues.categories.length; var i; if(uroPlacesGroupsCollapsed.length != nCategories) { for(i=0; i<nCategories; i++) { uroPlacesGroupsCollapsed.push(false); } } for(i=0; i<nCategories; i++) { var parentCategory = W.Config.venues.categories[i]; var localisedName = I18n.lookup("venues.categories." + parentCategory); if(uroPlacesGroupsCollapsed[i] === true) { tHTML += '<i class="fa fa-plus-square-o" style="cursor:pointer;font-size:14px;" id="_uroPlacesGroupState-'+i+'"></i>'; } else { tHTML += '<i class="fa fa-minus-square-o" style="cursor:pointer;font-size:14px;" id="_uroPlacesGroupState-'+i+'"></i>'; } tHTML += ' <input type="checkbox" id="_cbPlacesFilter-'+parentCategory+'"><b>'+localisedName+'</b></input><br>'; tHTML += '<div id="_uroPlacesGroup-'+i+'" style="padding:3px;border-width:2px;border-style:solid;border-color:#FFFFFF">'; for(var ii=0; ii<W.Config.venues.subcategories[parentCategory].length; ii++) { var subCategory = W.Config.venues.subcategories[parentCategory][ii]; localisedName = I18n.lookup("venues.categories." + subCategory); tHTML += ' <input type="checkbox" id="_cbPlacesFilter-'+subCategory+'">'+localisedName+'</input><br>'; } tHTML += '</div>'; } tHTML += '<input type="checkbox" id="_cbFilterPrivatePlaces"><b>Residential Places</b></input><br>'; tHTML += '<br><input type="checkbox" id="_cbInvertPlacesFilter">Invert Place filters?</input>'; uroCtrlPlaces.innerHTML = tHTML; } function uroWazeBits() { // "fake" uroWazeBits() function which only performs layer scan, to stop the uroWazeBits() call in WMETB from // messing around with other stuff in the actual uroWazeBits() function (now renamed uroRealWazeBits...) that // really only ought to be called once. var i; for(i=0;i<W.map.layers.length;i++) { if(W.map.layers[i].CLASS_NAME == 'OpenLayers.Layer.Vector.RootContainer') uroRootContainer = W.map.layers[i].div.id; if(W.map.layers[i].name == 'Node Connections') uroTurnsLayerIdx = i; if(W.map.layers[i].name == 'Map comments') uroMCLayerIdx = i; } uroPlacesRoot = W.map.landmarkLayer.id + '_vroot'; for(i=0;i<W.map.controls.length;i++) { if(W.map.controls[i].CLASS_NAME == 'Waze.View.ArchivePanel') dteControlsIdx = i; else if(W.map.controls[i].CLASS_NAME == 'Waze.Control.Archive') dteControlsIdx = i; if(W.map.controls[i].id !== null) { if(W.map.controls[i].id.indexOf('UpdateRequests') != -1) uroURControlsIdx = i; if(W.map.controls[i].id.indexOf('MapProblems') != -1) uroProblemControlsIdx = i; } } uroAddLog('Turns layer at idx '+uroTurnsLayerIdx); uroAddLog('MC layer at idx '+uroMCLayerIdx); uroAddLog('uroRootContainer = '+uroRootContainer); uroAddLog('Places root layer = '+uroPlacesRoot); } function uroRealWazeBits() { if(document.getElementsByClassName("sandbox").length > 0) { uroAddLog('WME practice mode detected, script is disabled...'); return; } if(document.location.href.indexOf('user') !== -1) { uroAddLog('User profile page detected, script is disabled...'); return; } uroAddLog('adding WazeBits...'+uroToHex(uroWazeBitsPresent,4)); if((uroWazeBitsPresent & 0x0001) === 0) { if(typeof W != "undefined") { if(typeof W.map != "undefined") { uroAddLog(' W.map OK'); uroWazeBitsPresent |= 0x0001; } } } if((uroWazeBitsPresent & 0x0002) === 0) { if(typeof W != "undefined") { if(typeof W.model != "undefined") { uroAddLog(' W.model OK'); uroWazeBitsPresent |= 0x0002; } } } if((uroWazeBitsPresent & 0x0004) === 0) { if(typeof W != "undefined") { if(typeof W.loginManager != "undefined") { uroAddLog(' loginManager OK'); uroWazeBitsPresent |= 0x0004; } } } if((uroWazeBitsPresent & 0x0008) === 0) { if(typeof W != "undefined") { if(typeof W.selectionManager != "undefined") { uroAddLog(' selectionManager OK'); uroWazeBitsPresent |= 0x0008; } } } if((uroWazeBitsPresent & 0x0010) === 0) { if(typeof OpenLayers != "undefined") { uroAddLog(' OpenLayers OK'); uroWazeBitsPresent |= 0x0010; } } if((uroWazeBitsPresent & 0x0020) === 0) { if(typeof Waze != "undefined") { uroAddLog(' Waze OK'); uroWazeBitsPresent |= 0x0020; } } if((uroWazeBitsPresent & 0x0040) === 0) { if(document.getElementById('user-tabs') !== null) { uroUserTabId = 'user-tabs'; uroAddLog(' user-tabs OK'); uroWazeBitsPresent |= 0x0040; } } if((uroWazeBitsPresent & 0x0080) === 0) { if(document.getElementById('sidepanel-drives') !== null) { uroAddLog(' sidepanel-drives OK'); uroWazeBitsPresent |= 0x0080; } } if((uroWazeBitsPresent & 0x0100) === 0) { if(typeof I18n != "undefined") { uroAddLog(' I18n OK'); uroWazeBitsPresent |= 0x0100; } } if(uroWazeBitsPresent !== 0x01FF) { setTimeout(uroRealWazeBits,250); } else if(W.loginManager.isLoggedIn() === false) { uroAddLog('Waiting for user log-in...'); setTimeout(uroRealWazeBits,1000); } else { uroAddLog('All WazeBits present and correct...'); W.app.modeController.model.bind("change:mode",uroInitialise); if(W.app.modeController.mode.mteModeState !== undefined) { uroMTEMode = true; uroSetupListeners = true; uroFinalisingListenerSetup = false; uroHidePopup(); uroAddLog('MTE mode, sleeping until normal service is resumed...'); return; } uroMTEMode = false; uroSetupUI(); uroDOMHasTurnProblems = (W.model.turnProblems != null); uroGetProblemTypes(); uroPopulateProblemsTab(); uroPopulatePlacesTab(); uroControls.appendChild(uroCtrlURs); uroControls.appendChild(uroCtrlMPs); uroControls.appendChild(uroCtrlPlaces); uroControls.appendChild(uroCtrlCameras); uroControls.appendChild(uroOWL); uroControls.appendChild(uroCtrlMisc); uroControls.appendChild(uroCtrlHides); uroControls.appendChild(uroAMList); uroCtrlURs.onclick = uroFilterItems_URTabClick; uroCtrlMPs.onclick = uroFilterItems_MPTabClick; uroCtrlPlaces.onclick = uroFilterItems_PlacesTabClick; uroCtrlCameras.onclick = uroFilterItems_CamerasTabClick; uroCtrlMisc.onclick = uroFilterItems_MiscTabClick; uroWazeBits(); uroDiv.addEventListener("mouseover", uroEnterPopup, false); uroDiv.addEventListener("mouseout", uroExitPopup, false); if(sessionStorage.UROverview_FID_IgnoreList === undefined) sessionStorage.UROverview_FID_IgnoreList = ''; if(sessionStorage.UROverview_FID_WatchList === undefined) sessionStorage.UROverview_FID_WatchList = ''; if(uroConfirmIntercepted === false) uroAddInterceptor(); setInterval(uroTenthSecondTick,100); } } function uroAddInterceptor() { uroAddLog('Adding interceptor function...'); // add interceptor function for confirm(), so that we can auto-select the "OK" option when solving URs // which have pending question... var _confirm = window.confirm; window.confirm = function(msg) { var cm_delete_confirm = I18n.lookup("closures.delete_confirm").split('"')[0].trimRight(1); if((I18n.lookup("update_requests.panel.confirm") == msg) && (uroGetCBChecked('_cbDisablePendingQuestions') === true)) { uroAddLog('Intercepted pending comments confirmation...'); return true; } else if(msg.indexOf(cm_delete_confirm) != -1) { uroAddLog('intercepted closure delete confirmation...'); if(uroConfirmClosureDelete) { return _confirm(msg); } else { return true; } } else if(typeof(msg) == 'undefined') { uroAddLog('Intercepted blank confirmation...'); return true; } else { return _confirm(msg); } }; uroConfirmIntercepted = true; } function uroEnterPopup() { uroMouseInPopup = true; } function uroExitPopup() { uroMouseInPopup = false; } function uroToggleDebug() { uroShowDebugOutput = !uroShowDebugOutput; var dbgMode = "none"; if(uroShowDebugOutput) { dbgMode = "inline"; } document.getElementById('_uroDebugMode').style.display = dbgMode; } function uroInitialise() { uroInitialised = false; if(document.URL.indexOf('beta') != -1) uroBetaEditor = true; var urlBits = document.URL.split("&mapUpdateRequest="); if(urlBits.length == 2) { uroURIDInURL = parseInt(urlBits[1].split('&')[0]); uroAddLog('found UR ID '+uroURIDInURL+' in URL'); } uroRealWazeBits(); } function uroSetupUI() { // create a new div to display the UR details floaty-box uroDiv = document.createElement('div'); uroDiv.id = "uroDiv"; uroDiv.style.position = 'absolute'; uroDiv.style.visibility = 'hidden'; uroDiv.style.top = '0'; uroDiv.style.left = '0'; uroDiv.style.zIndex = 100; uroDiv.style.backgroundColor = 'aliceblue'; uroDiv.style.borderWidth = '3px'; uroDiv.style.borderStyle = 'solid'; uroDiv.style.borderRadius = '10px'; uroDiv.style.boxShadow = '5px 5px 10px Silver'; uroDiv.style.padding = '4px'; document.body.appendChild(uroDiv); // create a new div to display script alerts uroAlerts = document.createElement('div'); uroAlerts.id = "uroAlerts"; uroAlerts.style.position = 'fixed'; uroAlerts.style.visibility = 'hidden'; uroAlerts.style.top = '50%'; uroAlerts.style.left = '50%'; uroAlerts.style.zIndex = 100; uroAlerts.style.backgroundColor = 'aliceblue'; uroAlerts.style.borderWidth = '3px'; uroAlerts.style.borderStyle = 'solid'; uroAlerts.style.borderRadius = '10px'; uroAlerts.style.boxShadow = '5px 5px 10px Silver'; uroAlerts.style.padding = '4px'; uroAlerts.style.webkitTransform = "translate(-50%, -50%)"; uroAlerts.style.transform = "translate(-50%, -50%)"; var alertsHTML = '<div id="header" style="padding: 4px; background-color:LightGreen; font-weight: bold;">Alert title goes here...</div>'; alertsHTML += '<div id="content" style="padding: 4px; background-color:White">Alert content goes here...</div>'; alertsHTML += '<div id="controls" style="padding: 4px;">'; alertsHTML += '<span id="uroAlertTickBtn" style="cursor:pointer;font-size:14px;border:thin outset black;padding:2px;">'; alertsHTML += '<i class="fa fa-check"> </i>'; alertsHTML += '<span id="uroAlertTickBtnCaption" style="font-weight: bold;"></span>'; alertsHTML += '</span>'; alertsHTML += ' '; alertsHTML += '<span id="uroAlertCrossBtn" style="cursor:pointer;font-size:14px;border:thin outset black;padding:2px;">'; alertsHTML += '<i class="fa fa-times"> </i>'; alertsHTML += '<span id="uroAlertCrossBtnCaption" style="font-weight: bold;"></span>'; alertsHTML += '</span>'; alertsHTML += '</div>'; uroAlerts.innerHTML = alertsHTML; document.body.appendChild(uroAlerts); uroControls = document.createElement('section'); uroControls.style.fontSize = '12px'; uroControls.id = 'uroControls'; var updateURL; if(navigator.userAgent.indexOf('Chrome') == -1) { updateURL = 'https://greasyfork.org/scripts/1952-uroverview-plus-uro'; } else { updateURL = 'https://chrome.google.com/webstore/detail/uroverview/amdamgkgchnbaopmphhjapmjcdghdphi'; } var tabbyHTML = '<b><a href="'+updateURL+'" target="_blank">UROverview Plus</a></b> <label id="_uroVersion">'+uroVersion+'</label>'; tabbyHTML += '<label id="_uroDebugMode">(dbg)</label>'; tabbyHTML += ' <input type="checkbox" id="_cbMasterEnable" checked>Enabled</input>'; tabbyHTML += '<p><table border=0 width="100%"><tr>'; tabbyHTML += '<td valign="center" align="center" id="_tabSelectUserRequests"><a href="#" id="_linkSelectUserRequests" style="text-decoration:none;font-size:12px">URs</a></td>'; tabbyHTML += '<td valign="center" align="center" id="_tabSelectMapProblems"><a href="#" id="_linkSelectMapProblems" style="text-decoration:none;font-size:12px">MPs</a></td>'; tabbyHTML += '<td valign="center" align="center" id="_tabSelectPlaces"><a href="#" id="_linkSelectPlaces" style="text-decoration:none;font-size:12px">Places</a></td>'; tabbyHTML += '<td valign="center" align="center" id="_tabSelectCameras"><a href="#" id="_linkSelectCameras" style="text-decoration:none;font-size:12px">Cams</a></td>'; tabbyHTML += '<td valign="center" align="center" id="_tabSelectCWL"><a href="#" id="_linkSelectOWL" style="text-decoration:none;font-size:12px">OWL</a></td>'; tabbyHTML += '<td valign="center" align="center" id="_tabSelectMisc"><a href="#" id="_linkSelectMisc" style="text-decoration:none;font-size:12px">Misc</a></td>'; tabbyHTML += '</tr></table>'; uroControls.innerHTML = tabbyHTML; uroCtrlURs = document.createElement('p'); uroCtrlMPs = document.createElement('p'); uroCtrlCameras = document.createElement('p'); uroOWL = document.createElement('p'); uroCtrlMisc = document.createElement('p'); uroAMList = document.createElement('div'); uroCtrlHides = document.createElement('div'); uroCtrlPlaces = document.createElement('p'); // UR controls tab uroCtrlURs.id = "uroCtrlURs"; uroCtrlURs.innerHTML = '<br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbURFilterOutsideArea">Hide URs outside my editable area</input><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbNoFilterForURInURL">Don\'t filter UR in URL</input><br><br>'; uroCtrlURs.innerHTML += '<b>Filter by type:</b><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterWazeAuto">Waze Automatic</input><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterIncorrectTurn">Incorrect turn</input><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterIncorrectAddress">Incorrect address</input><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterIncorrectRoute">Incorrect route</input><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterMissingRoundabout">Missing roundabout</input><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterGeneralError">General error</input><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterTurnNotAllowed">Turn not allowed</input><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterIncorrectJunction">Incorrect junction</input><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterMissingBridgeOverpass">Missing bridge overpass</input><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterWrongDrivingDirection">Wrong driving direction</input><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterMissingExit">Missing exit</input><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterMissingRoad">Missing road</input><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterBlockedRoad">Blocked road</input><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterMissingLandmark">Missing Landmark</input><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterSpeedLimits">Missing or Invalid Speed limit</input><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterUndefined">Undefined</input><br>'; uroCtrlURs.innerHTML += ' <i>Specially tagged types</i><br>'; uroCtrlURs.innerHTML += ' <input type="checkbox" id="_cbFilterRoadworks">[ROADWORKS]</input><br>'; uroCtrlURs.innerHTML += ' <input type="checkbox" id="_cbFilterConstruction">[CONSTRUCTION]</input><br>'; uroCtrlURs.innerHTML += ' <input type="checkbox" id="_cbFilterClosure">[CLOSURE]</input><br>'; uroCtrlURs.innerHTML += ' <input type="checkbox" id="_cbFilterEvent">[EVENT]</input><br>'; uroCtrlURs.innerHTML += ' <input type="checkbox" id="_cbFilterNote">[NOTE]</input><br>'; uroCtrlURs.innerHTML += ' <input type="checkbox" id="_cbFilterBOG">[BOG]</input><br>'; uroCtrlURs.innerHTML += ' <input type="checkbox" id="_cbFilterDifficult">[DIFFICULT]</input><br>'; uroCtrlURs.innerHTML += ' <input type="checkbox" id="_cbFilterWSLM">[WSLM]</input><br><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbInvertURFilter">Invert operation of type filters?</input><br>'; uroCtrlURs.innerHTML += '<hr>'; uroCtrlURs.innerHTML += '<br><b>Hide by state:</b><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterOpenUR">Open</input><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterClosedUR">Closed</input><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterSolved">Solved</input><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbFilterUnidentified">Not identified</input><br><br>'; uroCtrlURs.innerHTML += '<br><b>Filter by age of submission:</b><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableMinAgeFilter">Hide URs less than </input>'; uroCtrlURs.innerHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputFilterMinDays"> days old<br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableMaxAgeFilter">Hide URs more than </input>'; uroCtrlURs.innerHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputFilterMaxDays"> days old<br>'; uroCtrlURs.innerHTML += '<br><b>Filter by description/comments/following:</b><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideMyFollowed" pairedWith="_cbHideMyUnfollowed">Ones I am or </input>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideMyUnfollowed" pairedWith="_cbHideMyFollowed">am not following</input><br><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbURDescriptionMustBePresent" pairedWith="_cbURDescriptionMustBeAbsent">Hide</input> or '; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbURDescriptionMustBeAbsent" pairedWith="_cbURDescriptionMustBePresent">show</input> URs with no description<br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableKeywordMustBePresent">Hide URs not including </input>'; uroCtrlURs.innerHTML += '<input type="text" style="font-size:14px; line-height:16px; height:22px; margin-bottom:4px;" id="_textKeywordPresent"><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableKeywordMustBeAbsent">Hide URs including </input>'; uroCtrlURs.innerHTML += '<input type="text" style="font-size:14px; line-height:16px; height:22px; margin-bottom:4px;" id="_textKeywordAbsent"><br>'; uroCtrlURs.innerHTML += ' <input type="checkbox" id="_cbCaseInsensitive"><i>Case-insensitive matches?</i></input><br><br>'; uroCtrlURs.innerHTML += 'With comments from me?<br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideMyComments" pairedWith="_cbHideAnyComments">Yes </input>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideAnyComments" pairedWith="_cbHideMyComments">No</input><br>'; uroCtrlURs.innerHTML += 'If last comment made by me?<br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideIfLastCommenter" pairedWith="_cbHideIfNotLastCommenter">Yes </input>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideIfNotLastCommenter" pairedWith="_cbHideIfLastCommenter">No </input><br>'; uroCtrlURs.innerHTML += 'If last comment made by UR reporter?<br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideIfReporterLastCommenter" pairedWith="_cbHideIfReporterNotLastCommenter">Yes </input>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbHideIfReporterNotLastCommenter" pairedWith="_cbHideIfReporterLastCommenter">No</input><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableMinCommentsFilter">With less than </input>'; uroCtrlURs.innerHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputFilterMinComments"> comments<br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableMaxCommentsFilter">With more than </input>'; uroCtrlURs.innerHTML += '<input type="number" min="0" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputFilterMaxComments"> comments<br><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableCommentAgeFilter2">Last comment less than </input>'; uroCtrlURs.innerHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputFilterCommentDays2"> days ago<br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbEnableCommentAgeFilter">Last comment more than </input>'; uroCtrlURs.innerHTML += '<input type="number" min="1" size="3" style="width:50px;line-height:14px;height:22px;margin-bottom:4px;" id="_inputFilterCommentDays"> days ago<br>'; uroCtrlURs.innerHTML += ' <input type="checkbox" id="_cbIgnoreOtherEditorComments"><i>Ignore other editor comments?</i></input><br><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbURUserIDFilter">Without comments from user</input>'; uroCtrlURs.innerHTML += '<select id="_selectURUserID" style="width:80%; height:22px;"></select><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbURResolverIDFilter">Not resolved by user</input>'; uroCtrlURs.innerHTML += '<select id="_selectURResolverID" style="width:80%; height:22px;"></select>'; uroCtrlURs.innerHTML += '<br><br><input type="checkbox" id="_cbInvertURStateFilter">Invert operation of state/age filters?</input><br>'; uroCtrlURs.innerHTML += '<input type="checkbox" id="_cbNoFilterForTaggedURs">Don\'t apply state/age filters to tagged URs</input><br>'; // Map problems controls tab uroCtrlMPs.id = "uroCtrlMPs"; uroCtrlMPs.innerHTML = 'MP filter list being populated, please wait...'; // Places filtering tab uroCtrlPlaces.id = "uroCtrlPlaces"; uroCtrlPlaces.innerHTML = 'Places filter list being populated, please wait...'; // Camera controls tab uroCtrlCameras.id = "uroCtrlCameras"; uroCtrlCameras.innerHTML = '<br><b>Show Cameras created by:</b><br>'; uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowWorldCams" checked>world_* users</input><br>'; uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowUSACams" checked>usa_* users</input><br>'; uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowNonWorldCams" checked>other users</input><br>'; uroCtrlCameras.innerHTML += '<br><b>Show Cameras touched by a specific editor:</b><br>'; uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowOnlyCamsCreatedBy">Created by</input> / '; uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowOnlyCamsEditedBy">edited by</input><br>'; uroCtrlCameras.innerHTML += '<input type="text" style="font-size:14px; line-height:16px; height:22px; margin-bottom:4px;" id="_textCameraEditor"><br>'; uroCtrlCameras.innerHTML += '<select id="_selectCameraUserID" style="width:80%; height:22px;"></select><br>'; uroCtrlCameras.innerHTML += '<br><input type="checkbox" id="_cbShowOnlyMyCams">Show ONLY cameras created/edited by me</input><br>'; uroCtrlCameras.innerHTML += '<br><b>Show Cameras by approval status:</b><br>'; uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowApprovedCams" checked>approved</input><br>'; uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowNonApprovedCams" checked>non-approved</input><br>'; uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbShowOlderCreatedNonApproved"> if created more than </input>'; uroCtrlCameras.innerHTML += '<input type="number" min="1" size="3" style="width:50px;;line-height:14px;height:22px;margin-bottom:4px;" id="_inputCameraMinCreatedDays"> days ago<br>'; uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbShowOlderUpdatedNonApproved"> if updated more than </input>'; uroCtrlCameras.innerHTML += '<input type="number" min="1" size="3" style="width:50px;;line-height:14px;height:22px;margin-bottom:4px;" id="_inputCameraMinUpdatedDays"> days ago<br>'; uroCtrlCameras.innerHTML += '<br><b>Show Cameras by type:</b><br>'; uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowSpeedCams" checked>Speed</input><br>'; uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbShowIfSpeedSet" checked> with speed data</input><br>'; uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbShowIfNoSpeedSet" checked> with no speed data</input><br>'; uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowRedLightCams" checked>Red Light</input><br>'; uroCtrlCameras.innerHTML += '<input type="checkbox" id="_cbShowDummyCams" checked>Dummy</input><br>'; uroCtrlCameras.innerHTML += '<br><b>Hide Cameras by creator:</b><br>'; uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbHideCreatedByMe">me</input>'; uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbHideCreatedByRank0">L1</input>'; uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbHideCreatedByRank1">L2</input>'; uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbHideCreatedByRank2">L3</input>'; uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbHideCreatedByRank3">L4</input>'; uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbHideCreatedByRank4">L5</input>'; uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbHideCreatedByRank5">L6</input>'; uroCtrlCameras.innerHTML += '<br><b>Hide Cameras by updater:</b><br>'; uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbHideUpdatedByMe">me</input>'; uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbHideUpdatedByRank0">L1</input>'; uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbHideUpdatedByRank1">L2</input>'; uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbHideUpdatedByRank2">L3</input>'; uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbHideUpdatedByRank3">L4</input>'; uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbHideUpdatedByRank4">L5</input>'; uroCtrlCameras.innerHTML += ' <input type="checkbox" id="_cbHideUpdatedByRank5">L6</input>'; uroCtrlCameras.innerHTML += '<br><br><b><input type="checkbox" id="_cbHideCWLCams">Hide cameras on watchlist</input></b><br>'; // Object watchlist tab uroOWL.id = "uroOWL"; uroCWLGroups = []; uroOWLUpdateHTML(); // Misc controls tab uroCtrlMisc.id = "uroCtrlMisc"; uroCtrlMisc.innerHTML = '<br><b>Use default conversation markers:</b><br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbNativeConvoMarkers" checked />in public WME<br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbNativeBetaConvoMarkers" checked />in beta WME<br>'; uroCtrlMisc.innerHTML += '<br><br><b><input type="checkbox" id="_cbCommentCount" />Show comment count on UR markers</b><br>'; uroCtrlMisc.innerHTML += '<br><br><b><input type="checkbox" id="_cbURBackfill" />Backfill UR data</b><br>'; uroCtrlMisc.innerHTML += '<br><br><b>Marker Unstacking:</b><br>'; uroCtrlMisc.innerHTML += 'Distance threshold: <input type="number" min="1" max="30" value="15" size="2" style="width:50px;;line-height:14px;height:22px;margin-bottom:4px;" id="_inputUnstackSensitivity" /><br>'; uroCtrlMisc.innerHTML += 'Disable below zoom: <input type="number" min="0" max="10" value="3" size="2" style="width:50px;;line-height:14px;height:22px;margin-bottom:4px;" id="_inputUnstackZoomLevel" /><br>'; uroCtrlMisc.innerHTML += '<br><br><b>Use custom marker for URs tagged as:</b><br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomRoadworksMarkers" />[ROADWORKS]<br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomConstructionMarkers" />[CONSTRUCTION]<br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomClosuresMarkers" />[CLOSURE]<br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomEventsMarkers" />[EVENT]<br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomNotesMarkers" />[NOTE]<br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomBOGMarkers" />[BOG]<br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomDifficultMarkers" />[DIFFICULT]<br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomWSLMMarkers" />[WSLM]<br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomNativeSLMarkers" />Native speed limit reports<br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomKeywordMarkers" />'; uroCtrlMisc.innerHTML += '<input type="text" style="font-size:14px; line-height:16px; height:22px; margin-bottom:4px;" id="_textCustomKeyword" /><br>'; uroCtrlMisc.innerHTML += '<br><br><b>Use custom marker for MPs tagged as:</b><br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomElginMarkers" />[Elgin]<br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomTrafficMasterMarkers" />[TM]<br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomTrafficCastMarkers" />[TrafficCast]<br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomCaltransMarkers" />[Caltrans]<br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbCustomTFLMarkers" />[TfL Open Data]<br>'; uroCtrlMisc.innerHTML += '<br><br><b>Popup mouse behaviour:</b><br>'; uroCtrlMisc.innerHTML += 'Mouse idle <input type="number" min="1" max="10" value="2" size="2" style="width:50px;;line-height:14px;height:22px;margin-bottom:4px;" id="_inputPopupDwellTimeout" /> *100ms<br>'; uroCtrlMisc.innerHTML += 'Mouse over <input type="number" min="1" max="10" value="2" size="2" style="width:50px;;line-height:14px;height:22px;margin-bottom:4px;" id="_inputPopupEntryTimeout" /> *100ms<br>'; uroCtrlMisc.innerHTML += 'Distance <input type="number" min="0" max="10" value="2" size="2" style="width:50px;;line-height:14px;height:22px;margin-bottom:4px;" id="_inputMaxJitter" /> pixels<br>'; uroCtrlMisc.innerHTML += '<br><br><b>Disable popup for:</b><br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitURPopup" />URs<br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitMPPopup" />MPs<br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitCamPopup" />Cameras<br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitSegPopup" />Segments<br>'; uroCtrlMisc.innerHTML += ' <input type="checkbox" id="_cbInhibitSegGenericPopup" />Speed limit info<br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitTurnsPopup" />Restricted Turns<br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitLandmarkPopup" />Places<br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitPUPopup" />Place Updates<br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitMapCommentPopup" />Map Comments<br>'; uroCtrlMisc.innerHTML += '<br><br><b>Date/Time formatting for popups:</b><br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbDateFmtDDMMYY" pairedWith="_cbDateFmtMMDDYY,_cbDateFmtYYMMDD" checked />day/month/year<br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbDateFmtMMDDYY" pairedWith="_cbDateFmtDDMMYY,_cbDateFmtYYMMDD" />month/day/year<br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbDateFmtYYMMDD" pairedWith="_cbDateFmtMMDDYY,_cbDateFmtDDMMYY" />year/month/day<br><br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbTimeFmt24H" pairedWith="_cbTimeFmt12H" checked />24 hour<br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbTimeFmt12H" pairedWith="_cbTimeFmt24H" />12 hour<br><br>'; uroCtrlMisc.innerHTML += '<i>Unticked uses browser default setting</i>'; uroCtrlMisc.innerHTML += '<br><br><b><input type="checkbox" id="_cbWhiteBackground" />Use custom background colour</b><br>'; uroCtrlMisc.innerHTML += 'R:<input type="number" min="0" max="255" value="255" size="3" style="width:50px;;line-height:14px;height:22px;margin-bottom:4px;" id="_inputCustomBackgroundRed" />'; uroCtrlMisc.innerHTML += 'G:<input type="number" min="0" max="255" value="255" size="3" style="width:50px;;line-height:14px;height:22px;margin-bottom:4px;" id="_inputCustomBackgroundGreen" />'; uroCtrlMisc.innerHTML += 'B:<input type="number" min="0" max="255" value="255" size="3" style="width:50px;;line-height:14px;height:22px;margin-bottom:4px;" id="_inputCustomBackgroundBlue" /><br>'; uroCtrlMisc.innerHTML += '<br><br><b>Replace "Next ..." button with "Done" for:</b><br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitNURButton" />URs<br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitNMPButton" />MPs<br>'; uroCtrlMisc.innerHTML += '<input type="checkbox" id="_cbInhibitNPURButton" />PURs<br>'; uroCtrlMisc.innerHTML += '<br><br><b><input type="checkbox" id="_cbHideAMLayer" />Hide Area Manager polygons</b><br>'; uroCtrlMisc.innerHTML += '<b><input type="checkbox" id="_cbDisablePlacesFiltering" />Disable Places filtering</b><br>'; ////uroCtrlMisc.innerHTML += '<b><input type="checkbox" id="_cbDisablePendingQuestions">Disable UR Pending Questions confirmation</input></b><br>'; uroCtrlMisc.innerHTML += '<b><input type="checkbox" id="_cbDisableTabStyling" />Use default tab styling</b><br>'; uroCtrlMisc.innerHTML += '<b><input type="checkbox" id="_cbHideEditorInfo" />Hide sidebar editor info</b><br>'; uroCtrlMisc.innerHTML += '<b><input type="checkbox" id="_cbEnableDTE" />Drive Tab Enhancement (DTE)</b><br>'; uroCtrlMisc.innerHTML += '<br><br><b>Settings backup/restore/reset:</b><br>'; uroCtrlMisc.innerHTML += '<input type="button" id="_btnSettingsToText" value="Backup" /> '; uroCtrlMisc.innerHTML += '<input type="button" id="_btnTextToSettings" value="Restore" /> | '; uroCtrlMisc.innerHTML += '<input type="button" id="_btnResetSettings" value="Reset" /><br><br>'; uroCtrlMisc.innerHTML += '<textarea id="_txtSettings" value="" /><br>'; uroCtrlMisc.innerHTML += '<input type="button" id="_btnClearSettingsText" value="Clear" /><br>'; /* uroCtrlMisc.innerHTML += '<br><br><b>Debug:</b><br>'; uroCtrlMisc.innerHTML += '<input type="button" id="_btnDebugToScreen" value="Show debug data" />'; */ // footer for tabs container uroCtrlHides.id = 'uroCtrlHides'; uroCtrlHides.innerHTML = '<input type="button" id="_btnUndoLastHide" value="Undo last hide" /> '; uroCtrlHides.innerHTML += '<input type="button" id="_btnClearSessionHides" value="Undo all hides" /><p>'; // footer for AM list uroAMList.id = 'uroAMList'; window.addEventListener("beforeunload", uroSaveSettings, false); //uroRealWazeBits(); } function dteAddHeader() { if(uroMTEMode) return; if(!uroInitialised) return; var rlcObj = document.getElementsByClassName("result-list-container"); if(typeof rlcObj == "undefined") return; if(typeof rlcObj[0].children[0] == "undefined") return; if(typeof rlcObj[0].children[0].innerHTML == "undefined") return; var thtml = rlcObj[0].children[0].innerHTML; if(thtml.indexOf('Full drive history') == -1) { thtml += '<br><br><i><small>Full drive history goes back to '+dteOldestFullDrive.toDateString()+'</small></i>'; rlcObj[0].children[0].innerHTML = thtml; } } function dteGetData() { var loc = 'https://'+window.location.hostname+Waze.Config.api_base+'/Archive/MyList?minDistance=1000'; loc += '&offset='+dteOffset+'&count=5'; var dteReq = new XMLHttpRequest(); dteReq.onreadystatechange = function() { var foundMissingDrive = false; if(dteReq.readyState == 4) { uroAddLog('drive data request, response '+dteReq.status+' received'); if(dteReq.status == 200) { if(dteReq.responseText !== "") { var drives = JSON.parse(dteReq.responseText); var loadedDrives = drives.archives.objects.length; uroAddLog('received '+loadedDrives+' drives'); if(loadedDrives != 5) foundMissingDrive = true; for(var loop=0; loop < loadedDrives; loop++) { if(drives.archives.objects[loop].hasFullSession === false) { foundMissingDrive = true; } else { dteOffset++; dteOldestFullDrive = new Date(drives.archives.objects[loop].startTime); } } } else { foundMissingDrive = true; } } if(foundMissingDrive === false) { dteGetData(); } else { uroAddLog(dteOffset+' full drives in history'); uroAddLog('oldest drives are on '+dteOldestFullDrive.toDateString()); if(dteOffset < 5) { dteOffset = 5; uroAddLog('insufficient full drives, using standard drives tab'); } else if(dteOffset > 50) { var nPages = Math.ceil(dteOffset / 50); uroAddLog('too many full drives for a single tab page, splitting over '+nPages+' pages...'); dteOffset = Math.ceil(dteOffset/nPages); } if((dteOldestFullDrive - dteEpoch) > 0) { var totalDrives = 0; if(W.model.archives.additionalInfo !== null) { totalDrives = W.model.archives.additionalInfo.totalSessions; } if(totalDrives !== null) { uroAddLog('updating drives tab...'); W.map.controls[dteControlsIdx].sidePanelView.ResultsPerPage = dteOffset; uroAddLog(totalDrives+' drives in history'); W.map.controls[dteControlsIdx].sidePanelView.setSessions(totalDrives); W.map.controls[dteControlsIdx].loadSessions(0); } setInterval(dteAddHeader,250); setInterval(dteCheckDriveListChanges,250); } } } }; dteReq.open('GET',loc,true); dteReq.send(); } function dteSetNewTabLength() { uroAddLog('altering ResultsPerPage parameter...'); var t = document.getElementById('sidepanel-drives'); t.style.overflow = 'auto'; t.style.height = (window.innerHeight * 0.6) + 'px'; dteOffset = 0; dteGetData(); } function dteListClick() { dteClearListHighlight(); this.style.backgroundColor = "lightgreen"; dteArmClearHighlightsOnPanelClose = true; } function dteClearListHighlight() { var drivesShown = document.getElementById('sidepanel-drives').getElementsByClassName('result session').length; if(drivesShown > 0) { for(var loop = 0;loop < drivesShown; loop++) { var listEntry = document.getElementById('sidepanel-drives').getElementsByClassName('result session')[loop]; listEntry.style.backgroundColor = ""; } } } function dteCheckDriveListChanges() { if(uroMTEMode) return; if(!uroInitialised) return; var drivesShown = document.getElementById('sidepanel-drives').getElementsByClassName('result session').length; if(drivesShown > 0) { var topID = document.getElementById('sidepanel-drives').getElementsByClassName('result session')[0].getAttribute('data-id'); if(topID != dteTopID) { dteTopID = topID; for(var loop = 0;loop < drivesShown; loop++) { var listEntry = document.getElementById('sidepanel-drives').getElementsByClassName('result session')[loop]; var driveID = listEntry.getAttribute('data-id'); var driveObj = W.model.archives.objects[driveID]; var driveSecs = Math.floor((driveObj.endTime - driveObj.startTime) / 1000); var driveHours = Math.floor(driveSecs / 3600); driveSecs -= (driveHours * 3600); var driveMins = Math.floor(driveSecs / 60); driveSecs -= (driveMins * 60); var trueTime = (driveHours+':'+("0"+driveMins).slice(-2)+'.'+("0"+driveSecs).slice(-2)); listEntry.getElementsByTagName('span')[1].innerHTML = trueTime; listEntry.addEventListener("click", dteListClick, false); } } } } uroInitialise();