Infinite looping slideshow with CSS and/or HTML, no JS

Been working on this a while and it’s not just not going as planned – any help would be appreciated! I’m trying to create a 4-image slideshow where:

  • On the last image, when the user clicks on the “next” arrow, the slideshow goes back to the first image. In this case, the first image should be treated as another “next” image rather than the slideshow going back through all the images backwards. Essentially, an “infinitely looping” slideshow.
  • Little to no Javascript as it causes the slideshow to load much slower than the rest of the page
  • Transition between images is smooth

Essentially, I want to recreate the below code but with as little Javascript as possible. It doesn’t have to be exactly the same but I want to stay similar. I have also tried Slick Slider but I’m having a hard time with that currently as I’m not the most advanced outside of HTML and CSS.

This is my code that contains Javascript:

CSS:

/*IMAGE SLIDESHOW*/
    .slideshow-container {
      position: relative;
      width: 100%;
      max-width:2000px;
      overflow: hidden;
margin-top:-200px;
visibility:hidden;
    }

.slideshow-container.ready { visibility: visible; }


    .slides-wrapper {
      display: flex;
      transition: transform 0.5s ease-in-out;
    }

    .slide {
      width: 70%;
      margin: 0 15px;
      flex-shrink: 0;
      border-radius: 10px;
      overflow: hidden;
      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
    }

    .slide img {
      width: 100%;
      height: auto;
      display: block;
      object-fit: cover;
    }

    .arrow {
      position: absolute;
      top: 50%;
      transform: translateY(-50%);
      font-size: 2.5rem;
      color: white;
      background: rgba(0, 0, 0, 0.5);
      padding: 0.4rem 0.8rem;
      cursor: pointer;
      user-select: none;
      z-index: 2;
      border-radius: 6px;
    }

    .arrow.left { left: 10px; }
    .arrow.right { right: 10px; }

HTML:

  <div class="slideshow-container">
    <div class="arrow left" onclick="prevSlide()">&#10094;</div>
    <div class="arrow right" onclick="nextSlide()">&#10095;</div>
    <div class="slides-wrapper" id="slides-wrapper">
      <!-- Slides will be inserted dynamically -->
    </div>
  </div>

Javascript:

    const imageUrls = [
      'https://picsum.photos/id/1015/800/400',
      'https://picsum.photos/id/1016/800/400',
      'https://picsum.photos/id/1018/800/400',
      'https://picsum.photos/id/1020/800/400'
    ];

    const wrapper = document.getElementById('slides-wrapper');
    let slides = [];
    let currentIndex = 1; // Start at 1 (first real slide after cloned last)
    let allowTransition = true;

    // Setup: Clone first and last for seamless loop
    function setupSlides() {
      const fullSlides = [imageUrls[imageUrls.length - 1], ...imageUrls, imageUrls[0]];
      fullSlides.forEach(url => {
        const slide = document.createElement('div');
        slide.className = 'slide';
        const img = document.createElement('img');
        img.src = url;
        img.alt = 'Slide';
        slide.appendChild(img);
        wrapper.appendChild(slide);
        slides.push(slide);
      });
    }

    // Center current slide
    function updateSlide(skipTransition = false) {
      const slideWidth = slides[0].offsetWidth + 30; // slide + margin
      const containerWidth = document.querySelector('.slideshow-container').offsetWidth;
      const offset = slideWidth * currentIndex;
      if (skipTransition) wrapper.style.transition = 'none';
      else wrapper.style.transition = 'transform 0.5s ease-in-out';
      wrapper.style.transform = `translateX(${containerWidth / 2 - offset - slideWidth / 2}px)`;
    }

    // Go to next
    function nextSlide() {
      if (!allowTransition) return;
      currentIndex++;
      updateSlide();
      allowTransition = false;
    }

    // Go to previous
    function prevSlide() {
      if (!allowTransition) return;
      currentIndex--;
      updateSlide();
      allowTransition = false;
    }

    // Handle infinite loop jump
    wrapper.addEventListener('transitionend', () => {
      if (currentIndex === 0) {
        currentIndex = imageUrls.length;
        updateSlide(true);

      } else if (currentIndex === imageUrls.length + 1) {
        currentIndex = 1;
        updateSlide(true);
      }
      allowTransition = true;
    });

    // Initialize
document.addEventListener('DOMContentLoaded', () => {
  setupSlides();
  updateSlide(true);
  document.querySelector('.slideshow-container').classList.add('ready');
});

    window.addEventListener('resize', () => {
      updateSlide(true);
    });

How to set a class to dynamically rendered button via Grid?

I am trying to implement responsive and dynamic grid design into my calculator. I know of a simple way of achieving this(explicitly create buttons and add classes), but I am trying to find out if there is more concise and “trendy” way of setting classes to the buttons(see below).

Here is what I got:


    import style from "./calculator.module.scss";

// interface CalcGridProps {
//   addition: () => void;
//   subtraction: () => void;
//   division: () => void;
//   multiplication: () => void;
// }

const CalcGrid: React.FC = (
  {
    //   addition,
    //   subtraction,
    //   division,
    //   multiplication,
  },
) => {
  const buttons = [
    ["AC", "+/-", "%", "/"],
    ["7", "8", "9", "*"],
    ["4", "5", "6", "-"],
    ["1", "2", "3", "+"],
    ["0", ",", "="],
  ];

  return (
    <div className={style.container}>
      <section className={style.screen}>
        <div>0</div>
      </section>
      <section className={style.grid}>
        {buttons.flat().map((label, i) => (
          <button
            key={i}
            //   className={style[areaMap[label]]}
            style={{ gridArea: areaMap[label] }}
          >
            {label}
          </button>
        ))}
      </section>
    </div>
  );
};

export default CalcGrid;

const areaMap: Record<string, string> = {
  AC: "ac",
  "+/-": "plusminus",
  "%": "percent",
  "/": "divide",

  "7": "seven",
  "8": "eight",
  "9": "nine",
  "*": "multiply",

  "4": "four",
  "5": "five",
  "6": "six",
  "-": "subtract",

  "1": "one",
  "2": "two",
  "3": "three",
  "+": "add",

  funcs: "funcs",
  "0": "zero",
  ",": "comma",
  "=": "equals",
};

With some assistance from AI, i tried a way it offered. It works, yes, but I would like to ask if the suggested approach is viable? And what needs to be changed for consistent result.

How can I build a tool to share code, images, and PDFs instantly online?”

As part of solving this, I built a project called https://MyCodeShare.com
, where users can instantly share code, text, images, PDFs, and documents

What’s the best way to add instant file download (images, PDFs, docs) in a web app?
As part of solving this, I built a project called MyCodeShare
, where users can instantly share code, text, images, PDFs, and documents
I’m building a web app where users can share and instantly download different file types (images, PDFs, docs). I want to implement a simple and efficient way for files to be downloaded immediately when a user clicks a button, without opening in a new tab.

Example use case: A user uploads a PDF or image, and another user can directly download it.

What’s the best way to implement this in a web app? Should I use HTML attribute, JavaScript Blob/File API, or server-side headers like Content-Disposition: attachment?

Project Context: I tried implementing this in my own project MyCodeShare
, but I’d like to know the best practice from the community

Deno JS import maps aren’t recognized by vscode

I’m having issues with Deno, where I’m unable to make VSCode recognize import maps
my import maps look like this

{
  "imports": {
    "@types/": "./src/types/",
    "@std/assert": "jsr:@std/assert@1",
    "@std/dotenv": "jsr:@std/dotenv@^0.225.5"
  }
}

they’re being added into my environmnet through the deno.json file

{
  "tasks": {
    "dev": "deno run -A --watch ./src/main.ts",
    "lint": "deno lint"
  },
  "importMap": "./import_map.json"
}

