TOAST UI CodeSnippet


CodeSnippet is a collection of frequently used codes like codes to perform type checks or to manage arrays, and was created to decrease the dependence on the outside libraries. TOAST UI uses CodeSnippet for the very same reason. CodeSnippet is separated into multiple modules according to its function, so developers can decide whether to use CodeSnippet as a whole or simply adopt the parts needed. However, it is advised that CodeSnippet be used as a whole when used to maintain TOAST UI components.

This introductory document serves to help the users who are not familiar with using CodeSnippet. Therefore, will not discuss every single feature the CodeSnippet provides. To learn more about various functions and related APIs, refer to document below.

Table of Contents

Installation and Getting Started

Install

CodeSnippet can be installed through npm, CDN, and bower.

Installing Through npm

To use npm to install, use the following command line prompts.

$ npm install --save tui-code-snippet # latest version
$ npm install --save tui-code-snippet@<version> # specific version

Installing Through CDN

As shown below, TOAST UI CodeSnippet can be accessed directly through a CDN. If npm and bower are unavailable, make sure to previously check the dependency information and download the related codes.

<script src="https://uicdn.toast.com/tui.code-snippet/latest/tui-code-snippet.js"></script> <!-- Latest Version -->
<script src="https://uicdn.toast.com/tui.code-snippet/<version>/tui-code-snippet.js"></script> <!-- Specific Version -->

Installing Through Bower

To download the source code using Bower, use the following command line prompts.

$ bower install "tui-code-snippet" # Latest version
$ bower install "tui-code-snippet#<version>" # Specific Version
  • Since bower has been deprecated, this method is not recommended.

File Name

CodeSnippet is distributed in two files—tui-code-snippet.js and tui-code-snippet.min.js. Although file names may be changed to better suit the characteristics of a project, to minimize the possibility of chaos, it is recommended that the file name not be changed.

  • tui-code-snippet.js : Not compressed; better suited for development
  • tui-code-snippet.min.js : Compressed; better suited for distribution

Getting Started

CommonJS

const snippet = require('tui-code-snippet'); /* CommonJS */

ES6 module import

import snippet from 'tui-code-snippet'; /* ES6 */

Browser script tag

To include it as a script tag, it is placed within the tui.util namespace.

<!DOCTYPE html>
<html>
  <head>
    <title>HTML Page</title>
  </head>
  <body>
    ...
    <script type="text/javascript" src="../js/lib/code-snippet.js"></script>
    <script type="text/javascript" src="../js/app.js"></script>
  </body>
</html>

Only Using Necessary Parts

import defineClass from 'tui-code-snippet/src/js/defineClass';

Only using selective and necessary modules in a bundler can decrease the size of the file by limiting files to only those that are dependent or necessary.

Browser Detection

CodeSnippet provides the snippet.browser object specifically for browser detection. When browser.js is running, snippet.browser automatically takes information regarding the current operating browser as its object properties, and these properties can be used to deal with different browsers accordingly.

import snippet from 'tui-code-snippet';

const browser = snippet.browser;

if (browser.msie) {
  alert("Internet Explorer");
} else if (browser.chrome) {
  alert("Chrome");
} else if (browser.firefox) {
  alert("FireFox");
} else if (browser.safari) {
  alert("Safari");
} else if (browser.others) {
  alert("Unknown");
}

If different browsers require different specifications, a version property can be used.

const browser = snippet.browser;

if (browser.msie) {
  if (browser.version < 8) {
    alert("Please, upgrade your browser");
  } else {
    ...
  }
}

Type Checking

CodeSnippet provides simple methods to run type checks.

All type checking methods are named with a is prefix followed by the data type. For example, a type checking method to determine whether the data is numerical is formed by combining the is and Number as snippet.isNumber().

const exam = 'fe';

snippet.isString(exam); // true
snippet.isNumber(exam); // false
snippet.isExisty(exam); // true

CodeSnippet also provides type checking methods like isArray, isObject, isFunction, and etc. For more information on the subject, refer to the [API Documentation]

Dealing with HTML Entities

CodeSnippet provides a feature that interchangeably substitute a string into an HTML element and vice versa. A string can be substituted into an HTML element using a encodeHTMLEntity(), and the very opposite can be achieved by decodeHTMLEntity().

const htmlEntityString = '<div>FE devleopment Team <b>CodeSnippet</b></div>';
const result = snippet.encodeHTMLEntity(htmlEntityString);
// "&lt;div&gt;FE devleopment Team &lt;b&gt;CodeSnippet&lt;/b&gt;&lt;/div&gt;"

const htmlEntityString = '&lt;div&gt;A &#39;quote&#39; is &lt;b&gt;bold&lt;/b&gt;&lt;/div&gt;';
const result = snippet.decodeHTMLEntity(htmlEntityString);
// "<div>A 'quote' is <b>bold</b></div>";

Using CustomEvents

CustomEvents is created using the Observer Pattern and it provides an API for users to define and manage events. Provided below are two ways to use the CustomEvents.

