Is there a 'has focus' in JavaScript (or jQuery)? - javascript

Is there something I can do like this (perhap via a plugin)
if ( ! $('form#contact input]').hasFocus()) {
$('form#contact input:first]').focus();
}
Basically, set focus to the first input, but only if the user has not already clicked into anything?
I know this will work too, but is there anything more elegant?
$(function() {
var focused = false;
$('form#contact input]').focus(function() {
focused = true;
});
setTimeout(function() {
if ( ! focused) {
$('form#contact input:first]').focus();
}
}, 500);
});

There is no native solution but yes there is a more elegant way you can do it:
jQuery.extend(jQuery.expr[':'], {
focus: "a == document.activeElement"
});
You're defining a new selector. See Plugins/Authoring. Then you can do:
if ($("...").is(":focus")) {
...
}
or:
$("input:focus").doStuff();

$('input:focus')
It's CSS. You don't need to create a "custom selector." It already exists! http://www.w3schools.com/CSS/pr_pseudo_focus.asp
Just attach whatever process you want to do to that selector, and it will weed it out if the element in question is not focused. I did this recently to keep a keyup from instantiating an email input error check when the e-mail input wasn't being used.
If all you're trying to do is check if the user has focused on anything themselves, just do this:
if($('input:focus').size() == 0){
/* Perform your function! */
}

jQuery 1.6 now has a dedicated :focus selector.

I had trouble with cletus approach, using jQuery 1.3.2 and Firefox 3.6.8, because the string "a == document.activeElement" was not a valid function.
I fixed it defining a function for the focus key. In fact, all other keys defined in jQuery.expr[':'] are defined as functions. Here's the code:
jQuery.extend(jQuery.expr[':'], {
focus: function(e){ return e == document.activeElement; }
});
So, now it works as expected.
However, I was experiencing some strange behaviour in Firefox 3.6.8 (maybe a bug in FF?). If I clicked on an input text while the page was rendering, and if I called is(":focus") on page load, I would get an error from the browser, reported by FireBug, and the script would break.
To solve this, I surrounded the code with a try...catch block, returning false on error. Use it if you want to prevent your users from experiencing the same error:
jQuery.extend(jQuery.expr[':'], {
focus: function(e){
try{ return e == document.activeElement; }
catch(err){ return false; }
}
});

Frustratingly difficult to find a solution to this problem considering the solution is actually very simple:
if (document.activeElement == this) {
// has focus
}
if (document.activeElement != this) {
// does not have focus
}

No, there isn't.
However, you can simulate it like this:
$(':input')
.data('focused', false)
.focus(function() { $.data(this, 'focused', true); })
.blur(function() { $.data(this, 'focused', false); });

There is a plugin http://plugins.jquery.com/project/focused
Also you can check Using jQuery to test if an input has focus

Here is a succinct way to do it.
$(document.activeElement)
or to plug it into your example..
if ($('form#contact input]')[0]!=$(document.activeElement)) { ... }

I know this is an old question, but may be my solution will help someone :)
since this didnt worked for me:
if ($(this)!=$(document.activeElement)) { ... }
..were "this" is returned from blur function. So i did this:
if ($(document.activeElement).attr("class") != "input_textbox"){ ... }

$('*:focus')
(Necro ftw, but still valid and useful)

Related

AttachEvent Not Working on IE11

I am trying to make two checkboxes, out of which only one can be selected at any point of time. I searched the forums a lot and found a few suggestions.
if (document.attachEvent){
// For IE Browsers.
document.attachEvent("DOMContentLoaded", function (event) {
var saSelector = document.querySelector('input[name=saWrite]');
var cgSelector = document.querySelector('input[name=cgWrite]');
if (cgSelector !== null) {
cgSelector.attachEvent('change', function (event) {
if (cgSelector.checked) {
document.querySelector('input[name=saWrite]').checked = false;
}
});
}
if (saSelector !== null) {
saSelector.attachEvent('change', function (event) {
if (saSelector.checked) {
document.querySelector('input[name=cgWrite]').checked = false;
}
});
}
});
}
I wrote a similar function with addEventListener in place of attachEvent for non-IE browsers. That works on Firefox. But this method somehow doesn't work for IE. Am I doing something wrong here? Any suggestions would be helpful. I wish i could use JQuery for this. But i cant.
https://jsfiddle.net/20g7ym8q/
You say you want to use JQuery but you can't. I realize starting out that may seem like a real limitation, but it isn't. Anything you can do with JQuery you can do with JavaScript.
Your code won't work on IE11 because attachEvent has been deprecated and removed in favor of accepting addEventListener as the standard way to attach an event in all modern browsers. If you're looking for generational support without JQuery and without code duplication, setting up your own Object to use as an intermediate layer between your code and the browser is probably the best way to go about this.
function $(ele) {
return {
ele: document.querySelector(ele),
on: function(ev, fn) {
(document.attachEvent) ?
this.ele.attachEvent(ev, fn) :
this.ele.addEventListener(ev, fn);
},
checked: function(change) {
if(typeof change !== undefined) this.ele.checked = change;
return this.ele.checked;
}
}
}
The above is a function that returns an Object with two methods and a property. It works similarly to JQuery for familiarity and consistency, but it is without the overhead of including the entire JQuery library.
The methods allow you to add an event using .on with an event type and function as parameters. The methods also allow you to set or get the checked property of the specified element. .checked() will simply return a boolean as to whether the box is checked, .checked(boolean) will set the elements property to the desired state.
In practice, to solve your dilemma of only one allowable check box, you could do this:
var sa = $('input[name="saWrite"]');
var cg = $('input[name="cgWrite"]');
cg.on('click', function(ev) {
sa.checked(false)
});
sa.on('click', function(ev) {
cg.checked(false);
});

