views:

70

answers:

1

SOLVED: SEE "CORRECTED SOLUTION" Area (below)

--------------------------------- ORIGINAL TEXT ---------------------------

I've created a JavaScript toaster popup to show info about an individual row. It works great in FireFox...but it goes down in flames in IE.

...suggestions and help appreciated.

WHAT I THINK IS FAILING: I think I declared the "Toaster" class wrong and IE isn't doesn't recognize it as an array. As such, when I call "PopUp(clientId)" on the toaster it fails becuase it doesn't traverse the array.

Additionally, FireFox populates the array correctly in the documents "ready" function...but I'm not sure IE is doing so.

Lastly, since I am still new to JavaScript it (obviously) could be HOW I am creating the classes (as well).

WHERE IT FAILS: The code fails because the value of "target" is null. This variable is null because IE doesn't seem to traverse the Toaster (array).

this.PopUp = function(clientId) {

    var target = null;

    jQuery.each(this, function() {
        // Hide previous
        if (jQuery(this)[0].IsUp)
            jQuery(this)[0].PopDown();

        if (jQuery(this)[0].ClientId == clientId)
            target = jQuery(this)[0];
    });

    // Show current
    target.PopUp();
}

THE FULL CODE SET: Thanks for the help...

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title></title>

    <script src="../Includes/JavaScript/jQuery/Core/jquery-1.3.2.js" type="text/javascript"></script>

    <style type="text/css">
        .toast
        {
            width: 100%; 
            position: relative;
        }
        .toastBorder
        {
            width: 100%; 
            position: absolute;
            border-radius-topright:.5em;
            border-radius-topleft:.5em;
            -moz-border-radius-topright:.5em;
            -moz-border-radius-topleft:.5em;
            -webkit-border-radius-topright:.5em;
            -webkit-border-radius-topleft:.5em;
            background-color: #FFFFCC;
            border: 1px solid #969696;
            border-bottom-color: White;
            display:none;
            height: 0;
            bottom: 0;
        }
        .toastForm
        {
            display:none;
        }
    </style>

    <script type="text/javascript">

        // CLASS DEFINITION:
        function Toast(clientId, height, speed) {

            // PROPERTIES
            this.IsUp = false;
            this.IsDown = false;
            this.ClientId = clientId;
            this.Height = height;
            this.Speed = speed;

            // METHODS
            this.PopUp = function() {

                if (this.IsUp) { return; }
                this.IsUp = true;
                this.IsDown = false;

                var speed = this.Speed;
                var action = '+=' + this.Height + "px";

                // Border
                jQuery('#' + this.ClientId).children('div.toastBorder').fadeIn('fast', function() {
                    jQuery(this).animate({ height: action }, speed, function() {
                        // Form
                        jQuery(this).children('div.toastForm').fadeIn('fast');
                    });
                });
            }
            this.PopDown = function() {

                if (this.IsDown) { return; }
                this.IsUp = false;
                this.IsDown = true;

                var speed = this.Speed;
                var action = '-=' + this.Height + "px";

                // Form
                jQuery('#' + this.ClientId).children('div.toastBorder').children('div.toastForm').fadeOut('fast');

                // Border
                jQuery('#' + this.ClientId + ' div.toastBorder').animate({ height: action }, speed, function() {
                    jQuery(this).fadeOut('fast');
                });
            }
        }

        // CLASS DEFINITION:
        function Toaster() {
            // PROPERTIES

            // METHODS
            this.PopUp = function(clientId) {

                var target = null;

                jQuery.each(this, function() {
                    // Hide previous
                    if (jQuery(this)[0].IsUp)
                        jQuery(this)[0].PopDown();

                    if (jQuery(this)[0].ClientId == clientId)
                        target = jQuery(this)[0];
                });

                // Show current
                target.PopUp();
            }
            this.PopDown = function(clientId) {

                jQuery.each(this, function() {
                    if (jQuery(this)[0].ClientId == clientId)
                        jQuery(this)[0].PopDown(); // Hide current
                });
            }
            this.Add = function(toast) {

                var found = false;

                // No duplicates are allowed
                jQuery.each(this, function() {
                    if (jQuery(this)[0].ClientId == toast.ClientId)
                        found = true;
                });

                if (!found)
                    this.push(toast);
            }
        }

        // CLASS DEFINITION: Toaster inheritance
        Toaster.prototype = new Array();

        var myToaster;
        var myToast;

        // DOM EVENT: Document.Ready()
        jQuery(document).ready(function() {

            if (myToaster == null)
                myToaster = new Toaster();

            myToaster.Add(new Toast("row1", 100, 200));
            myToaster.Add(new Toast("row2", 100, 200));
            myToaster.Add(new Toast("row3", 100, 200));
            myToaster.Add(new Toast("row4", 100, 200));
            myToaster.Add(new Toast("row5", 100, 200));

            // These BOTH return true in IE...
            //alert(myToaster.Items instanceof Array);
            //alert(myToaster instanceof Array);

            // This is for the button example
            if (myToast == null)
                myToast = new Toast("row3", 100, 200);
        });
    </script>

