CINXE.COM

Look Up Service Requests  · NYC311

<!DOCTYPE html> <html lang="en-US" data-lang="en-US" crm-lang="en-US" dir="ltr" crm-lcid="1033" same-site-mode="None"> <head> <meta charset="utf-8" /><meta name="viewport" content="width=device-width,&#32;initial-scale=1.0" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /> <script type="text/javascript" > </script> <title> Look Up Service Requests &nbsp;· NYC311 </title> <script src="/_portal/d78574f9-20c3-4dcc-8d8d-85cf5b7ac141/Resources/ResourceManager?lang=en-US"></script> <script type="text/javascript"> // Refresh all powerBI Iframes on Login in one Iframe window.addEventListener('message', function (event) { if (event && event.data && event.data == 'refreshPowerBI') { $("iframe.powerbi").each(function () { this.src = this.src; }); } }); // Fix for incorrect viewport width setting in IE 10 on Windows Phone 8. if (navigator.userAgent.match(/IEMobile\/10\.0/)) { var msViewportStyle = document.createElement("style"); msViewportStyle.appendChild(document.createTextNode("@-ms-viewport{width:auto!important}")); document.getElementsByTagName("head")[0].appendChild(msViewportStyle); } </script> <link href="/bootstrap.min.css?1560906719000" rel="stylesheet" /> <link href="https://content.powerapps.com/resource/powerappsportal/dist/font-awesome.bundle-3d8a58a48f.css" onerror="javascript:&#32;var&#32;target&#32;=&#32;event.target;&#32;var&#32;link&#32;=&#32;document.createElement(&#39;link&#39;);&#32;link.crossOrigin&#32;=&#32;target.crossOrigin;&#32;link.href&#32;=&#32;&#39;/dist/font-awesome.bundle-3d8a58a48f.css&#39;;&#32;link.rel&#32;=&#32;&#39;stylesheet&#39;;&#32;target.insertAdjacentElement(&#39;afterend&#39;,link);" rel="stylesheet" /> <link href="https://content.powerapps.com/resource/powerappsportal/dist/preform.bundle-dd7b48484e.css" onerror="javascript:&#32;var&#32;target&#32;=&#32;event.target;&#32;var&#32;link&#32;=&#32;document.createElement(&#39;link&#39;);&#32;link.crossOrigin&#32;=&#32;target.crossOrigin;&#32;link.href&#32;=&#32;&#39;/dist/preform.bundle-dd7b48484e.css&#39;;&#32;link.rel&#32;=&#32;&#39;stylesheet&#39;;&#32;target.insertAdjacentElement(&#39;afterend&#39;,link);" rel="stylesheet" /> <link href="/v4-shims.min.css?1682007276000" rel="stylesheet" /> <link href="/311header-and-footer-v2.css?1682007274000" rel="stylesheet" /> <link href="/about-311.css?1674759502000" rel="stylesheet" /> <link href="/jquery-ui.min-custom.css?1560906718000" rel="stylesheet" /> <link href="/jquery-ui.css?1560906719000" rel="stylesheet" /> <link href="/theme.css?1664478696000" rel="stylesheet" /> <link href="/site.min.css?1614288238000" rel="stylesheet" /> <link href="/module.css?1560906717000" rel="stylesheet" /> <link href="/nyc311headerfooter.css?1560906712000" rel="stylesheet" /> <link href="https://content.powerapps.com/resource/powerappsportal/dist/pwa-style.bundle-2739c60227.css" onerror="javascript:&#32;var&#32;target&#32;=&#32;event.target;&#32;var&#32;link&#32;=&#32;document.createElement(&#39;link&#39;);&#32;link.crossOrigin&#32;=&#32;target.crossOrigin;&#32;link.href&#32;=&#32;&#39;/dist/pwa-style.bundle-2739c60227.css&#39;;&#32;link.rel&#32;=&#32;&#39;stylesheet&#39;;&#32;target.insertAdjacentElement(&#39;afterend&#39;,link);" rel="stylesheet" /> </head> <body data-sitemap-state="/check-status/:/" data-dateformat="M/d/yyyy" data-timeformat="h:mm tt" data-datetimeformat="M/d/yyyy h:mm tt" data-app-path="/" data-ckeditor-basepath="/js/BaseHtmlContentDesigner/Libs/msdyncrm_/libs/ckeditor/" data-case-deflection-url="/_services/search/d78574f9-20c3-4dcc-8d8d-85cf5b7ac141"> <link href="https://content.powerapps.com/resource/powerappsportal/dist/pcf-style.bundle-2659c6f064.css" onerror="javascript:&#32;var&#32;target&#32;=&#32;event.target;&#32;var&#32;link&#32;=&#32;document.createElement(&#39;link&#39;);&#32;link.crossOrigin&#32;=&#32;target.crossOrigin;&#32;link.href&#32;=&#32;&#39;/dist/pcf-style.bundle-2659c6f064.css&#39;;&#32;link.rel&#32;=&#32;&#39;stylesheet&#39;;&#32;target.insertAdjacentElement(&#39;afterend&#39;,link);" rel="stylesheet" /> <div id="offlineNotificationBar" style="display: none;"> <img alt="web" id="web" onerror="javascript:&#32;var&#32;target&#32;=&#32;event.target;&#32;var&#32;img&#32;=&#32;document.createElement(&#39;img&#39;);&#32;img.src&#32;=&#32;&#39;/css/images/web.png&#39;;&#32;img.alt&#32;=&#32;&#39;web&#39;;&#32;img.id&#32;=&#32;&#39;web&#39;&#32;;&#32;target.insertAdjacentElement(&#39;afterend&#39;,img);&#32;target.remove();" src="https://content.powerapps.com/resource/powerappsportal/img/web.png" /> <div id="message">You&#8217;re offline. This is a read only version of the page.</div> <div id="close" onclick="this.parentElement.style.display='none';"><img alt="close" onerror="javascript:&#32;var&#32;target&#32;=&#32;event.target;&#32;var&#32;img&#32;=&#32;document.createElement(&#39;img&#39;);&#32;img.src&#32;=&#32;&#39;/css/images/close.png&#39;;&#32;img.alt&#32;=&#32;&#39;close&#39;;&#32;img.id&#32;=&#32;&#39;&#39;&#32;;&#32;target.insertAdjacentElement(&#39;afterend&#39;,img);&#32;target.remove();" src="https://content.powerapps.com/resource/powerappsportal/img/close.png" /></div> </div> <script type="text/javascript"> window.DisableCkEditor = window.DisableCkEditor || {}; DisableCkEditor.Value = 'False'; </script> <script type="text/javascript"> var enableOmniChannelWidgetWithSiteCopilot = 'False'; if (enableOmniChannelWidgetWithSiteCopilot === "True" || enableOmniChannelWidgetWithSiteCopilot === "true") { const authUrl = window.location.origin + "/_services/auth/portalusertoken"; const fetchWithRetries = async (url, options, retries) => { try { const authResponse = await fetch(url, options); const token = await authResponse.text(); sessionStorage['c2Token'] = token; } catch (err) { if (retries === 1) throw err; return await fetchWithRetries(url, options, retries - 1); } }; fetchWithRetries(authUrl, { method: "POST" }, 4); } </script> <script type="text/javascript"> var isPvaBotAuthenticated = sessionStorage['isPvaBotAuthenticated']; var isPortalUserLoggedIn = 'False'; if ((isPvaBotAuthenticated != null || isPvaBotAuthenticated != undefined) && isPvaBotAuthenticated != isPortalUserLoggedIn) { sessionStorage['triggerPvaBotSignOut'] = true; sessionStorage.removeItem('c2Token'); sessionStorage.removeItem('directLinetoken'); sessionStorage.removeItem('conversation_Id'); } sessionStorage['isPvaBotAuthenticated'] = isPortalUserLoggedIn; </script> <script type="text/javascript"> window["Microsoft"] = window["Microsoft"] || {}; window["Microsoft"].Dynamic365 = { Portal: { User: { userName: '', contactId: '' }, version: '9.6.7.19', type: 'CommunityPortal', id: '6deb2669-474f-4b83-92ed-ad9b4fe16aae', geo: 'NAM', tenant: '73d61799-c284-4022-8d41-54cc4f1929ef', correlationId: '54792f58-a890-4c58-9219-e9c5c3a218f8', orgEnvironmentId: 'bd43eb4e-133c-4807-bbf7-0ffb27d44a01', portalProductionOrTrialType: 'Production', isTelemetryEnabled: 'True', InstrumentationSettings: { instrumentationKey: '197418c5cb8c4426b201f9db2e87b914-87887378-2790-49b0-9295-51f43b6204b1-7172', collectorEndpoint: 'https://us-mobile.events.data.microsoft.com/OneCollector/1.0/' }, timerProfileForBatching: 'NEAR_REAL_TIME' } } // Mark request not cacheable if Dynamics365PortalAnalytics cookie is being refreshed by the server or if the cookie in request header is invalid // For client side telemetry intializing Dynamics365PortalAnalytics cookie object window["Microsoft"].Dynamic365.Portal.dynamics365PortalAnalytics = 'lX3s_BoY3p_GrfoQz9F5uweq7fV39Ib93moMe3Jjw2m-sTbmBbo8ao2C_NOhpNoHNOPsRmeung8htZHAPi6H7w_pYyOjP9Ie5QlPBkYq0W_tPFfs8jxDFIV6Gp4DdUntiRFwlNu1ivjLZUFvve89QA2'; // CodeQL [SM00430] False Positive: only alphanumeric chars allowed, for non-alphanumeric char it will return INVALID_CHARACTERS_IN_COOKIE localStorage.setItem("Dynamics365PortalAnalytics", window["Microsoft"].Dynamic365.Portal.dynamics365PortalAnalytics); </script> <script type="text/javascript"> </script> <!-- <div class="" role="navigation" style="text-align:center;background-color: red;font-weight: bold;color:white;"> Due to technical issues, service requests are currently unavailable on 311 Online. If you are unable to submit a service request, please try again later. You can also call 311 or 212-NEW-YORK (212-639-9675) for assistance by phone. </div> --> <div class="navbar navbar-static-top" role="navigation"> <div class="xrm-editable-html&#32;xrm-attribute"><div class="xrm-attribute-value"> <meta name="google-translate-customization" content="4707bd7f535893a0-45bca7b6a97e5a2d-g609df9381571b349-c"/> <!-- GLOBAL STYLES --> <link href="https://www1.nyc.gov/assets/home/css/pages/311/311header-and-footer-v2.css" media="screen" rel="stylesheet" type="text/css" /> <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.1/css/all.min.css" media="screen" rel="stylesheet" type="text/css" /> <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/v4-shims.min.css" media="screen" rel="stylesheet" type="text/css" /> <!-- Expanding Nav parent div is inner-wrap --> <div id="inner-wrap"> <!--googleoff: all--> <!-- 311 Header Start --> <div role="banner" class="main-header header-nyc"> <div class="block"> <!-- Header Top Start --> <div class="row first-visit-alert-row" style="background-color: #1771b7;"> <div class="container"> <div class="module module-first-visit-alert" style="background-color: #1771b7; background-image: url(https://www.nyc.gov/assets/home/images/content/home/nycgo_statue_crown.png);"><strong>Visiting NYC? </strong>Find events, attractions, deals, and more at <a href="https://www.nyctourism.com/" title="" class="arrow-link white-link small" style="font-size: 15px"><strong>nyctourism.com</strong></a> <!--<a href="#" title="close" class="close-button white"></a> --></div> </div> </div> <a href="#main" class="sr-only sr-only-focusable">Skip Main Navigation</a> <div class="header-top-nyc"> <div class="container"> <div class="header-inner"> <div class="header-buttons header-buttons-mobile"> <div> <button aria-label="Show Main Menu" aria-expanded="false" aria-controls="nav" class="header-collapsed" id="nav-open-btn" type="button"><span class="fas fa-bars fa-lg" id="nav-open-ham"></span><span class="menu-text">Menu</span></button> </div> </div> <span class="three-one-one-logo-wrapper"><img class="logo-three-one-one visible-desktop" alt="NYC 311" src="https://www1.nyc.gov/assets/home/images/global/ico-311-51x51.png"></span> <div class="slogan">The Official Website of the City of New York </div> <div class="logo"> <div class="nyc-logo"> <a href="https://www1.nyc.gov" class="logo" aria-label="NYC.gov home"><img src="https://www1.nyc.gov/assets/home/images/global/nyc_black.png" class="hidden" alt="NYC.gov Home"></a> </div> </div> <div class="header-buttons right"> <div class="translate1"> <button aria-label="Toggle Language Translation" aria-expanded="false" aria-controls="global-language-selection" class="header-collapsed" id="global-language" type="button"><span class="fas fa-language fa-2x"></span></button> </div> <div class="search2"> <button aria-label="Show Search" aria-expanded="false" aria-controls="header-search-collapse" class="header-collapsed" id="search-collapse-button" type="button"><span class="fas fa-search fa-lg"></span></button> </div> <div class="text-size"> <a role="button" href="https://www1.nyc.gov/home/text-size.page"><span class="sr-only">Text Size</span><span aria-label="Learn how to change your Browser Text Size" class="fas fa-font"></span><span class="fas fa-font"></span></a> </div> </div> </div> </div> </div> <!-- Translate --> <div id="global-language-selection" class="row translate-container header-tool"> <div class="container"> <div id="google_translate_element"></div> </div> </div> <!-- Translate End --> <!-- Expand and collapse search for Tablet and Mobile --> <div id="header-search-collapse" class="row search-collapse header-tool"> <div class="container"> <form role="search" class="control-form" method="GET" action="https://www1.nyc.gov/home/search/index.page"> <div class="control-group control-group-nowrap"> <label class="control-label" for="header-search-input"><span class="sr-only">Search</span> <input id="header-search-input" name="search-terms" placeholder="Search" class="header-search-input" type="text"> </label> <button class="btn header-search-btn" type="submit"><span class="sr-only">Search</span><span class="fa fa-search"></span></button> </div> </form> </div> </div> <!-- Expand and collapse search for Tablet and Mobile End --> <!-- Header Top End --> <!-- Header Nav Start --> <div class="container nav-outer"> <!-- Visible Header Nav Start --> <nav role="navigation" class="nav-mobile" id="nav" tabindex="-1"> <div class="block"> <!-- <h2 class="block-title visible-phone">The official website of NYC </h2> --> <ul> <li class="nav-home hidden-phone"> <a href="https://www1.nyc.gov">Home</a> </li> <li> <a href="https://www1.nyc.gov/nyc-resources/categories.page">NYC Resources </a> </li> <li class="active"> <a href="/">NYC311 </a> </li> <li> <a href="https://www1.nyc.gov/office-of-the-mayor/index.page">Office of the Mayor</a> </li> <li> <a href="https://www1.nyc.gov/events/index.html">Events </a> </li> <li> <a href="https://www1.nyc.gov/connect/social-media.page">Connect </a> </li> <li> <a href="https://www1.nyc.gov/jobs/index.page">Jobs </a> </li> </ul> </div> </nav> <!-- Visible Header Nav End --> <div class="global-input-search global-input-search-v2"> <form id="global-search-form1" class="hidden hidden-phone" name="filter-search-form" method="GET" action="https://www1.nyc.gov/home/search/index.page"> <div class="field-search"> <div class="input-padding"> <input type="text" name="search-terms" placeholder="Search" id="search-terms" class="input-search input-black filter-item"> <input type="submit" class="ico-search btn-filter-search" value=""> </div> </div> </form> </div> </div> <!-- Header Nav End --> </div> </div> <!-- 311 Header End --> <!--googleon: all--> </div> </div></div> </div> <script type="text/javascript"> "use strict"; function setHeight(){ var windowHeight = window.innerHeight - 140; var navbar = document.getElementById("navbar"); if (navbar) { navbar.style.maxHeight = windowHeight + "px"; } } window.addEventListener('resize', function (event) { setHeight(); }); </script> <script type="text/javascript"> "use strict"; (function updateDates() { setTimeout(function() { var times = $('time'); times.each(function(index){ $(this).html(moment($(this)[0].dateTime).fromNow()); }); }, 3000); })(); </script> <script type="text/javascript"> "use strict"; (function getSetBroadcastCookies() { function updateStyles() { var alerts = $('.alert').not(".first-visit-alert-row"); $(alerts[0]).css('border-radius','4px 4px 0 0'); $(alerts[0]).css('margin-top','1rem'); $(alerts[alerts.length-1]).css('border-radius','0 0 4px 4px'); $(alerts[alerts.length-1]).css('margin-bottom','1rem'); }; setTimeout(function(){ var expires = ""; var date = new Date(); var broadcastcookievalue = ""; function readCookie(name) { var nameEQ = name + "="; var ca = document.cookie.split(';'); for(var i=0;i < ca.length;i++) { var c = ca[i]; while (c.charAt(0)==' ') c = c.substring(1,c.length); if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length); } return null; } $('.alert-broadcast').each(function(i) { var id = this.id; //check if a cookie for alert already exists and hide it if so broadcastcookievalue = readCookie('broadcast_cookie_' + id); $('#' + id).css('display', 'block'); //if (broadcastcookievalue != "" && broadcastcookievalue == 'closed') $('#' + id).css('display', 'none'); if (broadcastcookievalue != "" && broadcastcookievalue == 'closed') $('#' + id).remove(); //add a 24 hour cookie for each alert closed $('#' + id).bind('closed.bs.alert', function () { date.setTime(date.getTime() + (24*60*60*1000)); expires = "; expires=" + date.toUTCString(); document.cookie = 'broadcast_cookie_' + id + "=" + ('closed' || "") + expires + "; path=/"; updateStyles(); }); }); updateStyles(); }, 1000); })(); </script> <script> "use strict"; //If this page is the OOB article page, redirect the user to our new custom article page. if(window.location.pathname.indexOf("/knowledgebase/article/") >= 0) window.location = "http://" + window.location.host + "/article/?kanumber=" + window.location.pathname.replace("/knowledgebase/article/", ""); </script> <!-- add anti-forgery token--> <div id="antiforgerytoken" data-url="/_layout/tokenhtml"></div> <!-- Client Telemetry init if telemetry enabled--> <script onerror="javascript:&#32;var&#32;target&#32;=&#32;event.target;&#32;var&#32;script&#32;=&#32;document.createElement(&#39;script&#39;);&#32;script.crossOrigin&#32;=&#32;target.crossOrigin;&#32;script.src&#32;=&#32;&#39;/dist/client-telemetry.bundle-2a8c5a5bde.js&#39;;&#32;script.type&#32;=&#32;&#39;text/javascript&#39;;&#32;target.insertAdjacentElement(&#39;afterend&#39;,script);" src="https://content.powerapps.com/resource/powerappsportal/dist/client-telemetry.bundle-2a8c5a5bde.js" type="text/javascript"></script> <!-- Client Telemetry Wrapper init --> <script onerror="javascript:&#32;var&#32;target&#32;=&#32;event.target;&#32;var&#32;script&#32;=&#32;document.createElement(&#39;script&#39;);&#32;script.crossOrigin&#32;=&#32;target.crossOrigin;&#32;script.src&#32;=&#32;&#39;/dist/client-telemetry-wrapper.bundle-633e70f51b.js&#39;;&#32;script.type&#32;=&#32;&#39;text/javascript&#39;;&#32;target.insertAdjacentElement(&#39;afterend&#39;,script);" src="https://content.powerapps.com/resource/powerappsportal/dist/client-telemetry-wrapper.bundle-633e70f51b.js" type="text/javascript"></script> <script> window.clientLogWrapper = new ClientLogWrapper(); </script> <script onerror="javascript:&#32;var&#32;target&#32;=&#32;event.target;&#32;var&#32;script&#32;=&#32;document.createElement(&#39;script&#39;);&#32;script.crossOrigin&#32;=&#32;target.crossOrigin;&#32;script.src&#32;=&#32;&#39;/dist/preform.moment_2_29_4.bundle-4fdd3f639b.js&#39;;&#32;script.type&#32;=&#32;&#39;text/javascript&#39;;&#32;target.insertAdjacentElement(&#39;afterend&#39;,script);" src="https://content.powerapps.com/resource/powerappsportal/dist/preform.moment_2_29_4.bundle-4fdd3f639b.js" type="text/javascript"></script> <script onerror="javascript:&#32;var&#32;target&#32;=&#32;event.target;&#32;var&#32;script&#32;=&#32;document.createElement(&#39;script&#39;);&#32;script.crossOrigin&#32;=&#32;target.crossOrigin;&#32;script.src&#32;=&#32;&#39;/dist/pcf-dependency.bundle-805a1661b7.js&#39;;&#32;script.type&#32;=&#32;&#39;text/javascript&#39;;&#32;target.insertAdjacentElement(&#39;afterend&#39;,script);" src="https://content.powerapps.com/resource/powerappsportal/dist/pcf-dependency.bundle-805a1661b7.js" type="text/javascript"></script> <script onerror="javascript:&#32;var&#32;target&#32;=&#32;event.target;&#32;var&#32;script&#32;=&#32;document.createElement(&#39;script&#39;);&#32;script.crossOrigin&#32;=&#32;target.crossOrigin;&#32;script.src&#32;=&#32;&#39;/dist/pcf.bundle-9183da3d63.js&#39;;&#32;script.type&#32;=&#32;&#39;text/javascript&#39;;&#32;target.insertAdjacentElement(&#39;afterend&#39;,script);" src="https://content.powerapps.com/resource/powerappsportal/dist/pcf.bundle-9183da3d63.js" type="text/javascript"></script> <script onerror="javascript:&#32;var&#32;target&#32;=&#32;event.target;&#32;var&#32;script&#32;=&#32;document.createElement(&#39;script&#39;);&#32;script.crossOrigin&#32;=&#32;target.crossOrigin;&#32;script.src&#32;=&#32;&#39;/dist/pcf-extended.bundle-e303d53553.js&#39;;&#32;script.type&#32;=&#32;&#39;text/javascript&#39;;&#32;target.insertAdjacentElement(&#39;afterend&#39;,script);" src="https://content.powerapps.com/resource/powerappsportal/dist/pcf-extended.bundle-e303d53553.js" type="text/javascript"></script> <div class="container-fluid page-header"> <div class="container"> <div class="row"> <h1 class="entry-title page-title">Look Up Service Requests</h1> </div> </div> </div> <div class="container-fluid" id="signin-links"> <div class="container"> <div class="row pull-right"> <div class="login-area"> <a href="/SignIn?returnUrl=%2Fcheck-status%2F">Sign In</a> | <a href="/SignIn?returnUrl=%2Fcheck-status%2F">Sign Up</a> </div> </div> </div> </div> <div class="container" id="page-wrapper"> <div id="page-container" class="col-md-8"> <button aria-label="Top" onclick="topFunction()" id="scrollBtn" title="Go to top" aria-label="Button to go to top"><i class="fa fa-arrow-up" aria-hidden="true"></i></button> </div> <style> .text-uppercase::-webkit-input-placeholder { /* WebKit browsers */ text-transform: none; } .text-uppercase:-moz-placeholder { /* Mozilla Firefox 4 to 18 */ text-transform: none; } .text-uppercase::-moz-placeholder { /* Mozilla Firefox 19+ */ text-transform: none; } .text-uppercase:-ms-input-placeholder { /* Internet Explorer 10+ */ text-transform: none; } .container > .input-group { width: 100%; } </style> <script> "use strict"; $(()=>{ $('#checkstatus').on('submit',(e)=>{ const regex = /311-(\d{8})/ if(!regex.test($("#ReferenceNumberInput").val())){ $("#invalid-sr-error-message").removeClass('hidden') e.preventDefault() } else { $("#invalid-sr-error-message").addClass('hidden') } }) }) function openServiceRequestWebPageFromReferenceNumber(srname) { var srid; var url = '?number=' + srname; $("#searchErrorRow").hide(); $("#SubmitBtn").attr("disabled", "true"); $.ajax({ method: "GET", url: url, async: true }) .done(function (msg) { var data = JSON.parse(msg); var srid = data["srid"]; var correspondenceid = data["correspondenceid"]; $("#SubmitBtn").removeAttr("disabled"); if (srid != null && srid != undefined) { window.location.href = "/sr-details/?id=" + srid; } else if (correspondenceid != null && correspondenceid != undefined) { window.location.href = "/correspondence-details/?id=" + correspondenceid; } else { $("#searchErrorRow").show(); } }); } </script> <div class="service-request-tracker"> <form id="checkstatus" method="get" action="/sr-details"> <div class="row"> <div class="col-lg-12"> <h3 style="margin-top: 1px;margin-bottom:0" tabindex="0"><div class="xrm-editable-html&#32;xrm-attribute" data-languageContext="English"><div class="xrm-attribute-value">Check Service Request Status </div></div></h3> </div> </div> <div class="row" style="margin-top: 20px;"> <div class="col-lg-12"> <label id="lblReferenceNumberInput" for="ReferenceNumberInput" ><div class="xrm-editable-html&#32;xrm-attribute" data-languageContext="English"><div class="xrm-attribute-value">Look up a Service Request Number that starts with "311-" </div></div></label> </div> <div class="col-lg-6"> <input id="ReferenceNumberInput" value="" name="srnum" class="form-control text-uppercase" aria-labelledby="lblReferenceNumberInput" type="text" placeholder=""> <span id="invalid-sr-error-message" class="help-block error hidden">Invalid Service Request number</span> </div> </div> <div class="row" style="margin-top: 20px;"> <div class="col-md-2"> <button id="SubmitBtn" class="btn btn-primary">Search</button> </div> </div> </form> <div class="row" style="margin-top: 20px;"> <div class="col-md-12"> <div class="xrm-editable-html&#32;xrm-attribute" data-languageContext="English"><div class="xrm-attribute-value"><a href="https://portal.311.nyc.gov/article/?kanumber=KA-01066">Look up a Service Request Number that does not start with "311-"</a></div></div> </div> </div> <hr> <div class="map-container"> <h3 tabindex="0">See Service Requests on a Map</h3> <p tabindex="0">Search by location, date, or topic to see Service Requests that are open or were closed within the last five days.</p> <div class="map-view"> <script> "use strict"; //Use the method function to add new methods to an object - include the name of the function and the function logic Function.prototype.method = function (name, func) { this.prototype[name] = func; return this; }; //Inheritance: call the method as childobject.inherits(parentobject) Function.method('inherits', function (parent) { this.prototype = Object.create(parent.prototype); this.prototype.constructor = this; this.prototype.parent = parent.prototype; }); //Validates an object to ensure it inherits from a certain type Object.defineProperty(Object.prototype, 'validateType', { value : function(type) { if(!(this instanceof type)) throw new Error("Error validating object type - " + type.name); return true; }, enumerable : false }); </script> <script> "use strict"; function Log(id, enabled) { var self = this; this.getId = function () { return id; } this.log = function (args) { this.validateType(Log); if(enabled) this.writeLog.apply(this, Array.prototype.slice.call(arguments)); } this.writeLog = function (args) { this.validateType(Log); return this; } } function ConsoleLog(id, enabled) { this.parent.constructor.call(this, id, enabled); this.writeLog = function (args) { this.validateType(ConsoleLog); var newargs = Array.prototype.slice.call(arguments); newargs.splice(0, 0, this.getId()); newargs.splice(1, 0, "-"); console.log.apply(console, Array.prototype.slice.call(newargs)); return this; } } ConsoleLog.inherits(Log); function ErrorLog(id, enabled) { this.parent.constructor.call(this, id, enabled); this.writeLog = function (args) { this.validateType(ErrorLog); throw new Error(args); return this; } } ErrorLog.inherits(Log); /* Log List */ var Logs = { AddressPickerLog: new ConsoleLog('Address Picker Log', true), AjaxLog: new ConsoleLog('Ajax Log', false), BingMapsLog: new ConsoleLog('Bing Maps Log', false), CustomMapsLog: new ConsoleLog('Custom Maps Log', true), DependantOptionSetLog: new ConsoleLog('Dependant Option Set Log', false), DSNYLog: new ConsoleLog('DSNY Log', false), EntityPinMapLog: new ConsoleLog('Entity Pin Map Log', true), ErrorLog: new ErrorLog('Error', true), OptionsLog: new ConsoleLog('Options Log', true), TopRequestsLog: new ConsoleLog('Top Requests Log', false), } </script> <script> "use strict"; //Use the options object to pass optional parameters to an object function Options(inputoptions) { var self = this; Logs.OptionsLog.log('Adding Options'); var options = (inputoptions) ? inputoptions : {}; Logs.OptionsLog.log('Options', options); this.getValue = function (key, defaultvalue) { this.validateType(Options); if(options[key] != undefined) return options[key]; if(defaultvalue) return defaultvalue; return null; } this.getValueByType = function (key, type, defaultvalue) { this.validateType(Options); if (options[key] != undefined) if (options[key] instanceof type || (type === Boolean && options[key].constructor === Boolean) || (type === Number && options[key].constructor === Number) || (type === String && options[key].constructor === String)) return this.getValue(key, defaultvalue); else throw Error("Error: Option [" + key + "] must be of type [" + type + "]"); if(defaultvalue) return defaultvalue; return null; } } </script> <script> "use strict"; /* CONSTANTS */ var gis_baseurl = "https://api.nyc.gov/geo/geoclient/v1/search.json?Input="; var gis_header = { "ocp-apim-subscription-key": "f6130358c84c48c096d24cb12c1f1387" }; var default_lat = "40.7128"; var default_lon = "-74.0059"; var default_zoom = "12"; var getAddressUrl = "/address-feed/"; var bingCred = "7SR73xiKvMEcDhiVI6pI~s95mtiC3OywKqMcijpe-BQ~AnJRubw9xs1lMnVVkR3LpoydceKTwkrSQFYC5CvxUb-WggGQPLYLpyIvXrK1mHvi"; /* Custom Map Object */ /* This is a basic bing map object that can be extended to create address pickers and other map related features. All of the bing map specific logic should be contained here. */ /** * A constructor for the NYCMap that accepts a parent element and set of options. * @param {JQuery} _parentelement - The parent element the map will be appended to. * @param {Array} _inputoptions - An object containing configuration options for the map. */ function NYCMap(_parentelement, _inputoptions) { var _self = this; var _options = (_inputoptions && _inputoptions instanceof Options) ? _inputoptions : new Options(); Logs.CustomMapsLog.log('Create NYC Map - ', _parentelement, " - ", _options); var _startlatitude = _options.getValueByType('startlatitude', Number, null); var _startlongitude = _options.getValueByType('startlongitude', Number, null); var _startzoom = _options.getValueByType('startzoom', Number, default_zoom); Logs.CustomMapsLog.log('Start Latitude - ', _startlatitude); Logs.CustomMapsLog.log('Start Longitude - ', _startlongitude); Logs.CustomMapsLog.log('Start Zoom - ', _startzoom); var _bingmap = null; var _addresspicker = null; /** * Initializes a new bing maps object that will center on the user's location if they allow it and they are within NYC bounds. */ _self.loadMap = function () { this.validateType(NYCMap); var self = this; if(!_parentelement) return; var nycbounds = [40.917577, 40.477399, -73.700272, -74.259090]; Logs.CustomMapsLog.log('Load Custom Map', _parentelement[0]); //Create new bing map appended to parent element _bingmap = new Microsoft.Maps.Map(_parentelement[0], { credentials: bingCred, disableStreetside: true, disableBirdseye:true, enableClickableLogo: false, showLocateMeButton: false, maxBounds: new Microsoft.Maps.LocationRect.fromEdges(nycbounds[0] + .1, nycbounds[3] - .1, nycbounds[1] - .1, nycbounds[2] + .1) }); //TSet the start latitude and longitude. Use NYC center if none is provided. if(_startlatitude != null && _startlongitude != null) { _bingmap.setView({ center: new Microsoft.Maps.Location(_startlatitude, _startlongitude), zoom: _startzoom }); } else { var nycCoords = [40.70880669176046, -74.00867826994428]; _bingmap.setView({ center: new Microsoft.Maps.Location(nycCoords[0], nycCoords[1]), zoom: _startzoom }); } //Request that the user allows us to locate their position. If yes and their position is within NYC bounds, center on that position. Otherwise take no action. navigator.geolocation.getCurrentPosition(function (position) { var userinsidebounds = !( position.coords.latitude > nycbounds[0] || position.coords.latitude < nycbounds[1] || position.coords.longitude > nycbounds[2] || position.coords.longitude < nycbounds[3] ); //Show user's location if inside NYC bounds if(userinsidebounds) { _bingmap.setOptions({ showLocateMeButton: true }); } //Go to user's location if inside NYC bounds if(_startlatitude == null && _startlongitude == null) { if(userinsidebounds) { _bingmap.setView({ center: new Microsoft.Maps.Location(position.coords.latitude, position.coords.longitude), zoom: _startzoom }); } } }); } /** * Sets the map view and zoom level. * @param {Microsoft.Maps.Location} location - The location to center on. * @param {number} zoomlevel - The zoom level to zoom to. */ _self.setMapView = function (location, zoomlevel) { this.validateType(NYCMap); var self = this; Logs.CustomMapsLog.log('Set Map View: ', location, " - ", zoomlevel); var zoomlevel = zoomlevel || _bingmap.getZoom(); _bingmap.setView({ center: location, zoom: (zoomlevel < 15) ? 15 : zoomlevel }); } /** * Returns the bing map object. */ _self.getBingMap = function () { return _bingmap; } /** * Returns the start latitude. */ _self.getStartLatitude = function () { return _startlatitude; } /** * Returns the start longitude. */ _self.getStartLongitude = function () { return _startlongitude; } } function getGISAPIResults(queryparams, onSuccessCallback) { $.ajax({ url: gis_baseurl + queryparams, headers: gis_header , success: onSuccessCallback }); } </script> <script> "use strict"; function EntityPin(_id, _label, _sublabel, _latitude, _longitude, _data) { var _self = this; _self.getId = function () { return _id; } _self.getLabel = function () { return _label; } _self.getSubLabel = function () { return cleanString(_sublabel, ','); } //_self.getSubLabel = function () { return _sublabel; } _self.getLatitude = function () { return _latitude; } _self.getLongitude = function () { return _longitude; } _self.getLocation = function () { return new Microsoft.Maps.Location(_self.getLatitude(), _self.getLongitude()); } _self.getData = function () { return _data; } }; function cleanString(_str, trailToRemove){ var _str = _str.trim(); if (_str.substring(_str.length - 1) == trailToRemove) return cleanString(_str.substring(0, _str.length - 1), trailToRemove); else return _str; } function getEntityPinFromJSON(jsonpin) { return new EntityPin(jsonpin.id, jsonpin.label, jsonpin.sublabel, jsonpin.latitude, jsonpin.longitude, jsonpin.data); } </script> <script> "use strict"; function MapFilter() { var _self = this; _self.getBingMap = function () { return null; } _self.initialize = function () { } _self.getFilterHTMLElement = function () { return ""; } _self.getFetchParameters = function () { return {}; } _self.validatePin = function (pins) { return true; } } </script> <script> "use strict"; function removewhitespace(string) { return string.replace(/\s\s+/g, ' ') } </script> <!-- The proj4.js file used to convert state plane coordinates to lat long coordinates. --> <script src="/proj4.js"></script> <script> "use strict"; /* * An enumerable of address category types. */ var AddressCategory = { ADDRESS : "ADDRESS", BLOCKFACE: "BLOCKFACE", INTERSECTION : "INTERSECTION", PLACE : "PLACE" } /** * Converts an AddressCategory to a display string. * @param {AddressCategory} category - The category to be converted to a display string. */ function AddressCategoryToString(category) { switch(category) { case AddressCategory.ADDRESS: return "Address"; case AddressCategory.BLOCKFACE: return "Block"; case AddressCategory.INTERSECTION: return "Intersection"; case AddressCategory.PLACE: return "Landmark"; } } /** * An object that contains the relevant data for an address returned from geoclient. * @param {AddressCategory} _category - The category of the address. * @param {number} _latitude - The latitude of the address. * @param {number} _longitude - The longitude of the address. */ function AddressData(_category, _latitude, _longitude) { if(_category == null) throw new Error("Address Data Category can not be null."); this.getCategory = function () { return _category; } this.getLatitude = function () { return _latitude || null; } this.getLongitude = function () { return _longitude || null; } this.getFullAddress = function () { return null; } this.getCRMFullAddress = function () { return ""; } this.toJSON = function () { return { category: _category, latitude : _latitude, longitude : _longitude } } } /** * An object that contains the relevant data for an address of type ADDRESS. * @param {number} _latitude - The latitude of the address. * @param {number} _longitude - The longitude of the address. * @param {string} _number - The on number of the address. * @param {string} _street - The street of the address. * @param {string} _zip - The zip of the address. * @param {string} _city - The city of the address. * @param {string} _borough - The borough of the address. */ AddressDataAddress.inherits(AddressData); function AddressDataAddress(_latitude, _longitude, _number, _street, _zip, _city, _borough) { var _self = this; AddressData.prototype.constructor.call(_self, AddressCategory.ADDRESS, _latitude, _longitude); _self.getNumber = function () { return _number || ""; } _self.hasNumber = function () { return _number ? true : false; } _self.getStreet = function () { return _street || ""; } _self.hasStreet = function () { return _street ? true : false; } _self.getZip = function () { return _zip || ""; } _self.hasZip = function () { return _zip ? true : false; } _self.getCity = function () { return _city || ""; } _self.hasCity = function () { return _city ? true : false; } _self.getBorough = function () { return _borough || ""; } _self.hasBorough = function () { return _borough ? true : false; } _self.getStreetAddress = function () { var str = _self.getNumber(); str += _self.getNumber() != "" ? " " : ""; str += _self.getStreet(); return removewhitespace(str); } _self.getFullAddress = function () { var str = _self.getNumber(); str += _self.getNumber() != "" ? " " : ""; str += _self.getStreet(); str += _self.getStreet() != "" && _self.getCity() != "" ? ", " : ""; str += _self.getCity(); return removewhitespace(str); } _self.getCRMFullAddress = function () { var str = _self.getNumber(); str += _self.getNumber() != "" ? " " : ""; str += _self.getStreet(); str += _self.getStreet() != "" && _self.getBorough() != "" ? ", " : ""; str += _self.getBorough(); return removewhitespace(str); } _self.toJSON = function () { return { category : AddressCategory.ADDRESS, latitude : _latitude, longitude : _longitude, number : _number, street : _street, zip : _zip, city : _city, borough : _borough } } } /** * An object that contains the relevant data for an address of type BLOCKFACE. * @param {number} _latitude - The latitude of the blockface. * @param {number} _longitude - The longitude of the blockface. * @param {string} _onstreet - The on street of the blockface. * @param {string} _crossstreet1 - The crossstreet1 of the blockface. * @param {string} _crossstreet2 - The crossstreet2 of the blockface. * @param {string} _borough - The borough of the blockface. */ AddressDataBlockface.inherits(AddressData); function AddressDataBlockface(_latitude, _longitude, _onstreet, _crossstreet1, _crossstreet2, _borough) { var _self = this; AddressData.prototype.constructor.call(_self, AddressCategory.BLOCKFACE, _latitude, _longitude); _self.getOnStreet = function () { return _onstreet || ""; } _self.getCrossStreet1 = function () { return _crossstreet1 || ""; } _self.getCrossStreet2 = function () { return _crossstreet2 || ""; } _self.getBorough = function () { return _borough || ""; } _self.getFullAddress = function () { var str = _self.getOnStreet() + " between " + _self.getCrossStreet1() + " and " + _self.getCrossStreet2(); return removewhitespace(str); } _self.getCRMFullAddress = function () { var str = _self.getOnStreet() + " BETWEEN " + _self.getCrossStreet1() + " AND " + _self.getCrossStreet2() + ", " + _self.getBorough(); return removewhitespace(str); } _self.toJSON = function () { return { category : AddressCategory.INTERSECTION, latitude : _latitude, longitude : _longitude, onstreet : _onstreet, crossstreet1 : _crossstreet1, crossstreet2 : _crossstreet2 } } } /** * An object that contains the relevant data for an address of type INERSECTION. * @param {number} _latitude - The latitude of the intersection. * @param {number} _longitude - The longitude of the intersection. * @param {string} _crossstreet1 - The crossstreet1 of the intersection. * @param {string} _crossstreet2 - The crossstreet2 of the intersection. * @param {string} _borough - The borough of the intersection. */ AddressDataIntersection.inherits(AddressData); function AddressDataIntersection(_latitude, _longitude, _crossstreet1, _crossstreet2, _borough) { var _self = this; AddressData.prototype.constructor.call(_self, AddressCategory.INTERSECTION, _latitude, _longitude); _self.getCrossStreet1 = function () { return _crossstreet1 || ""; } _self.getCrossStreet2 = function () { return _crossstreet2 || ""; } _self.getBorough = function () { return _borough || ""; } _self.getFullAddress = function () { var str = _self.getCrossStreet1() + " & " + _self.getCrossStreet2(); return removewhitespace(str); } _self.getCRMFullAddress = function () { var str = _self.getCrossStreet1() + " AND " + _self.getCrossStreet2() + ", " + _self.getBorough(); return removewhitespace(str); } _self.toJSON = function () { return { category : AddressCategory.INTERSECTION, latitude : _latitude, longitude : _longitude, crossstreet1 : _crossstreet1, crossstreet2 : _crossstreet2 } } } /** * An object that contains the relevant data for an address of type PLACE. * @param {number} _latitude - The latitude of the place. * @param {number} _longitude - The longitude of the place. * @param {string} _placename - The name of the place. * @param {string} _zip - The zip of the place. * @param {string} _borough - The borough of the place. */ AddressDataPlace.inherits(AddressData); function AddressDataPlace(_latitude, _longitude, _placename, _zip, _borough) { var _self = this; AddressData.prototype.constructor.call(_self, AddressCategory.PLACE, _latitude, _longitude); _self.getPlaceName = function () { return _placename || ""; } _self.getZip = function () { return _zip || ""; } _self.getBorough = function () { return _borough || ""; } _self.getFullAddress = function () { return removewhitespace(_self.getPlaceName()); } _self.getCRMFullAddress = function () { var str = _self.getPlaceName() + ", " + _self.getBorough(); return removewhitespace(str); } _self.toJSON = function () { return { category : AddressCategory.PLACE, latitude : _latitude, longitude : _longitude, placename : _placename, zip : _zip, borough : _borough } } } /** * Converts a json object returned from the CRM into an address data object. * @param {Object} jsonObject - JSON data returned from CRM. */ function getAddressDataFromJSON(jsonObject) { console.log(jsonObject); var obj = JSON.parse(jsonObject); if(obj.category == AddressCategory.ADDRESS) { return new AddressDataAddress( obj.latitude, obj.longitude, obj.number, obj.street, obj.zip, obj.city, obj.borough ); } else if(obj.category == AddressCategory.BLOCKFACE) { return new AddressDataBlockface( obj.latitude, obj.longitude, obj.onstreet, obj.crossstreet1, obj.crossstreet2 ); } else if(obj.category == AddressCategory.INTERSECTION) { return new AddressDataIntersection( obj.latitude, obj.longitude, obj.crossstreet1, obj.crossstreet2 ); } else if(obj.category == AddressCategory.PLACE) { return new AddressDataPlace( obj.latitude, obj.longitude, obj.placename, obj.zip, obj.borough ); } } /** * Uses ajax to get convert an address id into an address data object. * @param {string} id - Guid of the address. * @param {string} callback - Callback function. */ function getAddressDataFromId(id, callback) { $.ajax({ url: "/get-address-from-id/?id=" + id, success: function (data) { var jsondata = JSON.parse(data); if(jsondata.count > 0) { callback(getAddressDataFromJSON(JSON.stringify(jsondata.results[0]))); } } }); } /** * Converts data return from ArcGIS into an address data object. * @param {string} value - Data returned from ArcGIS. */ function getAddressDataFromArcGISJSON(value) { console.log("ARCGIS data", value); var boroughValue = value.response.firstBoroughName; if(boroughValue == "STATEN IS") boroughValue = "STATEN ISLAND"; switch(value.category) { case AddressCategory.ADDRESS: return new AddressDataAddress( value.response.latitude, value.response.longitude, value.response.houseNumber, value.response.boePreferredStreetName, value.response.zipCode, value.response.uspsPreferredCityName, boroughValue ); break; case AddressCategory.BLOCKFACE: var fromNode = statePlaneToLatLong(value.response.fromXCoordinate, value.response.fromYCoordinate); var toNode = statePlaneToLatLong(value.response.toXCoordinate, value.response.toYCoordinate); return new AddressDataBlockface( (fromNode[0] + toNode[0]) / 2, (fromNode[1] + toNode[1]) / 2, value.response.firstStreetNameNormalized, value.response.secondStreetNameNormalized, value.response.thirdStreetNameNormalized, boroughValue ); break; case AddressCategory.INTERSECTION: return new AddressDataIntersection( value.response.latitude, value.response.longitude, value.response.streetName1, value.response.streetName2, boroughValue ); break; case AddressCategory.PLACE: return new AddressDataPlace( value.response.latitude, value.response.longitude, value.response.boePreferredStreetName, value.response.zipCode, boroughValue ); break; default: return null; } } /** * Converts a state plane (x,y) coordinate into a latitude and longitude coordinate. * @param {number} x - State plane x coordinate. * @param {number} y - State plane y coordinate. */ function statePlaneToLatLong(x, y) { //NYC State Plane Coordinates System proj4.defs["EPSG:2263"] = "+proj=lcc +lat_1=41.03333333333333 +lat_2=40.66666666666666 +lat_0=40.16666666666666 +lon_0=-74 +x_0=300000.0000000001 +y_0=0 +ellps=GRS80 +datum=NAD83 +to_meter=0.3048006096012192 +no_defs"; //WGS84 Lat Long system proj4.defs["WGS84"] = "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"; //Convert state plane coordinates to lat long var longlat = proj4(proj4.defs["EPSG:2263"],proj4.defs["WGS84"],[x,y]); return [longlat[1], longlat[0]] } //# sourceURL=AddressDataScripts.js </script> <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script> <script> "use strict"; //Get site settings for geoclient //var gis_baseurl = "https://api.nyc.gov/geo/geoclient/v1/search.json?Input="; var addresssearchboxnum = 0; function AddressSearchBox(_parentelement, _options) { var _self = this; var _options = _options || {}; var _num = addresssearchboxnum; var _categories = _options.categories || null; var _topitem = null; addresssearchboxnum++; var _inputgroup = $('<div class="input-group address-search-box" style="width:100%"></div>'); var _inputbox = $('<input id="address-search-box-input" type="text" class="text form-control exclude-from-summary" placeholder="Search for an NYC Location"></input>'); if(_options.placeholder != undefined) _inputbox.attr("placeholder", _options.placeholder); else updatePlaceholder(); var _suggestionsdiv = $('<div id="suggestion-list-' + _num + '"></div>'); var _clearbutton = $('<span class=" input-group-addon glyphicon glyphicon-remove-sign textbox-clear-button cursor-pointer"></span>'); _inputbox.keypress(function (e) { if (e.charCode == 13) { if(_topitem != null) { _topitem.click(); _topitem = null; } return false; } }); _inputgroup.append(_inputbox); _inputgroup.append(_clearbutton); _parentelement.append(_inputgroup); _parentelement.append(_suggestionsdiv); buildAddressAutoComplete.call(_self); _clearbutton.hide(); _clearbutton.click(function () { _inputbox.val(""); setInputDisabled(false); _self.onAddressSelected(null); }); function setInputDisabled(disabled) { if(disabled) { _clearbutton.show(); _inputbox.attr("disabled", "disabled"); } else { _clearbutton.hide(); _inputbox.removeAttr("disabled"); } } function buildAddressAutoComplete() { $.widget( "a.geoclientcomplete", $.ui.autocomplete, { _create: function() { this._super(); this.widget().menu( "option", "items", "> :not(.ui-autocomplete-category)" ); }, _renderMenu: function( ul, items ) { var that = this; var currentCategory = ""; _topitem = null; $.each( items, function( index, item ) { var li; if ( item.category != currentCategory ) { ul.append( "<li class='ui-autocomplete-category'>" + item.category + "</li>" ); currentCategory = item.category; } li = that._renderItemData( ul, item ); if(_topitem == null) _topitem = li; if ( item.category ) { li.attr( "aria-label", item.category + " : " + item.label ); } }); } }); _inputbox.geoclientcomplete({ delay: 0, appendTo: "#suggestion-list-" + _num, source: getAddressData.bind(_self), minLength: 3, select: function(event, ui) { setInputDisabled(true); _self.onAddressSelected(ui.item.data); } }); } function getAddressData(request, response) { function onSuccessGISCall(data) { debugger _topitem = null; if(data.status == "OK"){ var jsonObj = data.results; $.each(jsonObj, function(index, obj){ obj["id"] = index; if(obj.request.indexOf("address") == 0 && obj.response.houseNumber){ obj["category"] = AddressCategory.ADDRESS; } if(obj.request.indexOf("blockface") == 0){ obj["category"] = AddressCategory.BLOCKFACE; } if(obj.request.indexOf("intersection") == 0){ obj["category"] = AddressCategory.INTERSECTION; } if(obj.request.indexOf("place") == 0){ obj["category"] = AddressCategory.PLACE; } }) var unmatch = 0; response($.map(jsonObj, function (value, key) { if(_categories != null && value.category && _categories.indexOf(value.category) == -1){ unmatch++; if(unmatch == jsonObj.length){ alert("You must enter an address in one of the formats listed."); _self.clearText(); } return; } var addressdata = getAddressDataFromArcGISJSON(value); if(addressdata != undefined || addressdata != null) { unmatch = 0; return { category: AddressCategoryToString(addressdata.getCategory()), label: addressdata.getFullAddress(), key: value.id, data: addressdata }; } }) ); } } getGISAPIResults (_inputbox.val(), onSuccessGISCall); /* $.ajax({ url: gis_baseurl + _inputbox.val(), headers:{ "ocp-apim-subscription-key": "f6130358c84c48c096d24cb12c1f1387" }, success: function( data ) { _topitem = null; if(data.status == "OK"){ var jsonObj = data.results; $.each(jsonObj, function(index, obj){ obj["id"] = index; if(obj.request.indexOf("address") != -1){ obj["category"] = AddressCategory.ADDRESS; } if(obj.request.indexOf("blockface") != -1){ obj["category"] = AddressCategory.BLOCKFACE; } if(obj.request.indexOf("intersection") != -1){ obj["category"] = AddressCategory.INTERSECTION; } if(obj.request.indexOf("place") != -1){ obj["category"] = AddressCategory.PLACE; } }) var unmatch = 0; response($.map(jsonObj, function (value, key) { if(_categories != null && _categories.indexOf(value.category) == -1){ unmatch++; if(unmatch == jsonObj.length){ alert("You must enter an address in one of the formats listed."); _self.clearText(); } return; } var addressdata = getAddressDataFromArcGISJSON(value); if(addressdata != undefined || addressdata != null) { unmatch = 0; return { category: AddressCategoryToString(addressdata.getCategory()), label: addressdata.getFullAddress(), key: value.id, data: addressdata }; } }) ); } } });*/ } _self.onAddressSelected = function (addressdata) { } _self.setSearchText = function (text) { setInputDisabled(true); _inputbox.val(text); } _self.clearText = function () { setInputDisabled(false); _inputbox.val(""); } _self.setCategories = function (categories) { _categories = categories || []; updatePlaceholder(); } function updatePlaceholder() { if(_options.placeholder != undefined) { return; } var placeholder = "Search for an NYC "; var count = 0; _categories.forEach(function (category) { if(count == 0) placeholder += AddressCategoryToString(category); else if(count == _categories.length - 1) placeholder += " or " + AddressCategoryToString(category); else placeholder += ", " + AddressCategoryToString(category); count++; }); _inputbox.attr("placeholder", placeholder); } } //# sourceURL=AddressSearchBoxScripts.js </script> <script> "use strict"; MapAddressFilter.inherits(MapFilter); function MapAddressFilter(_options) { var _self = this; MapFilter.prototype.constructor.call(_self); _options = _options || {}; var _addressData = null; var _addressinputcontainer = $("<div id='addresseMapFilter'></div>"); var _addresssearchbox = new AddressSearchBox(_addressinputcontainer, { placeholder: "Address"}); var _searchRangeShape = null; _addresssearchbox.onAddressSelected = function (data) { _addressData = data; } /*************** OLD INPUT START ******************/ /*************** OLD INPUT END ******************/ var distancesFeet = [100, 200, 500, 1000, 2000]; var distancesMiles = [1, 2, 5, 10]; var _distanceselect = $('<select aria-label="Select distance search range"/>').attr({ class: "form-control exclude-from-summary" }); _distanceselect.append('<option value="0">Search within</option>') distancesFeet.forEach(function (distance) { var feetlabel = distance == 1 ? "foot" : "feet"; _distanceselect.append('<option value="' + distance + '" unit="' + feetlabel + '">' + distance + ' ' + feetlabel + '</option>'); }); distancesMiles.forEach(function (distance) { var mileslabel = distance == 1 ? "mile" : "miles"; _distanceselect.append('<option value="' + distance + '" unit="' + mileslabel + '">' + distance + ' ' + mileslabel + '</option>'); }); _distanceselect.val(500); _self.getFilterHTMLElement = function () { var element = $("<div></div>"); if(_options.label != undefined && _options.label.length > 0) element.append($('<label class="map-filter-label" for="address-search-box-input">' + _options.label + '</label>')); /*************** OLD INPUT START ******************/ /*************** OLD INPUT END ******************/ var distanceinputgroup = $('<div class="input-group" style="width: 100%;">').append(_distanceselect) element.append(_addressinputcontainer); element.append(distanceinputgroup); return element; } function addSearchRangeToMap(center, radius) { if(radius > 3000) radius = 3000; if(_searchRangeShape != null) _self.getBingMap().entities.remove(_searchRangeShape); Microsoft.Maps.loadModule('Microsoft.Maps.SpatialMath', function () { var locations = Microsoft.Maps.SpatialMath.getRegularPolygon(center, radius, 90, Microsoft.Maps.SpatialMath.DistanceUnits.Kilometers); _searchRangeShape = new Microsoft.Maps.Polygon(locations, null); _self.getBingMap().entities.push(_searchRangeShape); }); } _self.getFetchParameters = function () { var params = {}; if(_searchRangeShape != null) _self.getBingMap().entities.remove(_searchRangeShape); /*************** OLD INPUT START ******************/ /*************** OLD INPUT END ******************/ if(_distanceselect.val() != 0 && _distanceselect.val() != "" && _distanceselect.val() != "" && _addressData != null) { var distance = getDistanceKilometers(); var bounds = getDistanceBoundsFromKilometers(_addressData.getLatitude(), _addressData.getLongitude(), distance); params["minlatitude"] = bounds[0]; params["minlongitude"] = bounds[1]; params["maxlatitude"] = bounds[2]; params["maxlongitude"] = bounds[3]; addSearchRangeToMap(new Microsoft.Maps.Location(_addressData.getLatitude(), _addressData.getLongitude()), distance + .033); if(_self.getBingMap() != null) { if(distance > 480) { _self.getBingMap().setView({ center: new Microsoft.Maps.Location(_addressData.getLatitude(), _addressData.getLongitude()), zoom: 5 }); } else if(distance < 0.1990344) { _self.getBingMap().setView({ center: new Microsoft.Maps.Location(_addressData.getLatitude(), _addressData.getLongitude()), zoom: 16 }); } else { _self.getBingMap().setView({ bounds: Microsoft.Maps.LocationRect.fromCorners(new Microsoft.Maps.Location(bounds[2], bounds[1]), new Microsoft.Maps.Location(bounds[0], bounds[3])) }); } } } return params; } function getDistanceKilometers() { /*************** OLD INPUT START ******************/ /*************** OLD INPUT END ******************/ var distance = parseFloat(_distanceselect.val()); var units = _distanceselect.find("option:selected").attr('unit'); if(isNaN(distance)) distance = 0; if(units == "miles") { distance = distance * 1.609344; } else if(units == "feet") { distance = distance * 0.0003048; } if(distance <= 0) distance = parseFloat(0.0003048); return distance; } _self.validatePin = function (pin) { if(_addressData == null) return true; var distance = getDistanceKilometers(); if(parseFloat(getDistanceBetweenGeolocationsInKilometers(_addressData.getLatitude(), _addressData.getLongitude(), pin.getLatitude(), pin.getLongitude())) > parseFloat(distance)) return false; return true; } } function degToRad(degrees) { return (Math.PI * degrees)/180; } function radToDeg(radians) { return (radians * 180)/Math.PI; } var earthRadius = 6371.01; // Earth's radius in kilometres function getDistanceBoundsFromKilometers(latitude, longitude, distance) { var MIN_LAT = degToRad(-90); var MAX_LAT = degToRad(90); var MIN_LON = degToRad(-180); var MAX_LON = degToRad(180); //Radius of the Earth var raddistance = distance / earthRadius; //coordinates in radians var radlatitude = degToRad(latitude); var radlongitude = degToRad(longitude); var minlatitude = radlatitude - raddistance; var maxlatitude = radlatitude + raddistance; var minlongitude, maxlongitude; if(minlatitude > MIN_LAT && maxlatitude < MAX_LAT) { var deltalongitude = Math.asin(Math.sin(raddistance) / Math.cos(radlatitude)); minlongitude = radlongitude - deltalongitude; if(minlongitude < MIN_LON) minlongitude += 2 * Math.PI; maxlongitude = radlongitude + deltalongitude; if(maxlongitude > MAX_LON) maxlongitude -= 2 * Math.PI; } else { minlatitude = Math.max(minlatitude, MIN_LAT); maxlatitude = Math.min(maxlatitude, MAX_LAT); minlongitude = MIN_LON; maxlongitude = MAX_LON; } return [radToDeg(minlatitude), radToDeg(minlongitude), radToDeg(maxlatitude), radToDeg(maxlongitude)]; } function getDistanceBetweenGeolocationsInKilometers(lat1, lon1, lat2, lon2) { var radlat1 = degToRad(lat1); var radlat2 = degToRad(lat2); var raddistancelat = degToRad(lat2-lat1); var raddistancelon = degToRad(lon2-lon1); //Haversine Formula var a = Math.sin(raddistancelat/2) * Math.sin(raddistancelat/2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.sin(raddistancelon/2) * Math.sin(raddistancelon/2); var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); return earthRadius * c; } </script> <script> "use strict"; MapTextFilter.inherits(MapFilter); function MapTextFilter(_paramname, _options) { var _self = this; MapFilter.prototype.constructor.call(_self); _options = _options || {}; _options.default = _options.default != undefined ? _options.default : null; var _textinput = $('<input />').attr({ class : "form-control exclude-from-summary", value : _options.value || "", id: _paramname }); if(_options.default != null) _textinput.val(_options.default); _self.getFilterHTMLElement = function () { var element = $("<div></div>"); if(_options.label != undefined && _options.label.length > 0) element.append($('<label class="map-filter-label" for="' + _textinput.attr('id') + '">' + _options.label + '</label>')); element.append(_textinput); return element; } _self.getFetchParameters = function () { var params = {}; if(_textinput.val() != null && _textinput.val() != "") params[_paramname] = _textinput.val(); return params; } } </script> <script> "use strict"; //Base add validator function. Extend this to create new validator types. function addValidator(id, controltovalidateid, errormessage, evaluationfunction, options) { if (typeof (Page_Validators) == 'undefined') return; var validator = document.createElement('span'); options = options || {}; validator.style.display = "none"; validator.id = id; validator.controltovalidate = controltovalidateid; validator.labelid = options.labelid || controltovalidateid + "_label"; if(options.useasterisk) validator.useasterisk = true; validator.errormessage = "<a href='#" + validator.labelid + "'>" + errormessage.replace(/<a\b[^>]*>/i,"").replace(/<\/a>/i, "") + "</a>"; validator.validationGroup = ""; validator.initialvalue = ""; validator.enabled = true; validator.evaluationfunction = evaluationfunction; Page_Validators.push(validator); $("a[href='#" + validator.labelid + "']").on("click", function () { scrollToAndFocus(validator.labelid, controltovalidateid); }); toggleValidator(validator.id, true); return validator; } //options: labelid, errormessage, evaluationfunction function addRequiredValidator(fieldid, options) { if (typeof (Page_Validators) == 'undefined') return; if($("#" + fieldid).length <= 0) { console.log("Validator Extensions Error: Field with id " + fieldid + " does not exist."); return; } if(getValidator(fieldid + "Required").length > 0) { return toggleValidator(fieldid + "Required", true); } options = options || {}; var labelid = options.labelid || fieldid + "_label"; var labelname = $("#" + labelid).html(); var errormessage = options.errormessage || labelname + " is a required field."; var useasterisk = options.useasterisk != undefined ? options.useasterisk : true; var evaluationfunction = options.evaluationfunction != undefined ? options.evaluationfunction : function () { var field = $("#" + fieldid); if (field.is(".picklist") && field.is("select")){ return field[0].options.selectedIndex > 0; } else if(field.is(".boolean-radio") || field.is(".picklist")) { return field.find("input:checked").val() != undefined && field.find("input:checked").val() != "" ; } else { return field.val() != undefined && (field.val() != ""|| field.val().trim().length > 0); } }; return addValidator(fieldid + "Required", fieldid, errormessage, evaluationfunction, { labelid : labelid, useasterisk : useasterisk }); } function addRequiredValidators(fieldids) { fieldids.forEach(function(fieldid) { addRequiredValidator(fieldid); }); }; function toggleRequiredValidator(fieldid, enabled) { toggleValidator(fieldid + "Required", enabled); }; function toggleRequiredValidators(fieldids, enabled) { fieldids.forEach(function(fieldid) { toggleRequiredValidator(fieldid, enabled); }); }; //Returns the validator by id function getValidator(id) { if (typeof (Page_Validators) == 'undefined') return false; return $($.grep(Page_Validators, function(e){ return e.id == id; })[0]); } //Toggles or sets the validators enabled value function toggleValidator(validatorid, enabled) { if (typeof (Page_Validators) == 'undefined') return; var validator = getValidator(validatorid); if(validator.prop("enabled") == undefined) validator.prop("enabled", true); validator.prop("enabled", enabled != undefined ? enabled : !validator.prop("enabled")); if(validator.prop("useasterisk") || validatorid.indexOf("RequiredFieldValidator") != -1) { if(validator.prop("enabled")) addValidatorAsterisk(validator); else removeValidatorAsterisk(validator); } return validator; } function toggleValidators(validatorids, enabled) { validatorids.forEach(function(validatorid) { toggleValidator(validatorid, enabled); }); }; function addValidatorAsterisk(validator) { var labelid = validator.prop("labelid") || validator.controltovalidateid + "_label"; $("#" + labelid).parent(".info").addClass("required"); $("#" + labelid).change(); } function removeValidatorAsterisk(validator) { var labelid = validator.prop("labelid") || validator.controltovalidateid + "_label"; $("#" + labelid).parent(".info").removeClass("required"); $("#" + labelid).change(); } /* Add new validator types here */ function addPhoneValidator(fieldid, options) { options = options || {}; var labelid = options.labelid || fieldid + "_label"; var labelname = $("#" + labelid).html(); var errormessage = options.errormessage || labelname + " must be a valid phone number 10 digits in length."; var evaluationfunction = options.evaluationfunction != undefined ? options.evaluationfunction : function () { var field = $("#" + fieldid); return field.val() == undefined || field.val() == "" || (field.val().replace(/[^0-9]/g, '').length == 10); }; return addValidator(fieldid + "PhoneValidator", fieldid, errormessage, evaluationfunction, { labelid : labelid }); } function addEmailValidator(fieldid, options) { options = options || {}; var labelid = options.labelid || fieldid + "_label"; var errormessage = options.errormessage || "Enter a valid email in the format name@place.type"; var evaluationfunction = options.evaluationfunction != undefined ? options.evaluationfunction : function () { var re = /[a-z0-9!#$%&'*+\/=?^_{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9][a-z0-9-]*[a-z0-9]/; var field = $("#" + fieldid); return field.val() == undefined || field.val() == "" || re.test(field.val().toLowerCase()); }; return addValidator(fieldid + "EmailValidator", fieldid, errormessage, evaluationfunction, { labelid : labelid }); } function notValueValidator(fieldid, value) { return $("#" + fieldid).closest("td").is(":visible") && $('#' + fieldid).val() == value ? false : true; } function radioNotValueValidator(fieldid, value) { return $("#" + fieldid).closest("td").is(":visible") && $('#' + fieldid + ' input[type="radio"]:checked').val() == value ? false : true; } function checkboxNotValueValidator(fieldid, value) { return $("#" + fieldid).closest("td").is(":visible") && $('#' + fieldid + ' input[type="checkbox"]:checked').val() == value ? false : true; } function numericRangeValidator(fieldid, min, max) { return $("#" + fieldid).closest("td").is(":visible") && ($("#" + fieldid).val() < min || $("#" + fieldid).val() > max) ? false : true; } function lengthValidator(fieldid, min, max) { if(!$("#" + fieldid).closest("td").is(":visible")) return true; if($("#" + fieldid).val().length > 0 && min != null && $("#" + fieldid).val().length < min) return false; if($("#" + fieldid).val().length > 0 && max != null && $("#" + fieldid).val().length > max) return false; return true; } function maxLengthMessage(maxLengthElementID, errorMessage) { var maxLength = $('#'+maxLengthElementID).attr("maxlength"); maxLengthMessageWarning(maxLengthElementID, errorMessage, maxLength) } function maxLengthMessageWarning(maxLengthElementID, errorMessage, maxLength) { $('#'+maxLengthElementID).attr("placeholder", "Maximum " + maxLength + " characters"); $('#'+maxLengthElementID).attr("maxlength", maxLength); $('#'+maxLengthElementID).keyup(function() { var textlen = maxLength - $(this).val().length; $('#'+maxLengthElementID).nextAll().remove(); $('#'+maxLengthElementID).after('<div>' + textlen + ' Character(s) Remaining</div>'); if (textlen===0) $('#'+maxLengthElementID).after('<div class="alert-danger">'+errorMessage+'</div>'); }); } function pastDatevalidatorHistoricLimit(fieldid, errormessage, historicLimitInYears) { var field = $("#" + fieldid); addValidator(fieldid+"_DatepastonlyValidator", fieldid, errormessage, function () { var datetarget = new Date(field.val()); var today = new Date(); var todayMinusXYears = new Date(); todayMinusXYears.setFullYear( todayMinusXYears.getFullYear() - historicLimitInYears ); if(datetarget > today || datetarget < todayMinusXYears){ return false; } return true; }); } function pastDatevalidator(fieldid, errormessage) { //Standard historic limit is 50 years pastDatevalidatorHistoricLimit(fieldid, errormessage, 50); } function futureDatevalidator(fieldid, errormessage) { var field = $("#" + fieldid); addValidator(fieldid+"_DatefutureonlyValidator", fieldid, errormessage, function () { var datetarget = new Date(field.val()); var today = new Date(); if(datetarget <= today){ return false; } return true; }); } function compareDatevalidator(startfieldid, endfieldid, errormessage) { var startfield = $("#" + startfieldid); var endfield = $("#" + endfieldid); addValidator(startfieldid+"_DatecompareValidator", startfieldid, errormessage, function () { var startDate = new Date(startfield.val()); var endDate = new Date(endfield.val()); if(startDate >= endDate){ return false; } return true; }); } //# sourceURL=JavascriptValidatorExtensions.js </script> <script> "use strict"; var multiSelectFieldMappings = [ { fieldid: "n311_daysoftheweek", textfieldid: "n311_daysoftheweekportal", optionsfieldid: "n311_daysoftheweekportaloptions" }, { fieldid: "n311_whattimeoftheday", textfieldid: "n311_whattimeofthedayportal", optionsfieldid: "n311_whattimeofthedayportaloptions" }, { fieldid: "n311_whattimeofthedayindwaste", textfieldid: "n311_whattimeofthedayindwasteportal", optionsfieldid: "n311_whattimeofthedayindwasteportaloptions" }, { fieldid: "n311_wheredoyounoticetheproblem", textfieldid: "n311_wheredoyounoticetheproblemportal", optionsfieldid: "n311_wheredoyounoticetheproblemportaloptions" }, { fieldid: "n311_derelictbicycleconditions", textfieldid: "n311_derelictbicycleconditionsportal", optionsfieldid: "n311_derelictbicycleconditionsoptions" }, { fieldid: "n311_whattypeofrecyclingdidyouputoutmultios", textfieldid: "n311_whattypeofrecyclingdidyouputoutmosport", optionsfieldid: "n311_whattypeofrecyclingdidyouputoutmosportopt" }, { fieldid: "n311_howtheitemswereputout", textfieldid: "n311_howtheitemswereputoutmosport", optionsfieldid: "n311_howtheitemswereputoutmosportopt" }, { fieldid: "n311_howdidyouputoutthegarbagemulti", textfieldid: "n311_howdidyouputoutthegarbagemosport", optionsfieldid: "n311_howdidyouputoutthegarbagemosportopt" }, /* { fieldid: "n311_whattypeoforganicsdidyouputoutmulti", textfieldid: "n311_portalwhattypeoforganicsdidyouputout", optionsfieldid: "n311_portalwhattypeoforganicsdidyouputoutopt" },*/ { fieldid: "n311_howdidyouputouttheorganicsmulti", textfieldid: "n311_portalhowdidyouputouttheorganics", optionsfieldid: "n311_portalhowdidyouputouttheorganicsoptions" }/*, { fieldid: "n311_howdidyouputoutyourbranchesorlimbs", textfieldid: "n311_portalhowdidyouputoutyourbranchesorlimbs", optionsfieldid: "n311_prthowdidyouputoutyourbranchesorlimbsmult" }*/ ] </script> <script src="/moment-timezone.js"></script> <script src="/moment-timezone-with-data.js"></script> <script> "use strict"; var fullMonths = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; var shortMonths = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"]; Date.method('toNYCDate', function () { return new Date(moment.tz(this, 'America/New_York').format('YYYY/MM/DD HH:mm:ss')); }); Date.method('getMonthFull', function () { return fullMonths[this.getMonth()]; }); Date.method('getMonthShort', function () { return shortMonths[this.getMonth()]; }); function areDatesEqual(date1, date2) { return date1.getFullYear() == date2.getFullYear() && date1.getMonth() == date2.getMonth() && date1.getDate() == date2.getDate(); } //# sourceURL=JSExt-Date.js </script> <script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/2.3.2/purify.min.js"></script> <script> "use strict"; var KeyCode = { BACKSPACE : 8, TAB : 9, ENTER : 13, DELETE : 46 } function clearTwoOptionField(fieldid){ $('#' + fieldid + ' input[type=radio]').removeAttr('checked'); } function updateStartEndDropdown(start,end){ var startfield = $("#" + start); var endfield = $("#" + end ); var endfieldoption = $("#" + end + " option"); var startvalue = startfield.val(); var selectedend = endfield.val(); endfieldoption.each(function () { var endvalue = $(this).val(); if (startvalue >= endvalue && endvalue != "") { $(this).attr("disabled", true); if(selectedend == endvalue) endfield.prop("selectedIndex", -1); } else { $(this).attr("disabled", false); } }); } function daysDisabled(fieldid,days){ var datepicker = fieldid.siblings(".datetimepicker").data("DateTimePicker"); if (datepicker != undefined) { datepicker.daysOfWeekDisabled(days); } } function readOnlyField(fieldid) { var field = $("#" + fieldid); if(field.is(".picklist") || field.is(".boolean-radio")) { field.children().hide(); var selectedid = field.find("input:checked").attr("id"); field.find('label[for="' + selectedid + '"]').show(); } else if(field.siblings(".lookup").length > 0) { field.siblings(".input-group-btn").hide(); field.siblings(".input-group-btn").closest(".input-group").width("100%"); field.siblings(".lookup").attr("disabled", "disabled"); } else { field.attr("disabled", "disabled"); field.addClass("readonly"); } } function maxLengthField(fieldid, maxlength) { $("#" + fieldid).attr("maxlength", maxlength); } function phoneNumberField(fieldid, options) { var field = $("#" + fieldid); options = options || {}; numericField(fieldid); addPhoneValidator(fieldid, options); } function emailField(fieldid, options) { var field = $("#" + fieldid); options = options || {}; addEmailValidator(fieldid, options); } function textField(fieldid, options) { var field = $("#" + fieldid); if(field.length <= 0) return; options = options || {}; var stripCharacters = options.stripCharacters || ""; if (stripCharacters != "") { field.keyup(function () { $(this).val($(this).val().replace(new RegExp('[' + stripCharacters + ']','g'), '')); }); } var trimWhitespace = options.trimWhitespace || false; if (trimWhitespace) { field.change(function () { $(this).val($(this).val().trim()); }); } } function numericField(fieldid) { var field = $("#" + fieldid); if(field.length <= 0) return; field.keydown(function (e) { var key = e.charCode || e.keyCode || 0; if(key == KeyCode.BACKSPACE || key == KeyCode.TAB || key == KeyCode.ENTER || key == KeyCode.DELETE || (key >= 35 && key <= 40) || (key >= 48 && key <= 57) || (key >= 96 && key <= 105)) return true; return false; }); if(field.val().length > 0) field.val(parseInt(field.val())); field.change(function () { $(this).val($(this).val().replace(/[^0-9]/g, '')); }); } function pastOnlyDateField(fieldid) { var field = $("#" + fieldid); var datepicker = field.siblings(".datetimepicker").data("DateTimePicker"); console.log("sr created on date", ""); var createdOnDate = moment(moment.utc("").format()); var createdOnLocalTimeZone = createdOnDate._d; console.log("sr created on date localtime", createdOnLocalTimeZone); if(datepicker != undefined){ datepicker.maxDate(createdOnLocalTimeZone); } } function futureOnlyDateField(fieldid) { var field = $("#" + fieldid); var datepicker = field.siblings(".datetimepicker").data("DateTimePicker"); console.log("sr created on date", ""); var createdOnDate = moment(moment.utc("").format()); var createdOnLocalTimeZone = createdOnDate._d; console.log("sr created on date localtime", createdOnLocalTimeZone); if(datepicker != undefined){ datepicker.minDate(createdOnLocalTimeZone); } } function rangeDatePickers(frompicker, topicker) { frompicker.on("dp.change", function () { var isnull = topicker.data("DateTimePicker").date() == null; if(frompicker.data("DateTimePicker").date() != null) topicker.data("DateTimePicker").minDate(frompicker.data("DateTimePicker").date()); else topicker.data("DateTimePicker").minDate(false); if(isnull) topicker.data("DateTimePicker").date(null); }); topicker.on("dp.change", function () { var isnull = frompicker.data("DateTimePicker").date() == null; if(topicker.data("DateTimePicker").date() != null) frompicker.data("DateTimePicker").maxDate(topicker.data("DateTimePicker").date()); else frompicker.data("DateTimePicker").maxDate(moment()); if(isnull) frompicker.data("DateTimePicker").date(null); }); } function getFieldDatePicker(fieldid) { return $("#" + fieldid).siblings(".datetimepicker"); } function showSection(sectionid) { $('.section[data-name="' + sectionid + '"]').show(); $('.section[data-name="' + sectionid + '"]').siblings('.section-title').show(); } function showSections(sectionids) { sectionids.forEach(function (sectionid) { showSection(sectionid); }); } function hideSection(sectionid) { $('.section[data-name="' + sectionid + '"]').hide(); $('.section[data-name="' + sectionid + '"]').siblings('.section-title').hide(); } function hideSections(sectionids) { sectionids.forEach(function (sectionid) { hideSection(sectionid); }); } function showTab(tabid) { $('.tab[data-name="' + tabid + '"]').show(); } function hideTab(tabid) { $('.tab[data-name="' + tabid + '"]').hide(); } function fieldExists(fieldid) { return $('#' + fieldid).length > 0; } function fadeInField(fieldid, speed) { $('#' + fieldid).closest("td").fadeIn(speed); } function fadeOutField(fieldid, speed) { $('#' + fieldid).closest("td").fadeOut(speed); } function fadeInFields(fieldids, speed) { fieldids.forEach(function (fieldid) { fadeInField(fieldid); }); } function fadeOutFields(fieldids, speed) { fieldids.forEach(function (fieldid) { fadeOutField(fieldid); }); } function toggleField(fieldid, doShow) { if (doShow) showField(fieldid); else hideField(fieldid); } function showField(fieldid) { $('#' + fieldid).closest("td").show(); } function hideField(fieldid) { $('#' + fieldid).closest("td").hide(); } function hideFieldIfEmpty(fieldid) { if($('#' + fieldid).is('select') && $('#'+fieldid+'option').length <=0) { hideField(fieldid); } else if( $('#'+fieldid+'_select').length===1 && $('#'+fieldid+'_select').is('select') && $('#'+fieldid+'_select option').length === 0) { hideField(fieldid); } else if($('#' + fieldid).is('input') && !$('#' + fieldid).val()) { hideField(fieldid); } } function toggleFields(fieldids, doShow) { if (doShow) showFields(fieldids); else hideFields(fieldids); } function showFields(fieldids) { fieldids.forEach(function (fieldid) { showField(fieldid); }); } function hideFields(fieldids) { fieldids.forEach(function (fieldid) { hideField(fieldid); }); } function isFieldVisible(fieldid) { return $("#" + fieldid).closest("td").is(":visible"); } function showFieldsInSection(sectionid) { $('.section[data-name="' + sectionid + '"] td').show(); } function hideFieldsInSection(sectionid) { $('.section[data-name="' + sectionid + '"] td').hide(); } function setFormReadOnly(form) { debugger; //Remove validators form.find(".validators").remove(); //Disable all inputs form.find('input, textarea, button, select').attr("disabled", "disabled").addClass("readonly"); //Remove all buttons from the form form.find('.input-group-btn, .form-custom-actions, #EntityFormPanel .actions').remove(); //Remove map lookup classes form.find('.map-lookup-field').removeClass("map-lookup-field"); //Remove address generators form.find('#n311_addressgenerator').closest('td').remove(); //Remove required asterisks form.find('.info.required').removeClass("required"); //Remove and fields that are empty form.find('input.form-control, textarea.form-control, select.form-control').each(function () { if($(this).val() == null || $(this).val().length <= 0) { //hideField($(this).attr("id")); } }); //show textareas as text form.find('textarea.form-control').each(function () { $(this).hide(); $(this).parent().prepend($(this).val()); }); //Show lookups as text form.find('input.lookup').each(function () { $(this).replaceWith($(this).val()); $(this).siblings("input").remove(); }); //Set datetime fields to readonly form.find('input.form-control.datetime').each(function () { if($(this).val()) var date = new Date($(this).val()).toString("M/d/yyyy hh:mm tt"); else var date = ""; $(this).hide(); $(this).after('<input type="text" class="text form-control readonly" value="' + date + '">'); }); //Set radios to readonly form.find('.control > .picklist, .control > .boolean-radio').each(function () { //readOnlyField($(this).attr("id")); }); form.find('.control > .boolean-radio').each(function () { if($(this).find("input[type='radio']:checked").length <= 0) { //hideField($(this).attr("id")); } }); //Set multi selects to readonly multiSelectFieldMappings.forEach(function (multi) { if(form.find("#" + multi.textfieldid).length > 0 && form.find("#" + multi.optionsfieldid).length > 0) { form.find("#" + multi.textfieldid).siblings().hide(); var vals = form.find("#" + multi.textfieldid).val().split(","); var names = []; vals.forEach(function (val) { names.push(form.find("#" + multi.optionsfieldid + " option[value='" + val + "']").html()); }); form.find("#" + multi.textfieldid).parent().prepend("<div>" + names.join(', ') + "</div>"); form.find("#" + multi.textfieldid).hide(); form.find("#" + multi.optionsfieldid).remove(); } }); } function GenerateStepSummary(element) { var stepsummary = $('<div class="crmEntityFormView"></div>'); $("#sr-content").find(".form-control,.section-title,.include-in-summary, .boolean-radio, .entity-grid, table#ServiceActivity").each(function () { if($(this).is(".exclude-from-summary")) return; else if($(this).is(".form-control")) { if(!$(this).closest("td").is(":visible") || $(this).val() == undefined || $(this).val() == "" || $(this).is(".datetime")) return; var label = $(this).closest("td").find(".info label").first().clone(); var labelValue = $(label).text(); var value = $(this).val(); if($(this).is(".multiselecttext")){ value = $(this).attr("textval"); } else if($(this).is("select")) value = $(this).find("option:selected").html(); stepsummary.append(label); label.show(); stepsummary.append($(DOMPurify.sanitize('<div style="margin-bottom: 10px;" aria-label="' + labelValue + ' - ' + value + '" tabindex="0">' + value + '</div>'))); } else if($(this).is(".section-title,.include-in-summary")) { stepsummary.append($(this).clone()); } else if($(this).is(".boolean-radio")) { var label = $(this).closest("td").find(".info label").first().clone(); var labelValue = $(label).text(); var valueid = $(this).find("input[type='radio']:checked").attr("id"); value = $(this).find("label[for='" + valueid + "']"); var valueHTML = value.html(); var valueText = value.text(); if(!$(this).closest("td").is(":visible") || valueHTML == "" || valueHTML == null) return; stepsummary.append(label); stepsummary.append($(DOMPurify.sanitize('<div style="margin-bottom: 10px;" aria-label="' + valueText + '" tabindex="0">' + valueHTML + '</div>'))); } else if($(this).is(".subgrid")) { var label = $(this).closest("td").find(".info label").first().clone(); var grid = $(this).find(".view-grid").clone(); if($(this).find(".view-grid > table > tbody > tr").length <= 0) return; grid.find(".dropdown").remove(); grid.find("th.sort-enabled").each(function () { $(this).find("a").children().remove(); $(this).html($(this).find("a").html()); }); grid.attr("id", $(this).parent().attr("id")); stepsummary.append(label); stepsummary.append(grid); } else if ($(this).is("table#ServiceActivity")){ var problemDetailId = $("#n311_problemdetailid"); // var problemId = $("#n311_problemid"); // do not generate the summary by default var generateSummary = false; // generate the summary if problem details id field has a value and it's in the enabled attachments list if(problemDetailId.length && problemDetailId.val() && AttachmentEnabledProblemDetails.toString().indexOf(problemDetailId.val()) > -1) { generateSummary = true; } // generate the summary if problem id field has a value and it's in the enabled attachments list // if(problemId.length && problemId.val() && AttachmentEnabledProblemDetails.toString().indexOf(problem.val()) > -1) { // generateSummary = true; // } // only generate the summary if the attachments display is controlled externally, or the currently selected problem or problem detail has attachments enabled. if((typeof ForceAttachmentsEnabled === "boolean" && ForceAttachmentsEnabled) || generateSummary) { // custom implementation in generate summary to show attachments var label = $("label[for='notescontrol']").first().clone(); var grid = $(this).clone(); if(grid.find('tbody > tr').length > 0){ grid.find("button[aria-label='action menu']").remove(); stepsummary.append(label); stepsummary.append(grid); } } } }); return stepsummary; } function addFieldTooltip(fieldid, text) { $("#" + fieldid).closest("td").attr("data-toggle", "tooltip"); $("#" + fieldid).closest("td").attr("title", text); $("#" + fieldid).closest("td").tooltip(); } //# sourceURL=jsFieldExtensions.js </script> <script> "use strict"; function DateInputBox(_parentelement, _options) { var _self = this; _options = _options || {}; var _dateinputgroup = $('<div class="input-group date"></div>'); var _dateinput = $('<input />').attr({ "data-date-format": "M/D/YYYY", placeholder: _options.placeholdertext || "", "aria-label": _options.arialabel || (!!(_options.placeholdertext)) ? _options.placeholdertext + " Date" : "", class: "form-control number-input-without-arrows exclude-from-summary" }); var _clearbutton = $('<span class=" input-group-addon glyphicon glyphicon-remove-sign textbox-clear-button cursor-pointer"></span>'); _clearbutton.hide(); _clearbutton.click(function (e) { _clearbutton.hide(); _dateinputgroup.data("DateTimePicker").date(null); _dateinputgroup.data("DateTimePicker").toggle() }); _dateinputgroup.append(_dateinput); _dateinputgroup.append(_clearbutton); _dateinputgroup.append('<span title="Choose a Date" class="input-group-addon cursor-pointer map-btn"><span class="glyphicon glyphicon-calendar"></span></span>'); _dateinputgroup.datetimepicker({ locale: 'en-ie', defaultDate: false, maxDate: moment(), showClose: true, widgetParent: _options.widgetparentelement || null }); _dateinputgroup.data("DateTimePicker").date(null); _dateinputgroup.on('dp.change', function(e){ if(_dateinputgroup.data("DateTimePicker").date() == null) { _clearbutton.hide(); } else { _clearbutton.show(); } }); _parentelement.append(_dateinputgroup); _self.getDate = function() { return _dateinputgroup.data("DateTimePicker").date(); } _self.getInputGroup = function() { return _dateinputgroup; } } MapDateFilter.inherits(MapFilter); function MapDateFilter(_fromparamname, _toparamname, _options) { var _self = this; MapFilter.prototype.constructor.call(_self); _options = _options || {}; var _fromdatediv = $('<div style="margin-bottom: 5px;"></div>') var _todatediv = $("<div></div>") var _fromdateinput = null; var _todateinput = null; _self.initialize = function () { _fromdateinput = new DateInputBox(_fromdatediv, { placeholdertext: "From", arialabel: "From - Date", widgetparentelement: $(".entitypinmap-filters-container")}); _todateinput = new DateInputBox(_todatediv, { placeholdertext: "To", arialabel: "To - Date", widgetparentelement: $(".entitypinmap-filters-container")}); rangeDatePickers(_fromdateinput.getInputGroup(), _todateinput.getInputGroup()); } _self.getFilterHTMLElement = function () { var element = $("<div id='dateMapFilter'></div>"); if(_options.label != undefined && _options.label.length > 0) element.append($('<label class="map-filter-label">' + _options.label + '</label>')); element.append(_fromdatediv); element.append(_todatediv); return element; } _self.getFetchParameters = function () { var params = {}; if(_fromdateinput.getDate() != null) params[_fromparamname] = _fromdateinput.getDate().format('YYYY-MM-DD'); if(_todateinput.getDate() != null) params[_toparamname] = _todateinput.getDate().format('YYYY-MM-DD'); return params; } _self.validatePin = function (pin) { return true; } } </script> <script> "use strict"; MapDropdownFilter.inherits(MapFilter); function MapDropdownFilter(_paramname, _options) { var _self = this; MapFilter.prototype.constructor.call(_self); _options = _options || {}; _options.default = _options.default != undefined ? _options.default : null; _options.readonly = _options.readonly != undefined ? _options.readonly : false; _options.availableoptions = _options.availableoptions != undefined ? _options.availableoptions : []; _options.blanklabel = _options.blanklabel != undefined ? _options.blanklabel : ""; var _isFirstLoad = true; var _select = $('<select />').attr({ value : _options.value || "", class: "form-control exclude-from-summary", id: _options.label.replace(/\s/g, ''), //aria-labelledby: 'filterLabel' + _options.label.replace(/\s/g, '') }); if(_options.readonly) { _select.attr("disabled", "true"); _select.addClass("readonly"); } var _loadingspinner = $('<div id="loadingspinner_mapdropdownfilter" class="loading-spinner-small-containter lds-css ng-scope"> <div class="lds-dual-ring"> <div> </div> </div></div>'); _select.change(function() { _self.onSelectionChanged(); }); _self.getValue = function () { return _select.val() || null; } _self.onSelectionChanged = function () { } _self.setLoading = function (loading) { if(loading) { _select.css("visibility", "hidden"); _loadingspinner.show(); } else { _select.css("visibility", "visible"); _loadingspinner.hide(); } } _self.setLoading(true); _self.addDropdownFilterOptions = function(options) { _select.empty(); _select.append('<option value="">' + _options.blanklabel + '</option>'); if(_options.availableoptions.length > 0) options = $.grep(options, function (option) { return _options.availableoptions.indexOf(option.value) >= 0; }); options.forEach(function(option) { _select.append('<option value="' + option.value + '">' + option.name + '</option>'); }); _self.setLoading(false); _select.change(); if(_isFirstLoad && _options.default != null) { _select.val(_options.default); _self.onSelectionChanged(); } _isFirstLoad = false; } _self.getFilterHTMLElement = function () { var element = $("<div></div>"); if(_options.label != undefined && _options.label.length > 0) element.append($('<label class="map-filter-label" for="' + _select.attr('id') + '" id="' + 'filterLabel' + _options.label.replace(/\s/g, '') + '">' + _options.label + '</label>')); element.append(_loadingspinner); element.append(_select); return element; } var _isFirstFetch = true; _self.getFetchParameters = function () { var params = {}; if(_self.getValue() != null) params[_paramname] = _self.getValue(); else if(_options.availableoptions.length > 0) params[_paramname] = _options.availableoptions.toString(); if(_isFirstFetch && _options.default != null) params[_paramname] = _options.default; _isFirstFetch = false; return params; } } </script> <script> "use strict"; MapOptionSetFilter.inherits(MapDropdownFilter); function MapOptionSetFilter(_paramname, _entityname, _attribute, _options) { var _self = this; MapDropdownFilter.prototype.constructor.call(_self, _paramname, _options); $.ajax({ url: "/get-optionset-filter-options/", data: { entity: _entityname, attribute: _attribute }, dataType: "json" }).success(function (entities) { _self.addDropdownFilterOptions(entities); }); } </script> <script> "use strict"; MapLookupFilterBase.inherits(MapDropdownFilter); function MapLookupFilterBase(_paramname, _entityname, _idattribute, _nameattribute, _options) { var _self = this; _options.default = _options.default != undefined ? _options.default : null; _options.readonly = _options.readonly != undefined ? _options.readonly : false; MapDropdownFilter.prototype.constructor.call(_self, _paramname, _options); _self.addLookupFilterOptions = function () { _self.setLoading(true); $.ajax({ url: "/get-lookup-filter-options/", data: { lookupentity: _entityname, lookupidattribute: _idattribute, lookupdisplayattribute: _nameattribute, type: _options != undefined ? _options.type || "" : "" }, dataType: "json" }).success(function (entities) { _self.addDropdownFilterOptions(entities); }); } _self.setOptionToReadOnlyDefault = function() { _self.setLoading(true); $.ajax({ url: "/api-get-name-by-id/", data: { entityname: _entityname, id: _options.default }, dataType: "json" }).success(function (entity) { console.log("Default Entity", entity) _self.addDropdownFilterOptions([{ value: entity.id, name: entity.name }]); }); } if(_options.readonly) _self.setOptionToReadOnlyDefault(); } </script> <script> "use strict"; MapLookupFilter.inherits(MapLookupFilterBase); function MapLookupFilter(_paramname, _entityname, _idattribute, _nameattribute, _options) { var _self = this; _options.default = _options.default != undefined ? _options.default : null; _options.readonly = _options.readonly != undefined ? _options.readonly : false; MapLookupFilterBase.prototype.constructor.call(_self, _paramname, _entityname, _idattribute, _nameattribute, _options); if(!(_options.readonly)) _self.addLookupFilterOptions(); } </script> <script> "use strict"; MapLinkedLookupFilter.inherits(MapLookupFilterBase); function MapLinkedLookupFilter(_paramname, _entityname, _idattribute, _nameattribute, _parentfilter, _parentfilterattribute, _options) { var _self = this; _options.default = _options.default != undefined ? _options.default : null; _options.readonly = _options.readonly != undefined ? _options.readonly : false; MapLookupFilterBase.prototype.constructor.call(_self, _paramname, _entityname, _idattribute, _nameattribute, _options); _parentfilter.onSelectionChanged = function() { _self.addLookupFilterOptions(); }; _self.addLookupFilterOptions = function () { if(_options.readonly) return; _self.setLoading(true); $.ajax({ url: "/get-lookup-filter-options/", data: { lookupentity: _entityname, lookupidattribute: _idattribute, lookupdisplayattribute: _nameattribute, parentfilterattribute: _parentfilterattribute, parentfiltervalue: _parentfilter.getValue(), type: _options != undefined ? _options.type || "" : "" }, dataType: "json" }).success(function (entities) { _self.addDropdownFilterOptions(entities); }); } } </script> <script> "use strict"; function FilterManager(_url, _filters, _options) { var _self = this; _options = _options || {}; _filters = _filters || []; _self.getBingMap = function () { return null; } _self.getFiltersHTMLElement = function() { var container = $('<div class="entitypinmap-filters-list"></div>'); _filters.forEach(function (filter) { var item = $('<div class="entitypinmap-filters-item"></div>').append(filter.getFilterHTMLElement()); container.append(item); }); return container; } _self.initialize = function () { _filters.forEach(function (filter) { filter.getBingMap = function () { return _self.getBingMap(); }; filter.initialize(); }); } _self.getEntityPins = function(callback, data) { Logs.EntityPinMapLog.log("Get Entity Pins From Filter Manager", _self); data = data || {}; for(var key in _options.data) { Logs.EntityPinMapLog.log("Adding Fetch Data Parameter", key); data[key] = _options.data[key]; } _filters.forEach(function (filter) { Logs.EntityPinMapLog.log("Get Fetch Parameters From Filter", filter); var params = filter.getFetchParameters(); for(key in params) { Logs.EntityPinMapLog.log("Adding Fetch Data Parameter", key); data[key] = params[key]; } }); Logs.EntityPinMapLog.log("Fetch Data Parameters", data); $.ajax({ url: _url, data: data }).success(function (data) { var jsonpins = JSON.parse(data); var pins = []; Logs.EntityPinMapLog.log("Parse JSON to pins", jsonpins); jsonpins.forEach(function (jsonpin) { var pin = getEntityPinFromJSON(jsonpin); var valid = true; _filters.forEach(function (filter) { if(!filter.validatePin(pin)) valid = false; }); if(valid) pins.push(pin); }); Logs.EntityPinMapLog.log("Filter Returned Pins", pins); callback(pins); }); } } //# sourceURL=FilterManager.js </script> <style> .infobox-body { max-height: 400px !important; max-width: 300px !important; } .infobox-info { max-height: 400px !important; max-width: 300px !important; } </style> <script> "use strict"; /** * Constructor that creates a new entity pin infobox. This class can be overriden to create new EntityPinInfoBox classes. */ function EntityPinInfoBox() { var _self = this; var _infobox = new Microsoft.Maps.Infobox(); var _pins = []; var _location = null; var _map = null; /** * Event that triggers when the info boxes action label is clicked. * @params {Object} pin - The pushpin that was selected. */ _self.selectAction = function (pin) { return null; } /** * Event that triggers when a pin is centered on. * @params {Object} pin - The pushpin that was centered on. */ _self.onCenterPin = function (pin) { } /** * Returns the title of the infobox when there a list of pins to display. * @params {Object[]} pins - The list of pushpins to display. */ _self.getEntityPinListTitle = function (pins) { return "Cluster of " + pins.length + " pins"; } /** * Called to build a new entity pin list when there are multiple entity pins to display info for. * @params {Object[]} pins - The list of pushpins to display. */ _self.buildEntityPinListHTML= function(pins) { var container = $('<div></div>'); var title = $('<div class="entitypin-infobox-title" tabindex="0" aria-label="' + _self.getEntityPinListTitle(pins) + '"></div>').html(_self.getEntityPinListTitle(pins)); var content = $('<div class="entitypin-infobox-content"></div>'); container.append(title); container.append(content); _self.buildEntityPinListContent(pins, content); return container; } /** * Returns the content for an entity list infobox. This function can be overridden to define the appearance of the entity list infobox. * @params {Object[]} pins - The list of pushpins to display. * @params {JQuery} content - The container to add content to. */ _self.buildEntityPinListContent = function(pins, content) { pins.forEach(function (pin) { var pinlink = $('<a class="cursor-pointer" tabindex="0" aria-label="' + pin.getLabel() + ' - ' + pin.getSubLabel() + '">').html(pin.getLabel()).click(function () { var mapPinPromise = new Promise(function(resolve, reject) { setLocationFromPin(pin); resolve('map ready'); }); mapPinPromise.then(function(msg) { _self.buildInfoBox([pin]); }); }).ariaClick(); var subtitle = $('<div class="entitypin-infobox-subtitle" style="padding: 0;margin-bottom: 5px;">' + pin.getSubLabel() + '</div>'); content.append(pinlink); content.append(subtitle); }); return content; } /** * Called to build a new entity pin infobox when there is a single entity pin to display info for. * @params {Object} pin - The pushpin to display. */ _self.buildEntityPinHTML = function(pin) { var container = $('<div class="entitypin-infobox-div"></div>'); var title = $('<div class="entitypin-infobox-title"></div>').html(pin.getLabel()); var subtitle = $('<div class="entitypin-infobox-subtitle"></div>').html(pin.getSubLabel()); var content = $('<div class="entitypin-infobox-content"></div>'); var actionbuttons = $('<div class="entitypin-infobox-action-buttons"></div>'); container.append(title); container.append(subtitle); container.append(content); container.append(actionbuttons); _self.buildEntityPinContent(pin, content); var centerbutton = $('<a class="entitypin-infobox-center-button cursor-pointer"></a>'); centerbutton.click(function () { _self.onCenterPin(pin); }).ariaClick(); actionbuttons.append(centerbutton); if(_self.selectAction() != null) { var actionbutton = $('<a class="entitypin-infobox-action-button cursor-pointer">' + _self.selectAction().getLabel() + '</a>'); actionbutton.click(function () { _self.selectAction().getFunction(pin).call(_self, pin); }).ariaClick(); actionbuttons.append(actionbutton); } if(_pins.length > 1) { var backbutton = $('<a class="entitypin-infobox-back-button cursor-pointer">Back</a>'); backbutton.click(function () { var mapPinPromise = new Promise(function(resolve, reject) { _infobox.setMap(_map); _infobox.setLocation(_location); resolve('map ready'); }); mapPinPromise.then(function(msg) { _self.buildInfoBox(_pins); }); }).ariaClick(); actionbuttons.append(backbutton); } return container; } /** * Returns the content for an entity pin infobox. This function can be overridden to define the appearance of the single entity pin infobox. * @params {Object} pin - The pushpin to display. * @params {JQuery} content - The container to add content to. */ _self.buildEntityPinContent = function(pin, content) { return content; } /** * Builds an infobox for the input list of pins. If there are multiple pins an entity list infobox will be rendered. If there is a single pin an entity pin infobox will be rendered. Other functions are used to define the appearance of these infoboxes. * @params {Object[]} pins - The pushpins to display an infobox for. */ _self.buildInfoBox = function(pins) { var container = $('<div></div>'); if(pins.length > 1) container.append(_self.buildEntityPinListHTML(pins)); else if(pins.length == 1) container.append(_self.buildEntityPinHTML(pins[0])); container.hide(); $('body').append(container); var boxHeight = container.outerHeight(true); var boxWidth = container.outerWidth(true); console.log("container height ", container.outerHeight(true), "- pins -", pins, " - ", container); _infobox.setOptions({ description: '<div id="new-info-box" class="entitypin-infobox" style="height:' + boxHeight + 'px"></div>', visible: true, showPointer: true }); var infobox = $('#new-info-box'); infobox.removeAttr("id"); infobox.append(container); container.show(); } /** * Hides the infobox. */ _self.hide = function () { if(_infobox != null){ _infobox.setMap(null); } } /** * Shows the infobox given a set of pins, a location, and a map. * @params {Object[]} pins - The pushpins to display an infobox for. * @params {Object} location - Coordinates on the map where the info box is to be placed. * @params {Object} map - The Bing map to display the infobox on. */ _self.show = function (pins, location, map) { _pins = pins; _map = map; _location = location; var mapPinPromise = new Promise(function(resolve, reject) { _infobox.setMap(_map); _infobox.setLocation(_location); resolve('map ready'); }); mapPinPromise.then(function(msg) { _self.buildInfoBox(pins); }); } /** * Moves the Bing infobox to the location of the pin. * @params {Object} pin - The pushpin to move the infobox to. */ function setLocationFromPin(pin) { if(_map != null) { _infobox.setMap(_map); _infobox.setLocation(pin.getLocation()); } } } //# sourceURL=mapScriptsEntityPinInfoBox.js </script> <script> "use strict"; /** * Constructor that creates a new entity pin infobox. This class can be overriden to create new EntityPinInfoBox classes. */ function EntityPinListBox() { var _self = this; /** * Builds and returns the list box element. This function can be overriden to define the appearance of the listbox class. * @params {Object[]} pins - The list of pushpins to display. */ _self.buildListBox = function(pins) { var list = $('<div class="entitypinmap-list-box"></div>'); pins.forEach(function (pin) { var itemdiv = $('<div class="entitypinmap-list-box-item" tabindex="0" aria-label="' + pin.getLabel() + ' - ' + pin.getSubLabel() + '"></div>'); itemdiv.hover(function () { _self.onItemHover(pin); }); var link = $('<h4 class="title cursor-pointer"><a>' + pin.getLabel() + '</a></h4>'); link.click(function () { _self.onItemClick(pin); }).ariaClick(); itemdiv.click(function () { _self.onItemClick(pin); }).ariaClick(); itemdiv.append(link); itemdiv.append('<span class="subtitle">' + pin.getSubLabel() + '</span>'); if(_self.selectAction() != null) { var actionbutton = $('<a class="entitypin-infobox-action-button cursor-pointer" tabindex="0" aria-label="' + _self.selectAction().getLabel() + ' - ' + pin.getLabel() + '">' + _self.selectAction().getLabel() + '</a>'); actionbutton.click(function () { _self.selectAction().getFunction(pin).call(_self, pin); }).ariaClick(); itemdiv.append(actionbutton); } list.append(itemdiv); }); return list; } /** * Event that triggers when the info boxes action label is clicked. * @params {Object} pin - The pushpin item that was selected. */ _self.selectAction = function (pin) { return null; } /** * Event that triggers when an item is hovered over. * @params {Object} pin - The pushpin item that was hovered over. */ _self.onItemHover = function (pin) { } /** * Event that triggers when an item in the list is clicked. * @params {Object} pin - The pushpin item that was clicked. */ _self.onItemClick = function (pin) { } } //# sourceURL=EntityPinListBox.js </script> <div id="entitypinmap-loading-spinner-container" class="entitypinmap-loading-spinner-container" style="display:none"> <!-- Loading Spinner --> <div id="entitypinmap-loading-spinner" class="loading-spinner-container lds-css ng-scope"> <div class="lds-spinner" style="100%;height:100%"> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> </div> <h4 class="loading-text">Loading Map<span class="loadingdots"><span>.</span><span>.</span><span>.</span></span></h4> </div> </div> <script> "use strict"; (function( $ ) { $.fn.ariaClick = function() { $(this).keypress(function (e) { if (e.which == 13) { $(this).click(); return false; } }); return this; }; }( jQuery )); /** * Defines an entity pin map action with a label for the action and a function to perform when the label is clicked. * @param {string} _label - The label of the action. * @param {function} _function - The function to perform once the action is triggered. */ function EntityPinMapSelectAction (_label, _function) { var _self = this; _self.getLabel = function () { return _label; }; _self.getFunction = function () { return _function; }; } /** * A constructor for the EntityPinMap that accepts a parent element, a filter manager, and set of options. * @param {JQuery} _parentelement - The parent element the map will be appended to. * @param {Object} _filtermanager - The filter manager containing the map filters to be used. * @param {Object[]} _parentelement - An object containing configuration options for the map. */ EntityPinMap.inherits(NYCMap); function EntityPinMap(_parentelement, _filtermanager, _inputoptions) { var _self = this; _inputoptions = _inputoptions || {}; var _pins = []; var _clusterlayer = null; var _action = _inputoptions.action || null; var _makeinitialsearch = _inputoptions.makeinitialsearch != undefined ? _inputoptions.makeinitialsearch : true; //Update the filtermanager bingmap function to return the bing map. _filtermanager.getBingMap = function () { return _self.getBingMap(); } //Get the info box from the input options. var _infobox = _inputoptions.infobox || new EntityPinInfoBox(); //Update the infobox's select action. _infobox.selectAction = function (pin) { return _action; } //Center on a pin when it is clicked in an infobox. _infobox.onCenterPin = function (pin) { centerOnPin(pin); } //Get the list box from the input options. var _listbox = _inputoptions.listbox || new EntityPinListBox(); //Update the listbox's select action. _listbox.selectAction = function (pin) { return _action; } _listbox.onItemHover = function (pin) { } //Show infobox and center on pin when it is selected in the list box. _listbox.onItemClick = function (pin) { showPinInfoBox(pin); centerOnPin(pin); } var _showfilters = _inputoptions.showfilters != undefined ? _inputoptions.showfilters : true; var _showlistbox = _inputoptions.showlistbox != undefined ? _inputoptions.showlistbox : true; var _container = $('<div class="entitypinmap-container"></div>'); var _mapdiv = $('<div class="col-md-6 entitypinmap-map-div"></div>'); var _mapparentelement = $('<div class="map-parent-element"></div>'); _mapdiv.append(_mapparentelement); var _filtersdiv = $('<div class="col-md-3 entitypinmap-filters-container open"></div>'); var _listboxdiv = $('<div class="col-md-3 entitypinmap-listbox-container open" aria-label="List of found Service Requests" tabindex="0"></div>'); var _togglefiltersdiv = $('<div class="entitypinmap-toggle-panel left open" tabindex="0" aria-label="Toggle Filter Pane"></div>'); var _togglefiltersmobilediv = $('<div class="entitypinmap-toggle-panel-mobile top open"></div>'); var _togglelistboxdiv = $('<div class="entitypinmap-toggle-panel right open" tabindex="0" aria-label="Toggle List Pane"></div>'); var _togglelistmobilediv = $('<div class="entitypinmap-toggle-panel-mobile bottom open"></div>'); /* Set up logic to show or hide the filters and listbox using the toggle arrows */ var togglepanel = function (togglediv, toggledivother, paneldiv) { if(togglediv.hasClass("open")) { togglediv.removeClass("open"); toggledivother.removeClass("open"); paneldiv.removeClass("open"); } else { togglediv.addClass("open"); toggledivother.addClass("open"); paneldiv.addClass("open"); } updateMapDivSize(); } _togglefiltersdiv.click(function () { togglepanel(_togglefiltersdiv, _togglefiltersmobilediv, _filtersdiv); }).ariaClick(); _togglefiltersmobilediv.click(function () { togglepanel(_togglefiltersmobilediv, _togglefiltersdiv, _filtersdiv); }).ariaClick(); _togglelistboxdiv.click(function () { togglepanel(_togglelistboxdiv, _togglelistmobilediv, _listboxdiv); }).ariaClick(); _togglelistmobilediv.click(function () { togglepanel(_togglelistmobilediv, _togglelistboxdiv, _listboxdiv); }).ariaClick(); //Set up loading spinner to show while searching. var _loadingspinner = $('#entitypinmap-loading-spinner-container').clone(); if(_makeinitialsearch) _loadingspinner.show(); if(_showfilters) { _mapdiv.prepend(_togglefiltersmobilediv); _mapdiv.prepend(_togglefiltersdiv); _container.append(_filtersdiv); } _mapdiv.append(_togglelistmobilediv); if(_showlistbox) _mapdiv.append(_togglelistboxdiv); _container.append(_mapdiv); if(_showlistbox) _container.append(_listboxdiv); _mapdiv.append(_loadingspinner); _parentelement.append(_container); updateMapDivSize(); //Update the map div size when the filters or listbox change visible status function updateMapDivSize() { _mapdiv.removeClass("col-md-6").removeClass("col-md-9").removeClass("col-md-12"); if((_showfilters && _togglefiltersdiv.hasClass("open")) && (_showlistbox && _togglelistboxdiv.hasClass("open"))) { _mapdiv.addClass("col-md-6"); } else if((_showfilters && _togglefiltersdiv.hasClass("open")) || (_showlistbox && _togglelistboxdiv.hasClass("open"))) { _mapdiv.addClass("col-md-9"); } else { _mapdiv.addClass("col-md-12"); } } //Add filters and search button _filtersdiv.append(_filtermanager.getFiltersHTMLElement()); _filtermanager.initialize(); var _filterSearchButton = $('<input />').attr({ value: "Search", type: "button", class: "button btn btn-primary" }).click(searchEntityPins.bind(null, false)); var _searchButtonContainer = $('<div class="entitypinmap-filters-search-button-container"></div>'); _searchButtonContainer.append(_filterSearchButton); _filtersdiv.append(_searchButtonContainer); NYCMap.prototype.constructor.call(_self, _mapparentelement, _inputoptions); /** * Load the map and perform an initial search if applicable. */ var _superLoadMap = _self.loadMap; _self.loadMap = function () { _superLoadMap.call(_self); console.log("_makeinitialsearch", _makeinitialsearch); if(_makeinitialsearch) searchEntityPins(true); } /** * Event called once the map is loaded. */ _self.onMapLoaded = function () { $('#mapFocus').attr('aria-label','Service Requests on a New Your City Map'); } /** * Perform a search and update entity pins. * @param {boolean} isinitial - True if this is the initial search. */ function searchEntityPins(isinitial) { isinitial = isinitial || false; Logs.EntityPinMapLog.log("Search Entity Pins"); setLoading(true); _infobox.hide(); _filtermanager.getEntityPins(buildEntityPins, { initialsearch: isinitial }); } /** * Show or hide the loading spinner. * @param {boolean} loading - True if the loading spinner should be shown and the search button should be disabled. */ function setLoading(loading) { if(loading) { _loadingspinner.show(); _filterSearchButton.attr("disabled", true) } else { _loadingspinner.hide(); _filterSearchButton.removeAttr("disabled") } } /** * Update entitypins with a news list of pins. * @param {Object[]} entitypins - List of pushpins to update with. */ function buildEntityPins(entitypins) { _pins = []; entitypins.forEach(function (pin) { if(pin.getLatitude() != null && pin.getLongitude() != null) { var pushpin = new Microsoft.Maps.Pushpin(new Microsoft.Maps.Location(pin.getLatitude(), pin.getLongitude()), null); pushpin.entity.id = pin.getId(); pushpin.entitypin = pin; Logs.EntityPinMapLog.log("Adding PushPin", pushpin); _pins.push(pushpin); } }); buildClusters(_pins); } var _isInitialLoad = true; /** * Build pin clusters on the map. * @param {Object[]} pins - List of pushpins to be seperated into clusters. */ function buildClusters(pins) { Logs.EntityPinMapLog.log("Building Cluster"); _self.getBingMap().layers.clear(); Microsoft.Maps.loadModule('Microsoft.Maps.Clustering', function () { var visiblepins = $.grep(pins, function(pin){ return pin._options.visible == true; }); _clusterlayer = new Microsoft.Maps.ClusterLayer(visiblepins, { gridSize: 30, callback: function () { buildListBox(); }, clusteredPinCallback: function (pin) { clusterPinCallback(pin); } }); Microsoft.Maps.Events.addHandler(_clusterlayer, 'click', pinClicked); _self.getBingMap().layers.insert(_clusterlayer); }); if(_isInitialLoad && _inputoptions.centerpinid != undefined) centerOnPin(getPinById(_inputoptions.centerpinid)); if(_isInitialLoad) _self.onMapLoaded(); _isInitialLoad = false; setLoading(false); } function clusterPinCallback(pin) { _self.onClusterPinCallback(pin); } _self.onClusterPinCallback = function (pin) { } /** * Rebuilds the clusters on the map. */ _self.rebuildClusters = function () { buildClusters(_pins); } /** * Rebuilds the listbox on the map. Uses the input EntityPinListBox to render the list. */ function buildListBox() { Logs.EntityPinMapLog.log("Building List Box"); if(!_showlistbox) return; var pins = []; if(_clusterlayer != null) { _clusterlayer.getDisplayedPushpins().forEach(function (pin) { pins.push(pin.entitypin); }); } var listbox = _listbox.buildListBox(pins); Logs.EntityPinMapLog.log(listbox); _listboxdiv.html(listbox); } /** * Triggered when a pin is clicked. Shows an infobox for the pin based on the input EntityPinInfoBox. */ function pinClicked(e) { Logs.EntityPinMapLog.log("Pin Clicked", e.target); var pins = []; if(e.target instanceof Microsoft.Maps.ClusterPushpin) { e.target.containedPushpins.forEach(function (pin) { pins.push(pin.entitypin); }); } else { pins.push(e.target.entitypin); } _infobox.show(pins, e.target.getLocation(), _self.getBingMap()); } function pincallbackfunction() { } /** * Shows the infobox for a particular pin. * @param {Object} pin - The pushpin to show an infobox for. */ function showPinInfoBox(pin) { _infobox.show([pin], pin.getLocation(), _self.getBingMap()); } /** * Gets a pushpin from the pin list by id. * @param {Object} pin - The pushpin to show an infobox for. */ function getPinById(id) { var pinfilter = $.grep(_pins, function(pin) {return pin.entitypin.getId().toUpperCase() == id.toUpperCase() }); console.log(); return pinfilter[0] != undefined ? pinfilter[0].entitypin : null; } _self.getPinById = getPinById; /** * Centers the map on a pushpin. * @param {Object} pin - The pushpin to center on. */ function centerOnPin(pin) { if(pin == null) return; _self.getBingMap().setView({ center: pin.getLocation(), zoom: 16 }); } /** * Returns the current list of pushpins. */ _self.getEntityPins = function () { return _pins; } /** * Returns the current cluster layer. */ _self.getClusterLayer = function () { return _clusterlayer; } } //# sourceURL=EntityPinMap.js </script> <script> "use strict"; ServiceRequestInfoBox.inherits(EntityPinInfoBox); function ServiceRequestInfoBox(_action) { var _self = this; EntityPinInfoBox.prototype.constructor.call(_self); _self.buildEntityPinContent = function(pin, content) { var utcDate = new Date(pin.getData().submitteddate + " UTC") content.append('<div class="infobox-row"><span class="infobox-label">SR Number:</span>' + pin.getData().srnumber + '</div>'); content.append('<div class="infobox-row"><span class="infobox-label">Status:</span>' + pin.getData().status + '</div>'); content.append('<div class="infobox-row"><span class="infobox-label">Submitted Date:</span>' + moment(utcDate).format('M/D/YYYY h:mm a') + '</div>'); return content; } _self.getEntityPinListTitle = function (pins) { return "Cluster of " + pins.length + " service requests"; } } //# sourceURL=SRInfoBox.js </script> <script type='text/javascript' src='https://www.bing.com/api/maps/mapcontrol?callback=loadBingMaps' async defer></script> <script> "use strict"; var bingMapsReady = false; var bingMapsLoaded = false; var loadBingMapsFunctions = [] function addLoadBingMapsFunction(func) { if(bingMapsLoaded) func.call(); else loadBingMapsFunctions.push(func); } function loadBingMaps() { if(document.readyState !== "complete") { Logs.BingMapsLog.log("Bing Maps waiting for Document Ready"); setTimeout(loadBingMaps, 100); return; } bingMapsLoaded = true; loadBingMapsFunctions.forEach(function (func) { func.call(); }); } /* function loadBingMaps() { if(document.readyState !== "complete") { Logs.BingMapsLog.log("Bing Maps waiting for Document Ready"); setTimeout(loadBingMaps, 100); return; } Logs.BingMapsLog.log("Loading Bing Maps..."); if (typeof loadServiceRequestMap == 'function') { Logs.BingMapsLog.log("Loading SR Map..."); loadServiceRequestMap(); } if (typeof loadAddressMaps == 'function') { Logs.BingMapsLog.log("Loading Address Maps..."); loadAddressMaps(); } if (typeof loadCustomMapLiquid == 'function') { Logs.BingMapsLog.log("Loading Custom Liquid Maps..."); loadCustomMapLiquid(); } if (typeof loadCustomMap == 'function') { Logs.BingMapsLog.log("Loading Custom Maps..."); loadCustomMap(); } if (typeof loadMapLookupPickers == 'function') { Logs.BingMapsLog.log("Loading Map Lookup Pickers..."); loadMapLookupPickers(); } }*/ </script> <div id="servicerequestmap_1"> </div> <script> //# sourceURL=MapServiceRequestMap.js "use strict"; MapBoroughFilter.inherits(MapDropdownFilter); function MapBoroughFilter(_paramname, _options) { var _self = this; MapDropdownFilter.prototype.constructor.call(_self, _paramname, _options); _self.addDropdownFilterOptions([ { name : "Bronx", value : "BRONX" }, { name : "Brooklyn", value : "BROOKLYN" }, { name : "Manhattan", value : "MANHATTAN" }, { name : "Queens", value : "QUEENS" }, { name : "Staten Island", value : "STATEN ISLAND" } ]); } $(function () { addLoadBingMapsFunction(function () { var problemareafilter = new MapOptionSetFilter("problemarea", "n311_srproblem", "n311_problemareaglobal", { label: "Problem Area" }); var problemfilter = new MapLinkedLookupFilter("problem", "n311_srproblem", "n311_srproblemid", "n311_name", problemareafilter, "n311_problemareaglobal", { label: "Problem", type: "problem" }); var map = new EntityPinMap( $("#servicerequestmap_1"), new FilterManager("/entity-pin-fetch-service-requests/", [ new MapAddressFilter({label: "Address"}), new MapBoroughFilter("borough", {label: "Borough"}), //new MapTextFilter("srnumber", {label: "SR Number"}), new MapDateFilter("fromdate", "todate", {label: "Date"}), problemareafilter, problemfilter, new MapTextFilter("communitydistrict", { label: "Community Board", }), new MapTextFilter("citycouncildistrict", { label: "City Council District"}) ], { data : { } }), { infobox: new ServiceRequestInfoBox(), action: new EntityPinMapSelectAction("View Details", function (pin) { debugger document.location = "/sr-details/?srnum=" + pin.getData().srnumber; }), makeinitialsearch: true } ); map.loadMap(); }); }); </script> </div> <p>Looking for more information? Check <a href="https://nycopendata.socrata.com/Social-Services/311-Service-Requests-from-2010-to-Present/erm2-nwe9">NYC Open Data</a> for all Service Requests since 2010.</p> </div> </div> </div> <script> "use strict"; $(function () { $('[data-toggle="tooltip"]').tooltip() // US112923 - Language Need and Additional information fields if ($("#n311_languageneed").val() == "") hideField('n311_languageneed'); if ($("#n311_writtencommunicationpreference").val() == "") hideField('n311_writtencommunicationpreference'); if ($("#n311_specifyotherlanguage").val() == "") hideField('n311_specifyotherlanguage'); }); </script> <script onerror="javascript:&#32;var&#32;target&#32;=&#32;event.target;&#32;var&#32;script&#32;=&#32;document.createElement(&#39;script&#39;);&#32;script.crossOrigin&#32;=&#32;target.crossOrigin;&#32;script.src&#32;=&#32;&#39;/dist/pcf-loader.bundle-f4a0e619b8.js&#39;;&#32;script.type&#32;=&#32;&#39;text/javascript&#39;;&#32;target.insertAdjacentElement(&#39;afterend&#39;,script);" src="https://content.powerapps.com/resource/powerappsportal/dist/pcf-loader.bundle-f4a0e619b8.js" type="text/javascript"></script> <div id="pp-native-controls-react-root"></div> <script>window._nativeControlConfig = { "publicPath":"https://content.powerapps.com/resource/powerappsportal/controls", "versions": {"pcf_loader":"0.0.21","pcf_controls":"0.0.34","mf_shared":"0.2.1","host":"0.1.21","data_grid":"0.2.22","controls_fluent_v9":"0.0.24"} }</script> <script defer="defer" src="https://content.powerapps.com/resource/powerappsportal/controls/host/main.536e68876e.chunk.js"></script> <div class="wrapper" id="nyc311Footer"> <div class="container"> <div class="row"> <div id="custom_html-15" class="widget_text widelinks-widget widget_custom_html widget-count-4 col-md-4 nyc311FooterText"> <div class="textwidget custom-html-widget"> <div class="wrap-social"> <a href="https://twitter.com/NYC311" aria-label="NYC311 twitter" rel="noopener noreferrer" target="_blank"><i class="fa fa-lg fa-twitter pr-2" aria-hidden="true"></i></a> <a href="https://www.facebook.com/NYC311/" aria-label="NYC311 facebook" rel="noopener noreferrer" target="_blank"><i class="fa fa-lg fa-facebook p-2" aria-hidden="true"></i></a> <a href="https://www.instagram.com/nyc311/#" aria-label="NYC311 instagram" rel="noopener noreferrer" target="_blank"><i class="fa fa-lg fa-instagram p-2" aria-hidden="true"></i></a> <a href="https://www.youtube.com/user/NYC311" aria-label="NYC311 YouTube" rel="noopener noreferrer" target="_blank"><i class="fa fa-lg fa-youtube p-2" aria-hidden="true"></i></a> </div> <strong>Follow NYC311</strong> </div> </div><!-- .widelinks-widget --> <div id="mobileAppLinks" class="widget_text widelinks-widget widget_custom_html widget-count-4 col-md-4 col-md-offset-4"> <div class="textwidget custom-html-widget"> <div class="wrap-mobile"> <a href="https://itunes.apple.com/us/app/nyc-311/id324897619?mt=8" aria-label="Download mobile app for iPhone or iPad" rel="noopener noreferrer" target="_blank"><i class="fa fa-apple pr-2" aria-hidden="true"></i></a> <a href="https://play.google.com/store/apps/details?id=gov.nyc.doitt.ThreeOneOne" aria-label="Download mobile app for Android" rel="noopener noreferrer" target="_blank"><i class="fa fa-android p-2" aria-hidden="true"></i></a> <br> <strong>Download the NYC311 Mobile App</strong> </div> </div> </div><!-- .widelinks-widget --> </div> <br /> <div class="row"> <div id="custom_html-15" class="widget_text widelinks-widget widget_custom_html widget-count-4 col-md-4 nyc311FooterText nyc311FooterLinks"> <a href="/about-nyc-311/">About NYC311</a> <a href="/article/?id=931bdb68-c5b6-ee11-a568-000d3a10506c">Send Feedback</a> <a href="https://www.nyc.gov/html/misc/html/NYC311-privacy-policy.html" target="_blank">NYC311 Privacy Policy</a> </div><!-- .widelinks-widget --> <div id="nyc311logo" class="widget_text widelinks-widget widget_custom_html widget-count-4 col-md-4 col-md-offset-4"> <img src="/nyc311-logo.png" alt="NYC 311 Logo" style="width:3.3rem;" class="mb-2"> </div><!-- .widelinks-widget --> </div> </div> </div> <script> "use strict"; $('head').append('<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">'); </script> <!-- Global Footer 311 Modified Start --> <footer aria-labelledby="nyc-footer" role="contentinfo"> <span id="nyc-footer" class="sr-only">NYC.gov footer</span> <div class="container footerwrap"> <h2 class="sr-only">More on NYC.gov</h2> <ul class="footerLinks"> <li><a href="https://www1.nyc.gov/nyc-resources/agencies.page">Directory of City Agencies</a></li> <li><a href="https://www1.nyc.gov/home/contact-us.page">Contact NYC Government</a></li> <li><a href="https://a127-ess.nyc.gov">City Employees</a></li> <li><a href="https://www.nyc.gov/notifynyc">Notify NYC </a></li> <li><a href="https://a856-citystore.nyc.gov">City Store </a></li> <li><a href="https://www1.nyc.gov/connect/social-media.page">Stay Connected</a></li> <li><a href="https://www1.nyc.gov/connect/applications.page">NYC Apps</a></li> <li><a href="https://www1.nyc.gov/nyc-resources/nyc-maps.page">Maps</a></li> <li><a href="https://www1.nyc.gov/nyc-resources/resident-toolkit.page">Residents Toolkit </a></li> </ul> <h2 class="sr-only">Translation for NYC.gov</h2> <ul class="footerLang"> <li><a lang="ar" href="javascript:setLanguage('ar')">العربية</a></li> <li><a lang="bn" href="javascript:setLanguage('bn')">বাঙালি</a></li> <li><a lang="zh" href="javascript:setLanguage('zh-CN')">中文</a></li> <li><a lang="ht" href="javascript:setLanguage('ht')">Krey&ograve;l Ayisyen</a></li> <li><a lang="pl" href="javascript:setLanguage('pl')">Polskie</a></li> <li><a lang="es" href="javascript:setLanguage('es')">Espa&ntilde;ol</a></li> <li><a lang="ru" href="javascript:setLanguage('ru')">Русский</a></li> <li><a lang="fr" href="javascript:setLanguage('fr')">Fran&ccedil;ais</a></li> <li><a lang="ko" href="javascript:setLanguage('ko')">한국어</a></li> <li><a lang="ur" href="javascript:setLanguage('ur')">اُردُو</a></li> <li><a lang="ur" href="javascript:setLanguage('en')">English</a></li> </ul> <div class="footerSearch"><a href="https://www.nyc.gov"><img src="https://www1.nyc.gov/assets/home/images/global/nyc_white@x2.png" alt="NYC Logo" /></a></div> <div class="footerLegal"> <div>&copy; City of New York. 2024 All Rights Reserved,<br /> NYC is a trademark and service mark of the City of New York.</div> <div><a href="https://www1.nyc.gov/home/privacy-policy.page">Privacy Policy.</a>&nbsp;&nbsp;<a href="https://www1.nyc.gov/home/terms-of-use.page">Terms of Use.</a> <a href="https://www.nyc.gov/digitalaccess"><span class="sr-only">Learn more about Digital Accessibility from the Mayor's Office for People with Disabilities.</span> <span class="fab fa-2x fa-accessible-icon" aria-hidden="true"></span></a></div> </div> </div> </footer> <script src="https://www1.nyc.gov/assets/home/js/webtrends/webtrends.311-load.js" type="text/javascript"></script> <!-- GLOBAL JAVASCRIPT INCLUDES (/js/_global.js.html.erb) --> <script src="https://www1.nyc.gov/assets/home/js/libs/modernizr-2.6.2.min.js" type="text/javascript"></script> <!-- <script src="https://www1.nyc.gov/assets/home/js/libs/jquery-1.9.1.js" type="text/javascript"></script>--> <script src="https://www1.nyc.gov/assets/home/js/utils.js" type="text/javascript"></script> <script src="https://www1.nyc.gov/assets/home/js/libs/class.js" type="text/javascript"></script> <script src="https://www1.nyc.gov/assets/home/js/pages/311/header-footer/classes/NYC.MainNav.js" type="text/javascript"></script> <script src="https://www1.nyc.gov/assets/home/js/pages/311/header-footer/classes/NYC.311-portal.js" type="text/javascript"></script> <!-- Google Translate Plugin --> <script type="text/javascript"> function googleTranslateElementInit() { new google.translate.TranslateElement({ pageLanguage: 'en' }, 'google_translate_element'); } </script> <script type="text/javascript" src="//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit"></script> <!-- Global Footer 311 Modified End --> <script> "use strict"; $(document).ready(function(){ //Show Popup for extenal links otherthan "nyc.gov" $(".externallink").click(function(){ // var addressValue = $(this).attr("href"); var choice = confirm("You're being redirected to an external website. Do you want to continue?"); if(choice) { $(this).attr("target", "_self"); return true; } else return false; }); }); </script> <!-- Text Size Modal --> <div class="modal fade" id="textSizeModal" role="dialog"> <div class="modal-dialog"> <!-- Modal content--> <div class="modal-content"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal">&times;</button> </div> <div class="modal-body"> <div class="richtext"> <div class="xrm-editable-html&#32;xrm-attribute"><div class="xrm-attribute-value"><p>To change the text size on NYC.gov you can use your web browser's settings. Most browsers include functionality to let you increase or decrease the text on a web page. For example, to increase text size using:</p><h4>Chrome</h4><p>In the menu to the right of the address bar, select and set Zoom level. Menu > Zoom > +</p><h4>Firefox</h4><p>In the View menu, select Zoom. View > Zoom > Zoom In</p><h4>Internet Explorer</h4><p>In the View menu, select Text Size. View > Text Size > Largest</p><h4>Safari</h4><p>In the View menu, select Zoom In. View > Zoom In<br />Macintosh Shortcut: Command+</p><h4>No Web Browser Endorsement</h4><p>Common browsers are included in this page; mention of a specific browser does not imply endorsement or recommendation.</p></div></div> </div> </div> </div> </div> </div> <style> footer .footer-bottom { background-color: #000; } footer .footer-bottom p { margin: 0; } footer .footer-links a { color: #fff; text-decoration: none; display: block; font-weight: bold; float: left; margin-right: 2.12766%; padding: 5px 0; } footer .logo-nyc { text-indent: 100%; white-space: nowrap; overflow: hidden; width: 93px; height: 31px; display: block; background-image: url('/nyc_white.png'); background-size: 93px 31px; float: left; margin-right: 10px; color: #ffffff; } footer .form-search .input-search { width: 70px; height: 30px; padding: 4px 6px; outline: none; font-size: 14px; border-radius: 4px 0 0 4px; float: left; border-left: 2px solid #727272; border-top: 2px solid #727272; border-right: none; border-bottom: 2px solid #727272; color: #fff; background-color: #616161; font-weight: bold; margin-right: -1px; } footer .form-search .ico-search { text-indent: 100%; white-space: nowrap; overflow: hidden; background: url('/sprite-ico-search.png') no-repeat #616161 center -8px; padding: 0; display: block; width: 24px; height: 30px; border-radius: 0 4px 4px 0; border-right: 2px solid #727272; border-top: 2px solid #727272; border-bottom: 2px solid #727272; border-left: none; cursor: pointer; color: #ffffff; } footer .copyright { color: #fff; font-size: 10px; } footer .copyright a { color: #fff; } footer input::placeholder { color: #fff; font-family: "Helvetica Neue",Helvetica,Arial,sans-serif; } footer .span3 { margin-left: 15px; } footer ul { margin-bottom: 20px !important; } </style> <script onerror="javascript:&#32;var&#32;target&#32;=&#32;event.target;&#32;var&#32;script&#32;=&#32;document.createElement(&#39;script&#39;);&#32;script.crossOrigin&#32;=&#32;target.crossOrigin;&#32;script.src&#32;=&#32;&#39;/dist/bootstrap.bundle-105a4995b8.js&#39;;&#32;script.type&#32;=&#32;&#39;text/javascript&#39;;&#32;target.insertAdjacentElement(&#39;afterend&#39;,script);" src="https://content.powerapps.com/resource/powerappsportal/dist/bootstrap.bundle-105a4995b8.js" type="text/javascript"></script> <script onerror="javascript:&#32;var&#32;target&#32;=&#32;event.target;&#32;var&#32;script&#32;=&#32;document.createElement(&#39;script&#39;);&#32;script.crossOrigin&#32;=&#32;target.crossOrigin;&#32;script.src&#32;=&#32;&#39;/dist/postpreform.bundle-184c77da50.js&#39;;&#32;script.type&#32;=&#32;&#39;text/javascript&#39;;&#32;target.insertAdjacentElement(&#39;afterend&#39;,script);" src="https://content.powerapps.com/resource/powerappsportal/dist/postpreform.bundle-184c77da50.js" type="text/javascript"></script> <script onerror="javascript:&#32;var&#32;target&#32;=&#32;event.target;&#32;var&#32;script&#32;=&#32;document.createElement(&#39;script&#39;);&#32;script.crossOrigin&#32;=&#32;target.crossOrigin;&#32;script.src&#32;=&#32;&#39;/dist/app.bundle-9f74409731.js&#39;;&#32;script.type&#32;=&#32;&#39;text/javascript&#39;;&#32;target.insertAdjacentElement(&#39;afterend&#39;,script);" src="https://content.powerapps.com/resource/powerappsportal/dist/app.bundle-9f74409731.js" type="text/javascript"></script> <script onerror="javascript:&#32;var&#32;target&#32;=&#32;event.target;&#32;var&#32;script&#32;=&#32;document.createElement(&#39;script&#39;);&#32;script.crossOrigin&#32;=&#32;target.crossOrigin;&#32;script.src&#32;=&#32;&#39;/dist/default-1033.moment_2_29_4.bundle-eda4e638fd.js&#39;;&#32;script.type&#32;=&#32;&#39;text/javascript&#39;;&#32;target.insertAdjacentElement(&#39;afterend&#39;,script);" src="https://content.powerapps.com/resource/powerappsportal/dist/default-1033.moment_2_29_4.bundle-eda4e638fd.js" type="text/javascript"></script> <script type="text/javascript"> var appInsights=window.appInsights||function(a){ function b(a){c[a]=function(){var b=arguments;c.queue.push(function(){c[a].apply(c,b)})}}var c={config:a},d=document,e=window;setTimeout(function(){var b=d.createElement("script");b.src=a.url||"https://az416426.vo.msecnd.net/scripts/a/ai.0.js",d.getElementsByTagName("script")[0].parentNode.appendChild(b)});try{c.cookie=d.cookie}catch(a){}c.queue=[];for(var f=["Event","Exception","Metric","PageView","Trace","Dependency"];f.length;)b("track"+f.pop());if(b("setAuthenticatedUserContext"),b("clearAuthenticatedUserContext"),b("startTrackEvent"),b("stopTrackEvent"),b("startTrackPage"),b("stopTrackPage"),b("flush"),!a.disableExceptionTracking){f="onerror",b("_"+f);var g=e[f];e[f]=function(a,b,d,e,h){var i=g&&g(a,b,d,e,h);return!0!==i&&c["_"+f](a,b,d,e,h),i}}return c }({ instrumentationKey: "f0fbe3a3-5020-461f-a3b5-7c517b094831" }); window.appInsights=appInsights,appInsights.queue&&0===appInsights.queue.length&&appInsights.trackPageView(); </script> <script> //this event will update the title of the page based on active breadcrumb $('.breadcrumb').ready(function () { if ($('.breadcrumb').is(':visible')) { document.querySelector('title').innerHTML = ($('.breadcrumb > li.active').text() + "&nbsp;· NYC311"); } }); function GoToNewEditor() { var editCmsUrlSegment = "EditInCms"; var currentUrl = window.location.href; if (currentUrl.indexOf('?') > -1) { var urlSegments = currentUrl.split("?"); window.location.href = window.location.origin + '/' + editCmsUrlSegment + window.location.pathname + '?' + urlSegments[1]; } else { window.location.href = window.location.origin + '/' + editCmsUrlSegment + window.location.pathname; } } </script> <script> if ('serviceWorker' in navigator) { navigator.serviceWorker.getRegistrations().then(function(registrations) { for(let registration of registrations) { registration.unregister(); }}).catch(function(err) { console.log('Service Worker unregister action failed: ', err); }); } </script> <!--Start Show Session Expire Warning Popup here --> </body> </html> <!-- Generated at 12/1/2024 1:30:38 AM --> <!-- Page OK -->

Pages: 1 2 3 4 5 6 7 8 9 10