ASE Home Page Products Download Purchase Support About ASE
ChartDirector Support
Forum HomeForum Home   SearchSearch

Message ListMessage List     Post MessagePost Message

  Error 800
Posted by Chris on Apr-11-2011 21:15
Hello, I try since 2-3 days to take the zoomIn/zoomOut code and execute that on my localhost. So I can choose pointer, zoomIn zoomOut but when I want to click on the chart an error 800 occurs. Did you already have this problem?
Thanks.

  Re: Error 800
Posted by Peter Kwan on Apr-12-2011 00:34
Hi Chris,

The error 800 means the browser is sending an AJAX chart update request to the server, but the server does not reply with an AJAX response. Normally, the error message will also display what is received from the server instead.

To diagnose the problem, please try the exactly original unmodified sample code "Zooming and Scrolling Demonstration (2)" that comes with ChartDirector. If the original sample code works, it means the ChartDirector Javascript library is installed and working correctly. In this case, we may need to know how you are using the ChartDirector Javascript library in your code.

Normally, in the beginning of your code, it should check if the request is an AJAX chart update request, or if it is a normal HTML request. If it is an AJAX chart update request, your code would need to update the chart and generate an AJAX response. The exact code depends on your programming language and web framework. For example, in PHP, we have the following in the sample code:

# Create the WebChartViewer object
$viewer = new WebChartViewer("chart1");

if ($viewer->isPartialUpdateRequest()) {
    # Is a partial update request (AJAX chart update)
    processPartialUpdate($viewer);
    # Since it is a partial update, there is no need to output the entire web page. We stream the
    # chart and then terminate the script immediately.
    print($viewer->partialUpdateChart());
    exit();
} else if ($viewer->isFullUpdateRequest()) {
    # Is a full update request
    processFullUpdate($viewer);
} else {
    # Is a initial request
    createFirstChart($viewer);
}

If you need further help, would you mind to include your code, so that I can try it myself or just read it to see if I can find any issue?

Regards
Peter Kwan

  Re: Error 800
Posted by Chris on Apr-12-2011 14:34
Attachments:
Hi Peter,

First, thanks for your answer. Actually, I success Zooming and Scrolling Demonstration(1) on my localhost, but only when I execute the PHP simply. But for our project, we need to use it with the Symfony framework and then the sample original code doesn't works.

I attach the code with this post but its really the same, exept paths (pictures, .js and .php) of course.
zoomscrollSuccess.php
<?php
require_once("images\\ChartDirector\\lib\\phpchartdir.php");

#
# We need to handle 3 types of request: - initial request for the full web page - partial update
# (AJAX chart update) to update the chart without reloading the page - full page update for old
# browsers that does not support partial updates
#

# The total date range of all data.
$startDate = null;
$endDate = null;

# The date range of the data that we zoomed into (visible on the chart).
$viewPortStartDate = null;
$viewPortEndDate = null;

#
# Handles the initial request
#
function createFirstChart(&$viewer) {

    global $startDate, $endDate, $viewPortStartDate, $viewPortEndDate;

    # Initialize the Javascript ChartViewer
    $viewer->setMouseUsage(MouseUsageScroll);

    # In this demo, we allow scrolling the chart for the last 5 years
    list($unused, $unused, $unused, $d, $m, $y, $unused, $unused, $unused) = localtime();

    # The localtime month format is from 0 - 11, while the year is offsetted by 1900. We adjust them
    # to human used format.
    $m = $m + 1;
    $y = $y + 1900;

    $endDate = chartTime($y, $m, $d);

    # We roll back 5 years for the start date. Note that if the end date is Feb 29 (leap year only
    # date), we need to change it to Feb 28 in the start year
    if (($m == 2) && ($d == 29)) {
        $d = 28;
    }
    $startDate = chartTime($y - 5, $m, $d);

    # The initial selected date range is last 1 year
    $viewPortStartDate = chartTime($y - 1, $m, $d);
    $viewPortEndDate = $endDate;

    # We store the scroll range as custom Javascript ChartViewer attributes, so the range can be
    # retrieved later in partial or full update requests
    $viewer->setCustomAttr("startDate", $startDate);
    $viewer->setCustomAttr("endDate", $endDate);

    # In this demo, we set the maximum zoom-in to 10 days
    $viewer->setZoomInWidthLimit(10 * 86400 / ($endDate - $startDate));

    # Draw the chart
    drawChart($viewer);
}

#
# Handles partial update (AJAX chart update)
#
function processPartialUpdate(&$viewer) {

    global $startDate, $endDate, $viewPortStartDate, $viewPortEndDate;

    # Retrieve the overall date range from custom Javascript ChartViewer attributes.
    $startDate = $viewer->getCustomAttr("startDate");
    $endDate = $viewer->getCustomAttr("endDate");

    # Now we need to determine the visible date range selected by the user. There are two
    # possibilities. The user may use the zoom/scroll features of the Javascript ChartViewer to
    # select the range, or s/he may use the start date / end date select boxes to select the date
    # range.

    if ($viewer->isViewPortChangedEvent()) {
        # Is a view port change event from the Javascript ChartViewer, so we should get the selected
        # date range from the ChartViewer view port settings.
        $duration = $endDate - $startDate;
        $viewPortStartDate = $startDate + (int)(0.5 + $viewer->getViewPortLeft() * $duration);
        $viewPortEndDate = $viewPortStartDate + (int)(0.5 + $viewer->getViewPortWidth() * $duration)
            ;
    } else {
        # The user has changed the selected range by using the start date / end date select boxes.
        # We need to retrieve the selected dates from those boxes. For partial updates, the select
        # box values are sent in as Javascript ChartViewer custom attributes.
        $startYear = (int)($viewer->getCustomAttr("StartYear"));
        $startMonth = (int)($viewer->getCustomAttr("StartMonth"));
        $startDay = (int)($viewer->getCustomAttr("StartDay"));
        $endYear = (int)($viewer->getCustomAttr("EndYear"));
        $endMonth = (int)($viewer->getCustomAttr("EndMonth"));
        $endDay = (int)($viewer->getCustomAttr("EndDay"));

        # Note that for browsers that do not support Javascript, there is no validation on the
        # client side. So it is possible for the day to exceed the valid range for a month (eg. Nov
        # 31, but Nov only has 30 days). So we set the date by adding the days difference to the 1
        # day of a month. For example, Nov 31 will be treated as Nov 1 + 30 days = Dec 1.
        $viewPortStartDate = chartTime($startYear, $startMonth, 1) + ($startDay - 1) * 86400;
        $viewPortEndDate = chartTime($endYear, $endMonth, 1) + ($endDay - 1) * 86400;
    }

    # Draw the chart
    drawChart($viewer);

    #
    # We need to communicate the new start date / end date back to the select boxes on the browser
    # side.
    #

    # The getChartYMD function retrives the date as an 8 digit decimal number yyyymmdd.
    $startYMD = getChartYMD($viewPortStartDate);
    $endYMD = getChartYMD($viewPortEndDate);

    # Send year, month, day components to the start date / end date select boxes through Javascript
    # ChartViewer custom attributes.
    $viewer->setCustomAttr("StartYear", (int)($startYMD / 10000));
    $viewer->setCustomAttr("StartMonth", (int)($startYMD / 100) % 100);
    $viewer->setCustomAttr("StartDay", $startYMD % 100);
    $viewer->setCustomAttr("EndYear", (int)($endYMD / 10000));
    $viewer->setCustomAttr("EndMonth", (int)($endYMD / 100) % 100);
    $viewer->setCustomAttr("EndDay", $endYMD % 100);
}

#
# Handles full update
#
function processFullUpdate(&$viewer) {
    # A full chart update is essentially the same as a partial chart update. The main difference is
    # that in a full chart update, the start date / end date select boxes are in Form Post
    # variables, while in partial chart update, they are in Javascript ChartViewer custom
    # attributes.
    #
    # So a simple implementation of the full chart update is to copy the Form Post values to the
    # Javascript ChartViewer custom attributes, and then call the partial chart update.

    # Controls to copy
    $ctrls = array("StartYear", "StartMonth", "StartDay", "EndYear", "EndMonth", "EndDay");

    # Copy control values to Javascript ChartViewer custom attributes
    for($i = 0; $i < count($ctrls); ++$i) {
        $viewer->setCustomAttr($ctrls[$i], $_REQUEST[$ctrls[$i]]);
    }

    # Now can use partial chart update
    processPartialUpdate($viewer);
}

