Trending

#SMASHING

Latest posts tagged with #SMASHING on Bluesky

Latest Top
Trending

Posts tagged #SMASHING

Original post on 247webdevs.blogspot.com

Moving From Moment.js To The JS Temporal API Almost any kind of application written in JavaScript works with times or dates in some capacity. In the beginning, this was limited to the built-in Date...

#Articles #on #Smashing #Magazine #— #For #Web #Designers #And #Developers

Origin | Interest […]

1 0 0 0
Original post on grahamcluley.com

Smashing Security podcast #458: How not to steal $46 million from the US government A Wikipedia security engineer accidentally wakes a dormant JavaScript worm that hadn't stirred since 2024 - a...

#Law #& #order #Malware #Podcast #cryptocurrency #JavaScript […]

[Original post on grahamcluley.com]

1 0 0 0

I love creative requests. Dont get me wrong, all requests are fun to do and I appreciate them but sometimes yall come up with some real bangers. 🙌🥳 I will be smashing a cake with my cake. Want to watch? 🥹

#cake #cakebytheocean #smashing #foodplay #foodporn

2 0 0 0

Imagine being able to say you have raced at Silverstone?!

That's exactly what our brilliant student did this past weekend.

Josh works so hard at improving his skill, knowledge of tracks and his PB.

Keep at it Josh, you are #smashing it

2 0 0 0
Video

#ballbusting-time for slave's Master's amusement
Day 3/5 #smashing the #slaveballs with the bonger #naked inside the car at the #parkingspace of a supermarket
#enjoying the #pain
Thank you for that great task, Master @mastertaurusxl.bsky.social.🧎🏻‍♂️🙏🏽
#obey #grateful #balltorture #exhib #locked
Part 4/4

15 0 0 0
Video

#ballbusting-time for slave's Master's amusement
Day 3/5 #smashing the #slaveballs with the bonger #naked inside the car at the #parkingspace of a supermarket
#enjoying the #pain
Thank you for that great task, Master @mastertaurusxl.bsky.social.🧎🏻‍♂️🙏🏽
#obey #grateful #balltorture #exhib #locked
Part 3/4

19 4 1 0
Video

#ballbusting-time for slave's Master's amusement
Day 3/5 #smashing the #slaveballs with the bonger #naked inside the car at the #parkingspace of a supermarket
#enjoying the #pain
Thank you for that great task, Master @mastertaurusxl.bsky.social.🧎🏻‍♂️🙏🏽
#obey #grateful #balltorture #exhib #locked
Part 2/4

4 0 1 0
Video

#ballbusting-time for slave's Master's amusement
Day 3/5 #smashing the #slaveballs with the bonger #naked inside the car at the #parkingspace of a supermarket
#enjoying the #pain
Thank you for that great task, Master @mastertaurusxl.bsky.social.🧎🏻‍♂️🙏🏽
#obey #grateful #balltorture #exhib #locked
Part 1/4

27 3 1 0
Video

Day 1/5 #kitchen-#balltorture with #rollingpin & #tenderizer
#pressing, #smashing the #slaveballs
The slave #enjoyed the #pain for sure #locked.
Thank you for that great task,Master @mastertaurusxl.bsky.social. 🧎🏻‍♂️🙏🏽
#obey #grateful
Part 3/3

17 0 1 0
Video

Day 1/5 #kitchen-#balltorture with #rollingpin & #tenderizer
#pressing, #smashing the #slaveballs
The slave #enjoyed the #pain for sure #locked.
Thank you for that great task,Master @mastertaurusxl.bsky.social. 🧎🏻‍♂️🙏🏽
#obey #grateful
Part 2/3

11 0 1 0
Video

Slave's Master said, it's #ballbusting-time for his amusement
Day 1/5 #kitchen-#balltorture with #rollingpin & #tenderizer
#pressing, #smashing the #slaveballs
The slave #enjoyed the #pain for sure #locked.
Thank you for that great task,Master @mastertaurusxl.bsky.social. 🧎🏻‍♂️🙏🏽
#obey #grateful
Part 1/3

23 1 2 0
Original post on grahamcluley.com

Smashing Security podcast #455: Face off: Meta’s Glasses and America’s internet kill switch Could America turn off Europe's internet? That’s one of the questions that Graham and special g...

#Facebook #Law #& #order #Podcast #Privacy #Meta #Ray-Ban #smart […]

[Original post on grahamcluley.com]

0 0 0 0
Post image

Steady Away Lads!

Nigerian brewed Guinness "Foreign Extra" Stout. 7.5% abv. #Smashing #Bskybeer

