Pen Settings

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

You're using npm packages, so we've auto-selected Babel for you here, which we require to process imports and make it all work. If you need to use a different JavaScript preprocessor, remove the packages in the npm tab.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Use npm Packages

We can make npm packages available for you to use in your JavaScript. We use webpack to prepare them and make them available to import. We'll also process your JavaScript with Babel.

⚠️ This feature can only be used by logged in users.

Code Indentation

     

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

HTML Settings

Here you can Sed posuere consectetur est at lobortis. Donec ullamcorper nulla non metus auctor fringilla. Maecenas sed diam eget risus varius blandit sit amet non magna. Donec id elit non mi porta gravida at eget metus. Praesent commodo cursus magna, vel scelerisque nisl consectetur et.

            
              @import url("https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400");
@import url("https://fonts.googleapis.com/css?family=Roboto+Mono");

/* 
ref: https://flatuicolors.com/palette/us
$color-background: #eee;
$color-white-primary: #dfe6e9;
$color-white-secondary: #fff;
$color-black: #2d3436;
$color-grey: #b2bec3;
$color-orange: #e17055;
$color-red: #d63031;
*/

/* reset */
*,
*::after,
*::before {
  padding: 0;
  margin: 0;
  -webkit-box-sizing: inherit;
  box-sizing: inherit;
}

/* flex body */
body {
  font-family: "Open Sans", sans-serif;
  font-weight: 300;
  font-size: 2rem;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-pack: center;
  -ms-flex-pack: center;
  justify-content: center;
  -webkit-box-align: center;
  -ms-flex-align: center;
  align-items: center;
  min-height: 100vh;
  padding: 40px;
  background-color: #eee;
  color: #2d3436;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  animation: fadeIn 0.7s ease backwards;
}

.Movies {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
  -ms-flex-direction: column;
  flex-direction: column;
}

/* input */
input {
  font-family: "Roboto Mono", monospace;
  outline: none;
  color: #fff;
  width: 300px;
  background-color: #2d3436;
  display: inline;
  text-align: center;
  font-size: 2rem;
  font-weight: 300;
  letter-spacing: 8px;
  padding: 15px 12px 15px 20px;
  margin-right: 20px;
  border: none;
  border-radius: 5px;
  caret-color: #eee;
}

.margin-top-md {
  margin-top: 25px;
}

/* input[type="number"]::-webkit-inner-spin-button {
  -webkit-appearance: none;
} */

/* info button; ? */
.NumberInput-btn {
  position: relative;
  cursor: pointer;
}

.NumberInput-btn::before {
  content: "?";
  position: absolute;
  text-align: center;
  top: 12px;
  left: 3px;
  right: 0;
  bottom: 0;
  font-size: 0.7rem;
  border: solid 1px gray;
  border-radius: 50%;
  height: 15px;
  width: 15px;
  line-height: 13px;
  -webkit-transition: all 0.4s ease;
  -o-transition: all 0.4s ease;
  transition: all 0.4s ease;
  padding-left: 0.5px;
}

.NumberInput-btn:hover::before {
  color: #dfe6e9;
  background-color: #2d3436;
}

/* = */
.Movies-equal {
  text-align: center;
  margin: 10px 0;
  font-size: 4rem;
  font-weight: 400;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

/* info-panel */
.NumberInput-ubd-info {
  position: absolute;
  top: 50%;
  left: 50%;
  -webkit-transform: translate(-50%, -50%);
  -ms-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
  border: solid 1px #2d3436;
  padding: 25px 50px;
  color: #2d3436;
  background-color: #eee;
  border-radius: 5px;
  max-width: 950px;
  display: block;
  -webkit-animation: fadeIn 0.4s ease-in forwards;
  animation: fadeIn 0.4s ease-in forwards;
  z-index: 999;
}

.UbdInfo-title {
  font-size: 1.6rem;
  font-weight: 400;
  text-align: center;
  margin-bottom: 20px;
}

/* content */
.NumberInput-ubd-info > p {
  font-size: 1rem;
  text-align: left;
  line-height: 150%;
}

/* x */
.UbdInfo-close {
  font-size: 1.5rem;
  cursor: pointer;
  color: #e17055;
  position: absolute;
  top: 3px;
  right: 16px;
}

.UbdInfo-close:hover {
  color: #d63031;
}

.UbdInfo-bg {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.85);
  opacity: 0.95;
  z-index: 100;
}

