npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@rtstic.dev/ascent-floorplan

v1.0.8

Published

A lightweight front-end package for ascent project.

Readme

Interactive Floorplan System

A comprehensive JavaScript-based system for managing interactive SVG floorplans with CMS integration, URL-based navigation, and dynamic unit selection.


Table of Contents

  1. Overview
  2. File Structure
  3. Architecture
  4. Data Flow
  5. Core Components
  6. Initialization Sequence
  7. HTML Requirements
  8. CSS Selectors & Classes
  9. URL Query Parameters
  10. API Reference

Overview

This system creates an interactive floorplan interface where users can:

  • View units organized by bedroom types (tabs)
  • Click units on an SVG floorplan to see details
  • Navigate via URL parameters (deep linking)
  • See sold/available status for each unit
  • Auto-scroll to unit details when selected

File Structure

├── floorplan.js              # Main logic and orchestration
├── featured-floorplan.js     # CMS data collector & link updater
└── floorplan.css            # Styling for interactive states

File Responsibilities

floorplan.js (Main Controller)

  • Loads SVG floorplan from CDN
  • Collects data from SVG and CMS
  • Manages tab navigation
  • Handles unit selection
  • URL query parameter management
  • Browser history integration

featured-floorplan.js (CMS Helper)

  • Collects unit data from CMS elements
  • Updates card links with proper URLs
  • Exposes utility methods via window.CMSCollector

floorplan.css (Visual States)

  • Active/inactive tab styles
  • Selected unit highlighting
  • Sold unit styling
  • Detail panel visibility

Architecture

Data Sources

The system merges data from two sources:

  1. SVG Data - Extracted from the floorplan SVG structure
  2. CMS Data - Extracted from HTML elements with data-fp-* attributes

These are combined into a Master Data Array that powers the entire interface.

Three Data Collections

window.floorplanDataFromSVG    // Array of units from SVG
window.floorplanDataFromCMS    // Array of units from CMS
window.masterFloorplanData     // Merged + validated array

Data Flow

1. DOM Ready
   ↓
2. Load SVG from CDN
   ↓
3. Collect SVG Data (collectUnitDataFromSVG)
   ↓
4. Collect CMS Data (collectUnitDataFromCMS)
   ↓
5. Build Master Data (buildMasterFloorplanData)
   ↓
6. Initialize Tabs (initFloorPlanTabs)
   ↓
7. Read URL Query Params
   ↓
8. Set Active Tab from URL or Default
   ↓
9. Set Active Residence from URL (if present)
   ↓
10. Mark Sold Units (initializeSoldResidentsFromCMS)
   ↓
11. Attach Click Handlers (consoleSVGs)

Core Components

1. URL Query Parameter System

The system uses two query parameters for deep linking:

  • ?tab=<groupName> - Sets active bedroom type
  • ?residence=<unitId> - Selects specific unit

Functions:

  • updateTabQuery(tabValue) - Updates tab in URL
  • getTabFromQuery() - Reads tab from URL
  • updateResidenceQuery(id) - Updates residence in URL
  • getResidenceFromQuery() - Reads residence from URL

Example URLs:

# Default tab (1 BEDROOM + DEN)
/summit/floorplan

# Specific tab
/summit/floorplan?tab=2%20BEDROOM%20%2B%20DEN%20%2B%203%20BATH

# Tab with unit selection
/summit/floorplan?tab=1%20BEDROOM%20%2B%20DEN&residence=A_1209

2. Tab System

HTML Structure Required:

<div data-fp-tablink="1 BEDROOM + DEN" data-fp-tablink-active="false">
  1 Bedroom + Den
</div>
<div data-fp-tablink="2 BEDROOM" data-fp-tablink-active="false">
  2 Bedroom
</div>

Behavior:

  • Clicking a tab sets it as active
  • Updates URL query parameter
  • Highlights corresponding group in SVG
  • Resets any selected residence

Key Functions:

  • initFloorPlanTabs() - Attaches click handlers to all tabs
  • setActiveTab(tabValue) - Activates a specific tab

3. Unit Selection System

Selection Flow:

User clicks unit (SVG or CMS card)
   ↓
Find matching master data by ID
   ↓
Highlight unit in SVG (add 'selected' class)
   ↓
Show detail panel for that unit
   ↓
Update URL with residence ID
   ↓
Scroll to detail section

Key Functions:

  • setActiveResidence(masterOrId) - Main selection orchestrator
  • setSelectedResidenceSVG(el) - Highlights unit in SVG
  • showSelectedResidenceDetail(id) - Shows detail panel