#
# Draw the chart
#
function drawChart(&$viewer) {

    global $startDate, $endDate, $viewPortStartDate, $viewPortEndDate;

    #
    # Validate and adjust the view port dates.
    #

    # Verify if the view port dates are within limits
    $totalDuration = $endDate - $startDate;
    $minDuration = $viewer->getZoomInWidthLimit() * $totalDuration;
    if ($viewPortStartDate < $startDate) {
        $viewPortStartDate = $startDate;
    }
    if ($endDate - $viewPortStartDate < $minDuration) {
        $viewPortStartDate = $endDate - $minDuration;
    }
    if ($viewPortEndDate > $endDate) {
        $viewPortEndDate = $endDate;
    }
    if ($viewPortEndDate - $viewPortStartDate < $minDuration) {
        $viewPortEndDate = $viewPortStartDate + $minDuration;
    }

    # Adjust the view port to reflect the selected date range
    $viewer->setViewPortWidth(($viewPortEndDate - $viewPortStartDate) / $totalDuration);
    $viewer->setViewPortLeft(($viewPortStartDate - $startDate) / $totalDuration);

    #
    # Now we have the date range, we can get the necessary data. In this demo, we just use a random
    # number generator. In practice, you may get the data from a database or XML or by other means.
    # (See "Using Data Sources with ChartDirector" in the ChartDirector documentation if you need
    # some sample code on how to read data from database to array variables.)
    #

    # Just a random number generator to generate the data - emulates a table of numbers from
    # startDate to endDate
    $r = new RanTable(127, 4, (int)(0.5 + $totalDuration / 86400) + 1);
    $r->setDateCol(0, $startDate, 86400);
    $r->setCol(1, 150, -10, 10);
    $r->setCol(2, 200, -10, 10);
    $r->setCol(3, 250, -10, 10);

    # Emulate selecting the date range viewPortStartDate to viewPortEndDate. Note that we add one
    # day margin on both ends. It is because we are using daily data, but the view port can cover
    # partial days. For example, the view port end date can be at 3:00am Feb 1, 2006. In this case,
    # we need the data point at Feb 2, 2006.
    $r->selectDate(0, $viewPortStartDate - 86400, $viewPortEndDate + 86400);

    # Emulate getting the random data from the table
    $timeStamps = $r->getCol(0);
    $dataSeriesA = $r->getCol(1);
    $dataSeriesB = $r->getCol(2);
    $dataSeriesC = $r->getCol(3);

    if (count($timeStamps) >= 520) {
        #
        # Zoomable chart with high zooming ratios often need to plot many thousands of points when
        # fully zoomed out. However, it is usually not needed to plot more data points than the
        # pixel resolution of the chart. Plotting too many points may cause the points and the lines
        # to overlap on the same pixel. So rather than increasing resolution, this reduces the
        # clarity of the chart. It is better to aggregate the data first if there are too many
        # points.
        #
        # In our current example, the chart plot area only has 520 pixels in width and is using a 2
        # pixel line width. So if there are more than 520 data points, we aggregate the data using
        # the ChartDirector aggregation utility method.
        #
        # If in your real application, you do not have too many data points, you may remove the
        # following code altogether.
        #

        # Set up an aggregator to aggregate the data based on regular sized slots
        $m = new ArrayMath($timeStamps);
        $m->selectRegularSpacing(count($timeStamps) / 260);

        # For the timestamps, take the first timestamp on each slot
        $timeStamps = $m->aggregate($timeStamps, AggregateFirst);

        # For the data values, take the averages
        $dataSeriesA = $m->aggregate($dataSeriesA, AggregateAvg);
        $dataSeriesB = $m->aggregate($dataSeriesB, AggregateAvg);
        $dataSeriesC = $m->aggregate($dataSeriesC, AggregateAvg);
    }

    #
    # Now we have obtained the data, we can plot the chart.
    #

    #================================================================================
    # Step 1 - Configure overall chart appearance.
    #================================================================================

    # Create an XYChart object 600 x 300 pixels in size, with pale blue (0xf0f0ff) background, black
    # (000000) rounded border, 1 pixel raised effect.
    $c = new XYChart(600, 300, 0xf0f0ff, 0x000000);
    $c->setRoundedFrame();

    # Set the plotarea at (52, 60) and of size 520 x 192 pixels. Use white (ffffff) background.
    # Enable both horizontal and vertical grids by setting their colors to grey (cccccc). Set
    # clipping mode to clip the data lines to the plot area.
    $c->setPlotArea(55, 60, 520, 192, 0xffffff, -1, -1, 0xcccccc, 0xcccccc);
    $c->setClipping();

    # Add a top title to the chart using 15 pts Times New Roman Bold Italic font, with a light blue
    # (ccccff) background, black (000000) border, and a glass like raised effect.
    $textBoxObj = $c->addTitle("Zooming and Scrolling Demonstration", "timesbi.ttf", 15);
    $textBoxObj->setBackground(0xccccff, 0x000000, glassEffect());

    # Add a bottom title to the chart to show the date range of the axis, with a light blue (ccccff)
    # background.
    $textBoxObj = $c->addTitle2(Bottom, sprintf(
        "From <*font=arialbi.ttf*>%s<*/font*> to <*font=arialbi.ttf*>%s<*/font*> (Duration ".
        "<*font=arialbi.ttf*>%s<*/font*> days)", $c->formatValue($viewPortStartDate,
        "{value|mmm dd, yyyy}"), $c->formatValue($viewPortEndDate, "{value|mmm dd, yyyy}"), (int)(
        0.5 + ($viewPortEndDate - $viewPortStartDate) / 86400)), "ariali.ttf", 10);
    $textBoxObj->setBackground(0xccccff);

    # Add a legend box at the top of the plot area with 9pts Arial Bold font with flow layout.
    $legendObj = $c->addLegend(50, 33, false, "arialbd.ttf", 9);
    $legendObj->setBackground(Transparent, Transparent);

    # Set axes width to 2 pixels
    $c->xAxis->setWidth(2);
    $c->yAxis->setWidth(2);

    # Add a title to the y-axis
    $c->yAxis->setTitle("Price (USD)", "arialbd.ttf", 10);

    #================================================================================
    # Step 2 - Add data to chart
    #================================================================================

    #
    # In this example, we represent the data by lines. You may modify the code below if you want to
    # use other representations (areas, scatter plot, etc).
    #

    # Add a line layer for the lines, using a line width of 2 pixels
    $layer = $c->addLineLayer2();
    $layer->setLineWidth(2);

    # Now we add the 3 data series to a line layer, using the color red (ff0000), green (00cc00) and
    # blue (0000ff)
    $layer->setXData($timeStamps);
    $layer->addDataSet($dataSeriesA, 0xff0000, "Product Alpha");
    $layer->addDataSet($dataSeriesB, 0x00cc00, "Product Beta");
    $layer->addDataSet($dataSeriesC, 0x0000ff, "Product Gamma");

    #================================================================================
    # Step 3 - Set up x-axis scale
    #================================================================================

    # Set x-axis date scale to the view port date range. ChartDirector auto-scaling will
    # automatically determine the ticks on the axis.
    $c->xAxis->setDateScale($viewPortStartDate, $viewPortEndDate);

    #
    # In the current demo, the x-axis range can be from a few years to a few days. We can let
    # ChartDirector auto-determine the date/time format. However, for more beautiful formatting, we
    # set up several label formats to be applied at different conditions.
    #

    # If all ticks are yearly aligned, then we use "yyyy" as the label format.
    $c->xAxis->setFormatCondition("align", 360 * 86400);
    $c->xAxis->setLabelFormat("{value|yyyy}");

    # If all ticks are monthly aligned, then we use "mmm yyyy" in bold font as the first label of a
    # year, and "mmm" for other labels.
    $c->xAxis->setFormatCondition("align", 30 * 86400);
    $c->xAxis->setMultiFormat(StartOfYearFilter(), "<*font=bold*>{value|mmm yyyy}", AllPassFilter(),
        "{value|mmm}");

    # If all ticks are daily algined, then we use "mmm dd<*br*>yyyy" in bold font as the first label
    # of a year, and "mmm dd" in bold font as the first label of a month, and "dd" for other labels.
    $c->xAxis->setFormatCondition("align", 86400);
    $c->xAxis->setMultiFormat(StartOfYearFilter(),
        "<*block,halign=left*><*font=bold*>{value|mmm dd<*br*>yyyy}", StartOfMonthFilter(),
        "<*font=bold*>{value|mmm dd}");
    $c->xAxis->setMultiFormat2(AllPassFilter(), "{value|dd}");

    # For all other cases (sub-daily ticks), use "hh:nn<*br*>mmm dd" for the first label of a day,
    # and "hh:nn" for other labels.
    $c->xAxis->setFormatCondition("else");
    $c->xAxis->setMultiFormat(StartOfDayFilter(), "<*font=bold*>{value|hh:nn<*br*>mmm dd}",
        AllPassFilter(), "{value|hh:nn}");

    #================================================================================
    # Step 4 - Set up y-axis scale
    #================================================================================

    if ($viewer->getZoomDirection() == DirectionHorizontal) {
        # y-axis is auto-scaled - so vertically, the view port always cover the entire y data range.
        # We save the y-axis scale for supporting xy-zoom mode if needed in the future.
        $c->layout();
        $viewer->setCustomAttr("minValue", $c->yAxis->getMinValue());
        $viewer->setCustomAttr("maxValue", $c->yAxis->getMaxValue());
        $viewer->setViewPortTop(0);
        $viewer->setViewPortHeight(1);
    } else {
        # xy-zoom mode - retrieve the auto-scaled axis range, which contains the entire y data
        # range.
        $minValue = $viewer->getCustomAttr("minValue");
        $maxValue = $viewer->getCustomAttr("maxValue");

        # Compute the view port axis range
        $axisLowerLimit = $maxValue - ($maxValue - $minValue) * ($viewer->getViewPortTop() +
            $viewer->getViewPortHeight());
        $axisUpperLimit = $maxValue - ($maxValue - $minValue) * $viewer->getViewPortTop();

        # Set the axis scale to the view port axis range
        $c->yAxis->setLinearScale($axisLowerLimit, $axisUpperLimit);

        # By default, ChartDirector will round the axis scale to the tick position. For zooming, we
        # want to use the exact computed axis scale and so we disable rounding.
        $c->yAxis->setRounding(false, false);
    }

    #================================================================================
    # Step 5 - Output the chart
    #================================================================================

    # Create the image and save it in a temporary location
    $chartQuery = $c->makeSession($viewer->getId());
	
    # Include tool tip for the chart
    $imageMap = $c->getHTMLImageMap("", "",
        "title='[{dataSetName}] {x|mmm dd, yyyy}: USD {value|2}'");

    # Set the chart URL, image map, and chart metrics to the viewer. For the image map, we use
    # delayed delivery and with compression, so the chart image will show up quicker.
    $viewer->setImageUrl("http://localhost/sf_sandbox/web/images/ChartDirector/phpdemo/getchart.php?".$chartQuery);
    $viewer->setImageMap("http://localhost/sf_sandbox/web/images/ChartDirector/phpdemo/getchart.php?".$viewer->makeDelayedMap($imageMap, true));
    $viewer->setChartMetrics($c->getChartMetrics());
}

#
# A utility to create the <option> tags for the date range <select> boxes
#
# Parameters: startValue: The minimum selectable value. endValue: The maximum selectable value.
# selectedValue: The currently selected value.
#
function createSelectOptions($startValue, $endValue, $selectedValue) {
    $ret = array_pad(array(), ($endValue - $startValue + 1), null);
    for($i = $startValue; $i < $endValue + 1; ++$i) {
        if ($i == $selectedValue) {
            # Use a "selected" <option> tag if it is the selected value
            $ret[$i - $startValue] = "<option value='$i' selected>$i</option>";
        } else {
            # Use a normal <option> tag
            $ret[$i - $startValue] = "<option value='$i'>$i</option>";
        }
    }
    return join("", $ret);
}

# Create the WebChartViewer object
$viewer = new WebChartViewer("chart1");
if ($viewer->isPartialUpdateRequest()) {
    # Is a partial update request (AJAX chart update)
    processPartialUpdate($viewer);
    # Since it is a partial update, there is no need to output the entire web page. We stream the
    # chart and then terminate the script immediately.
    print($viewer->partialUpdateChart());
    exit();
} else if ($viewer->isFullUpdateRequest()) {
    # Is a full update request
    processFullUpdate($viewer);
} else {
    # Is a initial request
    createFirstChart($viewer);
}

# Create the <option> tags for the start date / end date select boxes to reflect the currently
# selected data range
$startYearSelectOptions = createSelectOptions((int)(getChartYMD($startDate) / 10000), (int)(
    getChartYMD($endDate) / 10000), (int)(getChartYMD($viewPortStartDate) / 10000));
$startMonthSelectOptions = createSelectOptions(1, 12, (int)(getChartYMD($viewPortStartDate) / 100) %
    100);
$startDaySelectOptions = createSelectOptions(1, 31, (int)(getChartYMD($viewPortStartDate) % 100));
$endYearSelectOptions = createSelectOptions((int)(getChartYMD($startDate) / 10000), (int)(
    getChartYMD($endDate) / 10000), (int)(getChartYMD($viewPortEndDate) / 10000));
$endMonthSelectOptions = createSelectOptions(1, 12, (int)(getChartYMD($viewPortEndDate) / 100) % 100
    );
