Skip to main content

javascript

JavaScript coding standards for Scenescape โ€” code style, conventions, and frontend patterns.

Source facts

Repository
open-edge-platform/scenescape
Last source activity
June 18, 2026 at 10:00
Detected SKILL.md language
English
Stars
46
Forks
51

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions ยท Read-only preview
name
javascript
description
JavaScript coding standards for Scenescape โ€” code style, conventions, and frontend patterns.
# JavaScript Coding Standards for Scenescape ## Code Style ### Linting & Formatting - **Linter**: ESLint (config in `.github/resources/eslint.config.js`) - **Formatter**: Prettier (config in `.github/resources/.prettierrc.json`) - **Commands**: ```bash make lint-javascript # Run ESLint make prettier-write # Auto-format all code make prettier-check # Check formatting ``` ### Indentation - Use **2 spaces** (never tabs) - Consistent with Prettier configuration ### Line Length - Enforced by Prettier configuration - Typically 80-100 characters ### Semicolons - Use semicolons consistently (enforced by Prettier) ### Quotes - Prefer **double quotes** for strings (enforced by Prettier) ## Naming Conventions - **Classes**: `PascalCase` (e.g., `MapboxPlugin`, `GoogleMapsPlugin`, `MapInterface`) - **Functions/Methods**: `camelCase` (e.g., `generateSnapshot`, `saveSnapshotToServer`) - **Constants**: `UPPER_SNAKE_CASE` (e.g., `DEFAULT_ZOOM`, `MAP_CENTER`) - **Variables**: `camelCase` (e.g., `sceneData`, `cameraList`) - **Private members**: Prefix with underscore `_` (convention only, not enforced) ## Architecture Patterns ### Class-Based Components Scenescape uses ES6 classes for map plugins and UI components: ```javascript class MapboxPlugin extends MapInterface { constructor() { super(); this.map = null; this.accessToken = null; } async initialize(containerId, config = {}) { // Implementation } generateSnapshot() { // Implementation } } ``` ### Plugin Pattern Map providers implement a common interface: ```javascript class MapInterface { async initialize(containerId, config) {} moveToLocation(input) {} generateBounds() {} generateSnapshot() {} getBounds() {} getCenter() {} getZoom() {} } ``` ### Async/Await Prefer async/await over promises for readability: ```javascript // Good async function fetchSceneData(sceneId) { try { const response = await fetch(`/api/v1/scenes/${sceneId}/`); const data = await response.json(); return data; } catch (error) { console.error("Failed to fetch scene:", error); return null; } } // Avoid function fetchSceneData(sceneId) { return fetch(`/api/v1/scenes/${sceneId}/`) .then((response) => response.json()) .catch((error) => console.error(error)); } ``` ## DOM Manipulation ### jQuery Usage Scenescape uses jQuery for DOM manipulation: ```javascript $(document).ready(function () { $("#login-submit").on("click", handleLogin); $(".roi-color").each(function () { // Process each element }); }); ``` ### Event Handlers ```javascript // Attach handlers $("#button-id").on("click", function (event) { event.preventDefault(); // Handle click }); // Delegate for dynamic elements $(document).on("click", ".dynamic-class", function () { // Handle click on dynamically added elements }); ``` ### Element Selection ```javascript // By ID const element = document.getElementById("map"); const $element = $("#map"); // By class const elements = document.querySelectorAll(".roi-item"); const $elements = $(".roi-item"); ``` ## AJAX Requests ### Fetch API with CSRF ```javascript async function saveData(data) { const csrfToken = document.querySelector("[name=csrfmiddlewaretoken]"); const response = await fetch("/api/v1/endpoint/", { method: "POST", headers: { "Content-Type": "application/json", "X-CSRFToken": csrfToken.value, }, body: JSON.stringify(data), }); if (response.ok) { const result = await response.json(); return result; } else { console.error("Request failed:", response.status); return null; } } ``` ### FormData for File Uploads ```javascript const formData = new FormData(); formData.append("image_data", imageData); formData.append("csrfmiddlewaretoken", csrfToken.value); const response = await fetch("/api/v1/save-snapshot/", { method: "POST", headers: { "X-CSRFToken": csrfToken.value, }, body: formData, }); ``` ## Error Handling ### Try-Catch with Async ```javascript async function processOperation() { try { const result = await riskyOperation(); console.log("Success:", result); return result; } catch (error) { console.error("Operation failed:", error); showErrorMessage(error.message); return null; } } ``` ### Null Checks ```javascript // Good - early return function processScene(scene) { if (!scene) { console.error("Scene is null"); return; } // Process scene } // Good - optional chaining const cameraCount = scene?.cameras?.length ?? 0; ``` ## Canvas & Graphics ### Canvas Manipulation ```javascript const canvas = document.createElement("canvas"); canvas.width = 1280; canvas.height = 1280; const ctx = canvas.getContext("2d"); // Draw image ctx.drawImage(image, 0, 0); // Get base64 data const imageData = canvas.toDataURL("image/png"); ``` ### SVG Manipulation ```javascript // Create SVG element const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg"); svg.setAttribute("width", "100"); svg.setAttribute("height", "100"); // Add to DOM $("#svgout").append(svg); ``` ## Console Logging ### Development Logging ```javascript // Debug information console.log("Processing scene:", sceneId); // Warnings console.warn("Camera not found:", cameraId); // Errors console.error("Failed to load scene:", error); // Structured data console.log("Response:", { status, data, timestamp }); ``` ### Production Considerations Remove or guard verbose logging in production code: ```javascript if (DEBUG_MODE) { console.log("Detailed debug info:", debugData); } ``` ## Comments ### Function Documentation ```javascript /** * Generate a snapshot of the current map view * @returns {Promise<string>} Base64-encoded image data */ async function generateSnapshot() { // Implementation } ``` ### Inline Comments ```javascript // Hide map controls before screenshot const style = document.createElement("style"); style.textContent = `...`; // Process each ROI point points.forEach((point, index) => { // Transform coordinates to map space const transformed = transformPoint(point); }); ``` ## Common Patterns ### Show/Hide Elements ```javascript // Show $("#element").show(); $("#element").css("display", "block"); // Hide $("#element").hide(); $("#element").css("display", "none"); ``` ### Add/Remove Classes ```javascript $("#element").addClass("active"); $("#element").removeClass("disabled"); $("#element").toggleClass("selected"); ``` ### Update Content ```javascript // Text $("#message").text("Operation complete"); // HTML $("#container").html("<div>New content</div>"); // Attributes $("#image").attr("src", imageUrl); ``` ### Animation & Effects ```javascript // Fade in/out $("#element").fadeIn(300); $("#element").fadeOut(300); // Scroll into view element.scrollIntoView({ behavior: "smooth" }); ``` ## Map Provider Integration ### Mapbox ```javascript mapboxgl.accessToken = apiKey; const map = new mapboxgl.Map({ container: "map", style: "mapbox://styles/mapbox/satellite-v9", center: [lng, lat], zoom: 15, }); ``` ### Google Maps ```javascript const map = new google.maps.Map(document.getElementById("map"), { center: { lat, lng }, zoom: 15, mapTypeId: "satellite", }); ``` ## File Organization ### Manager Static Files ``` manager/src/static/js/ โ”œโ”€โ”€ geospatial/ โ”‚ โ”œโ”€โ”€ mapbox-plugin.js โ”‚ โ”œโ”€โ”€ google-maps-plugin.js โ”‚ โ””โ”€โ”€ map-interface.js โ””โ”€โ”€ sscape.js ``` ### Script Loading Scripts are loaded via Django templates: ```html {% load static %} <script src="{% static 'js/sscape.js' %}"></script> <script src="{% static 'js/geospatial/mapbox-plugin.js' %}"></script> ``` ## Anti-Patterns to Avoid โŒ **Don't use var**: ```javascript // Bad var count = 0; // Good const count = 0; let counter = 0; ``` โŒ **Don't modify global scope unnecessarily**: ```javascript // Bad window.myGlobalVar = "value"; // Good - use module pattern or classes const MyModule = { value: "value", }; ``` โŒ **Don't use == for comparisons**: ```javascript // Bad if (value == null) { } // Good if (value === null) { } if (value == null) { } // OK only for null/undefined check ``` โŒ **Don't create functions in loops**: ```javascript // Bad for (let i = 0; i < items.length; i++) { $("#item-" + i).on("click", function () { process(i); // i will be wrong }); } // Good items.forEach((item, index) => {
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub