/**
 * Pieforms: Advanced web forms made easy
 * Copyright (C) 2006-2008 Catalyst IT Ltd (http://www.catalyst.net.nz)
 * Copyright (C) 2006 Drupal (http://www.drupal.org)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @package    pieform
 * @subpackage static
 * @author     Nigel McNie <nigel@catalyst.net.nz>
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL
 * @copyright  (C) 2006-2008 Catalyst IT Ltd http://catalyst.net.nz
 * @copyright  (C) 2006 Drupal http://www.drupal.org
 *
 */

/**
 * Retrieves the absolute position of an element on the screen
 * This function (C) 2006 Drupal
 */
function absolutePosition(el) {//{{{
    var sLeft = 0, sTop = 0;
    var isDiv = /^div$/i.test(el.tagName);
    if (isDiv && el.scrollLeft) {
        sLeft = el.scrollLeft;
    }
    if (isDiv && el.scrollTop) {
        sTop = el.scrollTop;
    }
    var r = { x: el.offsetLeft - sLeft, y: el.offsetTop - sTop };
    if (el.offsetParent) {
        var tmp = absolutePosition(el.offsetParent);
        r.x += tmp.x;
        r.y += tmp.y;
    }
    return r;
}//}}}

/**
 * This class based on Drupal's textArea class, which is (C) 2006 Drupal
 *
 * Provides a 'grippie' for resizing a textarea vertically.
 */
function PieformTextarea(element) {//{{{
    var self = this;

    this.element = element;
    this.parent = this.element.parentNode;
    this.dimensions = getElementDimensions(element);

    // Prepare wrapper
    this.wrapper = DIV({'class':'resizable-textarea'});
    insertSiblingNodesBefore(this.element, this.wrapper);

    // Add grippie and measure it
    this.grippie = DIV({'class': 'grippie'});
    appendChildNodes(this.wrapper, this.grippie);
    this.grippie.dimensions = getElementDimensions(this.grippie);

    // Set wrapper and textarea dimensions
    setElementDimensions(this.wrapper, {'h': this.dimensions.h + this.grippie.dimensions.h + 1, 'w': this.dimensions.w});
    setStyle(this.element, {
        'margin-bottom': '0',
        'width': '100%',
        'height': this.dimensions.h + 'px'
    });

    // Wrap textarea
    removeElement(this.element);
    insertSiblingNodesBefore(this.grippie, this.element);

    // Measure difference between desired and actual textarea dimensions to account for padding/borders
    this.widthOffset = getElementDimensions(this.wrapper).w - this.dimensions.w;

    // Make the grippie line up in various browsers
    if (window.opera) {
        setStyle(this.grippie, {'margin-right': '4px'});
    }
    if (document.all && !window.opera) {
        this.grippie.style.width = '100%';
        this.grippie.style.paddingLeft = '2px';
        setStyle(this.grippie, {
            'padding-left': '2px'
        });
    }
    this.element.style.MozBoxSizing = 'border-box';

    this.heightOffset = absolutePosition(this.grippie).y - absolutePosition(this.element).y - this.dimensions.h;


    this.handleDrag = function (e) {//{{{
        // Get coordinates relative to text area
        var pos = absolutePosition(this.element);
        var y = e.mouse().client.y - pos.y;

        // Set new height
        var height = Math.max(32, y - this.dragOffset - this.heightOffset);
        setStyle(this.wrapper, {'height': height + this.grippie.dimensions.h + 1 + 'px'});
        setStyle(this.element, {'height': height + 'px'});

        // Avoid text selection
        e.stop();
    }//}}}

    this.endDrag = function (e) {//{{{
        disconnect(this.mouseMoveHandler);
        disconnect(this.mouseUpHandler);
        document.isDragging = false;
    }//}}}

    this.beginDrag = function(e) {//{{{
        if (document.isDragging) {
            return;
        }
        document.isDragging = true;

        self.mouseMoveHandler = connect(document, 'onmousemove', self, 'handleDrag');
        self.mouseUpHandler   = connect(document, 'onmouseup', self, 'endDrag');

        // Store drag offset from grippie top
        var pos = absolutePosition(this.grippie);
        this.dragOffset = e.mouse().client.y - pos.y;

        // Process
        this.handleDrag(e);
    }//}}}

    connect(this.grippie, 'onmousedown', self, 'beginDrag');
}//}}}

