How to replace div contents effectively on clicking links using javascript? - javascript

I have created an HTML page that uses bootstrap CSS. I have a sidebar list which is actually a list of links.
Update table
I have a number of sections in the HTML which is hidden by default by applying CSS like below.
<section id="ut" style="display:none;">
I want to change the content when i click the links in the sidebar. What I've used here is JavaScript that sets the CSS display of the clicked link's section to block. For easier manipulation I remove the "ID" part from id of the link to get the id of the section
Eg: link=utID , section= ut
Given below is the JavaScript that I've used. Is there a better optimized method to do this?
// On clicking any of the side bar links
$('.list-group-item')
.click(function(event){
// Preventing the default action which may mess up the view
event.preventDefault();
// Getting all the anchor ids
var $a1 = document.getElementById("unfID");
var $a2 = document.getElementById("uiID");
var $a3 = document.getElementById("utID");
// Getting all the section ids
var $d1 = document.getElementById("unf");
var $d2 = document.getElementById("ui");
var $d3 = document.getElementById("ut");
// Store the id of the clicked link
var $clickedLink = $(this).attr('id');
// Storing the id of the corresponding Div by slicing of "ID" from the link's last part
var $clickedLinkDiv = $clickedLink.substring(0,$clickedLink.length-2);
// Setting the selected link active
SetLinkActive(document.getElementById($clickedLink))
// Setting the corresponding section visible
SectionVisibility(document.getElementById($clickedLinkDiv));
// Method to set the visibility of the section
function SectionVisibility(div){
// first hides al section
$d1.style.display = "none";
$d2.style.display = "none";
$d3.style.display = "none";
// then displays only the selected section
div.style.display = "block";
}
// Method to set the visibility of the section
function SetLinkActive(div){
// first deselect all links
$a1.className = "list-group-item";
$a2.className = "list-group-item";
$a3.className = "list-group-item";
// then applies selection to only the selected link
div.className = "list-group-item active";
}
});

Using jquery is much easier!
The example
HTML
Update UNF
Update UI
Update UT
<section class="unf" style="display:none;">
UNF SECTION
</section>
<section class="ut" style="display:none;">
UI SECTION
</section>
<section class="ui" style="display:none;">
UT SECTION
</section>
JAVASCRIPT
// On clicking any of the side bar links
$('.list-group-item').click(function(event){
// Preventing the default action which may mess up the view
event.preventDefault();
$('a.list-group-item').removeClass('active');
$(this).addClass('active');
$('section').css('display', 'none');
$('section.' + $(this).attr('id')).css('display', '');
});

Related

Dynamic bootstrap modal, jQuery can not access html elements on first load

So i'm dynamically loading modal from my controller, with product information. Each product has a calculator to calculate price. The issue is when I open the modal the first time, I can remove the disable class from the calculate button. If i open/close/open it will work for every calculator on the page.
products.blade.php
foreach product
<a
class="btn-icon"
data-toggle="modal"
data-target="#publicModal"
data-url="{!! route('public.products.partials.calculator', ['product_id'=>$pp->product->id]) !!}"
data-title="Calculate cost"
data-size="modal-xl" >
<i class="fas fa-calculator"></i>
</a>
jquery
if(
custSQFT > 0 &&
custWidth > "0.00" &&
custLength > "0.00" &&
totalCost > 0
){
document.getElementById("calc-cost").classList.remove("disabled");
document.getElementById("calc-cost").classList.add("visible");
calcValid = true;
}else{
$('#calc-cost').prop("disabled",true).addClass('disabled')
calcValid = false;
}
Modal
<script type="text/javascript">
$('#publicModal').on('show.bs.modal', function (event) {
if(event.relatedTarget){
var button = $(event.relatedTarget) // Button that triggered the modal
}else{
var button = $('#loginButton');
}
var url = button.data('url') // Extract info from data-* attributes
var size = button.data('size')
var modal = $(this)
if (typeof(size) !== 'undefined') {
modal.find('.modal-dialog').addClass(size)
}
modal.find('.modal-body').load(url);
modal.find('.modal-title').html(button.data('title'))
});
$('#publicModal').on("hidden.bs.modal", function(){
$(".modal-body").html("");
$(".modal-title").html("Loading...");
});
</script>
So when I open up the modal, fill out the forms, I can console.log that I have made it inside the IF statement, but can not remove the visible class.
If I'm understanding correctly, you are having an issue with replacing the element in the dom with the same id.
I think probably easiest fix would be to add a unique id and capture that specific id to take action within your jquery.
Name the id uniquely, perhaps using the product id:
<a id='calc-cost-{{$pp->product->id}}' //... etc
Then you have a number of options to identify the current iteration, but I'll illustrate using blade instead of pure JS/Jquery for simplicity:
$('#calc-cost-'{{$pp->product->id}}).removeClass('disabled'); //etc
Normally, I'd add a data element on the <a> and grab the id through jquery to make it a little cleaner ( $('#calc-cost-'+grabbedIdVar)), but the above should give you an idea of how to go.
HTH.

