whole_func_string: function showTransformModal (node, container) {
    var value = node.getValue();
  
    var content = '<label class="pico-modal-contents">' +
        '<div class="pico-modal-header">' + translate('transform') + '</div>' +
        '<p>' +
        'Enter a <a href="http://jmespath.org" target="_blank">JMESPath</a> query to filter, sort, or transform the JSON data.<br/>' +
        'To learn JMESPath, go to <a href="http://jmespath.org/tutorial.html" target="_blank">the interactive tutorial</a>.' +
        '</p>' +
        '<div class="jsoneditor-jmespath-label">' + translate('transformWizardLabel') + ' </div>' +
        '<div id="wizard" class="jsoneditor-jmespath-block jsoneditor-jmespath-wizard">' +
        '  <table class="jsoneditor-jmespath-wizard-table">' +
        '    <tbody>' +
        '      <tr>' +
        '        <th>' + translate('transformWizardFilter') + '</th>' +
        '        <td class="jsoneditor-jmespath-filter">' +
        '          <div class="jsoneditor-inline jsoneditor-jmespath-filter-field" >' +
        '            <select id="filterField">' +
        '            </select>' +
        '          </div>' +
        '          <div class="jsoneditor-inline jsoneditor-jmespath-filter-relation" >' +
        '            <select id="filterRelation">' +
        '              <option value="==">==</option>' +
        '              <option value="!=">!=</option>' +
        '              <option value="<">&lt;</option>' +
        '              <option value="<=">&lt;=</option>' +
        '              <option value=">">&gt;</option>' +
        '              <option value=">=">&gt;=</option>' +
        '            </select>' +
        '          </div>' +
        '          <div class="jsoneditor-inline jsoneditor-jmespath-filter-value" >' +
        '            <input placeholder="value..." id="filterValue" />' +
        '          </div>' +
        '        </td>' +
        '      </tr>' +
        '      <tr>' +
        '        <th>' + translate('transformWizardSortBy') + '</th>' +
        '        <td class="jsoneditor-jmespath-filter">' +
        '          <div class="jsoneditor-inline jsoneditor-jmespath-sort-field">' +
        '            <select id="sortField">' +
        '            </select>' +
        '          </div>' +
        '          <div class="jsoneditor-inline jsoneditor-jmespath-sort-order" >' +
        '            <select id="sortOrder">' +
        '              <option value="asc">Ascending</option>' +
        '              <option value="desc">Descending</option>' +
        '            </select>' +
        '          </div>' +
        '        </td>' +
        '      </tr>' +
        '      <tr id="selectFieldsPart">' +
        '        <th>' + translate('transformWizardSelectFields') + '</th>' +
        '        <td class="jsoneditor-jmespath-filter">' +
        '          <select class="jsoneditor-jmespath-select-fields" id="selectFields" multiple></select>' +
        '        </td>' +
        '      </tr>' +
        '    </tbody>' +
        '  </table>' +
        '</div>' +
        '<div class="jsoneditor-jmespath-label">' + translate('transformQueryLabel') + ' </div>' +
        '<div class="jsoneditor-jmespath-block">' +
        '  <textarea id="query" ' +
        '            rows="4" ' +
        '            autocomplete="off" ' +
        '            autocorrect="off" ' +
        '            autocapitalize="off" ' +
        '            spellcheck="false"' +
        '            title="' + translate('transformQueryTitle') + '">[*]</textarea>' +
        '</div>' +
        '<div class="jsoneditor-jmespath-label">' + translate('transformPreviewLabel') + ' </div>' +
        '<div class="jsoneditor-jmespath-block">' +
        '  <textarea id="preview" ' +
        '      class="jsoneditor-transform-preview"' +
        '      readonly> </textarea>' +
        '</div>' +
        '<div class="jsoneditor-jmespath-block jsoneditor-modal-actions">' +
        '  <input type="submit" id="ok" value="' + translate('ok') + '" autofocus />' +
        '</div>' +
        '</div>';
  
    picoModal({
      parent: container,
      content: content,
      overlayClass: 'jsoneditor-modal-overlay',
      modalClass: 'jsoneditor-modal jsoneditor-modal-transform',
      focus: false
    })
        .afterCreate(function (modal) {
          var elem = modal.modalElem();
  
          var wizard = elem.querySelector('#wizard');
          var ok = elem.querySelector('#ok');
          var filterField = elem.querySelector('#filterField');
          var filterRelation = elem.querySelector('#filterRelation');
          var filterValue = elem.querySelector('#filterValue');
          var sortField = elem.querySelector('#sortField');
          var sortOrder = elem.querySelector('#sortOrder');
          var selectFields = elem.querySelector('#selectFields');
          var query = elem.querySelector('#query');
          var preview = elem.querySelector('#preview');
  
          if (!Array.isArray(value)) {
            wizard.style.fontStyle = 'italic';
            wizard.innerHTML = '(wizard not available for objects, only for arrays)'
          }
  
          var paths = node.getChildPaths();
          paths.forEach(function (path) {
            var formattedPath = preprocessPath(path);
            var filterOption = document.createElement('option');
            filterOption.text = formattedPath;
            filterOption.value = formattedPath;
            filterField.appendChild(filterOption);
  
            var sortOption = document.createElement('option');
            sortOption.text = formattedPath;
            sortOption.value = formattedPath;
            sortField.appendChild(sortOption);
          });
  
          var allPaths = node.getChildPaths(true).filter(function(path) {
            return path !== '.';
          });
  
          if (allPaths.length > 0) {
            allPaths.forEach(function (path) {
              var formattedPath = preprocessPath(path);
              var option = document.createElement('option');
              option.text = formattedPath;
              option.value = formattedPath;
              selectFields.appendChild(option);
            });
          }
          else {
            var selectFieldsPart = elem.querySelector('#selectFieldsPart');
            if (selectFieldsPart) {
              selectFieldsPart.style.display = 'none';
            }
          }
  
          var selectrFilterField = new Selectr(filterField, { defaultSelected: false, clearable: true, allowDeselect: true, placeholder: 'field...' });
          var selectrFilterRelation = new Selectr(filterRelation, { defaultSelected: false, clearable: true, allowDeselect: true, placeholder: 'compare...' });
          var selectrSortField = new Selectr(sortField, { defaultSelected: false, clearable: true, allowDeselect: true, placeholder: 'field...' });
          var selectrSortOrder = new Selectr(sortOrder, { defaultSelected: false, clearable: true, allowDeselect: true, placeholder: 'order...' });
          var selectrSelectFields = new Selectr(selectFields, {multiple: true, clearable: true, defaultSelected: false, placeholder: 'select fields...'});
  
          selectrFilterField.on('selectr.change', generateQueryFromWizard);
          selectrFilterRelation.on('selectr.change', generateQueryFromWizard);
          filterValue.oninput = generateQueryFromWizard;
          selectrSortField.on('selectr.change', generateQueryFromWizard);
          selectrSortOrder.on('selectr.change', generateQueryFromWizard);
          selectrSelectFields.on('selectr.change', generateQueryFromWizard);
  
          elem.querySelector('.pico-modal-contents').onclick = function (event) {
            // prevent the first clear button (in any select box) from getting
            // focus when clicking anywhere in the modal. Only allow clicking links.
            if (event.target.nodeName !== 'A') {
              event.preventDefault();
            }
          };
  
          query.value = Array.isArray(value) ? '[*]' : '@';
  
          function preprocessPath(path) {
            if (path[0] === '.') {
              return (path === '.')
                  ? '@'
                  : path.slice(1);
            }
            else {
              return path;
            }
          }
  
          function generateQueryFromWizard () {
            if (filterField.value && filterRelation.value && filterValue.value) {
              var field1 = filterField.value;
              var examplePath = field1 !== '@'
                  ? ['0'].concat(util.parsePath('.' + field1))
                  : ['0']
              var exampleValue = util.get(value, examplePath)
              // TODO: move _stringCast into a static util function
              var value1 = typeof exampleValue === 'string'
                  ? filterValue.value
                  : node._stringCast(filterValue.value);
  
              query.value = '[? ' +
                  field1 + ' ' +
                  filterRelation.value + ' ' +
                  '`' + JSON.stringify(value1) + '`' +
                  ']';
            }
            else {
              query.value = '[*]';
            }
  
            if (sortField.value && sortOrder.value) {
              var field2 = sortField.value;
              if (sortOrder.value === 'desc') {
                query.value += ' | reverse(sort_by(@, &' + field2 + '))';
              }
              else {
                query.value += ' | sort_by(@, &' + field2 + ')';
              }
            }
  
            if (selectFields.value) {
              var values = [];
              for (var i=0; i < selectFields.options.length; i++) {
                if (selectFields.options[i].selected) {
                  var selectedValue = selectFields.options[i].value;
                  values.push(selectedValue);
                }
              }
  
              if (query.value[query.value.length - 1] !== ']') {
                query.value += ' | [*]';
              }
  
              if (values.length === 1) {
                query.value += '.' + selectedValue;
              }
              else if (values.length > 1) {
                query.value += '.{' +
                    values.map(function (value) {
                      var parts = value.split('.');
                      var last = parts[parts.length - 1];
                      return last + ': ' + selectedValue;
                    }).join(', ') +
                    '}';
              }
              else { // values.length === 0
                // ignore
              }
            }
  
            debouncedUpdatePreview();
          }
  
          function updatePreview() {
            try {
              var transformed = jmespath.search(value, query.value);
              var lines =  JSON.stringify(transformed, null, 2).split('\n');
  
              if (lines.length > MAX_PREVIEW_LINES) {
                lines = lines.slice(0, MAX_PREVIEW_LINES).concat(['...'])
              }
  
  
              preview.className = 'jsoneditor-transform-preview';
              preview.value = lines.join('\n');
              ok.disabled = false;
            }
            catch (err) {
              preview.className = 'jsoneditor-transform-preview jsoneditor-error';
              preview.value = err.toString();
              ok.disabled = true;
            }
          }
  
          var debouncedUpdatePreview = debounce(updatePreview, 300);
  
          query.oninput = debouncedUpdatePreview;
          debouncedUpdatePreview();
  
          ok.onclick = function (event) {
            event.preventDefault();
            event.stopPropagation();
  
            modal.close();
  
            node.transform(query.value)
          };
  
          setTimeout(function () {
            query.select();
            query.focus();
            query.selectionStart = 3;
            query.selectionEnd = 3;
          });
        })
        .afterClose(function (modal) {
          modal.destroy();
        })
        .show();
  }