Cheers m'dears!

285 18 26 2
Original post on 247webdevs.blogspot.com

CSS @scope: An Alternative To Naming Conventions And Heavy Abstractions When learning the principles of basic CSS, one is taught to write modular, reusable, and descriptive styles to ensure maintai...

#Articles #on #Smashing #Magazine #— #For #Web #Designers #And #Developers

Origin | Interest […]

1 0 0 0
Post image Post image Post image

Clips of this cake sploshing available now! 🎂

#sploshing #sploshingfetish #foodfetish #footfetish #footporn #amateurporn #footworship #fetish #cakefetish #cakesitting #stuffingkink #feedee #feederism #smashing #bbw #chubbygirl #nsfwsky #soles #dirtysoles #wetnmessy #feet #booty #camgirl

10 2 0 0
Preview
Practical Use Of AI Coding Tools For The Responsible Developer Over the last two years, my team at Work & Co and I have been testing out and gradually integrating AI coding tools like Copilot, Cursor, Claude, and ChatGPT to help us ship web experiences that are used by the masses. Admittedly, after some initial skepticism and a few aha moments, various AI tools have found their way into my daily use. Over time, the list of applications where we found it made sense to let AI take over started to grow, so I decided to share some **practical use cases** for AI tools for what I call the “responsible developer”. What do I mean by a **responsible developer**? We have to make sure that we deliver quality code as expected by our stakeholders and clients. Our contributions (i.e., pull requests) should not become a burden on our colleagues who will have to review and test our work. Also, in case you work for a company: The tools we use need to be approved by our employer. Sensitive aspects like security and privacy need to be handled properly: Don’t paste secrets, customer data (PII), or proprietary code into tools without policy approval. Treat it like code from a stranger on the internet. Always test and verify. **Note** : _This article assumes some very basic familiarity with AI coding tools like Copilot inside VSCode or Cursor. If all of this sounds totally new and unfamiliar to you, theGithub Copilot video tutorials can be a fantastic starting point for you._ Helpful Applications Of AI Coding Tools **Note** : The following examples will mainly focus on working in JavaScript-based web applications like React, Vue, Svelte, or Angular. ### Getting An Understanding Of An Unfamiliar Codebase It’s not uncommon to work on established codebases, and joining a large legacy codebase can be intimidating. Simply open your project and your AI agent (in my case, Copilot Chat in VSCode) and start asking questions just like you would ask a colleague. In general, I like to talk to any AI agent just as I would to a fellow human. Here is a more refined example prompt: > “Give me a high-level architecture overview: entrypoints, routing, auth, data layer, build tooling. Then list 5 files to read in order. Treat explanations as hypotheses and confirm by jumping to referenced files.” You can keep asking follow-up questions like _“How does the routing work in detail?”_ or _“Talk me through the authentication process and methods”_ and it will lead you to helpful directions to shine some light into the dark of an unfamiliar codebase. ### Triaging Breaking Changes When Upgrading Dependencies Updating npm packages, especially when they come with breaking changes, can be tedious and time-consuming work, and make you debug a fair amount of regressions. I recently had to upgrade the data visualization library plotly.js up one major release version from version 2 to 3, and as a result of that, the axis labeling in some of the graphs stopped working. I went on to ask ChatGPT: > “I updated my Angular project that uses Plotly. I updated the plotly.js — dist package from version 2.35.2 to 3.1.0 — and now the labels on the x and y axis are gone. What happened?” The agent came back with a solution promptly (see for yourself below). **Note** : _I still verified the explanation against the official migration guide before shipping the fix._ ### Replicating Refactors Safely Across Files Growing codebases most certainly unveil opportunities for code consolidation. For example, you notice code duplication across files that can be extracted into a single function or component. As a result, you decide to create a shared component that can be included instead and perform that refactor in one file. Now, instead of manually carrying out those changes to your remaining files, you ask your agent to roll out the refactor for you. Agents let you select multiple files as context. Once the refactor for one file is done, I can add both the refactored and untouched files into context and prompt the agent to roll out the changes to other files like this: _“Replicate the changes I made in file A to file B as well”_. ### Implementing Features In Unfamiliar Technologies One of my favorite aha-moments using AI coding tools was when it helped me create a quite complex animated gradient animation in GLSL, a language I have been fairly unfamiliar with. On a recent project, our designers came up with an animated gradient as a loading state on a 3D object. I really liked the concept and wanted to deliver something unique and exciting to our clients. The problem: I only had two days to implement it, and GLSL has quite the steep learning curve. Again, an AI tool (in this case, ChatGPT) came in handy, and I started quite simply prompting it to create a standalone HTML file for me that renders a canvas and a very simple animated color gradient. Step after step, I prompted the AI to add more finesse to it until I arrived at a decent result so I could start integrating the shader into my actual codebase. The end result: Our clients were super happy, and we delivered a complex feature in a small amount of time thanks to AI. ### Writing Tests In my experience, there’s rarely enough time on projects to continuously write and maintain a proper suite of unit and integration tests, and on top of that, many developers don’t really enjoy the task of writing tests. Prompting your AI helper to set up and write tests for you is entirely possible and can be done in a small amount of time. Of course, you, as a developer, should still make sure that your tests actually take a look at the critical parts of your application and follow sensible testing principles, but you can “outsource” the writing of the tests to our AI helper. Example prompt: > “Write unit tests for this function using Jest. Cover happy path, edge cases, and failure modes. Explain why each test exists.” You can even pass along testing guru Kent C. Dodds’ testing best practices as guidelines to your agent, like below: ### Internal Tooling Somewhat similar to the shader example mentioned earlier, I was recently tasked to analyze code duplication in a codebase and compare before and after a refactor. Certainly not a trivial task if you don’t want to go the time-consuming route of comparing files manually. With the help of Copilot, I created a script that analyzed code duplication for me, arranged and ordered the output in a table, and exported it to Excel. Then I took it a step further. When our code refactor was done, I prompted the agent to take my existing Excel sheet as the baseline, add in the current state of duplication in separate columns, and calculate the delta. ### Updating Code Written A Long Time Ago Recently, an old client of mine hit me up, as over time, a few features weren’t working properly on his website anymore. The catch: The website was built almost ten years ago, and the JavaScript and SCSS were using rather old compile tools like requireJS, and the setup required an older version of Node.js that wouldn’t even run on my 2025 MacBook. Updating the whole build process by hand would have taken me days, so I decided to prompt the AI agent, _“Can you update the JS and SCSS build process to a lean 2025 stack like Vite?”_ It sure did, and after around an hour of refining with the agent, I had my SCSS and JS build switched to Vite, and I was able to focus on actual bugfixing. Just make sure to properly validate the output and compiled files when doing such integral changes to your build process. ### Summarizing And Drafting Would you like to summarize all your recent code changes in one sentence for a commit message, or have a long list of commits and would like to sum them up in three bullet points? No problem, let the AI take care of it, but please make sure to proofread it. An example prompt is as simple as messaging a fellow human: _“Please sum up my recent changes in concise bullet points”_. My advice here would be to use GPT for writing with caution, and as with code, please check the output before sending or submitting. Recommendations And Best Practices ### Prompting One of the not-so-obvious benefits of using AI is that the more specific and tailored your prompts are, the better the output. The process of prompting an AI agent forces us to **formulate our requirements as specifically as possible** before we write and code. This is why, as a general rule, I highly recommend being as specific as possible with your prompting. Ryan Florence, co-author of Remix, suggests a simple yet powerful way to improve this process by finishing your initial prompt with the sentence: > “Before we start, do you have any questions for me?” At this point, the AI usually comes back with helpful questions where you can clarify your specific intent, guiding the agent to provide you with a **more tailored approach** for your task. ### Use Version Control And Work In Digestible Chunks Using version control like git not only comes in handy when collaborating as a team on a single codebase but also to provide you as an individual contributor with stable points to roll back to in case of an emergency. Due to its non-deterministic nature, AI can sometimes go rogue and make changes that are simply not helpful for what you are trying to achieve and eventually break things irreparably. Splitting up your work into **multiple commits** will help you create stable points that you can revert to in case things go sideways. And your teammates will thank you as well, as they will have an easier time reviewing your code when it is split up into semantically well-structured chunks. ### Review Thoroughly This is more of a general best practice, but in my opinion, it becomes even more important when using AI tools for development work: **Be the first critical reviewer of your code**. Make sure to take some time to go over your changes line by line, just like you would review someone else’s code, and only submit your work once it passes your own self-review. > “Two things are both true to me right now: AI agents are amazing and a huge productivity boost. They are also massive slop machines if you turn off your brain and let go completely.” > > — Armin Ronacher in his blog post Agent Psychosis: Are We Going Insane? Conclusion And Critical Thoughts In my opinion, AI coding tools can improve our productivity as developers on a daily basis and free up mental capacity for more planning and high-level thinking. They force us to articulate our desired outcome with meticulous detail. Any AI can, at times, hallucinate, which basically means it lies in a confident tone. So please make sure to check and test, especially when you are in doubt. AI is not a silver bullet, and I believe, excellence and the ability to solve problems as a developer will never go out of fashion. For developers who are just starting out in their career these tools can be highly tempting to do the majority of the work for them. What may get lost here is the often draining and painful work through bugs and issues that are tricky to debug and solve, aka “the grind”. Even Cursor AI’s very own Lee Robinson questions this in one of his posts: AI coding tools are evolving at a fast pace, and I am excited for what will come next. I hope you found this article and its tips helpful and are excited to try out some of these for yourself. Gain $200 in a week from Articles on Smashing Magazine — For Web Designers And Developers https://ift.tt/2HSm4zf