Bootstrap datetimepicker enter key to fill initial date

Bootstrap datetimepicker as seen here: http://eonasdan.github.io/bootstrap-datetimepicker/
Specifically upon first showing, the enter key should hide the widget and place the current date into the input field. Here's some stuff I tried:
There's a dp.hide event which doesn't inject clues into the callback. So, you don't know how it got triggered.
$("#datePicker").on("dp.hide", function(e) {
// e.notSquat
});
It's just not clear which DOM element of the datetimepicker is actually receiving an enter key internally. It's definitely not the input element:
// handler never gets called. css selector is correct
$("#datePicker input").keypress(function(e) {
console.log(e.which);
});
I braved it, somewhat, by jumping into the code of datetimepicker.js itself:
https://raw.githubusercontent.com/Eonasdan/bootstrap-datetimepicker/master/src/js/bootstrap-datetimepicker.js
There are clues, for example, line 2588, but my god there must be an easier way:
// line 2588
enter: function () {
this.hide();
}
Any help is appreciated.
Figured it out, in case anyone finds this helpful. I overwrote the keyBinds.enter property when initializing the plugin.
$("#datePicker").datetimepicker({
keyBinds: {
enter: function(){
if(this.date() === null) {
this.date(moment()); // moment() is similar to new Date()
}
this.hide();
}
},
useCurrent: false
});
Had the same problem using another library - uxsolutions/bootstrap-datepicker v1.8.0..
After a short investigation, I have found the reason why the enter key didn't work for me was the forceParse option set to false (not stated in the Docs).
Code taken from Datepicker.prototype.keydown:
switch (e.keyCode) {
case 13: // enter
if (!this.o.forceParse)
break;
}
See issue #2381

JQuery not finding element

