Problem with: Target[i].setAttribute("option",

Can anyone help
I want to change <option> tag value .
But I am missing the mark , here’s my code…
Sorry couldn’t get working:

<!DOCTYPE html>
<html>
<head>
<script>
  document.addEventListener("DOMContentLoaded", () => {
    alert("DOM ready!    Hit F12   to Open DevTools");
  });
</script>
</head>

<body>
	<h3>Accessing HTML 'option' of a DOM element in JavaScript .</h3>
<p>
<a href="https://www.w3schools.com" target="_blank"></a>1 Visit W3Schools.com _blank</a>
<br>
<a href="https://www.w3schools.com" target="_top"></a>2 Visit W3Schools.com _top</a>
<br>
<a href="https://www.w3schools.com" target="_self"></a>3 Visit W3Schools.com _self</a>
</p>
<p>
<!-- EXAMPLE: <form name="Arduino"> -->   <!-- rgb(250,240,255) -->
<select style="width:200px; font:14px Arial Black; color:rgb(0,0,0); background-color:rgb(214,226,255);" name="menu" onchange="window.open(this.value); window.location.reload();">
  <option selected="0" value="">aaDaily</option>
<option value="https://www.sitepoint.com/community/categories">Categories</option>
<option value="https://www.sitepoint.com/community/faq">FAQ</option>
</select>
</p>

	<button onclick="ATargetHtml()">
		Get and change the html for DOM element
	</button>
	<br><br>

<script>
  function ATargetHtml() {
    // Declare Target inside the function to guarantee that the list of links is up to date
    let Target = document.getElementsByTagName('OPTION');
    console.log(" let Target = document.getElementsByTagName('OPTION');")
    for (var i = 0; i < Target.length; i++) {
      // Show the current target element in the console
      console.log("Target = ", Target<i>);
      // Replaced "i" with "Target<i>"
      if (Target<i>.hasAttribute("option")) {
        Target<i>.setAttribute("option", "value=http://vmars.us");
      }
    }
  }
</script>
</body>
</html>

You have stray closing </a> tags in your links. (I haven’t looked further than that.)

1 Like

You need square brackets for an array.

Target[i]

An option isn’t an attribute? Were you looking for the value attribute instead?

e.g.

    if (Target[i].hasAttribute("value")) {
      Target[i].setAttribute("value", "http://vmars.us");
    }

That will change all the values in the options.

You will still need to call the function when the page has loaded otherwise it does nothing.

ATargetHtml();

Full Code:

function ATargetHtml() {
  // Declare Target inside the function to guarantee that the list of links is up to date
  let Target = document.getElementsByTagName("OPTION");

  for (var i = 0; i < Target.length; i++) {
    // Show the current target element in the console
    console.log("Target = " + Target[i]);
    if (Target[i].hasAttribute("value")) {
      Target[i].setAttribute("value", "http://vmars.us");
    }
  }
}

ATargetHtml();

Also the inline onchange event should really be in the js also rather than mixed in with the html.

I’m not really sure what you are doing with all that though :slight_smile:

1 Like

Thanks guys ,
I moved function into [head] & run function via [button] .
Sill having probs , , so I’ll try put code here.
I replaced console.log s with alert .
When I run code alert shows
3 of these Target = [object HTMLOptionElement]
1 of this Target = undefined

  document.addEventListener("DOMContentLoaded", () => {
   alert("DOM ready!   Hit F12  to Open DevTools");
  });
  function ATargetHtml() {
  // Dec  lare Target inside the function to guarantee that the list of links is up to date
  let Target = document.getElementsByTagName("OPTION");
      
  for (var i = 0; i < Target.length; i++) {
   // Show the current target element in the console
   alert("Target = " + Target[i]);
   if (Target[i].hasAttribute("value")) {
    Target[i].setAttribute("value", "http://vmars.us");
   }    
  }    
   alert("Target = " + Target.length[i]);
  }     

I wasn’t able to put whole code here because
```` ``` didn’t work
and 3 spaces didn’t work either

https://codepen.io/vmars316/pen/rNLPXvr

So my ? is how to fix ‘Target’ so that is is not ‘undefined’ ?
Thanks

3 back ticks your code 3 back ticks to close

You can put ‘javascript’ immediately after the first 3 ticks to change the theme accordingly. e.g.
```javascript code here... ```

Hope that helps.

1 Like

All sorts going on. I wouldn’t use br tags, inline styling or paragraphs as containers.

If you need to space things out or display content in block format, then a combination of css and the correct html is a better way to go.

For example you have 3 numbered anchor links inside a paragraph and you are using br to display them in block format. An ordered list I think would be better.

Finally codepen’s html section, as far as I know, is body content only. No doctype, head etc. just content.

This could well be improved on, but here is a cleaned up version of your code.

<h3>Accessing HTML 'option' of a DOM element in JavaScript .</h3>
<ol>
  <li>
    <a href="https://www.sitepoint.com/community/categories" target="_blank">https://www.sitepoint.com/community/categories _blank</a>
  </li>
  <li>
    <a href="https://www.sitepoint.com/community/categories" target="_top">https://www.sitepoint.com/community/categories _top</a>
  </li>
  <li>
    <a href="https://www.sitepoint.com/community/categories" target="_self">https://www.sitepoint.com/community/categories _self</a>
  </li>
</ol>
<div>
  <select class='sitepoint-options' name="sitepoint-options" onchange="window.open(this.value); window.location.reload();">
    <option selected value=''>aaDaily</option>
    <option value="https://www.sitepoint.com/community/categories">Categories</option>
    <option value="https://www.sitepoint.com/community/faq">FAQ</option>
  </select>
</div>
<button onclick="changeHtml(event)">Get and change the html for DOM element</button>

<script>
    function changeHtml(event) {
        const options = document.querySelectorAll('.sitepoint-options option')

        for (let i = 0, len = options.length; i < len; i++) {

            if (options[i].value !== '') {
                options[i].value = 'http://vmars.us'
            }
            console.log(options[i])
        }
    }
</script>

codepen here

2 Likes

Yes , when I try back ticks , it doesn’t work for me .
Thanks for cleaning up my code .
But the real issue is how to fix code so I dont get these
Target = [object HTMLOptionElement]
and this: Target = undefined .

Maybe I am missing something, but did you check out the codepen I posted and it’s console output?

I have changed the names in your code to something less vague e.g options instead of target and instead of using setAttribute just assigned the values. At the core it is doing the same.

Edit: just FYI when it come to naming conventions a capital letter at the start of a name e.g. ATargetHtml() usually signifies the function is a constructor function or a class - a function that returns an object.

1 Like

I don’t understand why that should be, as it worked fine when I added them to your code. Place three backticks on the line above, and three on the line below your code.

```
code goes here
```

For inline tags, you need a single backtick before and after the tag.

If you prefer, you can highlight your code block and use the </> button in the editor window, instead of adding backticks.

2 Likes

You have your script in the head of the page and therefore the html does not exist yet and so doesn’t find anything. If you move it to the end of the html like this:

<script>
   function ATargetHtml() {
      // Dec  lare Target inside the function to guarantee that the list of links is up to date
      let Target = document.getElementsByTagName("OPTION");
      for (var i = 0; i < Target.length; i++) {
        // Show the current target element in the console
        alert("Target = " + Target[i]);
        if (Target[i].hasAttribute("value")) {
          Target[i].setAttribute("value", "http://vmars.us");
        }
      }
      //alert("Target = " + Target.length[i]);
    }
</script>
</body>

It will now work except your alert (which I have commented out) is out of scope as the variable ‘i’ and Target are not accessible out of that function. (You should use console.log when testing anyway to see values as alerts are a nuisance and you could end up in an endless loop of alerts.)

1 Like

PaulOB
Should’t this ‘let Target = ’ make ‘Target’ global ,
then no more ‘undefined’ .

  <script>
  document.addEventListener("DOMContentLoaded", () => {
   alert("DOM ready!   Hit ...F12...  to Open DevTools");
  });
let Target = [] ;
   function ATargetHtml() {
      // Dec  lare Target inside the function to guarantee that the list of links is up to date
      Target = document.getElementsByTagName("OPTION");
      for (var i = 0; i < Target.length; i++) {
        // Show the current target element in the console
        alert("Target = " + Target[i]);
        if (Target[i].hasAttribute("value")) {
          Target[i].setAttribute("value", "http://vmars.us");
        }
      }   alert("Target = " + Target.length[i]);
   alert('<!DOCTYPE HTML>' + '\n' + document.documentElement.outerHTML);
  }     
  </script>

Yes Target is global but ‘i’ is not so you can’t say Target.length[i] outside that function.

Aha , Thank You

This still gets the same errors , how come ?

let Target = [] ; let i = 0 ;
   function ATargetHtml() {
      // Dec  lare Target inside the function to guarantee that the list of links is up to date
      Target = document.getElementsByTagName("OPTION");
      for ( i = 0; i < Target.length; i++) {
        // Show the current target element in the console
        alert("Target = " + Target[i]);
        if (Target[i].hasAttribute("value")) {
          Target[i].setAttribute("value", "http://vmars.us");
        }
      }   alert("Target = " + Target.length[i]);
   alert('<!DOCTYPE HTML>' + '\n' + document.documentElement.outerHTML);
  } 

What are you trying to do there?

There was no need for that alert outside of the function anyway and you don’t want to create global variables everywhere.

Firstly there is no Target.length[i] construct like that. It’s simply Target.length or did you mean Target[i] ? (You seemed to have mixed two different things).

Secondly at that position outside of the for loop the value of i will be 3 (because the loop has finished) and there is no array element at the third position as there is only 0,1 & 2 (3 items). If you had said alert("Target = " + Target[2]); you would have found the last element in that array.

However that would seem pointless so I don’t really know what you expected to find?

But for the
alert("Target = " + Target[i])
inside the loop

I want to show each Target line .

Why does it still show Target = [object HTMLOptionElement]
since both Target and i are global ?

Because that’s what each one is!

What were you expecting it to say?

I’m not sure I’m following your logic. You can see the code is working because the url (http://vmars.us) gets added to each of the options as expected. I don’t see what else it is you want to know? :slight_smile:

When I develop something , I like to see things (each line) as it is happening .
It gives me pleasure .
How can I do that ?

And then I have one more question re: value .
Thank you for sticking with me so far .

Use console.log() to pass values to the console and then you can see them in there without popping up the alerts all the time.

It will still say Target = [object HTMLOptionElement] but that’s what it is. You are looping through the option elements so it tells you it’s an option element. If you wanted the value of that element then you’d need to ask for that instead.

That’s the problem: How would I do That ?