4. Data Collection

SVG Data Collection (collectUnitDataFromSVG)

Looks for:

<g class="unit clickable" id="unit-205" data-name="Unit 205">
  <!-- Inside a parent group -->
  <g class="unit-group" data-name="2 BEDROOM" id="group-2bed">
    <!-- unit here -->
  </g>
</g>

Extracts:

{
  id: "A_1209",
  Name: "A 1209",
  isSold: false, // from 'sold' class
  groupName: "1 BEDROOM + DEN",
  groupId: "_1_BEDROOM_DEN"
}

Example from window.floorplanDataFromSVG:

[
  {
    "id": "S_2109",
    "Name": "S 2109",
    "isSold": false,
    "groupName": "3 BEDROOM + DEN",
    "groupId": "_3_BEDROOM_DEN"
  },
  {
    "id": "A_1209",
    "Name": "A 1209",
    "isSold": false,
    "groupName": "1 BEDROOM + DEN",
    "groupId": "_1_BEDROOM_DEN"
  }
  // ... more units
]

CMS Data Collection (collectUnitDataFromCMS)

Looks for:

<div data-fp-id="unit-205"
     data-fp-name="Unit 205"
     data-fp-group-name="2 BEDROOM"
     data-fp-project="Summit Tower"
     data-fp-soldout="false">
</div>

Extracts:

{
  id: "A_1209",
  dataName: "1209",
  groupName: "1 BEDROOM + DEN",
  project: "Summit floor plans",
  isSold: true
}

Example from window.floorplanDataFromCMS:

[
  {
    "dataName": "1209",
    "groupName": "1 BEDROOM + DEN",
    "project": "Summit floor plans",
    "id": "A_1209",
    "isSold": true
  },
  {
    "dataName": "2309",
    "groupName": "1 BEDROOM + DEN",
    "project": "Summit floor plans",
    "id": "T_2309",
    "isSold": true
  }
  // ... more units
]

5. Master Data Building (buildMasterFloorplanData)

Merges SVG and CMS data with validation:

Validation Checks:

  1. IDs present in SVG but not CMS → Warning
  2. IDs present in CMS but not SVG → Warning
  3. Mismatched group names between sources → Warning
  4. Missing DOM elements for IDs → Warning

Output Structure:

{
  id: "A_1209",
  isSold: true,
  groupName: "1 BEDROOM + DEN",
  floorPlanEl: <g element>,  // Direct reference to DOM node
  dataFromSVG: { /* SVG data */ },
  dataFromCMS: { /* CMS data */ }
}

Example from window.masterFloorplanData:

[
  {
    "id": "A_1209",
    "isSold": true,
    "groupName": "1 BEDROOM + DEN",
    "floorPlanEl": {}, // DOM element reference
    "dataFromSVG": {
      "id": "A_1209",
      "Name": "A 1209",
      "isSold": false,
      "groupName": "1 BEDROOM + DEN",
      "groupId": "_1_BEDROOM_DEN"
    },
    "dataFromCMS": {
      "dataName": "1209",
      "groupName": "1 BEDROOM + DEN",
      "project": "Summit floor plans",
      "id": "A_1209",
      "isSold": true
    }
  },
  {
    "id": "C_1303",
    "isSold": true,
    "groupName": "2 BEDROOM + DEN + 3 BATH",
    "floorPlanEl": {},
    "dataFromSVG": {
      "id": "C_1303",
      "Name": "C 1303",
      "isSold": false,
      "groupName": "2 BEDROOM + DEN + 3 BATH",
      "groupId": "_2_BEDROOM_DEN_3_BATH"
    },
    "dataFromCMS": {
      "dataName": "1303",
      "groupName": "2 BEDROOM + DEN + 3 BATH",
      "project": "Summit floor plans",
      "id": "C_1303",
      "isSold": true
    }
  }
  // ... more units
]

Key Points:

  • isSold at the top level comes from CMS (authoritative source)
  • floorPlanEl is a live DOM reference for direct manipulation
  • Both source data objects are preserved for debugging

6. Click Handler System (consoleSVGs)

Attaches click handlers to:

  1. All SVG units with class clickable
  2. All CMS elements with [data-fp-id]

On Click:

  • Finds matching data in all three collections
  • Sets active residence
  • Sets active tab (if group found)
  • Logs data to console for debugging

7. Detail Panel System

HTML Structure Required:

