PageSourceSearch

https://jalgaon.gov.in/wp-content/plugins/bhashini-translation/assets/js/bhashini-asr.js

js jalgaon.gov.in collected 2026-10-02 21:35:43 UTC 8,592 bytes, 215 lines download raw bytes

1jQuery(document).ready(function($) {
2    const micBtn = $('.voice_search_mic_button, #mic-button');
3    const overlay = $('#voice-fullscreen-overlay');
4    const voiceMsg = $('.voice-message');
5    const voiceClose = $('.voice-close');
6    const searchInput = $('#search');
7    const $formContainer = $('.goiSearch');
8
9    let mediaRecorder = null;
10    let audioChunks = [];
11    let recordingTimeout = null;
12
13    micBtn.on('click', function() {
14        overlay.addClass('active').show();
15        $formContainer.attr('inert', '').attr('aria-hidden', 'true');
16        // overlay.attr({
17        //     'role': 'dialog',
18        //     'aria-modal': 'true',
19        //     'aria-labelledby': 'voice-message',
20        //     'tabindex': '0'
21        // });
22
23        setTimeout(() => {
24            voiceClose.focus();
25            trapFocus(overlay);
26        }, 250);
27        const speakNowText = bhashiniAjax.speak_now_text;
28        if (voiceMsg.text().trim() !== speakNowText) {
29            voiceMsg.text(speakNowText);
30        }
31
32        startRecording();
33    });
34
35    voiceClose.on('click', function() {
36        stopRecording(true);
37        overlay.fadeOut(200);
38        micBtn.focus();
39    });
40
41    $(document).on('keydown', function(e) {
42        if (e.key === 'Escape' && overlay.is(':visible')) {
43        stopRecording(true);
44        overlay.fadeOut(200);
45        micBtn.focus();
46        }
47    });
48    function closeOverlay() {
49        stopRecording(true);
50        overlay.removeClass('active').fadeOut(200, function() {
51            overlay.off('keydown.trapFocus').removeAttr('tabindex role aria-modal aria-labelledby');
52            $formContainer.removeAttr('inert aria-hidden');
53        });
54        micBtn.focus();
55    }
56
57    voiceClose.on('click', closeOverlay);
58
59    $(document).on('keydown.bhashini', function(e) {
60        if (e.key === 'Escape' && overlay.hasClass('active')) {
61            closeOverlay();
62        }
63    });
64    function trapFocus(element) {
65        const focusable = element.find('button, [href], input, textarea, [tabindex]:not([tabindex="-1"])').filter(':visible');
66        const first = focusable.first()[0];
67        const last = focusable.last()[0];
68
69        if (!first || !last) return;
70
71        element.off('keydown.trapFocus').on('keydown.trapFocus', function(e) {
72            if (e.key === 'Tab' || e.keyCode === 9) {
73                if (e.shiftKey && document.activeElement === first) {
74                    e.preventDefault();
75                    last.focus();
76                } else if (!e.shiftKey && document.activeElement === last) {
77                    e.preventDefault();
78                    first.focus();
79                }
80            }
81        });
82
83        setTimeout(() => first.focus(), 50);
84    }    
85
86    function startRecording() {
87        let mimeType = 'audio/webm';
88        if (MediaRecorder.isTypeSupported('audio/wav')) {
89            mimeType = 'audio/wav';
90        } else if (MediaRecorder.isTypeSupported('audio/webm')) {
91            mimeType = 'audio/webm';
92        } else {
93            console.error('No supported audio format (WAV or WebM) found.');
94            voiceMsg.text('Your browser does not support required audio formats.');
95            setTimeout(() => overlay.fadeOut(300), 2000);
96            return;
97        }
98        console.log('Selected MIME type:', mimeType);
99
100        let language = localStorage.getItem('preferredLanguage');
101        if (!language || language === 'null') {
102            language = typeof pll_language !== 'undefined' ? pll_language : 'en';
103        }
104        console.log('Selected language:', language);
105
106        navigator.mediaDevices.getUserMedia({ audio: true }).then(stream => {
107            mediaRecorder = new MediaRecorder(stream, { mimeType: mimeType });
108            audioChunks = [];
109
110            setTimeout(() => {
111                voiceMsg.text(bhashiniAjax.listening_text);
112            }, 1000);
113            // voiceMsg.attr('aria-live', 'off');
114            // setTimeout(() => {
115            //     voiceMsg.text(bhashiniAjax.listening_text)
116            //     voiceMsg.attr('aria-live', 'assertive');
117            // }, 1000);
118            mediaRecorder.ondataavailable = e => {
119                audioChunks.push(e.data);
120                console.log('Audio chunk received, type:', e.data.type);
121            };
122
123            mediaRecorder.onstop = () => {
124                clearTimeout(recordingTimeout);
125                const audioBlob = new Blob(audioChunks, { type: mimeType });
126                const reader = new FileReader();
127                reader.readAsDataURL(audioBlob);
128                reader.onloadend = () => {
129                    const base64Audio = reader.result.split(',')[1];
130                    const audioFormat = mimeType.includes('wav') ? 'wav' : 'webm';
131                    overlay.attr('aria-busy', 'true');
132                    $.ajax({
133                    url: bhashiniAjax.ajaxurl,
134                    type: 'POST',
135                    data: {
136                        action: 'bhashini_asr',
137                        audio_content: base64Audio,
138                        language: language,
139                        audio_format: audioFormat
140                    },
141                    success: (response) => {
142                        overlay.attr('aria-busy', 'false');
143                        console.log('Server response:', response);
144                        let text = response?.data?.text?.trim()?.toLowerCase();
145
146                        // List of screen reader/system phrases to exclude
147                        const excludePhrases = [
148                            "close voice search dialogue button listening",
149                            "this page is accessing your microphone change the setting",
150                            "this page is accessing your microphone change this",
151                            "listening",
152                            "speak now",
153                            "search my voice button, dialogue speak now, listening",
154                            "firefox sharing indicator alert",
155                            "dialogue box",
156                            "dialogue speed now listening okay query",
157                            "you",
158                            'firebox sharing educator alert',
159                            "close button",
160                            "dialogue speed now listening",
161                            "dialogue speed, listen",
162                            "dialogue's too pale listen",
163                            "dialogue speak"
164                        ];
165
166                        const isExcluded = excludePhrases.some(phrase => text.includes(phrase));
167
168                        if (response.success && text && text.length >= 3 && !isExcluded) {
169                            text = text.replace(/\./g, '');
170                            voiceMsg.text(text);
171                            searchInput.val(text).focus();
172                            setTimeout(() => {
173                                overlay.fadeOut(200);
174                                const form = searchInput[0].form;
175                                if (form) form.submit();
176                            }, 2000);
177                        } else {
178                        console.warn('Text excluded (screen reader or invalid):', text);
179                        voiceMsg.text(bhashiniAjax.client_error);
180                        setTimeout(() => overlay.fadeOut(300), 2000);
181                        }
182                    },
183                    error: (xhr, status, error) => {
184                        overlay.attr('aria-busy', 'false');
185                        console.error('AJAX error:', status, error, xhr.responseText);
186                        voiceMsg.text(bhashiniAjax.server_error_text);
187                        setTimeout(() => overlay.fadeOut(300), 2000);
188                    }
189                    });
190                };
191            };
192
193            mediaRecorder.start();
194            recordingTimeout = setTimeout(() => {
195                if (mediaRecorder.state !== 'inactive') {
196                    mediaRecorder.stop();
197                }
198            }, 3000);
199        }).catch((err) => {
200            console.error('Microphone error:', err);
201            voiceMsg.text(bhashiniAjax.no_mic_detected);
202            setTimeout(() => overlay.fadeOut(300), 3000);
203        });
204    }
205
206    function stopRecording(cancel = false) {
207        if (mediaRecorder && mediaRecorder.state !== 'inactive') {
208            mediaRecorder.stop();
209        }
210        if (cancel) {
211            audioChunks = [];
212            clearTimeout(recordingTimeout);
213        }
214    }
215});

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.