1 /** 2 * @ignore 3 */ 4 var Ozone = Ozone ? Ozone : {}; 5 6 /** 7 * @ignore 8 * @namespace 9 */ 10 Ozone.chrome = Ozone.chrome ? Ozone.chrome : {}; 11 12 /** 13 * @deprecated Since OWF 3.7.0 You should use <a href="#.getInstance">Ozone.chrome.WidgetChrome.getInstance</a> 14 * @constructor widgetEventingController - Ozone.eventing.Widget object 15 * @param {Object} config - config object with parameters 16 * @param {Ozone.eventing.Widget} config.widgetEventingController - widget eventing object which handles eventing for the widget 17 * @description This object allows a widget to modify the button contained in the widget header (the chrome). 18 * To do so it requires a widgetEventingController 19 * @example 20 * this.wc = new Ozone.chrome.WidgetChrome({ 21 * widgetEventingController: this.widgetEventingController 22 * }); 23 * 24 * @throws {Error} throws an error with a message if widget initialization fails 25 */ 26 Ozone.chrome.WidgetChrome = function(config) { 27 if (Ozone.chrome.WidgetChrome.instance == null) { 28 var scope = this; 29 scope.channelName = "Ozone._WidgetChromeChannel"; 30 scope.version = Ozone.version.owfversion + Ozone.version.widgetChrome; 31 scope.items = {}; 32 scope.registerChromeMenu = function(menuConfig) { 33 // Regular menu item 34 scope.items[menuConfig.itemId != null ? menuConfig.itemId : menuConfig.id] = menuConfig; 35 36 if (menuConfig.menu) { 37 for (var j = 0 ; j < menuConfig.menu.items.length ; j++) { 38 var menuItem = menuConfig.menu.items[j]; 39 // Sub-menu 40 scope.registerChromeMenu(menuItem); 41 } 42 } 43 }; 44 45 var pub = /** @lends Ozone.chrome.WidgetChrome.prototype */ { 46 47 init : function(config) { 48 49 config = config || {}; 50 51 scope.widgetEventingController = config.widgetEventingController || Ozone.eventing.Widget.instance; 52 scope.widgetEventingController.registerHandler(scope.channelName, function(sender, msg) { 53 var returnValue = true; 54 55 //msg will always be a json string 56 var data = Ozone.util.parseJson(msg); 57 58 var id = data.itemId != null ? data.itemId : data.id; 59 var handler = scope.items[id].handler; 60 if (handler != null && owfdojo.isFunction(handler)) { 61 returnValue = handler.apply(data.scope != null ? data.scope : window, data.args != null ? data.args : []); 62 } 63 64 return returnValue; 65 }); 66 }, 67 68 /** 69 * @description Checks to see if the Widget Chrome has already been modified. This is useful if the widget iframe is reloaded 70 * @param {Object} cfg config object see below for properties 71 * @param {Function} cfg.callback The function which receives the results. 72 * This method will be passed an object which has following properties. <br> 73 * <br> 74 * {Boolean} success: true if the widget is currently opened on the dashboard, or else false. <br> 75 * {Boolean} modified: true if the widget chrome(header) is modified, or else false. <br> 76 * 77 * @example 78 * //this.wc is an already instantiated WidgetChrome obj 79 * this.wc.isModified({ 80 * callback: function(msg) { 81 * //msg will always be a json string 82 * var res = Ozone.util.parseJson(msg); 83 * if (res.success) { 84 * 85 * //if the chrome was never modified 86 * if (!res.modified) { 87 * //do something, perhaps add buttons 88 * } 89 * //if we already modified the chrome 90 * else { 91 * //do something or perhaps nothing if the buttons are already added 92 * } 93 * } 94 * } 95 * }); 96 */ 97 isModified: function(cfg) { 98 var data = { 99 action: 'isModified' 100 }; 101 var jsonString = gadgets.json.stringify(data); 102 gadgets.rpc.call('..', scope.channelName, cfg.callback, scope.widgetEventingController.getWidgetId(), jsonString); 103 }, 104 105 /** 106 * @description Adds buttons to the Widget Chrome. Buttons are added after existing buttons. 107 * @param {Object} cfg config object see below for properties 108 * @param {Object[]} cfg.items an array of buttons configurations to add to the chrome. See example for button configs 109 * @param {String} cfg.items[*].itemId itemId is a unique id among all buttons that are added. It is a required property. It is used for identification and defines the internal Eventing channel which is used to execute the handler function. If itemId is not unique this may result in duplicate buttons which may not be able to be removed properly. 110 * @param {String} cfg.items[*].xtype xtype is ExtJS-like property used to determine the component to create. Currently the Widget Chrome API only supports two xtype values: ‘button’ and ‘widgettool’. xtype is an optional field, if it is omitted ‘widgettool’ is used. 111 * @param {String} cfg.items[*].type Used only for ‘widgettool’ buttons. It determines the standard icon to be used. For a complete list of types please see the ExtJS 4.x API documentation, <a href='http://docs.sencha.com/ext-js/4-0/#/api/Ext.panel.Tool-cfg-type'>http://docs.sencha.com/ext-js/4-0/#/api/Ext.panel.Tool-cfg-type</a> 112 * @param {String} cfg.items[*].icon This property defines the URL of the image to be used for the button. If the URL is a relative path, it will be relative to the /owf context. This is useful if the desired image is hosted by the OWF web server. Otherwise a fully qualified URL should be used. If type is being used to determine the image, the icon property is optional 113 * @param {String} cfg.items[*].text This property defines text to appear alongside the button. This property is only used if the xtype is ‘button.’ ‘widgettool’ will not show text. 114 * @param {Object} cfg.items[*].tooltip This property defines a tooltip. It has two important sub properties, title and text. tooltip is only used when the xtype is ‘button’ 115 * @param {Function} cfg.items[*].handler The handler attribute defines a function to be executed when the button is pressed. This function is executed using Widget Eventing API from inside the widget. The internal channel name used is the itemId attribute. This function’s parameter list contains the standard parameters for an Eventing callback function. 116 * @example 117 * //this.wc is an already instantiated WidgetChrome obj 118 * this.wc.addHeaderButtons({ 119 * items: 120 * [ 121 * { 122 * xtype: 'button', 123 * //path to an image to use. this path should either be fully qualified or relative to the /owf context 124 * icon: './themes/common/images/skin/exclamation.png', 125 * text: 'Alert', 126 * itemId:'alert', 127 * tooltip: { 128 * text: 'Alert!' 129 * }, 130 * handler: function(sender, data) { 131 * //widgetState is an already instantiated WidgetState Obj 132 * if (widgetState) { 133 * widgetState.getWidgetState({ 134 * callback: function(state) { 135 * 136 * //check if the widget is visible 137 * if (!state.collapsed && !state.minimized && state.active) { 138 * //only render visual content, perhaps popup a message box if the widget is visible 139 * //otherwise it may not render correctly 140 * } 141 * } 142 * }); 143 * } 144 * } 145 * }, 146 * { 147 * xtype: 'widgettool', 148 * //path to an image to use. this path should either be fully qualified or relative to the /owf context 149 * icon: './themes/common/images/skin/information.png', 150 * itemId:'help', 151 * handler: function(sender, data) { 152 * alert('About Button Pressed'); 153 * } 154 * }, 155 * { 156 * //gear is a standard ext tool type 157 * type: 'gear', 158 * itemId:'gear', 159 * handler: function(sender, data) { 160 * alert('Utility Button Pressed'); 161 * } 162 * } 163 * ] 164 * }); 165 */ 166 addHeaderButtons : function(cfg) { 167 var data = {}; 168 var items = null; 169 170 if (!owfdojo.isArray(cfg.items)) { 171 items = [cfg.items]; 172 } 173 else { 174 items = cfg.items; 175 } 176 177 data.action = 'addHeaderButtons'; 178 data.type = 'button'; 179 data.items = items; 180 for (var i = 0; i < items.length; i++) { 181 scope.items[items[i].itemId != null ? items[i].itemId : items[i].id] = items[i]; 182 } 183 184 var jsonString = gadgets.json.stringify(data); 185 gadgets.rpc.call('..', scope.channelName, cfg.callback, scope.widgetEventingController.getWidgetId(), jsonString); 186 187 }, 188 189 /** 190 * @description Updates any existing buttons in the Widget Chrome based on the itemId. 191 * @param {Object} cfg config object see below for properties 192 * @param {Object[]} cfg.items an array of buttons configurations to add to the chrome. See example below for button configs 193 * @param {String} cfg.items[*].itemId itemId is a unique id among all buttons that are added. It is a required property. It is used for identification and defines the internal Eventing channel which is used to execute the handler function. If itemId is not unique this may result in duplicate buttons which may not be able to be removed properly. 194 * @param {String} cfg.items[*].xtype xtype is ExtJS-like property used to determine the component to create. Currently the Widget Chrome API only supports two xtype values: ‘button’ and ‘widgettool’. xtype is an optional field, if it is omitted ‘widgettool’ is used. 195 * @param {String} cfg.items[*].type Used only for ‘widgettool’ buttons. It determines the standard icon to be used. For a complete list of types please see the ExtJS 4.x API documentation, <a href='http://docs.sencha.com/ext-js/4-0/#/api/Ext.panel.Tool-cfg-type'>http://docs.sencha.com/ext-js/4-0/#/api/Ext.panel.Tool-cfg-type</a> 196 * @param {String} cfg.items[*].icon This property defines the URL of the image to be used for the button. If the URL is a relative path, it will be relative to the /owf context. This is useful if the desired image is hosted by the OWF web server. Otherwise a fully qualified URL should be used. If type is being used to determine the image, the icon property is optional 197 * @param {String} cfg.items[*].text This property defines text to appear alongside the button. This property is only used if the xtype is ‘button.’ ‘widgettool’ will not show text. 198 * @param {Object} cfg.items[*].tooltip This property defines a tooltip. It has two important sub properties, title and text. tooltip is only used when the xtype is ‘button’ 199 * @param {Function} cfg.items[*].handler The handler attribute defines a function to be executed when the button is pressed. This function is executed using Widget Eventing API from inside the widget. The internal channel name used is the itemId attribute. This function’s parameter list contains the standard parameters for an Eventing callback function. 200 * @example 201 * //this.wc is an already instantiated WidgetChrome obj 202 * this.wc.updateHeaderButtons({ 203 * items: 204 * [ 205 * { 206 * xtype: 'button', 207 * //path to an image to use. this path should either be fully qualified or relative to the /owf context 208 * icon: './themes/common/images/skin/exclamation.png', 209 * text: 'Alert', 210 * itemId:'alert', 211 * tooltip: { 212 * text: 'Alert!' 213 * }, 214 * handler: function(sender, data) { 215 * //widgetState is an already instantiated WidgetState Obj 216 * if (widgetState) { 217 * widgetState.getWidgetState({ 218 * callback: function(state) { 219 * 220 * //check if the widget is visible 221 * if (!state.collapsed && !state.minimized && state.active) { 222 * //only render visual content, perhaps popup a message box if the widget is visible 223 * //otherwise it may not render correctly 224 * } 225 * } 226 * }); 227 * } 228 * } 229 * }, 230 * { 231 * xtype: 'widgettool', 232 * //path to an image to use. this path should either be fully qualified or relative to the /owf context 233 * icon: './themes/common/images/skin/information.png', 234 * itemId:'help', 235 * handler: function(sender, data) { 236 * alert('About Button Pressed'); 237 * } 238 * }, 239 * { 240 * //gear is a standard ext tool type 241 * type: 'gear', 242 * itemId:'gear', 243 * handler: function(sender, data) { 244 * alert('Utility Button Pressed'); 245 * } 246 * } 247 * ] 248 * }); 249 */ 250 updateHeaderButtons : function(cfg) { 251 var data = {}; 252 var items = null; 253 254 if (!owfdojo.isArray(cfg.items)) { 255 items = [cfg.items]; 256 } 257 else { 258 items = cfg.items; 259 } 260 261 data.action = 'updateHeaderButtons'; 262 data.type = 'button'; 263 data.items = items; 264 for (var i = 0; i < items.length; i++) { 265 //save data 266 var id = items[i].itemId != null ? items[i].itemId : items[i].id; 267 if (scope.items[id] != null) { 268 owfdojo.mixin(scope.items[id], items[i]); 269 } 270 else { 271 scope.items[id] = items[i]; 272 } 273 } 274 275 var jsonString = gadgets.json.stringify(data); 276 gadgets.rpc.call('..', scope.channelName, cfg.callback, scope.widgetEventingController.getWidgetId(), jsonString); 277 278 }, 279 280 /** 281 * @description Inserts new buttons to the Widget Chrome. Buttons are added to the same area as existing buttons. 282 * @param {Object} cfg config object see below for properties 283 * @param {Number} [cfg.pos=0] 0-based index of where buttons will be added, among any pre-existing buttons. 284 * @param {Object[]} cfg.items an array of buttons configurations to insert to the chrome. See example below for button configs 285 * @param {String} cfg.items[*].itemId itemId is a unique id among all buttons that are added. It is a required property. It is used for identification and defines the internal Eventing channel which is used to execute the handler function. If itemId is not unique this may result in duplicate buttons which may not be able to be removed properly. 286 * @param {String} cfg.items[*].xtype xtype is ExtJS-like property used to determine the component to create. Currently the Widget Chrome API only supports two xtype values: ‘button’ and ‘widgettool’. xtype is an optional field, if it is omitted ‘widgettool’ is used. 287 * @param {String} cfg.items[*].type Used only for ‘widgettool’ buttons. It determines the standard icon to be used. For a complete list of types please see the ExtJS 4.x API documentation, <a href='http://docs.sencha.com/ext-js/4-0/#/api/Ext.panel.Tool-cfg-type'>http://docs.sencha.com/ext-js/4-0/#/api/Ext.panel.Tool-cfg-type</a> 288 * @param {String} cfg.items[*].icon This property defines the URL of the image to be used for the button. If the URL is a relative path, it will be relative to the /owf context. This is useful if the desired image is hosted by the OWF web server. Otherwise a fully qualified URL should be used. If type is being used to determine the image, the icon property is optional 289 * @param {String} cfg.items[*].text This property defines text to appear alongside the button. This property is only used if the xtype is ‘button.’ ‘widgettool’ will not show text. 290 * @param {Object} cfg.items[*].tooltip This property defines a tooltip. It has two important sub properties, title and text. tooltip is only used when the xtype is ‘button’ 291 * @param {Function} cfg.items[*].handler The handler attribute defines a function to be executed when the button is pressed. This function is executed using Widget Eventing API from inside the widget. The internal channel name used is the itemId attribute. This function’s parameter list contains the standard parameters for an Eventing callback function. 292 * @example 293 * //this.wc is an already instantiated WidgetChrome obj 294 * this.wc.insertHeaderButtons({ 295 * pos: 0, 296 * items: 297 * [ 298 * { 299 * xtype: 'button', 300 * //path to an image to use. this path should either be fully qualified or relative to the /owf context 301 * icon: './themes/common/images/skin/exclamation.png', 302 * text: 'Alert', 303 * itemId:'alert', 304 * tooltip: { 305 * text: 'Alert!' 306 * }, 307 * handler: function(sender, data) { 308 * //widgetState is an already instantiated WidgetState Obj 309 * if (widgetState) { 310 * widgetState.getWidgetState({ 311 * callback: function(state) { 312 * 313 * //check if the widget is visible 314 * if (!state.collapsed && !state.minimized && state.active) { 315 * //only render visual content, perhaps popup a message box if the widget is visible 316 * //otherwise it may not render correctly 317 * } 318 * } 319 * }); 320 * } 321 * } 322 * }, 323 * { 324 * xtype: 'widgettool', 325 * //path to an image to use. this path should either be fully qualified or relative to the /owf context 326 * icon: './themes/common/images/skin/information.png', 327 * itemId:'help', 328 * handler: function(sender, data) { 329 * alert('About Button Pressed'); 330 * } 331 * }, 332 * { 333 * //gear is a standard ext tool type 334 * type: 'gear', 335 * itemId:'gear', 336 * handler: function(sender, data) { 337 * alert('Utility Button Pressed'); 338 * } 339 * } 340 * ] 341 * }); 342 */ 343 insertHeaderButtons : function(cfg) { 344 var data = {}; 345 var items = null; 346 347 if (!owfdojo.isArray(cfg.items)) { 348 items = [cfg.items]; 349 } 350 else { 351 items = cfg.items; 352 } 353 354 data.action = 'insertHeaderButtons'; 355 data.type = 'button'; 356 if (cfg.pos != null) { 357 data.pos = cfg.pos; 358 } 359 data.items = items; 360 for (var i = 0; i < items.length; i++) { 361 scope.items[items[i].itemId != null ? items[i].itemId : items[i].id] = items[i]; 362 } 363 364 var jsonString = gadgets.json.stringify(data); 365 gadgets.rpc.call('..', scope.channelName, cfg.callback, scope.widgetEventingController.getWidgetId(), jsonString); 366 }, 367 368 /** 369 * @description Removes existing buttons on the Widget Chrome based on itemId. 370 * @param {Object} cfg config object see below for properties 371 * @param {Object[]} cfg.items an array of buttons configurations to remove to the chrome. Only itemId is required. 372 * See example below for button configs 373 * @param {String} cfg.items[*].itemId itemId is a unique id among all buttons that are added. It is a required property. It is used for identification and defines the internal Eventing channel which is used to execute the handler function. If itemId is not unique this may result in duplicate buttons which may not be able to be removed properly. 374 * @example 375 * //this.wc is an already instantiated WidgetChrome obj 376 * this.wc.removeHeaderButtons({ 377 * items: 378 * [ 379 * { 380 * itemId:'alert' 381 * }, 382 * { 383 * itemId:'help' 384 * }, 385 * { 386 * itemId:'gear' 387 * } 388 * ] 389 * }); 390 */ 391 removeHeaderButtons : function(cfg) { 392 var data = {}; 393 var items = null; 394 395 if (!owfdojo.isArray(cfg.items)) { 396 items = [cfg.items]; 397 } 398 else { 399 items = cfg.items; 400 } 401 402 data.action = 'removeHeaderButtons'; 403 data.type = 'button'; 404 data.items = items; 405 for (var i = 0; i < items.length; i++) { 406 var id = items[i].itemId != null ? items[i].itemId : items[i].id; 407 if (scope.items[id] != null) { 408 //delete saved data 409 delete scope.items[id]; 410 } 411 } 412 413 var jsonString = gadgets.json.stringify(data); 414 gadgets.rpc.call('..', scope.channelName, cfg.callback, scope.widgetEventingController.getWidgetId(), jsonString); 415 }, 416 417 418 /** 419 * @description Lists all buttons that have been added to the widget chrome. 420 * @param {Object} cfg config object see below for properties 421 * @param {Function} cfg.callback The function which receives the results. 422 * 423 * @example 424 * //this.wc is an already instantiated WidgetChrome obj 425 * this.wc.listHeaderButtons({ 426 * callback: function(msg) { 427 * //msg will always be a json string 428 * var res = Ozone.util.parseJson(msg); 429 * if (res.success) { 430 * for (var i = 0; i < res.items.length; i++) { 431 * // do something with the buttons 432 * } 433 * } 434 * } 435 * }); 436 */ 437 listHeaderButtons: function(cfg) { 438 var data = { 439 action: 'listHeaderMenus', 440 type: 'button' 441 }; 442 var jsonString = gadgets.json.stringify(data); 443 gadgets.rpc.call('..', scope.channelName, cfg.callback, scope.widgetEventingController.getWidgetId(), jsonString); 444 }, 445 446 /** 447 * @description Adds menus to the Widget Chrome. Menus are added after existing menus. 448 * @param {Object} cfg config object see below for properties 449 * @param {Object[]} cfg.items an array of menu configurations to add to the chrome. See example for menu configs 450 * @param {String} cfg.items[*].parentId itemId is the itemId of the menu to which this configuration should be added as a sub-menu. If omitted, the configuration will be added as a main menu on the menu toolbar. 451 * @param {String} cfg.items[*].itemId itemId is a unique id among all menus that are added. It is a required property. It is used for identification and defines the internal Eventing channel which is used to execute the handler function. If itemId is not unique this may result in duplicate menus which may not be able to be removed properly. 452 * @param {String} cfg.items[*].icon This property defines the URL of the image to be used for the menu. If the URL is a relative path, it will be relative to the /owf context. This is useful if the desired image is hosted by the OWF web server. Otherwise a fully qualified URL should be used. If type is being used to determine the image, the icon property is optional 453 * @param {String} cfg.items[*].text This property defines text to appear alongside the menu. 454 * @param {Object} cfg.items[*].menu menu configuration object 455 * @param {Object[]} cfg.items[*].menu.items an array of menu item configurations to add to the chrome. See example for menu item configs 456 * @param {String} cfg.items[*].menu.items[*].itemId itemId is a unique id among all menu items that are added. It is a required property. It is used for identification and defines the internal Eventing channel which is used to execute the handler function. 457 * @param {String} cfg.items[*].menu.items[*].xtype xtype is used to specify the type of menu item to add. This attribute should be omitted unless specifying a menuseparator. Setting this value to "menuseparator" adds a separator bar to a menu, used to divide logical groups of menu items. If specified, only xtype should be specified. Generally you will add one of these by using "-" in your items config rather than creating one directly using xtype. See example below for usage. 458 * @param {String} cfg.items[*].menu.items[*].icon This property defines the URL of the image to be used for the menu item. If the URL is a relative path, it will be relative to the /owf context. This is useful if the desired image is hosted by the OWF web server. Otherwise a fully qualified URL should be used. If type is being used to determine the image, the icon property is optional 459 * @param {String} cfg.items[*].menu.items[*].text This property defines text to appear for the menu item. 460 * @param {Function} cfg.items[*].menu.items[*].handler The handler attribute defines a function to be executed when the menu item is clicked. This function is executed using Widget Eventing API from inside the widget. The internal channel name used is the itemId attribute. This function's parameter list contains the standard parameters for an Eventing callback function. 461 * @param {Object} cfg.items[*].menu.items[*].menu sub-menu configuration object. See example for sub-menu config. 462 * @example 463 * //this.wc is an already instantiated WidgetChrome obj 464 * this.wc.addHeaderMenus({ 465 * items: 466 * [ 467 * { 468 * itemId:'regularMenu', 469 * icon: './themes/common/images/skin/exclamation.png', 470 * text: 'Regular Menu', 471 * menu: { 472 * items: [ 473 * { 474 * itemId:'regularMenuItem1', 475 * icon: './themes/common/images/skin/exclamation.png', 476 * text: 'Regular Menu Item 1', 477 * handler: function(sender, data) { 478 * alert('You clicked the Regular Menu menu item.'); 479 * } 480 * } 481 * ] 482 * } 483 * }, 484 * { 485 * itemId:'snacks', 486 * icon: './themes/common/images/skin/exclamation.png', 487 * text: 'Menu with Sub-Menu', 488 * menu: { 489 * items: [ 490 * { 491 * itemId:'fruits', 492 * icon: './themes/common/images/skin/exclamation.png', 493 * text: 'Fruits', 494 * menu: { 495 * items: [ 496 * { 497 * itemId:'apple', 498 * icon: './themes/common/images/skin/exclamation.png', 499 * text: 'Apple', 500 * handler: function(sender, data) { 501 * alert('Your snack will be an Apple.'); 502 * } 503 * }, 504 * { 505 * xtype: 'menuseparator' 506 * }, 507 * { 508 * itemId:'banana', 509 * icon: './themes/common/images/skin/exclamation.png', 510 * text: 'Banana', 511 * handler: function(sender, data) { 512 * alert('Your snack will be a Banana.'); 513 * } 514 * }, { 515 * itemId:'cherry', 516 * icon: './themes/common/images/skin/exclamation.png', 517 * text: 'Cherries', 518 * handler: function(sender, data) { 519 * alert('Your snack will be Cherries.'); 520 * } 521 * } 522 * ] 523 * } 524 * }, 525 * '-', // another way to add a menu separator 526 * { 527 * itemId:'cupcake', 528 * icon: './themes/common/images/skin/exclamation.png', 529 * text: 'Cupcake', 530 * handler: function(sender, data) { 531 * alert('Your snack will be a Cupcake.'); 532 * } 533 * }, { 534 * itemId:'chips', 535 * icon: './themes/common/images/skin/exclamation.png', 536 * text: 'Potato Chips', 537 * handler: function(sender, data) { 538 * alert('Your snack will be a Potato Chips.'); 539 * } 540 * } 541 * ] 542 * } 543 * } 544 * ] 545 * }); 546 */ 547 addHeaderMenus : function(cfg) { 548 var data = {}; 549 var items = null; 550 551 if (!owfdojo.isArray(cfg.items)) { 552 items = [cfg.items]; 553 } 554 else { 555 items = cfg.items; 556 } 557 558 data.action = 'addHeaderMenus'; 559 data.type = 'menu'; 560 data.items = items; 561 for (var i = 0; i < items.length; i++) { 562 var item = items[i]; 563 scope.registerChromeMenu(item); 564 } 565 566 var jsonString = gadgets.json.stringify(data); 567 gadgets.rpc.call('..', scope.channelName, cfg.callback, scope.widgetEventingController.getWidgetId(), jsonString); 568 569 }, 570 571 /** 572 * @description Updates any existing menus in the Widget Chrome based on the itemId. 573 * @param {Object} cfg config object see below for properties 574 * @param {Object[]} cfg.items an array of menu configurations to add to the chrome. See example for menu configs 575 * @param {String} cfg.items[*].itemId itemId is a unique id among all menus that are added. It is a required property. It is used for identification and defines the internal Eventing channel which is used to execute the handler function. If itemId is not unique this may result in duplicate menus which may not be able to be removed properly. 576 * @param {String} cfg.items[*].icon This property defines the URL of the image to be used for the menu. If the URL is a relative path, it will be relative to the /owf context. This is useful if the desired image is hosted by the OWF web server. Otherwise a fully qualified URL should be used. If type is being used to determine the image, the icon property is optional 577 * @param {String} cfg.items[*].text This property defines text to appear alongside the menu. 578 * @param {Object} cfg.items[*].menu menu configuration object 579 * @param {Object[]} cfg.items[*].menu.items an array of menu item configurations to add to the chrome. See example for menu item configs 580 * @param {String} cfg.items[*].menu.items[*].itemId itemId is a unique id among all menu items that are added. It is a required property. It is used for identification and defines the internal Eventing channel which is used to execute the handler function. 581 * @param {String} cfg.items[*].menu.items[*].xtype xtype is used to specify the type of menu item to add. This attribute should be omitted unless specifying a menuseparator. Setting this value to "menuseparator" adds a separator bar to a menu, used to divide logical groups of menu items. If specified, only xtype should be specified. See example below for usage. 582 * @param {String} cfg.items[*].menu.items[*].icon This property defines the URL of the image to be used for the menu item. If the URL is a relative path, it will be relative to the /owf context. This is useful if the desired image is hosted by the OWF web server. Otherwise a fully qualified URL should be used. If type is being used to determine the image, the icon property is optional 583 * @param {String} cfg.items[*].menu.items[*].text This property defines text to appear for the menu item. 584 * @param {Function} cfg.items[*].menu.items[*].handler The handler attribute defines a function to be executed when the menu item is clicked. This function is executed using Widget Eventing API from inside the widget. The internal channel name used is the itemId attribute. This function's parameter list contains the standard parameters for an Eventing callback function. 585 * @param {Object} cfg.items[*].menu.items[*].menu sub-menu configuration object. See example for sub-menu config. 586 * @example 587 * //this.wc is an already instantiated WidgetChrome obj 588 * this.wc.updateHeaderMenus({ 589 * items: 590 * [ 591 * { 592 * itemId:'regularMenu', 593 * icon: './themes/common/images/skin/exclamation.png', 594 * text: 'Regular Menu', 595 * menu: { 596 * items: [ 597 * { 598 * itemId:'regularMenuItem1', 599 * icon: './themes/common/images/skin/exclamation.png', 600 * text: 'Regular Menu Item 1', 601 * handler: function(sender, data) { 602 * alert('You clicked the Regular Menu menu item.'); 603 * } 604 * } 605 * ] 606 * } 607 * }, 608 * { 609 * itemId:'snacks', 610 * icon: './themes/common/images/skin/exclamation.png', 611 * text: 'Menu with Sub-Menu', 612 * menu: { 613 * items: [ 614 * { 615 * itemId:'fruits', 616 * icon: './themes/common/images/skin/exclamation.png', 617 * text: 'Fruits', 618 * menu: { 619 * items: [ 620 * { 621 * itemId:'apple', 622 * icon: './themes/common/images/skin/exclamation.png', 623 * text: 'Apple', 624 * handler: function(sender, data) { 625 * alert('Your snack will be an Apple.'); 626 * } 627 * }, 628 * { 629 * xtype: 'menuseparator' 630 * }, 631 * { 632 * itemId:'banana', 633 * icon: './themes/common/images/skin/exclamation.png', 634 * text: 'Banana', 635 * handler: function(sender, data) { 636 * alert('Your snack will be a Banana.'); 637 * } 638 * }, { 639 * itemId:'cherry', 640 * icon: './themes/common/images/skin/exclamation.png', 641 * text: 'Cherries', 642 * handler: function(sender, data) { 643 * alert('Your snack will be Cherries.'); 644 * } 645 * } 646 * ] 647 * } 648 * }, 649 * '-', // another way to add a menu separator 650 * { 651 * itemId:'cupcake', 652 * icon: './themes/common/images/skin/exclamation.png', 653 * text: 'Cupcake', 654 * handler: function(sender, data) { 655 * alert('Your snack will be a Cupcake.'); 656 * } 657 * }, { 658 * itemId:'chips', 659 * icon: './themes/common/images/skin/exclamation.png', 660 * text: 'Potato Chips', 661 * handler: function(sender, data) { 662 * alert('Your snack will be a Potato Chips.'); 663 * } 664 * } 665 * ] 666 * } 667 * } 668 * ] 669 * }); 670 */ 671 updateHeaderMenus : function(cfg) { 672 var data = {}; 673 var items = null; 674 675 if (!owfdojo.isArray(cfg.items)) { 676 items = [cfg.items]; 677 } 678 else { 679 items = cfg.items; 680 } 681 682 data.action = 'updateHeaderMenus'; 683 data.type = 'menu'; 684 data.items = items; 685 686 var merge = function(source, key, value) { 687 if (typeof key === 'string') { 688 if (value && value.constructor === Object) { 689 if (source[key] && source[key].constructor === Object) { 690 merge(source[key], value); 691 } 692 else { 693 source[key] = Ext.clone(value); 694 } 695 } 696 else { 697 source[key] = value; 698 } 699 700 return source; 701 } 702 703 var i = 1, 704 ln = arguments.length, 705 object, property; 706 707 for (; i < ln; i++) { 708 object = arguments[i]; 709 710 for (property in object) { 711 if (object.hasOwnProperty(property)) { 712 merge(source, property, object[property]); 713 } 714 } 715 } 716 717 return source; 718 }; 719 720 for (var i = 0; i < items.length; i++) { 721 var item = items[i]; 722 // don't re-register menu if submenu or handler are unchanged 723 if (item.menu || item.handler) { 724 scope.registerChromeMenu(item); 725 } 726 if (item.menu) { 727 for (var j = 0 ; j < item.menu.items.length ; j++) { 728 var menuItem = item.menu.items[j]; 729 if (!menuItem.menu) { 730 // Regular menu item 731 // Merge with current menu item 732 var key = menuItem.itemId != null ? menuItem.itemId : menuItem.id; 733 scope.items[key] = scope.items[key] ? scope.items[key] : {}; 734 scope.items[key] = merge(scope.items[key], menuItem); 735 } else { 736 // Sub-menu 737 for (var k = 0 ; k < menuItem.menu.items.length ; k++) { 738 var subMenuItem = menuItem.menu.items[k]; 739 // Merge with current sub-menu item 740 var key = subMenuItem.itemId != null ? subMenuItem.itemId : subMenuItem.id; 741 scope.items[key] = scope.items[key] ? scope.items[key] : {}; 742 scope.items[key] = merge(scope.items[key], subMenuItem); 743 } 744 } 745 } 746 } else { 747 // Regular menu item 748 // Merge with current menu item 749 var key = item.itemId != null ? item.itemId : item.id; 750 scope.items[key] = scope.items[key] ? scope.items[key] : {}; 751 scope.items[key] = merge(scope.items[key], item); 752 } 753 754 // Update data with merged item 755 data.items[i] = scope.items[data.items[i].itemId]; 756 } 757 758 var jsonString = gadgets.json.stringify(data); 759 gadgets.rpc.call('..', scope.channelName, cfg.callback, scope.widgetEventingController.getWidgetId(), jsonString); 760 761 }, 762 763 /** 764 * @description Inserts new menus into the Widget Chrome. Menus are added to the same area as existing menus. 765 * @param {Object} cfg config object see below for properties 766 * @param {Number} [cfg.pos=0] 0-based index of where menus will be added, among any pre-existing menus. 767 * @param {Object[]} cfg.items an array of menu configurations to add to the chrome. See example for menu configs 768 * @param {String} cfg.items[*].parentId itemId is the itemId of the menu to which this configuration should be added as a sub-menu. If omitted, the configuration will be added as a main menu on the menu toolbar. 769 * @param {String} cfg.items[*].itemId itemId is a unique id among all menus that are added. It is a required property. It is used for identification and defines the internal Eventing channel which is used to execute the handler function. If itemId is not unique this may result in duplicate menus which may not be able to be removed properly. 770 * @param {String} cfg.items[*].icon This property defines the URL of the image to be used for the menu. If the URL is a relative path, it will be relative to the /owf context. This is useful if the desired image is hosted by the OWF web server. Otherwise a fully qualified URL should be used. If type is being used to determine the image, the icon property is optional 771 * @param {String} cfg.items[*].text This property defines text to appear alongside the menu. This property is only used if the xtype is ‘menu.’ ‘widgettool’ will not show text. 772 * @param {Object} cfg.items[*].menu menu configuration object 773 * @param {Object[]} cfg.items[*].menu.items an array of menu item configurations to add to the chrome. See example for menu item configs 774 * @param {String} cfg.items[*].menu.items[*].itemId itemId is a unique id among all menu items that are added. It is a required property. It is used for identification and defines the internal Eventing channel which is used to execute the handler function. 775 * @param {String} cfg.items[*].menu.items[*].xtype xtype is used to specify the type of menu item to add. This attribute should be omitted unless specifying a menuseparator. Setting this value to "menuseparator" adds a separator bar to a menu, used to divide logical groups of menu items. If specified, only xtype should be specified. See example below for usage. 776 * @param {String} cfg.items[*].menu.items[*].icon This property defines the URL of the image to be used for the menu item. If the URL is a relative path, it will be relative to the /owf context. This is useful if the desired image is hosted by the OWF web server. Otherwise a fully qualified URL should be used. If type is being used to determine the image, the icon property is optional 777 * @param {String} cfg.items[*].menu.items[*].text This property defines text to appear for the menu item. 778 * @param {Function} cfg.items[*].menu.items[*].handler The handler attribute defines a function to be executed when the menu item is clicked. This function is executed using Widget Eventing API from inside the widget. The internal channel name used is the itemId attribute. This function's parameter list contains the standard parameters for an Eventing callback function. 779 * @param {Object} cfg.items[*].menu.items[*].menu sub-menu configuration object. See example for sub-menu config. 780 * @example 781 * //this.wc is an already instantiated WidgetChrome obj 782 * this.wc.insertHeaderMenus({ 783 * pos: 0, 784 * items: [{ 785 * itemId:'insertedMenu', 786 * icon: './themes/common/images/skin/exclamation.png', 787 * text: 'Inserted Menu', 788 * menu: { 789 * items: [ 790 * { 791 * itemId:'insertedMenuItem1', 792 * icon: './themes/common/images/skin/exclamation.png', 793 * text: 'Inserted Menu Item 1', 794 * handler: function(sender, data) { 795 * alert('You clicked the Inserted Menu menu item.'); 796 * } 797 * }, 798 * { 799 * xtype: 'menuseparator' 800 * }, 801 * { 802 * itemId:'insertedMenuItem2', 803 * icon: './themes/common/images/skin/exclamation.png', 804 * text: 'Inserted Menu Item 2', 805 * handler: function(sender, data) { 806 * alert('You clicked the Inserted Menu menu item.'); 807 * } 808 * }, 809 * '-', // another way to add a menu separator 810 * { 811 * itemId:'insertedMenuItem3', 812 * icon: './themes/common/images/skin/exclamation.png', 813 * text: 'Inserted Menu Item 3', 814 * handler: function(sender, data) { 815 * alert('You clicked the Inserted Menu menu item.'); 816 * } 817 * } 818 * ] 819 * } 820 * }] 821 * }); 822 */ 823 insertHeaderMenus : function(cfg) { 824 var data = {}; 825 var items = null; 826 827 if (!owfdojo.isArray(cfg.items)) { 828 items = [cfg.items]; 829 } 830 else { 831 items = cfg.items; 832 } 833 834 data.action = 'insertHeaderMenus'; 835 data.type = 'menu'; 836 if (cfg.pos != null) { 837 data.pos = cfg.pos; 838 } 839 data.items = items; 840 for (var i = 0; i < items.length; i++) { 841 var item = items[i]; 842 if (item.menu) { 843 for (var j = 0 ; j < item.menu.items.length ; j++) { 844 var menuItem = item.menu.items[j]; 845 if (!menuItem.menu) { 846 // Regular menu item 847 scope.items[menuItem.itemId != null ? menuItem.itemId : menuItem.id] = menuItem; 848 } else { 849 // Sub-menu 850 for (var k = 0 ; k < menuItem.menu.items.length ; k++) { 851 var subMenuItem = menuItem.menu.items[k]; 852 scope.items[subMenuItem.itemId != null ? subMenuItem.itemId : subMenuItem.id] = subMenuItem; 853 } 854 } 855 } 856 } else { 857 // Regular menu item 858 scope.items[item.itemId != null ? item.itemId : item.id] = item; 859 } 860 } 861 862 var jsonString = gadgets.json.stringify(data); 863 gadgets.rpc.call('..', scope.channelName, cfg.callback, scope.widgetEventingController.getWidgetId(), jsonString); 864 }, 865 866 /** 867 * @description Removes existing menus on the Widget Chrome based on itemId. 868 * @param {Object} cfg config object see below for properties 869 * @param {Object[]} cfg.items an array of objects containing itemIds for the menus to remove from the chrome. 870 * See example below for button configs 871 * @example 872 * //this.wc is an already instantiated WidgetChrome obj 873 * this.wc.removeHeaderMenus({ 874 * items: [{ 875 * itemId: 'regularMenu' 876 * }] 877 * }); 878 */ 879 removeHeaderMenus : function(cfg) { 880 var data = {}; 881 var items = null; 882 883 if (!owfdojo.isArray(cfg.items)) { 884 items = [cfg.items]; 885 } 886 else { 887 items = cfg.items; 888 } 889 890 data.action = 'removeHeaderMenus'; 891 data.type = 'menu'; 892 data.items = items; 893 for (var i = 0; i < items.length; i++) { 894 var id = items[i]; 895 if (scope.items[id] != null) { 896 //delete saved data 897 delete scope.items[id]; 898 } 899 } 900 901 var jsonString = gadgets.json.stringify(data); 902 gadgets.rpc.call('..', scope.channelName, cfg.callback, scope.widgetEventingController.getWidgetId(), jsonString); 903 }, 904 905 /** 906 * @description Lists all menus that have been added to the widget chrome. 907 * @param {Object} cfg config object see below for properties 908 * @param {Function} cfg.callback The function which receives the results. 909 * 910 * @example 911 * //this.wc is an already instantiated WidgetChrome obj 912 * this.wc.listHeaderMenus({ 913 * callback: function(msg) { 914 * //msg will always be a json string 915 * var res = Ozone.util.parseJson(msg); 916 * if (res.success) { 917 * for (var i = 0; i < res.items.length; i++) { 918 * // do something with the menus 919 * } 920 * } 921 * } 922 * }); 923 */ 924 listHeaderMenus: function(cfg) { 925 var data = { 926 action: 'listHeaderMenus', 927 type: 'menu' 928 }; 929 var jsonString = gadgets.json.stringify(data); 930 gadgets.rpc.call('..', scope.channelName, cfg.callback, scope.widgetEventingController.getWidgetId(), jsonString); 931 } 932 933 }; 934 935 pub.init(config); 936 Ozone.chrome.WidgetChrome.instance = pub; 937 } 938 return Ozone.chrome.WidgetChrome.instance; 939 }; 940 941 /** 942 * @description Retrieves Ozone.chrome.WidgetChrome Singleton instance. To do so it requires a widgetEventingController 943 * @param {Object} config - config object with parameters 944 * @param {Ozone.eventing.Widget} config.widgetEventingController - widget eventing object which handles eventing for the widget 945 * @example 946 * this.wc = Ozone.chrome.WidgetChrome.getInstance({ 947 * widgetEventingController: this.widgetEventingController 948 * }); 949 * 950 * @throws {Error} throws an error with a message if widget initialization fails 951 */ 952 Ozone.chrome.WidgetChrome.getInstance = function(cfg) { 953 if (Ozone.chrome.WidgetChrome.instance == null) { 954 Ozone.chrome.WidgetChrome.instance = new Ozone.chrome.WidgetChrome(cfg); 955 } 956 return Ozone.chrome.WidgetChrome.instance; 957 }; 958 959 960