I have a script with the following (only showing the applicable lines)
var setUploadDoneIndicator = function(form)
{
if ($(form).find('[id$=_upload_done_indicator]').is(':checked') == false)
{
console.log("Setting indicator");
$(form).find('[id$=_upload_done_indicator]').trigger('click');
}
}
var unsetUploadDoneIndicator = function(form)
{
if ($(form).find('[id$=_upload_done_indicator]').is(':checked') == true)
{
console.log("UnSetting indicator");
$(form).find('[id$=_upload_done_indicator]').trigger('click');
}
}
$('[id$=_upload_form]').each(function (event)
{
current_form = this;
$(this).fileupload(
{
done: function (e, data)
{
setUploadDoneIndicator(current_form);
}
});
}
This ticks a checkbox correctly, the idea is to listen on the checked state of the checkbox on another JS File. If I call unsetUploadDoneIndicator() right after setUploadDoneIndicator() in this script, it unticks the tickbox.
Then in another JS file I have
$('#pricing_ab_upload_done_indicator').change(function()
{
if ($(this).is(':checked'))
{
console.log("got checked");
unsetUploadDoneIndicator($('#pricing_ab_upload_form'));
}
});
Which calls the function in the first script, but does not untick the tickbox. I am unsure whether the pointer is passed over correctly, when printing out the received object in unsetUploadDoneIndicator() it does print out a JQuery object which seems correct, the
if ($(form).find('[id$=_upload_done_indicator]').is(':checked')
returns true, but the trigger does not happen, so i'm not sure if the element is actually found.
If I change the second script with the following, the trigger to uncheck the box does not happen either
$('#pricing_ab_upload_done_indicator').change(function()
{
if ($(this).is(':checked'))
{
console.log("got checked");
$('#pricing_ab_upload_done_indicator').trigger('click');
}
});
Why would the trigger not happen?
It's easier to just remove your functions and use the following:
$('[id$=_upload_form]').each(function (event) {
current_form = this;
$(this).fileupload( {
done: function (e, data) {
var checkbox = $(current_form).find('[id$=_upload_done_indicator]');
// Set the opposite value
checkbox.prop("checked", !checkbox.prop("checked"));
}
});
}
Avoid binding multiple events on the same action. I see you have a .change event on the checkbox as well, which will result in the "click" event triggering twice. This will make it look like nothing happened.
On a sidenote, if you are using the same selector often (like $(current_form).find('[id$=_upload_done_indicator]') in your code example), it's better to cache it in a variable to increase performance. It's also easier to work with to write a short variable name instead of repeating the entire selector.
Following #Dark Ashelin's advice, I added a custom event. This seems like a much simpler and more logical way of implementing this type of functionality.
In the first script when the upload is done I have
$(current_form).trigger('event_upload_completed');
In the second script I have
$('#pricing_ab_upload_form').on('event_upload_completed', function()
{
console.log("Upload completed");
});
This way does not require a callback to the first script from the second script to reset the state of the checkbox (it does not require a dummy html element at all)
I tested this in the latest Chrome and FireFox and in IE11. If this method has compatibility issues with older IE's please comment on this answer

How to register document.onkeypress event

I want to register keypress events for a document using javascript.
I have used:
document.attachEvent("onkeydown", my_onkeydown_handler);
It works fine with IE,
but not with Firefox and Chrome.
I also tried:
document.addEventListener("onkeydown", my_onkeydown_handler, true);
// (with false value also)
But it still doesn't work with Firefox and Chrome.
Is there a solution, am I missing something?
You are looking for:
EDIT:
Javascript:
document.addEventListener("keydown", keyDownTextField, false);
function keyDownTextField(e) {
var keyCode = e.keyCode;
if(keyCode==13) {
alert("You hit the enter key.");
} else {
alert("Oh no you didn't.");
}
}
DEMO: JSFIDDLE
You are probably looking for:
document.body.addEventListener('keydown', function (e) {
alert('hello world');
});​​​​​​​
But it is almost certainly going to be worth your time to use an existing library to abstract over the problems of the many browsers out there.
Please go through following links for detailed description.
https://developer.mozilla.org/en-US/docs/DOM/element.addEventListener?redirectlocale=en-US&redirectslug=DOM%3Aelement.addEventListener
http://www.reloco.com.ar/mozilla/compat.html
In short, write handler as
function myFunction(e)
{
///For IE
if(!e)
e=window.event;
// use e as event in rest of code.
}

How to validate a form with jQuery?

I tried to find the answer in other questions but actually nothing worked -.- Somehow I hate JavaScript ... Anyway! My Code looks like:
function validate()
{
if ($(":input").length == 0)
{
$(":input").addClass("notvalid");
return false;
}
else
{
$(":input").removeClass("notvalid");
return true;
}
return true;
}
$(":input").blur(validate());
$(":input").keyup(validate());
$("#customForm").submit(function(){
if(validate()){
return true;
}
else
{
return false;
}
});
I just want to test every tag to be not empty. The test should be done when the focus is lost or after every key type. And of course after the submit button has been clicked.
It doesn't work. Firefox error console says something like: unknown pseudoclass or pseudoelement 'input'. What does this mean?
You can alway use AJAX to validate your fields if you are more familiar with server side scripting like PHP.
Back to JS here what i think you want to accomplish:
$("input:text").bind("blur, keyup", function(){
if($(this).val().length > 0){
//Valid not empty
$(this).removeClass("notvalid");
}else{
//invalid empty
$(this).addClass("notvalid");
}
});
$("#customForm").submit(function(){
$("input:text").keyup(); //triggers the keyup event on input fields
//which then validates your fields according the
//code above.
if($("form .notvalid").length > 0){
//You got some invalid fields in form
return false;
}else{
//All fields are valid continue
return true;
}
});
it may look a whole different then your approach but if you want to learn jQuery is better to get familiar with it. I commented some of the process, but if you have any doubt of the methods or functions used in code above you just google it. Good Luck!
The error says the jQuery doesn't know what elements to select with :input. Just replace :input but input:text in your selectors. You could also take a look at the jquery.validate plugin which will simplify your validation logic. There are many demos on the site that should help you get started.
UPDATE:
My mistake. There's :input selector according to the documentation.
Instead of:
function validate()
{
if ($(":input").length == 0)
{
$(":input").addClass("notvalid");
return false;
}
else
{
$(":input").removeClass("notvalid");
return true;
}
return true;
}
Use:
function validate()
{
$(":input").each(function(){
if ($(this).val() === '')
{
$(this).addClass("notvalid");
return false;
}
else
{
$(this).removeClass("notvalid");
return true;
}
});
return true;
}
If your using jQuery already you should really use jquery.validate plugin like Darin said.
This will make you code much cleaner and easier to add standard validation rules like valid email, URL, min length, max length etc. Also removes the need of having to add and remove classes at does it for you.

Categories

Resources