<commit_before>var Emitter = require('events').EventEmitter;
var merge = require('merge');
var isArray = require('is-array');
var getHeight = require('./getHeight');

function Expander () {
	this.content;
	this.toggler;
	this.group;
	this.id;
	this.state;
}

Expander.prototype = merge(Expander.prototype, Emitter.prototype);

console.log(Expander.prototype);

/**
 * Set the state, update all elements and emit a status event.
 * Internal function.
 * @param {String} state The new state
 * @return {String} The current state
 */
Expander.prototype._setState = function (state) {
	if (!this.content) throw 'Expander: content is ' + this.content;
	if (!this.toggler) throw 'Expander: toggler is ' + this.toggler;

	this.state = state;
	this.content.setAttribute('data-expander-state', state);
	this.toggler.setAttribute('data-expander-state', state);
	this._emitStatus();

	return this.state;
}

/**
 * Broadcast the current state.
 * Internal function.
 */
Expander.prototype._emitStatus = function () {
	if (!this.state) throw 'Expander is stateless due to incorrect initialization.';

	this.emit(this.state);
}

Expander.prototype.open = function () {
	if (isArray(this.content)) throw 'Expander: content must be a single element.';

	var height = getHeight(this.content.children);
	
}

var test = document.querySelector('#test');
console.log(getHeight(test.children));
module.exports = Expander;<commit_msg>Heavy work on the main class<commit_after>var merge            = require('merge');
var isArray          = require('is-array');
var Emitter          = require('events').EventEmitter;
var transitionend    = require('transitionend-property');
var isHTMLCollection = require('./modules/isHTMLCollection');
var ExpanderGroup    = require('./ExpanderGroup');
var getHeightCopy    = require('./modules/getHeightCopy');

// Check if browser has transitionend event
// In IE9, returnal is an empty object
var hasTransitionEnd = Object.prototype.toString.call(transitionend) == '[object String]';

// The exportable object
function Expander (element) {
	this.content;
	this.toggler;
	this.group;
	this.hasGroup;
	this.id;
	this.state;

	if (element) { return this.initialize(element); }
}

Expander.prototype = merge(Expander.prototype, Emitter.prototype);

/**
 * Set the state, update all elements and emit a status event.
 * Internal function.
 * @param {String} state The new state
 * @return {String} The current state
 */
Expander.prototype._setState = function (state, emit) {
	if (!this.content) throw 'Expander: content is ' + this.content;
	if (!this.toggler) throw 'Expander: toggler is ' + this.toggler;
	if (!emit) emit = true;

	// Save state on instance
	this.state = state;

	// Set state reference for CSS rules
	this.content.setAttribute('data-expander-state', state);
	for (var i = 0; i < this.toggler.length; i++) {
		this.toggler[i].setAttribute('data-expander-state', state);
	}

	// Handle accessibility aria attribute
	if (state == 'open') {
		this._setAria('true');
	} else if (state == 'closed') {
		this._setAria('false');
	}

	// Emit status on instance
	if (emit) this._emitStatus(state);

	// Return the state
	return this.state;
}

/**
 * Set the aria-expanded attribute for
 * better accessibility of the expander
 * @param {String} state State according to
 *                       http://www.w3.org/TR/wai-aria/states_and_properties#aria-expanded
 */
Expander.prototype._setAria = function (state) {
	//if (state != true || state != false || state != undefined) throw 'Aria state of ' + state + ' not allowed.';
	
	this.content.setAttribute('aria-expanded', state);
}

/**
 * Broadcast the current state.
 * Internal function.
 */
Expander.prototype._emitStatus = function () {
	this.emit(this.state);
}

/**
 * Reset inline style height and the state. Remove
 * transitionend event listener
 */
Expander.prototype._openedEventHandler = function () {

	//console.log('open', arguments);
	//if (this._boundEvent) {
		this.content.removeEventListener(transitionend, this._boundEvent);
	//}
	this.content.style.height = '';
	this._setState('open');
}

/**
 * Set the correct state. Remove transitionend event
 * listener
 */
