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