Practical Use Of AI Coding Tools For The Responsible Developer Over the last two years, my team at Work & Co and I have been testing out and gradually integrating AI coding tools like Copilot, ...

#Articles #on #Smashing #Magazine #— #For #Web #Designers #And #Developers

Origin | Interest | Match

1 0 0 0
Original post on 247webdevs.blogspot.com

Unstacking CSS Stacking Contexts Have you ever set z-index: 99999 on an element in your CSS, and it doesn’t come out on top of other elements? A value that large should easily place that element ...

#Articles #on #Smashing #Magazine #— #For #Web […]

[Original post on 247webdevs.blogspot.com]

1 0 0 0
Video

Love breaking random stuff in other games so, Im now doing the same in my own! Others who enjoy mindlessly smashing things just for fun? :)

#videogames #indiegame #indie #steam #steamgame #wishlist #smashing #breaking #destructible #pc #pcgaming #fantasy #destroy #gamedev

12 3 0 0
Post image Post image Post image Post image

Happy snow day. Here are more cake sitting and smashing pics.
I am not a fan of how the cake sitting video came out. But I’m going to post it anyways because I promised.

fansly.com/ivydesire85
#bbw #cakesitting #foodporn #smashing #siren #nsfw #bustyvixen

26 2 5 0
Video

