<commit_before>/***
 * A plugin to add row detail panel
 * Original StackOverflow question & article making this possible (thanks to violet313)
 * https://stackoverflow.com/questions/10535164/can-slickgrids-row-height-be-dynamically-altered#29399927
 * http://violet313.org/slickgrids/#intro
 * 
 *
 * USAGE:
 *
 * Add the slick.rowDetailView.(js|css) files and register the plugin with the grid.
 *
 * AVAILABLE ROW DETAIL OPTIONS:
 *    cssClass:         A CSS class to be added to the row detail
 *    loadOnce:         Booleang flag, when True will load the data once and then reuse it.
 *    preTemplate:      Template that will be used before the async process (typically used to show a spinner/loading)
 *    postTemplate:     Template that will be loaded once the async function finishes
 *    process:          Async server function call
 *    panelRows:        Row count to use for the template panel
 *    useRowClick:      Boolean flag, when True will open the row detail on a row click (from any column), default to False
 * 
 * AVAILABLE PUBLIC OPTIONS:
 *    init:                 initiliaze the plugin
 *    destroy:              destroy the plugin and it's events
 *    collapseAll:          collapse all opened row detail panel
 *    getColumnDefinition:  get the column definitions 
 *    getOptions:           get current plugin options
 *    setOptions:           set or change some of the plugin options
 * 
 * THE PLUGIN EXPOSES THE FOLLOWING SLICK EVENTS:
 *    onAsyncResponse:  This event must be used with the "notify" by the end user once the Asynchronous Server call returns the item detail 
 *       Event args:
 *          itemDetail: Item detail returned from the async server call
 *          detailView:  An explicit view to use instead of template (Optional)
 *
 *    onAsyncEndUpdate: Fired when the async response finished
 *       Event args:
 *         grid:        Reference to the grid.
 *         itemDetail:  Column definition.
 * 
 *    onBeforeRowDetailToggle: Fired before the row detail gets toggled
 *       Event args:
 *         grid:        Reference to the grid.
 *         item:  Column definition.
 * 
 *    onAfterRowDetailToggle: Fired after the row detail gets toggled
 *       Event args:
 *         grid:        Reference to the grid.
 *         item:  Column definition.
 *
 */
