<commit_before>(function (Q, $) {
/**
 * @module Q-tools
 */
	
/**
 * Implements vertical drawers that work on most modern browsers,
 * including ones on touchscreens.
 * @class Q drawers
 * @constructor
 * @param {Object}   [options] Override various options for this tool
 *  @param {Element} [options.container=null] Optional container element for handling scrolling
 *  @param {Object}   [options.initial] Information for the initial animation
 *  @param {Number}   [options.initial.index=1] The index of the drawer to show, either 0 or 1
 *  @param {Number}   [options.initial.delay=0] Delay before starting initial animation
 *  @param {Number}   [options.initial.duration=300] The duration of the initial animation
 *  @param {Function} [options.initial.ease=Q.Animation.linear] The easing function of the initial animation
 *  @param {Object}   [options.transition] Information for the transition animation
 *  @param {Number}   [options.transition.duration=300] The duration of the transition animation
 *  @param {Function}   [options.transition.ease=Q.Animation.linear] The easing function of the transition animation
 *  @param {Function}   [options.width] Override the function that computes the width of the drawers
 *  @param {Function}   [options.height] Override the function that computes the height drawers tool
 *  @param {Array}   [options.heights=[100,100]] Array of [height0, height1] for drawers that are pinned
 *  @param {Array}   [options.placeholders=['','']] Array of [html0, html1] for drawers that are pinned
 *  @param {Array}   [options.behind=[true,false]] Array of [boolean0, boolean1] to indicate which drawer is behind the others
 *  @param {Array}   [options.bottom=[false,false]] Array of [boolean0, boolean1] to indicate whether to scroll to the bottom of a drawer after switching to it
 *  @param {Array}   [options.triggers=['plugins/Q/img/drawers/up.png', 'plugins/Q/img/drawers/down.png']] Array of [src0, src1] for img elements that act as triggers to swap drawers. Set array elements to false to avoid rendering a trigger.
 *  @param {Object}   [options.trigger]] Options for the trigger elements
 *  @param {Number}   [options.trigger.rightMargin=10]] How many pixels from the right side of the drawers
 *  @param {Number}   [options.transition=300]] Number of milliseconds for fading in the trigger images
 *  @param {Boolean}   [options.fullscreen=Q.info.isMobile && Q.info.isAndroid(1000)]] Whether the drawers should take up the whole screen
 *  @param {Number}   [options.foregroundZIndex=50] The z-index of the drawer in the foreground
 *  @param {Number}   [options.beforeSwap=new Q.Event()] Occurs right before drawer swap
 *  @param {Number}   [options.onSwap=new Q.Event()] Occurs right after drawer swap
 * @return {Q.Tool}
 */
Q.Tool.define("Q/drawers", function _Q_drawers(options) {
	var tool = this;
	var state = tool.state;
	var $te = $(tool.element);
	var $scrolling = state.$scrolling = 
		$(state.container && !state.fullscreen ? state.container : window);
	state.swapCount = 0;
	
	Q.addStylesheet('plugins/Q/css/drawers.css');
	
	if (state.fullscreen || !state.container) {
		state.container = $(tool.element).parents().eq(-3)[0];
	}
	
	if ($te.css('position') == 'static') {
		$te.css('position', 'relative');
	}

	if (!state.behind[0]) {
		state.bottom[0] = true;
	}
	if (!state.behind[1]) {
		state.bottom[1] = false;
	}

	state.$drawers = $(this.element).children();
	state.currentIndex = 1 - state.initial.index;
	state.canceledSwap = null;
	var lastScrollingHeight;
	setTimeout(function () {
		state.lastScrollingHeight = $scrolling[0].clientHeight || $scrolling.height();
		tool.swap(_layout);
		Q.onLayout(tool).set(_layout, tool);
	}, state.initial.delay);
	
	$te.parents().each(function () {
		var $this = $(this);
		$this.data('Q/drawers originalBackground', $this.css('background'));
		$this.css('background', 'transparent');
		if ($this.is(state.container)) return false;
	});
	
	if (Q.info.isMobile) {
		this.managePinned();
	}
	
	// Accomodate mobile keyboard
	if (Q.info.isMobile) {
		state.$drawers.eq(0).on(Q.Pointer.focusin, tool, function () {
			state.$drawers.eq(1).hide();
			state.$trigger.hide();
		});
		state.$drawers.eq(0).on(Q.Pointer.focusout, tool, function () {
			state.$drawers.eq(1).show();
			state.$trigger.show();
		});
	}

	function _layout() {
		// to do: fix for cases where element doesn't take up whole screen
		if (Q.info.isMobile) {
			var w = state.drawerWidth = $(window).width();
			$(tool.element).width(w);
			state.$drawers.each(function () {
				var $this = $(this);
				$this.width(w - $this.outerWidth(true) + $this.width());
			});
			state.$drawers.height();
		}
		var sh = $scrolling[0].clientHeight || $scrolling.height();
		var sHeights = (state.heights instanceof Array)
			? state.heights : Q.getObject(state.heights).apply(tool);
		var $d0 = state.$drawers.eq(0);
		var $d1 = state.$drawers.eq(1);
		$d0.css('min-height', sh-sHeights[1]+'px');
		$d1.css('min-height', sh-sHeights[0]+'px');
		if (state.currentIndex == 0) {
			var heightDiff = sh - lastScrollingHeight;
			var offset = $d1.offset();
			$d1.offset({
				left: offset.left,
				top: offset.top + heightDiff
			});
		}
		state.lastScrollingHeight = $scrolling[0].clientHeight || $scrolling.height();
	}
},

{
	initial: {
		delay: 0,
		duration: 300,
		ease: Q.Animation.linear,
		index: 1
	},
	transition: {
		duration: 300,
		easing: Q.Animation.linear
	},
	container: null,
	width: function () { return $(this.element).width() },
	height: function () {
		var sp = this.element.scrollingParent();
		if (sp === document.documentElement) {
			return Q.Pointer.windowHeight() - $(this.element).offset().top;
		}
		return this.clientHeight;
	},
	currentIndex: null,
	placeholders: ['', ''],
	heights: [100, 100],
	behind: [true, false],
	bottom: [false, false],
	triggers: ['plugins/Q/img/drawers/up.png', 'plugins/Q/img/drawers/down.png'],
	trigger: { rightMargin: 10, transition: 300 },
	fullscreen: Q.info.isMobile && Q.info.isAndroid(1000),
	foregroundZIndex: 50,
	beforeSwap: new Q.Event(),
	onSwap: new Q.Event()
},

{	
	swap: function (callback, animationStartCallback) {
		var tool = this;
		var state = tool.state;
		
		if (state.locked) return false;
		state.locked = true;
		
		var otherIndex = state.currentIndex;
		var index = state.currentIndex = (state.currentIndex + 1) % 2;
		var $drawer = state.$drawers.eq(index);
		var $otherDrawer = state.$drawers.eq(otherIndex);
		var sWidth = (typeof state.width === 'number')<commit_msg>Fixed drawer height refactoring<commit_after>(function (Q, $) {
/**
 * @module Q-tools
 */
	
/**
 * Implements vertical drawers that work on most modern browsers,
 * including ones on touchscreens.
 * @class Q drawers
 * @constructor
 * @param {Object}   [options] Override various options for this tool
 *  @param {Element} [options.container=null] Optional container element for handling scrolling
 *  @param {Object}   [options.initial] Information for the initial animation
 *  @param {Number}   [options.initial.index=1] The index of the drawer to show, either 0 or 1
 *  @param {Number}   [options.initial.delay=0] Delay before starting initial animation
 *  @param {Number}   [options.initial.duration=300] The duration of the initial animation
 *  @param {Function} [options.initial.ease=Q.Animation.linear] The easing function of the initial animation
 *  @param {Object}   [options.transition] Information for the transition animation
 *  @param {Number}   [options.transition.duration=300] The duration of the transition animation
 *  @param {Function}   [options.transition.ease=Q.Animation.linear] The easing function of the transition animation
 *  @param {Function}   [options.width] Override the function that computes the width of the drawers
 *  @param {Function}   [options.height] Override the function that computes the height drawers tool
 *  @param {Array}   [options.heights=[100,100]] Array of [height0, height1] for drawers that are pinned
 *  @param {Array}   [options.placeholders=['','']] Array of [html0, html1] for drawers that are pinned
 *  @param {Array}   [options.behind=[true,false]] Array of [boolean0, boolean1] to indicate which drawer is behind the others
 *  @param {Array}   [options.bottom=[false,false]] Array of [boolean0, boolean1] to indicate whether to scroll to the bottom of a drawer after switching to it
 *  @param {Array}   [options.triggers=['plugins/Q/img/drawers/up.png', 'plugins/Q/img/drawers/down.png']] Array of [src0, src1] for img elements that act as triggers to swap drawers. Set array elements to false to avoid rendering a trigger.
 *  @param {Object}   [options.trigger]] Options for the trigger elements
 *  @param {Number}   [options.trigger.rightMargin=10]] How many pixels from the right side of the drawers
 *  @param {Number}   [options.transition=300]] Number of milliseconds for fading in the trigger images
 *  @param {Boolean}   [options.fullscreen=Q.info.isMobile && Q.info.isAndroid(1000)]] Whether the drawers should take up the whole screen
 *  @param {Number}   [options.foregroundZIndex=50] The z-index of the drawer in the foreground
 *  @param {Number}   [options.beforeSwap=new Q.Event()] Occurs right before drawer swap
 *  @param {Number}   [options.onSwap=new Q.Event()] Occurs right after drawer swap
 * @return {Q.Tool}
 */
Q.Tool.define("Q/drawers", function _Q_drawers(options) {
	var tool = this;
	var state = tool.state;
	var $te = $(tool.element);
	var $scrolling = state.$scrolling = 
		$(state.container && !state.fullscreen ? state.container : window);
	state.swapCount = 0;
	
	Q.addStylesheet('plugins/Q/css/drawers.css');
	
	if (state.fullscreen || !state.container) {
		state.container = $(tool.element).parents().eq(-3)[0];
	}
	
	if ($te.css('position') == 'static') {
		$te.css('position', 'relative');
	}

	if (!state.behind[0]) {
		state.bottom[0] = true;
	}
	if (!state.behind[1]) {
		state.bottom[1] = false;
	}

	state.$drawers = $(this.element).children();
	state.currentIndex = 1 - state.initial.index;
	state.canceledSwap = null;
	var lastScrollingHeight;
	setTimeout(function () {
		state.lastScrollingHeight = $scrolling[0].clientHeight || $scrolling.height();
		tool.swap(_layout);
		Q.onLayout(tool).set(_layout, tool);
	}, state.initial.delay);
	
	$te.parents().each(function () {
		var $this = $(this);
		$this.data('Q/drawers originalBackground', $this.css('background'));
		$this.css('background', 'transparent');
		if ($this.is(state.container)) return false;
	});
	
	if (Q.info.isMobile) {
		this.managePinned();
	}
	
	// Accomodate mobile keyboard
	if (Q.info.isMobile) {
		state.$drawers.eq(0).on(Q.Pointer.focusin, tool, function () {
			state.$drawers.eq(1).hide();
			state.$trigger.hide();
		});
		state.$drawers.eq(0).on(Q.Pointer.focusout, tool, function () {
			state.$drawers.eq(1).show();
			state.$trigger.show();
		});
	}

	function _layout() {
		// to do: fix for cases where element doesn't take up whole screen
		if (Q.info.isMobile) {
			var w = state.drawerWidth = $(window).width();
			$(tool.element).width(w);
			state.$drawers.each(function () {
				var $this = $(this);
				$this.width(w - $this.outerWidth(true) + $this.width());
			});
			state.$drawers.height();
		}
		var sh = $scrolling[0].clientHeight || $scrolling.height();
		var sHeights = (state.heights instanceof Array)
			? state.heights : Q.getObject(state.heights).apply(tool);
		var $d0 = state.$drawers.eq(0);
		var $d1 = state.$drawers.eq(1);
		$d0.css('min-height', sh-sHeights[1]+'px');
		$d1.css('min-height', sh-sHeights[0]+'px');
		if (state.currentIndex == 0) {
			var heightDiff = sh - lastScrollingHeight;
			var offset = $d1.offset();
			$d1.offset({
				left: offset.left,
				top: offset.top + heightDiff
			});
		}
		state.lastScrollingHeight = $scrolling[0].clientHeight || $scrolling.height();
	}
},

{
	initial: {
		delay: 0,
		duration: 300,
		ease: Q.Animation.linear,
		index: 1
	},
	transition: {
		duration: 300,
		easing: Q.Animation.linear
	},
	container: null,
	width: function () { return $(this.element).width() },
	height: function () {
		var sp = this.element.scrollingParent();
		if (sp === document.documentElement) {
			return Q.Pointer.windowHeight() - $(this.element).offset().top;
		}
		return sp.clientHeight;
	},
	currentIndex: null,
	placeholders: ['', ''],
	heights: [100, 100],
	behind: [true, false],
	bottom: [false, false],
	triggers: ['plugins/Q/img/drawers/up.png', 'plugins/Q/img/drawers/down.png'],
	trigger: { rightMargin: 10, transition: 300 },
	fullscreen: Q.info.isMobile && Q.info.isAndroid(1000),
	foregroundZIndex: 50,
	beforeSwap: new Q.Event(),
	onSwap: new Q.Event()
},

{	
	swap: function (callback, animationStartCallback) {
		var tool = this;
		var state = tool.state;
		
		if (state.locked) return false;
		state.locked = true;
		
		var otherIndex = state.currentIndex;
		var index = state.currentIndex = (state.currentIndex + 1) % 2;
		var $drawer = state.$drawers.eq(index);
		var $otherDrawer = state.$drawers.eq(otherIndex);
		var sWidth = (typeof state.width === 'number')
{'fraction_non_alphanumeric': 0.1539284622439621, 'fraction_numerical': 0.013757260776520942, 'mean_word_length': 4.147521636506688, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '4615325', 'n_tokens_mistral': 4600, 'n_tokens_neox': 4261, 'n_words': 1128}