Font Awesome v5 alongside Font APEX

Font APEX is preferred most of the time but sometimes there are icons I really want to use which are not (yet) included. For these cases I want to load the latest Font Awesome library.

It is possible to load Font Awesome instead of Font APEX by opening Shared Components -> Themes -> Universal Theme, and setting Custom Library File URLs to the location of the library (wherever you have loaded it). However, this replaces the Font APEX font completely so you can’t use both at the same time using this method.

These regions are shown in the same page; the first region uses a Font APEX icon, the second uses a Font Awesome 5 Free icon.

In order to use both at the same time, I’ve downloaded the latest free version of Font Awesome 5 from here (fontawesome.com), taken a copy of the file css/all.css and edited it to replace all occurrences of “.fa” with “.fa5” (if you use CSS precompiler you can do this by editing the appropriate variables file, e.g. _variables.less). This is necessary because the “fa” class prefix would conflict with Font APEX. I named my custom file “fa5.css” and created a minified version as well.

On my web server I created the folder /fa5 under my public html folder, and copied the following files / folders into it:

  • /fa5/css/fa5.css
  • /fa5/css/fa5.min.css
  • /fa5/webfonts/* (all contents)

In my APEX application, in the Universal Theme properties I set:

  • Custom Library File URLs = /fa5/css/fa5#MIN#.css
  • Custom Prefix Class = fa5
  • (optional) Custom Classes = (comma-delimited list of your favourite icons)
Theme attributes to load a custom library.

Alternatively, you could upload the library into your Static Application Files and load them from there.

Files loaded into Static Application Files.
Theme settings to load the custom library from Static Application Files.
If you set the Custom Classes attribute on the theme, you get them listed for convenience in the Pick Icon / Custom list. It doesn’t show previews of the icons, however, since I don’t know how to load a custom library into the APEX builder environment itself.

There’s not enough room in the Custom Classes attribute to list every single icon, unfortunately. You might choose to include just the ones you use frequently. I’ve selected a number of them and listed them here if you want my list: https://github.com/jeffreykemp/sample/blob/master/fontawesome/fa5_selection_custom_icons.txt

If I want my page to use an icon from Font APEX, I use the fa- icons as usual, e.g. fa-apex. Where I need an icon from Font Awesome, I have to include both the fa5 class as well as the icon class, e.g. fa5-restroom. For brand icons, of which Font Awesome has a large selection, the class is fa5b, e.g. fa5b fa5-amazon-pay. Font Awesome also includes a range of modifiers including sizes, spin, pulse, rotating, mirroring, and stacking.

The spin and pulse effects are not visible in the screenshot above. A live demo can be viewed and examined here: https://jk64.com/apex/f?p=TEST:FA5:0.

You are, of course, asking, can I stack two icons AND spin just one of them? The answer, of course, is yes:

Issue #1: Featured Hero Region Icon

When I tried to use a Font Awesome icon in a Hero region with the “Featured” style, the font failed to load. This is because the “Featured” style overrides the font-family causing it to fail to use the Font Awesome font. To fix this, on the page I added the following CSS:

.apex-icons-fontapex .t-HeroRegion--featured .t-HeroRegion-icon.fa5:after,
.apex-icons-fontapex .t-HeroRegion--featured .t-HeroRegion-icon.fa5:before
  { font-family:'Font Awesome 5 Free'!important; } 

Issue #2: Navigation Menu Icon

In a navigation menu, APEX includes the “fa” class which controls the positioning of the icons in the menu, but it also overrides the font library and fails to load the icon from Font Awesome. To fix this, I further edited my fa5.css file (as well as the minified version) to add the following:

.fa.fa5:before, .fa.fa5:after {<br>
    font-family: 'Font Awesome 5 Free' !important;<br>
}

Bonus: Using an Icon Stack for a Region Icon

The Icon attribute on a region can only be used to provide a class (or list of classes) to serve as the icon for the region. To use a Stacked icon in this case is impossible as the stack must be specified using a span with nested nodes for each icon in the stack. A workaround for this is to use some jQuery to modify the html at runtime, as follows:

  1. Set the region’s Static ID, e.g. stacked
  2. Set the region’s Icon attribute to one of the icons in the stack (just so that there is something shown if the javascript is delayed), eg. fa5-camera
  3. Add this to the page’s Execute When Page Loads (this example is for a Hero region:
var stackCameraBan = '
<span class="t-HeroRegion-icon t-Icon fa5 fa5-stack">
  <i class="fa5 fa5-camera fa5-stack-1x"></i>
  <i class="fa5 fa5-ban fa5-stack-2x" style="color:Tomato"></i>
</span>';

$("#stacked span.t-HeroRegion-icon.fa5").replaceWith(stackCameraBan);

It’s a messy kludge, and you’ll have to adapt it if you want to use it in other region templates (check what the span class is), but if this provides significant business benefit then it might be worthwhile.

Comparing Font Awesome 5 Free with Font APEX

I’ve loaded lists of all the icons in the Font Awesome 5 Free and the Font APEX libraries into a table and created a little application that allows me to compare them.

You can browse the list here: https://apex.oracle.com/pls/apex/jk64/r/fa5/home

  • 348 icons appear in both libraries
  • 722 are unique to Font APEX
  • 1,089 are unique to Font Awesome 5 Free
  • 2,159 total

Note: these stats are not perfect because some of the icon names are slightly different between the libraries – for example, all of the “hand” icons have slightly different names between the two libraries.

You can download all the source files (including the APEX icon comparison list application) from here: https://github.com/jeffreykemp/sample/tree/master/fontawesome

References


Friendly URL structure

Oracle has updated apex.oracle.com to APEX 20.1 which includes among other features the new “Friendly URL” option. The legacy URL structure concatenated a string of parameters into a single “p” parameter, which works fine; but it can make it difficult to configure web server rules to match and rewrite URLs. Apart from the application ID or alias (the first part), all the parameters are optional; if all were specified the URL will be something like this (line breaks added for clarity):

f?p=SAMPLE_DB_APP:HOME:16801234560918:myrequest:mydebug
  :myclearcache:myitems:myvalues:myprinterfriendly
  &p_trace=mytrace
  &cs=19A56DBFDXXXE4DF293C96D786
  &c=jk64

In this example, the application alias is used (SAMPLE_DB_APP) and page alias (HOME) followed by the session ID etc. I’ve also specified the workspace (jk64) using the “c” query parameter.

In APEX 20.1 if you edit your Application Properties, you will see the new “Friendly URLs” setting.

With this setting turned on, URLs generated throughout the application will take this form (this is not exhaustive, there are other query parameters supported as well):

/pls/apex/jk64/r/sample_db_app/home
   ?myitems=myvalues
   &request=myrequest
   &clear=myclearcache
   &debug=mydebug
   &printerFriendly=myprinterfriendly
   &session=16801234560918
   &p_trace=mytrace
   &cs=19A56DBFDXXXE4DF293C96D786

When the documentation says the URLs should be “easier to read” I’m pretty sure they mean “by developers”, not end users. I suppose this means the URLs make more sense to developers of other web-based applications, because they conform better to REST URL conventions.

In its simplest form, the URL generated by APEX will include just the workspace path prefix, application, page, and session ID:

 /pls/apex/jk64/r/sample_db_app/home?session=16801234560918 

Calling APEX_PAGE.GET_URL generates the URLs correctly for the application according to whether the Friendly URL setting is on or not.

I noticed the following features of this new format:

  • The URL generated by APEX_PAGE.GET_URL now includes a full path (excluding the domain).
  • Instead of the “c” workspace query parameter, the application’s Path Prefix (which could be set to something other than the workspace name) is used (jk64 in my example). This is not the workspace name, although in most cases it usually will happen to be the same because it’s defaulted that way. This attribute is set at the workspace level, under Administration / Manage Service / Set Workspace Preferences / SQL Workshop.
  • If not specified, the application and page alias will be used rather than the application or page ID, which is nice.
  • Even if you specify the application or page alias in uppercase, APEX_PAGE.GET_URL returns them in all lowercase.
  • The more important attributes relevant to a user navigating the application are now further towards the start of the URL, such as page and item values, so they will be more likely to be noticed by the end user.
  • The “/r/” bit in the URL is just that. It’s just “r” and can’t be anything else, don’t ask me what it means. EDIT: apparently it stands for “router”

If your users have bookmarked your application using the legacy URL format, you can still safely upgrade your application to use Friendly URLs because both are still supported. This also means that if you have some old code that generates links programmatically they should still work the same (although it is best practice to call APEX_PAGE.GET_URL for this purpose).

In case you’re wondering, it is not possible to change the URL format when calling APEX_PAGE.GET_URL, it will follow your application’s Friendly URL setting. If you call APEX_PAGE.GET_URL for another application, it will return the correct format of URL for the target application. If you call APEX_PAGE.GET_URL for an application that does not exist, it will return the URL in the legacy format.

Existing applications after upgrading, or ones you import from an older version of APEX, will still use the legacy URL syntax. New applications will use the new Friendly URLs by default – but you can revert them to the legacy URLs if you wish.

On a side note, in earlier versions when you create a new application the application alias was set to the application ID by default. In APEX 20.1, a new application will have an application alias generated from the initial application name; when I tried it, it added a number as well for some reason.

For obvious reasons, existing code that parses the URL (e.g. in javascript on the client) will probably break. This is a fairly rare thing but does happen (such as in a plugin of mine which I’ll need to fix).

At this very early stage, the legacy URL format is still fully supported – I imagine it will eventually be deprecated, but not yet.

Finally, I’d like to point out some entries on the APEX Feature Requests site:

Our patience has been rewarded 🙂