Drop down div for multiple divs by id - javascript

What would be the best practice to use dropdowns in multiple divs by different id's
I have a user stream of which when I add a dropdown menu to add delete, edit post etc opens only one div on the top post so I know it has to be done by a unique id.
Maybe some javascript? This is what I have so far.
<div class="postdrop" id="postdrop'.$streamitem_data['streamitem_id'].'">
<a class="postdrop_button postdrop_close" href="#">
<span class="a rrow"></span>
</a>
<a class="postdrop_button postdrop_open"href="#postdrop">
<span class="arrow"></span>
</a>
<ul class="postdrop_content">
<li>Edit</li>
<li>Privacy - </li>
<li>Delete</li>
</ul>
</div>

You could do this with plain css.
.postdrop_content {
display:none;
}
Then you could invoke the display on the hover event.
.postdrop_button.postdrop_open:hover + postdrop_content {
display:block;
}
Do note that in this particular scenario, however, as the hover event will show the dropdown, you won't be able to hover over it and maintain the element staying open.
You have two methods to resolve this:
Move the :hover event to the parent contianer (postdrop in this case) and give postdrop a class when it has dropdown content, such as, postdrop_has_dropdown. You can then make your CSS selector target this element and the hover event will stay fired when you hover over the dropdown.
.postdrop_has_dropdown:hover .postdrop_content {
display:block;
}
Use some simple jQuery:
$('.postdrop_button.postdrop_open').on('click', function(){
$(this).next().show();
});
$('.postdrop_button.postdrop_close').on('click', function(){
$(this).next().hide();
});

You can handle it with javascript. I recommend using Knockout js http://knockoutjs.com/
Populate your feed using an observable array, and you can execute the javascript with whatever event binding you wish to use.
<div class="myFeed" data-bind="foreach: myFeed">
<div class="feedItem" data-bind="event:{click: function(e){$root.doStuff($data e);}}">
<div class="itemAction" data-bind="event:{mouseOver: function(e){$root.handleMouseOver($data)}}"></div>
</div>
</div>
The $root object is the controller bound to the DOM.
The $data object is the object within the array
The feed will update when you update the observableArray myFeed
var myController = function()
{
var self = this;
this.myFeed = ko.observableArray([]);
this.handleMouseOver = function(data)
{
// Do stuff with data
};
this.doStuff = function(data, e)
{
// e is the event that triggered it. e.target is the element you want to manipulate
// do stuff with data
};
};

Related

Proper way to handle many event listeners in javascript

In my website, I have a dynamically growing list, (from a database) that has buttons attached to each item of the list. The button goes to the same javascript function, but each element in the list has a different id, which needs to be included inside the function when it is running.
I'm currently using onclick in the html and can pass the id through the function's parameter, as I am using template literals to render the list.
Is there any way that I can do this with event listeners?
An example of what I currently have would be:
onclick="theFunction('id')"
which changes for every item in the list, so the list could look like
<ul>
<li onclick="theFunction('id1')">name1</li>
<li onclick="theFunction('id2')">name2</li>
<li onclick="theFunction('id3')">name3</li>
</ul>
Use event delegation instead: attach one listener to the <ul>, and then on click, check to see if the clicked element was a <li>. If so, check an attribute of the <li> to figure out what parameter to call theFunction with. For example:
const theFunction = console.log;
document.querySelector('ul').addEventListener('click', (e) => {
if (!e.target.matches('li')) {
return;
}
const param = 'id' + e.target.dataset.param;
theFunction(param);
});
<ul>
<li data-param="1">name1</li>
<li data-param="2">name2</li>
<li data-param="3">name3</li>
</ul>
Note how the onclick attributes have been replaced with data-param attributes.

what jquery event should i use for this type of dropdown menu

I am working on a project(back-end) and the front-end programmer wrote the dropdown code like this
<div class="drop-wrap drop-wrap-s-4 color-4 list-sort order-drop">
<div class="drop">
<b>Sort by price</b>
<i class="fa fa-angle-down"></i>
<span>
Cheapest
Most Expensive
</span>
</div>
</div>
How do i get the selected value? what event will i use on the javascript side for ajax call?
I tried something ike this
$(".order-drop").onselect(function () {
var order= $("a.order").val();
});
and this
$(".order-drop").onchange(function () {
var order= $("a.order").val();
});
Since it's not a regular dropdown/select element, there won't be any change events.
To get the text of the selected item, add an event handler to the link elements like this...
$(".order-drop .order").on("click", function() {
// here you can get the text of the selected item...
console.log(this.textContent);
});
That will attach the click handler to each of the elements with the class order inside any element with the class order-drop. This may or may not be suitable, depending on what else is on the page. Any other elements that fit that selector will also be targeted by this code, so watch out for that.