</head>
<body>

    <br />
    I need help on the following:
    <ul>
        <li>
            This works GREAT in FireFox
        </li>
        <li>
            IE doesn't seem to recognize the Toaster class as being an array.
        </li>
    </ul>

    <div style="width: 300;">   
        <label style="display:block;color: #660000;">INDIVIDUAL pieces of toast work fine in IE:</label>
        <input type="button" value="Down (row 3)" onclick="myToast.PopDown();" />
        <input type="button" value="Up (row 3)" onclick="myToast.PopUp();" />
    </div>

    <br /><br />

    <label style="color: #660000">Clicking a row IS SUPPOSED TO toggle a "piece of toast" for that row.</label>
    <br /><br />

    <table cellpadding="0" cellspacing="0" width="500" style=" border: solid 1px black">
        <tr>
            <td align="center" style="border-bottom: solid 1px black;">
                Header
            </td>
            <td align="center" style="border-bottom: solid 1px black;">
                Header
            </td>
            <td align="center" style="border-bottom: solid 1px black;">
                Header
            </td>
            <td align="center" style="border-bottom: solid 1px black;">
                Header
            </td>
            <td align="center" style="border-bottom: solid 1px black;">
                Header
            </td>
        </tr>
        <tr>
            <td>
            </td>
            <td colspan="3">
                <div id="row1" class="toast">
                    <div class="toastBorder">
                        <div align="center" class="toastForm">
                            <br />
                             Hello
                            <br /><br /><br /><br /><br />
                        </div>
                    </div>
                </div>
            </td>
            <td>
            </td>
        </tr>
        <tr onclick="myToaster.PopUp('row1');">
            <td align="center">
                Data
            </td>
            <td align="center">
                Data
            </td>
            <td align="center">
                Data
            </td>
            <td align="center">
                Data
            </td>
            <td align="center">
                Data
            </td>
        </tr>
        <tr>
            <td>
            </td>
            <td colspan="3">
                <div id="row2" class="toast">
                    <div class="toastBorder">
                        <div align="center" class="toastForm">
                            <br />
                             Hello
                            <br /><br /><br /><br /><br />
                            </div>
                    </div>
                </div>
            </td>
            <td>
            </td>
        </tr>
        <tr onclick="myToaster.PopUp('row2');">
            <td align="center">
                Data
            </td>
            <td align="center">
                Data
            </td>
            <td align="center">
                Data
            </td>
            <td align="center">
                Data
            </td>
            <td align="center">
                Data
            </td>
        </tr>
        <tr>
            <td>
            </td>
            <td colspan="3">
                <div id="row3" class="toast">
                    <div class="toastBorder">
                        <div align="center" class="toastForm">
                            <br />
                             Hello
                            <br /><br /><br /><br /><br />
                        </div>
                    </div>
                </div>
            </td>
            <td>
            </td>
        </tr>
        <tr onclick="myToaster.PopUp('row3');">
            <td align="center">
                Data
            </td>
            <td align="center">
                Data
            </td>
            <td align="center">
                Data
            </td>
            <td align="center">
                Data
            </td>
            <td align="center">
                Data
            </td>
        </tr>
        <tr>
            <td>
            </td>
            <td colspan="3">
                <div id="row4" class="toast">
                    <div class="toastBorder">
                        <div align="center" class="toastForm">
                            <br />
                             Hello
                            <br /><br /><br /><br /><br />
                        </div>
                    </div>
                </div>
            </td>
            <td>
            </td>
        </tr>
        <tr onclick="myToaster.PopUp('row4');">
            <td align="center">
                Data
            </td>
            <td align="center">
                Data
            </td>
            <td align="center">
                Data
            </td>
            <td align="center">
                Data
            </td>
            <td align="center">
                Data
            </td>
        </tr>
        <tr>
            <td>
            </td>
            <td colspan="3">
                <div id="row5" class="toast">
                    <div class="toastBorder">
                        <div align="center" class="toastForm">
                            <br />
                                Hello
                            <br /><br /><br /><br /><br />
                        </div>
                    </div>
                </div>
            </td>
            <td>
            </td>
        </tr>
        <tr onclick="myToaster.PopUp('row5');">
            <td align="center">
                Data
            </td>
            <td align="center">
                Data
            </td>
            <td align="center">
                Data
            </td>
            <td align="center">
                Data
            </td>
            <td align="center">
                Data
            </td>
        </tr>
    </table>

