I've got a lightbox textbox that is displayed using an AJAX call from an ASP.NET UpdatePanel. When the lightbox is displayed, I use the focus() method of a textbox that is in the lightbox to bring focus to the textbox right away.
When in Firefox, the text box gains focus with no problem. In IE, the text box does not gain focus unless I use
setTimeout(function(){txtBx.focus()}, 500);
to make the focus method fire slightly later, after the DOM element has been loaded I'm assuming.
The problem is, immediately above that line, I'm already checking to see if the element is null/undefined, so the object already should exist if it hits that line, it just won't allow itself to gain focus right away for some reason.
Obviously setting a timer to "fix" this problem isn't the best or most elegant way to solve this. I'd like to be able to do something like the following:
var txtBx = document.getElementById('txtBx');
if (txtPassword != null) {
txtPassword.focus();
while (txtPassword.focus === false) {
txtPassword.focus();
}
}
Is there any way to tell that a text box has focus so I could do something like above?
Or am I looking at this the wrong way?
Edit
To clarify, I'm not calling the code on page load. The script is at the top of the page, however it is inside of a function that is called when ASP.NET's Asynchronous postback is complete, not when the page loads.
Because this is displayed after an Ajax update, the DOM should already be loaded, so I'm assuming that jQuery's $(document).ready() event won't be helpful here.
Try putting the javascript that sets focus at the end of the page instead of the beginning or having it fire after the page loaded event. That will help ensure that the DOM is completely loaded before setting focus.
I've used FastInit for this. JQuery $(document).ready() would also work.
You can try this:
Use the endRequest event of the PageRequestManager. That event fires once an Ajax update has finished.
Focus the textbox in the event handler
Here is some sample code:
<script type="text/javascript">
function onRequestEnd()
{
var txtBx = $get('txtBx');
txtBx.focus();
}
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(onRequestEnd);
</script>
To focus the textbox initially you can use the pageLoad function (shortcut to the load event of the Application client-side object):
<script type="text/javascript">
function pageLoad()
{
var txtBx = $get('txtBx');
txtBx.focus();
}
</script>
you could try something like this [IE Specific]. (untested)
theAjaxCreatedElement.onreadystatechange = function() {
if ( this.readyState != "complete" )
return;
this.focus();
};
Another way might be to change the background color of the element with onfocus, then retrieve it with js check if it is what it should be, if not: refocus the element.
It seems that IE does not update the DOM until after the script has finished running. Thus, a loop testing for focus will not allow the DOM to update. Using setTimeout is probably the only working solution.
Your example with .focus() is a well known example, see e.g. this answer.
Have you tried adding the autofocus="autofocus" attribute to the textbox element you are calling via Ajax?
Normally, when I need certain additional JavaScript functionality to run on dynamic content, I'll simply add that JavaScript to the content being called as well.
That JavaScript will also execute after it's added to the DOM. I don't see a point in writing JavaScript to your parent file and then "listening" for changes to the DOM. Like you mentioned, setTimeout() is more of a hack than anything else for something like this :)
There are several things in IE, that does the trick:
If focusing element has different z-index - you can quickly set z-index to that of currently focused element (possibly setting hidden attribute), set focus, and then set it back to original z-index.
Try to blur() currently focused element.
If element is 'shimmed' - focus the 'shim' element.
Related
I have a div that when the page is loaded is set to display:none;. I can open it up using this simple code:
$(".field-group-format-toggler").click(function()
{
$(".field-group-format-wrapper").css({'display':'block'});
});
Once it's opened, I'd like the user to be able to close it so I tried using the .is(':visible') function and then wrapping my original code in an if statment but this time using display:none;
if($('.field-group-format-wrapper').is(':visible')){
$(".field-group-format-toggler").click(function()
{
$(".field-group-format-wrapper").css({'display':'none'});
});
}
This does not seem to work though and I am not getting any syntax errors that I know of.
I also tried this:
if ($('.field-group-format-wrapper').is(':visible'))
$(".field-group-format-toggler").click(function () {
$(".field-group-format-wrapper").css({'display':'none'});
});
... but that did not work either.
You can just use the toggle function:
$(".field-group-format-toggler").click(function()
{
$(".field-group-format-wrapper").toggle();
});
This will show the '.field-group-format-wrapper' elements if they are currently hidden and hide them if they're currently visible.
FYI the reason your code snippet in your question wasn't working is because you're only checking the visibility of the elements on dom ready, rather than on each click - so the event handler to show the elements will never be attached.
I guess your function is only being called on page load at which time all divs are hidden.
Why not check the visibility in the click event handler?
$('.field-group-format-toggler').click(function(){
var $wrapper = $('.field-group-format-wrapper'); //Maybe $(this).parent()?
if($wrapper.is(':visible'))
$wrapper.hide();
else
$wrapper.show();
As already mentioned, you can use the toggle function to achieve what you want.
To add a bit of extra information, when attaching events like you're doing, you're actually using a subscription model.
Registering an event puts it in a queue of events subscribed to that handler. In this case, when you add the second event to change the CSS, you're adding an event, not overwriting the first one.
Whilst thing isn't actually causing your problem, it's worth being aware of.
I'm trying to determine why something like this doesn't work:
$('a').focus( function() {
$(this).click();
});
Background:
I'm trying to create a form in which tabbing to various elements (e.g. textboxes, etc.) will trigger links to anchors in a div, so that relevant text is scrolled into view as the form is being filled out.
Is there a better way to do this?
$('yourInput').on('focus', function(){
$('yourAnchor').trigger('click');
});
should work just fine, however you are likely to loose focus on the input field as the new element has been 'clicked'. I would recommend using the jQuery scrollTo plugin instead. That would enable you to do something like this:
$('yourInput').on('focus', function(){
$('messageArea').scrollTo('yourAnchor');
});
This was scrolling occurs in a nice animated fashion and without triggering browser events.
Part of the reason the code you posted may be failing is that, 1. anchors do not always have a focus event, 2. clicking it right after focusing may be redundant and not causing the change you are looking for.
I have a problem that happens only on a specific computer(FFX 3.6.13,Windows 7,jQuery 1.4.3).
Sometimes document.ready is fired but when trying to get elements to attach the event handlers,the elements don't exist!
the code goes something like this:
$(function(){
window.initStart = true;
$("#id_of_element").click(function()...);
window.initEnd = $("#id_of_element");
});
the window.initStart/End are there for debugging,sometimes this code runs just fine,but sometimes window.initEnd is just a empty jQuery set(length == 0).
What this means is that document.ready is always fired,but sometimes it is fired before elements are available.
Does anybody had this problem? what could the problem be?
One way that you could try to get around this would be with using .live instead of .click. The following code
$('#idOfDiv').live('click', function() { doStuff(); });
will attach the input function to the click event of everything that is dropped on the page with an id of 'idOfDiv' as soon as it makes it to the page. Whereas .click executes immediately, this should be attached no matter what time the divs make it to the page.
Cheers
There's an article on SitePoint that demonstrates how to sense when certain dom elements are available.
Also I know this is a version specific issue, but if you were on Jquery 1.5 the deferred objects stuff would be useful here.
Here's what I want to do. I want to trigger an event every time a select element changes. I have a multiline select and when I make changes (click on elements), it does not change until the select box loses focus. So I'm trying to force a blur every time the select box is clicked. That way if it changes, it will trigger the changed event. If it doesn't change, nothing will happen.
How do I do this? Am I even approaching this the right way? Jquery answers are okay as well.
In addition to Ender the full code could be something like this.
$('#mySelectBox').change(function() {
$('#thingToBlur').blur();
})
Reference: http://api.jquery.com/blur/
This will find the element with the focus and trigger the blur event.
function blur(){
document.querySelectorAll('input,textarea').forEach(function(element){
if(element === document.activeElement) {
return element.blur();
}
});
}
Using jQuery do:
$('#mySelectBox').change(function() {
//do things here
});
According to the documentation at http://api.jquery.com/change/, the event is triggered immediately when the user makes a selection.
Check out this demo to verify that this works: http://jsfiddle.net/AHM8j/
You could attach an onclick handler to the select and the individual options. basically onclick="this.blur();". I've always found that click events on <select> elements to be a pain, as nothing happens at the point you expect it to.
Okay, Here's what was going on. I was including the -vsdoc version of JQuery instead of the actual JQuery library. This also fixes some issues I was having with some plugins such as blockUI.
Heres my link:
http://tinyurl.com/6j727e
If you click on the link in test.php, it opens in a modal box which is using the jquery 'facebox' script.
I'm trying to act upon a click event in this box, and if you view source of test.php you'll see where I'm trying to loacte the link within the modal box.
$('#facebox .hero-link').click(alert('click!'));
However, it doesn't detect a click and oddly enough the click event runs when the page loads.
The close button DOES however have a click event built in that closes the box, and I suspect my home-grown click event is being prevented somehow, but I can't figure it out.
Can anyone help? Typically its the very last part of a project and its holding me up, as is always the way ;)
First, the reason you're getting the alert on document load is because the #click method takes a function as an argument. Instead, you passed it the return value of alert, which immediately shows the alert dialog and returns null.
The reason the event binding isn't working is because at the time of document load, #facebox .hero-link does not yet exist. I think you have two options that will help you fix this.
Option 1) Bind the click event only after the facebox is revealed. Something like:
$(document).bind('reveal.facebox', function() {
$('#facebox .hero-link').click(function() { alert('click!'); });
});
Option 2) Look into using the jQuery Live Query Plugin
Live Query utilizes the power of jQuery selectors by binding events or firing callbacks for matched elements auto-magically, even after the page has been loaded and the DOM updated.
jQuery Live Query will automatically bind the click event when it recognizes that Facebox modified the DOM. You should then only need to write this:
$('#facebox .hero-link').click(function() { alert('click!'); });
Alternatively use event delegation
This basically hooks events to containers rather than every element and queries the event.target in the container event.
It has multiple benefits in that you reduce the code noise (no need to rebind) it also is easier on browser memory (less events bound in the dom)
Quick example here
jQuery plugin for easy event delegation
P.S event delegation is pencilled to be in the next release (1.3) coming very soon.