/*
 * This file contains functions and variables global to the advanced graph page.
 *
 * $Id: chart_functions_Advanced.js,v 1.3 2011/12/21 09:56:56 obo 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", addPX(-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) {
    if (eventId == 'news')
      return;

    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/dojo/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});
    slide.play();
  }

  function slideSettingsIn() {
    var chartSettingsNode = dojo.byId("chartSettingsLink");
    dojo.style(chartSettingsNode, "backgroundImage", "url(/resources/images/dojo/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});
    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;
    }
  }

