Dropdown doesn't work on newly added elements - javascript

I have multiple dl elements on a page. At the end of each one I have a dd tag acting as a dropdown which includes options for the element (like edit, delete, etc.)
Here's the jQuery for the dropdown:
$('dd.optiuni').mouseover(function() {
$(this).find('ul').show();
});
$('dd.optiuni').mouseout(function() {
$('dd.optiuni ul').hide();
});
Now before the dl tags I have an input and a submit button to add new dls and use jQuery to add them without reloading the page. The problem is that after the new element is added, the dd at the end doesn't seem to work.
How can I make my previous code recognize that new elements have been added to the page?
$(function() { // ie7 z-index fix
var zIndexNumber = 1000;
$('dl').each(function() {
$(this).css('zIndex', zIndexNumber);
zIndexNumber -= 10;
});
});

Use .live or .delegate:
$('dd.optiuni').live("mouseover", function() {
$(this).find('ul').show();
});
$('dd.optiuni').live("mouseout", function() {
$('dd.optiuni ul').hide();
});

Related

Remove transparency on menu drop down Javascript

I've been trying to implement a feature that removes the transparency of the dropdown menu on my website so that it is actually readable for visitors.
The code I am currently using, which removes transparency on scroll but not on drop down is:
$(document).ready(function(){
var stoptransparency = 100; // when to stop the transparent menu
var lastScrollTop = 0, delta = 5;
$(this).scrollTop(0);
$(window).on('scroll load resize', function() {
var position = $(this).scrollTop();
if(position > stoptransparency) {
$('#transmenu').removeClass('transparency');
} else {
$('#transmenu').addClass('transparency');
}
lastScrollTop = position;
});
$('#transmenu .dropdown').on('show.bs.dropdown', function() {
$(this).find('.dropdown-menu').first().stop(true, true).slideDown(300);
});
$('#transmenu .dropdown').on('hide.bs.dropdown', function() {
$(this).find('.dropdown-menu').first().stop(true, true).slideUp(300);
});
});
I tried changing it to this (and variations of this) but can't seem to get it to work:
$(document).ready(function(){
var stoptransparency = 100; // when to stop the transparent menu
var lastScrollTop = 0, delta = 5;
$(this).scrollTop(0);
$(window).on('scroll load resize', function() {
var position = $(this).scrollTop();
if(position > stoptransparency) {
$('#transmenu').removeClass('transparency');
} else {
$('#transmenu').addClass('transparency');
}
lastScrollTop = position;
});
$('#transmenu .dropdown').on('show.bs.dropdown', function() {
$(this).find('.dropdown-menu').first().stop(true, true).slideDown(300);
$('#transmenu').removeClass('transparency');
});
$('#transmenu .dropdown').on('hide.bs.dropdown', function() {
$(this).find('.dropdown-menu').first().stop(true, true).slideUp(300);
$('#transmenu').addClass('transparency');
});
});
Any help would be greatly appreciated!
Thanks!
Without the html that this is hooking into it's a bit difficult to answer your question.
But given the fact that scrolling gets the job done, the only element I can see that could be preventing the functionality you want is that your selector to add show event handler is either selecting nothing in particular or an element in the DOM that is not the bootstrap dropdown element that triggers 'show.bs.dropdown', which is my reasoning for the first statement.
You can try the following debug code to verify:
// Should log to console with 'selected' if selector works alternatively 'not selected'
console.log($('#transmenu .dropdown').length > 0 ? 'selected' : 'not selected');
// Log to console when show event triggered
$('#transmenu .dropdown').on('show.bs.dropdown', function() {
console.log('triggered');
});
Hope that helps you find a solution. Happy coding!
see the documentation at http://api.jquery.com/on/ and it should become obvious why your fancy named events are never being triggered (without defining any event namespace in the first place).
$('#transmenu .dropdown')
.on('show', function() {})
.on('hide', function() {});
the DOM selector also might be #transmenu.dropdown instead of #transmenu .dropdown (depending if id and class attributes are present on the DOM node to select - or if one selects the parent node by id and there is/are nested node/s with a class attribute present).

Closing nested accordion closes everything