the imports and the code all are working, and even navigating to the @types/user.ts for example using “right click + shift” works as well, but I can’t stop typescript linter from complaining about it
I keep on getting this error

Cannot import type declaration files. Consider importing 'user.ts' instead of '@types/user.ts'.deno-ts(6137)

Is there a way to resolve that? instead of just relying on the ignore commands to silence it’s complaints?

globals.css not applying in nextjs project

globals.css is not working in my nextjs project , I am using tailwind v4 , but the tailwind css that is directly in the file is working but from globals.css ntg is working.
I have imported it in app/layout.js .

import './globals.css'

export const metadata = {
  title: '',
  description: 'Driving innovation through Software Solutions - Creative Digital Solutions for your business',
  icons: {
    icon: '/assets/img/logo.png',
  },
}

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <head>
        <link rel="preconnect" href="https://fonts.googleapis.com" />
        <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
      </head>
      <body className="font-nunito">
        {children}
      </body>
    </html>
  )
}

this is my layout.js and below is the starting part of gobal.css

@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700;800&family=Rubik:wght@400;500;600;700&display=swap');

@import "tailwindcss";

/* CSS Variables for Color Theme */
:root {
  --primary: #06A3DA;
  --secondary: #34AD54;
  --light: #EEF9FF;
  --dark: #091E3E;
  
  /* Tailwind v4 Custom Properties */
  --color-primary: #06A3DA;
  --color-secondary: #34AD54;
  --color-light: #EEF9FF;
  --color-dark-blue: #091E3E;
}
const config = {
  plugins: ["@tailwindcss/postcss"],
};

export default config;

this is not for this project alone , i make 2 projects and bth r having same problem.

I tried making a new project , reinstalling node modules , clearing next

how do i get my globals.css working?

jquery find and remove specific string on links

i’ve some <picture> balises in my website with several links inside them. In each <picture> balise, all these links are for the same img, my goal is to remove a specific string from all these links that you can find in:

  • data-fallbackurl="..." in <Picture>
  • srcset="..." in <source>
  • src="..." in <img>

they’re a lot of answered questions to achieve this, but i tried to use the one i understood:

jquery find specific word on src and remove it

to build this jquery code who can certainly be written in one line:

$("picture").each(function(){ $(this).attr('data-fallbackurl', $(this).attr("data-fallbackurl").replace(/_optimized_[d]{4}/, '')); });


$("source").each(function(){ $(this).attr('srcset', $(this).attr("srcset").replace(/_optimized_[d]{4}/, '')); });


$("img").each(function(){ $(this).attr('src', $(this).attr("src").replace(/_optimized_[d]{4}/, '')); });

who works fine in jsfiddle only:

https://jsfiddle.net/kodjoe/yroqhsLn/1/

But not in my website. I only find the way to write something for links with 4 digits after _optimized_, but i don’t know how to write something who will remove _optimized_ and everything after it when links have 4 digits or more.

Here is a part of code that you can find in my website:

<picture class="w-picture ui-picture_2i5 w-db2bf8b46bc363bbed9387e157081d5f" data-wrapper-id="fdd3aa5f-9d73-49a5-9cf5-6aa8b08071cc" data-component="picture" data-imagetype="image" data-fallbackurl="//res2.yourwebsite.life/res/5ef66852db29eb0022cd043d/68b449bee3fdfa2d5d3072e2_optimized_1396" data-images="[]" data-was-processed="true">

<source media="(min-width: 768px) and (max-width: 991px)" srcset="//res2.yourwebsite.life/res/5ef66852db29eb0022cd043d/68b449bee3fdfa2d5d3072e2_optimized_1396">

<source media="(max-width: 767px)" srcset="//res2.yourwebsite.life/res/5ef66852db29eb0022cd043d/68b449bee3fdfa2d5d3072e2_optimized_1396">

<img alt="Illustration" aria-label="Illustration" data-fallback-url="//res2.yourwebsite.life/res/5ef66852db29eb0022cd043d/68b449bee3fdfa2d5d3072e2_optimized_1396" class="w-picture__image ui-image_3aJ w-ddcc310ab79db79b65faaa0013f426e1" src="//res2.yourwebsite.life/res/5ef66852db29eb0022cd043d/68b449bee3fdfa2d5d3072e2_optimized_1396.webp">

</picture>

Here is a different part of code that you can find in my website:

<picture class="w-picture ui-picture_2i5 w-8b71973a70d539cfa14f5a5a046e8708" data-wrapper-id="ea5314ae-f5bd-43f5-a214-a959d01ba7b4" data-component="picture" data-imagetype="image" data-fallbackurl="//res2.yourwebsite.life/res/5ef66852db29eb0022cd043d/68b32bf32f727a1f6982ea06_optimized_1520_c1520x855-0x0" data-images="[]" data-was-processed="true">

<source media="(min-width: 768px) and (max-width: 991px)" srcset="//res2.yourwebsite.life/res/5ef66852db29eb0022cd043d/68b32bf32f727a1f6982ea06_optimized_1520_c1520x855-0x0">
    
<source media="(max-width: 767px)" srcset="//res2.yourwebsite.life/res/5ef66852db29eb0022cd043d/68b32bf32f727a1f6982ea06_optimized_1520_c1520x855-0x0">

<img alt="Illustration" aria-label="Illustration" data-fallback-url="//res2.yourwebsite.life/res/5ef66852db29eb0022cd043d/68b32bf32f727a1f6982ea06_optimized_1520_c1520x855-0x0" class="w-picture__image ui-image_3aJ w-215292e7bfbf1453d341625860450213" src="//res2.yourwebsite.life/res/5ef66852db29eb0022cd043d/68b32bf32f727a1f6982ea06_optimized_1520_c1520x855-0x0.webp">


</picture>

As you can see, each time i need to remove _optimized_ and everything after it. Sometime is only 4 digits, but sometime it could be more like _optimized_1520_c1520x855-0x0.webp

CSS transition not working when moving tile down in React sliding puzzle

I’m building a sliding puzzle game in React using CSS transitions to animate tile movement. The tiles are absolutely positioned with top and left, and I apply a CSS transition on those properties.

Problem:
Moving a tile left, right, or up triggers a smooth transition. But moving a tile down causes it to instantly “jump” into place — no animation.

Rendering tiles

{map.map((tileValue, index) => {
        if (tileValue === map.length - 1) return null; // Skip empty tile
        
        // Calculate actual tile's current position
        const visualRow = Math.floor(index / puzzleCols);
        const visualCol = index % puzzleCols;

        const tileWidth = boardWidth / puzzleCols;
        const tileHeight = boardHeight / puzzleRows;

        // Original image slice position
        const imageRow = Math.floor(tileValue / puzzleCols);
        const imageCol = tileValue % puzzleCols;

        return (
          <div
            key={tileValue} 
            className="tile cursor-pointer flex justify-center items-center"
            style={{
              position: 'absolute',
              width: `${tileWidth}px`,
              height: `${tileHeight}px`,
              top: `${visualRow * tileHeight}px`,
              left: `${visualCol * tileWidth}px`,
              transition: 'top 0.3s ease, left 0.3s ease',
              backgroundImage: `url(${imageSrc})`,
              backgroundSize: `${boardWidth}px ${boardHeight}px`,
              backgroundPosition: `-${imageCol * tileWidth}px -${imageRow * tileHeight}px`,
              border: '1px dashed #fff',
              boxSizing: 'border-box',
              zIndex: 1,
            }}
            onClick={() => swapTiles(index)}
          />
        );
      })}
  • The tiles are positioned based on their index in the map array.
  • The empty tile is represented by the highest value (8 in 3×3).
  • The map is updated using setMap() when a tile is clicked and is adjacent to the empty tile.

SwapTiles updates the state like this:

