In the process of learning JavaScript I built a Google Chrome extension. It works but as I am adding more features the code is quickly getting duplicated, so I'm looking for ways to improve it.
This is the code (other parts of the extension are omitted for clarity):
let createProject = document.getElementById('cproject');
var errorMessage = document.getElementById('error_message');
const cprojectRipple = new mdc.ripple.MDCRipple(document.getElementById('cproject'));
const pLanguageElement = new mdc.select.MDCSelect(document.getElementById('planguage'));
const buildtoolElement = new mdc.select.MDCSelect(document.getElementById('buildtool'));
const frameworkElement = new mdc.select.MDCSelect(document.getElementById('framework'));
const buildtooljsElement = new mdc.select.MDCSelect(document.getElementById('buildtool-js'));
const frameworkjsElement = new mdc.select.MDCSelect(document.getElementById('framework-js'));
const isPrivateSwitch = new mdc.switchControl.MDCSwitch(document.querySelector('.mdc-switch'));
const pnameElement = new mdc.textField.MDCTextField(document.querySelector('.mdc-text-field'));
frameworkElement.listen('MDCSelect:change', () => {
// Set build tool to Maven if a framework is selected
if (frameworkElement.value !== 'none' && buildtoolElement.value === 'none') {
buildtoolElement.selectedIndex = 1;
}
});
buildtoolElement.listen('MDCSelect:change', () => {
// Reset framework if build tool is none
if (buildtoolElement.value === 'none' && frameworkElement.value !== 'none') {
frameworkElement.selectedIndex = 0;
}
});
frameworkjsElement.listen('MDCSelect:change', () => {
if (frameworkjsElement.selectedIndex !== buildtooljsElement.selectedIndex) {
buildtooljsElement.selectedIndex = frameworkjsElement.selectedIndex;
}
});
buildtooljsElement.listen('MDCSelect:change', () => {
if (frameworkjsElement.selectedIndex !== buildtooljsElement.selectedIndex) {
frameworkjsElement.selectedIndex = buildtooljsElement.selectedIndex;
}
});
pLanguageElement.listen('MDCSelect:change', () => {
console.log(`Selected language at index ${pLanguageElement.selectedIndex} with value "${pLanguageElement.value}"`);
const javaConfig = document.getElementById('java-configurator');
const pyConfig = document.getElementById('python-configurator');
const jsConfig = document.getElementById('javascript-configurator');
if (pLanguageElement.value === 'java') {
javaConfig.style.display = 'inline';
pyConfig.style.display = 'none';
jsConfig.style.display = 'none';
} else if (pLanguageElement.value === 'python') {
javaConfig.style.display = 'none';
jsConfig.style.display = 'none';
pyConfig.style.display = 'inline';
} else if(pLanguageElement.value === 'javascript'){
javaConfig.style.display = 'none';
jsConfig.style.display = 'inline';
pyConfig.style.display = 'node';
}
buildtoolElement.selectedIndex=0;
frameworkElement.selectedIndex=0;
buildtooljsElement.selectedIndex=0;
frameworkjsElement.selectedIndex=0;
});
createProject.onclick = function () {
errorMessage.innerHTML = '';
// Validate project name
if (!pnameElement.valid) {
errorMessage.innerHTML = 'Please provide the project name';
return false;
}
var projectName = pnameElement.value;
console.log('Project name: ', projectName);
// Get language
const language = pLanguageElement.value;
console.log('Language selected: ', language);
// Get Build Tool
const buildtool = buildtoolElement.value;
console.log('Build tool selected: ', buildtool);
const buildtooljs = buildtooljsElement.value;
const frameworkjs = frameworkjsElement.value;
//Get Framework
const framework = frameworkElement.value;
console.log('Framework selected: ', framework);
// build project type
var ptype = language;
if (buildtool !== 'none') {
ptype = ptype + '-' + buildtool;
}
if (framework !== 'none') {
ptype = ptype + '-' + framework;
}
if(buildtooljs !== 'none'){
ptype = ptype + '-' + buildtooljs;
}
if(frameworkjs !== 'none'){
ptype = ptype + '-' + frameworkjs;
}
console.log('Project type: ', ptype);
var isPrivate = isPrivateSwitch.checked;
alert(JSON.stringify({project_type:ptype,project_name:projectName,is_private:isPrivate}));
return true;
};
<link href="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.css" rel="stylesheet">
<script src="https://unpkg.com/material-components-web@latest/dist/material-components-web.min.js"></script>
<div id="pconfig">
<!-- PROJECT LANGUAGE -->
<div id="planguage" class="mdc-select mdc-select--filled">
<div class="mdc-select__anchor">
<span class="mdc-select__ripple"></span>
<span class="mdc-select__selected-text"></span>
<span class="mdc-select__dropdown-icon">
<svg class="mdc-select__dropdown-icon-graphic" viewBox="7 10 10 5">
<polygon class="mdc-select__dropdown-icon-inactive" stroke="none" fill-rule="evenodd" points="7 10 12 15 17 10">
</polygon>
<polygon class="mdc-select__dropdown-icon-active" stroke="none" fill-rule="evenodd" points="7 15 12 10 17 15">
</polygon>
</svg>
</span>
<span class="mdc-floating-label">Language</span>
<span class="mdc-line-ripple"></span>
</div>
<div class="mdc-select__menu mdc-menu mdc-menu-surface mdc-menu-surface--fullwidth">
<ul class="mdc-list">
<li class="mdc-list-item mdc-list-item--selected" data-value="java" aria-selected="true">
<span class="mdc-list-item__ripple"></span>
<span class="mdc-list-item__text">Java</span>
</li>
<li class="mdc-list-item" data-value="python">
<span class="mdc-list-item__ripple"></span>
<span class="mdc-list-item__text">Python</span>
</li>
<li class="mdc-list-item" data-value="javascript">
<span class="mdc-list-item__ripple"></span>
<span class="mdc-list-item__text">Javascript</span>
</li>
</ul>
</div>
</div>
<br><br>
<!-- JAVA CONFIGURATOR -->
<div id="java-configurator">
<!-- BUILD TOOLS -->
<div id="buildtool" class="mdc-select mdc-select--filled demo-width-class">
<div class="mdc-select__anchor">
<span class="mdc-select__ripple"></span>
<span class="mdc-select__selected-text"></span>
<span class="mdc-select__dropdown-icon">
<svg class="mdc-select__dropdown-icon-graphic" viewBox="7 10 10 5">
<polygon class="mdc-select__dropdown-icon-inactive" stroke="none" fill-rule="evenodd" points="7 10 12 15 17 10">
</polygon>
<polygon class="mdc-select__dropdown-icon-active" stroke="none" fill-rule="evenodd" points="7 15 12 10 17 15">
</polygon>
</svg>
</span>
<span class="mdc-floating-label">Build tool</span>
<span class="mdc-line-ripple"></span>
</div>
<div class="mdc-select__menu mdc-menu mdc-menu-surface mdc-menu-surface--fullwidth">
<ul class="mdc-list">
<li class="mdc-list-item mdc-list-item--selected" data-value="none" aria-selected="true">
<span class="mdc-list-item__ripple"></span>
<span class="mdc-list-item__text">None</span>
</li>
<li class="mdc-list-item" data-value="maven">
<span class="mdc-list-item__ripple"></span>
<span class="mdc-list-item__text">Maven</span>
</li>
<li class="mdc-list-item" data-value="gradle">
<span class="mdc-list-item__ripple"></span>
<span class="mdc-list-item__text">Gradle</span>
</li>
</ul>
</div>
</div>
<br><br>
<!-- FRAMEWORK -->
<div id="framework" class="mdc-select mdc-select--filled demo-width-class">
<div class="mdc-select__anchor">
<span class="mdc-select__ripple"></span>
<span class="mdc-select__selected-text"></span>
<span class="mdc-select__dropdown-icon">
<svg class="mdc-select__dropdown-icon-graphic" viewBox="7 10 10 5">
<polygon class="mdc-select__dropdown-icon-inactive" stroke="none" fill-rule="evenodd" points="7 10 12 15 17 10">
</polygon>
<polygon class="mdc-select__dropdown-icon-active" stroke="none" fill-rule="evenodd" points="7 15 12 10 17 15">
</polygon>
</svg>
</span>
<span class="mdc-floating-label">Framework</span>
<span class="mdc-line-ripple"></span>
</div>
<div class="mdc-select__menu mdc-menu mdc-menu-surface mdc-menu-surface--fullwidth">
<ul class="mdc-list">
<li class="mdc-list-item mdc-list-item--selected" data-value="none" aria-selected="true">
<span class="mdc-list-item__ripple"></span>
<span class="mdc-list-item__text">None</span>
</li>
<li class="mdc-list-item" data-value="springboot">
<span class="mdc-list-item__ripple"></span>
<span class="mdc-list-item__text">Spring Boot</span>
</li>
</ul>
</div>
</div>
<br><br>
</div>
<!-- PYTHON CONFIGURATOR -->
<div id="python-configurator" style="display:none">
</div>
<!-- JAVASCRIPT CONFIGURATOR -->
<div id="javascript-configurator" style="display:none">
<!-- BUILD TOOLS -->
<div id="buildtool-js" class="mdc-select mdc-select--filled demo-width-class">
<div class="mdc-select__anchor">
<span class="mdc-select__ripple"></span>
<span class="mdc-select__selected-text"></span>
<span class="mdc-select__dropdown-icon">
<svg class="mdc-select__dropdown-icon-graphic" viewBox="7 10 10 5">
<polygon class="mdc-select__dropdown-icon-inactive" stroke="none" fill-rule="evenodd" points="7 10 12 15 17 10">
</polygon>
<polygon class="mdc-select__dropdown-icon-active" stroke="none" fill-rule="evenodd" points="7 15 12 10 17 15">
</polygon>
</svg>
</span>
<span class="mdc-floating-label">Build tool</span>
<span class="mdc-line-ripple"></span>
</div>
<div class="mdc-select__menu mdc-menu mdc-menu-surface mdc-menu-surface--fullwidth">
<ul class="mdc-list">
<li class="mdc-list-item mdc-list-item--selected" data-value="none" aria-selected="true">
<span class="mdc-list-item__ripple"></span>
<span class="mdc-list-item__text">None</span>
</li>
<li class="mdc-list-item" data-value="npm">
<span class="mdc-list-item__ripple"></span>
<span class="mdc-list-item__text">npm</span>
</li>
</ul>
</div>
</div>
<br><br>
<!-- FRAMEWORK -->
<div id="framework-js" class="mdc-select mdc-select--filled demo-width-class">
<div class="mdc-select__anchor">
<span class="mdc-select__ripple"></span>
<span class="mdc-select__selected-text"></span>
<span class="mdc-select__dropdown-icon">
<svg class="mdc-select__dropdown-icon-graphic" viewBox="7 10 10 5">
<polygon class="mdc-select__dropdown-icon-inactive" stroke="none" fill-rule="evenodd" points="7 10 12 15 17 10">
</polygon>
<polygon class="mdc-select__dropdown-icon-active" stroke="none" fill-rule="evenodd" points="7 15 12 10 17 15">
</polygon>
</svg>
</span>
<span class="mdc-floating-label">Framework</span>
<span class="mdc-line-ripple"></span>
</div>
<div class="mdc-select__menu mdc-menu mdc-menu-surface mdc-menu-surface--fullwidth">
<ul class="mdc-list">
<li class="mdc-list-item mdc-list-item--selected" data-value="none" aria-selected="true">
<span class="mdc-list-item__ripple"></span>
<span class="mdc-list-item__text">None</span>
</li>
<li class="mdc-list-item" data-value="nodejs">
<span class="mdc-list-item__ripple"></span>
<span class="mdc-list-item__text">Node.js</span>
</li>
</ul>
</div>
</div>
<br><br>
</div>
<!-- PROJECT NAME -->
<label class="mdc-text-field mdc-text-field--filled mdc-text-field--label-floating">
<span class="mdc-text-field__ripple"></span>
<input class="mdc-text-field__input" type="text" aria-labelledby="my-label-id" value="my-new-project" required>
<span class="mdc-floating-label mdc-floating-label--float-above" id="my-label-id">Project name</span>
<span class="mdc-line-ripple"></span>
</label>
<br><br>
<!-- IS PRIVATE -->
<label for="basic-switch">Private project</label>
<div class="mdc-switch mdc-switch--checked">
<div class="mdc-switch__track"></div>
<div class="mdc-switch__thumb-underlay">
<div class="mdc-switch__thumb"></div>
<input type="checkbox" id="basic-switch" class="mdc-switch__native-control" role="switch" aria-checked="true" checked>
</div>
</div>
<br><br>
<!-- CREATE BUTTON-->
<button id="cproject" class="mdc-button mdc-button--outlined">
<div class="mdc-button__ripple"></div>
<span class="mdc-button__label">Create</span>
</button>
<p id="error_message" style="color:red;"></p>
</div>
The button CREATE
shows the result that I need to send to the server.
The project_type
is a lowercase string with this format: language-build tool-framework
. For example: java-gradle-springboot.
Every project has a name, a language and a boolean "isPrivate". Other fields depends on the language.
- How can I reduce the duplicated code and have a more flexible solution?
My plan is to add more languages and configurations. Any comments are welcome, thank you!
Side note: you can download Codestrap here if you want. It creates a project in your GitHub repo and opens it in Gitpod.
I developed it because after some time on Stack Overflow answering questions I wanted to:
- quickly start up a dev project to test my answer (less than 3 clicks)
- do everything in the browser (Repl.it is cool but adding frameworks is not straightforward)
Besides that, can be used to play around with new languages and frameworks.