IE, generated select boxes, change event and WTF?!

While I was writing a bigger JS project, I needed a generated select box that was filled with its options from somewhere. I tested it in Opera 11 and all was good. Then I opened Firefox and it worked, as it did in Chromium.

Did you notice something?

Yeah – IE is still missing. So fired up IE – 11 even – and, almost needless to say: It did not work 🙁

Normally the select box should fire a change event as soon as an option finally gets selected. While this works as intended in this example taken from MSDN:

<!DOCTYPE html> <html>  <head>   <title>onchange Event Sample</title> </head>  <body>   <h1>onchange Event Sample</h1>   <form>     <p>Select a different option in the drop-down listbox to trigger the <strong>onchange</strong> event.</p> 		<select name="selTest" onchange="alert('Index: ' + this.selectedIndex + '\nValue: ' + this.options[this.selectedIndex].value)">       <option value="Books">Books</option>       <option value="Clothing">Clothing</option>       <option value="Housewares">Housewares</option>     </select>   </form> </body>  </html> 

… it definitely does not work when the whole thing is set up a bit more complex like this (short excerpt, imagine the missing rest):

===================================================== menu.js =====================================================   function Menu() {         this.init(); }  Menu.prototype =  {     menucontainer: null,          foregroundColor: null,     backgroundColor: null,          selector: null,     save: null,     clear: null,     about: null,          init: function()     {         var option, space, separator, color_width = 15, color_height = 15;          this.menucontainer = document.createElement("div");         this.menucontainer.className = 'gui';         this.menucontainer.id = 'gui';         this.menucontainer.id = "menucontainer_menu";         this.menucontainer.style.position = 'absolute';         this.menucontainer.style.top = '0px';                  this.selector = document.createElement("select");          for (i = 0; i < BRUSHES.length; i++)         {             option = document.createElement("option");             option.id = i;             option.value = BRUSHES[i];             option.text = BRUSHES[i].toUpperCase();             this.selector.appendChild(option);         }         this.menucontainer.appendChild(this.selector);     } } ========================================== main.js  ========================================== var brush, BRUSHES = ["foo", "bar",  "", "baz", "bam"];  menu = new Menu(); menu.selector.onchange = onMenuSelectorChange;  /* ...  */ if (!brush)	{ 	brush = new window[BRUSHES[0]](context); }  /* ... */ function onMenuSelectorChange() {     if (BRUSHES[menu.selector.selectedIndex] == "")         return;      brush.destroy();     brush = new window[BRUSHES[menu.selector.selectedIndex]](context);      window.location.hash = BRUSHES[menu.selector.selectedIndex];     menu.selector.blur(); } 

So, what happens with IE here?

If the index was once set programatically, IE simply “forgets” to fire the change event, you can’t even select an option with the mouse. Opening the select box, moving to the option with the mouse and then pressing the [Enter] key surprisingly worked, so the select box was created and the event listener was attached to the select box. It seems that the select box only has a slight focus problem if you want to select something by using the mouse only. In the end it came down to a missing focus problem on the select element.

Solution

I added some extra code for IE – yes I used browser sniffing because I don’t know how to detect b0rked behavior of a browser.

menu = new Menu(); if(navigator.userAgent.indexOf(' MSIE ') > -1 || navigator.userAgent.indexOf(' Trident/') > -1){ menu.selector.onclick = (function() {     this.blur();     this.focus();   });  } menu.selector.onchange = onMenuSelectorChange; 

Not perfect, but it works – which is good enough for me now. If anyone has a better solution: I am willing to learn, please post it in the comments. Thank You!

PS: No, I don’t know what the MS devs were smoking when they implemented that behavior …

Lightweight Javascript SVG Editor

Always when I needed an SVG file for something I fired up Inkscape, even if I only needed a relatively simple image. While Inkscape is quite powerful when it comes to editing importing and exporting vector graphics, it is a memory and CPU hog too, so I was looking for a lightweight variant for simpler tasks.

Check this out:

http://svg-edit.googlecode.com/svn/trunk/editor/svg-editor.html

Fully written in HTML, CSS and Javascript and includes all the necessary tools I need for “normal” SVGs. It even works local.

 

You can download the latest version it in various forms, as zip file for local use, as Chromium extension and even as Opera 11 Widget:

