Bootstrap Popover - Close on click anywhere - css

I'm just wondering if this is a good way to do it or if I'm being stupid. Basically any click in body is verified to not be the popover anchor, or within the popover. If it's not, then it hides all popovers.
$("body").on('click', function(e) {
if(!$(event.target).hasClass('with-popover') && !$(event.target).parents('.with-popover').length && !$(event.target).parents('.popover').length){
$(".with-popover").popover('hide');
};
});

Is this stupid? no. Just a few modifications to make it a little more efficient.
$('body').on('click', function(event) {
var target = $(event.target); // One jQuery object instead of 3
// Compare length with an integer rather than with negation
if ( ! target.hasClass('with-popover')
&& target.parent('.with-popover').length === 0
&& target.parent('.popover').length === 0) {
$('.with-popover').popover('hide');
}
});
jQuery also provides a size() function that also just returns the length. I never use it anymore but just to be aware.
I was unsure what the return true was doing and the final }); maybe you had this wrapped in a function.

Related

addEventListener on Panel

I have a use-case where I need to programmatically add/remove the onClick event associated with a panel.
I have tried the following solution but receive a cijCell.addEventListener is not a function error.
function cij_enabled(){
var cijCell = app.pages.Home.descendants.cellFour;
var index = cijCell.styles.indexOf('disabled-card');
if (Report.riskOfLoss === 'High') {
cijCell.styles.splice(index, 1);
cijCell.addEventListener("click", function() {
app.popups.Customer.visible = true;
});
} else {
if (index === -1){
cijCell.styles.push('disabled-card');
cijCell.removeEventListener("click", function() {
app.popups.Customer.visible = true;
});
}
}
}
How can I achieve the desired outcome? Is adding eventlisteners possible in this fashion through app maker?
You can definitely do so and you got it almost right. The only thing you need to understand is that the appmaker widget is not a native html element hence the error:
cijCell.addEventListener is not a function
Fortunately, AppMaker has a way of getting the native html elements associated to a widget. You need to use the getElement() method and then you can use the add/remove event listeners methods. So you should change your code from cijCell.addEventListener... to cijCell.getElement().addEventListener...
Reference: https://developers.google.com/appmaker/scripting/api/widgets#Panel

CodeMirror - AutoComplete "options" not setting right

I am using CodeMirror and attempting to do some CSS styling to the autocomplete pop up. This is a bit difficult, because I need it to not go away when I go to inspect styles and stuff.
So I hunted for a way to do this. I found this code in show-hint.js
if (options.closeOnUnfocus !== false) {
var closingOnBlur;
cm.on("blur", this.onBlur = function () { closingOnBlur = setTimeout(function () { completion.close(); }, 100); });
cm.on("focus", this.onFocus = function () { clearTimeout(closingOnBlur); });
}
If I comment this out, then the autocomplete pop up does not go away when I click on other things; That's what I wanted. But I thought I would explore this more and try to determine what to do to toggle this on and off at will.
So I wanted to be able to set this closeOnUnfocus option on my own. That seemed simple enough.
I cannot find a way to do this, though. Exploring further I found an example on code mirror's website that demonstrates a way to setup the autocomplete system using the following code;
CodeMirror.commands.autocomplete = function(cm) {
CodeMirror.showHint(cm, CodeMirror.hint.anyword);
}
Exploring further, show-hint.js starts out with a function called showHint that has this signature;
CodeMirror.showHint = function (cm, getHints, options) {
// We want a single cursor position.
if (cm.somethingSelected()) return;
if (getHints == null) {
if (options && options.async) return;
else getHints = CodeMirror.hint.auto;
}
if (cm.state.completionActive) cm.state.completionActive.close();
var completion = cm.state.completionActive = new Completion(cm, getHints, options || {});
CodeMirror.signal(cm, "startCompletion", cm);
if (completion.options.async)
getHints(cm, function (hints) { completion.showHints(hints); }, completion.options);
else
return completion.showHints(getHints(cm, completion.options));
};
Okay, so it stands to reason that I could accomplish what I want by passing my option through here; like this...
CodeMirror.commands.autocomplete = function (cm) {
CodeMirror.showHint(cm, CodeMirror.hint.anyword, {
closeOnUnfocus: false
});
}
But this doesn't work - in fact, it seems that the options just don't get passed at all. If I do a console.log in the show-hint.js, the options are outright ignored. They never get through.
So how can I pass options through? I am very confused.
If you want to change the styles of of the hint menu, just use the provided CSS hooks. There is no need to mess around with the autocomplete handlers. e.g.:
.CodeMirror-hints {
background-color: red;
}
.CodeMirror-hint {
background-color: green;
}
.CodeMirror-hint-active {
background-color: blue;
color: yellow;
}
And here's a live Demo.
I've just started to use Codemirror (v4.1) and I've found the same problem. After checking show-hint.js contents it seems that documentation is not updated.
Try to write this when you want to get the suggestions:
CodeMirror.showHint({hint: CodeMirror.hint.deluge, completeSingle: false, closeOnUnfocus: true});
If you need to use the async mode of getting suggestions (it was my case), now you have to do this before previous snippet:
CodeMirror.hint.deluge.async = true;
Hope this helps!
You can pass the options like this :
CodeMirror.showHint(cm,CodeMirror.hint.anyword,{completeSingle: false,closeOnUnfocus:false});
You can write the code as follows:
editor.on("keyup",function(cm){
CodeMirror.showHint(cm,CodeMirror.hint.deluge,{completeSingle: false});
});
It's working for me.

