Skip to main content
Notice removed Improve details by Arnav Borborah
Bounty Ended with Sᴀᴍ Onᴇᴌᴀ's answer chosen by Arnav Borborah
update formatting, add dom tag
Source Link

I have recently started learning JavascriptJavaScript (A great language) and decided to start a small project which consists of a website with two inputs, one for hexadecimal input, and one for RGB input. When the user enters a valid color in either of the two inputs, then the background color of the website changes and the other input is updated with the same color in its corresponding format. Here is my code (CSS removed, as it doesn't pertain to the logic):

  1. Does my code use good JS/ES6 programming practices and proper coding style? (I tried to follow the airbnb style guide for this)
  2. Is my code well structured-structured and well written-written?
  3. Should I give the IIFE function in my JS a name, so that it can be tested using a framework like Mocha (Maybe if I wanted to extract these functions into a small plugin), or should this code be structured differently in order to make it more maintainable and testable? (I believe I currently cannot access these functions inside this anonymous function)

I have recently started learning Javascript (A great language) and decided to start a small project which consists of a website with two inputs, one for hexadecimal input, and one for RGB input. When the user enters a valid color in either of the two inputs, then the background color of the website changes and the other input is updated with the same color in its corresponding format. Here is my code (CSS removed as it doesn't pertain to the logic):

  1. Does my code use good JS/ES6 programming practices and proper coding style? (I tried to follow the airbnb style guide for this)
  2. Is my code well structured and well written?
  3. Should I give the IIFE function in my JS a name, so that it can be tested using a framework like Mocha (Maybe if I wanted to extract these functions into a small plugin), or should this code be structured differently in order to make it more maintainable and testable? (I believe I currently cannot access these functions inside this anonymous function)

I have recently started learning JavaScript (A great language) and decided to start a small project which consists of a website with two inputs, one for hexadecimal input, and one for RGB input. When the user enters a valid color in either of the two inputs, then the background color of the website changes and the other input is updated with the same color in its corresponding format. Here is my code (CSS removed, as it doesn't pertain to the logic):

  1. Does my code use good JS/ES6 programming practices and proper coding style? (I tried to follow the airbnb style guide for this)
  2. Is my code well-structured and well-written?
  3. Should I give the IIFE function in my JS a name, so that it can be tested using a framework like Mocha (Maybe if I wanted to extract these functions into a small plugin), or should this code be structured differently in order to make it more maintainable and testable? (I believe I currently cannot access these functions inside this anonymous function)
Removed extra font
Source Link
(function() {
    "use strict";
    
    window.onload = function() {
        let initialColorChoices = [
            "#0c6",
            "#099",
            "#c0c",
            "#39f",
            "#fa0",
            "#affd1b",
            "#d53e78",
            "#e04857",
            "#0cca9a",
            "#e6e600"
        ];
        
        let randomColor = initialColorChoices[Math.floor(Math.random() * 10)];
        
        document.body.style.backgroundColor = randomColor;
        
        let hexInput = document.getElementById("hex");
        let rgbInput = document.getElementById("rgb");
        
        hexInput.value = randomColor;
        rgbInput.value = convertHexToRGB(randomColor);
        
        // I've heard of something called arrow functions, how could 
        // I use those here?
        hexInput.addEventListener("change", function() {
            if (isValidColor(this.value)) {
                rgbInput.value = convertHexToRGB(this.value);
                document.body.style.backgroundColor = this.value;
            }  
        });
        
        rgbInput.addEventListener("change", function() {
            if (isValidColor(this.value)) {
                hexInput.value = convertRGBToHex(this.value);
                document.body.style.backgroundColor = convertRGBToHex(this.value);
            } 
        });
    };
    
    function convertHexToRGB(hexString) {
        let rgbColorValues = [];
        
        if (!isValidColor(hexString)) {
            return "";
        }
        
        if (hexString.length == 4) {
            for (const character of hexString.slice(1)) { // Excluding the #
                rgbColorValues.push(parseInt(character + character, 16));
            }
        }
        else {
            for (let i = 1; i < 7; i += 2) { // Starting at 1 to exclude #
                rgbColorValues.push(parseInt(hexString[i] + hexString[i + 1], 16));
            }
        }
        
        return `rgb(${rgbColorValues[0]}, ${rgbColorValues[1]}, ${rgbColorValues[2]})`;
    }
    
    function convertRGBToHex(rgbString) {
        let hexString = "#";
        
        if (!isValidColor(rgbString))
        {
            return "";
        }
        
        let rgbColorValues = rgbString.replace(/(\s)|(rgb\()|(\))/g, '') // Isolate the RGB colors by removing spaces, rgb(, and )
            .split(",") // Convert to string array
            .map(Number); // Convert to number array
        
        for (const color of rgbColorValues) {
            let currentColorString = color.toString(16);
            
            if (currentColorString.length < 2) {
                hexString += "0";
            }
            
            hexString += currentColorString;
        }
        
        return hexString;
    }
    
    function isValidColor(colorString) {
        const hexRegex = /^(#[0-9A-F]{3})|(#[0-9A-F]{6})$/i;
        const rgbRegex = /^rgb\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}\s*\)$/;
        
        if (hexRegex.test(colorString)) {
            return true;
        }
        else if (rgbRegex.test(colorString)) {
            let rgbColorValues = colorString.replace(/(\s)|(rgb\()|(\))/g, '') // Isolate the RGB colors by removing spaces, rgb(, and )
                .split(",") // Convert to string array
                .map(Number); // Convert to number array
                        
            for (const color of rgbColorValues) {
                if (color < 0 || color > 255) {
                    return false;
                }
            }
            
            return true;
        }
        return false;
    }
}());
<!DOCTYPE html>
<html>
    <head>
        <title>Color Converter</title>
        
        <link href="https://fonts.googleapis.com/css?family=Raleway" rel="stylesheet"/>
        <link href="resources/css/index.css" rel="stylesheet"/>
    </head>
    <body>
        <div class="container">
            <input class="color-input" id="hex" type="text" placeholder="Hex"/>
            <h1 id="heading">Color Converter</h1>
            <input class="color-input" id="rgb" type="text" placeholder="RGB"/>
        </div>
        <script src="resources/js/index.js"></script>
    </body>
</html>
(function() {
    "use strict";
    
    window.onload = function() {
        let initialColorChoices = [
            "#0c6",
            "#099",
            "#c0c",
            "#39f",
            "#fa0",
            "#affd1b",
            "#d53e78",
            "#e04857",
            "#0cca9a",
            "#e6e600"
        ];
        
        let randomColor = initialColorChoices[Math.floor(Math.random() * 10)];
        
        document.body.style.backgroundColor = randomColor;
        
        let hexInput = document.getElementById("hex");
        let rgbInput = document.getElementById("rgb");
        
        hexInput.value = randomColor;
        rgbInput.value = convertHexToRGB(randomColor);
        
        // I've heard of something called arrow functions, how could 
        // I use those here?
        hexInput.addEventListener("change", function() {
            if (isValidColor(this.value)) {
                rgbInput.value = convertHexToRGB(this.value);
                document.body.style.backgroundColor = this.value;
            }  
        });
        
        rgbInput.addEventListener("change", function() {
            if (isValidColor(this.value)) {
                hexInput.value = convertRGBToHex(this.value);
                document.body.style.backgroundColor = convertRGBToHex(this.value);
            } 
        });
    };
    
    function convertHexToRGB(hexString) {
        let rgbColorValues = [];
        
        if (!isValidColor(hexString)) {
            return "";
        }
        
        if (hexString.length == 4) {
            for (const character of hexString.slice(1)) { // Excluding the #
                rgbColorValues.push(parseInt(character + character, 16));
            }
        }
        else {
            for (let i = 1; i < 7; i += 2) { // Starting at 1 to exclude #
                rgbColorValues.push(parseInt(hexString[i] + hexString[i + 1], 16));
            }
        }
        
        return `rgb(${rgbColorValues[0]}, ${rgbColorValues[1]}, ${rgbColorValues[2]})`;
    }
    
    function convertRGBToHex(rgbString) {
        let hexString = "#";
        
        if (!isValidColor(rgbString))
        {
            return "";
        }
        
        let rgbColorValues = rgbString.replace(/(\s)|(rgb\()|(\))/g, '') // Isolate the RGB colors by removing spaces, rgb(, and )
            .split(",") // Convert to string array
            .map(Number); // Convert to number array
        
        for (const color of rgbColorValues) {
            let currentColorString = color.toString(16);
            
            if (currentColorString.length < 2) {
                hexString += "0";
            }
            
            hexString += currentColorString;
        }
        
        return hexString;
    }
    
    function isValidColor(colorString) {
        const hexRegex = /^(#[0-9A-F]{3})|(#[0-9A-F]{6})$/i;
        const rgbRegex = /^rgb\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}\s*\)$/;
        
        if (hexRegex.test(colorString)) {
            return true;
        }
        else if (rgbRegex.test(colorString)) {
            let rgbColorValues = colorString.replace(/(\s)|(rgb\()|(\))/g, '') // Isolate the RGB colors by removing spaces, rgb(, and )
                .split(",") // Convert to string array
                .map(Number); // Convert to number array
                        
            for (const color of rgbColorValues) {
                if (color < 0 || color > 255) {
                    return false;
                }
            }
            
            return true;
        }
        return false;
    }
}());
<!DOCTYPE html>
<html>
    <head>
        <title>Color Converter</title>
        
        <link href="https://fonts.googleapis.com/css?family=Raleway" rel="stylesheet"/>
        <link href="resources/css/index.css" rel="stylesheet"/>
    </head>
    <body>
        <div class="container">
            <input class="color-input" id="hex" type="text" placeholder="Hex"/>
            <h1 id="heading">Color Converter</h1>
            <input class="color-input" id="rgb" type="text" placeholder="RGB"/>
        </div>
        <script src="resources/js/index.js"></script>
    </body>
</html>
(function() {
    "use strict";
    
    window.onload = function() {
        let initialColorChoices = [
            "#0c6",
            "#099",
            "#c0c",
            "#39f",
            "#fa0",
            "#affd1b",
            "#d53e78",
            "#e04857",
            "#0cca9a",
            "#e6e600"
        ];
        
        let randomColor = initialColorChoices[Math.floor(Math.random() * 10)];
        
        document.body.style.backgroundColor = randomColor;
        
        let hexInput = document.getElementById("hex");
        let rgbInput = document.getElementById("rgb");
        
        hexInput.value = randomColor;
        rgbInput.value = convertHexToRGB(randomColor);
        
        // I've heard of something called arrow functions, how could 
        // I use those here?
        hexInput.addEventListener("change", function() {
            if (isValidColor(this.value)) {
                rgbInput.value = convertHexToRGB(this.value);
                document.body.style.backgroundColor = this.value;
            }  
        });
        
        rgbInput.addEventListener("change", function() {
            if (isValidColor(this.value)) {
                hexInput.value = convertRGBToHex(this.value);
                document.body.style.backgroundColor = convertRGBToHex(this.value);
            } 
        });
    };
    
    function convertHexToRGB(hexString) {
        let rgbColorValues = [];
        
        if (!isValidColor(hexString)) {
            return "";
        }
        
        if (hexString.length == 4) {
            for (const character of hexString.slice(1)) { // Excluding the #
                rgbColorValues.push(parseInt(character + character, 16));
            }
        }
        else {
            for (let i = 1; i < 7; i += 2) { // Starting at 1 to exclude #
                rgbColorValues.push(parseInt(hexString[i] + hexString[i + 1], 16));
            }
        }
        
        return `rgb(${rgbColorValues[0]}, ${rgbColorValues[1]}, ${rgbColorValues[2]})`;
    }
    
    function convertRGBToHex(rgbString) {
        let hexString = "#";
        
        if (!isValidColor(rgbString))
        {
            return "";
        }
        
        let rgbColorValues = rgbString.replace(/(\s)|(rgb\()|(\))/g, '') // Isolate the RGB colors by removing spaces, rgb(, and )
            .split(",") // Convert to string array
            .map(Number); // Convert to number array
        
        for (const color of rgbColorValues) {
            let currentColorString = color.toString(16);
            
            if (currentColorString.length < 2) {
                hexString += "0";
            }
            
            hexString += currentColorString;
        }
        
        return hexString;
    }
    
    function isValidColor(colorString) {
        const hexRegex = /^(#[0-9A-F]{3})|(#[0-9A-F]{6})$/i;
        const rgbRegex = /^rgb\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}\s*\)$/;
        
        if (hexRegex.test(colorString)) {
            return true;
        }
        else if (rgbRegex.test(colorString)) {
            let rgbColorValues = colorString.replace(/(\s)|(rgb\()|(\))/g, '') // Isolate the RGB colors by removing spaces, rgb(, and )
                .split(",") // Convert to string array
                .map(Number); // Convert to number array
                        
            for (const color of rgbColorValues) {
                if (color < 0 || color > 255) {
                    return false;
                }
            }
            
            return true;
        }
        return false;
    }
}());
<!DOCTYPE html>
<html>
    <head>
        <title>Color Converter</title>
        
        <link href="resources/css/index.css" rel="stylesheet"/>
    </head>
    <body>
        <div class="container">
            <input class="color-input" id="hex" type="text" placeholder="Hex"/>
            <h1 id="heading">Color Converter</h1>
            <input class="color-input" id="rgb" type="text" placeholder="RGB"/>
        </div>
        <script src="resources/js/index.js"></script>
    </body>