Make multiple data 'visible' or 'hidden' using CSS and Javascript

I need your support in selecting a logic. My script pulls few rows from DB and displays on screen. I want to give a feedback form for each data. These feedback forms must be hidden and should be visible on click of a text (Like reply to this) - Pls refer the picture.
I have tried with the help of java script and CSS
<script>
function hideElement()
{
document.getElementById("target").style.display="none";
}
function showElement()
{
document.getElementById("target").style.display="block";
}
</script>
// Data-1 fetched from DB goes here
<a href='#target'>Reply to this post</a>
<span id='target' style='display:none'>
// Feedback form for Data 1 here
</span>
// Data-2 fetched from DB goes here
<a href='#target'>Reply to this post</a>
<span id='target' style='display:none'>
// Feedback form for Data 2 here
</span>
But it works only for the first record, - Javascript finds the first object with the name "target" and sets display property 'none' or 'block'
What logic can I use to generate dynamic ID assigned to each record and make java sript to run for that. Are there any other better logics to do this? (I'm sure ther are)
Element IDs must be unique, but any time you find yourself generating unique IDs for repeating elements there's probably a simpler, more generic way to implement whatever you're doing.
For this type of function you don't need IDs at all, you can use classes and DOM navigation to get from the clicked item to the related span, using a single delegated event handler as follows:
// bind click handler to the document
document.addEventListener("click", function(e) {
// test if the actual clicked item has the class "reply"
if (e.target.className.match(/\breply\b/)) {
e.preventDefault();
// find the related target span
var target = e.target.parentNode.querySelector(".target");
// update its visibility
target.style.display = target.style.display === "none" ? "block" : "none";
}
});
<div> <!-- note added wrapper div -->
Reply to this post
<span class='target' style='display:none'>
Feedback form for Data 1 here
</span>
</div>
<div> <!-- note added wrapper div -->
Reply to this post
<span class='target' style='display:none'>
Feedback form for Data 2 here
</span>
</div>
I've put some comments within the above JS to explain what it's doing, but the important line is this one:
var target = e.target.parentNode.querySelector(".target");
Within the event listener, the e argument is the event object which holds various bits of information about the event being handled. e.target tells which element was clicked. Having already tested that element's class to see if it was one of the "reply" anchors, we then use the .parentNode property to get a reference to the wrapper div that I added to your markup, then from there .querySelector(".target") finds a descendant of the div that has the class target.
As you can see I've modified your html to support the above as follows:
Change the span ids to be classes
Given the anchors class="reply"
Added wrapper div elements for each group, to make the DOM navigation simple and reliable. You could navigate from the anchor to the span using e.target.nextSibling, except then you'd have to add extra code to skip over any text nodes. I find a wrapper element easier to work with. Of course, if your elements are already in some kind of wrappers for other purposes then you can just use the existing wrappers.
Note: it would be good to remove the inline styles, and to show and hide the spans by adding and removing classes rather than directly updating their styles, but that's not really the main issue here so I'll leave that as an exercise for the reader.
http://codepen.io/sheriffderek/pen/BzmAwg
Step 1: ditch those IDs
markup
<ul class="item-list">
<li>
<p>default stuff</p>
<div class="hidden-thing">
hidden stuff
</div>
</li>
<li>
<p>default stuff</p>
<div class="hidden-thing">
hidden stuff
</div>
</li>
<li>
<p>default stuff</p>
<div class="hidden-thing">
hidden stuff
</div>
</li>
</ul>
Step 2: hide the hidden stuff in CSS and not inline
styles
(this is stylus syntax.. but same point)
.item-list
list-style: none
margin: 0
padding: 0
li
background: gray
padding: .5rem
margin-bottom: 1rem
cursor: pointer
.hidden-thing
display: none // hide it
Step 3: get the thing you want to click with jquery or with vanilla JavaScript - attach event handler - use this to note what element the event happens on - with that element... traverse down the DOM and find the thing you want - then use the show method, whichs sets display: block... or fadeIn() or animate() or whatever you like.
JavaScript
$('.item-list li').on('click', function() {
$(this).find('.hidden-thing').show();
});
// or...
$('.item-list li').on('click', function() {
$('.item-list li').find('.hidden-thing').hide();
$(this).find('.hidden-thing').show();
});
If you want only one hidden thing open at a time, you can hide all the items each time first - which is kinda janky, but usual.
BUT... there is a better way to do this, where you add an active class to the whole item. This lets you style things inside it and just generally gives you a larger scope to work with. Here is an example of that. : ) It uses .closest - and passes the event into the click handler to stop the outer click action from bubbling up: http://codepen.io/sheriffderek/pen/oLoqEy

