11

I have a fairly simple page with a sidebar nav and an iFrame in which to load content.

I want to change the content of the of the iFrame by clicking on links in the sidebar nav. I'm using the javascript to change the source (.src) of the document.element.

I've read numerous articles (StackOverflow) and the code should work, but is simply doesn't.

The code below is the html page I've created and it includes the JS in a tag.

<head>
<meta charset="UTF-8">
<title>Untitled Document</title>
<link href="css/default.css" rel="stylesheet" type="text/css">

<script type="text/javascript">
    function getContent{

        document.getElementById("contentFrame").src="LoremIpsum.html";  

    }
    </script>


</head>

<body>
<div class="sidebar"><h1>Technical Documentation</h1>
<ul>
    <li>Configuration Guides</li>
    <li>API Guides</li>
    <li><a href="" onclick='getContent()'> LoremIpsum</a></li>
</ul>
<!-- <button onclick="getContent()">Lorem Ipsum</button>    -->

</div>


<iframe class="content"  id="contentFrame" src="dummy.html">
</iframe>

</body>
Sean McIntyre
  • 159
  • 2
  • 4
  • 3
    Try adding parentheses to the js function declaration. Instead of 'function getContent{' use 'function getContent() {'. – mrkd1991 Apr 17 '17 at 21:30
  • Look at the console, and you will see that you have a syntax error – Ibu Apr 17 '17 at 21:31

4 Answers4

31

Your problem was that you forgot to add () after your function name.

Beyond that, there are a few other things to correct:

Don't use inline HTML event attributes (onclick, onmouseover, etc.) as they:

  1. Create "spaghetti code" that is difficult to read and debug.
  2. Lead to duplication of code.
  3. Don't scale well
  4. Don't follow the separation of concerns development methodology.
  5. Create anonymous global wrapper functions around your attribute values that alter the this binding in your callback functions.
  6. Don't follow the W3C Event Standard.
  7. Don't cause a reference to the DOM event to be passed to the handler.

Even MDN agrees

Inline event handlers — don't use these

You might also see a pattern like this in your code:

<button onclick="bgChange()">Press me</button> 

function bgChange() {   
  const rndCol = `rgb(${random(255)}, ${random(255)}, ${random(255)})`;  
  document.body.style.backgroundColor = rndCol; 
} 

The earliest method of registering event handlers found on the Web involved event handler HTML attributes (or inline event handlers) like the one shown above — the attribute value is literally the JavaScript code you want to run when the event occurs. The above example invokes a function defined inside a element on the same page, but you could also insert JavaScript directly inside the attribute, for example:

 <button onclick="alert('This is my old-fashioned event handler!');">Press me</button> 

You can find HTML attribute equivalents for many of the event handler properties; however, you shouldn't use these — they are considered bad practice. It might seem easy to use an event handler attribute if you are doing something really quick, but they quickly become unmanageable and inefficient.

For a start, it is not a good idea to mix up your HTML and your JavaScript, as it becomes hard to read. Keeping your JavaScript separate is a good practice, and if it is in a separate file you can apply it to multiple HTML documents.

Even in a single file, inline event handlers are not a good idea. One button is OK, but what if you had 100 buttons? You'd have to add 100 attributes to the file; it would quickly turn into a maintenance nightmare. With JavaScript, you could easily add an event handler function to all the buttons on the page no matter how many there were, using something like this:

const buttons = document.querySelectorAll("button");
 
for (const button of buttons) {   
  button.addEventListener("click", bgChange); 
} 

Finally, many common server configurations will disallow inline JavaScript, as a security measure.

You should never use the HTML event handler attributes — those are outdated, and using them is bad practice.

Instead, do all your work in JavaScript and use .addEventListener() to set up event handlers.


Don't use a hyperlink when a button (or some other element) will do. If you do use a hyperlink, you need to disable its native desire to navigate, which is done by setting the href attribute to #, not "".

// Place this code into a <script> element that goes just before the closing body tag (</body>).

// Get a reference to the button and the iframe
var btn = document.getElementById("btnChangeSrc");
var iFrame = document.getElementById("contentFrame");

// Set up a click event handler for the button
btn.addEventListener("click", getContent);

function getContent() {
  console.log("Old source was: " +  iFrame.src);
  iFrame.src="LoremIpsum.html";  
  console.log("New source is: " +  iFrame.src);
}
<div class="sidebar"><h1>Technical Documentation</h1>
<ul>
    <li>Configuration Guides</li>
    <li>API Guides</li>
</ul>
<button id="btnChangeSrc">Change Source</button>

</div>