I think it’s more fun when I’m the cake. Just going through all these before I put the cake sitting on my fansly.
#foodporn #bbw #smashing #nsfw #fansly #siren #ivydesire85

18 1 3 0
MultiSearch Tag Explorer MultiSearch Tag Explorer - Explore tags and search results by aéPiot

#THE #SMASHING #PUMPKINS
multi-search-tag-explorer.aepiot.com/advanced-sea...
#PRODUTO #XÉNICO
multi-search-tag-explorer.headlines-world.com/advanced-sea...
#ELEMENTO #REGULADOR EN #CIS
multi-search-tag-explorer.allgraph.ro/advanced-sea...
aepiot.ro

0 0 0 0
Post image

If I can reach $100 in tips I will sit in a cake and rub it on myself and eat it off myself
Anything extra on top of that. Is well just adds frosting to the cake the biggest tipper will receive a special
custom video.

fans.ly/ivydesire85

Cashapp $ladybadwolf85

#birthday #bbw #cake #smashing

16 0 0 0
Post image

Paul McCartney smiling near biscuits (in Malmö)

#smashing #vest

46 2 0 0
Preview
Cock Smashing - WMV | Clips4sale <p>Goddess Savannah decided to take me out of chastity. After making me beg, she finally removes the cage. Unfortunately my pleasure wasn't what she had in mind. Her idea of fun is smashing my penis w...

Cock Smashing is now available in both MP4 and WMV formats on Clips4Sale at: www.clips4sale.com/studio/10678...

#smalldick #smallcock #boots #smashing #crushing #fetish #kink #kinky #femdom #femaledomination #domme #footdomination #slave #beta #loser #xxx

1 1 0 0
Post image

The mashup nobody asked for but got anyway, the Mild Volkarins lmao #emmrichvolkarin #dragonagetheveilguard #smashing #emmrichdragonage #dragonage

45 10 2 1
Video

The latest The 12th Man line up is just #smashing!

#jazz #music

