1 /*global Ext document */ 2 /* 3 * Author: Sierk Hoeksma. WebBlocks.eu 4 * Copyright 2007-2008, WebBlocks. All rights reserved. 5 * 6 * This extension enables a panel to be directly created from Gui Designer Json 7 * Dependend JavaScripts are loaded using ScriptLoader function 8 ************************************************************************************ 9 * This file is distributed on an AS IS BASIS WITHOUT ANY WARRANTY; 10 * without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. 12 ************************************************************************************ 13 14 License: This source is licensed under the terms of the Open Source LGPL 3.0 license. 15 Commercial use is permitted to the extent that the code/component(s) do NOT become 16 part of another Open Source or Commercially licensed development library or toolkit 17 without explicit permission.Full text: http://www.opensource.org/licenses/lgpl-3.0.html 18 19 * Donations are welcomed: http://donate.webblocks.eu 20 */ 21 22 /** 23 * Override Ext.Panel so that scope of keymap is always set to object when not set, 24 * instead of window 25 */ 26 Ext.override(Ext.Panel,{ 27 // private 28 getKeyMap : function(){ 29 if(!this.keyMap){ 30 if(Ext.isArray(this.keys)){ 31 for(var i = 0, len = this.keys.length; i < len; i++){ 32 this.keys[i].scope = this.keys[i].scope || this; 33 } 34 } else if (this.keys && !this.keys.scope) this.keys.scope = this; 35 this.keyMap = new Ext.KeyMap(this.el, this.keys); 36 } 37 return this.keyMap; 38 } 39 }); 40 41 42 /** 43 * Override Ext.FormPanel so that in case whe create a form without items from a json 44 * it still has a item list. 45 */ 46 Ext.override(Ext.FormPanel, { 47 // private 48 initFields : function(){ 49 //BEGIN FIX It can happend that there is a form created without items (json) 50 this.initItems(); 51 //END FIX 52 var f = this.form; 53 var formPanel = this; 54 var fn = function(c){ 55 if(c.doLayout && c != formPanel){ 56 Ext.applyIf(c, { 57 labelAlign: c.ownerCt.labelAlign, 58 labelWidth: c.ownerCt.labelWidth, 59 itemCls: c.ownerCt.itemCls 60 }); 61 if(c.items){ 62 c.items.each(fn); 63 } 64 }else if(c.isFormField){ 65 f.add(c); 66 } 67 } 68 this.items.each(fn); 69 } 70 }); 71 72 /** 73 * A Synchronized Content loader for data from url 74 * @param {String} url The url to load synchronized 75 * @param {Boolean} cachingOff Should caching of file be disabled 76 * @param {Boolean} responseXML Should responseXML be returned instead of responseText 77 * @return {Boolean/String/XMLObject} When there was a error False otherwise response base on responseXML flag 78 */ 79 Ext.ux.SyncLoader = function(url,cachingOff,responseXML) { 80 var activeX = Ext.lib.Ajax.activeX; 81 var isLocal = (document.location.protocol == 'file:'); 82 var conn; 83 84 try { 85 if(Ext.isIE7 && isLocal){throw("IE7forceActiveX");} 86 conn = new XMLHttpRequest(); 87 } catch(e) { 88 for (var i = 0; i < activeX.length; ++i) { 89 try {conn = new ActiveXObject(activeX[i]); break;} catch(e) {} 90 } 91 } 92 //Should we disable caching 93 if (!cachingOff) 94 url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime()); 95 try { 96 conn.open('GET', url , false); 97 conn.send(null); 98 if ((isLocal && conn.responseText.length!=0) || (conn.status !== undefined && conn.status>=200 && conn.status< 300)) { 99 return responseXML ? conn.responseXML : conn.responseText; 100 } 101 } catch (e) {} 102 return false; 103 } 104 105 /** 106 * Function used to load a JavaScript into a document.head element 107 * the id of the script item is the name of the file. 108 * @param {String} url The url to load javascript from 109 * @param {Boolean} cachingOff Should caching of javascript files be disabled 110 * @return {Boolean} Indicator if load went corretly true/false 111 */ 112 Ext.ux.ScriptLoader = function(url,cachingOff) { 113 if(url && !document.getElementById(url)) { 114 var content = Ext.ux.SyncLoader(url,cachingOff); 115 if (content===false) return false; 116 var head = document.getElementsByTagName("head")[0]; 117 var script = document.createElement("script"); 118 try { 119 script.text = content; 120 } catch (e) { 121 script.appendChild(content); 122 } 123 script.setAttribute("type", "text/javascript"); 124 script.setAttribute("id", url); 125 head.appendChild(script); 126 } 127 return true; 128 } 129 130 131 /** 132 * A class used by JsonPanel and JsonWindow to load a jsonFile 133 */ 134 Ext.ux.Json = Ext.extend(Ext.util.Observable,{ 135 /** 136 * Boolean indicator when true loadMsg will be shown 137 @cfg */ 138 loadMask: true, 139 /** 140 * The loading message 141 @cfg */ 142 loadMsg: 'Loading...', 143 /** 144 * Mask used for loading message 145 @cfg */ 146 msgCls : 'x-mask-loading', 147 148 /** 149 * The string used to indent 150 * @type {String} 151 @cfg */ 152 indentString : ' ', 153 154 /** 155 * Array with items which should be blocked during init 156 * @type {Array} 157 @cfg */ 158 blockedJsonInit : ['items'], 159 160 /** 161 * Should caching be disabled when JSON are loaded (defaults false). 162 * @type {Boolean} 163 @cfg */ 164 disableCaching:false, 165 166 /** 167 * @private Tag added to json code so whe can see begining of code 168 */ 169 scriptStart : '/*BEGIN*/', 170 171 /** 172 * @private Tag added to json code so whe can see ending of code 173 */ 174 scriptEnd : '/*END*/', 175 176 /** 177 * The lisenceText that should be added to each JSON File Created 178 * @type {String} 179 @cfg */ 180 licenseText : '', 181 182 /** 183 * @private Indicator if object hasOwnProperty 184 */ 185 useHasOwn : ({}.hasOwnProperty ? true : false), 186 187 //@private The internal tag used to create unique, when null no id is generated 188 jsonId : null, 189 //@private Last id used to create json 190 lastJsonId : 0, 191 192 193 //@private The maximum number of json histories to keep 194 jsonHistoryMax : 0, 195 //@private The history for json 196 jsonHistory : [], 197 198 /** 199 * Add a json to the json history 200 * @param {String} json the json to add 201 */ 202 addJsonHistory : function(json) { 203 if (json) { 204 this.jsonHistory.push(json); 205 while (this.jsonHistory.length > this.jsonHistoryMax) 206 this.jsonHistory.remove(this.jsonHistory[0]); 207 } 208 }, 209 210 /** 211 * Get the last item from the json history 212 * @param {Boolean} keep Should history be untouched 213 * @return {String} The json 214 */ 215 getJsonHistory : function(keep) { 216 if (this.jsonHistory.length > 0) { 217 if (keep) return this.jsonHistory[this.jsonHistory.length-1]; 218 return this.jsonHistory.pop(); 219 } 220 return null; 221 }, 222 223 /** 224 * Load one or more javascripts. Is trigger by root element window.required_js in json file. 225 * The javascripts are synchonrized load before the JSON is evaluated. Base on the config item 226 * disableCaching (defaults true) the url of the javascript to load is made unique with parameter _dc. 227 * @param {String} list A comma seperated list of javascripts to load 228 */ 229 setRequired_js : function(list) { 230 if (!list) return; 231 var files = list.split(','); 232 for (var f=0;f<files.length;f++) { 233 if (!Ext.ux.ScriptLoader(files[f],this.disableCaching)) { 234 Ext.Msg.alert('Failure','Failed to load javascript '+ files[f]); 235 } 236 } 237 }, 238 239 /** 240 * Load one or more stylesheets. Is triggered by root element window.required_css in json file 241 * @param {String} list A comma seperated list of stylesheets to load 242 */ 243 setRequired_css : function(list) { 244 if (!list) return; 245 var files = list.split(','); 246 for (var f=0;f<files.length;f++) { 247 if(document.getElementById(files[f])) {continue;} 248 Ext.util.CSS.swapStyleSheet(files[f], files[f]); 249 } 250 }, 251 252 /** 253 * Added items to blockedJsonInit during jsonInit 254 * @param {Object} args A object indexed by xtype containing array of blocked keys 255 */ 256 setBlockedJsonInit : function(args){ 257 if (this.getXType && args) { 258 var val = args[this.getXType()]; 259 if (typeof val == 'object') { 260 for (var i=0;i<val.length;i++) this.blockedJsonInit.push(val[i]); 261 } else this.blockedJsonInit.push(val); 262 } 263 }, 264 265 /** 266 * Function called with config object of json file 267 * @param {Object} config The config object that can be applied 268 * @return {Boolean} indicator if all changes where set 269 */ 270 jsonInit : function (config,element,all,scopeOnly) { 271 var allSet = true, el = element || this; 272 if (config) { 273 for (var i in config) { 274 var j = i; 275 if (all || this.blockedJsonInit.indexOf(i) == -1) { 276 if (i=='required_js') { 277 this.setRequired_js(config[i]); 278 } else if (i=='required_css') { 279 this.setRequired_css(config[i]); 280 } else { 281 var applyTo = el; 282 //When scope of var set if 283 if (i.indexOf('scope.')==0) { 284 j = i.substring(6); 285 applyTo = this.getJsonScope(); 286 } else if (scopeOnly) continue; 287 var k = 'set' + j.substring(0,1).toUpperCase() + j.substring(1); 288 try { 289 if (applyTo[k] && typeof applyTo[k] == 'function') { 290 applyTo[k].call(el,config[i]); 291 } else if (applyTo[j] && typeof applyTo[j] == 'function') { 292 applyTo[j].call(el,config[i]); 293 } else { 294 applyTo[j] = config[i]; 295 } 296 } catch (e) { 297 allSet = false; 298 } 299 } 300 } 301 } 302 } 303 return allSet; 304 }, 305 306 /** 307 * Check if a object is empty 308 */ 309 isEmptyObject : function(obj) { 310 for (var i in obj) {if (i!=this.jsonId) return false;} 311 return true; 312 }, 313 314 /** 315 * Apply the Json to given element 316 * @param {Object/String} json The json to apply 317 * @param {Element} element The element to apply the json to 318 * @return {Object} The elements applied 319 */ 320 applyJson : function (json,element) { 321 var el = element || this; 322 try { 323 if (this.loadMask && el.ownerCt) el.ownerCt.el.mask(this.loadMsg, this.msgCls); 324 var items = this.jsonId ? this.editableJson(json) : json || {}; 325 if (typeof(items) !== 'object') items = this.decode(json); 326 if (items) { 327 //Apply global json vars to element 328 if (el instanceof Ext.Container) { 329 //Clear out orignal content of container 330 while (el.items && el.items.first()) {el.remove(el.items.first(), true);} 331 if (items instanceof Array) { 332 el.add.apply(el,items); 333 } else if (!this.isEmptyObject(items)) { 334 el.add(items); 335 } 336 } else { 337 this.jsonInit(items,el); 338 } 339 } 340 if (el.rendered && el.layout && el.layout.layout) el.doLayout(); 341 } catch (e) { 342 throw e; 343 } finally { 344 if (this.loadMask && el.ownerCt) el.ownerCt.el.unmask(); 345 } 346 return items; 347 }, 348 349 /** 350 * Convert a Json to a editableJson by adding an edtiableId when set 351 * @param {Object/String} json The json to add an id to 352 * @param {Object} id The id object used to give id 353 * @return {Object} The decoded object with id 354 */ 355 editableJson : function(json) { 356 var items = json || {}; 357 if (typeof(items) !== 'object') items = this.decode(json); 358 if (items instanceof Array) { 359 for (var i=0;i<items.length;i++) { 360 items[i]=this.editableJson(items[i]); 361 } 362 return items; 363 } 364 if (this.jsonId) { 365 if (!items[this.jsonId]) { 366 items[this.jsonId]=Ext.id(); 367 } 368 for (var k in items) { 369 if (k.indexOf(this.jsonId)==0 && k!=this.jsonId) { 370 var orgK = k.substring(this.jsonId.length); 371 if (orgK && typeof(items[orgK])=='undefined') items[orgK]=null; //Code is there but not key, create it 372 } else if (!items[this.jsonId + k ]) { 373 if (typeof(items[k]) == 'function') { 374 items[this.jsonId + k]=String(items[k]); 375 } else if (typeof(items[k]) == 'object' && k!='items') { 376 items[this.jsonId + k] = Ext.ux.JSON.encode(items[k]); 377 } 378 } 379 } 380 if (items.items) items.items=this.editableJson(items.items); 381 } 382 return items; 383 }, 384 385 /** 386 * @private Encode a string to Json 387 * @param {String} s The string to encode 388 * @return {String} A string containing the encode string 389 */ 390 encodeString : function(s){ 391 var m = {"\b": '\\b',"\t": '\\t',"\n": '\\n',"\f": '\\f',"\r": '\\r','"' : '\\"',"\\": '\\\\'}; 392 if (/["\\\x00-\x1f]/.test(s)) { //" 393 return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) { //" 394 var c = m[b]; 395 if(c){ return c; } 396 c = b.charCodeAt(); 397 return "\\u00" + 398 Math.floor(c / 16).toString(16) + 399 (c % 16).toString(16); 400 }) + '"'; 401 } 402 return '"' + s + '"'; 403 }, 404 405 /** 406 * @private Create a indent so code is readable 407 * @param {Int} n The indent length 408 * @return {String} A string containing n spaces 409 */ 410 indentStr : function(n) { 411 var str = "", i = 0; 412 while (i<n) { 413 str += this.indentString; 414 i++; 415 } 416 return str; 417 }, 418 419 /** 420 * @private Encode an Array to Json 421 * @param {Array} o The array to encode 422 * @param {Int} indent The indent to uses (defaults 0) 423 * @param {Boolean} notags Should code be wrapped between scriptStart and scriptEnd 424 * @return {String} The array encode as string 425 */ 426 encodeArray : function(o,indent,keepJsonId){ 427 indent = indent || 0; 428 var a = ["["], b, i, l = o.length, v; 429 for (var i = 0; i < l; i += 1) { 430 v = o[i]; 431 switch (typeof v) { 432 case "undefined": 433 case "unknown": 434 break; 435 default: 436 if (b) a.push(','); 437 a.push(v === null ? "null" : this.encode(v, indent + 1,keepJsonId)); 438 b = true; 439 } 440 } 441 a.push("]"); 442 return a.join(""); 443 }, 444 445 /** 446 * @private Encode a date to json 447 * @param {Date} o The date object to encode 448 * @return {String} The data encode as string 449 */ 450 encodeDate : function(o){ 451 var pad = function(n) { return n < 10 ? "0" + n : n; }; 452 return '"' + o.getFullYear() + "-" + 453 pad(o.getMonth() + 1) + "-" + 454 pad(o.getDate()) + "T" + 455 pad(o.getHours()) + ":" + 456 pad(o.getMinutes()) + ":" + 457 pad(o.getSeconds()) + '"'; 458 }, 459 460 /** 461 * Customer encode decode and recode, enabling reading and writing of JSON files with javascript code 462 * @param {Object} o The object to encode 463 * @param {Int} indent The indent to uses (defaults 0) 464 * @return {String} The object encode as string 465 */ 466 encode : function(o,indent,keepJsonId,noLicense){ 467 indent = indent || 0; 468 if(typeof o == "undefined" || o === null){ 469 return "null"; 470 }else if(o instanceof Array){ 471 return this.encodeArray(o, indent,keepJsonId); 472 }else if(o instanceof Date){ 473 return this.encodeDate(o); 474 }else if(typeof o == "number"){ 475 return isFinite(o) ? String(o) : "null"; 476 }else if(typeof o == "string" && !isNaN(o) && o!='' ){ 477 return o; 478 } else if(typeof o == "string" && ['true','false'].indexOf(o)!=-1){ 479 return o; 480 } else if(typeof o == "boolean") { 481 return String(o); 482 } else if(typeof o == "string"){ 483 return this.encodeString(o); 484 }else { 485 if (o.constructor) { 486 var c = ""+o.constructor; 487 c=c.substring(c.indexOf('function ')+9); 488 c=c.substring(0,c.indexOf('(')).replace(' '); 489 if (!c) { 490 b = ""+o.constructor; 491 var b=b.substring(0,b.indexOf('.superclass')); 492 for (var i=b.length-1;i>0;i--) { 493 if ([';',' ','\n','\t'].indexOf(b.substring(i,i+1))!=-1) { 494 c=b.substring(i+1); 495 i=-1; 496 } 497 } 498 if (c && o.initialConfig) { 499 return this.indentStr(indent) + this.scriptStart 500 + 'new '+ c + '(' + 501 this.encode(o.initialConfig,indent+1,keepJsonId) 502 + ') ' + this.scriptEnd; 503 } 504 } 505 if (['Array','Object','Date'].indexOf(c)== -1) { 506 return 'null /* Class ' + c + ' has no initialConfig */'; 507 } 508 } 509 var a = [], b, i, v; 510 //Check if whe should create a license text 511 if (indent==0 && !noLicense) { 512 if (this.licenseText) a.push(this.licenseText + "\n"); 513 } 514 a.push("{\n"); 515 for (var i in o) { 516 v = o[i]; 517 //Check if key (i) is an internal jsonId and original is empty then use this 518 if (i.indexOf(this.jsonId)==0 && (!keepJsonId || i!=this.jsonId)) { 519 var orgK = i.substring(this.jsonId.length); 520 if (orgK && typeof(o[orgK])=='undefined' && v) { 521 if(b) a.push(',\n'); 522 a.push(this.indentStr(indent), orgK, " : ", this.scriptStart,v,this.scriptEnd); 523 b = true; 524 } 525 continue; //internal id skip it during encode 526 } 527 //Create code for item 528 if(!this.useHasOwn || o.hasOwnProperty(i)) { 529 if (this.jsonId && o[this.jsonId + i]) { 530 if(b) a.push(',\n'); 531 a.push(this.indentStr(indent), i, " : ", this.scriptStart,o[this.jsonId + i],this.scriptEnd); 532 b = true; 533 } else { 534 switch (typeof v) { 535 case "undefined": 536 case "unknown": 537 break; 538 case "function": 539 if(b) a.push(',\n'); 540 a.push(this.indentStr(indent), i, " : ", this.scriptStart,""+v,this.scriptEnd); 541 b = true; 542 break; 543 case "object" : 544 case "string" : 545 if (!v) break; //Skip empty string and objects else default 546 default: 547 if(b) a.push(',\n'); 548 a.push(this.indentStr(indent), i, " : ", 549 v === null ? "null" : this.encode(v,indent + 1,keepJsonId)); 550 b = true; 551 } 552 } 553 } 554 } 555 a.push("\n" + this.indentStr(indent-1) + "}"); 556 return a.join(""); 557 } 558 }, 559 560 /** 561 * Decode json evaluating Json tag (required_js,required_css) returning all elements as string 562 * @param {String} value The string to decode 563 * @return {Object} The decoded object with string only 564 */ 565 decodeAsString : function(json) { 566 if (!json) return; 567 /* Encode all functions between begin and end as string enabling load of packages */ 568 var value = json 569 var v = '', s = value.indexOf(this.scriptStart); 570 var jsonStr; 571 while (s!=-1) { 572 jsonStr = ''; 573 e = value.indexOf(this.scriptEnd,s); 574 v += value.substring(0,s); 575 if (this.jsonId) { 576 var i = v.lastIndexOf(':')-1; 577 while (i>0 && [" ","\t","\n","\r"].indexOf(v.substring(i,i+1))>=0) {i--;} 578 var w = ''; 579 while (i>0 && [" ","\t","\n","\r","{","["].indexOf(v.substring(i,i+1))==-1) { 580 w = v.substring(i,i+1) + w; 581 i--; 582 } 583 jsonStr += ',' + this.jsonId + w + ' : ' + this.encodeString(value.substring(s+this.scriptStart.length,e)); 584 } 585 v += this.encodeString(value.substring(s+this.scriptStart.length,e)) + jsonStr; 586 value = value.substring(e+this.scriptEnd.length); 587 s=value.indexOf(this.scriptStart); 588 } 589 v += value; 590 var scope = this.getJsonScope(); 591 var items = eval("(" + v + ")"); 592 if(items && items.json) { 593 items.json = eval("(" + items.json + ")"); 594 this.jsonInit(items.json,null,null,true); 595 } 596 597 //When jsonId is set convert changed fields to jsonId+key=StringValue 598 return items; 599 }, 600 601 /** 602 * Function returning the scope to beused for the json 603 * @return {Object} 604 */ 605 getJsonScope : function(){ 606 return this.jsonScope || this.scope || this; 607 }, 608 609 /** 610 * Clean null elements from json object 611 */ 612 deleteJsonNull : function(json) { 613 return json; 614 var c=0; 615 for (var k in json) { 616 if(!this.useHasOwn || json.hasOwnProperty(k)) { 617 if (k=='items') { 618 if (json[k] instanceof Array) { 619 var n =[]; 620 for (var i=0,a=json[k];i<a.length;i++) { 621 var o = this.deleteJsonNull(a[i]); 622 if (o!=null) n.push(o); 623 } 624 json[k] = (n.length>0) ? n : null; //Was null but form crashed on it 625 } else json[k]=this.deleteJsonNull(json[k]); 626 } 627 if (json[k]===null) { 628 delete json[k]; 629 } else { 630 c++; 631 } 632 } 633 } 634 return c ? json : null; 635 }, 636 637 /** 638 * Decode json evaluating Json tag (required_js,required_css) 639 * @param {String} value The string to decode 640 * @return {Object} The decoded object 641 */ 642 decode : function(json) { 643 var applyJsonId=function(o,j) { 644 if (!this.jsonId) return o; 645 for (var i in o) { 646 if(!this.useHasOwn || o.hasOwnProperty(i)) { 647 if (i=='items') { 648 for (var k=0,len=o.items.length;k<len;k++){ 649 o.items[k] = applyJsonId(o.items[k],j.items[k]); 650 } 651 } 652 else if (j[this.jsonId+i]) { 653 o[this.jsonId+i] = j[this.jsonId+i]; 654 } 655 } 656 } 657 return o; 658 }.createDelegate(this); 659 this.addJsonHistory(json); 660 var items = this.decodeAsString(json); 661 //Now we can do decode by using eval setting scope 662 var scope = this.getJsonScope(); 663 items = applyJsonId(eval("(" + json + ")"),items); 664 if(items) this.jsonInit(items.json); 665 return items; 666 }, 667 668 /** 669 * Function used to clone a object 670 * @param {Object} o the object to be cloned 671 * @return {Object} The cloned object 672 */ 673 clone : function(o) { 674 return this.decode(this.encode(o)); 675 } 676 }); 677 678 /** 679 * Create global object 680 */ 681 Ext.ux.JSON = new Ext.ux.Json(); 682 683 /** 684 * Component extending a panel giving it the capability to read or create a JSON file. 685 * When using Json file created with designer this JsonPanel will also evaluate the special items 686 * under Json root called <b>winbow</b>. The JsonPanel currently evaluates two special window items 687 * called <i>required_js,required_css</i> that enable loading of javascripts and stylesheets directly from the json. 688 * 689 *<p>Example how to create a Json from a external file filling the browser:</p> 690 * <pre><code>new Ext.Viewport({ 691 items : new Ext.ux.JsonPanel({autoLoad:'json/designer.json'}), 692 layout: 'fit' 693 }).show();</code></pre> 694 *<p>Example how to (re)load a JsonPanel that is allready loaded:</p> 695 * <pre><code>this.load({url:'new url'});</code></pre> 696 * <p><b>IMPORTANT:</b>When you want use the JsonPanel to load a Json file in a local browser make sure that you include a 697 * local xhr package like <a href="http://extjs.com/forum/showthread.php?t=10672">localXHR</a> or any other 698 * to fix the problem of ExtJs not supporting Ajax from local file system</p> 699 * @type component 700 */ 701 Ext.ux.JsonPanel = Ext.extend(Ext.Panel,Ext.applyIf({ 702 703 //@private Layout is by default fit 704 layout: 'fit', 705 706 //@private Border is by default false 707 border: false, 708 709 //@private Whe only read a JSON file once 710 single:true, //only needed once 711 712 /** 713 * Array with items which should be blocked during init 714 * @type {Array} 715 @cfg */ 716 blockedJsonInit : ['alignTo','anchorTo','items'], 717 718 719 /** 720 * @private Init the JSON Panel making sure caching is set depending on disableCaching 721 */ 722 initComponent : function(){ 723 if (this.autoLoad) { 724 if (typeof this.autoLoad !== 'object') this.autoLoad = {url: this.autoLoad}; 725 if (typeof this.autoLoad['nocache'] == 'undefined') this.autoLoad['nocache'] = this.disableCaching; 726 } 727 Ext.ux.JsonPanel.superclass.initComponent.call(this); 728 729 this.addEvents({ 730 /** 731 * Fires after the jsonfile is retrived from server but before it's loaded in panel 732 * @event beforejsonload 733 * @param {Object} response The response object returned 734 * @param {Exception} e The exception when avialable 735 */ 736 'beforejsonload' : true, 737 /** 738 * Fires after panel the panel is loaded with new content 739 * @event afterjsonload 740 */ 741 'afterjsonload' : true, 742 /** 743 * Fires when loading of jsonfile fails 744 * @event afterjsonload 745 */ 746 'failedjsonload' : false 747 }); 748 }, 749 750 751 /** 752 * @private We override the render function of the panel, so that the updater.renderer is changed to accept JSON 753 * @param {Component} ct The component to render 754 * @param {Object} position A object containing the position of the component 755 */ 756 onRender : function(ct, position){ 757 Ext.ux.JsonPanel.superclass.onRender.call(this, ct, position); 758 var um = this.getUpdater(); 759 um.showLoadIndicator = false; //disable it. 760 um.on('failure',function(el, response){ 761 this.ownerCt.el.unmask(); 762 this.fireEvent('failedjsonload',response) 763 }.createDelegate(this)); 764 um.on('beforeupdate',function(el, url, params) { 765 if (this.loadMask && this.ownerCt) 766 this.ownerCt.el.mask(this.loadMsg, this.msgCls); 767 }.createDelegate(this)); 768 769 um.setRenderer({render: 770 function(el, response, updater, callback){ 771 //add item configs to the panel layout 772 //Load the code to check if we should javascripts 773 this.fireEvent('beforejsonload', response); 774 try { 775 this.applyJson(response.responseText); 776 this.fireEvent('afterjsonload'); 777 this.ownerCt.el.unmask(); 778 779 if(callback) {callback();} 780 } catch (e) { 781 this.ownerCt.el.unmask(); 782 if (!this.fireEvent('afterjsonload',response,e)) 783 Ext.Msg.alert('Failure','Failed to decode load Json:' + e) 784 } 785 }.createDelegate(this) 786 }); 787 } 788 789 },Ext.ux.JSON)); 790 //Register the panel 791 Ext.reg('jsonpanel', Ext.ux.JsonPanel); 792 793 794 /* FOR NOW WE COPY CODE TO ALSO HAVE A WINDOW, WE NEED TO FIND A SOLUTION */ 795 Ext.ux.JsonWindow = Ext.extend(Ext.Window,Ext.applyIf({ 796 797 //@private Window is hidden by moving X out of screen 798 x : -1000, 799 //@private Window is hidden by moving Y out of screen 800 y : -1000, 801 802 //@private Layout is by default fit 803 layout: 'fit', 804 805 //@private Border is by default false 806 border: false, 807 808 //@private Whe only read a JSON file once 809 single:true, //only needed once 810 811 /** 812 * @private Init the JSON Panel making sure caching is set depending on disableCaching 813 */ 814 initComponent : function(){ 815 if (this.autoLoad) { 816 if (typeof this.autoLoad !== 'object') this.autoLoad = {url: this.autoLoad}; 817 if (typeof this.autoLoad['nocache'] == 'undefined') this.autoLoad['nocache'] = this.disableCaching; 818 } 819 Ext.ux.JsonWindow.superclass.initComponent.call(this); 820 821 this.addEvents({ 822 /** 823 * Fires after the jsonfile is retrived from server but before it's loaded in panel 824 * @event beforejsonload 825 * @param {Object} response The response object returned 826 * @param {Exception} e The exception when avialable 827 */ 828 'beforejsonload' : true, 829 /** 830 * Fires after panel the panel is loaded with new content 831 * @event afterjsonload 832 */ 833 'afterjsonload' : true, 834 /** 835 * Fires when loading of jsonfile fails 836 * @event afterjsonload 837 */ 838 'failedjsonload' : false 839 }); 840 }, 841 842 setX : function(x) { 843 this.setPosition(x,this.y); 844 }, 845 846 setY : function(y) { 847 this.setPosition(this.x,y); 848 }, 849 850 setAlignTo : function(arg) { 851 this.alignTo(arg[0],arg[1],arg[2]); 852 }, 853 854 setAnchorTo : function(ar) { 855 this.anchorTo(arg[0],arg[1],arg[2],arg[3]); 856 }, 857 858 859 /** 860 * @private We override the render function of the panel, so that the updater.renderer is changed to accept JSON 861 * @param {Component} ct The component to render 862 * @param {Object} position A object containing the position of the component 863 */ 864 onRender : function(ct, position){ 865 Ext.ux.JsonWindow.superclass.onRender.call(this, ct, position); 866 var um = this.getUpdater(); 867 um.showLoadIndicator = false; //disable it. 868 um.on('failure',function(el, response){ 869 this.ownerCt.el.unmask(); 870 this.fireEvent('failedjsonload',response) 871 }.createDelegate(this)); 872 um.on('beforeupdate',function(el, url, params) { 873 if (this.loadMask && this.ownerCt) 874 this.ownerCt.el.mask(this.loadMsg, this.msgCls); 875 }.createDelegate(this)); 876 877 um.setRenderer({render: 878 function(el, response, updater, callback){ 879 //add item configs to the panel layout 880 //Load the code to check if we should javascripts 881 this.fireEvent('beforejsonload', response); 882 try { 883 this.applyJson(response.responseText); 884 this.fireEvent('afterjsonload'); 885 if(callback) {callback();} 886 } catch (e) { 887 if (!this.fireEvent('afterjsonload',response,e)) 888 Ext.Msg.alert('Failure','Failed to decode load Json:' + e) 889 } 890 }.createDelegate(this) 891 }); 892 } 893 894 },Ext.ux.JSON)); 895 896 //Register the window 897 Ext.reg('jsonwindow