<iframe class="content" id="contentFrame" src="dummy.html"></iframe>
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
  • 2
    If using inline HTML event attributes is so bad - then tell me: why all modern frameworks like angular, react, vue etc... are designed to use inline events in their HTML templates? For small pure JS projects using inline HTML events is acceptable (because their are small and simple, and easy to control), for bigger project is better to use some modern framework instead pure js. – Kamil Kiełczewski Sep 26 '19 at 05:33
  • 6
    @KamilKiełczewski Your point has been brought up over and over again in many forums. It stems from a fundamental misunderstanding and false equivalency. A framework has to have "hooks" into the native code, so they come up with inline ways of doing that, but the ***rendered*** code does not contain these inline hooks. I am not discussing frameworks, I am discussing native code that doesn't get transformed into anything else. Your statement that small projects make inline events OK is not a "thing". Inline event handlers are bad... at any scale. – Scott Marcus Sep 26 '19 at 05:37
  • But begginers who start with pure js small project and use inline html events can very easy learn how to properly use frameworks templates. But begginers who dont use inline events develop very bad habbits and is hard for them to use framework in proper way (they focus on js part instead of template part and produce very unclear nad hard to maintain code) and need a lot of time (and usually luck and teacher) to break that habbits – Kamil Kiełczewski Sep 26 '19 at 05:42
  • Yes - not using inline event is bad habbit (taken from pure js experinece) in frameworks world - I see this offten in begginers 'frameworks' code - and this habbit is very hard to break for them. – Kamil Kiełczewski Sep 26 '19 at 05:50
  • 5
    Well, that's your opinion and you are entitled to it. After teaching this stuff since it was invented and some 20,000+ students later, my opinion is that as long as you understand what a framework is and how it accomplishes what it does, there is no problem at all in understanding that coding a framework takes a different approach than coding in native JS. The bad habit that I see is poor training that skips over this topic and dives right into coding without differentiating between the two. It's not rocket science to understand best practices to each. – Scott Marcus Sep 26 '19 at 05:57
  • 1
    And, as my post above lays out, this is not just a matter of style or preference. There are real negative implications for your code in JS if you use inline event handlers - - that's the real reason to stay away from them. The very bad habits you talk about truly do manifest in JS itself when you use them. – Scott Marcus Sep 26 '19 at 05:59
  • "#6 Don't follow the W3C Event Standard" is weak to me, as it seems to me the authoritative domain for this is the HTML spec: https://html.spec.whatwg.org/multipage/webappapis.html#event-handler-content-attributes – wtr Jul 02 '21 at 20:23
  • @wtr There are two HTML standards, W3C and WHATWG. W3C is the more authoritative. – Scott Marcus Jul 03 '21 at 16:06
  • That's useful to know! Thank you. (Interestingly, your #6 w3.org link redirects to WHATWG, so to match, my previous link ought to be: https://www.w3.org/TR/html/multipage/#event-handler-content-attributes) – wtr Jul 03 '21 at 23:14
  • Ultimately I'm saying #6 in this context seems to mildly imply this is against standards, but it's listed within section 8.1.7.1 of (both) html spec(s). Saying it's missing from the DOM standard, to me, is like saying the HTML tag isn't specified in the DOM standard; it's technically true, but it's effectively out of jurisdiction, and as it seems misleading it undermines my faith in the rest of your points. (I still appreciate you as a human being though, and thank you for sharing your insights! :) – wtr Jul 03 '21 at 23:28
  • Wow- as I've continued researching the meme of "EHCA's are bad practice" I keep finding that this post is referenced in _many_ other stack overflow posts on the topic as a definitive list of badness. Given the influence of this post, can we have a chat, @ScottMarcus? I have a seemingly unpopular opinion that I believe needs to be heard as legitimate use cases of EHCA's, and with claims being thrown around (not by this post) of EHCA's being deprecated, there's danger of a misguided mob that this SO post has indirect but substantial influence over. Requesting some assistance and understanding. – wtr Jul 04 '21 at 02:41
  • @wtr The redirect to WHATWG talks about “DOM Events”, which are standardized by the W3C. And if you read that spec. (in either document), it discusses .addEventListener, not inline event handlers. There really is no valid use case for inline handlers in native JavaScript. They are simply a relic from a time before there were standards and, while they are still supported (for legacy purposes), they have real world negative implications. – Scott Marcus Jul 04 '21 at 13:39
  • 1
    https://html.spec.whatwg.org/multipage/webappapis.html#introduction-11 "Various mechanisms can cause author-provided executable code to run in the context of a document. These mechanisms include, but are probably not limited to: [...] Event handlers, whether registered through the DOM using addEventListener(), **by explicit event handler content attributes,** by event handler IDL attributes, or otherwise." Emphasis added. EHCA's don't belong in the DOM spec; they belong in the HTML spec, so pointing at DOM Events is directly irrelevant and borderline misleading (as stated previously). – wtr Jul 04 '21 at 17:19
  • "They are simply a relic" – I respect this as your opinion. I just happen to disagree with it completely. Replacing declarative with imperative code is, in this author's opinion, not _always_ a good idea (as you apparently insist). I _am_ surprised that you seem to not allow for that possibility, given your vast experience & _age-refined_ wisdom. Regarding relics, some things get better with age. – wtr Jul 04 '21 at 17:55
  • @wtr I’ve had this conversation many times over the years, and no disrespect intended, it’s usually with less experienced and knowledgeable coders. Inline handlers are in fact relics, in the most literal sense. That is not an opinion, it’s a fact. They are not included in the current specs. and only supported for legacy compatibility. If you had been working with these languages since their inception as I have, you would understand how and why code has evolved. The only reason these don’t die the death they deserve, is because of the continued use by uninformed coders, hence my post. – Scott Marcus Jul 05 '21 at 15:34
  • 1
    Thanks for the respectful chat. For future visitors, there are additional voices that have a different take than @ScottMarcus's; please take these into consideration: https://stackoverflow.com/a/26439633/1302400, https://softwareengineering.stackexchange.com/a/225013/143891, https://stackoverflow.com/questions/5871640/why-is-using-onclick-in-html-a-bad-practice/5871830#comment7046688_5871830, https://stackoverflow.com/questions/12627443/jquery-click-vs-onclick/12627478#comment25122933_12627478, https://stackoverflow.com/questions/6941483/onclick-vs-event-handler/6941663#comment8274445_6941663 – wtr Jul 06 '21 at 00:05
  • @wtr I really think you should read through the original comments in this thread. The additional voices you are describing are conflating inline HTML event attributes for native JavaScript events with inline handlers with various frameworks, which is completely different because those frameworks compile that syntax down to native JavaScript. This is a subtle but important distinction. And, as I mentioned, new coders don’t fully understand this nuance and just lump it all together, when they should not be. – Scott Marcus Jul 06 '21 at 17:44
  • Maybe we're talking past each other. Let's check. When you say "inline HTML event attributes," do you mean the "event handler content attributes (EHCA)" that I've been referring to, linking to, and deriving quotes about? (e.g. the `onclick` in `` from the stack overflow question) – wtr Jul 06 '21 at 21:29
  • @wtr Yes, although no one calls them EHCA. The alternate voices you linked to were not actually discussing that. They were making a false equivalency between inline HTML event attributes used in “vanilla” JavaScript with inline event handlers in frameworks like Angular, where they are required as part of the framework syntax. I’m those applications, you have no choice and that custom code is compiled down to vanilla JavaScript in the background. – Scott Marcus Jul 06 '21 at 23:08
  • I started calling them EHCA's in this comment thread because it's an 87% reduction in characters in a character-limited comment box. – wtr Jul 07 '21 at 00:20
  • @wtr Sure, but it’s best to use terms and abbreviations that people understand. And since you asked for clarification that we were talking about the same thing, I felt it important to let you know. – Scott Marcus Jul 07 '21 at 00:36
  • Of the five links discussing the utility of EHCA's, I notice the one you picked merely references Angular's syntax as an example of similarity of form, with which you then A) "lump up" the meaning of his _entire_ post into that and B) "lump up" all five links into the idea that all 5 of them "were not actually discussing [the utility of EHCA's]". I think it was Scott Marcus the Wise that once said (6 hours ago) "new coders don’t fully understand this nuance and just lump it all together, when they should not be." – wtr Jul 07 '21 at 00:43
  • Sorry to bring this up a year later but I would like to know whether the use of inline handlers actually causes security problems as discussed here in the comment section https://stackoverflow.com/questions/72723943/good-alternative-for-deprecated-event-preventdefault-for-inline-javascript-c?noredirect=1#comment128455553_72723943 and how. If this is true I would recommend adding this aspect into the post as this post is referenced so many times as pointed out by wtr. – cr001 Jun 23 '22 at 03:27
  • @cr001 MDN states *Finally, many common server configurations will disallow inline JavaScript, as a security measure.*. So, i believe this may relate to server-side code execution, rather than browser (client) side code execution. But frankly, the items I mention in this answer are certainly enough to warrant not using inline event attributes any longer. – Scott Marcus Jun 23 '22 at 13:33
  • 1
    This is one of the funniest comment threads on stack overflow. The reasons given for not using inline HTML attributes — even by MDN — all boil down to "well what if you need it 100 times?" Which is great, but… I don't. I want to run a specific piece of Javascript on a specific page when a specific form is submitted. There is no scale, there's no duplication, and all that making the event handler added on separately in javascript would accomplish is make the code less readable, because then I have to search all included files for what's affecting the form submission. I'm sticking with inline. – tuxedobob Oct 03 '22 at 19:25
  • @tuxedobob Sure, it's always your choice to spit into the wind. Be my guest. – Scott Marcus Oct 04 '22 at 13:09
  • Explain to me, Scott, why I would want to have to hunt around to figure out what happens when I submit a form rather than it being right there in front of me. Explain to me what advantage to the user there is to have the event listener added elsewhere. – tuxedobob Oct 05 '22 at 17:44
  • @tuxedobob https://en.wikipedia.org/wiki/Separation_of_concerns – Scott Marcus Oct 05 '22 at 19:57
