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

naryan109Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

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
Ultimate Tool Kit for Technology Solution Provider

Broken down into practical pointers and step-by-step instructions, the IT Service Excellence Tool Kit delivers expert advice for technology solution providers. Get your free copy now.

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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
JavaScript

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.