https://code.google.com/p/svg-edit/

 

 

Just another userCSS for this site

Outdated. The forum and blog software was changed in the meantime

One of the first things I did after creating my account here was to write a userCSS for Opera <15. Bigger fonts (120dpi monitor, the standard font sizes used here are too tiny), % width to adapt to the screen (I don’t like fixed with or max-width layouts) and some other small changes …

Work in progress

May contain nuts …

* {     font-family: Candara, "DejaVu Sans", "Bitstream Vera Sans", "Trebuchet MS", Verdana, "Verdana Ref", sans-serif !important; }  * pre, * code {     font-family: Consolas, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier, monospace !important; }  body  {     color: #202020 !important;     font-size: 1.2em !important;     line-height: 1.6em !important; }  div#es-wrap, body div#fd .es-stream-list .type-blog .blog-description, body div#fd.es .es-stream-meta .es-stream-title, body div#fd.es .es-stream-meta .es-stream-title a, div#fd.es .es-stream-content a, div#fd.es .es-stream-content, body div.blog-text, #Kunena div .kcontainer, .mce-content-body, body div#fd.es .es-widget .es-widget-head, body div#fd.es .es-widget .widget-title, body div#fd.es p, #ezblog-body .blog-text p, #ezblog-body .blog-text li{     color: #202020 !important;     font-size: 1em !important;     line-height: 1.6em !important; }  body div#fd.es .es-dashboard .es-container .es-sidebar .fd-nav-stacked a, body div.es.mod-es-menu.module-menu.jmoddiv, div#fd.es .es-dashboard .es-container .es-sidebar .fd-nav-stacked a, div#fd.es .es-widget .fd-nav > li > a, div#fd.es .es-stream-meta .es-stream-title, body div#fd.es .small, body div#fd.es .small > a, body div#fd.es .popbox, #Kunena .ks, #Kunena .kms, #Kunena span.kcat-topics, #Kunena span.kcat-replies {     font-size: 1em !important; }  body.site {     padding: 10px 5px 10px 5px !important; }  .body .container {     padding: 15px !important; }  .container, .navbar-static-top .container, .navbar-fixed-top .container, .navbar-fixed-bottom .container {     width: 90% !important; }  .container {     max-width: 90% !important; }  .row-fluid .span9 {     width: 80.47% !important; }  .row-fluid .span3 {     width: 17.4% !important; }  #Kunena a:link, #Kunena a:visited, #Kunena a:active {     color: #202020 !important; }  #Kunena a:hover {     color: navy !important; }  #Kunena td.kcol-kcatlastpost {     width: 30% !important; }  #aside .module-menu, span4 a {     font-size: 0.9em !important; }  .kmessage-left .kmsgbody .kmsgbody {     font-size: 1.1em !important; }  .kprofile-left {     background-color: #f8f8f8 !important; }  a {     color: #600000 !important; }  .popbox-toolbar a, .media-object.pull-left a {     color: #333333 !important; }  body div.es-mod.mod-es-menu .media:first-child {     margin-top: -7px !important; }  body div.es-mod.mod-es-menu .media .pull-left {     margin-right: 0 !important;     float: right !important; }  body div.es-mod.mod-es-menu .es-avatar > img {     height: 30px !important;     width: 30px !important; }  body div.es-mod.mod-es-menu .es-menu-items {     padding: 10px 0 0 !important; }  i.ies-pencil {     display: none !important; }  div#es-wrap .row-fluid .span4 {     width: 23.5% !important; }  div#es-wrap .row-fluid .span8 {     width: 74.5% !important; }  div#es-wrap .es-widget .small {     float: right !important;     padding-right: 10px; }  body div#es-wrap div.es-mod.mod-es-recent-albums li {     max-width: 50px !important; }  .kavatar {     max-height: 72px !important; }  .kprofilebox {     display: none; }  #Kunena .kmsgtext a:link, #Kunena td.kcol-kcatlastpost a, #Kunena td.kcol-ktopiclastpost a {     text-decoration: underline !important;     color: #5555FF !important;     font-weight: bold !important; }  #Kunena td.kcol-kcatlastpost {     line-height: 1em !important; }    div#es-wrap .photo-content .es-photo-image, div#es-wrap .photo-content .es-photo-tag-viewport {     height: 600px !important; }  body.view-albums .es-album-cover, body.view-albums .album-cover {     display: none !important; }  .media {     margin-top: -20px !important; }  #es-wrap div.media-body div.object-title {     font-size: 0.8em !important;     padding-top: 0.5em !important; }  div#es-wrap li.message-item {     font-size: 1em !important; }  #menu-account, #menu-blog, #menu-settings {     display: block !important; }    #aside .module-menu, span4 a {     font-size: 0.9em !important; }  .kmessage-left .kmsgbody .kmsgbody {     font-size: 1.1em !important; }  .kprofile-left {     background-color: #f8f8f8 !important; }  a {     color: #600000 !important; }  .popbox-toolbar a, .media-object.pull-left a {     color: #333333 !important; }  body div.es-mod.mod-es-menu .media:first-child {     margin-top: -7px !important; }  body div.es-mod.mod-es-menu .media .pull-left {     margin-right: 0 !important;     float: right !important; }  body div.es-mod.mod-es-menu .es-avatar > img {     height: 30px !important;     width: 30px !important; }  body div.es-mod.mod-es-menu .es-menu-items {     padding: 10px 0 0 !important; }  i.ies-pencil {     display: none !important; }  div#es-wrap .row-fluid .span4 {     width: 23.5% !important; }  div#es-wrap .row-fluid .span8 {     width: 74.5% !important; }  div#es-wrap .es-widget .small {     float: right !important;     padding-right: 10px; }  body div#es-wrap div.es-mod.mod-es-recent-albums li {     max-width: 50px !important; }  /* Some special rules for the different sections */  /* FORUM  */  .kavatar {     max-height: 72px !important; }  .kprofilebox {     display: none; }  #Kunena a:link, #Kunena a:visited, #Kunena a:active {     color: #202020 !important; }  #Kunena a:hover {     color: navy !important; }  #Kunena td.kcol-kcatlastpost {     width: 30% !important;     line-height: 1em !important; }  #Kunena .kicon-button, #Kunena .kicon-button span {     line-height: inherit !important; }  #Kunena .kmsgtext a:link, #Kunena td.kcol-kcatlastpost a, #Kunena td.kcol-ktopiclastpost a {     text-decoration: underline !important;     color: #5555FF !important;     font-weight: bold !important; }  #Kunena .kmsgtext a:hover, #Kunena td.kcol-kcatlastpost a :hover, #Kunena td.kcol-ktopiclastpost a :hover {     background-color: #ffffee !important; }  #Kunena .kmsgtext a:visited, #Kunena td.kcol-kcatlastpost a :visited, #Kunena td.kcol-ktopiclastpost a :visited {     color: #000088 !important; }  #Kunena .kmsgtext-quote {     background: #f5f5f5;     border-left: 10px solid #ccc;     margin: 1.5em 10px;     padding: 0.5em 1em 0.5em 3em !important;     quotes: "\201C""\201D""\2018""\2019"; }  #Kunena .kmsgtext-quote:before {     color: #ccc;     content: open-quote;     font-size: 4em;     line-height: 0.1em;     margin-right: 0.25em;     margin-left: -0.75em;     vertical-align: -0.4em; }  #Kunena .kmsgtext-quote:first-child {     display: inline; }  #Kunena .kmsgtext-quote:last-child {     margin-bottom: 0; }  /* ALBUMS */ div#es-wrap .photo-content .es-photo-image, div#es-wrap .photo-content .es-photo-tag-viewport {     height: 600px !important; }  body.view-albums .es-album-cover, body.view-albums .album-cover {     display: none !important; }  .media {     margin-top: -20px !important; }  #es-wrap div.media-body div.object-title {     font-size: 0.8em !important;     padding-top: 0.5em !important; }  div#es-wrap li.message-item {     font-size: 1em !important; }  #menu-account, #menu-blog, #menu-settings {     display: block !important; }  /* BLOGS */  div#ezblog-body div.blog-text a:hover:after {     content: " " attr(href) !important;     color: #ff0000 !important;     background: #ffffff !important; }  div#ezblog-body div.blog-text a {     text-decoration: underline !important;     color: #5555FF !important;     font-weight: bold !important; }   /* NOTIFICATIONS */ .es-notification .media-body { 	margin-top:20px !important; }  /* FIX for NON JS use of the site. Makes the account dropdown accessible. Drawback, If you click on the account, you will see a double dropdown  */ li.toolbarItem.toolbar-profile:hover div, li.toolbarItem.toolbar-profile:focus div { 	display:block !important;  	width: 250px; 	position:absolute; 	z-index:1000; 	background:white; 	border:1px solid #AAA; }

 

Not yet finished because it produces some small quirks with the fonts of the blog post editor but already quite good as a base …

Hat tip to netsrak who brought in some additional ideas 🙂

btw:

Vux777 has created one too, head over to his blog post to view it.

About my old blog pages

… no, apart from a few selected posts I will not import contents from my.opera – but they are not lost, I submitted them “for eternity” to the waybackmachine aka archive.org.

 

If you really think that I wrote something interesting in the past, just look it up there: 

http://web.archive.org/web/20131219060110/http://my.opera.com/QuHno/archive/

 

PS:

If you plan submitting your pages to the archive or even if you occasionally look things up at there, please think about a donation to archive.org. 

Neither web space nor traffic, nor hardware or staff come for free and  they are a non-profit organization. The service is great,  It saved my a**e several times in the past when I needed to look up long gone web page content containing valuable information.  I donated a small amount too to  keep some of their disks spinning for some more time, because I think that the service is important to preserve knowledge that could (and would) otherwise get lost.

Thank you 🙂

Some thoughts about fonts (for math)

What fonts to use for a website that relies heavily on Unicode is quite difficult. Sometimes the look of a font, though quite important to make a good typographic impression, is not of the same importance as a full support of all glyphs you need to show.

While sorting the characters of a Math Keyboard for the JavaScript Graphical / Virtual Keyboard Interface I stumbled over the problem that there is only a small selection of fonts which offer a decent support of the necessary Unicode glyphs. Whereas it would be better for the VKI layout to use a monospace font, especially when it comes to mathematic symbols but true for other “esoteric” symbols too, there are too few monospace fonts installed on the average users system that provide a good Unicode support – even worse:

There are hardly any good (preferably free) monospace fonts available at all.

So, back to the sans-serif family – but:

  • Which one to use?
  • In which order?
  • What to use as fall-back fonts apart from the generic families?

If you use the following declaration:

font-family: Arial, "Lucida Sans Unicode", "Lucida Grande";

all will get messed up because the first font matches on 99.xx% of all MS Windows based systems and several *X*-oid systems too. In this case a character will be taken from “Lucida xxxx” only if it is not matched by Arial, which btw. offers a poor Unicode support – not to be confused with “Arial Unicode MS” which has an excellent support for every days use.

Example of the differences:

  • This is a ⨑ in Arial
  • This is a ⨑ in Lucida Sans Unicode
  • This is a ⨑ in DejaVu Sans

There is a high chance that you might not see the “‘ANTICLOCKWISE CONTOUR INTEGRAL’ (U+2233)” symbol between “a” and “in” at all if you don’t have “DejaVu Sans” installed – but you can see the different widths and heights, kerning and hinting of the fonts anyway. You can hit the “+” key of your keyboard several times to zoom into the page and see the differences in detail if you are using Opera.

The same goes for the Mac font-families Helvetica and Lucida Grande, which come with the system by default.

When it comes to Linux or other *X*-oid systems the situation becomes worse because you can never know what fonts came with the distribution and what fonts didn’t.

So precedence of your font declarations is important, if you want to provide a good Unicode support.

Here is my sorted font stack for an optimized Math display (but this would match most of the other Unicode characters in a very good way too):

{font-family: "Lucida Sans Unicode", "Lucida Grande", "DejaVu Sans", "Arial Unicode MS", Arial, Helvetica, sans-serif;}

Just try it out, its easy to use, but your mileage in CSS-font-stacks may vary.

View out of my Window

This was the first view I saw when I looked out of the window this morning: The first snow.

(OK, not really the first view – but it was still dark when I started my day, so I waited a bit) 

I wonder why the oaks (middle and right tree) still have their leaves – several nights during the last week the temperature went down to -10°C/14°F/263K

Vivaldi