3 0 0 0
Preview
CSS Gamepad API Visual Debugging With CSS Layers When you plug in a controller, you mash buttons, move the sticks, pull the triggers… and as a developer, you see none of it. The browser’s picking it up, sure, but unless you’re logging numbers in the console, it’s invisible. That’s the headache with the Gamepad API. It’s been around for years, and it’s actually pretty powerful. You can read buttons, sticks, triggers, the works. But most people don’t touch it. Why? Because there’s no feedback. No panel in developer tools. No clear way to know if the controller’s even doing what you think. It feels like flying blind. That bugged me enough to build a little tool: **Gamepad Cascade Debugger**. Instead of staring at console output, you get a live, interactive view of the controller. Press something and it reacts on the screen. And with CSS Cascade Layers, the styles stay organized, so it’s cleaner to debug. In this post, I’ll show you why debugging controllers is such a pain, how CSS helps clean it up, and how you can build a reusable visual debugger for your own projects. Even if you are able to log them all, you’ll quickly end up with unreadable console spam. For example: [0,0,1,0,0,0.5,0,...] [0,0,0,0,1,0,0,...] [0,0,1,0,0,0,0,...] Can you tell what button was pressed? Maybe, but only after straining your eyes and missing a few inputs. So, no, debugging doesn’t come easily when it comes to reading inputs. ### Problem 3: Lack Of Structure Even if you throw together a quick visualizer, styles can quickly get messy. Default, active, and debug states can overlap, and without a clear structure, your CSS becomes brittle and hard to extend. CSS Cascade Layers can help. They group styles into “layers” that are ordered by priority, so you stop fighting specificity and guessing, _“Why isn’t my debug style showing?”_ Instead, you maintain separate concerns: * **Base** : The controller’s standard, initial appearance. * **Active** : Highlights for pressed buttons and moved sticks. * **Debug** : Overlays for developers (e.g., numeric readouts, guides, and so on). If we were to define layers in CSS according to this, we’d have: /* lowest to highest priority */ @layer base, active, debug; @layer base { /* ... */ } @layer active { /* ... */ } @layer debug { /* ... */ } Because each layer stacks predictably, you always know which rules win. That predictability makes debugging not just easier, but actually manageable. We’ve covered the problem (invisible, messy input) and the approach (a visual debugger built with Cascade Layers). Now we’ll walk through the step-by-step process to build the debugger. The Debugger Concept The easiest way to make hidden input visible is to just draw it on the screen. That’s what this debugger does. Buttons, triggers, and joysticks all get a visual. * **Press`A`**: A circle lights up. * **Nudge the stick** : The circle slides around. * **Pull a trigger halfway** : A bar fills halfway. Now you’re not staring at 0s and 1s, but actually watching the controller react live. Of course, once you start piling on states like default, pressed, debug info, maybe even a recording mode, the CSS starts getting larger and more complex. That’s where cascade layers come in handy. Here’s a stripped-down example: @layer base { .button { background: #222; border-radius: 50%; width: 40px; height: 40px; } } @layer active { .button.pressed { background: #0f0; /* bright green */ } } @layer debug { .button::after { content: attr(data-value); font-size: 12px; color: #fff; } } The layer order matters: `base` → `active` → `debug`. * `base` draws the controller. * `active` handles pressed states. * `debug` throws on overlays. Breaking it up like this means you’re not fighting weird specificity wars. Each layer has its place, and you always know what wins. Building It Out Let’s get something on screen first. It doesn’t need to look good — just needs to exist so we have something to work with. <h1>Gamepad Cascade Debugger</h1> <!-- Main controller container --> <div id="controller"> <!-- Action buttons --> <div id="btn-a" class="button">A</div> <div id="btn-b" class="button">B</div> <div id="btn-x" class="button">X</div> <!-- Pause/menu button (represented as two bars) --> <div> <div id="pause1" class="pause"></div> <div id="pause2" class="pause"></div> </div> </div> <!-- Toggle button to start/stop the debugger --> <button id="toggle">Toggle Debug</button> <!-- Status display for showing which buttons are pressed --> <div id="status">Debugger inactive</div> <script src="script.js"></script> That’s literally just boxes. Not exciting yet, but it gives us handles to grab later with CSS and JavaScript. Okay, I’m using cascade layers here because it keeps stuff organized once you add more states. Here’s a rough pass: /* =================================== CASCADE LAYERS SETUP Order matters: base → active → debug =================================== */ /* Define layer order upfront */ @layer base, active, debug; /* Layer 1: Base styles - default appearance */ @layer base { .button { background: #333; border-radius: 50%; width: 70px; height: 70px; display: flex; justify-content: center; align-items: center; } .pause { width: 20px; height: 70px; background: #333; display: inline-block; } } /* Layer 2: Active states - handles pressed buttons */ @layer active { .button.active { background: #0f0; /* Bright green when pressed */ transform: scale(1.1); /* Slightly enlarges the button */ } .pause.active { background: #0f0; transform: scaleY(1.1); /* Stretches vertically when pressed */ } } /* Layer 3: Debug overlays - developer info */ @layer debug { .button::after { content: attr(data-value); /* Shows the numeric value */ font-size: 12px; color: #fff; } } The beauty of this approach is that each layer has a clear purpose. The `base` layer can never override `active,` and `active` can never override `debug`, regardless of specificity. This eliminates the CSS specificity wars that usually plague debugging tools. Now it looks like some clusters are sitting on a dark background. Honestly, not too bad. ### Adding the JavaScript JavaScript time. This is where the controller actually does something. We’ll build this step by step. #### Step 1: Set Up State Management First, we need variables to track the debugger’s state: // =================================== // STATE MANAGEMENT // =================================== let running = false; // Tracks whether the debugger is active let rafId; // Stores the requestAnimationFrame ID for cancellation These variables control the animation loop that continuously reads gamepad input. #### Step 2: Grab DOM References Next, we get references to all the HTML elements we’ll be updating: // =================================== // DOM ELEMENT REFERENCES // =================================== const btnA = document.getElementById("btn-a"); const btnB = document.getElementById("btn-b"); const btnX = document.getElementById("btn-x"); const pause1 = document.getElementById("pause1"); const pause2 = document.getElementById("pause2"); const status = document.getElementById("status"); Storing these references up front is more efficient than querying the DOM repeatedly. #### Step 3: Add Keyboard Fallback For testing without a physical controller, we’ll map keyboard keys to buttons: // =================================== // KEYBOARD FALLBACK (for testing without a controller) // =================================== const keyMap = { "a": btnA, "b": btnB, "x": btnX, "p": [pause1, pause2] // 'p' key controls both pause bars }; This lets us test the UI by pressing keys on a keyboard. #### Step 4: Create The Main Update Loop Here’s where the magic happens. This function runs continuously and reads gamepad state: // =================================== // MAIN GAMEPAD UPDATE LOOP // =================================== function updateGamepad() { // Get all connected gamepads const gamepads = navigator.getGamepads(); if (!gamepads) return; // Use the first connected gamepad const gp = gamepads[0]; if (gp) { // Update button states by toggling the "active" class btnA.classList.toggle("active", gp.buttons[0].pressed); btnB.classList.toggle("active", gp.buttons[1].pressed); btnX.classList.toggle("active", gp.buttons[2].pressed); // Handle pause button (button index 9 on most controllers) const pausePressed = gp.buttons[9].pressed; pause1.classList.toggle("active", pausePressed); pause2.classList.toggle("active", pausePressed); // Build a list of currently pressed buttons for status display let pressed = []; gp.buttons.forEach((btn, i) => { if (btn.pressed) pressed.push("Button " + i); }); // Update status text if any buttons are pressed if (pressed.length > 0) { status.textContent = "Pressed: " + pressed.join(", "); } } // Continue the loop if debugger is running if (running) { rafId = requestAnimationFrame(updateGamepad); } } The `classList.toggle()` method adds or removes the `active` class based on whether the button is pressed, which triggers our CSS layer styles. #### Step 5: Handle Keyboard Events These event listeners make the keyboard fallback work: // =================================== // KEYBOARD EVENT HANDLERS // =================================== document.addEventListener("keydown", (e) => { if (keyMap[e.key]) { // Handle single or multiple elements if (Array.isArray(keyMap[e.key])) { keyMap[e.key].forEach(el => el.classList.add("active")); } else { keyMap[e.key].classList.add("active"); } status.textContent = "Key pressed: " + e.key.toUpperCase(); } }); document.addEventListener("keyup", (e) => { if (keyMap[e.key]) { // Remove active state when key is released if (Array.isArray(keyMap[e.key])) { keyMap[e.key].forEach(el => el.classList.remove("active")); } else { keyMap[e.key].classList.remove("active"); } status.textContent = "Key released: " + e.key.toUpperCase(); } }); #### Step 6: Add Start/Stop Control Finally, we need a way to toggle the debugger on and off: // =================================== // TOGGLE DEBUGGER ON/OFF // =================================== document.getElementById("toggle").addEventListener("click", () => { running = !running; // Flip the running state if (running) { status.textContent = "Debugger running..."; updateGamepad(); // Start the update loop } else { status.textContent = "Debugger inactive"; cancelAnimationFrame(rafId); // Stop the loop } }); So yeah, press a button and it glows. Push the stick and it moves. That’s it. One more thing: raw values. Sometimes you just want to see numbers, not lights. At this stage, you should see: * A simple on-screen controller, * Buttons that react as you interact with them, and * An optional debug readout showing pressed button indices. To make this less abstract, here’s a quick demo of the on-screen controller reacting in real time: Now, pressing **Start Recording** logs everything until you hit **Stop Recording**. ### 2. Exporting Data to CSV/JSON Once we have a log, we’ll want to save it. <div class="controls"> <button id="export-json" class="btn">Export JSON</button> <button id="export-csv" class="btn">Export CSV</button> </div> #### Step 1: Create The Download Helper First, we need a helper function that handles file downloads in the browser: // =================================== // FILE DOWNLOAD HELPER // =================================== function downloadFile(filename, content, type = "text/plain") { // Create a blob from the content const blob = new Blob([content], { type }); const url = URL.createObjectURL(blob); // Create a temporary download link and click it const a = document.createElement("a"); a.href = url; a.download = filename; a.click(); // Clean up the object URL after download setTimeout(() => URL.revokeObjectURL(url), 100); } This function works by creating a Blob (binary large object) from your data, generating a temporary URL for it, and programmatically clicking a download link. The cleanup ensures we don’t leak memory. #### Step 2: Handle JSON Export JSON is perfect for preserving the complete data structure: // =================================== // EXPORT AS JSON // =================================== document.getElementById("export-json").addEventListener("click", () => { // Check if there's anything to export if (!frames.length) { console.warn("No recording available to export."); return; } // Create a payload with metadata and frames const payload = { createdAt: new Date().toISOString(), frames }; // Download as formatted JSON downloadFile( "gamepad-log.json", JSON.stringify(payload, null, 2), "application/json" ); }); The JSON format keeps everything structured and easily parseable, making it ideal for loading back into dev tools or sharing with teammates. #### Step 3: Handle CSV Export For CSV exports, we need to flatten the hierarchical data into rows and columns: // =================================== // EXPORT AS CSV // =================================== document.getElementById("export-csv").addEventListener("click", () => { // Check if there's anything to export if (!frames.length) { console.warn("No recording available to export."); return; } // Build CSV header row (columns for timestamp, all buttons, all axes) const headerButtons = frames[0].buttons.map((_, i) => btn${i}); const headerAxes = frames[0].axes.map((_, i) => axis${i}); const header = ["t", ...headerButtons, ...headerAxes].join(",") + "\n"; // Build CSV data rows const rows = frames.map(f => { const btnVals = f.buttons.map(b => b.value); return [f.t, ...btnVals, ...f.axes].join(","); }).join("\n"); // Download as CSV downloadFile("gamepad-log.csv", header + rows, "text/csv"); }); CSV is brilliant for data analysis because it opens directly in Excel or Google Sheets, letting you create charts, filter data, or spot patterns visually. Now that the export buttons are in, you’ll see two new options on the panel: **Export JSON** and **Export CSV**. JSON is nice if you want to throw the raw log back into your dev tools or poke around the structure. CSV, on the other hand, opens straight into Excel or Google Sheets so you can chart, filter, or compare inputs. The following figure shows what the panel looks like with those extra controls. ### 3. Snapshot System Sometimes you don’t need a full recording, just a quick “screenshot” of input states. That’s where a **Take Snapshot** button helps. <div class="controls"> <button id="snapshot" class="btn">Take Snapshot</button> </div> And the JavaScript: // =================================== // TAKE SNAPSHOT // =================================== document.getElementById("snapshot").addEventListener("click", () => { // Get all connected gamepads const pads = navigator.getGamepads(); const activePads = []; // Loop through and capture the state of each connected gamepad for (const gp of pads) { if (!gp) continue; // Skip empty slots activePads.push({ id: gp.id, // Controller name/model timestamp: performance.now(), buttons: gp.buttons.map(b => ({ pressed: b.pressed, value: b.value })), axes: [...gp.axes] }); } // Check if any gamepads were found if (!activePads.length) { console.warn("No gamepads connected for snapshot."); alert("No controller detected!"); return; } // Log and notify user console.log("Snapshot:", activePads); alert(Snapshot taken! Captured ${activePads.length} controller(s).); }); Snapshots freeze the exact state of your controller at one moment in time. ### 4. Ghost Input Replay Now for the fun one: ghost input replay. This takes a log and plays it back visually as if a phantom player was using the controller. <div class="controls"> <button id="replay" class="btn">Replay Last Recording</button> </div> JavaScript for replay: // =================================== // GHOST REPLAY // =================================== document.getElementById("replay").addEventListener("click", () => { // Ensure we have a recording to replay if (!frames.length) { alert("No recording to replay!"); return; } console.log("Starting ghost replay..."); // Track timing for synced playback let startTime = performance.now(); let frameIndex = 0; // Replay animation loop function step() { const now = performance.now(); const elapsed = now - startTime; // Process all frames that should have occurred by now while (frameIndex < frames.length && frames[frameIndex].t <= elapsed) { const frame = frames[frameIndex]; // Update UI with the recorded button states btnA.classList.toggle("active", frame.buttons[0].pressed); btnB.classList.toggle("active", frame.buttons[1].pressed); btnX.classList.toggle("active", frame.buttons[2].pressed); // Update status display let pressed = []; frame.buttons.forEach((btn, i) => { if (btn.pressed) pressed.push("Button " + i); }); if (pressed.length > 0) { status.textContent = "Ghost: " + pressed.join(", "); } frameIndex++; } // Continue loop if there are more frames if (frameIndex < frames.length) { requestAnimationFrame(step); } else { console.log("Replay finished."); status.textContent = "Replay complete"; } } // Start the replay step(); }); To make debugging a bit more hands-on, I added a ghost replay. Once you’ve recorded a session, you can hit replay and watch the UI act it out, almost like a phantom player is running the pad. A new **Replay Ghost** button shows up in the panel for this. Hit **Record** , mess around with the controller a bit, stop, then replay. The UI just echoes everything you did, like a ghost following your inputs. Why bother with these extras? * **Recording/export** makes it easy for testers to show exactly what happened. * **Snapshots** freeze a moment in time, super useful when you’re chasing odd bugs. * **Ghost replay** is great for tutorials, accessibility checks, or just comparing control setups side by side. At this point, it’s not just a neat demo anymore, but something you could actually put to work. Real-World Use Cases Now we’ve got this debugger that can do a lot. It shows live input, records logs, exports them, and even replays stuff. But the real question is: who actually cares? Who’s this useful for? ### Game Developers Controllers are part of the job, but debugging them? Usually a pain. Imagine you’re testing a fighting game combo, like `↓ →` + `punch`. Instead of praying, you pressed it the same way twice, you record it once, and replay it. Done. Or you swap `JSON` logs with a teammate to check if your multiplayer code reacts the same on their machine. That’s huge. ### Accessibility Practitioners This one’s close to my heart. Not everyone plays with a “standard” controller. Adaptive controllers throw out weird signals sometimes. With this tool, you can see exactly what’s happening. Teachers, researchers, whoever. They can grab logs, compare them, or replay inputs side-by-side. Suddenly, invisible stuff becomes obvious. ### Quality Assurance Testing Testers usually write notes like “I mashed buttons here and it broke.” Not very helpful. Now? They can capture the exact presses, export the log, and send it off. No guessing. ### Educators If you’re making tutorials or YouTube vids, ghost replay is gold. You can literally say, “Here’s what I did with the controller,” while the UI shows it happening. Makes explanations way clearer. ### Beyond Games And yeah, this isn’t just about games. People have used controllers for robots, art projects, and accessibility interfaces. Same issue every time: what is the browser actually seeing? With this, you don’t have to guess. Conclusion Debugging a controller input has always felt like flying blind. Unlike the DOM or CSS, there’s no built-in inspector for gamepads; it’s just raw numbers in the console, easily lost in the noise. With a few hundred lines of HTML, CSS, and JavaScript, we built something different: * **A visual debugger** that makes invisible inputs visible. * **A layered CSS system** that keeps the UI clean and debuggable. * **A set of enhancements** (recording, exporting, snapshots, ghost replay) that elevate it from demo to developer tool. This project shows how far you can go by mixing the Web Platform’s power with a little creativity in CSS Cascade Layers. The tool I just explained in its entirety is open-source. You can clone the GitHub repo and try it for yourself. But more importantly, you can make it your own. Add your own layers. Build your own replay logic. Integrate it with your game prototype. Or even use it in ways I haven’t imagined. For teaching, accessibility, or data analysis. At the end of the day, this isn’t just about debugging gamepads. It’s about **shining a light on hidden inputs** , and giving developers the confidence to work with hardware that the web still doesn’t fully embrace. So, plug in your controller, open up your editor, and start experimenting. You might be surprised at what your browser and your CSS can truly accomplish. Gain $200 in a week from Articles on Smashing Magazine — For Web Designers And Developers https://ift.tt/9ck5IrA

CSS Gamepad API Visual Debugging With CSS Layers When you plug in a controller, you mash buttons, move the sticks, pull the triggers… and as a developer, you see none of it. The browser’s picki...

#Articles #on #Smashing #Magazine #— #For #Web #Designers #And #Developers

Origin | Interest | Match

0 0 0 0
Original post on 247webdevs.blogspot.com

Older Tech In The Browser Stack I’ve been in front-end development long enough to see a trend over the years: younger developers working with a new paradigm of programming without understanding t...

#Articles #on #Smashing #Magazine #— #For #Web #Designers #And #Developers

Origin | Interest | […]

1 0 0 0