understanding jQuery parent, children and sibling

I am struggling to figure out where I am going with the current show and hide function I am trying to incorporate on my site. I have a drop down menu show and hide function similar to the one currently implemented at Hippodrome Mobile Casino. Which is identical to my HTML. My div class I am noticing with my Jquery when i click the next button .regNext it hides all three .regGroupContent divs. However i want to add and remove the active class which i current have as display:none on my site.
$('.regGroupContent').removeClass('active');
$('.regGroupContent').eq(0).addClass('active');
$('.regNext').click(function () {
var $this = $(this);
$('.regGroupContent').hide().removeClass('active');
$this.parent().children($('.regGroupContent')).show().addClass('active');
});
Html
<div class="vengeForm">
<div class="regGroupContent">
<div class ="fieldset">
<ul class="fieldset">
<li class="editor-next">
</li>
</ul>
</div>
</div>
</div>
This line has a bit of a syntax issue:
$this.parent().children($('.regGroupContent')).show().addClass('active');
In the children selector, you don't need a jQuery object, rather just the class name. Also, your .parent() selector is only going one level up, you need to get to the top of the element tree. Try changing it to:
$this.parents('.vengeForm').children('.regGroupContent').show().addClass('active');

Use JavaScript to change the class of an <li>

I have the following code:
<div id="nav">
<ul>
<li id="tabOne" class="first current">Page One</li>
<li id="tabTwo">Page Two</li>
<li id="tabThree"><a href="./CS3.html" target="SheetView">Page Three</li>
<li id="tabFour">Page Four</li>
<li id="tabFive">Page Five</li>
<li id="tabSix">Page Six</li>
</ul>
This loads the selected page into an iframe named "SheetView." What I need to do is use JavaScript to alter the class when an option that isn't the currently selected on is clicked. I should say that I have the current class already setup in my CSS. I just have no way to trigger it.
I thought adding an onlick event to the <UL> up there and calling onclick="Javascript:changeCurrent();" but there is the problem (four actually):
Is <ul onclick="JavaScript:changeCurrent();> where I need to have the event?
What is the resulting JavaScript to make the change happen?
How can I cause the first option to be set as current by default?
Is there a way to keep the currently selected option from being an active link?
I found a few different examples but I couldn't tailor them to work for me. Any help would be most appreciated.
Since you specified that you wanted a non-jQuery response, here's a function that will toggle appropriately:
function toggleNavSelected(el){
var list = document.getElementById('nav').children[0];
for(var i=0; i<list.children.length; i++){
var cur = list.children[i];
if(el==cur){
cur.classList.add("current");
cur.firstChild.onclick = (function(){
toggleNavSelected(this.parentElement);
return false;
});
} else {
if(cur.classList.contains("current")){
cur.classList.remove("current");
}
cur.firstChild.onclick = (function(){
toggleNavSelected(this.parentElement);
});
}
}
}
Either add an onclick handler to each LI (onclick="toggleNavSelected(this);") or execute the following after the menu has loaded:
var list = document.getElementById('nav').children[0];
for(var i=0; i<list.children.length; i++){
var el = list.children[i];
el.firstChild.onclick = (function(){
toggleNavSelected(this.parentElement);
});
}
Demo: http://jsfiddle.net/bWY7P/2/
(note: The JSFiddle script has a small difference; it adds a return false; to the onclick function so that you can play with it without the links actually following the HREF attribute. Do not use that line in your live code)
Explanation:
The function looks at each LI element within the #nav element.
If that element is the element passed to the function, then it adds the class .current.
Otherwise, it removes the class .current (if present).
The second part binds a function to the onclick event of each a element that calls the toggleNavSelected() function and passes its parent element (the li) as the argument.
1) if you want to change the currently selected class when you click an item, put the onclick into the li item
2) using jquery would be very easy here, all you have to do is import the jquery file with the <script> tag and you're ready! For example, you could do onclick="changeClass(this);" on the <li> tag and in a normal JavaScript file or in a script tag:
function changeClass(this){
$('#nav li').attr("class","");
$(this).attr("class","current");
}
Replace the 'current' with the class name you want to use
3) it should already be set as current
4) use the :visited CSS selector to change what colour followed links look like eg:
a:visited{
color: #000000;
}
First of all you should set the event handler from a separate script, not from an onclick attribute. You don't repeat your code that way and have anything in one place. The HTML is also much cleaner.
Using jQuery it would be as easy as:
var menuLinks = jQuery( '#nav a' );
menuLinks.on( 'click' function() {
menuLinks.removeClass( 'active' );
$( this ).addClass( 'active' );
} );
You could also do that in plain JS, but using some library keeps you out of the trouble of browser incompatibilities.

Categories

Resources