<div data-fp-detail="unit-205" data-fp-detail-selected="false">
  <!-- Unit details content -->
</div>

<!-- Scroll anchor -->
<div data-fp-detail-section-anchor></div>

Behavior:

  • Only one detail panel visible at a time
  • Auto-scrolls to anchor when unit selected
  • Smooth scroll animation (200ms delay for layout)

8. Sold Status System

Initialization Flow:

1. Remove 'sold' class from all units
2. Loop through masterFloorplanData
3. For each unit where isSold === true
4. Add 'sold' class to floorPlanEl

Visual Effect: CSS automatically styles .unit.sold elements


Initialization Sequence

Step-by-Step on Page Load

// 1. DOM Ready Event
document.addEventListener('DOMContentLoaded', () => {
  loadFloorPlan();
});

// 2. Load SVG from CDN
fetch(floorPlanSvg)
  .then(res => res.text())
  .then(svg => {
    // 3. Inject SVG into #floorplan container
    document.getElementById('floorplan').innerHTML = svg;
    
    // 4. Wait 200ms for SVG to render
    setTimeout(() => {
      // 5. Collect all data
      window.floorplanDataFromSVG = collectUnitDataFromSVG();
      window.floorplanDataFromCMS = collectUnitDataFromCMS();
      window.masterFloorplanData = buildMasterFloorplanData();
      
      // 6. Attach click handlers
      consoleSVGs();
      
      // 7. Initialize tabs
      initFloorPlanTabs();
      
      // 8. Restore state from URL (200ms delay)
      initActiveTabFromQuery({ 
        delayMs: 200, 
        fallback: '1 BEDROOM + DEN' 
      });
      initActiveResidenceFromQuery({ delayMs: 200 });
      
      // 9. Apply sold status styling
      initializeSoldResidentsFromCMS();
    }, 200);
  });

Timing Delays Explained:

  • 200ms after SVG injection: Allows browser to parse SVG DOM
  • 200ms for URL query init: Ensures tabs are ready before activation
  • Uses setTimeout to avoid race conditions

HTML Requirements

1. SVG Container

<div id="floorplan"></div>

Purpose: Target for SVG injection from CDN

2. Tab Links

<div data-fp-tablink="1 BEDROOM + DEN" 
     data-fp-tablink-active="false">
  1 Bedroom + Den
</div>
<div data-fp-tablink="2 BEDROOM + DEN + 3 BATH" 
     data-fp-tablink-active="false">
  2 Bedroom + Den + 3 Bath
</div>
<div data-fp-tablink="3 BEDROOM + DEN" 
     data-fp-tablink-active="false">
  3 Bedroom + Den
</div>

Attributes:

  • data-fp-tablink - Group name (must match SVG and CMS exactly)
  • data-fp-tablink-active - Managed by script ("true" | "false")

3. CMS Unit Cards

<div data-fp-id="A_1209"
     data-fp-name="1209"
     data-fp-group-name="1 BEDROOM + DEN"
     data-fp-project="Summit floor plans"
     data-fp-soldout="true">
  <!-- Card content -->
</div>

Attributes:

  • data-fp-id - Unique unit identifier (must match SVG exactly, e.g., "A_1209")
  • data-fp-name - Display name (e.g., "1209")
  • data-fp-group-name - Bedroom type (must match tab exactly)
  • data-fp-project - Project name
  • data-fp-soldout - Must be lowercase "true" or "false"

4. Unit Detail Panels

<div data-fp-detail="A_1209" 
     data-fp-detail-selected="false">
  <!-- Detail content -->
</div>

Attributes:

  • data-fp-detail - Unit ID to match (e.g., "A_1209")
  • data-fp-detail-selected - Managed by script ("true" | "false")

5. Detail Section Anchor

<div data-fp-detail-section-anchor></div>

Purpose: Scroll target when unit is selected

6. Card Links (Optional - for featured-floorplan.js)

<a href="#" data-fp-card-link="A_1209">View Details</a>

Purpose: Automatically updated with proper detail page URLs by featured-floorplan.js


CSS Selectors & Classes

Managed by JavaScript

| Selector | Added By | Purpose | |----------|----------|---------| | .clickable | Manual in SVG | Makes unit clickable | | .unit | Manual in SVG | Identifies unit element | | .unit-group | Manual in SVG | Groups units by type | | .sold | Script | Marks sold units | | .selected | Script | Highlights selected unit | | .active | Script | Highlights active group |

Attribute Selectors