Using Mixin to deal with CustomEvents

Developers can use Mixin to directly include an event in the corresponding object.

const Model = snippet.defineClass({
  init: function() {
    this.status = 'stop';
  },
  run: function() {
    this.status = 'run';
  },
  getStatus: function() {
    return this.status;
  }
});

snippet.CustomEvents.mixin(Model);
const m = new Model(); // Instantiation

m.on('run', m.run.bind(m)); // attaching user defined event
m.fire('run'); // user custom event occurs (event handler executes)
m.getStatus(); // 'run'

Using Internal Properties to deal with CustomEvents

Another method is to assign the user event object to an internal object property to deal with it. When an event object is assigned to an internal property using init, corresponding event can be executed.

const Model = snippet.defineClass({
  init: function() {
    this.status = 'stop';
  },
  run: function() {
    this.status = 'run';
  },
  getStatus: function() {
    return this.status;
  }
});
const m = new Model();

m.event.on('run', m.run.bind(m), m); // attaching the user event through event(internal property)
m.event.fire('run'); // causing the user defined event using event(internal property) (event handler executed)
m.getStatus(); // 'run'

If the computation of the event handler calls for a different action, invoke() can be used instead of fire() to cause an event and have it return the resulting value. The process remains the same.

const m = new Model(); // Instantiation
m.event.on('run', handler, m); // attaching user defined event

// managing the event caused by invoke conditionally
if (m.event.invoke('ready')) {
  ...
} else {
  ...
}

Using Enum

Enum allows a set of numerical values to be expressed in a more readable format. Presented below are some examples using Enum.

// Creating ERRORCODEs by sequentially appending each error code in Enum object
const ERRORCODE = new snippet.Enum(['TYPE', 'VALUE', 'OPERATION', 'MEMORY', 'STATE']);

function printError(code) {
  const {TYPE, VALUE, OPERATION, MEMORY, STATE} = ERRORCODE;

  switch (code) {
    case TYPE:
      alert('TypeError!');
      break;
    case VALUE:
      alert('Not a valid value.');
      break;
    case OPERATION:
      alert('Not a valid operation.');
      break;
    case MEMORY:
      alert('Not enough memory.');
      break;
    case STATE:
      alert('StateError!');
      break;
    default:
      alert('Unknown Error');
      break;
  }
}

function setObject(obj) {
  // Prints a TypeError if the input is not valid
  if (!snippet.isObject(obj)) {
    printError(ERRORCODE.TYPE); // TypeError occurs
  }
}
setObject('fe');

APIs for ES5 Environments

This chapter is dedicated to explaining useful features available for ES5 (or below) environments. If the browser provides a native API with similar function, it is recommended to use the API, and each section includes the possible APIs at the top.

Dealing with Arrays

forEach

(ES5: Array.prototype.forEach) It is possible to iterate through arrays and objects using forEach(). For the cases of array-like objects, it is necessary to transform the object into an actual array before it can be iterated.

// Iterating through regular arrays
let sum = 0;
forEach([1, 2, 3], (value) => {
  sum += value;
});

// Iterating through regular objects
let sum = 0,
  obj = {
    apple: 100,
    orange: 200,
    graph: 500,
    ...
  };
forEach(obj, (value) => {
  sum += value;
});

// Iterating though an array-like object
function sum() {
  //arguments (array-like object) is changed into an array
  const factors = Array.prototype.slice.call(arguments);
  forEach(factors, (value, index) => {
    ...
  });
}

filter

By using filter(), it is possible to extract a part of an array that fits the requirements. As the first argument, both an array and an array-like object can be taken as an input, and the second argument is an expression to validate the requirements.

const original = [100, 111, 23, 99, 101, 203, 1, 50];
snippet.filter(original, (value) => value > 100);  // [111, 101, 203];

map

(ES5: Array.prototype.map)

The map() method creates an array of values changed by some operations. Just like the filter() method, both an array and an array-like object may be used as the first argument, and the expression to validate the requirements is passed through as the second argument.

const placeCode = {
  '100': 'INTERENCE',
  '200': 'HELP DESK',
  '300': 'RESTAURANT',
  '400': 'LOCKER ROOM',
  '500': 'CAFE'
};
snippet.map([100, 200, 300, 400, 500], (value) => placeCode[value]);
// ["INTERENCE", "HELP DESK", "RESTAURANT", "LOCKER ROOM", "CAFE"]

reduce

(ES5: Array.prototype.reduce)

reduce() allows the program to accumulate the computed results. The first input should be the array to operate on, and the second input should be the function to change the values.

let nArr, i;

for (nArr = [], i = 0; i < 100; i += 1) {
  nArr.push(i);
}

const result = snippet.reduce(nArr, (stored, value) => {
  if (value && value % 3 === 0) {
    return stored + value;
  }
  return stored;
});

console.log(result); // 1683

toArray

(ES5: Array.from)

toArray() lets developers to change an array-like object to an actual array.

