Need help understanding something, not sure how to word it. Example inside

I’m struggling a lot with Javascript lately and I think it’s because I don’t understand how Javascript works. Observe the following example here.

<script>
function change_value()
{
  document.getElementById('alertbutton').value = "Changed Value";
}

function change_onclick()
{
  document.getElementById('alertbutton').onclick = "alert('Hello Changed!');";
}

function change_onclick_properly()
{
  document.getElementById('alertbutton').setAttribute('onclick',"alert('Hello Changed!');");
}

function check_onclick()
{
  alert(document.getElementById('alertbutton').onclick);
}
</script>
<input id="modifier" type="button" value="Check Onlick" onclick="check_onclick();" />

<input id="modifier" type="button" value="Change Value" onclick="change_value();" />

<input id="modifier" type="button" value="Change Onlick" onclick="change_onclick();" />
<input id="modifier" type="button" value="Change Onlick Properly" onclick="change_onclick_properly();" />
-
<input id="alertbutton" type="button" value="Hello World!" onclick="alert('Hello World!')" />

Now why is it exactly that I can change the value of the Hello World button with the above function change_value(), but the change_onclick() function does not work and instead must be written like change_onclick_properly().

I spent a lot of time programming tonight trying to figure out why JS can alter HTML in a straight forward manner but can’t adjust JS in the same.

neither of that is the proper way to do that. at best you’d call it historic (as felgall would put it).

<button id="modifier" type="button">Check Onlick</button>

document.getElementById('modifier').addEventListener('click', change_value);

You’re assigning the same ID to 4 different buttons, which is bound to confuse JS. Also as @Dormilich said, it’s much better practice to add event listeners entirely within the script; this way the multiple ID faux pas becomes more obvious instantly as you’d have to ask yourself: get which Element by this ID?

Js is not my area (which I say every time I post over here) but isn’t there something wrong with line of code.

document.getElementById('alertbutton').onclick = "alert('Hello Changed!');";

Shouldn’t it be like this?

document.getElementById('alertbutton').onclick = function(){alert('Hello Changed!')}

1 Like

@Dormilich What makes addEventLIstener the right way?

@m3g4p0p Yeah my bad on that. It was 5am when I posted this. I normally wouldn’t give a bunch of buttons the same ID. My question was in regarding how to set attributes properly and why some require special functions and others do not.

@PaulOB I’m not sure, there seems to be multiple ways to do a lot of things and I think that’s what I find confusing.

The difference between setAttribute("onclick", value) and object.onclick=value is that the first one expects the value as a string, whereas the second one expects the value as a function - so if you change your code as PaulOB notes, your code should work as expected.

Now, indeed, there’s a third way to add an event onclick and that is through addEventListener. While this is not necesarilly “better” than onclick=.., it is recomemended because you can add more than just a single event handler for an event and it comes with many other advantages.

3 Likes

Thank you! That helps.

Is there also a better way to modify innerHTML? Say for example that there is some Javascript onclick events inside of the innerHTML of a DIV. I think about doing something like

document.getElementById('somediv-withhtml-and-js').innerHTML = document.getElementById('somediv-withhtml-and-js').innerHTML.replace(regex_to_find_js,new_js_function_as_a_string);

but something tells me that wouldn’t work. I probably need to go and discover every onclick inside of the innerHTML right?

Hm… It’s not really clear to me what you are trying to achieve.

If I understand correctly, you want to change the onclick property on an element in the page - so why not just give that element and id so you can select it and then access its property directly?

If you have more elements whose onclick handlers you want to change, you could give them all a common class name and select them using getElementByClassName. After that, you could just loop through each element to update the onclick.

Either way, doing a replace on an innerHTML is something you should defintelly avoid :slight_smile:

1 Like

Yup, that’s what I’m trying to do right now. I’m writing a code editor that runs in the browser that uses codemirror. I want to be able to open and close and rename text files.

I’m writing the rename functionality right now and I have all of my elements that correspond to a specific file with an ID like “editorwindow./var/www/filename.html” or “contextmenu./var/www/filename.html”, many of these elements have onclicks, innerHTML, values etc, and I use queryselectorall to grab them all by looking for the filename in the ID.

Then when I’ve done a prompt to ask for a new filename I want to overwrite the respective ID’s with the new filename. It’s trickier than I figure it would be because it seems like different attributes require different methods to alter them properly.

If you can think of a better way to achieve this I’m open to suggestions but that’s asking a lot.

That’s easy enough to find out isn’t it. ;-). However it would be more efficient (and cleaner) to store the element in a variable so that the DOM doesn’t have to be queried twice, like e.g.

var element = document.getElementById('foo');

element.innerHTML = element.innerHTML.replace(/\d+/g, number => ('<sup>' + number + '</sup>'));

PS: If you want to change the ID of an element, parsing HTML bits might be a bit cumbersome indeed… you can change the ID of an element directly like

element.setAttribute('id', 'bar');
1 Like

It seems to me that the filename is more of “meta” information for each element, so why not use data attributes for this?

For example, say you have 2 files in the editor, and for each you would have 2 elements:

<div class="editorWindow" data-filename="/var/www/filename.html"></div>
<a href="#" class="contextMenu" data-filename="/var/www/filename.html"></a>

<div class="editorWindow" data-filename="/var/www/another-filename.html"></div>
<a href="#" class="contextMenu" data-filename="/var/www/another-filename.html"></a>

You can have just one handler for all context menus, and just distinguish between the files reading from the data attribute (using jQuery here):

$(".contextMenu").on('click', function() {
   var filename = $(this).data('filename');
  // Do domething with filename here
});

Or, to change the filename of multiple elements:

$('[data-filename="/var/www/another-filename.html"]').each(function() {
     $(this).data(newFilename);
});

If you want to skip jQuery, here’s how to use data attributes natively: https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Using_data_attributes.

1 Like

Wow! Great tips! Thank you. I’ll definitely use that!

addEventLIstener allows you to have more than one event listener to the element like hover double click etc.
But why add individual event listeners to your elements
Add a listener to the element which contains the elements e.g. buttons, then in that listener, get the target element and use a switch statement to process the event.
If you use an element which is always on your page, then you don’t have to check if the element is present before attaching an event listener to it.
If you intend being serious about using js then do a course on it. Code Academy or Lynda.com

1 Like

Good information man. Thank you. I should just bite the bullet and learn JS properly instead of just fumbling around with it.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.