How Small Is Small Code?

Skip Front Page | 0 comments

Code for the post at https://jonathanaddington.com/how-small-is-a-small-business/

100% generated by OpenAI’s gpt-4o model on 2024-05-29

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Autocomplete Example</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/nouislider/distribute/nouislider.min.css">
    <style>
        body {
            font-family: Arial, sans-serif;
        }
        .autocomplete-suggestions {
            border: 1px solid #ccc;
            max-height: 150px;
            overflow-y: auto;
            min-width: 300px; /* Adjust this value as needed */
        }
        .autocomplete-suggestion {
            padding: 8px;
            cursor: pointer;
        }
        .autocomplete-suggestion:hover {
            background-color: #e9e9e9;
        }
        .info {
            margin-top: 20px;
            font-family: Arial, sans-serif;
        }
        .info p {
            margin: 5px 0;
        }
        .info h2 {
            margin: 10px 0 5px;
            font-size: 1.2em;
        }
        .chart-container {
            width: 50%;
            margin: auto;
            height: 400px; /* Set a fixed height for the chart */
        }
        #autocomplete {
            width: 100%;
            padding: 10px;
            box-sizing: border-box;
            margin-bottom: 20px;
        }
        @media (max-width: 768px) {
            .chart-container {
                width: 100%;
                height: 400px; /* Maintain the height for smaller screens */
            }
        }
        .controls {
            margin-top: 20px;
        }
        .controls button {
            padding: 10px;
            margin-right: 10px;
        }
        .controls .slider-container {
            margin-top: 20px;
            max-width: 50%;
        }
        .industry-list {
            margin-top: 20px;
        }
        .industry-list ul {
            list-style-type: none;
            padding: 0;
        }
        .industry-list li {
            padding: 5px;
            cursor: pointer;
        }
        .industry-list li:hover {
            background-color: #e9e9e9;
        }
        #slider {
            margin: 20px 0;
        }
        .variance-positive {
            color: green;
        }
        .variance-negative {
            color: red;
        }
    </style>
    <script src="https://cdn.jsdelivr.net/npm/nouislider/distribute/nouislider.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body>
    <h1>Industry Information</h1>
    <label for="autocomplete">Search by Industry or NAICS Code:</label>
    <input type="text" id="autocomplete" placeholder="Type to search...">
    <div id="autocomplete-list" class="autocomplete-suggestions"></div>
    
    <div class="info">
        <p id="hierarchy"></p>
        <p><strong>Limit:</strong> <span id="limit"></span></p>
        <p><strong>Average Limit for Sector:</strong> <span id="averageSectorLimit"></span></p>
        <p><strong>Variance from Sector Average:</strong> <span id="sectorVariance"></span></p>
        <p><strong>Average Limit for Subsector:</strong> <span id="averageSubsectorLimit"></span></p>
        <p><strong>Variance from Subsector Average:</strong> <span id="subsectorVariance"></span></p>
    </div>
    
    <div class="chart-container">
        <canvas id="limitChart"></canvas>
    </div>
    
    <div class="controls">
        <button id="randomIndustryBtn">Show Random Industry</button>
        <button id="smallestIndustryBtn">List Industries with Smallest Limit</button>
        <button id="largestIndustryBtn">List Industries with Largest Limit</button>
        <div class="slider-container">
            <label for="metricSelect">Metric:</label>
            <select id="metricSelect">
                <option value="revenueLimit">Revenue</option>
                <option value="employeeCountLimit">Employees</option>
            </select>
            <div id="slider"></div>
            <span id="sliderValues"></span>
        </div>
    </div>
    
    <div class="industry-list" id="industryList">
        <ul></ul>
    </div>
    
    <script>
        let data = [];
        let chart;

        // Fetch data from the API
        fetch('https://api.sba.gov/naics/naics.json')
            .then(response => response.json())
            .then(json => {
                data = json;
                displayRandomEntry();
                initializeSlider();
            })
            .catch(error => console.error('Error fetching data:', error));

        const input = document.getElementById('autocomplete');
        const autocompleteList = document.getElementById('autocomplete-list');
        const hierarchySpan = document.getElementById('hierarchy');
        const limitSpan = document.getElementById('limit');
        const averageSectorLimitSpan = document.getElementById('averageSectorLimit');
        const sectorVarianceSpan = document.getElementById('sectorVariance');
        const averageSubsectorLimitSpan = document.getElementById('averageSubsectorLimit');
        const subsectorVarianceSpan = document.getElementById('subsectorVariance');
        const limitChartCtx = document.getElementById('limitChart').getContext('2d');
        const randomIndustryBtn = document.getElementById('randomIndustryBtn');
        const smallestIndustryBtn = document.getElementById('smallestIndustryBtn');
        const largestIndustryBtn = document.getElementById('largestIndustryBtn');
        const metricSelect = document.getElementById('metricSelect');
        const slider = document.getElementById('slider');
        const sliderValues = document.getElementById('sliderValues');
        const industryList = document.getElementById('industryList').querySelector('ul');

        input.addEventListener('input', function() {
            const query = this.value.toLowerCase();
            autocompleteList.innerHTML = '';

            if (query.length === 0) {
                return;
            }

            const filteredData = data.filter(item => 
                item.description.toLowerCase().includes(query) || item.id.includes(query)
            );

            filteredData.forEach(item => {
                const div = document.createElement('div');
                div.classList.add('autocomplete-suggestion');
                div.textContent = `${item.description} (${item.id})`;
                div.addEventListener('click', function() {
                    input.value = `${item.description} (${item.id})`;
                    displayEntry(item);
                    autocompleteList.innerHTML = '';
                });
                autocompleteList.appendChild(div);
            });
        });

        document.addEventListener('click', function(e) {
            if (e.target !== input) {
                autocompleteList.innerHTML = '';
            }
        });

        randomIndustryBtn.addEventListener('click', displayRandomEntry);
        smallestIndustryBtn.addEventListener('click', () => listIndustries('smallest'));
        largestIndustryBtn.addEventListener('click', () => listIndustries('largest'));
        metricSelect.addEventListener('change', updateSliderRange);

        function displayEntry(item) {
            hierarchySpan.textContent = `${item.sectorDescription} > ${item.subsectorDescription} > ${item.description} (${item.id})`;
            limitSpan.textContent = item.revenueLimit ? `$${item.revenueLimit} million` : (item.employeeCountLimit ? `${item.employeeCountLimit} employees` : 'N/A');

            const sectorItems = data.filter(d => d.sectorId === item.sectorId);
            const subsectorItems = data.filter(d => d.subsectorId === item.subsectorId);

            let sectorLimits = [];
            let subsectorLimits = [];
            let isRevenue = false;

            if (item.revenueLimit !== null) {
                sectorLimits = sectorItems.map(d => d.revenueLimit).filter(limit => limit !== null);
                subsectorLimits = subsectorItems.map(d => d.revenueLimit).filter(limit => limit !== null);
                isRevenue = true;
            } else if (item.employeeCountLimit !== null) {
                sectorLimits = sectorItems.map(d => d.employeeCountLimit).filter(limit => limit !== null);
                subsectorLimits = subsectorItems.map(d => d.employeeCountLimit).filter(limit => limit !== null);
            }

            const averageSectorLimit = Math.round(sectorLimits.reduce((sum, limit) => sum + limit, 0) / sectorLimits.length);
            const sectorVariance = Math.round((item.revenueLimit || item.employeeCountLimit) - averageSectorLimit);

            const averageSubsectorLimit = Math.round(subsectorLimits.reduce((sum, limit) => sum + limit, 0) / subsectorLimits.length);
            const subsectorVariance = Math.round((item.revenueLimit || item.employeeCountLimit) - averageSubsectorLimit);

            averageSectorLimitSpan.textContent = isRevenue ? `$${averageSectorLimit} million` : `${averageSectorLimit} employees`;
            sectorVarianceSpan.textContent = isRevenue ? `${sectorVariance > 0 ? '+' : ''}$${sectorVariance} million` : `${sectorVariance > 0 ? '+' : ''}${sectorVariance} employees`;
            averageSubsectorLimitSpan.textContent = isRevenue ? `$${averageSubsectorLimit} million` : `${averageSubsectorLimit} employees`;
            subsectorVarianceSpan.textContent = isRevenue ? `${subsectorVariance > 0 ? '+' : ''}$${subsectorVariance} million` : `${subsectorVariance > 0 ? '+' : ''}${subsectorVariance} employees`;

            // Add classes for variance colors
            sectorVarianceSpan.className = sectorVariance >= 0 ? 'variance-positive' : 'variance-negative';
            subsectorVarianceSpan.className = subsectorVariance >= 0 ? 'variance-positive' : 'variance-negative';

            // Update the chart
            updateChart(item, averageSectorLimit, averageSubsectorLimit, isRevenue);
        }

        function displayRandomEntry() {
            if (data.length > 0) {
                const randomIndex = Math.floor(Math.random() * data.length);
                const randomItem = data[randomIndex];
                displayEntry(randomItem);
            }
        }

        function updateChart(item, averageSectorLimit, averageSubsectorLimit, isRevenue) {
            const limit = item.revenueLimit || item.employeeCountLimit;
            const labels = [item.description, item.sectorDescription, item.subsectorDescription];
            const data = [limit, averageSectorLimit, averageSubsectorLimit];
            const label = isRevenue ? 'Revenue (in million $)' : 'Employees';

            if (chart) {
                chart.destroy();
            }

            chart = new Chart(limitChartCtx, {
                type: 'bar',
                data: {
                    labels: labels,
                    datasets: [{
                        label: label,
                        data: data,
                        backgroundColor: ['rgba(75, 192, 192, 0.2)', 'rgba(54, 162, 235, 0.2)', 'rgba(255, 206, 86, 0.2)'],
                        borderColor: ['rgba(75, 192, 192, 1)', 'rgba(54, 162, 235, 1)', 'rgba(255, 206, 86, 1)'],
                        borderWidth: 1
                    }]
                },
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    scales: {
                        y: {
                            beginAtZero: true
                        }
                    }
                }
            });
        }

        function listIndustries(type) {
            industryList.innerHTML = '';
            let sortedData;

            if (type === 'smallest') {
                sortedData = [...data].sort((a, b) => (a.revenueLimit || a.employeeCountLimit || Number.MAX_VALUE) - (b.revenueLimit || b.employeeCountLimit || Number.MAX_VALUE));
            } else if (type === 'largest') {
                sortedData = [...data].sort((a, b) => (b.revenueLimit || b.employeeCountLimit || Number.MIN_VALUE) - (a.revenueLimit || a.employeeCountLimit || Number.MIN_VALUE));
            }

            sortedData.forEach(item => {
                const li = document.createElement('li');
                li.textContent = `${item.description} (${item.id})`;
                li.addEventListener('click', () => displayEntry(item));
                industryList.appendChild(li);
            });
        }

        function updateRange() {
            const metric = metricSelect.value;
            const [lower, upper] = slider.noUiSlider.get().map(Number);
            sliderValues.textContent = `Selected range: ${lower} - ${upper}`;
            industryList.innerHTML = '';

            const filteredData = data.filter(item => {
                const limit = item[metric];
                return limit !== null && limit >= lower && limit <= upper;
            });

            const sortedData = filteredData.sort((a, b) => a.id - b.id);

            sortedData.forEach(item => {
                const li = document.createElement('li');
                li.textContent = `${item.description} (${item.id})`;
                li.addEventListener('click', () => displayEntry(item));
                industryList.appendChild(li);
            });
        }

        function initializeSlider() {
            // Initialize the slider with a default range
            noUiSlider.create(slider, {
                start: [0, 100],
                connect: true,
                range: {
                    'min': 0,
                    'max': 100
                },
                tooltips: [true, true]
            });

            slider.noUiSlider.on('update', updateRange);

            // Set the initial range based on the selected metric
            updateSliderRange();
        }

        function updateSliderRange() {
            const metric = metricSelect.value;
            const minLimit = Math.min(...data.map(item => item[metric] || Infinity));
            const maxLimit = Math.max(...data.map(item => item[metric] || 0));

            slider.noUiSlider.updateOptions({
                range: {
                    'min': minLimit,
                    'max': maxLimit
                },
                start: [minLimit, maxLimit]
            });

            // Update the range display
            updateRange();
        }
    </script>
</body>
</html>

0 Comments

What's your $0.02?

This site uses Akismet to reduce spam. Learn how your comment data is processed.