1/** 2 * Map Zoom Damping â frontend. 3 * 4 * Tames inertial ("momentum") wheel zooming on the explorer's Leaflet map. 5 * Magic Mouse / trackpad flicks keep emitting decaying wheel events after the 6 * finger stops, and Leaflet's ScrollWheelZoom rounds ANY leftover delta up to 7 * a full zoom level per debounce batch (Math.ceil against zoomSnap), so one 8 * forceful flick lands several consecutive zooms the visitor never intended. 9 * 10 * Three dampers, applied to the live map (Leaflet reads both options at 11 * event time, so no re-init is needed): 12 * 1. wheelDebounceTime 40 -> 100: the flick and most of its tail merge 13 * into fewer zoom batches. 14 * 2. wheelPxPerZoomLevel 60 -> 120: a level takes twice the scroll delta. 15 * 3. A patched _performZoom on the map's own scrollWheelZoom handler: 16 * - batches under DEAD_ZONE_PX are discarded outright; 17 * - within COOLDOWN_MS of a wheel zoom, batches weaker than 18 * STRONG_PX are discarded â that is the decaying momentum tail. 19 * A visitor still actively scrolling produces strong batches and 20 * zooms straight through the cooldown. 21 * 22 * Maps are captured via prototype-method hooks (the plugin constructs the 23 * map in a closure before this deferred script runs â same approach as 24 * map-viewport-fit.js). 25 */ 26(function () { 27 'use strict'; 28 29 var DEBOUNCE_MS = 100; 30 var PX_PER_LEVEL = 120; 31 var DEAD_ZONE_PX = 20; 32 var COOLDOWN_MS = 400; 33 var STRONG_PX = 120; 34 35 var MAX_POLL = 200; 36 var POLL_MS = 100; 37 38 function isExplorerLeafletMap( map ) { 39 try { 40 var div = map.getContainer && map.getContainer(); 41 return !! ( div && 'map' === div.id && div.closest && div.closest( '.hfse' ) ); 42 } catch ( e ) { 43 return false; 44 } 45 } 46 47 function damp( map ) { 48 if ( map.__hrtkZoomDamped ) { 49 return; 50 } 51 map.__hrtkZoomDamped = true; 52 53 map.options.wheelDebounceTime = DEBOUNCE_MS; 54 map.options.wheelPxPerZoomLevel = PX_PER_LEVEL; 55 56 var handler = map.scrollWheelZoom; 57 if ( ! handler || 'function' !== typeof handler._performZoom ) { 58 return; 59 } 60 61 var native = handler._performZoom; 62 var lastZoomAt = 0; 63 64 handler._performZoom = function () { 65 var strength = Math.abs( this._delta ); 66 67 var discard = 68 strength < DEAD_ZONE_PX || 69 ( Date.now() - lastZoomAt < COOLDOWN_MS && strength < STRONG_PX ); 70 71 if ( discard ) { 72 this._delta = 0; 73 this._startTime = null; 74 return; 75 } 76 77 lastZoomAt = Date.now(); 78 return native.call( this ); 79 }; 80 } 81 82 function hookLeaflet( L ) { 83 if ( L.Map.prototype.__hrtkZoomDampingHooked ) { 84 return; 85 } 86 L.Map.prototype.__hrtkZoomDampingHooked = true; 87 88 [ 'setView', 'panTo', 'fitBounds', 'getBounds', 'getCenter', 'addLayer' ].forEach( function ( name ) { 89 var native = L.Map.prototype[ name ]; 90 if ( 'function' !== typeof native ) { 91 return; 92 } 93 L.Map.prototype[ name ] = function () { 94 if ( ! this.__hrtkZoomDamped && isExplorerLeafletMap( this ) ) { 95 try { 96 damp( this ); 97 } catch ( e ) { 98 // Damping must never break the map itself. 99 } 100 } 101 return native.apply( this, arguments ); 102 }; 103 } ); 104 } 105 106 var attempts = 0; 107 var tick = setInterval( function () { 108 attempts++; 109 if ( window.L && window.L.Map && window.L.Map.prototype ) { 110 try { 111 hookLeaflet( window.L ); 112 } catch ( e ) { 113 // Leave native behaviour intact on any error. 114 } 115 clearInterval( tick ); 116 return; 117 } 118 if ( attempts >= MAX_POLL ) { 119 clearInterval( tick ); 120 } 121 }, POLL_MS ); 122})();
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.