Updating the content of a div with javascript - javascript

Rather than trying to create tons of different pages on my website, I'm trying to update the content of a single div when different items in the navbar are click to update the maint div content. I tried to find a simple example using Javascript:
<script type="text/javascript">
function ReplaceContentInContainer(id,content) {
var container = document.getElementById(id);
container.innerHTML = content;
}
</script>
<div id="example1div" style="border-style:solid; padding:10px; text-align:center;">
I will be replaced when you click.
</div>
<a href="javascript:ReplaceContentInContainer('example1div', '<img src='2.jpg'>' )">
Click me to replace the content in the container.
</a>
This works just fine when I only try and update text, but when I put an img tag in there, as you can see, it stops working.
Either
1) what is the problem with how I am trying to do it?
or 2) What is a better/easier way to do it?
I'm not stuck on Javascript. jQuery would work too, as long as it is just as simple or easy. I want to create a function that will just let me pass in whatever HTML I want to update and insert it into the div tag and take out the 'old' HTML.

You just have some escaping issues:
ReplaceContentInContainer('example1div', '<img src='2.jpg'>')
^ ^
The inner ' need to be escaped, otherwise the JS engine will see ReplaceContentInContainer('example1div', '<img src=' plus some syntax errors resulting from the subsequent 2.jpg'>'). Change the call to (tip of the hat to cHao' answer concerning escaping the < and > in the HTML):
ReplaceContentInContainer('example1div', '<img src=\'2.jpg\'>')
A simple way to do this with jQuery would be to add an ID to your link (say, "idOfA"), then use the html() function (this is more cross-platform than using innerHTML):
<script type="text/javascript">
$('#idOfA').click(function() {
$('#example1div').html('<img src="2.jpg">');
});
</script>

First of all, don't put complex JavaScript code in href attributes. It's hard to read or to maintain. Use the <script> tag or put your JavaScript code in a separate file altogether.
Second, use jQuery. JavaScript is a strange beast: the principles underlying its patterns were not designed with modern-day web development in mind. jQuery gives you lots of power without miring you in JavaScript's oddities.
Third, if your goal is to avoid having to endlessly duplicate the same basic structure for all (or many) of your pages, consider using a templating system. Templating systems allow you to plug in specific content into scaffolds containing the common elements of your site. If it sounds complicated, it's because I haven't explained it well. Google it and you'll find lots of great resources.
Relying on JavaScript for navigation means your site won't be indexed properly by search engines and will be completely unusable to someone with JavaScript turned off. It is increasingly common--and acceptable--to rely on JavaScript for basic functionality. But your site should, at minimum, provide discrete pages with sensible and durable URLs.
Now, all that said, let's get to your question. Here's one way of implementing it in jQuery. It's not the snazziest, tightest implementation, but I tried to make something very readable:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>jQuery Example</title>
<style type="text/css" media="all">
/* all content divs should be hidden initially */
.content {
display: none;
}
/* make the navigation bar stand out a little */
#nav {
background: yellow;
padding: 10px;
}
</style>
</head>
<body>
<!-- navigation bar -->
<span id="nav">
about me |
copyright notice |
a story
</span>
<!-- content divs -->
<div class="content" id="about_me">
<p>I'm a <strong>web developer</strong>!</p>
</div>
<div class="content" id="copyright">
<p>This site is in the public domain.</p>
<p>You can do whatever you want with it!</p>
</div>
<div class="content" id="my_story">
<p>Once upon a time...</p>
</div>
<!-- jquery code -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
<script>
// Wait for the document to load
$(document).ready(function() {
// When one of our nav links is clicked on,
$('#nav a').click(function(e) {
div_to_activate = $(this).attr('href'); // Store its target
$('.content:visible').hide(); // Hide any visible div with the class "content"
$(div_to_activate).show(); // Show the target div
});
});
</script>
</body>
</html>
Ok, hope this helps! If jQuery looks attractive, consider starting with this tutorial.

