0

This is a function that creates breadcrumbs. It initially came from someone else, but I've tweaked it to work for my needs. Now--I'd like to fix the bad syntax of 'for(i in bits)', but when I've tried what I thought would work, it does not work.

for (i = 0; i < bits; i++) {etc...};

I thought that would work, it does not work. Here is the full script...

function breadcrumbs() {
'use strict';
/*jslint plusplus:true*/
/*jslint browser:true*/
var sURL, bits, x, stop, output, i, y, chunkStart;
sURL = String();
bits = {};
x = 0;
stop = 0;
output = "";
sURL = location.href;
sURL = sURL.slice(8, sURL.length);
chunkStart = sURL.indexOf("/");
sURL = sURL.slice(chunkStart + 1, sURL.length);
while (!stop) {
    chunkStart = sURL.indexOf("/");
    if (chunkStart !== -1) {
        bits[x] = sURL.slice(0, chunkStart);
        sURL = sURL.slice(chunkStart + 1, sURL.length);
    } else {
        stop = 1;
    }
    x++;
}
for (i in bits) {
    output += "<a href=\"";
    for (y = 1; y < x - i; y++) {
        output += "../";
    }
    bits[i] = decodeURIComponent(bits[i]);
    output += bits[i] + "/\">" + bits[i] + "</a> &nbsp;|&nbsp; ";
}
document.write(output + document.title);
}
Mike Earley
  • 1,223
  • 4
  • 20
  • 47
  • You need to add the length property as show here: for (i = 0; i < bits.length; i++) {etc...}; – MKS Dec 12 '12 at 19:46
  • 2
    As `bits` is an object, not an `array`, there is nothing wrong with using the `for...in` statement to loop over it. – jbabey Dec 12 '12 at 19:47
  • It ends up being an array though, as what it's doing is getting the various directory folders and turning them in to links. So I'm guessing I should have bits = []; instead of bits = {};. – Mike Earley Dec 12 '12 at 20:31

6 Answers6

3

You need to replace object-related code with array-related in following lines:

// original code                 // fixed code
bits = {};                       bits = [];
for (i in bits) {                for (i = 0; i < bits.length; ++i) {

By the way, you can use sURL.split("/") to split URL into array of chunks.

Victor
  • 3,669
  • 3
  • 37
  • 42
2

This article Exploring JavaScript for-in loops might be helpful.

You would want to use a loop as in

for (i = 0; i < bits.length; i++) {
  // stuff.
}

Also see this stackover flow JavaScript "For ...in" with Arrays.

Community
  • 1
  • 1
Richard Chambers
  • 16,643
  • 4
  • 81
  • 106
2

Bits is an object ({}, instead of []). For in will iterate over all of its properties. If you want it to be an array bits should be initalized as an array. You'll also need to use the length property in your for loop. for (i = 0;i

  • 1
    Yeah I think this is what I need to do...it SHOULD be an array as I understand it, since it's attempting to iterate through the URL and pars out the directory structure. – Mike Earley Dec 12 '12 at 20:32
2

Your bits is a JavaScript Object Literal not an Array. You should not (cannot) use a traditional for loop to iterate an object. Thus, the usage of the for...in is correct. However, there is one mistake present -- the loop does not verify that the property of the object is one that should be iterated. That is, your loop is iterating over the prototype properties in addition to the object's own properties. The correct usage of the for...in would be:

for (prop in bits) {
  if (!bits.hasOwnProperty(prop)) {
    continue;
  }
  // Do something with `bits[prop]`.
}
James Sumners
  • 14,485
  • 10
  • 59
  • 77
2

The problem with for-in is that it iterates over an objects properties.

Try the following code. Note: The while loop that created the bits array has been replaced with split & slice, and the breadcrumb URL has been simplified

var sURL = location.href;
// the following line is just for testing...
sURL = "http://testURL.com/one/two/three/four";
var bits = sURL.split('/').slice(3);
var url = "";
var output = ""
for (i = 0; i < bits.length; i++) {
    bit = decodeURIComponent(bits[i]);
    url += "/" + bit;
    output += "<a href=\"" + url + "\">" + bit + "</a> &nbsp;|&nbsp; "
}
document.write(output);
mike
  • 7,137
  • 2
  • 23
  • 27
1

This is an extension/improvement of mike's answer above.

function breadcrumbs() {
    'use strict';
    /*jslint plusplus:true*/
    /*jslint browser:true*/
    var sURL, bits, bit, url, output, i, n, loc;
    sURL = location.href;
    bits = sURL.split('/').slice(3);
    url = {};
    output = "";
    for (i = 0; i < bits.length; i++) {
        if (bits[i] !== "") {
            bit = decodeURIComponent(bits[i]);
            if (bit.indexOf('.htm') >= 0) {
                n = bit.indexOf('.');
                bit = bit.slice(0, n);
            }//end bit.indexOf
            url += "/" + bit;
            output += "<a href=\"" + url + "\">" + bit + "</a> &nbsp;|&nbsp; ";
        }//end bits[i]
    }//end for bits.length
//  document.write(output);
    loc = document.getElementById('bread');
    loc.innerHTML = output;
}

I added in two if-statements. For some reason the .split is pulling in an empty "" string as the last string, so the first if statement only executes the rest of the code if the current array item isn't "". The second if statement trims off anything after the .--e.g. .htm, .html, .html#. Finally, i got rid of document.write(output) and replaced it with .innerHTML. This allowed me to get the script out of the middle of my HTML and move it to execute at the bottom in a document.ready function call.

Mike Earley
  • 1,223
  • 4
  • 20
  • 47
  • Thank you. +1! Wish more people would report back with what are often essential details, especially if the comments and/or answers were not coherent, or no consensus was reached. – MicroservicesOnDDD Jul 14 '23 at 03:33