How can I load the HTML resulting from external .js call? - javascript

Googlebot sees content differently (doesn't index it at all) than the visitor if the content was generated dynamically from a JS file (see image above). Let's say I have the following code:
<body>
<div>Bunch of Content</div>
<script type="text/javascript" src="/js/somefile.js" />
<div>Bunch of Content</div>
</body>
How can I display the actual resulting HTML in the document when the page loads:
<body>
<div>Bunch of Content</div>
<p>Javascript dynamically created this string and this string.</p>
<p>Date: timestamp by JS</p>
<p>Other info dynamically created by JS.</p>
<div>Bunch of Content</div>
</body>
I have JS doing the heavy lifting to generate some content dynamically specifically for the page. The problem is, because the content is being generated in a JS file, the content never gets loaded in the DOM for indexing by crawlers.
Is there a way to do this? Thanks!

Google CAN index dynamic content, but it does not mean it will index it, or display it in search results, as it usually only looks for it in search of negative aspects (like black-hat SEO practices), although for some sites it may decide to use it for its index (it's a blind guess really, when it comes to how Google handles this, as they don't disclose this kind of details).
If your JS is making an AJAX request, and you're the owner of the API or whatever endpoint you're calling from the request, then your best bet is to cache the result on the server side, and modify your HTML page (which should be dynamic) so it renders the latest cached result in the HTML sent to the browser, but wrapped in a container tag (like a <div>) with an inocuous CSS rule like opacity: 0; so the content isn't visible to users by default, which should be changed to opacity: 1; by your JS file once the up-to-date HTML is loaded.

You could use jQuery to accomplish this, like in the example below:
$(document).ready(function() {
var el = "<section>Dynamically added content</section>";
$('.a').after(el);
})
div {
padding: 10px;
background-color: #ccc;
}
section {
padding: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="a">Bunch of Content</div>
<div>Bunch of Content</div>
Update: If you're using Ajax to get data from the server, then you would include the update on your code from the returning data object. You could extend this to iterate through the values you get.
$.getJSON('[Your url]', { param: 'value' },
function (data) {
var el = "<section>" + data.value + "</section>";
$('.a').after(el);
});
});

Related

Loading different pages while keeping the same header