a {
  text-decoration: none;
  float: right;
  outline: 0;
  color: #2d3436;
}

a:hover {
  text-decoration: underline;
  color: rgba(0, 0, 0, 0.4);
}

/* example */
.Movies-refer {
  margin-top: 35px;
  height: 1px;
  text-align: center;
  font-size: 1.2rem;
  font-style: italic;
}

/* reset button */
.Movies-reset {
  cursor: pointer;
  text-transform: uppercase;
  color: #2d3436;
  background-color: #eee;
  letter-spacing: 10px;
  font-size: 1.5rem;
  margin-top: 60px;
  padding: 20px 42px 20px 50px;
  border-radius: 5px;
  border: solid 1px #2d3436;
  -webkit-transition: all 0.1s ease-out;
  -o-transition: all 0.1s ease-out;
  transition: all 0.1s ease-out;
  /*     -webkit-box-shadow: 2px 5px 5px rgba(0, 0, 0, 0.2);
  box-shadow: 2px 5px 5px rgba(0, 0, 0, 0.2); */
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  transition: all 0.3s linear;
  -webkit-animation: fadeIn 0.7s ease backwards 0.3s;
  animation: fadeIn 0.7s ease backwards 0.3s;
  outline: 0;
}

.Movies-reset:hover {
  opacity: 0.8;
  box-shadow: inset 0 -1px 5px rgba(0, 0, 0, 0.15);
}

.Movies-reset:active {
  opacity: 0.6;
}

.shaking {
  -webkit-animation: shake 150ms 2 linear;
  animation: shake 150ms 2 linear;
}

select {
  /*  chrome only  */
  text-align-last: center;
  text-align: center;
  position: absolute;
  top: 15px;
  right: 15px;
  font-size: 1.05rem;
  font-weight: 300;
}

@media screen and (max-width: 800px) {
  body,
  input {
    font-size: 1.5rem;
  }

  .NumberInput-btn::before {
    top: 9px;
  }

  .Movies-equal {
    font-size: 3rem;
    margin: -5px 0 0;
  }

  .NumberInput {
    text-align: center;
  }

  input {
    margin: 0;
    margin-bottom: 10px;
    width: 100%;
    padding: 20px 12px 20px 20px;
  }

  .NumberInput-ubd-info {
    padding: 25px 35px;
    width: 90%;
  }

  .Movies-reset {
    font-size: 1.2rem;
    margin-top: 60px;
  }

  select {
    font-size: 0.9rem;
    top: 10px;
    right: 10px;
  }
}

@media screen and (max-width: 400px) {
  body,
  input {
    font-size: 1.2rem;
  }

  .NumberInput-btn::before {
    font-size: 0.6rem;
    top: 5px;
  }

  .NumberInput-ubd-info {
    padding: 25px 25px;
  }

  .Movies-equal {
    font-size: 2.5rem;
    margin: -10px 0 -5px;
  }

  .Movies-reset {
    font-size: 1.1rem;
    margin-top: 50px;
  }

  .Movies-refer {
    margin: 15px 0 5px;
    font-size: 1rem;
  }

  select {
    font-size: 0.85rem;
    top: 5px;
    right: 5px;
  }
}

@-webkit-keyframes shake {
  0% {
    -webkit-transform: translate(4px, 0);
    transform: translate(4px, 0);
  }
  50% {
    -webkit-transform: translate(-4px, 0);
    transform: translate(-4px, 0);
  }
  100% {
    -webkit-transform: translate(0, 0);
    transform: translate(0, 0);
  }
}

@keyframes shake {
  0% {
    -webkit-transform: translate(4px, 0);
    transform: translate(4px, 0);
  }
  50% {
    -webkit-transform: translate(-4px, 0);
    transform: translate(-4px, 0);
  }
  100% {
    -webkit-transform: translate(0, 0);
    transform: translate(0, 0);
  }
}