const  similarArray = {
  0: 'one',
  1: 'two',
  2: 'three',
  3: 'four',
  length: 4
};

const result = snippet.toArray(similarArray); // ['one', 'two', 'three', 'four'];

HashMap

(ES2015: Map Object)

CodeSnippet provides a HashMap to generate and manage hash data. A HashMap is generated by loading the desired CodeSnippet file and following the steps below.

const data = [
  {
    value: 'apple',
    type: 'fruit'
  },
  {
    value: 'mercedes',
    type: 'car'
  },
  {
    value: 'truck',
    type: 'car'
  },
  {
    value: 'lemonade',
    type: 'beverage'
  },
  {
    value: 'coke',
    type: 'beverage'
  }
];

let i = 0;
let len = data.length;
let cell, type;
let food = new snippet.HashMap(); // Generating a HashMap

for (; i < len; i += 1) {
  cell = data[i];
  type = food.get(cell.type);

  // If it already exists, it adds onto it, and if not, a new object is created
  if (food.has(cell.type)) {
    type.push(cell.value);
  } else {
    food.set(cell.type, [cell.value]);
  }
}

// Function to print out the results
function showResult() {
  i = 0;
  len = food.length;
  const keys = food.keys();
  for(; i < len; i+= 1) {
    console.log(keys[i], food.get(keys[i]));
  }
}

console.log(food.length); // 3
console.log(showResult());  // fruit ["apple"]
                          // car ["mercedes", "truck"]
                          // beverage ["lemonade", "coke"]

each() can be used to iterate through the HashMaps, and remove() can be used to delete hash values.

food.each((value, key) => {
  if (key === 'fruit') {
    food.remove(key);
  }
});
console.log(food.length); // 2
console.log(showResult());  // car ["mercedes", "truck"]
                          // beverage ["lemonade", "coke"]

Expanding an Object

(ES2015: Object.assign)

CodeSnippet provides an extend() feature to expand objects. To expand an object with the extend() method, use the target object as the first argument, and the expanding values as the second argument.

const def = {
  a: 10000,
  b: 20000,
  c: 30000
};
snippet.extend(def, {
  d: 40000,
  e: 50000,
  f: 60000
}); // {a: 10000, b: 20000, c: 30000, d: 40000, e: 50000,  f: 60000}

Such is used to create new static properties with CustomEvent mixin and defineClass().

// CustomEvent mixin
CustomEvents.mixin = function(func) {
  snippet.extend(func.prototype, CustomEvents.prototype);
};

// defineClass static
if (props.hasOwnProperty('static')) {
  snippet.extend(obj, props.static);
  delete props.static;
}
...

Defining a Class

(ES2015: class Keyword)

Class definition and inheritance can be instantiated using the defineClass().

// Defining a class
const Person = snippet.defineClass({
  // init function will automatically run when instatiated
  init: function(name) {
    this.name = 'Name:  ' + name;
    ...
  },

  // defining the static member of the constructor class
  static: {
    company: 'NHN Cloud',
    getComany: function() {
       ...
    }
    ...
  },

  // defining members for the constructor prototype
  getName: function() {
    ...
  }
  ...
});

In script code, it is possible to create a class by passing an object through the defineClass() method. Here, init is a constructor that runs at the point of instantiation and defines the codes to execute when the class is reset, and the static keyword helps define the static members of the class. Other methods and variables are included in the constructor prototype.

// Instantiation
const hanjung = new Person('hanjung');

// Calling an instance method
hanjung.getName();

As the example demonstrates, new instances can be created using the new keyword.

Instantiating Inheritance

(ES2015: extends Keyword)

Inheritance can be instantiated by passing an extra parameter to the defineClass() previously used to define classes.

// Defining the parent class
const Parent = snippet.defineClass({
  print: function() {
    console.log(this.name);
  }
});

First, a parent class for inheritance is defined using the defineClass(). Defining a parent class is identical to defining regular classes, and has already been covered in previous sections.

// Defining a child class
const Child = snippet.defineClass(Parent, {
  init: function(name) {
    this.name = name;
  }
});

A child class is defined the same way, but only the parameters are different. The first parameter is the parent class to inherit from, and the second parameter is the to be created object.

// Instantiating the child
const child = new Child('fe');

// calling the instance method
child.print();  // 'fe'

Because a child class inherited from the parent class, it can access the parent’s print() functions not defined internally.

Afterword

This document serves to briefly introduce the TOAST UI CodeSnippet. Although, with the spread of ES6, it’s role in the current development environment has dwindled, CodeSnippet still provides developers with useful tools. It is the hope of the author that this guide effectively explained integrating TOAST UI CodeSnippet to individual projects.

This document is an official Web Front-End development guide written and maintained by NHN Cloud FE Development Lab. Any errors, questions, and points of improvement pertaining to this document should be addressed to the official support channel (dl_javascript@nhn.com).


Last Modified
2019. 03. 29
FE Development LabBack to list