Showing posts with label html. Show all posts
Showing posts with label html. Show all posts

Thursday, May 30, 2013

How do I turn off format autodection in Safari?

Always check out the original article at http://www.oraclequirks.com for latest comments, fixes and updates.

Your Apex mobile page looks weird because Safari is formatting automatically certain strings containing numbers mistaking them for telephone numbers?
You just need to add a meta tag in the head section of the HTML page (either in the header attribute of the relevant pages or at the template level, whichever you prefer).

 <meta name="format-detection" content="telephone=no" />  

It's that simple.

Tuesday, November 03, 2009

Zero ajax label help tooltips for Apex?

Always check out the original article at http://www.oraclequirks.com for latest comments, fixes and updates.

A couple of weeks ago i finally managed to complete a quick demo page showing a technique for displaying label tooltips without using Ajax or Javascript.
In practice, this means displaying the help text associated with the page item inside a sort of balloon that pops up whenever the mouse cursor hovers above the label link.
The floating label tooltip is rendered using CSS styles, which means that the whole thing is carried out on the client side, without the need of an extra round trip to the server to get that piece of information.
If we are talking of performance improvements, any technique that saves an additional request to the database should be considered positively.

This technique has been invented by Stuart Nicholls and i merely adapted it for use with Apex, with minor differences.
Stuart's site is very inspiring for anyone who wants to leverage the power of CSS stylesheets to achieve cool visual effects without resorting to the omnipresent javascript and i encourage everyone to have a look at it.

Basically the CSS technique consists in retrieving the help text of all the items involved upfront, format them using certain HTML tags that are matched by rules in the CSS stylesheet.
This at first may seem a contradiction, as i stated that the whole purpose of this was to save a request to the database, but if you compare this to a technique involving Ajax requests, it should be clear the advantage:
with the Ajax approach, a request is sent *every* time the cursor moves over a label link, no matter if the user already did it a few seconds or minutes before, while in the other case, the database request is made using a fast bulk collect statement retrieving all the involved labels in one shot, then it can be rendered as many times as necessary without accessing the db anymore, even if the user moves back and forth from other pages as the content is cached in session state.

Of course there are also a few limitations with this technique which can make it unsuitable for certain situations, for instance it can become unpractical for large texts or when the text contains links that you expect a user to click on. In these situations it makes sense to stick to the Ajax approach, and you could easily mix both on the same page as desired by choosing different label templates. The other major objection to this approach can be in the requirement of creating hidden items to hold the text. Of course it would be much better if we could have a substitution string for retrieving the help text at page rendering time, but i don't know if the Apex team is willing to include the code to support this in a future release.