@-webkit-keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes fadeIn {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

            
          
!
            
              // 1 UBD = 172,212 Audiences
// 1 UBD^2 = 30 billion
// 1 UBD/D = 1 UBD / 150M KRW * 150 (const)

const info = {
  UBD: {
    infoTitle: "Do you Know UBD?",
    infoUrl: "https://namu.wiki/w/UBD",
    infoContent:
      "UBD is an unit that is used to measure how many tickets a movie has sold so far. This term is originated in a South Korean movie called Bike King UBD, which had sold 172,212 tickets only. Therefore, 1 UBD represents 172,212 tickets sold. Coincidentally, 100 UBD is the highest box office record in South Korea. Any movies' tickets in South Korea can be measured as numbers between 0 and 100 UBD, which makes the unit useful."
  },
  "UBD^2": {
    infoTitle: "Do you Know UBD² ?",
    infoUrl: "https://namu.wiki/w/UBD#s-7.1",
    infoContent:
      "UBD² is an extended unit that is used to measure something countable. 1 UBD² is equal to 30 billion, since 172,212² is approximately 30 billion. The unit can be used for any numeric value, such as Korean Won or the number of people."
  },
  "UBD/D": {
    infoTitle: "Do you Know UBD/D?",
    infoUrl: "https://www.facebook.com/KaDaejeon/posts/2271201359865241",
    infoContent:
      "UBD/D is an extended unit that is used to measure how successful a movie is, taking its investment and tickets sold into account. For example, 1 UBD (tickets) and 150 million KRW (investment) is equal to 1 UBD/D. With UBD/D, you can calculate differences between movies' success in terms of the cost-to-benefit ratio."
  }
};

function UbdInfo(props) {
  return (
    <div className="UbdInfo">
      <div className="UbdInfo-bg" onClick={() => props.click()} />
      <div className="NumberInput-ubd-info">
        <div className="UbdInfo-title">{info[props.scale].infoTitle}</div>
        <p>
          {info[props.scale].infoContent}
          <a href={info[props.scale].infoUrl} target="_blank">
            Learn More
          </a>
        </p>
        <span className="UbdInfo-close" onClick={() => props.click()}>
          x
        </span>
      </div>
    </div>
  );
}

class NumberInput extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      info: false
    };
    this.handleChange = this.handleChange.bind(this);
    this.handleFocus = this.handleFocus.bind(this);
    this.handleClick = this.handleClick.bind(this);
  }

  handleChange(e) {
    this.props.change(e.target.value);
  }

  handleFocus(e) {
    this.props.focus(e.target.value, this.props.scale);
  }

  handleClick() {
    this.setState(st => ({
      info: !st.info
    }));
  }

  render() {
    const { number, scale, label, shaking } = this.props;
    const createInfoComponents = () => {
      if (scale == "UBD" || scale == "UBD/D" || scale == "UBD^2") {
        if (this.state.info) {
          return <UbdInfo click={this.handleClick} scale={scale} />;
        }

        return <span className="NumberInput-btn" onClick={this.handleClick} />;
      }
    };

    return (
      <div
        className={scale == "KRW" ? "NumberInput margin-top-md" : "NumberInput"}
      >
        <input
          className={shaking ? "shaking" : undefined}
          value={number}
          onChange={this.handleChange}
          onFocus={this.handleFocus}
        />
        <span className="NumberInput-unit">{label}</span>
        {createInfoComponents()}
      </div>
    );
  }
}

class UbdCalc extends React.Component {
  static defaultProps = {
    ubdUnit: 172212,
    maxUbd: 9999,
    maxUbds: 9999,
    maxKrw: 9999,
    maxUbdsValue: 2999700,
    maxValue: 1721947788,
    movies: [
      {
        name: "The Admiral: Roaring Currents ( 명량 )",
        ubd: 100
      },
      {
        name: "Extreme Job ( 극한직업 )",
        ubd: 94
      },
      {
        name: "Along With the Gods: The Two Worlds",
        ubd: 84
      },
      {
        name: "Ode to My Father",
        ubd: 82
      },
      {
        name: "Avatar",
        ubd: 79
      },
      {
        name: "Veteran",
        ubd: 78
      },
      {
        name: "The Thieves",
        ubd: 75
      },
      {
        name: "Miracle in cell No.7",
        ubd: 74
      },
      {
        name: "Masquerade",
        ubd: 72
      },
      {
        name: "A Taxi Driver",
        ubd: 71
      },
      {
        name: "TaeGukGi: Brotherhood Of War",
        ubd: 68
      },
      {
        name: "Train to Busan",
        ubd: 67
      },
      {
        name: "The Attorney",
        ubd: 66
      },
      {
        name: "Avengers: Infinity War",
        ubd: 65
      },
      {
        name: "Avengers: Age of Ultron",
        ubd: 60
      },
      {
        name: "Frozen",
        ubd: 60
      },
      {
        name: "Interstellar",
        ubd: 60
      },
      {
        name: "Your Name",
        ubd: 22
      },
      {
        name: "Howl's Moving Castle",
        ubd: 17
      },
      {
        name: "Justice League",
        ubd: 10
      },
      {
        name: "The Incredible Hulk",
        ubd: 5.76
      },
      {
        name: "Pororo, THE RACING ADVENTURE",
        ubd: 5.41
      },
      {
        name: "Hello Carbot the Movie: The Cretaceous Period",
        ubd: 5.11
      },
      {
        name: "Pororo, Dinosaur Island Adventure",
        ubd: 4.8
      },
      {
        name: "The Haunted House: The Secret of the Cave",
        ubd: 3.94
      },
      {
        name: "REAL",
        ubd: 2.79
      },
      {
        name: "Fantastic Four",
        ubd: 2.35
      },
      {
        name: "Green Lantern",
        ubd: 1.26
      },
      {
        name: "Solo: A Star Wars Story",
        ubd: 1.26
      },
      {
        name: "Pokémon the Movie: The Power of Us",
        ubd: 1.13
      },
      {
        name: "Bike King UBD",
        ubd: 1
      },
      {
        name: "SUNGNYANGPALI SONYEOUI JAERIM ",
        ubd: 0.82
      },
      {
        name: "ラブライブ! The School Idol Movie",
        ubd: 0.77
      },
      {
        name: "Clementine ( 아빠! 일어나!! )",
        ubd: 0.39
      }
    ]
  };

