<commit_before>/***
 * 
 * (c) 2009 <NAME> (<EMAIL>)
 * All rights reserved.
 * 
 * 
 * TODO:
 * 	- frozen columns
 * 	- consistent events (EventHelper?  jQuery events?)
 *
 * 
 * KNOWN ISSUES:
 * 	- keyboard navigation doesn't "jump" over unselectable cells for now
*
 * 
 * OPTIONS:
 *  rowHeight				-	Row height in pixels.
 * 	enableAddRow			-	If true, a blank row will be displayed at the bottom - typing values in that row will add a new one.
 * 	manualScrolling			-	Disable automatic rerender on scroll.  Client will take care of calling Grid.onScroll().
 * 	editable				-	If false, no cells will be switched into edit mode.
 * 	editOnDoubleClick		-	Cell will not automatically go into edit mode without being double-clicked.
 * 	enableCellNavigation	-	If false, no cells will be selectable.
 * 	defaultColumnWidth		-	Default column width in pixels (if columns[cell].width is not specified).
 * 	enableColumnReorder		-	Allows the user to reorder columns.
 * 	asyncEditorLoading		-	Makes cell editors load asynchronously after a small delay.
 * 								This greatly increases keyboard navigation speed.
 * 	forceFitColumns			-	Force column sizes to fit into the viewport (avoid horizontal scrolling).
 * 
 * 
 * COLUMN DEFINITION (columns) OPTIONS:
 * 	id						-	Column ID.
 * 	name					-	Column name to put in the header.
 * 	field					-	Property of the data context to bind to.
 * 	formatter				-	Function responsible for rendering the contents of a cell.
 * 	editor					-	An Editor class.
 * 	validator				-	An extra validation function to be passed to the editor.
 * 	unselectable			-	If true, the cell cannot be selected (and therefore edited).
 * 	cannotTriggerInsert		-	If true, a new row cannot be created from just the value of this cell.
 * 	setValueHandler			-	If true, this handler will be called to set field value instead of context[field].
 * 	width					-	Width of the column in pixels.
 * 	resizable				-	If false, the column cannot be resized.
 *  sortable				-	If true, the column can be sorted (onSort will be called).
 * 	minWidth				-	Minimum allowed column width for resizing.
 * 	maxWidth				-	Maximum allowed column width for resizing.
 * 	cssClass				-	A CSS class to add to the cell.
 * 	rerenderOnResize		-	Rerender the column when it is resized (useful for columns relying on cell width or adaptive formatters).
 * 	
 * 
 * EVENTS:
 * 
 * ...
 * 
 * 
 * NOTES:
 * 
 * 	Cell/row DOM manipulations are done directly bypassing jQuery's DOM manipulation methods.
 * 	This increases the speed dramatically, but can only be done safely because there are no event handlers
 * 	or data associated with any cell/row DOM nodes.  Cell editors must make sure they implement .destroy() 
 * 	and do proper cleanup.
 * 
 * 
 * @param {jQuery} $container	Container object to create the grid in.
 * @param {Array} data			An array of objects for databinding.
 * @param {Array} columns		An array of column definitions.
 * @param {Object} options		Grid options.
 * 
 */
