text: import {root} from './root';
  import {isArray, isString, isUndef} from './types';
  import {trim} from './string';
  
  /**
   * DOM utilities
   */
  
  const doc = root.document;
  
  /**
   * Returns text + text of children of given node
   * @param  {NodeElement} node
   * @return {String}
   */
  export const getText = (node) => {
      if (isUndef(node.textContent)) {
          return trim(node.innerText);
      }
      return trim(node.textContent);
  };
  
  /**
   * Returns the first text node contained in the supplied node
   * @param  {NodeElement} node node
   * @return {String}
   */
  export const getFirstTextNode = (node) => {
      for (let i = 0; i < node.childNodes.length; i++) {
          let n = node.childNodes[i];
          if (n.nodeType === 3) {
              return n.data;
          }
      }
  };
  
  /**
   * Creates an html element with given collection of attributes
   * @param  {String} tag a string of the html tag to create
   * @param  {Array} an undetermined number of arrays containing the with 2
   *                    items, the attribute name and its value ['id','myId']
   * @return {Object}     created element
   */
  export const createElm = (...args) => {
      let tag = args[0];
      if (!isString(tag)) {
          return null;
      }
  
      let el = doc.createElement(tag);
      for (let i = 0; i < args.length; i++) {
          let arg = args[i];
  
          if (isArray(arg) && arg.length === 2) {
              el.setAttribute(arg[0], arg[1]);
          }
      }
      return el;
  };
  
  /**
   * Removes passed node from DOM
   * @param  {DOMElement} node
   * @return {DOMElement} old node reference
   */
  export const removeElm = (node) => node.parentNode.removeChild(node);
  
  /**
   * Returns a text node with given text
   * @param  {String} txt
   * @return {Object}
   */
  export const createText = (txt) => doc.createTextNode(txt);
  
  /**
   * Determine whether the passed elements is assigned the given class
   * @param {DOMElement} ele DOM element
   * @param {String} cls CSS class name
   * @returns {Boolean}
   */
  export const hasClass = (ele, cls) => {
      if (isUndef(ele)) {
          return false;
      }
  
      if (supportsClassList()) {
          return ele.classList.contains(cls);
      }
      return ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
  };
  
  /**
   * Adds the specified class to the passed element
   * @param {DOMElement} ele DOM element
   * @param {String} cls CSS class name
   */
  export const addClass = (ele, cls) => {
      if (isUndef(ele)) {
          return;
      }
  
      if (supportsClassList()) {
          ele.classList.add(cls);
          return;
      }
  
      if (ele.className === '') {
          ele.className = cls;
      }
      else if (!hasClass(ele, cls)) {
          ele.className += ' ' + cls;
      }
  };
  
  /**
   * Removes the specified class to the passed element
   * @param {DOMElement} ele DOM element
   * @param {String} cls CSS class name
   */
  export const removeClass = (ele, cls) => {
      if (isUndef(ele)) {
          return;
      }
  
      if (supportsClassList()) {
          ele.classList.remove(cls);
          return;
      }
      let reg = new RegExp('(\\s|^)' + cls + '(\\s|$)', 'g');
      ele.className = ele.className.replace(reg, '');
  };
  
  /**
   * Creates and returns an option element
   * @param  {String}  text  option text
   * @param  {String}  value option value
   * @param  {Boolean} isSel whether option is selected
   * @return {Object}        option element
   */
  export const createOpt = (text, value, isSel) => {
      let isSelected = isSel ? true : false;
      let opt = isSelected ?
          createElm('option', ['value', value], ['selected', 'true']) :
          createElm('option', ['value', value]);
      opt.appendChild(createText(text));
      return opt;
  };
  
  /**
   * Creates and returns a checklist item
   * @param  {String} id  index of check item
   * @param  {String} chkValue  check item value
   * @param  {String} labelText check item label text
   * @param  {Array} extraAttr  array containing attribute name and its value
   * @return {Object}           li DOM element
   */
  export const createCheckItem = (id, chkValue, labelText, extraAttr = []) => {
      let li = createElm('li');
      let label = createElm('label', ['for', id]);
      let check = createElm('input',
          ['id', id],
          ['name', id],
          ['type', 'checkbox'],
          ['value', chkValue],
          extraAttr
      );
      label.appendChild(check);
      label.appendChild(createText(labelText));
      li.appendChild(label);
      li.label = label;
      li.check = check;
      return li;
  };
  
  /**
   * Returns the element matching the supplied Id
   * @param  {String} id  Element identifier
   * @return {DOMElement}
   */
  export const elm = (id) => doc.getElementById(id);
  
  /**
   * Returns list of element matching the supplied tag name
   * @param  {String} tagname  Tag name
   * @return {NodeList}
   */
  export const tag = (o, tagname) => o.getElementsByTagName(tagname);
  
  // HTML5 classList API
  function supportsClassList() {
      return doc.documentElement.classList;
  }
  