Vertical menu expanding is not working for dynamic content - javascript

I have tried a sample of Vertical menu from CSSmenu site, sample source code working and menu is expanding as per the sample, when i try to add the menu dynamically, those menu's are not expanding even i have verified the final object structure.
Code with dynamic menu:
<body>
<script>
/**
* Comment
*/
function add() {
var list = document.getElementById('list');
var elem=document.createElement('li');
elem.setAttribute('class','last has-sub');
elem.innerHTML="<a href='#'><span>My_Products</span></a>"
+"<ul style='display: none;' >"
+"<li><a href='#'><span>Product 1</span></a></li>"
+"<li><a href='#'><span>Product 2</span></a></li>"
+"<li class='last'><a href='#'><span>Product 3</span></a></li>"
+ "</ul>";
list.appendChild(elem);
}
</script>
<div id='cssmenu'>
<ul id='list'>
<li class='active'><a href='#'><span>Home</span></a></li>
<li class='has-sub'><a href='#'><span>Products</span></a>
<ul>
<li><a href='#'><span>Product 1</span></a></li>
<li><a href='#'><span>Product 2</span></a></li>
<li class='last'><a href='#'><span>Product 3</span></a></li>
</ul>
</li>
<li><a href='#'><span>Contact</span></a></li>
<li class='last has-sub'><a href='#'><span>About</span></a>
<ul>
<li><a href='#'><span>Company</span></a></li>
<li class='last'><a href='#'><span>Contact</span></a></li>
</ul>
</li>
</ul>
</div>
<input type="button" value="Add Menu" onclick="add()">
</body>