| Attribute | Values | Purpose | |-----------|--------|---------| | [data-fp-tablink-active] | "true" | "false" | Active tab styling | | [data-fp-selected] | "true" | "false" | Selected group card | | [data-fp-detail-selected] | "true" | "false" | Visible detail panel |

CSS Rules (from floorplan.css)

/* Active tab background */
[data-fp-tablink-active="true"] {
  background-color: #d6bdac;
}

/* Sold unit styling */
svg .unit.sold polygon, 
svg .unit.sold polyline {
  fill: #ac3833 !important;
}

/* Selected unit highlight */
svg .unit.selected polygon, 
svg .unit.selected polyline {
  fill: #ad7c59 !important;
}

/* Active group highlight */
svg .unit-group.active .unit polygon {
  fill: #d6bdac;
}

/* Detail panel visibility */
[data-fp-detail-selected="true"] {
  display: block;
}
[data-fp-detail-selected="false"] {
  display: none;
}

URL Query Parameters

Structure

/summit/floorplan?tab=<groupName>&residence=<unitId>

Examples

# Just tab selection
/summit/floorplan?tab=2%20BEDROOM%20%2B%20DEN%20%2B%203%20BATH

# Tab + unit selection
/summit/floorplan?tab=1%20BEDROOM%20%2B%20DEN&residence=A_1209

# No parameters (uses default: "1 BEDROOM + DEN")
/summit/floorplan

Browser History Integration

Forward/Back Button Support:

window.addEventListener('popstate', () => {
  // Restore tab from URL
  const fromTabQS = getTabFromQuery();
  if (fromTabQS) setActiveTab(fromTabQS);

  // Restore residence from URL
  const fromResQS = getResidenceFromQuery();
  if (fromResQS && Array.isArray(window.masterFloorplanData)) {
    const master = window.masterFloorplanData.find(m => m.id === fromResQS);
    if (master) setActiveResidence(master, { updateQS: false });
  }
});

Update Behavior:

  • replace: true - Replaces current history entry (default)
  • replace: false - Pushes new history entry

API Reference

Global Objects

window.floorplanDataFromSVG

Array of unit data extracted from SVG structure.

window.floorplanDataFromCMS

Array of unit data extracted from CMS elements.

window.masterFloorplanData

Master array combining SVG and CMS data with DOM references.

window.CMSCollector (from featured-floorplan.js)

{
  collect: collectUnitDataFromCMS,
  log: logCmsDataAsJson,
  updateFloorplanUrls: updateFloorplanUrls
}

Core Functions

Selection Functions

setActiveResidence(masterOrId, options)

  • Parameters:
    • masterOrId - Master object or unit ID string
    • options.updateQS - Update URL query (default: true)
  • Purpose: Selects and displays a unit

setSelectedResidenceSVG(element)

  • Parameters: DOM element (<g>)
  • Purpose: Highlights unit in SVG

showSelectedResidenceDetail(id)

  • Parameters: Unit ID string
  • Purpose: Shows detail panel and scrolls to it

resetActiveResidences()

  • Purpose: Clears all unit selections

Tab Functions

setActiveTab(tabValue)

  • Parameters: Tab name string
  • Purpose: Activates a tab and updates UI

initFloorPlanTabs()

  • Purpose: Attaches click handlers to all tabs

Group Functions

setActiveGroupSVG(groupName)

  • Parameters: Group name string
  • Purpose: Adds 'active' class to matching SVG group

highlightActiveGroup(groupName)

  • Parameters: Group name string
  • Purpose: Updates data-fp-selected on CMS cards

Data Collection Functions

collectUnitDataFromSVG()

  • Returns: Array of unit objects from SVG
  • Purpose: Extracts unit data from loaded SVG

collectUnitDataFromCMS()

  • Returns: Array of unit objects from CMS
  • Purpose: Extracts unit data from HTML attributes

buildMasterFloorplanData()

  • Returns: Master array with merged data
  • Purpose: Combines and validates SVG + CMS data

URL Functions

updateTabQuery(tabValue, options)

  • Parameters: Tab name, options object
  • Purpose: Updates URL with tab parameter

getTabFromQuery()

  • Returns: Tab name or null
  • Purpose: Reads tab from URL

updateResidenceQuery(id, options)

  • Parameters: Unit ID, options object
  • Purpose: Updates URL with residence parameter

getResidenceFromQuery()

  • Returns: Unit ID or null
  • Purpose: Reads residence from URL

initActiveTabFromQuery(options)

  • Parameters: { delayMs, fallback }
  • Purpose: Restores tab from URL on page load

