YAHOO.rowExpander = function(elContainer, aColumnDefs, oDataSource, oConfigs) {
	oConfigs.MSG_LOADING = 'Chargement..';
	oConfigs.MSG_EMPTY = 'Aucun enregistrement trouvé.';
	YAHOO.rowExpander.superclass.constructor.call(this, elContainer,
			aColumnDefs, oDataSource, oConfigs);
	this.Dom = YAHOO.util.Dom;
	STRING_STATENAME = 'yui_dt_state';
	CLASS_EXPANDED = 'yui-dt-expanded';
	CLASS_COLLAPSED = 'yui-dt-collapsed';
	CLASS_EXPANSION = 'yui-dt-expansion';
	CLASS_LINER = 'yui-dt-liner';
	

	// From YUI 3
	indexOf = function(a, val) {
		for (var i = 0; i < a.length; i = i + 1) {
			if (a[i] === val) {
				return i;
			}
		}
		return -1;
	};

}

YAHOO.lang.extend(YAHOO.rowExpander, YAHOO.widget.DataTable, {
			// ///////////////////////////////////////////////////////////////////////////
			//
			// Private members
			//
			// ///////////////////////////////////////////////////////////////////////////

			/**
			 * Gets state object for a specific record associated with the
			 * DataTable.
			 * 
			 * @method _getRecordState
			 * @param {Mixed}
			 *            record_id Record / Row / or Index id
			 * @param {String}
			 *            key Key to return within the state object. Default is
			 *            to return all as a map
			 * @return {Object} State data object
			 * @type mixed
			 * @private
			 */
			_getRecordState : function(record_id, key) {
				var recordSet = this.getRecordSet();
				var row = this.Dom.getAncestorByTagName(record_id, 'tr');
				var row_data = recordSet.getRecord(row.id);
				if (!row_data) {
					return false;
				}
				var row_state = row_data.getData(STRING_STATENAME);
				var state_data = (row_state && key)
						? row_state[key]
						: row_state;

				return state_data || {};

			},

			/**
			 * Sets a value to a state object with a unique id for a record
			 * which is associated with the DataTable
			 * 
			 * @method _setRecordState
			 * @param {Mixed}
			 *            record_id Record / Row / or Index id
			 * @param {String}
			 *            key Key to use in map
			 * @param {Mixed}
			 *            value Value to assign to the key
			 * @return {Object} State data object
			 * @type mixed
			 * @private
			 */
			_setRecordState : function(record_id, key, value) {

				var recordSet = this.getRecordSet();
				var row = this.Dom.getAncestorByTagName(record_id, 'tr');
				var row_data = recordSet.getRecord(row.id);
				if (!row_data) {
					var row_data = this.getRecord(record_id);
					row = this.getRow(row_data);
				}
				var merged_data = row_data[STRING_STATENAME] || {};

				merged_data[key] = value;

				row_data.setData(STRING_STATENAME, merged_data);

				return merged_data;

			},

			// ///////////////////////////////////////////////////////////////////////////
			//
			// Public methods
			//
			// ///////////////////////////////////////////////////////////////////////////

			/**
			 * Over-ridden initAttributes method from DataTable
			 * 
			 * @method initAttributes
			 * @param {Mixed}
			 *            record_id Record / Row / or Index id
			 * @param {String}
			 *            key Key to use in map
			 * @param {Mixed}
			 *            value Value to assign to the key
			 * @return {Object} State data object
			 * @type mixed
			 */
			initAttributes : function(oConfigs) {

				oConfigs = oConfigs || {};

				YAHOO.rowExpander.superclass.initAttributes
						.call(this, oConfigs);

				/**
				 * @attribute rowExpansionTemplate
				 * @description Value for the rowExpansionTemplate attribute.
				 * @type {Mixed}
				 * @default ""
				 */

				this.setAttributeConfig("rowExpansionTemplate", {
							value : "",
							validator : function(template) {
								return (YAHOO.lang.isString(template) || YAHOO.lang
										.isFunction(template));
							},
							method : this.initRowExpansion
						});

			},

			/**
			 * Initializes row expansion on the DataTable instance
			 * 
			 * @method initRowExpansion
			 * @param {Mixed}
			 *            template a string template or function to be called
			 *            when Row is expanded
			 * @type mixed
			 */
			initRowExpansion : function(template) {

				// Set subscribe restore method

				this.subscribe('postRenderEvent',
						this.onEventRestoreRowExpansion);

				// Setup template
				this.rowExpansionTemplate = template;

				// Set table level state
				this.a_rowExpansions = [];

			},

			/**
			 * Toggles the expansion state of a row
			 * 
			 * @method toggleRowExpansion
			 * @param {Mixed}
			 *            record_id Record / Row / or Index id
			 * @type mixed
			 */
			toggleRowExpansion : function(record_id) {
				var state = this._getRecordState(record_id);

				if (state && state.expanded) {
					this.collapseRow(record_id);
				} else {
					this.expandRow(record_id);
				}

			},

			/**
			 * Sets the expansion state of a row to expanded
			 * 
			 * @method expandRow
			 * @param {Mixed}
			 *            record_id Record / Row / or Index id
			 * @param {Boolean}
			 *            restore will restore an exisiting state for a row that
			 *            has been collapsed by a non user action
			 * @return {Boolean} successful
			 * @type mixed
			 */
			expandRow : function(record_id, restore) {

				var state = this._getRecordState(record_id);

				if (!state.expanded || restore) {
					if (state == false) {
						var row_data = this.getRecord(record_id);
						var row = this.getRow(row_data)
					} else {
						var recordSet = this.getRecordSet();
						var row = this.Dom
								.getAncestorByTagName(record_id, 'tr');
						var row_data = recordSet.getRecord(row.id);
					}

					var new_row = document.createElement('tr');

					var column_length = this.getFirstTrEl().childNodes.length;
					var expanded_data = row_data.getData();
					var expanded_content = null;
					var template = this.rowExpansionTemplate;
					// var next_sibling = this.Dom.getNextSibling(row);

					// Construct expanded row body
					new_row.className = CLASS_EXPANSION;

					var new_column = document.createElement('td');
					new_column.colSpan = column_length;

					new_column.innerHTML = '<div class="' + CLASS_LINER
							+ '"></div>';
					new_row.appendChild(new_column);

					var liner_element = new_row.firstChild.firstChild;

					if (YAHOO.lang.isString(template)) {
						var trimPath = TrimPath.parseTemplate(template);
						liner_element.innerHTML = trimPath
								.process(expanded_data);

					} else if (YAHOO.lang.isFunction(template)) {

						template({
									row_element : new_row,
									liner_element : liner_element,
									data : row_data,
									state : state

								});

					} else {

						return false;

					}

					// Insert new row
					newRow = this.Dom.insertAfter(new_row, row);

					if (newRow.innerHTML.length) {

						this._setRecordState(record_id, 'expanded', true);

						if (!restore) {
							this.a_rowExpansions.push(row.id);
						}

						this.Dom.removeClass(row, CLASS_COLLAPSED);
						this.Dom.addClass(row, CLASS_EXPANDED);

						// Fire custom event
						this.fireEvent("rowExpandEvent", {
									record_id : row_data.getId()
								});

						return true;

					} else {

						return false;

					}

				}

			},

			/**
			 * Sets the expansion state of a row to collapsed
			 * 
			 * @method collapseRow
			 * @param {Mixed}
			 *            record_id Record / Row / or Index id
			 * @return {Boolean} successful
			 * @type mixed
			 */
			collapseRow : function(record_id) {

				var state = this._getRecordState(record_id);

				if (state && state.expanded) {
					var row = this.Dom.getAncestorByTagName(record_id, 'tr');

					var next_sibling = this.Dom.getNextSibling(row);

					var hash_index = indexOf(this.a_rowExpansions, row.id);

					if (this.Dom.hasClass(next_sibling, CLASS_EXPANSION)) {

						next_sibling.parentNode.removeChild(next_sibling);
						this.a_rowExpansions.splice(hash_index, 1);
						this._setRecordState(record_id, 'expanded', false);
						this.Dom.addClass(row, CLASS_COLLAPSED);
						this.Dom.removeClass(row, CLASS_EXPANDED);

						// Fire custom event
						this.fireEvent("rowCollapseEvent", {
									record_id : row_data.getId()
								});

						return true;

					} else {
						return false;

					}

				}

			},

			/**
			 * Collapses all expanded rows. This should be called before any
			 * action where the row expansion markup would interfear with normal
			 * DataTable markup handling. This method does not remove exents
			 * attached during implementation. All event handlers should be
			 * removed separately.
			 * 
			 * @method collapseAllRows
			 * @type mixed
			 */
			collapseAllRows : function() {

				var rows = this.a_rowExpansions;

				for (var i = 0, l = rows.length; l > i; i++) {

					// Always pass 0 since collapseRow removes item from the
					// a_rowExpansions array
					this.collapseRow(rows[0]);

				}

				a_rowExpansions = [];

			},

			/**
			 * Restores rows which have an expanded state but no markup. This is
			 * to be called to restore row expansions after the DataTable
			 * renders or the collapseAllRows is called.
			 * 
			 * @method collapseAllRows
			 * @type mixed
			 */
			restoreExpandedRows : function() {

				var expanded_rows = this.a_rowExpansions;
				if (!expanded_rows.length) {

					return;

				}

				if (this.a_rowExpansions.length) {

					for (var i = 0, l = expanded_rows.length; l > i; i++) {
						this.expandRow(expanded_rows[i], true);

					}

				}

			},

			/**
			 * Abstract method which restores row expansion for subscribing to
			 * the DataTable postRenderEvent.
			 * 
			 * @method onEventRestoreRowExpansion
			 * @param {Object}
			 *            oArgs context of a subscribed event
			 * @type mixed
			 */
			onEventRestoreRowExpansion : function(oArgs) {

				this.restoreExpandedRows();

			},

			/**
			 * Abstract method which toggles row expansion for subscribing to
			 * the DataTable postRenderEvent.
			 * 
			 * @method onEventToggleRowExpansion
			 * @param {Object}
			 *            oArgs context of a subscribed event
			 * @type mixed
			 */
			onEventToggleRowExpansion : function(oArgs) {
				var cls= YAHOO.util.Dom.getAttribute(oArgs.target,'class');
				
				if (cls) {
					this.toggleRowExpansion(oArgs.target);
					console.log(oArgs.target)
				}
			}

		});

