src/pyams_skin/resources/js/ext/jquery-dataTables-rowGrouping.js
changeset 0 bb4aabe07487
equal deleted inserted replaced
-1:000000000000 0:bb4aabe07487
       
     1 /*
       
     2  * File:        jquery.dataTables.grouping.js
       
     3  * Version:     1.2.9.
       
     4  * Author:      Jovan Popovic
       
     5  *
       
     6  * Copyright 2013 Jovan Popovic, all rights reserved.
       
     7  *
       
     8  * This source file is free software, under either the GPL v2 license or a
       
     9  * BSD style license, as supplied with this software.
       
    10  *
       
    11  * This source file is distributed in the hope that it will be useful, but
       
    12  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
       
    13  * or FITNESS FOR A PARTICULAR PURPOSE.
       
    14  * Parameters:
       
    15  * @iGroupingColumnIndex                                 Integer             Index of the column that will be used for grouping - default 0
       
    16  * @sGroupingColumnSortDirection                         Enumeration         Sort direction of the group
       
    17  * @iGroupingOrderByColumnIndex                          Integer             Index of the column that will be used for ordering groups
       
    18  * @sGroupingClass                                       String              Class that will be associated to the group row. Default - "group"
       
    19  * @sGroupItemClass                                      String              Class that will be associated to the group row of group items. Default - "group-item"
       
    20  * @bSetGroupingClassOnTR                                Boolean             If set class will be set to the TR instead of the TD withing the grouping TR
       
    21  * @bHideGroupingColumn                                  Boolean             Hide column used for grouping once results are grouped. Default - true
       
    22  * @bHideGroupingOrderByColumn                           Boolean             Hide column used for ordering groups once results are grouped. Default - true
       
    23  * @sGroupBy                                             Enumeration         Type of grouping that should be applied. Values "name"(default), "letter", "year"
       
    24  * @sGroupLabelPrefix                                    String              Prefix that will be added to each group cell
       
    25  * @bExpandableGrouping                                  Boolean             Attach expand/collapse handlers to the grouping rows
       
    26  * @bExpandSingleGroup                                   Boolean             Use accordon grouping
       
    27  * @iExpandGroupOffset                                   Integer             Number of pixels to set scroll position above the currently selected group. If -1 scroll will be alligned to the table
       
    28  * General settings
       
    29  * @sDateFormat: "dd/MM/yyyy"                            String              Date format used for grouping
       
    30  * @sEmptyGroupLabel                                     String              Lable that will be placed as group if grouping cells are empty. Default "-"
       
    31 
       
    32  * Parameters used in the second level grouping
       
    33  * @iGroupingColumnIndex2                                Integer             Index of the secondary column that will be used for grouping - default 0
       
    34  * @sGroupingColumnSortDirection2                        Enumeration         Sort direction of the secondary group
       
    35  * @iGroupingOrderByColumnIndex2                         Integer             Index of the column that will be used for ordering secondary groups
       
    36  * @sGroupingClass2                                      String              Class that will be associated to the secondary group row. Default "subgroup"
       
    37  * @sGroupItemClass2                                     String              Class that will be associated to the secondary group row of group items. Default "subgroup-item"
       
    38  * @bHideGroupingColumn2                                 Boolean             Hide column used for secondary grouping once results are grouped. Default - true,
       
    39  * @bHideGroupingOrderByColumn2                          Boolean             Hide column used for ordering secondary groups once results are grouped. Default - true,
       
    40  * @sGroupBy2                                            Enumeration         Type of grouping that should be applied to secondary column. Values "name"(default), "letter", "year",
       
    41  * @sGroupLabelPrefix2                                   String              Prefix that will be added to each secondary group cell
       
    42  * @fnOnGrouped                                          Function            Function that is called when grouping is finished. Function has no parameters.
       
    43  */
       
    44 (function ($) {
       
    45 
       
    46 	"use strict";
       
    47 
       
    48 	$.fn.rowGrouping = function (options) {
       
    49 
       
    50 		function _fnOnGrouped() {
       
    51 
       
    52 		}
       
    53 
       
    54 		function _fnOnGroupCreated(oGroup, sGroup, iLevel) {
       
    55 			///<summary>
       
    56 			///Function called when a new grouping row is created(it should be overriden in properties)
       
    57 			///</summary>
       
    58 		}
       
    59 
       
    60 		function _fnOnGroupCompleted(oGroup, sGroup, iLevel) {
       
    61 			///<summary>
       
    62 			///Function called when a new grouping row is created(it should be overriden in properties)
       
    63 			///</summary>
       
    64 		}
       
    65 
       
    66 		function _getMonthName(iMonth) {
       
    67 			var asMonths = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
       
    68 			return asMonths[iMonth - 1];
       
    69 		}
       
    70 
       
    71 		var defaults = {
       
    72 
       
    73 			iGroupingColumnIndex: 0,
       
    74 			sGroupingColumnSortDirection: "",
       
    75 			iGroupingOrderByColumnIndex: -1,
       
    76 			sGroupingClass: "group",
       
    77 			sGroupItemClass: "group-item",
       
    78 			bHideGroupingColumn: true,
       
    79 			bHideGroupingOrderByColumn: true,
       
    80 			sGroupBy: "name",
       
    81 			sGroupLabelPrefix: "",
       
    82 			fnGroupLabelFormat: function (label) {
       
    83 				return label;
       
    84 			},
       
    85 			bExpandableGrouping: false,
       
    86 			bExpandSingleGroup: false,
       
    87 			iExpandGroupOffset: 100,
       
    88 			asExpandedGroups: null,
       
    89 
       
    90 			sDateFormat: "dd/MM/yyyy",
       
    91 			sEmptyGroupLabel: "-",
       
    92 			bSetGroupingClassOnTR: false,
       
    93 
       
    94 			iGroupingColumnIndex2: -1,
       
    95 			sGroupingColumnSortDirection2: "",
       
    96 			iGroupingOrderByColumnIndex2: -1,
       
    97 			sGroupingClass2: "subgroup",
       
    98 			sGroupItemClass2: "subgroup-item",
       
    99 			bHideGroupingColumn2: true,
       
   100 			bHideGroupingOrderByColumn2: true,
       
   101 			sGroupBy2: "name",
       
   102 			sGroupLabelPrefix2: "",
       
   103 			fnGroupLabelFormat2: function (label) {
       
   104 				return label;
       
   105 			},
       
   106 			bExpandableGrouping2: false,
       
   107 
       
   108 			fnOnGrouped: _fnOnGrouped,
       
   109 
       
   110 			fnOnGroupCreated: _fnOnGroupCreated,
       
   111 			fnOnGroupCompleted: _fnOnGroupCompleted,
       
   112 
       
   113 			oHideEffect: null, // { method: "hide", duration: "fast", easing: "linear" },
       
   114 			oShowEffect: null,//{ method: "show", duration: "slow", easing: "linear" }
       
   115 
       
   116 			bUseFilteringForGrouping: false // This is still work in progress option
       
   117 		};
       
   118 		return this.each(function (index, elem) {
       
   119 
       
   120 			var oTable = $(elem).dataTable();
       
   121 
       
   122 			var aoGroups = new Array();
       
   123 			$(this).dataTableExt.aoGroups = aoGroups;
       
   124 
       
   125 			function fnCreateGroupRow(sGroupCleaned, sGroup, iColspan) {
       
   126 				var nGroup = document.createElement('tr');
       
   127 				var nCell = document.createElement('td');
       
   128 				nGroup.id = "group-id-" + oTable.attr("id") + "_" + sGroupCleaned;
       
   129 
       
   130 				var oGroup = { id: nGroup.id, key: sGroupCleaned, text: sGroup, level: 0, groupItemClass: ".group-item-" + sGroupCleaned, dataGroup: sGroupCleaned, aoSubgroups: new Array() };
       
   131 
       
   132 
       
   133 				if (properties.bSetGroupingClassOnTR) {
       
   134 					nGroup.className = properties.sGroupingClass + " " + sGroupCleaned;
       
   135 				} else {
       
   136 					nCell.className = properties.sGroupingClass + " " + sGroupCleaned;
       
   137 				}
       
   138 
       
   139 				nCell.colSpan = iColspan;
       
   140 				nCell.innerHTML = properties.sGroupLabelPrefix + properties.fnGroupLabelFormat(sGroup == "" ? properties.sEmptyGroupLabel : sGroup, oGroup);
       
   141 				if (properties.bExpandableGrouping) {
       
   142 
       
   143 					if (!_fnIsGroupCollapsed(sGroupCleaned)) {
       
   144 						nCell.className += " expanded-group";
       
   145 						oGroup.state = "expanded";
       
   146 					} else {
       
   147 						nCell.className += " collapsed-group";
       
   148 						oGroup.state = "collapsed";
       
   149 					}
       
   150 					nCell.className += " group-item-expander";
       
   151 					$(nCell).attr('data-group', oGroup.dataGroup); //Fix provided by mssskhalsa (Issue 5)
       
   152 					$(nCell).attr("data-group-level", oGroup.level);
       
   153 					$(nCell).click(_fnOnGroupClick);
       
   154 				}
       
   155 				nGroup.appendChild(nCell);
       
   156 				aoGroups[sGroupCleaned] = oGroup;
       
   157 				oGroup.nGroup = nGroup;
       
   158 				properties.fnOnGroupCreated(oGroup, sGroupCleaned, 1);
       
   159 				return oGroup;
       
   160 			}
       
   161 
       
   162 			function _fnCreateGroup2Row(sGroup2, sGroupLabel, iColspan, oParentGroup) {
       
   163 
       
   164 				var nGroup2 = document.createElement('tr');
       
   165 				nGroup2.id = oParentGroup.id + "_" + sGroup2;
       
   166 				var nCell2 = document.createElement('td');
       
   167 				var dataGroup = oParentGroup.dataGroup + '_' + sGroup2;
       
   168 
       
   169 				var oGroup = { id: nGroup2.id, key: sGroup2, text: sGroupLabel, level: oParentGroup.level + 1, groupItemClass: ".group-item-" + dataGroup,
       
   170 					dataGroup: dataGroup, aoSubgroups: new Array()
       
   171 				};
       
   172 
       
   173 				if (properties.bSetGroupingClassOnTR) {
       
   174 					nGroup2.className = properties.sGroupingClass2 + " " + sGroup2;
       
   175 				} else {
       
   176 					nCell2.className = properties.sGroupingClass2 + " " + sGroup2;
       
   177 				}
       
   178 
       
   179 				nCell2.colSpan = iColspan;
       
   180 				nCell2.innerHTML = properties.sGroupLabelPrefix2 + properties.fnGroupLabelFormat2(sGroupLabel == "" ? properties.sEmptyGroupLabel : sGroupLabel, oGroup);
       
   181 
       
   182 				if (properties.bExpandableGrouping) {
       
   183 
       
   184 					nGroup2.className += " group-item-" + oParentGroup.dataGroup;
       
   185 				}
       
   186 
       
   187 
       
   188 				if (properties.bExpandableGrouping && properties.bExpandableGrouping2) {
       
   189 
       
   190 					if (!_fnIsGroupCollapsed(oGroup.dataGroup)) {
       
   191 						nCell2.className += " expanded-group";
       
   192 						oGroup.state = "expanded";
       
   193 					} else {
       
   194 						nCell2.className += " collapsed-group";
       
   195 						oGroup.state = "collapsed";
       
   196 					}
       
   197 					nCell2.className += " group-item-expander";
       
   198 					$(nCell2).attr('data-group', oGroup.dataGroup);
       
   199 					$(nCell2).attr("data-group-level", oGroup.level);
       
   200 					$(nCell2).click(_fnOnGroupClick);
       
   201 				}
       
   202 
       
   203 				nGroup2.appendChild(nCell2);
       
   204 
       
   205 				oParentGroup.aoSubgroups[oGroup.dataGroup] = oGroup;
       
   206 				aoGroups[oGroup.dataGroup] = oGroup;
       
   207 				oGroup.nGroup = nGroup2;
       
   208 				properties.fnOnGroupCreated(oGroup, sGroup2, 2);
       
   209 				return oGroup;
       
   210 			}
       
   211 
       
   212 			function _fnIsGroupCollapsed(sGroup) {
       
   213 				if (aoGroups[sGroup] != null)
       
   214 					return (aoGroups[sGroup].state == "collapsed");
       
   215 				else if (sGroup.indexOf("_") > -1)
       
   216 					true;
       
   217 				else if (bInitialGrouping && (asExpandedGroups == null || asExpandedGroups.length == 0))
       
   218 					return false;// initially if asExpandedGroups is empty - no one is collapsed
       
   219 				else
       
   220 					return ($.inArray(sGroup, asExpandedGroups) == -1); //the last chance check asExpandedGroups
       
   221 			}
       
   222 
       
   223 			function _fnGetYear(x) {
       
   224 				if (x.length < (iYearIndex + iYearLength))
       
   225 					return x;
       
   226 				else
       
   227 					return x.substr(iYearIndex, iYearLength);
       
   228 			}
       
   229 
       
   230 			function _fnGetGroupByName(x) {
       
   231 				return x;
       
   232 			}
       
   233 
       
   234 			function _fnGetGroupByLetter(x) {
       
   235 				return x.substr(0, 1);
       
   236 			}
       
   237 
       
   238 			function _fnGetGroupByYear(x) {
       
   239 				return _fnGetYear(x);
       
   240 				//return Date.parseExact(x, properties.sDateFormat).getFullYear();//slooooow
       
   241 			}
       
   242 
       
   243 			function _fnGetGroupByYearMonth(x) {
       
   244 				//var date = Date.parseExact(x, "dd/MM/yyyy");
       
   245 				//return date.getFullYear() + " / " + date.getMonthName();
       
   246 				//return x.substr(iYearIndex, iYearLength) + '/' + x.substr(iMonthIndex, iMonthLength);
       
   247 				return x.substr(iYearIndex, iYearLength) + ' ' + _getMonthName(x.substr(iMonthIndex, iMonthLength));
       
   248 			}
       
   249 
       
   250 			function _fnGetCleanedGroup(sGroup) {
       
   251 
       
   252 				if (sGroup === "") return "-";
       
   253 				return sGroup.toLowerCase().replace(/[^a-zA-Z0-9\u0080-\uFFFF]+/g, "-"); //fix for unicode characters (Issue 23)
       
   254 				//return sGroup.toLowerCase().replace(/\W+/g, "-"); //Fix provided by bmathews (Issue 7)
       
   255 			}
       
   256 
       
   257 			function _rowGroupingRowFilter(oSettings, aData, iDataIndex) {
       
   258 				///<summary>Used to expand/collapse groups with DataTables filtering</summary>
       
   259 				if (oSettings.nTable.id !== oTable[0].id) return true;
       
   260 				var sColData = aData[properties.iGroupingColumnIndex];
       
   261 				if (typeof sColData === "undefined")
       
   262 					sColData = aData[oSettings.aoColumns[properties.iGroupingColumnIndex].mDataProp];
       
   263 				if (_fnIsGroupCollapsed(_fnGetCleanedGroup(sColData))) {
       
   264 					if (oTable.fnIsOpen(oTable.fnGetNodes(iDataIndex))) {
       
   265 						if (properties.fnOnRowClosed != null) {
       
   266 							properties.fnOnRowClosed(this); //    $(this.cells[0].children[0]).attr('src', '../../Images/details.png');
       
   267 						}
       
   268 						oTable.fnClose(oTable.fnGetNodes(iDataIndex));
       
   269 					}
       
   270 					return false;
       
   271 				}
       
   272 				;
       
   273 				return true;
       
   274 			} //end of function _rowGroupingRowFilter
       
   275 
       
   276 
       
   277 			function fnExpandGroup(sGroup) {
       
   278 				///<summary>Expand group if expanadable grouping is used</summary>
       
   279 
       
   280 				aoGroups[sGroup].state = "expanded";
       
   281 
       
   282 				$("td[data-group^='" + sGroup + "']").removeClass("collapsed-group");
       
   283 				$("td[data-group^='" + sGroup + "']").addClass("expanded-group");
       
   284 
       
   285 
       
   286 				if (properties.bUseFilteringForGrouping) {
       
   287 					oTable.fnDraw();
       
   288 					return;//Because rows are expanded with _rowGroupingRowFilter function
       
   289 				}
       
   290 
       
   291 				if (jQuery.inArray(sGroup, asExpandedGroups) == -1)
       
   292 					asExpandedGroups.push(sGroup);
       
   293 
       
   294 				if (properties.oHideEffect != null)
       
   295 					$(".group-item-" + sGroup, oTable)
       
   296 						[properties.oShowEffect.method](properties.oShowEffect.duration,
       
   297 														properties.oShowEffect.easing,
       
   298 														function () {
       
   299 														});
       
   300 				else
       
   301 					$(".group-item-" + sGroup, oTable).show();
       
   302 
       
   303 
       
   304 			} //end of function fnExpandGroup
       
   305 
       
   306 			function fnCollapseGroup(sGroup) {
       
   307 				///<summary>Collapse group if expanadable grouping is used</summary>
       
   308 
       
   309 				aoGroups[sGroup].state = "collapsed";
       
   310 				$("td[data-group^='" + sGroup + "']").removeClass("expanded-group");
       
   311 				$("td[data-group^='" + sGroup + "']").addClass("collapsed-group");
       
   312 
       
   313 				if (properties.bUseFilteringForGrouping) {
       
   314 					oTable.fnDraw();
       
   315 					return;//Because rows are expanded with _rowGroupingRowFilter function
       
   316 				}
       
   317 				//var index = $.inArray(sGroup, asExpandedGroups);
       
   318 				//asExpandedGroups.splice(index, 1);
       
   319 
       
   320 				$('.group-item-' + sGroup).each(function () {
       
   321 					//Issue 24 - Patch provided by Bob Graham
       
   322 					if (oTable.fnIsOpen(this)) {
       
   323 						if (properties.fnOnRowClosed != null) {
       
   324 							properties.fnOnRowClosed(this); //    $(this.cells[0].children[0]).attr('src', '../../Images/details.png');
       
   325 						}
       
   326 						oTable.fnClose(this);
       
   327 					}
       
   328 				});
       
   329 
       
   330 				if (properties.oHideEffect != null)
       
   331 					$(".group-item-" + sGroup, oTable)
       
   332 						[properties.oHideEffect.method](properties.oHideEffect.duration,
       
   333 														properties.oHideEffect.easing,
       
   334 														function () {
       
   335 														});
       
   336 				else
       
   337 					$(".group-item-" + sGroup, oTable).hide();
       
   338 
       
   339 			} //end of function fnCollapseGroup
       
   340 
       
   341 			function _fnOnGroupClick(e) {
       
   342 				///<summary>
       
   343 				///Function that is called when user click on the group cell in order to
       
   344 				///expand of collapse group
       
   345 				///</summary>
       
   346 
       
   347 				//var sGroup = $(this).attr("rel");
       
   348 				var sGroup = $(this).attr("data-group");
       
   349 				var iGroupLevel = $(this).attr("data-group-level");
       
   350 
       
   351 				var bIsExpanded = !_fnIsGroupCollapsed(sGroup);
       
   352 				if (properties.bExpandSingleGroup) {
       
   353 					if (!bIsExpanded) {
       
   354 						var sCurrentGroup = $("td.expanded-group").attr("data-group");
       
   355 						fnCollapseGroup(sCurrentGroup);
       
   356 						fnExpandGroup(sGroup);
       
   357 
       
   358 						if (properties.iExpandGroupOffset != -1) {
       
   359 							var position = $("#group-id-" + oTable.attr("id") + "_" + sGroup).offset().top - properties.iExpandGroupOffset;
       
   360 							window.scroll(0, position);
       
   361 						} else {
       
   362 							var position = oTable.offset().top;
       
   363 							window.scroll(0, position);
       
   364 						}
       
   365 					}
       
   366 				} else {
       
   367 					if (bIsExpanded) {
       
   368 						fnCollapseGroup(sGroup);
       
   369 					} else {
       
   370 						fnExpandGroup(sGroup);
       
   371 					}
       
   372 				}
       
   373 				e.preventDefault();
       
   374 
       
   375 			}; //end function _fnOnGroupClick
       
   376 
       
   377 
       
   378 			function _fnDrawCallBackWithGrouping(oSettings) {
       
   379 
       
   380 				if (oTable.fnSettings().oFeatures.bServerSide)
       
   381 					bInitialGrouping = true;
       
   382 				var bUseSecondaryGrouping = false;
       
   383 
       
   384 				if (properties.iGroupingColumnIndex2 != -1)
       
   385 					bUseSecondaryGrouping = true;
       
   386 
       
   387 				//-----Start grouping
       
   388 
       
   389 				if (oSettings.aiDisplayMaster.length == 0) { //aiDisplay
       
   390 					return;
       
   391 				}
       
   392 
       
   393 				var nTrs = $('tbody tr', oTable);
       
   394 				var iColspan = 0; //nTrs[0].getElementsByTagName('td').length;
       
   395 				for (var iColIndex = 0; iColIndex < oSettings.aoColumns.length; iColIndex++) {
       
   396 					if (oSettings.aoColumns[iColIndex].bVisible)
       
   397 						iColspan += 1;
       
   398 				}
       
   399 				var sLastGroup = null;
       
   400 				var sLastGroup2 = null;
       
   401 				if (oSettings.aiDisplay.length > 0) {
       
   402 					for (var i = 0; i < nTrs.length; i++) {
       
   403 
       
   404 
       
   405 						var iDisplayIndex = oSettings._iDisplayStart + i;
       
   406 						if (oTable.fnSettings().oFeatures.bServerSide)
       
   407 							iDisplayIndex = i;
       
   408 						var sGroupData = "";
       
   409 						var sGroup = null;
       
   410 						var sGroupData2 = "";
       
   411 						var sGroup2 = null;
       
   412 
       
   413 						//Issue 31 - Start fix provided by Fabien Taysse
       
   414 //                      sGroupData = oSettings.aoData[oSettings.aiDisplay[iDisplayIndex]]._aData[properties.iGroupingColumnIndex];
       
   415 //                      if (sGroupData == undefined)
       
   416 //                          sGroupData = oSettings.aoData[oSettings.aiDisplay[iDisplayIndex]]._aData[oSettings.aoColumns[properties.iGroupingColumnIndex].mDataProp];
       
   417 						sGroupData = this.fnGetData(nTrs[i], properties.iGroupingColumnIndex);
       
   418 						//Issue 31 - End fix provided by Fabien Taysse
       
   419 
       
   420 						var sGroup = sGroupData;
       
   421 						if (properties.sGroupBy != "year")
       
   422 							sGroup = fnGetGroup(sGroupData);
       
   423 
       
   424 						if (bUseSecondaryGrouping) {
       
   425 							sGroupData2 = oSettings.aoData[oSettings.aiDisplay[iDisplayIndex]]._aData[properties.iGroupingColumnIndex2];
       
   426 							if (sGroupData2 == undefined)
       
   427 								sGroupData2 = oSettings.aoData[oSettings.aiDisplay[iDisplayIndex]]._aData[oSettings.aoColumns[properties.iGroupingColumnIndex2].mDataProp];
       
   428 							if (properties.sGroupBy2 != "year")
       
   429 								sGroup2 = fnGetGroup(sGroupData2);
       
   430 						}
       
   431 
       
   432 
       
   433 						if (sLastGroup == null || _fnGetCleanedGroup(sGroup) != _fnGetCleanedGroup(sLastGroup)) { // new group encountered (or first of group)
       
   434 							var sGroupCleaned = _fnGetCleanedGroup(sGroup);
       
   435 
       
   436 							if (sLastGroup != null) {
       
   437 								properties.fnOnGroupCompleted(aoGroups[_fnGetCleanedGroup(sLastGroup)]);
       
   438 							}
       
   439 							/*
       
   440 							 if (properties.bExpandableGrouping && bInitialGrouping) {
       
   441 							 if (properties.bExpandSingleGroup) {
       
   442 							 if (asExpandedGroups.length == 0)
       
   443 							 asExpandedGroups.push(sGroupCleaned);
       
   444 							 } else {
       
   445 							 asExpandedGroups.push(sGroupCleaned);
       
   446 							 }
       
   447 							 }
       
   448 							 */
       
   449 							if (properties.bAddAllGroupsAsExpanded && jQuery.inArray(sGroupCleaned, asExpandedGroups) == -1)
       
   450 								asExpandedGroups.push(sGroupCleaned);
       
   451 
       
   452 							var oGroup = fnCreateGroupRow(sGroupCleaned, sGroup, iColspan);
       
   453 							var nGroup = oGroup.nGroup;
       
   454 
       
   455 							if (nTrs[i].parentNode != null)
       
   456 								nTrs[i].parentNode.insertBefore(nGroup, nTrs[i]);
       
   457 							else
       
   458 								$(nTrs[i]).before(nGroup);
       
   459 
       
   460 							sLastGroup = sGroup;
       
   461 							sLastGroup2 = null; //to reset second level grouping
       
   462 
       
   463 
       
   464 						} // end if (sLastGroup == null || sGroup != sLastGroup)
       
   465 
       
   466 						$(nTrs[i]).attr("data-group", aoGroups[sGroupCleaned].dataGroup);
       
   467 
       
   468 						$(nTrs[i]).addClass(properties.sGroupItemClass);
       
   469 						$(nTrs[i]).addClass("group-item-" + sGroupCleaned);
       
   470 						if (properties.bExpandableGrouping) {
       
   471 							if (_fnIsGroupCollapsed(sGroupCleaned) && !properties.bUseFilteringForGrouping) {
       
   472 								$(nTrs[i]).hide();
       
   473 							}
       
   474 						}
       
   475 
       
   476 
       
   477 						if (bUseSecondaryGrouping) {
       
   478 
       
   479 							if (sLastGroup2 == null || _fnGetCleanedGroup(sGroup2) != _fnGetCleanedGroup(sLastGroup2)) {
       
   480 								var sGroup2Id = _fnGetCleanedGroup(sGroup) + '-' + _fnGetCleanedGroup(sGroup2);
       
   481 								var oGroup2 = _fnCreateGroup2Row(sGroup2Id, sGroup2, iColspan, aoGroups[sGroupCleaned])
       
   482 								var nGroup2 = oGroup2.nGroup;
       
   483 								nTrs[i].parentNode.insertBefore(nGroup2, nTrs[i]);
       
   484 
       
   485 								sLastGroup2 = sGroup2;
       
   486 							}
       
   487 
       
   488 							$(nTrs[i]).attr("data-group", oGroup2.dataGroup)
       
   489 								.addClass(properties.sGroupItemClass2)
       
   490 								.addClass("group-item-" + oGroup2.dataGroup);
       
   491 						} //end if (bUseSecondaryGrouping)
       
   492 
       
   493 
       
   494 					} // end for (var i = 0; i < nTrs.length; i++)
       
   495 				}
       
   496 				; // if (oSettings.aiDisplay.length > 0)
       
   497 
       
   498 				if (sLastGroup != null) {
       
   499 					properties.fnOnGroupCompleted(aoGroups[_fnGetCleanedGroup(sLastGroup)]);
       
   500 				}
       
   501 
       
   502 
       
   503 				//-----End grouping
       
   504 				properties.fnOnGrouped(aoGroups);
       
   505 
       
   506 				bInitialGrouping = false;
       
   507 
       
   508 			}; // end of _fnDrawCallBackWithGrouping = function (oSettings)
       
   509 
       
   510 
       
   511 			//var oTable = this;
       
   512 			var iYearIndex = 6;
       
   513 			var iYearLength = 4;
       
   514 			var asExpandedGroups = new Array();
       
   515 			var bInitialGrouping = true;
       
   516 
       
   517 			var properties = $.extend(defaults, options);
       
   518 
       
   519 			if (properties.iGroupingOrderByColumnIndex == -1) {
       
   520 				properties.bCustomColumnOrdering = false;
       
   521 				properties.iGroupingOrderByColumnIndex = properties.iGroupingColumnIndex;
       
   522 			} else {
       
   523 				properties.bCustomColumnOrdering = true;
       
   524 			}
       
   525 
       
   526 			if (properties.sGroupingColumnSortDirection == "") {
       
   527 				if (properties.sGroupBy == "year")
       
   528 					properties.sGroupingColumnSortDirection = "desc";
       
   529 				else
       
   530 					properties.sGroupingColumnSortDirection = "asc";
       
   531 			}
       
   532 
       
   533 
       
   534 			if (properties.iGroupingOrderByColumnIndex2 == -1) {
       
   535 				properties.bCustomColumnOrdering2 = false;
       
   536 				properties.iGroupingOrderByColumnIndex2 = properties.iGroupingColumnIndex2;
       
   537 			} else {
       
   538 				properties.bCustomColumnOrdering2 = true;
       
   539 			}
       
   540 
       
   541 			if (properties.sGroupingColumnSortDirection2 == "") {
       
   542 				if (properties.sGroupBy2 == "year")
       
   543 					properties.sGroupingColumnSortDirection2 = "desc";
       
   544 				else
       
   545 					properties.sGroupingColumnSortDirection2 = "asc";
       
   546 			}
       
   547 
       
   548 
       
   549 			iYearIndex = properties.sDateFormat.toLowerCase().indexOf('yy');
       
   550 			iYearLength = properties.sDateFormat.toLowerCase().lastIndexOf('y') - properties.sDateFormat.toLowerCase().indexOf('y') + 1;
       
   551 
       
   552 			var iMonthIndex = properties.sDateFormat.toLowerCase().indexOf('mm');
       
   553 			var iMonthLength = properties.sDateFormat.toLowerCase().lastIndexOf('m') - properties.sDateFormat.toLowerCase().indexOf('m') + 1;
       
   554 
       
   555 			var fnGetGroup = _fnGetGroupByName;
       
   556 			switch (properties.sGroupBy) {
       
   557 				case "letter":
       
   558 					fnGetGroup = _fnGetGroupByLetter;
       
   559 					break;
       
   560 				case "year":
       
   561 					fnGetGroup = _fnGetGroupByYear;
       
   562 					break;
       
   563 				case "month":
       
   564 					fnGetGroup = _fnGetGroupByYearMonth;
       
   565 					break;
       
   566 				default:
       
   567 					fnGetGroup = _fnGetGroupByName;
       
   568 					break;
       
   569 			}
       
   570 
       
   571 
       
   572 			if (properties.asExpandedGroups != null) {
       
   573 				if (properties.asExpandedGroups == "NONE") {
       
   574 					properties.asExpandedGroups = [];
       
   575 					asExpandedGroups = properties.asExpandedGroups;
       
   576 					bInitialGrouping = false;
       
   577 				} else if (properties.asExpandedGroups == "ALL") {
       
   578 					properties.bAddAllGroupsAsExpanded = true;
       
   579 				} else if (properties.asExpandedGroups.constructor == String) {
       
   580 					var currentGroup = properties.asExpandedGroups;
       
   581 					properties.asExpandedGroups = new Array();
       
   582 					properties.asExpandedGroups.push(_fnGetCleanedGroup(currentGroup));
       
   583 					asExpandedGroups = properties.asExpandedGroups;
       
   584 					bInitialGrouping = false;
       
   585 				} else if (properties.asExpandedGroups.constructor == Array) {
       
   586 					for (var i = 0; i < properties.asExpandedGroups.length; i++) {
       
   587 						asExpandedGroups.push(_fnGetCleanedGroup(properties.asExpandedGroups[i]));
       
   588 						if (properties.bExpandSingleGroup)
       
   589 							break;
       
   590 					}
       
   591 					bInitialGrouping = false;
       
   592 				}
       
   593 			} else {
       
   594 				properties.asExpandedGroups = new Array();
       
   595 				properties.bAddAllGroupsAsExpanded = true;
       
   596 			}
       
   597 			if (properties.bExpandSingleGroup) {
       
   598 				var nTrs = $('tbody tr', oTable);
       
   599 				var sGroupData = oTable.fnGetData(nTrs[0], properties.iGroupingColumnIndex);
       
   600 
       
   601 				var sGroup = sGroupData;
       
   602 				if (properties.sGroupBy != "year")
       
   603 					sGroup = fnGetGroup(sGroupData);
       
   604 
       
   605 				var sGroupCleaned = _fnGetCleanedGroup(sGroup);
       
   606 				properties.asExpandedGroups = new Array();
       
   607 				properties.asExpandedGroups.push(sGroupCleaned);
       
   608 
       
   609 			}
       
   610 
       
   611 			oTable.fnSetColumnVis(properties.iGroupingColumnIndex, !properties.bHideGroupingColumn);
       
   612 			if (properties.bCustomColumnOrdering) {
       
   613 				oTable.fnSetColumnVis(properties.iGroupingOrderByColumnIndex, !properties.bHideGroupingOrderByColumn);
       
   614 			}
       
   615 			if (properties.iGroupingColumnIndex2 != -1) {
       
   616 				oTable.fnSetColumnVis(properties.iGroupingColumnIndex2, !properties.bHideGroupingColumn2);
       
   617 			}
       
   618 			if (properties.bCustomColumnOrdering2) {
       
   619 				oTable.fnSetColumnVis(properties.iGroupingOrderByColumnIndex2, !properties.bHideGroupingOrderByColumn2);
       
   620 			}
       
   621 			oTable.fnSettings().aoDrawCallback.push({
       
   622 														"fn": _fnDrawCallBackWithGrouping,
       
   623 														"sName": "fnRowGrouping"
       
   624 													});
       
   625 
       
   626 			var aaSortingFixed = new Array();
       
   627 			aaSortingFixed.push([properties.iGroupingOrderByColumnIndex, properties.sGroupingColumnSortDirection]);
       
   628 			if (properties.iGroupingColumnIndex2 != -1) {
       
   629 				aaSortingFixed.push([properties.iGroupingOrderByColumnIndex2, properties.sGroupingColumnSortDirection2]);
       
   630 			} // end of if (properties.iGroupingColumnIndex2 != -1)
       
   631 
       
   632 			oTable.fnSettings().aaSortingFixed = aaSortingFixed;
       
   633 			//Old way
       
   634 			//oTable.fnSettings().aaSortingFixed = [[properties.iGroupingOrderByColumnIndex, properties.sGroupingColumnSortDirection]];
       
   635 
       
   636 			switch (properties.sGroupBy) {
       
   637 				case "name":
       
   638 					break;
       
   639 
       
   640 
       
   641 				case "letter":
       
   642 
       
   643 					/* Create an array with the values of all the input boxes in a column */
       
   644 					oTable.fnSettings().aoColumns[properties.iGroupingOrderByColumnIndex].sSortDataType = "rg-letter";
       
   645 					$.fn.dataTableExt.afnSortData['rg-letter'] = function (oSettings, iColumn) {
       
   646 						var aData = [];
       
   647 						$('td:eq(' + iColumn + ')', oSettings.oApi._fnGetTrNodes(oSettings)).each(function () {
       
   648 							aData.push(_fnGetGroupByLetter(this.innerHTML));
       
   649 						});
       
   650 						return aData;
       
   651 					}
       
   652 
       
   653 
       
   654 					break;
       
   655 
       
   656 
       
   657 				case "year":
       
   658 					/* Create an array with the values of all the input boxes in a column */
       
   659 					oTable.fnSettings().aoColumns[properties.iGroupingOrderByColumnIndex].sSortDataType = "rg-date";
       
   660 					$.fn.dataTableExt.afnSortData['rg-date'] = function (oSettings, iColumn) {
       
   661 						var aData = [];
       
   662 						var nTrs = oSettings.oApi._fnGetTrNodes(oSettings);
       
   663 						for (i = 0; i < nTrs.length; i++) {
       
   664 							aData.push(_fnGetYear(oTable.fnGetData(nTrs[i], iColumn)));
       
   665 						}
       
   666 
       
   667 						/*
       
   668 						 $('td:eq(' + iColumn + ')', oSettings.oApi._fnGetTrNodes(oSettings)).each(function () {
       
   669 						 aData.push(_fnGetYear(this.innerHTML));
       
   670 						 });
       
   671 						 */
       
   672 						return aData;
       
   673 					}
       
   674 					break;
       
   675 				default:
       
   676 					break;
       
   677 
       
   678 			} // end of switch (properties.sGroupBy)
       
   679 
       
   680 			if (properties.bUseFilteringForGrouping)
       
   681 				$.fn.dataTableExt.afnFiltering.push(_rowGroupingRowFilter);
       
   682 
       
   683 			oTable.fnDraw();
       
   684 
       
   685 
       
   686 		});
       
   687 	};
       
   688 })(jQuery);