__  __    __   __  _____      _            _          _____ _          _ _ 
 |  \/  |   \ \ / / |  __ \    (_)          | |        / ____| |        | | |
 | \  / |_ __\ V /  | |__) | __ ___   ____ _| |_ ___  | (___ | |__   ___| | |
 | |\/| | '__|> <   |  ___/ '__| \ \ / / _` | __/ _ \  \___ \| '_ \ / _ \ | |
 | |  | | |_ / . \  | |   | |  | |\ V / (_| | ||  __/  ____) | | | |  __/ | |
 |_|  |_|_(_)_/ \_\ |_|   |_|  |_| \_/ \__,_|\__\___| |_____/|_| |_|\___V 2.1
 if you need WebShell for Seo everyday contact me on Telegram
 Telegram Address : @jackleet
        
        
For_More_Tools: Telegram: @jackleet | Bulk Smtp support mail sender | Business Mail Collector | Mail Bouncer All Mail | Bulk Office Mail Validator | Html Letter private



Upload:

Command:

www-data@216.73.216.10: ~ $
/* global firstDayOfCalendar */ // templates/javascript/variables.twig

/**
 * Create advanced table (resize, reorder, and show/hide columns; and also grid editing).
 * This function is designed mainly for table DOM generated from browsing a table in the database.
 * For using this function in other table DOM, you may need to:
 * - add "draggable" class in the table header <th>, in order to make it resizable, sortable or hidable
 * - have at least one non-"draggable" header in the table DOM for placing column visibility drop-down arrow
 * - pass the value "false" for the parameter "enableGridEdit"
 * - adjust other parameter value, to select which features that will be enabled
 *
 * @param t the table DOM element
 * @param enableResize Optional, if false, column resizing feature will be disabled
 * @param enableReorder Optional, if false, column reordering feature will be disabled
 * @param enableVisib Optional, if false, show/hide column feature will be disabled
 * @param enableGridEdit Optional, if false, grid editing feature will be disabled
 */
// eslint-disable-next-line no-unused-vars
var makeGrid = function (t, enableResize, enableReorder, enableVisib, enableGridEdit) {
  var isResizeEnabled = enableResize === undefined ? true : enableResize;
  var isReorderEnabled = enableReorder === undefined ? true : enableReorder;
  var isVisibEnabled = enableVisib === undefined ? true : enableVisib;
  var isGridEditEnabled = enableGridEdit === undefined ? true : enableGridEdit;
  var g = {
    /** *********
     * Constant
     ***********/
    minColWidth: 15,
    /** *********
     * Variables, assigned with default value, changed later
     ***********/
    actionSpan: 5,
    // number of colspan in Actions header in a table
    tableCreateTime: null,
    // table creation time, used for saving column order and visibility to server, only available in "Browse tab"

    // Column reordering variables
    colOrder: [],
    // array of column order

    // Column visibility variables
    colVisib: [],
    // array of column visibility
    showAllColText: '',
    // string, text for "show all" button under column visibility list
    visibleHeadersCount: 0,
    // number of visible data headers

    // Table hint variables
    reorderHint: '',
    // string, hint for column reordering
    sortHint: '',
    // string, hint for column sorting
    markHint: '',
    // string, hint for column marking
    copyHint: '',
    // string, hint for copy column name
    showReorderHint: false,
    showSortHint: false,
    showMarkHint: false,
    // Grid editing
    isCellEditActive: false,
    // true if current focus is in edit cell
    isEditCellTextEditable: false,
    // true if current edit cell is editable in the text input box (not textarea)
    currentEditCell: null,
    // reference to <td> that currently being edited
    cellEditHint: '',
    // hint shown when doing grid edit
    gotoLinkText: '',
    // "Go to link" text
    wasEditedCellNull: false,
    // true if last value of the edited cell was NULL
    maxTruncatedLen: 0,
    // number of characters that can be displayed in a cell
    saveCellsAtOnce: false,
    // $cfg[saveCellsAtOnce]
    isCellEdited: false,
    // true if at least one cell has been edited
    saveCellWarning: '',
    // string, warning text when user want to leave a page with unsaved edited data
    lastXHR: null,
    // last XHR object used in AJAX request
    isSaving: false,
    // true when currently saving edited data, used to handle double posting caused by pressing ENTER in grid edit text box in Chrome browser
    alertNonUnique: '',
    // string, alert shown when saving edited nonunique table

    // Common hidden inputs
    token: null,
    server: null,
    db: null,
    table: null,
    /** **********
     * Functions
     ************/

    /**
     * Start to resize column. Called when clicking on column separator.
     *
     * @param e event
     * @param obj dragged div object
     */
    dragStartRsz: function (e, obj) {
      var n = $(g.cRsz).find('div').index(obj); // get the index of separator (i.e., column index)
      $(obj).addClass('colborder_active');
      g.colRsz = {
        x0: e.pageX,
        n: n,
        obj: obj,
        objLeft: $(obj).position().left,
        objWidth: $(g.t).find('th.draggable:visible').eq(n).find('span').outerWidth()
      };
      // eslint-disable-next-line compat/compat
      $(document.body).css('cursor', 'col-resize').noSelect();
      if (g.isCellEditActive) {
        g.hideEditCell();
      }
    },
    /**
     * Start to reorder column. Called when clicking on table header.
     *
     * @param e event
     * @param obj table header object
     */
    dragStartReorder: function (e, obj) {
      // prepare the cCpy (column copy) and cPointer (column pointer) from the dragged column
      $(g.cCpy).text($(obj).text());
      var objPos = $(obj).position();
      $(g.cCpy).css({
        top: objPos.top + 20,
        left: objPos.left,
        height: $(obj).height(),
        width: $(obj).width()
      });
      $(g.cPointer).css({
        top: objPos.top
      });

      // get the column index, zero-based
      var n = g.getHeaderIdx(obj);
      g.colReorder = {
        x0: e.pageX,
        y0: e.pageY,
        n: n,
        newn: n,
        obj: obj,
        objTop: objPos.top,
        objLeft: objPos.left
      };

      // eslint-disable-next-line compat/compat
      $(document.body).css('cursor', 'move').noSelect();
      if (g.isCellEditActive) {
        g.hideEditCell();
      }
    },
    /**
     * Handle mousemove event when dragging.
     *
     * @param e event
     */
    dragMove: function (e) {
      var dx;
      if (g.colRsz) {
        dx = e.pageX - g.colRsz.x0;
        if (g.colRsz.objWidth + dx > g.minColWidth) {
          $(g.colRsz.obj).css('left', g.colRsz.objLeft + dx + 'px');
        }
      } else if (g.colReorder) {
        // dragged column animation
        dx = e.pageX - g.colReorder.x0;
        $(g.cCpy).css('left', g.colReorder.objLeft + dx).show();

        // pointer animation
        var hoveredCol = g.getHoveredCol(e);
        if (hoveredCol) {
          var newn = g.getHeaderIdx(hoveredCol);
          g.colReorder.newn = newn;
          if (newn !== g.colReorder.n) {
            // show the column pointer in the right place
            var colPos = $(hoveredCol).position();
            var newleft = newn < g.colReorder.n ? colPos.left : colPos.left + $(hoveredCol).outerWidth();
            $(g.cPointer).css({
              left: newleft,
              visibility: 'visible'
            });
          } else {
            // no movement to other column, hide the column pointer
            $(g.cPointer).css('visibility', 'hidden');
          }
        }
      }
    },
    /**
     * Stop the dragging action.
     *
     * @param e event
     */
    dragEnd: function (e) {
      if (g.colRsz) {
        var dx = e.pageX - g.colRsz.x0;
        var nw = g.colRsz.objWidth + dx;
        if (nw < g.minColWidth) {
          nw = g.minColWidth;
        }
        var n = g.colRsz.n;
        // do the resizing
        g.resize(n, nw);
        g.reposRsz();
        g.reposDrop();
        g.colRsz = false;
        $(g.cRsz).find('div').removeClass('colborder_active');
      } else if (g.colReorder) {
        // shift columns
        if (g.colReorder.newn !== g.colReorder.n) {
          g.shiftCol(g.colReorder.n, g.colReorder.newn);
          // assign new position
          var objPos = $(g.colReorder.obj).position();
          g.colReorder.objTop = objPos.top;
          g.colReorder.objLeft = objPos.left;
          g.colReorder.n = g.colReorder.newn;
          // send request to server to remember the column order
          if (g.tableCreateTime) {
            g.sendColPrefs();
          }
          g.refreshRestoreButton();
        }

        // animate new column position
        $(g.cCpy).stop(true, true).animate({
          top: g.colReorder.objTop,
          left: g.colReorder.objLeft
        }, 'fast').fadeOut();
        $(g.cPointer).css('visibility', 'hidden');
        g.colReorder = false;
      }
      // eslint-disable-next-line compat/compat
      $(document.body).css('cursor', 'inherit').noSelect(false);
    },
    /**
     * Resize column n to new width "nw"
     *
     * @param n zero-based column index
     * @param nw new width of the column in pixel
     */
    resize: function (n, nw) {
      $(g.t).find('tr').each(function () {
        $(this).find('th.draggable:visible').eq(n).find('span').add($(this).find('td:visible').eq(g.actionSpan + n).find('span')).css('width', nw);
      });
    },
    /**
     * Reposition column resize bars.
     */
    reposRsz: function () {
      $(g.cRsz).find('div').hide();
      var $firstRowCols = $(g.t).find('tr').first().find('th.draggable:visible');
      var $resizeHandles = $(g.cRsz).find('div').removeClass('condition');
      $(g.t).find('table.pma_table').find('thead th').first().removeClass('before-condition');
      for (var n = 0, l = $firstRowCols.length; n < l; n++) {
        var $col = $($firstRowCols[n]);
        var colWidth;
        if (navigator.userAgent.toLowerCase().indexOf('safari') !== -1) {
          colWidth = $col.outerWidth();
        } else {
          colWidth = $col.outerWidth(true);
        }
        $($resizeHandles[n]).css('left', $col.position().left + colWidth).show();
        if ($col.hasClass('condition')) {
          $($resizeHandles[n]).addClass('condition');
          if (n > 0) {
            $($resizeHandles[n - 1]).addClass('condition');
          }
        }
      }
      if ($($resizeHandles[0]).hasClass('condition')) {
        $(g.t).find('thead th').first().addClass('before-condition');
      }
      $(g.cRsz).css('height', $(g.t).height());
    },
    /**
     * Shift column from index oldn to newn.
     *
     * @param oldn old zero-based column index
     * @param newn new zero-based column index
     */
    shiftCol: function (oldn, newn) {
      $(g.t).find('tr').each(function () {
        if (newn < oldn) {
          $(this).find('th.draggable').eq(newn).add($(this).find('td').eq(g.actionSpan + newn)).before($(this).find('th.draggable').eq(oldn).add($(this).find('td').eq(g.actionSpan + oldn)));
        } else {
          $(this).find('th.draggable').eq(newn).add($(this).find('td').eq(g.actionSpan + newn)).after($(this).find('th.draggable').eq(oldn).add($(this).find('td').eq(g.actionSpan + oldn)));
        }
      });
      // reposition the column resize bars
      g.reposRsz();

      // adjust the column visibility list
      if (newn < oldn) {
        $(g.cList).find('.lDiv div').eq(newn).before($(g.cList).find('.lDiv div').eq(oldn));
      } else {
        $(g.cList).find('.lDiv div').eq(newn).after($(g.cList).find('.lDiv div').eq(oldn));
      }
      // adjust the colOrder
      var tmp = g.colOrder[oldn];
      g.colOrder.splice(oldn, 1);
      g.colOrder.splice(newn, 0, tmp);
      // adjust the colVisib
      if (g.colVisib.length > 0) {
        tmp = g.colVisib[oldn];
        g.colVisib.splice(oldn, 1);
        g.colVisib.splice(newn, 0, tmp);
      }
    },
    /**
     * Find currently hovered table column's header (excluding actions column).
     *
     * @param e event
     * @return {object|undefined} the hovered column's th object or undefined if no hovered column found.
     */
    getHoveredCol: function (e) {
      var hoveredCol;
      var $headers = $(g.t).find('th.draggable:visible');
      $headers.each(function () {
        var left = $(this).offset().left;
        var right = left + $(this).outerWidth();
        if (left <= e.pageX && e.pageX <= right) {
          hoveredCol = this;
        }
      });
      return hoveredCol;
    },
    /**
     * Get a zero-based index from a <th class="draggable"> tag in a table.
     *
     * @param obj table header <th> object
     * @return {number} zero-based index of the specified table header in the set of table headers (visible or not)
     */
    getHeaderIdx: function (obj) {
      return $(obj).parents('tr').find('th.draggable').index(obj);
    },
    /**
     * Reposition the columns back to normal order.
     */
    restoreColOrder: function () {
      // use insertion sort, since we already have shiftCol function
      for (var i = 1; i < g.colOrder.length; i++) {
        var x = g.colOrder[i];
        var j = i - 1;
        while (j >= 0 && x < g.colOrder[j]) {
          j--;
        }
        if (j !== i - 1) {
          g.shiftCol(i, j + 1);
        }
      }
      if (g.tableCreateTime) {
        // send request to server to remember the column order
        g.sendColPrefs();
      }
      g.refreshRestoreButton();
    },
    /**
     * Send column preferences (column order and visibility) to the server.
     */
    sendColPrefs: function () {
      if ($(g.t).is('.ajax')) {
        // only send preferences if ajax class
        if (typeof g.db !== 'string' && typeof g.table !== 'string') {
          // The server has nothing to do with it
          // Issue: https://github.com/phpmyadmin/phpmyadmin/issues/15658
          return;
        }
        var postParams = {
          'ajax_request': true,
          'db': g.db,
          'table': g.table,
          'token': g.token,
          'server': g.server,
          'table_create_time': g.tableCreateTime
        };
        if (g.colOrder.length > 0) {
          $.extend(postParams, {
            'col_order': g.colOrder.toString()
          });
        }
        if (g.colVisib.length > 0) {
          $.extend(postParams, {
            'col_visib': g.colVisib.toString()
          });
        }
        $.post('index.php?route=/sql/set-column-preferences', postParams, function (data) {
          if (data.success !== true) {
            var $tempDiv = $(document.createElement('div'));
            $tempDiv.html(data.error);
            $tempDiv.addClass('alert alert-danger');
            Functions.ajaxShowMessage($tempDiv, false);
          }
        });
      }
    },
    /**
     * Refresh restore button state.
     * Make restore button disabled if the table is similar with initial state.
     */
    refreshRestoreButton: function () {
      // check if table state is as initial state
      var isInitial = true;
      for (var i = 0; i < g.colOrder.length; i++) {
        if (g.colOrder[i] !== i) {
          isInitial = false;
          break;
        }
      }
      // check if only one visible column left
      var isOneColumn = g.visibleHeadersCount === 1;
      // enable or disable restore button
      if (isInitial || isOneColumn) {
        $(g.o).find('div.restore_column').hide();
      } else {
        $(g.o).find('div.restore_column').show();
      }
    },
    /**
     * Update current hint using the boolean values (showReorderHint, showSortHint, etc.).
     *
     * @return {string}
     *
     */
    updateHint: function () {
      var text = '';
      if (!g.colRsz && !g.colReorder) {
        // if not resizing or dragging
        if (g.visibleHeadersCount > 1) {
          g.showReorderHint = true;
        }
        if ($(t).find('th.marker').length > 0) {
          g.showMarkHint = true;
        }
        if (g.showSortHint && g.sortHint) {
          text += text.length > 0 ? '<br>' : '';
          text += '- ' + g.sortHint;
        }
        if (g.showMultiSortHint && g.strMultiSortHint) {
          text += text.length > 0 ? '<br>' : '';
          text += '- ' + g.strMultiSortHint;
        }
        if (g.showMarkHint && g.markHint && !g.showSortHint &&
        // we do not show mark hint, when sort hint is shown
        g.showReorderHint && g.reorderHint) {
          text += text.length > 0 ? '<br>' : '';
          text += '- ' + g.reorderHint;
          text += text.length > 0 ? '<br>' : '';
          text += '- ' + g.markHint;
          text += text.length > 0 ? '<br>' : '';
          text += '- ' + g.copyHint;
        }
      }
      return text;
    },
    /**
     * Toggle column's visibility.
     * After calling this function and it returns true, afterToggleCol() must be called.
     *
     * @param {number} n
     *
     * @return {boolean} True if the column is toggled successfully.
     */
    toggleCol: function (n) {
      if (g.colVisib[n]) {
        // can hide if more than one column is visible
        if (g.visibleHeadersCount > 1) {
          $(g.t).find('tr').each(function () {
            $(this).find('th.draggable').eq(n).add($(this).find('td').eq(g.actionSpan + n)).hide();
          });
          g.colVisib[n] = 0;
          $(g.cList).find('.lDiv div').eq(n).find('input').prop('checked', false);
        } else {
          // cannot hide, force the checkbox to stay checked
          $(g.cList).find('.lDiv div').eq(n).find('input').prop('checked', true);
          return false;
        }
      } else {
        // column n is not visible
        $(g.t).find('tr').each(function () {
          $(this).find('th.draggable').eq(n).add($(this).find('td').eq(g.actionSpan + n)).show();
        });
        g.colVisib[n] = 1;
        $(g.cList).find('.lDiv div').eq(n).find('input').prop('checked', true);
      }
      return true;
    },
    /**
     * This must be called if toggleCol() returns is true.
     *
     * This function is separated from toggleCol because, sometimes, we want to toggle
     * some columns together at one time and do just one adjustment after it, e.g. in showAllColumns().
     */
    afterToggleCol: function () {
      // some adjustments after hiding column
      g.reposRsz();
      g.reposDrop();
      g.sendColPrefs();

      // check visible first row headers count
      g.visibleHeadersCount = $(g.t).find('tr').first().find('th.draggable:visible').length;
      g.refreshRestoreButton();

      // Display minimum of one column - disable checkbox for hiding last column
      if (g.visibleHeadersCount <= 1) {
        $(g.cList).find('.lDiv div').each(function () {
          $(this).find('input:checkbox:checked').prop('disabled', true);
        });
      } else {
        // Remove disabled property if showing more than one column
        $(g.cList).find('.lDiv div').each(function () {
          $(this).find('input:checkbox:disabled').prop('disabled', false);
        });
      }
    },
    /**
     * Show columns' visibility list.
     *
     * @param obj The drop down arrow of column visibility list
     */
    showColList: function (obj) {
      // only show when not resizing or reordering
      if (!g.colRsz && !g.colReorder) {
        var pos = $(obj).position();
        $(g.cList).css({
          top: pos.top + $(obj).outerHeight(true)
        }).show();
        $(obj).addClass('coldrop-hover');
      }
    },
    /**
     * Hide columns' visibility list.
     */
    hideColList: function () {
      $(g.cList).hide();
      $(g.cDrop).find('.coldrop-hover').removeClass('coldrop-hover');
    },
    /**
     * Reposition the column visibility drop-down arrow.
     */
    reposDrop: function () {
      var $th = $(t).find('th:not(.draggable)');
      for (var i = 0; i < $th.length; i++) {
        var $cd = $(g.cDrop).find('div').eq(i); // column drop-down arrow
        var pos = $($th[i]).position();
        $cd.css({
          left: pos.left + $($th[i]).width() - $cd.width(),
          top: pos.top
        });
      }
    },
    /**
     * Show all hidden columns.
     */
    showAllColumns: function () {
      for (var i = 0; i < g.colVisib.length; i++) {
        if (!g.colVisib[i]) {
          g.toggleCol(i);
        }
      }
      g.afterToggleCol();
    },
    /**
     * Show edit cell, if it can be shown
     *
     * @param cell <td> element to be edited
     */
    showEditCell: function (cell) {
      // destroy the date picker instance left if any, see: #17703
      var $datePickerInstance = $(g.cEdit).find('.hasDatepicker');
      if ($datePickerInstance.length > 0) {
        $datePickerInstance.datepicker('destroy');
      }
      if ($(cell).is('.grid_edit') && !g.colRsz && !g.colReorder) {
        if (!g.isCellEditActive) {
          var $cell = $(cell);
          if ('string' === $cell.attr('data-type') || 'blob' === $cell.attr('data-type') || 'json' === $cell.attr('data-type')) {
            g.cEdit = g.cEditTextarea;
          } else {
            g.cEdit = g.cEditStd;
          }

          // remove all edit area and hide it
          $(g.cEdit).find('.edit_area').empty().hide();
          // reposition the cEdit element
          $(g.cEdit).css({
            top: $cell.position().top,
            left: $cell.position().left
          }).show().find('.edit_box').css({
            width: $cell.outerWidth(),
            height: $cell.outerHeight()
          });
          // fill the cell edit with text from <td>
          var value = Functions.getCellValue(cell);
          if ($cell.attr('data-type') === 'json' && $cell.is('.truncated') === false) {
            value = Functions.stringifyJSON(value, null, 4);
          }
          $(g.cEdit).find('.edit_box').val(value);
          g.currentEditCell = cell;
          $(g.cEdit).find('.edit_box').trigger('focus');
          moveCursorToEnd($(g.cEdit).find('.edit_box'));
          $(g.cEdit).find('*').prop('disabled', false);
        }
      }
      function moveCursorToEnd(input) {
        var originalValue = input.val();
        var originallength = originalValue.length;
        input.val('');
        input.trigger('blur').trigger('focus').val(originalValue);
        input[0].setSelectionRange(originallength, originallength);
      }
    },
    /**
     * Remove edit cell and the edit area, if it is shown.
     *
     * @param force Optional, force to hide edit cell without saving edited field.
     * @param data  Optional, data from the POST AJAX request to save the edited field
     *              or just specify "true", if we want to replace the edited field with the new value.
     * @param field Optional, the edited <td>. If not specified, the function will
     *              use currently edited <td> from g.currentEditCell.
     * @param options Optional, this object contains a boolean named move (true, if called from move* functions)
     *                and a <td> to which the grid_edit should move
     */
    hideEditCell: function (force, data, field, options) {
      if (g.isCellEditActive && !force) {
        // cell is being edited, save or post the edited data
        if (options !== undefined) {
          g.saveOrPostEditedCell(options);
        } else {
          g.saveOrPostEditedCell();
        }
        return;
      }

      // cancel any previous request
      if (g.lastXHR !== null) {
        g.lastXHR.abort();
        g.lastXHR = null;
      }
      if (data) {
        if (g.currentEditCell) {
          // save value of currently edited cell
          // replace current edited field with the new value
          var $thisField = $(g.currentEditCell);
          var isNull = $thisField.data('value') === null;
          if (isNull) {
            $thisField.find('span').html('NULL');
            $thisField.addClass('null');
          } else {
            $thisField.removeClass('null');
            var value = data.isNeedToRecheck ? data.truncatableFieldValue : $thisField.data('value');

            // Truncates the text.
            $thisField.removeClass('truncated');
            if (CommonParams.get('pftext') === 'P' && value.length > g.maxTruncatedLen) {
              $thisField.addClass('truncated');
              value = value.substring(0, g.maxTruncatedLen) + '...';
            }

            // Add <br> before carriage return.
            var newHtml = Functions.escapeHtml(value);
            newHtml = newHtml.replace(/\n/g, '<br>\n');
            var decimals = parseInt($thisField.attr('data-decimals'));

            // remove decimal places if column type not supported
            if (decimals === 0 && $thisField.attr('data-type').indexOf('time') !== -1) {
              newHtml = newHtml.substring(0, newHtml.indexOf('.'));
            }

            // remove additional decimal places
            if (decimals > 0 && $thisField.attr('data-type').indexOf('time') !== -1) {
              newHtml = newHtml.substring(0, newHtml.length - (6 - decimals));
            }
            var selector = 'span';
            if ($thisField.hasClass('hex') && $thisField.find('a').length) {
              selector = 'a';
            }

            // Updates the code keeping highlighting (if any).
            var $target = $thisField.find(selector);
            if (!Functions.updateCode($target, newHtml, value)) {
              $target.html(newHtml);
            }
          }
          if ($thisField.is('.bit')) {
            $thisField.find('span').text($thisField.data('value'));
          }
        }
        if (data.transformations !== undefined) {
          $.each(data.transformations, function (cellIndex, value) {
            var $thisField = $(g.t).find('.to_be_saved').eq(cellIndex);
            $thisField.find('span').html(value);
          });
        }
        if (data.relations !== undefined) {
          $.each(data.relations, function (cellIndex, value) {
            var $thisField = $(g.t).find('.to_be_saved').eq(cellIndex);
            $thisField.find('span').html(value);
          });
        }

        // refresh the grid
        g.reposRsz();
        g.reposDrop();
      }

      // hide the cell editing area
      $(g.cEdit).hide();
      $(g.cEdit).find('.edit_box').trigger('blur');
      g.isCellEditActive = false;
      g.currentEditCell = null;
      // destroy datepicker in edit area, if exist
      var $dp = $(g.cEdit).find('.hasDatepicker');
      if ($dp.length > 0) {
        // eslint-disable-next-line no-underscore-dangle
        $(document).on('mousedown', $.datepicker._checkExternalClick);
        $dp.datepicker('refresh');

        // change the cursor in edit box back to normal
        // (the cursor become a hand pointer when we add datepicker)
        $(g.cEdit).find('.edit_box').css('cursor', 'inherit');
      }
    },
    /**
     * Show drop-down edit area when edit cell is focused.
     */
    showEditArea: function () {
      if (!g.isCellEditActive) {
        // make sure the edit area has not been shown
        g.isCellEditActive = true;
        g.isEditCellTextEditable = false;
        /**
         * @var $td current edited cell
         */
        var $td = $(g.currentEditCell);
        /**
         * @var $editArea the editing area
         */
        var $editArea = $(g.cEdit).find('.edit_area');
        /**
         * @var whereClause WHERE clause for the edited cell
         */
        var whereClause = $td.parent('tr').find('.where_clause').val();
        /**
         * @var fieldName  String containing the name of this field.
         * @see Sql.getFieldName()
         */
        var fieldName = Sql.getFieldName($(t), $td);
        /**
         * @var relationCurrValue String current value of the field (for fields that are foreign keyed).
         */
        var relationCurrValue = $td.text();
        /**
         * @var relationKeyOrDisplayColumn String relational key if in 'Relational display column' mode,
         * relational display column if in 'Relational key' mode (for fields that are foreign keyed).
         */
        var relationKeyOrDisplayColumn = $td.find('a').attr('title');
        /**
         * @var currValue String current value of the field (for fields that are of type enum or set).
         */
        var currValue = $td.find('span').text();

        // empty all edit area, then rebuild it based on $td classes
        $editArea.empty();

        // remember this instead of testing more than once
        var isNull = $td.is('.null');

        // add goto link, if this cell contains a link
        if ($td.find('a').length > 0) {
          var gotoLink = document.createElement('div');
          gotoLink.className = 'goto_link';
          $(gotoLink).append(g.gotoLinkText + ' ').append($td.find('a').clone());
          $editArea.append(gotoLink);
        }
        g.wasEditedCellNull = false;
        if ($td.is(':not(.not_null)')) {
          // append a null checkbox
          $editArea.append('<div class="null_div"><label>NULL:<input type="checkbox"></label></div>');
          var $checkbox = $editArea.find('.null_div input');
          // check if current <td> is NULL
          if (isNull) {
            $checkbox.prop('checked', true);
            g.wasEditedCellNull = true;
          }

          // if the select/editor is changed un-check the 'checkbox_null_<field_name>_<row_index>'.
          if ($td.is('.enum, .set')) {
            $editArea.on('change', 'select', function () {
              $checkbox.prop('checked', false);
            });
          } else if ($td.is('.relation')) {
            $editArea.on('change', 'select', function () {
              $checkbox.prop('checked', false);
            });
            $editArea.on('click', '.browse_foreign', function () {
              $checkbox.prop('checked', false);
            });
          } else {
            $(g.cEdit).on('keypress change paste', '.edit_box', function () {
              $checkbox.prop('checked', false);
            });
            // Capture ctrl+v (on IE and Chrome)
            $(g.cEdit).on('keydown', '.edit_box', function (e) {
              if (e.ctrlKey && e.which === 86) {
                $checkbox.prop('checked', false);
              }
            });
            $editArea.on('keydown', 'textarea', function () {
              $checkbox.prop('checked', false);
            });
          }
          // if some text is written in textbox automatically unmark the null checkbox and if it is emptied again mark the checkbox.
          $(g.cEdit).find('.edit_box').on('input', function () {
            if ($(g.cEdit).find('.edit_box').val() !== '') {
              $checkbox.prop('checked', false);
            } else {
              $checkbox.prop('checked', true);
            }
          });
          // if null checkbox is clicked empty the corresponding select/editor.
          $checkbox.on('click', function () {
            if ($td.is('.enum')) {
              $editArea.find('select').val('');
            } else if ($td.is('.set')) {
              $editArea.find('select').find('option').each(function () {
                var $option = $(this);
                $option.prop('selected', false);
              });
            } else if ($td.is('.relation')) {
              // if the dropdown is there to select the foreign value
              if ($editArea.find('select').length > 0) {
                $editArea.find('select').val('');
              }
            } else {
              $editArea.find('textarea').val('');
            }
            $(g.cEdit).find('.edit_box').val('');
          });
        }

        // reset the position of the edit_area div after closing datetime picker
        $(g.cEdit).find('.edit_area').css({
          'top': '0',
          'position': ''
        });
        var postParams;
        if ($td.is('.relation')) {
          // handle relations
          $editArea.addClass('edit_area_loading');

          // initialize the original data
          $td.data('original_data', null);

          /**
           * @var postParams Object containing parameters for the POST request
           */
          postParams = {
            'ajax_request': true,
            'server': g.server,
            'db': g.db,
            'table': g.table,
            'column': fieldName,
            'curr_value': relationCurrValue,
            'relation_key_or_display_column': relationKeyOrDisplayColumn
          };
          g.lastXHR = $.post('index.php?route=/sql/get-relational-values', postParams, function (data) {
            g.lastXHR = null;
            $editArea.removeClass('edit_area_loading');
            if ($(data.dropdown).is('select')) {
              // save original_data
              var value = $(data.dropdown).val();
              $td.data('original_data', value);
              // update the text input field, in case where the "Relational display column" is checked
              $(g.cEdit).find('.edit_box').val(value);
            }
            $editArea.append(data.dropdown);
            $editArea.append('<div class="cell_edit_hint">' + g.cellEditHint + '</div>');

            // for 'Browse foreign values' options,
            // hide the value next to 'Browse foreign values' link
            $editArea.find('span.curr_value').hide();
            // handle update for new values selected from new window
            $editArea.find('span.curr_value').on('change', function () {
              $(g.cEdit).find('.edit_box').val($(this).text());
            });
          }); // end $.post()

          $editArea.show();
          $editArea.on('change', 'select', function () {
            $(g.cEdit).find('.edit_box').val($(this).val());
          });
          g.isEditCellTextEditable = true;
        } else if ($td.is('.enum')) {
          // handle enum fields
          $editArea.addClass('edit_area_loading');

          /**
           * @var postParams Object containing parameters for the POST request
           */
          postParams = {
            'ajax_request': true,
            'server': g.server,
            'db': g.db,
            'table': g.table,
            'column': fieldName,
            'curr_value': currValue
          };
          g.lastXHR = $.post('index.php?route=/sql/get-enum-values', postParams, function (data) {
            g.lastXHR = null;
            if (typeof data === 'object' && data.success === false) {
              Functions.ajaxShowMessage(data.error, undefined, 'error');
              return;
            }
            $editArea.removeClass('edit_area_loading');
            $editArea.append(data.dropdown);
            $editArea.append('<div class="cell_edit_hint">' + g.cellEditHint + '</div>');
          }); // end $.post()

          $editArea.show();
          $editArea.on('change', 'select', function () {
            $(g.cEdit).find('.edit_box').val($(this).val());
          });
        } else if ($td.is('.set')) {
          // handle set fields
          $editArea.addClass('edit_area_loading');

          // if the data is truncated, get the full data
          if ($td.is('.truncated')) {
            postParams = {
              'ajax_request': true,
              'server': g.server,
              'db': g.db,
              'table': g.table,
              'column': fieldName,
              'curr_value': currValue,
              'get_full_values': true,
              'where_clause': whereClause
            };
          } else {
            postParams = {
              'ajax_request': true,
              'server': g.server,
              'db': g.db,
              'table': g.table,
              'column': fieldName,
              'curr_value': currValue
            };
          }
          g.lastXHR = $.post('index.php?route=/sql/get-set-values', postParams, function (data) {
            g.lastXHR = null;
            if (typeof data === 'object' && data.success === false) {
              Functions.ajaxShowMessage(data.error, undefined, 'error');
              return;
            }
            $editArea.removeClass('edit_area_loading');
            $editArea.append(data.select);
            $td.data('original_data', $(data.select).val().join());
            $editArea.append('<div class="cell_edit_hint">' + g.cellEditHint + '</div>');
          }); // end $.post()

          $editArea.show();
          $editArea.on('change', 'select', function () {
            $(g.cEdit).find('.edit_box').val($(this).val());
          });
        } else if ($td.is('.truncated, .transformed')) {
          if ($td.is('.to_be_saved')) {
            // cell has been edited
            var value = $td.data('value');
            $(g.cEdit).find('.edit_box').val(value);
            $editArea.append('<textarea></textarea>');
            $editArea.find('textarea').val(value);
            $editArea.on('keyup', 'textarea', function () {
              $(g.cEdit).find('.edit_box').val($(this).val());
            });
            $(g.cEdit).on('keyup', '.edit_box', function () {
              $editArea.find('textarea').val($(this).val());
            });
            $editArea.append('<div class="cell_edit_hint">' + g.cellEditHint + '</div>');
          } else {
            // handle truncated/transformed values values
            $editArea.addClass('edit_area_loading');

            // initialize the original data
            $td.data('original_data', null);

            /**
             * @var sqlQuery   String containing the SQL query used to retrieve value of truncated/transformed data
             */
            var sqlQuery = 'SELECT `' + fieldName + '` FROM `' + g.table + '` WHERE ' + whereClause;

            // Make the Ajax call and get the data, wrap it and insert it
            g.lastXHR = $.post('index.php?route=/sql', {
              'server': g.server,
              'db': g.db,
              'ajax_request': true,
              'sql_query': sqlQuery,
              'grid_edit': true
            }, function (data) {
              g.lastXHR = null;
              $editArea.removeClass('edit_area_loading');
              if (typeof data !== 'undefined' && data.success === true) {
                if ($td.attr('data-type') === 'json') {
                  data.value = Functions.stringifyJSON(data.value, null, 4);
                }
                $td.data('original_data', data.value);
                $(g.cEdit).find('.edit_box').val(data.value);
              } else {
                Functions.ajaxShowMessage(data.error, false);
              }
            }); // end $.post()
          }

          g.isEditCellTextEditable = true;
        } else if ($td.is('.timefield, .datefield, .datetimefield, .timestampfield')) {
          var $inputField = $(g.cEdit).find('.edit_box');

          // remember current datetime value in $input_field, if it is not null
          var datetimeValue = !isNull ? $inputField.val() : '';
          var showMillisec = false;
          var showMicrosec = false;
          var timeFormat = 'HH:mm:ss';
          // check for decimal places of seconds
          if ($td.attr('data-decimals') > 0 && $td.attr('data-type').indexOf('time') !== -1) {
            if (datetimeValue && datetimeValue.indexOf('.') === false) {
              datetimeValue += '.';
            }
            if ($td.attr('data-decimals') > 3) {
              showMillisec = true;
              showMicrosec = true;
              timeFormat = 'HH:mm:ss.lc';
              if (datetimeValue) {
                datetimeValue += '000000';
                datetimeValue = datetimeValue.substring(0, datetimeValue.indexOf('.') + 7);
                $inputField.val(datetimeValue);
              }
            } else {
              showMillisec = true;
              timeFormat = 'HH:mm:ss.l';
              if (datetimeValue) {
                datetimeValue += '000';
                datetimeValue = datetimeValue.substring(0, datetimeValue.indexOf('.') + 4);
                $inputField.val(datetimeValue);
              }
            }
          }

          // add datetime picker
          Functions.addDatepicker($inputField, $td.attr('data-type'), {
            showMillisec: showMillisec,
            showMicrosec: showMicrosec,
            timeFormat: timeFormat,
            firstDay: firstDayOfCalendar
          });
          $inputField.on('keyup', function (e) {
            if (e.which === 13) {
              // post on pressing "Enter"
              e.preventDefault();
              e.stopPropagation();
              g.saveOrPostEditedCell();
            } else if (e.which !== 27) {
              Functions.toggleDatepickerIfInvalid($td, $inputField);
            }
          });
          $inputField.datepicker('show');
          Functions.toggleDatepickerIfInvalid($td, $inputField);

          // unbind the mousedown event to prevent the problem of
          // datepicker getting closed, needs to be checked for any
          // change in names when updating
          // eslint-disable-next-line no-underscore-dangle
          $(document).off('mousedown', $.datepicker._checkExternalClick);

          // move ui-datepicker-div inside cEdit div
          var datepickerDiv = $('#ui-datepicker-div');
          datepickerDiv.css({
            'top': 0,
            'left': 0,
            'position': 'relative'
          });
          $(g.cEdit).append(datepickerDiv);

          // cancel any click on the datepicker element
          $editArea.find('> *').on('click', function (e) {
            e.stopPropagation();
          });
          g.isEditCellTextEditable = true;
        } else {
          g.isEditCellTextEditable = true;
          // only append edit area hint if there is a null checkbox
          if ($editArea.children().length > 0) {
            $editArea.append('<div class="cell_edit_hint">' + g.cellEditHint + '</div>');
          }
        }
        if ($editArea.children().length > 0) {
          $editArea.show();
        }
      }
    },
    /**
     * Post the content of edited cell.
     *
     * @param options Optional, this object contains a boolean named move (true, if called from move* functions)
     *                and a <td> to which the grid_edit should move
     */
    postEditedCell: function (options) {
      if (g.isSaving) {
        return;
      }
      g.isSaving = true;
      /**
       * @var relationFields Array containing the name/value pairs of relational fields
       */
      var relationFields = {};
      /**
       * @var relationalDisplay string 'K' if relational key, 'D' if relational display column
       */
      var relationalDisplay = $(g.o).find('input[name=relational_display]:checked').val();
      /**
       * @var transformFields    Array containing the name/value pairs for transformed fields
       */
      var transformFields = {};
      /**
       * @var transformationFields   Boolean, if there are any transformed fields in the edited cells
       */
      var transformationFields = false;
      /**
       * @var fullSqlQuery String containing the complete SQL query to update this table
       */
      var fullSqlQuery = '';
      /**
       * @var relFieldsList  String, url encoded representation of {@link relations_fields}
       */
      var relFieldsList = '';
      /**
       * @var transformFieldsList  String, url encoded representation of {@link transformFields}
       */
      var transformFieldsList = '';
      /**
       * @var fullWhereClause Array containing where clause for updated fields
       */
      var fullWhereClause = [];
      /**
       * @var isUnique   Boolean, whether the rows in this table is unique or not
       */
      var isUnique = $(g.t).find('td.edit_row_anchor').is('.nonunique') ? 0 : 1;
      /**
       * multi edit variables
       */
      var multiEditFieldsName = [];
      var multiEditFieldsType = [];
      var multiEditFields = [];
      var multiEditFieldsNull = [];

      // alert user if edited table is not unique
      if (!isUnique) {
        alert(g.alertNonUnique);
      }

      // loop each edited row
      $(g.t).find('td.to_be_saved').parents('tr').each(function () {
        var $tr = $(this);
        var whereClause = $tr.find('.where_clause').val();
        if (typeof whereClause === 'undefined') {
          whereClause = '';
        }
        fullWhereClause.push(whereClause);
        var conditionArray = JSON.parse($tr.find('.condition_array').val());

        /**
         * multi edit variables, for current row
         * @TODO array indices are still not correct, they should be md5 of field's name
         */
        var fieldsName = [];
        var fieldsType = [];
        var fields = [];
        var fieldsNull = [];

        // loop each edited cell in a row
        $tr.find('.to_be_saved').each(function () {
          /**
           * @var $thisField    Object referring to the td that is being edited
           */
          var $thisField = $(this);

          /**
           * @var fieldName  String containing the name of this field.
           * @see Sql.getFieldName()
           */
          var fieldName = Sql.getFieldName($(g.t), $thisField);

          /**
           * @var thisFieldParams   Array temporary storage for the name/value of current field
           */
          var thisFieldParams = {};
          if ($thisField.is('.transformed')) {
            transformationFields = true;
          }
          thisFieldParams[fieldName] = $thisField.data('value');

          /**
           * @var isNull String capturing whether 'checkbox_null_<field_name>_<row_index>' is checked.
           */
          var isNull = thisFieldParams[fieldName] === null;
          fieldsName.push(fieldName);
          if (isNull) {
            fieldsNull.push('on');
            fields.push('');
          } else {
            if ($thisField.is('.bit')) {
              fieldsType.push('bit');
            } else if ($thisField.hasClass('hex')) {
              fieldsType.push('hex');
            }
            fieldsNull.push('');
            if ($thisField.attr('data-type') !== 'json') {
              fields.push($thisField.data('value'));
            } else {
              const JSONString = Functions.stringifyJSON($thisField.data('value'));
              fields.push(JSONString);
            }
            var cellIndex = $thisField.index('.to_be_saved');
            if ($thisField.is(':not(.relation, .enum, .set, .bit)')) {
              if ($thisField.is('.transformed')) {
                transformFields[cellIndex] = {};
                $.extend(transformFields[cellIndex], thisFieldParams);
              }
            } else if ($thisField.is('.relation')) {
              relationFields[cellIndex] = {};
              $.extend(relationFields[cellIndex], thisFieldParams);
            }
          }
          // check if edited field appears in WHERE clause
          if (whereClause.indexOf(Sql.urlEncode(fieldName)) > -1) {
            var fieldStr = '`' + g.table + '`.' + '`' + fieldName + '`';
            for (var field in conditionArray) {
              if (field.indexOf(fieldStr) > -1) {
                conditionArray[field] = isNull ? 'IS NULL' : '= \'' + thisFieldParams[fieldName].replace(/'/g, '\'\'') + '\'';
                break;
              }
            }
          }
        }); // end of loop for every edited cells in a row

        // save new_clause
        var newClause = '';
        for (var field in conditionArray) {
          newClause += field + ' ' + conditionArray[field] + ' AND ';
        }
        newClause = newClause.substring(0, newClause.length - 5); // remove the last AND
        $tr.data('new_clause', newClause);
        // save condition_array
        $tr.find('.condition_array').val(JSON.stringify(conditionArray));
        multiEditFieldsName.push(fieldsName);
        multiEditFieldsType.push(fieldsType);
        multiEditFields.push(fields);
        multiEditFieldsNull.push(fieldsNull);
      }); // end of loop for every edited rows

      relFieldsList = $.param(relationFields);
      transformFieldsList = $.param(transformFields);

      // Make the Ajax post after setting all parameters
      /**
       * @var postParams Object containing parameters for the POST request
       */
      var postParams = {
        'ajax_request': true,
        'sql_query': fullSqlQuery,
        'server': g.server,
        'db': g.db,
        'table': g.table,
        'clause_is_unique': isUnique,
        'where_clause': fullWhereClause,
        'fields[multi_edit]': multiEditFields,
        'fields_name[multi_edit]': multiEditFieldsName,
        'fields_type[multi_edit]': multiEditFieldsType,
        'fields_null[multi_edit]': multiEditFieldsNull,
        'rel_fields_list': relFieldsList,
        'do_transformations': transformationFields,
        'transform_fields_list': transformFieldsList,
        'relational_display': relationalDisplay,
        'goto': encodeURIComponent('index.php?route=/sql'),
        'submit_type': 'save'
      };
      if (!g.saveCellsAtOnce) {
        $(g.cEdit).find('*').prop('disabled', true);
        $(g.cEdit).find('.edit_box').addClass('edit_box_posting');
      } else {
        $(g.o).find('div.save_edited').addClass('saving_edited_data').find('input').prop('disabled', true); // disable the save button
      }

      $.ajax({
        type: 'POST',
        url: 'index.php?route=/table/replace',
        data: postParams,
        success: function (data) {
          g.isSaving = false;
          if (!g.saveCellsAtOnce) {
            $(g.cEdit).find('*').prop('disabled', false);
            $(g.cEdit).find('.edit_box').removeClass('edit_box_posting');
          } else {
            $(g.o).find('div.save_edited').removeClass('saving_edited_data').find('input').prop('disabled', false); // enable the save button back
          }

          if (typeof data !== 'undefined' && data.success === true) {
            if (typeof options === 'undefined' || !options.move) {
              Functions.ajaxShowMessage(data.message);
            }

            // update where_clause related data in each edited row
            $(g.t).find('td.to_be_saved').parents('tr').each(function () {
              var newClause = $(this).data('new_clause');
              var $whereClause = $(this).find('.where_clause');
              var oldClause = $whereClause.val();
              var decodedOldClause = oldClause;
              var decodedNewClause = newClause;
              $whereClause.val(newClause);
              // update Edit, Copy, and Delete links also
              $(this).find('a').each(function () {
                $(this).attr('href', $(this).attr('href').replace(oldClause, newClause));
                // update delete confirmation in Delete link
                if ($(this).attr('href').indexOf('DELETE') > -1) {
                  $(this).removeAttr('onclick').off('click').on('click', function () {
                    return Functions.confirmLink(this, 'DELETE FROM `' + g.db + '`.`' + g.table + '` WHERE ' + decodedNewClause + (isUnique ? '' : ' LIMIT 1'));
                  });
                }
              });
              // update the multi edit checkboxes
              $(this).find('input[type=checkbox]').each(function () {
                var $checkbox = $(this);
                var checkboxName = $checkbox.attr('name');
                var checkboxValue = $checkbox.val();
                $checkbox.attr('name', checkboxName.replace(oldClause, newClause));
                $checkbox.val(checkboxValue.replace(decodedOldClause, decodedNewClause));
              });
            });
            // update the display of executed SQL query command
            if (typeof data.sql_query !== 'undefined') {
              // extract query box
              var $resultQuery = $($.parseHTML(data.sql_query));
              var sqlOuter = $resultQuery.find('.sqlOuter').wrap('<p>').parent().html();
              var tools = $resultQuery.find('.tools').wrap('<p>').parent().html();
              // sqlOuter and tools will not be present if 'Show SQL queries' configuration is off
              if (typeof sqlOuter !== 'undefined' && typeof tools !== 'undefined') {
                $(g.o).find('.result_query').not($(g.o).find('.result_query').last()).remove();
                var $existingQuery = $(g.o).find('.result_query');
                // If two query box exists update query in second else add a second box
                if ($existingQuery.find('div.sqlOuter').length > 1) {
                  $existingQuery.children().eq(3).remove();
                  $existingQuery.children().eq(3).remove();
                  $existingQuery.append(sqlOuter + tools);
                } else {
                  $existingQuery.append(sqlOuter + tools);
                }
                Functions.highlightSql($existingQuery);
              }
            }
            // hide and/or update the successfully saved cells
            g.hideEditCell(true, data);

            // remove the "Save edited cells" button
            $(g.o).find('div.save_edited').hide();
            // update saved fields
            $(g.t).find('.to_be_saved').removeClass('to_be_saved').data('value', null).data('original_data', null);
            g.isCellEdited = false;
          } else {
            Functions.ajaxShowMessage(data.error, false);
            if (!g.saveCellsAtOnce) {
              $(g.t).find('.to_be_saved').removeClass('to_be_saved');
            }
          }
        }
      }).done(function () {
        if (options !== undefined && options.move) {
          g.showEditCell(options.cell);
        }
      }); // end $.ajax()
    },

    /**
     * Save edited cell, so it can be posted later.
     *
     * @return {bool}
     */
    saveEditedCell: function () {
      /**
       * @var $thisField    Object referring to the td that is being edited
       */
      var $thisField = $(g.currentEditCell);
      var $testElement = ''; // to test the presence of a element

      var needToPost = false;

      /**
       * @var fieldName  String containing the name of this field.
       * @see Sql.getFieldName()
       */
      var fieldName = Sql.getFieldName($(g.t), $thisField);

      /**
       * @var thisFieldParams   Array temporary storage for the name/value of current field
       */
      var thisFieldParams = {};

      /**
       * @var isNull String capturing whether 'checkbox_null_<field_name>_<row_index>' is checked.
       */
      var isNull = $(g.cEdit).find('input:checkbox').is(':checked');
      if ($(g.cEdit).find('.edit_area').is('.edit_area_loading')) {
        // the edit area is still loading (retrieving cell data), no need to post
        needToPost = false;
      } else if (isNull) {
        if (!g.wasEditedCellNull) {
          thisFieldParams[fieldName] = null;
          needToPost = true;
        }
      } else {
        if ($thisField.is('.bit')) {
          thisFieldParams[fieldName] = $(g.cEdit).find('.edit_box').val();
        } else if ($thisField.is('.set')) {
          $testElement = $(g.cEdit).find('select');
          thisFieldParams[fieldName] = $testElement.map(function () {
            return $(this).val();
          }).get().join(',');
        } else if ($thisField.is('.relation, .enum')) {
          // for relation and enumeration, take the results from edit box value,
          // because selected value from drop-down, new window or multiple
          // selection list will always be updated to the edit box
          thisFieldParams[fieldName] = $(g.cEdit).find('.edit_box').val();
        } else if ($thisField.hasClass('hex')) {
          if ($(g.cEdit).find('.edit_box').val().match(/^(0x)?[a-f0-9]*$/i) !== null) {
            thisFieldParams[fieldName] = $(g.cEdit).find('.edit_box').val();
          } else {
            var hexError = '<div class="alert alert-danger" role="alert">' + Messages.strEnterValidHex + '</div>';
            Functions.ajaxShowMessage(hexError, false);
            thisFieldParams[fieldName] = Functions.getCellValue(g.currentEditCell);
          }
        } else {
          thisFieldParams[fieldName] = $(g.cEdit).find('.edit_box').val();
        }
        let isValueUpdated;
        if ($thisField.attr('data-type') !== 'json') {
          isValueUpdated = thisFieldParams[fieldName] !== Functions.getCellValue(g.currentEditCell);
        } else {
          const JSONString = Functions.stringifyJSON(thisFieldParams[fieldName]);
          isValueUpdated = JSONString !== JSON.stringify(JSON.parse(Functions.getCellValue(g.currentEditCell)));
        }
        if (g.wasEditedCellNull || isValueUpdated) {
          needToPost = true;
        }
      }
      if (needToPost) {
        $(g.currentEditCell).addClass('to_be_saved').data('value', thisFieldParams[fieldName]);
        if (g.saveCellsAtOnce) {
          $(g.o).find('div.save_edited').show();
        }
        g.isCellEdited = true;
      }
      return needToPost;
    },
    /**
     * Save or post currently edited cell, depending on the "saveCellsAtOnce" configuration.
     *
     * @param options Optional, this object contains a boolean named move (true, if called from move* functions)
     *                and a <td> to which the grid_edit should move
     */
    saveOrPostEditedCell: function (options) {
      var saved = g.saveEditedCell();
      // Check if $cfg['SaveCellsAtOnce'] is false
      if (!g.saveCellsAtOnce) {
        // Check if need_to_post is true
        if (saved) {
          // Check if this function called from 'move' functions
          if (options !== undefined && options.move) {
            g.postEditedCell(options);
          } else {
            g.postEditedCell();
          }
          // need_to_post is false
        } else {
          // Check if this function called from 'move' functions
          if (options !== undefined && options.move) {
            g.hideEditCell(true);
            g.showEditCell(options.cell);
            // NOT called from 'move' functions
          } else {
            g.hideEditCell(true);
          }
        }
        // $cfg['SaveCellsAtOnce'] is true
      } else {
        // If need_to_post
        if (saved) {
          // If this function called from 'move' functions
          if (options !== undefined && options.move) {
            g.hideEditCell(true, true, false, options);
            g.showEditCell(options.cell);
            // NOT called from 'move' functions
          } else {
            g.hideEditCell(true, true);
          }
        } else {
          // If this function called from 'move' functions
          if (options !== undefined && options.move) {
            g.hideEditCell(true, false, false, options);
            g.showEditCell(options.cell);
            // NOT called from 'move' functions
          } else {
            g.hideEditCell(true);
          }
        }
      }
    },
    /**
     * Initialize column resize feature.
     */
    initColResize: function () {
      // create column resizer div
      g.cRsz = document.createElement('div');
      g.cRsz.className = 'cRsz';

      // get data columns in the first row of the table
      var $firstRowCols = $(g.t).find('tr').first().find('th.draggable');

      // create column borders
      $firstRowCols.each(function () {
        var cb = document.createElement('div'); // column border
        $(cb).addClass('colborder').on('mousedown', function (e) {
          g.dragStartRsz(e, this);
        });
        $(g.cRsz).append(cb);
      });
      g.reposRsz();

      // attach to global div
      $(g.gDiv).prepend(g.cRsz);
    },
    /**
     * Initialize column reordering feature.
     */
    initColReorder: function () {
      g.cCpy = document.createElement('div'); // column copy, to store copy of dragged column header
      g.cPointer = document.createElement('div'); // column pointer, used when reordering column

      // adjust g.cCpy
      g.cCpy.className = 'cCpy';
      $(g.cCpy).hide();

      // adjust g.cPointer
      g.cPointer.className = 'cPointer';
      $(g.cPointer).css('visibility', 'hidden'); // set visibility to hidden instead of calling hide() to force browsers to cache the image in cPointer class

      // assign column reordering hint
      g.reorderHint = Messages.strColOrderHint;

      // get data columns in the first row of the table
      var $firstRowCols = $(g.t).find('tr').first().find('th.draggable');

      // initialize column order
      var $colOrder = $(g.o).find('.col_order'); // check if column order is passed from PHP
      var i;
      if ($colOrder.length > 0) {
        g.colOrder = $colOrder.val().split(',');
        for (i = 0; i < g.colOrder.length; i++) {
          g.colOrder[i] = parseInt(g.colOrder[i], 10);
        }
      } else {
        g.colOrder = [];
        for (i = 0; i < $firstRowCols.length; i++) {
          g.colOrder.push(i);
        }
      }

      // register events
      $(g.t).find('th.draggable').on('mousedown', function (e) {
        $(g.o).addClass('turnOffSelect');
        if (g.visibleHeadersCount > 1) {
          g.dragStartReorder(e, this);
        }
      }).on('mouseenter', function () {
        if (g.visibleHeadersCount > 1) {
          $(this).css('cursor', 'move');
        } else {
          $(this).css('cursor', 'inherit');
        }
      }).on('mouseleave', function () {
        g.showReorderHint = false;
        $(this).uiTooltip('option', {
          content: g.updateHint()
        });
      }).on('dblclick', function (e) {
        e.preventDefault();
        var res = Functions.copyToClipboard($(this).data('column'));
        if (res) {
          Functions.ajaxShowMessage(Messages.strCopyColumnSuccess, false, 'success');
        } else {
          Functions.ajaxShowMessage(Messages.strCopyColumnFailure, false, 'error');
        }
      });
      $(g.t).find('th.draggable a').on('dblclick', function (e) {
        e.stopPropagation();
      });
      // restore column order when the restore button is clicked
      $(g.o).find('div.restore_column').on('click', function () {
        g.restoreColOrder();
      });

      // attach to global div
      $(g.gDiv).append(g.cPointer);
      $(g.gDiv).append(g.cCpy);

      // prevent default "dragstart" event when dragging a link
      $(g.t).find('th a').on('dragstart', function () {
        return false;
      });

      // refresh the restore column button state
      g.refreshRestoreButton();
    },
    /**
     * Initialize column visibility feature.
     */
    initColVisib: function () {
      g.cDrop = document.createElement('div'); // column drop-down arrows
      g.cList = document.createElement('div'); // column visibility list

      // adjust g.cDrop
      g.cDrop.className = 'cDrop';

      // adjust g.cList
      g.cList.className = 'cList';
      $(g.cList).hide();

      // assign column visibility related hints
      g.showAllColText = Messages.strShowAllCol;

      // get data columns in the first row of the table
      var $firstRowCols = $(g.t).find('tr').first().find('th.draggable');
      var i;
      // initialize column visibility
      var $colVisib = $(g.o).find('.col_visib'); // check if column visibility is passed from PHP
      if ($colVisib.length > 0) {
        g.colVisib = $colVisib.val().split(',');
        for (i = 0; i < g.colVisib.length; i++) {
          g.colVisib[i] = parseInt(g.colVisib[i], 10);
        }
      } else {
        g.colVisib = [];
        for (i = 0; i < $firstRowCols.length; i++) {
          g.colVisib.push(1);
        }
      }

      // make sure we have more than one column
      if ($firstRowCols.length > 1) {
        var $colVisibTh = $(g.t).find('th:not(.draggable)').slice(0, 1);
        Functions.tooltip($colVisibTh, 'th', Messages.strColVisibHint);

        // create column visibility drop-down arrow(s)
        $colVisibTh.each(function () {
          var cd = document.createElement('div'); // column drop-down arrow
          $(cd).addClass('coldrop').on('click', function () {
            if (g.cList.style.display === 'none') {
              g.showColList(this);
            } else {
              g.hideColList();
            }
          });
          $(g.cDrop).append(cd);
        });

        // add column visibility control
        g.cList.innerHTML = '<div class="lDiv"></div>';
        var $listDiv = $(g.cList).find('div');
        var tempClick = function () {
          if (g.toggleCol($(this).index())) {
            g.afterToggleCol();
          }
        };
        for (i = 0; i < $firstRowCols.length; i++) {
          var currHeader = $firstRowCols[i];
          var listElmt = document.createElement('div');
          $(listElmt).text($(currHeader).text()).prepend('<input type="checkbox" ' + (g.colVisib[i] ? 'checked="checked" ' : '') + '>');
          $listDiv.append(listElmt);
          // add event on click
          $(listElmt).on('click', tempClick);
        }
        // add "show all column" button
        var showAll = document.createElement('div');
        $(showAll).addClass('showAllColBtn').text(g.showAllColText);
        $(g.cList).append(showAll);
        $(showAll).on('click', function () {
          g.showAllColumns();
        });
        // prepend "show all column" button at top if the list is too long
        if ($firstRowCols.length > 10) {
          var clone = showAll.cloneNode(true);
          $(g.cList).prepend(clone);
          $(clone).on('click', function () {
            g.showAllColumns();
          });
        }
      }

      // hide column visibility list if we move outside the list
      $(g.t).find('td, th.draggable').on('mouseenter', function () {
        g.hideColList();
      });

      // attach to first row first col of the grid
      var thFirst = $(g.t).find('th.d-print-none');
      $(thFirst).append(g.cDrop);
      $(thFirst).append(g.cList);

      // some adjustment
      g.reposDrop();
    },
    /**
     * Move currently Editing Cell to Up
     *
     * @param e
     *
     */
    moveUp: function (e) {
      e.preventDefault();
      var $thisField = $(g.currentEditCell);
      var fieldName = Sql.getFieldName($(g.t), $thisField);
      var whereClause = $thisField.parents('tr').first().find('.where_clause').val();
      if (typeof whereClause === 'undefined') {
        whereClause = '';
      }
      var found = false;
      var $prevRow;
      $thisField.parents('tr').first().parents('tbody').children().each(function () {
        if ($(this).find('.where_clause').val() === whereClause) {
          found = true;
        }
        if (!found) {
          $prevRow = $(this);
        }
      });
      var newCell;
      if (found && $prevRow) {
        $prevRow.children('td').each(function () {
          if (Sql.getFieldName($(g.t), $(this)) === fieldName) {
            newCell = this;
          }
        });
      }
      if (newCell) {
        g.hideEditCell(false, false, false, {
          move: true,
          cell: newCell
        });
      }
    },
    /**
     * Move currently Editing Cell to Down
     *
     * @param e
     *
     */
    moveDown: function (e) {
      e.preventDefault();
      var $thisField = $(g.currentEditCell);
      var fieldName = Sql.getFieldName($(g.t), $thisField);
      var whereClause = $thisField.parents('tr').first().find('.where_clause').val();
      if (typeof whereClause === 'undefined') {
        whereClause = '';
      }
      var found = false;
      var $nextRow;
      var j = 0;
      var nextRowFound = false;
      $thisField.parents('tr').first().parents('tbody').children().each(function () {
        if ($(this).find('.where_clause').val() === whereClause) {
          found = true;
        }
        if (found) {
          if (j >= 1 && !nextRowFound) {
            $nextRow = $(this);
            nextRowFound = true;
          } else {
            j++;
          }
        }
      });
      var newCell;
      if (found && $nextRow) {
        $nextRow.children('td').each(function () {
          if (Sql.getFieldName($(g.t), $(this)) === fieldName) {
            newCell = this;
          }
        });
      }
      if (newCell) {
        g.hideEditCell(false, false, false, {
          move: true,
          cell: newCell
        });
      }
    },
    /**
     * Move currently Editing Cell to Left
     *
     * @param e
     *
     */
    moveLeft: function (e) {
      e.preventDefault();
      var $thisField = $(g.currentEditCell);
      var fieldName = Sql.getFieldName($(g.t), $thisField);
      var whereClause = $thisField.parents('tr').first().find('.where_clause').val();
      if (typeof whereClause === 'undefined') {
        whereClause = '';
      }
      var found = false;
      var $foundRow;
      $thisField.parents('tr').first().parents('tbody').children().each(function () {
        if ($(this).find('.where_clause').val() === whereClause) {
          found = true;
          $foundRow = $(this);
        }
      });
      var leftCell;
      var cellFound = false;
      if (found) {
        $foundRow.children('td.grid_edit').each(function () {
          if (Sql.getFieldName($(g.t), $(this)) === fieldName) {
            cellFound = true;
          }
          if (!cellFound) {
            leftCell = this;
          }
        });
      }
      if (leftCell) {
        g.hideEditCell(false, false, false, {
          move: true,
          cell: leftCell
        });
      }
    },
    /**
     * Move currently Editing Cell to Right
     *
     * @param e
     *
     */
    moveRight: function (e) {
      e.preventDefault();
      var $thisField = $(g.currentEditCell);
      var fieldName = Sql.getFieldName($(g.t), $thisField);
      var whereClause = $thisField.parents('tr').first().find('.where_clause').val();
      if (typeof whereClause === 'undefined') {
        whereClause = '';
      }
      var found = false;
      var $foundRow;
      var j = 0;
      $thisField.parents('tr').first().parents('tbody').children().each(function () {
        if ($(this).find('.where_clause').val() === whereClause) {
          found = true;
          $foundRow = $(this);
        }
      });
      var rightCell;
      var cellFound = false;
      var nextCellFound = false;
      if (found) {
        $foundRow.children('td.grid_edit').each(function () {
          if (Sql.getFieldName($(g.t), $(this)) === fieldName) {
            cellFound = true;
          }
          if (cellFound) {
            if (j >= 1 && !nextCellFound) {
              rightCell = this;
              nextCellFound = true;
            } else {
              j++;
            }
          }
        });
      }
      if (rightCell) {
        g.hideEditCell(false, false, false, {
          move: true,
          cell: rightCell
        });
      }
    },
    /**
     * Initialize grid editing feature.
     */
    initGridEdit: function () {
      function startGridEditing(e, cell) {
        if (g.isCellEditActive) {
          g.saveOrPostEditedCell();
        } else {
          g.showEditCell(cell);
        }
        e.stopPropagation();
      }
      function handleCtrlNavigation(e) {
        if (e.ctrlKey && e.which === 38 || e.altKey && e.which === 38) {
          g.moveUp(e);
        } else if (e.ctrlKey && e.which === 40 || e.altKey && e.which === 40) {
          g.moveDown(e);
        } else if (e.ctrlKey && e.which === 37 || e.altKey && e.which === 37) {
          g.moveLeft(e);
        } else if (e.ctrlKey && e.which === 39 || e.altKey && e.which === 39) {
          g.moveRight(e);
        }
      }

      // create cell edit wrapper element
      g.cEditStd = document.createElement('div');
      g.cEdit = g.cEditStd;
      g.cEditTextarea = document.createElement('div');

      // adjust g.cEditStd
      g.cEditStd.className = 'cEdit';
      $(g.cEditStd).html('<input class="edit_box" rows="1"><div class="edit_area"></div>');
      $(g.cEditStd).hide();

      // adjust g.cEdit
      g.cEditTextarea.className = 'cEdit';
      $(g.cEditTextarea).html('<textarea class="edit_box" rows="1"></textarea><div class="edit_area"></div>');
      $(g.cEditTextarea).hide();

      // assign cell editing hint
      g.cellEditHint = Messages.strCellEditHint;
      g.saveCellWarning = Messages.strSaveCellWarning;
      g.alertNonUnique = Messages.strAlertNonUnique;
      g.gotoLinkText = Messages.strGoToLink;

      // initialize cell editing configuration
      g.saveCellsAtOnce = $(g.o).find('.save_cells_at_once').val();
      g.maxTruncatedLen = CommonParams.get('LimitChars');

      // register events
      $(g.t).find('td.data.click1').on('click', function (e) {
        startGridEditing(e, this);
        // prevent default action when clicking on "link" in a table
        if ($(e.target).is('.grid_edit a')) {
          e.preventDefault();
        }
      });
      $(g.t).find('td.data.click2').on('click', function (e) {
        var $cell = $(this);
        // In the case of relational link, We want single click on the link
        // to goto the link and double click to start grid-editing.
        var $link = $(e.target);
        if ($link.is('.grid_edit.relation a')) {
          e.preventDefault();
          // get the click count and increase
          var clicks = $cell.data('clicks');
          clicks = typeof clicks === 'undefined' ? 1 : clicks + 1;
          if (clicks === 1) {
            // if there are no previous clicks,
            // start the single click timer
            var timer = setTimeout(function () {
              // temporarily remove ajax class so the page loader will not handle it,
              // submit and then add it back
              $link.removeClass('ajax');
              AJAX.requestHandler.call($link[0]);
              $link.addClass('ajax');
              $cell.data('clicks', 0);
            }, 700);
            $cell.data('clicks', clicks);
            $cell.data('timer', timer);
          } else {
            // When double clicking a link, switch to edit mode
            // this is a double click, cancel the single click timer
            // and make the click count 0
            clearTimeout($cell.data('timer'));
            $cell.data('clicks', 0);
            // start grid-editing
            startGridEditing(e, this);
          }
        }
      }).on('dblclick', function (e) {
        if ($(e.target).is('.grid_edit a')) {
          e.preventDefault();
        } else {
          startGridEditing(e, this);
        }
      });
      $(g.cEditStd).on('keydown', 'input.edit_box, select', handleCtrlNavigation);
      $(g.cEditStd).find('.edit_box').on('focus', function () {
        g.showEditArea();
      });
      $(g.cEditStd).on('keydown', '.edit_box, select', function (e) {
        if (e.which === 13) {
          // post on pressing "Enter"
          e.preventDefault();
          g.saveOrPostEditedCell();
        }
      });
      $(g.cEditStd).on('keydown', function (e) {
        if (!g.isEditCellTextEditable) {
          // prevent text editing
          e.preventDefault();
        }
      });
      $(g.cEditTextarea).on('keydown', 'textarea.edit_box, select', handleCtrlNavigation);
      $(g.cEditTextarea).find('.edit_box').on('focus', function () {
        g.showEditArea();
      });
      $(g.cEditTextarea).on('keydown', '.edit_box, select', function (e) {
        if (e.which === 13 && !e.shiftKey) {
          // post on pressing "Enter"
          e.preventDefault();
          g.saveOrPostEditedCell();
        }
      });
      $(g.cEditTextarea).on('keydown', function (e) {
        if (!g.isEditCellTextEditable) {
          // prevent text editing
          e.preventDefault();
        }
      });
      $('html').on('click', function (e) {
        // hide edit cell if the click is not fromDat edit area
        if ($(e.target).parents().index($(g.cEdit)) === -1 && !$(e.target).parents('.ui-datepicker-header').length && !$('.browse_foreign_modal.ui-dialog:visible').length && !$(e.target).closest('.dismissable').length) {
          g.hideEditCell();
        }
      }).on('keydown', function (e) {
        if (e.which === 27 && g.isCellEditActive) {
          // cancel on pressing "Esc"
          g.hideEditCell(true);
        }
      });
      $(g.o).find('div.save_edited').on('click', function () {
        g.hideEditCell();
        g.postEditedCell();
      });
      $(window).on('beforeunload', function () {
        if (g.isCellEdited) {
          return g.saveCellWarning;
        }
      });

      // attach to global div
      $(g.gDiv).append(g.cEditStd);
      $(g.gDiv).append(g.cEditTextarea);

      // add hint for grid editing feature when hovering "Edit" link in each table row
      if (Messages.strGridEditFeatureHint !== undefined) {
        Functions.tooltip($(g.t).find('.edit_row_anchor a'), 'a', Messages.strGridEditFeatureHint);
      }
    }
  };

  /** ****************
   * Initialize grid
   ******************/

  // wrap all truncated data cells with span indicating the original length
  // todo update the original length after a grid edit
  $(t).find('td.data.truncated:not(:has(span))').wrapInner(function () {
    return '<span title="' + Messages.strOriginalLength + ' ' + $(this).data('originallength') + '"></span>';
  });

  // wrap remaining cells, except actions cell, with span
  $(t).find('th, td:not(:has(span))').wrapInner('<span></span>');

  // create grid elements
  g.gDiv = document.createElement('div'); // create global div

  // initialize the table variable
  g.t = t;

  // enclosing .sqlqueryresults div
  g.o = $(t).parents('.sqlqueryresults');

  // get data columns in the first row of the table
  var $firstRowCols = $(t).find('tr').first().find('th.draggable');

  // initialize visible headers count
  g.visibleHeadersCount = $firstRowCols.filter(':visible').length;

  // assign first column (actions) span
  if (!$(t).find('tr').first().find('th').first().hasClass('draggable')) {
    // action header exist
    g.actionSpan = $(t).find('tr').first().find('th').first().prop('colspan');
  } else {
    g.actionSpan = 0;
  }

  // assign table create time
  // table_create_time will only available if we are in "Browse" tab
  g.tableCreateTime = $(g.o).find('.table_create_time').val();

  // assign the hints
  g.sortHint = Messages.strSortHint;
  g.strMultiSortHint = Messages.strMultiSortHint;
  g.markHint = Messages.strColMarkHint;
  g.copyHint = Messages.strColNameCopyHint;

  // assign common hidden inputs
  var $commonHiddenInputs = $(g.o).find('div.common_hidden_inputs');
  g.server = $commonHiddenInputs.find('input[name=server]').val();
  g.db = $commonHiddenInputs.find('input[name=db]').val();
  g.table = $commonHiddenInputs.find('input[name=table]').val();

  // add table class
  $(t).addClass('pma_table');

  // add relative position to global div so that resize handlers are correctly positioned
  $(g.gDiv).css('position', 'relative');

  // link the global div
  $(t).before(g.gDiv);
  $(g.gDiv).append(t);

  // FEATURES
  if (isResizeEnabled) {
    g.initColResize();
  }
  // disable reordering for result from EXPLAIN or SHOW syntax, which do not have a table navigation panel
  if (isReorderEnabled && $(g.o).find('table.navigation').length > 0) {
    g.initColReorder();
  }
  if (isVisibEnabled) {
    g.initColVisib();
  }
  // make sure we have the ajax class
  if (isGridEditEnabled && $(t).is('.ajax')) {
    g.initGridEdit();
  }

  // create tooltip for each <th> with draggable class
  Functions.tooltip($(t).find('th.draggable'), 'th', g.updateHint());

  // register events for hint tooltip (anchors inside draggable th)
  $(t).find('th.draggable a').on('mouseenter', function () {
    g.showSortHint = true;
    g.showMultiSortHint = true;
    $(t).find('th.draggable').uiTooltip('option', {
      content: g.updateHint()
    });
  }).on('mouseleave', function () {
    g.showSortHint = false;
    g.showMultiSortHint = false;
    $(t).find('th.draggable').uiTooltip('option', {
      content: g.updateHint()
    });
  });

  // register events for dragging-related feature
  if (isResizeEnabled || isReorderEnabled) {
    $(document).on('mousemove', function (e) {
      g.dragMove(e);
    });
    $(document).on('mouseup', function (e) {
      $(g.o).removeClass('turnOffSelect');
      g.dragEnd(e);
    });
  }

  // some adjustment
  $(t).removeClass('data');
  $(g.gDiv).addClass('data');
};

/**
 * jQuery plugin to cancel selection in HTML code.
 */
(function ($) {
  $.fn.noSelect = function (p) {
    // no select plugin by Paulo P.Marinas
    var prevent = p === null ? true : p;
    /* eslint-disable compat/compat */
    var isMsie = navigator.userAgent.indexOf('MSIE') > -1 || !!window.navigator.userAgent.match(/Trident.*rv:11\./);
    var isFirefox = navigator.userAgent.indexOf('Firefox') > -1;
    var isSafari = navigator.userAgent.indexOf('Safari') > -1;
    var isOpera = navigator.userAgent.indexOf('Presto') > -1;
    /* eslint-enable compat/compat */
    if (prevent) {
      return this.each(function () {
        if (isMsie || isSafari) {
          $(this).on('selectstart', false);
        } else if (isFirefox) {
          $(this).css('MozUserSelect', 'none');
          $('body').trigger('focus');
        } else if (isOpera) {
          $(this).on('mousedown', false);
        } else {
          $(this).attr('unselectable', 'on');
        }
      });
    } else {
      return this.each(function () {
        if (isMsie || isSafari) {
          $(this).off('selectstart');
        } else if (isFirefox) {
          $(this).css('MozUserSelect', 'inherit');
        } else if (isOpera) {
          $(this).off('mousedown');
        } else {
          $(this).removeAttr('unselectable');
        }
      });
    }
  }; // end noSelect
})(jQuery);

Filemanager

Name Type Size Permission Actions
codemirror Folder 0755
database Folder 0755
designer Folder 0755
jqplot Folder 0755
server Folder 0755
setup Folder 0755
table Folder 0755
transformations Folder 0755
ajax.js File 29.25 KB 0644
chart.js File 16.66 KB 0644
common.js File 4.42 KB 0644
config.js File 23.5 KB 0644
console.js File 48.39 KB 0644
cross_framing_protection.js File 405 B 0644
doclinks.js File 17.85 KB 0644
drag_drop_import.js File 12.14 KB 0644
error_report.js File 9.05 KB 0644
export.js File 30.6 KB 0644
export_output.js File 364 B 0644
functions.js File 144.6 KB 0644
gis_data_editor.js File 13.26 KB 0644
home.js File 5.15 KB 0644
import.js File 5.5 KB 0644
indexes.js File 26.33 KB 0644
jquery.sortable-table.js File 9.27 KB 0644
keyhandler.js File 2.01 KB 0644
makegrid.js File 79.11 KB 0644
menu_resizer.js File 5.59 KB 0644
multi_column_sort.js File 1.25 KB 0644
name-conflict-fixes.js File 43 B 0644
navigation.js File 50.62 KB 0644
normalization.js File 23.54 KB 0644
ol.js File 1.41 KB 0644
page_settings.js File 1.78 KB 0644
replication.js File 3.46 KB 0644
shortcuts_handler.js File 3.23 KB 0644
sql.js File 34.71 KB 0644
u2f.js File 2.87 KB 0644
webauthn.js File 3.86 KB 0644
Filemanager