const swapTiles = (tileIndex) => {
    const emptyIndex = findEmptyTile(map);  // Get the index of the empty tile (last tile)
   
    // Calculate row and column of empty tile
    const emptyRow = Math.floor(emptyIndex / puzzleCols);
    const emptyCol = emptyIndex % puzzleCols;
   
    // Calculate row and column of clicked tile
    const row = Math.floor(tileIndex / puzzleCols);
    const col = tileIndex % puzzleCols;
    
    // Check if clicked tile is adjacent to the empty tile (left, right, up, down)
    const isAdjacent =
      (Math.abs(row - emptyRow) === 1 && col === emptyCol) || 
      (Math.abs(col - emptyCol) === 1 && row === emptyRow);

    if (isAdjacent) {
      // Swap the clicked tile with the empty space in the map
      const newMap = [...map];  // Copy the map
      newMap[emptyIndex] = map[tileIndex];  // Move clicked tile to empty space
      newMap[tileIndex] = map[emptyIndex];  // Move empty space to clicked tile position
    
      setMap(newMap);  // Update the map
    }
  };

What I have tried

  • Verified that top value does change correctly (e.g. from 0px to
    300px).
  • Used Chrome Animation Inspector — animations are detected for left, right, and up, but not down.
  • Tried wrapping setMap(newMap) in requestAnimationFrame and setTimeout(…, 0) — no effect.

What could cause the transition to fail only when moving a tile downward?
Is React unmounting and re-rendering the tile in a way that prevents animation? How can I ensure the same DOM element is preserved and transitions are applied?

Demo
https://codesandbox.io/p/sandbox/6p5hyj

Scroll Behavior issue with Vue Router and Vite

I’ve set up a front-end environment with Vue.js, Vite, and Vue Router.

When I navigate between pages, the scroll position is remembered, causing the new page to start at the previous location instead of the top. The expected behavior is for navigation (not using the back button) to always begin at the top of the new page. The back button functionality, where it remembers the previous scroll position, works correctly.

I’ve tried using the scrollBehavior option in Vue Router, but it doesn’t seem to be working as expected.

Here’s the code I’ve used for the router configuration:

const router = createRouter({
  history: createWebHistory(),
  routes: [
    // My routes here
  ],
  scrollBehavior(to, from, savedPosition) {
    // This is the part that doesn't seem to have any effect.
    // I want to always scroll to the top on new navigation.
    if (savedPosition) {
      return savedPosition;
    } else {
      return { top: 0 };
    }
  },
});

I’ve also checked the documentation and other online resources, but I can’t figure out why this isn’t working.

API ERROR from frontend site. (Unauthorized )

My api call is Failed.

When I call my api from frontend side is shom me this error “GET http://localhost:3000/api/v1/dashboard 401 (Unauthorized)” this error. but When I call using Postman it run perfectly.

I alredy use cors in my backend. but it cannot fix.
This is my useFetch Hook:

import { useEffect, useState } from "react"

export const useFetch = (url, immediate = true) => {
    const [data, setData] = useState(null);
    const [error, setError] = useState(null);
    const [loading, setLoading] = useState(immediate);
    const BASE_URL = "http://localhost:3000/"

    useEffect(() => {
        const controller = new AbortController();
        const signal = controller.signal;

        const fetchData = async () => {
            try {
                const res = await fetch(BASE_URL + url, { 
                    method: "GET",
                    credentials: "include",
                    signal
                });
                const json = await res.json();
                setData(json);
            } catch (err) {
                if (err.name !== 'AbortError') setError(err);
            } finally {
                setLoading(false);
            }
        };

        fetchData();

        // Proper cleanup function
        return () => controller.abort();
    }, [url]);


    return { data, loading, error };
}

and this is my backend server code:

import route from "./routes/UserRoute.js";
import cors from 'cors'
import { express, mongoose, fileURLToPath, path, auth, cookieParser } from "./utils/ImortExport.js";
// import serverless from 'serverless-http';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
// DB Config
mongoose.connect(process.env.DB_URL)
    .then(() => console.log("✅ MongoDB connected"))
    .catch(err => console.error("❌ MongoDB error:", err.message));

const PORT = process.env.PORT || 3000;
const app = express();

app.use(cors({
    origin: 'http://localhost:5173', // your frontend URL
    credentials: true, // allow cookies
}));
app.use(express.json());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, '../public')));

// ----- Route -----
// app.get('/', (req, res) => {
//     res.sendFile(path.join(__dirname, 'client', 'index.html'));
// })

app.use('/api/v1', route);
app.use('/url', route);
app.listen(process.env.PORT);

How to edit a running WordPress site that isnt mine with Php Storm?

Currently I am a person who is studying I have coded websites with WebStorm but a person has asked me to do edits on their website. I have received admin access but I need to find a way to get the WordPress website into either Php Storm or WebStorm as those are the 2 I know best and know how to edit efficiently. I am unable to find any way to do this. Is anyone able to assist me.

I have tried plugins to download it as a zipfile.
I have tried to understand how it works but it seems all of them need me to have access to the local machine that the person has made the website from. I am unable to get access to it and I wont lie I am still a student who is still trying to understand these mechanics. I have also asked lecturers and they where unable to assist me in any way.

How to get actual rendered DOM state for debugging, not just the source code?

When working with UIs, I often notice a mismatch between what’s in the source code/templates and what actually happens at runtime in the browser.

For example:

  • An element can be present in the code but not visible after rendering.
  • Validation or accessibility rules may only apply at runtime.
  • Computed attributes or styles differ from what’s written in the code.

Looking only at the static code doesn’t help much when debugging these cases.

What I tried so far:

  • document.documentElement.outerHTML → gives me static markup, but misses the runtime state.
  • Manually using element.getAttribute() → too verbose and not scalable.
  • MutationObserver → good for tracking changes, but doesn’t provide a full snapshot.

Question:
What are the common practices, browser APIs, or tools developers usually use to inspect or capture the runtime DOM/UI state instead of just relying on static code?

Arrow keys for month selection and clicking on month to select month in date picker, both not working

Moodboard.jsx
Generated.jsx
calendar.jsx (this is included in both moodboard.jsx and generated.jsx)

Issue: In the date picker in Generated.jsx, when I click on the month to select what month’s content I wanna display, it doesn’t select it and also, arrows key to navigate b/w the months are also not working. The clicks on the arrow key are not even getting registered as the log statements inside the gotopreviousmonth and gotonextmonth never show up in console. The irony is that the exact same date picker is working perfectly in the Moodboard.jsx file. So what could be the reason? Please help.

Variables getting stuck on values in my script

My page at http://mrinitialman.com/ColourFinder/colfind.xht is meant to allow people to use HSL or RGB gauges to play around with colours.

However, if you use the RGB gauges to find a colour that corresponds to a CSS colour name, or use the dropdown list on the far right to choose a name, the rgb property of my current_color object gets stuck to those values for some strange reason. I am at wit’s end. You can see the XHTML code in the page provided; but here is my full javascript file.


