I'm having trouble figuring out how to use session storage for list items. This doesn't seem to be working and because of the styling, I can't use the basic select/option:
<div class="btn-group">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"><span data-bind="label">Day</span><span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu" name="country">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
var item = window.localStorage.getItem('country');
$('ul[name=country]').val(item);
$('ul[name=country]').change(function() {
window.localStorage.setItem('country', $(this).val());
});
fiddle
It is a basic click() event. You should not use change():
$('ul[name=country] li').click(function() {
window.localStorage.setItem('country', $(this).text());
});
Check in the console, using localStorage.getItem("country").
Fiddle: https://jsfiddle.net/5z0nkdjb/
You're trying to use val in a ul tag, and it does not have value property.
Also, you're trying to use a change event on it, and it does not have that event either.
First, you must understand what you're doing there. You've probably copied this Dropdown Picker from anywhere else, and you don't understand what it's doing.
It's simulating a select behavior by using a label inside a button, and anytime a li inside the ul tag is clicked, your code changes the label text to the li's one.
So, firstly, when your page is loaded, you must see if anything is already in your localStorage, and if it is, you must change the label's text to the value saved in the localStorage.
var item = localStorage.getItem('country');
if (item) $('span[data-bind="label"]').text(item);
After that, inside your li's click event, you must save the clicked li's text into the localStorage for persisting purposes later.
// Dropdown picker
$('.dropdown-menu').on('click', 'li', function(e) {
var $target = $(e.currentTarget);
/* the rest of your code */
localStorage.setItem('country', $target.text());
});
I've updated your fiddle with the code working.
Related
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.
I'm new to Javascript so this may be a stupid question, but I'm at a loss. I've been trying to get my dropdown to hide/close when the right list item is selected. I'm using the hover dropdown provided by W3Schools. I've copied the CSS they've provided and my HTML and JS look like this:
<div class="dropdown" id = "menu3">
<button class="dropbtn" id = "menu3btn">Menu 3</button>
<div class="dropdown-content" id = "menu3c">
<ul>
<li><a id="item30">Cheese</a></li>
<li><a id="item31">Pepperoni</a></li>
<li><a id="item32">Sausage</a></li>
</ul>
</div>
</div>
And JS:
$(document).ready(function(){
$('li').click(function(){
if($(this).text() == "Sausage"){
$(this).parent().parent().hide();
}
}
}
The current Javascript is closing the dropdown if the user clicks "Sausage", which is what I want. But when I hover over the menu again, the dropdown doesn't open/show. I've tried changing
$(this).parent().parent().hide();
to
$(this).parent().hide();
and the results are the same.
I've also tried to toggle the dropbtn by replacing the parent().hide() code with:
var btnName = "#"+$(this).parent().parent().parent().attr("id")+"btn";
$(btnName).toggle();
This removed the button and dropdown menu from the screen entirely.
I've also tried forcing the hover to show hidden dropdown-content by adding this method to my JS:
$(".dropdown").hover(function() {
if($(this).attr("id") == "menu3"){
$("#menu3c").show();
}
}
This didn't do anything either (the hidden content stayed hidden).
Any help would be much appreciated.
Instead of $(this).parent().parent().hide();, you can use this to hide the parent
$(this).closest('div').hide();
To show the menu again,
$('#menu3btn').on('click', function() {
$('#menu3c').toggle();
});
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
};
};
I have a problem similar to this . But the solutions there does not work for my issue. And that discussion has been closed for further suggestions.
Unfortunately I can't show my code exactly as it is on jsfiddle. However the issue is something like this. When trying to expand the dropdown inside first panel section, the dropdown hidden behind other elements.
I've spent hours trying different suggestions concerning "stacking context", "position", and "z-index".
I would really appreciate if anyone could point me to any resources that could help.
<div class="btn-group">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"> <span data-bind="label">Select One</span> <span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li>Item 1
</li>
<li>Another item
</li>
<li>This is a longer item that will not fit properly
</li>
</ul>
</div>
You have two options. You can make the container's overflow expand to fit the content by setting 'overflow: auto' to the parent's css.
FIDDLE DEMO
.panel-body { /* parent container of the menu */
overflow:auto;
}
Or you could do something functionally with JavaScript to handle the menu placement. This option is a little bit 'hacky' and would require further improvements. You would need to improve it to handle multiple menus open at once on the same page, and you would need to improve how it selects the menu. You might also want to add scroll support to move the menu with its target element unless that's not an issue. Here's the fiddle:
FIDDLE DEMO
(function() {
// hold onto the drop down menu
var dropdownMenu;
// and when you show it, move it to the body
$(window).on('show.bs.dropdown', function(e) {
// grab the menu
dropdownMenu = $(e.target).find('.dropdown-menu');
// detach it and append it to the body
$('body').append(dropdownMenu.detach());
// grab the new offset position
var eOffset = $(e.target).offset();
// make sure to place it where it would normally go (this could be improved)
dropdownMenu.css({
'display': 'block',
'top': eOffset.top + $(e.target).outerHeight(),
'left': eOffset.left
});
});
// and when you hide it, reattach the drop down, and hide it normally
$(window).on('hide.bs.dropdown', function(e) {
$(e.target).append(dropdownMenu.detach());
dropdownMenu.hide();
});
})();
There is probably a better way to do this, but the concept is to move the menu from the confines of the parent element to the body. When you're relying on the html data-attributes to setup the menu, you'll have trouble doing this, but that is where the second solution I reference becomes useful.
Sadly I would have suggested looking into the 'Via Javascript' options that bootstrap provides, but apparently they don't have the option to set the target append element. It would have been nice to have an option to append the menu on to whichever element you want like most of their other items: Bootstrap Docs
EDIT
As #Andrea Pizzirani mentioned, you could try removing the css for the menu absolute positioning, but I wouldn't recommend it! That will mess up all other instances of the menu unless you add other css to restrict scope of the change. Also, if you want the menu positioned under the button, you'll have to redo CSS that bootstrap already had in place.
Still, if it works, and you're not worried about messing up all other menus, it may be the solution you were looking for. Heres a fiddle demonstrating the solution:
FIDDLE DEMO
dropdown-menu {}
EDIT
I finally found where I originally found this solution. Gotta give credit where credit is due!
Try to remove position: absolute; from:
dropdown-menu {}
and place the menu under the button by css.
Modification of Jonathan's answer above, which was a huge help, but I modified it to place the menu back at it's source row, which allows custom jQuery to function properly (because the menu still exists at its initial parent element hierarchy. My use case was a jQuery DataTable with frozen columns. We had a bootstrap 4 "Action" dropdown-menu embedded in a cell of that table. The menu was appearing behind the hidden columns. This function allowed it be copied and pasted above the fixed columns where users can actually interact with it.
function BringActionMenuToForeground() {
var dropdownMenu;
/// When you show the menu, remove it from its current row and place it right back. This puts it on top of the DOM.
$(window).on('show.bs.dropdown', function (e) {
/// grab the menu
dropdownMenu = $(e.target).find('.dropdown-menu');
/// get the row where the menu appers.
var menuRow = $(dropdownMenu).closest("tr");
/// detach it and append it right back to the row from which it was taken.
$(menuRow).append(dropdownMenu.detach());
/// grab the new offset position
var eOffset = $(e.target).offset();
/// make sure to place it where it would normally go (this could be improved)
dropdownMenu.css({
'display': 'block',
'top': eOffset.top + $(e.target).outerHeight(),
'left': eOffset.left
});
});
/// and when you hide it, reattach the drop down, and hide it normally
$(window).on('hide.bs.dropdown', function (e) {
$(e.target).append(dropdownMenu.detach());
dropdownMenu.hide();
});
}
Add an additional class on your HTML and use the below codepen reference code.
check here: https://codepen.io/qpqinc/pen/yLyPVMJ
<div class="dropdown">
<button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
Dropdown
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
<li>Item 7</li>
<li>Item 8</li>
<li>Item 9</li>
<li>Item 10</li>
</ul>
</div>
$(function() {
//add BT DD show event
$(".dropdown").on("show.bs.dropdown", function() {
var $btnDropDown = $(this).find(".dropdown-toggle");
var $listHolder = $(this).find(".dropdown-menu");
//reset position property for DD container
$(this).css("position", "static");
$listHolder.css({
"top": ($btnDropDown.offset().top + $btnDropDown.outerHeight(true)) + "px",
"left": $btnDropDown.offset().left + "px"
});
$listHolder.data("open", true);
});
//add BT DD hide event
$(".dropdown").on("hidden.bs.dropdown", function() {
var $listHolder = $(this).find(".dropdown-menu");
$listHolder.data("open", false);
});
//add on scroll for table holder
$(".ak-holder").scroll(function() {
var $ddHolder = $(this).find(".dropdown")
var $btnDropDown = $(this).find(".dropdown-toggle");
var $listHolder = $(this).find(".dropdown-menu");
if ($listHolder.data("open")) {
$listHolder.css({
"top": ($btnDropDown.offset().top + $btnDropDown.outerHeight(true)) + "px",
"left": $btnDropDown.offset().left + "px"
});
$ddHolder.toggleClass("open", ($btnDropDown.offset().left > $(this).offset().left))
}
})
});
You need to add only:
.panel.panel-default{
overflow: inherit !important;
}
JSFIDDLE DEMO
I'm working on a menu that is designed using an unordered list, with each list element containing a link to another page. However, I would also like to be able to click on each bullet point to open more subcategories that will also link to other pages.
Essentially, I would like to be able to click once on a link and have it go to the correct page, but I would also like to click on the bullet point and have it expand into the subcategories. I've been researching how to separate the bullet from the content of the li, but it doesn't seem to be working in my case, likely because my li contains a lot of subcategories. Here's an example:
<li id="m2l1" class="child">
Y
<ul id="u11">
<li class="gchild">Y.1</li>
<li class="gchild">Y.2</li>
<li class="gchild">Y.3</li>
<li class="gchild">Y.4</li>
<li class="gchild">Y.5</li>
<li class="gchild">Y.6</li>
<li class="gchild">Y.7</li>
<li class="gchild">Y.8</li>
<li class="gchild">Y.9</li>
</ul>
</li>
Does anyone have any suggestions as to how to separate the bullet from the text in my case?
Here's the link: http://jsfiddle.net/stamblerre/XYp48/17/
Thank you!!!
Your HTML is invalid. You can't have div inside your ul. Moreover, you can greatly simplify your code by moving separate logic for each li into one generic handler.
Something like this:
Demo: http://jsfiddle.net/abhitalks/XYp48/18/
CSS:
ul {
display: none;
overflow: hidden;
}
ul:first-child {
display: block;
}
JS:
$("li").on("click", function () {
$(this).children("ul").slideToggle();
return false;
});
Edit:
I deliberately left out checking of a because clicking the a would navigate to the respective pages (as mentioned in your question), so expand/collapse wouldn't matter.
However, as per your comment if you really want to remove a altogether from the handler, then you can use the event target to handle li without a. Something like this:
Demo 2: http://jsfiddle.net/abhitalks/XYp48/22/
JS:
$("li").on("click", function (e) {
var $t = $(e.target); // get the event target as a jQuery object
if (!$t.is('a')) { // check if the target is not an anchor
$(this).children("ul").slideToggle();
return false;
}
// otherwise if target is anchor, then do nothing
});
Change your list still to hide bullets, then modify your html to :
<li class="gchild">•Y.1</li>
Should do the trick.
<li class="gchild">Y.1</li>
One way that worked for me: remove the bullet with li { list-style-type: none; } then add your own bullets with the character • (alt-8 on a mac). Add that character inside a elements like so:
• X
with the label now outside of the element.
Hope this works for you!