1if(!window.APPLICATION) { // Prevent re-inclusion .. 2/** 3 * solid application settings 4 */ 5var Application = function() { 6 var contextPath; 7 var logoutSettings = { 8 solidLogoutUrl:'', 9 solidRedirectUrl:'', 10 bcvLogoutUrl:'' 11 }; 12 13 return { 14 init: function(ctxPath) { 15 contextPath = ctxPath; 16 }, 17 contextPath: function() { 18 return contextPath; 19 }, 20 logoutSettings:function(){ 21 return logoutSettings; 22 } 23 } 24}(); 25Solid = (function ($) { 26 return { 27 contextPath: Application.contextPath(), 28 decorateCSRF: function(object) { 29 object[$("meta[name='_csrf_param']").attr("content")] = $("meta[name='_csrf']").attr("content"); 30 return object; 31 }, 32 decorateCSRFHeader: function(object) { 33 object[$("meta[name='_csrf_header']").attr("content")]= $("meta[name='_csrf']").attr("content"); 34 return object; 35 }, 36 initElasticSearchChart: function (finCharts, containerId) { 37 $("#" + containerId + "-searchParams").solidFastSearch({ 38 query:{ 39 fields: "M_NAME,M_SYMB,M_ISIN,M_MARKET:value:description,SC_GROUPED:value:description,M_CUR:value:description,MIC,EUSIPA,DOMICILE,M_BC", 40 flavor: "EQU,OPT,BON,IND", 41 size: 2, 42 mainMarket:false, 43 useWildcards: false 44 }, 45 action: function(context) { 46 if (context.highlighted) { 47 var listingId = context.highlighted.data('listing'); 48 if (listingId) { 49 finCharts.addOverlay(listingId); 50 } 51 } 52 }, 53 useFieldWidth: false 54 }).closest('td').next().contents().hide(); 55 }, 56 manageLogin: function (vToHost) { 57 $('.nav-link.btn.btn-header.login').on('click', function(){ 58 59 $.ajax({ 60 url: vToHost + '/sso/username', 61 dataType: 'text', 62 success: function (userID) { 63 if (userID) { 64 $("#sessionAlive").fadeIn(); 65 $("#sessionAlive p:first").append(userID); 66 $("#premiun").hide(); 67 } 68 // Nothing on error 69 } 70 }); 71 }); 72 }, 73 initClockDisplay: function (iterationClass) { 74 var panels = $(".marketInfo div.tab-content div.tab-pane ." + iterationClass); 75 panels.each(function() { 76 var data = $(this).data(); 77 var clock = $(this).find('.bcClock'); 78 clock.clock({ 79 data: { 80 bc: data.symbol, 81 name: data.name, 82 bcOpen: (data.breakfrom && data.breakto) ? [data.open, data.breakto] : data.open, 83 bcClose: (data.breakfrom && data.breakto) ? [data.breakfrom, data.close] : data.close, 84 offsetUTC: data.utc, 85 offsetDST: data.dst, 86 isOpen: data.isopen 87 }, 88 bcTime: true 89 }); 90 }); 91 }, 92 initElasticSearch: function (relativeUrl, inputId) { 93 var inputField = $("#" + inputId); 94 var inputFieldGroup = inputField.closest('.input-group'); 95 inputField.solidFastSearch({ 96 query: { 97 flavor: "EQU,IND,BON,ETF,FON,TFO,CUR,COM,INT,OPT,DER,FUT,TER,CTR,DIV", 98 fields: "M_NAME,M_SYMB,M_ISIN,LVAL:value:datetime,NC2_PR_NORM:value,M_MARKET:value:description,SC_GROUPED:value:description,M_CUR:value:description,MOST_LIQUID,MIC,EUSIPA,DOMICILE,M_BC", 99 mainMarket: false, 100 useWildcards: true, 101 size: 15 102 }, 103 alignElement: inputFieldGroup.length ? inputFieldGroup : null 104 }); 105 }, 106 initPortfolioElasticSearch: function (relativeUrl, inputId) { 107 var inputField = $("#" + inputId); 108 var inputFieldGroup = inputField.closest('.input-group'); 109 inputField.solidFastSearch({ 110 query: { 111 flavor: "EQU,IND,BON,ETF,FON,TFO,CUR,COM,INT,OPT,DER,FUT,TER,CTR,DIV", 112 fields: "M_NAME,M_SYMB,M_ISIN,M_MARKET:value:description,SC_GROUPED:value:description,M_CUR:value:description,MOST_LIQUID,MIC,EUSIPA,DOMICILE,M_BC", 113 mainMarket: false, 114 useWildcards: true, 115 size: 15 116 }, 117 action: function(context) { 118 if (context.highlighted) { 119 var listingId = context.highlighted.data('listing'); 120 if (listingId) { 121 var a = $("#portfolioId"); 122 var url = Application.contextPath() + "/portfolio/add/instrumentToThisPortfolio/" + a.val() + "/" + listingId +"?context=show"; 123 var title = a.data('title'); 124 var loadingText = a.data('loading-text') || ''; 125 var ajaxOptionsName = a.data('ajax-options') || ''; 126 var dialogOptions = dialogOptions = {}; 127 var ajaxOptions = window[ajaxOptionsName]; 128 if (!ajaxOptions) { 129 ajaxOptions = { 130 error: function(jqXHR, textStatus, errorThrown) {
131 this.find('.modal-body').text(errorThrown); 132 } 133 }; 134 } 135 window.location = Application.contextPath() + "/portfolio/add/instrumentToThisPortfolio/" + $("#portfolioId").val() + "/" + listingId +"?context=show"; 136 } 137 } 138 }, 139 template:'quicksearch/result', 140 errorTemplate:'quicksearch/error', 141 alignElement: inputFieldGroup.length ? inputFieldGroup : null 142 }); 143 }, 144 initDynMenuTransactionnals: function() { 145 146 /* Define the element that will react on click */ 147 var $dynItem = $('a.dyn-item.nav-link'); 148 149 /* Proceed only when all the mandatory elements are defined */ 150 if($dynItem && $dynItem.length > 0){ 151 /* React when clicking on the dyn Item*/ 152 $dynItem.on('click', function(e){ 153 e.preventDefault(); 154 e.stopImmediatePropagation(); 155 156 var $this = $(this), 157 menu = $this.data("menu"); 158 159 var $navsecond = $('#dynMenu'); 160 161 // remove all elements 162 $('#dynMenu li.dyn-item.nav-item').remove(); 163 164 // append html from div layer! 165 $navsecond.append($('#menu' + menu).html()); 166 }) 167 } 168 }, 169 checkURLDocument: function(event, url) { 170 event.preventDefault(); 171 var documentCheck = $().trading().checkURLDocument(url); 172 $.when(documentCheck).done(function(data){ 173 window.open(url, '_blank').focus(); 174 }); 175 }, 176 getDocumentsFromBCV: function(isin) { 177 var documentsDerivatives = $().trading().documentsFromBCV(isin); 178 $.when(documentsDerivatives).done(function(data){ 179 if(data !== undefined && data.length !== undefined && data.length > 0) { 180 var lang = document.documentElement.lang; 181 if(lang.indexOf("_") >= 0){ 182 lang = lang.split('_', 1)[0]; 183 } 184 var mainLanguage = null; 185 var langEn = false; 186 var langFr = false; 187 var langDe = false; 188 data.forEach(function (op, index) { 189 if (op.documentType == 'PRIIP' && op.source == 'SIXDOCHUB') { // if is not PRIIP is a termsheet, that we musn't take account 190 var langDocument; 191 if (op.language == 1) { 192 langEn = true; 193 langDocument = 'en'; 194 $('.' + langDocument + '_docs_sub').attr("onclick", "Solid.checkURLDocument(event,'" + $().trading().documentsFromBCVGet() + op.disseminationRecipient + "')"); 195 $('.' + langDocument + '_docs_sub').attr("href", "#"); 196 } 197 if (op.language == 2) { 198 langFr = true; 199 langDocument = 'fr'; 200 $('.' + langDocument + '_docs_sub').attr("onclick", "Solid.checkURLDocument(event,'" + $().trading().documentsFromBCVGet() + op.disseminationRecipient + "')"); 201 $('.' + langDocument + '_docs_sub').attr("href", "#"); 202 } 203 if (op.language == 3) { 204 langDe = true; 205 langDocument = 'de'; 206 $('.' + langDocument + '_docs_sub').attr("onclick", "Solid.checkURLDocument(event,'" + $().trading().documentsFromBCVGet() + op.disseminationRecipient + "')"); 207 $('.' + langDocument + '_docs_sub').attr("href", "#"); 208 } 209 if (langDocument == lang) { 210 mainLanguage = lang; 211 $('#' + langDocument + '_docs').attr("href", "#"); 212 $('#' + langDocument + '_docs').show(); 213 $('#spinnerDocument').hide(); 214 $('.' + langDocument + '_docs_sub').attr("onclick", "Solid.checkURLDocument(event,'" + $().trading().documentsFromBCVGet() + op.disseminationRecipient + "')"); 215 $('.' + langDocument + '_docs_sub').attr("href", "#"); 216 } 217 } 218 }); 219 if (!langEn || !langFr || !langDe) { 220 data.forEach(function (op, index) { 221 if (op.documentType == 'KIDS' && op.source == 'STRUCTURES_BCV') { 222 var langDocument; 223 url = op.linkUrl; 224 if (op.language == 1 && !langEn) { 225 langEn = true; 226 langDocument = 'en'; 227 $('.' + langDocument + '_docs_sub').attr("onclick", "Solid.checkURLDocument(event,'" + url + "')"); 228 $('.' + langDocument + '_docs_sub').attr("href", "#"); 229 } 230 if (op.language == 2 && !langFr) { 231 langFr = true; 232 langDocument = 'fr'; 233 $('.' + langDocument + '_docs_sub').attr("onclick", "Solid.checkURLDocument(event,'" + url + "')"); 234 $('.' + langDocument + '_docs_sub').attr("href", "#"); 235 } 236 if (op.language == 3 && !langDe) { 237 langDe = true; 238 langDocument = 'de'; 239 $('.' + langDocument + '_docs_sub').attr("onclick", "Solid.checkURLDocument(event,'" + url + "')"); 240 $('.' + langDocument + '_docs_sub').attr("href", "#"); 241 } 242 if (langDocument == lang) { 243 mainLanguage = lang; 244 $('#' + langDocument + '_docs').attr("href", "#"); 245 $('#' + langDocument + '_docs').show(); 246 $('#spinnerDocument').hide(); 247 $('.' + langDocument + '_docs_sub').attr("onclick", "Solid.checkURLDocument(event,'" + url + "')"); 248 $('.' + langDocument + '_docs_sub').attr("href", "#"); 249 } 250 } 251 }); 252 } 253 if (mainLanguage == null) { 254 var fallbackDoc = null; 255 for (var i = 0; i < data.length; i++) { 256 var op = data[i]; 257 if (op !== undefined && op.language !== undefined && op.language != null) { 258 if (op.language == 1 || op.language == 2 || op.language == 3) { 259 fallbackDoc = op; 260 break; 261 } 262 } 263 } 264 if (fallbackDoc != null) { 265 var langAux = fallbackDoc.language; 266 var langFirst = ''; 267 if (langAux == 1) { 268 langFirst = 'en'; 269 } 270 if (langAux == 2) { 271 langFirst = 'fr'; 272 } 273 if (langAux == 3) { 274 langFirst = 'de'; 275 } 276 $('#spinnerDocument').hide(); 277 $('#' + langFirst + '_docs').attr("onclick", "Solid.checkURLDocument(event,'" + $().trading().documentsFromBCVGet() + fallbackDoc.disseminationRecipient + "')"); 278 $('#' + langFirst + '_docs').attr("href", "#"); 279 $('#' + langFirst + '_docs').show(); 280 $('.' + langFirst + '_docs_sub').attr("href", "#"); 281 $('.' + langFirst + '_docs_sub').attr("onclick", "Solid.checkURLDocument(event,'" + $().trading().documentsFromBCVGet() + fallbackDoc.disseminationRecipient + "')"); 282 } 283 } 284 // hide anchor if some of languages doesn't exist 285 if(!langDe) { 286 $('.de_docs_sub').hide(); 287 } 288 if(!langEn) { 289 $('.en_docs_sub').hide(); 290 } 291 if(!langFr) { 292 $('.fr_docs_sub').hide(); 293 } 294 if(!langEn && !langFr && !langDe){ // if the source is STRUCTURES_BCV structuredproducts(non BCV) that has no PRIIP 295 $('#textDocument').show(); 296 $('#kiidTextWarning').show(); 297 $('#spinnerDocument').hide(); 298 data = []; 299 } 300 } 301 else{ 302 $('#textDocument').show(); 303 $('#kiidTextWarning').show(); 304 $('#spinnerDocument').hide(); 305 } 306 307 308 }).fail(function (xhr) { 309 console.log("No documents from bcv. Code error from service: " + xhr.status); 310 $('#textDocument').show(); 311 $('#kiidTextWarning').show(); 312 $('#spinnerDocument').hide(); 313 }); 314 }, 315 initUserInformation: function(time) { 316 317 /* Define the element that will react on click */ 318 var $userName = $('#userName'); 319 320 /* Proceed only when all the mandatory elements are defined */ 321 // if ($userName && $userName.length > 0 ) { 322 var me = {}; 323 /* React when clicking on the dyn Item*/ 324 var ajaxMe = $().trading().me(); 325 $.when(ajaxMe).then(function(dataMe) { 326 me = dataMe; 327 console.log("User information: ", me); 328 if (me == false) { 329 // if the user information is not loading, we must remove sessionstorage and refresh the page 330 // and it will work. 331 sessionStorage.removeItem('userSession'); 332 sessionStorage.removeItem('attributes'); 333 sessionStorage.removeItem('noAttributes'); 334 sessionStorage.removeItem('attributesJSON'); 335 time = time + time; 336 if(window.location.href != null && !window.location.href.includes('localhost')) { 337 setTimeout(function () { 338 Solid.initUserInformation(time); 339 }, time); 340 } 341 } 342 else { 343 if (me.person !== undefined && me.person.short
343Name !== undefined) { 344 $userName.html(me.person.shortName); 345 346 /* Checks if we must add the user name and account into containers (user preferences) */ 347 var $userAccountElem = $('span#trading-user-account'); 348 var $userNameElem = $('span#trading-user-name'); 349 350 if ($userAccountElem && $userNameElem) { 351 $userAccountElem.text(me.userName); 352 $userNameElem.text(me.person.shortName); 353 } 354 } 355 356 if (me.qualifiers !== undefined && $.isArray(me.qualifiers)) { 357 const $corpacNav = $('.nav-item.corpac'); 358 const $notificationsNav = $('.coparc-notificaions'); 359 const comumnity = me.qualifiers.includes('CORPACCommunity'); 360 const featureBase = me.qualifiers.includes('Feature/CORPAC'); 361 const featureDisabled = me.qualifiers.includes('Feature/CORPAC/disabled'); 362 if (featureBase && comumnity) { 363 $corpacNav.removeClass('d-none'); 364 } 365 if (featureBase && comumnity && !featureDisabled) { 366 $notificationsNav.removeClass('d-none'); 367 } 368 } 369 //STINGRAY 370 <!-- Stingray removed JS method by BCVSETUPS-1143 --> 371 372 } 373 374 }).fail(function () { 375 console.log("No User information!"); 376 me = {}; 377 }); 378 //} 379 <!-- Stingray removed JS method by BCVSETUPS-1143 --> 380 381 }, 382 initMostConsulted: function(url){ 383 /* State variables, will be used to define what action will be taken */ 384 url += "&lang=" + document.documentElement.lang; 385 var webfgConfig = { 386 mouseOnMostConsulted:false, 387 mouseOnTdIcon:false, 388 page:1 389 }; 390 391 /* Define the element that will react on click */ 392 var $tdIcon = $('a.nav-link span.tdIcon'); 393 var $mostConsultedPanel = $("div.webfg.most-consulted"); 394 var $navigationBar = $('nav.nav-secondLevel'); 395 var $body = $('body'); 396 397 /* Proceed only when all the mandatory elements are defined */ 398 if($tdIcon && $tdIcon.length > 0 && $navigationBar && $navigationBar.length > 0 && $body && $body.length > 0){ 399 /* Keep track of the mouse position towards the td icon. */ 400 $tdIcon.mouseover(function(){ 401 webfgConfig.mouseOnTdIcon = true; 402 }); 403 404 $tdIcon.mouseout(function(){ 405 webfgConfig.mouseOnTdIcon = false; 406 }); 407 408 /* React when clicking on the td icon */ 409 $tdIcon.on('click', function(){ 410 411 /* If the panel exists remove it to ensure that we always have the latest state of the widget */ 412 if($mostConsultedPanel.length !== undefined && $mostConsultedPanel.children().length > 0) { 413 $mostConsultedPanel.hide(); 414 $mostConsultedPanel.empty(); 415 $('div.dim').remove(); 416 } 417 else { 418 $('div.dim').remove(); 419 webfg.dim(); 420 421 /* Create the base div */ 422 $mostConsultedPanel = $('<div></div>'); 423 $mostConsultedPanel.addClass('webfg most-consulted'); 424 $mostConsultedPanel.css('position', 'absolute'); 425 426 /* Compute the position of the popup */ 427 var top = $navigationBar.offset().top + $navigationBar.height(); 428 429 $mostConsultedPanel.css('top', top + 'px'); 430 $mostConsultedPanel.css('left', $("#dynMenu").position().left - 15 + 'px'); 431 432 $mostConsultedPanel.load(url, function(){ 433 /* Append the event handlers on the whole body */ 434 $mostConsultedPanel.mouseover(function(){ 435 webfgConfig.mouseOnMostConsulted = true; 436 }); 437 438 $mostConsultedPanel.mouseout(function(){ 439 webfgConfig.mouseOnMostConsulted = false;
440 }); 441 442 /* The table links */ 443 var $moreResultsElem = $mostConsultedPanel.find('a.more-results'); 444 var $lessResultsElem = $mostConsultedPanel.find('a.less-results'); 445 446 /* Append an event handler to the 'more results' link */ 447 $moreResultsElem.on('click', function(e){ 448 /* Prevents the link from being called */ 449 e.preventDefault(); 450 451 if(webfgConfig.page < 5){ 452 453 /* Build the default URL */ 454 webfgConfig.page = webfgConfig.page + 1; 455 456 var anchor = $(this).attr('href') + '?decorator=empty&tableOnly=true'; 457 458 /* Reload the new table */ 459 $mostConsultedPanel.find('table').load( 460 anchor + '&pageSize=' + webfgConfig.page, 461 Solid.handleMostConsultedLinks(webfgConfig.page, $moreResultsElem, $lessResultsElem) 462 ); 463 } 464 }); 465 466 /* Append an event handler to the 'more results' link */ 467 $lessResultsElem.on('click', function(e){ 468 /* Prevents the link from being called */ 469 e.preventDefault(); 470 471 if(webfgConfig.page > 1){ 472 473 /* Build the default URL */ 474 webfgConfig.page = webfgConfig.page -1; 475 476 var anchor = $(this).attr('href') + '?decorator=empty&tableOnly=true'; 477 478 /* Reload the new table */ 479 $mostConsultedPanel.find('table').load( 480 anchor + '&pageSize=' + webfgConfig.page, 481 Solid.handleMostConsultedLinks(webfgConfig.page, $moreResultsElem, $lessResultsElem) 482 ); 483 } 484 }); 485 486 $body.append($mostConsultedPanel); 487 $body.on('click', function(){ 488 if(!webfgConfig.mouseOnMostConsulted && !webfgConfig.mouseOnTdIcon){ 489 $mostConsultedPanel.hide(); 490 $mostConsultedPanel.empty(); 491 } 492 }); 493 }); 494 } 495 }); 496 } 497 }, 498 handleMostConsultedLinks:function(pageSize, $moreResultsElem, $lessResultsElem){ 499 /* I'm tired, this explains that. Add a to-do if a better implementation is needed */ 500 if(pageSize > 1){ 501 $lessResultsElem.show(); 502 } 503 else{ 504 $lessResultsElem.hide(); 505 } 506 507 if(pageSize < 5){ 508 $moreResultsElem.show(); 509 } 510 else{ 511 $moreResultsElem.hide(); 512 } 513 }, 514 initElasticSearchUnderlyingValorExtendedSearch: function (relativeUrl, inputField) { 515 var inputField = $("#" + inputField); 516 var inputFieldGroup = inputField.closest('.input-group'); 517 inputField.solidFastSearch({ 518 query: { 519 fields: "M_NAME,M_SYMB,M_ISIN,M_MARKET:value:description,SC_GROUPED:value:description,M_CUR:value:description,MIC,EUSIPA,DOMICILE,M_BC", 520 flavor: "EQU,IND,COM,CUR,BON,DIV,INT,LIQ", 521 size: 2, 522 useWildcards: true 523 }, 524 alignElement: inputFieldGroup.length ? inputFieldGroup : null 525 }); 526 }, 527 createMiniChart:function(fltPrevDayClose){ 528 529 var color = '#009933'; 530 var langChart = document.documentElement.lang.trim().replace(/_/g, '-'); 531 /** 532 * Create a constructor for sparklines that takes some sensible defaults and merges in the individual 533 * chart options. This function is also available from the jQuery plugin as $(element).highcharts('SparkLine'). 534 */ 535 if(typeof Highcharts !== "undefined"){ 536 Highcharts.setOptions({ 537 accessibility: { 538 enabled: false 539 }, 540 lang: { 541 locale: langChart 542 } 543 }); 544 Highcharts.SparkLine = function (a, b, c) { 545 var hasRenderToArg = typeof a === 'string' || a.nodeName, 546 options = arguments[hasRenderToArg ? 1 : 0], 547 defaultOptions = { 548 chart: { 549 renderTo: (options.chart && options.chart.renderTo) || this, 550 backgroundColor: null, 551 borderWidth: 0, 552 type: 'line', 553 margin: [2, 0, 2, 0], 554 width: 100, 555 height: 40, 556 style: { 557 overflow: 'visible' 558 }, 559 lineWidth: 2, 560 lineColor: 'red', 561 skipClone: true 562 }, 563 title: { 564 text: '' 565 }, 566 credits: { 567 enabled: false 568 }, 569 navigation: { 570 buttonOptions: { 571 enabled: false, 572 symbolStroke: '#DDDDDD', 573 theme: { 574 fill: '#e3e3e3' 575 } 576 } 577 }, 578 xAxis: { 579 labels: { 580 enabled: false 581 }, 582 title: { 583 text: null 584 }, 585 startOnTick: false, 586 endOnTick: false, 587 lineColor: 'transparent', 588 tickPositions: [] 589 }, 590 yAxis: { 591 endOnTick: false, 592 startOnTick: false, 593 labels: { 594 enabled: false 595 }, 596 title: { 597 text: null 598 }, 599 gridLineColor: 'transparent', 600 plotLines: [{ 601 value: fltPrevDayClose, 602 width: 1, 603 color: '#aaa' 604 }], 605 tickPositions: [] 606 }, 607 legend: { 608 enabled: false 609 }, 610 tooltip: { 611 enabled: true, 612 backgroundColor: null, 613 borderWidth: 0, 614 shadow: false, 615 useHTML: true, 616 hideDelay: 0, 617 shared: true, 618 padding: 0, 619 positioner: function (w, h, point) { 620 return { x: point.plotX - w / 2, y: point.plotY - h }; 621 } 622 }, 623 plotOptions: { 624 series: { 625 animation: false, 626 lineWidth: 1, 627 shadow: false, 628 color: color, 629 states: { 630 hover: { 631 lineWidth: 1 632 } 633 }, 634 marker: { 635 radius: 1, 636 states: { 637 hover: { 638 radius: 2 639 } 640 } 641 }, 642 fillOpacity: 0.25 643 }, 644 column: { 645 negativeColor: '#910000', 646 borderColor: 'silver' 647 } 648 } 649 }; 650 651 options = Highcharts.merge(defaultOptions, options); 652 653 return hasRenderToArg ? 654 new Highcharts.Chart(a, options, c) : 655 new Highcharts.Chart(options, b); 656 }; 657 658 var start = +new Date(), 659 $tds = $('div[data-sparkline]'), 660 fullLen = $tds.length, 661 n = 0; 662 663 // Creating 153 sparkline charts is quite fast in modern browsers, but IE8 and mobile 664 // can take some seconds, so we split the input into chunks and apply them in timeouts 665 // in order avoid locking up the browser process and allow interaction. 666 function doChunk() { 667 var time = +new Date(), 668 i, 669 len = $tds.length, 670 $td,
671 stringdata, 672 fltPrevDayClose, 673 colorvalue, 674 arr, 675 data, 676 chart; 677 678 for (i = 0; i < len; i += 1) { 679 $td = $($tds[i]); 680 stringdata = $td.data('sparkline'); 681 fltPrevDayClose = $td.data('prevdayclose'); 682 colorvalue = $td.data('colorvalue'); 683 data = stringdata; 684 arr = data.map(function(elem) { 685 return [elem[0],parseFloat(elem[1])]; 686 }); 687 //arr = stringdata; 688 chart = {}; 689 if (arr[1]) { 690 // chart.type = arr[1]; 691 } 692 $td.highcharts('SparkLine', { 693 series: [{ 694 data: arr, 695 pointStart: 1 696 }], 697 tooltip: { 698 formatter: function() { 699 return this.points.reduce(function (s, point) { 700 return '<div style="width:200px;"><strong>'+point.key + ' <p style="color:'+point.color+';"> ' + 701 point.y+'</p></strong>' ; 702 }, '<b>' + this.x + '</b></div>'); 703 } 704 }, 705 plotOptions: { 706 series: { 707 animation: false, 708 lineWidth: 1, 709 shadow: false, 710 zones: [{value: fltPrevDayClose, color: '#dc3545'}], 711 color: '#28a745' 712 } 713 }, 714 yAxis: { 715 716 plotLines: [{ 717 value: fltPrevDayClose, 718 width: 1, 719 color: '#aaa' 720 }], 721 }, 722 chart: chart 723 }); 724 725 n += 1; 726 // If the process takes too much time, run a timeout to allow interaction with the browser 727 if (new Date() - time > 500) { 728 $tds.splice(0, i + 1); 729 setTimeout(doChunk, 0); 730 break; 731 } 732 733 // Print a feedback on the performance 734 if (n === fullLen) { 735 $('#result').html('Generated ' + fullLen + ' sparklines in ' + (ne
735w Date() - start) + ' ms'); 736 } 737 } 738 } 739 doChunk(); 740 741 742 } 743 else { 744 setTimeout(Solid.createMiniChart, 50); 745 } 746 }, 747 initMiniChartsIntraday:function(){ 748 var fltPrevDayClose = 0; 749 $.each(timeSeries, function(index, value){ 750 $.each(value, function(index2, value2){ 751 var listingId = value2.listingId; 752 var prices = value2.prices; 753 var dataArray = []; 754 if(listingId && prices && prices.length > 0){ 755 var divId = "mini-chart-" + listingId.replace(new RegExp(',', 'g'), '-'); 756 var $miniChart = $('div#' + divId); 757 var attributeData = $miniChart.attr('data-sparkline'); 758 if (typeof attributeData === 'undefined' && attributeData !== true) { 759 if($miniChart.length > 0){ 760 var value = $miniChart.data('value'); 761 var strPrevDayClose = $miniChart.data("prevdayclose"); 762 fltPrevDayClose = parseFloat($miniChart.data('prevdayclose')); 763 $.get(Application.contextPath() + "/api/series/intraday",{ 764 lid: listingId, // man 765 max: 2500, 766 mode: 'snap', // man 767 period: '1d', // man 768 vt: 'yes', 769 intra: true // include intraday prices series! 770 }, function(data) { 771 var fltPrevDayClose = parseFloat(strPrevDayClose); 772 if(data != ""){ 773 //add the reference line with the previous day value 774 for (var i = 0; i < data.data.length; i++) { 775 // date, positive value, negative value, previous day close 776 var tickVal = data.data[i][1]; 777 var date = new Date(data.data[i][0]); 778 var hours = date.getHours(); 779 var minutes = date.getMinutes(); 780 var seconds = date.getSeconds(); 781 var day = date.getDate(); 782 var month = date.getMonth()+1; 783 var year = date.getFullYear(); 784 785 if(hours < 10){hours = '0'+hours;} 786 if(minutes < 10){minutes = '0'+minutes;} 787 if(seconds < 10){seconds = '0'+seconds;} 788 if(month<10){month = '0'+month;} 789 if(day<10){day = '0'+day;} 790 if(tickVal >= fltPrevDayClose) { 791 dataArray.push([day+"/"+month+"/"+year+" "+hours+":"+minutes, tickVal, 'line {color: #009933}', fltPrevDayClose]); 792 } else { 793 dataArray.push([day+"/"+month+"/"+year+" "+hours+":"+minutes, tickVal, 'line {color: #FF5B5B}', fltPrevDayClose]); 794 } 795 } 796 797 var pricesPrint = ""; 798 $.each(dataArray, function(ind,val) { 799 // dataArray.push([val.d, val.c, pval]); 800 if(pricesPrint != ""){ 801 pricesPrint = pricesPrint + ', '; 802 } 803 pricesPrint = pricesPrint + "[\""+val[0]+"\",\"" +val[1]+"\"]"; 804 }); 805 $('#'+divId).attr('data-sparkline', "["+pricesPrint+"]"); 806 Solid.createMiniChart(fltPrevDayClose); 807 808 } else { // There is no data for the graph and we display an alternative message 809 //$('div.sparklight').append('<div class="no-chart-data">' + msg + '</div>'); 810 $('div.sparklight div.no-chart-data').css('display', 'inline'); 811 } 812 }); 813 } 814 } 815 else{ 816 var divId = "mini-chart-" + value2.listingId.replace(new RegExp(',', 'g'), '-'); 817 var $miniChart = $('div#' + divId); 818 var strPrevDayClose = $miniChart.data("prevdayclose"); 819 fltPrevDayClose = parseFloat($miniChart.data('prevdayclose')); 820 Solid.createMiniChart(fltPrevDayClose); 821 } 822 } 823 }); 824 }); 825 }, 826 initMiniCharts:function(){ 827 var lastValue = 0; 828 var color = ''; 829 // first, put attributes in div for chart 830 // data-sparkline="71, 78, 39, 66 " 831 $.each(timeSeries, function(index, value){ 832 $.each(value, function(index2, value2){ 833 var listingId = value2.listingId; 834 var prices = value2.prices; 835 836 if(listingId && prices && prices.length > 0){ 837 var divId = "mini-chart-" + listingId.replace(new RegExp(',', 'g'), '-'); 838 var $miniChart = $('div#' + divId); 839 if($miniChart.length > 0){ 840 841 var value = $miniChart.data('value'); 842 var pval = $miniChart.data('pval'); 843 844 if(value > 0 ){ 845 color = '#009933'; 846 } 847 else { 848 color = '#FF5B5B'; 849 } 850 851 var dataArray = []; 852 var pricesPrint = ""; 853 $.each(prices, function(ind,val) { 854 // dataArray.push([val.d, val.c, pval]); 855 if(pricesPrint != ""){ 856 pricesPrint = pricesPrint + ', '; 857 } 858 pricesPrint = pricesPrint + val.c; 859 }); 860 861 $('#'+divId).attr('data-sparkline', pricesPrint);
862 lastValue = prices[prices.length-1].c; 863 $('#'+divId).attr('data-lastvalue', lastValue); 864 $('#'+divId).attr('data-colorvalue', color); 865 866 /** 867 * Create a constructor for sparklines that takes some sensible defaults and merges in the individual 868 * chart options. This function is also available from the jQuery plugin as $(element).highcharts('SparkLine'). 869 */ 870 Highcharts.SparkLine = function (a, b, c) { 871 var hasRenderToArg = typeof a === 'string' || a.nodeName, 872 options = arguments[hasRenderToArg ? 1 : 0], 873 defaultOptions = { 874 chart: { 875 renderTo: (options.chart && options.chart.renderTo) || this, 876 backgroundColor: null, 877 borderWidth: 0, 878 type: 'line', 879 margin: [2, 0, 2, 0], 880 width: 100, 881 height: 40, 882 style: { 883 overflow: 'visible' 884 }, 885 lineWidth: 2, 886 lineColor: 'red', 887 skipClone: true 888 }, 889 title: { 890 text: '' 891 }, 892 credits: { 893 enabled: false 894 }, 895 navigation: { 896 buttonOptions: { 897 enabled: false, 898 symbolStroke: '#DDDDDD', 899 theme: { 900 fill: '#e3e3e3' 901 } 902 } 903 }, 904 xAxis: { 905 labels: { 906 enabled: false 907 }, 908 title: { 909 text: null 910 }, 911 startOnTick: false, 912 endOnTick: false, 913 lineColor: 'transparent', 914 tickPositions: [] 915 }, 916 yAxis: { 917 endOnTick: false, 918 startOnTick: false, 919 labels: { 920 enabled: false 921 }, 922 title: { 923 text: null 924 }, 925 gridLineColor: 'transparent', 926 plotLines: [{ 927 value: lastValue, 928 width: 1, 929 color: '#aaa' 930 }], 931 tickPositions: [] 932 }, 933 legend: { 934 enabled: false 935 }, 936 tooltip: { 937 enabled: true, 938 backgroundColor: null, 939 borderWidth: 0, 940 shadow: false, 941 useHTML: true, 942 hideDelay: 0, 943 shared: true, 944 padding: 0, 945 positioner: function (w, h, point) { 946 return { x: point.plotX - w / 2, y: point.plotY - h }; 947 } 948 }, 949 plotOptions: { 950 series: { 951 animation: false, 952 lineWidth: 1, 953 shadow: false, 954 color: color, 955 states: { 956 hover: { 957 lineWidth: 1 958 } 959 }, 960 marker: { 961 radius: 1, 962 states: { 963 hover: { 964 radius: 2 965 } 966 } 967 }, 968 fillOpacity: 0.25 969 }, 970 column: { 971 negativeColor: '#910000', 972 borderColor: 'silver' 973 } 974 } 975 }; 976 977 options = Highcharts.merge(defaultOptions, options); 978 979 return hasRenderToArg ? 980 new Highcharts.Chart(a, options, c) : 981 new Highcharts.Chart(options, b); 982 }; 983 984 var start = +new Date(), 985 $tds = $('div[data-sparkline]'), 986 fullLen = $tds.length, 987 n = 0; 988 989 // Creating 153 sparkline charts is quite fast in modern browsers, but IE8 and mobile 990 // can take some seconds, so we split the input into chunks and apply them in timeouts 991 // in order avoid locking up the browser process and allow interaction. 992 function doChunk() { 993 var time = +new Date(), 994 i, 995 len = $tds.length, 996 $td,
997 stringdata, 998 lastvalue, 999 colorvalue, 1000 arr, 1001 data, 1002 chart; 1003 1004 for (i = 0; i < len; i += 1) { 1005 $td = $($tds[i]); 1006 stringdata = $td.data('sparkline'); 1007 lastvalue = $td.data('lastvalue'); 1008 colorvalue = $td.data('colorvalue'); 1009 arr = stringdata.split('; '); 1010 data = $.map(arr[0].split(', '), parseFloat); 1011 chart = {}; 1012 if (arr[1]) { 1013 chart.type = arr[1]; 1014 } 1015 $td.highcharts('SparkLine', { 1016 series: [{ 1017 data: data, 1018 pointStart: 1 1019 }], 1020 tooltip: { 1021 headerFormat: '', 1022 pointFormat: '<b>{point.y}</b>' 1023 }, 1024 plotOptions: { 1025 series: { 1026 animation: false, 1027 lineWidth: 1, 1028 shadow: false, 1029 color: colorvalue 1030 } 1031 }, 1032 yAxis: { 1033 1034 plotLines: [{ 1035 value: lastvalue, 1036 width: 1, 1037 color: '#aaa' 1038 }], 1039 }, 1040 chart: chart 1041 }); 1042 1043 n += 1; 1044 // If the process takes too much time, run a timeout to allow interaction with the browser 1045 if (new Date() - time > 500) { 1046 $tds.splice(0, i + 1); 1047 setTimeout(doChunk, 0); 1048 break; 1049 } 1050 1051 // Print a feedback on the performance 1052 if (n === fullLen) { 1053 $('#result').html('Generated ' + fullLen + ' sparklines in ' + (new Date() - start) + ' ms'); 1054 } 1055 } 1056 } 1057 doChunk(); 1058 } 1059 } 1060 }); 1061 }); 1062 }, 1063 initDetailIndex:function(){ 1064 /* Initialisation of the mini-charts */ 1065 Solid.initMiniChartsIntraday(); 1066 1067 /* Initialisation of the bar chart scripts */ 1068 Solid.convertBarcharts(); 1069 1070 /* Initialisation of the tooltip */ 1071 $('[data-bs-toggle="tooltip"]').tooltip({html:true}); 1072 1073 Solid.patchLightboxAjaxLinks($("a.lightBoxAjaxLink")); 1074 }, 1075 initTheScreenerPortfolioChart:function(name, reference){ 1076 var lang = document.documentElement.lang; 1077 if(!lang){ 1078 lang = "en"; 1079 } 1080 /* Check if all the variables are here */ 1081 if(Highcharts && name && reference){ 1082 /* Initialize the time series */ 1083 var timeSeries = {}; 1084 1085 /* The list of dropdown items */ 1086 var $dropdownItems = $('.webfg-select-box a.dropdown-item'); 1087 1088 /* The list of performance tables */ 1089 var $performanceTables = $('table.thescreener-portfolio-performance'); 1090 1091 /* The dropdown button*/ 1092 var $dropdownBtn = $('button.dropdown-toggle span'); 1093 1094 /* Add the cumulated performances if we have data */ 1095 if(cumperfTimeSeriesPf && cumperfTimeSeriesRef){ 1096 timeSeries.cum = { pf:cumperfTimeSeriesPf, ref:cumperfTimeSeriesRef, type:'line' }; 1097 } 1098 1099 /* Add the yearly performance if we have data */ 1100 if(yearlyperfTimeSeriesPf && yearlyperfTimeSeriesRef){ 1101 timeSeries.yearly = { pf:yearlyperfTimeSeriesPf, ref:yearlyperfTimeSeriesRef, type:'column' }; 1102 } 1103 1104 /* Add the monthly performance if we have data */ 1105 if(yearlyperfTimeSeriesPf && yearlyperfTimeSeriesRef){ 1106 timeSeries.monthly = { pf:monthlyperfTimeSeriesPf, ref:monthlyperfTimeSeriesRef, type:'column' }; 1107 } 1108 var langChart = document.documentElement.lang.trim().replace(/_/g, '-'); 1109 if(lang === "de" || lang === "de_CH" || lang === "de_DE") { 1110 Highcharts.setOptions({ 1111 lang: { 1112 months: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'], 1113 weekdays: ['Sonntag', 'Montag', 'Die
1113nstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'], 1114 shortMonths: ['Jan', 'Feb', 'Mar', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'], 1115 decimalPoint: '.', 1116 thousandsSep: "'", 1117 rangeSelectorFrom: 'Von', 1118 rangeSelectorTo: 'bis', 1119 printChart: "Diagramm drucken", 1120 downloadCSV:"CSV herunterladen", 1121 downloadJPEG:"JPEG Bild herunterladen", 1122 downloadPDF:"PDF Dokument herunterladen", 1123 downloadPNG:"PNG Bild herunterladen", 1124 downloadSVG:"SVG Vektor Bild herunterladen", 1125 downloadXLS:"XLS herunterladen", 1126 locale: langChart 1127 1128 } 1129 }); 1130 }else if(lang === "fr" || lang === "fr_CH" || lang === "fr_FR"){ 1131 Highcharts.setOptions({ 1132 lang: { 1133 months: ['Janvier','Février','Mars','Avril','Mai','Juin','Juillet','Août','Septembre','Octobre','Novembre','Décembre'], 1134 weekdays: ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi'], 1135 shortMonths: ['Janv','Fév','Mars','Avr','Mai','Juin','Juil','Août','Sep','Oct','Nov','Déc'], 1136 decimalPoint: ',', 1137 thousandsSep: ' ', 1138 rangeSelectorFrom: 'De', 1139 rangeSelectorTo: 'A', 1140 printChart: "Imprimer le graphique", 1141 downloadCSV:"Télécharger CSV", 1142 downloadJPEG:"Télécharger l'image JPEG", 1143 downloadPDF:"Télécharger le document PDF", 1144 downloadPNG:"Télécharger l'image PNG", 1145 downloadSVG:"Télécharger l'image vectorielle SVG", 1146 downloadXLS:"Télécharger XLS", 1147 locale: langChart 1148 } 1149 }); 1150 }else if(lang === "it" || lang === "it_CH" || lang === "it_IT"){ 1151 Highcharts.setOptions({ 1152 lang: { 1153 months: ['gennaio','febbraio','marzo','aprile','maggio','giugno','luglio','agosto','settembre','ottobre','novembre','dicembre'], 1154 weekdays: ['domenica', 'lunedì', 'martedì', 'mercoledì', 'giovedì', 'venerdì', 'sabato'], 1155 shortMonths: ['Gen','Feb','Mar','Apr','Mag','Giu','Lug','Ago','Set','Ott','Nov','Dic'], 1156 decimalPoint: '.', 1157 thousandsSep: "'", 1158 rangeSelectorFrom: 'Da', 1159 rangeSelectorTo: 'a', 1160 printChart: "Stampa grafico", 1161 downloadCSV:"Scarica CSV", 1162 downloadJPEG:"Scarica l'immagine JPEG", 1163 downloadPDF:"Scarica il documento PDF", 1164 downloadPNG:"Scarica l'immagine PNG", 1165 downloadSVG:"Scarica l'immagine vettoriale SVG", 1166 downloadXLS:"Scarica XLS", 1167 locale: langChart 1168 } 1169 }); 1170 }else if(lang === "en"){ 1171 Highcharts.setOptions({ 1172 lang: { 1173 decimalPoint: '.', 1174 thousandsSep: ",", 1175 locale: langChart 1176 } 1177 }); 1178 } 1179 1180 // Create the chart 1181 var stockChart = Highcharts.stockChart('thescreener-portfolio-chart', { 1182 legend: { 1183 enabled: true, 1184 align: 'center', 1185 borderColor: '#dee2e6', 1186 borderWidth: 1, 1187 layout: 'horizontal',
1188 verticalAlign: 'top', 1189 y: 50 1190 }, 1191 chart:{ height:500, type:'line' }, 1192 rangeSelector: { selected: 3 }, 1193 title: { text: '' }, 1194 series: [{ 1195 name: name, 1196 data: timeSeries.cum.pf, 1197 tooltip: { 1198 valueDecimals: 2, 1199 pointFormat: '<span style="color:{series.color}">\u25CF</span> {series.name}: <b>{point.y:,.2f} %</b><br/>', 1200 } 1201 },{ 1202 name: reference, 1203 data: timeSeries.cum.ref, 1204 tooltip: { 1205 valueDecimals: 2, 1206 pointFormat: '<span style="color:{series.color}">\u25CF</span> {series.name}: <b>{point.y:,.2f} %</b><br/>', 1207 } 1208 }] 1209 }); 1210 1211 if($dropdownItems && $performanceTables){ 1212 /* Event handler for the chart select box */ 1213 $dropdownItems.each(function(){ 1214 $(this).on('click', function(){ 1215 /* Set the selected element */ 1216 var element = $(this).data('element'); 1217 1218 /* Set the text of the dropdown button correctly */ 1219 if($dropdownBtn){ 1220 $dropdownBtn.text($(this).text()); 1221 } 1222 1223 /* Proceed only if the selected time series exists */ 1224 if(element && timeSeries[element]){ 1225 stockChart.series[0].update({ type: timeSeries[element].type}); 1226 stockChart.series[1].update({ type: timeSeries[element].type}); 1227 stockChart.series[0].setData(timeSeries[element].pf, false); 1228 stockChart.series[1].setData(timeSeries[element].ref, true); 1229 1230 /* Compute the id of the table that should be displayed if it exist */ 1231 var id = 'thescreener-portfolio-' + element + '-performance'; 1232 1233 $performanceTables.each(function(){ 1234 if($(this).attr('id') === id){ 1235 $(this).show(); 1236 } 1237 else { 1238 $(this).hide(); 1239 } 1240 }); 1241 } 1242 }); 1243 }); 1244 } 1245 } 1246 }, 1247 initGlobalMarkets:function(){ 1248 /* Initialisation of the bar chart scripts */ 1249 Solid.convertBarcharts(); 1250 1251 /* Initialisation of the mini charts */ 1252 Solid.initMiniChartsIntraday(); 1253 1254 /* Initialisation of the tooltip */ 1255 $('[data-bs-toggle="tooltip"]').tooltip({html:true}); 1256 }, 1257 initFundinfoDocumentationPanel:function(){ 1258 1259 var ajaxMe = $().trading().me(); 1260 $.when(ajaxMe).then(function(dataMe){ 1261 me = dataMe; 1262 $('#USER').val(me.userName); 1263 console.log("User information: ", me.userName); 1264 }); 1265 1266 /* Initialisation of the mini-charts */ 1267 Solid.initMiniChartsIntraday(); 1268 1269 /* Initialisation of the tooltip */ 1270 $('[data-bs-toggle="tooltip"]').tooltip({html:true}); 1271 1272 /* Handle the documentation request */ 1273 var $documentationForm = $('div#documentation-details-tabs-row form'); 1274 if($documentationForm && $documentationForm.length > 0){ 1275 $documentationForm.on('submit', function(e){ 1276 /* Don't explicitly send the form */ 1277 e.preventDefault(); 1278 1279 /* Duration of the fadeIn and fadeOut function */ 1280 var duration = 1500; 1281 1282 /* Send the form via ajax */ 1283 $.ajax({ 1284 type: "POST", 1285 url: $documentationForm.attr('action'), 1286 data: $documentationForm.serialize(), 1287 success: function(){ 1288 /* Code redundancy with the error callback, implement a function when you have enough time */ 1289 var $successElem = $('div#documentation-detail
1289s-tabs-row div.alert-success'); 1290 if($successElem && $successElem.length > 0){ 1291 $successElem.fadeIn(duration, function(){ 1292 setTimeout(function(){ 1293 $successElem.fadeOut(duration); 1294 }, 3000); 1295 }); 1296 } 1297 }, 1298 error:function(XMLHttpRequest, textStatus){ 1299 var $errorElem = $('div#documentation-details-tabs-row div.alert-danger'); 1300 if($errorElem && $errorElem.length > 0){ 1301 $errorElem.fadeIn(duration, function(){ 1302 setTimeout(function(){ 1303 $errorElem.fadeOut(duration); 1304 }, 3000); 1305 }); 1306 } 1307 } 1308 }); 1309 }); 1310 } 1311 }, 1312 initStreaming:function(ctx, pullID){ 1313 if(ThemeManager && Streaming && ctx && pullID){ 1314 ThemeManager.defaults({ themeUrl: ''}); 1315 1316 var defaultColors = { 1317 equal: { background: '#FFFF00' }, 1318 up: { background: '#00FF00' }, 1319 down: { background: '#FF0000' } 1320 }; 1321 1322 function setColors(settings) { 1323 settings = $.extend(true, defaultColors, settings); 1324 Highlighter.setEffect('default', Highlighter.Effects.createHighlightEffect(settings.equal.background, settings.equal.text, 1500)); 1325 Highlighter.setEffect('highlightUp', Highlighter.Effects.createHighlightEffect(settings.up.background, settings.up.text, 1500)); 1326 Highlighter.setEffect('highlightDown', Highlighter.Effects.createHighlightEffect(settings.down.background, settings.down.text, 1500)); 1327 } 1328 1329 if (window.ThemeManager) { 1330 setColors(ThemeManager.register('highlighter', setColors)); 1331 } 1332 else { 1333 setColors({}); 1334 } 1335 Streaming.init({ 1336 type: 'pull', 1337 pullSettings: { 1338 pullInterval: 10000, 1339 pullURL: ctx + '/pull', 1340 destroyURL: ctx + '/listing/stopPull', 1341 settingsURL: ctx + '/listing/updatePull', 1342 pullID: pullID 1343 } 1344 }); 1345 1346 // Add default renderer for all (value) fields .. 1347 Streaming.setDefaultRenderer({ 1348 isApplicable: function (field, entry) { 1349 return entry === 'value'; 1350 }, 1351 adaptConfig: function (fieldConfig) { 1352 // We need VAS / VAT data .. 1353 fieldConfig.type = true; 1354 }, 1355 prepareFieldEntry: function (/*fieldEntry*/) { 1356 return false; 1357 }, 1358 handleUpdate: function (fieldEntry, data/*, pluginConfig*/) { 1359 if (data.vas === 339) { 1360 // -> Deleted price .. 1361 fieldEntry.cell.addClass('deleted').attr('title', 'price deleted'); 1362 } 1363 else if (data.vas === 114) { 1364 // -> Trade Temporaly stopped price .. 1365 fieldEntry.cell.text(''); 1366 return true; 1367 } 1368 else { 1369 fieldEntry.cell.removeClass('deleted').removeAttr('title'); 1370 } 1371 return false; // Return false so normal rendering takes place .. 1372 } 1373 }); 1374 Streaming.debug = true; 1375 Streaming.convertAndSubscribe(); 1376 } 1377 else{ 1378 console.error("Could not initialize the streaming, some elements must be missing") 1379 } 1380 }, 1381 submitDerivatives:function(baseUrl, requestValue, derivativesParameters, parameterName){ 1382 /* Set the correct value before sending the request */ 1383 if(requestValue) { 1384 derivativesParameters[parameterName] = requestValue; 1385 1386 /* Build the query string */ 1387 var queryString = '?'; 1388 var separator = ''; 1389 for (var key in derivativesParameters) { 1390 if (derivativesParameters.hasOwnProperty(key) && derivativesParameters[key] !== 'gui.issuer' && derivativesParameters[key]) { 1391 queryString += separator + key + "=" + derivativesParameters[key]; 1392 if(!separator){ 1393 separator = '&'; 1394 } 1395 } 1396 } 1397 1398 /* Call the new link */ 1399 window.location = baseUrl + queryString; 1400 } 1401 }, 1402 initDerivatives:function() { 1403 /* The parameters name */ 1404 var derivativesParameters = { 1405 sortField: '', 1406 eusipaCategory: '', 1407 optionType: '', 1408 issuer:'', 1409 underlyer:'' 1410 }; 1411 1412 /* The fastsearch parameter name */ 1413 var fastSearchParameters = { 1414 fields: 'M_NAME,M_SYMB,M_ISIN,M_MARKET:value:description,SC_GROUPED:value:description,M_CUR:value:description,MIC,EUSIPA,DOMICILE,M_BC', 1415 assetClasses:'EQU,IND,COM,CUR,BON,DIV,INT,LIQ', 1416 size:'5', 1417 useWildcards:'true', 1418 mouseOnPanel:false, 1419 mouseOnSearchInput:false 1420 }; 1421 1422 /* Isolate the dropdown elements */ 1423 var $selectBox = $('div.webfg-select-box'); 1424 1425 /* Basic check */ 1426 if($selectBox && $selectBox.length > 0){ 1427 /* Initialisation of the parameters */ 1428 $selectBox.each(function() { 1429 /* Get the key / value pair out of the element and set them */ 1430 var parameterName = $(this).find('button').data('param'); 1431 var parameterValue = $(this).find('button').data('selected'); 1432 if(parameterName && parameterValue){ 1433 derivativesParameters[parameterName] = parameterValue; 1434 1435 $(this).find('a.dropdown-item').each(function(){ 1436 $(this).on('click', function(e){ 1437 /* Do nothing on click */ 1438 e.preventDefault(); 1439 1440 /* Check upon the current underlyer */ 1441 if(!$underlyingInput.val() || $underlyingInput.val().length <= 0){ 1442 $underlyingInput.data('underlying-id', ''); 1443 derivativesParameters.underlyer = ''; 1444 } 1445 1446 /* Submit the form with all the values */ 1447 Solid.submitDerivatives( 1448 $(this).attr('href'), 1449 $(this).data('element'), 1450 derivativesParameters, 1451 parameterName 1452 ); 1453 }); 1454 }); 1455 } 1456 }); 1457 } 1458 1459 /* The elements needed to make the search of underlying available */ 1460 var $underlyingRow = $('div#derivatives-underlying-row'); 1461 var $body = $('body'); 1462 if($underlyingRow && $underlyingRow.length > 0 && $body && $body.length > 0){ 1463 var $underlyingInput = $underlyingRow.find('input'); 1464 var $underlyingPanel = $underlyingRow.find('div.derivatives-underlying-results-panel'); 1465 1466 /* This snippet sets the underlying id (listing id) if needed */ 1467 var underlyingId = $underlyingInput.data('underlying-id'); 1468 if(underlyingId && underlyingId.length > 0){ 1469 derivativesParameters.underlyer = underlyingId; 1470 } 1471 1472 /* This snippet will decide whether the search results panel must be displayed */ 1473 $body.on('click', function(){ 1474 if(!fastSearchParameters.mouseOnPanel && $underlyingPanel.find('table').length > 0){ 1475 $underlyingPanel.addClass('d-none'); 1476 } 1477 }); 1478 1479 if($underlyingInput && $underlyingPanel){
1480 /* Will contain the ajax request */ 1481 var ajaxRequest; 1482 1483 /* Add an on mouse over and on mouse out event handler to the panel */ 1484 $underlyingPanel.on('mouseover', function(){ 1485 fastSearchParameters.mouseOnPanel = true; 1486 }); 1487 1488 $underlyingPanel.on('mouseout', function(){ 1489 fastSearchParameters.mouseOnPanel = false; 1490 }); 1491 1492 /* Add a key pressed listener to the input field */ 1493 $underlyingInput.on('keyup', function() { 1494 /* Cancel the ajax request */ 1495 if(ajaxRequest){ 1496 ajaxRequest.abort(); 1497 } 1498 1499 /* Retrieve the value from the input field */ 1500 var searchTerm = $underlyingInput.val(); 1501 1502 /* Proceed if the patter matches */ 1503 if (searchTerm.match(/[a-zA-Z\.]{3,}/)) { 1504 /* The base URL */ 1505 var url = $underlyingInput.data('url'); 1506 if(url){ 1507 /* The request parameters (hardcoded, I know it's not good ;-) )*/ 1508 var queryString = 'fields=' + fastSearchParameters.fields + "&flavor=" + fastSearchParameters.assetClasses; 1509 queryString += '&size=' + fastSearchParameters.size + '&useWildcards=' + fastSearchParameters.useWildcards; 1510 queryString += '&searchTerm=' + searchTerm + '&showMoreResults=false'; 1511 1512 ajaxRequest = $.ajax({ 1513 url:url + '?' + queryString, 1514 success: function(data){ 1515 /* The element that will contain the table */ 1516 $underlyingPanel.find('.row .col').html(data); 1517 1518 /* Compute the position of the element that will be displayed */ 1519 var underlyingInputPosition = $underlyingInput.position(); 1520 var top = underlyingInputPosition.top + $underlyingInput.height() + 15; 1521 var left = (underlyingInputPosition.left + $underlyingInput.width()) - $underlyingPanel.width() - 15; 1522 1523 /* Add the mandatory css to the underlying panel */ 1524 $underlyingPanel.css('position', 'absolute'); 1525 $underlyingPanel.css('top', top + 'px'); 1526 $underlyingPanel.css('left', left + 'px'); 1527 1528 /* Add an event handler to all the table rows */ 1529 $underlyingPanel.find('table tbody tr').each(function(){ 1530 $(this).on('click', function(){ 1531 /* Get the listing id out of the table */ 1532 var requestValue = $(this).data('listing'); 1533 1534 /* Submit the values to get the new list of derivatives */ 1535 Solid.submitDerivatives( 1536 $underlyingPanel.data('url'), 1537 requestValue, 1538 derivativesParameters, 1539 'underlyer' 1540 ); 1541 }); 1542 }); 1543 1544 /* Show the panel */ 1545 $underlyingPanel.removeClass('d-none'); 1546 } 1547 }); 1548 } 1549 } 1550 }); 1551 } 1552 } 1553 }, 1554 initPreferences:function(){ 1555 /* Check for the presence of the success div and get it's landingpage data attribute */ 1556 var $successElem = $('div.webfg.row').find('div.alert-success'); 1557 if($successElem && $successElem.length > 0) { 1558 var url = $successElem.data('landingpage'); 1559 /* If the URL has been set redirect the user to the correct page */ 1560 if(url && url.length > 0){ 1561 setTimeout(function(){ 1562 window.location = url; 1563 }, 10000); 1564 } 1565 } 1566 1567 var $showDisclaimerSelectbox = $('div.webfg form#preferences-form select#showDisclaimer'); 1568 var $showDisclaimerDialog = $('div.webfg form#preferences-form div#showDisclaimerDialog'); 1569 if($showDisclaimerSelectbox){ 1570 var val = ($showDisclaimerSelectbox.val() === 'true'); 1571 if (val){ 1572 $showDisclaimerDialog.hide(); 1573 }else{ 1574 $showDisclaimerDialog.show(); 1575 } 1576 $showDisclaimerSelectbox.on('change', function () { 1577 var val = ($showDisclaimerSelectbox.val() === 'true'); 1578 if (val){ 1579 $showDisclaimerDialog.hide(); 1580 }else{ 1581 $showDisclaimerDialog.show(); 1582 } 1583 }); 1584 } 1585 1586 var $showCBOESelectbox = $('div.webfg form#preferences-form select#showCBOE'); 1587 var $showCBOEDialog = $('div.webfg form#preferences-form div#showCBOEDialog'); 1588 if($showCBOESelectbox){ 1589 var val = ($showCBOESelectbox.val() === 'true'); 1590 if (val){ 1591 $showCBOEDialog.show(); 1592 }else{ 1593 $showCBOEDialog.hide(); 1594 } 1595 $showCBOESelectbox.on('change', function () { 1596 var val = ($showCBOESelectbox.val() === 'true'); 1597 if (val){ 1598 $showCBOEDialog.show(); 1599 }else{ 1600 $showCBOEDialog.hide(); 1601 } 1602 }); 1603 } 1604 1605 /* Gets the 'defaultAccount' select box */ 1606 var $defaultDepositSelectbox = $('div.webfg form#preferences-form select#defaultDeposit'); 1607 if($defaultDepositSelectbox){ 1608 var $defaultAccountBalance = $('span#defaultAccountBalance'); 1609 1610 /* The id of the default deposit */ 1611 var selectedDefaultDeposit = $defaultDepositSelectbox.data('currentdefaultdeposit'); 1612 1613 /* Get fetch the list of portfolios */ 1614 var portfolios = $().trading().portfolios(); 1615 $.when(portfolios).done(function(portfolioList) { 1616 if (portfolioList && $.isArray(portfolioList)) { 1617 $.each(portfolioList, function(index, value){ 1618 /* The portfolio id */ 1619 var productId = value["productId"]; 1620 1621 /* The portfolio owner must also be part of the select box */ 1622 var portfolioOwnerObj = value["owner"]["shortName"]; 1623 var portfolioOwner = portfolioOwnerObj ? portfolioOwnerObj : ''; 1624 1625 /* Defines whether or not the current portfolio is the selected one */ 1626 var selected = selectedDefaultDeposit !== undefined && selectedDefaultDeposit !== '' && productId === selectedDefaultDeposit; 1627 1628 /* Create the option element */ 1629 var selectedText = selected ? 'selected' : ''; 1630 var optionText = value["formattedNumber"] + ' - ' + portfolioOwner; 1631 var optionOpen = '<option value="' + value["productId"] + '"' + selectedText + '>'; 1632 var optionClose = '</option>'; 1633 $defaultDepositSelectbox.append(optionOpen + optionText
1633+ optionClose); 1634 }); 1635 1636 /* Attach an event listener to the deposit select box */ 1637 $defaultDepositSelectbox.on('change', function(){ 1638 /* Remove the current options to replace them with the new one 1639 $defaultAccountSelectbox.find('option').remove();*/ 1640 1641 /* Remove the account/deposit balance information */ 1642 $defaultAccountBalance.html(''); 1643 1644 /* Build the new option list */ 1645 var defaultDepositSelectboxVal = $defaultDepositSelectbox.val(); 1646 1647 /* Informs the client about the balance of the current deposit */ 1648 Solid.setPreferencesDepositBalance(defaultDepositSelectboxVal); 1649 1650 1651 }); 1652 1653 /* Get the selected option in order to retrieve the correct accounts */ 1654 selectedDefaultDeposit = $defaultDepositSelectbox.val(); 1655 if(selectedDefaultDeposit === undefined || selectedDefaultDeposit === ''){ 1656 selectedDefaultDeposit = $defaultDepositSelectbox.prop("selectedIndex", 0).val(); 1657 } 1658 1659 1660 } 1661 else { 1662 console.error("No portfolios could be retrieved") 1663 } 1664 }); 1665 } 1666 }, 1667 formatNumber:function(value){ 1668 value = parseFloat(value).toFixed(2); 1669 value += ''; 1670 var x = value.split('.'); 1671 var x1 = x[0]; 1672 var x2 = x.length > 1 ? '.' + x[1] : ''; 1673 var rgx = /(\d+)(\d{3})/; 1674 while (rgx.test(x1)) { 1675 x1 = x1.replace(rgx, '$1' + '\'' + '$2'); 1676 } 1677 return x1 + x2; 1678 }, 1679 setPreferencesDepositBalance:function(depositId){ 1680 /* The span for which the balance will be set */ 1681 var $defaultDepositBalance = $('span#defaultDepositBalance'); 1682 1683 if($defaultDepositBalance){ 1684 /* Reset the value */ 1685 $defaultDepositBalance.html(''); 1686 1687 /* Set the balance of the currently selected deposit */ 1688 $.when($().trading().portfolio(depositId)).done(function(portfolio){ 1689 if(portfolio && portfolio.accountGroup && portfolio.depositDetail){ 1690 var balanceCurrency = portfolio.accountGroup.balance.currency.isoCode; 1691 var evalValue = portfolio.depositDetail.evalValue.value; 1692 $defaultDepositBalance.html(balanceCurrency + " " + Solid.formatNumber(evalValue)); 1693 } 1694 else{ 1695 $defaultDepositBalance.html(''); 1696 } 1697 }); 1698 } 1699 }, 1700 activityWatcher:function(maxInactivityInMinutes, _publicHost) { 1701 /* Log the current timeout */ 1702 console.info('Activity watcher has been set to: ' + maxInactivityInMinutes + ' minutes'); 1703 1704 /* Copied from https://thisinterestsme.com/javascript-detect-user-activity/ */ 1705 1706 /* The number of minutes that have passed since the user was active */ 1707 let minutesSinceLastActivity = 0; 1708 1709 /* The maximum inactivity in minutes */ 1710 let maxInactivity = (maxInactivityInMinutes); 1711 1712 /* Setup the setInterval method to run every second. 1000 milliseconds = 1 second */ 1713 setInterval(function(){ 1714 minutesSinceLastActivity++; 1715 1716 // Log only when approaching timeout , to avoid console spam. 1717 if (maxInactivity - minutesSinceLastActivity <= 2 ) { 1718 console.log('User inactive for ' + minutesSinceLastActivity + ' minutes. Timeout in ' + (maxInactivity - minutesSinceLastActivity) + ' minutes.'); 1719 } 1720 1721 /* If the user has been inactive or idle for longer then the seconds specified in maxInactivity */ 1722 if(minutesSinceLastActivity > maxInactivity) { 1723 console.info("The maximum allowed inactivity period has been reached! The user will now be logged out."); 1724 let $logoutBtn = $('a.logOutLink'); 1725 if ($logoutBtn) { 1726 checkLogout(_publicHost); 1727 } else { 1728 console.warn("Could not find the logout button!"); 1729 } 1730 } 1731 }, 60000); 1732 1733 /* The function that will be called whenever a user is active */ 1734 function activity(){ 1735 /*reset the secondsSinceLastActivity variable back to 0 */ 1736 minutesSinceLastActivity = 0; 1737 } 1738 1739 /* An array of DOM events that should be interpreted as user activity */
1740 let activityEvents = ['mousedown', 'keydown', 'scroll', 'touchstart']; 1741 1742 /* Add these events to the document. register the activity function as the listener parameter */ 1743 activityEvents.forEach(function(eventName) { 1744 document.addEventListener(eventName, activity, true); 1745 }); 1746 }, 1747 initStocksUpDown:function(){ 1748 /* The request parameters for the theScreener stocks up / downgrades */ 1749 var parameters = { 1750 country: '', 1751 sector: '' 1752 }; 1753 1754 /* The table configuration */ 1755 var tableConfig = { 1756 sort:false, 1757 autoPagingAndFiltering: false, 1758 pagination: true, 1759 displayLength: 10 1760 }; 1761 1762 /* The list of select boxes */ 1763 $("div#thescreener-stocks-up-title-row div.webfg-select-box").each(function(){ 1764 var paramName = $(this).find('button').data('param'); 1765 var selected = $(this).find('button').data('selected'); 1766 1767 if(paramName && paramName.length > 0){ 1768 parameters[paramName] = selected ? selected : ""; 1769 1770 $(this).find('div.dropdown-menu a').each(function(){ 1771 $(this).on('click', function(e){ 1772 e.preventDefault(); 1773 1774 /* Get the value of the currently selected element and set the parameters object */ 1775 var paramValue = $(this).data('element'); 1776 parameters[paramName] = paramValue ? paramValue : ""; 1777 1778 /* Build the query string */ 1779 var qs = ''; 1780 for(var key in parameters){ 1781 if(qs !== ''){ 1782 qs += '&' 1783 } 1784 qs += key + "=" + parameters[key]; 1785 } 1786 1787 /* Redirect to the requested page */ 1788 window.location = $(this).attr('href') + '?' + qs; 1789 }); 1790 }); 1791 } 1792 }); 1793 1794 /* Add pagination to the tables */ 1795 $('div#thescreener-stocks-up-row table').solidTable(tableConfig); 1796 $('div#thescreener-stocks-down-row table').solidTable(tableConfig); 1797 1798 /* Initialisation of the tooltip */ 1799 $('[data-bs-toggle="tooltip"]').tooltip({trigger: 'hover', 1800 html: true, 1801 placement: 'bottom', 1802 sanitize: false}); 1803 }, 1804 initTradingOpportunities:function(type){ 1805 /* The request parameters for the theScreener stocks up / downgrades */ 1806 var parameters = { 1807 country: '', 1808 sector: '' 1809 }; 1810 1811 /* The type of list that we want to display */ 1812 if(type){ 1813 $('a#tab' + type).trigger('click'); 1814 } 1815 1816 /* The list of select boxes */ 1817 $("div#thescreener-trading-opportunities-select-box-row div.webfg-select-box").each(function(){ 1818 var paramName = $(this).find('button').data('param'); 1819 var selected = $(this).find('button').data('selected'); 1820 1821 if(paramName && paramName.length > 0){ 1822 parameters[paramName] = selected ? selected : ""; 1823 1824 $(this).find('div.dropdown-menu a').each(function(){ 1825 $(this).on('click', function(e){ 1826 e.preventDefault(); 1827 1828 /* Get the value of the currently selected element and set the parameters object */ 1829 var paramValue = $(this).data('element'); 1830 parameters[paramName] = paramValue ? paramValue : ""; 1831 1832 /* Build the query string */ 1833 var qs = ''; 1834 for(var key in parameters){ 1835 if(qs !== ''){ 1836 qs += '&' 1837 } 1838 qs += key + "=" + parameters[key]; 1839 } 1840 1841 /* Redirect to the requested page */ 1842 window.location = $(this).attr('href') + '?' + qs; 1843 }); 1844 }); 1845 } 1846 }); 1847 1848 $('[data-bs-toggle="tooltip"]').tooltip({html:true}); 1849 }, 1850 handleWebfgContextMenu:function(){ 1851 //need a click event hanlder for clicks outside the context menu 1852 var $dim = $("body > .surrogate") === true ? $("body > .surrogate") : $("<div class='surrogate'></div>").prependTo("body"); 1853 1854 var $contextMenuElem = $('div.webfg-context-menu'); 1855 $contextMenuElem.click(function(e) { 1856 /* Prevent the actual action from being triggered */ 1857 //e.preventDefault(); 1858 var $thisMenu = $(this).find(".contextMenu"); 1859 var $otherMenu = $(".contextMenu").not($thisMenu); 1860 //Close all other dropdowns 1861 $otherMenu.removeClass("open"); 1862 1863 if($thisMenu.hasClass("open")) { 1864 //close this menu 1865 $thisMenu.removeClass("open"); 1866 } else { 1867 //open this menu 1868 $thisMenu.addClass("open"); 1869 $(".surrogate").addClass("active"); 1870 } 1871 1872 }); 1873 //the offcontext click is triggered 1874 $(".surrogate").click(function(e){ 1875 $(".surrogate").removeClass("active"); 1876 $(".contextMenu").removeClass("open"); 1877 }); 1878 //A function within the context menu was clicked 1879 $(".contextMenu a").click(function(e){ 1880 $(".surrogate").removeClass("active"); 1881 $(".contextMenu").removeClass("open"); 1882 }); 1883 1884 /* Handling of the context menu 1885 if($contextMenuElem && $contextMenuElem.length > 0) { 1886 $contextMenuElem.find('a.context-menu-toggle-link').on('click', function(e) { 1887 /* Prevent the actual action from being triggered */ 1888 /* e.preventDefault(); 1889 $(this).siblings('div.contextMenu').toggle(); 1890 }); 1891 }*/ 1892 }, 1893 convertBarcharts: function (selector) { 1894 var cellSelectorClass = 'ytd_perf_pr'; 1895 var barChartClass = 'barchart'; 1896 ((selector === undefined) ? $('table') : (typeof selector === 'string' ? $(selector) : selector)).each(function () { 1897 var table = $(this); 1898 var isMainField = true; 1899 var containsNested = false;
1900 var barChartHeader = table.find('> thead > tr > th.' + cellSelectorClass); 1901 if (!barChartHeader.length) { 1902 barChartHeader = table.find('> thead > tr > th.nested > div.nested > span.' + cellSelectorClass); 1903 if (barChartHeader.length) { 1904 isMainField = false; 1905 } else { 1906 // No BarChart in this table .. 1907 return; 1908 } 1909 } else { 1910 containsNested = barChartHeader.hasClass('nested'); 1911 } 1912 barChartHeader.addClass(barChartClass); 1913 if (table.hasClass('streamingTable')) { 1914 // Update streaming renderer .. 1915 if (barChartHeader.data('r') === 'default' || barChartHeader.data('r') === undefined) { 1916 barChartHeader.data('r', 'BarChart'); 1917 } 1918 } 1919 var dataCells; 1920 if (isMainField) { 1921 dataCells = table.find('> tbody > tr > td.' + cellSelectorClass); 1922 } else { 1923 dataCells = table.find('> tbody > tr > td.nested > div.nested > span.' + cellSelectorClass); 1924 } 1925 var maxValue = 0; 1926 dataCells.each(function () { 1927 var rawValue = parseFloat($(this).data('raw')); 1928 if (!isNaN(rawValue)) { 1929 $(this).data('parsed', rawValue); 1930 //I dont get that....this guy made a master...but this code does not make sense to me.... 1931 if (rawValue < 0) { 1932 rawValue = -rawValue; 1933 } 1934 if (rawValue > maxValue) { 1935 maxValue = rawValue; 1936 } 1937 } else { 1938 $(this).data('parsed', 0); 1939 } 1940 }).addClass(barChartClass); 1941 if (maxValue > 0) { 1942 dataCells.each(function () { 1943 var cell = $(this), currentValue = cell.data('parsed'); 1944 var container = containsNested ? cell.find('> div:first') : cell; 1945 container.attr('title', $.trim(container.text())).data('maxValue', maxValue).removeClass('pos neg eq').empty(); 1946 var html = isMainField ? '<div/>' : '<span/>'; 1947 var negBar = $(html).addClass("float-end barChartNeg").hide(); 1948 var posBar = $(html).addClass("float-start barChartPos").hide(); 1949 var cellTitle = cell.attr("title"); 1950 var cellTitleClass = 'pos'; 1951 if(currentValue < 0){ 1952 cellTitleClass = 'neg' 1953 } 1954 container 1955 .append($(html).addClass(cellTitleClass).append(cellTitle)) 1956 .append($(html).addClass('width50P float-start').append(negBar)) 1957 .append($(html).addClass('width50P float-end').append(posBar)) 1958 if (currentValue > 0.0000001) { 1959 posBar.css("width", Math.max(currentValue / maxValue * 100, 5).toFixed(0) + "%").show(); 1960 } else if (currentValue < -0.0000001) { 1961 negBar.css("width", Math.max(-currentValue / maxValue * 100, 5).toFixed(0) + "%").show(); 1962 } 1963 }); 1964 } 1965 }) 1966 }, 1967 patchLightboxAjaxLinks: function (linkElements, defaultDialogOptions, defaultAjaxOptions, forceDataType) { 1968 linkElements.each(function (i, a) { 1969 a = $(a); 1970 if (a.data('patched')) { 1971 return; 1972 } 1973 a.data('patched', true); 1974 var title = a.data('title'); 1975 var loadingText = a.data('loading-text') || ''; 1976 var dialogOptionsName = a.data('dialog-options') || defaultDialogOptions || ''; 1977 var ajaxOptionsName = a.data('ajax-options') || defaultAjaxOptions || ''; 1978 var dialogOptions = window[dialogOptionsName]; 1979 if (!dialogOptions) { 1980 dialogOptions = {}; 1981 } 1982 var ajaxOptions = window[ajaxOptionsName]; 1983 if (!ajaxOptions) { 1984 ajaxOptions = { 1985 error: function(jqXHR, textStatus, errorThrown) {
1986 this.find('.modal-body').text(errorThrown); 1987 } 1988 }; 1989 } 1990 if (forceDataType) { 1991 ajaxOptions.dataType = forceDataType; 1992 } 1993 var url = a.attr('href'); 1994 a.prop('href', '#'); 1995 a.click(function (e) { 1996 e.preventDefault(); 1997 e.stopPropagation(); 1998 // Bind lightbox .. 1999 $.fn.lightBoxAjax({url: url, title: title, dialogOptions: dialogOptions, ajaxOptions: ajaxOptions, loadingText: loadingText}); 2000 }); 2001 }); 2002 }, 2003 initCBOE: function(cur, isin, market, isCBOE, portfolioId) { 2004 // The current currency, isin and marketId come from a solidListing! 2005 var ajaxUserPref = $().trading().userPreferences(); 2006 $.when(ajaxUserPref).done(function (dataPref) { 2007 var userPreferences = Array.isArray(dataPref) ? dataPref[0] : dataPref; 2008 var ajaxTradingForm = $().trading().tradingForm(cur, isin, market, userPreferences.language, portfolioId); 2009 $.when(ajaxTradingForm).done(function (dataTradingForm) { 2010 tradingForm = Array.isArray(dataTradingForm) ? dataTradingForm[0] : dataTradingForm; 2011 cboeSpread = tradingForm.spreadCboeWarningShown; 2012 2013 if (portfolioId != null && tradingForm.tradingPosition !== undefined) { 2014 $('nav.nav-thirdLevel').hide(); 2015 if (tradingForm.tradingPosition.quantity !== undefined) 2016 $('#quantityPosition').html(tradingForm.tradingPosition.quantity); 2017 if (tradingForm.tradingPosition.available !== undefined) 2018 $('#availablePosition').html(tradingForm.tradingPosition.available); 2019 if (tradingForm.tradingPosition.value !== undefined && tradingForm.tradingPosition.value.value !== undefined) 2020 $('#amountPosition').html(tradingForm.tradingPosition.value.value.toFixed(2) + ' ' + tradingForm.tradingPosition.value.currency.isoCode); 2021 $('nav.nav-thirdLevel').show(); 2022 2023 if ($("#sellradio").is(":checked")) { 2024 /* only for sell! set in quantity form if exist! */ 2025 var availablePosition = $('#availablePosition'); 2026 if (availablePosition.length > 0) { 2027 $('#quantity').val(availablePosition.html()); 2028 } 2029 } 2030 } 2031 2032 $('div.short-name.cboeQualifier').html(tradingForm.marketMapping.exchangeName); 2033 if(tradingForm.showOsirisQuote) { 2034 $('#lastQuoteValue').hide(); 2035 $('.lastQuoteDate').hide(); 2036 $('.nc2_subfield_data').hide(); 2037 const date = new Date(tradingForm.osirisQuote.price.date); 2038 const year = date.getFullYear();
2039 const month = (date.getMonth() + 1).toString().padStart(2, '0'); 2040 const day = date.getDate().toString().padStart(2, '0'); 2041 const lang = document.documentElement.lang; 2042 if (lang.includes('en')) { 2043 var englishFormathDate = month + '/' + day + '/' + year; 2044 $('#osirisQuoteDate').html(englishFormathDate); 2045 $('#osirisQuoteDate').show(); 2046 } else { 2047 var otherFormatDate = day + '.' + month + '.' + year; 2048 $('#osirisQuoteDate').html(otherFormatDate); 2049 $('#osirisQuoteDate').show(); 2050 } 2051 if (tradingForm.osirisQuote.price.isPercent == "true") { 2052 $('#osirisQuoteValue').html(tradingForm.osirisQuote.price.value + '%'); 2053 $('#osirisQuoteValue').show(); 2054 } else { 2055 $('#osirisQuoteValue').html(tradingForm.osirisQuote.price.amount.value); 2056 $('#osirisQuoteValue').show(); 2057 } 2058 } 2059 2060 var $warningOrderTradingForm = $('#warningOrderTradingForm'); // already hide! 2061 var $warningMsgOrderTradingForm = $('#warningMsgOrderTradingForm'); 2062 if(tradingForm.delayedOrderMarket){ 2063 $warningMsgOrderTradingForm.html(labelsError['delayedOrderMarket']); 2064 $warningOrderTradingForm.show(); 2065 }else if(tradingForm.pennyStocksMarket){ 2066 $warningMsgOrderTradingForm.html(labelsError['pennyStocksMarket']); 2067 $warningOrderTradingForm.show(); 2068 } 2069 2070 if (isCBOE) { 2071 var ajaxMe = $().trading().me(); 2072 $.when(ajaxMe).then(function (dataMe) { 2073 var me = Array.isArray(dataMe) ? dataMe[0] : dataMe; 2074 me.qualifiers.forEach(function (entry) { 2075 if (entry.includes("CBOEQuotationEligible")) { 2076 cboeQualifier = true; 2077 } 2078 }); 2079 2080 if (userPreferences.showCBOE === true) { 2081 cboePreferences = true; 2082 } 2083 //if CBOEQuotationEligible is false or CBOEQuotationEligible is available but isCBOE data is not 2084 // available display old view 2085 if (!cboeQualifier || (cboeQualifier && !isCBOE)) { 2086 return; 2087 } else { 2088 if (cboeQualifier) { 2089 $('.cboe-div-container div.cboSwitch').show(); 2090 } 2091 $('.cboe-span-dataType').show(); 2092 } 2093 if (cboePreferences && cboeQualifier && isCBOE && !cboeExclusion) { 2094 $('.cboe-div-container div.cboSwitch :checkbox').click(); 2095 $('.cboe-div-container span.market-tooltip-name button.cboe-tooltip-icon.spread-tooltip-off').show(); 2096 2097 if (cboeSpread) { 2098 $('h5.spread-h5').show(); 2099 $('button.spread-tooltip-on').show(); 2100 $('button.spread-tooltip-off').hide(); 2101 $('div.spread').addClass('spread-div'); 2102 $('table#index-details-header-table-cboe').addClass('spread-color'); 2103 $('div.screenerBlock').addClass('spread-screenerBlock'); 2104 $('#index-details-header-quotes-row.webfg .widthContainer #index-detail
2104s-header-table tbody tr td').addClass('spread-table-td'); 2105 $('#index-details-header-quotes-row.webfg .widthContainer #index-details-header-table-cboe tbody tr td').addClass('spread-table-td'); 2106 } 2107 } else if (((cboeExclusion && cboePreferences) || (!cboePreferences && !cboePreferences)) && cboeQualifier && isCBOE) { 2108 $('.cboe-info-div h5.realTime').hide(); 2109 $('.cboe-info-div h5.defered').show(); 2110 $('.marketName').html(tradingForm.marketMapping.name); 2111 $('.marketName').prop('title', tradingForm.marketMapping.name); 2112 } 2113 2114 2115 }).fail(function () { 2116 console.log("No Data to display cboe"); 2117 }); 2118 } 2119 }).fail(function (xhr) { 2120 $('div.market-tooltip-main.headerAlternative').show(); 2121 $('div.market-tooltip-main.headerAlternativeLogged').hide(); 2122 console.log("No Data to display tradingform"); 2123 tradingForm = {}; 2124 xhrSolid = xhr; 2125 }); 2126 }).fail(function () { 2127 console.log("No Data to display userPreferences"); 2128 }); 2129 }, 2130 switchCBOEFuncionality: function () { 2131 $('table.noCboe').removeClass('bt'); 2132 $('table.isCboe').removeClass('bt'); 2133 if($('.switch :checkbox').is(":checked")) { 2134 //display cboe table 2135 $('.isCboe').show(); 2136 $('.noCboe').hide(); 2137 //modify title for cboe table 2138 $('.marketName').html('CBOE'); 2139 $('.marketName').prop('title', 'CBOE'); 2140 //display realtime for cboe table 2141 $('table#index-details-header-table-cboe').show(); 2142 $('table#index-details-header-table').hide(); 2143 //change the trend arrow if is cbeo data 2144 $('div.webfg-trend.trendIsCBOE').show(); 2145 $('div.webfg-trend.trendNoCBOE').hide(); 2146 $('.cboe-info-div h5.timeCboe').show(); 2147 $('.cboe-info-div h5.timeNormal').hide(); 2148 //switch on or off the spread style. 2149 if(cboeSpread) { 2150 $('h5.spread-h5').show(); 2151 $('button.spread-tooltip-on').show(); 2152 $('button.spread-tooltip-off').hide(); 2153 $('div.spread').addClass('spread-div'); 2154 $('table#index-details-header-table-cboe').addClass('spread-color'); 2155 $('div.screenerBlock').addClass('spread-screenerBlock'); 2156 $('#index-details-header-quotes-row.webfg .widthContainer #index-details-header-table tbody tr td').addClass('spread-table-td'); 2157 $('#index-details-header-quotes-row.webfg .widthContainer #index-details-header-table-cboe tbody tr td').addClass('spread-table-td'); 2158 } else{ 2159 $('button.spread-tooltip-off').show(); 2160 } 2161 } else { 2162 $('.noCboe').show(); 2163 $('.isCboe').hide(); 2164 $('.marketName').html(tradingForm.marketMapping.name); 2165 $('.marketName').prop('title', tradingForm.marketMapping.name); 2166 $('table#index-details-header-table-cboe').hide(); 2167 $('table#index-details-header-table').show(); 2168 $('div.webfg-trend.trendIsCBOE').hide(); 2169 $('div.webfg-trend.trendNoCBOE').show(); 2170 $('.cboe-info-div h5.timeCboe').hide(); 2171 $('.cboe-info-div h5.timeNormal').show(); 2172 if(cboeSpread) { 2173 $('h5.spread-h5').hide(); 2174 $('button.spread-tooltip-on').hide(); 2175 $('div.spread').removeClass('spread-div'); 2176 $('table#index-details-header-table-cboe').removeClass('spread-color'); 2177 $('div.screenerBlock').removeClass('spread-screenerBlock');
2178 $('#index-details-header-quotes-row.webfg .widthContainer #index-details-header-table tbody tr td').removeClass('spread-table-td'); 2179 $('#index-details-header-quotes-row.webfg .widthContainer #index-details-header-table-cboe tbody tr td').removeClass('spread-table-td'); 2180 } else { 2181 $('button.spread-tooltip-off').hide(); 2182 } 2183 } 2184 2185 }, 2186 returnPlaylist: function(hasPlaylistId){ 2187 if(hasPlaylistId){ 2188 $('nav.nav-thirdLevel.playlistNav').removeClass("d-none"); 2189 }else{ 2190 $('nav.nav-thirdLevel.playlistNav').addClass("d-none"); 2191 } 2192 2193 } 2194 } 2195})(jQuery); 2196 2197var dialogOptionsNews = { 2198 //width:700, 2199 height:600, 2200 modal:true, 2201 draggable:false, 2202 resizable:false 2203}; 2204 2205var dialogOptionsAddInstrument = { 2206 modal:true, 2207 height:400, 2208 width:600 2209}; 2210 2211var modalDialogOptions = { 2212 modal:true 2213}; 2214 2215var ajaxOptionsPortfolioAddInstrument = { 2216 success:function () { 2217 var forward = $('#context').val(); 2218 $("#elasticSearch").solidFastSearch({ 2219 query:{ 2220 fields: "M_NAME,M_SYMB,M_ISIN,M_MARKET:value:description,SC_GROUPED:value:description,M_CUR:value:description,M_BC", 2221 flavor: "EQU,OPT,BON,FON,ETF,TFO", 2222 size: 15, 2223 useWildcards: true 2224 }, 2225 action: function(context) { 2226 if (context.highlighted) { 2227 var listingId = context.highlighted.data('listing'); 2228 if (listingId) { 2229 window.location = Application.contextPath() + "/portfolio/add/instrumentToThisPortfolio/" + $("#portfolioId").val() + "/" + listingId +"?context="+forward; 2230 } 2231 } 2232 }, 2233 alignElement: $("#elasticSearch").closest('.input-group') 2234 }); 2235 } 2236}; 2237 2238var ajaxOptionsWatchlistAddInstrument = { 2239 success:function () { 2240 var path = "/watchlist/add/listing/"; 2241 var suffix = ''; 2242 if ($("#context").val() == "show") { 2243 suffix = '?context=show'; 2244 } 2245 $("#elasticSearch").solidFastSearch({ 2246 query:{ 2247 fields: "M_NAME,M_SYMB,M_ISIN,M_MARKET:value:description,SC_GROUPED:value:description,M_CUR:value:description,M_BC", 2248 // Same flavors as in Solid.initElasticSearch .. 2249 flavor: "EQU,IND,BON,ETF,FON,TFO,CUR,COM,INT,OPT,DER,FUT,TER,CTR,DIV", 2250 size: 15, 2251 useWildcards: true 2252 }, 2253 action: function(context) { 2254 if (context.highlighted) { 2255 var listingId = context.highlighted.data('listing'); 2256 if (listingId) { 2257 window.location = Application.contextPath() + path + $("#watchlistId").val() + "/" + 2258 encodeURIComponent(listingId) + suffix; 2259 } 2260 } 2261 }, 2262 alignElement: $("#elasticSearch").closest('.input-group') 2263 }); 2264 } 2265}; 2266 2267var flyoutMenuSettings = { 2268 content:"Dummy Content", 2269 current:undefined, 2270 show:{ 2271 solo: true, 2272 event:'mouseover' 2273 }, 2274 hide:{ 2275 fixed:true, 2276 delay:500 2277 }, 2278 position:{ 2279 viewport:$(window) 2280 }, 2281 style:{ 2282 classes:"ui-tooltip-blue ui-tooltip-no-padding", 2283 tip:{ 2284 corner:false 2285 } 2286 } 2287}; 2288(function ($) { 2289 'use strict'; 2290 var DATA_KEY = '.solidTable'; 2291 2292 var DEFAULTS = { 2293 autoPagingAndFiltering: true, // -> shorthand for {pagination: true, filtering: true} 2294 sDom: "<'row'<'col-sm-12'<'pull-right'f><'pull-left'l>r<'clearfix'>>>t<'row'<'col-sm-12'<'pull-left'i><'pull-right'p><'clearfix'>>>", 2295 2296 // Columns (custom settings) .. 2297 columns: undefined, 2298 2299 // Filtering .. 2300 filtering: false, // Don't use filtering by default .. (i.e. if autoPagingAndFiltering = false) 2301 filterDelay: 350, 2302 resetPageOnFiltering: false, // Set page to 0 on/after filtering .. 2303 2304 // Sorting .. 2305 sort: true, 2306 specifySortableColumns: false, // true = sortable columns must be specified explicitly, false = not sortable columns must be specified explicitly! 2307 sortingUrl: undefined, 2308 sortData: {}, // -> This is always sent to the server .. 2309 sortDataAttribute: 'raw', 2310 initiallySorted: false, 2311 indicesOnTop: true, 2312 2313 // Paging .. 2314 displayLength: 25, 2315 pagination: false, // Don't use paging by default .. (i.e. if autoPagingAndFiltering = false) 2316 2317 // Renderer for setRowData method .. 2318 rowRenderer: undefined, 2319 cellRenderer: undefined, 2320 2321 // Server-side paging & data .. 2322 dataUrl: undefined, 2323 totalLength: undefined, 2324 2325 // Could the data potentially change during lifecycle .. 2326 dynamicData: false, 2327 2328 oLanguage : { 2329 //sSearch: 'Search', 2330 oPaginate:{ 2331 sPrevious: 'Previous', 2332 sNext: 'Next', 2333 sLast: 'Last', 2334 sFirst: 'First' 2335 }, 2336 sInfoThousands: '\''//, 2337 // 2338 ////sLengthMenu: 'Show _MENU_ elements', 2339 // 2340 //sZeroRecords: 'No data', // -> Empty row text (due to filtering) .. 2341 //sEmptyTable: 'No data available in the table', // -> Empty-row text .. 2342 // 2343 //sInfo: '_START_ to _END_ of _TOTAL_ records', 2344 //sInfoEmpty: 'No entries', 2345 //sInfoFiltered: '(filtered out of _MAX_ entries)', // -> Suffix added to sInfo 2346 //sInfoPostFix: '', 2347 //sInfoThousands: '\'', 2348 // 2349 // 2350 //sLoadingRecords: 'Loading', // -> On ajax request .. 2351 //sProcessing: 'Please wait' // -> When sorting / filtering .. 2352 } 2353 2354 // TODO: Should we introduce a creation callback ? 2355 }; 2356 2357 var methods = { 2358 setRowData: function(rowData, options) { 2359 var tableData = this.data(DATA_KEY); 2360 var body = createRows(tableData, rowData); 2361 var settings = $.extend({ 2362 resetFilter: true, 2363 resetSort: false, 2364 resetPage: true 2365 }, options); 2366 // Update filtering .. 2367 tableData.rows = body.find('> tr'); 2368 if (tableData.filter) { 2369 // Filtering feature is enabled .. 2370 if (settings.resetFilter) { 2371 tableData.filter.clear(); 2372 } else { 2373 tableData.filter.update(true); 2374 } 2375 } else { 2376 // Simply set displayed rows to "all" rows .. 2377 tableData.displayRows = tableData.rows; 2378 tableData.filteredRows = $([]); 2379 } 2380 // Update pageCount .. 2381 if (tableData.pagination) { 2382 tableData.pagination.recalculate(); 2383 // Show correct page .. 2384 if (settings.resetPage) { 2385 tableData.pagination.setPage(0); 2386 } else { 2387 tableData.pagination.updatePage(); 2388 } 2389 } 2390 // Update sort ... 2391 if (tableData.sort) { 2392 var sortSettings = convertSortSettings(tableData.sort.columns, settings.dataSort); 2393 if (sortSettings) { 2394 // Data is sorted -> give visual feedback .. 2395 tableData.sort.setSorted(sortSettings.column, sortSettings.ascending); 2396 } else if (settings.resetSort) { 2397 tableData.sort.setSorted(); 2398 } else {
2399 tableData.sort.update(); 2400 } 2401 } 2402 }, 2403 reload: function(overrides) { 2404 var tableData = this.data(DATA_KEY); 2405 if (tableData.settings.dataUrl) { 2406 // Reload data from server .. 2407 loadDataFromServer(tableData, overrides); 2408 } 2409 }, 2410 destroy: function() { 2411 this.trigger('SolidTable.beforeDestroy'); 2412 var tableData = this.data(DATA_KEY); 2413 tableData.rows.show(); 2414 this.removeData(DATA_KEY); 2415 if (tableData.sort) { 2416 // Remove sort decoration from header .. 2417 tableData.sort.destroy(); 2418 } 2419 if (tableData.filter) { 2420 // TODO: Destroy filter .. ? 2421 } 2422 if (tableData.pagination) { 2423 // TODO: Destroy pagination .. ? 2424 } 2425 tableData.table.insertBefore(tableData.rootElement); 2426 tableData.rootElement.remove(); 2427 this.trigger('SolidTable.destroyed'); 2428 } 2429 }; 2430 2431 /** 2432 * SolidTable plugin. 2433 * @class SolidTable 2434 * @public 2435 * @memberOf $.fn 2436 * @param options 2437 * @returns {*|jQuery} 2438 */ 2439 $.fn.solidTable = function (options) { 2440 if (typeof options === 'string') { 2441 if (methods[options]) { 2442 var args = Array.prototype.slice.call(arguments, 1); 2443 return this.each(function() { 2444 var $table = $(this); 2445 if (!$table.data(DATA_KEY)) { 2446 $.error('Element is not a SolidTable: ' + this); 2447 } 2448 methods[options].apply($table, args); 2449 }); 2450 } else { 2451 $.error('Invalid option: ' + options); 2452 } 2453 } 2454 var baseSettings = prepareBaseSettings(options); 2455 return this.each(function() { 2456 var $table = $(this); 2457 var settings = $.extend({}, baseSettings); 2458 var $rows = $table.find("> tbody > tr"); 2459 var rowCount = $rows.length; 2460 if (settings.dataUrl) { 2461 if (settings.totalLength === undefined) { 2462 $.error('SolidTable: totalLength must be set if dataUrl is set'); 2463 } 2464 rowCount = settings.totalLength; 2465 } 2466 var multiplePage = rowCount > settings.displayLength; 2467 // Enable optional paging & filtering if necessary .. 2468 if (typeof settings.autoPagingAndFiltering === 'object') { 2469 if (settings.autoPagingAndFiltering.pagination) { 2470 settings.pagination = multiplePage; 2471 } 2472 if (settings.autoPagingAndFiltering.filtering) { 2473 settings.filtering = multiplePage; 2474 } 2475 } else if (settings.autoPagingAndFiltering) { 2476 settings.pagination = multiplePage; 2477 settings.filtering = multiplePage; 2478 } 2479 // Apply sort settings provided in table markup ..
2480 if ($table.data('sort') === 0) { 2481 // Disable sorting ... 2482 settings.sort = false; 2483 } else { 2484 if ($table.data('initial-sort')) { 2485 // Apply initial sort settings ... 2486 settings.initiallySorted = $table.data('initial-sort'); 2487 // Make sure no sort is triggered since data is already sorted! 2488 settings.triggerSort = false; 2489 } 2490 if ($table.data('sort-key')) { 2491 settings.sortData.sortKey = $table.data('sort-key'); 2492 } 2493 } 2494 var tableData = { 2495 table: $table, 2496 rows: $rows, 2497 displayRows: $rows, 2498 filteredRows: $([]), 2499 settings: settings, 2500 currentPage: 0 2501 }; 2502 tableData.rows.each(function(i) { 2503 if ($(this).data('fixed')) { 2504 if (!tableData.fixed) { 2505 tableData.fixed = []; 2506 } 2507 tableData.fixed.push({row: this, position: i}); 2508 } 2509 }); 2510 prepareGroups(tableData); 2511 $table.data(DATA_KEY, tableData); 2512 tableData.columns = extractColumnDefinitions(tableData); 2513 if (settings.sort) { 2514 tableData.sort = createSort(tableData); 2515 } 2516 if (settings.pagination || settings.dynamicData && isAutoPagination(settings)) { 2517 tableData.pagination = createPagination(tableData); 2518 if (settings.dynamicData && isAutoPagination(settings) && !multiplePage) { 2519 tableData.pagination.element.hide(); 2520 } 2521 } 2522 if (settings.filtering) { 2523 tableData.filter = createFilter(tableData); 2524 } 2525 layoutElements(tableData); 2526 // TODO: Allow to load initial data from server .. 2527 if (tableData.pagination) { 2528 tableData.pagination.recalculate(); // Calculate number of pages .. 2529 if (!settings.dataUrl) { 2530 tableData.pagination.setPage(0); // Update visible rows & paging visual state .. 2531 } else { 2532 tableData.pagination.update(); // Update visual state of paging .. 2533 } 2534 } 2535 $table.trigger('SolidTable.created'); 2536 }); 2537 }; 2538 2539 function prepareBaseSettings(options) { 2540 // Merge options using deep-merge .. 2541 var baseSettings = $.extend(true, {}, DEFAULTS, options); 2542 if (!baseSettings.sortCallback) { 2543 // Select default sort callback .. 2544 baseSettings.sortCallback = baseSettings.sortingUrl ? $.fn.solidTable.serverSideSort : $.fn.solidTable.defaultSort; 2545 } 2546 // Apply default renderers if none specified .. 2547 if (!baseSettings.rowRenderer) { 2548 baseSettings.rowRenderer = $.fn.solidTable.defaultRowRenderer; 2549 if (!baseSettings.cellRenderer) { 2550 baseSettings.cellRenderer = $.fn.solidTable.defaultCellRenderer; 2551 } 2552 if (!baseSettings.nestedCellRenderer) { 2553 baseSettings.nestedCellRenderer = $.fn.solidTable.defaultNestedCellRenderer; 2554 } 2555 } 2556 return baseSettings; 2557 } 2558 2559 function prepareGroups(tableData) { 2560 var bodyGroups = tableData.table.find('> tbody[data-group]'); 2561 if (bodyGroups.length) { 2562 // There are groups .. 2563 var groups = []; 2564 bodyGroups.each(function(i, body) { 2565 var groupBody = $(body); 2566 var currentGroup; 2567 groupBody.find('> tr').each(function(i) { 2568 if (i == 0) { 2569 // The first row of a group is the "group title row" .. 2570 groups.push(currentGroup = { 2571 key: groupBody.data('group'), 2572 groupBody: groupBody, 2573 groupRow: this, 2574 rows: [] 2575 }); 2576 } else { 2577 if ($(this).data('fixed')) { 2578 if (!currentGroup.fixed) { 2579 currentGroup.fixed = []; 2580 } 2581 currentGroup.fixed.push({row: this, position: i - 1}); 2582 } 2583 currentGroup.rows.push(this); 2584 } 2585 }); 2586 }); 2587 tableData.groups = groups; 2588 // Disable paging .. 2589 tableData.settings.pagination = false;
2590 } 2591 } 2592 2593 function loadDataFromServer(tableData, overrides) { 2594 // Data-Tables compatible ajax request: 2595 tableData.table.trigger('SolidTable.beforeDataRequest'); 2596 var pageNumber; 2597 if (overrides && overrides.pageNumber !== undefined) { 2598 pageNumber = overrides.pageNumber; 2599 } else { 2600 pageNumber = tableData.pagination ? tableData.pagination.getPage() : 0; 2601 } 2602 var sortColumn; 2603 var sortField; 2604 var sortDirection; 2605 var sortSettings; 2606 if (overrides && overrides.sortSettings !== undefined) { 2607 sortSettings = overrides.sortSettings; 2608 } else if (tableData.sort && tableData.sort.sortColumn) { 2609 sortSettings = tableData.sort.getSettings(); 2610 } 2611 if (sortSettings) { 2612 sortColumn = sortSettings.column.index; 2613 sortField = sortSettings.column.fieldName; 2614 if (sortSettings.column.entry != 'value') { 2615 sortField += ':' + sortSettings.column.entry; 2616 } 2617 sortDirection = sortSettings.ascending ? 'asc' : 'desc'; 2618 } 2619 var data = { 2620 iTotalRecords: tableData.settings.totalLength, 2621 iDisplayStart: pageNumber * tableData.settings.displayLength, 2622 iDisplayLength: tableData.settings.displayLength, 2623 iSortCol_0: sortColumn, 2624 sSortField_0: sortField, 2625 sSortDir_0: sortDirection, 2626 sSearch: tableData.filter ? tableData.filter.getFilter() : undefined, 2627 sEcho: 0 2628 }; 2629 var customData = tableData.settings.dataAjaxOptions; 2630 if (typeof customData === 'function') { 2631 customData = tableData.settings.dataAjaxOptions(tableData, overrides); 2632 } 2633 var success = false; 2634 $.ajax($.extend(true, { 2635 type: "GET", 2636 url: tableData.settings.dataUrl, 2637 data: data 2638 }, customData, { 2639 success: function (data/*, textStatus, jqXHR*/) { 2640 if (data) { 2641 var rowCountChanged = (tableData.settings.totalLength != data.iTotalDisplayRecords); 2642 tableData.settings.totalLength = data.iTotalDisplayRecords; 2643 var body = createRows(tableData, data.aaData); 2644 // If data was requested from server, filtering is also done on server .. 2645 tableData.displayRows = tableData.rows = body.find('> tr'); 2646 tableData.filteredRows = $([]); 2647 2648 if (tableData.pagination) { 2649 var oldPageCount = tableData.pageCount; 2650 if (rowCountChanged) { 2651 tableData.pagination.recalculate(); 2652 } 2653 if (tableData.pagination.getPage() != pageNumber) { 2654 // Page number was manually overridden ?? 2655 tableData.pagination.setPage(pageNumber, true); 2656 } else if (rowCountChanged && oldPageCount != tableData.pageCount) { 2657 //if (tableData.pagination.getPage() >= tableData.pageCount) { 2658 // // TODO: This should not be done here!!! 2659 // // Show first page!! 2660 // tableData.pagination.setPage(0); 2661 //} else { 2662 // tableData.pagination.update(); 2663 //} 2664 tableData.pagination.update(); 2665 } 2666 } 2667 tableData.table.trigger('SolidTable.dataRequested'); 2668 success = true; 2669 } else { 2670 success = false; 2671 } 2672 }, 2673 error: function() { 2674 tableData.table.trigger('SolidTable.dataRequestFailed'); 2675 }, 2676 async: false 2677 })); 2678 return success; 2679 } 2680 2681 function extractFieldName(cell, cellDefinition) { 2682 var fieldName = cell.data('k'); 2683 if (fieldName) { 2684 // SOLID field .. 2685 var split = fieldName.split(':'); 2686 var entry = 'value'; 2687 if (split.length > 1) { 2688 fieldName = split[0]; 2689 entry = split[1]; 2690 } 2691 cellDefinition.fieldName = fieldName; 2692 cellDefinition.entry = entry; 2693 } 2694 return cellDefinition; 2695 } 2696 2697 function extractColumnDefinitions(tableData) { 2698 var columnSettings = tableData.settings.columns; 2699 var columns = []; 2700 var sortDefault = !tableData.settings.specifySortableColumns; 2701 tableData.table.find('thead > tr:first > th').each(function(idx) { 2702 var header = $(this); 2703 var columnDefinition = extractFieldName(header, {
2704 index: idx, 2705 element: header 2706 }); 2707 if (header.data('sort') === 0) { 2708 // Sort was disabled in table markup .. 2709 columnDefinition.sortable = false; 2710 } 2711 var nestedFields, nestedFieldSeparator; 2712 if (header.hasClass('nested')) { 2713 nestedFields = []; 2714 header.find('> div.nested > .subfield').each(function(i) { 2715 var cellElement = $(this); 2716 nestedFields.push(extractFieldName(cellElement, { 2717 index: i, 2718 element: cellElement, 2719 cssClass: cellElement.attr('class') 2720 })); 2721 }); 2722 if (nestedFields.length > 1) { 2723 var current = nestedFields[0].element[0]; 2724 var end = nestedFields[1].element[0]; 2725 var separator = $('<div/>'); 2726 while (current.nextSibling && (current = current.nextSibling) !== end) { 2727 separator.append(current.cloneNode(true)); 2728 } 2729 nestedFieldSeparator = separator.html(); 2730 } 2731 } 2732 var overrideSettings; 2733 if (columnSettings) { 2734 // User specified some (additional) column definitions .. 2735 overrideSettings = columnSettings[idx]; 2736 if (!overrideSettings && columnDefinition.fieldName) { 2737 var complexFieldKey = (columnDefinition.fieldName + ':' + columnDefinition.entry); 2738 if (columnDefinition.entry === 'value') { 2739 overrideSettings = columnSettings[columnDefinition.fieldName] || columnSettings[complexFieldKey]; 2740 } else { 2741 overrideSettings = columnSettings[complexFieldKey]; 2742 } 2743 } 2744 } 2745 columns.push($.extend({ 2746 // Default settings (can be overridden) .. 2747 sortable: sortDefault, 2748 sortType: 'natural', 2749 cssClass: header.attr('class'), 2750 nestedFields: nestedFields, 2751 nestedFieldSeparator: nestedFieldSeparator 2752 }, overrideSettings, columnDefinition)); 2753 }); 2754 return columns; 2755 } 2756 2757 // ========= 2758 // Sorting 2759 // ========= 2760 2761 function createSort(tableData) { 2762 // Create column definitions .. 2763 var columns = tableData.columns; 2764 function sortCallback() { 2765 var colIdx = $(this).index(); 2766 var columnInfo = tableData.sort.columns[colIdx]; 2767 var isAscending = columnInfo.element.hasClass('sorting_asc'); 2768 doSort(tableData, columnInfo, !isAscending); 2769 } 2770 $.each(columns, function() { 2771 if (!this.sortable) { 2772 // -> Not sortable .. 2773 return; 2774 } 2775 this.element.addClass('sorting').on('click', sortCallback); 2776 if (typeof $.fn.solidTable.sortValueExtractor[this.sortType] !== 'function') { 2777 $.error('Unsupported sort type: ' + this.sortType); 2778 } 2779 }); 2780 2781 var settings = tableData.settings; 2782 var sortSettings = convertSortSettings(columns, settings.initiallySorted); 2783 if (sortSettings && sortSettings.column) { 2784 if (settings.triggerSort) { 2785 setTimeout(function() { 2786 // Trigger sort .. 2787 doSort(tableData, sortSettings.column, sortSettings.ascending); 2788 }, 0); 2789 } else { 2790 // Just mark specified column as sorted in correct order .. 2791 updateSortColumn(columns, sortSettings.column, sortSettings.ascending); 2792 } 2793 } 2794 2795 return { 2796 indicesOnTop: settings.indicesOnTop, 2797 columns: columns, 2798 sortColumn: sortSettings ? sortSettings.column : undefined, 2799 getSettings: function() { 2800 if (tableData.sort.sortColumn) { 2801 return { 2802 column: tableData.sort.sortColumn, 2803 ascending: !tableData.sort.sortColumn.element.hasClass('sorting_desc') 2804 }; 2805 } 2806 return null; 2807 }, 2808 sort: function(columnIndex) { 2809 if (columns[columnIndex]) { 2810 sortCallback.call(columns[columnIndex].element); 2811 } else { 2812 $.error("Not a sort column: " + columnIndex); 2813 } 2814 }, 2815 update: function() {
2816 // Trigger sort on current sort-column without changing order (asc/desc) .. 2817 if (tableData.sort.sortColumn) { 2818 var isAscending = tableData.sort.sortColumn.element.hasClass('sorting_asc'); 2819 doSort(tableData, tableData.sort.sortColumn, isAscending) 2820 } 2821 }, 2822 setSorted: function(column, ascending) { 2823 // This function is called if the table content was entirely replaced .. 2824 // -> Simply adapt sort-mark of columns .. 2825 updateSortColumn(columns, column, ascending); 2826 tableData.sort.sortColumn = column; 2827 }, 2828 destroy: function() { 2829 $.each(tableData.sort.columns, function() { 2830 this.element.removeClass("sorting sorting_asc sorting_desc").off('click', sortCallback); 2831 }); 2832 delete tableData.sort; 2833 } 2834 } 2835 } 2836 2837 function convertSortSettings(columns, sortSettings) { 2838 var columnIdx; 2839 var field; 2840 var entry = 'value'; 2841 var ascending = true; 2842 2843 function applyField(unparsed) { 2844 field = unparsed; 2845 var split = field.split(':'); 2846 if (split.length > 1) { 2847 field = split[0]; 2848 if (split[1]) { 2849 entry = split[1]; 2850 } 2851 if (split.length > 2) { 2852 ascending = 'desc' != split[2]; 2853 } 2854 } 2855 } 2856 2857 if (sortSettings !== false && sortSettings !== undefined) { 2858 if (typeof sortSettings === 'object') { 2859 if (sortSettings instanceof Array) { 2860 if (sortSettings.length > 0) { 2861 if (typeof sortSettings[0] === 'number') { 2862 columnIdx = sortSettings[0]; 2863 if (sortSettings.length > 1) { 2864 ascending = 'desc' != sortSettings[1]; 2865 } 2866 } else { 2867 if (sortSettings.length > 2) { 2868 // -> ['FIELD', 'entry', order] 2869 field = sortSettings[0]; 2870 entry = sortSettings[1]; 2871 ascending = 'desc' != sortSettings[2]; 2872 } else if (sortSettings.length == 2) { 2873 if (sortSettings[1] == 'asc' || sortSettings[1] == 'desc') { 2874 // -> ['FIELD', order], ['FIELD:entry', order] 2875 applyField(sortSettings[0]); 2876 ascending = 'desc' != sortSettings[1]; 2877 } else { 2878 // -> ['FIELD', 'entry'] .. 2879 field = sortSettings[0]; 2880 entry = sortSettings[1]; 2881 } 2882 } else { 2883 // -> ['FIELD'], ['FIELD:entry'], ['FIELD:entry:order'] .. 2884 applyField(sortSettings[0]); 2885 } 2886 } 2887 } 2888 } else { 2889 field = sortSettings.field; 2890 entry = sortSettings.entry || 'value'; 2891 columnIdx = sortSettings.column; 2892 ascending = 'desc' != sortSettings.order; 2893 } 2894 } else { 2895 if (typeof sortSettings === 'number') { 2896 columnIdx = sortSettings; 2897 } else if (typeof sortSettings === 'string') { 2898 applyField(sortSettings); 2899 } 2900 } 2901 var column; 2902 if (field) { 2903 // Must be a field name .. 2904 for (var i = 0; i < columns.length; ++i) { 2905 if (columns[i] && columns[i].fieldName == field && columns[i].entry == entry) { 2906 column = columns[i]; 2907 break; 2908 } 2909 } 2910 } else if (columnIdx !== undefined) { 2911 // Must be a column number .. 2912 column = columns[columnIdx]; 2913 } 2914 if (column && column.sortable) { 2915 return { 2916 column: column, 2917 ascending: ascending 2918 } 2919 } 2920 } 2921 return null; 2922 } 2923 2924 function doSort(tableData, columnInfo, ascending) { 2925 // Abort current sort operation (if any) .. 2926 if (tableData.sort.activeSort && tableData.sort.activeSort.abort) { 2927 tableData.sort.activeSort.abort(); 2928 } 2929 tableData.table.trigger('SolidTable.beforeSort'); 2930 if (tableData.settings.dataUrl) { 2931 // Special handling for server side paging / sorting .. 2932 // Load new data from server .. 2933 if (loadDataFromServer(tableData, {sortSettings: { 2934 column: columnInfo, 2935 ascending: !columnInfo.element.hasClass('sorting_asc') 2936 }})) { 2937 // Success -> Set new column as sort column .. 2938 tableData.sort.sortColumn = columnInfo; 2939 updateSortColumn(tableData.sort.columns, columnInfo, ascending); 2940 tableData.table.trigger('SolidTable.sorted'); 2941 } else { 2942 // Server data request failed / was cancelled / ... 2943 tableData.table.trigger('SolidTable.sortCancelled'); 2944 } 2945 return; 2946 } 2947 2948 var sortDone = false;
2949 var sortControl = tableData.settings.sortCallback.call(tableData.table, columnInfo.index, ascending, tableData, function(rows) { 2950 sortDone = true; 2951 if (tableData.sort.activeSort) { 2952 delete tableData.sort.activeSort; 2953 } 2954 if (rows !== false) { 2955 // Sort was successful .. 2956 // -> Update table .. 2957 if (tableData.groups) { 2958 $.each(tableData.groups, function(i, group) { 2959 group.rows = rows[i]; 2960 group.groupBody.append($(group.rows)); 2961 }); 2962 } else { 2963 tableData.rows = $(rows); 2964 tableData.table.find('> tbody').append(tableData.rows); 2965 } 2966 // Set the new sort column .. 2967 tableData.sort.sortColumn = columnInfo; 2968 // Visualize sorting on correct column .. 2969 updateSortColumn(tableData.sort.columns, columnInfo, ascending); 2970 // Update filtering (if any) .. 2971 if (tableData.filter) { 2972 tableData.filter.update(); 2973 } else { 2974 tableData.displayRows = tableData.rows; 2975 tableData.filteredRows = $([]); 2976 } 2977 if (tableData.pagination) { 2978 // Update the current page content .. 2979 tableData.pagination.updatePage(); 2980 } 2981 tableData.table.trigger('SolidTable.sorted'); 2982 } else { 2983 tableData.table.trigger('SolidTable.sortCancelled'); 2984 } 2985 }); 2986 if (!sortDone) { 2987 // It's (probably) an asynchronous sort -> save control in order to allow aborting the active sort .. 2988 tableData.sort.activeSort = sortControl; 2989 } 2990 } 2991 2992 function updateSortColumn(columns, column, ascending) { 2993 // Reset any other sort .. 2994 for (var j = 0; j < columns.length; ++j) { 2995 if (columns[j]) { 2996 columns[j].element.removeClass('sorting_asc sorting_desc'); 2997 } 2998 } 2999 if (column) { 3000 // Set correct order on specified column .. 3001 if (ascending) { 3002 column.element.addClass('sorting_asc'); 3003 } else { 3004 column.element.addClass('sorting_desc'); 3005 } 3006 } 3007 } 3008 3009 // Extract the value of a single cell used to sort the table rows ... 3010 $.fn.solidTable.sortValueExtractor = { 3011 natural: function(row, cell, columnInfo, tableData) { 3012 var value = cell.data(tableData.settings.sortDataAttribute); 3013 if (value === undefined) { 3014 value = $.trim(getTexts(cell[0], []).join(' ')).toLowerCase(); 3015 } else if (typeof value === 'string') { 3016 value = value.toLowerCase(); 3017 } 3018 return value; 3019 }, 3020 string: function(row, cell, columnInfo, tableData) { 3021 var value = cell.data(tableData.settings.sortDataAttribute); 3022 if (value === undefined) { 3023 value = $.trim(getTexts(cell[0], []).join(' ')).toLowerCase(); 3024 } else if (typeof value === 'string') { 3025 value = value.toLowerCase(); 3026 } else { 3027 value = value.toString().toLowerCase(); 3028 } 3029 return value; 3030 }, 3031 date: function(row, cell, columnInfo, tableData) { 3032 var value = cell.data(tableData.settings.sortDataAttribute); 3033 if (value === undefined) { 3034 value = $.trim(getTexts(cell[0], []).join(' ')); 3035 } 3036 var indices = []; 3037 if(value){ 3038 for(var i = 0; i < value.length; i++) { 3039 if (value[i].toLowerCase() === "." || value[i].toLowerCase() === "/" ) indices.push(i); 3040 } 3041 } 3042 if(value && indices.length == 2 && value.includes('.')){ 3043 var day = value.split('.')[0];
3044 var month = value.split('.')[1]; 3045 var year = value.split('.')[2]; 3046 return parseFloat(year+month+day); 3047 } 3048 else if(value && value.includes('/') && indices.length == 2){ 3049 var month = value.split('/')[0]; 3050 var day = value.split('/')[1]; 3051 var year = value.split('/')[2]; 3052 return parseFloat(year+month+day); 3053 } 3054 else{ 3055 value = value.toLowerCase(); 3056 } 3057 3058 return value; 3059 }, 3060 dateTime: function(row, cell, columnInfo, tableData) { 3061 var value = cell.data(tableData.settings.sortDataAttribute); 3062 if (value === undefined) { 3063 value = $.trim(getTexts(cell[0], []).join(' ')); 3064 } 3065 3066 if (!value) return value; 3067 3068 var parts = value.split(' '); 3069 var datePart = parts[0]; 3070 var timePart = parts[1] || '00:00'; 3071 3072 var timeComponents = timePart.split(':'); 3073 var hours = timeComponents[0] || '00'; 3074 var minutes = timeComponents[1] || '00'; 3075 3076 var indices = []; 3077 for (var i = 0; i < datePart.length; i++) { 3078 if (datePart[i] === '.' || datePart[i] === '/') indices.push(i); 3079 } 3080 3081 var day, month, year; 3082 3083 if (datePart.includes('.') && indices.length == 2) { 3084 var dateParts = datePart.split('.'); 3085 day = dateParts[0]; 3086 month = dateParts[1]; 3087 year = dateParts[2]; 3088 } else if (datePart.includes('/') && indices.length == 2) { 3089 var dateParts = datePart.split('/'); 3090 month = dateParts[0]; 3091 day = dateParts[1]; 3092 year = dateParts[2]; 3093 } else { 3094 return value.toLowerCase(); 3095 } 3096 3097 var dateObj = new Date( 3098 parseInt(year), 3099 parseInt(month) - 1, 3100 parseInt(day), 3101 parseInt(hours), 3102 parseInt(minutes) 3103 ); 3104 3105 return dateObj.getTime(); 3106 }, 3107 numeric: (function() { 3108 function toNumber(strValue) { 3109 if(strValue == ""){ 3110 return 0; 3111 } 3112 // Undefined, empty string, or non numerical -> Set to: NaN 3113 // TODO: Improve number conversion .. (i.e. strip non-numerical characters) .. 3114 if(strValue.includes("(")){ 3115 strValue=strValue.split("(")[0]; 3116 } 3117 //strValue=strValue.replaceAll('.',''); 3118 strValue=strValue.replaceAll(',',''); 3119 strValue=strValue.replaceAll('\'',''); 3120 3121 let numValue = parseFloat(strValue); 3122 let units = 1; 3123 if(strValue.includes(" M")) units = 1000000; 3124 if(strValue.includes(" B")) units = 1000000000; 3125 if(strValue.includes(" Md")) units = 1000000000000; 3126 3127 let result = numValue * units; 3128 return result; 3129 } 3130 3131 return function(row, cell, columnInfo, tableData) { 3132 var value = cell.data(tableData.settings.sortDataAttribute); 3133 if (value === undefined) { 3134 value = toNumber(getTexts(cell[0], []).join(' ')); 3135 } else if (typeof value !== 'number') { 3136 value = toNumber(value.toString()); 3137 } 3138 return value; 3139 } 3140 })() 3141 }; 3142 3143 $.fn.solidTable.defaultSortComparator = function(a, b, ascending) { 3144 return (ascending ? 1 : -1) * (a.value > b.value ? 1 : (a.value < b.value ? -1 : 0)); 3145 }; 3146 3147 $.fn.solidTable.defaultSort = function(colIdx, ascending, tableData, callback) { 3148 var columnInfo = tableData.sort.columns[colIdx]; 3149 var valueExtractor = $.fn.solidTable.sortValueExtractor[columnInfo.sortType]; 3150 // Get sort data for each row .. 3151 if (tableData.groups) { 3152 var groupRows = []; 3153 $.each(tableData.groups, function(idx, group) { 3154 groupRows.push(sortRows(group, tableData, colIdx, columnInfo, valueExtractor, ascending)); 3155 }); 3156 callback(groupRows); 3157 } else { 3158 callback(sortRows(tableData, tableData, colIdx, columnInfo, valueExtractor, ascending)); 3159 } 3160 }; 3161 3162 function sortRows(container, tableData, colIdx, columnInfo, valueExtractor, ascending) { 3163 var allData = []; 3164 $.each(container.rows, function() { 3165 var row = $(this); 3166 if (!row.data('fixed')) { 3167 var listingId = row.data('l'); 3168 var instrType = row.data('t'); 3169 var cell = row.find('> :eq(' + colIdx + ')'); 3170 allData.push({ 3171 listingId: listingId, 3172 instrType: instrType, 3173 value: valueExtractor.call(tableData.table, row, cell, columnInfo, tableData), 3174 row: this 3175 }); 3176 } 3177 }); 3178 // Sort array of sort data .. 3179 if (tableData.sort.indicesOnTop) { 3180 allData.sort(function(a, b) { 3181 if ((a.instrType === 'IND' || b.instrType === 'IND') && a.instrType !== b.instrType) { 3182 return a.instrType === 'IND' ? -1 : 1; 3183 } 3184 return $.fn.solidTable.defaultSortComparator(a, b, ascending); 3185 }); 3186 } else { 3187 allData.sort(function(a, b) { 3188 return $.fn.solidTable.defaultSortComparator(a, b, ascending); 3189 }); 3190 } 3191 // Extract row elements from sort data .. 3192 var sortedRows = []; 3193 for (var i = 0; i < allData.length; ++i) { 3194 sortedRows.push(allData[i].row); 3195 } 3196 if (container.fixed) { 3197 $.each(container.fixed, function () { 3198 sortedRows.splice(this.position, 0, this.row); 3199 }); 3200 } 3201 return sortedRows; 3202 } 3203 3204 $.fn.solidTable.serverSideSort = function(colIdx, ascending, tableData, callback) { 3205 var columnInfo = tableData.sort.columns[colIdx]; 3206 var valueExtractor = $.fn.solidTable.sortValueExtractor[columnInfo.sortType]; 3207 // Extract data ... 3208 var sortData; 3209 var rowLookup; 3210 if (tableData.groups) { 3211 rowLookup = {}; 3212 sortData = {}; 3213 $.each(tableData.groups, function(idx, group) { 3214 var groupRowLookup = rowLookup[group.key] = []; 3215 sortData[group.key] = extractServerSortData(group, groupRowLookup, tableData, colIdx, columnInfo, valueExtractor); 3216 }); 3217 } else { 3218 rowLookup = []; 3219 sortData = extractServerSortData(tableData, rowLookup, tableData, colIdx, columnInfo, valueExtractor); 3220 } 3221 // Do server-side sorting .. 3222 var sortedRows = false;
3223 return $.ajax({ 3224 type: "POST", 3225 url: tableData.settings.sortingUrl, 3226 data: $.extend({}, tableData.settings.sortData, { 3227 data: JSON.stringify(sortData), 3228 field: columnInfo.fieldName ? (columnInfo.fieldName + ':' + columnInfo.entry) : undefined, 3229 // indicesOnTop: true = indices on top, false = no special sorting .. 3230 indicesOnTop: tableData.sort.indicesOnTop, 3231 asc: ascending, 3232 grouped: !!tableData.groups 3233 }), 3234 success: function (data/*, textStatus, jqXHR*/) { 3235 // Apply sort order .. 3236 if (tableData.groups) { 3237 var groupRows = []; 3238 $.each(tableData.groups, function(idx, group) { 3239 groupRows.push(applyServerSortOrder(group, data[group.key], rowLookup[group.key])); 3240 }); 3241 callback(groupRows); 3242 } else { 3243 callback(applyServerSortOrder(tableData, data, rowLookup)); 3244 } 3245 }, 3246 error: function() { 3247 // -> Returns false if there was an error .. 3248 callback(false); 3249 }, 3250 async: true 3251 }); 3252 }; 3253 3254 function extractServerSortData(container, rowLookup, tableData, colIdx, columnInfo, valueExtractor) { 3255 var listingIds = []; 3256 var instrumentTypes = []; 3257 var cellValues = []; 3258 $.each(container.rows, function() { 3259 var row = $(this); 3260 if (!row.data('fixed')) { 3261 var lid = row.data('l'); 3262 listingIds.push(lid); 3263 instrumentTypes.push(row.data('t')); 3264 var cell = row.find('> :eq(' + colIdx + ')'); 3265 cellValues.push(valueExtractor.call(tableData.table, row, cell, columnInfo, tableData)); 3266 rowLookup.push(this); 3267 } 3268 }); 3269 return { 3270 listingIds: listingIds, 3271 instrumentTypes: instrumentTypes, 3272 values: cellValues 3273 }; 3274 } 3275 3276 function applyServerSortOrder(container, data, rowLookup) { 3277 var sortedRows = []; 3278 $.each(data, function (i, index) { 3279 sortedRows.push(rowLookup[index]); 3280 }); 3281 if (container.fixed) { 3282 $.each(container.fixed, function () { 3283 sortedRows.splice(this.position, 0, this.row); 3284 }); 3285 } 3286 return sortedRows; 3287 } 3288 3289 function getTexts(node, texts) { 3290 if (node.nodeType == 3) { 3291 if (!/^[\s]*$/.test(node.nodeValue)) { 3292 // Split text by whitespaces and add to array of texts .. 3293 texts = texts.concat($.trim(node.nodeValue).split(/[\s]+/)); 3294 } 3295 } else { 3296 for (var i = 0, len = node.childNodes.length; i < len; ++i) { 3297 texts = getTexts(node.childNodes[i], texts); 3298 } 3299 } 3300 return texts; 3301 } 3302 3303 $.fn.solidTable.getCellText = getTexts; 3304 3305 // ======== 3306 // Paging 3307 // ======== 3308 3309 function createPagination(tableData) { 3310 var i18n = tableData.settings.oLanguage.oPaginate; 3311 var mailboxId = document.getElementById("mailBoxTable"); 3312 3313 function createButton(linkClass, title, icon) { 3314 return $('<li/>').append( 3315 $('<a/>') 3316 .addClass('paginate_button ' + linkClass) 3317 .attr('title', title) 3318 .append($('<span/>').addClass('fa fa-' + icon)) 3319 ); 3320 } 3321 3322 var element = $('<div/>').addClass('tablePagination'); 3323 var buttons = { 3324 first: createButton('first', i18n.sFirst, 'backward'), 3325 prev: createButton('previous', i18n.sPrevious, 'chevron-left'), 3326 pages: [$('<li><a></a></li>'), $('<li><a></a></li>'), $('<li><a></a></li>')], 3327 next: createButton('next', i18n.sNext, 'chevron-right'), 3328 last: createButton('last', i18n.sLast, 'forward') 3329 }; 3330 $('<ul/>').addClass('pagination') 3331 .append(buttons.first).append(buttons.prev).append(buttons.pages).append(buttons.next).append(buttons.last) 3332 .appendTo(element); 3333 // Add click handlers .. 3334 buttons.first.find('a').on('click', function() { 3335 !buttons.first.hasClass('disabled') && setPage(0); 3336 }); 3337 buttons.prev.find('a').on('click', function() { 3338 !buttons.prev.hasClass('disabled') && setPage(tableData.currentPage - 1); 3339 }); 3340 buttons.next.find('a').on('click', function() { 3341 !buttons.next.hasClass('disabled') && setPage(tableData.currentPage + 1); 3342 }); 3343 buttons.last.find('a').on('click', function() { 3344 !buttons.last.hasClass('disabled') && setPage(tableData.pageCount - 1); 3345 }); 3346 var directCallback = function() { 3347 !$(this).parent().hasClass('active') && setPage($(this).data('pageIdx')); 3348 }; 3349 $.each(buttons.pages, function() { 3350 this.find('a').on('click', directCallback); 3351 }); 3352 3353 function addOrRemoveClass(elts, className, remove) { 3354 $.each(elts, function() { 3355 if(mailboxId !== null) { 3356 if (remove) { 3357 this.find("a").removeClass(className); 3358 } else { 3359 this.find("a").addClass(className); 3360 } 3361 }else{ 3362 if (remove) { 3363 this.removeClass(className); 3364 } else { 3365 this.addClass(className); 3366 } 3367 } 3368 }); 3369 } 3370 3371 function calculatePageCount() {
3372 // TODO: Support grouped tables .. $table.find('> tbody[data-group]').length > 0 3373 var rowCount = tableData.displayRows.length; 3374 if (tableData.settings.totalLength !== undefined) { 3375 // This property is expected if server-side paging/sorting/filtering is active .. 3376 rowCount = tableData.settings.totalLength; 3377 } 3378 if (tableData.settings.displayLength > 0 && rowCount > 0) { 3379 tableData.pageCount = Math.ceil(rowCount / tableData.settings.displayLength); 3380 } else { 3381 tableData.pageCount = 1; 3382 } 3383 } 3384 3385 function setPage(page, noDataUpdate) { 3386 showPage(page, noDataUpdate); 3387 } 3388 3389 function updatePage() { 3390 showPage(tableData.currentPage); 3391 } 3392 3393 function showPage(pageNumber, noDataUpdate) { 3394 tableData.table.trigger('SolidTable.beforePageUpdate'); 3395 // Make sure page is within interval [0, tableData.pageCount[ 3396 var pageToShow = Math.max(0, Math.min(pageNumber, tableData.pageCount - 1)); 3397 if (tableData.settings.dataUrl) { 3398 // Data comes from the server (i.e. server side sort & pagination) -> we need to acquire the data NOW! 3399 if (!noDataUpdate && !loadDataFromServer(tableData, {pageNumber: pageToShow})) { 3400 return; 3401 } 3402 tableData.currentPage = pageToShow; 3403 } else { 3404 tableData.currentPage = pageToShow; 3405 var settings = tableData.settings; 3406 var rowsPerPage = settings.displayLength < 0 ? tableData.rows.length : settings.displayLength; 3407 var from = tableData.currentPage * rowsPerPage; 3408 var to = from + rowsPerPage; 3409 // .prevObject refers to the original selector -> tableData.rows .. 3410 tableData.displayRows.slice(0, from).hide() 3411 .prevObject.slice(from, to).show() 3412 .prevObject.slice(to).hide(); 3413 } 3414 // Update visuals .. 3415 updatePagination(); 3416 tableData.table.trigger('SolidTable.pageUpdated'); 3417 } 3418 3419 function updatePagination() { 3420 var visiblePages = Math.min(tableData.pageCount, buttons.pages.length); 3421 $.each(buttons.pages, function(i) { 3422 if (i < visiblePages) { 3423 // Don't use this.show() as it has some strange side effects .. 3424 this.removeAttr('style'); 3425 } else { 3426 this.hide(); 3427 } 3428 }); 3429 var fromIdx; 3430 if (tableData.currentPage == 0) { 3431 // First page active .. 3432 fromIdx = 0; 3433 } else if (tableData.currentPage == (tableData.pageCount - 1)) { 3434 // Last page active .. 3435 fromIdx = Math.max(tableData.currentPage - visiblePages + 1, 0); 3436 } else { 3437 // Somewhere in the middle .. 3438 // -> Show active in middle .. 3439 fromIdx = Math.max(tableData.currentPage - Math.floor(visiblePages / 2), 0); 3440 } 3441 addOrRemoveClass([buttons.first, buttons.prev], 'disabled', tableData.currentPage !== 0); 3442 addOrRemoveClass([buttons.next, buttons.last], 'disabled', tableData.currentPage < (tableData.pageCount - 1)); 3443 var thousandsSeparator = tableData.settings.oLanguage.sInfoThousands || ''; 3444 for (var i = 0; i < visiblePages; ++i) { 3445 if (tableData.currentPage == fromIdx + i) { 3446 if(mailboxId !== null) { 3447 buttons.pages[i].find("a").addClass('active'); 3448 }else{ 3449 buttons.pages[i].addClass('active'); 3450 } 3451 } else { 3452 if(mailboxId !== null) { 3453 buttons.pages[i].find("a").removeClass('active'); 3454 }else{ 3455 buttons.pages[i].removeClass('active') 3456 } 3457 } 3458 var displayNumber = fromIdx + i + 1; 3459 if (thousandsSeparator && displayNumber > 999) { 3460 displayNumber = displayNumber.toString().replace(/\B(?=(\d{3})+(?!\d))/g, thousandsSeparator); 3461 } 3462 buttons.pages[i].find('a').text(displayNumber).data('pageIdx', fromIdx + i); 3463 } 3464 } 3465 3466 return { 3467 element: element, 3468 getPage: function() { 3469 return tableData.currentPage; 3470 }, 3471 recalculate: calculatePageCount, // Recalculates the number of displayable pages .. 3472 setPage: setPage, // -> Set the current page & updates the displayed table rows .. 3473 updatePage: updatePage, // -> Updates the displayed table rows .. 3474 update: updatePagination // -> Updates the pagination visuals, not the displayed table rows .. 3475 }; 3476 } 3477 3478 // =========== 3479 // Filtering 3480 // =========== 3481 3482 function createFilter(tableData) { 3483 var element = $('<div/>').addClass('tableFilter'); 3484 var previousFilterString = null; 3485 var timeout = null; 3486 var filterDelay = typeof tableData.settings.filterDelay === 'number' ? Math.max(tableData.settings.filterDelay, 100) : 350; 3487 var filterField = $('<input type="text"/>') 3488 .addClass('form-control input-sm') 3489 .on('keyup', function() { 3490 // Clear previous filtering .. 3491 timeout && clearTimeout(timeout); 3492 // Trigger delayed filtering .. 3493 timeout = setTimeout(function() { 3494 timeout = null; 3495 applyFilter(); 3496 }, filterDelay); 3497 }).appendTo($('<label/>').appendTo(element)); 3498 3499 function applyFilter() { 3500 var filterString = $.trim(filterField.val()); 3501 if (previousFilterString !== filterString) { 3502 tableData.table.trigger('SolidTable.beforeFilter'); 3503 previousFilterString = filterString; 3504 if (tableData.settings.dataUrl) { 3505 var overridings = undefined; 3506 if (tableData.pagination && tableData.settings.resetPageOnFiltering) { 3507 overridings = {pageNumber: 0}; 3508 } 3509 if (loadDataFromServer(tableData, overridings) && tableData.pagination) { 3510 // Update visual state of paging as there could be less total rows now .. 3511 // TODO: We should make sure that the current page corresponds to the page loaded from the server .. !!!! 3512 tableData.pagination.recalculate(); 3513 tableData.pagination.update(); 3514 } 3515 return; 3516 } 3517 3518 if (filterString) { 3519 // Create regex per filter keyword .. 3520 var allRegex = filterString.split(/[\s]+/); 3521 for (var i = 0; i < allRegex.length; ++i) { 3522 allRegex[i] = new RegExp(escapeRegExp(allRegex[i]), "i");
3522 // Ignore case! 3523 } 3524 if (tableData.groups) { 3525 $.each(tableData.groups, function() { 3526 filterRows(this.rows, allRegex, this); 3527 }); 3528 } else { 3529 filterRows(tableData.rows, allRegex, tableData); 3530 } 3531 } else { 3532 // Reset filtering .. 3533 resetFilteredRows(); 3534 } 3535 // Update filtered rows visibility .. 3536 if (tableData.pagination) { 3537 tableData.filteredRows.hide(); 3538 // Recalculate pageCount .. 3539 tableData.pagination.recalculate(); 3540 if (tableData.settings.resetPageOnFiltering) { 3541 // Show first page .. 3542 tableData.pagination.setPage(0); 3543 } else { 3544 // Display the "current" page .. (i.e. maybe there are less pages available after filtering) 3545 tableData.pagination.updatePage(); 3546 } 3547 } else { 3548 if (tableData.groups) { 3549 $.each(tableData.groups, function() { 3550 this.filteredRows.hide(); 3551 this.displayRows.show(); 3552 if (!this.displayRows.length) { 3553 this.groupBody.hide(); 3554 } else { 3555 this.groupBody.show(); 3556 } 3557 }); 3558 } else { 3559 tableData.filteredRows.hide(); 3560 tableData.displayRows.show(); 3561 } 3562 } 3563 tableData.table.trigger('SolidTable.filtered'); 3564 } 3565 } 3566 3567 function filterRows(rows, allRegex, container) { 3568 var visibleRows = []; 3569 var hiddenRows = []; 3570 $.each(rows, function() { 3571 // For each row, find cells and create concatenated string .. 3572 var allTexts = []; 3573 $(this).find('>').each(function() { 3574 allTexts = getTexts(this, allTexts); 3575 }); 3576 var rowString = allTexts.join(' '); 3577 // Check whether row matches all regex patterns .. 3578 var hideRow = false; 3579 $.each(allRegex, function(i, regex) { 3580 if (!regex.test(rowString)) { 3581 hideRow = true; 3582 return false; 3583 } 3584 }); 3585 // Mark row so we can re-apply easily after sort .. 3586 if (hideRow) { 3587 hiddenRows.push(this); 3588 $(this).data('.solidTable.filtered', true); 3589 } else { 3590 $(this).removeData('.solidTable.filtered'); 3591 visibleRows.push(this); 3592 } 3593 }); 3594 container.displayRows = $(visibleRows); 3595 container.filteredRows = $(hiddenRows); 3596 } 3597 3598 function resetFilteredRows() { 3599 if (tableData.groups) { 3600 $.each(tableData.groups, function() { 3601 this.filteredRows = $([]); 3602 this.displayRows = $(this.rows); 3603 this.displayRows.each(function () { 3604 if ($(this).data('.solidTable.filtered')) { 3605 $(this).removeData('.solidTable.filtered'); 3606 } 3607 }); 3608 }); 3609 } else { 3610 tableData.displayRows = tableData.rows; 3611 tableData.filteredRows = $([]); 3612 tableData.rows.each(function () { 3613 if ($(this).data('.solidTable.filtered')) { 3614 $(this).removeData('.solidTable.filtered'); 3615 } 3616 }); 3617 } 3618 } 3619 3620 // Return filter context .. 3621 return { 3622 element: element, 3623 getFilter: function() { 3624 return previousFilterString; 3625 }, 3626 update: function(force) { 3627 if (force) { 3628 // We must re-apply the current filter .. 3629 if (previousFilterString) { 3630 previousFilterString = null; 3631 applyFilter(); 3632 } 3633 } else { 3634 // This function is usually triggered after sorting .. 3635 // (i.e. the rows are still the same, but the order may have changed) 3636 // TODO: Probably not necessary for grouped table since paging is inactive!! 3637 var groups = tableData.groups ? tableData.groups : [tableData]; 3638 $.each(groups, function(i, group) { 3639 var hiddenRows = []; 3640 var visibleRows = []; 3641 $.each(group.rows, function () { 3642 if ($(this).data('.solidTable.filtered')) { 3643 hiddenRows.push(this); 3644 } else { 3645 visibleRows.push(this); 3646 } 3647 }); 3648 group.displayRows = $(visibleRows); 3649 group.filteredRows = $(hiddenRows); 3650 }); 3651 } 3652 }, 3653 clear: function() { 3654 // Clear filter field & reset rows .. 3655 previousFilterString = null; 3656 filterField.val(''); 3657 resetFilteredRows(); 3658 } 3659 }; 3660 } 3661 3662 function escapeRegExp(str) { 3663 return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); 3664 } 3665 3666 // ======== 3667 // Layout 3668 // ======== 3669 3670 function layoutElements(tableData) { 3671 var root = $('<div/>').addClass('solidTableWrapper'); 3672 // Save root object to remove the table decoration on SolidTable destroy .. 3673 tableData.rootElement = root; 3674 var result = $.fn.solidTable.parse(tableData.settings.sDom); 3675 $.each(result.elements, function() { 3676 // Place all elements before root element (i.e. wrapper) .. 3677 root.append(this); 3678 }); 3679 // Now replace special elements .. 3680 if (result.lengthChooser) { 3681 result.lengthChooser.remove(); 3682 } 3683 if (result.information) { 3684 result.information.remove(); 3685 } 3686 if (result.processing) { 3687 result.processing.remove(); 3688 } 3689 if (result.filtering) { 3690 if (tableData.filter) { 3691 result.filtering.replaceWith(tableData.filter.element); 3692 } else { 3693 result.filtering.remove(); 3694 } 3695 } 3696 if (result.pagination) { 3697 if (tableData.pagination) { 3698 result.pagination.replaceWith(tableData.pagination.element); 3699 } else { 3700 result.pagination.remove(); 3701 } 3702 } 3703 // Finally reposition table .. 3704 tableData.table.before(root); 3705 if (result.table) { 3706 result.table.replaceWith(tableData.table); 3707 } 3708 } 3709 3710 $.fn.solidTable.parse = function(domString) { 3711 var rootContext = { 3712 elements: [] 3713 }; 3714 3715 function extractClass(element, domStr, idx) { 3716 var quote = domStr[idx]; 3717 var closeQuoteIdx = domStr.indexOf(quote, idx + 1); 3718 if (closeQuoteIdx < 0) { 3719 $.error('Invalid dom string: ' + domStr + '. Missing closing quote character [' + 3720 quote + '] for class name starting at index ' + idx); 3721 } 3722 var className = $.trim(domStr.substring(idx + 1, closeQuoteIdx)); 3723 if (className.length && className[0] == '#') { 3724 element.attr('id', className.substring(1)); 3725 } else { 3726 element.addClass(className); 3727 } 3728 return closeQuoteIdx; 3729 } 3730 3731 var context = rootContext; 3732 for (var i = 0; i < domString.length; ++i) { 3733 var nextChar = domString[i]; 3734 switch (nextChar) { 3735 case '<': 3736 // Start of tag .. 3737 context = { 3738 parentContext: context, 3739 elements: [],
3740 element: $('<div/>') 3741 }; 3742 break; 3743 case '>': 3744 // End of tag .. 3745 if (context.parentContext) { 3746 // Add elements to context element .. 3747 $.each(context.elements, function() { 3748 context.element.append(this); 3749 }); 3750 // Add current contexts element to parent context element list .. 3751 context.parentContext.elements.push(context.element); 3752 // Restore old context .. 3753 context = context.parentContext; 3754 } else { 3755 $.error('Found unexpected character at index ' + i+": " + nextChar); 3756 } 3757 break; 3758 case '\'': 3759 case '"': 3760 // Start of class name .. 3761 if (!context.element) { 3762 $.error('Invalid syntax for dom string. Found ' + nextChar + ' at index: ' + i); 3763 } 3764 i = extractClass(context.element, domString, i); 3765 break; 3766 case 'l': // Length changing 3767 context.elements.push(rootContext.lengthChooser = $('<div/>')); 3768 break; 3769 case 'f': // Filtering input 3770 context.elements.push(rootContext.filtering = $('<div/>')); 3771 break; 3772 case 't': // The table! 3773 context.elements.push(rootContext.table = $('<div/>')); 3774 break; 3775 case 'i': // Information 3776 context.elements.push(rootContext.information = $('<div/>')); 3777 break; 3778 case 'p': // Pagination 3779 context.elements.push(rootContext.pagination = $('<div/>')); 3780 break; 3781 case 'r': // Processing 3782 context.elements.push(rootContext.processing = $('<div/>')); 3783 break; 3784 default: 3785 $.error('Found unexpected character at index ' + i+": " + nextChar); 3786 break; 3787 } 3788 } 3789 return rootContext; 3790 }; 3791 3792 // =========== 3793 // Rendering 3794 // =========== 3795 // -> dynamic data .. 3796 3797 function createRows(tableData, rowData) { 3798 // TODO: Support grouping .. 3799 if (tableData.groups) { 3800 delete tableData.groups; 3801 } 3802 var table = tableData.table; 3803 var body = $('<tbody/>'); 3804 $.each(rowData, function(i) { 3805 var row = tableData.settings.rowRenderer.call(table, tableData, this, i); 3806 if (row) { 3807 body.append(row); 3808 } 3809 }); 3810 table.find('> tbody').replaceWith(body); 3811 return body; 3812 } 3813 3814 $.fn.solidTable.defaultRowRenderer = function(tableData, rowData, rowIdx) { 3815 var rowElement = $('<tr/>'); 3816 var cellRenderer = tableData.settings.cellRenderer; 3817 $.each(tableData.columns, function() { 3818 var cellData = rowData[this.index] !== undefined ? rowData[this.index] : 3819 (rowData[this.fieldName] !== undefined ? rowData[this.fieldName] : rowData[this.fieldName + ':' + this.entry]); 3820 var cell = cellRenderer.call(tableData.table, tableData, this, rowData, cellData, rowIdx) || $('<td/>'); 3821 rowElement.append(cell); 3822 }); 3823 return rowElement 3824 }; 3825 3826 $.fn.solidTable.defaultCellRenderer = function(tableData, column, rowData, cellData, rowIdx) { 3827 var cell = $('<td/>'); 3828 if (cellData !== undefined) { 3829 if (column.nestedFields) { 3830 // Add class "nested" to cell .. 3831 cell.addClass("nested"); 3832 // Wrap cellData with span element .. 3833 var mainCell = $('<span/>').appendTo(cell); 3834 // Add nested container ..
3835 var nestedContainer = $('<div/>').addClass("nested"); 3836 var nestedData; 3837 if (rowData instanceof Array) { 3838 // The current cell-data must be of type object!!! 3839 nestedData = typeof cellData === 'object' ? cellData.nested : undefined; 3840 mainCell.text(cellData.value); 3841 } else { 3842 nestedData = typeof cellData === 'object' && cellData.nested ? cellData.nested : rowData; 3843 mainCell.text(cellData.value !== undefined ? cellData.value : cellData); 3844 } 3845 if (nestedData) { 3846 var indexed = nestedData !== rowData; 3847 var cellRenderer = tableData.settings.nestedCellRenderer; 3848 $.each(column.nestedFields, function (i) { 3849 if (i > 0) { 3850 nestedContainer.append(column.nestedFieldSeparator); 3851 } 3852 var nestedCellData = (indexed && nestedData[this.index] !== undefined) ? nestedData[this.index] : 3853 (nestedData[this.fieldName] !== undefined ? nestedData[this.fieldName] : nestedData[this.fieldName + ':' + this.entry]); 3854 nestedContainer.append(cellRenderer.call(tableData.table, tableData, column, rowData, cellData, this, nestedCellData, rowIdx)); 3855 }); 3856 } 3857 cell.append(nestedContainer); 3858 } else { 3859 cell.text(cellData); 3860 } 3861 } 3862 if (column.cssClass) { 3863 cell.addClass(column.cssClass); 3864 } 3865 return cell; 3866 }; 3867 3868 $.fn.solidTable.defaultNestedCellRenderer = function(tableData, column, rowData, cellData, nestedField, nestedData/*, rowIdx*/) { 3869 return $('<span/>').addClass(this.cssClass).text(nestedData); 3870 }; 3871 3872 // Defaults .. 3873 3874 $.fn.solidTable.setDefaults = function (options) { 3875 $.extend(true, DEFAULTS, options); 3876 }; 3877 3878})(jQuery); 3879// application.js 3880//--= pre null 3881//--= post solid.service.application.resources.NewLineRemover 3882 3883window.APPLICATION = true; 3884}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.