Almost all web pages that I see designed to set the focus to an input box add the code into a body onload event. This causes the code to execute once the entire html document has loaded. In theory, this seems like good practice.
However, in my experience, what this usually causes is double work on the user, as they have already entered data into two or three fields and are typing into another when their cursor is jumped back without their knowledge. I've seen a staggering number of users type the last 2/3 of their password into the beginning of a username field. As such, I've always placed the JS focus code immediately after the input to insure there is no delay.
My question is: Is there any technical reason not to place this focus code inline? Is there an advantage to calling it at the end of the page, or within an onload event? I'm curious why it has become common practice considering the obvious practical drawbacks.
A couple thoughts:
I would use a framework like jQuery and have this type of code run on $(document).ready(.... window.onload doesn't run until everything on the page is fully loaded, which explains the delay you have experienced. $(document).ready(... runs when jQuery determines the DOM has been loaded. You could probably write the same sort of logic without jQuery, but it varies by browser.
I prefer to keep my Javascript separate from my HTML because it allows for a cleaner separation of concerns. Then your behavior is then kept separate from your document structure which is separate from your presentation in your CSS. This also allows you to more easily re-use logic and maintain that code — possibly across projects.
Google and Yahoo both suggest placing scripts at the bottom of the html page for performance reasons.
The Yahoo article: http://developer.yahoo.com/performance/rules.html#js_bottom
You should definitely place the script in the appropriate place if it means the correct user experience -- in fact I would load that part of the script (Used for tabbing inputs) before the inputs to ensure it always works no matter how slow the connection.
The "document.ready" function allows you to ensure the elements you want to reference are in the dom and fires right when your whole document dom is loaded (This does not mean images are fully loaded).
If you want you could have the inputs start out as disabled and then reenable them on document ready. This would handle the rare case the script is not ready yet when the inputs are displayed.
Well if you call it before whole page has loaded you really don't know if the element already has been loaded when you make your call. And if you make your call in pre-hand you should check if the element really exists even if you know it always should.
Then to make the call inline, which might seem ideal. But on the other hand it's really bad if a page takes that long to load that you can make several inputs during the loading phase.
Also you could check if input has been made etc.
Also it is possible to check if any input on page contains focus if($("input::focus, textarea::focus").length)... and otherwise set focus on desired input.
Use the autofocus HTML attribute to specify which element should initially receive focus. This decouples JavaScript and gracefully degrades in older browsers.
Related
I'm trying to figure out if altering the DOM of a website will present any accessibility problems. I am placing all of the jQuery in a $(document).ready() function. Will this cause any accessibility issues with the altered elements?
We don't have access to the theme template HTML files, only CSS and JS files. So for example I'm adding a div into our theme using$('[element name]').before('<div>[div content here]</div>') will this content be as accessible as the rest of the DOM as long as I include all the appropriate aria attributes etc.?
In theory, you shouldn't rely on JavaScript to produce the whole HTML code of your site, it's basically a bad practice.
However, it's exactly how big frameworks like angular and react work.
Given that 99% of browsers support JavaScript, it's in fact no longer a problem nowadays.
The true answer is in fact both yes and no, it depends. It depends on the actual HTML code injected.
The key point is that, you must have the same care with generated code as with the code directly written in HTML by hand, i.e. be careful on headings, form labels, alt texts, ARIA attributes if you need them, etc. all the time and in particular each time you add/remove something in the DOM. Additionally, you must pay attention to where the focus is or might be and a few other things.
It's often overlooked precisely because some people assume that it's anyway not accessible, what isn't true.
In order to be accessible, a site with dynamic contents must be accessible at any moment. If it isn't always the case, then you will lose users in need of accessibility at some point. In practice the loss of accessibility often happens at the most critical moment: checkout or paiement, maybe not because of your fault if the paiement site isn't accessible.
You might even improve accessibility by manipulating the DOM via JavaScript (JS). So no, per se, manipulating the DOM does not pose accessibility issues.
If you cannot control the HTML, and the theme is badly accessible, all you can do to improve that is using JavaScript. Think adding role attributes to generic <div> elements. Also, CSS-only solutions seem appealing, but are often not exposing the appropriate state via ARIA-attributes to assistive technology, which needs to be corrected via JS.
Whether your manipulations produce problems or improve accessibility, therefore depends strongly on your implementation.
Here are some examples.
Adding or Removing Content
When adding content, like in your example, it depends on where that content is added in the document, and at which moment.
If it’s being added on DOM Ready, there should be no issue (One exception might be live regions added after the DOM loaded). But if it’s being added at arbitrary moments, it’s problematic.
The Web Content Accessibility Guidelines (WCAG) refer to this as a Change of Context, which must not happen on focus, on input and on user request
See A change of content is not always a change of context. Changes in content, such as an expanding outline, dynamic menu, or a tab control do not necessarily change the context, unless they also change one of the above (e.g., focus).
If it’s being added after DOM Ready, it should happen on user request, or must be a status message and carry the appropriate role to be announced.
For example, in a Disclosure pattern, the aria-expanded of the trigger indicates that new content will become accessible right after the trigger on pressing it. It might just be added to the DOM, depending on the implementation.
Lazy Loading Content
Another, very valid use case would be content that’s added asynchronously. This is tricky to get right, but basically aria-busy can render this more accessible.
I'm trying to identify roughly when the DOM is finished updating after a page is loaded via AJAX on any arbitrary website.
My current method first listens for the chrome.webNavigation.onHistoryStateUpdated event in a background script, then executes a content script in which a MutationObserver detects changes to the website's body. From there, unfortunately, it seems like it's a bit more finicky. If I just wait for the first mutation where nodes are added to the DOM, I wind up in many cases (YouTube, to give one example) where the page is still blank. Other more hacky approaches I've considered include things like just using setTimeout or waiting for the page to reach a certain length, but those seem clearly wide open to exception cases.
Is there a more fool-proof way to detect that the DOM has roughly finished updating? It doesn't necessarily have to be perfectly precise, and erring on the side of triggering late in my use case is better than triggering early. Also it isn't important at all that resources like video and images be fully loaded, just that the text contents of the page are basically in place.
Thanks for your help!
I have an asp.net-mvc website where there is a top section with a bunch of filter information and the middle section is a reports. I now have a few different report formats and I want to toggle between a few reports. I have it working by making them all partial views and loading them via ajax (to avoid loading the common info over and over again) but one issue i realized is that some of the different reports have different javascript that goes along with them. For now, I am loading up all of the javascript files in the main parent page but I realized that I am wasting a lot of resources by download and wiring up all of the jquery events even if i never actually view a report
Is there anyway I can pass some javascript along with downloading a partial view in asp.net-mvc so I only load this and wire up the events "on demand" as required (instead of always)
Of course you can. Just be aware that the effects of the code will stick around even if you later remove the code itself: any functions you defined will remain defined, any listeners you attached will remain attached (as long as their target elements persist)... so it would be a good idea to make a setup() and teardown() methods for the loading code, that you'd invoke from your controlling code, rather than just drop a bunch of code to execute as it loads.
However, I would say it would need to be a rather unique set of circumstances for me to employ this method; for most part, it would be much easier and efficient to just load all the code you need at once, to benefit from client caching if nothing else. Toggle the behaviour of your code, don't toggle the code.
For my current project, I require the facility to be able to remove all functionality from a page, so that it is complete and literal static page. Removing the ability to follow any links, and disabling and javascript listeners allowing content to be changed on the page. Here is my attempt so far:
$("*").unbind().attr("href", "#");
But in the pursuit of a perfect script, and to allow it to work in every eventuality for any possible page (and with the uncertainty of a on liner being effective enough), I thought i'd consult the experts here at stackOverflow.
In summary, my question is, 'Can this be (and has it been) done in a one liner, is there anything this could miss?'. Please break this as best you can.
No. Nothing in this stops meta redirects, or timeouts or intervals already in flight, and it does nothing about same origin iframes (or ones that can become same origin via document.domain) that can reach back into the parent page to redynamize content.
EDIT:
The sheer number of ways scripts can stay submerged to pop up later is large, so unless you control all the code that can run before you want to do this, I would be inclined to say that it's impossible in practice to lock this down unless you have a team including some browser implementors working on this for some time.
Other possible sources of submarine scripts : XMLHttpRequests (and their onreadystatechange handlers), flash objects that canscript, web workers, and embedding code to run in things like Object.prototype.toString.
I did not want to write a lengthy comment so I'm posting this instead.
As #Felix Kling said, I don't think your code will remove the href attributes on every element but rather remove every element and then select their href attributes.
You probably need to write:
$("*").attr("href", "#").detach() ;
to remove the attributes instead of the elements.
Other than that, I doubt that you could remove the event handlers in one line. For one thing you would need to account for DOM level 2 Event registration (only settable with scripting) and DOM level 1 Event registration (via attributes or scripting).
As far as I'm concerned, your best bet is to make a shallow document copy using an XML parser and replace the old document (which you could backup-save to the window).
First: Your code will remove everything from the page, leaving a blank page. I cannot see how it would make the page "static".
$('*').detach();
will remove every element form the DOM. Nothing left. So yes, you remove every functionality in a way, but you also remove all the content.
Update: Even with the change from detach to unbind, the below points are still valid.
Event listeners added in the markup via oneventname="foo()" won't be affected.
javascript: URLs e.g. in images might still be triggered.
Event listeners added to window and document will persist.
See a DEMO.
I have made few changes on this huge JSF page, which is full of Javascript as well. I dont know which change make the problem happen.
The problem is: after some Javascript is executed, all the text fields in the page become readonly. The problem is not occurring in IE7 nor in Firefox. I have debugged all the javascript, there is no errors thrown! And there is nothing telling the fields to become readonly, since its working correctly in IE7.
Not sure what the problem is, could be CSS related? or Javascript? And why is it happening on IE6 only?
Note: "Don't support IE6 is not an option"
While IE may be buggy make trouble in some situations, I'm quite sure this is not an IE bug.
How do you tell the fields are read only? Do you get any optical confirmation or is it just that you can't click them any more? In that case, I'll bet you a beer that is's some invisible DIV or other layout element that, due to some CSS setting, squeezes itself above the input fields.
Try the IE developer toolbar to find out whether it's a layout problem.
If they are really disabled as in <input disabled> you need to show some JavaScript or (better) a link.
Still not sure what happened with that build, but what i was sure about is all the Ajax modifications i did was responsible for the problem.
The scenario was like:
Fill textfield1 (hit getValues1 , then hit a validate Ajax)
Fill textfield2 (hit getValues2 , then hit validate on both values together)
Fill textfield3 (hit getValues3 , then hit validate on all three values)
And a forth time again the same scenario. The page was built by a new to JSF guy, and it was very huge. I took long time refactoring it. But now its much better, each text field still have a getValues Ajax, but instead of validating them after getting all the values, i filter the allowed values on the server by sending the chosen criteria
The scenario now:
Fill textfield1 (hit getValues1 Ajax)
Fill textfield2 (hit getValues2 Ajax with value of 1, and get only allowed values)
... etc
The problem seems to be an Ajax racing conditions and at some moment IE6 was hanging or stuck in a deadlock, im not sure.
Lesson learned, "Refactoring once may take a week, but without every single issue will take longer"
um... don't support IE6??? ;)
Suggest disabling your CSS and seeing if the problem goes away. I'm not aware of any CSS tags that can disable a field, though.
Other than that, debugging is your only option. Remove all your .js and add it back in line-by-line until something breaks.
It will probably be hard for us to help you without seeing some code.
See if the HTML for the page has the 'disabled' attribute set on those INPUT elements. If so, then javascript is being used to enable the elements after the page has loaded. This is a not-uncommon technique to keep users from prematurely trying to interact with a page before all scripts have loaded.
If that's what is happening, then what you've probably done is break the way the script recognizes which elements need to be enabled. Since this is only happening on IE6, it sounds like the script might be doing some esoteric DOM navigation, which broke as a result of changes to the markup or CSS.
Unfortunately this is something you'll have to debug by reverting back to previous versions until you identify the change you made that broke the page.
Based on the other answers here, and some of your comments to them, it seems there is a JavaScript function in your page that sets elements to be enabled or disabled.
In order to help, we would have to see your code. Here is something you can do yourself, though, that would solve your problem:
Find that function (or ANY function) that sets elements in your page to disabled or enabled.
Depending on your development environment, there are different ways to do this, but somehow add a breakpoint there at the function.
Load the page.
Whenever that function is called, code execution will stop at that function. Whenever it stops, make sure that it was supposed to be called (and watch the call stack).
Eventually, you'll hit that breakpoint at a point where you weren't supposed to. Look at the call stack to see what caused it (which function resulted in a call to this function).