</html>
Notice added Improve details by Arnav Borborah
Bounty Started worth 50 reputation by Arnav Borborah
Tweeted twitter.com/StackCodeReview/status/972377038752542720
Fixed bug
Source Link
(function() {
    "use strict";
    
    window.onload = function() {
        let initialColorChoices = [
            "#0c6",
            "#099",
            "#c0c",
            "#39f",
            "#fa0",
            "#affd1b",
            "#d53e78",
            "#e04857",
            "#0cca9a",
            "#e6e600"
        ];
        
        let randomColor = initialColorChoices[Math.floor(Math.random() * 10)];
        
        document.body.style.backgroundColor = randomColor;
        
        let hexInput = document.getElementById("hex");
        let rgbInput = document.getElementById("rgb");
        
        hexInput.value = randomColor;
        rgbInput.value = convertHexToRGB(randomColor);
        
        // I've heard of something called arrow functions, how could 
        // I use those here?
        hexInput.addEventListener("change", function() {
            if (isValidColor(this.value)) {
                rgbInput.value = convertHexToRGB(this.value);
                document.body.style.backgroundColor = this.value;
            }  
        });
        
        rgbInput.addEventListener("change", function() {
            if (isValidColor(this.value)) {
                hexInput.value = convertRGBToHex(this.value);
                document.body.style.backgroundColor = convertRGBToHex(this.value);
            } 
        });
    };
    
    function convertHexToRGB(hexString) {
        let rgbColorValues = [];
        
        if (!isValidColor(hexString)) {
            return "";
        }
        
        if (hexString.length == 4) {
            for (const character of hexString.slice(1)) { // Excluding the #
                rgbColorValues.push(parseInt(character + character, 16));
            }
        }
        else {
            for (let i = 1; i < 7; i += 2) { // Starting at 1 to exclude #
                rgbColorValues.push(parseInt(hexString[i] + hexString[i + 1], 16));
            }
        }
        
        return `rgb(${rgbColorValues[0]}, ${rgbColorValues[1]}, ${rgbColorValues[2]})`;
    }
    
    function convertRGBToHex(rgbString) {
        let hexString = "#";
        
        if (!isValidColor(rgbString))
        {
            return "";
        }
        
        let rgbColorValues = rgbString.replace(/(\s)|(rgb\()|(\))/g, '') // Isolate the RGB colors by removing spaces, rgb(, and )
            .split(",") // Convert to string array
            .map(Number); // Convert to number array
        
        for (const color of rgbColorValues) {
            hexStringlet +=currentColorString = color.toString(16);
            
            if (currentColorString.length < 2) {
                hexString += "0";
            }
            
            hexString += currentColorString;
        }
        
        return hexString;
    }
    
    function isValidColor(colorString) {
        const hexRegex = /^(#[0-9A-F]{3})|(#[0-9A-F]{6})$/i;
        const rgbRegex = /^rgb\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}\s*\)$/;
        
        if (hexRegex.test(colorString)) {
            return true;
        }
        else if (rgbRegex.test(colorString)) {
            let rgbColorValues = colorString.replace(/(\s)|(rgb\()|(\))/g, '') // Isolate the RGB colors by removing spaces, rgb(, and )
                .split(",") // Convert to string array
                .map(Number); // Convert to number array
                        
            for (const color of rgbColorValues) {
                if (color < 0 || color > 255) {
                    return false;
                }
            }
            
            return true;
        }
        return false;
    }
}());
<!DOCTYPE html>
<html>
    <head>
        <title>Color Converter</title>
        
        <link href="https://fonts.googleapis.com/css?family=Raleway" rel="stylesheet"/>
        <link href="resources/css/index.css" rel="stylesheet"/>
    </head>
    <body>
        <div class="container">
            <input class="color-input" id="hex" type="text" placeholder="Hex"/>
            <h1 id="heading">Color Converter</h1>
            <input class="color-input" id="rgb" type="text" placeholder="RGB"/>
        </div>
        <script src="resources/js/index.js"></script>
    </body>
