// ==UserScript==
// @name SLITHER.IO STANDALONE CHAT MOD (NOW TALK WITH SLITHER GAMERS!)
// @namespace http://tampermonkey.net/
// @version 11.6
// @description Adds the 143X community chat with profiles, GIFs, Discord integration, and settings to Slither.io.
// @author dxxthly & waynesg
// @match http://slither.io/
// @match https://slither.io/
// @match http://slither.com/io
// @match https://slither.com/io
// @grant none
// @icon https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQUNcRl2Rh40pZLhgffYGFDRLbYJ4qfMNwddQ&s
// ==/UserScript==
(function() {
'use strict';
// --- NEW: THE UNBREAKABLE GUARDIAN ---
// This injects a high-priority stylesheet to override any malicious CSS.
(function createGuardianStylesheet() {
const guardianStyle = document.createElement('style');
guardianStyle.id = 'mod-guardian-styles';
// The '!important' flag ensures these rules win against any injected styles.
guardianStyle.textContent = `
html {
filter: none !important;
transform: none !important;
}
body {
transform: none !important;
}
`;
(document.head || document.documentElement).appendChild(guardianStyle);
console.log('Guardian Stylesheet is active.');
})();
// --- END OF GUARDIAN ---
let hasInitialized = false;
// =================================================================================
// INITIALIZATION CHECKER
// This is the new, robust way to start the script.
// It will repeatedly check if the slither.io page is ready.
// =================================================================================
const initChecker = setInterval(() => {
// We check for the 'login' div, which is a reliable indicator that the core page has loaded.
if (document.getElementById('login') && !hasInitialized) {
hasInitialized = true; // Prevents the script from running multiple times
clearInterval(initChecker); // Stop checking once we've started
main(); // Run the main script logic
}
}, 100); // Check every 100 milliseconds
// REPLACE WITH THIS
const systemAccounts = [
"system",
"discord_bot",
"system_badge" // <-- THE FIX IS HERE
];
// =================================================================================
// MAIN SCRIPT FUNCTION
// All of our chat logic now lives inside this function.
// =================================================================================
function main() {
// --- CONFIGURATION ---
const config = {
chatMaxMessages: 75,
firebaseConfig: {
apiKey: "AIzaSyCtTloqGNdhmI3Xt0ta11vF0MQJHiKpO7Q",
authDomain: "chatforslither.firebaseapp.com",
databaseURL: "https://chatforslither-default-rtdb.firebaseio.com",
projectId: "chatforslither",
storageBucket: "chatforslither.appspot.com",
messagingSenderId: "1045559625491",
appId: "1:1045559625491:web:79eb8200eb87edac00bce6"
},
devList: [{ uid: "CiOpgh1RLBg3l5oXn0SAho66Po93" }, { uid: "PZA5qgKWsPTXc278pyx7NwROf313" }, { uid: "P75eMwh756Rb6h1W6iqQfHN2Dm92" }],
vipMembers: [{ uid: "crcOY9hoRrfayStCxMVm7Zdx2W92", name: "stevao" }, { uid: "DhGhICAZwkRa7wuMsyquM9a5uO92", name: "LUANBLAYNER" }]
};
// --- STYLES (CSS INJECTION) ---
const style = document.createElement('style');
style.textContent = `
#chat-container { position: fixed; left: 20px; top: 100px; width: 380px; height: 400px; z-index: 9999; display: flex; flex-direction: column; background: rgba(28, 28, 32, 0.97); border: 1px solid #4CAF50; border-radius: 8px; box-shadow: 0 5px 20px rgba(0,0,0,0.3); overflow: hidden; user-select: none; resize: both; min-width: 320px; min-height: 250px; }
#chat-header { display: flex; align-items: center; border-bottom: 1px solid #4CAF50; background: rgba(0,0,0,0.2); cursor: move; }
.chat-tab { flex: 1; padding: 10px 12px; text-align: center; cursor: pointer; font-weight: 500; transition: background 0.2s, color 0.2s; }
#chat-tab-main { background: rgba(76, 175, 80, 0.25); color: #fff; } #chat-tab-users { background: transparent; color: #ccc; }
#chat-settings-btn, #chat-hide-btn { background: none; border: none; color: #ccc; font-size: 20px; padding: 0 12px; cursor: pointer; transition: color 0.2s; border-left: 1px solid rgba(255,255,255,0.1); }
#chat-settings-btn:hover, #chat-hide-btn:hover { color: white; }
#chat-area { flex: 1; display: flex; flex-direction: column; overflow: hidden; }
#chat-body, #online-users { flex: 1; padding: 10px 15px; overflow-y: auto; display: flex; flex-direction: column; gap: 5px; scrollbar-width: thin; scrollbar-color: #4CAF50 rgba(0,0,0,0.2); }
#online-users { display: none; }
#chat-input-container { display: flex; align-items: center; border-top: 1px solid #4CAF50; }
#chat-input { flex-grow: 1; padding: 12px 15px; border: none; background: transparent; color: #e0e0e0; outline: none; font-size: 14px; }
.chat-username { font-weight: bold; cursor: pointer; text-decoration: underline dotted; }
.chat-modal-overlay { display: none; position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; z-index: 10001; background: rgba(0,0,0,0.75); align-items: center; justify-content: center; }
.chat-modal-content { background: #2E2E34; border-radius: 10px; padding: 25px 30px; min-width: 400px; display: flex; flex-direction: column; gap: 15px; border: 1px solid #555; }
.chat-modal-content h2 { margin: 0 0 10px 0; color: #4CAF50; text-align: center; }
.settings-field { display: flex; flex-direction: column; gap: 5px; } .settings-field label { color: #bbb; font-size: 0.9em; }
.settings-field input[type="text"] { width: 100%; box-sizing: border-box; padding: 10px; background: #222; border: 1px solid #555; border-radius: 5px; color: #eee; font-size: 1em; }
.color-input-wrapper { display: flex; align-items: center; gap: 10px; padding: 5px; background: #222; border: 1px solid #555; border-radius: 5px; }
.color-input-wrapper input[type="color"] { width: 30px; height: 30px; border: none; background: none; cursor: pointer; padding: 0; }
.color-input-wrapper input[type="text"] { flex-grow: 1; border: none; background: none; color: #eee; padding: 5px; }
.modal-buttons { display: flex; justify-content: flex-end; gap: 10px; margin-top: 10px; }
.modal-btn { padding: 9px 20px; border: none; border-radius: 5px; font-size: 0.95em; cursor: pointer; }
#settings-save-btn { background: #4CAF50; color: #fff; } #settings-cancel-btn { background: #555; color: #fff; }
.profile-popup { position: fixed; z-index: 10002; display: flex; flex-direction: column; align-items: center; left: 50%; top: 50%; transform: translate(-50%, -50%); min-width: 280px; background: #2A2A2F; color: #e0e0e0; border-radius: 12px; border: 1px solid #4CAF50; box-shadow: 0 8px 32px rgba(0,0,0,0.35); padding: 24px 30px; }
.profile-popup .avatar { width: 72px; height: 72px; border-radius: 50%; object-fit: cover; border: 3px solid #4CAF50; margin-bottom: 16px; }
.profile-popup .close-btn { position: absolute; top: 12px; right: 12px; background: none; border: none; color: #aaa; font-size: 1.6em; cursor: pointer; }
`;
document.head.appendChild(style);
// --- HELPER FUNCTIONS ---
const escapeHTML = (str) => { const p = document.createElement('p'); p.appendChild(document.createTextNode(str)); return p.innerHTML; };
const isDev = (uid) => config.devList.some(dev => dev.uid === uid);
const isVip = (uid, name) => config.vipMembers.some(vip => vip.uid === uid && vip.name.toLowerCase() === (name || '').toLowerCase());
const rainbowTextStyle = (name) => name.split('').map((char, i) => `<span style="color:${["#ef3550","#f48fb1","#7e57c2","#2196f3","#26c6da","#43a047","#eeff41","#f9a825","#ff5722"][i % 9]}; font-weight: bold;">${char}</span>`).join('');
const vipGlowStyle = (name, color) => `<span style="color:#fff;font-weight:bold;text-shadow:0 0 5px #fff, 0 0 10px ${color}, 0 0 15px ${color};">${name}</span>`;
// --- UI & MODAL CREATION ---
const chatContainer = document.createElement('div'); chatContainer.id = 'chat-container';
chatContainer.innerHTML = `
<div id="chat-header"> <div id="chat-tab-main" class="chat-tab">143X Chat</div> <div id="chat-tab-users" class="chat-tab">Online Users</div> <button id="chat-settings-btn" title="Settings">⚙️</button> <button id="chat-hide-btn" title="Hide Chat">×</button> </div>
<div id="chat-area"> <div id="chat-body"><p style="color:#888; text-align:center;">Initializing...</p></div> <div id="online-users"></div> <div id="chat-input-container"><input id="chat-input" type="text" placeholder="Connecting..." disabled></div> </div>`;
document.body.appendChild(chatContainer);
makeDraggable(chatContainer, document.getElementById('chat-header'));
const settingsModal = document.createElement('div'); settingsModal.id = 'settings-modal-overlay'; settingsModal.className = 'chat-modal-overlay';
settingsModal.innerHTML = `
<div id="settings-modal" class="chat-modal-content">
<h2>Chat & Profile Settings</h2>
<div class="settings-field"><label>Nickname</label><input type="text" id="settings-nickname" maxlength="20"></div>
<div class="settings-field"><label>Chat Name Color</label>
<div class="color-input-wrapper">
<input type="color" id="settings-name-color">
</div>
</div>
<div class="settings-field"><label>Profile Avatar URL</label><input type="text" id="settings-avatar"></div>
<div class="settings-field"><label>Profile Motto</label><input type="text" id="settings-motto" maxlength="60"></div>
<div class="modal-buttons"><button id="settings-cancel-btn" class="modal-btn">Cancel</button><button id="settings-save-btn" class="modal-btn">Save</button></div>
</div>`;
document.body.appendChild(settingsModal);
// --- FIREBASE & CHAT LOGIC ---
function loadFirebaseAndInit() {
const script1 = document.createElement('script'); script1.src = 'https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js';
script1.onload = () => { const script2 = document.createElement('script'); script2.src = 'https://www.gstatic.com/firebasejs/8.10.0/firebase-database.js';
script2.onload = () => { const script3 = document.createElement('script'); script3.src = 'https://www.gstatic.com/firebasejs/8.10.0/firebase-auth.js';
script3.onload = () => initializeChat(window.firebase); document.head.appendChild(script3); }; document.head.appendChild(script2); }; document.head.appendChild(script1);
}
function initializeChat(firebase) {
if (!firebase.apps.length) firebase.initializeApp(config.firebaseConfig);
const auth = firebase.auth(); const db = firebase.database();
auth.signInAnonymously().catch(err => console.error("Firebase Sign-In Error:", err));
auth.onAuthStateChanged(user => {
if (user) {
const chatInput = document.getElementById('chat-input'); chatInput.disabled = false; chatInput.placeholder = 'Type and press Enter...'; document.getElementById('chat-body').innerHTML = '';
let nickname = localStorage.getItem("slitherChatNickname");
if (!nickname) { nickname = prompt("Welcome! Please enter a nickname:", "Player") || "Anon"; localStorage.setItem("slitherChatNickname", nickname); }
const userRef = db.ref("onlineUsers/" + user.uid);
userRef.onDisconnect().remove();
const localData = { name: nickname, chatNameColor: localStorage.getItem("slitherChatNameColor") || "#FFD700", profileAvatar: localStorage.getItem("slitherChatAvatar") || "", profileMotto: localStorage.getItem("slitherChatMotto") || "" };
userRef.update({ ...localData, uid: user.uid, lastActive: firebase.database.ServerValue.TIMESTAMP });
setInterval(() => userRef.update({ lastActive: Date.now() }), 45000);
listenForOnlineUsers(db, user.uid);
setupEventListeners(db, user.uid);
}
});
let chatMessagesArray = [];
let latestTimeLoaded = 0;
const chatBody = document.getElementById('chat-body');
const currentUser = auth.currentUser;
// Step 1: Load initial messages
db.ref("slitherChat").orderByChild("time").limitToLast(config.chatMaxMessages).once("value", async (snapshot) => {
if (!snapshot.exists()) return;
snapshot.forEach(child => { chatMessagesArray.push({ key: child.key, ...child.val() }); });
chatMessagesArray.sort((a, b) => a.time - b.time);
if (chatMessagesArray.length > 0) { latestTimeLoaded = chatMessagesArray[chatMessagesArray.length - 1].time; }
if (chatBody) {
chatBody.innerHTML = '';
for (const msg of chatMessagesArray) { await renderChatMessage(msg, chatBody, currentUser?.uid); }
chatBody.scrollTop = chatBody.scrollHeight;
}
// Step 2: Listen for ONLY new messages from now on
db.ref("slitherChat").orderByChild("time").startAt(latestTimeLoaded + 1).on("child_added", async (newSnapshot) => {
const newMsg = { key: newSnapshot.key, ...newSnapshot.val() };
if (chatMessagesArray.some(m => m.key === newMsg.key)) return;
chatMessagesArray.push(newMsg);
if (chatMessagesArray.length > config.chatMaxMessages) chatMessagesArray.shift();
if (chatBody) {
while (chatBody.children.length >= config.chatMaxMessages) { chatBody.removeChild(chatBody.firstChild); }
await renderChatMessage(newMsg, chatBody, currentUser?.uid, true);
}
});
});
}
function renderChatMessage(msg, chatBodyElement, currentUid, shouldScroll = false) {
// Check if user is ignored
if (window.standaloneState && window.standaloneState.ignoredUsers && window.standaloneState.ignoredUsers[msg.uid]) return;
if (!msg || !msg.uid) return;
// --- 1. SETUP & VALIDATION ---
const isValidHexColor = (color) => /^#([0-9a-fA-F]{3}){1,2}$/.test(color);
let userColor = (msg.chatNameColor && isValidHexColor(msg.chatNameColor)) ? msg.chatNameColor : '#FFD700';
const isSystemMessage = systemAccounts.includes(msg.uid);
const isDiscordBot = msg.uid === 'discord_bot';
const displayName = escapeHTML(msg.name || 'Anon');
let nameHtml;
let roleTagHTML = '';
// --- 2. BUILD THE NAME HTML BASED ON USER TYPE ---
if (isDiscordBot) {
// Discord names are not clickable as they don't have in-game profiles
nameHtml = `<span style="color:${userColor};font-weight:bold;">${displayName}</span>`;
roleTagHTML = ` <span style="background: #7289DA; color: #fff; padding: 2px 7px; border-radius: 4px; font-size: 0.8em; font-weight: 700; vertical-align:middle;">DISCORD</span>`;
} else if (isDev(msg.uid)) {
// Dev names are clickable
nameHtml = `<span class="chat-username" data-uid="${msg.uid}" style="cursor:pointer;">${rainbowTextStyle(displayName)}</span>`;
roleTagHTML = ` <span style="background: #E91E63; color: #fff; padding: 2px 7px; border-radius: 4px; font-size: 0.8em; font-weight: 700; vertical-align:middle;">DEV</span>`;
} else if (isVip(msg.uid, msg.name)) {
// VIP names are clickable
nameHtml = `<span class="chat-username" data-uid="${msg.uid}" style="cursor:pointer;">${vipGlowStyle(displayName, userColor)}</span>`;
roleTagHTML = ` <span style="background: #9C27B0; color: #fff; padding: 2px 7px; border-radius: 4px; font-size: 0.8em; font-weight: 700; vertical-align:middle;">VIP</span>`;
} else if (isSystemMessage) {
// System names are not clickable
nameHtml = `<span style="color:${userColor};font-weight:bold;">System</span>`;
roleTagHTML = ` <span style="background: #e74c3c; color: #fff; padding: 2px 7px; border-radius: 4px; font-size: 0.8em; font-weight: 700; vertical-align:middle;">SYSTEM</span>`;
} else {
// *** THIS IS THE KEY CHANGE FOR REGULAR USERS ***
// We add the class and data-uid to make them clickable too.
nameHtml = `<span class="chat-username" data-uid="${msg.uid}" style="color:${userColor};font-weight:bold;cursor:pointer;">${displayName}</span>`;
}
// --- 3. HANDLE MESSAGE CONTENT (IMAGES, HTML, ETC.) ---
let finalMessage = '';
const imageRegex = /(https?:\/\/[^\s]+\.(?:png|jpg|jpeg|gif|webp))/i;
const imageMatch = msg.text.match(imageRegex);
if (imageMatch) {
// If there's an image, separate it from the text
const textPart = escapeHTML(msg.text.replace(imageRegex, '').trim());
finalMessage = `${textPart}<br><img src="${imageMatch[0]}" style="max-width:90%; border-radius:6px; margin-top:5px; cursor:pointer;" onclick="window.open('${imageMatch[0]}', '_blank')">`;
} else if (isSystemMessage || isDev(msg.uid)) {
// Allow HTML for Devs and System messages
finalMessage = msg.text;
} else {
// Escape HTML for everyone else to prevent injection
finalMessage = escapeHTML(msg.text);
}
// --- 4. ASSEMBLE AND RENDER THE FINAL ELEMENT ---
const el = document.createElement('div');
const borderColor = (msg.uid === currentUid) ? '#4CAF50' : '#444';
const bgColor = (msg.uid === currentUid) ? 'rgba(76, 175, 80, 0.12)' : 'rgba(255,255,255,0.04)';
el.style.cssText = `margin-bottom: 8px; word-break: break-word; background: ${bgColor}; padding: 8px 12px; border-radius: 6px; color: #ddd; font-family: inherit; font-size: 14px; line-height: 1.5; border-left: 3px solid ${borderColor};`;
const timestamp = new Date(msg.time).toLocaleTimeString([], { hour12: true, hour: '2-digit', minute: '2-digit' });
el.innerHTML = `<span style="color:#888; font-size:0.9em; margin-right:5px;">${timestamp}</span> <b>${nameHtml}${roleTagHTML}:</b> ${finalMessage}`;
chatBodyElement.appendChild(el);
// Auto-scroll logic
if (shouldScroll || chatBodyElement.scrollTop >= chatBodyElement.scrollHeight - chatBodyElement.clientHeight - 150) {
chatBodyElement.scrollTop = chatBodyElement.scrollHeight;
}
}
function listenForOnlineUsers(db, currentUid) {
const onlineUsersRef = db.ref("onlineUsers");
const onlineUsersDiv = document.getElementById('online-users');
const onlineUsersTab = document.getElementById('chat-tab-users');
const tenMinutesAgo = Date.now() - (10 * 60 * 1000);
onlineUsersRef.orderByChild('lastActive').startAt(tenMinutesAgo).on('value', (snapshot) => {
if (!onlineUsersDiv) return;
onlineUsersDiv.innerHTML = '';
let userCount = 0;
if (snapshot.exists()) {
snapshot.forEach(childSnapshot => {
const user = childSnapshot.val();
if (!user || !user.name) return;
userCount++;
const userEl = document.createElement('div');
userEl.style.cssText = `padding: 5px; cursor: pointer; border-radius: 4px; display:flex; align-items:center;`;
userEl.className = 'chat-username'; // Make it clickable
userEl.dataset.uid = user.uid; // Store UID for click event
const userColor = (user.chatNameColor && /^#([0-9a-fA-F]{3}){1,2}$/.test(user.chatNameColor)) ? user.chatNameColor : '#FFFFFF';
let nameHtml;
if (isDev(user.uid)) {
nameHtml = rainbowTextStyle(escapeHTML(user.name));
} else if (isVip(user.uid, user.name)) {
nameHtml = vipGlowStyle(escapeHTML(user.name), userColor);
} else {
nameHtml = `<span style="color:${userColor};">${escapeHTML(user.name)}</span>`;
}
userEl.innerHTML = nameHtml;
onlineUsersDiv.appendChild(userEl);
});
}
onlineUsersTab.textContent = `Online Users (${userCount})`;
});
}
async function showUserProfile(db, uid) {
// Prevent opening multiple popups
if (document.querySelector('.profile-popup')) return;
try {
const userSnapshot = await db.ref(`onlineUsers/${uid}`).once('value');
if (!userSnapshot.exists()) {
console.log("User not found or offline.");
return;
}
const userData = userSnapshot.val();
const popup = document.createElement('div');
popup.className = 'profile-popup';
const defaultAvatar = 'https://i.imgur.com/M6NYjjO.jpeg';
const avatarUrl = (userData.profileAvatar || '').trim() || defaultAvatar;
popup.innerHTML = `
<button class="close-btn">×</button>
<img src="${escapeHTML(avatarUrl)}" class="avatar" onerror="this.src='${defaultAvatar}'">
<h3 style="margin: 0; color: ${escapeHTML(userData.chatNameColor || '#fff')};">${escapeHTML(userData.name || 'Anonymous')}</h3>
<p style="color: #bbb; font-style: italic; margin: 5px 0 15px 0;">"${escapeHTML(userData.profileMotto || 'No motto.')}"</p>
<div class="profile-actions">
<!-- Add buttons for ignore, etc. here if needed -->
</div>
`;
document.body.appendChild(popup);
// Add event listener to the close button
popup.querySelector('.close-btn').addEventListener('click', () => {
popup.remove();
});
} catch (error) {
console.error("Error fetching user profile:", error);
}
}
// --- EVENT LISTENERS ---
function setupEventListeners(db, uid) {
document.getElementById('chat-tab-main').addEventListener('click', () => { document.getElementById('chat-body').style.display = 'flex'; document.getElementById('online-users').style.display = 'none'; document.getElementById('chat-tab-main').style.background='rgba(76, 175, 80, 0.25)'; document.getElementById('chat-tab-users').style.background='transparent';});
document.getElementById('chat-tab-users').addEventListener('click', () => { document.getElementById('chat-body').style.display = 'none'; document.getElementById('online-users').style.display = 'flex'; document.getElementById('chat-tab-users').style.background='rgba(76, 175, 80, 0.25)'; document.getElementById('chat-tab-main').style.background='transparent';});
document.getElementById('chat-input').addEventListener('keydown', (e) => { if (e.key === 'Enter') { const text = e.target.value.trim(); if (text) { const name = localStorage.getItem("slitherChatNickname"); const color = localStorage.getItem("slitherChatNameColor") || "#FFD700"; db.ref("slitherChat").push({ uid, name, text, time: firebase.database.ServerValue.TIMESTAMP, chatNameColor: color }); db.ref("discordBridge").push({ uid, name, text, time: firebase.database.ServerValue.TIMESTAMP }); e.target.value = ''; } } });
const settingsOverlay = document.getElementById('settings-modal-overlay');
document.getElementById('chat-settings-btn').addEventListener('click', () => {
document.getElementById('settings-nickname').value = localStorage.getItem("slitherChatNickname") || '';
// CORRECTED: Only set the value for the existing color picker
document.getElementById('settings-name-color').value = localStorage.getItem("slitherChatNameColor") || '#FFD700';
document.getElementById('settings-avatar').value = localStorage.getItem("slitherChatAvatar") || '';
document.getElementById('settings-motto').value = localStorage.getItem("slitherChatMotto") || '';
settingsOverlay.style.display = 'flex';
});
document.getElementById('settings-cancel-btn').addEventListener('click', () => settingsOverlay.style.display = 'none');
const cPicker = document.getElementById('settings-name-color');
document.getElementById('settings-save-btn').addEventListener('click', () => { const newData = { name: document.getElementById('settings-nickname').value.trim().slice(0, 20) || 'Anon', chatNameColor: cPicker.value, profileAvatar: document.getElementById('settings-avatar').value.trim(), profileMotto: document.getElementById('settings-motto').value.trim() }; localStorage.setItem("slitherChatNickname", newData.name); localStorage.setItem("slitherChatNameColor", newData.chatNameColor); localStorage.setItem("slitherChatAvatar", newData.profileAvatar); localStorage.setItem("slitherChatMotto", newData.profileMotto); db.ref("onlineUsers/" + uid).update(newData); settingsOverlay.style.display = 'none'; });
document.getElementById('chat-hide-btn').addEventListener('click', () => document.getElementById('chat-container').style.display = 'none');
document.body.addEventListener('click', e => { if (e.target.closest('.chat-username')) showUserProfile(db, e.target.closest('.chat-username').dataset.uid); });
}
// --- UTILITY ---
function makeDraggable(el, handle) { let p1=0, p2=0, p3=0, p4=0; handle.onmousedown = (e) => { e.preventDefault(); p3 = e.clientX; p4 = e.clientY; document.onmouseup = () => {document.onmouseup=null; document.onmousemove=null;}; document.onmousemove = (e) => { e.preventDefault(); p1=p3-e.clientX; p2=p4-e.clientY; p3=e.clientX; p4=e.clientY; el.style.top=(el.offsetTop-p2)+"px"; el.style.left=(el.offsetLeft-p1)+"px"; }; }; }
// --- RUN ---
loadFirebaseAndInit();
}
})();