google maps API v3 events

I have the following situation:
A polyline is added on the map and when the user clicks over it its state changes to editable. Also i have event where if the user clicks the last vertext of the polyline and starts moving the mouse to be able to extend the polyline with the mouse path the user is drawing.
However it seems that when i have an event and inside this event i try to add another one it simply does not work and i don't kwow why.
Just in case to make things simpler to undrstand i will paste a part of my code.
google.maps.event.addListener(polyLine, "mousedown", function(event){
if(polyLine.getEditable() === true)
{
if(typeof event.vertex !== "undefined")
{
if(event.vertex === polyLine.getPath().getLength() - 1)
{
polyLine.setEditable(false);
if(mouseMoveDrawingEvent === null)
{
map.setOptions({draggable:false});
polyLine.setOptions({clickable:false});
mouseMoveDrawingEvent = google.maps.event.addListener(map, "mousemove", function(event)
{
alert("1"); // <== this never fires
polyLine.getPath().push(event.latLng);
drawingLabel.setPoint(event.latLng);
drawingLabel.setContents("<div style='background-color:white'>" + (google.maps.geometry.spherical.computeLength(polyLine.getPath()) / 1000).toFixed(2) + " км.</div>");
});
}
map.getDiv().onmouseup = function(ev) {
polyLine.setOptions({clickable:true});
map.getDiv().onmousedown = null;
map.getDiv().onmouseup = null;
google.maps.event.removeListener(mouseMoveDrawingEvent);
mouseMoveDrawingEvent = null;
};
}
}
}
});
.....
thre is another event here that listens for 'mouseup'....
Do you guys have any idea how to make this peace of code works.
I found a solution to my questions.
The problem was that when i set the polyline {clickable:false} the api removes the event ( and obviously everyhing inside it:)

Binding Keyup to an Element using jQuery extension and jquery.on