  constructor(props) {
    super(props);
    this.state = {
      mode: "ubd",
      value: 0,
      ubd: 0,
      ubdd: 0,
      ubds: 0,
      refer: "",
      shaking: false
    };
    this.ubdToBase10Change = this.ubdToBase10Change.bind(this);
    this.base10ToUbdChange = this.base10ToUbdChange.bind(this);
    this.ubddChange = this.ubddChange.bind(this);
    this.ubdSquareChange = this.ubdSquareChange.bind(this);
    this.handleReset = this.handleReset.bind(this);
    this.handleFocus = this.handleFocus.bind(this);
    this.handleChange = this.handleChange.bind(this);
  }

  showMovieName(ubd) {
    const refer = this.props.movies
      .filter(e => e.ubd.toFixed(2) == parseFloat(ubd))
      .map(e => e.name);
    const randomIdx = Math.floor(Math.random() * refer.length);

    return refer[randomIdx];
  }

  ubdToBase10Change(ubd) {
    if (isNaN(ubd)) {
      return;
    }

    if (ubd > this.props.maxUbd) {
      ubd = this.props.maxUbd;
    } else if (ubd < 0) {
      ubd = 0;
    }

    const decimal = String(ubd).split(".");
    if (decimal[1] && decimal[1].length > 2) {
      ubd = decimal[0] + "." + decimal[1].slice(0, 2);
    }

    if (this.state.mode === "ubd") {
      this.setState({
        value: Math.floor(ubd * this.props.ubdUnit),
        ubd: ubd,
        refer: this.showMovieName(ubd)
      });
    } else if (this.state.mode == "ubd/d") {
      const value = (ubd / this.state.ubdd * 150).toFixed(2);
      this.setState({
        ubd: ubd,
        value: isFinite(value) ? value : 0
      });
    }
  }

  base10ToUbdChange(base) {
    if (isNaN(base)) {
      return;
    }

    base = base.replace(/[^0-9]/g, "");

    if (this.state.mode === "ubd") {
      if (base > this.props.maxValue) {
        base = this.props.maxValue;
      } else if (base < 0) {
        base = 0;
      }

      const ubd = (base / this.props.ubdUnit).toFixed(2);
      this.setState({
        value: base,
        ubd: ubd,
        refer: this.showMovieName(ubd)
      });
    } else if (this.state.mode == "ubd/d") {
      this.setState(st => ({
        value: st.value
      }));
    } else if (this.state.mode == "ubd^2") {
      if (base > this.props.maxUbdsValue) {
        base = this.props.maxUbdsValue;
      } else if (base < 0) {
        base = 0;
      }

      this.setState(st => ({
        ubds: isFinite(base / 300) ? (base / 300).toFixed(2) : 0,
        value: isFinite(parseInt(base)) ? parseInt(base) : 0
      }));
    }
  }

