1var loadedScripts = { 2 agendaComments: { 3 script: "/Scripts/AgendaComments.js" 4 }, 5 alphabeticalSortModule: { 6 script: "/Scripts/AlphabeticalSortModule.js" 7 }, 8 analytics: { 9 script: "https://www.google-analytics.com/analytics.js" 10 }, 11 budgetQuestion: { 12 script: "/Scripts/budgetQuestion.js" 13 }, 14 fundingAllocator: { 15 script: "/Scripts/FundingAllocator/FundingAllocator.js" 16 }, 17 qaTool: { 18 script: "/dist/qa-tool.bundle.js" 19 }, 20 bootstrap: { 21 script: "/Scripts/bootstrap.min.js" 22 }, 23 bootstrap5: { 24 script: 25 "https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" 26 }, 27 BootstrapToast: { 28 script: "/Scripts/BootstrapToast.js" 29 }, 30 CalendarEmbed: { 31 script: "/Scripts/CalendarEmbed.js" 32 }, 33 constants: { 34 script: "/Scripts/constants.js" 35 }, 36 commentMap: { 37 script: "/Scripts/commentMap.js" 38 }, 39 ckEditor4: { 40 // AB#9952 / WASP#756: customers with ModuleSettings.DisableCkEditor never receive the 41 // CKEditor bundle. CkEditorPlainText.js exposes the same CKEDITOR surface over plain 42 // inputs, so no caller changes. Deliberately a GETTER rather than a value computed at 43 // load time: it resolves on every read, so this file has no ordering dependency on when 44 // the page sets window.piDisableCkEditor. 45 get script() { 46 return window.piDisableCkEditor === true 47 ? "/Scripts/CkEditorPlainText.js" 48 : "/Scripts/CkEditor4/ckeditor.js"; 49 }, 50 // The loader assigns `loaded` on this object; a get-only `script` would throw on an 51 // accidental write in strict mode, so absorb one harmlessly. 52 set script(ignored) {} 53 }, 54 canvg: { 55 script: "/Scripts/charts/canvg.min.js" 56 }, 57 stackedCards: { 58 script: "/Scripts/stackedCards.js" 59 }, 60 commentBuilder: { 61 script: "/Scripts/CommentBuilder.js" 62 }, 63 commentSection: { 64 script: "/Scripts/CommentSection.js" 65 }, 66 consensus: { 67 script: "/Scripts/consensus-module.js" 68 }, 69 esri: { 70 script: "https://js.arcgis.com/4.23/" 71 }, 72 fullCalendar: { 73 script: 74 "https://cdn.jsdelivr.net/npm/[email protected]/index.global.min.js" 75 }, 76 fullCalendarModule: { 77 script: "/Scripts/FullCalendarModule.js" 78 }, 79 mapCommentTools: { 80 script: "/Scripts/MapCommentTools.js" 81 }, 82 myData: { 83 script: "/Scripts/MyData/my-data.js" 84 }, 85 myDataModuleLoader: { 86 script: "/Scripts/MyData/my-data.module-loader.js" 87 }, 88 myDataPortalView: { 89 script: "/Scripts/MyData/my-data.portal-view.js" 90 }, 91 myDataSearchUI: { 92 script: "/Scripts/MyData/my-data.search-ui.js" 93 }, 94 myDataSectionUI: { 95 script: "/Scripts/MyData/my-data.section-ui.js" 96 }, 97 canvasToBlob: { 98 script: 99 "https://blueimp.github.io/JavaScript-Canvas-to-Blob/js/canvas-to-blob.min.js" 100 }, 101 engagementMapBase: { 102 script: "/Scripts/engagementMap/base.js" 103 }, 104 esriMapsHub: { 105 script: "/Scripts/engagementMap/hubMap.js" 106 }, 107 canvasToImage: { 108 script: "https://superal.github.io/canvas2image/canvas2image.js" 109 }, 110 chosen: { 111 script: "/lib/chosen/chosen.jquery.min.js" 112 }, 113 chatBot: { 114 script: "/Scripts/chat-widget.js" 115 }, 116 chartDataLoader: { 117 script: "/Scripts/charts/chart-data-loader.js" 118 }, 119 chartFactory: { 120 script: "/Scripts/charts/chart-factory.js" 121 }, 122 contactForm: { 123 script: "/Scripts/ContactForm/ContactForm.js" 124 }, 125 customStyleEditor: { 126 script: "/Scripts/CustomStyleEditor.js" 127 }, 128 customReport: { 129 script: "/Scripts/Reporting/custom-report.js" 130 }, 131 customRegistrationForm: { 132 script: "/Scripts/CustomRegistrationForm.js" 133 }, 134 dataTables: { 135 script: "/Scripts/dataTables/jquery.dataTables.min.js" 136 }, 137 dropzone: { 138 script: "/Scripts/dropzone.js" 139 }, 140 datepicker: { 141 script: 142 "https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/js/bootstrap-datepicker.min.js" 143 }, 144 dateTimePicker: { 145 script: "/lib/bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js" 146 }, 147 demographicModule: { 148 script: "/Scripts/demographicModule.js" 149 }, 150 dynamicSignupBuilder: { 151 script: "/Scripts/AdminShared/DynamicSignupBuilder.js?v=bs5-2" 152 }, 153 emailCommunicationUI: { 154 script: "/Scripts/AdminShared/EmailCommunicationUI.js?v=bs5-2" 155 }, 156 draftEmail: { 157 script: "/Scripts/AdminShared/DraftEmail.js" 158 }, 159 emailProject: { 160 script: "/Scripts/AdminShared/EmailProject.js" 161 }, 162 flotMin: { 163 script: "/Scripts/charts/flot/jquery.flot.min.js" 164 }, 165 flotTooltip: { 166 script: "/Scripts/charts/flot/jquery.flot.tooltip.min.js" 167 }, 168 flotTime: { 169 script: "/Scripts/charts/flot/jquery.flot.time.js" 170 }, 171 // AB#10165: pinned to 3.64 because DrawingManager was removed in 3.65 172 // (deprecated Aug 2025). 3.64 is the newest version that still ships it. 173 // Google keeps only ~4 numbered versions live, so this pin stops resolving 174 // around mid-Feb 2027 -- and it expires SILENTLY: an unavailable v= is served 175 // the latest version, not an error. Supersedes the v=quarterly pin from 176 // Bug 8928, which broke when quarterly rolled to 3.65 in Aug 2026. 177 // Permanent fix (migrate off DrawingManager) tracked separately. 178 googleMaps: { 179 // AB#10257: v=quarterly is a rolling channel. It rolled onto 3.65, which removed 180 // DrawingManager, and constructing one threw before mappoll.js could finish init - 181 // taking the whole interactive map question down, not just line drawing. Pinned 182 // below 3.65 until we migrate off DrawingManager. Google retires old versions, so 183 // this is a stopgap with an expiry, not a resting place. 184 script:
185 "https://maps.googleapis.com/maps/api/js?key=AIzaSyAiRD1TL9mZQfmpBOZ3MaX_pGxI5MlLCZI&loading=async&v=3.64&libraries=places,drawing&callback=initScriptLoaderMapCallback" 186 }, 187 googleMapsMarkerClusterer: { 188 script: "https://unpkg.com/@googlemaps/markerclusterer/dist/index.min.js" 189 }, 190 highlight: { 191 script: "/Scripts/AdminShared/Jquery.Highlight.js" 192 }, 193 html2Canvas: { 194 script: "/lib/html2canvas/html2canvas.min.js" 195 }, 196 ideaBoard: { 197 script: "/Scripts/ideaBoard.js" 198 }, 199 imagePollShape: { 200 script: "/Scripts/imagePollShape.js" 201 }, 202 intercomHelper: { 203 script: "/Scripts/intercom-helper.js" 204 }, 205 isotope: { 206 script: "https://unpkg.com/isotope-layout@3/dist/isotope.pkgd.min.js" 207 }, 208 jqueryUIWidget: { 209 script: "/Scripts/file-upload/jquery.ui.widget.js" 210 }, 211 jqueryFileUpload: { 212 script: "/lib/blueimp-file-upload/js/jquery.fileupload.min.js" 213 }, 214 jqueryIframeTransport: { 215 script: "/lib/blueimp-file-upload/js/jquery.iframe-transport.min.js" 216 }, 217 jqueryCloudinary: { 218 script: "/Scripts/file-upload/jquery.cloudinary.js" 219 }, 220 loadImageAll: { 221 script: "/Scripts/file-upload/load-image.all.min.js" 222 }, 223 jqueryFileUploadProcess: { 224 script: "/Scripts/file-upload/jquery.fileupload-process.js" 225 }, 226 jqueryFileUploadImage: { 227 script: "/Scripts/file-upload/jquery.fileupload-image.js" 228 }, 229 jqueryFileUploadUI: { 230 script: "/Scripts/file-upload/jquery.fileupload-ui.js" 231 }, 232 jqueryUi: { 233 script: "/lib/jqueryui/jquery-ui.min.js?v=1.13.3" 234 }, 235 linkify: { 236 script: "/Scripts/linkify.min.js" 237 }, 238 linkifyJquery: { 239 script: "/Scripts/linkify-jquery.min.js" 240 }, 241 locationPoll: { 242 script: "/Scripts/locationpoll.js" 243 }, 244 mapPoll: { 245 // ?v= bumped with each participant-facing fix (AB#9710 add-point tray, 246 // AB#10879 duplicate-pin recovery) so returning participants are not served a 247 // cached copy of the broken script (same pattern as matrix). 248 script: "/Scripts/mappoll.js?v=10879" 249 }, 250 mapPollParcel: { 251 script: "/Scripts/mappoll.parcels.js" 252 }, 253 mapPollShape: { 254 script: "/Scripts/mapPollShape.js" 255 }, 256 polygonCentering: { 257 script: "/Scripts/polygonCentering.js" 258 }, 259 mapLabel: { 260 script: "/Scripts/maplabel-compiled.js" 261 }, 262 mapA11y: { 263 script: "/Scripts/AdminShared/map-a11y.js" 264 }, 265 mapA11yStatus: { 266 script: "/Scripts/AdminShared/map-a11y-status.js" 267 }, 268 mapLayerManager: { 269 script: "/Scripts/MapLayerManager.js" 270 }, 271 mapPollEditor: { 272 script: "/Scripts/mappolleditor.js" 273 }, 274 masonry: { 275 script: "https://unpkg.com/masonry-layout@4/dist/masonry.pkgd.min.js" 276 }, 277 magnificPopup: { 278 script: "/lib/magnific-popup.js/jquery.magnific-popup.min.js" 279 }, 280 materialExtensions: { 281 script: "/Scripts/materialExtensions.js" 282 }, 283 matrix: { 284 script: "/Scripts/poll.matrix.js?v=a6321" 285 }, 286 meetingTranscriptionsUI: { 287 script: "/Scripts/MeetingTranscriptionsUI.js" 288 }, 289 moment: { 290 script: "/lib/moment.js/moment.min.js" 291 }, 292 mustache: { 293 script: "/Scripts/mustache.min.js" 294 }, 295 newPoll: { 296 script: "/Scripts/new-poll.js" 297 }, 298 notify: { 299 script: "/Scripts/notify1.min.js" 300 }, 301 noUiSliderJquery: { 302 script: "/Scripts/jquery.nouislider.js" 303 }, 304 noUiSlider: { 305 script: 306 "https://cdnjs.cloudflare.com/ajax/libs/noUiSlider/11.0.3/nouislider.min.js" 307 }, 308 offlineEventUI: { 309 script: "/Scripts/OfflineEventUI.js" 310 }, 311 signalRCoreBridge: { 312 script: "/dist/signalRCoreBridge.bundle.js" 313 }, 314 poll: { 315 script: "/Scripts/poll.js" 316 }, 317 pollSlider: { 318 script: "/Scripts/poll_slider.js" 319 }, 320 pollVisioner: { 321 script: "/Scripts/poll.visioner.js" 322 }, 323 projectsOnMapViewer: { 324 script: "/Scripts/projectsOnMapViewer.js" 325 }, 326 projectPage: { 327 script: "/Scripts/Project/ProjectPageUI.js" 328 }, 329 parsley: { 330 script: "/Scripts/parsley.min.js" 331 }, 332 ranking: { 333 script: "/Scripts/RankPoll.js" 334 }, 335 rgbcolor: { 336 script: "/Scripts/charts/rgbcolor.js" 337 }, 338 starModule: { 339 script: "/Scripts/poll.starModule.js" 340 }, 341 tools: { 342 script: "/Scripts/Tools.js" 343 }, 344 twitterBootstrapWizard: { 345 script: "/lib/twitter-bootstrap-wizard/jquery.bootstrap.wizard.min.js" 346 }, 347 zoomDesktop: { 348 script: "/Scripts/zoom.js" 349 }, 350 d3: { 351 script: "/Scripts/Bubble/D3-old.js" 352 }, 353 entityCloud: { 354 script: "/Scripts/Bubble/entity-cloud.js" 355 }, 356 organizationEditor: { 357 script: "/Scripts/AdminShared/OrganizationEditor.js" 358 }, 359 organizationListUI: { 360 script: "/Scripts/AdminShared/OrganizationListUI.js" 361 }, 362 organizationMap: { 363 script: "/Scripts/AdminShared/OrganizationMap.js" 364 }, 365 audienceShared: { 366 script: "/Scripts/AdminShared/AudienceShared.js" 367 }, 368 googleAutoComplete: { 369 script: "/Scripts/GoogleAutoComplete.js" 370 } 371}; 372 373// AB#9726: `ckEditor` used to be the CKEditor 4.4.7 build under /CkEditor/. 374// There is now a single CKEditor 4 build in the application, so `ckEditor` is an 375// alias for `ckEditor4` -- the SAME object, not a copy, so both share one
376// `loaded` flag. Two separate entries would trigger a redundant fetch and a full 377// re-parse of a ~1.3 MB build on any page that uses both. The build does guard 378// against re-initialising (`if (window.CKEDITOR && window.CKEDITOR.dom) return;`), 379// so this is about not paying for work that is thrown away, not correctness. 380loadedScripts.ckEditor = loadedScripts.ckEditor4; 381 382var ScriptLoader = { 383 /** 384 * Loads a set of scripts and executes callbacks once all scripts are loaded. 385 * 386 * @param {Object} scriptSet - An object containing scripts and callbacks. 387 * @param {Function} callback - Function to be called once all scripts are loaded. 388 */ 389 loadScriptArray: function (scriptSet, callback, extraConfig = null) { 390 var allScriptsLoaded = true; 391 scriptSet.callbacks = scriptSet.callbacks || []; 392 if (callback) { 393 scriptSet.callbacks.push(callback); 394 } 395 $.each(scriptSet.scripts, function (index, value) { 396 if (value.loaded === false || value.loaded == null) { 397 allScriptsLoaded = false; 398 var script = document.createElement("script"); 399 script.src = value.script; 400 if (extraConfig && extraConfig.type) { 401 script.type = extraConfig.type; 402 } 403 var oldOnload = script.onload; 404 script.onload = script.onreadystatechange = function () { 405 if (!this.readyState || this.readyState === "complete") { 406 scriptSet.scripts[index].loaded = true; 407 ScriptLoader.loadScriptArray(scriptSet); 408 oldOnload && oldOnload(); 409 } 410 }; 411 412 var oldOnerror = script.onerror; 413 script.onerror = function () { 414 // A 404 returns the /Error HTML page (text/html), which fires onerror, not 415 // onload. Mark this script done so one failed load can't stall the whole chain. 416 if (window.console && console.error) { 417 console.error( 418 "ScriptLoader: failed to load script " + value.script 419 ); 420 } 421 scriptSet.scripts[index].loaded = true; 422 ScriptLoader.loadScriptArray(scriptSet); 423 oldOnerror && oldOnerror(); 424 }; 425 426 var head = 427 document.head || document.getElementsByTagName("head")[0] || document; 428 head.appendChild(script); 429 scriptSet.scripts[index].loaded = "pending"; 430 if (!scriptSet.async) { 431 return false; 432 } 433 } else if (value.loaded === "pending") { 434 allScriptsLoaded = false; 435 if ($ != null) { 436 var $script = $("script[src='" + value.script + "']"); 437 if ($script.length) { 438 var pendingScript = $script[0]; 439 var pendingOnload = pendingScript.onload; 440 pendingScript.onload = function () { 441 scriptSet.scripts[index].loaded = true; 442 ScriptLoader.loadScriptArray(scriptSet); 443 pendingOnload && pendingOnload(); 444 }; 445 } 446 } 447 if (!scriptSet.async) { 448 return false; 449 } 450 } 451 }); 452 if (allScriptsLoaded && scriptSet.callbacks.length) { 453 scriptSet.callbacks.forEach(function (cb, index) { 454 scriptSet.callbacks[index] = null; // prevent loop 455 cb && cb(); 456 }); 457 scriptSet.callbacks = []; 458 } else { 459 return false; 460 } 461 }, 462 isScriptLoadedOnPage: function (scriptUrl) { 463 return document.querySelector('script[src="' + scriptUrl + '"]') !== null; 464 }, 465 scriptArrays: { 466 agendaComments: { 467 scripts: [ 468 loadedScripts.constants, 469 loadedScripts.agendaComments, 470 loadedScripts.commentBuilder, 471 loadedScripts.tools, 472 loadedScripts.moment 473 ], 474 async: true 475 }, 476 alphabeticalSortModule: { 477 scripts: [loadedScripts.alphabeticalSortModule], 478 async: true 479 }, 480 chosen: { scripts: [loadedScripts.chosen] }, 481 ckEditor: { scripts: [loadedScripts.ckEditor] }, 482 ckEditor4: { scripts: [loadedScripts.ckEditor4] }, 483 consensus: { 484 scripts: [ 485 loadedScripts.consensus, 486 loadedScripts.materialExtensions, 487 loadedScripts.tools, 488 loadedScripts.stackedCards 489 ], 490 async: true 491 }, 492 calendarEmbed: { 493 scripts: [loadedScripts.calendarEmbed], 494 async: true 495 }, 496 customReportCore: { 497 scripts: [ 498 loadedScripts.customReport, 499 loadedScripts.chartFactory, 500 loadedScripts.chartDataLoader 501 ], 502 async: true 503 }, 504 dateTimePicker: { 505 scripts: [ 506 loadedScripts.moment, 507 loadedScripts.tools, 508 loadedScripts.dateTimePicker 509 ], 510 async: false 511 }, 512 dropzone: { scripts: [loadedScripts.dropzone] }, 513 bootstrap: { scripts: [loadedScripts.bootstrap] }, 514 flot: { 515 scripts: [ 516 loadedScripts.flotMin, 517 loadedScripts.flotTooltip, 518 loadedScripts.flotTime 519 ] 520 }, 521 bootstrapToast: { scripts: [loadedScripts.BootstrapToast] }, 522 fullCalendar: { 523 scripts: [loadedScripts.fullCalendarModule, loadedScripts.fullCalendar], 524 async: true 525 }, 526 googleAutoComplete: { 527 scripts: [loadedScripts.googleAutoComplete, loadedScripts.maps], 528 async: true 529 }, 530 mapShapeScripts: { 531 scripts: [ 532 loadedScripts.constants, 533 loadedScripts.googleMaps, 534 loadedScripts.polygonCentering, 535 loadedScripts.mapLabel, 536 loadedScripts.mapA11yStatus, 537 loadedScripts.mapPollShape 538 ], 539 async: false 540 }, 541 ideaBoard: { 542 scripts: [ 543 loadedScripts.constants, 544 loadedScripts.commentSection, 545 loadedScripts.ideaBoard, 546 loadedScripts.isotope, 547 loadedScripts.tools 548 ], 549 async: false 550 }, 551 pollVisioner: { 552 scripts: [ 553 loadedScripts.constants, 554 loadedScripts.commentSection, 555 loadedScripts.pollVisioner, 556 loadedScripts.tools 557 ], 558 async: false 559 }, 560 imageShapeScripts: { 561 scripts: [ 562 loadedScripts.constants, 563 loadedScripts.polygonCentering, 564 loadedScripts.imagePollShape 565 ], 566 async: false 567 }, 568 locationPollScripts: { 569 scripts: [ 570 loadedScripts.constants, 571 loadedScripts.googleMaps, 572 loadedScripts.mapA11yStatus, 573 loadedScripts.locationPoll 574 ], 575 async: false 576 }, 577 mapPollScripts: { 578 scripts: [ 579 loadedScripts.constants, 580 loadedScripts.googleMaps, 581 loadedScripts.mapCommentTools, 582 loadedScripts.mapA11yStatus, 583 loadedScripts.mapPoll 584 ], 585 async: false 586 }, 587 mapPollParcelScripts: { 588 scripts: [ 589 loadedScripts.constants, 590 loadedScripts.googleMaps, 591 loadedScripts.mapCommentTools, 592 loadedScripts.mapA11yStatus, 593 loadedScripts.mapPoll, 594 loadedScripts.mapPollParcel, 595 loadedScripts.parsley 596 ], 597 async: true 598 }, 599 mapComments: { 600 scripts: [ 601 loadedScripts.constants, 602 loadedScripts.googleMaps, 603 loadedScripts.commentMap 604 ], 605 async: false 606 }, 607 maps: { 608 scripts: [ 609 loadedScripts.googleMapsMarkerClusterer, 610 loadedScripts.googleMaps, 611 loadedScripts.mapLayerManager, 612 // AB#9979: every consumer of this array names its map region via window.piMapA11y, so the 613 // helper ships with the map libraries rather than being wired
613into each host page. 614 loadedScripts.mapA11y 615 ] 616 }, 617 mapsMarkerClusterer: { 618 scripts: [loadedScripts.googleMapsMarkerClusterer] 619 }, 620 myData: { 621 scripts: [ 622 loadedScripts.esri, 623 loadedScripts.myData, 624 loadedScripts.myDataPortalView, 625 loadedScripts.myDataSectionUI, 626 loadedScripts.myDataModuleLoader, 627 loadedScripts.myDataSearchUI, 628 loadedScripts.googleMaps 629 ], 630 async: false 631 }, 632 rankPollScripts: { 633 scripts: [ 634 loadedScripts.constants, 635 // AB#9727: was a separate `sorting` entry pointing at a CDN copy of jQuery UI. Now that 636 // both resolve to the same vendored file, they must share one entry -- loadScriptArray 637 // dedupes on the entry's own `loaded` flag, not on the URL, so two entries with the same 638 // src would append and execute jQuery UI twice on any page that pulled both. 639 loadedScripts.jqueryUi, 640 loadedScripts.ranking 641 ], 642 async: false 643 }, 644 chatBotScripts: { scripts: [loadedScripts.chatBot], async: false }, 645 intercomHelper: { 646 scripts: [loadedScripts.tools, loadedScripts.intercomHelper] 647 }, 648 magnificPopup: { scripts: [loadedScripts.magnificPopup], async: false }, 649 matrix: { 650 scripts: [loadedScripts.matrix, loadedScripts.constants], 651 async: true 652 }, 653 matrixStar: { 654 scripts: [ 655 loadedScripts.matrix, 656 loadedScripts.starModule, 657 loadedScripts.constants 658 ], 659 async: true 660 }, 661 audienceShared: { 662 scripts: [loadedScripts.esri, loadedScripts.audienceShared], 663 async: true 664 }, 665 engagementMapBase: { 666 scripts: [loadedScripts.esri, loadedScripts.engagementMapBase], 667 async: true 668 }, 669 esriMapsHub: { 670 scripts: [ 671 loadedScripts.mustache, 672 loadedScripts.esri, 673 loadedScripts.esriMapsHub 674 ], 675 async: false 676 }, 677 newPoll: { scripts: [loadedScripts.newPoll], async: true }, 678 projectPage: { 679 scripts: [ 680 loadedScripts.constants, 681 loadedScripts.projectPage, 682 loadedScripts.tools 683 ] 684 }, 685 notify: { scripts: [loadedScripts.notify] }, 686 zoomDesktop: { scripts: [loadedScripts.zoomDesktop], async: false }, 687 linkify: { 688 scripts: [loadedScripts.linkify, loadedScripts.linkifyJquery], 689 async: false 690 }, 691 contactForm: { 692 scripts: [ 693 loadedScripts.constants, 694 loadedScripts.parsley, 695 loadedScripts.contactForm 696 ], 697 async: true 698 }, 699 offlineEvent: { 700 scripts: [ 701 loadedScripts.constants, 702 loadedScripts.signalRCoreBridge, 703 loadedScripts.offlineEventUI, 704 loadedScripts.tools, 705 loadedScripts.parsley, 706 loadedScripts.chosen 707 ], 708 async: true 709 }, 710 organizationEditor: { 711 scripts: [ 712 loadedScripts.organizationEditor, 713 loadedScripts.mapLayerManager 714 ], 715 async: true 716 }, 717 organizationListUI: { 718 scripts: [loadedScripts.organizationListUI], 719 async: true 720 }, 721 organizationMap: { 722 scripts: [loadedScripts.esri, loadedScripts.organizationMap], 723 async: true 724 }, 725 commentSection: { 726 scripts: [ 727 loadedScripts.constants, 728 loadedScripts.mustache, 729 loadedScripts.tools, 730 loadedScripts.commentSection, 731 loadedScripts.constants 732 ], 733 async: false 734 }, 735 highlight: { scripts: [loadedScripts.highlight] }, 736 fileUpload: { 737 scripts: [loadedScripts.jqueryUIWidget, loadedScripts.jqueryFileUpload] 738 }, 739 imageUpload: { 740 scripts: [ 741 loadedScripts.jqueryUIWidget, 742 loadedScripts.loadImageAll, 743 loadedScripts.canvasToBlob, 744 loadedScripts.jqueryIframeTransport,
745 loadedScripts.jqueryFileUpload, 746 loadedScripts.jqueryFileUploadProcess, 747 loadedScripts.jqueryFileUploadImage, 748 loadedScripts.jqueryCloudinary 749 ], 750 async: false 751 }, 752 demographicModule: { 753 scripts: [ 754 loadedScripts.constants, 755 loadedScripts.demographicModule, 756 loadedScripts.twitterBootstrapWizard, 757 loadedScripts.parsley, 758 loadedScripts.chosen, 759 loadedScripts.jqueryUi 760 ], 761 async: true 762 }, 763 budgetQuestion: { 764 scripts: [ 765 loadedScripts.constants, 766 loadedScripts.budgetQuestion, 767 loadedScripts.notify 768 ], 769 async: false 770 }, 771 communityQa: { 772 scripts: [loadedScripts.qaTool] 773 }, 774 fundingAllocator: { 775 scripts: [ 776 loadedScripts.constants, 777 loadedScripts.noUiSlider, 778 loadedScripts.noUiSliderJquery, 779 loadedScripts.fundingAllocator 780 ], 781 async: false 782 }, 783 parsley: { scripts: [loadedScripts.parsley], async: false }, 784 projectsOnMapPublic: { 785 scripts: [ 786 loadedScripts.googleMaps, 787 loadedScripts.constants, 788 loadedScripts.polygonCentering, 789 loadedScripts.mapLabel, 790 loadedScripts.mapA11yStatus, 791 loadedScripts.projectsOnMapViewer, 792 loadedScripts.chosen 793 ] 794 }, 795 saveToImage: { 796 scripts: [ 797 loadedScripts.rgbcolor, 798 loadedScripts.canvg, 799 loadedScripts.html2Canvas, 800 loadedScripts.canvasToImage 801 ], 802 async: true 803 }, 804 slider: { 805 scripts: [ 806 loadedScripts.constants, 807 loadedScripts.noUiSlider, 808 loadedScripts.noUiSliderJquery, 809 loadedScripts.pollSlider 810 ], 811 async: true 812 }, 813 tools: { scripts: [loadedScripts.tools] }, 814 dataTables: { scripts: [loadedScripts.dataTables] }, 815 entityCloud: { scripts: [loadedScripts.d3, loadedScripts.entityCloud] }, 816 meetingTranscriptionsUI: { 817 scripts: [loadedScripts.meetingTranscriptionsUI] 818 }, 819 customRegistrationForm: { scripts: [loadedScripts.customRegistrationForm] }, 820 datepicker: { 821 scripts: [ 822 loadedScripts.moment, 823 loadedScripts.tools, 824 loadedScripts.datepicker 825 ], 826 async: false 827 } 828 }, 829 loadNew: function (scriptPathArray, async, callback) { 830 var newEntry = { scripts: [], async: async }; 831 $.each(scriptPathArray, function (idx, path) { 832 newEntry.scripts.push({ script: path }); 833 }); 834 ScriptLoader.loadScriptArray(newEntry, callback); 835 }, 836 waitForGoogle: function () { 837 return new Promise((res) => { 838 const waitForGoogle = setInterval(() => { 839 if (window.isGoogleLoaded) { 840 clearInterval(waitForGoogle); 841 return res(); 842 } 843 }, 500); 844 }); 845 } 846}; 847 848window.initScriptLoaderAdminScripts && window.initScriptLoaderAdminScripts(); 849window.isGoogleLoaded = false; 850 851function initScriptLoaderMapCallback() { 852 // this is an empty method required by Google Maps js to prevent console errors 853 window.isGoogleLoaded = true; 854 855 // AB#10165: the v=3.64 pin above expires silently -- when 3.64 falls out of 856 // Google's supported window (~mid-Feb 2027) they serve the latest version 857 // instead of erroring, and every drawing tool dies with no obvious cause. 858 // Feature detection cannot catch this: in 3.65+ google.maps.drawing still 859 // exists and DrawingManager is still a function -- it is just inert. The 860 // resolved version string is the only reliable signal. 861 if ( 862 window.google && 863 google.maps && 864 google.maps.version && 865 google.maps.version.indexOf("3.64.") !== 0 866 ) { 867 console.error( 868 "Google Maps resolved to " + 869 google.maps.version + 870 " but the map drawing tools require 3.64.x -- the v=3.64 pin has expired. " + 871 "Drawing (Regions, Audiences, project maps, map polls) will silently stop working. See AB#10165." 872 ); 873 } 874}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.