Skip to main content
1 of 4
Marc
  • 5.7k
  • 2
  • 14
  • 35

Improving a project builder for Stack Overflow (Codestrap)

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:

  1. quickly start up a dev project to test my answer (less than 3 clicks)
  2. 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.

Marc
  • 5.7k
  • 2
  • 14
  • 35