(function ($) {
  // register namespace
  $.extend(true, window, {
    "Slick": {
      "Plugins": {
        "RowDetailView": RowDetailView
      }
    }
  });


  function RowDetailView(options) {
    var _grid;
    var _self = this;
    var _expandedRows = [];
    var _handler = new Slick.EventHandler();
    var _defaults = {
      columnId: "_detail_selector",
      cssClass: null,
      toolTip: "",
      width: 30
    };

    var _options = $.extend(true, {}, _defaults, options);

    function init(grid) {
      _grid = grid;
      _dataView = _grid.getData();

      // Update the minRowBuffer so that the view doesn't disappear when it's at top of screen + the original default 3
      _grid.getOptions().minRowBuffer = _options.panelRows + 3;

      _handler
        .subscribe(_grid.onClick, handleClick)
        .subscribe(_grid.onSort, handleSort)
		.subscribe(_grid.onScroll, handleScroll);

      _grid.getData().onRowCountChanged.subscribe(function () { _grid.updateRowCount(); _grid.render(); });
      _grid.getData().onRowsChanged.subscribe(function (e, a) { _grid.invalidateRows(a.rows); _grid.render(); });

      // subscribe to the onAsyncResponse so that the plugin knows when the user server side calls finished
      subscribeToOnAsyncResponse();
    }

    function destroy() {
      _handler.unsubscribeAll();
      _self.onAsyncResponse.unsubscribe();
      _self.onAsyncEndUpdate.unsubscribe();
      _self.onAfterRowDetailToggle.unsubscribe();
      _self.onBeforeRowDetailToggle.unsubscribe();
    }

    function getOptions(options) {
      return _options;
    }

    function setOptions(options) {
      _options = $.extend(true, {}, _options, options);
    }
  
    function handleClick(e, args) {
      // clicking on a row select checkbox
      if (_options.useRowClick || _grid.getColumns()[args.cell].id === _options.columnId && $(e.target).hasClass("detailView-toggle")) {
        // if editing, try to commit
        if (_grid.getEditorLock().isActive() && !_grid.getEditorLock().commitCurrentEdit()) {
          e.preventDefault();
          e.stopImmediatePropagation();
          return;
        }

        var item = _dataView.getItem(args.row);

        // trigger an event before toggling
        _self.onBeforeRowDetailToggle.notify({
          "grid": _grid,
          "item": item
        }, e, _self);

        toggleRowSelection(item);

        // trigger an event after toggling
        _self.onAfterRowDetailToggle.notify({
          "grid": _grid,
          "item": item
        }, e, _self);

        e.stopPropagation();
        e.stopImmediatePropagation();
      }
    }

    // Sort will just collapse all of the open items
    function handleSort(e, args) {
      collapseAll();
    }

	// If we scroll save detail views that go out of cache range
    function handleScroll(e, args) {
        
        var range = _grid.getRenderedRange();

        var start = (range.top > 0 ? range.top : 0);
        var end = (range.bottom > _dataView.getLength() ? range.bottom : _dataView.getLength());
        
        // Get the item at the top of the view
        var topMostItem = _dataView.getItemByIdx(start);

        // Check it is a parent item
        if (topMostItem._parent == undefined)
        {
            // This is a standard row as we have no parent.
            var nextItem = _dataView.getItemByIdx(start + 1);
            if(nextItem !== undefined && nextItem._parent !== undefined)
            {
                // This is likely the expanded Detail Row View
                // Check for safety
                if(nextItem._parent == topMostItem)
                {
                    saveDetailView(topMostItem);
                }
            }
        }

        // Find the bottom most item that is likely to go off screen
        var bottomMostItem = _dataView.getItemByIdx(end - 1);

        // If we are a detailView and we are about to go out of cache view
        if(bottomMostItem._parent !== undefined)
        {
            saveDetailView(bottomMostItem._parent);
            
        }
    }
	
    // Toggle between showing and hiding a row
    function toggleRowSelection(row) {
      _grid.getData().beginUpdate();
      HandleAccordionShowHide(row);
      _grid.getData().endUpdate();
    }

    // Collapse all of the open items
    function collapseAll() {
      for (var i = _expandedRows.length - 1; i >= 0; i--) {
        collapseItem(_expandedRows[i]);
      }
    }
	
    // Saves the current state of the detail view<commit_msg>fix error in rowdetailsview plugin as per #228<commit_after>/***
 * A plugin to add row detail panel
 * Original StackOverflow question & article making this possible (thanks to violet313)
 * https://stackoverflow.com/questions/10535164/can-slickgrids-row-height-be-dynamically-altered#29399927
 * http://violet313.org/slickgrids/#intro
 * 
 *
 * USAGE:
 *
 * Add the slick.rowDetailView.(js|css) files and register the plugin with the grid.
 *
 * AVAILABLE ROW DETAIL OPTIONS:
 *    cssClass:         A CSS class to be added to the row detail
 *    loadOnce:         Booleang flag, when True will load the data once and then reuse it.
 *    preTemplate:      Template that will be used before the async process (typically used to show a spinner/loading)
 *    postTemplate:     Template that will be loaded once the async function finishes
 *    process:          Async server function call
 *    panelRows:        Row count to use for the template panel
 *    useRowClick:      Boolean flag, when True will open the row detail on a row click (from any column), default to False
 * 
 * AVAILABLE PUBLIC OPTIONS:
 *    init:                 initiliaze the plugin
 *    destroy:              destroy the plugin and it's events
 *    collapseAll:          collapse all opened row detail panel
 *    getColumnDefinition:  get the column definitions 
 *    getOptions:           get current plugin options
 *    setOptions:           set or change some of the plugin options
 * 
 * THE PLUGIN EXPOSES THE FOLLOWING SLICK EVENTS:
 *    onAsyncResponse:  This event must be used with the "notify" by the end user once the Asynchronous Server call returns the item detail 
 *       Event args:
 *          itemDetail: Item detail returned from the async server call
 *          detailView:  An explicit view to use instead of template (Optional)
 *
 *    onAsyncEndUpdate: Fired when the async response finished
 *       Event args:
 *         grid:        Reference to the grid.
 *         itemDetail:  Column definition.
 * 
 *    onBeforeRowDetailToggle: Fired before the row detail gets toggled
 *       Event args:
 *         grid:        Reference to the grid.
 *         item:  Column definition.
 * 
 *    onAfterRowDetailToggle: Fired after the row detail gets toggled
 *       Event args:
 *         grid:        Reference to the grid.
 *         item:  Column definition.
 *
 */
(function ($) {
  // register namespace
  $.extend(true, window, {
    "Slick": {
      "Plugins": {
        "RowDetailView": RowDetailView
      }
    }
  });


  function RowDetailView(options) {
    var _grid;
    var _self = this;
    var _expandedRows = [];
    var _handler = new Slick.EventHandler();
    var _defaults = {
      columnId: "_detail_selector",
      cssClass: null,
      toolTip: "",
      width: 30
    };

    var _options = $.extend(true, {}, _defaults, options);

    function init(grid) {
      _grid = grid;
      _dataView = _grid.getData();

      // Update the minRowBuffer so that the view doesn't disappear when it's at top of screen + the original default 3
      _grid.getOptions().minRowBuffer = _options.panelRows + 3;

      _handler
        .subscribe(_grid.onClick, handleClick)
        .subscribe(_grid.onSort, handleSort)
		.subscribe(_grid.onScroll, handleScroll);

      _grid.getData().onRowCountChanged.subscribe(function () { _grid.updateRowCount(); _grid.render(); });
      _grid.getData().onRowsChanged.subscribe(function (e, a) { _grid.invalidateRows(a.rows); _grid.render(); });

      // subscribe to the onAsyncResponse so that the plugin knows when the user server side calls finished
      subscribeToOnAsyncResponse();
    }

    function destroy() {
      _handler.unsubscribeAll();
      _self.onAsyncResponse.unsubscribe();
      _self.onAsyncEndUpdate.unsubscribe();
      _self.onAfterRowDetailToggle.unsubscribe();
      _self.onBeforeRowDetailToggle.unsubscribe();
    }

    function getOptions(options) {
      return _options;
    }

    function setOptions(options) {
      _options = $.extend(true, {}, _options, options);
    }
  
    function handleClick(e, args) {
      // clicking on a row select checkbox
      if (_options.useRowClick || _grid.getColumns()[args.cell].id === _options.columnId && $(e.target).hasClass("detailView-toggle")) {
        // if editing, try to commit
        if (_grid.getEditorLock().isActive() && !_grid.getEditorLock().commitCurrentEdit()) {
          e.preventDefault();
          e.stopImmediatePropagation();
          return;
        }

        var item = _dataView.getItem(args.row);

        // trigger an event before toggling
        _self.onBeforeRowDetailToggle.notify({
          "grid": _grid,
          "item": item
        }, e, _self);

        toggleRowSelection(item);

        // trigger an event after toggling
        _self.onAfterRowDetailToggle.notify({
          "grid": _grid,
          "item": item
        }, e, _self);

        e.stopPropagation();
        e.stopImmediatePropagation();
      }
    }

    // Sort will just collapse all of the open items
    function handleSort(e, args) {
      collapseAll();
    }

	// If we scroll save detail views that go out of cache range
    function handleScroll(e, args) {
        
        var range = _grid.getRenderedRange();

        var start = (range.top > 0 ? range.top : 0);
        var end = (range.bottom > _dataView.getLength() ? range.bottom : _dataView.getLength());
        
        // Get the item at the top of the view
        var topMostItem = _dataView.getItemByIdx(start);

        // Check it is a parent item
        if (topMostItem && topMostItem._parent == undefined)
        {
            // This is a standard row as we have no parent.
            var nextItem = _dataView.getItemByIdx(start + 1);
            if(nextItem !== undefined && nextItem._parent !== undefined)
            {
                // This is likely the expanded Detail Row View
                // Check for safety
                if(nextItem._parent == topMostItem)
                {
                    saveDetailView(topMostItem);
                }
            }
        }

        // Find the bottom most item that is likely to go off screen
        var bottomMostItem = _dataView.getItemByIdx(end - 1);

        // If we are a detailView and we are about to go out of cache view
        if (bottomMostItem && bottomMostItem._parent !== undefined)
        {
            saveDetailView(bottomMostItem._parent);
            
        }
    }
	
    // Toggle between showing and hiding a row
    function toggleRowSelection(row) {
      _grid.getData().beginUpdate();
      HandleAccordionShowHide(row);
      _grid.getData().endUpdate();
    }

    // Collapse all of the open items
    function collapseAll() {
      for (var i = _expandedRows.length - 1; i >= 0; i--) {
        collapseItem(_expandedRows[i]);
      }
    }
	
    // Saves the current state of the detail view
{'fraction_non_alphanumeric': 0.09239799985506196, 'fraction_numerical': 0.004855424306109139, 'mean_word_length': 2.247823017180513, 'pattern_counts': {'":': 14, '<': 3, '<?xml version=': 0, '>': 9, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4015486', 'n_tokens_mistral': 3849, 'n_tokens_neox': 3714, 'n_words': 1209}