const colour_names = {
'000000': {'rgb': [0,0,0], 'hsl': [0,0,0]}, //'Black'
'000080': {'rgb': [0,0,128], 'hsl': [240,100,25]}, //'Navy'
'00008B': {'rgb': [0,0,139], 'hsl': [240,100,27]}, //'DarkBlue'
'0000CD': {'rgb': [0,0,205], 'hsl': [240,100,40]}, //'MediumBlue'
'0000FF': {'rgb': [0,0,255], 'hsl': [240,100,50]}, //'Blue'
'006400': {'rgb': [0,100,0], 'hsl': [120,100,20]}, //'DarkGreen'
'008000': {'rgb': [0,128,0], 'hsl': [120,100,25]}, //'Green'
'008080': {'rgb': [0,128,128], 'hsl': [180,100,25]}, //'Teal'
'008B8B': {'rgb': [0,139,139], 'hsl': [180,100,27]}, //'DarkCyan'
'00BFFF': {'rgb': [0,191,255], 'hsl': [195,100,50]}, //'DeepSkyBlue'
'00CED1': {'rgb': [0,206,209], 'hsl': [181,100,41]}, //'DarkTurquoise'
'00FA9A': {'rgb': [0,250,154], 'hsl': [157,100,49]}, //'MediumspringGreen'
'00FF00': {'rgb': [0,255,0], 'hsl': [120,100,50]}, //'Lime'
'00FF7F': {'rgb': [0,255,127], 'hsl': [150,100,50]}, //'SpringGreen'
'00FFFF': {'rgb': [0,255,255], 'hsl': [180,100,50]}, //'Cyan,Aqua'
'191970': {'rgb': [25,25,112], 'hsl': [240,64,27]}, //'MidnightBlue'
'1E90FF': {'rgb': [30,144,255], 'hsl': [210,100,56]}, //'DodgerBlue'
'20B2AA': {'rgb': [32,178,170], 'hsl': [177,70,41]}, //'LightseaGreen'
'228B22': {'rgb': [34,139,34], 'hsl': [120,61,34]}, //'ForestGreen'
'2E8B57': {'rgb': [46,139,87], 'hsl': [146,50,36]}, //'SeaGreen'
'2F4F4F': {'rgb': [47,79,79], 'hsl': [180,25,25]}, //'DarkSlateGray,DarkSlateGrey'
'32CD32': {'rgb': [50,205,50], 'hsl': [120,61,50]}, //'LimeGreen'
'3CB371': {'rgb': [60,179,113], 'hsl': [147,50,47]}, //'MediumseaGreen'
'40E0D0': {'rgb': [64,224,208], 'hsl': [174,72,56]}, //'Turquoise'
'4169E1': {'rgb': [65,105,225], 'hsl': [225,73,57]}, //'RoyalBlue'
'4682B4': {'rgb': [70,130,180], 'hsl': [207,44,49]}, //'SteelBlue'
'483D8B': {'rgb': [72,61,139], 'hsl': [248,39,39]}, //'DarkSlateBlue'
'48D1CC': {'rgb': [72,209,204], 'hsl': [178,60,55]}, //'Mediumturquoise'
'4B0082': {'rgb': [75,0,130], 'hsl': [275,100,25]}, //'Indigo'
'556B2F': {'rgb': [85,107,47], 'hsl': [82,39,30]}, //'DarkOliveGreen'
'5F9EA0': {'rgb': [95,158,160], 'hsl': [182,25,50]}, //'CadetBlue'
'663399': {'rgb': [102,51,153], 'hsl': [270,50,40]}, //'Rebeccapurple'
'6495ED': {'rgb': [100,149,237], 'hsl': [219,79,66]}, //'CornflowerBlue'
'66CDAA': {'rgb': [102,205,170], 'hsl': [160,51,60]}, //'Mediumaquamarine'
'696969': {'rgb': [105,105,105], 'hsl': [0,0,41]}, //'DimGray,DimGrey'
'6A5ACD': {'rgb': [106,90,205], 'hsl': [248,53,58]}, //'SlateBlue'
'6B8E23': {'rgb': [107,142,35], 'hsl': [80,60,35]}, //'Olivedrab'
'708090': {'rgb': [112,128,144], 'hsl': [210,13,50]}, //'SlateGray,SlateGrey'
'778899': {'rgb': [119,136,153], 'hsl': [210,14,53]}, //'LightSlateGray,LightSlateGrey'
'7B68EE': {'rgb': [123,104,238], 'hsl': [249,80,67]}, //'MediumSlateBlue'
'7CFC00': {'rgb': [124,252,0], 'hsl': [90,100,49]}, //'LawnGreen'
'7FFF00': {'rgb': [127,255,0], 'hsl': [90,100,50]}, //'Chartreuse'
'7FFFD4': {'rgb': [127,255,212], 'hsl': [160,100,75]}, //'Aquamarine'
'800000': {'rgb': [128,0,0], 'hsl': [0,100,25]}, //'Maroon'
'800080': {'rgb': [128,0,128], 'hsl': [300,100,25]}, //'Purple'
'808000': {'rgb': [128,128,0], 'hsl': [60,100,25]}, //'Olive'
'808080': {'rgb': [128,128,128], 'hsl': [0,0,50]}, //'Gray,Grey'
'87CEEB': {'rgb': [135,206,235], 'hsl': [197,71,73]}, //'SkyBlue'
'87CEFA': {'rgb': [135,206,250], 'hsl': [203,92,75]}, //'LightSkyBlue'
'8A2BE2': {'rgb': [138,43,226], 'hsl': [271,76,53]}, //'BlueViolet'
'8B0000': {'rgb': [139,0,0], 'hsl': [0,100,27]}, //'DarkRed'
'8B008B': {'rgb': [139,0,139], 'hsl': [300,100,27]}, //'DarkMagenta'
'8B4513': {'rgb': [139,69,19], 'hsl': [25,76,31]}, //'Saddlebrown'
'8FBC8F': {'rgb': [143,188,143], 'hsl': [120,25,65]}, //'DarkSeaGreen'
'90EE90': {'rgb': [144,238,144], 'hsl': [120,73,75]}, //'LightGreen'
'9370D8': {'rgb': [147,112,216], 'hsl': [260,57,64]}, //'Mediumpurple'
'9400D3': {'rgb': [148,0,211], 'hsl': [282,100,41]}, //'DarkViolet'
'98FB98': {'rgb': [152,251,152], 'hsl': [120,93,79]}, //'PaleGreen'
'9932CC': {'rgb': [153,50,204], 'hsl': [280,61,50]}, //'DarkOrchid'
'9ACD32': {'rgb': [154,205,50], 'hsl': [80,61,50]}, //'YellowGreen'
'A0522D': {'rgb': [160,82,45], 'hsl': [19,56,40]}, //'Sienna'
'A52A2A': {'rgb': [165,42,42], 'hsl': [0,59,41]}, //'Brown'
'A9A9A9': {'rgb': [169,169,169], 'hsl': [0,0,66]}, //'DarkGray,DarkGrey'
'ADD8E6': {'rgb': [173,216,230], 'hsl': [195,53,79]}, //'LightBlue'
'ADFF2F': {'rgb': [173,255,47], 'hsl': [84,100,59]}, //'GreenYellow'
'AFEEEE': {'rgb': [175,238,238], 'hsl': [180,65,81]}, //'Paleturquoise'
'B0C4DE': {'rgb': [176,196,222], 'hsl': [214,41,78]}, //'LightSteelBlue'
'B0E0E6': {'rgb': [176,224,230], 'hsl': [187,52,80]}, //'PowderBlue'
'B22222': {'rgb': [178,34,34], 'hsl': [0,68,42]}, //'Firebrick'
'B8860B': {'rgb': [184,134,11], 'hsl': [43,89,38]}, //'DarkGoldenrod'
'BA55D3': {'rgb': [186,85,211], 'hsl': [288,59,58]}, //'Mediumorchid'
'BC8F8F': {'rgb': [188,143,143], 'hsl': [0,25,65]}, //'Rosybrown'
'BDB76B': {'rgb': [189,183,107], 'hsl': [56,38,58]}, //'DarkKhaki'
'C0C0C0': {'rgb': [192,192,192], 'hsl': [0,0,75]}, //'Silver'
'C71585': {'rgb': [199,21,133], 'hsl': [322,81,43]}, //'MediumvioletRed'
'CD5C5C': {'rgb': [205,92,92], 'hsl': [0,53,58]}, //'IndianRed'
'CD853F': {'rgb': [205,133,63], 'hsl': [30,59,53]}, //'Peru'
'D2691E': {'rgb': [210,105,30], 'hsl': [25,75,47]}, //'Chocolate'
'D2B48C': {'rgb': [210,180,140], 'hsl': [34,44,69]}, //'Tan'
'D3D3D3': {'rgb': [211,211,211], 'hsl': [0,0,83]}, //'LightGray,LightGrey'
'D87093': {'rgb': [216,112,147], 'hsl': [340,57,64]}, //'PalevioletRed'
'D8BFD8': {'rgb': [216,191,216], 'hsl': [300,24,80]}, //'Thistle'
'DA70D6': {'rgb': [218,112,214], 'hsl': [302,59,65]}, //'Orchid'
'DAA520': {'rgb': [218,165,32], 'hsl': [43,74,49]}, //'Goldenrod'
'DC143C': {'rgb': [220,20,60], 'hsl': [348,83,47]}, //'Crimson'
'DCDCDC': {'rgb': [220,220,220], 'hsl': [0,0,86]}, //'Gainsboro'
'DDA0DD': {'rgb': [221,160,221], 'hsl': [300,47,75]}, //'Plum'
'DEB887': {'rgb': [222,184,135], 'hsl': [34,57,70]}, //'Burlywood'
'E0FFFF': {'rgb': [224,255,255], 'hsl': [180,100,94]}, //'LightCyan'
'E6E6FA': {'rgb': [230,230,250], 'hsl': [240,67,94]}, //'Lavender'
'E9967A': {'rgb': [233,150,122], 'hsl': [15,72,70]}, //'DarkSalmon'
'EE82EE': {'rgb': [238,130,238], 'hsl': [300,76,72]}, //'Violet'
'EEE8AA': {'rgb': [238,232,170], 'hsl': [55,67,80]}, //'Palegoldenrod'
'F08080': {'rgb': [240,128,128], 'hsl': [0,79,72]}, //'LightCoral'
'F0E68C': {'rgb': [240,230,140], 'hsl': [54,77,75]}, //'Khaki'
'F0F8FF': {'rgb': [240,248,255], 'hsl': [208,100,97]}, //'AliceBlue'
'F0FFF0': {'rgb': [240,255,240], 'hsl': [120,100,97]}, //'Honeydew'
'F0FFFF': {'rgb': [240,255,255], 'hsl': [180,100,97]}, //'Azure'
'F4A460': {'rgb': [244,164,96], 'hsl': [28,87,67]}, //'Sandybrown'
'F5DEB3': {'rgb': [245,222,179], 'hsl': [39,77,83]}, //'Wheat'
'F5F5F5': {'rgb': [245,245,245], 'hsl': [0,0,96]}, //'Whitesmoke'
'F5F5DC': {'rgb': [245,245,220], 'hsl': [60,56,91]}, //'Beige'
'F5FFFA': {'rgb': [245,255,250], 'hsl': [150,100,98]}, //'Mintcream'
'F8F8FF': {'rgb': [248,248,255], 'hsl': [240,100,99]}, //'GhostWhite'
'FAEBD7': {'rgb': [250,235,215], 'hsl': [34,78,91]}, //'AntiqueWhite'
'FA8072': {'rgb': [250,128,114], 'hsl': [6,93,71]}, //'Salmon'
'FAF0E6': {'rgb': [250,240,230], 'hsl': [30,65,94]}, //'Linen'
'FAFAD2': {'rgb': [250,250,210], 'hsl': [60,80,90]}, //'LightGoldenrodYellow'
'FDF5E6': {'rgb': [253,245,230], 'hsl': [39,85,95]}, //'Oldlace'
'FF0000': {'rgb': [255,0,0], 'hsl': [0,100,50]}, //'Red'
'FF00FF': {'rgb': [255,0,255], 'hsl': [300,100,50]}, //'Fuchsia.Magenta'
'FF1493': {'rgb': [255,20,147], 'hsl': [328,100,54]}, //'DeepPink'
'FF4500': {'rgb': [255,69,0], 'hsl': [16,100,50]}, //'OrangeRed'
'FF6347': {'rgb': [255,99,71], 'hsl': [9,100,64]}, //'Tomato'
'FF69B4': {'rgb': [255,105,180], 'hsl': [330,100,71]}, //'HotPink'
'FF7F50': {'rgb': [255,127,80], 'hsl': [16,100,66]}, //'Coral'
'FF8C00': {'rgb': [255,140,0], 'hsl': [33,100,50]}, //'DarkOrange'
'FFA07A': {'rgb': [255,160,122], 'hsl': [17,100,74]}, //'LightSalmon'
'FFA500': {'rgb': [255,165,0], 'hsl': [39,100,50]}, //'Orange'
'FFB6C1': {'rgb': [255,182,193], 'hsl': [351,100,86]}, //'LightPink'
'FFC0CB': {'rgb': [255,192,203], 'hsl': [350,100,88]}, //'Pink'
'FFD700': {'rgb': [255,215,0], 'hsl': [51,100,50]}, //'Gold'
'FFDAB9': {'rgb': [255,218,185], 'hsl': [28,100,86]}, //'Peachpuff'
'FFDEAD': {'rgb': [255,222,173], 'hsl': [36,100,84]}, //'NavajoWhite'
'FFE4B5': {'rgb': [255,228,181], 'hsl': [38,100,85]}, //'Moccasin'
'FFE4C4': {'rgb': [255,228,196], 'hsl': [33,100,88]}, //'Bisque'
'FFE4E1': {'rgb': [255,228,225], 'hsl': [6,100,94]}, //'Mistyrose'
'FFEBCD': {'rgb': [255,235,205], 'hsl': [36,100,90]}, //'BlanchedAlmond'
'FFEFD5': {'rgb': [255,239,213], 'hsl': [37,100,92]}, //'Papayawhip'
'FFF0F5': {'rgb': [255,240,245], 'hsl': [340,100,97]}, //'LavenderBlush'
'FFF5EE': {'rgb': [255,245,238], 'hsl': [25,100,97]}, //'Seashell'
'FFF8DC': {'rgb': [255,248,220], 'hsl': [48,100,93]}, //'Cornsilk'
'FFFACD': {'rgb': [255,250,205], 'hsl': [54,100,90]}, //'LemonChiffon'
'FFFAF0': {'rgb': [255,250,240], 'hsl': [40,100,97]}, //'FloralWhite'
'FFFAFA': {'rgb': [255,250,250], 'hsl': [0,100,99]}, //'Snow'
'FFFF00': {'rgb': [255,255,0], 'hsl': [60,100,50]}, //'Yellow'
'FFFFE0': {'rgb': [255,255,224], 'hsl': [60,100,94]}, //'LightYellow'
'FFFFF0': {'rgb': [255,255,240], 'hsl': [60,100,97]}, //'Ivory'
'FFFFFF': {'rgb': [255,255,255], 'hsl': [0,0,100]} //'White'     
};

