1 /* 2 * ***** BEGIN LICENSE BLOCK ***** 3 * Zimbra Collaboration Suite Web Client 4 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016 Synacor, Inc. 5 * 6 * The contents of this file are subject to the Common Public Attribution License Version 1.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: https://www.zimbra.com/license 9 * The License is based on the Mozilla Public License Version 1.1 but Sections 14 and 15 10 * have been added to cover use of software over a computer network and provide for limited attribution 11 * for the Original Developer. In addition, Exhibit A has been modified to be consistent with Exhibit B. 12 * 13 * Software distributed under the License is distributed on an "AS IS" basis, 14 * WITHOUT WARRANTY OF ANY KIND, either express or implied. 15 * See the License for the specific language governing rights and limitations under the License. 16 * The Original Code is Zimbra Open Source Web Client. 17 * The Initial Developer of the Original Code is Zimbra, Inc. All rights to the Original Code were 18 * transferred by Zimbra, Inc. to Synacor, Inc. on September 14, 2015. 19 * 20 * All portions of the code are Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2016 Synacor, Inc. All Rights Reserved. 21 * ***** END LICENSE BLOCK ***** 22 */ 23 24 /** 25 * @overview 26 * This file contains the Zimlet manager class. 27 */ 28 29 /** 30 * Creates the Zimlet manager. 31 * @class 32 * This class represents the Zimlet manager. 33 * 34 */ 35 ZmZimletMgr = function() { 36 this._ZIMLETS = []; 37 this._ZIMLETS_BY_ID = {}; 38 this._CONTENT_ZIMLETS = []; 39 this._serviceZimlets = []; 40 this._requestNotHandledByAnyZimlet = []; 41 this.loaded = false; 42 }; 43 44 ZmZimletMgr.prototype.constructor = ZmZimletMgr; 45 46 /** 47 * Returns a string representation of the object. 48 * 49 * @return {String} a string representation of the object 50 */ 51 ZmZimletMgr.prototype.toString = 52 function() { 53 return "ZmZimletMgr"; 54 }; 55 56 // 57 // Constants 58 // 59 60 ZmZimletMgr._RE_REMOTE = /^((https?|ftps?):\x2f\x2f|\x2f)/; 61 62 /** 63 * List of Core Zimlets. 64 * com_zimbra_apptsummary|com_zimbra_date|com_zimbra_dnd|com_zimbra_email|com_zimbra_linkedin|com_zimbra_phone|com_zimbra_webex|com_zimbra_social|com_zimbra_srchhighlighter|com_zimbra_url 65 */ 66 ZmZimletMgr.CORE_ZIMLETS = /com_zimbra_apptsummary|com_zimbra_date|com_zimbra_dnd|com_zimbra_email|com_zimbra_linkedin|com_zimbra_phone|com_zimbra_webex|com_zimbra_social|com_zimbra_srchhighlighter|com_zimbra_url/; 67 68 /** 69 * If the Zimlet's config_template has hasSensitiveData = true, it will be considered as sensitive Zimlet 70 * and such zimlets are disabled (by-default) in mixed-mode. 71 * System admin can set: mcf zimbraZimletDataSensitiveInMixedModeDisabled FALSE (instead of TRUE), to enable 72 */ 73 ZmZimletMgr.HAS_SENSITIVE_DATA_CONFIG_NAME = "hasSensitiveData"; 74 75 // 76 // Public methods 77 // 78 79 /** 80 * Checks if the manager is loaded. 81 * 82 * @return {Boolean} <code>true</code> if loaded; <code>false</code> otherwise 83 */ 84 ZmZimletMgr.prototype.isLoaded = 85 function() { 86 return this.loaded; 87 }; 88 89 /** 90 * Loads the zimlets. 91 * 92 * @param {Array} zimletArray an array of {@link ZmZimlet} objects 93 * @param {Array} userProps an array of properties 94 * @param {String} target the target 95 * @param {AjxCallback} callback the callback 96 * @param {Boolean} sync <code>true</code> for synchronous 97 * 98 * @private 99 */ 100 ZmZimletMgr.prototype.loadZimlets = 101 function(zimletArray, userProps, target, callback, sync) { 102 var href = window.location.href.toLowerCase(); 103 if(href.indexOf("zimlets=none") > 0 || appCtxt.isWebClientOffline()) { 104 return; 105 } else if(href.indexOf("zimlets=core") > 0) { 106 zimletArray = this._getCoreZimlets(zimletArray); 107 } 108 var isHttp = document.location.protocol == ZmSetting.PROTO_HTTP; 109 var isMixedMode = appCtxt.get(ZmSetting.PROTOCOL_MODE) == ZmSetting.PROTO_MIXED; 110 var showAllZimlets = href.indexOf("zimlets=all") > 0; 111 if(isMixedMode && !appCtxt.isOffline && !showAllZimlets && isHttp 112 && appCtxt.get(ZmSetting.DISABLE_SENSITIVE_ZIMLETS_IN_MIXED_MODE) == "TRUE") { 113 zimletArray = this._getNonSensitiveZimlets(zimletArray); 114 } 115 var packageCallback = callback ? new AjxCallback(this, this._loadZimlets, [zimletArray, userProps, target, callback, sync]) : null; 116 AjxPackage.require({ name: "Zimlet", callback: packageCallback }); 117 if (!callback) { 118 this._loadZimlets(zimletArray, userProps, target, callback, sync); 119 } 120 }; 121 122 123 /** 124 * Returns non-sensitive Zimlets whose config_template.xml file does not contain "hasSensitiveData=true" 125 * @param {Array} zimletArray an array of {@link ZmZimlet} objects 126 * 127 * @private 128 */ 129 ZmZimletMgr.prototype._getNonSensitiveZimlets = 130 function(zimletArray) { 131 if (!zimletArray || !zimletArray.length) { 132 return; 133 } 134 var nonSensitiveZimlets = []; 135 var len = zimletArray.length; 136 for(var i = 0; i < len; i++) { 137 var configProps = []; 138 var zimletObj = zimletArray[i]; 139 var isSensitiveZimlet = false; 140 var zimletName = zimletObj.zimlet && zimletObj.zimlet[0] ? zimletObj.zimlet[0].name : ""; 141 var zimletConfig = zimletObj.zimletConfig; 142 143 if(zimletConfig) { 144 if(zimletConfig[0] 145 && zimletConfig[0].global 146 && zimletConfig[0].global[0] 147 && zimletConfig[0].global[0].property) { 148 149 configProps = zimletConfig[0].global[0].property; 150 for(var j = 0; j < configProps.length; j++) { 151 var property = configProps[j]; 152 if(property.name == ZmZimletMgr.HAS_SENSITIVE_DATA_CONFIG_NAME && property._content == "true") { 153 isSensitiveZimlet = true; 154 break; 155 } 156 } 157 } 158 } 159 if(!isSensitiveZimlet) { 160 nonSensitiveZimlets.push(zimletObj); 161 } 162 } 163 return nonSensitiveZimlets; 164 }; 165 166 /** 167 * Returng an array with only core-Zimlets. This is used when we want to debug with only core-zimlets (?zimlets=core) 168 * @param {Array} zimletArray an array of {@link ZmZimlet} objects 169 * 170 * @private 171 */ 172 ZmZimletMgr.prototype._getCoreZimlets = 173 function(zimletArray) { 174 if (!zimletArray || !zimletArray.length) { 175 return; 176 } 177 var coreZimlets = []; 178 var len = zimletArray.length; 179 for(var i = 0; i < len; i++) { 180 var zimletObj = zimletArray[i].zimlet; 181 var zimletName = zimletObj && zimletObj[0] ? zimletObj[0].name : ""; 182 if(ZmZimletMgr.CORE_ZIMLETS.test(zimletName)) { 183 coreZimlets.push(zimletArray[i]); 184 } 185 } 186 return coreZimlets; 187 }; 188 189 /** 190 * @private 191 */ 192 ZmZimletMgr.prototype._loadZimlets = 193 function(zimletArray, userProps, target, callback, sync) { 194 var z; 195 var loadZimletArray = []; 196 var targetRe = new RegExp("\\b"+(target || "main")+"\\b"); 197 for (var i=0; i < zimletArray.length; i++) { 198 var zimletObj = zimletArray[i]; 199 var zimlet0 = zimletObj.zimlet[0]; 200 // NOTE: Only instantiate zimlet context for specified target 201 if (!targetRe.test(zimlet0.target || "main")) { continue; } 202 z = new ZmZimletContext(i, zimletObj); 203 this._ZIMLETS_BY_ID[z.name] = z; 204 this._ZIMLETS.push(z); 205 loadZimletArray.push(zimletObj); 206 } 207 if (userProps) { 208 for (i = 0; i < userProps.length; ++i) { 209 var p = userProps[i]; 210 z = this._ZIMLETS_BY_ID[p.zimlet]; 211 if (z) { 212 z.setPropValue(p.name, p._content); 213 } 214 } 215 } 216 if (!appCtxt.isChildWindow) { 217 var panelZimlets = this.getPanelZimlets(); 218 if (panelZimlets && panelZimlets.length > 0) { 219 var zimletTree = appCtxt.getZimletTree(); 220 if (!zimletTree) { 221 zimletTree = new ZmFolderTree(ZmOrganizer.ZIMLET); 222 var account = appCtxt.multiAccounts && appCtxt.accountList.mainAccount; 223 appCtxt.setTree(ZmOrganizer.ZIMLET, zimletTree, account); 224 } 225 zimletTree.reset(); 226 zimletTree.loadFromJs(panelZimlets, "zimlet"); 227 } else { // reset overview tree accordingly 228 this._resetOverviewTree(); 229 } 230 } 231 232 // load zimlet code/CSS 233 var zimletNames = this._getZimletNames(loadZimletArray); 234 this._loadIncludes(loadZimletArray, zimletNames, (sync ? callback : null) ); 235 this._loadStyles(loadZimletArray, zimletNames); 236 237 if (callback && !sync) { 238 callback.run(); 239 } 240 }; 241 242 /** 243 * @private 244 */ 245 ZmZimletMgr.prototype._resetOverviewTree = 246 function() { 247 var zimletTree = appCtxt.getZimletTree(); 248 if (zimletTree) { 249 var panelZimlets = this.getPanelZimlets(); 250 zimletTree.loadFromJs(panelZimlets, "zimlet"); 251 var overview = appCtxt.getCurrentApp().getOverview(); 252 if (overview) { 253 var treeView = overview.getTreeView(ZmOrganizer.ZIMLET); 254 if (treeView && (!panelZimlets || !panelZimlets.length)) { 255 treeView.clear(); //Clear the tree if thr are no panel zimlets 256 } 257 } 258 } 259 }; 260 261 /** 262 * Gets the panel zimlets. 263 * 264 * @return {Array} an array of objects 265 */ 266 ZmZimletMgr.prototype.getPanelZimlets = 267 function() { 268 var panelZimlets = []; 269 for (var i = 0; i < this._ZIMLETS.length; i++) { 270 if (this._ZIMLETS[i].zimletPanelItem) { 271 DBG.println(AjxDebug.DBG2, "Zimlets - add to panel " + this._ZIMLETS[i].name); 272 panelZimlets.push(this._ZIMLETS[i]); 273 } 274 } 275 return panelZimlets; 276 }; 277 278 /** 279 * Gets the indexed zimlets. 280 * 281 * @return {Array} an array of objects 282 */ 283 ZmZimletMgr.prototype.getIndexedZimlets = 284 function() { 285 var indexedZimlets = []; 286 for (var i=0; i < this._ZIMLETS.length; i++) { 287 if (this._ZIMLETS[i].keyword) { 288 DBG.println(AjxDebug.DBG2, "Zimlets - add to indexed " + this._ZIMLETS[i].name); 289 indexedZimlets.push(this._ZIMLETS[i]); 290 } 291 } 292 return indexedZimlets; 293 }; 294 295 /** 296 * Gets the portlet zimlets. 297 * 298 * @return {Array} an array of objects 299 */ 300 ZmZimletMgr.prototype.getPortletZimlets = 301 function() { 302 if (!this._portletArray) { 303 this._portletArray = []; 304 this._portletMap = {}; 305 for (var i = 0; i < this._ZIMLETS.length; i++) { 306 var zimlet = this._ZIMLETS[i]; 307 if (zimlet.portlet) { 308 this._portletArray.push(zimlet); 309 this._portletMap[zimlet.name] = zimlet; 310 } 311 } 312 } 313 return this._portletArray; 314 }; 315 316 /** 317 * Gets the portlets hash. 318 * 319 * @return {Hash} the portlets hash 320 */ 321 ZmZimletMgr.prototype.getPortletZimletsHash = 322 function() { 323 this.getPortletZimlets(); 324 return this._portletMap; 325 }; 326 327 /** 328 * Registers the content zimlet. 329 * 330 * @param {ZmZimlet} zimletObj the zimlet 331 * @param {constant} type the type 332 * @param {constant} priority the priority 333 * 334 * @private 335 */ 336 ZmZimletMgr.prototype.registerContentZimlet = 337 function(zimletObj, type, priority) { 338 var i = this._CONTENT_ZIMLETS.length; 339 this._CONTENT_ZIMLETS[i] = zimletObj; 340 this._CONTENT_ZIMLETS[i].type = type; 341 this._CONTENT_ZIMLETS[i].prio = priority; 342 DBG.println(AjxDebug.DBG2, "Zimlets - registerContentZimlet(): " + this._CONTENT_ZIMLETS[i]._zimletContext.name); 343 }; 344 345 /** 346 * Gets the content zimlets. 347 * 348 * @return {Array} an array of objects 349 */ 350 ZmZimletMgr.prototype.getContentZimlets = 351 function() { 352 return this._CONTENT_ZIMLETS; 353 }; 354 355 /** 356 * Gets the zimlets. 357 * 358 * @return {Array} an array of {@link ZmZimletContext} objects 359 */ 360 ZmZimletMgr.prototype.getZimlets = 361 function() { 362 return this._ZIMLETS; 363 }; 364 365 /** 366 * Gets the zimlets hash. 367 * 368 * @return {Hash} as hash of zimlets 369 */ 370 ZmZimletMgr.prototype.getZimletsHash = 371 function() { 372 return this._ZIMLETS_BY_ID; 373 }; 374 375 /** 376 * Checks if the zimlet exists. 377 * 378 * @param {String} name the name 379 * @return {ZmZimletContext} the zimlet or <code>null</code> if not found 380 */ 381 ZmZimletMgr.prototype.zimletExists = 382 function(name) { 383 return this._ZIMLETS_BY_ID[name]; 384 }; 385 386 /** 387 * Gets the zimlet. 388 * 389 * @param {String} name the name 390 * @return {ZmZimletContext} the zimlet or <code>null</code> if not found 391 */ 392 ZmZimletMgr.prototype.getZimletByName = 393 function(name) { 394 for (var i = 0; i < this._ZIMLETS.length; i++) { 395 var z = this._ZIMLETS[i]; 396 if (z && (z.name == name)) 397 { 398 return z; 399 } 400 } 401 return null; 402 }; 403 404 /** 405 * Handles zimlet notification. 406 * 407 * @param {Object} event the event 408 * @param {Object} args the arguments 409 * 410 * @return true if any zimlet handled the notification 411 * 412 * @private 413 */ 414 ZmZimletMgr.prototype.notifyZimlets = 415 function(event, args) { 416 417 args = AjxUtil.toArray(args); 418 419 var handled = false; 420 for (var i = 0; i < this._ZIMLETS.length; ++i) { 421 var z = this._ZIMLETS[i].handlerObject; 422 if (z && z.isZmObjectHandler && z.getEnabled() && (typeof z[event] == "function")) { 423 var result = args ? z[event].apply(z, args) : z[event].apply(z); // IE cannot handle empty args 424 handled = handled || result; 425 } 426 } 427 428 return handled; 429 }; 430 431 ZmZimletMgr.prototype.notifyZimlet = 432 function(zimletName, event, args) { 433 var zimlet = this.getZimletByName(zimletName); 434 var z = zimlet && zimlet.handlerObject; 435 if (z && z.isZmObjectHandler && z.getEnabled() && (typeof z[event] == "function")) { 436 return (args ? z[event].apply(z, args) : z[event].apply(z)); // IE cannot handle empty args 437 } 438 }; 439 440 /** 441 * Processes a request (from core-zcs to zimlets) and returns value of the 442 * first zimlet that serves the request. 443 * PS: 444 * - Requestor must handle 'null' value 445 * - stores/caches the zimlet for a given request to improve performance. 446 * - also stores _requestNotHandledByAnyZimlet if no zimlet handles this 447 * request(in the current session), again to improve performance. 448 * e.g: appCtxt.getZimletMgr().processARequest("getMailCellStyle", item, field) 449 * 450 * @private 451 */ 452 ZmZimletMgr.prototype.processARequest = 453 function(request) { 454 if (this._requestNotHandledByAnyZimlet[request]) { return null; } 455 456 var args = new Array(arguments.length - 1); 457 for (var i = 0; i < args.length;) { 458 args[i] = arguments[++i]; 459 } 460 var sz = this._serviceZimlets[request]; 461 if (sz) { // if we already know a zimlet that serves this request, use it. 462 return sz[request].apply(sz, args); 463 } 464 465 var a = this._ZIMLETS; 466 for (var i = 0; i < a.length; ++i) { 467 var z = a[i].handlerObject; 468 if (z && (z instanceof ZmZimletBase) && z.getEnabled() && 469 (typeof z[request] == "function")) 470 { 471 this._serviceZimlets[request] = z;//store 472 return z[request].apply(z, args); 473 } 474 } 475 if (this.isLoaded()) { // add to an array to indicate that no zimlet implements this request 476 this._requestNotHandledByAnyZimlet[request]=request; 477 } 478 return null; 479 }; 480 481 // 482 // Protected methods 483 // 484 485 /** 486 * @private 487 */ 488 ZmZimletMgr.prototype._getZimletNames = 489 function(zimletArray) { 490 var array = new Array(zimletArray ? zimletArray.length : 0); 491 for (var i = 0; i < zimletArray.length; i++) { 492 array[i] = zimletArray[i].zimlet[0].name; 493 } 494 return array; 495 }; 496 497 /** 498 * @private 499 */ 500 ZmZimletMgr.prototype._loadIncludes = 501 function(zimletArray, zimletNames, callback) { 502 var includes = this.__getIncludes(zimletArray, zimletNames, true); 503 var includesCallback = new AjxCallback(this, this._finished_loadIncludes, [zimletNames, callback]); 504 505 AjxInclude(includes, null, includesCallback, ZmZimletBase.PROXY); 506 }; 507 508 /** 509 * @private 510 */ 511 ZmZimletMgr.prototype._finished_loadIncludes = 512 function(zimletNames, callback) { 513 if (!appCtxt.isChildWindow) { 514 this.renameZimletsLabel(); 515 } 516 this.loaded = true; 517 var zimlets = this.getZimletsHash(); 518 for (var i = 0; i < zimletNames.length; i++) { 519 var showedDialog = false; 520 var name = zimletNames[i]; 521 try { 522 zimlets[name]._finished_loadIncludes(); 523 } catch (e) { 524 if (!showedDialog) { 525 var dialog = appCtxt.getErrorDialog(); 526 var message = AjxMessageFormat.format(ZmMsg.zimletInitError, name); 527 dialog.setMessage(message, e.toString(), DwtMessageDialog.CRITICAL_STYLE); 528 dialog.popup(); 529 showedDialog = true; 530 } 531 DBG.println(AjxDebug.DBG1, "Error initializing zimlet '" + name + "': " + e); 532 } 533 } 534 if (appCtxt.get(ZmSetting.PORTAL_ENABLED) && !appCtxt.isChildWindow) { 535 var params = { 536 name: "Portal", 537 callback: (new AjxCallback(this, this._finished_loadIncludes2, [callback])) 538 }; 539 AjxPackage.require(params); 540 } else { 541 this._finished_loadIncludes2(callback); 542 } 543 }; 544 545 /** 546 * @private 547 */ 548 ZmZimletMgr.prototype._finished_loadIncludes2 = 549 function(callback) { 550 appCtxt.allZimletsLoaded(); 551 552 if (callback) { 553 callback.run(); 554 } 555 }; 556 557 /** 558 * @private 559 */ 560 ZmZimletMgr.prototype._loadStyles = 561 function(zimletArray, zimletNames) { 562 var head = document.getElementsByTagName("head")[0]; 563 var includes = this.__getIncludes(zimletArray, zimletNames, false); 564 for (var i = 0; i < includes.length; i++) { 565 var style = document.createElement("link"); 566 style.type = "text/css"; 567 style.rel = "stylesheet"; 568 style.href = includes[i]; 569 570 head.appendChild(style); 571 572 // XXX: say what?! 573 style.disabled = true; 574 style.disabled = false; 575 } 576 }; 577 578 // 579 // Private methods 580 // 581 582 /** 583 * @private 584 */ 585 ZmZimletMgr.prototype.__getIncludes = 586 function(zimletArray, zimletNames, isJS) { 587 // get language info 588 var languageId = null; 589 var countryId = null; 590 if (appCtxt.get(ZmSetting.LOCALE_NAME)) { 591 var locale = appCtxt.get(ZmSetting.LOCALE_NAME) || ""; 592 var parts = locale.split("_"); 593 languageId = parts[0]; 594 countryId = parts[1]; 595 } 596 var locid = ""; 597 if (languageId) locid += "&language="+languageId; 598 if (countryId) locid += "&country="+countryId; 599 600 // add cache killer to each url 601 var query = [ 602 "?v=", window.cacheKillerVersion 603 // window.appDevMode ? new Date().getTime() : window.cacheKillerVersion 604 ].join(""); 605 606 // add messages for all zimlets 607 var includes = []; 608 if (window.appDevMode && isJS) { 609 var zimlets = appCtxt.get(ZmSetting.ZIMLETS) || []; 610 if(appCtxt.isChildWindow) { 611 var winOpener = window.opener || window; 612 zimlets = winOpener.appCtxt.get(ZmSetting.ZIMLETS) || [] 613 } 614 for (var i = 0; i < zimlets.length; i++) { 615 var zimlet = zimlets[i].zimlet[0]; 616 includes.push([appContextPath, "/res/", zimlet.name, ".js", query, locid].join("")); 617 } 618 } 619 620 // add remote urls 621 for (var i = 0; i < zimletArray.length; i++) { 622 var zimlet = zimletArray[i].zimlet[0]; 623 var baseUrl = zimletArray[i].zimletContext[0].baseUrl; 624 var isDevZimlet = baseUrl.match("/_dev/"); 625 626 // include links 627 var links = (isJS ? zimlet.include : zimlet.includeCSS) || []; 628 for (var j = 0; j < links.length; j++) { 629 var url = links[j]._content; 630 if (ZmZimletMgr._RE_REMOTE.test(url)) { 631 var fullurl = [ ZmZimletBase.PROXY, AjxStringUtil.urlComponentEncode(url) ].join(""); 632 includes.push(fullurl); 633 continue; 634 } 635 if (window.appDevMode || isDevZimlet) { 636 var debug = isDevZimlet ? "&debug=1" : ""; 637 includes.push([baseUrl, url, query, locid, debug].join("")); 638 } 639 } 640 } 641 642 // add link to aggregated files 643 if (!window.appDevMode) { 644 var cosId = null; 645 if (appCtxt.getSettings() && appCtxt.getSettings().getInfoResponse && appCtxt.getSettings().getInfoResponse.cos) { 646 cosId = appCtxt.getSettings().getInfoResponse.cos.id; 647 } 648 var extension = (!AjxEnv.isIE || (!AjxEnv.isIE6 && AjxEnv.isIE6up)) ? appExtension : ""; 649 includes.unshift([ 650 "/service/zimlet/res/Zimlets-nodev_all", 651 (isJS ? (".js" + extension) : ".css"), 652 (languageId ? "?language=" + languageId : ""), 653 (countryId ? "&country=" + countryId : ""), 654 (cosId ? "&cosId=" + cosId : "") // For an explanation of why we add cosId here, please see bug #58979 655 ].join("")); 656 } 657 658 return includes; 659 }; 660 661 /** 662 * Renames the zimlets label. 663 * 664 * @private 665 */ 666 ZmZimletMgr.prototype.renameZimletsLabel = 667 function() { 668 var treeController = appCtxt.getOverviewController().getTreeController("ZIMLET"); 669 var treeView = (treeController) ? treeController.getTreeView("Mail") : null; 670 var root = (treeView) ? treeView.getItems()[0] : null; 671 if (root) { 672 var items = root.getItems(); 673 for (var i = 0; i < items.length; i++) { 674 this.changeZimletLabel(items[i]); 675 } 676 } 677 }; 678 679 /** 680 * Changes the zimlet label. 681 * 682 * @param {Object} item the item 683 */ 684 ZmZimletMgr.prototype.changeZimletLabel = 685 function(item) { 686 var zimlet = item.getData(Dwt.KEY_OBJECT); 687 if (zimlet) { 688 var currentLabel = zimlet.getName(); 689 var regEx = /\$/; 690 if (currentLabel.match(regEx)) { 691 var replaceLabel = currentLabel.replace(/\${msg./,'').replace(/}/,''); 692 var zimletContextName = zimlet.getZimletContext().name; 693 if (window[zimletContextName]) { 694 var str = window[zimletContextName][replaceLabel]; 695 if (str) { 696 item.setText(str); 697 zimlet.setName(str); 698 } 699 } 700 } 701 } 702 }; 703