Quicksort Algorithm

JavaScript
  /*** GLOBALS ***/
  
  var morphArray;
  var numberRange = 500;
  var prints = 21;
  var waitTime = 100;

  /*** FUNCTIONS ***/

  /*create the actual array to be sorted*/
  function createArray() {
    morphArray = [];
    for (i = 0; i < prints; i++) {
      var number = Math.floor((Math.random() * numberRange));
      morphArray.push(number);
    }
    var uniqueArray = Array.from(new Set(morphArray));
    //test that every number in array is unique
    if (JSON.stringify(uniqueArray) === JSON.stringify(morphArray)) {
      return morphArray
    } else {
      //recreate the array if each number is not unique
      return createArray();
    }
  }

  /*create the visual representation of the array - a set of boxes*/
  function createBoxes() {
    morphArray = createArray();
    for (i = 0; i < prints; i++) {
      var randomNumber = morphArray[i];
      //append each box to the container; wrapper is necessary to assign different transition durations for float effect (class "wrap") and rotate effect (class "box") transforms
      $('.box-container').append('<div class="wrap float"><div class="box invisible unsorted"><div class="number-text">' + randomNumber + '</div></div></div>');
      //assign unique data attribute to each box
      $('.wrap:eq(' + i + ')>.box').attr('data-num', randomNumber);
      /* 
      ADD CLASS "VISIBLE" TO EACH BOX TRIGGERING ENTRANCE ANIMATION
      -IIFE is used to create execution context so the current iteration's context is remembered when time comes to add "visible" class.  This enables the setTimeout to work before the execution context expires and the loop is completed.
      -The outer IIFE provides delay b/t creation of each box and addition of animation class, so element exists long enough for animation to kick in successfully.  This only seemed necessary for the first box.
      -The inner IIFE does the work of adding the class to each box after the delay period   
      */
      (function buyTime(i) {
        setTimeout(function () {

          (function triggerAnimation(i) {
            setTimeout(function () {
              var currentBox = '.wrap:eq(' + i + ')>.box';
              $(currentBox).toggleClass('visible invisible');
            }, waitTime * i);
          })(i);

        }, waitTime);
      })(i);
    }
  }

  /*quicksort function*/

  //add method quicksort to Array.prototype that exists in browser
  Array.prototype.quicksort = function () {

    //"this" is equal to the array on which the quicksort function is executed
    var r = this;
    // base case - return the array when it is one digit, and thus doesn't need more sorting
    if (r.length <= 1) {
      return r;
    }

    //create pivot of 1 digit that is just past mid-point of the array, removing it from the array
    var pivot = r.splice(Math.floor(r.length / 2), 1);

    //initialize sub-arrays for each side of the pivot
    var less = [];
    var greater = [];

    //run number of times there are items left in the array after pivot is removed
    for (i = r.length - 1; i >= 0; i--) {
      if (r[i] < pivot) {
        less.push(r[i]);
      } else {
        greater.push(r[i]);
      }
    }

    var c = [];

    //recursive cases - sort each sub array
    return c.concat(less.quicksort(), pivot, greater.quicksort());
  }

  /***EVENTS***/

  /* click event for "Create Array" button */
  $('.create-array-btn').click(function () {

    var allVisible = true;

    //turn allVisible false if any .box is missing .visible (entrance animation) class 
    $('.wrap').each(function () {
      if ($(this).children().hasClass('visible') === false) {
        allVisible = false;
      };
    });

    //create boxes if there are none
    if ($('.wrap').length === 0) {
      createBoxes();
    } else if ($('.wrap').length === prints && allVisible === true) {
      $('.wrap').remove();
      createBoxes();
    } //or remove and recreate boxes only if a prior array with its boxes has finished displaying  
  });

  /* click event for "Quick Sort" button */
  $('.sort-btn').click(function () {

    var readyToSort = false;

    //if the full number of prints exist, we are provisionally ready to sort
    if ($('.box-container').get(0).childElementCount === prints) {
      readyToSort = true;
    }

    //but don't sort if all the boxes are not finished animating onto the screen, or if they're already sorted
    $('.box').each(function () {
      if ($(this).hasClass('invisible') || $(this).hasClass('sorted')) {
        readyToSort = false;
      }
    });

    if (readyToSort === true) {
      morphArray = morphArray.quicksort();

      /*move first box into position of the sorted morphArray*/
      var sortedDataAttr = morphArray[0];
      //data attribute must be absolutely unique for fetching it based on that to work
      var sortedElement = '*[data-num="' + sortedDataAttr + '"]';
      $('.box-container').prepend($(sortedElement).parent());
      $(sortedElement).toggleClass('sorted unsorted');

      /*move remaining boxes into their postion in the sorted morphArray*/
      for (i = 1; i < prints; i++) {

        (function (i) {
          setTimeout(function () {
            var sortedDataAttr = morphArray[i];
            var sortedElement = '*[data-num="' + sortedDataAttr + '"]';
            //place box after the last instance of .sorted
            $('.sorted:last').parent().after($(sortedElement).parent());
            $(sortedElement).toggleClass('sorted unsorted');
          }, waitTime * i);
        })(i);
      }
    }
  });