</html>
(function() {
    "use strict";
    
    window.onload = function() {
        let initialColorChoices = [
            "#0c6",
            "#099",
            "#c0c",
            "#39f",
            "#fa0",
            "#affd1b",
            "#d53e78",
            "#e04857",
            "#0cca9a",
            "#e6e600"
        ];
        
        let randomColor = initialColorChoices[Math.floor(Math.random() * 10)];
        
        document.body.style.backgroundColor = randomColor;
        
        let hexInput = document.getElementById("hex");
        let rgbInput = document.getElementById("rgb");
        
        hexInput.value = randomColor;
        rgbInput.value = convertHexToRGB(randomColor);
        
        // I've heard of something called arrow functions, how could 
        // I use those here?
        hexInput.addEventListener("change", function() {
            if (isValidColor(this.value)) {
                rgbInput.value = convertHexToRGB(this.value);
                document.body.style.backgroundColor = this.value;
            }  
        });
        
        rgbInput.addEventListener("change", function() {
            if (isValidColor(this.value)) {
                hexInput.value = convertRGBToHex(this.value);
                document.body.style.backgroundColor = convertRGBToHex(this.value);
            } 
        });
    };
    
    function convertHexToRGB(hexString) {
        let rgbColorValues = [];
        
        if (!isValidColor(hexString)) {
            return "";
        }
        
        if (hexString.length == 4) {
            for (const character of hexString.slice(1)) { // Excluding the #
                rgbColorValues.push(parseInt(character + character, 16));
            }
        }
        else {
            for (let i = 1; i < 7; i += 2) { // Starting at 1 to exclude #
                rgbColorValues.push(parseInt(hexString[i] + hexString[i + 1], 16));
            }
        }
        
        return `rgb(${rgbColorValues[0]}, ${rgbColorValues[1]}, ${rgbColorValues[2]})`;
    }
    
    function convertRGBToHex(rgbString) {
        let hexString = "#";
        
        if (!isValidColor(rgbString))
        {
            return "";
        }
        
        let rgbColorValues = rgbString.replace(/(\s)|(rgb\()|(\))/g, '') // Isolate the RGB colors by removing spaces, rgb(, and )
            .split(",") // Convert to string array
            .map(Number); // Convert to number array
        
        for (const color of rgbColorValues) {
            hexString += color.toString(16);
        }
        
        return hexString;
    }
    
    function isValidColor(colorString) {
        const hexRegex = /^(#[0-9A-F]{3})|(#[0-9A-F]{6})$/i;
        const rgbRegex = /^rgb\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}\s*\)$/;
        
        if (hexRegex.test(colorString)) {
            return true;
        }
        else if (rgbRegex.test(colorString)) {
            let rgbColorValues = colorString.replace(/(\s)|(rgb\()|(\))/g, '') // Isolate the RGB colors by removing spaces, rgb(, and )
                .split(",") // Convert to string array
                .map(Number); // Convert to number array
                        
            for (const color of rgbColorValues) {
                if (color < 0 || color > 255) {
                    return false;
                }
            }
            
            return true;
        }
        return false;
    }
}());
<!DOCTYPE html>
<html>
    <head>
        <title>Color Converter</title>
        
        <link href="https://fonts.googleapis.com/css?family=Raleway" rel="stylesheet"/>
        <link href="resources/css/index.css" rel="stylesheet"/>
    </head>
    <body>
        <div class="container">
            <input class="color-input" id="hex" type="text" placeholder="Hex"/>
            <h1 id="heading">Color Converter</h1>
            <input class="color-input" id="rgb" type="text" placeholder="RGB"/>
        </div>
        <script src="resources/js/index.js"></script>
    </body>