I have a problem with my nested accordions.
I have been trying to figure out how to nest my accordions but in a sense that I dont need to write any extra jquery codes for each specific one I add.
I made a jsfiddle as an example... https://jsfiddle.net/L2bwmgL8/
and the code for the accordion looks like this:
$(document).ready(function() {
function close_accordion_section() {
$('.accordion .accordion-section-title').removeClass('active');
$('.accordion .accordion-section-content').slideUp(1000).removeClass('open');
}
$('.accordion-section-title').click(function(e) {
// Grab current anchor value
var currentAttrValue = $(this).closest('.accordion-section-title');
//console.log(currentAttrValue);
if (currentAttrValue.hasClass('active')) {
close_accordion_section();
} else {
close_accordion_section();
// Add active class to section title
currentAttrValue.addClass('active');
// Open up the hidden content panel
$('.accordion ' + currentAttrValue.attr('href')).slideDown(1000).addClass('open');
setTimeout(function() {
$('html, body').animate({
scrollTop: $(currentAttrValue.attr('href')).offset().top
}, 1000);
}, 1001);
//console.log((currentAttrValue.attr('href')));
}
e.preventDefault();
});
});
This way it works fine when I dont have them nested. However, when they are nested as in the example, under the first accordion (ignore the broken images).
Then when I click on the specific accordion to close, everything inside that accordion closes, including the parent one. Or, maybe I think just the parent closes.
Now, I tried, maybe passing the currentAttrValue inside the close_accordion_section() function like close_accordion_section(currentAttrValue) and changing the close_acordion_section to:
function close_accordion_section() {
$(this).closest('.accordion .accordion-section-title').removeClass('active');
$(this).closest('.accordion .accordion-section-content').slideUp(1000).removeClass('open');
}
But then everything opens up nicely, but I cant close any of the accordions anymore.
Any help and explanation would be appriciated, I am still learning the ropes so to speak.
I would simplify it, and then just target the siblings of the current accordion so as to not affect the parent accordion of nested accordions etc.
$(document).ready(function() {
$('.accordion-section-title').on('click', function(e) {
e.preventDefault();
var self = $(this).toggleClass('active');
var section = self.closest('.accordion-section');
var siblings = section.siblings('.accordion-section');
siblings.find('.accordion-section-content').slideUp(1000).removeClass('open').end()
.find('.accordion-section-title').removeClass('active');
$('.accordion ' + self.attr('href')).slideToggle(1000).toggleClass('open')
.find('.accordion-section-title.active')
.trigger('click');
if (self.hasClass('active')) {
setTimeout(function() {
$('html, body').animate({
scrollTop: $(self.attr('href')).offset().top
}, 1000);
}, 1001);
}
});
});
FIDDLE
The issue is in your if else statement:
you need to cut one of the calls to close_accordion_section():
I have a problem with my nested accordions. I have been trying to figure out how to nest my accordions but in a sense that I dont need to write any extra jquery codes for each specific one I add.
I made a jsfiddle as an example... https://jsfiddle.net/L2bwmgL8/
and the code for the accordion looks like this:
$(document).ready(function() {
function close_accordion_section() {
$('.accordion .accordion-section-title').removeClass('active');
$('.accordion .accordion-section-content').slideUp(1000).removeClass('open');
}
$('.accordion-section-title').click(function(e) {
// Grab current anchor value
var currentAttrValue = $(this).closest('.accordion-section-title');
//console.log(currentAttrValue);
if (currentAttrValue.hasClass('active')) {
close_accordion_section();
} else {
//CUT THIS
// Add active class to section title
currentAttrValue.addClass('active');
// Open up the hidden content panel
$('.accordion ' + currentAttrValue.attr('href')).slideDown(1000).addClass('open');
setTimeout(function() {
$('html, body').animate({
scrollTop: $(currentAttrValue.attr('href')).offset().top
}, 1000);
}, 1001);
//console.log((currentAttrValue.attr('href')));
}
e.preventDefault();
});
});
fiddle: https://jsfiddle.net/kjyqmzuh/

Auto clicking on page load quicksand jquery

I am using quicksand jquery and i have searched for solutions and none work. I am trying to auto-click a category when the page loads to filter what I want to filter.
Here is the links on the page that allow users to click and filter
<li>Everything</li>
<li>cat1</li>
<li>cat2</li>
<li>cat3</li>
<li>cat4</li>
when the page loads, it show ALL items and then the user can select the category to filter by. i want to auto click one, and am looking for the function to generate the click.
here is what i have tried with no solution:
<script type="text/javascript">
$(document).ready(function() {
$(".filter li a.cat2").trigger('click');
});
</script>
and
<script type="text/javascript">
$(document).ready(function() {
$(".filter li a.cat2").trigger('click');
});
</script>
and
<script>
$(function() {
// It would be better to create a function for this, but
// to avoid code duplication the click() event is triggered/reused
$('.filteroptions li a cat2').click();
});
</script>
Here is the js file it operates from and why i chose to remove "filteroptions" and try "filter" as was suggested in other posts. as mine shows ".filter li a" not filteroptions li a
// DOMContentLoaded
$(function () {
// bind radiobuttons in the form
var $filterType = $('.filter li a');
// get the first collection
var $applications = $('#list');
// clone applications to get a second collection
var $data = $applications.clone();
// attempt to call Quicksand on every form change
$filterType.click(function (e) {
$('.filter li a').removeClass('selected');
$(this).addClass('selected');
if ($(this).attr('id') == 'all') {
var $filteredData = $data.find('li');
} else {
var $filteredData = $data.find('li[class=' + $(this).attr('id') + ']');
}
// finally, call quicksand
$applications.quicksand($filteredData, {
duration: 800,
easing: 'easeInOutQuad',
attribute: 'id'
}, function () {
$("a[data-rel^='prettyPhoto']").prettyPhoto({ animationSpeed: 'slow', social_tools: false, slideshow: 2000 });
});
});
});
And here are other posts that you may say are the same, but i tried them and they do not work. They are using an older type of quicksand.
JQuery Quicksand: Link directly to pre-filtered Quicksand from another page
First open limited item not all in jQuery Quicksand?
You are using id on not class so change your click tigger to
$(".filter li #cat2").trigger('click');

