I'm using twitter bootstrap to display popovers with a click event. I'm requesting the info with the click event but I want to hide the popover after it looses focus so the user isn't required to click it again. Is this possible?
Basically I want to show the popover with a click event but then when the launch point looses focus from the mouse the popover is hidden.
Here is a link to the popover doc from twitter-bootstrap: http://twitter.github.com/bootstrap/javascript.html#popovers
This is what I'm currently doing:
jQuery:
$('.knownissue').on('click', function() {
var el = $(this);
if (el.data('showissue') == 'true') {
el.popover('toggle');
el.data('showissue', 'false');
return;
}
$.post('functions/get_known_issues.php', function(data) {
if (data.st) {
el.attr('data-content', data.issue);
el.popover('toggle');
el.data('showissue', 'true');
}
}, "json");
});
Any thoughts?
The following should work.
$('.knownissue').mouseleave(function() {
$(this).popover('hide');
});
Here is a custom jQuery event I call 'clickoutside'. It gets fired if and only if you click the mouse outside of the target element. It could easily be adapted for other event types (mousemove, keydown, etc). In your case, when fired it could close your modal.
(function ($) {
var count = 0;
$.fn.clickoutside = function (handler) {
// If the source element does not have an ID, give it one, so we can reference it
var self = $(this);
var id = self.attr('id');
if (id === '') {
id = 'clickoutside' + count++;
self.attr('id', id);
}
// Watch for the event everywhere
$('html').click(function (e) {
var source = $(e.target);
// ... but, stop it from propagating if it is inside the target
// element. The result being only events outside the target
// propagate to the top.
if (source.attr('id') == id || source.parents('#' + id).length > 0) {
return;
}
handler.call(this, e);
})
};
})(jQuery);
$('#targetElement').clickoutside(function(){
});
EDIT: Example JSFiddle.
Related
I'm using this awesome bouncy filter from Codyhouse but i can't for the life of me figure out how to make it run automatically i.e flip on its own and still accept user click events. The jsfiddle...Thanks.
jQuery(document).ready(function($) {
//wrap each one of your filter in a .cd-gallery-container
bouncy_filter($('.cd-gallery-container'));
function bouncy_filter($container) {
$container.each(function() {
var $this = $(this);
var filter_list_container = $this.children('.cd-filter'),
filter_values = filter_list_container.find('li:not(.placeholder) a'),
filter_list_placeholder = filter_list_container.find('.placeholder a'),
filter_list_placeholder_text = filter_list_placeholder.text(),
filter_list_placeholder_default_value = 'Select',
gallery_item_wrapper = $this.children('.cd-gallery').find('.cd-item-wrapper');
//store gallery items
var gallery_elements = {};
filter_values.each(function() {
var filter_type = $(this).data('type');
gallery_elements[filter_type] = gallery_item_wrapper.find('li[data-type="' + filter_type + '"]');
});
//detect click event
filter_list_container.on('click', function(event) {
event.preventDefault();
//detect which filter item was selected
var selected_filter = $(event.target).data('type');
//check if user has clicked the placeholder item (for mobile version)
if ($(event.target).is(filter_list_placeholder) || $(event.target).is(filter_list_container)) {
(filter_list_placeholder_default_value == filter_list_placeholder.text()) ? filter_list_placeholder.text(filter_list_placeholder_text): filter_list_placeholder.text(filter_list_placeholder_default_value);
filter_list_container.toggleClass('is-open');
//check if user has clicked a filter already selected
} else if (filter_list_placeholder.data('type') == selected_filter) {
filter_list_placeholder.text($(event.target).text());
filter_list_container.removeClass('is-open');
} else {
//close the dropdown (mobile version) and change placeholder text/data-type value
filter_list_container.removeClass('is-open');
filter_list_placeholder.text($(event.target).text()).data('type', selected_filter);
filter_list_placeholder_text = $(event.target).text();
//add class selected to the selected filter item
filter_values.removeClass('selected');
$(event.target).addClass('selected');
//give higher z-index to the gallery items selected by the filter
show_selected_items(gallery_elements[selected_filter]);
//rotate each item-wrapper of the gallery
//at the end of the animation hide the not-selected items in the gallery amd rotate back the item-wrappers
// fallback added for IE9
var is_explorer_9 = navigator.userAgent.indexOf('MSIE 9') > -1;
if (is_explorer_9) {
hide_not_selected_items(gallery_elements, selected_filter);
gallery_item_wrapper.removeClass('is-switched');
} else {
gallery_item_wrapper.addClass('is-switched').eq(0).one('webkitAnimationEnd oanimationend msAnimationEnd animationend', function() {
hide_not_selected_items(gallery_elements, selected_filter);
gallery_item_wrapper.removeClass('is-switched');
});
}
}
});
});
}
});
function show_selected_items(selected_elements) {
selected_elements.addClass('is-selected');
}
function hide_not_selected_items(gallery_containers, filter) {
$.each(gallery_containers, function(key, value) {
if (key != filter) {
$(this).removeClass('is-visible is-selected').addClass('is-hidden');
} else {
$(this).addClass('is-visible').removeClass('is-hidden is-selected');
}
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I'm assuming by "make it run automatically" you're talking about triggering the content-selection animation programatically, rather than requiring a user click. One possible solution is to assign an id to the selection elements, and then register the click handler directly to those elements, rather than the parent filter_list_container. Then, you can use jQuery's trigger() method to simulate a click on the appropriate element.
Assign an id in the html like this:
<a id="green" href="#0">Green</a>
Then register the click handler like this:
$("#red, #green, #blue").on('click', function(event){ ... }
...and trigger like this:
$("#green").trigger("click");
Here's a JSfiddle with an example.
I have a problem with ckeditor widgets. I have inline non-editable text widget which I can drag drop enywhere in editor (using its default functionality). So I need to check where I'm dropping my widget and if this place is undroppable (according my rules it us TABLE) do cancel events propagations and widget should stay on previous place.
editor.widgets.add('customWidgetAdd', {
inline: true,
template: '<span class="simplebox">' +
'<span class="simplebox-title" ></span>' +
'</span>',
init: function(){
var that = this;
that.widgetData = ko.observable(self.activeWidgetData);
var subscription = that.widgetData.subscribe(function (value) {
$(that.element.$).find('.simplebox-title').text(value.name);
if (that.isSelected) {
self.activeWidgetData = value;
}
});
var destroyListener = function(ev){
subscription.dispose();
};
that.once('destroy', destroyListener);
that.on('doubleclick', function (evt) {
editor.execCommand(editAction.command);
});
that.on('select', function (evt){
that.isSelected = true;
self.activeWidgetData = that.widgetData();
});
that.on('deselect', function (evt){
try {
var endContainer = editor.getSelection().getRanges()[0].endContainer.getName();
} catch (e) {
}
that.isSelected = false;
if (endContainer == 'td' || endContainer == 'th') {
//SO here comes the problem. My rule is executed and
//I want CKEDITOR do nothing from here... but stil widget is getting cutted from DOM and inserted to place where I have dropped it...
//that.removeListener('destroy', destroyListener);
//that.removeAllListeners();
evt.cancel();
evt.stop();
return false;
}
});
}
});
Unfortunately there is no easy solution in this situation.
The only one way you can do it is to subscribe to editor's drop event, and cancel it if needed, like:
editor.on('contentDom', function() {
var editable = editor.editable(),
// #11123 Firefox needs to listen on document, because otherwise event won't be fired.
// #11086 IE8 cannot listen on document.
dropTarget = (CKEDITOR.env.ie && CKEDITOR.env.version < 9) || editable.isInline() ? editable : editor.document;
editable.attachListener(dropTarget, 'drop', function(evt) {
//do all checks here
});
});
You can find how it works in CKEditor (See code of function setupDragAndDrop)
I have a small panel which i close if mouse down button is pressed anywhere else than that panel, basically it clears the data to display and just with the help of angularjs ng-show i hide it if there is no data...application is in angularjs and jquery
please find the code below
var closeSearchResultsIfClickedOutside = function (e) {
if ($(e.target).parents('.searchResults').length === 0) {
var scope = angular.element($("#searchContainer")).scope();
scope.$apply(function () {
/*Cancels any existing search*/
if ($scope.defer != undefined) {
$scope.defer.resolve();
}
$scope.showSearchResults = false;
reinitialize();
});
$("html").off("mousedown", closeSearchResultsIfClickedOutside);
reinitializePanelsWidth();
}
};
but i dont want to close this panel if mouse down is on scrollbar of browser window or any scrollbar..please tell me how to do that
to fix the above problem i am not capturing both event, mouse down and click, if the target element on both event matches then only i am closing the panel.
/*
If mouse down and click on the same control, then only close the panel,
Click event closing is added to avoid closing panel on scrollbar click.
*/
var closeSearchResultsIfClickedOutside = function (e) {
if (e.type === 'mousedown') { /* only if mouse down is outside of search panel then only close the panel. */
if($(e.target).parents('.searchResults').length === 0)
{
isMouseDownOnSearchPanel = true;
}
else {
isMouseDownOnSearchPanel = false;
}
}
else if (e.type === 'click' && isMouseDownOnSearchPanel) { /*click event is implemented to avoid closing when mouse down is on scrollbar. you dont get click get event for scrollbar*/
var scope = angular.element($("#searchContainer")).scope();
$("html").off("mousedown", closeSearchResultsIfClickedOutside);
$("html").off("click", closeSearchResultsIfClickedOutside);
isMouseDownOnSearchPanel = false;
reinitializePanelsWidth();
}
};
I have a function that needs to fire when I click on a chevron tab. However I only need that function to fire that first time we load the page. How can I prevent it form firing every time the tab is clicked?
$('#navi a').bind('click',function(e){
var $this = $(this);
var prevButton = current;
$this.closest('ul').find('li').removeClass('selected');
if ( $(this).attr('id') == 'tab2')
{
//fire function only once
}
});
In case you need only part of your event handler to run once :
$("div").on("click",function(){
if (!$(this).data("fired")) {
console.log("Running once");
$(this).data("fired",true);
}
console.log("Things as usual");
});
Demo
Use the .one binding instead. This will attach it to fire on the first click and remove itself.
Use:
var isalreadyclicked=false;
$('#navi a').bind('click',function(e){
var $this = $(this);
var prevButton = current;
$this.closest('ul').find('li').removeClass('selected');
if ( $(this).attr('id') == 'tab2')
{
if(!isalreadyclicked){
//fire function only once
isalreadyclicked=true;
}
}
});
I have a button that toggles a menu popup. I have can make the menu disappear if you click outside of the menu but now my button toggle does not work. If I click the button again the menu stays up. How can I make the menu disappear if you toggle the button or if you click off the container?
jsFiddle: http://jsfiddle.net/PPcfN/
$('.quicklinks-rollover').click(function () {
$('.quicklinks').toggle();
});
$(document).mouseup(function (e) {
var container = $(".quicklinks");
if (container.has(e.target).length === 0) {
container.hide();
}
});
The mouseup function has to take care of the click on the button (quicklinks-rollover).
If fixed the whole thing here:
http://jsfiddle.net/8VUnq/1/
$(document).mouseup(function (e) {
var popup = $('#quickLinksPopup'),
button = $('#quickLinksToggle');
if (popup.is(':visible')
&& !popup.is(e.target)
&& !button.is(e.target)
&& popup.has(e.target).length === 0
&& button.has(e.target).length === 0) {
popup.toggle();
}
});
Keep in mind those two things:
Use IDs to refer to the items quicker and prevent multiple popup conflicts
Using a mouse event on the whole page is not recommended as the event will get triggered very frequently, try using an alternative method such as adding a close button in the popup, or to be more effective, think about adding the mouseup listener on the show of the popup and removing it on the hide.
You can determine the state of the popup with: $(popup).is(':visible') or is(':hidden').
Try :
var $quicklinks = $('.quicklinks');
var msOverLinks = false;
$('.quicklinks-rollover').click(function () {
$quicklinks.toggle();
});
$quicklinks.mouseenter(function() {
msOverLinks = true;
}).mouseleave(function() {
msOverLinks = false;
});
$(document).mouseup(function (e) {
if( ! msOverLinks ) {
$quicklinks.toggle();
}
});
You can do this Normal hide and show method. Because mostly toggle() function wont works in proper manner...
put your HTML button with attribute p="closed" by default:
<button class="quicklinks-rollover" p="closed" title="Quick Links">toggle</button>
Change Your Jquery:
$('.quicklinks-rollover').click(function () {
var a = $(this).attr("p");
var container = $(".quicklinks");
if(a=="closed"){
container.show();
$(this).attr("p","open");
}else{
container.hide();
$(this).attr("p","closed");
}
});
$(document).mouseup(function (e) {
var container = $(".quicklinks");
if (container.has(e.target).length === 0) {
container.hide();
}
});
The reason for this behavior, the mouseup() is binded when I perform the click() on the div. You can check this behavior by adding console.log message in .mouseup event.
So instead try like below.
$('.quicklinks-rollover').on('click', function (e) {
$('.quicklinks').toggle();
e.stopImmediatePropagation();
});
$(document).click(function (e) {
var container = $(".quicklinks");
console.log(container.has(e.target).length);
if (container.has(e.target).length === 0) {
container.hide();
}
});
Working Fiddle