2
0

stats.js 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. function smf_StatsCenter(oOptions)
  2. {
  3. this.opt = oOptions;
  4. this.oTable = null;
  5. this.oYears = {};
  6. this.bIsLoading = false;
  7. this.init();
  8. }
  9. smf_StatsCenter.prototype.init = function ()
  10. {
  11. this.oTable = document.getElementById(this.opt.sTableId);
  12. // Is the table actually present?
  13. if (typeof(this.oTable) != 'object')
  14. return;
  15. // Find all months and years defined in the table.
  16. var aRows = this.oTable.getElementsByTagName('tr');
  17. var aResults = [];
  18. var sYearId = null;
  19. var oCurYear = null;
  20. var sMonthId = null;
  21. var oCurMonth = null;
  22. for (var i = 0, n = aRows.length; i < n; i++)
  23. {
  24. // Check if the current row represents a year.
  25. if ((aResults = this.opt.reYearPattern.exec(aRows[i].id)) != null)
  26. {
  27. // The id is part of the pattern match.
  28. sYearId = aResults[1];
  29. // Setup the object that'll have the state information of the year.
  30. this.oYears[sYearId] = {
  31. oCollapseImage: document.getElementById(this.opt.sYearImageIdPrefix + sYearId),
  32. oMonths: {}
  33. };
  34. // Create a shortcut, makes things more readable.
  35. oCurYear = this.oYears[sYearId];
  36. // Use the collapse image to determine the current state.
  37. oCurYear.bIsCollapsed = oCurYear.oCollapseImage.src.indexOf(this.opt.sYearImageCollapsed) >= 0;
  38. // Setup the toggle element for the year.
  39. oCurYear.oToggle = new smc_Toggle({
  40. bToggleEnabled: true,
  41. bCurrentlyCollapsed: oCurYear.bIsCollapsed,
  42. instanceRef: this,
  43. sYearId: sYearId,
  44. funcOnBeforeCollapse: function () {
  45. this.opt.instanceRef.onBeforeCollapseYear(this);
  46. },
  47. aSwappableContainers: [
  48. ],
  49. aSwapImages: [
  50. {
  51. sId: this.opt.sYearImageIdPrefix + sYearId,
  52. srcExpanded: smf_images_url + '/' + this.opt.sYearImageExpanded,
  53. altExpanded: '-',
  54. srcCollapsed: smf_images_url + '/' + this.opt.sYearImageCollapsed,
  55. altCollapsed: '+'
  56. }
  57. ],
  58. aSwapLinks: [
  59. {
  60. sId: this.opt.sYearLinkIdPrefix + sYearId,
  61. msgExpanded: sYearId,
  62. msgCollapsed: sYearId
  63. }
  64. ]
  65. });
  66. }
  67. // Or maybe the current row represents a month.
  68. else if ((aResults = this.opt.reMonthPattern.exec(aRows[i].id)) != null)
  69. {
  70. // Set the id to the matched pattern.
  71. sMonthId = aResults[1];
  72. // Initialize the month as a child object of the year.
  73. oCurYear.oMonths[sMonthId] = {
  74. oCollapseImage: document.getElementById(this.opt.sMonthImageIdPrefix + sMonthId)
  75. };
  76. // Create a shortcut to the current month.
  77. oCurMonth = oCurYear.oMonths[sMonthId];
  78. // Determine whether the month is currently collapsed or expanded..
  79. oCurMonth.bIsCollapsed = oCurMonth.oCollapseImage.src.indexOf(this.opt.sMonthImageCollapsed) >= 0;
  80. var sLinkText = getInnerHTML(document.getElementById(this.opt.sMonthLinkIdPrefix + sMonthId));
  81. // Setup the toggle element for the month.
  82. oCurMonth.oToggle = new smc_Toggle({
  83. bToggleEnabled: true,
  84. bCurrentlyCollapsed: oCurMonth.bIsCollapsed,
  85. instanceRef: this,
  86. sMonthId: sMonthId,
  87. funcOnBeforeCollapse: function () {
  88. this.opt.instanceRef.onBeforeCollapseMonth(this);
  89. },
  90. funcOnBeforeExpand: function () {
  91. this.opt.instanceRef.onBeforeExpandMonth(this);
  92. },
  93. aSwappableContainers: [
  94. ],
  95. aSwapImages: [
  96. {
  97. sId: this.opt.sMonthImageIdPrefix + sMonthId,
  98. srcExpanded: smf_images_url + '/' + this.opt.sMonthImageExpanded,
  99. altExpanded: '-',
  100. srcCollapsed: smf_images_url + '/' + this.opt.sMonthImageCollapsed,
  101. altCollapsed: '+'
  102. }
  103. ],
  104. aSwapLinks: [
  105. {
  106. sId: this.opt.sMonthLinkIdPrefix + sMonthId,
  107. msgExpanded: sLinkText,
  108. msgCollapsed: sLinkText
  109. }
  110. ]
  111. });
  112. oCurYear.oToggle.opt.aSwappableContainers[oCurYear.oToggle.opt.aSwappableContainers.length] = aRows[i].id;
  113. }
  114. else if((aResults = this.opt.reDayPattern.exec(aRows[i].id)) != null)
  115. {
  116. oCurMonth.oToggle.opt.aSwappableContainers[oCurMonth.oToggle.opt.aSwappableContainers.length] = aRows[i].id;
  117. oCurYear.oToggle.opt.aSwappableContainers[oCurYear.oToggle.opt.aSwappableContainers.length] = aRows[i].id;
  118. }
  119. }
  120. // Collapse all collapsed years!
  121. for (i = 0; i < this.opt.aCollapsedYears.length; i++)
  122. this.oYears[this.opt.aCollapsedYears[i]].oToggle.toggle();
  123. }
  124. smf_StatsCenter.prototype.onBeforeCollapseYear = function (oToggle)
  125. {
  126. // Tell SMF that all underlying months have disappeared.
  127. for (var sMonth in this.oYears[oToggle.opt.sYearId].oMonths)
  128. if (this.oYears[oToggle.opt.sYearId].oMonths[sMonth].oToggle.opt.aSwappableContainers.length > 0)
  129. this.oYears[oToggle.opt.sYearId].oMonths[sMonth].oToggle.changeState(true);
  130. }
  131. smf_StatsCenter.prototype.onBeforeCollapseMonth = function (oToggle)
  132. {
  133. if (!oToggle.bCollapsed)
  134. {
  135. // Tell SMF that it the state has changed.
  136. getXMLDocument(smf_prepareScriptUrl(smf_scripturl) + 'action=stats;collapse=' + oToggle.opt.sMonthId + ';xml');
  137. // Remove the month rows from the year toggle.
  138. var aNewContainers = [];
  139. var oYearToggle = this.oYears[oToggle.opt.sMonthId.substr(0, 4)].oToggle;
  140. for (var i = 0, n = oYearToggle.opt.aSwappableContainers.length; i < n; i++)
  141. if (!in_array(oYearToggle.opt.aSwappableContainers[i], oToggle.opt.aSwappableContainers))
  142. aNewContainers[aNewContainers.length] = oYearToggle.opt.aSwappableContainers[i];
  143. oYearToggle.opt.aSwappableContainers = aNewContainers;
  144. }
  145. }
  146. smf_StatsCenter.prototype.onBeforeExpandMonth = function (oToggle)
  147. {
  148. // Ignore if we're still loading the previous batch.
  149. if (this.bIsLoading)
  150. return;
  151. if (oToggle.opt.aSwappableContainers.length == 0)
  152. {
  153. // A complicated way to call getXMLDocument, but stay in scope.
  154. this.tmpMethod = getXMLDocument;
  155. this.oXmlRequestHandle = this.tmpMethod(smf_prepareScriptUrl(smf_scripturl) + 'action=stats;expand=' + oToggle.opt.sMonthId + ';xml', this.onDocReceived);
  156. delete this.tmpMethod;
  157. if ('ajax_indicator' in window)
  158. ajax_indicator(true);
  159. this.bIsLoading = true;
  160. }
  161. // Silently let SMF know this one is expanded.
  162. else
  163. getXMLDocument(smf_prepareScriptUrl(smf_scripturl) + 'action=stats;expand=' + oToggle.opt.sMonthId + ';xml');
  164. }
  165. smf_StatsCenter.prototype.onDocReceived = function (oXMLDoc)
  166. {
  167. // Loop through all the months we got from the XML.
  168. var aMonthNodes = oXMLDoc.getElementsByTagName('month');
  169. for (var iMonthIndex = 0, iNumMonths = aMonthNodes.length; iMonthIndex < iNumMonths; iMonthIndex++)
  170. {
  171. var sMonthId = aMonthNodes[iMonthIndex].getAttribute('id');
  172. var iStart = document.getElementById('tr_month_' + sMonthId).rowIndex + 1;
  173. var sYearId = sMonthId.substr(0, 4);
  174. // Within the current months, check out all the days.
  175. var aDayNodes = aMonthNodes[iMonthIndex].getElementsByTagName('day');
  176. for (var iDayIndex = 0, iNumDays = aDayNodes.length; iDayIndex < iNumDays; iDayIndex++)
  177. {
  178. var oCurRow = this.oTable.insertRow(iStart + iDayIndex);
  179. oCurRow.className = this.opt.sDayRowClassname;
  180. oCurRow.id = this.opt.sDayRowIdPrefix + aDayNodes[iDayIndex].getAttribute('date');
  181. for (var iCellIndex = 0, iNumCells = this.opt.aDataCells.length; iCellIndex < iNumCells; iCellIndex++)
  182. {
  183. var oCurCell = oCurRow.insertCell(-1);
  184. if (this.opt.aDataCells[iCellIndex] == 'date')
  185. oCurCell.style.paddingLeft = '6ex';
  186. else
  187. oCurCell.style.textAlign = 'center';
  188. var sCurData = aDayNodes[iDayIndex].getAttribute(this.opt.aDataCells[iCellIndex]);
  189. oCurCell.appendChild(document.createTextNode(sCurData));
  190. }
  191. // Add these day rows to the toggle objects in case of collapse.
  192. this.oYears[sYearId].oMonths[sMonthId].oToggle.opt.aSwappableContainers[this.oYears[sYearId].oMonths[sMonthId].oToggle.opt.aSwappableContainers.length] = oCurRow.id;
  193. this.oYears[sYearId].oToggle.opt.aSwappableContainers[this.oYears[sYearId].oToggle.opt.aSwappableContainers.length] = oCurRow.id;
  194. }
  195. }
  196. this.bIsLoading = false;
  197. if (typeof(window.ajax_indicator) == 'function')
  198. ajax_indicator(false);
  199. }