Given the aforementioned prerequisites, here are the components to get it done in Apex (item names refer to the demo page hosted on apex.oracle.com:
-- before header process, conditional on (P11_ITEM1_HELP is null)
-- the process will run only the first time the page is loaded
-- thereafter values cached in session state will be used.
-- Each item with tooltip needs a hidden item to store the text
-- i.e. P11_ITEM1 is matched by P11_ITEM1_HELP.
declare
type vc2_4k_tab is table of varchar2(4000) index by binary_integer;
type vc2_255_tab is table of varchar2(255) index by binary_integer;
type vc2_coll is table of varchar2(4000) index by varchar2(255);
apex_item_names vc2_255_tab;
apex_item_help_text vc2_4k_tab;
apex_item_help_coll vc2_coll;
begin
select item_name, item_help_text
bulk collect into
apex_item_names, apex_item_help_text
from apex_application_page_items
where application_id = :APP_ID
and page_id = :APP_PAGE_ID
and item_label_template = 'Optional Label with Tooltip';

for i in 1..apex_item_names.count loop
apex_item_help_coll(apex_item_names(i)) := apex_item_help_text(i);
end loop;

:P11_ITEM1_HELP := apex_item_help_coll('P11_ITEM1');
:P11_ITEM2_HELP := apex_item_help_coll('P11_ITEM2');
end;


-- content of the CSS stylesheet (either inline or external)

a.t18tooltip {
text-decoration:none;
font-weight: bold;
}

a.t18tooltip cite {
display:none;
}

a.t18tooltip:hover {
cursor: help;
border:0;
position:relative;
z-index:500;
text-decoration:none;
}

a.t18tooltip:hover cite {
cursor: help;
display:block;
position:absolute;
top:20px;
left:-25px;
padding:5px;
font-weight:normal;
font-style:normal;
color:#000;
border:1px solid #888;
background:#ffc;
width:150px;
text-align: left;
}

a.t18tooltip:hover cite em {
position:absolute;
left:20px;
top:-6px;
width:11px;
height:6px;
background:#fff url(#WORKSPACE_IMAGES#tooltip.gif) 0 0;
display:block;
font-size:1px;
}

<a class="t18tooltip" href="javascript:popupFieldHelp('#CURRENT_ITEM_ID#','&SESSION.')">
Test Item 1<cite><em></em>&P11_ITEM1_HELP.</cite>
</a>


Please note that #WORKSPACE_IMAGES# in the case of Apex with EPG (Embedded PL/SQL Gateway), will generate one db roundtrip. As of Apex 3.1 images in the repository are cached by the browser, however there is still one request to retrieve the E-TAG attribute and compare it with the cached version. If the HTTP server is not EPG, then there won't be any db requests, just a web server request. This tiny image is required to show the nice "spike" pointing to the label, but it can be omitted or perhaps you can dare to implement the second method for rendering CSS tooltips slightly more elaborated to achieve the effects by means of border graphics only.

Updated January 26, 2010
After further thinking, i made some improvements to the technique shown above.
First of all i found out a sort of hack that allows me to put all the required HTML code inside the label template, thereby simplifying the whole thing. No more HTML tags inside the label text and no more explicit reference to the hidden item holding the help text:

-- this code goes into the before label template
<label for="#CURRENT_ITEM_NAME#" tabindex="999">
<a class="t18tooltip" href="" tabindex="999">


-- this code goes into the after label template
<cite><em></em>&#CURRENT_ITEM_NAME#_HELP.</cite><
</a>
</label>


The trick consists in building a dynamic substitutions by means of #CURRENT_ITEM_NAME#, appending the suffix _HELP. Apex processes the label template substitution variable first, then it uses the resulting string for the subsequent substitution of the resulting page item (at  a later stage of the label rendering), on the assumption that the help text is held by a hidden page item whose name is made up of the item name plus the _HELP suffix.

As i said this gives me two advantages compared to the initial method:
  1. i do not need to use HTML tags inside the label text
  2. i do not need to manually specify the hidden item name every time
Cool!

Secondly, i came up with a generalized on-demand process that i invoke as a before header process in the relevant pages (the pages containing items with tooltips). This code is completely generic so i don't even need to bother specifying the items names one by one, so this is another improvement over the initial version.


procedure init_page_tooltips (
p_app_id in pls_integer,
p_page_id in pls_integer,
p_temp_name in varchar2
as
type vc2_4k_tab is table of varchar2(4000) index by binary_integer;
type vc2_255_tab is table of varchar2(255) index by binary_integer;
apex_item_names vc2_255_tab;
apex_item_help_text vc2_4k_tab;
begin
select item_name, item_help_text bulk collect
into apex_item_names, apex_item_help_text
from apex_application_page_items
where application_id = p_app_id
and page_id = p_page_id
and item_label_template = p_temp_name;

for i in 1..apex_item_names.count loop
APEX_UTIL.SET_SESSION_STATE(apex_item_names(i)||'_HELP', apex_item_help_text(i));
end loop;
end;


Note that APEX_UTIL.SET_SESSION_STATE uses a rather uncommon approach when it comes to report errors.
Undefined items will not generate an error at the time of calling the API (that is inside the loop), but the Apex error page will be displayed later. In other words we cannot trap the error inside our procedure because this API sets some status variable inside the Apex engine. As a consequence, be aware that a missing help element will "break" the page.
I hoped i could work around this, but, up to date, i could not find how. This is not a big problem though because we do want to create such elements anyway, so the workaround is to change the label template to a different value until the help item holder has been added to the page.

Another optimization consists in specifying a non default value for the aforementioned on-load before header process: instead of keeping the default setting of "Once per page visit" and then making the process conditional, as illustrated in the article above, i chose "Once per session or when Reset", so it runs only the first time you load a page.

Last, be sure to remove any nowrap or nowrap="nowrap" from the HTML Table Cell Attributes in the Label section of the page item (not the help container), otherwise the tooltip will not fit in the box.

See more articles about Oracle Application Express or download tools and utilities.

Tuesday, June 26, 2007

Accessibility, TABINDEX, ACCESSKEY and a weird Apex quirk

I am eventually back to my desk after an exciting week spent traveling across USA, where most of my time was spent either on a aircraft or in a queue waiting to be searched by security agents, plus a couple of days in Daytona Beach, at the ODTUG Kaleidoscope 2007, so now you know why i didn't update my blog in the last 9 days.
Actually if i reckon all the hours wasted in the long lines of people at the airports, i could have written a dozen new blog entries!

You can find a variety of detailed comments on the ODTUG Kaleidoscope 2007 in other blogs, see the work done by Dimitri Gielis for example (by the way, thank you Dimitri, i enjoyed the meetings with you and the other APEX gurus!), including photos of the attendees and snapshots of the slides being shown.

Even if many of the topics were already known to me, it was an opportunity to learn about certain details that i had overlooked in the past and HTML's TABINDEX attribute is one of such cases.
Scott Spendolini, President of Sumnertech, included a reference to this form element property in his presentation (that spanned many aspects of Oracle Application Express by the way) and i realized that i had never paid too much attention on web accessibility issues previously.

TABINDEX plays an important role in the keyboard navigation of a web page and you can read more about the rules that a W3C HTML 4.0 compliant browser should follow when it comes to move the so-called cursor focus.

If you are mousaholic, it can be of scarce importance to you, however there are a lot of people out there, especially the visually impaired ones, who are forced to use this approach when browsing pages, consisting in hopping from one form element to the next one, in the order specified by the various TABINDEXex, so it is something that you might want to consider carefully when creating pages with Oracle APEX.

Not only, if you are developing web pages on behalf of governmental institutions, you may be bound to certain standards like Section 508 of the Rehabilitation Act in the USA or other similar requirements by other countries.

If you are not yet convinced, then imagine that your mouse breaks down or it runs out of batteries and you there are no replacements at hand.

You could be forced to navigate web sites using the keyboard.
So it is not something that you can quickly dismiss without any concerns.

There is nothing particularly difficult in the subject but it is important to understand how the whole thing works in an APEX page, where there is no specific TABINDEX property defined as such, with the only exception of the page level property called Cursor Focus, that allows either to set the focus on the first item of a page (in Apex Region/Items order) or to not focus any particular item.



So, how does a typical Apex page work as far as TABINDEX is concerned?

If you look at the page source of an Apex page, you will find a lot of elements with TABINDEX="999", that is default value provided by Apex.
If you opted for having the focus on first item of page, then you should find a script element near the bottom of the page that looks like the following:
<script type="text/javascript">
<!-- first_field('item');

//-->
<script>

Where item is the name of the first item in the displayed sequence of items defined in Apex.
As you see, Apex doesn't tamper with TABINDEXex to obtain the result but instead it uses a javascript program to show the cursor in the relevant position.

However, while working on this topic, i found out a really strange quirk affecting this configuration setting. The problem seems to be known to some extent, i found a couple of messages in the OTN forum where people talk of a similar problem but the real reason was not clearly identified, so i invested some time to figure out where was the catch exactly.

I could not try with other Apex versions, so what i am saying applies to version 3.0.0.00.20 basically, however i do believe that it holds for previous ones as well.

In short, this piece of Javascript is not included even if you selected the relevant option as outlined above, when the item on which you want to put the focus is of type "text field always submits page when Enter is pressed".

In other words, if item P1_XXX is of that special type *AND* it is also the first one to be displayed, then it cannot receive the focus because, for some unknown reason, the link to the javascript code will be omitted.

Is it a bug or is it a feature? Don't ask me.

Aside from this Apex alleged quirk, the general rule (explained in the document linked above) defines that the focus will move between items in character stream order, that is in order of appearance within the HTML source files when all TABINDEX values are the same and, by default, in APEX they are all set to 999.

If the focus is on the first element of the page (whatever this means...), pressing the TAB keys (TAB or SHIFT TAB), will take you to the next or previous element as they appear in the source file, which can be a consistent behavior for most pages actually.

Frankly speaking i made several attempts with different browsers in order to understand if their behavior was consistent with the aforementioned rules but i had to give up.

It seems to me that both latest versions of Internet Explorer and Firefox do not follow these rules when it comes to decide which element is the first to receive the focus, but once you have manually set the focus on some page element, then the cursor is moved consistently according to the rules.

So, unless you are satisfied with the built-in order that comes off the region/items sequencing combination, you may want to rearrange items using a different order that is more consistent from the user experience point of view.

For instance, if you have a page where the main input fields items are in a central region surrounded by other regions and items on both sides, you are probably better off setting the TABINDEX of each page item manually.
Enabling cursor focus on the first item of a page doesn't interfere with TABINDEX ordering although you can easily achieve inconsistent settings because there is no direct relationship between Apex's item sequence and the TABINDEX values you define in the item's attributes.
For example, you may have a page where you set TABINDEX="10" for the first item displayed and TABINDEX="1" on an the fifth element displayed.
Clearly this doesn't make much sense, but there is nothing to stop you from doing it.

Setting TABINDEX or ACCESSKEY (see below for more on ACCESSKEY) is accomplished in the following ways, depending on the item element type:

  1. Standard items:

  2. Standard buttons (either HTML, image or template based buttons):

  3. Special button items (HTML buttons):
  4. Special buttons (image or template based buttons):

Note that if you click on the Attributes label in these forms, the online help will suggest exactly this type of usage for this attribute property. Also, in order to successfully set the property, the button template must contain the #BUTTON_ATTRIBUTES# substitution string.

All right, but what kind of page elements come with this TABINDEX attribute?
As per the W3C document, eligible HTML tags are only: A, AREA, BUTTON, INPUT, OBJECT, SELECT, and TEXTAREA.

  • A maps to links, either internal pages or external URLs, including pop-up select lists and date pickers, as well as image or template based buttons and labels with help.
  • AREA is not mapped to any built-in page element.
  • BUTTON maps to HMTL buttons (both for region and item buttons).
  • INPUT maps to text fields, checkboxes and radiobuttons in their various forms.
  • OBJECT is not mapped to any built-in page element.
  • SELECT maps to combo boxes in their various forms.
  • TEXTAREA maps to textarea items in their various forms.

Another thing worth mentioning is the fact that in Apex items are often preceded by a label.
If the label is created using a template and the template includes a link to a pop-up help window, you must consider that the link is made up of an A tag embedding an image or text and that it can receive the focus. If you look at one of these label templates you will probably see a hardcoded TABINDEX="999", if any.

Currently i don't know of any simple way of dynamically setting a different value for TABINDEXex contained in label templates, because the problem is to keep it in sync with the underlying form element's TABINDEX value. My guess is that both values should be the same in order to mantain a consistent navigation order, but probably the only way to do that is to update the label's TABINDEX property values by means of some javascript code that loops on the target elements at onLoad time. But this is easier to say than to do.

Finally, let's talk about ACCESSKEY. This attribute specifies a keyboard shortcut for quickly moving the cursor focus from one element to another. For instance, in a login page you could define value "P" as ACCESSKEY for the User ID text field and "P" for the password. This setting would allow a user to get to the desired field by pressing either ALT+U or ALT+P on a Windows PC equipped with an English version of Internet Explorer 7 .
Practically speaking, one can add ACCESSKEY definitions in the same way as TABINDEX (see pictures above).

Unfortunately this is pure academical theory.

The blunt reality is that browser implementations and language localization differences make ACCESSKEY completely unusable unless you are 100% sure of the browser version that users will use to navigate your application.

Just to make a short list of main ACCESSKEY usage problems i found so far:
  • ALT+D will not work because both IE and Firefox perform the address bar activation.
  • ALT+U will not work in spanish version of IE because it opens the Help (Ayuda) menu.
  • ALT+ char for any characters mapped to the built in menu functions will not work either (language edition dependent).
  • Firefox implemented changes between versions 1.5 and 2.0., apparently in 2.0 one must press SHIFT+ALT+char, and char must not be a number, but i could not get it to work, no matter what the character was in FF 2.0.0.4.
  • in Safari for Mac O/S, you must use Ctrl+char supposedly, however a page working with IE and Opera failed to work for some unknown reason.
  • in IE7, when accesskey is attached to an A element, then you must also press Enter to follow the link.
  • probably many other amenities i had no time to try out.
A far more positive experience was with Opera browser, where a user can activate accessibility keys by pressing SHIFT+ESC first and the browser will display a preview list of all the available shortcuts, thereafter by pressing char the cursor focus can be set onto the desired element.

In the end, given the state of the art, i don't see how one can get ACCESSKEY to work reliably in mixed environments, so the only accessibility feature that one can reasonably implement in Apex remains the TABINDEX attribute.

yes you can!

Two great ways to help us out with a minimal effort. Click on the Google Plus +1 button above or...
We appreciate your support!

latest articles