JavaScript tabs works only when an individual tab is present

I have created a simple tabs widget, here is a working jsfiddle: http://jsfiddle.net/G3eRn/1/
When I add another Tabs widget "as you will see in the example" in the same page, everything get missed up! I really don't know how to describe it... after looking into it and trying to debug it, I have concluded that it is the JavaScript that needs to be looked at, so I have researched, but didn't really find an answer that would fix it. However, I found that using .each might fix it? so I did try it but didn't work - maybe I used it wrong.
What I am doing wrong?
Here is the JS:
//Tabs Navigation
$('.tabs .tabs-menu a:eq(0)').addClass('active');
$('.tabs .tabs-sections .tabs-section:not(:first-child)').hide();
$('.tabs .tabs-menu a').on('click', function() {
$('.tabs-menu a').removeClass('active');
$(this).addClass('active');
$('.tabs .tabs-sections > .tabs-section:eq(' + $(this).index() + ')').show().siblings().hide();
});
You have to make sure only the current tab group is being affected (using .each):
http://jsfiddle.net/G3eRn/2/
//Tabs Navigation
$('.tabs').each(function(){
var $tabs = $(this);
$tabs.find('.tabs-menu a:eq(0)').addClass('active');
$tabs.find('.tabs-sections .tabs-section:not(:first-child)').hide();
$tabs.find('.tabs-menu a').on('click', function () {
$tabs.find('.tabs-menu a').removeClass('active');
$(this).addClass('active');
$tabs.find('.tabs-sections > .tabs-section:eq(' + $(this).index() + ')').show().siblings().hide();
});
});
And here's a version that's a little more performant:
http://jsfiddle.net/G3eRn/7/
//Tabs Navigation
$('.tabs').each(function(){
var $tabs = $(this);
$tabs.find('.tabs-sections .tabs-section:not(:first-child)').hide().end()
.find('.tabs-menu a').on('click', function () {
$tabs.find('.tabs-menu a').removeClass('active').end()
.find('.tabs-sections > .tabs-section:eq(' + $(this).index() + ')').show().siblings().hide();
$(this).addClass('active');
}).eq(0).addClass('active');
});
The second example uses end() which "undoes" the last selector.
So for example
$('.el').find('div').end().addClass('test')
would add the class "test" to the .el element instead of all div's inside it.
In your "click" handler, you have to make sure that you're applying changes only to the relevant group of tabs. As your code is currently written, the handler code will affect all the matching tab groups on the page.
You can use jQuery DOM navigation methods to do it:
$('.tabs .tabs-menu a:eq(0)').addClass('active');
$('.tabs .tabs-sections .tabs-section:not(:first-child)').hide();
$('.tabs .tabs-menu a').on('click', function () {
// find the current menu group and deactivate all tab labels
$(this).closest('.tabs-menu').find('a').removeClass('active');
// activate this tab
$(this).addClass('active');
// find the tab section corresponding to this tab menu
$(this).closest('.tabs').find('.tabs-sections > .tabs-section:eq(' + $(this).index() + ')').show().siblings().hide();
});
The .closest() method walks up the DOM looking for a match. From that point, .find() looks down the DOM in that isolated subtree.
Here's your fiddle, updated.
Personally I'd use a delegated handler setup so that tab groups could be added dynamically without needing to re-run the code:
$('body').on('click', '.tabs-menu a', function() {
// as above
});
You need to apply the functions to every .tabs element.
$('.tabs').each(function() {
var $tabs = $(this);
$('.tabs-menu a:eq(0)', $tabs).addClass('active');
$('.tabs-sections .tabs-section:not(:first-child)', $tabs).hide();
$('.tabs-menu a', $tabs).on('click', function() {
$('.tabs-menu a', $tabs).removeClass('active');
$(this).addClass('active');
$('.tabs-sections > .tabs-section:eq(' + $(this).index() + ')', $tabs).show().siblings().hide();
});
});
The syntax jQuery( 'selector', node ) selects child elements only inside the given HTML element node. In this case an element with the class .tabs. This is similar to do jQuery( node ).find( 'selector' ).
Using $ is just a way for me to always know, which variable is a jQuery object. For example: var $this = jQuery( this );.
If you want more performance in your script store selected node in a variable (e.g. .tabs-menu a in your code). You may even querySelector to get the elements via plain JS instead of jQuery. The jQuery each on the other hand is very comfortable.
An example mixup of different methods:
$('.tabs').each(function() {
var tabs = this,
links = this.querySelectorAll( '.tabs-menu a' );
/* passing a DOMNodeList to jQuery and filter it */
$(links).filter(':eq(0)', tabs).addClass('active');
$('.tabs-sections .tabs-section:not(:first-child)', tabs).hide();
/* setup event handler */
/* without jQuery, one need to itererate over the list of elements */
for( var i = links.length; i--; ) {
var currentLink = links[i];
currentLink.addEventListener('click', function() {
var currentTab = this;
/* jQuery does the loop internally */
$(links).removeClass('active');
currentTab.classList.add('active');
$('.tabs-sections > .tabs-section:eq(' + $(currentTab).index() + ')', tabs).show().siblings().hide();
}, false);
}
});
For documentation and browser support see here:
https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.addEventListener
https://developer.mozilla.org/en-US/docs/Web/API/Document.querySelector
https://developer.mozilla.org/en-US/docs/Web/API/Document.querySelectorAll
https://developer.mozilla.org/en-US/docs/Web/API/Element.classList
There is a JS ployfill for nearly any modern feature:
https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-browser-Polyfills

