How can I load multiples html files into a Div - javascript

here's my case, I've been working on online manual for the company that I work and recently I decide to make it look better by changing some visual elements, so I thought, why not use bootstrap, and So I did.
Here's the thing, I have a tree-view where I have each part (titles) of the manual, and those titles load an HTML file where I have the information and links to CSS file.
I used to load the content into an Iframe, but that seems to be a terrible idea for all the problems I've deal with it trying to apply CSS, So I decided I'll use DIV'S instead of the Iframe.
Here goes the question:
IS THERE ANY WAY TO LOAD ALL MULTIPLE HTML FILES INTO A SINGLE DIV BY CLICKING EACH TIME A TITLE?
Because All the titles are contained in a "a" tag, and then I use to target it into the Iframe, but now it's not that easy with DIV'S
I've try a little bit of JavaScript and nothing, with Jquery the only thing I've done it's making a function and that function load a specific html file, and by trying adding some parameters to it and it doesn't recognized the path for those HTML files, and it happens the same with InnerHTML.
PD: Those files are locally hosted in a server where they are displayed
Here's a little bit of what I got...
JS:
<script type="text/javascript">
$(document).ready(function(){
$('#content').load('intro.html')
});
</script>
HTML:
<div class="bg-light border-right" id="sidebar-wrapper">
<div class="list-group list-group-flush">
<ul id="tree3" class="list-group-item list-group-item-action bg-light">
<li>TITLE 1
<ul>
<li>TITLE 2</li>
<li>TITLE 3
</ul>
</li>
</div>
</div>
And a want to display all the FILES into this div:
<div id="page-content-wrapper">
<div class="container-fluid">
<div id="content">
HERE THE HTML FILES
</div>
</div>
</div>

I recommend you add a class to the a elements you want to load on the div, for instance class='dynamic'. Set a click handler to all those a.dynamic elements, get the link by using the href attribute of the target, and use preventDefault so the default behaviour (navigating) is not triggered:
$(body).on("click", "a.dynamic", function(event) {
$('#content').load(event.target.href);
event.preventDefault();
}
Remember to add the class on the links:
<a class="dynamic" href="PATHFILE_2">TITLE 2</a>
Note that your dynamically loaded HTML should have only the partial content, no html or body tags. That being said, it's better to not use a elements to trigger the load:
<div class="dynamic" data-href="PATHFILE_2">TITLE 2</div>
And retrieve the url with this:
$('#content').load(event.target.dataset.href);

As far as I know, you cannot load multiple HTML files in one div container.
But why don't you just use multiple div elements inside your #content? You can generate those divs dynamically when one of the hyperlinks is clicked. Each div will then load up one of your HTML files.
The HTML structure stays the same as you have posted it above.
In JavaScript / jQuery it would look something like this:
$('#tree3').on('click', 'a', function (e) {
e.preventDefault();
e.stopImmediatePropagation();
// clear the entire content div
$('#content').empty();
let parentLi = $(this).closest("li");
// load the HTML content for the hyperlink that has been clicked.
let dynamicDiv = $('<div></div>');
$('#content').append(dynamicDiv);
dynamicDiv.load($(this).attr('href'), function(){
// done loading the main HTML content
});
// check if there is a list inside the li element
let subList = parentLi.children("ul");
if(subList.length && subList.length > 0){
$.each(subList.children("li"), function(k, v){
let subLi = $(v);
let hyperlink = $('a', subLi).attr('href');
// load the HTML content for each of the sub entries
let dynamicDiv = $('<div></div>');
$('#content').append(dynamicDiv);
dynamicDiv.load(hyperlink, function(){
// done loading...
});
});
}
});
If you want to have more than two levels in your list, you can modify the code and make it recursive. So instead of iterating through the li elements of the subList once, you would have to check whether those li elements contain other subLists recursively. The overall logic for generating the divs and loading up the HTML content would stay the same.
For styling purposes I recommend giving the main #content container an overflow-y: auto. This way you only have a single scrollbar for the entire content. The divs that are generated dynamically will adjust their height according to the HTML content.

Related

Show multiple containers with the same class when clicking an item

I have a long page, where one section is tabbed content. However, at the same time as showing tabs, I'd like for other sections further down the page to be visible or hidden, depending on which tab is clicked. Since each tab would display about 4 containers further down the page, I'd like to use classes for this rather than ID's. This is a rough outline of what I have so far (tab content removed, as it's unnecessary):
<div class="horisontal-tabs">
<ul class="tabs">
<li class="tab-label active person-sam" rel="tab1">Sam</li>
<li class="tab-label person-bob" rel="tab2">Bob</li>
<li class="tab-label person-jack" rel="tab3">Jack</li>
<li class="tab-label person-kelly" rel="tab4">Kelly</li>
</ul>
</div>
<div class="container-sam section-visible">Custom content only for Sam</div>
<div class="container-bob section-hidden">Custom content only for Bob</div>
<div class="container-jack section-hidden">Custom content only for Jack</div>
<div class="container-kelly section-hidden">Custom content only for Kelly</div>
<div class="container-sam section-visible">Other content for Sam</div>
<div class="container-bob section-hidden">Other content for Bob</div>
<div class="container-jack section-hidden">Other content for Jack</div>
<div class="container-kelly section-hidden">Other content for Kelly</div>
And I have jquery as per below for each person, but it doesn't seem to be working, and I can't figure out how to simplify it down. The idea is that when you click on one person's tab, all the other people's sections will be hidden and that person's will be visible.
$('.horizontal-tabs ul.tabs li.person-sam').click(function (event) {
$('.container-sam').removeClass('section-hidden').addClass('section-visible');
$('.container-sam.section-visible').removeClass('section-visible').addClass('section-hidden');
event.stopPropagation();
});
I have opted to not use ID on the sections and use a class instead, because multiple will need to show at once, so they wouldn't be unique.
Any tips will be greatly appreciated! :)
So the question is how to make simpler?
What comes to mind is you don't need active and inactive classes, you just need one of them, and then you can make the other be the default state . That is, add a default class .section to all sections and either use .section as the visible state and add .section-hidden to hide it, or use .section as the hidden state and add .section-visible to show it.
Say you go with .section-visible, the css would be something like this:
.section { display: none }
.section.section-visible { display: block }
This would also simplify your javascript because now you can reset all sections and just turn on/off the ones you need.
If you go, again, with .section-visible, run this on click:
$('.section').removeClass('section-visible'); // reset all sections
$('.container-sam').addClass('section-visible'); // add visible class to specific sections
You can see you only need one extra class, not two.
BONUS 1: you can use BEM to make it clearer.
BONUS 2: it looks like you have one click listener for each person, but instead you can use the HTML dataset API and the jQuery .data() function to detect which person's button you're pressing. That way you would have only one click listener, and you can detect which li was clicked by checking the data- attribute. Like <li data-person="sam">sam</li> and const containerSelector = `.container-${$(this).data('person')}`;. $(this) will select the li clicked, and .data('person') will return 'sam'. So the selector will be .container-sam.

