I have seen many scripts for accordion on the internet, but haven't found anything which meets my needs. I want to make a plugin for accordion just like that which Facebook uses. It should work like this:
Click to open and close.
Add style class while open.
Close upon an outside click. It should not close when click event is inside the accordion box.
Is there any way to achieve this? Please help if you know. I am new to jQuery...
Thanks in advance.
No need for a plug-in when 15 lines of code will solve it: it's about changing the order of the click events that trigger on a specific DOM element and on the window using setTimeout.
var ShowingAccordion = false;
$(document).ready(function () {
$('.MyAccordionOpener').click(function () {
if ($(this).next('.MyAccordion').is(':visible') === false) {
ShowingAccordion = false;
$('.MyAccordion').hide(500);
$(this).next('.MyAccordion').addClass('SomeClass');
$(this).next('.MyAccordion').show(500);
setTimeout(function () { ShowingAccordion = true; }, 1);
}
});
$('.MyAccordion').click(function () {
ShowingAccordion = false;
//this is the line that solves your problem
setTimeout(function () { ShowingAccordion = true; }, 1);
});
$(document).click(function () {
if (ShowingAccordion === true) {
$('.MyAccordion').hide(500);
ShowingAccordion = false;
}
});
});
And here's the demo
If it does what you need then you can accept the answer and happy coding!
Related
I am facing a weird issue and tried to implement 3 solutions but it didn't worked out for me.
The problem is with the default functionality of kendo dropdown collapsing on outer page scroll. I want to prevent the collapsing and did some research.
I have got a solution here to prevent this but this is working fine under the Preview section shown there but the same is not working under Dojo (the upper right link) and in the real project.
There is no difference I can see which prevents the collapsing of Dropdown in Preview and not in Dojo.
Please, help me resolving the same as I am a newbie in Kendo.
I believe that you need to handle the close event of the widget in order to control this behavior.
Here is an example:
<input id="dropdownlist" />
<script>
$("#dropdownlist").kendoDropDownList({
dataSource: [ "text1", "text2" ],
close: _myClose.bind(this)
});
var _myClose = function (e) {
var wish = true;
var element = e.sender;
if (wish) {
e.preventDefault();
}
};
</script>
I bind this so that you can have the advantage of your class attributes. You can remove it if you want. The kendo widget instance is available under the e.sender object.
Here is the link to the Docs.
Hope it helps.
$(".k-list-container").each(function () {
var elementId = this.id.split("-")[0];
var widget = $("#" + elementId).data("kendoDropDownList");
if (widget) {
widget.ul.parent().on("wheel", function (e) {
var container = this;
if ((container.scrollTop == 0 && e.originalEvent.deltaY < 0) ||
(container.scrollTop == container.scrollHeight - container.offsetHeight && e.originalEvent.deltaY > 0)) {
e.preventDefault();
e.stopPropagation();
}
});
}
});
I've found this simple snippet to reliably disable page scrolling as long as a kendo dropdownlist is open and the mouse is hovered over the list options.
// Fix annoyance where entire page scrolls when you scroll to the bottom of a dropdown
$(document).bind('mousewheel DOMMouseScroll', function (e) {
var kendoDropdownBoxes = $('.k-list-container[style*="display: block"]');
if (kendoDropdownBoxes.length > 0 && kendoDropdownBoxes.is(':hover')) {
$("body").css("overflow", "hidden");
} else {
$("body").css("overflow", "auto");
}
});
I have an handler on clicking an element. It is getting stuck in an infinite loop. How can I turn off the listener for the 2nd click in this code... so that it doesn't keep repeating.
I'm trying to automatically close the toggle after 4.5 seconds. But the close click triggers another click... and so on...
$(document).ready(function(){
$(".navbar-toggle").click(function() {
setTimeout(function () {
$(".navbar-toggle").click();
}, 4500);
});
});
Add a 'flag' variable to your code
var has_clicked = false;
$(document).ready(function(){
$(".navbar-toggle").click(function() {
if(!has_clicked){
setTimeout(function () {
has_clicked = true;
$(".navbar-toggle").click();
}, 4500);
}
});
});
$(function(){
function callback2(){
$("#test").one("click", callback1);
}
function callback1(){
console.log('hi');
setTimeout(callback2, 4500);
}
$("#test").one("click", callback1);
});
jsFiddle Demo
Is this similar to what you want?
Attach the click event which execute only once, using .one(),
do whatever you want in the callback function, and attach it again after 4.5 seconds. If you cannot even modify your code to this, please let me know, I will try to think another work around
This is what I am going with for now though I believe I will use shole's approach when I get some more time... for now this is working well.
var is_open = false;
$(document).ready(function(){
$(".navbar-toggle").click(function() {
if(!is_open){
setTimeout(function () {
is_open = true;
$(".navbar-toggle").click();
is_open = false;
}, 3500);
}
});
});
I made a simple plunkr here http://plnkr.co/edit/zNb65ErYH5HXgAQPOSM0?p=preview
I created a little datepicker I would like this to close itself when you focus out of it (focusout of datepicker) if I put blur on input I'm unable to use the datepicker, if I put focusout event on datepicker it doesn't works
I also tried:
angular.element(theCalendar).bind('blur', function () {
$scope.hideCalendar();
});
but it doesn't work.
Any clue?
this is because you are removing the item before you get a chance to do anything, here is a working example:
http://plnkr.co/edit/mDfV9NLAQCP4l7wHdlfi?p=preview
just add a timeout:
thisInput.bind('blur', function () {
$timeout(function(){
$scope.hideCalendar();
}, 200);
});
have you considered using existing datepickers? like angularUI or angular-strap: http://mgcrea.github.io/angular-strap/##datepickers
Update:
Not a complete solution, but should get you quite closer:
angular.element($document[0].body).bind('click', function(e){
console.log(angular.element(e.target), e.target.nodeName)
var classNamed = angular.element(e.target).attr('class');
var inThing = (classNamed.indexOf('datepicker-calendar') > -1);
if (inThing || e.target.nodeName === "INPUT") {
console.log('in');
} else {
console.log('out');
$timeout(function(){
$scope.hideCalendar();
}, 200);
}
});
http://plnkr.co/edit/EbQl5xsCnG837rAEhBZh?p=preview
What you want to do then is to listen for a click on the page, and if the click is outside of the calendar, then close it, otherwise do nothing. The above only takes into account that you are clicking on something that has a class name which includes datepicker-calendar, you will need to adjust it so that clicking within the calendar doesn't close it as well.
How about closing on mouseout?
You need to cancel the close if you move to another div in the calendar though:
//get the calendar as element
theCalendar = element[0].children[1];
// hide the calendar on mouseout
var closeCalendarTimeout = null;
angular.element(theCalendar).bind('mouseout', function () {
if ( closeCalendarTimeout !== null )
$timeout.cancel(closeCalendarTimeout);
closeCalendarTimeout = $timeout(function () {
$scope.hideCalendar();
},250)
});
angular.element(theCalendar).bind('mouseover', function () {
if ( closeCalendarTimeout === null ) return
$timeout.cancel(closeCalendarTimeout);
closeCalendarTimeout = null;
});
EDIT
Adding a tabindex attribute to a div causes it to fire focus and blur events.
, htmlTemplate = '<div class="datepicker-calendar" tabindex="0">' +
angular.element(theCalendar).bind('blur', function () {
$scope.hideCalendar();
});
So, i know it probably is not the best practice or the best way to do this, but at the end i fixed and got what i need using this:
thisInput.bind('focus click', function bindingFunction() {
isMouseOnInput = true;
$scope.showCalendar();
angular.element(theCalendar).triggerHandler('focus');
});
thisInput.bind('blur focusout', function bindingFunction() {
isMouseOnInput = false;
});
angular.element(theCalendar).bind('mouseenter', function () {
isMouseOn = true;
});
angular.element(theCalendar).bind('mouseleave', function () {
isMouseOn = false;
});
angular.element($window).bind('click', function () {
if (!isMouseOn && !isMouseOnInput) {
$scope.hideCalendar();
}
});
I setted up some boolean vars to check where mouse is when you click the page and it works like a charm if you have some better solution that works , please let me know, but this actually fixed all.
I accept this as the answer but i thank all the guys on this page!
I have a basic JQuery script that changes a few divs when you click - thus showing them - via toggle.
<script type="text/javascript">
$('#content_display').click(function() {
$(this).toggleClass('selected');
$('#content_display_selector_container').toggle();
});
</script>
However - to call the even you need to click only on the first main div with the ID of "content_display".
My question is this: how can I hide these changes using JQuery if the user also clicks on BODY - i.e. if you click away, the divs go back to their original hidden state?
Thanks for helping a JQuery clutz!
Something like this should work:
$('body').click(function(e) {
if (!$(e.target).is('#content_display')) {
$('#content_display').removeClass('selected');
$('content_display_selector_container').hide();
}
});
Hey - found a way to do this - does anyone think there's a better way?
Here's the result:
<script type="text/javascript">
var mousetrap = false;
$('body').click(function() {
if (mousetrap == false) {
$('#content_display').removeClass('selected');
$('#content_display_selector_container').hide();
}
});
$('#content_display').hover(function() {
mousetrap = true;
},function(){
mousetrap = false;
});
$('#content_display').click(function() {
$(this).toggleClass('selected');
$('#content_display_selector_container').toggle();
});
</script>
I have a small jQuery script:
$('.field').blur(function() {
$(this).next().children().hide();
});
The children that is hidden contains some links. This makes it impossible to click the links (because they get hidden). What is an appropriate solution to this?
This is as close as I have got:
$('.field').blur(function() {
$('*').not('.adress').click(function(e) {
foo = $(this).data('events').click;
if(foo.length <= 1) {
// $(this).next('.spacer').children().removeClass("visible");
}
$(this).unbind(e);
});
});
The uncommented line is suppose to refer to the field that is blurred, but it doesn't seem to work. Any suggestions?
You can give it a slight delay, like this:
$('.field').blur(function() {
var kids = $(this).next().children();
setTimeout(function() { kids.hide(); }, 10);
});
This gives you time to click before those child links go away.
This is how I ended up doing it:
var curFocus;
$(document).delegate('*','mousedown', function(){
if ((this != curFocus) && // don't bother if this was the previous active element
($(curFocus).is('.field')) && // if it was a .field that was blurred
!($(this).is('.adress'))
) {
$('.' + $(curFocus).attr("id")).removeClass("visible"); // take action based on the blurred element
}
curFocus = this; // log the newly focussed element for the next event
});
I believe you can use .not('a') in this situation:
$('.field').not('a').blur(function() {
$(this).next().children().hide();
});
This isn't tested, so I am not sure if this will work or not.