function SlickGrid($container,data,columns,options)
{
	// settings
	var defaults = {
		rowHeight: 25,
		defaultColumnWidth: 80,
		enableAddRow: true,
		leaveSpaceForNewRows: false,
		manualScrolling: false,
		editable: true,
		editOnDoubleClick: false,
		enableCellNavigation: true,
		enableColumnReorder: true,
		asyncEditorLoading: false,
		forceFitColumns: false
	};
	
	var columnDefaults = {
		resizable: true,
		sortable: true,
		formatter: defaultFormatter
	}
	
	// consts
	var CAPACITY = 50;
	var MIN_BUFFER = 5;
	var BUFFER = MIN_BUFFER;  // will be set to equal one page
	var POSTPROCESSING_DELAY = 50;
	
	// private
	var uid = "slickgrid_" + Math.round(1000000 * Math.random());
	var self = this;
	var $divHeadersScroller;
	var $divHeaders;
	var $divMainScroller;
	var $divMain;
	var viewportH, viewportW;
	var headerColumnWidthDiff, headerColumnHeightDiff, cellWidthDiff, cellHeightDiff;  // padding+border
		
	var currentRow, currentCell;
	var currentCellNode = null;
	var currentEditor = null;	
	
	var rowsCache = {};
	var renderedRows = 0;
	var numVisibleRows;
	var lastRenderedScrollTop = 0;
	var currentScrollTop = 0;
	var currentScrollLeft = 0;
	var scrollDir = 1;
	var avgRowRenderTime = 10;
	
	var selectedRows = [];
	var selectedRowsLookup = {};
	var columnsById = {};
	
	// async call handles
	var h_editorLoader = null;
	var h_render = null;	
	var h_postrender = null;
	var postProcessedRows = {};
	var rowsToPostProcess = [];
	
	// perf counters
	var counter_rows_rendered = 0;
	var counter_rows_removed = 0;
	
	
	function init() {
		options = $.extend({},defaults,options);
		columnDefaults.width = options.defaultColumnWidth;
		
		$container
			.empty()
			.attr("tabIndex",0)
			.attr("hideFocus",true)
			.css("overflow","hidden")
			.css("outline",0)
			.css("position","relative")
			.addClass(uid);
		
		$divHeadersScroller = $("<div class='slick-header' style='overflow:hidden;position:relative;' />").appendTo($container);
		$divHeaders = $("<div class='slick-header-columns' style='width:100000px' />").appendTo($divHeadersScroller);
		$divMainScroller = $("<div tabIndex='0' hideFocus style='width:100%;overflow:scroll;outline:0;position:relative;outline:0px;'>").appendTo($container);
		$divMain = $("<div class='grid-canvas' tabIndex='0' hideFocus />").appendTo($divMainScroller);
	
		// header columns and cells may have different padding/border skewing width calculations (box-sizing, hello?)
		// calculate the diff so we can set consistent sizes
		measureCellPaddingAndBorder();
		
		$divMainScroller.height($container.innerHeight() - $divHeadersScroller.outerHeight());
		
		if ($.browser.msie)		
				$divMainScroller[0].onselectstart = function() {		
					if (event.srcElement.tagName != "INPUT" && event.srcElement.tagName != "TEXTAREA")		
						return false;		
					};
		
		$divHeaders.disableSelection();

		createColumnHeaders();
		if (options.forceFitColumns)
			autosizeColumns();
			
		setupMoveEvents();
		createCssRules();
		resizeCanvas();
		render();
		
		if (!options.manualScrolling)
			$divMainScroller.bind("scroll", handleScroll);
		
		$container.bind("resize", resizeCanvas);
		
		$divMain.bind("keydown", handleKeyDown);
		$divMain.bind("click", handleClick);
		$divMain.bind("dblclick", handleDblClick);
		$divMain.bind("contextmenu", handleContextMenu)
		$divHeadersScroller.bind("contextmenu", handleHeaderContextMenu);
	}
	
	function createColumnHeaders() {
		for (var i = 0; i < columns.length; i++) {
			var m = columns[i] = $.extend({},columnDefaults,columns[i]);
			columnsById[m.id] = i;
			
			var header = $("<div class='slick-header-column' cell=" + i + " id='" + m.id + "' />")
				.html(m.name)
				.width(m.width - headerColumnWidthDiff)
				.appendTo($divHeaders);
			
			if (m.sortable) header.append("<span class='slick-sort-indicator' />")
			if (m.resizable) header.append("<div class='slick-resizable-handle' />");
		}
		
		setupColumnSort();
		setupColumnResizeEvents();
		if (options.enableColumnReorder) <commit_msg>ForceFitColumns wasn't working on init.<commit_after>/***
 * 
 * (c) 2009 <NAME> (<EMAIL>)
 * All rights reserved.
 * 
 * 
 * TODO:
 * 	- frozen columns
 * 	- consistent events (EventHelper?  jQuery events?)
 *
 * 
 * KNOWN ISSUES:
 * 	- keyboard navigation doesn't "jump" over unselectable cells for now
*
 * 
 * OPTIONS:
 *  rowHeight				-	Row height in pixels.
 * 	enableAddRow			-	If true, a blank row will be displayed at the bottom - typing values in that row will add a new one.
 * 	manualScrolling			-	Disable automatic rerender on scroll.  Client will take care of calling Grid.onScroll().
 * 	editable				-	If false, no cells will be switched into edit mode.
 * 	editOnDoubleClick		-	Cell will not automatically go into edit mode without being double-clicked.
 * 	enableCellNavigation	-	If false, no cells will be selectable.
 * 	defaultColumnWidth		-	Default column width in pixels (if columns[cell].width is not specified).
 * 	enableColumnReorder		-	Allows the user to reorder columns.
 * 	asyncEditorLoading		-	Makes cell editors load asynchronously after a small delay.
 * 								This greatly increases keyboard navigation speed.
 * 	forceFitColumns			-	Force column sizes to fit into the viewport (avoid horizontal scrolling).
 * 
 * 
 * COLUMN DEFINITION (columns) OPTIONS:
 * 	id						-	Column ID.
 * 	name					-	Column name to put in the header.
 * 	field					-	Property of the data context to bind to.
 * 	formatter				-	Function responsible for rendering the contents of a cell.
 * 	editor					-	An Editor class.
 * 	validator				-	An extra validation function to be passed to the editor.
 * 	unselectable			-	If true, the cell cannot be selected (and therefore edited).
 * 	cannotTriggerInsert		-	If true, a new row cannot be created from just the value of this cell.
 * 	setValueHandler			-	If true, this handler will be called to set field value instead of context[field].
 * 	width					-	Width of the column in pixels.
 * 	resizable				-	If false, the column cannot be resized.
 *  sortable				-	If true, the column can be sorted (onSort will be called).
 * 	minWidth				-	Minimum allowed column width for resizing.
 * 	maxWidth				-	Maximum allowed column width for resizing.
 * 	cssClass				-	A CSS class to add to the cell.
 * 	rerenderOnResize		-	Rerender the column when it is resized (useful for columns relying on cell width or adaptive formatters).
 * 	
 * 
 * EVENTS:
 * 
 * ...
 * 
 * 
 * NOTES:
 * 
 * 	Cell/row DOM manipulations are done directly bypassing jQuery's DOM manipulation methods.
 * 	This increases the speed dramatically, but can only be done safely because there are no event handlers
 * 	or data associated with any cell/row DOM nodes.  Cell editors must make sure they implement .destroy() 
 * 	and do proper cleanup.
 * 
 * 
 * @param {jQuery} $container	Container object to create the grid in.
 * @param {Array} data			An array of objects for databinding.
 * @param {Array} columns		An array of column definitions.
 * @param {Object} options		Grid options.
 * 
 */
function SlickGrid($container,data,columns,options)
{
	// settings
	var defaults = {
		rowHeight: 25,
		defaultColumnWidth: 80,
		enableAddRow: true,
		leaveSpaceForNewRows: false,
		manualScrolling: false,
		editable: true,
		editOnDoubleClick: false,
		enableCellNavigation: true,
		enableColumnReorder: true,
		asyncEditorLoading: false,
		forceFitColumns: false
	};
	
	var columnDefaults = {
		resizable: true,
		sortable: true,
		formatter: defaultFormatter
	}
	
	// consts
	var CAPACITY = 50;
	var MIN_BUFFER = 5;
	var BUFFER = MIN_BUFFER;  // will be set to equal one page
	var POSTPROCESSING_DELAY = 50;
	
	// private
	var uid = "slickgrid_" + Math.round(1000000 * Math.random());
	var self = this;
	var $divHeadersScroller;
	var $divHeaders;
	var $divMainScroller;
	var $divMain;
	var viewportH, viewportW;
	var headerColumnWidthDiff, headerColumnHeightDiff, cellWidthDiff, cellHeightDiff;  // padding+border
		
	var currentRow, currentCell;
	var currentCellNode = null;
	var currentEditor = null;	
	
	var rowsCache = {};
	var renderedRows = 0;
	var numVisibleRows;
	var lastRenderedScrollTop = 0;
	var currentScrollTop = 0;
	var currentScrollLeft = 0;
	var scrollDir = 1;
	var avgRowRenderTime = 10;
	
	var selectedRows = [];
	var selectedRowsLookup = {};
	var columnsById = {};
	
	// async call handles
	var h_editorLoader = null;
	var h_render = null;	
	var h_postrender = null;
	var postProcessedRows = {};
	var rowsToPostProcess = [];
	
	// perf counters
	var counter_rows_rendered = 0;
	var counter_rows_removed = 0;
	
	
	function init() {
		options = $.extend({},defaults,options);
		columnDefaults.width = options.defaultColumnWidth;
		
		$container
			.empty()
			.attr("tabIndex",0)
			.attr("hideFocus",true)
			.css("overflow","hidden")
			.css("outline",0)
			.css("position","relative")
			.addClass(uid);
		
		$divHeadersScroller = $("<div class='slick-header' style='overflow:hidden;position:relative;' />").appendTo($container);
		$divHeaders = $("<div class='slick-header-columns' style='width:100000px' />").appendTo($divHeadersScroller);
		$divMainScroller = $("<div tabIndex='0' hideFocus style='width:100%;overflow:scroll;outline:0;position:relative;outline:0px;'>").appendTo($container);
		$divMain = $("<div class='grid-canvas' tabIndex='0' hideFocus />").appendTo($divMainScroller);
	
		// header columns and cells may have different padding/border skewing width calculations (box-sizing, hello?)
		// calculate the diff so we can set consistent sizes
		measureCellPaddingAndBorder();
		
		$divMainScroller.height($container.innerHeight() - $divHeadersScroller.outerHeight());
		
		if ($.browser.msie)		
				$divMainScroller[0].onselectstart = function() {		
					if (event.srcElement.tagName != "INPUT" && event.srcElement.tagName != "TEXTAREA")		
						return false;		
					};
		
		$divHeaders.disableSelection();

		createColumnHeaders();			
		setupMoveEvents();
		createCssRules();
		resizeCanvas();
		if (options.forceFitColumns)
			autosizeColumns();		
		render();
		
		if (!options.manualScrolling)
			$divMainScroller.bind("scroll", handleScroll);
		
		$container.bind("resize", resizeCanvas);
		
		$divMain.bind("keydown", handleKeyDown);
		$divMain.bind("click", handleClick);
		$divMain.bind("dblclick", handleDblClick);
		$divMain.bind("contextmenu", handleContextMenu)
		$divHeadersScroller.bind("contextmenu", handleHeaderContextMenu);
	}
	
	function createColumnHeaders() {
		for (var i = 0; i < columns.length; i++) {
			var m = columns[i] = $.extend({},columnDefaults,columns[i]);
			columnsById[m.id] = i;
			
			var header = $("<div class='slick-header-column' cell=" + i + " id='" + m.id + "' />")
				.html(m.name)
				.width(m.width - headerColumnWidthDiff)
				.appendTo($divHeaders);
			
			if (m.sortable) header.append("<span class='slick-sort-indicator' />")
			if (m.resizable) header.append("<div class='slick-resizable-handle' />");
		}
		
		setupColumnSort();
		setupColumnResizeEvents();
		if (options.enableColumnReorder) 
{'fraction_non_alphanumeric': 0.11177017079968556, 'fraction_numerical': 0.006574715929393268, 'mean_word_length': 3.688107202680067, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 21, 'https://': 0, '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': '3251610', 'n_tokens_mistral': 4916, 'n_tokens_neox': 4327, 'n_words': 1336}