/*
 * This file contains functions and variables global to the advanced graph page.
 * 
 * $Id: chart_functions_Advanced.js,v 1.5 2010/07/12 13:12:36 trm Exp $
 */

  // old values
  var oldHigh = -1;
  var oldLow = -1;
  var oldPriceChange = -1;
  var oldAvgVolume = -1;
  var oldPerformance = -1;
  // highlight color
  var color = "#FFB000";
  // highlight duration
  var duration = 1500;


  // the selected Time Range (default to 6m) This is first updated by the chart domain
  var selectedTimeRange = "";
  
  var MIN_SLIDER_WIDTH_GIF = 14;
  var MIN_SLIDER_WIDTH = null; // will be filled depending on the values and the gif;

  var displayedMinPercent = 0;
  var displayedMaxPercent = 1;
  var graphAddons = {};
  var renderStyle = "line";
  var domainDatesMap = {}; // for the given date, it contains: domainDatesMap._1d = Date...
  domainDatesMap._max = new Date(0); // oldest possible date

  var startDate = new Date();
  startDate.setFullYear(startDate.getFullYear() - 10);
  domainDatesMap._10y = startDate;
  
  var startDate = new Date();
  startDate.setFullYear(startDate.getFullYear() - 6);
  domainDatesMap._6y = startDate;
  
  var startDate = new Date();
  startDate.setFullYear(startDate.getFullYear() - 5);
  domainDatesMap._5y = startDate;
  
  var startDate = new Date();
  startDate.setFullYear(startDate.getFullYear() - 4);
  domainDatesMap._4y = startDate;
  
  var startDate = new Date();
  startDate.setFullYear(startDate.getFullYear() - 3);
  domainDatesMap._3y = startDate;
  
  var startDate = new Date();
  startDate.setFullYear(startDate.getFullYear() - 2);
  domainDatesMap._2y = startDate;
  
  var startDate = new Date();
  startDate.setFullYear(startDate.getFullYear() - 1);
  domainDatesMap._1y = startDate;
  
  var startDate = new Date();
  startDate.setFullYear(startDate.getFullYear() -1);
  startDate.setMonth(11);
  startDate.setDate(31);
  startDate.setHours(23);
  startDate.setMinutes(59);
  domainDatesMap._ytd = startDate;
  
  var startDate = new Date();
  startDate.setMonth(startDate.getMonth() - 6);
  domainDatesMap._6m = startDate;
  
  var startDate = new Date();
  startDate.setMonth(startDate.getMonth() - 3);
  domainDatesMap._3m = startDate;

  var startDate = new Date();
  startDate.setMonth(startDate.getMonth() - 2);
  startDate.setHours(23);
  startDate.setMinutes(59);
  domainDatesMap._2m = startDate;

  var startDate = new Date();
  startDate.setMonth(startDate.getMonth() - 1);
  startDate.setHours(23);
  startDate.setMinutes(59);
  domainDatesMap._1m = startDate;
  
  var timeRanges = ["1d", "2d", "5d", "10d", "1m", "2m", "3m", "6m", "1y", "2y", "4y", "3y", "6y", "5y", "10y", "max"];
  
  var domainIndexesMap = {};
  domainIndexesMap._1d = [ 0 , 0 ];
  domainIndexesMap._2d = [ 0 , 0 ];
  domainIndexesMap._5d = [ 0 , 0 ];
  domainIndexesMap._10d = [ 0 , 0 ];
  domainIndexesMap._1m = [ 0 , 0 ];
  domainIndexesMap._2m = [ 0 , 0 ];
  domainIndexesMap._3m = [ 0 , 0 ];
  domainIndexesMap._6m = [ 0 , 0 ];
  domainIndexesMap._1y = [ 0 , 0 ];
  domainIndexesMap._ytd = [ 0 , 0 ];
  domainIndexesMap._2y = [ 0 , 0 ];
  domainIndexesMap._3y = [ 0 , 0 ];
  domainIndexesMap._4y = [ 0 , 0 ];
  domainIndexesMap._5y = [ 0 , 0 ];
  domainIndexesMap._6y = [ 0 , 0 ];
  domainIndexesMap._10y = [ 0 , 0 ];
  domainIndexesMap._max = [ 0 , 0 ];
  
  var domainToDaysMap = {"1d":"0",
                         "5d":"5",
                         "10d":"10",
                         "1m":"30",
                         "3m":"90",
                         "6m":"180",
                         "1y":"365",
                         "2y":"730",
                         "3y":"1095",
                         "5y":"1825",
                         "max":"max"};
 
  var updateSelectedPeriodPriceEnabled = false;
  
  var trackBallConnector = null;
  
  function changePeriod(timeRange, skipRedraw) {
    changeGraph(timeRange, skipRedraw);
  };

  function changeGraph(timeRange, skipRedraw) {
    
    // Rewrite the domain in the CSV download link, if present (e.g. Stoxx 2010)
    var csvDownloadLink = dojo.byId("csvDownloadLink");
    if (csvDownloadLink) {
      var newDomain = "180";
      if (domainToDaysMap[timeRange])
        newDomain = domainToDaysMap[timeRange];
      var urlPrefix = csvDownloadLink.href.match(/.+\//)[0];
      var urlSuffix = csvDownloadLink.href.match(/_.+$/)[0];
      csvDownloadLink.href = urlPrefix + newDomain + urlSuffix;
    }
 
    // Continue
    if (! (advancedChart.values_days.id ||
           advancedChart.values_intra.id ||
           advancedChart.values_inter.id )) return; // no values loaded!
    
    var node = dojo.byId("trh_"+selectedTimeRange);
    if (node != null) {
      // change old selected one
      dojo.removeClass(node, "selectedTimeRange");
      dojo.addClass(node, "nonSelectedTimeRange");
    }
    
    selectedTimeRange = timeRange; // save new time range
    
    if (timeRange != "" && (domainDatesMap == null || !domainDatesMap["_"+timeRange])) {
      fillDomainDatesMap();
    }
    
    var biggerTimeRange = "";
    
    if (timeRange != "") {
      
      var index = 0;
      for (; index < timeRanges.length; index++) {
        if (timeRanges[index] == timeRange) break;
      }
      index++; // take the next one
      if (index >= timeRanges.length) index = timeRanges.length - 1;
      biggerTimeRange = timeRanges[index];
      if (timeRange == "ytd") biggerTimeRange = "1y";
      
      var forceType = null;
      if (timeRange=="2m" || timeRange=="max") forceType = "historic";
      if (timeRange=="10d" || timeRange=="1m") forceType = "intermediate";
      
      var arraysToDownloadAndCalculate = advancedChart._chartDataUpdater.calculateAndDownloadDataIfNeeded(
            biggerTimeRange, function () {changeGraph(selectedTimeRange);}, null, forceType
      );
    
      if (arraysToDownloadAndCalculate.arrayOfQueryStringsToDownload.length > 0) {
        return; // Do nothing, first we download the data, and this function is recalled after
      }

      if (arraysToDownloadAndCalculate.arrayOfLineTypesToCalculate.length > 0) {
        for (var i in arraysToDownloadAndCalculate.arrayOfLineTypesToCalculate) {
          var arrayToCalculate = arraysToDownloadAndCalculate.arrayOfLineTypesToCalculate[i];
          advancedChart._chartDataUpdater.calculateData(arrayToCalculate);
        }
      }
    }
    
    advancedChart.chartDrawer.preparePreview();
    advancedChart.chartDrawer.displayInfotxt("Drawing..."); // TODO translate
    
    if (timeRange != "") { // Intraday for less than 10 days
      if (biggerTimeRange == "10d" ||
          biggerTimeRange == "5d"  ||
          biggerTimeRange == "2d"  ||
          biggerTimeRange == "1d") {
        advancedChart.chartDrawer.sliderHelper.setDailyTrackLine();
        advancedChart.values_domain = advancedChart.valuesHelper.cutValuesByDates(
          advancedChart.values_intra, domainDatesMap["_"+biggerTimeRange]
        );
      } else { // Intermediate for 10-day and 1 month
        if (biggerTimeRange == "2m"  ||
            biggerTimeRange == "1m") {
          advancedChart.chartDrawer.sliderHelper.setDailyTrackLine();
          advancedChart.values_domain = advancedChart.valuesHelper.cutValuesByDates(
            advancedChart.values_inter, domainDatesMap["_"+biggerTimeRange]
          );
        } else { // Historic for greater than 1 month
          advancedChart.chartDrawer.sliderHelper.setHistoricalTrackLine();
          advancedChart.values_domain = advancedChart.valuesHelper.cutValuesByDates(
            advancedChart.values_days, domainDatesMap["_"+biggerTimeRange]
          );
        }
        
      }
    }
    
    // use this settimeout to be sure the browser changed the preview text...
    setTimeout(dojo.hitch(this, function() { 
      if (timeRange != "") {
        var startDate = domainDatesMap["_"+timeRange];
        var stopDate = new Date();
        stopDate.setMinutes(59);
        stopDate.setHours(23);
        stopDate.setMilliseconds(999);
        advancedChart.chartDrawer.sliderHelper.moveSliderToDates(startDate, stopDate);
      } else {
        // reset slider to max. Also changes left and right borders of the displayed part
        advancedChart.chartDrawer.sliderHelper.resetSlider();
      }
      
      node = dojo.byId("trh_"+timeRange);
      if (node != null) {
        // change new selected one
        dojo.removeClass(node, "nonSelectedTimeRange");
        dojo.addClass(node, "selectedTimeRange");
      }
      
      if (timeRange != "") {
        // Get the indices corresponding to the start and stop date
        var startIndex = 0; 
        for (;startIndex<advancedChart.values_domain.id.vals.length; startIndex++) {
          if (advancedChart.values_domain.id.vals[startIndex].d > startDate) {
            // hack for 10d to correct the From/To fields
            if (timeRange == "10d" && startIndex>0) startIndex --;
            break;
          }
        }
        var stopIndex = 0; 
        for (;stopIndex<advancedChart.values_domain.id.vals.length; stopIndex++) {
          if (advancedChart.values_domain.id.vals[stopIndex].d > stopDate) {
            break;
          }
        }
        if (stopIndex > 0) stopIndex--;
        domainIndexesMap[ "_" + timeRange ][ 0 ] = startIndex;
        domainIndexesMap[ "_" + timeRange ][ 1 ] = stopIndex;
        updateHTML(startIndex, stopIndex);
      } else {
        //domainIndexesMap[ "_" + selectedTimeRange ][ 0 ] = startIndex;
        //domainIndexesMap[ "_" + selectedTimeRange ][ 1 ] = stopIndex;
        updateHTML(0, advancedChart.values_domain.id.vals.length-1);
      }
  
      advancedChart.draw();  // draw graph, axis, ...
      
      var fullGraphWidth = advancedChart._chartLayout.paddingLeft + 
                        advancedChart._chartLayout.graphWidth + 
                        advancedChart._chartLayout.paddingRight; 
      MIN_SLIDER_WIDTH = Math.max(MIN_SLIDER_WIDTH_GIF, fullGraphWidth / (advancedChart.values_domain.id.vals.length-1) );
    }), 0);
    
  };
  
  function fillDomainDatesMap() {

    if (advancedChart.values_days.id) {
      if (advancedChart.values_days.id.vals.length >= 20) {
        var _20DaysAgo = advancedChart.values_days.id.vals[advancedChart.values_days.id.vals.length-20].date;
        domainDatesMap._20d = _20DaysAgo;
      }
      
      if (advancedChart.values_days.id.vals.length >= 10) {
        var _10DaysAgo = advancedChart.values_days.id.vals[advancedChart.values_days.id.vals.length-10].date;
        domainDatesMap._10d = _10DaysAgo;
      }
      
      if (advancedChart.values_days.id.vals.length >= 5) {
        var _5DaysAgo = advancedChart.values_days.id.vals[advancedChart.values_days.id.vals.length-5].date;
        domainDatesMap._5d = _5DaysAgo;
      }

      if (advancedChart.values_days.id.vals.length >= 2) {
        var _2DaysAgo = advancedChart.values_days.id.vals[advancedChart.values_days.id.vals.length-2].date;
        domainDatesMap._2d = _2DaysAgo;
      }

// getting the intraday date from the historical data does not work for us indices, we can't use this
//      var _today = advancedChart.values_days.id.vals[advancedChart.values_days.id.vals.length-1].date;
//      domainDatesMap._1d = _today;
    } else if (advancedChart.values_intra.id) {
            
      var index = advancedChart.values_intra.id.vals.length-1;
      var days = 0;

      // initializes dates with the first date received in case of two few days
      var firstDay = new Date(advancedChart.values_intra.id.vals[0].d);
      firstDay.setHours(0);
      firstDay.setMinutes(0);
      firstDay.setSeconds(0);
      firstDay.setMilliseconds(0);
      domainDatesMap._10d = firstDay;
      domainDatesMap._5d = firstDay;
      domainDatesMap._2d = firstDay; 

      while (index >= 0) {
        var tmpValue = advancedChart.values_intra.id.vals[index];
        if (tmpValue.newDay) {
          days++;
          if (days == 20) {
            var _20DaysAgo = new Date(tmpValue.d);
            _20DaysAgo.setHours(0);
            _20DaysAgo.setMinutes(0);
            _20DaysAgo.setSeconds(0);
            _20DaysAgo.setMilliseconds(0);
            domainDatesMap._20d = _20DaysAgo;
          } else if (days == 10) {
            var _10DaysAgo = new Date(tmpValue.d);
            _10DaysAgo.setHours(0);
            _10DaysAgo.setMinutes(0);
            _10DaysAgo.setSeconds(0);
            _10DaysAgo.setMilliseconds(0);
            domainDatesMap._10d = _10DaysAgo;
          } else if (days == 5) {
            var _5DaysAgo = new Date(tmpValue.d);
            _5DaysAgo.setHours(0);
            _5DaysAgo.setMinutes(0);
            _5DaysAgo.setSeconds(0);
            _5DaysAgo.setMilliseconds(0);
            domainDatesMap._5d = _5DaysAgo;
          } else if (days == 2) {
            var _2DaysAgo = new Date(tmpValue.d);
            _2DaysAgo.setHours(0);
            _2DaysAgo.setMinutes(0);
            _2DaysAgo.setSeconds(0);
            _2DaysAgo.setMilliseconds(0);
            domainDatesMap._2d = _2DaysAgo;
          }
        }
        index--;
      }

    }
    
    if (advancedChart.values_intra.id) {
      var _today = new Date(advancedChart.values_intra.id.vals[advancedChart.values_intra.id.vals.length-1].d);
      _today.setHours(0);
      _today.setMinutes(0);
      _today.setSeconds(0);
      _today.setMilliseconds(0);
      domainDatesMap._1d = _today;
    }
    
  };
  
  // this function should not be in the function file (it is not called by the user)
  // It is only used by the large chart to update data under it
  function clearHTML() {
    dojo.byId("data_high").innerHTML = "-";
    dojo.byId("data_low").innerHTML = "-";
    dojo.byId("data_change_value").innerHTML = "-";  
    dojo.byId("data_change_value").className = "perf";
    var volumeLabel = dojo.byId("data_volume"); 
    if (volumeLabel)
      volumeLabel.innerHTML = "-";
    var performanceLabel = dojo.byId("data_performance");
    if (performanceLabel)
        performanceLabel.innerHTML = "-";
  };
    
  // this function should not be in the function file (it is not called by the user)
  // It is only used by the large chart to update data under it
  function updateHTML(startIndex, stopIndex) {
          
    
    if ( selectedTimeRange != "" &&
         domainIndexesMap[ "_" + selectedTimeRange ][ 0 ] >= startIndex - 1 && 
         domainIndexesMap[ "_" + selectedTimeRange ][ 0 ] <= startIndex + 1 &&
         domainIndexesMap[ "_" + selectedTimeRange ][ 1 ] >= stopIndex - 1 && 
         domainIndexesMap[ "_" + selectedTimeRange ][ 1 ] <= stopIndex + 1 ) {      
      updateSelectedPeriodPriceEnabled = true;
    } else {      
      updateSelectedPeriodPriceEnabled = false;
    }
            
    // Date
    var vals = updateDates(startIndex, stopIndex);
    var stopVal = vals[1];
    var startVal = vals[0];
    
    // HIGH / LOW
    var minVal = advancedChart.values_displayed.id.vals[advancedChart.values_displayed.id.iForyMin];
    var maxVal = advancedChart.values_displayed.id.vals[advancedChart.values_displayed.id.iForyMax];
    if (maxVal) {
      dojo.byId("data_high").innerHTML = chartGetNiceNumber(maxVal.max, 2)+"<br>"+chartGetNiceDate(maxVal.date);
      // highlight if changed
      if (maxVal.max!=oldHigh) {
        if (oldHigh!=-1) highlight("data_high");
        oldHigh = maxVal.max;
      }
    } else {
      dojo.byId("data_high").innerHTML = "-";
    }
    if (minVal) {
      dojo.byId("data_low").innerHTML = chartGetNiceNumber(minVal.min, 2)+"<br>"+chartGetNiceDate(minVal.date);
      // highlight if changed
      if (minVal.min!=oldLow) {
        if (oldLow!=-1) highlight("data_low");
        oldLow = minVal.min;
      }
    } else {
      dojo.byId("data_low").innerHTML = "-";
    }
    
    var oldClose = advancedChart.values_displayed.id.oldClose;
    while (!oldClose && startIndex < stopIndex) {
      oldClose = advancedChart.values_domain.id.vals[++startIndex].y;
    }
    while (!stopVal.y && startIndex < stopIndex) {
      stopVal = advancedChart.values_domain.id.vals[--stopIndex];
    }
    while (!startVal.y && startIndex < stopIndex) {
      startVal = advancedChart.values_domain.id.vals[++startIndex];
    }
    
    // % CHANGE
    var change = (100 * (stopVal.y - oldClose) / oldClose).toFixed(2);
    var data_change_value = dojo.byId("data_change_value");
    var data_change_cell = dojo.byId("data_change_cell");
    
    if (isNaN(change)) {
      data_change_value.innerHTML = "-"; 
    } else {
      data_change_value.innerHTML = change+"%";
      if (change>0) {
        data_change_cell.className = "perf-pos";
      } else if (change<0) {
        data_change_cell.className = "perf-neg";
      } else {
        data_change_cell.className = "perf";
      }
    }

    // highlight if changed
    if (change!=oldPriceChange) {
      if (oldPriceChange!=-1) highlight("data_change_cell");
      oldPriceChange = change;
    }
    
    // Performance based on total return
    var data_performance = dojo.byId("data_performance");
    var data_performance_cell = dojo.byId("data_performance_cell");

    if (startVal.tr && stopVal.tr && data_performance_cell && data_performance ) {
      var performance = (100 * (stopVal.tr / startVal.tr - 1)).toFixed(2);
      if (isNaN(performance)) {
        data_performance.innerHTML = "-";
      }
      else {
        data_performance.innerHTML = performance+"%";  
        
        if (performance>0) {
          data_performance_cell.className = "perf-pos";
        } else if (performance<0) {
          data_performance_cell.className = "perf-neg";
        } else {
          data_performance_cell.className = "perf";
        }

        // highlight if change
        if (performance!=oldPerformance) {
            if (oldPerformance!=-1) highlight("data_performance_cell");
            oldPerformance = performance;
        }
      }
    }

    // AVERAGE VOLUME
    // For intraday and intermediate, the average is calculated per day, to look like historical avg
    if (advancedChart.values_displayed.id.valuesType == swx.inv.Chart.prototype.statics.INTRADAY
        || advancedChart.values_displayed.id.valuesType == swx.inv.Chart.prototype.statics.INTERMEDIATE) {
      
      var avgVolume = 0;
      var values = advancedChart.values_displayed.id.vals;
      var valsInVolume = 0;
      
      // look for the first index for a new day (should exclude fraction of the first day)
      var start = 0;
      while (start<advancedChart.values_displayed.id.vals.length
              && !advancedChart.values_displayed.id.vals[start].newDay) {
        start ++;
      }
      
      // and the last
      var stop = advancedChart.values_displayed.id.vals.length - 1;
      while (stop>0
              && !advancedChart.values_displayed.id.vals[stop].newDay) {
        stop--;
      }
      
      // if we display less than one day, volume should not be calculated
      // start = stop means that we only have 2 uncomplete days, so volume should be -
      if (start==advancedChart.values_displayed.id.vals.length || stop==0 || stop<=start) {
        valsInVolume = 0;
      } else {
        for (var i=start;i<stop;i++) {
          if (values[i].d && !_isToday(new Date(values[i].d))) {
            if (values[i].newDay) {
              valsInVolume++;
            }
            if (values[i].v) avgVolume += values[i].v;
          }      
        }
      }
      
      var avgVolumeFormated = "-";
      if (valsInVolume!=0) {
        avgVolume /= valsInVolume;
        avgVolumeFormated = chartGetNiceNumber(avgVolume, 0);
      }
      
      var volume = dojo.byId("data_volume");
      if (volume) {
        volume.innerHTML = avgVolumeFormated;
      }
      
      // highlight if changed
      if (avgVolume!=oldAvgVolume) {
        if (oldAvgVolume!=-1) highlight("data_volume");
        oldAvgVolume = avgVolume;
      }
      
    } else {
      var avgVolume = 0;
      var valuesToConsider = advancedChart.values_displayed.id.vals.length;

      // if the last value is for today, ignore its volume in the average
      if (_isToday(stopVal.date)) {
        valuesToConsider -= 1;
      }
      
      for (var i=0; i<valuesToConsider; i++) {
        avgVolume += advancedChart.values_displayed.id.vals[i].v;
      }
      avgVolume /= valuesToConsider;
      
      var avgVolumeFormated = chartGetNiceNumber(avgVolume, 0);
      var volume = dojo.byId("data_volume");
      if (volume) {
        volume.innerHTML = avgVolumeFormated;
      }
      
      // highlight if changed
      if (avgVolume!=oldAvgVolume) {
        if (oldAvgVolume!=-1) highlight("data_volume");
        oldAvgVolume = avgVolume;
      }
      
    }

    
  };
  
  function updateDates(startIndex, stopIndex) {
    var startVal = advancedChart.values_domain.id.vals[startIndex];
    var stopVal = advancedChart.values_domain.id.vals[stopIndex];
    
    // Fill in the "from / to" custom dates
    dijit.byId("periodStartDate").setValue(startVal.date);
    dijit.byId("periodStopDate").setValue(stopVal.date);
              
    return [startVal, stopVal];
  };
  
  /*
   * Highlights the specified nodeName.
   * Color and duration are global constants defined on top of this file. 
   */
  function highlight(nodeName) {
        var anim = common.fx.highlight({node:nodeName, color:color, duration:duration});
        anim.play();
  };
  
  function makeConnects() {
    dojo.connect(dojo.byId("trh_1d"), "onclick", function() {changePeriod("1d");});
    dojo.connect(dojo.byId("trh_5d"), "onclick", function() {changePeriod("5d");});
    dojo.connect(dojo.byId("trh_10d"), "onclick", function() {changePeriod("10d");});
    dojo.connect(dojo.byId("trh_1m"), "onclick", function() {changePeriod("1m");});
    dojo.connect(dojo.byId("trh_3m"), "onclick", function() {changePeriod("3m");});
    dojo.connect(dojo.byId("trh_6m"), "onclick", function() {changePeriod("6m");});
    dojo.connect(dojo.byId("trh_ytd"), "onclick", function() {changePeriod("ytd");});
    dojo.connect(dojo.byId("trh_1y"), "onclick", function() {changePeriod("1y");});
    dojo.connect(dojo.byId("trh_2y"), "onclick", function() {changePeriod("2y");});
    dojo.connect(dojo.byId("trh_3y"), "onclick", function() {changePeriod("3y");});
    dojo.connect(dojo.byId("trh_5y"), "onclick", function() {changePeriod("5y");});
    dojo.connect(dojo.byId("trh_max"), "onclick", function() {changePeriod("max");});
    
    connectSlider();
    
    connectTrackBall();
  };
  
  function connectSlider() {
    
    dojo.connect(dojo.byId("slider_moveMe"), "onmousedown", 
                 function(event) { advancedChart.chartDrawer.sliderHelper.sliderDown.call(
                 advancedChart.chartDrawer.sliderHelper, 
                 event, swx.inv.ChartSliderHelper.prototype.statics.MOVE_SLIDER_MIDDLE)});
    dojo.connect(dojo.byId("slider_btn"), "onmousedown", 
                 function(event) { advancedChart.chartDrawer.sliderHelper.sliderDown.call(
                 advancedChart.chartDrawer.sliderHelper, 
                 event, swx.inv.ChartSliderHelper.prototype.statics.MOVE_SLIDER_MIDDLE)});  // Cheat for IE
    dojo.connect(dojo.byId("leftBorderButton"), "onmousedown", 
                 function(event) { advancedChart.chartDrawer.sliderHelper.sliderDown.call(
                 advancedChart.chartDrawer.sliderHelper, 
                 event, swx.inv.ChartSliderHelper.prototype.statics.MOVE_SLIDER_LEFT)});
    dojo.connect(dojo.byId("rightBorderButton"), "onmousedown", 
                 function(event) { advancedChart.chartDrawer.sliderHelper.sliderDown.call(
                 advancedChart.chartDrawer.sliderHelper, 
                 event, swx.inv.ChartSliderHelper.prototype.statics.MOVE_SLIDER_RIGHT)});
                 
    dojo.connect(dojo.byId("slider_left_button"), "onmousedown", 
                 function(event) { advancedChart.chartDrawer.sliderHelper.sliderLeftButtonDown.call(
                 advancedChart.chartDrawer.sliderHelper, event)});
    dojo.connect(dojo.byId("slider_right_button"), "onmousedown", 
                 function(event) { advancedChart.chartDrawer.sliderHelper.sliderRightButtonDown.call(
                 advancedChart.chartDrawer.sliderHelper, event)});
    dojo.connect(dojo.byId("slider_behind"), "onmousedown", 
                 function(event) { advancedChart.chartDrawer.sliderHelper.sliderBackgroundDown.call(
                 advancedChart.chartDrawer.sliderHelper, event)});
    
  };
  
  function connectTrackBall() {
    
    try { // to avoid errors while reloading the page or another page
      trackBallConnector = 
        dojo.connect(dojo.byId("priceInfo"), "onmousemove", 
                   function(event) {
                           try {
                             advancedChart.chartDrawer.sliderHelper.trackMove.call(
                              advancedChart.chartDrawer.sliderHelper, 
                              event);
                           } catch (err) {} // do nothing, it is probably advancedChart that doesn't exist
                   });
      dojo.style("priceInfo", "visibility", "");
      dojo.style("legendInfo", "visibility", "");
      dojo.style(advancedChart.chartDrawer._axisGridDrawer._trackLineGroup.getNode(), "visibility", "");
    } catch (Exception) {}; // nothing
  	
  };
  
  function disConnectTrackBall() {
    if (trackBallConnector) {
      dojo.disconnect(trackBallConnector);
      dojo.style("priceInfo", "visibility", "hidden");
      dojo.style("legendInfo", "visibility", "hidden");
      dojo.style(advancedChart.chartDrawer._axisGridDrawer._trackLineGroup.getNode(), "visibility", "hidden");
    }
  };
  
  
  function compareIndex(id, indexName) {
    _addOn(id, "idx1", indexName);
  };
  
  function compareSecurity(id) {
    _addOn(id, "idx2", id);
  };
  
  /*
   * Provide additional interfaces to allow repeated indices in STOXX
   */
  function benchmarkIndexA(id, indexName) {
    _addOn(id, "idx1", indexName);
  };
  function benchmarkIndexB(id, indexName) {
    _addOn(id, "idx2", indexName);
  };
  
  
  /**
   * Resets the Chart settings panel
   */
  function _addOn(id, lineType, title) {
    // reload new data every time
    advancedChart._chartDataUpdater.downloadedData[lineType] = null;
    advancedChart.values_intra[lineType] = null;
    advancedChart.values_days[lineType] = null;
    
    advancedChart.chartDrawer.preparePreview();
    if (id == "") {
      // will remove the add-on
      advancedChart.showedLines[lineType] = false;
      advancedChart.draw(true);
      var node = dojo.byId("img_"+lineType);
      if (node) {
        dojo.style(node, "display", "none");
        node.title = null;
      }
      node = dojo.byId("legend_"+lineType);
      if (node) {
        dojo.style(node, "display", "none");
        node.innerHTML = "";
      }
      node = dojo.byId("trash_"+lineType);
      if (node) dojo.style(node, "display", "none");
    } else {
      advancedChart.showedLines[lineType] = id;
      var node = dojo.byId("img_"+lineType);
      if (node) {
        dojo.style(node, "display", "");
        node.title = title;
      }
      node = dojo.byId("legend_"+lineType);
      if (node) {
        dojo.style(node, "display", "");
        node.innerHTML = title;
      }
      node = dojo.byId("trash_"+lineType);
      if (node) dojo.style(node, "display", "");

      // Set the displayed values and redraw (changeGraph calls draw)
      if ("" != selectedTimeRange) {
        changeGraph(selectedTimeRange);
      } else {
        changeCustomPeriod(
          new Date(advancedChart.values_domain.id.vals[0].d),
          new Date(advancedChart.values_domain.id.vals[advancedChart.values_domain.id.vals.length-1].d)
        );
      }
    }
  };
  
  function showVolume(showIt) {
    if ("true" == showIt) {
      advancedChart.chartDrawer.showVolume();
      advancedChart.chartDrawer.drawVolume(advancedChart.graph_values.id.points, advancedChart.values_displayed.id);
    } else {
      advancedChart.chartDrawer.hideVolume();
    }
  };
  
  function idstyle(what) {
    if ((what == swx.inv.ChartDrawer.prototype.statics.LINE_STYLE) 
         && (advancedChart.chartDrawer.renderStyle != swx.inv.ChartDrawer.prototype.statics.LINE_STYLE)) {
      if (advancedChart.chartDrawer.renderStyle == swx.inv.ChartDrawer.prototype.statics.BARS_STYLE) {
      	advancedChart.chartDrawer.hideBars();
      } else if (advancedChart.chartDrawer.renderStyle == swx.inv.ChartDrawer.prototype.statics.CANDLESTICKS_STYLE) {
      	advancedChart.chartDrawer.hideCandles();
      }
      advancedChart.chartDrawer.showLine();
      advancedChart.chartDrawer.renderStyle = swx.inv.ChartDrawer.prototype.statics.LINE_STYLE;
    }

    if ((what == swx.inv.ChartDrawer.prototype.statics.BARS_STYLE) 
         && (advancedChart.chartDrawer.renderStyle != swx.inv.ChartDrawer.prototype.statics.BARS_STYLE)) {
      if (advancedChart.chartDrawer._graphDrawer.graphShapes.idBars == null) {
        advancedChart.chartDrawer.drawBars( advancedChart.graph_values.id.points)
      } else {
      	advancedChart.chartDrawer.showBars();
      }
      if (advancedChart.chartDrawer.renderStyle == swx.inv.ChartDrawer.prototype.statics.CANDLESTICKS_STYLE) {
        advancedChart.chartDrawer.hideCandles();
      }
      if (advancedChart.chartDrawer.renderStyle == swx.inv.ChartDrawer.prototype.statics.LINE_STYLE) {
        advancedChart.chartDrawer.hideLine();
      }
      advancedChart.chartDrawer.renderStyle = swx.inv.ChartDrawer.prototype.statics.BARS_STYLE;
    }
    
    if ((what == swx.inv.ChartDrawer.prototype.statics.CANDLESTICKS_STYLE)
         && (advancedChart.chartDrawer.renderStyle != swx.inv.ChartDrawer.prototype.statics.CANDLESTICKS_STYLE)) {
      if (advancedChart.chartDrawer._graphDrawer.graphShapes.idCandles == null) {
        advancedChart.chartDrawer.drawCandles( advancedChart.graph_values.id.points)
      } else {
      	advancedChart.chartDrawer.showCandles();
      }
      if (advancedChart.chartDrawer.renderStyle == swx.inv.ChartDrawer.prototype.statics.BARS_STYLE) {
      	advancedChart.chartDrawer.hideBars();
      }
      if (advancedChart.chartDrawer.renderStyle == swx.inv.ChartDrawer.prototype.statics.LINE_STYLE) {
        advancedChart.chartDrawer.hideLine();
      }
      advancedChart.chartDrawer.renderStyle = swx.inv.ChartDrawer.prototype.statics.CANDLESTICKS_STYLE;
    }
    
  };
  
  function setCrosshairStyle(style, chart) {
    if (!chart) chart = advancedChart;
    
    // hide crosshairs (small and large)
    dojo.style(dojo.byId("trackBall"), "left", -1000); // Hide the crosshair if no point to display
    chart.chartDrawer._axisGridDrawer._horiTrackLine.applyTransform({ dy: -1000 });
    chart.chartDrawer._axisGridDrawer._vertTrackLine.applyTransform({ dx: -1000 });
          
    chart.chartDrawer.crosshairStyle = style;
  }
  
  function changeCustomPeriod(startDate, stopDate) {
    var today = new Date();
    if (!stopDate || stopDate > today) {
      stopDate = today;
    }
    
    if (startDate > stopDate) {
      alert('startDate is after stopDate!');
      return;
    }
    
    var timeRange = findTimeRangeFromStartDate(startDate);
    
    var arraysToDownloadAndCalculate = advancedChart._chartDataUpdater.calculateAndDownloadDataIfNeeded(
          timeRange, function () {changeCustomPeriod(startDate, stopDate);}, false, false
    );
    
    if (arraysToDownloadAndCalculate.arrayOfQueryStringsToDownload.length > 0) {
      return; // Do nothing, first we download the data, and this function is recalled after
    }
    
    if (arraysToDownloadAndCalculate.arrayOfLineTypesToCalculate.length > 0) {
      for (var i in arraysToDownloadAndCalculate.arrayOfLineTypesToCalculate) {
        var arrayToCalculate = arraysToDownloadAndCalculate.arrayOfLineTypesToCalculate[i];
        advancedChart._chartDataUpdater.calculateData(
          arrayToCalculate
        );
      }
    }
    
    advancedChart.chartDrawer.sliderHelper.setHistoricalTrackLine();
    advancedChart.values_domain = advancedChart.valuesHelper.cutValuesByDates(
      advancedChart.values_days, startDate, stopDate
    );
    changePeriod("");
  };
  
  // this function returns the smallest common timerange that at least contains the startDate.
  function findTimeRangeFromStartDate(startDate) {
    // find timerange needed for this custom period
    var timeRanges = ["_1m", "_3m", "_6m", "_1y", "_2y", "_3y", "_5y", "_max"];
    var j = 0;
    for (j=0; j<timeRanges.length; j++) {
      if (domainDatesMap[timeRanges[j]] <= startDate) break;
    }
    if (j >= timeRanges.length) {
      j = timeRanges.length - 1; // go for max whatever the other date was (even before 1970)
    }
    return timeRanges[j].substring(1);  
  }
  
  isTechnicalIndicatorConnected = false;
  function technicalIndicatorChange() {
    if (isTechnicalIndicatorConnected) {
      return;
    } else {
      // Hack the technical indicator to execute a function every time it is closed
      var p = dijit.byId("fs_techId")._popupWidget;
      if (!p) return;
      isTechnicalIndicatorConnected = true;
      dojo.connect(p, "onChange", technicalIndicatorClosed);
    }
  };
  
  fs_techId_oldValue = "";
  function technicalIndicatorClosed() {
    var indicatorId = dijit.byId("fs_techId").getValue();
    if (indicatorId != fs_techId_oldValue || // value changed
        indicatorId == "SMA" ||             // or special case SMA
        indicatorId == "EMA" ||             // or special case SMA
        indicatorId == "BB"  ||             // or special case BB
        indicatorId == "RSI"  ||             // or special case RSI
        indicatorId == "MOM") {              // or special case MOM
    
      fs_techId_oldValue = indicatorId;
      if (indicatorId == "") {
        removeTechnicalIndicators(true);
      } else if (indicatorId == "SMA") {
        dijit.byId("chartSMADialog").show();
      } else if (indicatorId == "EMA") {
        dijit.byId("chartEMADialog").show();
      } else if (indicatorId == "BB") {
        dijit.byId("chartBBDialog").show();
      } else if (indicatorId == "RSI") {
        dijit.byId("chartRSIDialog").show();
      } else if (indicatorId == "MOM") {
        dijit.byId("chartMOMDialog").show();
      } else {
        removeTechnicalIndicators(true);
        _addOn(indicatorId, "ti1");
      }
    }
  };
  
  function plotSMAs() {
    return plotSMA_EMAs("SMA");
  }
  function plotEMAs() {
    return plotSMA_EMAs("EMA");
  }
  function plotSMA_EMAs(averageType) {
    var techIds = [];
    var icons = [];
    var legends = [];
    
    removeTechnicalIndicators(true);
    advancedChart.chartDrawer.preparePreview();
    
    var isSomethingToDraw = false;
    for (var i=1; i<=3; i++) {
      var period = dijit.byId(averageType+'Period'+i).getValue();
      if (period != null && period.length > 0) {
        isSomethingToDraw = true;
        
        techIds.push(averageType+period);
        var SMAEMALabel = getEMASMAsParamsLabel(defaultConfig.language);
        icons.push(SMAEMALabel[i-1] + " : "+period);
        legends.push(averageType);
      }
    }
    
    if (isSomethingToDraw) {
      prepareTechnicalIndicators(techIds, icons, null, legends);
    }
    
    if ("" != selectedTimeRange) {
      changeGraph(selectedTimeRange);
    } else {
      changeCustomPeriod(
        new Date(advancedChart.values_domain.id.vals[0].d),
        new Date(advancedChart.values_domain.id.vals[advancedChart.values_domain.id.vals.length-1].d)
      );
    }

  }
  
  function plotBBs() {
    removeTechnicalIndicators(true);
    advancedChart.chartDrawer.preparePreview();
    
    var period = dijit.byId('BBPeriod').getValue();
    var sigmaFactor = dijit.byId('BBSigmaFactor').getValue();
    
    if (period != null && period.length > 0 && 
        sigmaFactor != null && sigmaFactor.length > 0) {

      var bbLabel = getBBParamsLabel(defaultConfig.language);
      prepareTechnicalIndicators(["BB"+period+"\t"+sigmaFactor, null, "fake", "fake"], [bbLabel[0] + " : "+period, null, bbLabel[1] + " : "+sigmaFactor], null, ["BB", null, null]);
      
    }
    
    if ("" != selectedTimeRange) {
      changeGraph(selectedTimeRange);
    } else {
      changeCustomPeriod(
        new Date(advancedChart.values_domain.id.vals[0].d),
        new Date(advancedChart.values_domain.id.vals[advancedChart.values_domain.id.vals.length-1].d)
      );
    }
  }
  
  function plotRSI() {
    plotMOM_RSI("RSI", "Relative strength index");
  }
  function plotMOM() {
    plotMOM_RSI("MOM", "Momentum");
  }
  
  function plotMOM_RSI(indicatorType, indicatorNiceName) {
    removeTechnicalIndicators(false);
    advancedChart.chartDrawer.preparePreview();
    
    var period = dijit.byId(indicatorType+"Period").getValue();
    
    if (period != null && period.length > 0) {
      var MOMRSILABEL = getMOMRSIParamsLabel(defaultConfig.language);
      prepareTechnicalIndicators([indicatorType+period], [MOMRSILABEL + " : "+period], indicatorNiceName + " ( "+period+" )");
      
    }
    
    if ("" != selectedTimeRange) {
      changeGraph(selectedTimeRange);
    } else {
      changeCustomPeriod(
        new Date(advancedChart.values_domain.id.vals[0].d),
        new Date(advancedChart.values_domain.id.vals[advancedChart.values_domain.id.vals.length-1].d)
      );
    }
  }
  
  function prepareTechnicalIndicators(techIds, icons, title, legends) {
    
    prepareTechnicalIndicatorsHTML(icons, title, legends);
    
    if (techIds) {
      for (var i=0; i<techIds.length; i++) {
        if (!techIds[i]) continue;
        advancedChart.showedLines["ti"+(i+1)] = techIds[i];
      }
    }
  }
  function prepareTechnicalIndicatorsHTML(icons, title, legends) {
    var node = null;
    if (icons) {
      for (var i=0; i<icons.length; i++) {
        if (!icons[i]) continue;
        node = dojo.byId("img_ti"+(i+1));
        if (node) {
          dojo.style(node, "display", "");
          node.title = icons[i];
        }
        if ( !title && legends[i] ) { // no title, it must be a line
          node = dojo.byId("legend_ti"+(i+1));
          if (node) {
            dojo.style(node, "display", "");
            node.innerHTML = legends[i];
          }
        }
      }
      node = dojo.byId("trash_ti");
      if (node) dojo.style(node, "display", "");
    }
    
    if (title) {
      node = dojo.byId("techIndicator_id");
      if (node) node.innerHTML = title
    }
  }
  
  function removeTechnicalIndicators(alsoRemoveAddon) {
    removeTechnicalIndicatorsHTML();
    
    for (var i=1; i<10; i++) {
      advancedChart.showedLines["ti"+i] = null;
    }
    advancedChart.draw(true);
    
    if (alsoRemoveAddon) {
      advancedChart.chartDrawer._addonDrawer.hideTechnicalIndicator();
    }
  }
  
  function removeTechnicalIndicatorsHTML() {
    // remove icons and eventually downloaded/calculated  things
    for (var i=1; i<=10; i++) {
      var node = dojo.byId("img_ti"+i);
      if (node) {
        dojo.style(node, "display", "none");
        node.title = null;
      }
      node = dojo.byId("legend_ti"+i);
      if (node) {
        dojo.style(node, "display", "none");
        node.innerHTML = "";
      }
      var lineType = "ti"+i;
      advancedChart._chartDataUpdater.downloadedData[lineType] = null;
      advancedChart.values_intra[lineType] = null;
      advancedChart.values_days[lineType] = null;
    }
    var node = dojo.byId("trash_ti");
    if (node) dojo.style(node, "display", "none");
  }
  
  function loadEvents(eventId, checked, language, chart) {
    chart.chartDrawer.hideEvents();
    
    chart.showedEvents[eventId] = checked;
     
    if (chart._chartDataUpdater
          .downloadEventsIfNeeded(eventId, language, function () {loadEvents(eventId, checked, language, chart);})
       ) {
      return; // Do nothing, first we download the data, and this function is recalled after
    }
    chart.chartDrawer.showEvents();

    chart.draw(true);
  };

  // Function called when user clicks on the news icon
  function chartShowNews(divNode) {
    
    if (divNode.events.length == 1) {
      var news = divNode.events[0];
      var niceDate = chartGetNiceDateFromEventDate(new Date(news.d));
      newsContentDisp.showNewsContent(news.dId, news.nId, news.l, niceDate, news.h);
    } else {
            
      dijit.byId("tt_"+divNode.id).close(); // hide tooltip show number of news + click for more
            
      // show a dialog tooltip box
      var chartTT = dijit.byId("chartTT");
      var chartDD = dijit.byId("chartFakeDropdown");
      
      var content = "<table class='chartNewsTooltipDialog' cellpadding='0' cellspacing='0' border='0'>";
      content += getChartShowNewsMultilinesContent(divNode.events);
      content += "</table>";
      
      chartTT.setContent(
        content
      );
      
      dijit.popup.open(
          { parent:chartDD, 
            popup:chartDD.dropDown, 
            around: divNode,
            orient:chartDD.isLeftToRight() ? {BL:"TL", BR:"TR", TL:"BL", TR:"BR"} : {BR:"TR", BL:"TL", TR:"BR", TL:"BL"}
          }
      );
      chartDD._opened = true;
    }
    
  };
  
  
  function getChartShowNewsMultilinesContent(events){
      var content = ""; 
      for (var i=0; i<events.length; i++) {
        var news = events[i];
        var niceDate = chartGetNiceDateFromEventDate(new Date(news.d));  
        var className = (i%2 == 0 ? "row-odd" : "row-even"); 
        content += "<tr class=\"" + className +"\" onmouseover='this.className=\""+ className 
            + "-mouseover\";' onmouseout='this.className=\""+ className +"\"'"
            + "><td class='first'><div class='chartNewsTooltipDialogLine' onclick='newsContentDisp.showNewsContent("
            + news.dId+", "+news.nId+", \""+news.l+"\", \""+niceDate+"\", \""
            + news.h.replace(/\"/g, "\\\"").replace(/'/g,"\\u0027")+"\");' style=\"width: 550px;\" >"
            
            + "<div style=\"width: 100px; float: left; left: 0px; \">"
            + niceDate
            + "</div><div style=\"width: 450px; float: left;\">" 
            + news.h + "</div>"
            
            + "</div></td></tr>";         
      }
      
      return content;
  }
  
  
    function getChartShowMTMultilinesContent(events){
        var content = ""; 
  
        for (var i=0; i<events.length; i++) {
                var MTEvent = events[i];
                var niceDate = chartGetNiceDate(new Date(MTEvent.d));
                
                var className = (i%2 == 0 ? "row-odd" : "row-even"); 
                content += "<tr class=\"" + className +"\" onmouseover='this.className=\""+ className 
                    + "-mouseover\";' onmouseout='this.className=\""+ className +"\"'"
                    + "><td class='first'><div class='chartNewsTooltipDialogLine'"
                    + " onclick='openMTDialog(\"" + MTEvent.fullObject.Id + "\"," +MTEvent.d  + ",\"" +MTEvent.v.replace(/\"/g, "\\\"").replace(/'/g,"\\u0027") + "\")' "
                    + " style=\"width: 400px;\" >"
                    + "<div style=\"width: 65px; float: left; left: 0px; \">"
                    + niceDate
                    + "</div><div style=\"width: 335px; float: left;\">" 
                    + MTEvent.v + "</div>"
                    
                    + "</div></td></tr>";
                    
        }
        return content;          
      }
  
  
  // Function called when user clicks on the news icon
  function chartShowBothNewsAndMT(divNode) {
    
            
      dijit.byId("tt_"+divNode.id).close(); // hide tooltip show number of news + click for more
            
      // show a dialog tooltip box
      var chartTT = dijit.byId("chartTT");
      var chartDD = dijit.byId("chartFakeDropdown");
      
      var content = "<table class='chartNewsTooltipDialog' cellpadding='0' cellspacing='0' border='0'>";
      content += "<tr><td colspan='2' ><div style='padding-left:5px'>"+CHART_HEADER_FOR_EVENT_TYPES.T+"</div><td>";
      content += getChartShowMTMultilinesContent(divNode.managementTransactionEvents);
      content += "<tr><td colspan='2'><div style='padding-left:5px'>" +CHART_HEADER_FOR_EVENT_TYPES.N +"</div><td>";
      content += getChartShowNewsMultilinesContent(divNode.newsEvents);
      content += "</table>";
      
      chartTT.setContent(
        content
      );
      
      dijit.popup.open(
          { parent:chartDD, 
            popup:chartDD.dropDown, 
            around: divNode,
            orient:chartDD.isLeftToRight() ? {BL:"TL", BR:"TR", TL:"BL", TR:"BR"} : {BR:"TR", BL:"TL", TR:"BR", TL:"BL"}
          }
      );
      chartDD._opened = true;
    
  };
 
 function openMTDialog(eventId, eventDate, eventTitle){
        var dialog = dijit.byId("mTransDialog");
        var niceDate = chartGetNiceDate(new Date(eventDate));
        var title; 
        title = niceDate;
        title += " ";
        title += eventTitle;
        dialog.titleNode.innerHTML = title;
        dialog.show();

        var printLinkEl1 = dojo.byId("MTPrintLink1");
        var printLinkEl2 = dojo.byId("MTPrintLink2");
        printLinkEl1.onclick = null;
        printLinkEl2.onclick = null;
        var e = dojo.byId("mTransDialogPane");
        e.innerHTML = "";

        dojo.xhrGet( {
            url         : siteChartConfig.MANAGEMENT_INCLUDE_URL + defaultConfig.language + ".html?id=" + eventId,
            handleAs    : "text",
            timeout         : 15000,      // in miliseconds
            preventCache    : true,

            load: function(response, ioArgs) {
                e.innerHTML = response;

                printLinkEl1.onclick = function(evt) {
                    printTransactionManagement(eventId);
                }
                printLinkEl2.onclick = function(evt) {
                    printTransactionManagement(eventId);
                }


                return response;     
            },      // end load

                error: function(response, ioArgs) {
                e.innerHTML = "Error...." + response + " " + ioArgs.xhr.status;

                return response;
            }       // end error

        } );        // end dojo.xhrGet  
 }
 
 function printTransactionManagement(eventId) {
    var url = siteChartConfig.MANAGEMENT_PRINT_URL + defaultConfig.language + ".html?id=" + eventId;
    var width = 600;
    var height = 800;
    
    var left = (screen.width - width) / 2;
    var top = (screen.height - height) / 2;
    var popup = window.open(url, 'popup',
        "width=" + width + ",height=" + height + ",top=" + top + ",left=" + left + ",resizable=1"
        + "directories=0,location=0,menubar=0,scrollbars=1,status=0,titlebar=0,toolbar=0");
    popup.window.focus();

    return false;
}
  
   // Function called when user clicks on the MT icon
  function chartShowMT(divNode) {
    
    dijit.byId("tt_"+divNode.id).close(); // hide tooltip show number of management transactions + click for more
    if (divNode.events.length == 1){  
        var MTEvent = divNode.events[0];

        openMTDialog(MTEvent.fullObject.Id,MTEvent.d,MTEvent.v);
    }
    else {
                        
      // show a dialog tooltip box
      var chartTT = dijit.byId("chartTT");
      var chartDD = dijit.byId("chartFakeDropdown");
      
      var content = "<table class='chartNewsTooltipDialog' cellpadding='0' cellspacing='0' border='0'>";
      content += getChartShowMTMultilinesContent(divNode.events);
      content += "</table>";
      chartTT.setContent(
        content
      );
      
      dijit.popup.open(
          { parent:chartDD, 
            popup:chartDD.dropDown, 
            around: divNode,
            orient:chartDD.isLeftToRight() ? {BL:"TL", BR:"TR", TL:"BL", TR:"BR"} : {BR:"TR", BL:"TL", TR:"BR", TL:"BL"}
          }
      );
      chartDD._opened = true;
    }
    
  };
  
  function slideSettingsOut() {
    var chartSettingsNode = dojo.byId("chartSettingsLink");
    dojo.style(chartSettingsNode, "backgroundImage", "url(/resources/images/layout/nav_arrow_down.gif)");
    dojo.style(chartSettingsNode, "backgroundPosition", "0px center");
    chartSettingsNode.href = "javascript: slideSettingsIn()";
    
    var slide = dojo.fx.slideTo({node: "chartInputFormDiv",duration: 1000, left: 160, top: 0});
    //dojo.connect(slide, "onEnd", function(){
    //    // something
    //});
    slide.play();
  }

  function slideSettingsIn() {
    var chartSettingsNode = dojo.byId("chartSettingsLink");
    dojo.style(chartSettingsNode, "backgroundImage", "url(/resources/images/layout/nav_arrow_right.gif)");
    dojo.style(chartSettingsNode, "backgroundPosition", "2px center");
    chartSettingsNode.href = "javascript: slideSettingsOut()";
    
    var slide = dojo.fx.slideTo({node: "chartInputFormDiv",duration: 1000, left: 600, top: -140});
    //dojo.connect(slide, "onEnd", function(){
    //    // something
    //});
    slide.play()
  }
  
  function getPeriodTranslation(language){
        if(language == "fr"){
                return "Période";
           }
           else if(language == "de"){ 
                  return "Periode";
           }
           else{
                 return "Period";
          }
  }
  
  function getEMASMAsParamsLabel(language){     
        var period = getPeriodTranslation(language);
        return [period + " 1",period + " 2",period + " 3"];
  }
  

  function getBBParamsLabel(language){
        if(language == "fr"){
                return ["Périodes pour moyenne mobile simple","Facteur de l'écart-type"];
        }
        else if(language == "de"){ 
               return ["Perioden für einfach gleitenden Durchschnitt","Faktor der Standardabweichung"]; 
        }
        else{
               return ["Periods for simple moving average","Factor of standard deviation"]; 
        }                  
    }

   function getMOMRSIParamsLabel(language){
       return getPeriodTranslation(language);
   }
   

/************************************************************************
 *   ZOOM INTO INTRADAY FROM HISTORICAL
 */
 
  function zoomIntoIntermediate(onlyUpdateIfPossible) {

    // if there is any indicator, we have to get more data (in the past)
    // numbers are /9 to get days from hours§
    
    var delayBeforeStart = 0;
    for (var lineType in advancedChart.showedLines) {
      if (advancedChart.showedLines[lineType] && (lineType.indexOf("ti") == 0)) {
              
        var techId = advancedChart.showedLines[lineType];
        if (!techId || techId == "fake") continue;
  
        if ( (techId.indexOf("SMA") == 0 || techId.indexOf("EMA") == 0 ||
              techId.indexOf("RSI") == 0 || techId.indexOf("MOM") == 0) ) {
          
          delayBeforeStart = parseInt(techId.substring(3) / 9);
          
        } else if (techId.indexOf("BB") == 0) {
                
          delayBeforeStart = parseInt(techId.substring(2).split("\t")[0] / 9);
        
        }
      }
    }
    
    // look for dates to display
    var yyyyMMddArrayToShow = [];
    var start = advancedChart.values_displayed.id.vals[0].date.getTime();
    var date = new Date();
    for (i=delayBeforeStart;i>=1;i--) {
      date.setTime(start-i*24*3600*1000);
      yyyyMMddArrayToShow.push(getYYYYMMDDFromRealDate(date));
    }
    
    for (var i=0; i<advancedChart.values_displayed.id.vals.length; i++) {
      var val = advancedChart.values_displayed.id.vals[i];
      yyyyMMddArrayToShow.push(getYYYYMMDDFromVal(val));
    }
        
    //build all query strings to get data for all displayed lines
    var arrayOfDownload = [];
    for (var lineType in advancedChart.showedLines) {
      if (advancedChart.showedLines[lineType] && (lineType.indexOf("ti") != 0)) {
        // return a couple {start;stop} dates according of what to show and what is already downloaded
        var startStopDates = hasToDownloadZoomedDataForLineType(lineType, yyyyMMddArrayToShow, advancedChart.values_inter_zoom);
        
        if (startStopDates!= null) {
          arrayOfDownload.push(
            getQueryStringOfItemToDownload(lineType, startStopDates.start, startStopDates.stop)
          );
          
          // We save the dates in the values_zoomed to know we don't download them again
          if (!advancedChart.values_inter_zoom[lineType]) {
            advancedChart.values_inter_zoom[lineType] = {};
          }
          for (var i=0; i<yyyyMMddArrayToShow.length; i++) {
            advancedChart.values_inter_zoom[lineType][yyyyMMddArrayToShow[i]] = true;
          }
        }        
      }
    }

    if (arrayOfDownload.length > 0) {
      // Download it
      var callbackFunction = function() {
         advancedChart.draw(onlyUpdateIfPossible);
      }
    
      // We have to download some data
      advancedChart._chartDataUpdater.downloadZoomedIntermediateValues(arrayOfDownload, callbackFunction);
      return null;
    }
        
    var arraysToCalculate = getArraysToCalculateForZoomedData();
    if (arraysToCalculate.length > 0) {
      for (var i in arraysToCalculate) {
        var lineType = arraysToCalculate[i];
        if (lineType.indexOf("ti") == 0) {
          calculateDataForTechnicalIndicator(lineType, null, swx.inv.Chart.prototype.statics.INTERMEDIATE);
        }
      }
    }
      
    var startTime = advancedChart.values_displayed.id.vals[0].d;
    var stopTime = advancedChart.values_displayed.id.vals[advancedChart.values_displayed.id.vals.length - 1].d;
    return getFakeDisplayValues(yyyyMMddArrayToShow, advancedChart.values_inter, startTime, stopTime);
    
  }
 
  function zoomIntoIntradayFromHistorical(onlyUpdateIfPossible) {
    
    // remove average volume because we are using intraday values
    /*var volume = dojo.byId("data_volume");
    if (volume) {
        volume.innerHTML = "-";
    }*/
    
    // look for dates to display
    var yyyyMMddArrayToShow = [];
    for (var i=0; i<advancedChart.values_displayed.id.vals.length; i++) {
      var val = advancedChart.values_displayed.id.vals[i];
      yyyyMMddArrayToShow.push(getYYYYMMDDFromVal(val));
    }
        
    //build all query strings to get data for all displayed lines
    var arrayOfDownload = [];
    for (var lineType in advancedChart.showedLines) {
      if (advancedChart.showedLines[lineType] && (lineType.indexOf("ti") != 0)) {
        var startStopDates = hasToDownloadZoomedDataForLineType(lineType, yyyyMMddArrayToShow, advancedChart.values_zoomed);
        if (startStopDates != null) {
          arrayOfDownload.push(
            getQueryStringOfItemToDownload(lineType, startStopDates.start, startStopDates.stop)
          );
          
          // We save the dates in the values_zoomed to know we don't download them again
          if (!advancedChart.values_zoomed[lineType]) {
            advancedChart.values_zoomed[lineType] = {};
          }
          for (var i=0; i<yyyyMMddArrayToShow.length; i++) {
            advancedChart.values_zoomed[lineType][yyyyMMddArrayToShow[i]] = true;
          }
        } 
      }
    }
        
    if (arrayOfDownload.length > 0) {
      // Download it
      var callbackFunction = function() {
         advancedChart.draw(onlyUpdateIfPossible);
      }
    
      // We have to download some data
      advancedChart._chartDataUpdater.downloadZoomedIntradayValues(arrayOfDownload, callbackFunction);
      return null;
    }
    
    var arraysToCalculate = getArraysToCalculateForZoomedData();
    if (arraysToCalculate.length > 0) {
      for (var i in arraysToCalculate) {
        var lineType = arraysToCalculate[i];
        if (lineType.indexOf("ti") == 0) {
          calculateDataForTechnicalIndicator(lineType, null, swx.inv.Chart.prototype.statics.INTRADAY);
        }
      }
    }
      
    var startTime = advancedChart.values_displayed.id.vals[0].d;
    var stopTime = advancedChart.values_displayed.id.vals[advancedChart.values_displayed.id.vals.length - 1].d;
    
    return getFakeDisplayValues(yyyyMMddArrayToShow, advancedChart.values_intra, startTime, stopTime);
  };
  
  getArraysToCalculateForZoomedData = function() {

    var arrayToCalculate = [];

    for (var lineType in advancedChart.showedLines) {
      if (advancedChart.showedLines[lineType]) {
        if (lineType.indexOf("ti") == 0 &&
            hasToCalculateDataForTechnicalIndicator(lineType, advancedChart)) {
            // calculate data, do not download
            arrayToCalculate.push(lineType);
        }
      }
    }
    
    return arrayToCalculate;
  };
          
  hasToDownloadZoomedDataForLineType = function(lineType, yyyyMMddArrayToShow, zoomedDataArray) {
  
    var startStringDate = null;
    var stopStringDate = null;
    
    // Check what we already have...
    
    // Where do we start
    for (var i=0; i<yyyyMMddArrayToShow.length; i++) {
      if (!zoomedDataArray[lineType] || !zoomedDataArray[lineType][yyyyMMddArrayToShow[i]]) {
        startStringDate = yyyyMMddArrayToShow[i];
        break;
      }
    }
    
    // where do we stop
    for (var i=yyyyMMddArrayToShow.length-1; i>=0; i--) {
      if (!zoomedDataArray[lineType] || !zoomedDataArray[lineType][yyyyMMddArrayToShow[i]]) {
        stopStringDate = yyyyMMddArrayToShow[i];
        break;
      }
    }
    
    if (startStringDate) {
      return { start: startStringDate, stop: stopStringDate};
    }
    return null;
  };
  
  getQueryStringOfItemToDownload = function(lineType, startStringDate, stopStringDate) {
    // LineType, start and stop are always needed
    var queryString = "line=" + 
                      lineType +","+ 
                      startStringDate +","+ 
                      stopStringDate;
      
    if (lineType == "id") { // Basic line (add width)
      queryString += ","+ advancedChart._chartLayout.graphWidth;
      
    } else if (lineType.substring(0,3) == "idx") { // comparing to another security (add security id)
      queryString += ","+ advancedChart.showedLines[lineType];
      
    } else if (lineType.substring(0,2) == "ti") { // technical indicator (add technical indicator id)
      queryString += ","+ advancedChart.showedLines[lineType];
      
    }
    return queryString;
  };
  
  getFakeDisplayValues = function(yyyyMMddArrayToShow, dataArray, startTime, stopTime) {
    
    var startDate = new Date(startTime);
    
    // Set the stop date to the end of the day of the stopVal date
    var stopDate = new Date(stopTime);
    stopDate.setHours(23);
    stopDate.setMinutes(59);
    stopDate.setSeconds(59);

    return advancedChart.valuesHelper.cutValuesByDates(dataArray, startDate, stopDate)
  };
  
  getYYYYMMDDFromVal = function(val) {
    var day = val.dayDate;
    if (day < 10) day = "0" + day;
    var month = val.month + 1;
    if (month < 10) month = "0" + month;
    return val.fullyear + "" + month + day;
  };
  
  function getYYYYMMDDFromRealDate(date) {
    var day = date.getDate();
    if (day < 10) day = "0" + day;
    var month = date.getMonth() + 1;
    if (month < 10) month = "0" + month;
    return date.getFullYear() + "" + month + day;
  };
  
  /**
   * Checks if the specified date is today or not.
   * @param date (Date) The date to check.
   */
  function _isToday(date) {
    var today = new Date();
    
    if (today.getFullYear()==date.getFullYear() 
        && today.getMonth()==date.getMonth() 
        && today.getDate()==date.getDate()) {
      return true; 
    }
    else {
      return false;
    }
  }
  
   
  
  