Remove dynamically generated div with jquery

I would like to add/remove a new div when the corresponding checkbox is checked/unchecked with jQuery. Here's my attempt:
<script type="text/javascript">
$(function() {
$("#form1 :checkbox#checkbox1").click(function() {
var d = document.createElement('div');
if ($(this).is(":checked")) {
$(d).addClass("newdiv")
.html("This is a new div")
.appendTo($("#mydiv"))
.hide()
.fadeIn(1000);
}
else {
//$(".newdiv").fadeOut(1000);
$(d).fadeOut(1000);
}
});
});
</script>
The fadeIn process comes out smoothly. But when I tried to fadeOut $(d) using the same methodology, it didn't work: the new generated div remained on the page. I did some research and get a work around, with $(".newdiv").fadeOut(1000); (commented in the code above), but that's not the best solution for me I think. And also I really want to know why my first attempt didn't work. Any suggestions? Thanks.
There are few changes you can make
1. No need for the selector #form1 :checkbox#checkbox1 since you have an id for the checkbox, you can just use #checkbox1
2. Create the div using jQuery instead of using createElement $('<div/>')
3. After fading out the div you need to remove it from the dom
$(function() {
$("#checkbox1").click(function() {
if ($(this).is(":checked")) {
$('<div/>').addClass("newdiv")
.html("This is a new div")
.appendTo($("#mydiv"))
.hide()
.fadeIn(1000);
}
else {
$('#mydiv .newdiv').fadeOut(function(){
$(this).remove()
})
}
});
});
Demo: Fiddle
Another solution is to have a static div which will be shown and hidden
$(function() {
var div = $('<div/>').addClass("newdiv")
.html("This is a new div")
.appendTo($("#mydiv"))
.hide();
$("#checkbox1").click(function() {
if ($(this).is(":checked")) {
div.fadeIn(1000);
} else {
div.fadeOut(1000)
}
});
});
Demo: Fiddle
jsFiddle Demo
Every time your click handler runs, you're creating a new variable d with a new element. Instead, do that before the click handler, so each instance will reference the same element. I have included other optional improvements below.
A change event is more appropriate for checkboxes. Also, notice I made your selector just #checkbox1, since that is already unambiguous and maximally specific.
To get a better visual effect, don't add the element, hide it, then fade it in. In most browsers that will show the element flicker before it appears. Instead, use a class to hide it with css: .hidden {display: none;}. You can also use fadeToggle to toggle the visibility, instead of doing if/else. clearQueue removes extra events for multiple clicks during a transition, and makes transitions appear smoother.
Finally, use jQuery to create the element:
$(function () {
var $d = $('<div>', {
"class": "hidden",
text: "This is a new div"
}).appendTo("#mydiv");
$("#checkbox1").change(function () {
$d.clearQueue()
.stop()
.fadeToggle(1000);
});
});
You better make d a jQuery object.
<script type="text/javascript">
$(function() {
$("#checkbox1").click(function() {
var d = $('<div class="newdiv"></div>');
if ($(this).is(":checked")) {
d.html("This is a new div")
.appendTo($("#mydiv"))
.hide()
.fadeIn(1000);
}
else {
d.fadeOut(1000);
}
});
});
</script>

Categories