{"id":150,"date":"2009-05-23T10:49:40","date_gmt":"2009-05-22T21:49:40","guid":{"rendered":"http:\/\/www.thunderguy.com\/semicolon\/?p=150"},"modified":"2009-12-04T22:40:27","modified_gmt":"2009-12-04T09:40:27","slug":"tooltips-on-disabled-buttons-with-dojo","status":"publish","type":"post","link":"https:\/\/thunderguy.com\/semicolon\/2009\/05\/23\/tooltips-on-disabled-buttons-with-dojo\/","title":{"rendered":"Tooltips on disabled buttons with Dojo"},"content":{"rendered":"<p>Here&#8217;s how to add tooltips to disabled form controls using <a href=\"http:\/\/www.dojotoolkit.com\/\">Dojo<\/a>. The technique could be adapted for use in other frameworks or standalone JavaScript code.<\/p>\n<p>I recently needed to add tooltips to a web application. The specific requirement was that when a button was disabled, there should be a tooltip explaining why. We were using Dojo 1.2. Now Dojo includes a Tooltip class, but it doesn&#8217;t work on disabled elements.<\/p>\n<p>Fortunately, Dojo&#8217;s complex implementation came to the rescue. Dojo injects quite a lot of extra markup around its buttons; in particular the buttons are wrapped with spans. So it occurred to me that I could attach the tooltip to one of the wrappers instead of the button itself. Then even if the button were disabled, the wrapper would still be enabled and the tooltip would appear. The simplest way is just to attach the tooltip to the button&#8217;s parents.<\/p>\n<p>And it worked! Even better, it worked on both Firefox and Internet Explorer. I only tested on FF3 and IE6, but it may well also work on IE7, IE8, Chrome, Safari et al.<\/p>\n<p>Here&#8217;s some code, with an example. It&#8217;s self-explanatory if you have some familiarity with Dojo.<\/p>\n<pre class=\"code\">\r\n<code>dojo.require(\"dijit.Tooltip\");\r\n\r\n\/\/ Some examples of my tooltip functions    \r\ndojo.addOnLoad(function() {\r\n    \/\/ Add a tooltip to the button whose ID is \"save-button\"; only works\r\n    \/\/ if it's enabled\r\n    addTooltip(\"save-button\", \"Save the information to the database.\");\r\n    \/\/ Add an appropriate tooltip to the Delete button that works\r\n    \/\/ even if it's disabled\r\n    var deleteButton = dojo.byId(\"delete-button\");\r\n    var deleteTip = \"Delete the information from the database.\";\r\n    if (deleteButton.attr(\"disabled\")) {\r\n        deleteTip += \" Unavailable because it's too dangerous.\";\r\n    }\r\n    addParentTooltip(deleteButton, deleteTip);\r\n    \/\/ There are two Next buttons with no IDs: add tooltips to\r\n    \/\/ them that work even if disabled\r\n    addParentTooltipByName(\"next-button\", \"Go to the next page.\");\r\n});\r\n\r\n\/** Add a tooltip to any number of nodes passed directly or as IDs. *\/\r\nfunction addTooltip(\/*node or string or array*\/nodes, \/*string*\/text) {\r\n    if (!dojo.isArray(nodes)) {\r\n        nodes = [nodes];\r\n    }\r\n    \/\/ connectId can be an id or a node (not that you'd know from the\r\n    \/\/ documentation) or an array of ids and nodes\r\n    new dijit.Tooltip({connectId: nodes, label: text});\r\n}\r\n\/** Add a tooltip to all form elements with the given name. *\/\r\nfunction addTooltipByName(\/*string*\/name, \/*string*\/text) {\r\n    addTooltip(dojo.query('[name=\"' + name + '\"]'), text);\r\n}\r\n\/** Add a tooltip to the parents of all form elements with the given\r\n    name. The tooltips will show even if the element is disabled,\r\n    provided the parent is not disabled. *\/\r\nfunction addParentTooltip(\/*string*\/name, \/*string*\/text) {\r\n    var nodes = dojo.query('[name=\"' + name + '\"]');\r\n    var parents = dojo.map(nodes, function(node) {\r\n        return node.parentNode;\r\n    });\r\n    addTooltip(parents, text);\r\n}\r\n\/** Add a tooltip to the parents of all nodes passed either directly\r\n    or as IDs. The tooltips will show even if the element is disabled,\r\n    provided the parent is not disabled. *\/\r\nfunction addParentTooltipByName(\/*node or string or array*\/nodes, \/*string*\/text) {\r\n    var parents = dojo.map(nodes, function(node) {\r\n        return dojo.byId(node).parentNode;\r\n    });\r\n    addTooltip(parents, text);\r\n}<\/code>\r\n<\/pre>\n<p>You could extend this in lots of ways:<\/p>\n<ul>\n<li>Put it in some fancy namespace<\/li>\n<li>Extend the Tooltip class itself to add these functions<\/li>\n<li>Automatically wrap the control (in case it&#8217;s not a Dojo button)<\/li>\n<li>Use jQuery instead of Dojo \ud83d\ude42<\/li>\n<\/ul>\n<p>When this problem first came up, my colleague David googled for a solution but couldn&#8217;t find one. Hopefully this post has filled the gap.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Here&#8217;s how to add tooltips to disabled form controls using Dojo. The technique could be adapted for use in other frameworks or standalone JavaScript code. I recently needed to add tooltips to a web application. The specific requirement was that when a button was disabled, there should be a tooltip explaining why. We were using [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[33,21],"class_list":["post-150","post","type-post","status-publish","format-standard","hentry","category-general","tag-dojo","tag-javascript"],"_links":{"self":[{"href":"https:\/\/thunderguy.com\/semicolon\/wp-json\/wp\/v2\/posts\/150","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/thunderguy.com\/semicolon\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/thunderguy.com\/semicolon\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/thunderguy.com\/semicolon\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/thunderguy.com\/semicolon\/wp-json\/wp\/v2\/comments?post=150"}],"version-history":[{"count":7,"href":"https:\/\/thunderguy.com\/semicolon\/wp-json\/wp\/v2\/posts\/150\/revisions"}],"predecessor-version":[{"id":277,"href":"https:\/\/thunderguy.com\/semicolon\/wp-json\/wp\/v2\/posts\/150\/revisions\/277"}],"wp:attachment":[{"href":"https:\/\/thunderguy.com\/semicolon\/wp-json\/wp\/v2\/media?parent=150"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/thunderguy.com\/semicolon\/wp-json\/wp\/v2\/categories?post=150"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/thunderguy.com\/semicolon\/wp-json\/wp\/v2\/tags?post=150"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}