1 /** 2 * @fileOverview 3 * @author <a href="https://www.labkey.org">LabKey</a> (<a href="mailto:info@labkey.com">info@labkey.com</a>) 4 * @license Copyright (c) 2014-2019 LabKey Corporation 5 * <p/> 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * <p/> 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * <p/> 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * <p/> 18 */ 19 (function($) { 20 21 /** 22 * @description WebPart class to render a web part into an existing page element. If you wish to render a Query web part, please 23 * use the {@link LABKEY.QueryWebPart} class instead. 24 * @class Web Part class to render a web part into an existing page element. If you wish to render a Query web part, please 25 * use the {@link LABKEY.QueryWebPart} class instead. 26 * <p>Additional Documentation: 27 * <ul> 28 * <li><a href= "https://www.labkey.org/Documentation/wiki-page.view?name=webPartConfig"> 29 Web Part Configuration Properties</a></li> 30 * <li><a href= "https://www.labkey.org/Documentation/wiki-page.view?name=webPartInventoryWikiSimple"> 31 List of LabKey Web Parts</a></li> 32 * <li><a href="https://www.labkey.org/Documentation/wiki-page.view?name=javascriptTutorial">LabKey JavaScript API Tutorial</a> and 33 * <a href="https://www.labkey.org/home/Study/demo/wiki-page.view?name=reagentRequest">Demo</a></li> 34 * </ul> 35 * </p> 36 * 37 * @constructor 38 * @param {Object} config Describes configuration properties for this class. 39 * @param {String} config.partName Name of the web part ("Wiki", "Lists", etc.), as listed in the 40 "Add Web Part" drop-down menu on the portal page of the container. 41 * @param {String} config.renderTo ID of the element in which the web part should be rendered. 42 Typically this is a div. 43 * @param {String} [config.frame] The type of frame to wrap around the web part's content. This can 44 be any one of the following: 45 <ul> 46 <li><b>portal</b>: (Default) Includes the standard portal frame around the web part content 47 <li><b>title</b>: Includes a lighter frame around the web part content (title with line underneath) 48 <li><b>left-nav</b>: Similar to the title frame, but enforces a thinner width. 49 <li><b>div</b>: Includes the content in a simple <div> tag. Use the config.bodyClass parameter to set a CSS class for the div. 50 <li><b>dialog</b>: Includes the content in a frame that looks similar to a dialog box. 51 <li><b>none</b>: Includes no frame around the web part content 52 </ul> 53 * @param {String} [config.bodyClass] The name of a CSS class available in the current page. This class name will be applied to the tag that 54 contains the web part's body content. 55 * @param {String} [config.title] Overrides the web part's default title. 56 * Note that titles are not displayed when config.frame is set to "none". 57 * @param {String} [config.titleHref] Overrides the hyperlink href around the web part's title. 58 * Note that titles are not displayed when config.frame is set to "none". 59 * @param {Object} [config.partConfig] Object containing name/value pairs that will be sent to the server as configuration 60 * parameters for the web part. Each web part defines its own set of config parameters. See the 61 * <a href= https://www.labkey.org/Documentation/wiki-page.view?name=webPartConfig> 62 Web Part Configuration Properties</a> page for further information on these name/value pairs. 63 * @param {boolean} [config.suppressRenderErrors] If true, no alert will appear if there is a problem rendering the QueryWebpart. This is most often encountered if page configuration changes between the time when a request was made and the content loads. Defaults to false. 64 * @param {Function} [config.success] Callback function that will be executed after the web part content as been inserted into the page. 65 * @param {Function} [config.failure] Callback function that will be executed if an error occurs. This function 66 * should have two parameters: response and partConfig. The response parameter is the XMLHttpResponse 67 * object, which can be used to determine the error code and obtain the error text if desired. 68 * The partConfig parameter will contain all the parameters sent to the server. 69 * @param {String} [config.containerPath] The container path in which this web part is defined. If not supplied, 70 * the current container path will be used. 71 * @param {Object} [config.scope] A scope object to use when calling the successCallback or errorCallback functions (defaults to this). 72 * @example Example for a Wiki web part:<pre name="code" class="xml"> 73 <div id='wikiTestDiv'/> 74 <script type="text/javascript"> 75 var wikiWebPartRenderer = new LABKEY.WebPart({ 76 partName: 'Wiki', 77 renderTo: 'wikiTestDiv', 78 partConfig: {name: 'home'} 79 }) 80 wikiWebPartRenderer.render(); 81 </script> </pre></code> 82 * @example Example for a Report web part, from the Reagent Request <a href="https://www.labkey.org/Documentation/wiki-page.view?name=reagentRequestConfirmation">Tutorial</a> and <a href="https://www.labkey.org/home/Study/demo/wiki-page.view?name=Confirmation">Demo</a>: <pre name="code" class="xml"> 83 <div id='reportDiv'>Loading...</div> 84 <script type="text/javascript"> 85 // This snippet draws a histogram of the current user's requests. 86 // A partConfig parameter identifies the R report ('db:151') 87 // used to draw the histogram. partConfig also 88 // supplies a filter ('query.UerID~eq') to ensure that 89 // R uses data for only the current user. Lastly, partConfig 90 // provides R with an arbitrary URL parameter ('displayName') 91 // to indicate the displayName of the user. 92 93 var reportWebPartRenderer = new LABKEY.WebPart({ 94 partName: 'Report', 95 renderTo: 'reportDiv', 96 containerPath: '/home/Study/demo/guestaccess', 97 frame: 'title', 98 partConfig: { 99 title: 'Reagent Request Histogram', 100 reportId: 'db:151', 101 showSection: 'histogram', 102 'query.UserID~eq' : LABKEY.Security.currentUser.id, 103 displayName: LABKEY.Security.currentUser.displayName 104 }}); 105 reportWebPartRenderer.render(); 106 </script> </pre></code> 107 */ 108 LABKEY.WebPart = function(config) 109 { 110 //private data 111 var _renderTo = config.renderTo; 112 var _partName = config.partName; 113 var _frame = config.frame; 114 var _bodyClass = config.bodyClass; 115 var _title = config.title; 116 var _titleHref = config.titleHref; 117 var _partConfig = config.partConfig; 118 var _errorCallback = LABKEY.Utils.getOnFailure(config); 119 var _success = LABKEY.Utils.getOnSuccess(config); 120 var _containerPath = config.containerPath; 121 var _scope = config.scope || this; 122 var _suppressRenderErrors = config.supressRenderErrors; 123 var _partUrl = config.partUrl || LABKEY.ActionURL.buildURL('project', 'getWebPart', _containerPath); 124 125 //validate config 126 if (!_partName) 127 { 128 LABKEY.Utils.alert("Configuration Error", "You must supply the name of the desired web part in the partName config property."); 129 return; 130 } 131 if (!_renderTo) 132 { 133 LABKEY.Utils.alert("Configuration Error", "You must supply the name of the target element in the renderTo config property."); 134 return; 135 } 136 137 // private methods: 138 var handleLoadError = function(response) 139 { 140 var msg = "Error getting the web part: "; 141 if (response.status == 0) 142 { 143 return; 144 } 145 if(response.status >= 500 && response.status < 600) 146 { 147 var json = LABKEY.Utils.decode(response.responseText); 148 if(json) 149 msg += json.exception; 150 } 151 else 152 msg += response.statusText; 153 154 LABKEY.Utils.alert("Error", msg); 155 }; 156 157 var renderPart = function(response, partConfig) 158 { 159 // beforeRender callback to allow for editing of the response 160 // if 'false' is returned then rendering will be stopped. 161 if (partConfig.params.beforeRender) 162 { 163 var r = partConfig.params.beforeRender.call(_scope, response); 164 if (r === false) 165 return; 166 else if (r) 167 response = r; 168 } 169 170 // render the part inside the target element 171 if (_renderTo) 172 { 173 var targetElem = $('#' + _renderTo); 174 if (targetElem.length > 0) 175 { 176 LABKEY.Utils.loadAjaxContent(response, targetElem, _success, _scope); 177 } 178 else 179 { 180 if (!_suppressRenderErrors) 181 LABKEY.Utils.alert("Rendering Error", "The element '" + _renderTo + "' does not exist in the document!"); 182 } 183 } 184 else 185 { 186 if (!_suppressRenderErrors) 187 LABKEY.Utils.alert("Rendering Error", "The target element name was not set!"); 188 } 189 }; 190 191 // public methods: 192 /** @scope LABKEY.WebPart.prototype */ 193 return { 194 /** 195 * Renders the WebPart to the div element specified in the configuration settings. 196 * @returns A transaction id for the async request that can be used to cancel the request 197 * (see <a href="http://dev.sencha.com/deploy/dev/docs/?class=Ext.Ajax" target="_blank">Ext.Ajax.abort()</a>). 198 */ 199 render : function() 200 { 201 if (!_partConfig) 202 _partConfig = {}; 203 204 _partConfig["webpart.name"] = _partName; 205 if (_frame) 206 _partConfig["webpart.frame"] = _frame; 207 if (_bodyClass) 208 _partConfig["webpart.bodyClass"] = _bodyClass; 209 if (_title) 210 _partConfig["webpart.title"] = _title; 211 if (_titleHref) 212 _partConfig["webpart.titleHref"] = _titleHref; 213 // Prefer using 'returnUrl' instead of 'returnURL' 214 if (_partConfig.returnURL) { 215 if (LABKEY.experimental.strictReturnUrl) 216 throw new Error("Use 'returnUrl' instead of 'returnURL'"); 217 _partConfig.returnUrl = _partConfig.returnURL; 218 } 219 220 if (!_errorCallback) 221 _errorCallback = handleLoadError; 222 223 // forward query string parameters (for Query web parts) 224 var config = $.extend(true, {}, LABKEY.ActionURL.getParameters(), _partConfig); 225 226 // Ext uses a param called _dc to defeat caching, and it may be 227 // on the URL if the Query web part has done a sort or filter 228 // strip it if it's there so it's not included twice (Ext always appends one) 229 delete config["_dc"]; 230 231 return LABKEY.Ajax.request({ 232 url: _partUrl, 233 success: renderPart, 234 failure: _errorCallback, 235 method: 'GET', 236 params: config 237 }); 238 } 239 }; 240 }; 241 242 /** 243 * This is a static method to generate a report webpart. It is equivalent to LABKEY.WebPart with partName='Report'; however, 244 * it simplifies the configuration 245 * @param config The config object 246 * @param {String} config.renderTo The Id of the element in which the web part should be rendered. 247 * @param {String} [config.reportId] The Id of the report to load. This can be used in place of schemaName/queryName/reportName 248 * @param {String} [config.schemaName] The name of the schema where the report is associated. 249 * @param {String} [config.queryName] The name of the query where the report is attached. 250 * @param {String} [config.reportName] The name of the report to be loaded. 251 * @param {String} [config.title] The title that will appear above the report webpart 252 * @param {Object} [config.webPartConfig] A optional config object used to create the LABKEY.WebPart. Any config options supported by WebPart can be used here. 253 * @param {Object} [config.reportProperties] An optional config object with additional report-specific properties. This is equal to partConfig from LABKEY.Webpart 254 * @return A LABKEY.WebPart instance 255 * @example 256 <div id='testDiv'/> 257 <div id='testDiv2'/> 258 <script type="text/javascript"> 259 //a report can be loaded using its name, schema and query 260 var reportWebpart = LABKEY.WebPart.createReportWebpart({ 261 schemaName: 'laboratory', 262 queryName: 'DNA_Oligos', 263 reportName: 'My Report', 264 renderTo: 'testDiv', 265 webPartConfig: { 266 title: 'Example Report', 267 suppressRenderErrors: true 268 }, 269 reportProperties: { 270 'query.name~eq': 'Primer2' 271 } 272 }); 273 reportWebpart.render(); 274 275 //the report can also be loaded using its Id 276 var reportWebpartUsingId = LABKEY.WebPart.createReportWebpart({ 277 reportId: 'module:laboratory/schemas/laboratory/DNA_Oligos/Query.report.xml', 278 renderTo: 'testDiv2', 279 webPartConfig: { 280 title: 'Example Report', 281 suppressRenderErrors: true 282 }, 283 reportProperties: { 284 'query.name~eq': 'Primer2' 285 } 286 }).render(); 287 </script> </pre></code> 288 */ 289 LABKEY.WebPart.createReportWebpart = function(config) 290 { 291 var wpConfig = $.extend({}, config.webPartConfig); 292 wpConfig.partName = 'Report'; 293 294 // for convenience, support these wp properties in config 295 $.each(['renderTo', 'success', 'failure'], function(index, prop) 296 { 297 if (LABKEY.Utils.isDefined(config[prop])) 298 { 299 wpConfig[prop] = config[prop]; 300 } 301 }); 302 303 // then merge the partConfig options. we document specific Report-specific options for clarity to the user 304 wpConfig.partConfig = $.extend({}, config.reportProperties); 305 $.each(['reportId', 'reportName', 'schemaName', 'queryName', 'title'], function(index, prop) 306 { 307 if (LABKEY.Utils.isDefined(config[prop])) 308 { 309 wpConfig.partConfig[prop] = config[prop]; 310 } 311 }); 312 313 return new LABKEY.WebPart(wpConfig); 314 }; 315 316 })(jQuery); 317 318