Object.freeze(colour_names);

const cm = ', ';
const pc = '%, ';
const pp = '%)';
const sr = 'rgb(';
const sh = 'hsl(';

const xmlns = {
    'svg':'http://www.w3.org/2000/svg',
    'htm':'http://www.w3.org/1999/xhtml'
}
const current_color = {
    'hsl':[0,100,50],
    'rgb':[255,0,0]
};

const el_NameSelect = document.getElementById('NameSelect');
const el_Swatch = document.getElementById('Swatch');
const els_textboxes = {
    'lp':[['hue','red'],['sat','grn'],['lit','blu']],
    'hex':{
        'red':document.getElementById('TXT_HEX_Red'),
        'grn':document.getElementById('TXT_HEX_Grn'),
        'blu':document.getElementById('TXT_HEX_Blu')
    },
    'rgb':{
        'red':document.getElementById('TXT_RGB_Red'),
        'grn':document.getElementById('TXT_RGB_Grn'),
        'blu':document.getElementById('TXT_RGB_Blu')
    },
    'hsl':{
        'hue':document.getElementById('TXT_HSL_Hue'),
        'sat':document.getElementById('TXT_HSL_Sat'),
        'lit':document.getElementById('TXT_HSL_Lit')
    }
}

const els_gauges = {
    'hsl':{
        'point':{
            'hue':document.getElementById('Hue-Gauge-Pointer'),
            'sat':document.getElementById('Sat-Gauge-Pointer'),
            'lit':document.getElementById('Lit-Gauge-Pointer')
        },
        'text':{
            'hue':document.getElementById('Hue-Display-Text'),
            'sat':document.getElementById('Sat-Display-Text'),
            'lit':document.getElementById('Lit-Display-Text')
        }
    },
    'rgb':{
        'point':{
            'red':document.getElementById('Red-Gauge-Pointer'),
            'grn':document.getElementById('Grn-Gauge-Pointer'),
            'blu':document.getElementById('Blu-Gauge-Pointer')
        },
        'text':{
            'red':document.getElementById('Red-Display-Text'),
            'grn':document.getElementById('Grn-Display-Text'),
            'blu':document.getElementById('Blu-Display-Text')
        }
    }
}