Javascript based content dissapears from sticky sidebar

I have a sidebar with a ul list, like so:
<div id="sidebar">
<ul>
</ul>
</div>
There is no actual html content in the sidebar because the ul list are being populated through a javascript function. So my javascript function fills in the ul list once the page has finished loading.
The problem is that I want to make this sidebar sticky, but the moment I make it sticky, the content inside the ul list dissapears (as if javascript cant recognize my ul list anymore).
What I tried:
I tried making the sidebar sticky using pure css like "position: sticky"
I tried using the "Sticksy" script from: https://sticksy.js.org/ The sticksy script works great, but the result is the same: my ul list are no longer being filled in by my javascript function.
As mentioned, it's as if javascript can't find the ul list to add the content to, while the sidebar is sticky. Any advice on how to get around this?
EDIT: (here is the function that ads code to my ul list)
var summaryWidgetList = document.querySelector("#sidebar ul");
function mySummary() {
var selectionList = document.querySelectorAll("#site-main .product-title");
selectionList.forEach(selectionItem => {
var selectionItemTag = document.createElement("li");
selectionItemTag.innerHTML = selectionItem.textContent;
summaryWidgetList.appendChild(selectionItemTag);
})
}
window.addEventListener('load', mySummary);
Well, try to append data to your ul element.
Create ID for ul element:
<ul id="list">
</ul>
Now append the <li> elements in your desired way to "list" element.
F.ex. using vanilla JavaScript:
document.getElementById("list").innerHTML += "<li> filled </li>"
I created a very simple example:
https://playcode.io/695917/

Replacing the content of a div with the content of another hidden div in Jquery

i am trying to replace the content of a div with the content of another div(which is hidden). The code works for the first time only but the second time doesn't work at all.
I have a div where the titles of some articles are scrolling. I want to achieve that:everytime i am going to click the title of an article its content(the content is in hidden div) is going to appear in another div with the id="sreen".
<script type="text/javascript">
//everytime you click the title of an article
$("a.title").live("click", function(){
//replace the content of div screen with the content of an article
$('div#screen').replaceWith($(this).next('div.content'));
});
</script>
Any ideas???
Using .replaceWith will effectively remove div#screen. So using .html() will be what you want to do to maintain the element div#screen.
You mentioned that your formating is not working correctly which leads me to believe you have css classes on div.content. Calling .html() on div.content will ommit the root node of div.content.
<div class="content">
<span>some text</span>
</div>
$("div.content").html() will produce <span>some text</span>
If my assumptions are correct you might want to look at using clone() which will clone the current object without events or clone(true) to include any data and events.
var $content = $(this).next('div.content').clone();
$content.css("display", "block");
$('div#screen').html($content);
Another way of doing this would be use .outerHTML
$("a.title").live("click", function() {
$('div#screen').html($(this).next('div.content')[0].outerHTML);
});
Example on jsfiddle.
use the .htmldocs method for this
<script type="text/javascript">
//everytime you click the title of an article
$("a.title").live("click", function(){
//replace the content of div screen with the content of an article
$('div#screen').html( $(this).next('div.content').html() );
});
</script>