Your main problem with your example (besides that innerHTML is not always supported) is that < and > can easily break HTML if they're not escaped. Use < and > instead. (Don't worry, they'll be decoded before the JS sees them.) You can use the same trick with quotes (use " instead of " to get around quote issues).

Related

How can I render raw HTML [duplicate]

How can I show HTML snippets on a webpage without needing to replace each < with < and > with >?
In other words, is there a tag for don't render HTML until you hit the closing tag?
The tried and true method for HTML:
Replace the & character with &
Replace the < character with <
Replace the > character with >
Optionally surround your HTML sample with <pre> and/or <code> tags.
sample 1:
<pre>
This text has
been formatted using
the HTML pre tag. The brower should
display all white space
as it was entered.
</pre>
sample 2:
<pre>
<code>
My pre-formatted code
here.
</code>
</pre>
sample 3:
(If you are actually "quoting" a block of code, then the markup would be)
<blockquote>
<pre>
<code>
My pre-formatted "quoted" code here.
</code>
</pre>
</blockquote>
is there a tag for don't render HTML until you hit the closing tag?
No, there is not. In HTML proper, there’s no way short of escaping some characters:
& as &
< as <
(Incidentally, there is no need to escape > but people often do it for reasons of symmetry.)
And of course you should surround the resulting, escaped HTML code within <pre><code>…</code></pre> to (a) preserve whitespace and line breaks, and (b) mark it up as a code element.
All other solutions, such as wrapping your code into a <textarea> or the (deprecated) <xmp> element, will break.1
XHTML that is declared to the browser as XML (via the HTTP Content-Type header! — merely setting a DOCTYPE is not enough) could alternatively use a CDATA section:
<![CDATA[Your <code> here]]>
But this only works in XML, not in HTML, and even this isn’t a foolproof solution, since the code mustn’t contain the closing delimiter ]]>. So even in XML the simplest, most robust solution is via escaping.
1 Case in point:
textarea {border: none; width: 100%;}
<textarea readonly="readonly">
<p>Computer <textarea>says</textarea> <span>no.</span>
</textarea>
<xmp>
Computer <xmp>says</xmp> <span>no.</span>
</xmp>
Kind of a naive method to display code will be including it in a textarea and add disabled attribute so its not editable.
<textarea disabled> code </textarea>
Hope that help someone looking for an easy way to get stuff done.
But warning, this won't escape the tags for you, as you can see here (the following obviously does not work):
<textarea disabled>
This is the code to create a textarea:
<textarea></textarea>
</textarea>
Deprecated, but works in FF3 and IE8.
<xmp>
<b>bold</b><ul><li>list item</li></ul>
</xmp>
Recommended:
<pre><code>
code here, escape it yourself.
</code></pre>
i used <xmp> just like this :
http://jsfiddle.net/barnameha/hF985/1/
The deprecated <xmp> tag essentially does that but is no longer part of the XHTML spec. It should still work though in all current browsers.
Here's another idea, a hack/parlor trick, you could put the code in a textarea like so:
<textarea disabled="true" style="border: none;background-color:white;">
<p>test</p>
</textarea>
Putting angle brackets and code like this inside a text area is invalid HTML and will cause undefined behavior in different browsers. In Internet Explorer the HTML is interpreted, whereas Mozilla, Chrome and Safari leave it uninterpreted.
If you want it to be non-editable and look different then you could easily style it using CSS. The only issue would be that browsers will add that little drag handle in the bottom-right corner to resize the box. Or alternatively, try using an input tag instead.
The right way to inject code into your textarea is to use server side language like this PHP for example:
<textarea disabled="true" style="border: none;background-color:white;">
<?php echo '<p>test</p>'; ?>
</textarea>
Then it bypasses the html interpreter and puts uninterpreted text into the textarea consistently across all browsers.
Other than that, the only way is really to escape the code yourself if static HTML or using server-side methods such as .NET's HtmlEncode() if using such technology.
If your goal is to show a chunk of code that you're executing elsewhere on the same page, you can use textContent (it's pure-js and well supported: http://caniuse.com/#feat=textcontent)
<div id="myCode">
<p>
hello world
</p>
</div>
<div id="loadHere"></div>
document.getElementById("myCode").textContent = document.getElementById("loadHere").innerHTML;
To get multi-line formatting in the result, you need to set css style "white-space: pre;" on the target div, and write the lines individually using "\r\n" at the end of each.
Here's a demo: https://jsfiddle.net/wphps3od/
This method has an advantage over using textarea: Code wont be reformatted as it would in a textarea. (Things like are removed entirely in a textarea)
In HTML? No.
In XML/XHTML? You could use a CDATA block.
I assume:
you want to write 100% valid HTML5
you want to place the code snippet (almost) literal in the HTML
especially < should not need escaping
All your options are in this tree:
with HTML syntax
there are five kinds of elements
those called "normal elements" (like <p>)
can't have a literal <
it would be considered the start of the next tag or comment
void elements
they have no content
you could put your HTML in a data attribute (but this is true for all elements)
that would need JavaScript to move the data elsewhere
in double-quoted attributes, " and &thing; need escaping: " and &thing; respectively
raw text elements
<script> and <style> only
they are never rendered visible
but embedding your text in Javascript might be feasable
Javascript allows for multi-line strings with backticks
it could then be inserted dynamically
a literal </script is not allowed anywhere in <script>
escapable raw text elements
<textarea> and <title> only
<textarea> is a good candidate to wrap code in
it is totally legal to write </html> in there
not legal is the substring </textarea for obvious reasons
escape this special case with </textarea or similar
&thing; needs escaping: &thing;
foreign elements
elements from MathML and SVG namespaces
at least SVG allows embedding of HTML again...
and CDATA is allowed there, so it seems to have potential
with XML syntax
covered by Konrad's answer
Note: > never needs escaping. Not even in normal elements.
It's vey simple ....
Use this xmp code
<xmp id="container">
<xmp >
<p>a paragraph</p>
</xmp >
</xmp>
<textarea ><?php echo htmlentities($page_html); ?></textarea>
works fine for me..
"keeping in mind Alexander's suggestion, here is why I think this is a good approach"
if we just try plain <textarea> it may not always work since there may be closing textarea tags which may wrongly close the parent tag and display rest of the HTML source on the parent document, which would look awkward.
using htmlentities converts all applicable characters such as < > to HTML entities which eliminates any possibility of leaks.
There maybe benefits or shortcomings to this approach or a better way of achieving the same results, if so please comment as I would love to learn from them :)
This is a simple trick and I have tried it in Safari and Firefox
<code>
<span><</span>meta property="og:title" content="A very fine cuisine" /><br>
<span><</span>meta property="og:image" content="http://www.example.com/image.png" />
</code>
It will show like this:
You can see it live Here
You could try:
Hello! Here is some code:
<xmp>
<div id="hello">
</div>
</xmp>
This is a bit of a hack, but we can use something like:
body script {
display: block;
font-family: monospace;
white-space: pre;
}
<script type="text/html">
<h1>Hello World</h1>
<ul>
<li>Enjoy this dodgy hack,
<li>or don't!
</ul>
</script>
With that CSS, the browser will display scripts inside the body. It won’t attempt to execute this script, as it has an unknown type text/html. It’s not necessary to escape special characters inside a <script>, unless you want to include a closing </script> tag.
I’m using something like this to display executable JavaScript in the body of the page, for a sort of "literate progamming".
There’s some more info in this question When should tags be visible and why can they?.
function escapeHTML(string)
{
var pre = document.createElement('pre');
var text = document.createTextNode(string);
pre.appendChild(text);
return pre.innerHTML;
}//end escapeHTML
it will return the escaped Html
Ultimately the best (though annoying) answer is "escape the text".
There are however a lot of text editors -- or even stand-alone mini utilities -- that can do this automatically. So you never should have to escape it manually if you don't want to (Unless it's a mix of escaped and un-escaped code...)
Quick Google search shows me this one, for example: http://malektips.com/zzee-text-utility-html-escape-regular-expression.html
This is by far the best method for most situations:
<pre><code>
code here, escape it yourself.
</code></pre>
I would have up voted the first person who suggested it but I don't have reputation. I felt compelled to say something though for the sake of people trying to find answers on the Internet.
You could use a server side language like PHP to insert raw text:
<?php
$str = <<<EOD
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="description" content="Minimal HTML5">
<meta name="keywords" content="HTML5,Minimal">
<title>This is the title</title>
<link rel='stylesheet.css' href='style.css'>
</head>
<body>
</body>
</html>
EOD;
?>
then dump out the value of $str htmlencoded:
<div style="white-space: pre">
<?php echo htmlentities($str); ?>
</div>
There are a few ways to escape everything in HTML, none of them nice.
Or you could put in an iframe that loads a plain old text file.
Actually there is a way to do this. It has limitation (one), but is 100% standard, not deprecated (like xmp), and works.
And it's trivial. Here it is:
<div id="mydoc-src" style="display: none;">
LlNnlljn77fggggkk77csJJK8bbJBKJBkjjjjbbbJJLJLLJo
<!--
YOUR CODE HERE.
<script src="WidgetsLib/all.js"></script>
^^ This is a text, no side effects trying to load it.
-->
LlNnlljn77fggggkk77csJJK8bbJBKJBkjjjjbbbJJLJLLJo
</div>
Please let me explain. First of all, ordinary HTML comment does the job, to prevent whole block be interpreted. You can easily add in it any tags, all of them will be ignored. Ignored from interpretation, but still available via innerHTML! So what is left, is to get the contents, and filter the preceding and trailing comment tokens.
Except (remember - the limitation) you can't put there HTML comments inside, since (at least in my Chrome) nesting of them is not supported, and very first '-->' will end the show.
Well, it is a nasty little limitation, but in certain cases it's not a problem at all, if your text is free of HTML comments. And, it's easier to escape one construct, then a whole bunch of them.
Now, what is that weird LlNnlljn77fggggkk77csJJK8bbJBKJBkjjjjbbbJJLJLLJo string? It's a random string, like a hash, unlikely to be used in the block, and used for? Here's the context, why I have used it. In my case, I took the contents of one DIV, then processed it with Showdown markdown, and then the output assigned into another div. The idea was, to write markdown inline in the HTML file, and just open in a browser and it would transform on the load on-the-fly. So, in my case, <!-- became transformed to <p><!--</p>, the comment properly escaped. It worked, but polluted the screen. So, to easily remove it with regex, the random string was used. Here's the code:
var converter = new showdown.Converter();
converter.setOption('simplifiedAutoLink', true);
converter.setOption('tables', true);
converter.setOption('tasklists', true);
var src = document.getElementById("mydoc-src");
var res = document.getElementById("mydoc-res");
res.innerHTML = converter.makeHtml(src.innerHTML)
.replace(/<p>.{0,10}LlNnlljn77fggggkk77csJJK8bbJBKJBkjjjjbbbJJLJLLJo.{0,10}<\/p>/g, "");
src.innerHTML = '';
And it works.
If somebody is interested, this article is written using this technique. Feel free to download, and look inside the HTML file.
It depends what you are using it for. Is it user input? Then use <textarea>, and escape everything. In my case, and probably it's your case too, I simply used comments, and it does the job.
If you don't use markdown, and just want to get it as is from a tag, then it's even simpler:
<div id="mydoc-src" style="display: none;">
<!--
YOUR CODE HERE.
<script src="WidgetsLib/all.js"></script>
^^ This is a text, no side effects trying to load it.
-->
</div>
and JavaScript code to get it:
var src = document.getElementById("mydoc-src");
var YOUR_CODE = src.innerHTML.replace(/(<!--|-->)/g, "");
This is how I did it:
$str = file_get_contents("my-code-file.php");
echo "<textarea disabled='true' style='border: none;background-color:white;'>";
echo $str;
echo "</textarea>";
It may not work in every situation, but placing code snippets inside of a textarea will display them as code.
You can style the textarea with CSS if you don't want it to look like an actual textarea.
If you are looking for a solution that works with frameworks.
const code = `
<div>
this will work in react
<div>
`
<pre>
<code>{code}</code>
</pre>
And you can give it a nice look with css:
pre code {
background-color: #eee;
border: 1px solid #999;
display: block;
padding: 20px;
}
JavaScript string literals can be used to write the HTML across multiple lines. Obviously, JavaScript, ECMA6 in particular, is required for this solution.
.createTextNode paired with CSS white-space: pre-wrap; does the trick.
.innerText alone also works. Run code snippet below.
let codeBlock = `
<!DOCTYPE HTML>
<html lang="en">
<head>
<title>My Page</title>
</head>
<body>
<h1>Welcome to my page</h1>
<p>I like cars and lorries and have a big Jeep!</p>
<h2>Where I live</h2>
<p>I live in a small hut on a mountain!</p>
</body>
</html>
`
const codeElement = document.querySelector("#a");
let textNode = document.createTextNode(codeBlock);
codeElement.appendChild(textNode);
const divElement = document.querySelector("#b");
divElement.innerText = codeBlock;
#a {
white-space: pre-wrap;
}
<div id=a>
</div>
<div id=b>
</div>
//To show xml tags in table columns you will have to encode the tags first
function htmlEncode(value) {
//create a in-memory div, set it's inner text(which jQuery automatically encodes)
//then grab the encoded contents back out. The div never exists on the page.
return $('<div/>').text(value).html();
}
html = htmlEncode(html)
A combination of a couple answers that work together here:
function c(s) {
return s.split("<").join("<").split(">").join(">").split("&").join("&")
}
displayMe.innerHTML = ok.innerHTML;
console.log(
c(ok.innerHTML)
)
<textarea style="display:none" id="ok">
<script>
console.log("hello", 5&9);
</script>
</textarea>
<div id="displayMe">
</div>
I used this a long time ago and it did the trick for me, I hope it helps you too.
var preTag = document.querySelectorAll('pre');
console.log(preTag.innerHTML);
for (var i = 0; i < preTag.length; i++) {
var pattern = preTag[i].innerHTML;
pattern = pattern.replace(/</g, "<").replace(/>/g, ">");
console.log(pattern);
preTag[i].innerHTML = pattern;
}
<pre>
<p>example</p>
<span>more text</span>
</pre>
You can separate the tags by changing them to spans.
Like this:
<span><</span> <!-- opening bracket of h1 here -->
<span>h1></span> <!-- opening tag of h1 completed here -->
<span>hello</span> <!-- text to print -->
<span><</span> <!-- closing h1 tag's bracket here -->
<span>/h1></span> <!-- closing h1 tag ends here -->
And also, you can just only add the <(opening angle bracket) to the spans
<span><</span> <!-- opening bracket of h1 here -->
h1> <!-- opening tag of h1 completed here -->
hello <!-- text to print -->
<span><</span> <!-- closing h1 tag's bracket here -->
/h1><!-- closing h1 tag ends here -->
<code><?php $str='<';echo htmlentities($str);?></code>
I found this to be the easiest, fastest and most compact.