Dynamically create a div with dynamic onclick function

Context: I'm lazy, and I'm trying to dynamically/automatically create menu buttons which are hyperlinked to the headers of a page with raw JavaScript.
My site loads the content of the body from an external file located at the same folder with document.onload, and I'm trying to set up a menu function, which then should load the default page's menu items. Loading the menu manually each time I change from one page to another works, as I've included loadMenues(thispage) on the end loadContents(), but it doesn't work as soon as the page is loaded, as loading the body content does. I don't understand this behaviour.
function setVisible(thisdiv){
var alldivs = document.getElementsByClassName("container");
[].forEach.call(alldivs, function(uniquediv){
document.getElementById(uniquediv.id).style.display = "none";
return;
});
document.getElementById(thisdiv).style.display = "block";
window.scrollTo(0,0);
loadMenues(thisdiv);
}
window.onload = function(){
loadContent("personalinfo");
loadContent("contactdetails");
setVisible("personalinfo");
loadMenues("personalinfo");
}
I'm explaining this, secondary question, in order to contextualize my main problem.
loadContents(file) is a function which extracts the contents from the requested file. The layout of each of these files is the same, pretty much, with each section of the file being separated by a custompadding div, where its first child is a h1 element as shown below:
<html>
<div class="custompadding">
<h1 id="headerpersonaldetails">Personal details</h1>
<p>Lorem ipsum</p>
</div>
<div class="custompadding">
<h1 id="headercontactdetails">Contact details</h1>
<p>Lorem ipsum</p>
</div>
</html>
I'm trying to set up a menu item for each of these headings, which scrolls to the clicked-on header. Setting up each menu-item manually works as expected, but I want to automatize it, so changing any file will automatically add the menu items to whichever page we change to. Following is my code which adds these elements to the divisor, but I'm having issues handling the onclick function.
function loadMenues(file) {
var rightmenu = document.getElementById("right-menu");
while(rightmenu.firstChild){
rightmenu.removeChild(rightmenu.firstChild);
}
[].forEach.call(document.getElementById(file).children, function(custompaddingchild) {
console.log(custompaddingchild);
headerelement = custompaddingchild.getElementsByTagName("h1")[0]
newbutton = document.createElement("div");
newbutton.setAttribute("class", "menu-item");
let movehere = function() { location.href="#"+headerelement.id; console.log(headerelement.id); }
newbutton.onclick = movehere;
/*rightmenu = document.getElementById("right-menu");*/
buttonspanner = document.createElement("span");
buttoncontent = document.createTextNode(headerelement.innerHTML);
buttonspanner.appendChild(buttoncontent);
newbutton.appendChild(buttonspanner);
rightmenu.appendChild(newbutton);
});
}
The first part of the function deletes all the nodes which already are in the menu, in order to add the new ones when changing pages.
Trying to define newbutton.setAttribute() with onclick results in a SyntaxError (fields are not currently supported) in Firefox. It doesn't work if I set a static string as newbutton.setAttribute("onclick", "location.href=#headerpersonalinfo"); either.
Trying to set a static anchor link with newbutton.onclick set to a function, instead, works, such that
newbutton.onclick = function() {
location.href = "#headerpersonalinfo";
}
and this is pretty much how my current code is set up, except that I have given this function a unique variable, which I then call.
The problem I have is this, as I see it: The variable is redefined each time it finds a new header, so calling the function sends the user to the last header, and not the expected one. How can I set the function to be parsed at the moment I define onclick with it, and not call the function when the user presses the button?
PS: I'm using my own internal naming convention of files, headers, and items, in order to modularize my site as much as I can. Since this is a website only intended for my Curriculum Vitae, I'm its only developer.
The issue occurs because the you are hoisting "variables" to the global scope (newbutton and headerelement).
Set them to block scoped variables (const or let) and you will see that it works:
https://codesandbox.io/s/rm4ko35vnm
function loadMenues(file) {
var rightmenu = document.getElementById("right-menu");
while (rightmenu.firstChild) {
rightmenu.removeChild(rightmenu.firstChild);
}
[].forEach.call(document.getElementById(file).children, function(
custompaddingchild
) {
console.log(custompaddingchild);
const headerelement = custompaddingchild.getElementsByTagName("h1")[0];
console.log(headerelement.innerHTML);
const newbutton = document.createElement("div");
newbutton.setAttribute("class", "menu-item");
console.log(headerelement.id);
let movehere = function() {
location.href = "#" + headerelement.id;
console.log(headerelement.id);
};
newbutton.addEventListener('click', movehere);
const rightmenu = document.getElementById("right-menu");
const buttonspanner = document.createElement("span");
buttoncontent = document.createTextNode(headerelement.innerHTML);
buttonspanner.appendChild(buttoncontent);
newbutton.appendChild(buttonspanner);
rightmenu.appendChild(newbutton);
});
}

