{"id":7663,"date":"2010-10-08T05:49:31","date_gmt":"2010-10-08T12:49:31","guid":{"rendered":"http:\/\/css-tricks.com\/?p=7663"},"modified":"2010-12-08T18:03:17","modified_gmt":"2010-12-09T01:03:17","slug":"make-a-view-source-button","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/make-a-view-source-button\/","title":{"rendered":"Make a \u2018View Source\u2019\u00a0Button"},"content":{"rendered":"
Remy Sharp’s cool site for HTML5 demos<\/a> has a “View Source” button on each of the individual demo<\/a> pages. Click it, and you see the entire source code for the page you are looking at. It’s not a popup or a new tab, it just shows the source right there on the page. I thought that was cool so I set out to recreate it my own way.<\/p>\n <\/p>\n <\/p>\n View Demo<\/a> Download Files<\/a><\/p>\n The idea that first came to mind was to use CSS3’s :target pseudo class. We talked about these a while back while exporting CSS3 tabs<\/a>. The idea is to have a link that links to the #source-code hash tag. That puts #source-code at the end of the URL, and allows the :target selector to match and apply styling. The basics:<\/p>\n Now it’s just a matter of filling that #source-code element with the actual source code. That is JavaScript territory, since we’ll want to pull that code dynamically, not actually repeat the source code just for sake of display. This way whenever we alter the page, we don’t have to adjust anything, our View Source button shows the updated source code as written. We can lean on jQuery to grab this for us:<\/p>\n That will give us all the HTML for the page, excluding only the DOCTYPE and actual A few quick considerations with that gathered HTML: 1) Let’s escape the <‘s so they show on the page correctly without trying to render as actual HTML. 2) Let’s “linkify” any links it finds so they can be clickable (taken in part from here<\/a>). <\/p>\n Then we’ll place that newly created Closing the source code is deliciously simple. Since the “View Source” button, when clicked, adds a hash-tag to the page, that means that the “Back” button in the browser will work. Pressing it removes the hash tag, thus #source-code is no longer :targeted, and it is automatically hidden by CSS. The #source-code div also has within it a simple “X” graphic, which links to the hash tag “#”, which has the exact same effect.<\/p>\n This just links to “#”, which takes our source viewing element out of :target, which instantly hides it.<\/p>\n<\/div>\n One of the easiest ways to apply syntax highlighting to code is the google-code-prettify project<\/a>. This is a JavaScript based highlighter. Essentially you link up the JavaScript file and the CSS file that comes with the download:<\/p>\n Make sure your and call the I altered the colors a bit to work on the dark background. This is the top part of the prettify.css file:<\/p>\n Prettify works by wrapping parts of the code in spans, which colorize that part. Also notice the properly escaped characters.<\/p>\n<\/div>\n Pretty much everything modern, as long as it supports CSS3 :target. Breaks in IE 8 and down, but OK in IE 9.<\/p>\n Firefox and Chrome support the URL protocol “view-source:” which opens up its native source code viewer. If you are making these links only for yourself, you could do:<\/p>\n Turns out the way I did it is pretty much nothing like how it’s done on the HTML5 demos pages<\/a>. This is my attempt at explaining his technique:<\/p>\n And then the clever bit of CSS which allows the source code to be hidden normally and take over the screen when the body acquires the The cool part about Remy’s method is that it’s far more cross-browser compatible than my idea. It uses pure JavaScript, so it’s not library dependent at all, and it doesn’t use any technique that is “fancy” and wouldn’t work in older(ish) browsers. He could have used the Of course, feel free to use this however you would like.<\/p>\n View Demo<\/a> Download Files<\/a><\/p>\n In its current form, this code relies on certain markup on the page, namely the button itself and the #view-source div. This could definitely be converted into a plugin which appends those things automatically which would make this much easier to implement. I may do that eventually.<\/p>\n This also has me thinking that 1) I really need to get on putting in syntax highlighting back into the blog design itself here on CSS-Tricks and 2) I should do this View Source thing on all demo pages. Both of those things will get done in time.<\/p>\nThe Fancy Way<\/h3>\n
<a href=\"#source-code\">View Source<\/a><\/code><\/pre>\n
#source-code { display: none; }\r\n#source-code:target { display: block; }<\/code><\/pre>\n
var html = $(\"html\").html();<\/code><\/pre>\n
<html><\/code> tags. You could also access this through
document.documentElement.innerHTML<\/code> but hey, if we’re gonna use jQuery let’s just use it. We’ll create a brand new
<pre><\/code> element, and fill it with a “fake” DOCTYPE and html tags, and then drop in that HTML that we just gathered from the page. <\/p>\n
<pre><\/code> inside our #source-code div.<\/p>\n
$(function() {\r\n\t$(\"<pre \/>\", {\r\n\t\t\"html\": '<!DOCTYPE html>\\n<html>\\n' + \r\n\t\t\t\t$(\"html\")\r\n\t\t\t\t\t.html()\r\n\t\t\t\t\t.replace(\/[<>]\/g, function(m) { return {'<':'<','>':'>'}[m]})\r\n\t\t\t\t\t.replace(\/((ftp|http|https):\\\/\\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\\/|\\\/([\\w#!:.?+=&%@!\\-\\\/]))?)\/gi,'<a href=\"$1\">$1<\/a>') + \r\n\t\t\t\t'\\n<\/html>'\r\n\t}).appendTo(\"#source-code\");\r\n});<\/code><\/pre>\n
Styling the code<\/h4>\n
<link rel='stylesheet' href='css\/prettify.css' \/>\r\n<script src=\"prettify\/prettify.js\"><\/script><\/code><\/pre>\n
<pre><\/code> tags have a class of “prettyprint”. I added this to the element creation syntax we’re using to create the
<pre><\/code>:<\/p>\n
\"class\": \"prettyprint\"<\/code><\/pre>\n
prettyPrint()<\/code> function when the page is ready. They recommend adding an onload to the body tag, but since we’re using the jQuery DOM ready function, we can just call it inside there.<\/p>\n
.str { color: #61ff74; }\r\n.kwd { color: #ea5eff; }\r\n.com { color: white; }\r\n.typ { color: red; }\r\n.lit { color: red; }\r\n.pun { color: white; }\r\n.pln { color: white; }\r\n.tag { color: #ffab58; }\r\n.atn { color: #fabb4e; }\r\n.atv { color: #ffd996; }\r\n.dec { color: red; }<\/code><\/pre>\n
Compatibility<\/h4>\n
Primitive Method<\/h3>\n
<a class=\"button\" onClick='window.location=\"view-source:\" + window.location.href'>View Source<\/a><\/code><\/pre>\n
Remy’s Method<\/h3>\n
\n
<pre><\/code>)<\/li>\n
<pre><\/code> to the body with ID #view-source<\/li>\n
<pre><\/code> is filled with HTML taken from
document.documentElement.innerHTML<\/code><\/li>\n
<pre><\/code>) and cancel the timer.<\/li>\n<\/ol>\n
(function () {\r\n\r\nvar pre = document.createElement('pre');\r\npre.id = \"view-source\"\r\n\r\n\/\/ private scope to avoid conflicts with demos\r\naddEvent(window, 'click', function (event) {\r\n if (event.target.hash == '#view-source') {\r\n \/\/ event.preventDefault();\r\n if (!document.getElementById('view-source')) {\r\n pre.innerHTML = ('<!DOCTYPE html>\\n<html>\\n' + document.documentElement.innerHTML + '\\n<\/html>').replace(\/[<>]\/g, function (m) { return {'<':'<','>':'>'}[m]});\r\n document.body.appendChild(pre); \r\n }\r\n document.body.className = 'view-source';\r\n \r\n var sourceTimer = setInterval(function () {\r\n if (window.location.hash != '#view-source') {\r\n clearInterval(sourceTimer);\r\n document.body.className = '';\r\n }\r\n }, 200);\r\n }\r\n});\r\n \r\n})();<\/code><\/pre>\n
.view-source<\/code> class:<\/p>\n
#view-source {\r\n display: none;\r\n}\r\n\r\nbody.view-source > * {\r\n display: none;\r\n}\r\n\r\nbody.view-source #view-source {\r\n display: block !important;\r\n}<\/code><\/pre>\n
Big time benefits<\/h4>\n
hashchange<\/code> event, for example, to watch for when the #view-source goes away, but that’s not supported in some older browsers so even that was handled well.<\/p>\n
Usage<\/h3>\n