  ubddChange(krw) {
    if (isNaN(krw)) {
      return;
    }

    if (krw > this.props.maxKrw) {
      krw = this.props.maxKrw;
    } else if (krw < 0) {
      krw = 0;
    }

    const decimal = String(krw).split(".");
    if (decimal[1] && decimal[1].length > 2) {
      krw = decimal[0] + "." + decimal[1].slice(0, 2);
    }

    const value = (this.state.ubd / krw * 150).toFixed(2);
    this.setState({
      ubdd: krw,
      value: isFinite(value) ? value : 0
    });
  }

  ubdSquareChange(ubds) {
    if (isNaN(ubds)) {
      return;
    }

    if (ubds > this.props.maxUbds) {
      ubds = this.props.maxUbds;
    } else if (ubds < 0) {
      ubds = 0;
    }

    const decimal = String(ubds).split(".");
    if (decimal[1] && decimal[1].length > 2) {
      ubds = decimal[0] + "." + decimal[1].slice(0, 2);
    }

    this.setState({
      ubds: ubds,
      value: ubds * 300
    });
  }

  handleReset() {
    this.setState(
      {
        value: 0,
        ubd: 0,
        ubdd: 0,
        ubds: 0,
        refer: "",
        shaking: true
      },
      () => {
        setTimeout(() => {
          this.setState({ shaking: false });
        }, 300);
      }
    );
  }

  handleFocus(value, scale) {
    if (value != 0) {
      return;
    }

    if (this.state.mode == "ubd") {
      if (scale == "UBD") {
        this.setState({
          value: 0,
          ubd: ""
        });
      } else {
        this.setState({
          value: "",
          ubd: 0
        });
      }
    } else if (this.state.mode == "ubd/d") {
      if (scale == "UBD") {
        this.setState({
          value: 0,
          ubd: ""
        });
        if (this.state.ubdd == "") {
          this.setState({
            ubdd: 0
          });
        }
      } else if (scale == "KRW") {
        this.setState({
          value: 0,
          ubdd: ""
        });
        if (this.state.ubd == "") {
          this.setState({
            ubd: 0
          });
        }
      }
    } else if (this.state.mode == "ubd^2") {
      if (scale == "UBD^2") {
        this.setState({
          value: 0,
          ubds: ""
        });
      } else {
        this.setState({
          value: "",
          ubds: 0
        });
      }
    }
  }

  handleChange(e) {
    this.setState({
      ubdd: 0,
      ubd: 0,
      ubds: 0,
      value: 0,
      mode: e.target.value
    });
  }

  render() {
    const { mode, ubd, ubdd, ubds, value, refer, shaking } = this.state;
    const getValueLabel = () => {
      if (mode == "ubd") {
        return "Tickets";
      } else if (mode == "ubd/d") {
        return "UBD/D";
      } else if (mode == "ubd^2") {
        return "100m/1억";
      }
    };

    return (
      <div className="Movies">
        <select onChange={this.handleChange}>
          <option value="ubd">UBD</option>
          <option value="ubd^2">UBD²</option>
          <option value="ubd/d">UBD/D</option>
        </select>
        {(mode == "ubd" || mode == "ubd/d") && (
          <NumberInput
            scale="UBD"
            label="UBD"
            change={this.ubdToBase10Change}
            focus={this.handleFocus}
            number={ubd}
            shaking={shaking}
            click={this.handleClick}
          />
        )}
        {mode == "ubd^2" && (
          <NumberInput
            scale="UBD^2"
            label="UBD²"
            change={this.ubdSquareChange}
            focus={this.handleFocus}
            number={ubds}
            shaking={shaking}
            click={this.handleClick}
          />
        )}
        {mode == "ubd/d" && (
          <NumberInput
            scale="KRW"
            label="KRW (100m/1억)"
            change={this.ubddChange}
            focus={this.handleFocus}
            number={ubdd}
            shaking={shaking}
            click={this.handleClick}
          />
        )}
        <div className="Movies-equal">=</div>
        <NumberInput
          scale={getValueLabel()}
          label={getValueLabel()}
          change={this.base10ToUbdChange}
          focus={this.handleFocus}
          number={value}
          shaking={shaking}
        />
        {mode === "ubd" && (
          <div className="Movies-refer">{refer && `e.g., ${refer}`}</div>
        )}
        <button className="Movies-reset" onClick={this.handleReset}>
          Reset
        </button>
      </div>
    );
  }
}

ReactDOM.render(
  <div>
    <UbdCalc />
  </div>,
  document.getElementById("root")
);

            
          
!
999px
🕑 One or more of the npm packages you are using needs to be built. You're the first person to ever need it! We're building it right now and your preview will start updating again when it's ready.

Console