Bootstrap dropdown disappear with right-click on Firefox - firefox

I have some kind of problem with twitter-bootstrap and firefox.
I have a button and a dropdown menu with an input text. If I right click on the input ( for right-click + Paste for example), firefox closes the dropdown. And that quite boring.
Is there any solution for prevent that behaviour ?
Thanks !

As an immediate stop-gap workaround you can use something along the following lines to prevent the click event from propagating when the click event is a right-click
JS
$(document).on('click', function(e) {
e.button === 2 && e.stopImmediatePropagation()
})
This would need to be placed between jQuery loading and Bootstrap loading.
Plunk
However, this is a rather blunt approach and you'd probably be better off doing something more subtle if possible.
Update
One way to circumvent this issue in a more targeted manner is to disable the original event listener and replace it with one that checks for right-clicks first.
JS
// obtain a reference to the original handler
var _clearMenus = $._data(document, "events").click.filter(function (el) {
return el.namespace === 'data-api.dropdown' && el.selector === undefined
})[0].handler;
// disable the old listener
$(document)
.off('click.data-api.dropdown', _clearMenus)
.on('click.data-api.dropdown', function (e) {
// call the handler only when not right-click
e.button === 2 || _clearMenus()
})
Unlike the previous example, this code would need to run after Bootstrap has loaded.
Plunk

For Bootstrap 3 you have to update the namespace to bs.data-api.dropdown.
JS
// obtain a reference to the original handler
var _clearMenus = $._data(document, "events").click.filter(function (el) {
return el.namespace === 'bs.data-api.dropdown' && el.selector === undefined
})[0].handler;
// disable the old listener
$(document)
.off('click.data-api.dropdown', _clearMenus)
.on('click.data-api.dropdown', function (e) {
// call the handler only when not right-click
e.button === 2 || _clearMenus()
})
Plunk

Related

jQuery Mobile 1.4+ pagecontainerbeforechange bug?

I am experimenting with the new way of handling page events in jqM and have run into a curious issue. When handling the pagecontainerbeforechange event
$(document).on('pagecontainerbeforechange',function(e,u){test(e,u,'changing');})
function test(e,u,msg){console.log($(u.toPage));}
Attempting to put a jQuery object wrapper around u.toPage - as done above - produces strange behavior.
Check out this fiddle to see what I mean
Click on the Second Page button and then view the console. Nothing will happen (the second page is not shown) and you will see a message along the lines of *Uncaught error:syntax error, unrecognized expression http://jsfiddle.net/egn7g5xb/1/show/#second
Now comment out Line 7 and run the fiddle again. No such issue this time and the second page gets shown.
Perhaps someone here might be able to explain what is going on here?
On initial run, jQuery Mobile creates a fake page before navigating to first page in DOM. At that stage, pagecontainerbeforechange fires twice and returns .toPage as an object.
Later on, upon navigating to other pages, it fires twice again; however, it returns a string first time (URL/hash) and second time it returns an object which is the page itself.
Therefore, when using that event, you have to determine whether .toPage is an object or a string.
$(document).on("pagecontainerbeforechange", function (e, data) {
if (typeof data.toPage == "string") {
/* parse url */
}
if (typeof data.toPage == "object") {
/* manipulate page navigating to */
}
});
Note that pagecontainerbeforetransition is similar to beforechange, however, it fires once and returns .toPage as an object.
First, create your pagecontainer events within $(document).on("pagecreate", "#first", function(){ .. }).
Then the selector for these events should be $(":mobile-pagecontainer") or $("body") NOT $(document).
function test(e,u,msg)
{
console.log(msg);
var IsJQ = u.toPage instanceof $;
console.log(IsJQ);
if (IsJQ){
console.log(u.toPage.data());
} else {
console.log(u.toPage);
}
console.log('---');
}
$(document).on("pagecreate", "#first", function(){
$(":mobile-pagecontainer").on('pagecontainerbeforechange', function (e, u) {
test(e,u,'changing');
});
$(":mobile-pagecontainer").on('pagecontainerchange',function(e,u){
test(e,u,'changed');
});
});
Updated FIDDLE

CKEditor - prevent mouse wheel scrolling outside of textarea