2

This is a syntax error. Parenthesis are required no matter the parameters of the function. However, it is a good practice to place script tags at the bottom of the body tag.

lazar0169
  • 21
  • 2
1

You have a syntax error in your function declaration (missing parenthesis):

function getContent {
   document.getElementById("contentFrame").src="LoremIpsum.html";
}

Should be:

function getContent() {
   document.getElementById("contentFrame").src="LoremIpsum.html";
}

You also need to prevent the default event for the link

<head>
<meta charset="UTF-8">
<title>Untitled Document</title>
<link href="css/default.css" rel="stylesheet" type="text/css">

<script type="text/javascript">
    function getContent(event) {
       event.preventDefault();
       document.getElementById("contentFrame").src="LoremIpsum.html";
    }
    </script>


</head>

<body>
<div class="sidebar"><h1>Technical Documentation</h1>
<ul>
    <li>Configuration Guides</li>
    <li>API Guides</li>
    <li><a href="#" onclick='getContent(event)'> LoremIpsum</a></li>
</ul>
<!-- <button onclick="getContent()">Lorem Ipsum</button>    -->

</div>


<iframe class="content"  id="contentFrame" src="dummy.html">
</iframe>

</body>
Rob M.
  • 35,491
  • 6
  • 51
  • 50
  • To prevent the link navigation, you can just set the `href` to `#`. No JavaScript needed. – Scott Marcus Apr 17 '17 at 21:38
  • Fair enough, I tend to steer clear of inlining javascript like this and prefer to use `event.preventDefault()` – Rob M. Apr 17 '17 at 21:40
  • Setting the value to `#` is not inlining JavaScript. There's no JavaScript at all with that. – Scott Marcus Apr 17 '17 at 21:41
  • I'm aware of that, I was referring to `onclick='getContent(event)'` – Rob M. Apr 17 '17 at 21:41
  • Yes, agreed (and I discuss that in detail in my answer). But, your reply to my comment was not about what my comment was about in the first place. – Scott Marcus Apr 17 '17 at 21:42
  • Yes, it was - though perhaps I wasn't being clear enough: I avoid using inline event handlers, therefore I don't set `href="#"` in links and instead rely on `event.preventDefault()` – Rob M. Apr 17 '17 at 21:46
  • Not to go round and round on this, but that takes me back to my original point. If you don't use inline event handlers (as we both agree you shouldn't), you don't need to add `event.preventDefault()` at all, as long as you set the `href` to `#`. In other words, setting the `href` is independent of whether or not you use inline event handlers. Or, as I suggest in my answer, avoid using `a` elements for operations such as this in the first place. – Scott Marcus Apr 17 '17 at 21:48
0

You can use javascript:void(0).

    <a href="javascript:void(0)" onclick='getContent(event)'> LoremIpsum</a>

Or return false on javascript

     <script type="text/javascript">
function getContent(){

    document.getElementById("contentFrame").src="LoremIpsum.html";
    return false;

}
</script>
Niladri
  • 169
  • 1
  • 5
  • 1
    Oh no, please don't advocate `javascript:void(0)` (it's not 1997)! Also, **if** you were going to do this, adding `return false` to the function wouldn't be enough. You'd also need the `onclick` attribute to look like this: `onclick="return getContent()"` and the `event` argument wouldn't be passed to `getContent`, it would wind up being passed to the anonymous global wrapper function that wraps it. See my answer for more details on why this is bad. – Scott Marcus Apr 17 '17 at 21:50