<commit_before>/*!
 * VisualEditor UserInterface Toolbar class.
 *
 * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
 * @license The MIT License (MIT); see LICENSE.txt
 */

/**
 * UserInterface toolbar.
 *
 * @class
 * @extends ve.Element
 * @mixins ve.EventEmitter
 *
 * @constructor
 * @param {ve.ui.Surface} surface
 * @param {Object} [config] Config options
 * @cfg {boolean} [actions] Add an actions section opposite to the tools
 * @cfg {boolean} [shadow] Add a shadow below the toolbar
 */
ve.ui.Toolbar = function VeUiToolbar( surface, options ) {
	// Configuration initialization
	options = options || {};

	// Parent constructor
	ve.Element.call( this, options );

	// Mixin constructors
	ve.EventEmitter.call( this );

	// Properties
	this.surface = surface;
	this.$bar = this.$$( '<div>' );
	this.$tools = this.$$( '<div>' );
	this.$actions = this.$$( '<div>' );
	this.floating = false;
	this.$window = null;
	this.windowEvents = {
		'resize': ve.bind( this.onWindowResize, this ),
		'scroll': ve.bind( this.onWindowScroll, this )
	};

	// Events
	this.$
		.add( this.$bar ).add( this.$tools ).add( this.$actions )
		.on( 'mousedown', false );

	// Initialization
	this.$tools.addClass( 've-ui-toolbar-tools' );
	this.$bar.addClass( 've-ui-toolbar-bar' ).append( this.$tools );
	if ( options.actions ) {
		this.$actions.addClass( 've-ui-toolbar-actions' );
		this.$bar.append( this.$actions );
	}
	this.$bar.append( '<div style="clear:both"></div>' );
	if ( options.shadow ) {
		this.$bar.append( '<div class="ve-ui-toolbar-shadow"></div>' );
	}
	this.$.addClass( 've-ui-toolbar' ).append( this.$bar );

	// Events
	this.surface.getModel().connect( this, { 'contextChange': 'onContextChange' } );
};

/* Inheritance */

ve.inheritClass( ve.ui.Toolbar, ve.Element );

ve.mixinClass( ve.ui.Toolbar, ve.EventEmitter );

/* Events */

/**
 * @event updateState
 * @see ve.dm.SurfaceFragment#getAnnotations
 * @param {ve.dm.Node[]} nodes List of nodes covered by the current selection
 * @param {ve.dm.AnnotationSet} full Annotations that cover all of the current selection
 * @param {ve.dm.AnnotationSet} partial Annotations that cover some or all of the current selection
 */

/* Methods */

/**
 * Handle window resize events while toolbar floating is enabled.
 *
 * @returns {jQuery.Event} e Window resize event
 */
ve.ui.Toolbar.prototype.onWindowScroll = function () {
	var scrollTop = this.$window.scrollTop(),
		toolbarOffset = this.$.offset();

	if ( scrollTop > toolbarOffset.top ) {
		this.setPosition(
			0,
			toolbarOffset.left,
			this.$window.width() - this.$.outerWidth() - toolbarOffset.left
		);
	} else if ( this.floating ) {
		this.resetPosition();
	}
};

/**
 * Handle window scroll events while toolbar floating is enabled.
 *
 * Toolbar will stick to the top of the screen unless it would be over or under the last visible
 * branch node in the root of the document being edited, at which point it will stop just above it.
 *
 * @see ve.ui.Surface#event-toolbarPosition
 * @returns {jQuery.Event} e Window scroll event
 */
ve.ui.Toolbar.prototype.onWindowResize = function () {
	var offset = this.$.offset();

	if ( this.floating ) {
		this.$bar.css( {
			'left': offset.left,
			'right': this.$window.width() - this.$.outerWidth() - offset.left
		} );
		this.surface.emit( 'toolbarPosition', this.$bar );
	}
};
<commit_msg>If cursor is obscured by toolbar, on keypress scroll to cursor.<commit_after>/*!
 * VisualEditor UserInterface Toolbar class.
 *
 * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
 * @license The MIT License (MIT); see LICENSE.txt
 */

/**
 * UserInterface toolbar.
 *
 * @class
 * @extends ve.Element
 * @mixins ve.EventEmitter
 *
 * @constructor
 * @param {ve.ui.Surface} surface
 * @param {Object} [config] Config options
 * @cfg {boolean} [actions] Add an actions section opposite to the tools
 * @cfg {boolean} [shadow] Add a shadow below the toolbar
 */
