I return to the user a list of his notes, surely that there may be an indefinite number of them.
I create buttons when the text is longer than 80 characters.
By clicking on this button, I want to catch a click among other buttons and find out all the information about his parent div. How can i do this?
<div class="d-flex flex-wrap">
#foreach (var item in ViewBag.UserTodoList)
{
<div class="card" style="width: 32%; margin-left: 1%; margin-top:1%">
<div class="card-body">
<h5 class="card-title">#item.Name</h5>
#if (item.Body.Length > 80)
{
<p class="card-text">#item.Body.Substring(0, 80)...</p>
<button class="btn btn-info" id="1234">Прочитать</button>
}
else
{
<p class="card-text">#item.Body</p>
}
<a asp-controller="ToDo" asp-action="DeleteTodos" asp-route-todoId="#item.Id" class="btn btn-primary">Удалить</a>
</div>
</div>
}
</div>
Something like this:
const buttons = Array.from(document.querySelectorAll('.card .btn'));
function handleClick() {
const parent = this.parentNode; // here is parent
console.log(parent) // lets log it to console
}
buttons.forEach((button) => { button.addEventListener('click', handleClick);})
BTW, you should add unique class to your buttons. It will be easier to get them by querySelectorAll or getElementsByClassName
I am not expert in this (new one to it too) but how i would do it is add that button some class like ErrorClass and then inside script i would do
$('.ErrorButton').click(function() {
var parent = this.parent(); // With this you get parent div container
});
Related
I have several links in the menu. Each link is making opacity from 0 to 1 for hidden div. I made dropdown menu this way because I use flex inside that div so I toggle the opacity.
I am using document.getElementsByClassName for selecting an elements. When someone is making a variable with this selector basically he or she has an array with all of the elements with this class.
My code is working, because when I envoke the function from HTML, I'm doing it using parameters. What I would like to do is to connect the link I'm clicking and the div that it shows by index. For example, all links with class A are opening divs with class B. I want to be sure that the first link with class A always opens the first link with class B. I don't want to rely on the parameters in HTML.
How can I do it more efficiently?
function showDropDown(n) {
let hiddenDiv = document.getElementsByClassName("hidden_dropdown_div");
hiddenDiv[n].classList.toggle("active");
for (let i = 0; i < hiddenDiv.length; i++) {
if (i != n) {
hiddenDiv[i].classList.remove("active")
};
}
};
$(".maindrop_link").click(function(e) {
e.stopPropagation(); // This is the preferred method.
return false; // This should not be used unless you do not want
// any click events registering inside the div
});
$(document).click(function() {
let hiddenDiv = document.getElementsByClassName("hidden_dropdown_div");
for (let i = 0; i < hiddenDiv.length; i++) {
hiddenDiv[i].classList.remove("active");
}
});
.hidden {
opacity: 0;
}
.active {
opacity: 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<!-- See the link above the hidden block -->
<li class="dropmenu inlineblock">
<a class="maindrop_link" href="#" onclick="showDropDown(0)">Makeup</a>
</li>
<div class="hidden_dropdown_div hidden" id="hidden_dropdown_div">
<div class="hidden_dropdown_link_wrapper">
<ul class="hidden_dropdown_ul">
<li><a class="hiddendrop_link" href="#">Wedding Makeup</a></li>
<li><a class="hiddendrop_link" href="#">Event Makeup</a></li>
<li><a class="hiddendrop_link" href="#">Creative Makeup</a></li>
</ul>
</div>
<div class="hidden_dropdown_pic_wrapper">
<div class="item_for_hidden_div">
<div class="picholder_for_hidden_div"></div>
<div class="textholder_for_hidden_div"></div>
</div>
<div class="item_for_hidden_div">
<div class="picholder_for_hidden_div"></div>
<div class="textholder_for_hidden_div"></div>
</div>
<div class="item_for_hidden_div">
<div class="picholder_for_hidden_div"></div>
<div class="textholder_for_hidden_div"></div>
</div>
</div>
</div>
<div class="gallery-container">
<?php while (have_rows('gallery')): ?>
[...]
<div class="toggle-container">
<button class="toggle-button active" onclick="gridView()">Grid</button>
<button class="toggle-button" onclick="listView()">List</button>
</div>
<div class="gallery-items grid-items">
[...Gallery Items...]
</div>
<?php endwhile; ?>
</div>
What would be the best way to select specific elements on a page when the elements are created with a while loop shown above. It's an ever-growing list and elements can also be removed.
In this example I am generating a page full of small galleries together with the toggle buttons for the Grid/List view next to each gallery.
I am trying to make all of those buttons work with just the gallery they are generated together with.
I know how to select them based on their index manually, but I don't know how I could tweak the code to be able to make it work with every small gallery separately.
This is what I came up with to make it work with the first gallery:
<script>
const button = document.getElementsByClassName('toggle-button');
const element = document.getElementsByClassName('gallery-items');
function listView() {
if ( element[0].classList.contains('grid-items') ){
element[0].classList.remove("grid-items");
}
button[0].classList.toggle('active');
button[1].classList.toggle('active');
}
function gridView() {
if ( !element[0].classList.contains('grid-items') ){
element[0].classList.add("grid-items");
}
button[0].classList.toggle('active');
button[1].classList.toggle('active');
}
</script>
You might consider using event delegation instead: add a click listener to .gallery-container. If the clicked target is a .toggle-button, run the appropriate logic, selecting the relevant surrounding elements on click:
document.querySelector('.gallery-container').addEventListener('click', ({ target }) => {
if (!target.matches('.toggle-button')) {
return;
}
const toggleContainer = target.parentElement;
const btns = toggleContainer.children;
if (target === btns[0]) {
btns[0].classList.add('active');
btns[1].classList.remove('active');
} else {
btns[0].classList.remove('active');
btns[1].classList.add('active');
}
const galleryItems = toggleContainer.nextElementSibling;
if (target === btns[0]) {
galleryItems.classList.add('grid-items');
} else {
galleryItems.classList.remove('grid-items');
}
});
.active {
background-color: yellow;
}
.grid-items {
background-color: red;
}
<div class="gallery-container">
<div class="toggle-container">
<button class="toggle-button active">Grid</button>
<button class="toggle-button">List</button>
</div>
<div class="gallery-items grid-items">
[...Gallery Items...]
</div>
<div class="toggle-container">
<button class="toggle-button active">Grid</button>
<button class="toggle-button">List</button>
</div>
<div class="gallery-items grid-items">
[...Gallery Items 2...]
</div>
</div>
Note that there's no need to explicitly test if a classList.contains a particular class before adding it (though, there's no harm in doing so, it's just unnecessary).
I'm trying to show container on click with localstorage. I mean that when you click the button, CSS classess:is-hidden and is-visible will be saved and remembered by browser.
This is my code:
var comments = document.getElementById("js-comments");
if (comments) {
comments.addEventListener("click", function() {
localStorage.setItem('comments', 'true');
comments.classList.add("is-hidden");
var container = document.getElementById("js-comments__inner");
container.classList.add("is-visible");
if (localStorage.getItem('comments') == 'true') {
container.classList.add("is-visible");
}
});
}
HTML markup:
<div class="comments">
<button class="comments__button" id="js-comments">Load comments</button>
<div class="comments__inner" id="js-comments__inner">
<h3 class="h4">Comments</h3>
</div>
</div>
Idea is: when you click on the button and the comments__inner elements then they receive the CSS clasess.
I have my main page which contains a number of PartialViews
Here is my Index.cshtml
<div class="container">
#{
foreach (var summary in Model.Summaries)
{
<div class="partialViewWrapper">
#Html.Partial("_Summary", summary)
</div>
}
}
</div>
Here is my Javascript:
$(document).ready(function() {
$(".toggle").on("click",
function() {
var btn = $(this);
var state = btn.html();
if (state === 'Show Down Times') {
btn.html('Hide Down Times');
$('.foo').show();
} else {
btn.html('Show Down Times');
$('.foo').hide();
}
My partial View (relevant bits):
<div class="row">
<div class="col-md-12">
<button class="toggle btn btn-default" >Show Down Times</button>
</div>
<div class="foo col-md-12" style="display: none">
<table class="table table-striped table-bordered table-responsive">
...
</table>
</div>
</div>
My issue is, when I click the button on the first partial view, it changes its text to Hide from Show, but both Partial Views show their respective table.
So, the JS to change the button text is being applied to the correct partial view buttons but the showing / hiding the table is being applied to all partial views.
I think I need to do something with $(this) rather than just referencing it by class but I have no idea how to achieve this with JQuery.
Thanks,
Use relative selectors to get the .closest() ancestor containing both elements and then .find() the other element inside that ancestor.
var btn = $(this);
var foo = btn.closest('.row').find('.foo');
if (state === 'Show Down Times') {
btn.html('Hide Down Times');
foo.show();
} else {
btn.html('Show Down Times');
foo.hide();
}
The reason is $('.foo'). Since you are not pointing out the table in a specific partial. The selector selects all classes with the class foo.
The solution to this problem is to
Either
Select the sibling of the parent using the parent and next functions with btn and then use hide or show.
Or
Add an additional attribute to the button say data-target and add the name of the class or id. Access it using btn.data('target') and then use hide or show.
I've got help with a script that works in the first modal but doesn't in any of the next couple. When you scroll down, the background color changes in the first modal but nothing happens in the second and so forth.
https://jsfiddle.net/qhrmtass/10/
var scrollFn = function () {
var targetOffset = $("#anchor-point")[0].offsetTop;
console.log('Scrolling...');
if ($('.remodal').scrollTop() > targetOffset) {
$(".projectTitle").addClass("topper");
} else {
$(".projectTitle").removeClass("topper");
}
};
$('.remodal').scroll(scrollFn);
Specification says UNIQUE
HTML 4.01 specification says ID must be document-wide unique.
HTML 5 specification says the same thing but in other words. It says that ID must be unique in its home subtree which is basically the document if we read the definition of it.
First for the best practice you have to change duplicate id anchor-point (in my example i change it to class) also for the id one should be unique.
Secondly you have to use $(this) inside your scroll function scrollFn to detect the current scrolling remodal and to select the elements that belong to it.
HTML :
<a class="project-link" href="#modal1" id="one" style="margin-right:25px;">Modurra Shelving </a>
<div class="remodal" data-remodal-id="modal1">
<div class="dar">Darrien Tu.</div>
<button class="remodal-close" data-remodal-action="close"></button>
<div class="anchor-point">sdfsfs</div>
<div class="title">
<p class="projectTitle">Modurra
<br>Shelving.</p>
</div>
</div> <a class="project-link" href="#modal2" id="one" style="margin-right:25px;">Other stuff </a>
<div class="remodal" data-remodal-id="modal2">
<div class="dar">Darrien Tu.</div>
<button class="remodal-close" data-remodal-action="close"></button>
<div class="anchor-point">sdfsfs</div>
<div class="title">
<p class="projectTitle">Modurra
<br>Shelving.</p>
</div>
</div>
Js :
var scrollFn = function () {
var targetOffset = $(this).find(".anchor-point")[0].offsetTop;
console.log('Scrolling...');
if ($(this).scrollTop() > targetOffset) {
$(this).find(".projectTitle").addClass("topper");
} else {
$(this).find(".projectTitle").removeClass("topper");
}
};
$('.remodal').scroll(scrollFn);
Hope this could help, take a look at Working fiddle