{"id":2917,"date":"2011-08-17T15:38:29","date_gmt":"2011-08-17T22:38:29","guid":{"rendered":"http:\/\/blog.mozilla.org\/addons\/?p=2917"},"modified":"2011-08-17T15:38:29","modified_gmt":"2011-08-17T22:38:29","slug":"panel-anchoring-follow-up","status":"publish","type":"post","link":"https:\/\/blog.mozilla.org\/addons\/2011\/08\/17\/panel-anchoring-follow-up\/","title":{"rendered":"Panel anchoring follow-up."},"content":{"rendered":"<p>Last week <a href=\"http:\/\/blog.mozilla.org\/addons\/2011\/08\/11\/add-on-sdk-faq-widgets-panels\/\">I blogged<\/a> about how to use the Add-on SDK&#8217;s high-level api to display a panel anchored to a widget. I also talked about how the panel implementation has some shortcomings, in particular that it is not currently possible to anchor a panel to a content node using only the high-level apis in add-on-kit.<\/p>\n<p>This is all true, but I thought it might be <del>useful<\/del> fun to show you how to do it anyway. Here is an example extension I wrote using Builder that does implement anchoring a panel to a content DOM node:<br \/>\n<!--more--><br \/>\n<a href=\"https:\/\/builder.addons.mozilla.org\/addon\/1013359\/revision\/33\/\" target=\"_blank\">https:\/\/builder.addons.mozilla.org\/addon\/1013359\/revision\/33\/<\/a><\/p>\n<p>The key part of this implementation that makes it work is the function &#8220;getWindowNode&#8221;: <\/p>\n<pre lang=\"javascript\">\r\nvar {Cc,Ci} = require(\"chrome\");\r\nfunction getWindowNode(selector) {\r\n    try {\r\n        var dom = Cc['@mozilla.org\/appshell\/window-mediator;1']\r\n            .getService(Ci.nsIWindowMediator)\r\n            .getMostRecentWindow('navigator:browser')\r\n            .gBrowser.contentWindow.document;\r\n       \r\n        return dom.querySelector(selector);\r\n\r\n    } catch(e) {\r\n        console.log(e);\r\n    }\r\n}<\/pre>\n<p>The function takes a selector string and returns a handle to the first matching dom node in the current tab. You can then pass the dom handle to panel.show(anchor) and the panel is correctly anchored visually to the node in the page. If you run the extension in Builder you&#8217;ll see the panel is hung directly below the &#8216;mozilla&#8217; logo image:<\/p>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"http:\/\/blog.mozilla.org\/addons\/files\/2011\/08\/anchored.png\" alt=\"\" title=\"anchored\" width=\"333\" height=\"378\" class=\"alignnone size-full wp-image-2925\" srcset=\"https:\/\/blog.mozilla.org\/addons\/files\/2011\/08\/anchored.png 333w, https:\/\/blog.mozilla.org\/addons\/files\/2011\/08\/anchored-264x300.png 264w\" sizes=\"(max-width: 333px) 100vw, 333px\" \/><\/p>\n<p>That&#8217;s great, right? This code <em>happens<\/em> to work, but unfortunately there is no way to guarantee that it will <em>continue<\/em> to work in the future. In particular the hacky way in which I have accessed the current Tab&#8217;s DOM will likely break once Firefox switches to the multi-process model called &#8216;<a href=\"http:\/\/benjamin.smedbergs.us\/blog\/2009-06-16\/electrolysis-making-mozilla-faster-and-more-stable-using-multiple-processes\/\">Electrolysis<\/a>&#8216;. <\/p>\n<p>Now, That doesn&#8217;t mean you should never require chrome in your add-on code, in fact I expect many experienced add-on developers will need access to lower-level apis to write more complex add-ons. What this <em>does<\/em> mean is that you should be aware that the parts of your code that use lower-level apis are inherently brittle compared to those provided by addon-kit. I personally am considering a standard snippet like this:<\/p>\n<pre lang=\"javascript\">\r\n\/** \r\n * XXX WARNING!! Any use of Cc and Ci may break later! \r\n * If you have a bug in a new version of Firefox, check this first!! \r\n * Here be Dragons, etc. \r\n *\/\r\nvar {Cc,Ci} = require(\"chrome\");\r\n\/\/ awesome low-level hacking ensues...\r\n<\/pre>\n<p>The best practice is to break out any code that uses lower-level apis into <a href=\"https:\/\/addons.mozilla.org\/en-US\/developers\/docs\/sdk\/1.0\/dev-guide\/addon-development\/implementing-reusable-module.html\">a separate module<\/a> with its own set of unit tests. That way when you test your add-on against Beta or Aurora builds, you&#8217;ll see problems right away.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Last week I blogged about how to use the Add-on SDK&#8217;s high-level api to display a panel anchored to a widget. I also talked about how the panel implementation has &hellip; <a class=\"go\" href=\"https:\/\/blog.mozilla.org\/addons\/2011\/08\/17\/panel-anchoring-follow-up\/\">Read more<\/a><\/p>\n","protected":false},"author":316,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[44,121,588],"tags":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v22.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Panel anchoring follow-up. - Mozilla Add-ons Community Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blog.mozilla.org\/addons\/2011\/08\/17\/panel-anchoring-follow-up\/\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Jeff Griffiths\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"2 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/blog.mozilla.org\/addons\/2011\/08\/17\/panel-anchoring-follow-up\/\",\"url\":\"https:\/\/blog.mozilla.org\/addons\/2011\/08\/17\/panel-anchoring-follow-up\/\",\"name\":\"Panel anchoring follow-up. - Mozilla Add-ons Community Blog\",\"isPartOf\":{\"@id\":\"https:\/\/blog.mozilla.org\/addons\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/blog.mozilla.org\/addons\/2011\/08\/17\/panel-anchoring-follow-up\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/blog.mozilla.org\/addons\/2011\/08\/17\/panel-anchoring-follow-up\/#primaryimage\"},\"thumbnailUrl\":\"http:\/\/blog.mozilla.org\/addons\/files\/2011\/08\/anchored.png\",\"datePublished\":\"2011-08-17T22:38:29+00:00\",\"dateModified\":\"2011-08-17T22:38:29+00:00\",\"author\":{\"@id\":\"https:\/\/blog.mozilla.org\/addons\/#\/schema\/person\/e2f4c71eb45392ea29162432c3f1d433\"},\"breadcrumb\":{\"@id\":\"https:\/\/blog.mozilla.org\/addons\/2011\/08\/17\/panel-anchoring-follow-up\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/blog.mozilla.org\/addons\/2011\/08\/17\/panel-anchoring-follow-up\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/blog.mozilla.org\/addons\/2011\/08\/17\/panel-anchoring-follow-up\/#primaryimage\",\"url\":\"http:\/\/blog.mozilla.org\/addons\/files\/2011\/08\/anchored.png\",\"contentUrl\":\"http:\/\/blog.mozilla.org\/addons\/files\/2011\/08\/anchored.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/blog.mozilla.org\/addons\/2011\/08\/17\/panel-anchoring-follow-up\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/blog.mozilla.org\/addons\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Panel anchoring follow-up.\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/blog.mozilla.org\/addons\/#website\",\"url\":\"https:\/\/blog.mozilla.org\/addons\/\",\"name\":\"Mozilla Add-ons Community Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/blog.mozilla.org\/addons\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/blog.mozilla.org\/addons\/#\/schema\/person\/e2f4c71eb45392ea29162432c3f1d433\",\"name\":\"Jeff Griffiths\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/blog.mozilla.org\/addons\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/b07ae75dd1a5414bf30d7f773ccfc894?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/b07ae75dd1a5414bf30d7f773ccfc894?s=96&d=mm&r=g\",\"caption\":\"Jeff Griffiths\"},\"description\":\"Jeff is Product Manager for the Firefox Developer Tools and occasional Open Web hacker, based in Vancouver, BC.\",\"sameAs\":[\"http:\/\/canuckistani.ca\/\",\"https:\/\/x.com\/canuckistani\"],\"url\":\"https:\/\/blog.mozilla.org\/addons\/author\/jgriffithsmozilla-com\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Panel anchoring follow-up. - Mozilla Add-ons Community Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blog.mozilla.org\/addons\/2011\/08\/17\/panel-anchoring-follow-up\/","twitter_misc":{"Written by":"Jeff Griffiths","Est. reading time":"2 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/blog.mozilla.org\/addons\/2011\/08\/17\/panel-anchoring-follow-up\/","url":"https:\/\/blog.mozilla.org\/addons\/2011\/08\/17\/panel-anchoring-follow-up\/","name":"Panel anchoring follow-up. - Mozilla Add-ons Community Blog","isPartOf":{"@id":"https:\/\/blog.mozilla.org\/addons\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blog.mozilla.org\/addons\/2011\/08\/17\/panel-anchoring-follow-up\/#primaryimage"},"image":{"@id":"https:\/\/blog.mozilla.org\/addons\/2011\/08\/17\/panel-anchoring-follow-up\/#primaryimage"},"thumbnailUrl":"http:\/\/blog.mozilla.org\/addons\/files\/2011\/08\/anchored.png","datePublished":"2011-08-17T22:38:29+00:00","dateModified":"2011-08-17T22:38:29+00:00","author":{"@id":"https:\/\/blog.mozilla.org\/addons\/#\/schema\/person\/e2f4c71eb45392ea29162432c3f1d433"},"breadcrumb":{"@id":"https:\/\/blog.mozilla.org\/addons\/2011\/08\/17\/panel-anchoring-follow-up\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blog.mozilla.org\/addons\/2011\/08\/17\/panel-anchoring-follow-up\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blog.mozilla.org\/addons\/2011\/08\/17\/panel-anchoring-follow-up\/#primaryimage","url":"http:\/\/blog.mozilla.org\/addons\/files\/2011\/08\/anchored.png","contentUrl":"http:\/\/blog.mozilla.org\/addons\/files\/2011\/08\/anchored.png"},{"@type":"BreadcrumbList","@id":"https:\/\/blog.mozilla.org\/addons\/2011\/08\/17\/panel-anchoring-follow-up\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blog.mozilla.org\/addons\/"},{"@type":"ListItem","position":2,"name":"Panel anchoring follow-up."}]},{"@type":"WebSite","@id":"https:\/\/blog.mozilla.org\/addons\/#website","url":"https:\/\/blog.mozilla.org\/addons\/","name":"Mozilla Add-ons Community Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blog.mozilla.org\/addons\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/blog.mozilla.org\/addons\/#\/schema\/person\/e2f4c71eb45392ea29162432c3f1d433","name":"Jeff Griffiths","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blog.mozilla.org\/addons\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/b07ae75dd1a5414bf30d7f773ccfc894?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/b07ae75dd1a5414bf30d7f773ccfc894?s=96&d=mm&r=g","caption":"Jeff Griffiths"},"description":"Jeff is Product Manager for the Firefox Developer Tools and occasional Open Web hacker, based in Vancouver, BC.","sameAs":["http:\/\/canuckistani.ca\/","https:\/\/x.com\/canuckistani"],"url":"https:\/\/blog.mozilla.org\/addons\/author\/jgriffithsmozilla-com\/"}]}},"_links":{"self":[{"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/posts\/2917"}],"collection":[{"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/users\/316"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/comments?post=2917"}],"version-history":[{"count":0,"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/posts\/2917\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/media?parent=2917"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/categories?post=2917"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.mozilla.org\/addons\/wp-json\/wp\/v2\/tags?post=2917"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}