Javascript based content dissapears from sticky sidebar - javascript

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/

Related

How can I load multiples html files into a Div

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.

Open an anchor link inside a div

I want to prevent an anchor link to open on the document body and instead render inside a div. I've used e.preventDefault() but I think JQuery isn't targeting that event.
I'm programmatic-ly creating a ul and appending li's to it from array items then appending the ul to a div. The structure looks like this:
//this is just a structure, not the actual HTML
<div id="results">
<ul> .ulStyle
<li> .list-group-item
-header
-p .lead
-a .anchorStyle
</li>
</ul>
</div>
Then, I add classes to each element. Everything but the ul is getting the class and I think that may be why it's not targeting the anchors.
jQuery:
$(function(){
console.info('** anchor-tag click handler **')
/*
I've tried variations on the targeting from a
single $('.anchorStyle') to what you see below.
*/
$('div #results ul .ulStyle li .list-group-item a .anchorStyle')
.click(function(e) {
e.preventDefault();
$('#results').empty();
$('#results').load( this.getAttribute('href') );
console.log('anchor clicked...');
});
});
I get the first console message on reload but not the second on click.
Questions:
Do I need a class on the ul to target it properly? I'm only adding
it to the ul for that purpose.
Does this piece of code execute with everything else and the ul may not have been created yet? JS/jQuery should
still bind and keep listening to an event if it exists - or in this
case, find the element I'm targeting after the click event fires,
no?
Couple of problems in the code to point out...
First is that the selectors are not right. You have a space after your element and it's class which is wrong (Eg:ul .ulStyle here .ulStyle is considered as a child of ul).The selector must be like this
$('div#results ul.ulStyle li.list-group-item a.anchorStyle')
Notice I have removed the spaces between the element and it's class..
Even after getting this changes done it still won't work for you because the elements are added dynamically. Taking this line from the OP
I'm programmatic-ly creating a ul and appending li's to it from array items then appending the ul to a div.
So this calls for a need to use event delegation
The syntax must change to
$(document).on('click','div#results ul.ulStyle li.list-group-item a.anchorStyle',function(){//your stuff here});
Further you can keep the selector simple as
'#results a.anchorStyle'
Here you have a working example with your structure:
$('#results ul li a').click(function(e){
e.preventDefault();
console.log(this.href);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="results">
<ul>
<li>
<header>HEADER</header>
<p></p>
ANCHOR
</li>
</ul>
</div>

Selecting text within a span within a link within an unordered list... and then replacing it

Here's the HTML I'm focusing on:
<nav>
<ul id='nav'>
<li></icon>Home<span> +</span></li>
<li><icon><img src="images/skills-icon.png"></icon>Skillsets</li>
<li><icon><img src="images/gallery-icon.png"></icon>Gallery</li>
<li><icon><img src="images/about-icon.png"></icon>About</li>
<li></icon>Contact</li>
</ul>
</nav>
I want to select the text within the span—preferably only the "+" part of the text within the span (without the space). The way I'm trying to do that right now is with this code:
$(document).ready(function(){
var ul = $('nav > ul'),
li = ul.children('li'),
top = li.find('a').hasClass("top"),
navSpan = $(top).children('span');
$(navSpan).contents().replaceWith(' -');
});
but it isn't selecting the element correctly. With the way I have my javascript set up (there's a lot more of it than this) I need to keep these variables. However, it appears that some of these variables aren't set up correctly, or that my $(navSpan).contents().replaceWith() command isn't set up correctly. Do you guys have any ideas on how to fix it? Thanks!
First of all, lets fix your selectors and your double-wrapping:
$(function(){
var ul = $('#nav'),
li = ul.children('li'),
top = li.find('a.top'), // you can remove the 'a' qualifier if there is never another item with the top class
navSpan = top.children('span');
Second of all ... you can just replace the contents with this:
navSpan.text(' -');
});
Final code:
$(function(){
var ul = $('#nav'),
li = ul.children('li'),
top = li.find('a.top'),
navSpan = top.children('span');
navSpan.text(' -');
});
I cringe a little bit at the volume of unnecessary variables in this example, but you said you need all of them so I won't try to further optimize.
EDIT: Couldn't resist optimizing a little. Even if you need to capture all of those variables, you will have a faster querying with an id than you will using nav > li. If you have multiple menus that this applies to then disregard, but if not then this would be a little faster.
Here is a jsFiddle of the working code.
hasClass returns a boolean value. If you want to filter an element, you can use the filter method: li.find('a').filter(".top")
contents returns the childNodes of an element, you can't call jQuery methods on the returned value.
$('nav > ul').find('a.top span').text(' -');

Target current menu item in a single page site with fixed menu

I'm working a single-page website for my friend's photo studio: http://dev.manifold.ws/yorckstudio/
The site is divided in six sections, each the size of the viewport. When you click on one of the menu item, it takes you to the corresponding section. What I can't figure out is how to get a menu item to be underline when viewing the corresponding section. So if I'm viewing the "Photos" section, the item "Photos" in my fixed menu would be underlined.
My guess is that there must be a relatively simple way to achieve that with a bit of javascript / jQuery magic. But my js skills being quite poor, I'm not sure where to start.
Does anyone have a idea of how this could be achieved?
Cheers,
Thom
Using jQuery, add this is your JS:
$('#menu a').click(function(){
$(this).css('text-decoration','underline');
$(this).parent().siblings().find('a').css('text-decoration','none');
})
This will add an underline to the clicked anchor tags and remove the attribute on all the other ones.
jsFiddle: http://jsfiddle.net/z97RX/
Try this:
$('#menu ul li a').click(function(){
var that = $(this);
that.addClass('underline');
that.parent().siblings().find('a').removeClass('underline');
});
And add to css
.underline{
text-decoration: underline;
}
If you could, please take a look here http://jsfiddle.net/xv8tf/3/
It could be cleaned up a bit, but here is the jist of it.
All you require to do on your end is update you menu and your scrollto elements and just add a rel tag with matching values
Example:
<div id="menu">
<ul>
<li><a rel="photos" href="javascript:void(0)">Photos</a></li>
</ul>
</div>
<div rel="photos" id="photos"></div>
//create a list of all elements to be tested against
var scrollMatches = [
$('#photos'),
$('#studio'),
$('#rates'),
$('#features'),
$('#plan'),
$('#contact')
];
$(window)
.on('scroll', function(){
//save scrolltop to var to prevent multiple callings
var scroll = $(this).scrollTop();
//iterate through each of the elements to be testing against
$.each(scrollMatches, function(k, v){
var offset = v.offset()
// if the element is in the viewport
if(offset.top <= scroll && (offset.top + v.outerHeight()) > scroll){
// get associated element
var element = $('#menu li > a[rel='+v.attr('rel')+']');
// do whatever you want to the current tested element
element.css('text-decoration','underline');
// dp whatever you want to the associated menu item
element.parent().siblings().find('a').css('text-decoration','none');
return false;
}
});
});

Using jQuery .remove() to take <li> elements out of an <ol> but the DOM still thinks that the <li> elements are there?

I have a function that removes li elements from an ol when you click on an icon. When the ol is totally emptied, I would like to replace the li with a bit off filler material so that the user can still drag and drop new li elements into the list. (It's kind of a shopping cart setup.)
The problem that I'm running into is that when I use jQuery .remove() the li is removed from the DOM BUT jQuery doesn't it as being gone. So, for example, calling .has(".li") returns true even when all the li's are gone, and calling childNodes.length returns the total number of li that have ever existed in the ol. Code follows:
function onClick(element)
var parent = $(element).parent().attr('id');
$(element).remove();
var container = document.getElementById(parent);
console.log(container.childNodes.length); //always logs the total number that have ever existed
if(container.childNodes.length < 1){
parent.append("<li class='placeholder'>Drag and Drop Components Here</li>");
I'm pretty sure that this isn't the problem because I've been careful to grab the parent container only after the element was removed from the DOM.
Any ideas?
EDIT: The requested ul and li structure:
<h4>Components</h4>
<ol id="components" class="droppable">
<li class="placeholder">Drag and Drop Components Here</li>
</ol>
Users drag and drop the following code into the list, which is retrieved via $.get from some php scripts.
<li id="$id"><table style="color:white"><tr><td>$this->longname</td>
<td>Delete image</div></td></tr></table></li>
The click handler is the code above.
Assuming you have misplaced the function name onClick instead of destrComp, there are multiple problems.
To the click handler you are passing the clicked anchor element not the li element as you as assuming, so when you say $(element).parent() or $(element).remove() it is not dealing with the elements you think it is dealing.
Try
function destrComp(element) {
var $parent = $(element).closest('ul');
$(element).closest('li').remove();
if ($parent.children().length < 1) {
$parent.append("<li class='placeholder'>Drag and Drop Components Here</li>");
}
}
According to your code you seem to be removing the "a" tag, but not the parent.
$(element).remove(); //This removes the a tag
$(element).parents('li').remove(); //This removes the parent li element

Categories