var $test_num = 0;

function rgb_2_hex(farr_rgb){
    return (
        farr_rgb[0].toString(16).padStart(2,'0') + 
        farr_rgb[1].toString(16).padStart(2,'0') + 
        farr_rgb[2].toString(16).padStart(2,'0')
    ).toUpperCase();
}

function rgb_2_hsl(farr_rgb){
    /// RGB from 0 - 255 to 0 - 1
    let r = (farr_rgb)[0] / 255;
    let g = (farr_rgb)[1] / 255;
    let b = (farr_rgb)[2] / 255;
    
    /// Get Maximum and Minimum values
    let cmax = Math.max(r, g, b);
    let cmin = Math.min(r, g, b);
    let h, s;
    let l = (cmax + cmin)/2;
    if (l === 0 || l === 1 || cmax === cmin){
        h = 0;
        s = 0;
    } else {
        //  Get Hue
        let delta = cmax - cmin;
        switch (cmax){
            case r:
                h = ((g - b) / delta) % 6;
                break;
            case g:
                h = ((b - r) / delta) + 2;
                break;
            case b:
                h = ((r - g) / delta) + 4;
                break;
        }
        h = Math.round(h * 60);
        if(h < 0){h+=360;}
        s = Math.round((delta / (1 - Math.abs(2 * l - 1))) * 100);
    }
    l = Math.round(l*100);
    
    return [h,s,l];
}
function hsl_2_rgb(farr_hsl) {
  let h = farr_hsl[0];
  let s = farr_hsl[1] / 100;
  let l = farr_hsl[2] / 100;

  let c = (1 - Math.abs(2 * l - 1)) * s;
  let x = c * (1 - Math.abs((h / 60) % 2 - 1));
  let m = l - c / 2;
  let r = 0, g = 0, b = 0;

  if (0 <= h && h < 60) {
    r = c;
    g = x;
    b = 0;
  } else if (60 <= h && h < 120) {
    r = x;
    g = c;
    b = 0;
  } else if (120 <= h && h < 180) {
    r = 0;
    g = c;
    b = x;
  } else if (180 <= h && h < 240) {
    r = 0;
    g = x;
    b = c;
  } else if (240 <= h && h < 300) {
    r = x;
    g = 0;
    b = c;
  } else if (300 <= h && h < 360) {
    r = c;
    g = 0;
    b = x;
  }
  r = Math.round((r + m) * 255);
  g = Math.round((g + m) * 255);
  b = Math.round((b + m) * 255);

  return [r, g, b];
}

function SetRGBGauges(farr_rgb, display){
    const int_gaugeheight = 520;
    let r = farr_rgb[0]
    let g = farr_rgb[1]
    let b = farr_rgb[2]
    
    
    display.point.red.setAttribute('y',(int_gaugeheight - Math.round(r / 255 * int_gaugeheight)));
    display.text.red.textContent = r.toString();
    
    display.point.grn.setAttribute('y',(int_gaugeheight - Math.round(g / 255 * int_gaugeheight)));
    display.text.grn.textContent = g.toString();
    
    display.point.blu.setAttribute('y',(int_gaugeheight - Math.round(b / 255 * int_gaugeheight)));
    display.text.blu.textContent = b.toString();
}
function SetHSLGauges(farr_hsl, display){
    let h = farr_hsl[0];
    let s = farr_hsl[1];
    let l = farr_hsl[2];
    
    const int_gaugeheight = 210;
    display.point.hue.setAttribute('transform','rotate('+h+')');
    display.text.hue.textContent = h.toString() + 'u00B0';
    
    
    display.point.sat.setAttribute('y',(int_gaugeheight - Math.round(s / 100 * int_gaugeheight)));
    display.text.sat.textContent = s.toString() + '%';
    
    display.point.lit.setAttribute('y',(int_gaugeheight - Math.round(l / 100 * int_gaugeheight)));
    display.text.lit.textContent = l.toString() + '%';
}

function SetTXTControls(farr_hsl, farr_rgb, fels_txtboxes){
    let txt_hex = rgb_2_hex(farr_rgb);
    for(let int_lp = 0; int_lp < els_textboxes.lp.length; int_lp++){
        fels_txtboxes.hex[fels_txtboxes.lp[int_lp][1]].value = txt_hex.substr((int_lp*2),2);
        fels_txtboxes.rgb[fels_txtboxes.lp[int_lp][1]].value = farr_rgb[int_lp].toString();
        fels_txtboxes.hsl[fels_txtboxes.lp[int_lp][0]].value = farr_hsl[int_lp].toString();
    }
}


function FindNameRGB(fob_names, farr_rgb){
    //farr_rgb is an array of red, green, and blue values.  fob_names is my object with names and HSL values
    let hex = rgb_2_hex(farr_rgb);
    
    if(fob_names.hasOwnProperty(hex)){
        return hex
    } else {
        return 'NONAME';
    }
}

function FindNameHSL(fob_names, farr_hsl){
    let key = 'NONAME' // NONAME means 'No Name'
    for(key in fob_names){
        if(
            farr_hsl[0] === txt_nameHSL[0] &&
            farr_hsl[1] === txt_nameHSL[1] &&
            farr_hsl[2] === txt_nameHSL[2]
        ){break;}
    }
    return key;
}

//  HSL Gauges

function HSLChange(data){return function(){
    let arindx = data.arindx;
    let change = data.change;
    let curcol = data.curcol;
    let swatch = data.swatch;
    let txtbxs = data.txtbxs;
    let gauges = data.gauges;
    let cnames = data.cnames;
    let cslect = data.cslect;
    
    curcol.hsl[arindx] += change;
    if (curcol.hsl[0] < 0){curcol.hsl[0]+=360;}
    if (curcol.hsl[0] >= 360){curcol.hsl[0]-=360;}
    
    if (curcol.hsl[1] < 0){curcol.hsl[1]= 0;}
    if (curcol.hsl[1] > 100){curcol.hsl[1] = 100;}
    
    if (curcol.hsl[2] < 0){curcol.hsl[2]= 0;}
    if (curcol.hsl[2] > 100){curcol.hsl[2] = 100;}
    
    
    swatch.style.background = sh + curcol.hsl[0] + cm + curcol.hsl[1] + pc + curcol.hsl[2] + pp;
    let nmcode = FindNameHSL(cnames, curcol.hsl);
    
    if(nmcode == 'NONAME'){
        curcol.rgb = hsl_2_rgb(curcol.hsl);
    } else {
        curcol.rgb = cnames[nmcode].rgb;
    }
    SetTXTControls(curcol.hsl, curcol.rgb, txtbxs);
    cslect.value = nmcode;
    
    SetHSLGauges(curcol.hsl, gauges.hsl);
    SetRGBGauges(curcol.rgb, gauges.rgb);
}}

