1// B4J WebSockets client library v0.93 - Enhanced Reconnection & Compatibility 2/*jslint browser: true*/ 3/*global $, jQuery, WebSocket*/ 4/*jshint curly: false */ 5"use strict"; 6var b4j_ws; 7var b4j_closeMessage = false; 8var b4j_lastPath = ""; 9var b4j_reconnectAttempts = 0; 10var b4j_isReconnecting = false; 11 12function showWsReconnectBanner(show, customText) { 13 var banner = document.getElementById("b4j-reconnect-indicator"); 14 if (show) { 15 if (!banner) { 16 banner = document.createElement("div"); 17 banner.id = "b4j-reconnect-indicator"; 18 banner.style.cssText = "position:fixed;bottom:24px;right:24px;background:#1e293b;color:#f8fafc;padding:10px 18px;border-radius:10px;box-shadow:0 8px 24px rgba(0,0,0,0.25);font-family:'Inter',system-ui,sans-serif;font-size:13px;font-weight:600;z-index:999999;display:flex;align-items:center;gap:10px;border:1px solid rgba(255,255,255,0.12);transition:all 0.3s ease;"; 19 document.body.appendChild(banner); 20 } 21 var msg = customText || 'Reconectando servidor...'; 22 banner.innerHTML = '<span style="width:10px;height:10px;border-radius:50%;background:#f59e0b;display:inline-block;box-shadow:0 0 10px #f59e0b;animation:pulse 1.5s infinite;"></span> ' + msg; 23 banner.style.display = "flex"; 24 } else { 25 if (banner) { 26 var okMsg = customText || 'Servidor conectado'; 27 banner.innerHTML = '<span style="width:10px;height:10px;border-radius:50%;background:#10b981;display:inline-block;box-shadow:0 0 10px #10b981;"></span> ' + okMsg; 28 setTimeout(function() { 29 if (banner && banner.parentNode) banner.style.display = "none"; 30 }, 1200); 31 } 32 } 33} 34 35var b4j_eventQueue = []; 36 37function b4j_sendData(data) { 38 if (b4j_ws && b4j_ws.readyState === 1) { 39 b4j_ws.send(JSON.stringify({type: "data", data: data})); 40 } 41} 42 43function b4j_raiseEvent(eventName, parameters) { 44 try { 45 if (b4j_ws && b4j_ws.readyState === 0) { 46 // Socket still connecting; queue event to fire upon onopen 47 b4j_eventQueue.push({eventName: eventName, parameters: parameters}); 48 return; 49 } 50 if (!b4j_ws || b4j_ws.readyState !== 1) { 51 b4j_eventQueue.push({eventName: eventName, parameters: parameters}); 52 if (b4j_closeMessage === false) { 53 window.console.warn("WebSocket connection not ready. Queueing event and reconnecting..."); 54 showWsReconnectBanner(true, "Conectando al servidor..."); 55 if (typeof alertify !== 'undefined' && alertify.warning) { 56 alertify.warning("Conectando con el servidor... Espere un momento."); 57 } 58 b4j_closeMessage = true; 59 } 60 if (b4j_lastPath && !b4j_isReconnecting) { 61 b4j_scheduleReconnect(); 62 } 63 } else { 64 b4j_closeMessage = false; 65 showWsReconnectBanner(false); 66 b4j_ws.send(JSON.stringify({type: "event", event: eventName, params: parameters})); 67 } 68 } catch (e) { 69 window.console.error(e); 70 } 71} 72 73function b4j_scheduleReconnect() { 74 if (b4j_isReconnecting) return; 75 b4j_isReconnecting = true; 76 b4j_reconnectAttempts++; 77 if (b4j_reconnectAttempts > 8) { 78 window.console.warn("WebSocket session lost. Retrying in background..."); 79 b4j_reconnectAttempts = 4; 80 } 81 var delay = Math.min(1000 * Math.pow(1.5, b4j_reconnectAttempts - 1), 6000); 82 setTimeout(function() { 83 b4j_isReconnecting = false; 84 if (b4j_lastPath && (!b4j_ws || b4j_ws.readyState > 1)) { 85 b4j_connect(b4j_lastPath); 86 } 87 }, delay); 88} 89 90function b4j_addEvent(selector, event, eventName, preventDefault) { 91 var obj = $(selector); 92 if (obj.length > 0) { 93 obj.off(event).on(event, function (e) { 94 if (preventDefault) { 95 e.preventDefault(); 96 e.stopPropagation(); 97 } 98 b4j_raiseEvent(eventName, {which: e.which, target: e.target.id, pageX: e.pageX, pageY: e.pageY, metaKey: e.metaKey}); 99 }); 100 } 101} 102 103function b4j_addAutomaticEvents(data) { 104 $.each(data, function (index, value) { 105 b4j_addEvent("#" + value.id, value.event, value.id + "_" + value.event, true); 106 }); 107} 108 109function b4j_runFunction(func, params) { 110 if (typeof window[func] === 'function') { 111 return window[func].apply(null, params); 112 } else { 113 window.console.warn("b4j_runFunction: Function '" + func + "' is not defined."); 114 return null; 115 } 116} 117 118function b4j_eval(params, script) { 119 var f = new Function(script); 120 return f.apply(null, params); 121} 122 123function b4j_connect(absolutePath) { 124 if (typeof WebSocket === 'undefined') { 125 window.alert("WebSockets are not supported by your browser."); 126 return; 127 }
128 b4j_lastPath = absolutePath; 129 var l = window.location, fullpath; 130 var portStr = (l.port && l.port !== "80" && l.port !== "443") ? ":" + l.port : ""; 131 fullpath = ((l.protocol === "https:") ? "wss://" : "ws://") + l.hostname + portStr + absolutePath; 132 133 showWsReconnectBanner(true, 'Conectando al servidor...'); 134 135 try { 136 if (b4j_ws) { 137 if (b4j_ws.readyState === 0 || b4j_ws.readyState === 1) { 138 // Already connecting or open 139 return; 140 } 141 try { b4j_ws.close(); } catch(e) {} 142 } 143 b4j_ws = new WebSocket(fullpath); 144 145 b4j_ws.onopen = function() { 146 b4j_reconnectAttempts = 0; 147 b4j_closeMessage = false; 148 b4j_isReconnecting = false; 149 showWsReconnectBanner(false, 'Servidor conectado'); 150 window.console.log("WebSocket connected successfully to:", absolutePath); 151 152 // Flush any events that were queued while socket was connecting 153 while (b4j_eventQueue.length > 0) { 154 var item = b4j_eventQueue.shift(); 155 try { 156 b4j_ws.send(JSON.stringify({type: "event", event: item.eventName, params: item.parameters})); 157 } catch(qe) { 158 window.console.error("Error sending queued event:", qe); 159 } 160 } 161 }; 162 163 b4j_ws.onclose = function(e) { 164 window.console.warn("WebSocket closed. Code:", e.code, "Reason:", e.reason); 165 showWsReconnectBanner(true, 'Reconectando con el servidor...'); 166 if (!b4j_isReconnecting) { 167 b4j_scheduleReconnect(); 168 } 169 }; 170 171 b4j_ws.onerror = function(err) { 172 window.console.error("WebSocket error:", err); 173 showWsReconnectBanner(true, 'Error de conexión. Reintentando...'); 174 }; 175 176 b4j_ws.onmessage = function (event) { 177 if (event.data instanceof Blob) { 178 if (event.data.size == 0) return; 179 } 180 try { 181 var ed = JSON.parse(event.data); 182 if (ed.etype === "runmethod") { 183 var el = $(ed.id); 184 if (el.length > 0 && typeof el[ed.method] === 'function') { 185 el[ed.method].apply(el, ed.params); 186 } 187 } else if (ed.etype === "runmethodWithResult") { 188 var el2 = $(ed.id); 189 if (el2.length > 0 && typeof el2[ed.method] === 'function') { 190 b4j_sendData(el2[ed.method].apply(el2, ed.params)); 191 } 192 } else if (ed.etype === "setAutomaticEvents") { 193 b4j_addAutomaticEvents(ed.data); 194 } else if (ed.etype === "runFunction") { 195 b4j_runFunction(ed.prop, ed.value); 196 } else if (ed.etype === "runFunctionWithResult") { 197 b4j_sendData(b4j_runFunction(ed.prop, ed.value)); 198 } else if (ed.etype === "eval") { 199 b4j_eval(ed.value, ed.prop); 200 } else if (ed.etype === "evalWithResult") { 201 b4j_sendData(b4j_eval(ed.value, ed.prop)); 202 } else if (ed.etype === "alert") { 203 if (typeof alertify !== 'undefined') { 204 alertify.alert('Notificación', ed.prop); 205 } else { 206 window.alert(ed.prop); 207 } 208 } 209 } catch(ex) { 210 window.console.error("Error processing WebSocket message:", ex); 211 } 212 }; 213 } catch(err) { 214 window.console.error("Failed to establish WebSocket connection:", err); 215 showWsReconnectBanner(true); 216 b4j_scheduleReconnect(); 217 } 218}
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.