whole_func_string: function(textNodes, range) {
        var firstNode = textNodes[0], lastNode = textNodes[textNodes.length - 1];
  
        var merges = [], currentMerge;
  
        var rangeStartNode = firstNode, rangeEndNode = lastNode;
        var rangeStartOffset = 0, rangeEndOffset = lastNode.length;
  
        var textNode, precedingTextNode;
  
        for (var i = 0, len = textNodes.length; i < len; ++i) {
          textNode = textNodes[i];
          precedingTextNode = this.getAdjacentMergeableTextNode(textNode.parentNode, false);
          if (precedingTextNode) {
            if (!currentMerge) {
              currentMerge = new Merge(precedingTextNode);
              merges.push(currentMerge);
            }
            currentMerge.textNodes.push(textNode);
            if (textNode === firstNode) {
              rangeStartNode = currentMerge.firstTextNode;
              rangeStartOffset = rangeStartNode.length;
            }
            if (textNode === lastNode) {
              rangeEndNode = currentMerge.firstTextNode;
              rangeEndOffset = currentMerge.getLength();
            }
          } else {
            currentMerge = null;
          }
        }
  
        // Test whether the first node after the range needs merging
        var nextTextNode = this.getAdjacentMergeableTextNode(lastNode.parentNode, true);
        if (nextTextNode) {
          if (!currentMerge) {
            currentMerge = new Merge(lastNode);
            merges.push(currentMerge);
          }
          currentMerge.textNodes.push(nextTextNode);
        }
  
        // Do the merges
        if (merges.length) {
          for (i = 0, len = merges.length; i < len; ++i) {
            merges[i].doMerge();
          }
          // Set the range boundaries
          range.setStart(rangeStartNode, rangeStartOffset);
          range.setEnd(rangeEndNode, rangeEndOffset);
        }
      }
func_code_string: function(textNodes, range) {
        var firstNode = textNodes[0], lastNode = textNodes[textNodes.length - 1];
  
        var merges = [], currentMerge;
  
        var rangeStartNode = firstNode, rangeEndNode = lastNode;
        var rangeStartOffset = 0, rangeEndOffset = lastNode.length;
  
        var textNode, precedingTextNode;
  
        for (var i = 0, len = textNodes.length; i < len; ++i) {
          textNode = textNodes[i];
          precedingTextNode = this.getAdjacentMergeableTextNode(textNode.parentNode, false);
          if (precedingTextNode) {
            if (!currentMerge) {
              currentMerge = new Merge(precedingTextNode);
              merges.push(currentMerge);
            }
            currentMerge.textNodes.push(textNode);
            if (textNode === firstNode) {
              rangeStartNode = currentMerge.firstTextNode;
              rangeStartOffset = rangeStartNode.length;
            }
            if (textNode === lastNode) {
              rangeEndNode = currentMerge.firstTextNode;
              rangeEndOffset = currentMerge.getLength();
            }
          } else {
            currentMerge = null;
          }
        }
  
        // Test whether the first node after the range needs merging
        var nextTextNode = this.getAdjacentMergeableTextNode(lastNode.parentNode, true);
        if (nextTextNode) {
          if (!currentMerge) {
            currentMerge = new Merge(lastNode);
            merges.push(currentMerge);
          }
          currentMerge.textNodes.push(nextTextNode);
        }
  
        // Do the merges
        if (merges.length) {
          for (i = 0, len = merges.length; i < len; ++i) {
            merges[i].doMerge();
          }
          // Set the range boundaries
          range.setStart(rangeStartNode, rangeStartOffset);
          range.setEnd(rangeEndNode, rangeEndOffset);
        }
      }
func_documentation_string: Normalizes nodes after applying a CSS class to a Range.