initActiveResidenceFromQuery(options)

  • Parameters: { delayMs }
  • Purpose: Restores unit selection from URL

Initialization Functions

loadFloorPlan()

  • Purpose: Main initialization function
  • Triggers: Full data collection and setup sequence

initializeSoldResidentsFromCMS()

  • Purpose: Applies 'sold' class to units based on CMS data

consoleSVGs()

  • Purpose: Attaches click handlers and console logging

Common Patterns

Adding a New Unit

  1. In SVG:

    <g class="unit-group" data-name="2 BEDROOM + DEN + 3 BATH" id="_2_BEDROOM_DEN_3_BATH">
      <g class="unit clickable" id="C_2306" data-name="C 2306">
        <!-- polygon/polyline shapes -->
      </g>
    </g>
  2. In CMS:

    <div data-fp-id="C_2306"
         data-fp-name="2306"
         data-fp-group-name="2 BEDROOM + DEN + 3 BATH"
         data-fp-project="Summit floor plans"
         data-fp-soldout="false">
    </div>
  3. Detail Panel:

    <div data-fp-detail="C_2306" data-fp-detail-selected="false">
      <!-- content -->
    </div>

Important: IDs must match exactly across all three locations (SVG, CMS, detail panel).

Marking a Unit as Sold

Update CMS attribute:

<div data-fp-id="C_2306" data-fp-soldout="true">

Script will automatically:

  1. Parse the boolean attribute (must be lowercase "true")
  2. Add 'sold' class to SVG element
  3. Apply red styling from CSS

Example of sold units:

  • A_1209 - Sold (1 BEDROOM + DEN)
  • C_2306 - Sold (2 BEDROOM + DEN + 3 BATH)
  • B3_1208 - Sold (2 BEDROOM + DEN + 2.5 BATH)

Adding a New Bedroom Type (Tab)

  1. Add tab link:

    <div data-fp-tablink="STUDIO" data-fp-tablink-active="false">
      Studio
    </div>
  2. Update SVG with matching group:

    <g class="unit-group" data-name="STUDIO" id="_STUDIO">
      <!-- units -->
    </g>
  3. Update CMS cards:

    <div data-fp-group-name="STUDIO" ...>

Note: Group names are case-sensitive and must match exactly everywhere.

Debugging

Check collected data:

console.log(window.floorplanDataFromSVG);
console.log(window.floorplanDataFromCMS);
console.log(window.masterFloorplanData);

Manual control:

// Select a unit manually
setActiveResidence('A_1209');

// Switch tabs manually
setActiveTab('2 BEDROOM + DEN + 3 BATH');

// Reset selections
resetActiveResidences();

featured-floorplan.js Extension

Purpose

Collects CMS data and updates card link URLs with proper query parameters.

Key Features

  1. Data Collection:

    window.CMSCollector.collect()
  2. URL Building:

    // Builds: /summit/floorplan?tab=1%20BEDROOM%20%2B%20DEN&residence=A_1209
    buildDetailSlug(groupName, id)
  3. Link Updates:

    // Updates all [data-fp-card-link] hrefs
    window.CMSCollector.updateFloorplanUrls(data)

Auto-Execution

Runs automatically on DOMContentLoaded or immediately if DOM is ready.

Configuration

const DETAIL_BASE_PATH = "/summit/floorplan"; // Adjust as needed

Troubleshooting

Issue: Units not clickable

  • Check for .clickable class on <g> elements in SVG
  • Verify consoleSVGs() was called after SVG load

Issue: Data mismatch warnings

  • Ensure IDs match exactly between SVG and CMS
  • Check group names are identical (case-sensitive)
  • Verify all required data-fp-* attributes present

Issue: Details not showing

  • Check [data-fp-detail] matches unit ID exactly
  • Verify detail section has anchor element
  • Check CSS display rules for selected state

Issue: URL parameters not working

  • Verify 200ms delay in initialization functions
  • Check browser history state on back/forward
  • Ensure tab/residence values are URL-encoded properly

Issue: Sold status not applying

  • Confirm data-fp-soldout is lowercase "true"/"false"
  • Check initializeSoldResidentsFromCMS() runs after data build
  • Verify CSS .sold rules are present

License & Credits

SVG Source: Picked from this repository.

const floorPlanSvg = "https://cdn.jsdelivr.net/npm/@rtstic.dev/[email protected]/dist/floorplan.svg";

Last Updated: 22 October 2025