Trying to build a content locker using jQuery

I am very new to jQuery and not entirely sure what I'm doing. Will try my best to explain the problem I'm facing.
I'm trying to lock some content on a landing page until a user shares the link using FB, Twitter, LinkedIN or G+. The first version of the script I wrote (which worked fine) ran like this:
<head>
<script type="text/javascript">
...
$(document).ready(function()
{
$('.class').click(clearroadblock());
buildroadblock();
}
</script>
<style>
.class
{
[css stuff]
}
</style>
</head>
<body>
<div id="something">
<ul>
<li> Link1 </li>
<li> Link2 </li>
</ul>
</div>
</body>
The problem I'm now facing is changing out this code to replace the list elements with social share buttons. As they are no longer under .class, but classes like fb-share-button and twitter-share-button. Please help me understand what I need to modify to accommodate this? PS: This is not a Wordpress site.
function clearroadblock()
{
$('#roadblockdiv').css('display', 'none');
$('#roadblockBkg').css('display','none');
}
This is the way I'm clearing the overlay once a click is detected, BTW.
Can I wrap the social buttons in divs, assign them IDs and use those IDs to trigger the click like below?
<div id="Button">
Tweet
</div>
$('#Button').click(clearroadblock());
You can have multiple classes on an element by separating them with a space. Try the following:
class="class fb-share-button"
Your jquery will still work off the "class" class. I would recommend you change this name to something more meaningful though. Your css can target the "class" for general styles, but you can also target fb and twitter separately.
Update
I decided to create a quick JSFiddle for this.
Some of the styles etc won't be the same as what you're doing, but the problem is resolved. I've created a div with id main that contains the content that you want to hide. There's an absolutely positioned div over the top of this, this is the roadblock. The javascript is showing the roadblock (assuming that's what you wanted to do with buildroadblock()).
On click of a link in the ul with id socialMedia we call clearroadblock. Notice the lack of parenthesis. This hides the roadblock.
This isn't a great way of preventing someone from seeing information, you might want to think about pulling the content down from the server when the action is performed, however, I think this answers your question.

innerHTML does not work with Javascript output contents

I try to make some kind of ads rotator as follows:
<html>
<head>
<title></title>
<style>
body {
margin:0;
padding:0;
}
</style>
<script>
function fillBoard() {
s = document.getElementsByClassName('slots');
board = document.getElementById('board');
board.innerHTML = s[0].innerHTML
alert(board.innerHTML);
}
</script>
</head>
<body>
<div id="board" style="width:160px; text-align: center; margin:0">
</div>
<div class="slots" style="display:none">
<!-- THE PROBLEM IS HERE -->
<!-- Begin Hsoub Ads Ad Place code -->
<script type="text/javascript">
<!--
hsoub_adplace = 1310003403401506;
hsoub_adplace_size = '125x125';
//-->
</script>
<script src="http://ads2.hsoub.com/show.js" type="text/javascript"></script>
<!-- End Hsoub Ads Ad Place code -->
</div>
<div class="slots" style="display:none">
<img src="http://lorempixel.com/160/90/sports/1/" />
</div>
<div class="slots" style="display:none">
<img src="http://lorempixel.com/160/90/sports/2/" />
</div>
<div class="slots" style="display:none">
<img src="http://lorempixel.com/160/90/sports/3/" />
</div>
<script>
fillBoard();
</script>
</body>
</html>
In the code above:
There is a div with id board to act as a board that displays contents.
The board should be filled with data supplied from other hidden divs with class name slots using innerHTML property.
To do the above a function named fillBoard() is defined in the head section of the page and then called at the end of it just before closing </body> tag.
What is happening?
The hidden divs slots works fine with divs that contain images. However, in the first div there are a javascript code that should generates ads from an ads network which it does not work.
I expect that the javascript code of the ads network should fill its div with data, then the calling of fillBoard() will just copy its content to the board div. However, this is does not occur!
I need to know how could I overcome this issue?
A live example is found here
You can just show the desired hidden div and it's usually a better practice than copying DOM content. If you make sure to only show one of the hidden divs at a time you can show the image always in the same place.
Try this to show the first "slots" element:
s[0].style.display = 'block';
Ok so after some more digging I've found the issue, although I don't have an easy solution at the moment.
The js file show.js is generating some ad content inside of an iframe for you, which you are placing in the first 'slots' div. Simple enough. When you are setting the content of the board to the content of the first slots class, an iframe is being created in the board div but without the same content.
After some searching it seems that innerHTML of an iframe will not copy the contents of the iframe if it comes from a domain other than the page domain for security reasons.
It seems to me that the solution at this point is to either show and hide the slots divs like Zhertal suggested or you can possible find some other way to physically move the content of the slots div into board, but this may still be a violation of the same security concern. I'm going to keep digging and I'll edit this answer if I find anything more.
Reference SO posts:
Get IFrame innerHTML using JavaScript
Javascript Iframe innerHTML

Displaying Hidden Javascript Divs if Java Enabled without Duplicate content

In short, I am trying to have an HREF menu with Javascript functions to display DIVs. However, my concern is that while I could have two seperate DIVs, one with Javascript if enabled, and one with No JAvascript enabled, I do not want to duplicate raw content on my page (as spiders will index Display: none html)
I am not familiar with functions of javascript, and best practices. My instinct is to string replace the DIVs for a specific id style tags when javascript is present..
Ie, logic that if javascript enabled, then replace text of style tags to to display=none (for specific ID's)
Also - is there a way to be nonspecific with javascript. Such as if i have contentid1,contentid2,contentid3,contentid4,contentid5,contentid6 I could use, via regular expression or equivalent for contentid 2-6
I will use this on multiple pages where contentids change. I do not know if i should create a javascript conditional style, as I am not sure how that style would be applied for multiple IDs (seen here)
Hide html only when Javascript is available
Heres my current code
<script type="text/javascript">
function showHide(d)
{
var onediv = document.getElementById(d);
var divs=['content1','content2','content3','content4'];
for (var i=0;i<divs.length;i++)
{
if (onediv != document.getElementById(divs[i]))
{
document.getElementById(divs[i]).style.display='none';
}
}
onediv.style.display = 'block';
}
</script>
then here is my menu
<ul>
<li>link1</li>
<li>link2</li>
<li>link3</li>
<li>link4</li>
</ul>
Then here is my content (note, i leave the content1 div visible by default
<div id="content1" >Content</div>
<div id="content2" style="display: none;">Stuff</div>
<div id="content3" style="display: none;">Things</div>`
I would like to avoid flickering if possible, and page refreshing if possible. Like could there be a condition so that content2+ have inlinestyle changed to hidden. If no javascript, my paeg just becomes really, really long.
?
Sorry-rambling. Tired, and have pneumonia :)

Better alternative to an iframe to display tab content?

I have a page with an iframe to feature the contents of the clicked tab. There are 3 tabs and 1 iframe. The sources of the contents relating to each tab clicked are formatted and coded in other html & css files.
What is another alternative to using an iframe, because I noticed that when the tab is clicked, it still shows the white background, similar to when a new page is loading?
Here's my code:
<div id="tabs">
<div id="overview">
<a target="tabsa" class="imagelink lookA" href="toframe.html">Overviews</a>
</div>
<div id="gallery">
<a target="tabsa" class="imagelink lookA" href="tawagpinoygallery.html">Gallery</a>
</div>
<div id="reviews">
<a target="tabsa" class="imagelink lookA" href="trframe.html">Reviews</a>
</div>
</div>
<div id="tabs-1">
<iframe src="toframe.html" name= "tabsa" width="95%" height="100%" frameborder="0">
</iframe>
</div>
The only alternative to using IFRAMEs to load dynamic content (after the page has loaded) is using AJAX to update a container on your web page. It's pretty elegant and usually faster than loading a full page structure into an IFRAME.
Ajax with JQuery (use this and you will be loved on SO; the AJAX functions are great and simple)
Ajax with Prototype
Ajax with MooTools
Standalone Ajax with Matt Kruse's AJAX toolbox (Used to use this, using JQuery today because I needed a framework)
AJAX with Dojo (Said to be fast, but AJAX is not as straightforward)
Another alternative is to use AJAX to load the content of a tab and use a div to display the content. I would suggest that using an existing Tab library might be an option rather than trying to solve all the problems associated with creating tabs.
Maybe the jQuery UI Tab might be helpful here if you like to try it.
EDIT: AJAX example with UI Tabs.
First, the HTML will look like this.
<div id="tabs">
<ul>
<li><span>Overviews</span></li>
<li><span>Gallery</span></li>
<li><span>Reviews</span></li>
</ul>
</div>
Then make sure that you import the appropriate jQuery files:
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/ui-lightness/jquery-ui.css" type="text/css" media="all" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js" type="text/javascript"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js" type="text/javascript"></script>
etc...
Then add the code to create the tabs:
<script type="text/javascript">
$(function() {
$("#tabs").tabs();
});
</script>
There's an alternative to AJAX!
You can load ALL three possible contents into separate DIVs.
Then clicking on a tab will simply make the display attribute of the appropriate content's DIV "block" while making the other two DIVs' display property "none".
Cheap, easy, does not require AJAX costs for extra http request or for coding.
Mind you, AJAX is a better solution if the contents of the tabs will change dynamically based on other data as opposed to being known at the time the page loads.
You don't need script.
<ul><li>foo link<li>bar link</ul>
<div class="tab" id="foo">foo contents</div>
<div class="tab" id="bar">bar contents</div>
Plus this CSS, in most browsers: .tab:not(:target) { display: none !important; }, which defaults to all content visible if :target isn't supported (any modern browser supports it).
If you're showing content with script, always hide it with script. Let it degrade gracefully if that script doesn't run.
It's probably better to load in the content for each tab into DIVs on the same page and then switch the visibility of each DIV when a tab button is clicked using JavaScript and the CSS display property.
If you can't do that then iframe is probably the best solution. You can make the iframe background transparent, see below:
<iframe src="toframe.html" name= "tabsa" width="95%" height="100%" frameborder="0" allowtransparency="true"></iframe>
You would then need to add the following CSS to the BODY element using:
BODY { Background: transparent; }
The HTML iframe is to be used to include/display non-template content, such as a PDF file. It's considered bad practice when used for template content (i.e. HTML), in both the SEO and UX opinions.
In your case you just want to have a tabbed panel. This can be solved in several ways:
Have a bunch of links as tabs and a bunch of div's as tab contents. Initially only show the first tab content and hide all others using CSS display: none;. Use JavaScript to toggle between tabs by setting CSS display: block; (show) and display: none; (hide) on the tab content divs accordingly.
Have a bunch of links as tabs and one div as tab contents. Use Ajax to get the tab content asynchronously and use JavaScript to replace the current tab contents with the new content.
Have a bunch of links as tabs and one div as tab contents. Let each link send a different GET request parameter or pathinfo representing the clicked tab. Use server-side flow-control (PHP's if(), or JSP's <c:if>, etc) or include capabilities (PHP's include(), or JSP's <jsp:include>, etc) to include the desired tab content depending on the parameter/pathinfo.
When going for the JavaScript based approach, I can warmly recommend to adopt jQuery for this.
This is jQuery example that includes another html page into your document. This is much more SEO friendly than iframe. In order to be sure that the bots are not indexing the included page just add it to disallow in robots.txt
<html>
<header>
<script src="/js/jquery.js" type="text/javascript">
</header>
<body>
<div id='include-from-outside'></div>
<script type='text/javascript'>
$('#include-from-outside').load('http://example.com/included.html');
</script>
</body>
</html>
You could also include jQuery directly from Google: http://code.google.com/apis/ajaxlibs/documentation/ - this means optional auto-inclusion of newer versions and some significant speed increase. Also, means that you have to trust them for delivering you just the jQuery ;)
As mentioned, you could use jQuery or another library to retrieve the contents of the HTML file and populate it into the div. Then you could even do a fancy fade to make it look all pretty.
http://docs.jquery.com/Ajax/jQuery.get
Something along these lines:
$.get("toframe.html", function(data){
$("#tabs-1").html(data);
});
edit..
you could prepopulate or onclick you could do the get dynamically
$("#tabs a").click(function(){
var pagetoget = $(this).attr("href");
$.get...
})
If you prepopulate could have three containers instead of the one you have now, 2 hidden, 1 display, and the click functions will hide them all except for the one you want.
The get is less code though, easier time.

Categories

Resources