I am trying to apply a solution described here: Prevent body from scrolling on mouswheel, but not the texarea to textareas which are editable by CKEditor.
I tried to add the following code to the bottom of config.js and styles.js
$( document ).ready(function() {
debugger;
$('.cke_editable')
.bind('mousewheel', function(event, delta) {
if (this.scrollHeight && this.scrollHeight <= $(this).height() + $(this).scrollTop() && delta < 0){
event.preventDefault()
} else if($(this).scrollTop()===0 && delta > 0){
event.preventDefault()
}
});
});
But the scrolling doesn't change and I think the code doesn't run at all (e.g. it doesn't break on debugger).
I've no clue about the other solution (wrapping content inside <body> tag), looks like some hacking would be necessary to apply to CKEditor.
[Edit]
After including code from the accepted answer and after further experimenting with CKEditor on my Drupal site, this is the code that finally works:
CKEDITOR.on('instanceReady', function(ev) {
var $iframe = jQuery('.cke').find('iframe');
$iframe
.bind('mousewheel', function(event, delta) {
if (this.scrollHeight && this.scrollHeight <= jQuery(this).height() + jQuery(this).scrollTop() && delta < 0){
event.preventDefault()
} else if(jQuery(this).scrollTop()===0 && delta > 0){
event.preventDefault()
}
});
});
It still has one problem, after changing edit mode to "Source" and then back to wysiwyg, the binding is lost. It probably needs re-binding on yet another CKEditor event. I tried CKEDITOR.on('mode', function(ev) {... following this post, but it didn't fire. If I find a solution I'll update.
By the way, here is my CKEditor fiddle with this problem: http://jsfiddle.net/67v3rwfo/
[Edit 2]
I noticed that the fiddle works only in Chrome. In Firefox and IE it scrolls the window anyway, even without changing to "Source".
Are you sure that .cke_editable exists during the document ready event? I'm guessing that even though CKE init is quite fast they only appear after .ready. Try something like this
CKEDITOR.on('instanceReady', function(ev) {
alert("InstanceReady");
// $('.cke_editable')... here
});
$(document).ready(function() {
alert(1);
});
Using alert makes sure that the code does get hit, even if the debugger is somehow derping out on you. If you never see the alert(1); it is very likely that some javascript is actually broken, because that code is unrelated to CKEditor. Check your Developer console for messages during page loading.
Edit 10.9.2014
Not sure if this helps with the underlying issue, but to target the .cke_editable element(s) in an iframe, this seems to work:
var iframeDocument = $('.cke').find('iframe').contents();
var editable = $(iframeDocument).find('.cke_editable');
// editable is like [<body contenteditable=​"true" ​…>​…​</body>​]

Slickgrid - Lost focus to end edit

When editing my grid, if I click outside the grid, the box I was editing is still editable. How do I get the edited cell to "complete" the edit when it looses focus?
The following code will save the current edit.
Slick.GlobalEditorLock.commitCurrentEdit();
You'll need to place this inside an event handler that you think should trigger the save. For example, if you're using the sample text editor plugin, I believe an editor-text CSS class is added to the input field that's created when you're editing a cell so something like this should work:
$('#myGrid').on('blur', 'input.editor-text', function() {
Slick.GlobalEditorLock.commitCurrentEdit();
});
I found that I needed to wrap clav's handler in a timeout:
$("#myGrid").on('blur', 'input.editor-text', function() {
window.setTimeout(function() {
if (Slick.GlobalEditorLock.isActive())
Slick.GlobalEditorLock.commitCurrentEdit();
});
});
to avoid errors like:
Uncaught NotFoundError: An attempt was made to reference a Node in a context where it does not exist.
when using the keyboard to navigate. Presumably the new blur handler fires before SlickGrid can do its own handling and this causes problems.
Unfortunately, probably due to differences in event processing, Grame's version breaks keyboard navigation in chrome.
To fix this, I added another check to only commit the edit, if the newly focused element is not another editor element within the grid (as the result of keyboard navigation):
$('#grid').on('blur.editorFocusLost', 'input.editor-text', function() {
window.setTimeout(function() {
var focusedEditor = $("#grid :focus");
if (focusedEditor.length == 0 && Slick.GlobalEditorLock.isActive()) {
Slick.GlobalEditorLock.commitCurrentEdit();
}
});
});
This seems to work in current versions of firefox, chrome and ie.

Loading a hidden div into an AJAX jQuery UI tab (future DOM element)

I have been trying to manipulate content that is loaded into jQuery UI tabs via AJAX.
As you can imagine, these elements are "future" DOM elements and aren't manipulated by normal $(".someClass")functions.
I've read using .live() for event handling is now deprecated using jQuery 1.7+ and is replaced by the new .on() method.
My issue is that the div I want to hide, when it loads in an AJAX tab, must be manipulated after the initial DOM load and is not bound to a click event at first.
My functions, which are currently wrapped in $() are below.
I think I have the syntax correct for links that use a click handler, but I'm not sure of the correct way to ".hide()" my "hiddenStory" div at load.
I also think that the functions themselves shouldn't be wrapped in an overall $()?
Any help or advice would be greatly appreciated.
$(function(){
// this .hiddenStory div below is what I want to hide on AJAX load
// need syntax and/or new methods for writing this function
$(".hiddenStory").hide();
// this is a function that allows me to toggle a "read more/read less" area
// on the "hiddenStory" div
$(".showMoreOrLess").on('click', (function() {
if (this.className.indexOf('clicked') != -1 ) {
$(this).removeClass('clicked');
$(this).prev().slideUp(500);
$(this).html("Read More" + "<span class='moreUiIcon'></span>");
}
else {
$(this).addClass('clicked');
$(this).prev().slideDown(500);
$(this).html("See Less" + "<span class='lessUiIcon'></span>");
}
}));
});
// prevents default link behavior
// on BBQ history stated tab panes with
// "showMoreOrLess" links
$('.showMoreOrLess').click(function (event)
{
event.preventDefault();
// here you can also do all sort of things
});
// /prevents default behavior on "showMoreOrLess" links
Could you set the display: none via CSS and override it when you wanted to show the element's content? Another option, if you have to do it this way would be to add the `$(".hiddenStory").hide() in the callback from the AJAX load that is populating the element. For example:
$(".hiddenStory").load("http://myurl.com", function(){
$(".hiddenStory").hide();
}
);
If you aren't using the .load method, you should have some sort of call back to tie into (e.g. success if using $.ajax...)

Adding handler to form inside div, in the future

I am using the following code to direct the results from a form to a specific div.
$(window).load(function () {
$("#form1").submit(function() {
$.post($(this).attr("action"), $(this).serialize(), function(html) {
$("#resultsDiv").html(html);
});
return false; // prevent normal submit
});
});
How can I apply this (or any) handler to future forms that may be created within an updated div ( with new yet to created content inserted into the div at some point in the future)?
I have looked at the .on but I do not see an event for the updating or reloading of a div.
I have tried adding a similar function to the above, but replacing (window) with ("#thefutureDivID"), but no luck.
The best place to add the handler is right after you know the element exists. So, right after this line:
$("#resultsDiv").html(html);
you can add your code that references $("#thefutureDivID").

Resources