This seems very simple, but for some reason it's not working as expected.
I am trying to make a very simple jQuery extension/plugin which allows me to simply reduce my lines of code when requiring a trigger on an enter key (and a similar for an escape)
Here's my code:
$.fn.enterListen = function (callBack) {
$(this).on('keyup', function (e) {
if (e.keyCode == 13) {
callBack;
// $(this).enterListen(callBack); // trying to rebind...
};
})
};
Then when an element is dynamically created with jquery we might do something like:
var input = $('<input'>).enterListen(function (){ alert("Enter was pressed"); });
$(input).appendTo('body');
Now we've added an input element to the page, in which we can type and when enter is pressed it triggers the alert.
This works, except, only once.
You can see a commented out line in my code above where I am trying to rebind the function the the element after the enter trigger is activated, and even that doesn't make it work a second time.
You can press as many other keys as you like before pressing Enter, but as soon as you do, it seems to unbind the keyup event.
IF... however, I run it like this:
function isEnter(e, ele) {
if ((e * 1) == 13) {
$(ele).click();
};
};
Called by:
var input = $('<input'>).on('keyup', function (e) { isEnter(e.keyCode, $(ok)) });
$(input).appendTo('body');
It works fine, but to me it is clumsier in the code, I am trying to create a library of extensions to make the inner coding of this project a bit shorter... perhaps I am just putting too much time into something I needn't...
Anyway, if anyone could shed any light on why the event becomes unbound, that'd be lovely!
Inside a jQuery plugin, this is the jQuery object, no need to rewrap it. e.which is normalized in jQuery. To execute a function you need parenthesis (). And most importantly, you need to return this otherwise the input variable will be undefined, and if you intend to do stuff inside your plugin with selectors containing multiple elements, you need to return this.each(function() { ... }) etc. as explained in the plugin authoring documentation from jQuery.
$.fn.enterListen = function (callBack) {
return this.each(function() {
$(this).on('keyup', function (e) {
if (e.which == 13) {
e.preventDefault();
callBack();
}
});
});
};
var input = $('<input />').enterListen(function (){
alert("Enter was pressed");
});
input.appendTo('body');
FIDDLE

Disallow typing of few of characters e.g.'<', '>' in all input textboxes using jquery

How do I achieve this:-
When user types character like 'abcd' and then '>'(an invalid character for my application), I want to set the text back to 'abcd'. Better if we can cancel the input itself as we do in winforms application. This should happen when user is typing and not on a click of button.
I want this to be applied on all text boxes in my web page. This will be easy if the solution is jQuery based. May be something which will start like this.
$("input[type='text']")
SOLUTION
I used both of the answer provided by #jAndy and #Iacopo (Sorry, couldn't mark as answer to both) as below.
$(document).ready(function() {
//makes sure that user cannot enter < or > sign in text boxes.
$("input:text").keyup(purgeInvalidChars)
.blur(purgeInvalidChars)
.bind('keypress', function(event) {
if (event.which === 62 || event.which === 60)
return (false);
});
function purgeInvalidChars() {
if (this.value != this.value.replace(/[<>]/g, '')) {
this.value = this.value.replace(/[<>]/g, '');
}
}
});
Though one issue still remained i.e. It doesn't allow user to select text in the textbox and this only happens on chrome, work fine on IE (for the first time :D), not tested on firefox. It would be glad if anyone can find solution for that or hope people at Google solves it :D.
UPDATE
I solved it by if (this.value != this.value.replace(/[<>]/g, '')) check. Also updated solution.
Thanks again to all the answerers.
You should catch the 'keyup' and 'blur' events and attach them to a function that bonifies the input: don't forget that the user can paste an invalid sequence of characters.
So for example
$('input[type="text"]').keyup(purgeInvalidChars).blur(purgeInvalidChars)
function purgeInvalidChars()
{
this.value = this.value.replace(/[<>]/g, '');
}
surely you will improve the regexp, maybe replacing all characters except the enabled ones.
Sorry, I can't test my code, so you should take it cum grano salis :-)
Example (keypress):
$(document).ready(function(){
$('input:text').bind('keypress', function(event){
if(event.which === 62 || event.which === 60)
return(false);
});
});​
Example (keydown):
$(document).ready(function(){
$('input:text').bind('keydown', function(event){
if(event.which === 226)
return(false);
});
});​
Just make use of the preventDefault and stopPropagation functions for events. Those are triggered by returning (false) within an event handler.
In this example, I just check for the keycode of < and > which is thankfully on the same key. If we hit that code, we just prevent the default behavior.
Reference: .preventDefault(), .stopPropagation()
$('#textBox').keyup(function(e){
var myText = $('#textBox').val();
myText = myText.replace(">", "");
myText = myText.replace("<", "");
$('#textBox').val(myText);
});
-- Update --
keyup instead keypress

Resources