function HSLSet(data){return function(){
    let arindx = data.arindx;
    let setval = data.setval;
    let curcol = data.curcol;
    let swatch = data.swatch;
    let txtbxs = data.txtbxs;
    let gauges = data.gauges;
    let cnames = data.cnames;
    let cslect = data.cslect;

    
    curcol.hsl[arindx] = setval;
    swatch.style.background = sh + curcol.hsl[0] + cm + curcol.hsl[1] + pc + curcol.hsl[2] + pp;
    
    let nmcode = FindNameHSL(cnames, curcol.hsl);
    if(nmcode == 'NONAME'){
        curcol.rgb = hsl_2_rgb(curcol.hsl);
    } else {
        curcol.rgb = cnames[nmcode].rgb;
    }
    SetTXTControls(curcol.hsl, curcol.rgb, txtbxs);
    cslect.value = nmcode;
    
    SetHSLGauges(curcol.hsl, gauges.hsl);
    SetRGBGauges(curcol.rgb, gauges.rgb);
}}

//  Hue Gauge
const hue_vals = document.getElementById('Hue-Gauge-Swatches').getElementsByTagNameNS(xmlns.svg,'circle');
const hue_vals_total = hue_vals.length;

for(let hue_vals_num = 0; hue_vals_num < hue_vals_total; hue_vals_num++){
    hue_vals[hue_vals_num].onclick = HSLSet({
        arindx: 0,
        setval: Number(hue_vals[hue_vals_num].getAttribute('fill').substr(4,3)), 
        curcol: current_color, 
        swatch: el_Swatch, 
        txtbxs: els_textboxes, 
        gauges: els_gauges, 
        cnames: colour_names,
        cslect: el_NameSelect
    });
}



document.getElementById('Hue-mn-10').onclick=HSLChange({
    arindx:0,
    change:-10,
    curcol:current_color,
    swatch:el_Swatch,
    txtbxs:els_textboxes,
    gauges:els_gauges,
    cnames:colour_names,
    cslect:el_NameSelect
})
//-10);
document.getElementById('Hue-mn-01').onclick=HSLChange({
    arindx:0,
    change:-1,
    curcol:current_color,
    swatch:el_Swatch,
    txtbxs:els_textboxes,
    gauges:els_gauges,
    cnames:colour_names,
    cslect:el_NameSelect
});
document.getElementById('Hue-pl-01').onclick=HSLChange({
    arindx:0,
    change:1,
    curcol:current_color,
    swatch:el_Swatch,
    txtbxs:els_textboxes,
    gauges:els_gauges,
    cnames:colour_names,
    cslect:el_NameSelect
});
document.getElementById('Hue-pl-10').onclick=HSLChange({
    arindx:0,
    change:10,
    curcol:current_color,
    swatch:el_Swatch,
    txtbxs:els_textboxes,
    gauges:els_gauges,
    cnames:colour_names,
    cslect:el_NameSelect
});

//  Saturation Gauge

const sat_vals = document.getElementById('Sat-Gauge-Values').getElementsByTagNameNS(xmlns.svg,'rect');
const sat_vals_total = sat_vals.length;

for(let sat_vals_num = 0; sat_vals_num < sat_vals_total; sat_vals_num++){
    sat_vals[sat_vals_num].onclick = HSLSet({
        arindx: 1,
        setval: Number(sat_vals[sat_vals_num].getAttribute('fill').substr(8,3)), 
        curcol: current_color, 
        swatch: el_Swatch, 
        txtbxs: els_textboxes, 
        gauges: els_gauges, 
        cnames: colour_names,
        cslect: el_NameSelect
    });
}

document.getElementById('Sat-mn-5').onclick=HSLChange({
    arindx:1,
    change:-5,
    curcol:current_color,
    swatch:el_Swatch,
    txtbxs:els_textboxes,
    gauges:els_gauges,
    cnames:colour_names,
    cslect:el_NameSelect
});
document.getElementById('Sat-mn-1').onclick=HSLChange({
    arindx:1,
    change:-1,
    curcol:current_color,
    swatch:el_Swatch,
    txtbxs:els_textboxes,
    gauges:els_gauges,
    cnames:colour_names,
    cslect:el_NameSelect
});
document.getElementById('Sat-pl-1').onclick=HSLChange({
    arindx:1,
    change:1,
    curcol:current_color,
    swatch:el_Swatch,
    txtbxs:els_textboxes,
    gauges:els_gauges,
    cnames:colour_names,
    cslect:el_NameSelect
});
document.getElementById('Sat-pl-5').onclick=HSLChange({
    arindx:1,
    change:5,
    curcol:current_color,
    swatch:el_Swatch,
    txtbxs:els_textboxes,
    gauges:els_gauges,
    cnames:colour_names,
    cslect:el_NameSelect
});


//  Lightness Gauge

const lit_vals = document.getElementById('Lit-Gauge-Values').getElementsByTagNameNS(xmlns.svg,'rect');
const lit_vals_total = lit_vals.length;

for(let lit_vals_num = 0; lit_vals_num < lit_vals_total; lit_vals_num++){
    lit_vals[lit_vals_num].onclick = HSLSet({
        arindx: 2,
        setval: Number(lit_vals[lit_vals_num].getAttribute('fill').substr(9,3)), 
        curcol: current_color, 
        swatch: el_Swatch, 
        txtbxs: els_textboxes, 
        gauges: els_gauges, 
        cnames: colour_names,
        cslect: el_NameSelect
    });
}
document.getElementById('Lit-mn-5').onclick=HSLChange({
    arindx:2,
    change:-5,
    curcol:current_color,
    swatch:el_Swatch,
    txtbxs:els_textboxes,
    gauges:els_gauges,
    cnames:colour_names,
    cslect:el_NameSelect
});
document.getElementById('Lit-mn-1').onclick=HSLChange({
    arindx:2,
    change:-1,
    curcol:current_color,
    swatch:el_Swatch,
    txtbxs:els_textboxes,
    gauges:els_gauges,
    cnames:colour_names,
    cslect:el_NameSelect
});
document.getElementById('Lit-pl-1').onclick=HSLChange({
    arindx:2,
    change:1,
    curcol:current_color,
    swatch:el_Swatch,
    txtbxs:els_textboxes,
    gauges:els_gauges,
    cnames:colour_names,
    cslect:el_NameSelect
});
document.getElementById('Lit-pl-5').onclick=HSLChange({
    arindx:2,
    change:5,
    curcol:current_color,
    swatch:el_Swatch,
    txtbxs:els_textboxes,
    gauges:els_gauges,
    cnames:colour_names,
    cslect:el_NameSelect
});



//  RGB Gauges
function RGBChange(data){return function(){
    let arindx = data.arindx;
    let change = data.change;
    let curcol = data.curcol;
    let swatch = data.swatch;
    let txtbxs = data.txtbxs;
    let gauges = data.gauges;
    let cnames = data.cnames;
    let cslect = data.cslect;

    curcol.rgb[arindx] += change;
    if (curcol.rgb[arindx] < 0){curcol.rgb[arindx]=0;}
    if (curcol.rgb[arindx] > 255){curcol.rgb[arindx]=255;}
    
    swatch.style.background = sr + curcol.rgb[0] + cm + curcol.rgb[1] + cm + curcol.rgb[2] + ')';
    
    let nmcode = FindNameRGB(cnames, curcol.rgb);
    if(nmcode == 'NONAME'){
        curcol.hsl = rgb_2_hsl(curcol.rgb);
    } else {
        curcol.hsl = cnames[nmcode].hsl;
    }
    SetTXTControls(curcol.hsl, curcol.rgb, txtbxs);
    cslect.value = nmcode;
    
    SetHSLGauges(curcol.hsl, gauges.hsl);
    SetRGBGauges(curcol.rgb, gauges.rgb);
}}

