Search code examples
javascriptjqueryhtmlcsssubstr

JS - How to remove all whitespaces except in the middle of the string, that is generated using substr() function?


I'm creating a JS / JQuery calculator and there is an #info element, which shows the user what they typed, or what is the calculation sequence like in the "Windows 10 Calculator", here: enter image description here

I've tried many things which I'll list below but they didn't work.


Let me show you how it should look like:

  1. The user just pressed the "Sqrt" button. The #info element has changed accordingly. By using "Inspect element", we can see, #info element has one whitespace from each side: " √(0) ". enter image description here
  2. Let's press the button one more time and see what we've got. Now, the #info element has more whitespaces: " √( √(0) )". One from the left side, one after the first √(, and two whitespaces after the √(0), until we reach ). This behavior is caused by substr() function.

    However, it should be only one whitespace each side √(0) string. Without any other whitespaces. substr() function copies my whitespaces and that's the wrong thing.

    So, above, using " √( √(0) )" example, it should be "√( √(0) )", and by pressing "Sqrt" button again, we should get the result of #info as "√(√( √(0) ))". enter image description here


let firstResult, firstResultWithSign;

$("#sqrt").on("click", function() {
  if (typeof firstResult === "undefined") {
    firstResult = $("#result h3").text();
  }

  if (typeof firstResultWithSign === 'undefined') {
    firstResultWithSign = ' \u221A(' + firstResult + ') ';
  }

  $("#result h3").text(Math.sqrt($("#result h3").text()));

  if (
    $("#info")
    .text()
    .lastIndexOf("\u221A") > -1
  ) {
    /**************************************************************************************/
    $('#info').text($('#info').text().substr(0, $('#info').text().lastIndexOf(firstResultWithSign) + 3) + firstResultWithSign + $('#info').text().substr($('#info').text().indexOf(')') + 1) + ')');
    /**************************************************************************************/
  } else {
    $("#info").html(firstResultWithSign);
  }
});
body {
  margin: 0;
  padding: 0;
  font-family: sans-serif;
  background-image: url("https://images8.alphacoders.com/702/702959.jpg");
  background-attachment: fixed;
  background-size: cover;
}

* {
  box-sizing: border-box;
  -webkit-user-select: none;
  user-select: none;
}

.text-center {
  text-align: center;
}

#result {
  background-color: #eee;
  min-height: 150px;
  max-height: 200px;
  position: relative;
}

#result h3 {
  font-size: 40px;
  margin: 0;
  position: absolute;
  bottom: 15px;
  right: 15px;
  -webkit-user-select: text;
  user-select: text;
}

.history {
  text-align: right;
  padding: 17px 17px 10px;
  display: inline-block;
  float: right;
}

.history:hover {
  background-color: #ddd;
}

#main-panel {
  background-color: #eee;
}

#title {
  float: left;
  padding: 17px;
}

#info {
  position: absolute;
  right: 15px;
  top: 55px;
  color: #616161;
  font-size: 15px;
}

.column {
  float: left;
  width: calc(25% - 5px);
  background-color: #ddd;
  height: 40px;
  margin: 0 4px 4px 0;
  line-height: 40px;
}

#one,
#two,
#three,
#four,
#five,
#six,
#seven,
#eight,
#nine,
#zero {
  background-color: #fff;
  font-weight: bold;
}

#divide:hover,
#times:hover,
#minus:hover,
#plus:hover,
#equals:hover {
  background-color: #01579b !important;
  color: #fff;
}

#divide:active,
#times:active,
#minus:active,
#plus:active,
#equals:active {
  background-color: #005395 !important;
  color: #fff;
}

.material-icons {
  font-size: 22px;
}

.column:first-child {
  margin-left: 4px;
}

.column:hover {
  background-color: #bcbcbc !important;
}

.column:active {
  background-color: #aeaeae !important;
}

.row:after {
  content: "";
  display: table;
  clear: both;
}

.fa-erase-left:before {
  content: "⌫";
}

.three-dots {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.overflow-x-auto {
  overflow-x: auto;
}

:focus {
  outline: 0;
}

footer {
  font-size: 0.85rem;
  margin: 1rem 0;
}

a {
  text-decoration: none;
  color: #fff;
  position: relative;
  cursor: pointer;
}

footer a:before {
  content: "";
  position: absolute;
  width: 100%;
  height: 0.0625rem;
  bottom: 0;
  left: 0;
  background-color: #fff;
  visibility: hidden;
  -webkit-transform: scaleX(0);
  transform: scaleX(0);
  -webkit-transition: all 0.3s ease-in-out 0s;
  transition: all 0.3s ease-in-out 0s;
}

footer a:hover:before {
  visibility: visible;
  -webkit-transform: scaleX(1);
  transform: scaleX(1);
}

.calculator-container {
  width: 45%;
  min-width: 200px;
  margin: 2.5rem auto 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<html>
<div class="calculator-container text-center">
  <div id="result">
    <div id="title">Calculator</div>
    <div class="history" title="History"><i class="material-icons">&#xE889;</i></div>
    <div id="info"></div>
    <h3 data-auto-generated="true" data-true-zero="true">0</h3>
  </div>
  <div id="main-panel">
    <div class="row">
      <div id="percentage" class="column">%</div>
      <div id="sqrt" class="column">&#x0221A;</div>
      <div id="exponentiation-by-two" class="column">x<sup>2</sup></div>
      <div id="one-divide-by-x" class="column"><sup>1</sup>/x</div>
    </div>
    <div class="row">
      <div id="ce" class="column">CE</div>
      <div id="c" class="column">C</div>
      <div id="erase-left" class="column">
        <div class="fa-erase-left"></div>
      </div>
      <div id="divide" class="column">&divide;</div>
    </div>
    <div class="row">
      <div id="seven" class="column">7</div>
      <div id="eight" class="column">8</div>
      <div id="nine" class="column">9</div>
      <div id="times" class="column">&#215;</div>
    </div>
    <div class="row">
      <div id="four" class="column">4</div>
      <div id="five" class="column">5</div>
      <div id="six" class="column">6</div>
      <div id="minus" class="column">&#8722;</div>
    </div>
    <div class="row">
      <div id="one" class="column">1</div>
      <div id="two" class="column">2</div>
      <div id="three" class="column">3</div>
      <div id="plus" class="column">&#43;</div>
    </div>
    <div class="row">
      <div id="plus-minus" class="column">&#177;</div>
      <div id="zero" class="column">0</div>
      <div id="comma" class="column">,</div>
      <div id="equals" class="column">&#61;</div>
    </div>
  </div>
  <footer>
    <a href="https://codepen.io/Kestis500">Created by LukasLSC</a>
  </footer>
</div>

JsFiddle: https://jsfiddle.net/xob6Luhh/.


What didn't work?

  1. Using replace(), because then the substr() will copy absolutely no whitespace.
  2. Using indexOf(firstResultWithSign).
  3. Using ' ' + firstResultWithSignNoSpace + ' ', this will make substr() to copy whitespaces.

I've tried almost 10 ways, however, they are very similar to 1 - 3.

Any ideas? :) Thank you.


Solution

  • You can achieve it with this statement:

    $('#info').text(
        $('#info').text().replace(firstResultWithSign, firstResultWithSign.substr(1,2) 
                                                     + firstResultWithSign + ')')
    );
    

    There are several other ways to get the same, depending on how dynamic you want it to be. For instance:

    $('#info').text(
        $('#info').text().replace(firstResultWithSign, 
                                  firstResultWithSign.replace(/\s*([^(]*).*/, '$1($&)'))
    );