I use the jQuery to hide and show a div.
function bindIconClick() {
$('span.scroIcon').click(function(event) {
var eventIcon = $(event.target);
var contentPanel = eventIcon.parents('.panelTitle').next();
if (contentPanel.is(':hidden')) {
contentPanel.slideDown('slow');
} else {
contentPanel.slideUp('slow');
}
});
}
I want to test the function, I can use the trigger() to simulate the click event, but I don't know how to test the slideDown() and slideUp() effect.
I want to test the function bindIconClick ,means if I use the trigger() function simulate the click event, I want know does the contentPanel hide or show.
I want to test the full function bindIconClick , not the part of it. I want to test the full function is correct!
In fact , I want to test the effetc that when the span be clicked, will contentPanel hide or show ?
Use slideToggle function instead of if and else
function bindIconClick() {
$('span.scroIcon').click(function(event) {
var eventIcon = $(event.target);
var contentPanel = eventIcon.parents('.panelTitle').next();
contentPanel.slideToggle('slow');
});
}
Related
I have this function where I toggle a class on click, but also append HTML to an element, still based on that click.
The problem is that now, I'm not listening to any DOM changes at all, so, once I do my first click, yup, my content will be added, but if I click once again - the content gets added again, because as far as this instance of jQuery is aware, the element is not there.
Here's my code:
(function($) {
"use strict";
var closePluginsList = $('#go-back-to-setup-all');
var wrapper = $('.dynamic-container');
$('#install-selected-plugins, #go-back-to-setup-all').on('click', function(event) {
$('.setup-theme-container').toggleClass('plugins-list-enabled');
if ( !wrapper.has('.plugins-container') ){
var markup = generate_plugins_list_markup();
wrapper.append(markup);
} else {
$('.plugins-container').hide();
}
});
//Below here, there's a lot of code that gets put into the markup variable. It's just generating the HTML I'm adding.
})(jQuery);
Someone suggested using data attributes, but I've no idea how to make them work in this situation.
Any ideas?
You could just do something like adding a flag and check for it before adding your markup.
var flag = 0;
$('#install-selected-plugins, #go-back-to-setup-all').on('click', function(event) {
$('.setup-theme-container').toggleClass('plugins-list-enabled');
if ( !wrapper.has('.plugins-container') ){
var markup = generate_plugins_list_markup();
if(flag == 0){
wrapper.append(markup);
flag = 1;
}
} else {
$('.plugins-container').hide();
}
});
If you want to add element once only on click then you should make use of .one() and put logic you want to execute once only in that handler.
Example :
$(document).ready(function(){
$("p").one("click", function(){
//this will get execute once only
$(this).animate({fontSize: "+=6px"});
});
$("p").on("click", function(){
//this get execute multiple times
alert('test');
});
});
html
<p>Click any p element to increase its text size. The event will only trigger once for each p element.</p>
How to expand one element at a time and the others to be closed?
When click open one at a time...
Thanks!
jQuery(document).ready(function($) {
$(".se-q").click( function () {
var container = $(this).parents(".se-c");
var answer = container.find(".se-a");
var trigger = container.find(".se-t");
answer.slideToggle(200);
if (trigger.hasClass("se-o")) {
trigger.removeClass("se-o");
}
else {
trigger.addClass("se-o");
}
})
});
You can use .not() , removeClass() , toggleClass();
jQuery(document).ready(function($) {
$(".se-q").click( function () {
var container = $(this).parents(".se-c");
var answer = container.find(".se-a");
var trigger = container.find(".se-t");
answer.slideToggle(200);
$('.se-t').not(trigger).removeClass('se-o'); // remove the class from all .se-t element but not this one(container.find(".se-t"))
trigger.toggleClass("se-o"); // toggle class for this(container.find(".se-t"))
})
});
Note: you can catch the point from my code .. but actually you need to provide your html code .. what I got from your code its
question/answer script .. so you may need to toggle answer as
well
For answer you can use the next line before answer.slideToggle(200);
$('.se-a').not(answer).slideUp(200);
I have a div who can be displayed or not. When it's display I want to pass display to none if you click somewhere not in that div. So what I did is :
document.addEventListener('click',closeDiv)
document.getElementById('myDiv').addEventListener('click',stopPropagation)
function closeDiv(){
let div = document.getElementById('myDiv')
div.style.display='none'
}
But with that even if I click on the div, the display goes to none
Found the solution :
document.addEventListener('click',closeModal)
document.getElementById('myDiv').addEventListener('click',stopPropagation)
function stopPropagation(e){
e.stopPropagation();
}
function closeDiv(){
let div = document.getElementById('myDiv')
div.style.display='none'
}
If you make an window.addEventListener('click', outDiv);
and this function :
let myDiv = document.querySelector('myDiv');
function outDiv (event) {
if (!myDiv.classList.contain(event.target)) {
// Make Something
}
}
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!
Basically I'm trying to make a button be able to handle editing of an element. I want it so that when I click on the Edit button, it changes the text to Save Changes and adds a class which will then bind the button to another click event so that when they click Save Changes, it'll alert "Saved!" and change the text back to Edit. It does this perfectly once. If you continue to try to do it, it simply won't add the class or change the text anymore.
Here is a demo on jsfiddle
The code:
$(function() {
$button = $('button[name="edit"]');
$button.on('click', $button, function() {
var $that = $(this);
$that.text('Save Changes');
$that.addClass('js-editing');
if ($that.hasClass('js-editing')) {
$that.off('click').on('click', $that, function() {
alert('Saved!');
$that.text('Edit');
$that.removeClass('js-editing');
});
}
});
});
Try this http://jsfiddle.net/bpD8B/4/
$(function() {
$button = $('button[name="edit"]');
$button.on('click', $button, function() {
var $that = $(this);
if($that.text()=='Edit'){
$that.text('Save Changes');
$that.addClass('js-editing');
}
else{
alert('Saved!');
$that.text('Edit');
$that.removeClass('js-editing');
}
});
});
You never add back the original handler after calling off(), which removes it.
That being said, it might be easier to have two buttons, with appropriate click handlers, and then use hide() and show() to alternate which one is available. To the end user it should look and act exactly the same, and to you it will be a lot less of a headache to code.
Example: http://jsfiddle.net/VgsLA/
I think in the end, this code is more robust and manageable.
This is just a logic problem. And with $that.off('click').on('click', $that, function() { you are delegating to itself, which is not how you should do it.
Here is a solution using your code:
$(function() {
$button = $('button[name="edit"]');
$button.on('click', $button, function() {
var $that = $(this);
if ($that.hasClass('js-editing')) {
alert('Saved!');
$that.text('Edit');
$that.removeClass('js-editing');
} else {
$that.text('Save Changes');
$that.addClass('js-editing');
}
});
});
Demo