{"id":2883,"date":"2005-09-12T16:42:00","date_gmt":"2005-09-12T16:42:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/heaths\/2005\/09\/12\/blog-customizations-part-2\/"},"modified":"2005-09-12T16:42:00","modified_gmt":"2005-09-12T16:42:00","slug":"blog-customizations-part-2","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/setup\/blog-customizations-part-2\/","title":{"rendered":"Blog Customizations, Part 2"},"content":{"rendered":"<p>As <a href=\"\/heaths\/archive\/2005\/09\/12\/463976.aspx\">mentioned earlier<\/a>, I wanted to persist your preferences for whether certain collapsible panels were in the collapsed or expanded state. With a simple ECMA-compliant wrapper class around <code>document.cookie<\/code> and a few minor changes to the <code>CollapsiblePanel<\/code> class, state for unique panels can be remembered. The cookie wrapper class is pretty straight forward:<\/p>\n<pre><font color=\"blue\">function<\/font> Cookie() {\n  <font color=\"blue\">this<\/font>.path = \"\/\";\n  <font color=\"green\">\/\/ Expire cookie after one year.<\/font>\n  <font color=\"blue\">this<\/font>.expires = <font color=\"blue\">function<\/font>() {\n    <font color=\"blue\">var<\/font> d = <font color=\"blue\">new<\/font> Date();\n    d.setUTCFullYear(d.getUTCFullYear() + 1);\n    <font color=\"blue\">return<\/font> d.toGMTString();\n  }\n  <font color=\"blue\">this<\/font>.getValue = <font color=\"blue\">function<\/font>(name) {\n    <font color=\"blue\">var<\/font> i, names = document.cookie.split(\"; \");\n    <font color=\"blue\">for<\/font> (i = 0; i &gt; names.length; i++) {\n      <font color=\"blue\">var<\/font> crumb = names[i].split(\"=\");\n      <font color=\"blue\">if<\/font> (<font color=\"blue\">this<\/font>.canonicalize(name) == crumb[0]) {\n        <font color=\"blue\">var<\/font> value = unescape(crumb[1]);\n        <font color=\"blue\">return<\/font> value;\n      }\n    }\n    <font color=\"blue\">return<\/font> <font color=\"blue\">null<\/font>;\n  }\n  <font color=\"blue\">this<\/font>.setValue = <font color=\"blue\">function<\/font>(name, value) {\n    <font color=\"blue\">var<\/font> str = <font color=\"blue\">this<\/font>.canonicalize(name) +\n      \"=\" + escape(value) + \"; \" +\n      \"path=\" + <font color=\"blue\">this<\/font>.path + \"; \" +\n      \"expires=\" + <font color=\"blue\">this<\/font>.expires();\n    document.cookie = str;\n  }\n  <font color=\"blue\">this<\/font>.canonicalize = <font color=\"blue\">function<\/font>(name) {\n    <font color=\"blue\">var<\/font> parts = name.split(\" \");\n    <font color=\"blue\">return<\/font> parts.join(\"\");\n  }\n}\n<font color=\"blue\">var<\/font> g_cookie = <font color=\"blue\">new<\/font> Cookie;<\/pre>\n<p>To initialize the <code>CollapsiblePanel<\/code>, an <code>init()<\/code> function is defined for the class that does pretty much the oppose of the <code>toggle()<\/code> function. <code>init()<\/code> is also defined to read from the cookie while <code>toggle()<\/code> is changed to write the cookie:<\/p>\n<pre><font color=\"blue\">function<\/font> CollapsiblePanel(elem) {\n  <font color=\"blue\">if<\/font> (!elem) {\n    <font color=\"blue\">return<\/font> <font color=\"blue\">null<\/font>;\n  }\n  <font color=\"green\">\/\/ Close 'this'.<\/font>\n  <font color=\"blue\">var<\/font> self = <font color=\"blue\">this<\/font>;\n  <b><font color=\"blue\">this<\/font>.init = <font color=\"blue\">function<\/font>() {\n    <font color=\"blue\">if<\/font> (g_cookie.getValue(self.title, \"block\") == \"block\") {\n      self.elem.innerHTML = self.collapseHTML + self.title;\n      self.sibling.style.display = \"block\";\n    } <font color=\"blue\">else<\/font> {\n      self.elem.innerHTML = self.expandHTML + self.title;\n      self.sibling.style.display = \"none\";\n    }\n  }<\/b>\n  <font color=\"blue\">this<\/font>.toggle = <font color=\"blue\">function<\/font>() {\n    <font color=\"blue\">if<\/font> (self.sibling.style.display == \"none\") {\n      self.elem.innerHTML = self.collapseHTML + self.title;\n      self.sibling.style.display = \"block\";\n    } <font color=\"blue\">else<\/font> {\n      self.elem.innerHTML = self.expandHTML + self.title;\n      self.sibling.style.display = \"none\";\n    }\n    <b>g_cookie.setValue(self.title, self.sibling.style.display);<\/b>\n  }\n  <font color=\"blue\">this<\/font>.elem = elem;\n  <font color=\"blue\">this<\/font>.title = elem.innerHTML;\n  <font color=\"blue\">this<\/font>.expandHTML = '&lt;img src=\"expand.gif\" width=\"9\" height=\"9\"&gt;&amp;nbsp;';\n  <font color=\"blue\">this<\/font>.collapseHTML = '&lt;img src=\"collapse.gif\" width=\"9\" height=\"9\"&gt;&amp;nbsp;';\n  <font color=\"blue\">this<\/font>.elem.style.cursor = \"pointer\";\n  <font color=\"blue\">this<\/font>.sibling = elem.nextSibling;\n  <font color=\"blue\">if<\/font> (<font color=\"blue\">this<\/font>.sibling.nodeType == 3) {\n    <font color=\"green\">\/\/ Get second sibling if text node is next.<\/font>\n    <font color=\"blue\">this<\/font>.sibling = <font color=\"blue\">this<\/font>.sibling.nextSibling;\n  }\n  elem.onclick = <font color=\"blue\">this<\/font>.toggle;\n  <b><font color=\"blue\">this<\/font>.init();<\/b>\n}<\/pre>\n<p>All bold lines above show the changes to the <code>CollapsiblePanel<\/code> class.<\/p>\n<p>Now when you expand or collapse a panel, its sibling&#8217;s display state is persisted and used to initial the class when the page is refreshed or you navigate to another page under the given path for the cookie, which can be easily changed to suit your needs.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>As mentioned earlier, I wanted to persist your preferences for whether certain collapsible panels were in the collapsed or expanded state. With a simple ECMA-compliant wrapper class around document.cookie and a few minor changes to the CollapsiblePanel class, state for unique panels can be remembered. The cookie wrapper class is pretty straight forward: function Cookie() [&hellip;]<\/p>\n","protected":false},"author":389,"featured_media":3843,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[11,14,29,34],"class_list":["post-2883","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-customizations","tag-development","tag-personal","tag-script"],"acf":[],"blog_post_summary":"<p>As mentioned earlier, I wanted to persist your preferences for whether certain collapsible panels were in the collapsed or expanded state. With a simple ECMA-compliant wrapper class around document.cookie and a few minor changes to the CollapsiblePanel class, state for unique panels can be remembered. The cookie wrapper class is pretty straight forward: function Cookie() [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/setup\/wp-json\/wp\/v2\/posts\/2883","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/setup\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/setup\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/setup\/wp-json\/wp\/v2\/users\/389"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/setup\/wp-json\/wp\/v2\/comments?post=2883"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/setup\/wp-json\/wp\/v2\/posts\/2883\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/setup\/wp-json\/wp\/v2\/media\/3843"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/setup\/wp-json\/wp\/v2\/media?parent=2883"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/setup\/wp-json\/wp\/v2\/categories?post=2883"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/setup\/wp-json\/wp\/v2\/tags?post=2883"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}