</body>
</html>

HERE IS THE CORRECTED SOLUTION:

// CLASS DEFINITION:
function Toast(clientId, maxHeight, speed) {

    // PROPERTIES
    this.ClientId = clientId;
    this.MaxHeight = maxHeight;
    this.Speed = speed;

    // METHODS
    this.IsUp = function() {
        return (jQuery('#' + this.ClientId).children().height() > 0) ? true : false;
    }
    this.PopUp = function() {

        if (this.IsUp()) { return; }

        var speed = this.Speed;
        var action = '+=' + this.MaxHeight + "px";

        // Border
        jQuery('#' + this.ClientId).children('div.toastBorder').fadeIn('fast', function() {
            jQuery(this).animate({ height: action }, speed, function() {
                // Form
                jQuery(this).children('div.toastForm').fadeIn('fast');
            });
        });

        this.IsUp(true);
    }
    this.PopDown = function() {

        if (!this.IsUp()) { return; }

        var speed = this.Speed;
        var action = '-=' + this.MaxHeight + "px";

        // Form
        jQuery('#' + this.ClientId).children('div.toastBorder').children('div.toastForm').fadeOut('fast');

        // Border
        jQuery('#' + this.ClientId).children('div.toastBorder').animate({ height: action }, speed, function() {
            jQuery(this).fadeOut('fast');
        });

        this.IsUp(false);
    }
}

// CLASS DEFINITION:
function Toaster() {
    // PROPERTIES
    this.Items = new Array();

    // METHODS
    this.PopUp = function(clientId) {

        var target = null;

        jQuery.each(this.Items, function() {
            if (jQuery(this)[0].ClientId != clientId) {
                if (jQuery(this)[0].IsUp()) {
                    jQuery(this)[0].PopDown(); // Hide previous
                }
            }

            if (jQuery(this)[0].ClientId == clientId) {
                target = jQuery(this)[0];
            }
        });

        if (target != null) {
            if (target.IsUp() == false)
                target.PopUp();
        }
    }
    this.PopDown = function(clientId) {
        jQuery.each(this.Items, function() {
            if (jQuery(this)[0].ClientId == clientId)
                jQuery(this)[0].PopDown(); // Hide current
        });
    }
    this.Add = function(toast) {

        var found = false;

        // No duplicates are allowed
        jQuery.each(this.Items, function() {
            if (jQuery(this.Items)[0].ClientId == toast.ClientId)
                found = true;
        });

        if (!found)
            this.Items.push(toast);
    }
}

var myToaster;
var myToast;

// DOM EVENT: Document.Ready()
$j(document).ready(function() {

    if (myToaster == null)
        myToaster = new Toaster();

    myToaster.Add(new Toast("row1", 125, 200));
    myToaster.Add(new Toast("row2", 125, 200));
    myToaster.Add(new Toast("row3", 125, 200));
    myToaster.Add(new Toast("row4", 125, 200));
    myToaster.Add(new Toast("row5", 125, 200));
});
</script>
+1  A: 

The attempt to "subclass" Array by using it as the prototype object for your "Toaster" class is not going to work in IE, for whatever reason. If you debug the "Add" method, you'll notice that calls to "push" don't seem to fail, but they also don't change the length of the Toaster.

Trying to make Javascript act like a nice polite object-oriented language is fraught with peril, particularly when you try and treat the native types (like Array) as if they're implemented in Javascript too.

I'd just keep an array around as part of "Toaster" someplace.

Pointy
@Pointy: Thanks...I'll try that and report back.
@Pointy: You are correct sir! Muchas Thankas!