I have a question, I'm working on my first portfolio with html, css and javascript.It's just a simple site with a header with the nav menu and the body with some of my info, I was wondering if there's a way besides iframe to load only the body everytime I click a link without affecting the header:
<header>
<nav>
Home, about me, etc
</nav>
</header>
<body>
this is my home page
</body>
To really get in to one page app development using a library like Angularjs really does the trick. If you just need something really simple you can use the jQuery load function. For instance:
<body>
<button id="home">Home</button>
<button id="about">About</button>
<button id="examples">Examples</button>
<div id="content">
this is my home page
</div>
</body>
<script language="Javascript">
$("#home").click(function() {
$( "#content" ).load( "home.html" ); //Load all retrieved content
});
$("#about").click(function() {
//Only load content from a specific node
$( "#content" ).load( "about.html #desc" );
});
$("#examples").click(function() {
//More specific loading of node
$( "#content" ).load( "examples.html #storeMain .container" );
});
</script>
This is the same question that started me off learning to program.
Things have gotten a lot better as far as loading dynamic content on the fly... but also - much more complicated as far as setup / build tools / JS frameworks etc.
People will say --- just use HTML or PHP / and that it doesn't matter if the whole page is reloaded and the header repaints... but those people aren't like you. What if you want to look at a picture of the band WHILE listening to a song (myspace)... - or you want your header to fade to a different background and do an animation...
Here is a PHP example that explains it all: https://css-tricks.com/dynamic-page-replacing-content
Here is a hacky JS way to do it / where all of the info is on one page... but is hidden and then shown with JS / but - the URL isn't going to change: https://codepen.io/sheriffderek/pen/zxmjgr
// build a reusable function that switches the "view"
var switchView = function(trigger) {
$('.view').addClass('hidden');
var currentSection;
currentSection = $(trigger).data('view');
$('.' + currentSection).removeClass('hidden');
console.log("you are currently on:" + currentSection);
};
// when you click the menu item... run that function to switch to the associated "view" based on it's data attribute
$('.view-controls a').on('click', function() {
switchView(this);
});
$('.header').on('click', function() {
$('.compact-menu').toggleClass('active');
});
$('.compact-menu a').on('click', function() {
$('.compact-menu').removeClass('active');
}); // I had to add this code just to post a codepen link : /
Example in action: http://bryanleebrowncomposer.com
Not ideal... but if you aren't going to have URL change anyway... this is actually better for SEO - and it's easy - and gets you the snappy style.
Here is a JavaScript framework way: https://www.codementor.io/sheriffderek/less-than-ambitious-websites-with-ember-js-5mtthoijp
I love Ember.js - but if you were going to try your hand at another framework - I'd take a look at this vue.js way: https://scotch.io/tutorials/how-to-build-a-simple-single-page-application-using-vue-2-part-1
All roads lead to pain and suffering - for the most part. Good luck! Post your outcome, will yah?
You could dynamically load your pages and inject it to your main page (single page).
As another option, which is partially not what you are looking for, you can load different pages via url and then dynamically rendering a header/footer onload (multiple page). But multiple pages will allow you to avoid having to manipulate URL states manually through something like domain.com?page=about and it's generally much more manageable in terms of regular website development.
If I make it single page, I load the body content via ajax. Like so
<div class="header">Lorem ipsum</div>
<div class="content-wrapper">
<!--Load content HTML here via ajax -->
</div>
<div class="footer">Lorem ipsum</div>
For multi-page setups, I do this
<div class="header-wrapper">
<!--Load header HTML here via ajax or render them via a javascript component -->
</div>
<div class="content-wrapper">Lorem ipsum</div>
<div class="footer-wrapper">
<!--Load footer HTML here via ajax or render them via a javascript component -->
</div>
The ajax part is as simple as this. (using jQuery ajax, axios, or http)
$.ajax({
type : 'GET',
url : 'foo.html',
dataType : 'html',
success : function(data){
wrapper.innerHTML = data;
},
Look up dynamically loading html via ajax so that you don't have to constantly repeat yourself implementing the same headers/footers across your pages. OR, like I said, you can also make/adopt a UI component to do it for you without ajax.

Access view-source instead of prepared DOM

Hopefully I can explain my question correctly, so sorry in advance for any wrong use of jargon or other:
Is it possible to access with javascript the original markup as viewed in the source code rather then the code from the DOM after it has been 'modified'
Let's say an element #div1 has the actual text that will be used in another element with id #div2, in the source code the text will be visible in #div1 but in the DOM while inspecting #div1 will be empty and #div2 will have that text,
I know it would be a matter of the order of loading the scripts, but I was hoping there could be another way.
Hopefully this makes some sense.
Yep, the simpliest way to access original html is to place your js code before any other scripts (or place only libs like jquery before).
The second opportunity is to load document again with ajax, parse and get what you want. Here is code example:
<div id="div1">
Hello
</div>
<div id="div2">
</div>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script>
$('#div2').html($('#div1').html())
$('#div1').html('')
</script>
<script>
alert($('#div1').html())
// ajax get
// empty string in get request means current location
$.get("", function (html) {
var el = $(html).filter('#div1');
alert(el.html())
});
</script>

Formatting dynamically formed HTML elements created after Script is run

So this is actually a very tricky concept to portray so here is my attempt.
I am utilizing an HTML form template in LANDesk Service Desk - tool is irrelevant but important to note that there is back-end code that I cannot touch that is generating HTML.
So basically, the tool is pulling data from a back-end database containing a list of objects. It then inputs this data into an HTML form template that I have created using variables as placeholders for the objects. The HTML is then built on the fly with however many objects are in the database. Thus, I have no way of accessing the head - (which means native JS, and inline CSS).
My template looks like this...
<div class="my-template">
<a class="my-template my-link">My Link</a>
</div>
<script>
var myLinks = document.getElementsByClassName('my-link');
for (var i = 0 ; i < myLinks.length ; i++) {
myLinks[i].style.display = "none";
}
</script>
When I view the source on the loaded page it looks something like this...
<body>
<!--misc. page stuff-->
<!--First Item-->
<div class="auto-create">
<div class="my-template">
<a class="my-template my-link">My-Link</a>
</div>
</div>
<!--Second Item-->
<div class="auto-create">
<div class="my-template">
<a class="my-template my-link">My-Link</a>
</div>
</div>
</body>
All of the elements are formatted the way I want them to be...besides the last element on each page. I have determined that this is because each time the tool is running the object through the template, it is running the script. The issue is, there is a stupid default button that they place at the bottom of each object that is broken. (This is why I have the script changing the style to display: none..should have mentioned this earlier). Basically I want to delay the execution of the script until not only the object has been run through the template...but the entire page has loaded...but I can't seem to get the last button to go away.
I know that this is a lot of poorly written words trying to form an explanation, but I really think this is impossible...but I am convinced there has to be a way. (Also, the company isn't providing us with any help in finding a workaround, so I had to basically MacGyver this one

Updating the content of a div with 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).

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