Any reason why jquery .click() wouldent target an a tag?

I am stumped as to why my query .click() is not working. I am trying to change the href tag on an a element, before it goes to the next page.
here is my jquery
$('.individualFormSections').click(function() {
var formSectionTitle = $(this).siblings('div').text(); // gets section title that was clicked
console.log(formSectionTitle);
assetConfigIdForURL = assetConfigIdForURL.replace(/\s+/g,'-');
woTypeCodeForURL = woTypeCodeForURL.replace(/\s+/g,'-');
woMaintTypeCode = woMaintTypeCode.replace(/\s+/g,'-');
formSectionTitle = formSectionTitle.replace(/\s+/g,'-');
// Change href dynamically to set url parameters
$(this).attr("href",'airSystem.html?insp_asset_config_id='+assetConfigIdForURL+'&wo_type_code='+woTypeCodeForURL+'&wo_maint_type_code='+woMaintTypeCode+'&formSection='+formSectionTitle+'&wo_id='+woIdForURL+'');
});
Here is the html
<a class="individualFormSections" href="">
<img class="bus-form-img" src="pull-up.jpg" alt="Trolltunga Norway">
</a>
<div class="desc" id="bodyDamageDesc">AirSystem</div>
I also tried doing a simple alert and its not even targeting the a tag. My javascript link is set up correctly.
A little background, the html is getting generated dynamically from a previous javascript function. When I use chrome developer tools, all the html shows just fine. Any ideas on what could be causing this?
Always use prevent default in such cases
$('.individualFormSections').click(function(e) {
e.preventDefault();
var formSectionTitle = $(this).siblings('div').text(); // gets section title that was clicked
console.log(formSectionTitle);
assetConfigIdForURL = assetConfigIdForURL.replace(/\s+/g,'-');
woTypeCodeForURL = woTypeCodeForURL.replace(/\s+/g,'-');
woMaintTypeCode = woMaintTypeCode.replace(/\s+/g,'-');
formSectionTitle = formSectionTitle.replace(/\s+/g,'-');
// Change href dynamically to set url parameters
$(this).attr("href",'airSystem.html?insp_asset_config_id='+assetConfigIdForURL+'&wo_type_code='+woTypeCodeForURL+'&wo_maint_type_code='+woMaintTypeCode+'&formSection='+formSectionTitle+'&wo_id='+woIdForURL+'');
});
Change to this.
$('.individualFormSections').click(function(e) {
e.preventDefault();
var formSectionTitle = $(this).siblings('div').text(); // gets section title that was clicked
console.log(formSectionTitle);
assetConfigIdForURL = assetConfigIdForURL.replace(/\s+/g,'-');
woTypeCodeForURL = woTypeCodeForURL.replace(/\s+/g,'-');
woMaintTypeCode = woMaintTypeCode.replace(/\s+/g,'-');
formSectionTitle = formSectionTitle.replace(/\s+/g,'-');
// Change href dynamically to set url parameters
$(this).attr("href",'airSystem.html?insp_asset_config_id='+assetConfigIdForURL+'&wo_type_code='+woTypeCodeForURL+'&wo_maint_type_code='+woMaintTypeCode+'&formSection='+formSectionTitle+'&wo_id='+woIdForURL+'');
});

