Common Task results
Common_TaskResults_CSharp\TaskResultsWebSite\JavaScript\TaskResultsPanel.js
 Copyright 2010 ESRI
 
 All rights reserved under the copyright laws of the United States
 and applicable international laws, treaties, and conventions.
 
 You may freely redistribute and use this sample code, with or
 without modification, provided you include the original copyright
 notice and use restrictions.
 
 See <a href="http://help.arcgis.com/en/sdk/10.0/usageRestrictions.htm">the use restrictions</a>.
 

//====================================================
// TaskResultsPanel client-side control definition
//====================================================

Type.registerNamespace('ESRI.ADF.Samples.CustomTasks');

// Constructor for the TaskResultsPanel, used here to declare member variables.  Since the control
// is implemented as an AJAX component, initialization logic is placed in the initialize function.
ESRI.ADF.Samples.CustomTasks.TaskResultsPanel = function(element) {
    ESRI.ADF.Samples.CustomTasks.TaskResultsPanel.initializeBase(this, [element]);
    
    this._id = null;
    this._widthDiff = null;
    this._heightDiff = null;
    this._sizeInitialized = false;
    this._top = null;
}
ESRI.ADF.Samples.CustomTasks.TaskResultsPanel.prototype = {
        
    //===================
    // Initialization 
    //===================    

    initialize : function() {   
        // Add handlers for events inherited from FloatingPanel        
        this.add_show(this._onPanelShown);
        this.add_resizeStart(this._onPanelResizeStart);
        this.add_resizing(this._onPanelResizing);
        
        // Initialize the base class
        ESRI.ADF.Samples.CustomTasks.TaskResultsPanel.callBaseMethod(this, 'initialize'); 
    },


    //==============
    // Properties
    //==============

    
    // Returns the object's id
    get_id : function () {
        return this._id;
    },
    
    // Sets the object's id
    set_id : function (value) {
        this._id = value;
    },
    
    // Retrieves the specified maximum width when the panel is first displayed
    get_initialMaxWidth : function() {
        return this._initialMaxWidth;
    },
    
    // Sets the maximum width for when the panel is first displayed
    set_initialMaxWidth : function(value) {
        this._initialMaxWidth = value;
    },
    
    // Retrieves the specified maximum height for when the panel is first displayed
    get_initialMaxHeight : function() {
        return this._initialMaxHeight;
    },
    
    // Sets the maximum height for when the panel is first displayed
    set_initialMaxHeight : function(value) {
        this._initialMaxHeight = value;
    },


    //============
    // Methods
    //============
    
    
    // Fires when the panel is starting to be resized.  Initializes a private property storing
    // the difference between the dimensions of the entire panel and its content div.  This is
    // used to preserve that difference when the panel is resized.
    _onPanelResizeStart : function(panel) {
        if (!panel._widthDiff)
        {
            var panelBounds = Sys.UI.DomElement.getBounds(panel.get_element());          
            var divBounds = Sys.UI.DomElement.getBounds(panel._contentDiv);
            panel._widthDiff = panelBounds.width - divBounds.width;
            panel._heightDiff = panelBounds.height - divBounds.height;
        }
    },

    // Fires when the panel is resizing.  Resizes the panel content along with the panel frame.
    _onPanelResizing : function(panel) {                    
        var panelBounds = Sys.UI.DomElement.getBounds(panel.get_element());          
        divWidth = panelBounds.width - panel._widthDiff - 5;
        divHeight = panelBounds.height - panel._heightDiff - 1;
        panel._contentDiv.style.width = divWidth + 'px';
        panel._contentDiv.style.height = divHeight + 'px';
        if (divHeight < parseInt(panel._contentTable.style.height))
            divWidth -= 20;
        if (divWidth < parseInt(panel._contentTable.style.width))
        {        
            panel._contentDiv.style.overflowX = '';
            panel._contentDiv.style.overflow = 'auto';
            panel._contentDiv.style.overflowY = '';
        }
        else
        {
            panel._contentDiv.style.overflowX = 'hidden';
            panel._contentDiv.style.overflow = '';
            panel._contentDiv.style.overflowY = 'auto';
        }
    },

    // Fires when the panel is shown. 
    _onPanelShown : function(panel) {
        if (!panel._sizeInitialized)               
        {
            // Move the panel off-screen for resizing
            var panelElement = panel.get_element();
            panel._top = panelElement.style.top;
            var browserDimensions = panel._getBrowserDimensions();
            var newTop = browserDimensions.height + 200;
            panelElement.style.top = newTop + 'px';
            
            // Put call to initializeSize in a timeout so the panel elements are displayed when
            // it executes.  The panel elements need to be displayed to be able to access
            // their dimensions.
            window.setTimeout(String.format("$find('{0}').initializeSize()", panel.get_id()), 0);
        }
    },

    // Called by _onPanelShown when the panel is first displayed and size has yet to be initialized.
    // Applies the specified initial maximum width and height.
    initializeSize: function() {   
        // Get the panel's content div and table                             
        var contentDivID = String.format('{0}_ContentDiv', this.get_id());
        this._contentDiv = $get(contentDivID);        
        var contentTableID = String.format('{0}_ContentTable', this.get_id());
        this._contentTable = $get(contentTableID);

        // Get the DOM element encapsulating the panel and retrieve its bounds
        var panelElement = this.get_element();
        var panelBounds = Sys.UI.DomElement.getBounds(panelElement); 
        
        // Get the panel's body cell and its bounds
        var panelBodyID = String.format('{0}_BodyCell', this.get_id());
        var panelBody = $get(panelBodyID);
        var panelBodyBounds = Sys.UI.DomElement.getBounds(panelBody);   

        // Get the bounds of the content div
        var divBounds;
        var getDimensionsFromStyle = false;
        try {
            divBounds = Sys.UI.DomElement.getBounds(this._contentDiv);
        } catch (ex) {
            getDimensionsFromStyle = true;
        }        
        if (getDimensionsFromStyle || divBounds.width == 0)
            divBounds = this._getDimensionsFromStyle(this._contentDiv);

        // Get the bounds of the content table
        getDimensionsFromStyle = false;
        var tableBounds;
        try {           
            tableBounds = Sys.UI.DomElement.getBounds(this._contentTable);
        } catch (ex) {
            getDimensionsFromStyle = true;
        }
        if (getDimensionsFromStyle || tableBounds.width == 0)
            tableBounds = this._getDimensionsFromStyle(this._contentTable);
        
        // Get the numeric values of the specified initial maximum width and height
        var initialMaxWidthStyle = this.get_initialMaxWidth();
        var initialMaxWidth = parseInt(initialMaxWidthStyle);
        var initialMaxHeightStyle = this.get_initialMaxHeight();
        var initialMaxHeight = parseInt(initialMaxHeightStyle);
        
        var initialWidth;
        var initialHeight;
        
        var verticalScrollbarBuffer = 0;
        var horizontalScrollbarBuffer = 0;
        var usingMaxWidth = false;
        
        // Check whether the initial maximum width is defined and the table dimensions exceed it
        if (initialMaxWidth && initialMaxWidth > 0 && tableBounds.width > initialMaxWidth) {
            // The table width exceeds the initial max width, so initialize the initial width as the
            // max width and set a buffer for the horizontal scroll bar that will appear.
            initialWidth = initialMaxWidthStyle;
            horizontalScrollbarBuffer = 20;
        }
        else {
            // The table width can be contained within the max initial width, so simply use the table
            // width as the initial width
            initialWidth = tableBounds.width + 'px';
        }

        if (initialMaxHeight && initialMaxHeight > 0 && tableBounds.height > initialMaxHeight)
        {
            // The table height exceeds the initial max width, so initialize the initial height as the
            // max height and set a buffer for the vertical scroll bar that will appear.
            initialHeight = initialMaxHeightStyle;
            verticalScrollbarBuffer = 20;
            // Set style properties needed to properly format the panel contents if there is no 
            // horizontal scrollbar
            if (horizontalScrollbarBuffer == 0)
            {
                this._contentDiv.style.overflowX = 'hidden';
                this._contentDiv.style.overflow = '';
                this._contentDiv.style.overflowY = 'auto';
            }            
        }
        else {
            // The table height can be contained within the max initial height, so simply use the table
            // height as the initial height
            initialHeight = tableBounds.height + 'px';
        }
        
        // Get the numeric initial dimensions, taking into account scrollbar buffers
        initialWidth = (parseInt(initialWidth) + verticalScrollbarBuffer) + 'px';
        initialHeight = (parseInt(initialHeight) + horizontalScrollbarBuffer) + 'px';

        // If the content div's width and height don't already equal the calculated initial dimenions, 
        // apply the calculated dimensions
        this._contentDiv.style.width = (divBounds.width != parseInt(initialWidth)) ? 
            initialWidth : this._contentDiv.style.width;
        this._contentDiv.style.height = (divBounds.height != parseInt(initialHeight)) ?
            initialHeight : this._contentDiv.style.height;

        // If the panel container element's width doesn't already match the calculated initial
        // width, apply the calculated width
        panelElement.style.width = (panelBounds.width != parseInt(initialWidth)) ?
            initialWidth : panelElement.style.width;

        // If the panel body cell's height doesn't already match the calculated initial height,
        // apply the calculated height
        panelBody.style.height = (panelBodyBounds.height != parseInt(initialHeight)) ? 
            initialHeight : panelBody.style.height;

        // The panel was moved off screen by _onPanelShown so the user would not see it before its
        // size was initialized.  Move the it back on-screen to its original position        
        panelElement.style.top = this._top;

        // Set the flag indicating that size has been initialized
        this._sizeInitialized = true;
    },    
    
    // Retrieves the element's dimensions based on its CSS properties
    _getDimensionsFromStyle : function(element)
    {
        var width = parseInt(element.style.width);
        width = isNaN(width) ? 0 : width;
        var height = parseInt(element.style.height);
        height = isNaN(height) ? 0 : height;
        
        return { 'width':width, 'height':height };
    },
    
    // Retrieves the browser windows dimensions
    _getBrowserDimensions : function() {
        var browserWidth, browserHeight;
        // Window dimensions:
        if (window.innerWidth) 
            browserWidth=window.innerWidth;
        else if (document.documentElement && document.documentElement.clientWidth)
            browserWidth=document.documentElement.clientWidth;
        else if (document.body) 
            browserWidth=document.body.clientWidth;
            
        if (window.innerHeight) 
            browserHeight=window.innerHeight;
        else if (document.documentElement && document.documentElement.clientHeight) 
            browserHeight=document.documentElement.clientHeight;
        else if (document.body) 
            browserHeight=document.body.clientHeight;
            
        return { 'width':browserWidth, 'height':browserHeight };
    }
}

// Register the TaskResultsPanel class, specifying inheritance from ESRI.ADF.UI.FloatingPanel
ESRI.ADF.Samples.CustomTasks.TaskResultsPanel.registerClass(
    'ESRI.ADF.Samples.CustomTasks.TaskResultsPanel', ESRI.ADF.UI.FloatingPanel);