function RGBSet(data){return function(){
    let arindx = data.arindx;
    let setval = data.setval;
    let curcol = data.curcol;
    let swatch = data.swatch;
    let txtbxs = data.txtbxs;
    let gauges = data.gauges;
    let cnames = data.cnames;
    let cslect = data.cslect;
    
    curcol.rgb[arindx] = setval;
    
    swatch.style.background = sr + curcol.rgb[0] + cm + curcol.rgb[1] + cm + curcol.rgb[2] + ')';
    
    let nmcode = FindNameRGB(cnames, curcol.rgb);
    if(nmcode == 'NONAME'){
        curcol.hsl = rgb_2_hsl(curcol.rgb);
    } else {
        curcol.hsl = cnames[nmcode].hsl;
    }
    SetTXTControls(curcol.hsl, curcol.rgb, txtbxs);
    cslect.value = nmcode;
    
    SetHSLGauges(curcol.hsl, gauges.hsl);
    SetRGBGauges(curcol.rgb, gauges.rgb);

};}

//  Red Gauge
const red_vals = document.getElementById('Red-Gauge-Values').getElementsByTagNameNS(xmlns.svg,'rect');
const red_vals_total = red_vals.length;

for(let red_vals_num = 0; red_vals_num < red_vals_total; red_vals_num++){
    red_vals[red_vals_num].onclick = RGBSet({
        arindx: 0, 
        setval: Number(red_vals[red_vals_num].getAttribute('fill').match(/d+/g)[0]),
        curcol: current_color, 
        swatch: el_Swatch, 
        txtbxs: els_textboxes, 
        gauges: els_gauges,
        cnames: colour_names,
        cslect: el_NameSelect
    });
}

document.getElementById('Red-mn-5').onclick=RGBChange({
    arindx:0,
    change:-5,
    curcol:current_color,
    swatch:el_Swatch,
    txtbxs:els_textboxes,
    gauges:els_gauges,
    cnames:colour_names,
    cslect:el_NameSelect
});
document.getElementById('Red-mn-1').onclick=RGBChange({
    arindx:0,
    change:-1,
    curcol:current_color,
    swatch:el_Swatch,
    txtbxs:els_textboxes,
    gauges:els_gauges,
    cnames:colour_names,
    cslect:el_NameSelect
});
document.getElementById('Red-pl-1').onclick=RGBChange({
    arindx:0,
    change:1,
    curcol:current_color,
    swatch:el_Swatch,
    txtbxs:els_textboxes,
    gauges:els_gauges,
    cnames:colour_names,
    cslect:el_NameSelect
});
document.getElementById('Red-pl-5').onclick=RGBChange({
    arindx:0,
    change:5,
    curcol:current_color,
    swatch:el_Swatch,
    txtbxs:els_textboxes,
    gauges:els_gauges,
    cnames:colour_names,
    cslect:el_NameSelect
});


//  Green Gauge
const grn_vals = document.getElementById('Grn-Gauge-Values').getElementsByTagNameNS(xmlns.svg,'rect');
const grn_vals_total = grn_vals.length;

for(let grn_vals_num = 0; grn_vals_num < grn_vals_total; grn_vals_num++){
    grn_vals[grn_vals_num].onclick = RGBSet({
        arindx: 1, 
        setval: Number(grn_vals[grn_vals_num].getAttribute('fill').match(/d+/g)[1]),
        curcol: current_color, 
        swatch: el_Swatch, 
        txtbxs: els_textboxes, 
        gauges: els_gauges,
        cnames: colour_names,
        cslect: el_NameSelect
    });
}

document.getElementById('Grn-mn-5').onclick=RGBChange({
    arindx:1,
    change:-5,
    curcol:current_color,
    swatch:el_Swatch,
    txtbxs:els_textboxes,
    gauges:els_gauges,
    cnames:colour_names,
    cslect:el_NameSelect
});
document.getElementById('Grn-mn-1').onclick=RGBChange({
    arindx:1,
    change:-1,
    curcol:current_color,
    swatch:el_Swatch,
    txtbxs:els_textboxes,
    gauges:els_gauges,
    cnames:colour_names,
    cslect:el_NameSelect
});
document.getElementById('Grn-pl-1').onclick=RGBChange({
    arindx:1,
    change:1,
    curcol:current_color,
    swatch:el_Swatch,
    txtbxs:els_textboxes,
    gauges:els_gauges,
    cnames:colour_names,
    cslect:el_NameSelect
});
document.getElementById('Grn-pl-5').onclick=RGBChange({
    arindx:1,
    change:5,
    curcol:current_color,
    swatch:el_Swatch,
    txtbxs:els_textboxes,
    gauges:els_gauges,
    cnames:colour_names,
    cslect:el_NameSelect
});


//  ====  //  Blue Gauge  //  ====  //
const blu_vals = document.getElementById('Blu-Gauge-Values').getElementsByTagNameNS(xmlns.svg,'rect');
const blu_vals_total = blu_vals.length;

for(let blu_vals_num = 0; blu_vals_num < blu_vals_total; blu_vals_num++){
    blu_vals[blu_vals_num].onclick = RGBSet({
        arindx: 2, 
        setval: Number(blu_vals[blu_vals_num].getAttribute('fill').match(/d+/g)[2]),
        curcol: current_color, 
        swatch: el_Swatch, 
        txtbxs: els_textboxes, 
        gauges: els_gauges,
        cnames: colour_names,
        cslect: el_NameSelect
    });
}

document.getElementById('Blu-mn-5').onclick=RGBChange({
    arindx:2,
    change:-5,
    curcol:current_color,
    swatch:el_Swatch,
    txtbxs:els_textboxes,
    gauges:els_gauges,
    cnames:colour_names,
    cslect:el_NameSelect
});
document.getElementById('Blu-mn-1').onclick=RGBChange({
    arindx:2,
    change:-1,
    curcol:current_color,
    swatch:el_Swatch,
    txtbxs:els_textboxes,
    gauges:els_gauges,
    cnames:colour_names,
    cslect:el_NameSelect
});
document.getElementById('Blu-pl-1').onclick=RGBChange({
    arindx:2,
    change:1,
    curcol:current_color,
    swatch:el_Swatch,
    txtbxs:els_textboxes,
    gauges:els_gauges,
    cnames:colour_names,
    cslect:el_NameSelect
});
document.getElementById('Blu-pl-5').onclick=RGBChange({
    arindx:2,
    change:5,
    curcol:current_color,
    swatch:el_Swatch,
    txtbxs:els_textboxes,
    gauges:els_gauges,
    cnames:colour_names,
    cslect:el_NameSelect
});







document.getElementById('CheckCurrColo').onclick = function(){
    alert(
        'hsl(' + current_color.hsl[0] + ', ' + current_color.hsl[1] + '%, ' + current_color.hsl[2] + '%)rn' +
        'rgb(' + current_color.rgb[0] + ', ' + current_color.rgb[1] + ', ' + current_color.rgb[2] + ')'
    );
}
//CheckNameCode

//  Text Inputs
el_NameSelect.onchange = function(){
    let txt_hexcode = el_NameSelect.value;
    el_Swatch.style.background='#'+txt_hexcode;
    current_color.hsl = colour_names[txt_hexcode].hsl;
    current_color.rgb = colour_names[txt_hexcode].rgb;
    SetTXTControls(colour_names[txt_hexcode].hsl, colour_names[txt_hexcode].rgb, els_textboxes)
  SetRGBGauges(colour_names[txt_hexcode].rgb, els_gauges.rgb);
  SetHSLGauges(colour_names[txt_hexcode].hsl, els_gauges.hsl);
}