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) 2008-2016 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 if (_partConfig.returnUrl) { 214 _partConfig.returnUrl = encodeURI(_partConfig.returnUrl); 215 } 216 else if (_partConfig.returnURL) { 217 if (LABKEY.experimental.strictReturnUrl) 218 throw new Error("Use 'returnUrl' instead of 'returnURL'"); 219 _partConfig.returnUrl = encodeURI(_partConfig.returnURL); 220 } 221 222 if (!_errorCallback) 223 _errorCallback = handleLoadError; 224 225 // forward query string parameters (for Query web parts) 226 var config = $.extend(true, {}, LABKEY.ActionURL.getParameters(), _partConfig); 227 228 // Ext uses a param called _dc to defeat caching, and it may be 229 // on the URL if the Query web part has done a sort or filter 230 // strip it if it's there so it's not included twice (Ext always appends one) 231 delete config["_dc"]; 232 233 return LABKEY.Ajax.request({ 234 url: _partUrl, 235 success: renderPart, 236 failure: _errorCallback, 237 method: 'GET', 238 params: config 239 }); 240 } 241 }; 242 }; 243 244 /** 245 * This is a static method to generate a report webpart. It is equivalent to LABKEY.WebPart with partName='Report'; however, 246 * it simplifies the configuration 247 * @param config The config object 248 * @param {String} config.renderTo The Id of the element in which the web part should be rendered. 249 * @param {String} [config.reportId] The Id of the report to load. This can be used in place of schemaName/queryName/reportName 250 * @param {String} [config.schemaName] The name of the schema where the report is associated. 251 * @param {String} [config.queryName] The name of the query where the report is attached. 252 * @param {String} [config.reportName] The name of the report to be loaded. 253 * @param {String} [config.title] The title that will appear above the report webpart 254 * @param {Object} [config.webPartConfig] A optional config object used to create the LABKEY.WebPart. Any config options supported by WebPart can be used here. 255 * @param {Object} [config.reportProperties] An optional config object with additional report-specific properties. This is equal to partConfig from LABKEY.Webpart 256 * @return A LABKEY.WebPart instance 257 * @example 258 <div id='testDiv'/> 259 <div id='testDiv2'/> 260 <script type="text/javascript"> 261 //a report can be loaded using its name, schema and query 262 var reportWebpart = LABKEY.WebPart.createReportWebpart({ 263 schemaName: 'laboratory', 264 queryName: 'DNA_Oligos', 265 reportName: 'My Report', 266 renderTo: 'testDiv', 267 webPartConfig: { 268 title: 'Example Report', 269 suppressRenderErrors: true 270 }, 271 reportProperties: { 272 'query.name~eq': 'Primer2' 273 } 274 }); 275 reportWebpart.render(); 276 277 //the report can also be loaded using its Id 278 var reportWebpartUsingId = LABKEY.WebPart.createReportWebpart({ 279 reportId: 'module:laboratory/schemas/laboratory/DNA_Oligos/Query.report.xml', 280 renderTo: 'testDiv2', 281 webPartConfig: { 282 title: 'Example Report', 283 suppressRenderErrors: true 284 }, 285 reportProperties: { 286 'query.name~eq': 'Primer2' 287 } 288 }).render(); 289 </script> </pre></code> 290 */ 291 LABKEY.WebPart.createReportWebpart = function(config) 292 { 293 var wpConfig = $.extend({}, config.webPartConfig); 294 wpConfig.partName = 'Report'; 295 296 // for convenience, support these wp properties in config 297 $.each(['renderTo', 'success', 'failure'], function(index, prop) 298 { 299 if (LABKEY.Utils.isDefined(config[prop])) 300 { 301 wpConfig[prop] = config[prop]; 302 } 303 }); 304 305 // then merge the partConfig options. we document specific Report-specific options for clarity to the user 306 wpConfig.partConfig = $.extend({}, config.reportProperties); 307 $.each(['reportId', 'reportName', 'schemaName', 'queryName', 'title'], function(index, prop) 308 { 309 if (LABKEY.Utils.isDefined(config[prop])) 310 { 311 wpConfig.partConfig[prop] = config[prop]; 312 } 313 }); 314 315 return new LABKEY.WebPart(wpConfig); 316 }; 317 318 })(jQuery); 319 320