HTML
<div class="button-container">
  <button class="create-array-btn wpforms-submit">Create Array</button>
  <button class="sort-btn wpforms-submit   ">Quick Sort</button>
</div>
<div class="box-container"></div>
CSS
.button-container {
  display: flex;
  justify-content: center;
  margin-bottom: 18px;
}

@media(max-width:500px) {
  .button-container {
    flex-direction: column;
    align-items: center;
  }
  .sort-btn {
    margin-top: 7px;
  }
}

@media(min-width:501px) {
  .sort-btn {
    margin-left: 7px;
  }
}

.box-container {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
}

.box {
  margin: 15px;
  justify-content: center;
  align-items: center;
  width: 130px;
  height: 130px;
  font-family: Montserrat, sans-serif;
  font-size: 30px;
  display: flex;
  transition: opacity .5s, transform .5s;
}

.invisible {
  opacity: 0;
  transform: rotate(-90deg);
}

.visible {
  opacity: 1;
  transform: rotate(0deg);
}

.unsorted {
  background: #4d4d4d;
}

.sorted {
  background: black;
}

.number-text {
  font-size: 24px;
  color: white;
}

/*float effect on hover*/

.float {
  transition-duration: .3s;
  transition-property: transform;
  transition-timing-function: cubic-bezier(0.09, 0.51, 0.83, 0.96);
}

.float:active,
.float:focus,
.float:hover {
  transform: translateY(-8px)
}

Roman Numeral Converter

JavaScript
function convertToRoman(num) {

    var roman = [];
    var numString = num.toString();
    //split number into an array containing only any digits entered
    var numArr = numString.match(/\d/g);
    //store value of the number without any special characters, such as commas
    var bareNumber = numArr.join('');
    var thousands = bareNumber / 1000;
    //initialize variables for each index in the array that contains the last 3 digits
    var hundreds = 0;
    var tens = 1;
    var ones = 2;

    //if the number has digits for the thousands, push an "M" into the array for each thousand
    if (thousands >= 1) {
        thousands = Math.floor(thousands);
        console.log(thousands);

        for (i = 0; i < thousands; i++) {
            roman.push("M");
        }
        var thousandsString = thousands.toString();

        //remove each digit for thousands from the beginning of the array
        for (i = 0; i < thousandsString.length; i++) {
            numArr.shift();
        }
    }

    //function to convert last 3 array digits to their Roman numerals
    function parseNumbers(first, second, third, position) {
        //hundreds, tens, or ones: 1-2
        if (numArr[position] >= 1 && numArr[position] <= 3) {
            for (i = 0; i < numArr[position]; i++) {
                roman.push(first);
            }
        }
        //4
        if (numArr[position] == 4) {
            roman.push(first + second);
        }
        //5
        if (numArr[position] == 5) {
            roman.push(second);
        }
        //6-8
        if (numArr[position] >= 6 && numArr[position] <= 8) {
            roman.push(second);
            for (i = 5; i < numArr[position]; i++) {
                roman.push(first);
            }
        }
        //9
        if (numArr[position] == 9) {
            roman.push(first + third);
        }
    }

    //if there is a hundreds digit, do the conversion for this digit
    console.log(numArr.length);
    if (numArr.length === 3) {
        //hundreds
        parseNumbers("C", "D", "M", hundreds);
    }

    //if there is a tens digit, do the conversion for this digit
    if (numArr.length >= 2) {

        if (numArr.length === 2) {
            //if the number starts with tens, shift the array position fed to the parser to the correct digit
            tens = 0;
            ones = 1;
        }
        //tens
        parseNumbers("X", "L", "C", tens);
    }

    //if there is a ones digit, do the conversion for this digit
    if (numArr.length >= 1) {
        //if the number starts with ones, shift the array position fed to the parser to the correct digit
        if (numArr.length === 1) {
            ones = 0;
        }
        //ones
        parseNumbers("I", "V", "X", ones);
    }

    num = roman.toString();
    num = num.replace(/,/g, '');
    console.log(num);
    return num;
}

