I've got a problem to open Bootstrap 4 modal using element generated by Javascript.
There are two very similar cards (identical but with diffrent id). First is hard coded in html doc (and work correctly). Another is generated by simple JS script. I try to use the same class name "openEditModal" but it doesn't work. Then I declared "data-toggle" "data-target" attributes for both but still work only hard coded card. Is there any possibility that Bootstrap JS file work only with hard coded element?
HTML Coded Card
<div class="row" id="all-contacts-box">
<!-- ____EXIST_ADDRESSES____ -->
<!-- addressBoxWrapper -->
<div class="col-xl-3 col-md-4 col-sm-6 col-12 mt-2 d-flex">
<!-- addressBox -->
<div class="card bg-light openEditModal label flex-fill">
<!--contactHeader-->
<div class="card-header pl-2 pt-1 font-weight-bold text-muted label-title">
Office Address
</div>
<!-- contactBody -->
<div class="card-body row pt-0">
<!-- contactBodyLeft -->
<div class="col-4 d-flex justify-content-center align-items-center maps-pin">
<i class="fas fa-map-marker-alt"></i>
</div>
<!-- contactBodyRight -->
<div class="col-8">
<h4 class="label-title font-weight-bold">Main Name</h4>
<h5 class="label-address font-weight-normal">Street 22</h5>
<h5 class="label-address font-weight-normal">City, Country</h5>
</div>
</div>
</div>
</div>
Part of JS Code that generate new card
var createContactBox = function(dataToDisplay, idCounter) {
var mainAddressContainer = document.getElementById("all-contacts-box");
var addNewBox = document.getElementById("add-new-box");
var addressBoxWrapper = document.createElement("div");
var addressBox = document.createElement("div");
mainAddressContainer.insertBefore(addressBoxWrapper, addNewBox);
addressBoxWrapper.appendChild(addressBox);
addressBoxWrapper.classList = "col-xl-3 col-md-4 col-sm-6 col-12 mt-2 d-
flex";
addressBox.classList = "card bg-light openEditModal label flex-fill";
addressBox.setAttribute("data-toggle", "modal");
addressBox.setAttribute("data-target", "editBoxModal");
};
$(".openEditModal").click(function() {
$("#editBoxModal").modal();
});
The problem with dynamically created elements, is that they aren’t born with the same event handlers as the existing elements.
In order to fix it, you need to "refresh" the listeners after you add a dynamically element.
So I add events handlers to a function and turn it off before I turn it on (something like restart). If you don't turn it off, the event will triggered as many times this function is called, and you don't want it.
function refreshEvents() {
$(".openEditModal").off();
$("#add-new-box").off();
$(".openEditModal").click(function() {
$("#editBoxModal").modal();
});
$("#add-new-box").click(function() {
$("#addNewBoxModal").modal();
});
}
Now you can call this function whenever you create another element.
So I call it after you created the element.
This is a working fiddle
Related
I am rendering dynamic data from array of objects on an html page. i want to flip the specific box. On front page i want to show image and heading while on the back page i want to show the paragraph. I am attaching the HTML and JavaScript file.
The HTML code
<div class="row rwOneOurservices ourServicesContainer" ></div>
JavaScript where I am rendering my data from an array of objects
const FnRenderOurService = () => {
if (ElourServicesContainer) {
ElourServicesContainer.innerHTML = "";
for (singleOurService of ourServices) {
ElourServicesContainer.innerHTML += `
<div class="col-sm-3 col-10 ourServiceElement" onclick="FnShowService('${singleOurService.id}')" id="${singleOurService.id}">
<div class="row">
<div class="col-md-4 col-12">
<img
src="${singleOurService.serviceImg}"
alt=""
/>
</div>
<div class="col-md-8 col-12">
<h5>${singleOurService.serviceName}</h5>
</div>
</div>
<div class="row">
<div class="col-12">
<p>
${singleOurService.serviceShortDesc}
</p>
</div>
</div>
</div>
`;
}
}
};
How to apply flip on every grid separately (might be on the basis of 'Id')?
Here's my code for a section of my page that i want to change
let existinguser = document.querySelector('#existing-user');
let table= document.querySelector('#table-contents');
existinguser.addEventListener('click', () => {
table.innerHTML = '';
});
since innerHTML only accepts string, how do i display content from another page
eg. new_page.html using .innerHTML
I dont't know if this will be required but here are the #existing-user snippets
<div class="col-xl-3 col-md-6">
<div class="card bg-primary text-white mb-4">
<div class="card-body">Existing User's requests</div>
<div class="card-footer d-flex align-items-center justify-content-between">
<a class="small text-white stretched-link" href="#" id="existing-user">View Details</a>
<div class="small text-white"><i class="fas fa-angle-right"></i></div>
</div>
</div>
</div>
You should use iframe for adding html pages
You can do hacky stuff. You can use Javascript to fetch another html.
fetch('new_page.html').then(res=>res.text()) and add the response to the innerHTML.
Use jQuery .load(url) or any other method of Ajax in general.
$(".container").load("https://jsonplaceholder.typicode.com/");
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<h1>next content is loaded from another html page</h1>
<div class="container" style="background:#eee"></div>
<h1>previous content was loaded from another html page</h1>
Hi I'm new to web development and I'm trying to practice by making a small site for my mom!
So basically I have this div that I want to replicate multiple times only changing the image url & the h3 caption.
<div class="col-lg-4 mb-5 col-md-6">
<div class="wine_v_1 text-center pb-4">
<a class="thumbnail d-block mb-4"><img src="images/im.jpg" alt="Image" class="img-fluid"></a>
<div>
<h3 class="heading mb-1">Us</h3>
</div>
</div>
</div>
I was thinking of using JavaScript to copy the div as a string to be something like ( pseudocode )
for image.length {
getelementbyid.print (div1 + imageArray(i) + div2 + caption(i) + endofDiv )
}
Would this be possible? Would it make sense to do it this way or is there a more simple way?
Example
The example works by having a data object, which stores the captions and image URLs. Then, there is a clone template. It loops through each and clones the template, and replaces each element with the correct content. Then it adds it to the HTML with .appendChild.
You can write a function doing this job. Creating copies of your element and change the attributes corresponding to your new data.
function copyAndChangeImageAndCaption(){
const images = [
{imageUrl: "images/de.jpg", caption: "De"},
{imageUrl: "images/it.jpg", caption: "It"},
{imageUrl: "images/fr.jpg", caption: "Fr"}
];
images.forEach(image => {
const el = document.getElementsByClassName('col-lg-4 mb-5 col-md-6');
let copy = el[0].cloneNode(true)
copy.getElementsByClassName('thumbnail')[0].childNodes[0].src=image.imageUrl;
copy.getElementsByClassName('heading')[0].childNodes[0].innerHTML = image.caption;
document.getElementsByClassName('container')[0].appendChild(copy);
});
}
<div class='container'>
<div class="col-lg-4 mb-5 col-md-6">
<div class="wine_v_1 text-center pb-4">
<a class="thumbnail d-block mb-4"><img src="images/im.jpg" alt="Image" class="img-fluid"></a>
<div>
<h3 class="heading mb-1">Us</h3>
</div>
</div>
</div>
</div>
<button onClick="copyAndChangeImageAndCaption()">Add images</button>
I have a few rows with linked elements in them. The code looks like this:
<a href="link" class="list-group-item list-group-item-action" data-lat="30.25552298" data-lon="-97.555554">
<div class="row">
<div class="col-sm-12 col-md-7 col-lg-8 col-xl-9 lead">
label
</div>
<div class="col-sm-12 col-md-5 col-lg-4 col-xl-3 d-flex justify-content-between align-items-center">
<span class="badge bg-success"><small>33</small></span>
<strong>5 mi.</strong>
</div>
</div>
</a>
Then I use event listeners to call couple functions when my mouse moves over the links:
let loc = document.querySelectorAll("a[data-lat]");
var marker;
loc.forEach(node => {
node.addEventListener("mouseover", locOver);
node.addEventListener("mouseout", locOut);
})
function locOver(event) {
var llt = event.target.dataset["lat"],
lln = event.target.dataset["lon"];
marker = L.marker([llt, lln]).addTo(map);
}
function locOut(event) {
marker.remove();
}
Since there's a little padding on the link it works great when a mouse enters it, however, as soon as the mouse hits divs within the link the marker disappears, which seems weird to me since it's still linked.
I've tried modifying selector like this:
let loc = document.querySelectorAll("a[data-lat] div");
But my code just stops working, and no marker is shown. What am I missing here?
I need help with Bootstrap Columns Toggle that converts a 12 column grid into other two columns with 9 and 3 columns, and back to 12 columns again.
I have a prototype, but I can't seem to get it quite right. Here's the JSFIDDLE.
To understand the issue, I have 3 different scenarios that are explained in the prototype that basically starts at 12 columns, gets toggled to 9 + 3 columns, and back to 12 columns.
The HTML code is as follow:
<div class="container-fluid col-lg-12 col-md-12 col-sm-12 col-xs-12">
<h2 class="align-center">Current Prototype</h2></div>
<div id="LeftColumn" class="col-md-12 col-sm-12 col-xs-12">
<h4>Left Column</h4>
<p>Currently is set to col-md-9, but it should initially be col-md-12 and be toggled to col-md-9 while maintaining its responsive properties.</p>
<p><span class="strong">DESIRED RESULT:</span>Toggle the properties <div class="col-md-12 col-sm-12 col-xs-12"> to <div class="col-md-9 col-sm-9 col-xs-12"> when the "Toggle Right" column button is clicked while maintaining the existing functionality.</p>
<div id="Bar" class="main-container collapse in">
Toggle Right
</div>
<div class="clearfix"></div>
<br />
</div>
<div id="RightColumn" class="col-md-3 col-sm-3 col-xs-12">
<div id="Foo" class="main-container collapse" style="border: dotted 1px green;">
Toggle Left Column <i class="fa fa-bars"></i>Additional content will be displayed in this column once triggered.
<div style="height: 150px;"></div>
</div>
</div>
The Javascript that needs attention is as follow:
$(".main-container.collapse").on('shown.bs.collapse', function() {
//when a collapsed div is shown hide all other collapsible divs that are
visible
$(".main-container.collapse").not($(this)).collapse('hide');
});
$('#toggle-right').click(function(e) {
var left = $('#LeftColumn');
if (left.hasClass('col-md-9')) {
left.removeClass("col-md-9 col-sm-9").addClass("col-sm-12 col-md-12");
} else {
left.removeClass("col-md-12 col-sm-12").addClass("col-sm-9 col-md-9");
}
})
I would certainly appreciate any help and expertise you can provide with a custom jsfiddle. Thanks!
There are just couple of minor changes you need to do to toggle.
Problem: You are adding/removing the classes on the click of the #toggle-right button which is fine but you are NOT again doing the same on the next toggle button namely your <a>(yellow warning button) once your 12 columns get divided to 9 and 3.
<i class="fa fa-bars"></i>
Solution:
All you need to do is call that same function which adds/removes the classes on the click of the <a> button as well. Firstly give a class or an id to the element to identify it.
<i class="fa fa-bars"></i>
Now you just need to add that new selector in your existing click function.
$('#toggle-right, #toggle-left').click(function(e) {
var left = $('#LeftColumn');
if (left.hasClass('col-md-9')) {
left.removeClass("col-md-9 col-sm-9").addClass("col-sm-12 col-md-12");
} else {
left.removeClass("col-md-12 col-sm-12").addClass("col-sm-9 col-md-9");
}
})