• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 142
  • Last Modified:

Script looping when no element is present on page

In this script towards the bottom is the 'blink' function.  The problem with it is that if the element with id 'blink' is not on the page (which it won't be until user add item to basket) then the script keeps looping ad infinitum whilst it looks for the element.  How could I modify the code so that it gives up after one loop if the element's not there?


var floatingMenu =
{
    hasInner: typeof(window.innerWidth) == 'number',
    hasElement: typeof(document.documentElement) == 'object'
        && typeof(document.documentElement.clientWidth) == 'number'
};

var floatingArray =
[
];

floatingMenu.add = function(obj, options)
{
    var name;
    var menu;

    if (typeof(obj) === "string")
        name = obj;
    else
        menu = obj;
        

    if (options == undefined)
    {
        floatingArray.push( 
            {
                id: name,
                menu: menu,

                targetLeft: 0,
                targetTop: 0,

                snap: true
            });
    }
    else
    {
        floatingArray.push( 
            {
                id: name,
                menu: menu,

                targetLeft: options.targetLeft,
                targetRight: options.targetRight,
                targetTop: options.targetTop,
                targetBottom: options.targetBottom,

                centerX: options.centerX,
                centerY: options.centerY,

                prohibitXMovement: options.prohibitXMovement,
                prohibitYMovement: options.prohibitYMovement,

                snap: options.snap,
                ignoreParentDimensions: options.ignoreParentDimensions,

                scrollContainer: options.scrollContainer,
                scrollContainerId: options.scrollContainerId
            });
    }
};

floatingMenu.findSingle = function(item)
{
    if (item.id)
        item.menu = document.getElementById(item.id);

    if (item.scrollContainerId)
        item.scrollContainer = document.getElementById(item.scrollContainerId);
};

floatingMenu.move = function (item)
{
    if (!item.prohibitXMovement)
    {
        item.menu.style.left = item.nextX + 'px';
        item.menu.style.right = '';
    }

    if (!item.prohibitYMovement)
    {
        item.menu.style.top = item.nextY + 'px';
        item.menu.style.bottom = '';
    }
};

floatingMenu.scrollLeft = function(item)
{
    if (item.scrollContainer)
        return item.scrollContainer.scrollLeft;

    var w = window;

    // Find top window scroll parameters if we're IFRAMEd
    while (w != w.parent)
        w = w.parent;

    return this.hasInner
        ? w.pageXOffset  
        : this.hasElement  
          ? w.document.documentElement.scrollLeft  
          : w.document.body.scrollLeft;
};

floatingMenu.scrollTop = function(item)
{
    if (item.scrollContainer)
        return item.scrollContainer.scrollTop;

    var w = window;

    // Find top window scroll parameters if we're IFRAMEd
    while (w != w.parent)
        w = w.parent;

    return this.hasInner
        ? w.pageYOffset
        : this.hasElement
          ? w.document.documentElement.scrollTop
          : w.document.body.scrollTop;
};

floatingMenu.windowWidth = function()
{
    return this.hasElement
        ? document.documentElement.clientWidth
        : document.body.clientWidth;
};

floatingMenu.windowHeight = function()
{
    if (floatingMenu.hasElement && floatingMenu.hasInner)
    {
        // Handle Opera 8 problems
        return document.documentElement.clientHeight > window.innerHeight
            ? window.innerHeight
            : document.documentElement.clientHeight
    }
    else
    {
        return floatingMenu.hasElement
            ? document.documentElement.clientHeight
            : document.body.clientHeight;
    }
};

floatingMenu.documentHeight = function()
{
    var innerHeight = this.hasInner
        ? window.innerHeight
        : 0;

    var body = document.body,
        html = document.documentElement;

    return Math.max(
        body.scrollHeight,
        body.offsetHeight, 
        html.clientHeight,
        html.scrollHeight,
        html.offsetHeight,
        innerHeight);
};

floatingMenu.documentWidth = function()
{
    var innerWidth = this.hasInner
        ? window.innerWidth
        : 0;

    var body = document.body,
        html = document.documentElement;

    return Math.max(
        body.scrollWidth,
        body.offsetWidth, 
        html.clientWidth,
        html.scrollWidth,
        html.offsetWidth,
        innerWidth);
};

floatingMenu.calculateCornerX = function(item)
{
    var offsetWidth = item.menu.offsetWidth;

    if (item.centerX)
        return this.scrollLeft(item) + (this.windowWidth() - offsetWidth)/2;

    var result = this.scrollLeft(item) - item.parentLeft;
    if (item.targetLeft == undefined)
    {
        result += this.windowWidth() - item.targetRight - offsetWidth;
    }
    else
    {
        result += item.targetLeft;
    }
        
    if (document.body != item.menu.parentNode
        && result + offsetWidth >= item.confinedWidthReserve)
    {
        result = item.confinedWidthReserve - offsetWidth;
    }

    if (result < 0)
        result = 0;

    return result;
};

floatingMenu.calculateCornerY = function(item)
{
    var offsetHeight = item.menu.offsetHeight;

    if (item.centerY)
        return this.scrollTop(item) + (this.windowHeight() - offsetHeight)/2;

    var result = this.scrollTop(item) - item.parentTop;
    if (item.targetTop === undefined)
    {
        result += this.windowHeight() - item.targetBottom - offsetHeight;
    }
    else
    {
        result += item.targetTop;
    }

    if (document.body != item.menu.parentNode
        && result + offsetHeight >= item.confinedHeightReserve)
    {
        result = item.confinedHeightReserve - offsetHeight;
    }

    if (result < 0)
        result = 0;
        
    return result;
};

floatingMenu.computeParent = function(item)
{
    if (item.ignoreParentDimensions)
    {
        item.confinedHeightReserve = this.documentHeight();
        item.confinedWidthReserver = this.documentWidth();
        item.parentLeft = 0;  
        item.parentTop = 0;  
        return;
    }

    var parentNode = item.menu.parentNode;
    var parentOffsets = this.offsets(parentNode, item);
    item.parentLeft = parentOffsets.left;
    item.parentTop = parentOffsets.top;

    item.confinedWidthReserve = parentNode.clientWidth;

    // We could have absolutely-positioned DIV wrapped
    // inside relatively-positioned. Then parent might not
    // have any height. Try to find parent that has
    // and try to find whats left of its height for us.
    var obj = parentNode;
    while (obj.clientHeight < item.menu.offsetHeight)
    {
        obj = obj.parentNode;
    }

    var hasHeightOffsets = this.offsets(obj, item);

    item.confinedHeightReserve = obj.clientHeight
        - (parentOffsets.top - hasHeightOffsets.top);
};

floatingMenu.offsets = function(obj, item)
{
    var result =
    {
        left: 0,
        top: 0
    };

    if (obj === item.scrollContainer)
        return;

    while (obj.offsetParent && obj.offsetParent != item.scrollContainer)
    {  
        result.left += obj.offsetLeft;  
        result.top += obj.offsetTop;  
        obj = obj.offsetParent;
    }  

    if (window == window.parent)
        return result;

    // we're IFRAMEd
    var iframes = window.parent.document.body.getElementsByTagName("IFRAME");
    for (var i = 0; i < iframes.length; i++)
    {
        if (iframes[i].contentWindow != window)
           continue;

        obj = iframes[i];
        while (obj.offsetParent)  
        {  
            result.left += obj.offsetLeft;  
            result.top += obj.offsetTop;  
            obj = obj.offsetParent;
        }  
    }

    return result;
};

floatingMenu.doFloatSingle = function(item)
{
    this.findSingle(item);

    var stepX, stepY;

    this.computeParent(item);

    var cornerX = this.calculateCornerX(item);

    var stepX = (cornerX - item.nextX) * .07;
    if (Math.abs(stepX) < .5 && item.snap
        || Math.abs(cornerX - item.nextX) == 1)
    {
        stepX = cornerX - item.nextX;
    }

    var cornerY = this.calculateCornerY(item);

    var stepY = (cornerY - item.nextY) * .07;
    if (Math.abs(stepY) < .5 && item.snap
        || Math.abs(cornerY - item.nextY) == 1)
    {
        stepY = cornerY - item.nextY;
    }

    if (Math.abs(stepX) > 0 ||
        Math.abs(stepY) > 0)
    {
        item.nextX += stepX;
        item.nextY += stepY;
        this.move(item);
    }
};

floatingMenu.fixTargets = function()
{
};

floatingMenu.fixTarget = function(item)
{
};

floatingMenu.doFloat = function()
{
    this.fixTargets();
    for (var i=0; i < floatingArray.length; i++)
    {
        this.fixTarget(floatingArray[i]);
        this.doFloatSingle(floatingArray[i]);
    }
    setTimeout('floatingMenu.doFloat()', 20);
};


floatingMenu.insertEvent = function(element, listener, handler)
{
    var oldHandler = element[listener];
    element[listener] = function (e)
        {
            e = (e) ? e : window.event;
            var result = handler(e);
            return (oldHandler != undefined) 
                && (oldHandler(e) == true)
                && (result == true);
        };
};

floatingMenu.init = function()
{
    floatingMenu.fixTargets();

    for (var i=0; i < floatingArray.length; i++)
    {
        floatingMenu.initSingleMenu(floatingArray[i]);
    }

    setTimeout('floatingMenu.doFloat()', 100);
    timer = setInterval('blink()', 200);            // activate blink function
};

var i = 1,timer;
function blink() {
 if (i<10) {
        if (i%2 == 0) { 
              document.getElementById('blink').style.backgroundColor = '#D9789F';
         } else {
              document.getElementById('blink').style.backgroundColor = '#FFFFFF';
         }
 } else {
      document.getElementById('blink').style.backgroundColor = '#FFFFFF';
      clearInterval(timer);
  }
 i++;
}


// Some browsers init scrollbars only after
// full document load.
floatingMenu.initSingleMenu = function(item)
{
    this.findSingle(item);
    this.computeParent(item);
    this.fixTarget(item);
    item.nextX = this.calculateCornerX(item);
    item.nextY = this.calculateCornerY(item);
    this.move(item);
};

floatingMenu.insertEvent(window, 'onload', floatingMenu.init);

Open in new window

0
naryan109
Asked:
naryan109
  • 5
  • 4
1 Solution
 
sjklein42Commented:
I think that what is happening is that the execution of Blink is aborted by the error triggered by the missing ID, and the i++ is not executed.

My quick and dirty solution is to move the i++ to the beginning of the function, so it is done even if the ID is missing.

Change the initial value for i to zero to make up for the changed order.

var i = 0,timer;
function blink() {
 i++;
 if (i<10) {
        if (i%2 == 0) { 
              document.getElementById('blink').style.backgroundColor = '#D9789F';
         } else {
              document.getElementById('blink').style.backgroundColor = '#FFFFFF';
         }
 } else {
      document.getElementById('blink').style.backgroundColor = '#FFFFFF';
      clearInterval(timer);
  }
}

Open in new window

0
 
naryan109Author Commented:
I've tried it, but unfortunately it doesn't seem of fixed the problem - the line of code below keeps repeating endlessly.

 
document.getElementById('blink').style.backgroundColor = '#FFFFFF';

Open in new window

0
 
sjklein42Commented:
Try moving the definition of the timer variable several lines up, to before you first refer to it, at least before line 383.

If that doesn't help, put an "alert(i)" right before the repeating 'blink' line so we can see why it isn't properly incrementing and controlling the loop.
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
naryan109Author Commented:
I've just moved the line: "var i = 0,timer;" to line 382.  The same problem occurred so I put the alert in as below.  The dialogues demonstrate that "i" is incrementing as each dialogue has the next incrementing number.

function blink() {
 i++;
 if (i<0) {
        if (i%2 == 0) { 
              document.getElementById('blink').style.backgroundColor = '#D9789F';
         } else {

			  document.getElementById('blink').style.backgroundColor = '#FFFFFF';
         }
 } else {
		alert(i)
		document.getElementById('blink').style.backgroundColor = '#FFFFFF';
      clearInterval(timer);
  }
}

Open in new window

0
 
naryan109Author Commented:
Moving "i++" to earlier in the script also stopped the script from working, so I've moved it back for now.
0
 
sjklein42Commented:
You are incrementing i, but checking it against zero on line 3!  So it will always be greater than zero!

What happened to this code?  You changed the 10 to zero!

 if (i<10) {

Open in new window

0
 
naryan109Author Commented:
That was a mistake.  I realised what I had done and changed it back.  The script is thus now:

var i = 0,timer;
function blink() {
 if (i<10) {
        if (i%2 == 0) { 
              document.getElementById('blink').style.backgroundColor = '#D9789F';
         } else {
              document.getElementById('blink').style.backgroundColor = '#FFFFFF';
         }
 } else {
	  document.getElementById('blink').style.backgroundColor = '#FFFFFF';
      clearInterval(timer);
  }
   i++;
}

Open in new window

0
 
sjklein42Commented:
Here's an easy, clean solution:

var i = 0,timer;
function blink() {
        if ( document.getElementById('blink') == undefined ) clearInterval(timer);
        else if (i<10) {
                if (i%2 == 0) { 
                        document.getElementById('blink').style.backgroundColor = '#D9789F';
                } else {
                        document.getElementById('blink').style.backgroundColor = '#FFFFFF';
                }
        } else {
                document.getElementById('blink').style.backgroundColor = '#FFFFFF';
                clearInterval(timer);
        }
        i++;
}

Open in new window

0
 
naryan109Author Commented:
Of course.  That makes sense and indeed it works.  Thank you for your help!  I'm learning javascript so this has been useful, thanks.
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 5
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now