I like to keep my code as DRY as possible and would like to know if the following is possible.
I'll need to reuse the code below many times with the only difference being what I do in the following function.
.on("click", "a", function(e) {})
I could just duplicate the addToBooking function, give it a different name, make the slight change in the click handler but that feels wasteful and repetitive.
Can I perhaps pass a code block to the addToBooking function?
Or maybe there's another cool, efficient way I'm not aware of.
The full code block
var addToBooking = function(that, event) {
var left, top;
event.stopPropagation();
//Turn off all calendar tracking
$(".track").off();
//Get proper sticky positioning (Checks to make sure it wont display off screen)
left = getPosition(".add_to_booking", "left");
top = getPosition(".add_to_booking", "top");
//Position sticky, display and listen for click event to see what to do next
$(".add_to_booking").css({top: top, left: left})
.fadeIn('fast')
.on("click", function(e) { e.stopPropagation(); })
.on("click", "a", function(e) {
if($(this).text() === "YES") {
//Close dialog
closeTT();
//Open new add to booking box
addBooking(that, event);
} else {
closeTT();
}
});
}
Pass in the function and assign it
var addToBooking = function(that, event, custFnc) {
...
...
.on("click", "a", custFnc );
}
Fiddle
To pass parameters, you need to use call()
jQuery( function(){
function hey(evt, test){
var text = jQuery(this).text();
alert(text + ":" + test);
}
function addClick( custFnc ){
var test=99;
jQuery("#foo").on("click",
function(e){
custFnc.call(this, e,test);
}
);
}
addClick(hey);
});
Fiddle
Related
I have this function:
NewShowHideDiv2(iconID, divID, disabled) {
var x = document.getElementById(divID);
var y = document.getElementById(iconID);
$(eval(y)).click(function() {
console.log(eval(y));
$(eval(y)).toggleClass( "clicked" );
});
$(eval(x)).slideToggle("slow", function() {
});
}
All i am trying to get it to do is toggle the "clicked" class on click. However, it ignores the first and second click, and then applies it on the third and all subsequent odd number clicks. any ideas?
Without knowing how NewShowHideDiv2 is called it's difficult to be certain but there are some likely issues.
First, by putting your click binding function inside another function, the event isn't bound to the element until NewShowHideDiv2 is run. So you'll want to pull that out and put it in something like this:
$( document ).ready(function() {
$(eval(y)).click(function() {
console.log(eval(y));
$(eval(y)).toggleClass( "clicked" );
});
});
Also, the eval approach on the JS object is likely causing issues and certainly isn't the best practice. You'll want to modify that to be:
$( document ).ready(function() {
$("#iconIDHere").click(function() {
console.log(this);
$(this).toggleClass( "clicked" );
});
function NewShowHideDiv2(divID, disabled) {
$("#" + divID).slideToggle("slow", function() {
});
}
});
Try this with vanilla JS:
var x = document.getElementById('divID');
x.addEventListener('click', function(e) {
if(e.target.classList.contains('clicked')) {
e.target.classList.remove('clicked');
} else {
e.target.classList.add('clicked');
}
});
I think JQuery is:
$('#divID').click(function() {
$('#divID').toggleClass('clicked');
});
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!
The User should be able to change the Name and then confirm the change. I'm not able to archive it with this code as when I click confirm, it returns like before.
What am I missing?
Any better way to put this together (which I'm sure there's one) ?
Please check the demo where you can also see the changeElementTypefunction
http://jsfiddle.net/dLk6E/
js:
$('.replace').on('click', function () {
$("h2").changeElementType("textarea");
$('.replace').hide();
$('.confirm').show();
//Confermation of the change
$('.confirm').bind('click', function () {
$('.replace').show();
$('.confirm').hide();
$("textarea").changeElementType("h2");
});
if ($('textarea:visible')) {
$(document).keypress(function (e) {
if (e.which == 13) {
alert('You pressed enter!');
$("textarea").changeElementType("h2");
$('.replace').css('opacity', '1');
}
});
}
});
Here are your updated code and working fiddle http://jsfiddle.net/dLk6E/
(function($) {
$.fn.changeElementType = function(newType) {
var attrs = {};
$.each(this[0].attributes, function(idx, attr) {
attrs[attr.nodeName] = attr.nodeValue;
});
this.replaceWith(function() {
return $("<" + newType + "/>", attrs).append($(this).contents());
});
}
})(jQuery);
$('.replace').on('click', function (){
$("h2").changeElementType("textarea");
$('.replace').hide();
$('.confirm').show();
//Confermation of the change
$('.confirm').on('click', function(){
$('.replace').show();
$('.confirm').hide();
// you are missing this
$('.replaceble').html($("textarea").val());
$("textarea").changeElementType("h2");
});
if ($('textarea:visible')){
$(document).keypress(function(e) {
if(e.which == 13) {
alert('You pressed enter!');
$("textarea").changeElementType("h2");
$('.replace').css('opacity','1');
}
});
}
});
updated
jsfiddle.net/dLk6E/1
I think your code is right but you need to use the value you're entering when replacing it. So the confirmation binding would be something like this (fetching it, and then using it to update the textarea before "transforming" it into an h2 tag.
$('.confirm').bind('click', function(){
var valueEntered = $('textarea').val();
$('.replace').show();
$('.confirm').hide();
$("textarea").html(valueEntered).changeElementType("h2");
});
You could be using .on for this as well as of jQuery 1.7 is prefered to .bind.
Another thing I would suggest is whenever you struggle with something like this just put in google (or whatever...) exactly what you want, in this case "jquery get value of input" will get asw first result the jquery documentation
This way you won't forget it ;)
Update: Maybe a small detail but in the binding I use it would be more efficient to just hit $('textarea') once, so it would be something like this. Something that you may keep in mind (not really an issue here), better to store in a variable than hit the DOM several times.
$('.confirm').on('click', function(){
var $textarea = $('textarea');
$('.replace').show();
$('.confirm').hide();
$textarea.html($textarea.val()).changeElementType("h2");
});
jsfiddle
I have the following jQuery
$('img[title*=\"Show\"]').click(function() {
//$e.preventDefault();
var position = $('img[title*=\"Show\"]').parent().position();
$('#popover').css('top', position.top + $('img[title*=\"Show\"]').parent().height() + 150);
console.log(position);
$('#popover').fadeToggle('fast');
if ($('img[title*=\"Show\"]').hasClass('active')) {
$(this).removeClass('active');
} else {
$('img[title*=\"Show\"]').addClass('active');
}
});
I have two images with the title "Show Options." For some reason whenever I click on any of these images, it gets printed TWICE. When I only have 1 image, it only gets printed once. Why is this?
instead of $('img[title*=\"Show\"]') inside click function use $(this)
if doesn't works use:
$('img[title*=\"Show\"]').click(function(e) {
e.stopImmediatePropagation();
//other code
});
Use the following code
$('img[title*="Show"]').click(function (evt) {
$('#popover').hide();
$('img[title*="Show"]').removeClass("active");
$(this).addClass("active");
var p = $(this).parent();
$('#popover').css('top', p.position().top + p.height() + 150).fadeToggle('fast');
});
You can use event.stopPropogation so that event is not bubbled further. Maybe your function is being triggered from two different events and other one also get triggered while bubbling.
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.