$endDaySelectOptions = createSelectOptions(1, 31, (int)(getChartYMD($viewPortEndDate) % 100));
?>
<html>
<head>
    <title>ChartDirector Zoom and Scroll Demonstration</title>
    <script type="text/javascript" src="/sf_sandbox/web/images/ChartDirector/phpdemo/cdjcv.js"></script>
    <style type="text/css">
        div.chartPushButtonSelected { padding:5px; background:#ccffcc; cursor:hand; }
        div.chartPushButton { padding:5px; cursor:hand; }
        td.chartPushButton { font-family:Verdana; font-size:9pt; cursor:pointer; border-bottom:#000000 1px solid; }
    </style>
</head>
<body style="margin:0px" onload="initJsChartViewer()">
<script type="text/javascript">
// Initialize browser side Javascript controls
function initJsChartViewer()
{
    // Check if the Javascript ChartViewer library is loaded
    if (!window.JsChartViewer)
        return;

    // Get the Javascript ChartViewer object
    var viewer = JsChartViewer.get('<?php echo $viewer->getId()?>');

    // Connect the mouse usage buttons to the Javascript ChartViewer object
    connectViewerMouseUsage('ViewerMouseUsage1', viewer);
    // Connect the xy zoom mode buttons to the Javascript ChartViewer object
    connectViewerZoomControl('ViewerZoomControl1', viewer);

    // Detect if browser is capable of support partial update (AJAX chart update)
    if (JsChartViewer.canSupportPartialUpdate())
    {
        // Browser can support partial update, so connect the view port change event and
        // the submit button to trigger a partial update
        viewer.attachHandler("ViewPortChanged", viewer.partialUpdate);
        document.getElementById('SubmitButton').onclick = function() { viewer.partialUpdate(); return false; };

        // For partial updates, we need to pass the start date / end date select boxes values to/from
        // the server via Javascript ChartViewer custom attributes
        var controlsToSync = ['StartYear', 'StartMonth', 'StartDay', 'EndYear', 'EndMonth', 'EndDay'];
        viewer.attachHandler("PreUpdate", function() { copyToViewer(viewer, controlsToSync); });
        viewer.attachHandler("PostUpdate", function() { copyFromViewer(viewer, controlsToSync); });
    }
    else
        // Browser cannot support partial update - so use full page update
        viewer.attachHandler("ViewPortChanged", function() { document.forms[0].submit(); });
}
// A utility to copy HTML control values to Javascript ChartViewer custom attributes
function copyToViewer(viewer, controlsToSync)
{
    for (var i = 0; i < controlsToSync.length; ++i)
    {
        var obj = document.getElementById(controlsToSync[i]);
        if (obj && !{"button":1, "file":1, "image":1, "reset":1, "submit":1}[obj.type])
        {
            if ((obj.type == "checkbox") || (obj.type == "radio"))
                viewer.setCustomAttr(obj.id, obj.checked ? 1 : 0);
            else
                viewer.setCustomAttr(obj.id, obj.value);
        }
    }
}
// A utility to copy Javascipt ChartViewer custom attributes to HTML controls
function copyFromViewer(viewer, controlsToSync)
{
    for (var i = 0; i < controlsToSync.length; ++i)
    {
        var obj = document.getElementById(controlsToSync[i]);
        if (obj)
        {
            var value = viewer.getCustomAttr(obj.id);
            if (typeof value != "undefined")
            {
                if ((obj.type == "checkbox") || (obj.type == "radio"))
                    obj.checked = parseInt(value);
                else
                    obj.value = value;

                if (obj.validate)
                    obj.validate();
            }
        }
    }
}
</script>
<form method="post">
<table cellspacing="0" cellpadding="0" border="0">
    <tr>
        <td align="right" colspan="2" style="background:#000088">
            <div style="padding-bottom:2px; padding-right:3px; font-weight:bold; font-size:10pt; font-style:italic; font-family:Arial;">
                <a style="color:#FFFF00; text-decoration:none" href="http://www.advsofteng.com/">Advanced Software Engineering</a>
            </div>
        </td>
    </tr>
    <tr valign="top">
        <td style="width:150px; background:#c0c0ff; border-left:black 1px solid; border-right:black 1px solid; border-bottom:black 1px solid;">
            <!-- The following table is to create 3 cells for 3 buttons. The buttons are used to control
                 the mouse usage mode of the Javascript ChartViewer. -->
            <table id="ViewerMouseUsage1" cellspacing="0" cellpadding="0" width="100%" border="0">
                <tr>
                    <td class="chartPushButton">
                        <div class="chartPushButton" id="ViewerMouseUsage1_Scroll" title="Pointer">
                            <img src="/sf_sandbox/web/images/ChartDirector/phpdemo/pointer.gif" style="vertical-align:middle" width="16" height="16" alt="Pointer" />&nbsp;&nbsp;Pointer
                        </div>
                    </td>
                </tr>
                <tr>
                    <td class="chartPushButton">
                        <div class="chartPushButton" id="ViewerMouseUsage1_ZoomIn" title="Zoom In">
                            <img src="/sf_sandbox/web/images/ChartDirector/phpdemo/zoomInIcon.gif" style="vertical-align:middle" width="16" height="16" alt="Zoom In" />&nbsp;&nbsp;Zoom In
                        </div>
                    </td>
                </tr>
                <tr>
                    <td class="chartPushButton">
                        <div class="chartPushButton" id="ViewerMouseUsage1_ZoomOut" title="Zoom Out">
                            <img src="/sf_sandbox/web/images/ChartDirector/phpdemo/zoomOutIcon.gif" style="vertical-align:middle" width="16" height="16" alt="Zoom Out" />&nbsp;&nbsp;Zoom Out
                        </div>
                    </td>
                </tr>
            </table>
            <script type="text/javascript">
            // Connect the mouse usage buttons to the Javascript ChartViewer
            function connectViewerMouseUsage(controlId, viewer)
            {
                // A cross browser utility to get the object by id.
                function getObj(id) { return document.getElementById ? document.getElementById(id) : document.all[id]; }

                // Set the button styles (colors) based on the current mouse usage mode of the Javascript ChartViewer
                function syncButtons()
                {
                    getObj(controlId + "_Scroll").className = (viewer.getMouseUsage() == JsChartViewer.Scroll) ?
                        "chartPushButtonSelected" : "chartPushButton";
                    getObj(controlId + "_ZoomIn").className = (viewer.getMouseUsage() == JsChartViewer.ZoomIn) ?
                        "chartPushButtonSelected" : "chartPushButton";
                    getObj(controlId + "_ZoomOut").className = (viewer.getMouseUsage() == JsChartViewer.ZoomOut) ?
                        "chartPushButtonSelected" : "chartPushButton";
                }
                syncButtons();

                // Run syncButtons whenever the Javascript ChartViewer is updated
                viewer.attachHandler("PostUpdate", syncButtons);

                // Set the Javascript ChartViewer mouse usage mode if a button is clicked.
                getObj(controlId + "_Scroll").onclick = function() { viewer.setMouseUsage(JsChartViewer.Scroll); syncButtons(); }
                getObj(controlId + "_ZoomIn").onclick = function() { viewer.setMouseUsage(JsChartViewer.ZoomIn); syncButtons(); }
                getObj(controlId + "_ZoomOut").onclick = function() { viewer.setMouseUsage(JsChartViewer.ZoomOut); syncButtons(); }
            }
            </script>
            <div style="font-size:9pt; margin:15px 5px 0px; font-family:verdana"><b>Zoom Mode</b></div>
            <!-- The following table is to create 2 cells for 2 buttons. The buttons are used to control
                 the zoom/scroll directions of the Javascript ChartViewer. -->
            <table id="ViewerZoomControl1" cellspacing="0" cellpadding="0" width="100%" border="0">
                <tr>
                    <td class="chartPushButton" style="border-bottom: #000000 1px solid; border-top: #000000 1px solid;">
                        <div class="chartPushButton" id="ViewerZoomControl1_Xmode" title="X-Axis zoomable / Y-Axis auto-scaled">
                            <img src="/sf_sandbox/web/images/ChartDirector/phpdemo/xrange.gif" style="vertical-align:middle" width="16" height="16" alt="X Zoom/Y Auto" />&nbsp;&nbsp;X Zoom / Y Auto
                        </div>
                    </td>
                </tr>
                <tr>
                    <td class="chartPushButton" style="border-bottom: #000000 1px solid;">
                        <div class="chartPushButton" id="ViewerZoomControl1_XYmode" title="X-Axis and Y-Axis zoomable">
                            <img src="/sf_sandbox/web/images/ChartDirector/phpdemo/xyrange.gif" style="vertical-align:middle" width="16" height="16" alt="XY Zoom" />&nbsp;&nbsp;XY Zoom
                        </div>
                    </td>
                </tr>
            </table>
            <script type="text/javascript">
            // Connect the zoom/scroll direction buttons to the Javascript ChartViewer
            function connectViewerZoomControl(controlId, viewer)
            {
                // A cross browser utility to get the object by id.
                function getObj(id) { return document.getElementById ? document.getElementById(id) : document.all[id]; }

                // Set the button styles (colors) based on current zoom/scroll direction settings of the Javascript ChartViewer
                function syncButtons()
                {
                    getObj(controlId + "_Xmode").className = (viewer.getZoomDirection() == JsChartViewer.Horizontal) ?
                        "chartPushButtonSelected" : "chartPushButton";
                    getObj(controlId + "_XYmode").className = (viewer.getZoomDirection() == JsChartViewer.HorizontalVertical) ?
                        "chartPushButtonSelected" : "chartPushButton";
                }
                syncButtons();

                // Run syncButtons whenever the Javascript ChartViewer is updated
                viewer.attachHandler("PostUpdate", syncButtons);

                // Set the Javascript ChartViewer zoom/scroll direction if a button is clicked.
                function setViewerDirection(d)
                {
                    viewer.setScrollDirection(d);
                    viewer.setZoomDirection(d);
                    syncButtons();
                }
                getObj(controlId + "_Xmode").onclick = function() { setViewerDirection(JsChartViewer.Horizontal); }
                getObj(controlId + "_XYmode").onclick = function() { setViewerDirection(JsChartViewer.HorizontalVertical); }
            }
            </script>
            <div style="font-size:9pt; margin:15px 5px 0px; font-family:Verdana">
                <b>Start Time</b><br />
                <table cellspacing="0" cellpadding="0" border="0">
                    <tr>
                        <td style="font-size:8pt; font-family:Arial">Year</td>
                        <td style="font-size:8pt; font-family:Arial">Mon</td>
                        <td style="font-size:8pt; font-family:Arial">Day</td>
                    </tr>
                    <tr>
                        <td><select id="StartYear" name="StartYear" style="width:60">
                            <?php echo $startYearSelectOptions?>
                        </select></td>
                        <td><select id="StartMonth" name="StartMonth" style="width:40">
                            <?php echo $startMonthSelectOptions?>
                        </select></td>
                        <td><select id="StartDay" name="StartDay" style="width:40">
                            <?php echo $startDaySelectOptions?>
                        </select></td>
                    </tr>
                </table>
            </div>
            <div style="font-size:9pt; margin:15px 5px 0px; font-family:Verdana">
                <b>End Time</b><br />
                <table cellspacing="0" cellpadding="0" border="0">
                    <tr>
                        <td style="font-size:8pt; font-family:Arial">Year</td>
                        <td style="font-size:8pt; font-family:Arial">Mon</td>
                        <td style="font-size:8pt; font-family:Arial">Day</td>
                    </tr>
                    <tr>
                        <td><select id="EndYear" name="EndYear" style="width:60">
                            <?php echo $endYearSelectOptions?>
                        </select></td>
                        <td><select id="EndMonth" name="EndMonth" style="width:40">
                            <?php echo $endMonthSelectOptions?>
                        </select></td>
                        <td><select id="EndDay" name="EndDay" style="width:40">
                            <?php echo $endDaySelectOptions?>
                        </select></td>
                    </tr>
                </table>
            </div>
            <script type="text/javascript">
            // A utility to validate the day of month for the start date / end date HTML controls.
            // It sets the day of month select so that it only shows the legal range.
            function validateYMDControls(yearObj, monthObj, dayObj)
            {
                // Get the number of days in a month
                var noOfDays = [31, (parseInt(yearObj.value) % 4 == 0) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
                    [monthObj.selectedIndex];

                // Ensure the selected day of month is not bigger than the days in month
                dayObj.selectedIndex = Math.min(noOfDays - 1, dayObj.selectedIndex);

                // Extend/Shrink the day of month select box to ensure it covers the legal day range
                for (var i = dayObj.options.length; i < noOfDays; ++i)
                    dayObj.options[i] = new Option(i + 1, i + 1);
                for (var j = dayObj.options.length; j > noOfDays; --j)
                    dayObj.remove(j - 1);
            }
            // Initialize the HTML select controls for selecting dates
            function initYMDControls(yearId, monthId, dayId)
            {
                // A cross browser utility to get the object by id.
                var getObj = function(id) { return document.getElementById ? document.getElementById(id) : document.all[id]; }

                // Connect the onchange event to validateYMDControls
                getObj(yearId).onchange = getObj(yearId).validate = getObj(monthId).onchange = getObj(monthId).validate =
                    function() { validateYMDControls(getObj(yearId), getObj(monthId), getObj(dayId)); };

                // Validate once immediately
                getObj(yearId).validate();
            }
            // Connnect the start date / end date HTML select controls
            initYMDControls('StartYear', 'StartMonth', 'StartDay');
            initYMDControls('EndYear', 'EndMonth', 'EndDay');
            </script>
            <div style="margin-top:20px; font-family:Verdana; font-size:9pt; text-align:center">
                <input type="submit" id="SubmitButton" name="SubmitButton" value="Update Chart"></input>
            </div>
        </td>
        <td>
            <div style="font-weight:bold; font-size:20pt; margin:5px 0px 0px 5px; font-family:Arial">
                ChartDirector Zoom and Scroll Demonstration
            </div>
            <hr style="border:solid 1px #000080" />
            <div style="padding:0px 5px 0px 10px">
                <!-- ****** Here is the chart image ****** -->
                <?php 
					echo $viewer->renderHTML();
				?>
				
            </div>
        </td>
    </tr>
</table>
</form>
</body>
</html>

  Re: Error 800
Posted by Peter Kwan on Apr-12-2011 18:27
Hi Chris,

I have never used the Symfony framework myself and does not know the details of how it works. From their web site, it seems to be a kind of MVC framework.

I assume the code you attached is the exact code you are testing in your Symfony framework. From my general experience with MVC (not specific to Symfony), I think any HTTP request will be routed to a "controller" (by using a routing table or some default routing rule) and output through a "view". So the URL being used may not be the direct URL of the web page, but some other URL that gets routed to the web page.

I suspect the error 800 in your case is because one or more of the followings:

(a) The AJAX chart update request is not routed to your PHP page.

(b) The Symfony framework removes some or all query parameters before routing the request to the PHP page, so the PHP page does not receive the necessary AJAX chart update parameters.

To diagnose the problem, in the "Error 800", there may be further information that shows exactly what is received from the server. May be it contains the error message or some clue as why the error occurs. Would you mind to inform me the exact details of the error?

Also, in the Apache access log, you should see the AJAX request. Please inform me what is the URL structure of the AJAX request. In the Symfony framework, are there any log file that you can use to see how the URL is routed? Is it routed to the correct PHP page?

If you web site is accessible from the Internet, you may email the URL to me (my email is pkwan@advsofteng.net). I can then try myself to see what is the exact error message and the page structure.

Regards
Peter Kwan

  Re: Error 800
Posted by Chris on Apr-21-2011 22:03
Thanks Peter! Sorry for my later answer..

I saw server log access and I found interesting things :

"[21/Apr/2011:14:49:54 +0200] "GET /sf_sandbox/web/testC.php?cdLoopBack=1&cdPartialUpdate=chart1&cdCacheDefeat=13033901 "
It's the line for the partial update.

"127.0.0.1 - - [21/Apr/2011:14:41:59 +0200] "GET /sf_sandbox/web/testC.php/form/zoom HTTP/1.1" 200 19990"
And here the first requ?te send to the server.

I notice that two Urls are different. So the partial update is seemly throw in a wrong PHP file.

I go to found solutions and I'll give you news.

  Re: Error 800
Posted by Peter Kwan on Apr-21-2011 22:55
Hi Chris,

From your information, the partial update is posted to the testC.php. Would you mind to confirm if this is the correct PHP file?

A URL consists of serveral parts, including the path of the PHP file, the extra path info, and the query parameters. Your original URL is "/sf_sandbox/web/testC.php/form/zoom". I suspect the PHP file is "/sf_sandbox/web/testC.php" (as reported by Apache/PHP), and the path info is "/form/zoom", and the query parameters are empty. ChartDirector should send the partial request back to the same PHP file, but it may use different path info or query parameters. (As you can see in the partial update URL, ChartDirector does use different query parameters - it adds some parameters to your original URL.)

ChartDirector gets the path of the PHP file by using the standard SCRIPT_NAME environmental variable. You may check if your system is really reporting "/sf_sandbox/web/testC.php" as the PHP file by using:

$phpFile = $_SERVER["SCRIPT_NAME"];
$c->addTitle($phpFile);

You should see the actual PHP file as reported by your Apache/PHP in the chart title.

Anyway, it is possible that certain framework insists there must be some other information in the URL (such as the path info or some special query parameters) in order for it to work. For example, sometimes the main PHP script "testC.php" is just a "routing" front-end, and require the path info or query parameters to look up another file to run the actual code. If this is the case, you may modify the $_SERVER["SCRIPT_NAME"] to the URL structure as required by your framework. For example:

$_SERVER["SCRIPT_NAME"] = "/sf_sandbox/web/testC.php/form/zoom";

Hope this can help.

Regards
Peter Kwan

  Re: Error 800
Posted by Chris on Apr-22-2011 18:35
Hello!

Still thanks Peter Kwan, I succes to route in the great Url with :
==>  $_SERVER["SCRIPT_NAME"] = "/sf_sandbox/web/testC.php/form/zoom";  <==

Actually, the PHP file found the Chart image, it displays the image on the screen but when I try to execute update with ZoomIn or ZoomOut for example, no error occurs but no update too. The loading logo appear and disappear but there is no change.

Here is the acces log wich seems suitable :
127.0.0.1 - "GET /sf_sandbox/web/testC.php/form/zoom HTTP/1.1" 200 20137

127.0.0.1 - "GET /sf_sandbox/web/images/ChartDirector/phpdemo/getchart.php?img=chart1&id=tb55rmlcclsc1kd5up2mptc6t54db156259d16e& HTTP/1.1" 200 33099

127.0.0.1 - "GET /sf_sandbox/web/images/ChartDirector/phpdemo/getchart.php?img=chart1_map&isMap=1&id=tb55rmlcclsc1kd5up2mptc6t54db15625a482b& HTTP/1.1" 200 16990

127.0.0.1 - "GET /sf_sandbox/web/testC.php/form/zoom?cdLoopBack=1& cdPartialUpdate=chart1&cdCacheDefeat=1303467560350&chart1_JsChartViewerState=0*55%...

This is just for see that the Urls are good. But the problem now is the update and I think that SYMFONY don't like to oblige him Urls with rename $_SERVER["SCRIPT_NAME"]. It's my opinion but I don't know really good the SYMFONY behaviour.

I hope that I clear. Still thanks for your help.

  Re: Error 800
Posted by Chris on Apr-22-2011 21:16
Ok, indeed I successed the chart update..Another problem with the routing of the chart storage. I used the PHP file gave in the ChartDirector/phpdemo folder but with SYMFONY, We need to define another route with another PHP file.

Now, it stays one problem. Another one.. The date of the select date boxes are bad. Is it a frequently problem? First, they are only the 2 year boxes wich are bad, the two stay at 1 and in the select option there is only this choice. But for months and days it's ok. 12 months, and the day corresponding with months. Moreover, this problem with select year boxes not affect the scales when I zoom in or zoom out the date are good on the chart. An idea?Thanks.

  Re: Error 800
Posted by Peter Kwan on Apr-22-2011 23:07
Hi Chris,

The code for select date list boxes are not related to ChartDirector. They are just normal HTML/PHP code. I think in the sample code, the year list boxes are set to include all the years between the global variable $startDate and $endDate. I think the original sample code sets the $startDate and $endDate as being 5 years apart.

Are you using the exact original sample code, or have you modified the code, such as using different $startDate and $endDate or forgetting to set them, or using local variables instead of global variables?

May be you can save the output as seen by the browser (select "File/Save As" on the browser). I will try to trouble-shoot what is the issue.

Regards
Peter Kwan

  Re: Error 800
Posted by Chris on Apr-26-2011 15:54
Attachments:
Hi Peter,

I have not change anything in sources for the date. I don't understand why it doesn't work.
I attach the html with post as you ask me.
zoom-html.zip
zoom-html.zip

76.28 Kb

  Re: Error 800
Posted by Peter Kwan on Apr-27-2011 00:15
Hi Chris,

In the original sample code, the Start Year and End Year select boxes are filled using the following code:

$startYearSelectOptions = createSelectOptions((int)(getChartYMD($startDate) / 10000), (int)(getChartYMD($endDate) / 10000), (int)(getChartYMD($viewPortStartDate) / 10000));

$endYearSelectOptions = createSelectOptions((int)(getChartYMD($startDate) / 10000), (int)(getChartYMD($endDate) / 10000), (int)(getChartYMD($viewPortEndDate) / 10000));

The above code should fill the select boxes from the year of the start date, to the year of the end date. The start date and end date are obtained from the global variables $startDate and $endDate.

I suspect your code may have been modified so that the above are referenced as global variables. For example, suppose the above code is included in a function like:

function abc()
{
$startYearSelectOptions = createSelectOptions((int)(getChartYMD($startDate) / 10000), (int)(getChartYMD($endDate) / 10000), (int)(getChartYMD($viewPortStartDate) / 10000));

$endYearSelectOptions = createSelectOptions((int)(getChartYMD($startDate) / 10000), (int)(getChartYMD($endDate) / 10000), (int)(getChartYMD($viewPortEndDate) / 10000));
}

Then you call the function "abc();". The error you see will occur because PHP will aasume $startDate and $endDate as local variables to the function, which are undefined. (The line "global $startDate, $endDate, $viewPortStartDate, $viewPortEndDate;" would be need to tell PHP that these are gloabl variables.)

Would you mind to clarify if you have modified the code structure to fit the Symfony framework? (Such as declaring extra functions, or changing the scope of the variables, etc.)

If the above still cannot solve the problem, may be you can inform me your exact modified Symfony code to see if I can locate the issue.

Regards
Peter Kwan

  Re: Error 800
Posted by Chris on Apr-27-2011 15:58
Attachments:
Hi Peter,

Thanks but I didn't create other functions, I attach the src with my post. I have only change a little the look of the frame.
chartzoomSuccess.php
<?php

require_once("../lib/ChartDirector/lib/phpchartdir.php");

//Permet de forcer le routing du graph dynamique sur ce fichier PHP
$_SERVER["SCRIPT_NAME"] = "/SYTGEMweb/web/requeteurGeo.php/fonctionSQL/chartzoom";

#
# We need to handle 3 types of request: - initial request for the full web page - partial update
# (AJAX chart update) to update the chart without reloading the page - full page update for old
# browsers that does not support partial updates
#

# The total date range of all data.
$startDate = null;
$endDate = null;

# The date range of the data that we zoomed into (visible on the chart).
$viewPortStartDate = null;
$viewPortEndDate = null;

#
# Handles the initial request
#
function createFirstChart(&$viewer) {

    global $startDate, $endDate, $viewPortStartDate, $viewPortEndDate;

    # Initialize the Javascript ChartViewer
    $viewer->setMouseUsage(MouseUsageScroll);

    # In this demo, we allow scrolling the chart for the last 5 years
    list($unused, $unused, $unused, $d, $m, $y, $unused, $unused, $unused) = localtime();

    # The localtime month format is from 0 - 11, while the year is offsetted by 1900. We adjust them
    # to human used format.
    $m = $m + 1;
    $y = $y + 1900;

    $endDate = chartTime($y, $m, $d);

    # We roll back 5 years for the start date. Note that if the end date is Feb 29 (leap year only
    # date), we need to change it to Feb 28 in the start year
    if (($m == 2) && ($d == 29)) {
        $d = 28;
    }
    $startDate = chartTime($y - 5, $m, $d);

    # The initial selected date range is last 1 year
    $viewPortStartDate = chartTime($y - 1, $m, $d);
    $viewPortEndDate = $endDate;

    # We store the scroll range as custom Javascript ChartViewer attributes, so the range can be
    # retrieved later in partial or full update requests
    $viewer->setCustomAttr("startDate", $startDate);
    $viewer->setCustomAttr("endDate", $endDate);

    # In this demo, we set the maximum zoom-in to 10 days
    $viewer->setZoomInWidthLimit(10 * 86400 / ($endDate - $startDate));

    # Draw the chart
    drawChart($viewer);
}

#
# Handles partial update (AJAX chart update)
#
function processPartialUpdate(&$viewer) {

    global $startDate, $endDate, $viewPortStartDate, $viewPortEndDate;

    # Retrieve the overall date range from custom Javascript ChartViewer attributes.
    $startDate = $viewer->getCustomAttr("startDate");
    $endDate = $viewer->getCustomAttr("endDate");

    # Now we need to determine the visible date range selected by the user. There are two
    # possibilities. The user may use the zoom/scroll features of the Javascript ChartViewer to
    # select the range, or s/he may use the start date / end date select boxes to select the date
    # range.

    if ($viewer->isViewPortChangedEvent()) {
        # Is a view port change event from the Javascript ChartViewer, so we should get the selected
        # date range from the ChartViewer view port settings.
        $duration = $endDate - $startDate;
        $viewPortStartDate = $startDate + (int)(0.5 + $viewer->getViewPortLeft() * $duration);
        $viewPortEndDate = $viewPortStartDate + (int)(0.5 + $viewer->getViewPortWidth() * $duration)
            ;
    } else {
        # The user has changed the selected range by using the start date / end date select boxes.
        # We need to retrieve the selected dates from those boxes. For partial updates, the select
        # box values are sent in as Javascript ChartViewer custom attributes.
        $startYear = (int)($viewer->getCustomAttr("StartYear"));
        $startMonth = (int)($viewer->getCustomAttr("StartMonth"));
        $startDay = (int)($viewer->getCustomAttr("StartDay"));
        $endYear = (int)($viewer->getCustomAttr("EndYear"));
        $endMonth = (int)($viewer->getCustomAttr("EndMonth"));
        $endDay = (int)($viewer->getCustomAttr("EndDay"));

        # Note that for browsers that do not support Javascript, there is no validation on the
        # client side. So it is possible for the day to exceed the valid range for a month (eg. Nov
        # 31, but Nov only has 30 days). So we set the date by adding the days difference to the 1
        # day of a month. For example, Nov 31 will be treated as Nov 1 + 30 days = Dec 1.
        $viewPortStartDate = chartTime($startYear, $startMonth, 1) + ($startDay - 1) * 86400;
        $viewPortEndDate = chartTime($endYear, $endMonth, 1) + ($endDay - 1) * 86400;
    }

    # Draw the chart
    drawChart($viewer);

    #
    # We need to communicate the new start date / end date back to the select boxes on the browser
    # side.
    #

    # The getChartYMD function retrives the date as an 8 digit decimal number yyyymmdd.
    $startYMD = getChartYMD($viewPortStartDate);
    $endYMD = getChartYMD($viewPortEndDate);

    # Send year, month, day components to the start date / end date select boxes through Javascript
    # ChartViewer custom attributes.
    $viewer->setCustomAttr("StartYear", (int)($startYMD / 10000));
    $viewer->setCustomAttr("StartMonth", (int)($startYMD / 100) % 100);
    $viewer->setCustomAttr("StartDay", $startYMD % 100);
    $viewer->setCustomAttr("EndYear", (int)($endYMD / 10000));
    $viewer->setCustomAttr("EndMonth", (int)($endYMD / 100) % 100);
    $viewer->setCustomAttr("EndDay", $endYMD % 100);
}

#
# Handles full update
#
function processFullUpdate(&$viewer) {
    # A full chart update is essentially the same as a partial chart update. The main difference is
    # that in a full chart update, the start date / end date select boxes are in Form Post
    # variables, while in partial chart update, they are in Javascript ChartViewer custom
    # attributes.
    #
    # So a simple implementation of the full chart update is to copy the Form Post values to the
    # Javascript ChartViewer custom attributes, and then call the partial chart update.

    # Controls to copy
    $ctrls = array("StartYear", "StartMonth", "StartDay", "EndYear", "EndMonth", "EndDay");

    # Copy control values to Javascript ChartViewer custom attributes
    for($i = 0; $i < count($ctrls); ++$i) {
        $viewer->setCustomAttr($ctrls[$i], $_REQUEST[$ctrls[$i]]);
    }

    # Now can use partial chart update
    processPartialUpdate($viewer);
}

#
# Draw the chart
#
function drawChart(&$viewer) {

    global $startDate, $endDate, $viewPortStartDate, $viewPortEndDate;

    #
    # Validate and adjust the view port dates.
    #

    # Verify if the view port dates are within limits
    $totalDuration = $endDate - $startDate;
    $minDuration = $viewer->getZoomInWidthLimit() * $totalDuration;
    if ($viewPortStartDate < $startDate) {
        $viewPortStartDate = $startDate;
    }
    if ($endDate - $viewPortStartDate < $minDuration) {
        $viewPortStartDate = $endDate - $minDuration;
    }
    if ($viewPortEndDate > $endDate) {
        $viewPortEndDate = $endDate;
    }
    if ($viewPortEndDate - $viewPortStartDate < $minDuration) {
        $viewPortEndDate = $viewPortStartDate + $minDuration;
    }

    # Adjust the view port to reflect the selected date range
    $viewer->setViewPortWidth(($viewPortEndDate - $viewPortStartDate) / $totalDuration);
    $viewer->setViewPortLeft(($viewPortStartDate - $startDate) / $totalDuration);

    #
    # Now we have the date range, we can get the necessary data. In this demo, we just use a random
    # number generator. In practice, you may get the data from a database or XML or by other means.
    # (See "Using Data Sources with ChartDirector" in the ChartDirector documentation if you need
    # some sample code on how to read data from database to array variables.)
    #

    # Just a random number generator to generate the data - emulates a table of numbers from
    # startDate to endDate
    $r = new RanTable(127, 4, (int)(0.5 + $totalDuration / 86400) + 1);
    $r->setDateCol(0, $startDate, 86400);
    $r->setCol(1, 150, -10, 10);
    $r->setCol(2, 200, -10, 10);
    $r->setCol(3, 250, -10, 10);

    # Emulate selecting the date range viewPortStartDate to viewPortEndDate. Note that we add one
    # day margin on both ends. It is because we are using daily data, but the view port can cover
    # partial days. For example, the view port end date can be at 3:00am Feb 1, 2006. In this case,
    # we need the data point at Feb 2, 2006.
    $r->selectDate(0, $viewPortStartDate - 86400, $viewPortEndDate + 86400);

    # Emulate getting the random data from the table
    $timeStamps = $r->getCol(0);
    $dataSeriesA = $r->getCol(1);
    $dataSeriesB = $r->getCol(2);
    $dataSeriesC = $r->getCol(3);

    if (count($timeStamps) >= 520) {
        #
        # Zoomable chart with high zooming ratios often need to plot many thousands of points when
        # fully zoomed out. However, it is usually not needed to plot more data points than the
        # pixel resolution of the chart. Plotting too many points may cause the points and the lines
        # to overlap on the same pixel. So rather than increasing resolution, this reduces the
        # clarity of the chart. It is better to aggregate the data first if there are too many
        # points.
        #
        # In our current example, the chart plot area only has 520 pixels in width and is using a 2
        # pixel line width. So if there are more than 520 data points, we aggregate the data using
        # the ChartDirector aggregation utility method.
        #
        # If in your real application, you do not have too many data points, you may remove the
        # following code altogether.
        #

        # Set up an aggregator to aggregate the data based on regular sized slots
        $m = new ArrayMath($timeStamps);
        $m->selectRegularSpacing(count($timeStamps) / 260);

        # For the timestamps, take the first timestamp on each slot
        $timeStamps = $m->aggregate($timeStamps, AggregateFirst);

        # For the data values, take the averages
        $dataSeriesA = $m->aggregate($dataSeriesA, AggregateAvg);
        $dataSeriesB = $m->aggregate($dataSeriesB, AggregateAvg);
        $dataSeriesC = $m->aggregate($dataSeriesC, AggregateAvg);
    }

    #
    # Now we have obtained the data, we can plot the chart.
    #

    #================================================================================
    # Step 1 - Configure overall chart appearance.
    #================================================================================

    # Create an XYChart object 600 x 300 pixels in size, with pale blue (0xf0f0ff) background, black
    # (000000) rounded border, 1 pixel raised effect.
    $c = new XYChart(750, 510, 0xffffff, 0x000000);
	#$c->setRoundedFrame();

    # Set the plotarea at (52, 60) and of size 520 x 192 pixels. Use white (ffffff) background.
    # Enable both horizontal and vertical grids by setting their colors to grey (cccccc). Set
    # clipping mode to clip the data lines to the plot area.
    $c->setPlotArea(55, 50, 650, 400, 0xffffff, -1, -1, 0xcccccc, 0xcccccc);
    $c->setClipping();

    # Add a top title to the chart using 15 pts Times New Roman Bold Italic font, with a light blue
    # (ccccff) background, black (000000) border, and a glass like raised effect.
    #$textBoxObj = $c->addTitle("Zooming and Scrolling Demonstration", "timesbi.ttf", 15);
    #$textBoxObj->setBackground(0xccccff, 0x000000, glassEffect());

    # Add a bottom title to the chart to show the date range of the axis, with a light blue (ccccff)
    # background.
    #$textBoxObj = $c->addTitle2(Bottom, sprintf(
    #    "From <*font=arialbi.ttf*>%s<*/font*> to <*font=arialbi.ttf*>%s<*/font*> (Duration ".
    #    "<*font=arialbi.ttf*>%s<*/font*> days)", $c->formatValue($viewPortStartDate,
    #    "{value|mmm dd, yyyy}"), $c->formatValue($viewPortEndDate, "{value|mmm dd, yyyy}"), (int)(
    #    0.5 + ($viewPortEndDate - $viewPortStartDate) / 86400)), "ariali.ttf", 10);
    #$textBoxObj->setBackground(0xccccff);

    # Add a legend box at the top of the plot area with 9pts Arial Bold font with flow layout.
    $legendObj = $c->addLegend(140, 20, false, "arialbd.ttf", 9);
    $legendObj->setBackground(Transparent, Transparent);

    # Set axes width to 2 pixels
    $c->xAxis->setWidth(2);
    $c->yAxis->setWidth(2);

    # Add a title to the y-axis
    $c->yAxis->setTitle("Price (USD)", "arialbd.ttf", 10);

    #================================================================================
    # Step 2 - Add data to chart
    #================================================================================

    #
    # In this example, we represent the data by lines. You may modify the code below if you want to
    # use other representations (areas, scatter plot, etc).
    #

    # Add a line layer for the lines, using a line width of 2 pixels
    $layer = $c->addLineLayer2();
    $layer->setLineWidth(2);

    # Now we add the 3 data series to a line layer, using the color red (ff0000), green (00cc00) and
    # blue (0000ff)
    $layer->setXData($timeStamps);
    $layer->addDataSet($dataSeriesA, 0xff0000, "Product Alpha");
    $layer->addDataSet($dataSeriesB, 0x00cc00, "Product Beta");
    $layer->addDataSet($dataSeriesC, 0x0000ff, "Product Gamma");

    #================================================================================
    # Step 3 - Set up x-axis scale
    #================================================================================

    # Set x-axis date scale to the view port date range. ChartDirector auto-scaling will
    # automatically determine the ticks on the axis.
    $c->xAxis->setDateScale($viewPortStartDate, $viewPortEndDate);

    #
    # In the current demo, the x-axis range can be from a few years to a few days. We can let
    # ChartDirector auto-determine the date/time format. However, for more beautiful formatting, we
    # set up several label formats to be applied at different conditions.
    #

    # If all ticks are yearly aligned, then we use "yyyy" as the label format.
    $c->xAxis->setFormatCondition("align", 360 * 86400);
    $c->xAxis->setLabelFormat("{value|yyyy}");

    # If all ticks are monthly aligned, then we use "mmm yyyy" in bold font as the first label of a
    # year, and "mmm" for other labels.
    $c->xAxis->setFormatCondition("align", 30 * 86400);
    $c->xAxis->setMultiFormat(StartOfYearFilter(), "<*font=bold*>{value|mmm yyyy}", AllPassFilter(),
        "{value|mmm}");

    # If all ticks are daily algined, then we use "mmm dd<*br*>yyyy" in bold font as the first label
    # of a year, and "mmm dd" in bold font as the first label of a month, and "dd" for other labels.
    $c->xAxis->setFormatCondition("align", 86400);
    $c->xAxis->setMultiFormat(StartOfYearFilter(),
        "<*block,halign=left*><*font=bold*>{value|mmm dd<*br*>yyyy}", StartOfMonthFilter(),
        "<*font=bold*>{value|mmm dd}");
    $c->xAxis->setMultiFormat2(AllPassFilter(), "{value|dd}");

    # For all other cases (sub-daily ticks), use "hh:nn<*br*>mmm dd" for the first label of a day,
    # and "hh:nn" for other labels.
    $c->xAxis->setFormatCondition("else");
    $c->xAxis->setMultiFormat(StartOfDayFilter(), "<*font=bold*>{value|hh:nn<*br*>mmm dd}",
        AllPassFilter(), "{value|hh:nn}");

    #================================================================================
    # Step 4 - Set up y-axis scale
    #================================================================================

    if ($viewer->getZoomDirection() == DirectionHorizontal) {
        # y-axis is auto-scaled - so vertically, the view port always cover the entire y data range.
        # We save the y-axis scale for supporting xy-zoom mode if needed in the future.
        $c->layout();
        $viewer->setCustomAttr("minValue", $c->yAxis->getMinValue());
        $viewer->setCustomAttr("maxValue", $c->yAxis->getMaxValue());
        $viewer->setViewPortTop(0);
        $viewer->setViewPortHeight(1);
    } else {
        # xy-zoom mode - retrieve the auto-scaled axis range, which contains the entire y data
        # range.
        $minValue = $viewer->getCustomAttr("minValue");
        $maxValue = $viewer->getCustomAttr("maxValue");

        # Compute the view port axis range
        $axisLowerLimit = $maxValue - ($maxValue - $minValue) * ($viewer->getViewPortTop() +
            $viewer->getViewPortHeight());
        $axisUpperLimit = $maxValue - ($maxValue - $minValue) * $viewer->getViewPortTop();

        # Set the axis scale to the view port axis range
        $c->yAxis->setLinearScale($axisLowerLimit, $axisUpperLimit);

        # By default, ChartDirector will round the axis scale to the tick position. For zooming, we
        # want to use the exact computed axis scale and so we disable rounding.
        $c->yAxis->setRounding(false, false);
    }

    #================================================================================
    # Step 5 - Output the chart
    #================================================================================

    # Create the image and save it in a temporary location
    $chartQuery = $c->makeSession($viewer->getId());

    # Include tool tip for the chart
    $imageMap = $c->getHTMLImageMap("", "",
        "title='[{dataSetName}] {x|mmm dd, yyyy}: USD {value|2}'");

    # Set the chart URL, image map, and chart metrics to the viewer. For the image map, we use
    # delayed delivery and with compression, so the chart image will show up quicker.
    $viewer->setImageUrl("http://localhost/SYTGEMweb/web/ChartDirector.php/graph/getchart?".$chartQuery);
    $viewer->setImageMap("http://localhost/SYTGEMweb/web/ChartDirector.php/graph/getchart?".$viewer->makeDelayedMap($imageMap, true));
    $viewer->setChartMetrics($c->getChartMetrics());
}

#
# A utility to create the <option> tags for the date range <select> boxes
#
# Parameters: startValue: The minimum selectable value. endValue: The maximum selectable value.
# selectedValue: The currently selected value.
#
function createSelectOptions($startValue, $endValue, $selectedValue) {
    $ret = array_pad(array(), ($endValue - $startValue + 1), null);
    for($i = $startValue; $i < $endValue + 1; ++$i) {
        if ($i == $selectedValue) {
            # Use a "selected" <option> tag if it is the selected value
            $ret[$i - $startValue] = "<option value='$i' selected>$i</option>";
        } else {
            # Use a normal <option> tag
            $ret[$i - $startValue] = "<option value='$i'>$i</option>";
        }
    }
    return join("", $ret);
}

# Create the WebChartViewer object
$viewer = new WebChartViewer("chart1");
if ($viewer->isPartialUpdateRequest()) {
    # Is a partial update request (AJAX chart update)
    processPartialUpdate($viewer);
    # Since it is a partial update, there is no need to output the entire web page. We stream the
    # chart and then terminate the script immediately.
    print($viewer->partialUpdateChart());
    exit();
} else if ($viewer->isFullUpdateRequest()) {
    # Is a full update request
    processFullUpdate($viewer);
} else {
    # Is a initial request
    createFirstChart($viewer);
}

# Create the <option> tags for the start date / end date select boxes to reflect the currently
# selected data range
$startYearSelectOptions = createSelectOptions((int)(getChartYMD($startDate) / 10000), (int)(
    getChartYMD($endDate) / 10000), (int)(getChartYMD($viewPortStartDate) / 10000));
$startMonthSelectOptions = createSelectOptions(1, 12, (int)(getChartYMD($viewPortStartDate) / 100) %
    100);
$startDaySelectOptions = createSelectOptions(1, 31, (int)(getChartYMD($viewPortStartDate) % 100));
$endYearSelectOptions = createSelectOptions((int)(getChartYMD($startDate) / 10000), (int)(
    getChartYMD($endDate) / 10000), (int)(getChartYMD($viewPortEndDate) / 10000));
$endMonthSelectOptions = createSelectOptions(1, 12, (int)(getChartYMD($viewPortEndDate) / 100) % 100
    );
$endDaySelectOptions = createSelectOptions(1, 31, (int)(getChartYMD($viewPortEndDate) % 100));
?>
<html>
<head>
    <title></title>
    <script type="text/javascript" src="/SYTGEMweb/lib/ChartDirector/phpdemo/cdjcv.js"></script>
    <style type="text/css">
        div.chartPushButtonSelected { padding:5px; background:#ccffcc; cursor:hand; }
        div.chartPushButton { padding:5px; cursor:hand; }
        td.chartPushButton { font-family:Verdana; font-size:9pt; cursor:pointer; border-bottom:#000000 1px solid; }
    </style>
</head>
<body style="margin:0px" onload="initJsChartViewer()">
<script type="text/javascript">
// Initialize browser side Javascript controls
function initJsChartViewer()
{
    // Check if the Javascript ChartViewer library is loaded
    if (!window.JsChartViewer)
        return;

    // Get the Javascript ChartViewer object
    var viewer = JsChartViewer.get('<?php echo $viewer->getId()?>');

    // Connect the mouse usage buttons to the Javascript ChartViewer object
    connectViewerMouseUsage('ViewerMouseUsage1', viewer);
    // Connect the xy zoom mode buttons to the Javascript ChartViewer object
    connectViewerZoomControl('ViewerZoomControl1', viewer);

    // Detect if browser is capable of support partial update (AJAX chart update)
    if (JsChartViewer.canSupportPartialUpdate())
    {
        // Browser can support partial update, so connect the view port change event and
        // the submit button to trigger a partial update
        viewer.attachHandler("ViewPortChanged", viewer.partialUpdate);
        document.getElementById('SubmitButton').onclick = function() { viewer.partialUpdate(); return false; };

        // For partial updates, we need to pass the start date / end date select boxes values to/from
        // the server via Javascript ChartViewer custom attributes
        var controlsToSync = ['StartYear', 'StartMonth', 'StartDay', 'EndYear', 'EndMonth', 'EndDay'];
        viewer.attachHandler("PreUpdate", function() { copyToViewer(viewer, controlsToSync); });
        viewer.attachHandler("PostUpdate", function() { copyFromViewer(viewer, controlsToSync); });
    }
    else
        // Browser cannot support partial update - so use full page update
        viewer.attachHandler("ViewPortChanged", function() { document.forms[0].submit(); });
}
// A utility to copy HTML control values to Javascript ChartViewer custom attributes
function copyToViewer(viewer, controlsToSync)
{
    for (var i = 0; i < controlsToSync.length; ++i)
    {
        var obj = document.getElementById(controlsToSync[i]);
        if (obj && !{"button":1, "file":1, "image":1, "reset":1, "submit":1}[obj.type])
        {
            if ((obj.type == "checkbox") || (obj.type == "radio"))
                viewer.setCustomAttr(obj.id, obj.checked ? 1 : 0);
            else
                viewer.setCustomAttr(obj.id, obj.value);
        }
    }
}
// A utility to copy Javascipt ChartViewer custom attributes to HTML controls
function copyFromViewer(viewer, controlsToSync)
{
    for (var i = 0; i < controlsToSync.length; ++i)
    {
        var obj = document.getElementById(controlsToSync[i]);
        if (obj)
        {
            var value = viewer.getCustomAttr(obj.id);
            if (typeof value != "undefined")
            {
                if ((obj.type == "checkbox") || (obj.type == "radio"))
                    obj.checked = parseInt(value);
                else
                    obj.value = value;

                if (obj.validate)
                    obj.validate();
            }
        }
    }
}
</script>
<form method="post">
<table cellspacing="0" cellpadding="0" border="0">
    <tr valign="top">
        
		<td style="width:150px; background:#ffffff; border-left:black 1px solid; border-right:black 1px solid; border-bottom:black 1px solid; border-top:black 1px solid;">
            <!-- The following table is to create 3 cells for 3 buttons. The buttons are used to control
                 the mouse usage mode of the Javascript ChartViewer. -->
            <table id="ViewerMouseUsage1" cellspacing="0" cellpadding="0" width="100%" border="0">
                <tr style="height:50px">
                    <td class="chartPushButton">
                        <div class="chartPushButton" id="ViewerMouseUsage1_Scroll" title="Pointer">
                            <img src="/SYTGEMweb/lib/ChartDirector/phpdemo/pointer.gif" style="vertical-align:middle" width="16" height="16" alt="Pointer" />&nbsp;&nbsp;Pointer
                        </div>
                    </td>
                </tr>
                <tr style="height:50px">
                    <td class="chartPushButton">
                        <div class="chartPushButton" id="ViewerMouseUsage1_ZoomIn" title="Zoom In">
                            <img src="/SYTGEMweb/lib/ChartDirector/phpdemo/zoomInIcon.gif" style="vertical-align:middle" width="16" height="16" alt="Zoom In" />&nbsp;&nbsp;Zoom In
                        </div>
                    </td>
                </tr>
                <tr style="height:50px">
                    <td class="chartPushButton">
                        <div class="chartPushButton" id="ViewerMouseUsage1_ZoomOut" title="Zoom Out">
                            <img src="/SYTGEMweb/lib/ChartDirector/phpdemo/zoomOutIcon.gif" style="vertical-align:middle" width="16" height="16" alt="Zoom Out" />&nbsp;&nbsp;Zoom Out
                        </div>
                    </td>
                </tr>
            </table>
            <script type="text/javascript">
            // Connect the mouse usage buttons to the Javascript ChartViewer
            function connectViewerMouseUsage(controlId, viewer)
            {
                // A cross browser utility to get the object by id.
                function getObj(id) { return document.getElementById ? document.getElementById(id) : document.all[id]; }

                // Set the button styles (colors) based on the current mouse usage mode of the Javascript ChartViewer
                function syncButtons()
                {
                    getObj(controlId + "_Scroll").className = (viewer.getMouseUsage() == JsChartViewer.Scroll) ?
                        "chartPushButtonSelected" : "chartPushButton";
                    getObj(controlId + "_ZoomIn").className = (viewer.getMouseUsage() == JsChartViewer.ZoomIn) ?
                        "chartPushButtonSelected" : "chartPushButton";
                    getObj(controlId + "_ZoomOut").className = (viewer.getMouseUsage() == JsChartViewer.ZoomOut) ?
                        "chartPushButtonSelected" : "chartPushButton";
                }
                syncButtons();

                // Run syncButtons whenever the Javascript ChartViewer is updated
                viewer.attachHandler("PostUpdate", syncButtons);

                // Set the Javascript ChartViewer mouse usage mode if a button is clicked.
                getObj(controlId + "_Scroll").onclick = function() { viewer.setMouseUsage(JsChartViewer.Scroll); syncButtons(); }
                getObj(controlId + "_ZoomIn").onclick = function() { viewer.setMouseUsage(JsChartViewer.ZoomIn); syncButtons(); }
                getObj(controlId + "_ZoomOut").onclick = function() { viewer.setMouseUsage(JsChartViewer.ZoomOut); syncButtons(); }
            }
            </script>
            <div style="font-size:9pt; margin:15px 5px 0px; font-family:verdana"><b>Zoom Mode</b></div>
            <!-- The following table is to create 2 cells for 2 buttons. The buttons are used to control
                 the zoom/scroll directions of the Javascript ChartViewer. -->
            <table id="ViewerZoomControl1" cellspacing="0" cellpadding="0" width="100%" border="0">
                <tr style="height:50px">
                    <td class="chartPushButton" style="border-bottom: #000000 1px solid; border-top: #000000 1px solid;">
                        <div class="chartPushButton" id="ViewerZoomControl1_Xmode" title="X-Axis zoomable / Y-Axis auto-scaled">
                            <img src="/SYTGEMweb/lib/ChartDirector/phpdemo/xrange.gif" style="vertical-align:middle" width="16" height="16" alt="X Zoom/Y Auto" />&nbsp;&nbsp;X Zoom / Y Auto
                        </div>
                    </td>
                </tr>
                <tr style="height:50px">
                    <td class="chartPushButton" style="border-bottom: #000000 1px solid;">
                        <div class="chartPushButton" id="ViewerZoomControl1_XYmode" title="X-Axis and Y-Axis zoomable">
                            <img src="/SYTGEMweb/lib/ChartDirector/phpdemo/xyrange.gif" style="vertical-align:middle" width="16" height="16" alt="XY Zoom" />&nbsp;&nbsp;XY Zoom
                        </div>
                    </td>
                </tr>
            </table>
            
			<script type="text/javascript">
            // Connect the zoom/scroll direction buttons to the Javascript ChartViewer
            function connectViewerZoomControl(controlId, viewer)
            {
                // A cross browser utility to get the object by id.
                function getObj(id) { return document.getElementById ? document.getElementById(id) : document.all[id]; }

                // Set the button styles (colors) based on current zoom/scroll direction settings of the Javascript ChartViewer
                function syncButtons()
                {
                    getObj(controlId + "_Xmode").className = (viewer.getZoomDirection() == JsChartViewer.Horizontal) ?
                        "chartPushButtonSelected" : "chartPushButton";
                    getObj(controlId + "_XYmode").className = (viewer.getZoomDirection() == JsChartViewer.HorizontalVertical) ?
                        "chartPushButtonSelected" : "chartPushButton";
                }
                syncButtons();

                // Run syncButtons whenever the Javascript ChartViewer is updated
                viewer.attachHandler("PostUpdate", syncButtons);

                // Set the Javascript ChartViewer zoom/scroll direction if a button is clicked.
                function setViewerDirection(d)
                {
                    viewer.setScrollDirection(d);
                    viewer.setZoomDirection(d);
                    syncButtons();
                }
                getObj(controlId + "_Xmode").onclick = function() { setViewerDirection(JsChartViewer.Horizontal); }
                getObj(controlId + "_XYmode").onclick = function() { setViewerDirection(JsChartViewer.HorizontalVertical); }
            }
            </script>
            
			<div style="font-size:9pt; margin:15px 5px 0px; font-family:Verdana">
                <b>Start Time</b><br />
                <table cellspacing="0" cellpadding="0" border="0">
                    <tr>
                        <td style="font-size:8pt; font-family:Arial">Year</td>
                        <td style="font-size:8pt; font-family:Arial">Mon</td>
                        <td style="font-size:8pt; font-family:Arial">Day</td>
                    </tr>
                    <tr>
                        <td><select id="StartYear" name="StartYear" style="width:60">
                            <?php echo $startYearSelectOptions?>
                        </select></td>
                        <td><select id="StartMonth" name="StartMonth" style="width:40">
                            <?php echo $startMonthSelectOptions?>
                        </select></td>
                        <td><select id="StartDay" name="StartDay" style="width:40">
                            <?php echo $startDaySelectOptions?>
                        </select></td>
                    </tr>
                </table>
            </div>
			
            <div style="font-size:9pt; margin:15px 5px 0px; font-family:Verdana">
                <b>End Time</b><br />
                <table cellspacing="0" cellpadding="0" border="0">
                    <tr>
                        <td style="font-size:8pt; font-family:Arial">Year</td>
                        <td style="font-size:8pt; font-family:Arial">Mon</td>
                        <td style="font-size:8pt; font-family:Arial">Day</td>
                    </tr>
                    <tr>
                        <td><select id="EndYear" name="EndYear" style="width:60">
                            <?php echo $endYearSelectOptions?>
                        </select></td>
                        <td><select id="EndMonth" name="EndMonth" style="width:40">
                            <?php echo $endMonthSelectOptions?>
                        </select></td>
                        <td><select id="EndDay" name="EndDay" style="width:40">
                            <?php echo $endDaySelectOptions?>
                        </select></td>
                    </tr>
                </table>
            </div>-->
            <script type="text/javascript">
            // A utility to validate the day of month for the start date / end date HTML controls.
            // It sets the day of month select so that it only shows the legal range.
            function validateYMDControls(yearObj, monthObj, dayObj)
            {
                // Get the number of days in a month
                var noOfDays = [31, (parseInt(yearObj.value) % 4 == 0) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
                    [monthObj.selectedIndex];

                // Ensure the selected day of month is not bigger than the days in month
                dayObj.selectedIndex = Math.min(noOfDays - 1, dayObj.selectedIndex);

                // Extend/Shrink the day of month select box to ensure it covers the legal day range
                for (var i = dayObj.options.length; i < noOfDays; ++i)
                    dayObj.options[i] = new Option(i + 1, i + 1);
                for (var j = dayObj.options.length; j > noOfDays; --j)
                    dayObj.remove(j - 1);
            }
            // Initialize the HTML select controls for selecting dates
            function initYMDControls(yearId, monthId, dayId)
            {
                // A cross browser utility to get the object by id.
                var getObj = function(id) { return document.getElementById ? document.getElementById(id) : document.all[id]; }

                // Connect the onchange event to validateYMDControls
                getObj(yearId).onchange = getObj(yearId).validate = getObj(monthId).onchange = getObj(monthId).validate =
                    function() { validateYMDControls(getObj(yearId), getObj(monthId), getObj(dayId)); };

                // Validate once immediately
                getObj(yearId).validate();
            }
            // Connnect the start date / end date HTML select controls
            initYMDControls('StartYear', 'StartMonth', 'StartDay');
            initYMDControls('EndYear', 'EndMonth', 'EndDay');
            </script>
            
			<div style="margin-top:20px; font-family:Verdana; font-size:9pt; text-align:center">
                <input type="submit" id="SubmitButton" name="SubmitButton" value="Update Chart"></input>
            </div>
			
        </td>
        <td>
            
			<div style="font-weight:bold; font-size:20pt; margin:5px 0px 0px 5px; font-family:Arial">
                ChartDirector Zoom and Scroll Demonstration
            </div>
            <hr style="border:solid 1px #000080" />
			
            <div style="padding:0px 5px 0px 10px">
                <!-- ****** Here is the chart image ****** -->
                <?php echo $viewer->renderHTML()?>
            </div>
        </td>
    </tr>
</table>
</form>
</body>
</html>

  Re: Error 800
Posted by Peter Kwan on Apr-27-2011 17:52
Hi Chris,

I suspect the Symfony framework is automatically changing all global variables into local variabels. I searched the Internet and in fact found a message that confirms this is the case.

http://stackoverflow.com/questions/3006658/symfony-1-4-and-global-variables

The message basically says the symfony code "lib/vendor/symfony/lib/view/sfPHPView.class.php" will change all global variables in the PHP file into local variables.

In the sample code, the first few lines contain:

$startDate = null;
$endDate = null;

$viewPortStartDate = null;
$viewPortEndDate = null;

The above variables are clearly global variables, assuming the sample code file is passed to PHP to execute.

However, Symfony probably does not execute the sample PHP file directly, but include it  in another function or scope, and execute the function. I do not know the details, but an example is like:

function someInternalSymfonyFunction($fileName)
{
     include($fileName);
}

The above includes the PHP file into another function. Now the global variables in the PHP file becomes the local variables of someInternalSymfonyFunction.

If the above is the cause of the problem, then in translating the code to Symfony, in addition to modifying the path, you would need to explicitly declared global variables as well. This can avoid Symfony from changing the variable scope to local.

For your case, you may put the following as the first line in the PHP code. It explicity declares the variables as global.

global $startDate, $endDate, $viewPortStartDate, $viewPortEndDate;

Please let me know if this solves the porblem.

Regards
Peter Kwan

  Re: Error 800
Posted by Chris on Apr-27-2011 21:14
Ohoh! Great!! It really works!

Thanks to you if I success my internship :) I have no more problems now, until next..

Still thanks,

Regards.

  Re: Error 800
Posted by Chris on May-04-2011 17:40
Hi Peter,

As we found the key of success about my problems with the zoomscroll demo. I try to create my own chart with my data and the zoom. Before do It, we used already chartdirector for our soft and create image that we stores on the serveur. Now we want to create the same chart but add the zoom. So, I want to know if some tools that we used for create any chart operate with the zoom scroll. because when I want to draw my chart with my option and next add the zoom, I have the main look what i decided but the data are not insert in the chart.

Simply, I would like to know if all the tools of ChartDirector operate with zoomscroll or other dynamic tools purpose in chartDirector.

Regards.

  Re: Error 800
Posted by Peter Kwan on May-04-2011 22:58
Hi Chris,

The zoom/scroll is supported in charts based on XYChart. It is not supported in non-XY chart types (eg. PieChart, PolarChart, LinearMeter, AngularMeter, PyramidChart, SurfaceChart).

If the chart is shown with no data (that is, you can see the chart title, plot area, etc), first, please check if you have provided the data to the chart. For zoom/scroll chart, please also check if the data are within the chart range. (For example, if the chart is scrolled to show the data from Jan 2010 to Dec 2010, but you pass the data for year 2001 to 2008 to ChartDirector, the chart will not drawn anything, because your data are not within the date range the user scrolled to.)

To diagnose the problem, one common method is to display your data in something you can see. For example, if you can see the chart title, you may display the first and last x-coordinates in the chart title. In this way, you can see if your code have passed data to ChartDirector, and whether the data are within the axis range.

Hope this can help.

Regards
Peter Kwan

  Re: Error 800
Posted by Chris on May-05-2011 15:12
Hi Peter, Thanks!
I passed dates with a wrong format in the setXDate argument, it was'nt in chartime. Now it work correctly!
We have 7 type of chart but lucky for us, six are based in XYchart type, only one is a polar chart. I'm going to work on all this chart now. Still thanks!

Regards,
Chris.

  Re: Error 800
Posted by Chris on May-16-2011 15:44
Hi Peter!

I have some javascript in my page but when I try to add the javascript of ChartDirector all the other javascript doesn't work! I want to know if there is a special way with this script for it not prevent the other.

  Re: Error 800
Posted by Chris on May-16-2011 22:43
Hi!

I success what I had try to do! You don't need to spend time on this! Thank you anyway!

Regards,

Chris.

  Re: Error 800
Posted by Chris on May-17-2011 22:31
Hello Peter,

When I do "createfirstchart" and that I use in my function the auto-scaling in the demo, I can't define my scale with setLinearScale(Min,Max). I try to put this at the end of the "drawchart" but it nothing happens, it keep an auto-scale. Is it a way to choose a scale the first I draw the chart.

I seriously need your help, thanks.

Regards.

  Re: Error 800
Posted by Peter Kwan on May-18-2011 00:40
Hi Chris,

Do you mean you want to specify a certain y-axis scale when the chart is first drawn (when vertical zooming is not used)? In the original code, there are the lines:

    if ($viewer->getZoomDirection() == DirectionHorizontal) {
            ..........
    } .........

Please insert the setLinearScale there, like:

    if ($viewer->getZoomDirection() == DirectionHorizontal) {
            $c->yAxis->setLinearScale(0, 100);
            $c->yAxis->setRounding(false, false);
            ..........
    } .........


Hope this can help.

Regards
Peter Kwan

  Re: Error 800
Posted by Chris on May-18-2011 15:16
Hi peter,

When I create then draw the first chart:
        $viewer->setMouseUsage(MouseUsageZoomIn);
$viewer->setZoomDirection(DirectionHorizontal);
$viewer->setScrollDirection(DirectionHorizontal);
So, it pass in the sample code:
        if ($viewer->getZoomDirection() == DirectionHorizontal) {...
But then when the initJsChartViewer is coming, I initialize the viewer zoom control as here:
        getObj(controlId + "_XYmode").onclick = setViewerDirection(JsChartViewer.HorizontalVertical);

I had try to put in the "   if ($viewer->getZoomDirection() == DirectionHorizontal) {..." like you said me ( $c->yAxis->setLinearScale(0,5); ) but the scale are not written on the chart of 0 to 5.

When I put no data in the yaxis, no scale appear and when there are data, the code choose the scale as we like.

Sorry, but there is a something that I don't understand.

Reagrds.

  Re: Error 800
Posted by Chris on May-18-2011 16:34
Still hi Peter,

I discovered the utility of layout().. I think it is the source of my problem. But now, I have an other question.

When I do an HorizontalVerticalZoom with a chart who has yaxis and yaxis2, it take the lower value of the yaxis one for doing his scale, at least, approximately.. So if the lowerLimit ine the zoom for axis one is 2 and in the other side the lowerLimite for the axis two is 1, after the zoom the two scale begin to 2 and the data that I had at start are no more visible for the axis 2 then I have zoom over. There is way to auto-scale the 2 yaxis correctly selon le zoom.

Regards,

  Re: Error 800
Posted by Chris on May-26-2011 17:17
Hello Peter,

Can you help me please. I want to know if the zoom can be support the log scale option? In this case, is there known issues?

Regards.

Chris.

  Re: Error 800
Posted by Peter Kwan on May-27-2011 00:44
Hi Chris,

Yes. You can freely use log scale. To do this, you may perform the followings:

(a) Add a line of code to configure log scale when the chart initially load and the y-axis is auto-scaled (eg. just before calling $c->layout() in the original "Zooming and Scrolling Demonstration" sample code):

$c->yAxis->setLogScale();

(b) In subsequent zooming/scrolling. modify the view port computation code to use log scale.

The original code is:

        # Compute the view port axis range
        $axisLowerLimit = $maxValue - ($maxValue - $minValue) * ($viewer->getViewPortTop() + $viewer->getViewPortHeight());
        $axisUpperLimit = $maxValue - ($maxValue - $minValue) * $viewer->getViewPortTop();

        # Set the axis scale to the view port axis range
        $c->yAxis->setLinearScale($axisLowerLimit, $axisUpperLimit);

Please change the above to:

        # Compute the view port axis range
        $axisLowerLimit = $maxValue / pow($maxValue / $minValue, $viewer->getViewPortTop() + $viewer->getViewPortHeight());
        $axisUpperLimit = $maxValue / pow($maxValue / $minValue, $viewer->getViewPortTop());

        # Set the axis scale to the view port axis range
        $c->yAxis->setLogScale($axisLowerLimit, $axisUpperLimit);

Hope this can help.

Regards
Peter Kwan

  Chartzoom date error
Posted by Chris on Jun-06-2011 21:57
Hi Peter,

I have a new problem.

My zoom on chart works fine on wamp in localhost but when I use it in a Linux server, my chart doesn't keep my zoom date. The viewStartDate and viewEndDate take the same value as the startDate of my initial chart. It work in localhost.

Thanks.

Chris

  Re: Chartzoom date error
Posted by Peter Kwan on Jun-07-2011 02:16
Hi Chris,

Also, have you tried the original ChartDirector "Zooming and Scrolling Demonstration" sample code in your Linux host? Does it work?

We are aware of 1 bug in ChartDirector that may have similar symptoms to your case. It is about the locale setting of the running process. However, this bug rarely affects PHP. We only see it affects C++ with QT. We have never seen it affects any other configuration. Anyway, if your system is affected, it should affect the original ChartDirector sample code as well. If it does affect the original sample code, please use the following method to update the "libchartdir.so":

- Download "ChartDirector for C++" for your Linux (either Linux i386 or Linux x86_64, depending on which type of Linux you are using). Inside, please find the file "libchartdir.so.5.0.0". This is the latest "libchartdir.so" that has the bug fixed. Please rename the file "libchartdir.so" and use it to replace your existing "libchartdir.so" in the PHP extension directory. Depending on your server configuration, you may or may not need to restart the Apache server.

If the sample code works normally, but your code does not work, please inform me of your code. Is your host accessible from the Internet? If yes, may be you can email the URL to me so that I can go in to have a look to see how your code runs. My email is pkwan@advsofteng.net.

Regards
Peter Kwan

  Re: Chartzoom date error
Posted by Chris on Jun-07-2011 15:44
Hi,

The demo code works fine in the linux Server.
My linux is a 64b (appache, php5 and MySQL) and the windows is a 32b (Wamp).
The createFirstChart seams to works fine too.
But if we write in a file the value of the $viewer->getViewPortLeft() and $viewer->getViewPortWidth() in a Partial Update process it apear to be null !!!

I have try to change the "libchartdir.so" like you tell me but nothing appends !!

Here is my code of my processPartialUpdate.
src:

#
# Mise ? jour partiel (MAJ AJAX)
#
function processPartialUpdate(&$viewer, &$startDate, &$endDate, &$viewPortStartDate, &$viewPortEndDate, $tabattr,$typeGraph)
{

# On r?cup?re les dates stock?es dans l'objet dynamique JsChartViewer
     $startDate = $viewer->getCustomAttr("startDate");
     $endDate = $viewer->getCustomAttr("endDate");

    # Ici on va d?termin? ce que l'utilisateur a modifi? dans son action qui a entrain? l'appelle ? la MAJ partiel.
     if ($viewer->isViewPortChangedEvent())
{
# Dans le cas ou un ?venement JavaScript de mise ? jour des extr?mit? du graphe a ?t? d?clanch? ,
# Ainsi on r?cup?re les nouvelles valeurs qui sont stock?es dans l'objet viewer.
$duration = $endDate - $startDate;
$viewPortStartDate = $startDate + (int)(0.5 + $viewer->getViewPortLeft() * $duration);
$viewPortEndDate = $viewPortStartDate + (int)(0.5 + $viewer->getViewPortWidth() * $duration);
}

     # Draw the chart
drawChart($viewer, $startDate, $endDate, $viewPortStartDate, $viewPortEndDate, $tabattr,$typeGraph);

creatFichier('processPartialUpdate', $viewer->getCustomAttr("startDate"), $viewer->getCustomAttr("endDate"), $viewer->getViewPortWidth(), $viewer->getViewPortLeft() ); // => 63435225600 , 63443087999 , 0 , 0

}

Thanks !!

Chris

  Re: Chartzoom date error
Posted by Peter Kwan on Jun-08-2011 01:40
Hi Chris,

From your previous message, you mentioned that your code works on a Windows host. I assume the code in your Linux host is "exactly the same" as your Windows code, and it does not work. However, the sample code works in both hosts.

For your case, I suspect some part of your code may be is written in a locale dependent way, and it breaks if the locale between the server and the browser is different (eg. the browser is in French locale, but the server is in English locale). The issue may be in the browser Javascript code or the server PHP code.

If you server is accessible from the Internet, you may provide the URL to me, so I can use a protocol analyzer to check the data transfer between the browser and the server.

If the server is not accessible from the Internet, please go to the server access log file and check if your can see the URL used in the AJAX transfer. The URL should contain a long list of query parameters. Please send the URLs to me for analysis. Also, in your browser, please use IE Flie/Save As, and save a copy of your web page as a "Web Archive" for analysis. You may email the information to me at pkwan@advsofteng.net.

Regards
Peter Kwan

  Re: Chartzoom date error
Posted by Chris on Jun-08-2011 15:54
Hi Peter,

The demo code works fine on windows 32b without Synfony.
The demo code works fine on windows 32b with Synfony.
The demo code works fine on LINUX 64b without Synfony.
                                BUT
The demo code  doesn't work on LINUX 64b with Synfony.

And my server is not accessible from the Internet for the moment.

So you have got a mail at pkwan@advsofteng.net whith my appache log and the save of my page.

Thanks

Chris

  Re: Chartzoom date error
Posted by Chris on Jun-08-2011 21:11
Attachments:
Re-Hi,

If it can help you here is the Viewer attributs before and after zoom when it works and when it doesn't work.

I suspect a behaviour wich round the float number to an integer.

Thanks!

Chris.
Viewer attributs.zip
Viewer attributs.zip

1.67 Kb

  Re: Chartzoom date error
Posted by Chris on Jun-08-2011 23:27
Re Re Hi Peter,

The problem seems coming from the function "callmethod("WebChartViewer.putAttrF or S", $this->ptr, $attr, $value);" in the file phpchartdir.php

If i enter a value like 1.258 or 1,258 whith the set... function, it return me 1 (on linux+synfony server 64b)
If i enter a value like 0.12345 or 0,12345 whith the set... function, it return me 0 (on linux+synfony server 64b)

So where can i show this one or can you tell me what to do to keep my float number ? After this my zoom will work realy fine !!

Really thanks for your help.

Chris,

  Re: Chartzoom date error
Posted by Peter Kwan on Jun-09-2011 01:45
Hi Chris,

It seems to be a Symfony bug. See:

http://trac.symfony-project.org/ticket/4102

Basically, if the Symfony locale settings is configured to use comma as the decimal separator (as in French number format), it will cause some PHP numeric functions to fail. This include the function that parse floating point numbers.

To solve the problem, you may try the following methods:

(a) Try to use the work around as mentioned in the Symfony bug report.

or

(b) Try to add the line:

setlocale(LC_NUMERIC,'C');

or the line

setlocale(LC_ALL, 'en_US.utf8');

as the first line in your PHP code.

Hope this can help.

Regards
Peter Kwan

  Re: Chartzoom date error
Posted by Chris on Jun-09-2011 23:46
Hi,

It is juste tell you that you are the best !!! ;)

It works fine thanks to you,

Thanks

Chris.

  Chartzoom in IE
Posted by Chris on Jun-10-2011 18:24
Hi Peter,

I try to use the zoom on IE6 ,IE7or IE8 and all actions seems to work but after the upper clic nothing happened !!!!
Have you an idee to find my problem.

All the javascript seems to be good but .... it is IE....

Of course the demo code works !

Thanks,

Chris

  Re: Chartzoom in IE
Posted by Peter Kwan on Jun-10-2011 23:41
Hi Chris,

I am not sure what you mean by "upper clic". Woud you mind to clarify?

Regards
Peter Kwan

  Re: Chartzoom in IE
Posted by Chris on Jun-13-2011 19:19
Hi peter,

When I say "upper clic", I meant about the event mouseup. Usually, it is after this event
what we able to see the updating of the chart (Firefox). But hear, in Internet Explorer after
the mouseup event an with the same code used in firefox nothing happened.

I hope, I was more clear.

Thanks.

Chris.

  Re: Chartzoom in IE
Posted by Peter Kwan on Jun-14-2011 00:48
Hi Chris,

As the issue only occurs in your code, but not in the sample code, but I have never seen or try your code, it is hard for me to debug the problem. Is it possible that you can modify the sample code to reproduce the same problem, and then send the modified sample code to me?

Regards
Peter Kwan