</html>
(function() {
    "use strict";
    
    window.onload = function() {
        let initialColorChoices = [
            "#0c6",
            "#099",
            "#c0c",
            "#39f",
            "#fa0",
            "#affd1b",
            "#d53e78",
            "#e04857",
            "#0cca9a",
            "#e6e600"
        ];
        
        let randomColor = initialColorChoices[Math.floor(Math.random() * 10)];
        
        document.body.style.backgroundColor = randomColor;
        
        let hexInput = document.getElementById("hex");
        let rgbInput = document.getElementById("rgb");
        
        hexInput.value = randomColor;
        rgbInput.value = convertHexToRGB(randomColor);
        
        // I've heard of something called arrow functions, how could 
        // I use those here?
        hexInput.addEventListener("change", function() {
            if (isValidColor(this.value)) {
                rgbInput.value = convertHexToRGB(this.value);
                document.body.style.backgroundColor = this.value;
            }  
        });
        
        rgbInput.addEventListener("change", function() {
            if (isValidColor(this.value)) {
                hexInput.value = convertRGBToHex(this.value);
                document.body.style.backgroundColor = convertRGBToHex(this.value);
            } 
        });
    };
    
    function convertHexToRGB(hexString) {
        let rgbColorValues = [];
        
        if (!isValidColor(hexString)) {
            return "";
        }
        
        if (hexString.length == 4) {
            for (const character of hexString.slice(1)) { // Excluding the #
                rgbColorValues.push(parseInt(character + character, 16));
            }
        }
        else {
            for (let i = 1; i < 7; i += 2) { // Starting at 1 to exclude #
                rgbColorValues.push(parseInt(hexString[i] + hexString[i + 1], 16));
            }
        }
        
        return `rgb(${rgbColorValues[0]}, ${rgbColorValues[1]}, ${rgbColorValues[2]})`;
    }
    
    function convertRGBToHex(rgbString) {
        let hexString = "#";
        
        if (!isValidColor(rgbString))
        {
            return "";
        }
        
        let rgbColorValues = rgbString.replace(/(\s)|(rgb\()|(\))/g, '') // Isolate the RGB colors by removing spaces, rgb(, and )
            .split(",") // Convert to string array
            .map(Number); // Convert to number array
        
        for (const color of rgbColorValues) {
            let currentColorString = color.toString(16);
            
            if (currentColorString.length < 2) {
                hexString += "0";
            }
            
            hexString += currentColorString;
        }
        
        return hexString;
    }
    
    function isValidColor(colorString) {
        const hexRegex = /^(#[0-9A-F]{3})|(#[0-9A-F]{6})$/i;
        const rgbRegex = /^rgb\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}\s*\)$/;
        
        if (hexRegex.test(colorString)) {
            return true;
        }
        else if (rgbRegex.test(colorString)) {
            let rgbColorValues = colorString.replace(/(\s)|(rgb\()|(\))/g, '') // Isolate the RGB colors by removing spaces, rgb(, and )
                .split(",") // Convert to string array
                .map(Number); // Convert to number array
                        
            for (const color of rgbColorValues) {
                if (color < 0 || color > 255) {
                    return false;
                }
            }
            
            return true;
        }
        return false;
    }
}());
<!DOCTYPE html>
<html>
    <head>
        <title>Color Converter</title>
        
        <link href="https://fonts.googleapis.com/css?family=Raleway" rel="stylesheet"/>
        <link href="resources/css/index.css" rel="stylesheet"/>
    </head>
    <body>
        <div class="container">
            <input class="color-input" id="hex" type="text" placeholder="Hex"/>
            <h1 id="heading">Color Converter</h1>
            <input class="color-input" id="rgb" type="text" placeholder="RGB"/>
        </div>
        <script src="resources/js/index.js"></script>
    </body>
</html>
Added beginner tag
Link
Loading
added 87 characters in body
Source Link
Loading
Source Link
Loading