Why is my javascript file not re-setting a div's attribute?

I have a script that is adding and removing a class to a couple divs when a link is clicked on. Each div has a set class that does not need to be removed. However, said class is being removed. How do I stop this from happening?
HTML
<div id="home" class="page pageShowing"></div>
<div id="portfolio" class="page"></div>
JS
let holder = document.getElementById("main");
let pageShowingClass = holder.getElementsByClassName("pageShowing");
let pages = holder.getElementsByClassName("page");
Navigation.Links.forEach(function(value){
let createNavLink = document.createElement("li");
let createNavText = document.createTextNode(value.title);
createNavLink.appendChild(createNavText);
createNavList.appendChild(createNavLink);
createNavLink.addEventListener("click", function(){
let link = createNavLink.innerHTML;
link = link.toLowerCase().replace(" ", "_");
let page = document.getElementById(link);
page.setAttribute("class", "page");
for(let i = 0; i < pageShowingClass.length; i++){
Here, the click handler should only be removing the pageShowing class
if it exists but is also removing the page class
if(pageShowingClass[i].getAttribute("class") == "pageShowing"){
pageShowingClass[i].removeAttribute("class");
}
}
Here, the click handler should be readding the page class when the
link is clicked on.
page.setAttribute("class", "page");
page.setAttribute("class", "pageShowing");
page.style.display = "block";
});
});
I know it's easier to do this in jQuery, but I don't want it to be in jQuery. I also already have it to where it will add and remove the pageShowing class dynamically, so that's not an issue.
As Siguza said in the reply, you're removing the class attribute, which is what you DON'T want to be doing in this case.
Let's put the element in question here for reference:
<div id="home" class="page pageShowing"></div>
class is an attribute of the element div. When you call removeAttribute('class'), it will do as it says:
<div id="home"></div>
If you check the element in chrome's dev tools or whatever you use, you'll be seeing the element as it says above.
You're probably looking for Element.className to modify your classes, so instead of
if(pageShowingClass[i].getAttribute("class") == "pageShowing"){
pageShowingClass[i].removeAttribute("class");
}
you'll want
if(pageShowingClass[i].getAttribute("class") == "pageShowing"){
pageShowingClass[i].className = "page";
}
and if you want to add the pageShowing class again, you'd just say pageShowingClass[i].className = "page pageShowing"
Element.setAttribute() adds a new attribute or changes the value of an existing attribute on the specified element.
Use Element.classList.add(String [, String]), adds specified class values. If these classes already exist in attribute of the element, then they are ignored.
page.classList.add('page', 'pageShowing')

Display : None/Block Style Tab Menu Creation with Buttons and Javascript

function tab_menu(){
if (buttonObject.value == value){
document.getElementById("div1").style.display = "block";
}
}
i was trying when click to buttons check Button Value and show a div based on Button's Value and hide others divs it should show just one div at same time. I wonder there is a javascript Master who can solve this problem.
SCRIPT:
function tabmenu(buttonObject){
var value = buttonObject.value
var target = document.getElementById(value);
if(target) {
var siblings = target.parentNode.getElementsByTagName("DIV");
for(i=0;i<siblings.length;i++){
siblings[i].style.display = "none";
}
target.style.display = "block";
}
}
HTML:
<div>
<div id="tab1">Tab1</div>
<div id="tab2">Tab2</div>
<div id="tab3">Tab3</div>
</div>
<button onclick="tabmenu(this);" value="tab1">Tab1</button>
<button onclick="tabmenu(this);" value="tab2">Tab2</button>
find the tab to activate (assuming value = tab.id)
find the parent and hence it's siblings (assuming they are DIVs)
hide the siblings
show the target
You can see it working here: http://jsfiddle.net/4rWdQ/

Categories