1 /** 2 * @author Amit Kumar 3 * @date 02/27/2008 4 * @since 1.2M1 5 * @extends Workbench.component.Component 6 * @class Monk.component.ComparisonComponent 7 * @description This component displays various feature comparisons 8 */ 9 10 Ext.namespace('Ext.ux'); 11 Ext.ux.ErrorHandlingConnection = Ext.extend(Ext.data.Connection, { 12 timeout: 600000, 13 handleResponse : function(response){ 14 this.transId = false; 15 var options = response.argument.options; 16 response.argument = options ? options.argument : null; 17 18 var error = null; 19 if (response.getResponseHeader['Content-Type'].match(/text\/javascript/) != null) { 20 error = Ext.decode(response.responseText).error; 21 } else if (response.getResponseHeader['Content-Type'].match(/text\/html/) != null) { 22 var errorMatch = response.responseText.match(/<div id="error">(.*)<\/div>/); 23 if (errorMatch != null) error = errorMatch[1]; 24 }else if(response.getResponseHeader['Content-Type'].match(/text\/plain/) != null){ 25 // this assumes there are no text/plain content type 26 error=null; 27 }else { 28 var errorTest = response.responseXML.getElementsByTagName('error'); 29 if(errorTest==null){ 30 error="could not retrieve error message"; 31 }else{ 32 if (errorTest.length > 0) error = errorTest[0].firstChild.data; 33 } 34 } 35 36 if (error != null) { 37 Workbench.console.info('An error has occurred: '+error); 38 Monk.component.messenger.alert('MONK Workbench', 'An server error has occurred:<br/>'+error); 39 Workbench.component.manager.notify( 40 new Monk.event.ServerError({ 41 label: 'A server error has occurred: '+error 42 }), { 43 error: error, 44 url: this.url // the url we stored in beforerequest 45 } 46 ); 47 } else { 48 Ext.callback(options.success, options.scope, [response, options]); 49 } 50 51 this.fireEvent("requestcomplete", this, response, options); 52 Ext.callback(options.callback, options.scope, [options, true, response]); 53 } 54 }); 55 56 57 Monk.component.ComparisonComponent = function(args) { 58 59 this.searchParams ={'corpusCriterion':'eaf','limit':'1000','start':'0'}; 60 61 this.genreStore = new Ext.data.SimpleStore({ 62 fields: ['id','label'] 63 , data : [['*','All'], 64 ['play','Play'], 65 ["prose","Prose All"], 66 ["prose-sermon","--Sermon"], 67 ["prose-witchcraft","--Witchcraft"], 68 ["poetry","Poetry"], 69 ["fiction","Fiction"] 70 ] 71 }); 72 73 74 75 this.dunningFeatureRecord = new Ext.data.Record.create([ 76 {name : 'term', mapping : '@tag'}, 77 {name : 'freq_ref', mapping : '@freq_ref', type: 'float', 78 convert:function(value){var num = parseFloat(value);return num.toFixed(2)}}, 79 {name : 'count_ref', mapping : '@count_ref',type: 'float'}, 80 {name : 'freq_analysis', mapping : '@freq_analysis', type: 'float', 81 convert:function(value){var num = parseFloat(value);return num.toFixed(2)}}, 82 {name : 'count_analysis', mapping : '@count_analysis',type: 'float'}, 83 {name : 'score', mapping : '@score',type: 'float', 84 convert:function(value){var num = parseFloat(value);return num.toFixed(2)}}, 85 {name : 'score_scaled', mapping : '@score_scaled',type: 'float', 86 convert:function(value){var num = parseFloat(value);return num.toFixed(2)}} 87 ]); 88 89 90 this.dunningStore = new Ext.data.Store({ 91 proxy: new Ext.data.HttpProxy( 92 new Ext.ux.ErrorHandlingConnection({url: Monk.data.PROXY_URL + 'get/AnalyticsManager.compareFeaturesFrequencyDunning'}) 93 ), 94 reader: new Ext.data.XmlReader({record : 'ft'}, this.dunningFeatureRecord), 95 autoLoad: false, 96 sortInfo:{field: 'score', direction: "DESC"} 97 }); 98 99 100 this.tfidfStore = new Ext.data.JsonStore({ 101 url: Monk.data.PROXY_URL + 'get/FeatureSearchManager.compareFeaturesTfIdf', 102 root: 'features', 103 totalProperty: 'numFeatures', 104 id: 'tag', 105 fields: [ 106 {name: 'term', mapping: 'term'}, 107 {name: 'field', mapping: 'field'}, 108 {name: 'score', mapping: 'score', type: 'float'}, 109 {name: 'idf', mapping: 'idf', type: 'float'}, 110 {name: 'index_freq', mapping: 'index_freq', type: 'float'}, 111 {name: 'source_freq', mapping: 'source_freq', type: 'float'} 112 ], 113 baseParams: {maxFeatures : '-1', limit:20, feature:'lemma', onlyFeatures: true, minWordLen:5}, 114 listeners: { 115 beforeload: { 116 fn: function(store, options){ 117 store.baseParams = this.searchParams; 118 }, 119 scope: this 120 } 121 } 122 }); 123 124 125 this.featureRecord = new Ext.data.Record.create([ 126 {name : 'type', mapping : '@type'}, 127 {name : 'term', mapping : '@tag'}, 128 {name : 'freq', mapping : '@freq', type: 'float'}, 129 {name : 'count', mapping : '@count'} 130 ]); 131 132 this.featureStore = new Ext.data.Store({ 133 proxy: new Ext.data.HttpProxy( 134 new Ext.ux.ErrorHandlingConnection({url: Monk.data.PROXY_URL + 'get/AnalyticsManager.compareFeatures'}) 135 ), 136 reader: new Ext.data.XmlReader({record : 'ft'}, this.featureRecord), 137 autoLoad: false 138 }); 139 this.featureStore.proxy.on({load: { 140 fn: function(proxy, data, options){ 141 var nodes = Ext.DomQuery.select('chart', data.reader.xmlData); 142 if(nodes!=null){ 143 this.chartUrl = nodes[0].firstChild.data; 144 } 145 }, 146 scope: this 147 }}); 148 149 this.chartUrl = ''; 150 this.chartWin = null; 151 152 Monk.component.ComparisonComponent.superclass.constructor.call(this, args); 153 } 154 155 156 Workbench.extend(Monk.component.ComparisonComponent, Workbench.component.Component, { 157 label : "Feature Comparison", 158 description : "This component is for feature comparison", 159 "window" : this.window, 160 displayFeatureCirculationPeriodChart: function (searchParams, sm){ 161 Ext.get("feature_img").update('Loading...'); 162 var conn = new Ext.data.Connection(); 163 var featureValues= new Array(); 164 var featureGroupTypes = new Array(); 165 var records = sm.getSelections(); 166 for(record in records){ 167 if(records[record].data==null){ 168 break; 169 } 170 Workbench.console.info(records[record].data.term); 171 featureValues.push(records[record].data.term); 172 featureGroupTypes.push(records[record].data.type); // this is a misnomer -it is actually a group 173 } 174 this.searchParams.featureValues=featureValues; 175 this.searchParams.featureGroupTypes=featureGroupTypes; 176 177 conn.request({ 178 url: Monk.data.PROXY_URL+'get/AnalyticsManager.compareFeatureFrequency', 179 method: 'POST', 180 params: this.searchParams, 181 success: function(responseObject) { 182 var document = responseObject.responseXML; 183 var chartUrl = ''; 184 var nodes = Ext.DomQuery.select("chart", document); 185 if(nodes==null || nodes.length==0){ 186 // check for error node 187 var errorNode = Ext.DomQuery.select("error",document); 188 if(errorNode!=null){ 189 var message=errorNode[0].firstChild.data; 190 Ext.Msg.alert('Monk Workbench', 'Error trying to get feature frequency chart <br/>'+message); 191 return; 192 }else{ 193 Ext.Msg.alert('Monk Workbench', 'Error trying to get feature frequency chart <br/><b>Error '+response.status+'</b>: '+response.statusText); 194 } 195 } 196 if(nodes[0].firstChild==null){ 197 return; 198 } 199 chartUrl = nodes[0].firstChild.data; 200 201 Ext.get("feature_img").update('<img alt="Feature Frequency Graph" width="350" height="150" src="'+chartUrl+'"/>'); 202 }, 203 failure: function(response, options) { 204 Ext.Msg.alert('Monk Workbench', 'Error trying to get feature frequency chart <br/><b>Error '+response.status+'</b>: '+response.statusText); 205 } 206 }); 207 }, 208 displayTfIdfTermCirculationPeriodChart: function(searchParams, sm){ 209 Ext.get("tfidffeature_img").update('Loading...'); 210 var conn = new Ext.data.Connection(); 211 var featureValues= new Array(); 212 var featureGroupTypes = new Array(); 213 var records = sm.getSelections(); 214 for(record in records) { 215 if(records[record].data==null){ 216 break; 217 } 218 Workbench.console.info(records[record].data.term); 219 featureValues.push(records[record].data.term); 220 featureGroupTypes.push('combined'); // this is a misnomer -it is actually a group 221 } 222 this.searchParams.featureValues=featureValues; 223 this.searchParams.featureGroupTypes=featureGroupTypes; 224 this.searchParams.wordClass="*"; 225 conn.request({ 226 url: Monk.data.PROXY_URL+'get/AnalyticsManager.compareFeatureFrequency', 227 method: 'GET', 228 params: this.searchParams, 229 success: function(responseObject) { 230 var document = responseObject.responseXML; 231 var chartUrl = ''; 232 var nodes = Ext.DomQuery.select("chart", document); 233 234 if(nodes[0]==null){ 235 return; 236 } 237 238 if(nodes[0].firstChild==null){ 239 return; 240 } 241 if (nodes != null) chartUrl = nodes[0].firstChild.data; 242 243 Ext.get("tfidffeature_img").update('<img alt="TF IDF Feature Frequency Graph" width="350" height="150" src="'+chartUrl+'"/>'); 244 }, 245 failure: function(response, options) { 246 Ext.Msg.alert('Monk Workbench', 'Error trying to get feature frequency chart <br/><b>Error '+response.status+'</b>: '+response.statusText); 247 } 248 }); 249 }, 250 251 252 displayConcordance: function(word) { 253 var tabs = Ext.getCmp('tab-container'); 254 if (tabs.getItem('tab-'+word) != null) { 255 tabs.setActiveTab('tab-'+word); 256 } else { 257 var record = new Ext.data.Record.create([ 258 {name: 'id', mapping: '@id'}, 259 {name: 'title', mapping: 'title'}, 260 {name: 'numFound', mapping:'@numFound'}, 261 {name: 'author', mapping: function(record){ 262 return Ext.DomQuery.selectValue('@id', record.parentNode); 263 }}, 264 {name: 'circulation', mapping: '@start'}, 265 {name: 'concordances', mapping: function(record){ 266 var xmlArray = Ext.DomQuery.select('c', record); 267 var stringArray = []; 268 for (var i = 0, len = xmlArray.length; i < len; i++) { 269 var c = xmlArray[i]; 270 var string = ''; 271 string += c.firstChild.data; 272 string += '<span class="concordance">'+c.childNodes[1].firstChild.data+'</span>'; 273 string += c.lastChild.data; 274 stringArray.push(string); 275 } 276 if (stringArray.length == 0) { 277 return ['']; 278 } 279 return stringArray; 280 } 281 282 }, 283 {name:'showing' , mapping: function(record){ 284 var xmlArray = Ext.DomQuery.select('c', record); 285 return xmlArray.length; 286 } 287 } 288 289 ]); 290 /* var params = { 291 corpusCriterion: this.searchParams.corpusCriterion, 292 wordClass: this.searchParams.wordClass, 293 feature: this.searchParams.feature, 294 numMatchesPerDocument: 3, 295 format: 'xml', 296 featureValues: word 297 } 298 */ 299 var params = this.searchParams; 300 params.numMatchesPerDocument = 3; 301 params.format = 'xml'; 302 params.featureValues = word; 303 params.limit = 10; 304 delete params.start; 305 306 var concordanceStore = new Ext.data.Store({ 307 proxy: new Ext.data.HttpProxy({ 308 url: Monk.data.PROXY_URL + "get/FeatureSearchManager.getConcordance", 309 timeout: 50000, 310 method: 'GET' 311 }), 312 baseParams: params, 313 reader: new Ext.ux.XmlReader({record : 'doc', totalRecords: '@total'}, record), 314 listeners: { 315 beforeload: function() { 316 Ext.getCmp('tab-'+word).getEl().mask('Loading '+word+'...'); 317 }, 318 load: function() { 319 Ext.getCmp('tab-'+word).getEl().unmask(); 320 } 321 } 322 }); 323 324 var tab = tabs.add({ 325 id: 'tab-'+word, 326 title: 'Concordance: '+word, 327 closable: true, 328 autoScroll: true, 329 items: { 330 title: '', 331 border: false, 332 xtype: 'dataview', 333 tpl: new Ext.XTemplate( 334 '<font color="blue"><i>Click on the Work/Workpart to View the document.</i></font><hr/>', 335 '<tpl for=".">', 336 '<div class="concordance-item" id="{id}">', 337 '<div class="circulation">{circulation}</div>', 338 '<div class="header"><span class="title">{title}</span> by <span>{author}</span> <i>({numFound}) hits -showing {showing}</i></div>', 339 '<div class="concordances">', 340 '<tpl for="concordances"><div>{.}</div></tpl>', 341 '</div>', 342 '</div>', 343 '<hr/>', 344 '</tpl>' 345 ), 346 singleSelect: true, 347 overClass: 'x-view-over', 348 selectedClass: '', 349 itemSelector: 'div.concordance-item', 350 store: concordanceStore, 351 listeners: { 352 click: { 353 fn: function(dataview, index, node, event) { 354 var id = node.id; 355 var text = Ext.DomQuery.selectValue('span[class=title]', node); 356 this.notify(new Monk.event.toolflowmanager.OpenTool({ 357 label: 'Open tool: ChunkViewer' 358 }), 359 {id: 'chunk-viewer'} 360 ); 361 this.notify(new Monk.event.chunk.ChunkSelected({ 362 label: 'Work selected: '+'"'+text+'"' 363 }), 364 {id: id, text: text, chunkType: 'work', displayText:true} 365 ); 366 }, 367 scope: this 368 } 369 } 370 }, 371 tbar:[ 372 { 373 text:"Toggle show all", 374 tooltip: {title:'Toggle',text:'Show/Hide All the Concordance'}, 375 iconCls: 'toogle-icon', 376 handler:function(){ 377 var params = this.searchParams; 378 379 if( params.numMatchesPerDocument==-1) 380 params.numMatchesPerDocument = 3; 381 else 382 params.numMatchesPerDocument = -1; 383 384 params.format = 'xml'; 385 params.featureValues = word; 386 params.limit = 10; 387 concordanceStore.reload(); 388 }, 389 scope:this 390 } 391 ], 392 bbar: new Ext.PagingToolbar({ 393 store: concordanceStore, 394 pageSize: 10, 395 displayInfo: true, 396 displayMsg: 'Concordance {0} - {1} of {2}', 397 emptyMsg: 'No concordance found.' 398 }) 399 }); 400 tabs.setActiveTab(tab); 401 concordanceStore.load({params: {start: 0}}); 402 } 403 }, 404 getDunnings: function(){ 405 var dunningsBody = Ext.get('dunningsBody'); 406 var parent = dunningsBody.findParent('div.x-panel-body', 2, true); 407 parent.mask('Loading Dunnings...'); 408 409 var conn = new Ext.ux.ErrorHandlingConnection(); 410 conn.request({ 411 url: Monk.data.PROXY_URL+'get/AnalyticsManager.compareFeaturesFrequencyDunning', 412 method: 'POST', 413 scope:this, 414 params: this.searchParams, 415 success: function(responseObject, options) { 416 parent.unmask(); 417 var height = parent.getHeight(); 418 dunningsBody.setHeight(height); 419 dunningsBody.update(responseObject.responseText); 420 dunningsBody.scroll('up', dunningsBody.getScroll().top); 421 var links = Ext.DomQuery.select('a', dunningsBody.dom); 422 for (var i = 0, len = links.length; i < len; i++) { 423 var linkEl = links[i]; 424 Ext.EventManager.on(linkEl, 'click', function(event, el) { 425 event.preventDefault(); 426 var word = el.firstChild.data.replace(/\s/g, ''); 427 var type = el.getAttribute('class').split(' hi')[0]; 428 // handling for lemma 429 if (type != 'spelling') word += ' ('+type+')'; 430 this.displayConcordance(word); 431 }, this); 432 } 433 this.searchParams.format="xml"; 434 this.searchParams.formatType="xml"; 435 this.dunningStore.load({params: this.searchParams}); 436 437 }, 438 failure: function(response, options) { 439 parent.unmask(); 440 Ext.Msg.alert('Monk Workbench', 'Error trying to get dunnings.<br/><b>Error '+response.status+'</b>: '+response.statusText); 441 } 442 }); 443 }, 444 handle : function(monkEvent, data) { 445 if(monkEvent.instanceOf(Monk.event.workbench.AdvancedSearchQuery)){ 446 this.chartUrl = ''; 447 this.searchParams = data[0]; 448 this.searchParams.limit = 1000; 449 this.searchParams.start = 0; 450 }else if(monkEvent.instanceOf( Monk.event.workbench.WorksetFeatureComparison)){ 451 this.searchParams=data; 452 if(this.searchParams.method=="Dunnings" || this.searchParams.method=="Dunnings:swap"){ 453 this.searchParams.format = 'html'; 454 this.searchParams.formatType = 'html'; 455 /* 456 if(this.searchParams.firstComparisonCriterionAsReference){ 457 this.searchParams.firstComparisonCriterionAsReference=true; 458 }else{ 459 this.searchParams.firstComparisonCriterionAsReference=false; 460 } 461 */ 462 Ext.getCmp("tab-container").activate('dunningsPanel'); 463 this.getDunnings(); 464 465 }else if(this.searchParams.method=="FrequencyCount"){ 466 Ext.getCmp("tab-container").activate('frequencyComparisonPanel'); 467 this.featureStore.load({params: this.searchParams}); 468 }else if(this.searchParams.method=="SimilarFeatures" || 469 this.searchParams.method=="SimilarFeatures:swap"){ 470 Ext.getCmp("tab-container").activate('tfidfComparisonPanel'); 471 this.tfidfStore.load({params: this.searchParams}); 472 } 473 } else if (monkEvent.instanceOf(Monk.event.workbench.SimpleSearchQuery)) { 474 var query = data.featureValue.split(' (*)')[0]; 475 var tab = Ext.getCmp('tab-container').getActiveTab(); 476 switch (tab.id) { 477 case 'frequencyComparisonPanel': 478 this.filterGrid(query, Ext.getCmp('features-grid')); 479 break; 480 case 'dunningsPanel': 481 this.highlightLinks(query); 482 this.filterGrid(query,Ext.getCmp('dunningfeatures-grid')); 483 break; 484 case 'tfidfComparisonPanel': 485 this.filterGrid(query, Ext.getCmp('tfidffeatures-grid')); 486 break; 487 } 488 489 } else if (monkEvent.instanceOf(Monk.event.workbench.ClearSearch)){ 490 var tab = Ext.getCmp('tab-container').getActiveTab(); 491 switch (tab.id) { 492 case 'frequencyComparisonPanel': 493 this.clearFilter(Ext.getCmp('features-grid')); 494 break; 495 case 'dunningsPanel': 496 this.highlightLinks(''); 497 this.clearFilter(Ext.getCmp('dunningfeatures-grid')); 498 break; 499 case 'tfidfComparisonPanel': 500 this.clearFilter(Ext.getCmp('tfidffeatures-grid')); 501 break; 502 } 503 } 504 }, 505 506 filterGrid: function(query, grid) { 507 grid.getStore().filter('term', query, true, false); 508 }, 509 510 clearFilter: function(grid) { 511 grid.getStore().clearFilter(); 512 }, 513 514 exportItems: function(grid,list){ 515 var model=grid.getColumnModel(); 516 var output=[]; 517 var columnOutput =""; 518 for(var i=0; i < model.getColumnCount();i++){ 519 output[i]=model.getColumnHeader(i); 520 } 521 output = output.join("\t")+"\n"; 522 grid.getStore().each(function(record) { 523 var values=[]; 524 for (c in list){ 525 values.push(record.get(list[c])); 526 } 527 output+=values.join("\t") + "\n"; 528 529 }, this); 530 531 Monk.component.messenger.show({ 532 title: 'Export Features as Tab Separated Values (TSV)', 533 msg: 'Select all the data below, copy, and paste directly into your favourite spreadsheet program.', 534 width: 600, 535 defaultTextHeight: 25, 536 buttons: Ext.MessageBox.OK, 537 multiline: true, 538 value: output, 539 scope: this 540 }, this.window.parent ? this.window.parent.window : this.window); 541 542 543 }, 544 545 highlightLinks: function(query, cls) { 546 if (query == '') query = '^$'; // clears selections 547 var re = new RegExp(query,'gi'); 548 var links = Ext.DomQuery.select('a', Ext.get('dunningsBody').dom); 549 var firstHighlight = true; 550 for (var i = 0, len = links.length; i < len; i++) { 551 var link = Ext.get(links[i]); 552 if (link.dom.innerHTML.search(re) != -1) { 553 link.addClass('hi'); 554 if (firstHighlight) { 555 link.scrollIntoView(Ext.get('dunningsBody')); 556 firstHighlight = false; 557 } 558 } else { 559 link.removeClass('hi'); 560 } 561 } 562 }, 563 564 beforeExit: function() { 565 // destroy the results grid and remove any listeners it might have set 566 var results = Ext.getCmp('features-grid'); 567 results.getStore().purgeListeners(); 568 results.destroy(); 569 570 var results1 = Ext.getCmp('tfidffeatures-grid'); 571 results1.getStore().purgeListeners(); 572 results1.destroy(); 573 574 var results2 = Ext.getCmp('dunningfeatures-grid'); 575 results2.getStore().purgeListeners(); 576 results2.destroy(); 577 578 579 }, 580 581 init: function(){ 582 583 this.notify( 584 new Monk.event.view.ShowSearchOption({label: 'Show Search Option'}) 585 ); 586 587 this.notify( 588 new Monk.event.view.HideAdvancedSearchLink({label: 'Hide Advanced Search Link'}) 589 ); 590 591 592 var selectionModel = new Ext.grid.RowSelectionModel({ 593 singleSelect: true 594 }); 595 596 // create the feature Grid 597 var dunningGrid = new Ext.grid.GridPanel({ 598 id: 'dunningfeatures-grid', 599 region: 'west', 600 minWidth: 245, 601 width: 300, 602 autoScroll: true, 603 split: true, 604 tbar:[{ 605 iconCls: 'exportBtn', 606 text: 'Export Features', 607 handler: function(button, even){this.exportItems(dunningGrid,['term','score','score_scaled', 608 'freq_analysis','freq_ref',"count_analysis","count_ref"])}, 609 scope:this 610 }], 611 loadMask: {msg: 'Loading features, please wait.'}, 612 store: this.dunningStore, 613 sm: new Ext.grid.RowSelectionModel({ 614 singleSelect: true, 615 listeners: { 616 rowselect: { 617 fn: function(sm,rowindex,record) { 618 }, scope: this 619 } 620 } 621 }), 622 columns: [ 623 {id:'term',header: "Term", width: 60, sortable: true, dataIndex: 'term'}, 624 {header: "score", width: 60, sortable: true, dataIndex: 'score',type: 'float'}, 625 {header: "score_scaled", width: 60, hidden:true,sortable: true, dataIndex: 'score_scaled',type: 'float'}, 626 {header: "#Ref", width: 60, sortable: true, dataIndex: 'freq_analysis',type: 'float'}, 627 {header: "#Analysis", width: 60, sortable: true, dataIndex: 'freq_ref',type: 'float'}, 628 {header: "Ref", width: 60, sortable: true, dataIndex: 'count_analysis',type: 'float'}, 629 {header: "Analysis", width: 60, sortable: true, dataIndex: 'count_ref',type: 'float'} 630 ], 631 stripeRows: true, 632 title:'Dunning Features', 633 listeners: { 634 rowclick:function(grid,rowIndex,event){ 635 636 } 637 638 639 } 640 }); 641 642 643 644 645 // create the feature Grid 646 var tfidfGrid = new Ext.grid.GridPanel({ 647 id: 'tfidffeatures-grid', 648 region: 'west', 649 minWidth: 245, 650 width: 300, 651 autoScroll: true, 652 split: true, 653 loadMask: {msg: 'Loading features, please wait.'}, 654 store: this.tfidfStore, 655 tbar:[{ 656 iconCls: 'exportBtn', 657 text: 'Export Features', 658 handler: function(button, even){this.exportItems(tfidfGrid,['term','score','idf', 659 'index_freq','source_freq'])}, 660 scope:this 661 }], 662 sm: new Ext.grid.RowSelectionModel({ 663 singleSelect: false, 664 listeners: { 665 rowselect: { 666 fn: function(sm,rowindex,record) { 667 this.displayTfIdfTermCirculationPeriodChart(this.searchParams, sm); 668 }, scope: this 669 } 670 } 671 }), 672 columns: [ 673 {id:'term',header: "Term", width: 60, sortable: true, dataIndex: 'term'}, 674 {header: "score", width: 60, sortable: true, dataIndex: 'score',type: 'float'}, 675 {header: "idf", width: 60, sortable: true, dataIndex: 'idf',type: 'float'}, 676 {header: "#Test", width: 60, sortable: true, dataIndex: 'index_freq',type: 'float'}, 677 {header: "#Train", width: 60, sortable: true, dataIndex: 'source_freq',type: 'float'} 678 ], 679 stripeRows: true, 680 // autoExpandColumn: 'term', 681 // viewConfig: {forceFit: true}, 682 // autoWidth: true, 683 title:'Features', 684 // bbar: featureListPagingBar, 685 listeners: { 686 rowclick:function(grid,rowIndex,event){ 687 var record = grid.getSelectionModel().getSelected(); 688 var featureInstance = record.get('term'); 689 var posTest = /\(.+?\)$/; 690 var type="spelling"; 691 if (featureInstance.match(posTest)) { 692 type="lemma"; 693 }else{ 694 type="spelling"; 695 } 696 697 var params = { 698 term: featureInstance, 699 type: type 700 }; 701 702 Workbench.component.manager.notify(new Monk.event.chunk.FeatureSelected({ 703 label: 'Text feature selected: '+'"'+featureInstance+'"' 704 }), params); 705 706 707 708 } 709 } 710 }); 711 712 713 function doHeight() { 714 var h = Ext.getCmp('viewport').getBox().height; 715 var tabs = Ext.getCmp('tab-container'); 716 tabs.setHeight(h); 717 var dunningsBody = Ext.get('dunningsBody'); 718 if (dunningsBody) { 719 var height = dunningsBody.findParent('div.x-panel-body', 2, true).getHeight(); 720 dunningsBody.setHeight(height); 721 } 722 } 723 724 this.viewport = new Ext.Viewport({ 725 id: 'viewport', 726 layout: 'fit', 727 renderTo: 'container', 728 items: { 729 730 items: { 731 732 733 id: 'tab-container', 734 xtype: 'tabpanel', 735 activeTab: 0, 736 autoWidth: true, 737 layoutOnTabChange: true, 738 border: false, 739 listeners: { 740 tabchange: doHeight 741 }, 742 items:[{ 743 xtype: 'panel', 744 tbar:[{ 745 text: 'Summary', 746 tooltip: {title:'Vocabulary Summary',text:'Display Vocabulary Summary'}, 747 iconCls: 'summary-icon', 748 handler: function(button, event){ 749 if (this.chartUrl == '') { 750 751 } else { 752 if (this.chartWin == null) { 753 this.chartWin = new Ext.Window({ 754 title: 'Summary (Venn Diagram)', 755 width: 420, 756 height: 240, 757 closeAction: 'hide', 758 modal: false, 759 plain: true, 760 border: false, 761 items: { 762 border: false, 763 html: '<div id="chart_img"></div>' 764 } 765 }); 766 } 767 this.chartWin.on('show', function(){ 768 Ext.get('chart_img').update('<img alt="Venn Diagram" src="'+this.chartUrl+'"/>'); 769 }, this, {single: true}); 770 this.chartWin.show(button.getEl()); 771 } 772 }, 773 scope: this 774 }, 775 { 776 iconCls: 'exportBtn', 777 text: 'Export Features', 778 handler: function(button, event){this.exportItems(Ext.getCmp("features-grid"), 779 ['term','count', 780 'freq','type'] 781 ) 782 }, 783 scope:this 784 } 785 786 ], 787 id: 'frequencyComparisonPanel', 788 title: 'Frequency Comparison', 789 layout: 'border', 790 border: false, 791 items: [{ 792 xtype: 'grid', 793 id: 'features-grid', 794 title: 'Features', 795 region: 'west', 796 minWidth: 245, 797 width: 300, 798 autoScroll: true, 799 split: true, 800 store: this.featureStore, 801 loadMask: {msg: 'Loading features, please wait.'}, 802 columns: [ 803 {header: "Feature", width: 100, dataIndex: 'term', renderer: function(value, metadata, record){ 804 var type = record.data.type; 805 if (type=="group1") metadata.attr = 'style = "background-color:#9C9CDB;"'; 806 else if(type=="group2") metadata.attr = 'style = "background-color:#8BA353;"'; 807 return value; 808 }, sortable:true}, 809 {header: "Count", width: 50, dataIndex: 'count', sortable:true}, 810 {header: "Frequency", width: 70, dataIndex: 'freq', renderer: function(value, metadata, record){ 811 var num = parseFloat(value); 812 return num.toFixed(4); 813 }, sortable:true}, 814 {header: "Type", width: 55, dataIndex: 'type', sortable:true, hidden:false} 815 ], 816 sm: new Ext.grid.RowSelectionModel({ 817 singleSelect: false, 818 listeners: { 819 rowselect: { 820 fn: function(sm,rowindex,record) { 821 this.displayFeatureCirculationPeriodChart(this.searchParams, sm); 822 }, scope: this 823 } 824 } 825 }) 826 },{ 827 title: 'Frequency Graph', 828 region: 'center', 829 split: true, 830 //collapsible: true, 831 minWidth: 400, 832 width: 400, 833 autoScroll: false, 834 // bodyStyle: 'padding: 5px;', 835 html: '<div id="feature_img" style=""></div>' 836 }] 837 },{ 838 xtype: 'panel', 839 id: 'dunningsPanel', 840 title: 'Dunnings', 841 layout: 'border', 842 border: false, 843 items: [ 844 dunningGrid, 845 { 846 title: 'Cloud', 847 region: 'center', 848 split: true, 849 collapsible: true, 850 minWidth: 400, 851 width: 400, 852 autoScroll: true, 853 border: false, 854 html: '<div id="dunningsBody"></div>', 855 bodyStyle: 'padding: 5px;' 856 } 857 ] 858 }, 859 { 860 xtype: 'panel', 861 id: 'tfidfComparisonPanel', 862 title: 'TF IDF Comparison', 863 layout: 'border', 864 border: false, 865 items: [ 866 tfidfGrid, 867 { 868 title: 'Frequency Graph', 869 region: 'center', 870 split: true, 871 //collapsible: true, 872 minWidth: 400, 873 width: 400, 874 autoScroll: true, 875 bodyStyle: 'padding: 5px;', 876 html: '<div id="tfidffeature_img"></div>' 877 }] 878 } 879 880 881 ] 882 } 883 } 884 }); 885 886 887 888 889 890 Ext.getCmp("tab-container").activate('tfidfComparisonPanel'); 891 Ext.getCmp("tab-container").activate('dunningsPanel'); 892 Ext.getCmp("tab-container").activate('frequencyComparisonPanel'); 893 894 } // end init function 895 896 }); 897