Expander.prototype._closedEventHandler = function (e) {
	//if (this._boundEvent) {
		this.content.removeEventListener(transitionend, this._boundEvent);
	//}
	this._setState('closed');
}

/**
 * Open the expander
 * Pulic function
 */
Expander.prototype.open = function () {

	console.log(this);

	if (this.state != 'closed') return;
	if (isArray(this.content)) throw 'Expander: content must be a single element.';

	// Get the height of the contents children
	var height = getHeightCopy(this.content);

	// Close the open content if this is part of
	// a group
	if (this.group.openContent) {
		this.group.openContent.apply(this.group.openContent);
	}

	// Set the state
	this._setState('opening');

	// Set the height
	this.content.style.height = height + 'px';

	if (hasTransitionEnd) {

		// Register transitionend handler
		this._boundEvent = this._openedEventHandler.bind(this);
		this.content.addEventListener(transitionend, this._boundEvent);
	} else {

		// Fallback transitionend trigger
		this._openedEventHandler.apply(this);
	}
}

/**
 * Close the expander.
 * Public function
 */
Expander.prototype.close = function () {

	if (this.state != 'open') return;

	// Get the height directly from content
	this.content.style.height = this.content.offsetHeight + 'px';

	// Trigger page rendering
	this.content.offsetHeight;

	// Set state
	this._setState('closing');

	// Set height
	this.content.style.height = 0;

	if (hasTransitionEnd) {

		// Register transitionend event handler
		this._boundEvent = this._closedEventHandler.bind(this);
		this.content.addEventListener(transitionend, this._boundEvent);
	} else {

		// Fallback transitionend trigger
		this._closedEventHandler.apply(this);
	}
}

/**
 * Toggle the expander, based on current state
 * Public function
 */
Expander.prototype.toggle = function (e) {

	// Prevent following links or submitting
	// forms
	if (e && e.preventDefault) e.preventDefault();

	// Call close or open, depending on current state
	if (this.state == 'closed') {
		this.open.apply(this);
	} else if (this.state == 'open') {
		this.close.apply(this);
	} else {

		// State is invalid or the expander is 
		// currently animating -> do nothing.
		//console.log('Expander: Tried to toggle, but state was: ' + this.state);
	}
}

/**
 * Initialize an expander instance based on 
 * a content element
 * @param  {DOMElement} element The content of the expander
 * @return {Object}         The expander instance
 */
Expander.prototype.initialize = function (element) {

	var states = ['open', 'closed'];
	var id = element.getAttribute('data-expander-content');
	var state = element.getAttribute('data-expander-state');
	var groupID = element.getAttribute('data-expander-group');

	if (!id) throw 'Expander content with invalid data-expander-content attribute';

	this.content = element;
	this.id = id;
	//this.state = (states.indexOf(state) > 0) ? state : 'closed';
	this.group = (groupID) ? new ExpanderGroup() : false;
	this.toggler = document.querySelectorAll('[data-expander-toggler~="' + id + '"]');
	
	if (this.group) {
		this.group.id = groupID;
	}
	console.log('states', states.indexOf(state) >= 0)
	if (states.indexOf(state) >= 0) {
		this._setState(state, false);
	} else {
		this._setState('closed', false);
	}

	for (var i = 0; i < this.toggler.length; i++) {
		this.toggler[i].addEventListener('click', this.toggle.bind(this));
	}
	return this;
}

/**
 * Initialize all expanders based on the data-expander-content
 * attribute
 * @return {Array} All initialized instances
 */
Expander.autoInitialize = function () {

	var expanders = document.querySelectorAll('[data-expander-content]');
	var instances = [];

	for (var i = 0; i < expanders.length; i++) {
		instances.push(new Expander(expanders[i]));
	}

	return instances;
}

module.exports = Expander;
{'fraction_non_alphanumeric': 0.1422830591485621, 'fraction_numerical': 0.0011302273012683663, 'mean_word_length': 3.999372253609542, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 1, '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': '7105995', 'n_tokens_mistral': 2509, 'n_tokens_neox': 2447, 'n_words': 649}