ve.ui.Toolbar = function VeUiToolbar( surface, options ) {
	// Configuration initialization
	options = options || {};

	// Parent constructor
	ve.Element.call( this, options );

	// Mixin constructors
	ve.EventEmitter.call( this );

	// Properties
	this.surface = surface;
	this.$bar = this.$$( '<div>' );
	this.$tools = this.$$( '<div>' );
	this.$actions = this.$$( '<div>' );
	this.floating = false;
	this.$window = null;
	this.windowEvents = {
		'resize': ve.bind( this.onWindowResize, this ),
		'scroll': ve.bind( this.onWindowScroll, this ),
		'keypress': ve.bind( this.onWindowKeypress, this )
	};

	// Events
	this.$
		.add( this.$bar ).add( this.$tools ).add( this.$actions )
		.on( 'mousedown', false );

	// Initialization
	this.$tools.addClass( 've-ui-toolbar-tools' );
	this.$bar.addClass( 've-ui-toolbar-bar' ).append( this.$tools );
	if ( options.actions ) {
		this.$actions.addClass( 've-ui-toolbar-actions' );
		this.$bar.append( this.$actions );
	}
	this.$bar.append( '<div style="clear:both"></div>' );
	if ( options.shadow ) {
		this.$bar.append( '<div class="ve-ui-toolbar-shadow"></div>' );
	}
	this.$.addClass( 've-ui-toolbar' ).append( this.$bar );

	// Events
	this.surface.getModel().connect( this, { 'contextChange': 'onContextChange' } );
};

/* Inheritance */

ve.inheritClass( ve.ui.Toolbar, ve.Element );

ve.mixinClass( ve.ui.Toolbar, ve.EventEmitter );

/* Events */

/**
 * @event updateState
 * @see ve.dm.SurfaceFragment#getAnnotations
 * @param {ve.dm.Node[]} nodes List of nodes covered by the current selection
 * @param {ve.dm.AnnotationSet} full Annotations that cover all of the current selection
 * @param {ve.dm.AnnotationSet} partial Annotations that cover some or all of the current selection
 */

/* Methods */

/**
 * Handle window resize events while toolbar floating is enabled.
 *
 * @returns {jQuery.Event} e Window resize event
 */
ve.ui.Toolbar.prototype.onWindowScroll = function () {
	var scrollTop = this.$window.scrollTop(),
		toolbarOffset = this.$.offset();

	if ( scrollTop > toolbarOffset.top ) {
		this.setPosition(
			0,
			toolbarOffset.left,
			this.$window.width() - this.$.outerWidth() - toolbarOffset.left
		);
	} else if ( this.floating ) {
		this.resetPosition();
	}
};

/**
 * Handle window resize events while toolbar floating is enabled.
 *
 * Toolbar will stick to the top of the screen unless it would be over or under the last visible
 * branch node in the root of the document being edited, at which point it will stop just above it.
 *
 * @see ve.ui.Surface#event-toolbarPosition
 * @returns {jQuery.Event} e Window scroll event
 */
ve.ui.Toolbar.prototype.onWindowResize = function () {
	var offset = this.$.offset();

	if ( this.floating ) {
		this.$bar.css( {
			'left': offset.left,
			'right': this.$window.width() - this.$.outerWidth() - offset.left
		} );
		this.surface.emit( 'toolbarPosition', this.$bar );
	}
};

/**
 * Method to scroll to the cursor position while toolbar is floating on keypress only if
 * the cursor is obscured by the toolbar.
 *
 */
ve.ui.Toolbar.prototype.onWindowKeypress = function () {
	var cursorPos = this.surface.view.getSelectionRect(),
		scrollTo = cursorPos.end.y - this.surface.view.$.offset().top,
		obscured = cursorPos.end.y - this.$window.scrollTop() < this.$.height() + this.$.offset().top;

	// If toolbar is floating and cursor is obscured, scroll cursor into view
	if ( obscured && this.floating ) {
		$( 'html,body' ).animate( { scrollTop: scrollTo }, 0 );
	}
};

{'fraction_non_alphanumeric': 0.15805022156573117, 'fraction_numerical': 0.00255136296495233, 'mean_word_length': 3.6491885143570535, 'pattern_counts': {'":': 0, '<': 18, '<?xml version=': 0, '>': 19, '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': '100141', 'n_tokens_mistral': 2443, 'n_tokens_neox': 2344, 'n_words': 659}