func_code_string: function showTransformModal (node, container) {
    var value = node.getValue();
  
    var content = '<label class="pico-modal-contents">' +
        '<div class="pico-modal-header">' + translate('transform') + '</div>' +
        '<p>' +
        'Enter a <a href="http://jmespath.org" target="_blank">JMESPath</a> query to filter, sort, or transform the JSON data.<br/>' +
        'To learn JMESPath, go to <a href="http://jmespath.org/tutorial.html" target="_blank">the interactive tutorial</a>.' +
        '</p>' +
        '<div class="jsoneditor-jmespath-label">' + translate('transformWizardLabel') + ' </div>' +
        '<div id="wizard" class="jsoneditor-jmespath-block jsoneditor-jmespath-wizard">' +
        '  <table class="jsoneditor-jmespath-wizard-table">' +
        '    <tbody>' +
        '      <tr>' +
        '        <th>' + translate('transformWizardFilter') + '</th>' +
        '        <td class="jsoneditor-jmespath-filter">' +
        '          <div class="jsoneditor-inline jsoneditor-jmespath-filter-field" >' +
        '            <select id="filterField">' +
        '            </select>' +
        '          </div>' +
        '          <div class="jsoneditor-inline jsoneditor-jmespath-filter-relation" >' +
        '            <select id="filterRelation">' +
        '              <option value="==">==</option>' +
        '              <option value="!=">!=</option>' +
        '              <option value="<">&lt;</option>' +
        '              <option value="<=">&lt;=</option>' +
        '              <option value=">">&gt;</option>' +
        '              <option value=">=">&gt;=</option>' +
        '            </select>' +
        '          </div>' +
        '          <div class="jsoneditor-inline jsoneditor-jmespath-filter-value" >' +
        '            <input placeholder="value..." id="filterValue" />' +
        '          </div>' +
        '        </td>' +
        '      </tr>' +
        '      <tr>' +
        '        <th>' + translate('transformWizardSortBy') + '</th>' +
        '        <td class="jsoneditor-jmespath-filter">' +
        '          <div class="jsoneditor-inline jsoneditor-jmespath-sort-field">' +
        '            <select id="sortField">' +
        '            </select>' +
        '          </div>' +
        '          <div class="jsoneditor-inline jsoneditor-jmespath-sort-order" >' +
        '            <select id="sortOrder">' +
        '              <option value="asc">Ascending</option>' +
        '              <option value="desc">Descending</option>' +
        '            </select>' +
        '          </div>' +
        '        </td>' +
        '      </tr>' +
        '      <tr id="selectFieldsPart">' +
        '        <th>' + translate('transformWizardSelectFields') + '</th>' +
        '        <td class="jsoneditor-jmespath-filter">' +
        '          <select class="jsoneditor-jmespath-select-fields" id="selectFields" multiple></select>' +
        '        </td>' +
        '      </tr>' +
        '    </tbody>' +
        '  </table>' +
        '</div>' +
        '<div class="jsoneditor-jmespath-label">' + translate('transformQueryLabel') + ' </div>' +
        '<div class="jsoneditor-jmespath-block">' +
        '  <textarea id="query" ' +
        '            rows="4" ' +
        '            autocomplete="off" ' +
        '            autocorrect="off" ' +
        '            autocapitalize="off" ' +
        '            spellcheck="false"' +
        '            title="' + translate('transformQueryTitle') + '">[*]</textarea>' +
        '</div>' +
        '<div class="jsoneditor-jmespath-label">' + translate('transformPreviewLabel') + ' </div>' +
        '<div class="jsoneditor-jmespath-block">' +
        '  <textarea id="preview" ' +
        '      class="jsoneditor-transform-preview"' +
        '      readonly> </textarea>' +
        '</div>' +
        '<div class="jsoneditor-jmespath-block jsoneditor-modal-actions">' +
        '  <input type="submit" id="ok" value="' + translate('ok') + '" autofocus />' +
        '</div>' +
        '</div>';
  
    picoModal({
      parent: container,
      content: content,
      overlayClass: 'jsoneditor-modal-overlay',
      modalClass: 'jsoneditor-modal jsoneditor-modal-transform',
      focus: false
    })
        .afterCreate(function (modal) {
          var elem = modal.modalElem();
  
          var wizard = elem.querySelector('#wizard');
          var ok = elem.querySelector('#ok');
          var filterField = elem.querySelector('#filterField');
          var filterRelation = elem.querySelector('#filterRelation');
          var filterValue = elem.querySelector('#filterValue');
          var sortField = elem.querySelector('#sortField');
          var sortOrder = elem.querySelector('#sortOrder');
          var selectFields = elem.querySelector('#selectFields');
          var query = elem.querySelector('#query');
          var preview = elem.querySelector('#preview');
  
          if (!Array.isArray(value)) {
            wizard.style.fontStyle = 'italic';
            wizard.innerHTML = '(wizard not available for objects, only for arrays)'
          }
  
          var paths = node.getChildPaths();
          paths.forEach(function (path) {
            var formattedPath = preprocessPath(path);
            var filterOption = document.createElement('option');
            filterOption.text = formattedPath;
            filterOption.value = formattedPath;
            filterField.appendChild(filterOption);
  
            var sortOption = document.createElement('option');
            sortOption.text = formattedPath;
            sortOption.value = formattedPath;
            sortField.appendChild(sortOption);
          });
  
          var allPaths = node.getChildPaths(true).filter(function(path) {
            return path !== '.';
          });
  
          if (allPaths.length > 0) {
            allPaths.forEach(function (path) {
              var formattedPath = preprocessPath(path);
              var option = document.createElement('option');
              option.text = formattedPath;
              option.value = formattedPath;
              selectFields.appendChild(option);
            });
          }
          else {
            var selectFieldsPart = elem.querySelector('#selectFieldsPart');
            if (selectFieldsPart) {
              selectFieldsPart.style.display = 'none';
            }
          }
  
          var selectrFilterField = new Selectr(filterField, { defaultSelected: false, clearable: true, allowDeselect: true, placeholder: 'field...' });
          var selectrFilterRelation = new Selectr(filterRelation, { defaultSelected: false, clearable: true, allowDeselect: true, placeholder: 'compare...' });
          var selectrSortField = new Selectr(sortField, { defaultSelected: false, clearable: true, allowDeselect: true, placeholder: 'field...' });
          var selectrSortOrder = new Selectr(sortOrder, { defaultSelected: false, clearable: true, allowDeselect: true, placeholder: 'order...' });
          var selectrSelectFields = new Selectr(selectFields, {multiple: true, clearable: true, defaultSelected: false, placeholder: 'select fields...'});
  
          selectrFilterField.on('selectr.change', generateQueryFromWizard);
          selectrFilterRelation.on('selectr.change', generateQueryFromWizard);
          filterValue.oninput = generateQueryFromWizard;
          selectrSortField.on('selectr.change', generateQueryFromWizard);
          selectrSortOrder.on('selectr.change', generateQueryFromWizard);
          selectrSelectFields.on('selectr.change', generateQueryFromWizard);
  
          elem.querySelector('.pico-modal-contents').onclick = function (event) {
            // prevent the first clear button (in any select box) from getting
            // focus when clicking anywhere in the modal. Only allow clicking links.
            if (event.target.nodeName !== 'A') {
              event.preventDefault();
            }
          };
  
          query.value = Array.isArray(value) ? '[*]' : '@';
  
          function preprocessPath(path) {
            if (path[0] === '.') {
              return (path === '.')
                  ? '@'
                  : path.slice(1);
            }
            else {
              return path;
            }
          }
  
          function generateQueryFromWizard () {
            if (filterField.value && filterRelation.value && filterValue.value) {
              var field1 = filterField.value;
              var examplePath = field1 !== '@'
                  ? ['0'].concat(util.parsePath('.' + field1))
                  : ['0']
              var exampleValue = util.get(value, examplePath)
              // TODO: move _stringCast into a static util function
              var value1 = typeof exampleValue === 'string'
                  ? filterValue.value
                  : node._stringCast(filterValue.value);
  
              query.value = '[? ' +
                  field1 + ' ' +
                  filterRelation.value + ' ' +
                  '`' + JSON.stringify(value1) + '`' +
                  ']';
            }
            else {
              query.value = '[*]';
            }
  
            if (sortField.value && sortOrder.value) {
              var field2 = sortField.value;
              if (sortOrder.value === 'desc') {
                query.value += ' | reverse(sort_by(@, &' + field2 + '))';
              }
              else {
                query.value += ' | sort_by(@, &' + field2 + ')';
              }
            }
  
            if (selectFields.value) {
              var values = [];
              for (var i=0; i < selectFields.options.length; i++) {
                if (selectFields.options[i].selected) {
                  var selectedValue = selectFields.options[i].value;
                  values.push(selectedValue);
                }
              }
  
              if (query.value[query.value.length - 1] !== ']') {
                query.value += ' | [*]';
              }
  
              if (values.length === 1) {
                query.value += '.' + selectedValue;
              }
              else if (values.length > 1) {
                query.value += '.{' +
                    values.map(function (value) {
                      var parts = value.split('.');
                      var last = parts[parts.length - 1];
                      return last + ': ' + selectedValue;
                    }).join(', ') +
                    '}';
              }
              else { // values.length === 0
                // ignore
              }
            }
  
            debouncedUpdatePreview();
          }
  
          function updatePreview() {
            try {
              var transformed = jmespath.search(value, query.value);
              var lines =  JSON.stringify(transformed, null, 2).split('\n');
  
              if (lines.length > MAX_PREVIEW_LINES) {
                lines = lines.slice(0, MAX_PREVIEW_LINES).concat(['...'])
              }
  
  
              preview.className = 'jsoneditor-transform-preview';
              preview.value = lines.join('\n');
              ok.disabled = false;
            }
            catch (err) {
              preview.className = 'jsoneditor-transform-preview jsoneditor-error';
              preview.value = err.toString();
              ok.disabled = true;
            }
          }
  
          var debouncedUpdatePreview = debounce(updatePreview, 300);
  
          query.oninput = debouncedUpdatePreview;
          debouncedUpdatePreview();
  
          ok.onclick = function (event) {
            event.preventDefault();
            event.stopPropagation();
  
            modal.close();
  
            node.transform(query.value)
          };
  
          setTimeout(function () {
            query.select();
            query.focus();
            query.selectionStart = 3;
            query.selectionEnd = 3;
          });
        })
        .afterClose(function (modal) {
          modal.destroy();
        })
        .show();
  }
func_documentation_string: Show advanced filter and transform modal using JMESPath
  @param {Node} node the node to be transformed
  @param {HTMLElement} container   The container where to center
  the modal and create an overlay