Easiest way to dyanmically load a DIV on button click?

I have a relatively simple question here.
What I require is this; I need to have a page with 5 buttons at the top and a DIV beneath them (initially hidden). When a button is clicked, it loads content into the DIV (in the form of another DIV)
eg.
[Button 1] [Button 2] [Button 3] [Button 4] [Button 5] //5 buttons or links
<div id="content">
// area for content to be loaded
</div>
<div id="content1">
//could be a table or image
</div>
<div id="content2">
//could be a table or image
</div>
<div id="content3">
//could be a table or image
</div>
<div id="content4">
//could be a table or image
</div>
<div id="content5">
//could be a table or image
</div>
In the above example, when the user loads the page they see 5 buttons. If they press button 5, it loads the "content5" DIV inside of the "content" DIV eg.
<div id="content">
<div id="content5">
</div>
</div>
If another button is selected it loads it's content.
Can be achieved with jQuery or simple JavaScript.
Many thanks
You need to bind a click handler on all of the buttons. Smart way in this particular example would be, to use the index of the elements to determine which div belongs to a button.
$('button').bind('click', function() {
$('div#content').html($('div#content' + ($(this).index()+1)).html());
});
Demo: http://www.jsfiddle.net/8f8jt/
This will add an click event handler to all <button> nodes. On click, it looks for the index of the current clicked button (.index()help) and uses this value to query for the accordant <div> elements id. Once found, use .html()help to get and set the value.
You also can use jQueryUI tabs, but it requires additional script.
Try this
$('#button1').click(function() {
$("#content").html(("#content1").html());
});
$('#button2').click(function() {
$("#content").html(("#content2").html());
});
// etc
This way clears any existing content and copies the correct div into the main #content div.

Open/Close Icons

I'm doing some shennanigans with jQuery to put little plus/minus icons next to my expanders. Its similar to the windows file trees, or firebugs code expanders.
It works, but its not specific enough.
Hopefully this makes sense...
$('div.toggle').hide();//hide all divs that are part of the expand/collapse
$('ul.product-info li a').toggle(function(event){
event.preventDefault();
$(this).next('div').slideToggle(200);//find the next div and sliiiide it
$('img.expander').attr('src','img/content/info-close.gif');//this is the part thats not specific enough!!!
},function(event) { // opposite here
event.preventDefault();
$(this).next('div').slideToggle(200);
$('img.expander').attr('src','img/content/info-open.gif');
});
<ul class="product-info">
<li>
<a class="img-link" href="#"><img class="expander" src="img/content/info-open.gif" alt="Click to exand this section" /> <span>How it compares to the other options</span>
</a>
<div class="toggle"><p>Content viewable when expanded!</p></div>
</li>
</ul>
There are loads of $('img.expander') tags on the page, but I need to be specific. I've tried the next() functionality ( like I've used to find the next div), but it says that its undefined. How can I locate my specific img.expander tag? Thanks.
EDIT, updated code as per Douglas' solution:
$('div.toggle').hide();
$('ul.product-info li a').toggle(function(event){
//$('#faq-copy .answer').hide();
event.preventDefault();
$(this).next('div').slideToggle(200);
$(this).contents('img.expander').attr('src','img/content/info-close.gif');
//alert('on');
},function(event) { // same here
event.preventDefault();
$(this).next('div').slideToggle(200);
$(this).contents('img.expander').attr('src','img/content/info-open.gif');
});
$(this).contents('img.expander')
This is what you want. It will select all of the nodes that are children of your list. In your case, all of your images are nested inside of the list element, so this will filter out only what you want.
How about making your click event toggle a CSS class on a parent item (in your case, perhaps the ul.product-info). Then you can use CSS background properties to change the background image for a <span> instead of using a literal <img> and trying to fiddle with the src. You would also be able to accomplish a showing and hiding on your div.toggle's.
ul.product-info.open span.toggler {
background-image: url( "open-toggler.png" );
}
ul.product-info.closed span.toggler {
background-image: url( "closed-toggler.png" );
}
ul.product-info.open div.toggle {
display: block;
}
ul.product-info.closed div.toggle {
display: hidden;
}
Using jQuery navigation/spidering functions can be slow when the DOM has many items and deep nesting. With CSS, your browser will render and change things more quickly.
Have you tried the .siblings() method?
$(this).siblings('img.expander').attr('src','img/content/info-close.gif');

Categories