script.js in this "library" has line:
$('#cssmenu > ul > li > a').click(function() {
So dynamically created elements will not be handled with this click handler. You can modify script's line, transforming this handler into delegated event handler:
$('#cssmenu').on('click', '#list > li > a', function() {

Related

jQuery to locate an element by Attribute and Replace it's HTML

JS:
$('.translate').on('click', function(){
$("*").each(function() {
$.each(this.attributes, function() {
if (this.name.indexOf('uloc') == 0) {
$(this).parent().html("HELLOOOOOOOO!");
console.log(this.name + ' has the value: ' + this.value);
}
});
});
});
HTML:
<ul>
<li>Report a problem</li>
<li>Privacy Policy</li>
<li>Terms of Service</li>
</ul>
<ul>
<li><a class="translate" locale="fr">Français</a></li>
<li><a class="translate" locale="en">English</a></li>
</ul>
So on click, the text in the found elements should be replaced with Hello.
How can I accomplish this?
You could a simple attribute selector in the first place:
$('.translate').on('click', function() {
$("[uloc]").html("HELLOOOOOOOO!");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>Report a problem</li>
<li>Privacy Policy</li>
<li>Terms of Service</li>
</ul>
<ul>
<li><a class="translate" locale="fr">Français</a></li>
<li><a class="translate" locale="en">English</a></li>
</ul>
We don't need to iterate over all elements with attribute uloc. jQuery will do it for us. The simplest solution can be-
$('.translate').on('click', function() {
$("[uloc]").html("HELLOOOOOOOO!");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>Report a problem</li>
<li>Privacy Policy</li>
<li>Terms of Service</li>
</ul>
<ul>
<li><a class="translate" locale="fr">Français</a></li>
<li><a class="translate" locale="en">English</a></li>
</ul>
The each function has 2 parameters: index and element that you are iterating. You can use that element to modify the html.
https://api.jquery.com/each/
$('.translate').on('click', function(){
$('[uloc]').each(function(index, element) {
$(element).html("HELLOOOOOOOO!");
});
});
The error is simple. When you refer to $(this).parent().html("HELLOOOOOOOO!");, this points to the attribute that you are iterating on. To avoid that, you can keep track of the element from outer loop and use that while accessing the parent element:
$('.translate').on('click', function() {
$("*").each(function() {
// *** Remember the element, to be used later
var element = this;
$.each(this.attributes, function() {
if (this.name.indexOf('uloc') == 0) {
$(element).parent().html("HELLOOOOOOOO!");
console.log(this.name + ' has the value: ' + this.value);
}
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul>
<li>Report a problem</li>
<li>Privacy Policy</li>
<li>Terms of Service</li>
</ul>
<ul>
<li><a class="translate" locale="fr">Français</a></li>
<li><a class="translate " locale="en ">English</a></li>
</ul>
you can use attribute selector of jquery to find all elements having attribute uloc and replace it's text. see below code
$(function(){
$('.translate').on('click', function(){
$("[uloc]").each(function() {
$(this).text("HELLOOOOOOOO!");
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>Report a problem</li>
<li>Privacy Policy</li>
<li>Terms of Service</li>
</ul>
<ul>
<li><a class="translate" locale="fr">Français</a></li>
<li><a class="translate" locale="en">English</a></li>
</ul>

JQuery trouble understanding event order

I am trying to create a Bootstrap dropdown menu with two sub-menus. My problem is that the dropdowns are dynamically created after the document is loaded, and don't respond to how I would normally get them to work.
How I would normally go about it would be
$(document).ready(function(){
addItem(); //adds the first instance of the drop down
$('ul.dropdown-menu [data-toggle=dropdown]').on('click', function(e){
e.stopPropagation();
e.preventDefault();
$(this).siblings().removeClass("open");
$(this).parent().toggleClass("open");
});
});
But this obviously doesn't work for dynamically created content. I saw elsewhere online that this would work for dynamic content;
//still has first instance of dropdown, just later in the doc
$(document).on('click', 'ul.dropdown-menu [data-toggle=dropdown]', function(e){
e.stopPropagation();
e.preventDefault();
$(this).siblings().removeClass("open");
$(this).parent().toggleClass("open");
});
but for the life of me, I can't figure out why this doesn't work. What I'm seeing is that it is adding the open class to the sub-menu, but toggle the parent menu(not stopping propagation?) So, my question is, why doesn't the second one execute as expected, and how can I make it?
List structure for reference:
<div class="dropdown open">
<button id="select0" class="btn new-btn" data-toggle="dropdown" aria-expanded="true">Select Your Item <span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a class="sub" data-toggle="dropdown">Item 1</a>
<ul class="dropdown-menu sub-menu">
<li><a data-def-cost="6">Item 1.1</a></li>
<li><a data-def-cost="8">Item 1.2</a></li>
</ul>
</li>
<li><a class="sub" data-toggle="dropdown">Item 2</a>
<ul class="dropdown-menu sub-menu">
<li><a data-def-cost="5">Item 2.1</a></li>
<li><a data-def-cost="3">Item 2.2</a></li>
</ul>
</li>
<li><a data-plu="xyz" data-def-cost="8.00">Item 3</a></li>
<li><a data-plu="xyz" data-def-cost="8.00">Item 4</a></li>
<li><a data-plu="xyz" data-def-cost="10.00">Item 5</a></li>
<li class="dropdown-header">Other Items</li>
<li><a data-plu="143">Item 6</a></li>
<li><a data-plu="xyz">Item 7</a></li>
<li><a data-plu="xyz">Item 8</a></li>
</ul>
<input type="text" class="hidden" name="input1">
<input type="text" class="hidden" name="otherinput1">
</div>
$(this).siblings() points to an ul element, however, the .open class is supposed to be added to the parent li : http://getbootstrap.com/javascript/#dropdowns-usage.
Via data attributes or JavaScript, the dropdown plugin toggles hidden content (dropdown menus) by toggling the .open class on the parent list item.
Here is a suggestion (inspired by the following code snippet : Multi-Level Dropdowns) :
$(document).ready(function () {
// this variable keeps track of the last open menus
// in order to close them when another link is clicked
// or when the entire dropdown is closed
var open;
$("#my-dropdown").on("hide.bs.dropdown", function () {
if (open) open.removeClass("open");
});
$(".dropdown-submenu > a").on("click", function (e) {
if (open) open.removeClass("open");
open = $(this).parents(".dropdown-submenu");
open.addClass("open");
e.stopPropagation();
e.preventDefault();
});
});
.dropdown-submenu {
position: relative;
}
.dropdown-submenu .dropdown-menu {
top: 0;
left: 100%;
margin-top: -1px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<div class="dropdown" id="my-dropdown">
<button type="button" data-toggle="dropdown">
Dropdown trigger
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li>Action 1</li>
<li>Action 2</li>
<li class="dropdown-submenu">
Submenu 1
<ul class="dropdown-menu">
<li>Action 1.1</li>
<li>Action 1.2</li>
</ul>
</li>
<li class="dropdown-submenu">
Submenu 2
<ul class="dropdown-menu">
<li>Action 2.1</li>
<li>Action 2.2</li>
<li class="dropdown-submenu">
Submenu 2.3
<ul class="dropdown-menu">
<li>Action 2.3.1</li>
<li>Action 2.3.2</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
Unsure as to efficiency of my solution, but I rearranged the order a bit, and forced the parent to stay open
$(document).on('click', 'ul.dropdown-menu [data-toggle=dropdown]', function(e){
$(this).siblings().removeClass("open");
$(this).parent().addClass("open");
$(this).parent().parent().parent().addClass("open");
e.stopPropagation();
e.preventDefault();
});
and this solved my issue
use one of these below lines.
$(this).siblings('.dropdown-menu').removeClass('open');
$(this).next('.dropdown-menu').removeClass('open');

Disable scrollable event on a specified id

I have a responsive navigation on my website. And, this js code is for smooth scrolling within my webpage.
$(function(){$("a[href*=#]:not([href=#])").click(function() {
if(location.pathname.replace(/^\//,"")==this.pathname.replace(/^\//,"")
&&location.hostname==this.hostname){
var target=$(this.hash);
target=target.length?target:$("[name="+this.hash.slice(1)+"]");
if(target.length){
$("html,body").animate({scrollTop:target.offset().top},1000);return false}}})});
When i create a link Scroll to Topwrapper, i can scroll it smoothly to the div as long as the div name is #topWrapper or #whatever. I have also an id name navi in my navigation. I would like to ask that, is there anyway i can disable the id in this js code so that it doesn't scroll when i click on the hamburger icon to open the menu? Thank you!
Hope you understand what i am asking as English is not my primary language. Thank you!
Update:
<nav class="menu" id="navi">
<ul>
<li class="has-sub-menu">About
<ul class="sub-menu">
<li>Our Vision</li>
<li>Our Services</li>
<li>Latest New</li>
<li>Our Blog</li>
</ul>
</li>
<li class="has-sub-menu">Gallery
<ul class="sub-menu">
<li class="has-sub-menu">Kitchen Cabinet
<ul class="sub-menu">
<li>Melamine ABS Kitchen Cabinet</li>
<li>Acrylic Door Kitchen Cabinet</li>
<li>3G Glass Door Kitchen Cabinet</li>
<li>4G Glass Door Kitchen Cabinet</li>
</ul>
</li>
<li class="has-sub-menu">Wardrobe Design
<ul class="sub-menu">
<li>Swing Door Wardrobe</li>
<li>Sliding Door Wardrobe</li>
<li>Walk In Closet</li>
</ul>
</li>
<li>TV Cabinet</li>
<li>Study Table Design</li>
<li>3D Cabinet Design</li>
<li>Others Cabinet Design</li>
</ul>
</li>
<li class="has-sub-menu">Materials
<ul class="sub-menu">
<li class="has-sub-menu">Doors
<ul>
<li>Melamine ABS Door</li>
<li>3G Glass Door</li>
<li>Acrylic Door</li>
<li>4G Glass Door</li>
<li>Membrane Pressed</li>
<li>Multi-Layer Ply Laminated</li>
</ul>
</li>
<li class="has-sub-menu">Carcass
<ul>
<li>Compressed Wood</li>
<li>Blockboard</li>
<li>Solid Wood</li>
<li>Aluminium</li>
</ul>
</li>
<li class="has-sub-menu">Worktop
<ul>
<li>HPL Worktop</li>
<li>Solid Surface</li>
<li>Granite Stone</li>
<li>Quartz Stone</li>
</ul>
</li>
</ul>
</li>
<li class="has-sub-menu">Promotion
<ul class="sub-menu">
<li>Kitchen Cabinet</li>
<li>Wardrobe</li>
<li>Appliances</li>
<li>Extended Promotion</li>
</ul>
</li>
<li class="has-sub-menu">Contact
<ul class="sub-menu">
<li>Contact Information</li>
<li>Enquiry Form</li>
<li>Meet Our Designers</li>
<li>Facebook</li>
<li>Twitter</li>
<li class="share">Whatsapp</li>
</ul>
</li>
</ul>
</nav>
Js Code for navigation:
$(document).ready(function(e){
var t=$("#navi"),a=$(".menu-link"),l=$(".has-sub-menu > a");
a.click(function(e){e.preventDefault(),a.toggleClass("active"),t.toggleClass("active")}),l.click(function(e){e.preventDefault();
var t=$(this);t.toggleClass("active").next("ul").toggleClass("active")}),e.preventDefault()});
Do:
document.getElementById("desired-id-name").addEventListener('click', function(){
return false; // does nothing
});
EDIT 1:
Since you are using jQuery, here is a jQuery version:
$("#desired-id-name").click(function(){
return false;
});
Make sure to add this inside:
$(function(){ ... };
EDIT 2:
$("#desired-id-name").scroll(function(){
return false;
});
Docs: https://api.jquery.com/scroll/

How to refactor this JQuery code so that it follows the DRY principle

See. I have the following html <ul>-<li> lists here.
<ul class="nav">
<li class="active">Home</li>
<li class="dropdown">
About Us<b class="caret"></b>
<ul class="dropdown-menu">
<li>Who we are?</li>
<li>What we stand for?</li>
</ul>
</li>
<li class="dropdown">
Campaigns<b class="caret"></b>
<ul class="dropdown-menu">
<li>Get Involved</li>
</ul>
</li>
<li>News</li>
<li>Donate</li>
</ul>
Then I have the following jquery code
$("#about-us").click(function(){
$("ul.nav").children("li").children("a").css("background-color", "#0E0E0E");
$(this).css("background-color","#47F514");
});
$("#campaigns").click(function(){
$("ul.nav").children("li").children("a").css("background-color", "#0E0E0E");
$(this).css("background-color","#F2720A");
});
$("#news").click(function(){
$("ul.nav").children("li").children("a").css("background-color", "#0E0E0E");
$(this).css("background-color","#0A76F2");
});
$("#donate").click(function(){
$("ul.nav").children("li").children("a").css("background-color", "#0E0E0E");
$(this).css("background-color","#F7A116");
});
I can see that line $("ul.nav").children("li").children("a").css("background-color", "#0E0E0E") is repeated in many lines. So surely I can take this out and put a new function in each click events to make this same calls this many times.
What should I do to refactor this?
You can do it this way :
var colors_array_by_id = { "about-us" : "#47F514", "campaigns" : "#F2720A", "news" : "#0A76F2", "donate" : "#F7A116" };
$("#about-us, #campaigns, #news, #donate").click(function(){
$("ul.nav > li > a").css("background-color", "#0E0E0E");
$(this).css("background-color", colors_array_by_id[$(this).attr('id')]);
});
The only thing that changes is the color depending of the clicked element. So, I created here an associative array containing id-color couples.
Here's how I would do it -
<ul class="nav">
<li class="active">Home</li>
<li class="dropdown">
About Us<b class="caret"></b>
<ul class="dropdown-menu">
<li>Who we are?</li>
<li>What we stand for?</li>
</ul>
</li>
<li class="dropdown">
Campaigns<b class="caret"></b>
<ul class="dropdown-menu">
<li>Get Involved</li>
</ul>
</li>
<li><a href="#" id="news" class="navLinks" data-bgcolor="#0A76F2" >News</a></li>
<li><a href="#" id="donate" class="navLinks" data-bgcolor="#F7A116" >Donate</a></li>
</ul>
I've added a data attribute to the links called data-bgcolor which has the color value. Next I attach a single click handler to all the links.
$("#about-us, #campaigns, #news, #donate").click(function(){
$("ul.nav").children("li").children("a").css("background-color", "#0E0E0E");
$(this).css("background-color", $(this).attr("data-bgcolor"));
});
You could do this,
In css,
.myClass{ background-color: #OEOEOE;}
on load,
var elm = $("ul.nav").children("li").children("a");
and then,
$("#about-us, #campaigns, #news, #donate").click(function(){
$this = $(this);
elm.addClass("myClass");
$this.css("background-color", $this.data("bgcolor"));
});
You can use the .data() instead of .attr().

How do I change the css of a child of $(this)

I have a page of search results, each of which has an icon to add each result to a group (listed on the page in a hidden UL element: display:none;).
Right now it works... but when I click on the icon for one result listing... the UL appears under every single result.
I need it to only show up for the result listing that I am clicking the icon on... not all the listings...
Currently the onload code is this:
$("a.quicklist, a[href=#newgrp]").toggle(
function(){
$("ul.quicklist_menu").css('display','block');
$(this).addClass("current");
},
function(){
$("ul.quicklist_menu").css('display','none');
$(this).removeClass("current");
});
I tried to change it to this:
$("a.quicklist, a[href=#newgrp]").toggle(
function(){
$(this).children("ul.quicklist_menu").css('display','block');
$(this).addClass("current");
},
function(){
$(this).children("ul.quicklist_menu").css('display','none');
$(this).removeClass("current");
});
But, yeh.. the icon is highlighted as "current" or active, but the UL does not appear...
Any help would be greatly appreciated.
OOPs. Sorry! Here is the HTML:
<li class='vcard'>
<a href='profile.php?id=1288'><img class='user-photo' src='profile_images/sq_avatar.png' alt='Paul Dietzel' /></a>
<div class='user-info'>
<a class='fn url name' href='profile.php?id=1288'>Paul Dietzel</a>
<ul class='attributes'>
<li class='adr'><span class='locality'>Los Angeles</span>, <abbr class='region' title='California'>CA</abbr></li>
</ul>
</div>
<ul class='options'>
<li><a class='view-profile' href='profile.php?id=1288'>View profile</a></li>
<li><abbr title="Add/Remove Favorite"><button class="favorite ICON" id="1288">Remove Favorite</button></abbr></li>
<li><a class='add-to-group' href='#newgrp'>Add to group</a></li>
<ul class="quicklist_menu"><li><a href='#addgrp' id='1147' rel='1988'>Test 3</a></li>
<li><a href='#addgrp' id='1147' rel='1989'>Test 4</a></li>
<li><a href='#addgrp' id='1147' rel='1990'>Test 5</a></li>
<li><a href='#addgrp' id='1147' rel='1991'>Test 7</a></li>
<li><a href='#addgrp' id='1147' rel='1129'>Lou Herthum Acting Class</a></li>
<li><a href='#addgrp' id='1147' rel='1967'>test group</a></li>
<li class="mgrp">Manage Groups »</li>
</ul>
</ul>
</li>
You need to correct your markup by moving that <ul> to be a sibling of the anchor, not outside the <li></li> but inside (<ul> can't be a child of a <ul>, it's invalid HTML). Like this:
<ul class='options'>
<li><a class='view-profile' href='profile.php?id=1288'>View profile</a></li>
<li><abbr title="Add/Remove Favorite"><button class="favorite ICON" id="1288">Remove Favorite</button></abbr></li>
<li><a class='add-to-group' href='#newgrp'>Add to group</a>
<ul class="quicklist_menu">
<li><a href='#addgrp' id='1147' rel='1988'>Test 3</a></li>
<li><a href='#addgrp' id='1147' rel='1989'>Test 4</a></li>
<li><a href='#addgrp' id='1147' rel='1990'>Test 5</a></li>
<li><a href='#addgrp' id='1147' rel='1991'>Test 7</a></li>
<li><a href='#addgrp' id='1147' rel='1129'>Lou Herthum Acting Class</a></li>
<li><a href='#addgrp' id='1147' rel='1967'>test group</a></li>
<li class="mgrp">Manage Groups »</li>
</ul>
</li>
</ul>
Then you can use .next() like this:
$("a.quicklist, a[href=#newgrp]").toggle(
function(){
$(this).addClass("current").next("ul.quicklist_menu").show();
},
function(){
$(this).removeClass("current").next("ul.quicklist_menu").hide();
});
This uses the .show() and .hide() shortcuts to apply the display as well. Alternatively, you can use .click() to toggle using .toggleClass() and .toggle(), like this:
$("a.quicklist, a[href=#newgrp]").click(function() {
$(this).toggleClass("current").next("ul.quicklist_menu").toggle();
});
use .closest() and .next()
$("a.quicklist, a[href=#newgrp]").toggle(
function(){
$(this).closest('li').next("ul.quicklist_menu").css('display','block');
$(this).addClass("current");
},
function(){
$(this).closest('li').next("ul.quicklist_menu").css('display','none');
$(this).removeClass("current");
});
or you may also try like this,
$("a.quicklist, a[href=#newgrp]").toggle(
function(){
$(this).addClass("current")
.closest('ul.options')
.children("ul.quicklist_menu")
.css('display','block');
},
function(){
$(this).removeClass("current")
.closest('ul.options')
.children("ul.quicklist_menu")
.css('display','none');
});

Categories

Resources