Rotate 13 Algorithm

JavaScript
function rot13(str) {
  
  // 1- Convert every character to the number portion (charCode) of the that character's HTML entity ---  
  //helpful map of HTML entities: https://unicode-table.com/en/
  //create an array containing all characters
  var indivChars = str.split("");
  //create an array of only every character that is not a capital letter
  var nonLetterRE = /[^A-Z]/g;
  var nonLetters = str.match(nonLetterRE);
  //create an empty array that will contain all the numerical values for the characters
  var numEntityArr = [];
  //cycle through array containing all characters & convert the capital letters to their character code
  //if a character does not belong to A-Z, assign it a value of 0
  for (let i = 0; i < indivChars.length; i++) {
    var numberEntity = indivChars[i].charCodeAt(0);
    if (numberEntity >= 65 && numberEntity <= 90) {
      numEntityArr.push(numberEntity);
    } else {
      numEntityArr.push(0);
    }
  }

  // 2 - shift each character code 13 positions numerically ---
  var shiftedArray = [];
  var counter = 0;
  for (let i = 0; i < numEntityArr.length; i++) {
    //if the character code represents a letter within A-M, add 13 to the character code
    if (numEntityArr[i] >= 65 && numEntityArr[i] <= 77) {
      numEntityArr[i] = numEntityArr[i] + 13;
      //push this new number into an array, along with prefix and suffix that make the character code an HTML entity
      shiftedArray.push("&#" + numEntityArr[i] + ";");
      //if the character code represents a letter within N-Z, subtract 13 from the character code
    } else if (numEntityArr[i] >= 78 && numEntityArr[i] <= 90) {
      numEntityArr[i] = numEntityArr[i] - 13;
      shiftedArray.push("&#" + numEntityArr[i] + ";");
      //if the character code is not A-Z or 0, simply add prefix and suffix to make it an HTML entity & push it into the array
    } else if (numEntityArr[i] !== 0) {
      shiftedArray.push("&#" + numEntityArr[i] + ";");
      //if the character code is 0, replace it with the corresponding index of the nonLetter array created above 
    } else if (numEntityArr[i] === 0) {
      shiftedArray.push(nonLetters[counter]);
      counter += 1;
    }
  }

  // 3 - return correct letters ---
  //join in a string the html entities and non A-Z characters pushed into shiftedArray
  var entityString = shiftedArray.join("");
  //convert the HTML entities into characters, while passing all other non-entity characters through
  //credit: http://stackoverflow.com/questions/7394748/whats-the-right-way-to-decode-a-string-that-has-special-html-entities-in-it
  function decodeHTML(html) {
    var txt = document.createElement("textarea");
    txt.innerHTML = html;
    return txt.value;
  }
  var decodedHTML = decodeHTML(entityString);
  return decodedHTML;
}

Flexbox Demo

CSS
  .flex-container {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    max-width: 1000px;
    margin: 0 auto;
    padding: 1%;
  }
  
  .flex-item {
    width: 30%;
    max-width: 275px;
    min-width: 200px;
    margin-left: 1%;
    margin-right: 1%;
  }
  
  .image {
    width: 100%;
    height: auto;
  }
HTML
<div class="flex-container">

  <a class="flex-item" href="http://example-url.org">
    <img class="image" src="http://example-image.jpg">
    <h3 class="pic-title">Spirograph Nebula</h3>
  </a>

  <!--Each of the nine flex items follow the format above-->

</div>