/* * Class representing a report (specifically a page of the report). */ //Utility functions var XmlUtil = { getContentAsString: function( parentNode ) { return parentNode.xml != undefined ? this._getContentAsStringIE(parentNode) : this._getContentAsStringMozilla(parentNode); }, _getContentAsStringIE: function(parentNode) { var contentStr = ""; for ( var i = 0 ; i < parentNode.childNodes.length ; i++ ) { var n = parentNode.childNodes[i]; if (n.nodeType == 4) { contentStr += n.nodeValue; } else { contentStr += n.xml; } } return contentStr; }, _getContentAsStringMozilla: function(parentNode) { var xmlSerializer = new XMLSerializer(); var contentStr = ""; for ( var i = 0 ; i < parentNode.childNodes.length ; i++ ) { var n = parentNode.childNodes[i]; if (n.nodeType == 4) { contentStr += n.nodeValue; } else { contentStr += xmlSerializer.serializeToString(n); } } return contentStr; } }; //Class representing a report var Report = Class.create(); Report.prototype = { /* * Initializes the report class * Parameters: controller - the controller class instance being used for the control, id - The uniqueID parameter used to identify the controller instance. This value is passed in with * with the request Url for creating javascript calls with the link provider. */ initialize: function(controller, id) { this.reportName = ""; this.pageCount = 0; this.hasParameters = false; this.parametersRequireUserInput = false; this.requiresParameters = false; this.reportStreamId; this.reportHtml; this.controller = controller; this.pageNumber = 0; this.drillThroughHistoryStack = new Array(); this.currentUrl = ""; this.hasDocumentMap = false; this.parameters = new ReportParameters(this); this.documentMapHtml = ""; this.id = id; this.format = "Html"; this.webReportViewerId = ""; this.reportRuntimeId = ""; this.target = ""; this.refreshDocumentMap = false; this.pageSize = ""; this.margins = ""; this.landscape = false; this.hasPageInfo = false; this.hasNewPageInfo = false; this.renderingExtensionSettings = ""; this.renderMode = "Paginated"; this.toggleUniqueId = ""; this.refreshData = false; this.hyperlinkTarget = ""; this.printingDelayPerPage = 10; this.reportLanguage = ""; }, /* * REQUIRED by Prototype AJAX for callback * Gets called when send request is called on a report */ ajaxUpdate: function(request) { DiagContext.traceVerbose('Ajax Update'); var cancel = request.responseXML.getElementsByTagName('cancel'); if (cancel.length > 0) { this.controller.toggleReportLoadingImage(false); return; } var metadata = request.responseXML.getElementsByTagName('reportmetadata'); if (metadata.length > 0) { var elm = metadata[0].childNodes[0]; this.setupReport(metadata[0]); } else { DiagContext.traceVerbose('no report meta data found'); var error = request.responseXML.getElementsByTagName('errorMessage'); if (error.length > 0) { DiagContext.traceVerbose('Error Message returned'); var message = XmlUtil.getContentAsString(error[0]); this.controller.setErrorMessage(message); } } }, /* * A function to refresh a report using original parameter values. */ refreshReport: function() { DiagContext.traceVerbose('Refresh Report'); this.currentUrl = this._buildUrl(); this.controller.loadReport(this.currentUrl); }, /* * A function to refresh a report using parameter values from parameter panel. */ refreshReportWithNewParameters: function() { DiagContext.traceVerbose('Refresh Report'); this.currentUrl = this._buildUrl(true); this.controller.loadReport(this.currentUrl); }, /* * A function to call the refresh parameters command. Used to refresh the parameters after making a change. */ refreshParameters: function() { DiagContext.traceVerbose('Refresh parameters'); this.currentUrl = this._buildUrl(true); this.controller.refreshParameters(this.currentUrl + "&rs:Command=RefreshParameters"); }, /* * Send the request to update the specific parameter only. */ refreshParameter: function(parameter) { this.currentUrl = this._buildUrl(true); this.controller.refreshParameters(this.currentUrl + "&rs:Command=RefreshParameters¶meterName=" + encodeURIComponent(parameter.name)); }, /* * Setups up the report class content with the xml information returned by the ajax call */ setupReport: function(reportNode) { var linehit = 0; try { var elem = reportNode.getElementsByTagName('reportName'); var tempName = this._getChildNodeValue(elem); if (tempName != this.reportName) { this.refreshDocumentMap = true; this.hasNewPageInfo = false; this.reportName = tempName; } linehit++; var currentTime = new Date() DiagContext.traceVerbose('Building report ' + this.reportName + ' For ' + this.id + ' ' + currentTime.getMinutes() + ':' + currentTime.getMilliseconds()); elem = reportNode.getElementsByTagName('format'); this.format = this._getChildNodeValue(elem); linehit++; elem = reportNode.getElementsByTagName('pageCount'); this.pageCount = this._getChildNodeValue(elem); if (this.pageCount < 0) this.pageCount = 0; linehit++; elem = reportNode.getElementsByTagName('renderMode'); this.renderMode = this._getChildNodeValue(elem); linehit++; elem = reportNode.getElementsByTagName('reportStream'); if (elem != null && elem.length > 0) { this.reportStreamId = elem[0].getAttribute('id'); this.reportHtml = XmlUtil.getContentAsString(elem[0]); } /* * Credentials Handling */ linehit++; this.controller.credentialManager.readMetadataCredentials(reportNode); /* * Parameters Handling */ linehit++; elem = reportNode.getElementsByTagName('requiresParameters'); this.requiresParameters = this._getChildNodeValue(elem); linehit++; elem = reportNode.getElementsByTagName('Parameters'); if (elem != null && elem.length > 0) { this.parameters.clear(); this.parameters.setParametersFromXml(elem[0], true); this.hasParameters = this.parameters.hasUserInteractiveParameters; this.parametersRequireUserInput = this.parameters.hasParametersThatNeedInput; var refreshData = elem[0].getAttribute('refreshData'); if (refreshData == 'True') { this.refreshData = true; } } linehit++; elem = reportNode.getElementsByTagName('hasDocumentMap'); if (this._getChildNodeValue(elem) == "True") { if (this.hasDocumentMap == false) this.refreshDocumentMap = true; this.hasDocumentMap = true; } else { this.refreshDocumentMap = false; this.hasDocumentMap = false; } linehit++; elem = reportNode.getElementsByTagName('pageNumber'); this.pageNumber = this._getChildNodeValue(elem); if (this.pageCount == 0) { this.pageNumber = 0; } else if (this.pageNumber < 0) { if (this.renderMode == "Galley") { if (this.pageCount > 0) { this.pageNumber = 1; } } else { this.pageNumber = 0; } } linehit++; elem = reportNode.getElementsByTagName('reportLanguage'); if (elem != null && elem.length > 0) this.reportLanguage = XmlUtil.getContentAsString(elem[0]); linehit++; elem = reportNode.getElementsByTagName('documentMapHtml'); if (elem != null && elem.length > 0) this.documentMapHtml = XmlUtil.getContentAsString(elem[0]); linehit++; elem = reportNode.getElementsByTagName('pageSize'); this.hasPageInfo = false; if (elem != null && elem.length > 0) { this.hasPageInfo = true; this.pageSize = this._getChildNodeValue(elem); } else { this.pageSize = ""; } linehit++; if (this.hasPageInfo) { elem = reportNode.getElementsByTagName('margins'); if (elem != null && elem.length > 0) { this.hasPageInfo = true; this.margins = this._getChildNodeValue(elem); } else { this.margins = ""; } } linehit++; elem = reportNode.getElementsByTagName('landscape'); if (this._getChildNodeValue(elem) == "True") { this.landscape = true } else { this.landscape = false; } elem = reportNode.getElementsByTagName('toggleUniqueId'); this.toggleUniqueId = this._getChildNodeValue(elem); linehit++; currentTime = new Date() DiagContext.traceVerbose('...Finish Building Report ' + this.reportName + ' ' + currentTime.getMinutes() + ':' + currentTime.getMilliseconds()); linehit++; this.currentUrl = this._buildUrl(); this.controller.reportLoaded(this); linehit++; } catch (e) { DiagContext.traceError("Error setting up report: linehit " + linehit, e); } }, /* * Helper member to return the first child node value for the first parent node element being passed in. * The elements are present, or the nodeValue is null an empty string will be returned */ _getChildNodeValue: function(parentNode) { if (parentNode != null && parentNode.length > 0) { if (parentNode[0].childNodes != null && parentNode[0].childNodes.length > 0) { return parentNode[0].childNodes[0].nodeValue; } return ""; } return ""; }, /* * Sends an ajax call to load a specific page. * page: The page number to navigate to. */ gotoPage: function(page, isAction) { this.refreshDocumentMap = false; this.pageNumber = page; this.currentUrl = this._buildUrl(); if (isAction) this.currentUrl += "&rs:IsAction=true"; this.controller.loadReport(this.currentUrl); }, /* * Navigates the report to the selected found text */ gotoFindResult: function(lpath, pageNumber, searchString) { this.refreshDocumentMap = false; this.pageNumber = pageNumber; DiagContext.traceVerbose('gotoFindResult ' + this.pageNumber + ' for word ' + searchString); searchString = encodeURIComponent(searchString); this.currentUrl = this._buildUrl() + "&rc:FindResultTarget=" + lpath + "&rc:FindResultWord=" + searchString + "&target=#FindTarget"; this.controller.loadReport(this.currentUrl); }, /* * Navigates the report to the specified target on the specified page. */ gotoTarget: function(target, pageNumber, isAction) { this.refreshDocumentMap = false; this.target = target; this.gotoPage(pageNumber, isAction); }, /* * Navigates back to the parent report from inside a drilled through report. */ gotoParent: function() { this.refreshDocumentMap = true; if (this.getDrillThroughHistoryCount() > 0) { var parentUrl = this.drillThroughHistoryStack.pop(); if (parentUrl != null && parentUrl.length > 0) { this.controller.loadReport(parentUrl); } } }, /* * Sends an ajax call to navigate to an URL. * page: The page number to navigate to. */ gotoUrl: function(url) { this.currentUrl = this._buildUrl(); this.controller.navigateCommand(this.currentUrl + "&rs:Command=Navigate&rc:NavigateUrl=" + url + "&rs:IsAction=true"); }, /* * Creates a url with the toggle path information and reloads the report. This is used to control visiblity toggling. *Parameter: lpath is the LPath string value that should map to a specific layout area that needs to be toggled when * the report is rendered to html. */ toggle: function(lpath) { this.refreshDocumentMap = true; this.currentUrl = this._buildUrl(); fullUrl = this.currentUrl + "&rc:ToggleLPath=" + lpath; DiagContext.traceVerbose('Toggle ' + fullUrl); this.controller.loadReport(fullUrl); }, /* * Sends an ajax call to load a specific URL * url: The url to navigate to */ navigateToReport: function(url) { this.drillThroughHistoryStack.push(this.currentUrl); this.controller.loadReport(url); }, /* * Returns the number of items in the navigation history stack. */ getDrillThroughHistoryCount: function() { return this.drillThroughHistoryStack.length; }, /* * Function replaces incorrect URL symbols by its equivalent */ fixURL: function(url) { // url replacement symbols // " # % & ' * , : ; < > ? [ ] ^ ` { | } // %22 %23 %25 %26 %27 %2a %2c %3a %3b %3c %3e %3f %5b %5d %5e %60 %7b %7c %7d %20 //debugger url = url.replace(/%/g, '%25'); url = url.replace(//g, '%3e'); url = url.replace(/\n/g, ''); return url; }, /* * Builds a url based off of the current setting of the report class. * used internall to construct urls for the ajax calls. */ _buildUrl: function(useNewParameterValues) { var url = this.reportName if (this.pageNumber > 0) { url += "&rc:section=" + this.pageNumber } url += "&rc:UniqueId=" + this.id; if (this.reportRuntimeId.length > 0) { url += "&rc:ReportRuntimeId=" + this.reportRuntimeId; } var urlCombined = ""; if (useNewParameterValues == undefined || useNewParameterValues == false) this.parameters.revertChanges(); for (var parameterIndex = 0; parameterIndex < this.parameters.length; parameterIndex++) { parameter = this.parameters.getParameter(parameterIndex); var encodedParameterName = encodeURIComponent(parameter.name); if (parameter.multiValue && (parameter.values != null && parameter.values.length > 0)) { var values = ""; var seperator = ""; for (var valueIndex = 0; valueIndex < parameter.values.length; valueIndex++) { value = "&" + encodedParameterName + "=" + encodeURIComponent(parameter.values[valueIndex].value); urlCombined += value; } } else if (parameter.value == null) { value = "&" + encodedParameterName + "=ddNullValue"; urlCombined += value; } else { value = "&" + encodedParameterName + "=" + encodeURIComponent(parameter.value); urlCombined += value; } } urlCombined = this.fixURL(urlCombined); url += urlCombined; if (this.refreshData || this.parameters.refreshData) { url += "&rc:RefreshData=true"; } url += "&rc:RenderMode=" + this.renderMode; url += "&rs:Format=" + this.format; if (this.hasPageInfo) { url += "&rs:pageSize=" + this.pageSize; url += "&rs:margins=" + this.margins; } if (this.renderingExtensionSettings.length > 0) url += "&rs:reSettings=" + this.renderingExtensionSettings; if (this.landscape) { url += "&rc:Landscape=true"; } else { url += "&rc:Landscape=false"; } url += "&rs:WebReportViewerId=" + this.webReportViewerId; url += "&rs:HyperlinkTarget=" + this.hyperlinkTarget; url += "&rs:PrintingDelayPerPage=" + this.printingDelayPerPage; if (this.toggleUniqueId.length > 0) { url += "&rc:ToggleUniqueId=" + this.toggleUniqueId; } DiagContext.traceVerbose('Url build: ' + url); return url; }, /* *Sends the print command to print the current report. */ printReport: function() { DiagContext.traceVerbose('Report: printReport'); this.controller.printReport(this._buildUrl() + "&rs:Command=Print&rc:PrintOnOpen=true"); }, /* *Sends the cancel command to cancel the current report. */ cancelReport: function() { DiagContext.traceVerbose('Report: cancelReport'); this.controller.cancelReport(this._buildUrl() + "&rs:Command=CancelReport"); }, /* *Sends the find command to perform a search for the passed in stream *Parameter: searchString - the text to search for in the report. *Parameter: matchWholeWord - boolean indicating to match whole word when performing search *Parameter: matchCase - boolean indicating to match case when performing search *Parameter: advancedOption - the selected advanced option to use when performing a search */ findText: function(searchString, matchWholeWord, matchCase, advancedOption) { DiagContext.traceVerbose('findText ' + searchString + ' Match Whole Word ' + matchWholeWord + ' Match Case ' + matchCase + ' Advanced Option ' + advancedOption); searchString = encodeURIComponent(searchString); var matchExact = (advancedOption == 'MatchExact') ? true : false DiagContext.traceVerbose("matchExact? " + matchExact); this.controller.searchReport(this._buildUrl() + "&rs:Command=Find&rc:FindString=" + searchString + "&rc:MatchWholeWord=" + matchWholeWord + "&rc:MatchCase=" + matchCase + "&rc:MatchExact=" + matchExact); }, /* * Sends the email command to email the current report. * Parameters: from - the email address to send the email from, to - the email address to send the email to * cc - the email address to carbon-copy the email to, subject - the text string to use as the email subject * message - the text string to use as the message of the email. */ emailReport: function(from, to, cc, subject, message) { DiagContext.traceVerbose('Sending email ' + from + ' ' + to + ' ' + ' ' + cc + ' ' + subject + ' ' + message); this.currentUrl = this._buildUrl(); this.controller.refreshParameters(this.currentUrl + "&rs:Command=Email&rs:To=" + to + "&rs:From=" + from + "&rs:Cc=" + cc + "&rs:subject=" + subject + "&rs:Message=" + message); }, /* * Sends the command to export a report to the given format. * Parameters: format - the format to export the report to. */ exportReport: function(format) { var currentFormat = this.format; if (format == 'Mhtml') { this.format = 'Html'; //Mhtml still uses the html format. } else { this.format = format; } var url = this._buildUrl(); this.format = currentFormat; if (format == 'Mhtml') { url += "&rc:MhtOutput=True"; //Set the RE setting to use Mhtml output. } var currentDate = new Date(); url += "&rs:Command=Export&requestTime=" + currentDate.getTime(); DiagContext.traceVerbose('Report: Export Report ' + url); this.controller.exportReport(url); }, /* * Changes the page size and margin information for the report. Once these values have been changed for the first * time the pageSize and margin information will become part of the url. */ applyPageSetupChanges: function(pageWidth, pageHeight, marginTop, marginBottom, marginLeft, marginRight, landscape) { this.pageSize = 'width=' + pageWidth + ';height=' + pageHeight; this.margins = 'top=' + marginTop + ';bottom=' + marginBottom + ';left=' + marginLeft + ';right=' + marginRight; this.landscape = landscape; this.hasNewPageInfo = true; this.refreshReport(); }, /* * Toggles the render mode between Paginated and Gally modes. */ toggleRenderMode: function() { if (this.renderMode == "Paginated") { this.renderMode = "Galley"; } else { this.renderMode = "Paginated"; } this.refreshDocumentMap = true; this.hasNewPageInfo = true; this.refreshReport(); }, /* *Changes the viewer mode to match what is selected on the viewer mode select control on the main toolbar. */ changeViewerMode: function(format) { DiagContext.traceVerbose("report changing viewer mode to " + format); if (this.format != format) { this.format = format; this.refreshDocumentMap = true; this.hasNewPageInfo = true; this.refreshReport(); } } }; /* * Class used to handle the ajax call for the search functionality. */ var FindController = Class.create(); FindController.prototype = { initialize: function(controller){ this.controller = controller; }, /* * REQUIRED by Prototype AJAX for callback * Gets called when send request is called on a report */ ajaxUpdate: function(request){ DiagContext.traceVerbose('Find Controller Ajax Update'); var elem = request.responseXML.getElementsByTagName('findResultsHtml'); if(elem.length>0){ var html = XmlUtil.getContentAsString(elem[0]); this.controller.updateSearchResults(html); } } };