@constructor JSONEditor
@param {Element} container    Container element
@param {Object}  [options]    Object with options. available options:
{String} mode        Editor mode. Available values:
'tree' (default), 'view',
'form', 'text', and 'code'.
{function} onChange  Callback method, triggered
on change of contents.
Does not pass the contents itself.
See also `onChangeJSON` and
`onChangeText`.
{function} onChangeJSON  Callback method, triggered
in modes on change of contents,
passing the changed contents
as JSON.
Only applicable for modes
'tree', 'view', and 'form'.
{function} onChangeText  Callback method, triggered
in modes on change of contents,
passing the changed contents
as stringified JSON.
{function} onError   Callback method, triggered
when an error occurs
{Boolean} search     Enable search box.
True by default
Only applicable for modes
'tree', 'view', and 'form'
{Boolean} history    Enable history (undo/redo).
True by default
Only applicable for modes
'tree', 'view', and 'form'
{String} name        Field name for the root node.
Only applicable for modes
'tree', 'view', and 'form'
{Number} indentation     Number of indentation
spaces. 4 by default.
Only applicable for
modes 'text' and 'code'
{boolean} escapeUnicode  If true, unicode
characters are escaped.
false by default.
{boolean} sortObjectKeys If true, object keys are
sorted before display.
false by default.
{function} onSelectionChange Callback method,
triggered on node selection change
Only applicable for modes
'tree', 'view', and 'form'
{function} onTextSelectionChange Callback method,
triggered on text selection change
Only applicable for modes
{HTMLElement} modalAnchor        The anchor element to apply an
overlay and display the modals in a
centered location.
Defaults to document.body
'text' and 'code'
{function} onEvent Callback method, triggered
when an event occurs in
a JSON field or value.
Only applicable for
modes 'form', 'tree' and
'view'
{function} onClassName Callback method, triggered
when a Node DOM is rendered. Function returns
a css class name to be set on a node.
Only applicable for
modes 'form', 'tree' and
'view'
{Number} maxVisibleChilds Number of children allowed for a node
in 'tree', 'view', or 'form' mode before
the "show more/show all" buttons appear.
100 by default.

@param {Object | undefined} json JSON object
function JSONEditor (container, options, json) {
  if (!(this instanceof JSONEditor)) {
    throw new Error('JSONEditor constructor called without "new".');
  }

  // check for unsupported browser (IE8 and older)
  var ieVersion = util.getInternetExplorerVersion();
  if (ieVersion != -1 && ieVersion < 9) {
    throw new Error('Unsupported browser, IE9 or newer required. ' +
        'Please install the newest version of your browser.');
  }

  if (options) {
    // check for deprecated options
    if (options.error) {
      console.warn('Option "error" has been renamed to "onError"');
      options.onError = options.error;
      delete options.error;
    }
    if (options.change) {
      console.warn('Option "change" has been renamed to "onChange"');
      options.onChange = options.change;
      delete options.change;
    }
    if (options.editable) {
      console.warn('Option "editable" has been renamed to "onEditable"');
      options.onEditable = options.editable;
      delete options.editable;
    }

    // warn if onChangeJSON is used when mode can be `text` or `code`
    if (options.onChangeJSON) {
      if (options.mode === 'text' || options.mode === 'code' ||
          (options.modes && (options.modes.indexOf('text') !== -1 || options.modes.indexOf('code') !== -1))) {
        console.warn('Option "onChangeJSON" is not applicable to modes "text" and "code". ' +
            'Use "onChangeText" or "onChange" instead.');
      }
    }

    // validate options
    if (options) {
      Object.keys(options).forEach(function (option) {
        if (JSONEditor.VALID_OPTIONS.indexOf(option) === -1) {
          console.warn('Unknown option "' + option + '". This option will be ignored');
        }
      });
    }
  }

  if (arguments.length) {
    this._create(container, options, json);
  }
}