├── .gitignore ├── source └── templates │ ├── meta_copyright.handlebars │ ├── meta_title.handlebars │ ├── link_class.handlebars │ ├── link_file.handlebars │ ├── link_method.handlebars │ ├── link_module.handlebars │ ├── abctabs.handlebars │ ├── meta_resources.handlebars │ ├── info_method.handlebars │ ├── info_class_method.handlebars │ ├── info_attribute.handlebars │ ├── info_document.handlebars │ ├── info_constant.handlebars │ ├── info_script.handlebars │ ├── info_module.handlebars │ ├── info_class.handlebars │ └── detail.handlebars ├── assets ├── javascripts │ ├── jquery.mousewheel.min.js │ ├── handlebars.helpers.js │ ├── keymaster.js │ ├── jquery.jqote2.min.js │ ├── quicksearch.js │ ├── shortcut.js │ ├── handlebars.runtime.js │ ├── jquery.history.js │ ├── hypervisor.js │ ├── showdown.js │ ├── rundown.js │ └── handlebars.templates.js └── stylesheets │ ├── customize.css │ └── normalize.css ├── Rulefile ├── README.rdoc ├── index.html └── COPYING.rdoc /.gitignore: -------------------------------------------------------------------------------- 1 | .fire/digest 2 | web 3 | -------------------------------------------------------------------------------- /source/templates/meta_copyright.handlebars: -------------------------------------------------------------------------------- 1 | Copyright © {{year}} {{holder}} 2 | -------------------------------------------------------------------------------- /source/templates/meta_title.handlebars: -------------------------------------------------------------------------------- 1 |

{{title}}

2 |

{{summary}}

3 | 4 | -------------------------------------------------------------------------------- /source/templates/link_class.handlebars: -------------------------------------------------------------------------------- 1 |
  • 2 | 3 | {{name}} 4 | 5 |
  • 6 | 7 | -------------------------------------------------------------------------------- /source/templates/link_file.handlebars: -------------------------------------------------------------------------------- 1 |
  • 2 | 3 | {{name}} 4 | 5 |
  • 6 | 7 | -------------------------------------------------------------------------------- /source/templates/link_method.handlebars: -------------------------------------------------------------------------------- 1 |
  • 2 | 3 | {{name}} 4 | 5 |
  • 6 | 7 | -------------------------------------------------------------------------------- /source/templates/link_module.handlebars: -------------------------------------------------------------------------------- 1 |
  • 2 | 3 | {{name}} 4 | 5 |
  • 6 | 7 | -------------------------------------------------------------------------------- /source/templates/abctabs.handlebars: -------------------------------------------------------------------------------- 1 | {{#letters}} 2 | 3 | {{/letters}} 4 | 5 | 6 | -------------------------------------------------------------------------------- /source/templates/meta_resources.handlebars: -------------------------------------------------------------------------------- 1 |
    2 | {{#resources}} 3 | {{label}} 4 | {{/resources}} 5 |
    6 |
    7 |   8 |
    9 | 10 | -------------------------------------------------------------------------------- /source/templates/info_method.handlebars: -------------------------------------------------------------------------------- 1 | 14 | 15 | -------------------------------------------------------------------------------- /source/templates/info_class_method.handlebars: -------------------------------------------------------------------------------- 1 | 14 | 15 | -------------------------------------------------------------------------------- /source/templates/info_attribute.handlebars: -------------------------------------------------------------------------------- 1 | 14 | 15 | -------------------------------------------------------------------------------- /source/templates/info_document.handlebars: -------------------------------------------------------------------------------- 1 | 16 | 17 | -------------------------------------------------------------------------------- /source/templates/info_constant.handlebars: -------------------------------------------------------------------------------- 1 | 18 | 19 | -------------------------------------------------------------------------------- /source/templates/info_script.handlebars: -------------------------------------------------------------------------------- 1 | 22 | 23 | -------------------------------------------------------------------------------- /source/templates/info_module.handlebars: -------------------------------------------------------------------------------- 1 | 22 | 23 | -------------------------------------------------------------------------------- /source/templates/info_class.handlebars: -------------------------------------------------------------------------------- 1 | 22 | 23 | -------------------------------------------------------------------------------- /assets/javascripts/jquery.mousewheel.min.js: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2009 Brandon Aaron (http://brandonaaron.net) 2 | * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 3 | * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. 4 | * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers. 5 | * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix. 6 | * 7 | * Version: 3.0.2 8 | * 9 | * Requires: 1.2.2+ 10 | */ 11 | (function(c){var a=["DOMMouseScroll","mousewheel"];c.event.special.mousewheel={setup:function(){if(this.addEventListener){for(var d=a.length;d;){this.addEventListener(a[--d],b,false)}}else{this.onmousewheel=b}},teardown:function(){if(this.removeEventListener){for(var d=a.length;d;){this.removeEventListener(a[--d],b,false)}}else{this.onmousewheel=null}}};c.fn.extend({mousewheel:function(d){return d?this.bind("mousewheel",d):this.trigger("mousewheel")},unmousewheel:function(d){return this.unbind("mousewheel",d)}});function b(f){var d=[].slice.call(arguments,1),g=0,e=true;f=c.event.fix(f||window.event);f.type="mousewheel";if(f.wheelDelta){g=f.wheelDelta/120}if(f.detail){g=-f.detail/3}d.unshift(f,g);return c.event.handle.apply(this,d)}})(jQuery); -------------------------------------------------------------------------------- /Rulefile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | ignore 'web' 4 | 5 | # 6 | # Run thin server to give site a spin. 7 | # 8 | desc "start thin server" 9 | task "serve" do 10 | sh "thin start -A file" 11 | end 12 | 13 | # 14 | # Compile Handlebar.js templates. 15 | # 16 | desc "compile templates" 17 | task "compile" do 18 | sh "handlebars source/templates/*.handlebars -f assets/javascripts/handlebars.templates.js" 19 | end 20 | 21 | # compile templates 22 | file 'source/templates/**/*' do 23 | run :compile 24 | end 25 | 26 | # Copy files to web directory. 27 | task 'web:copy' do 28 | mkdir_p 'web' 29 | install 'index.html', 'web/index.html' 30 | install 'doc.json', 'web/doc.json' 31 | sync 'assets', 'web/assets' 32 | end 33 | 34 | # The publish task uses the detroit-github plugin 35 | # from the Detroit project. 36 | desc "publish to github" 37 | task 'web:publish' => ['web:copy'] do 38 | github.publish 39 | end 40 | 41 | # Create web directory for gh-pages repo. 42 | desc "prepare for github" 43 | task "prepare" do 44 | github.prepare 45 | end 46 | 47 | # 48 | def github 49 | @github ||= ( 50 | require 'detroit' 51 | require 'detroit-github' 52 | 53 | Detroit::GitHub.new( 54 | :folder => 'web' 55 | #:sitemap => { 56 | # 'index.html' => 'index.html', 57 | # 'doc.json' => 'doc.json', 58 | # 'assets' => 'assets' 59 | #} 60 | ) 61 | ) 62 | end 63 | 64 | -------------------------------------------------------------------------------- /assets/javascripts/handlebars.helpers.js: -------------------------------------------------------------------------------- 1 | // rdoc convertor 2 | var rundown = new Rundown.converter(); /* TODO: support other formats */ 3 | 4 | // @todo handle this.format 5 | Handlebars.registerHelper('render_comment', function(comment) { 6 | var ret = rundown.makeHtml(this.comment); 7 | return new Handlebars.SafeString(ret); 8 | }); 9 | 10 | // @todo handle format 11 | Handlebars.registerHelper('render', function(text) { 12 | var ret = rundown.makeHtml(text); 13 | return new Handlebars.SafeString(ret); 14 | }); 15 | 16 | // The #doc block helper looks up each documentation object 17 | // in the given context array and renders the template. 18 | Handlebars.registerHelper('doc', function(context, options) { 19 | var ret = ""; 20 | var sub; 21 | 22 | for(var i=0, j=context.length; i1){h=a.slice(0,a.length-1);for(j=0;j0;for(j in d)if(!d[j]&&h(i.mods,+j)>-1||d[j]&&h(i.mods,+j)==-1)m=!1;(i.mods.length==0&&!d[16]&&!d[18]&&!d[17]&&!d[91]||m)&&i.method(a,i)===!1&&(a.preventDefault?a.preventDefault():a.returnValue=!1,a.stopPropagation&&a.stopPropagation(),a.cancelBubble&&(a.cancelBubble=!0))}}}}function h(a,b){var c=a.length;while(c--)if(a[c]===b)return c;return-1}var b,c={},d={16:!1,18:!1,17:!1,91:!1},e="all",f={"⇧":16,shift:16,"⌥":18,alt:18,option:18,"⌃":17,ctrl:17,control:17,"⌘":91,command:91},g={backspace:8,tab:9,clear:12,enter:13,"return":13,esc:27,escape:27,space:32,left:37,up:38,right:39,down:40,del:46,"delete":46,home:36,end:35,pageup:33,pagedown:34,",":188,".":190,"/":191,"`":192,"-":189,"=":187,";":186,"'":222,"[":219,"]":221,"\\":220};for(b=1;b<20;b++)f["f"+b]=111+b;for(b in f)k[b]=!1;m(document,"keydown",i),m(document,"keyup",j),a.key=k,a.key.setScope=l,typeof module!="undefined"&&(module.exports=key)})(this) -------------------------------------------------------------------------------- /source/templates/detail.handlebars: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 16 | 30 | 31 | 32 | 43 | 54 | 55 | 66 | 77 | 78 |
    ClassInstance
    8 | 15 | 17 |
      18 | {{#doc includes}} 19 |
    • 20 | {{#if id}} 21 | {{name}} 22 | {{else}} 23 | 24 | {{name}} 25 | {{/if}} 26 |
    • 27 | {{/doc}} 28 |
    29 |
    33 |
      34 | {{#doc accessors}} 35 | {{#if singleton}} 36 |
    • 37 | {{name}} 38 |
    • 39 | {{/if}} 40 | {{/doc}} 41 |
    42 |
    44 |
      45 | {{#doc accessors}} 46 | {{#unless singleton}} 47 |
    • 48 | {{name}} 49 |
    • 50 | {{/unless}} 51 | {{/doc}} 52 |
    53 |
    56 |
      57 | {{#doc methods}} 58 | {{#if singleton}} 59 |
    • 60 | {{name}} 61 |
    • 62 | {{/if}} 63 | {{/doc}} 64 |
    65 |
    67 |
      68 | {{#doc methods}} 69 | {{#unless singleton}} 70 |
    • 71 | {{name}} 72 |
    • 73 | {{/unless}} 74 | {{/doc}} 75 |
    76 |
    79 | 80 | 81 | 82 | 83 | 84 | 93 | 94 | 95 | 96 | 97 | 98 | 107 | 108 |
    Constants
    85 |
      86 | {{#doc constants}} 87 |
    • 88 | {{name}} 89 |
    • 90 | {{/doc}} 91 |
    92 |
    In Scripts
    99 |
      100 | {{#doc files}} 101 |
    • 102 | {{path}} 103 |
    • 104 | {{/doc}} 105 |
    106 |
    109 | -------------------------------------------------------------------------------- /README.rdoc: -------------------------------------------------------------------------------- 1 | = Hypervisor 2 | 3 | 4 | == Welcome 5 | 6 | And prepare to be amazed! The incredible Hypervisor is here. Your one-way 7 | ticket to documentation nirvana. Women have wept for less. Men have broken 8 | knuckles for less. 9 | 10 | Harnessing the powers of the Shomen, a standardize OOP documentation 11 | data format, and built on a jQuery powerhouse, Hypervisor is the champion 12 | of all poorly documented projects around the world, upholding the principles 13 | of clarity, accessiblity and the Ruby Way! 14 | 15 | 16 | == Features 17 | 18 | * Invoative mouse wheel scrolling menus. 19 | * Very clean interface. 20 | 21 | 22 | == How To 23 | 24 | Generate a shomen `.json` file for you project to replace. 25 | 26 | $ cd .. 27 | $ shomen rdoc > site/foo-1.0.0.json 28 | 29 | See Shomen project to learn more about this. 30 | 31 | To locally view your documentation, clone this repo to your project's 32 | webite directory (or `gh-pages` branch if you are crazy like that). 33 | 34 | $ cd myproject 35 | $ git clone http://rubyworks.github.com/hypervisor.git site 36 | $ cd site 37 | $ rm -rf .git 38 | 39 | By default it will look for `doc.json` so you can link that to 40 | the latest documentation file. 41 | 42 | $ ln -s foo-1.0.0.json doc.json 43 | 44 | Now fire up local directory webserver. The `shomen` command provides 45 | one (must have `sinatra` installed): 46 | 47 | $ shomen server 48 | 49 | You can also view the files directly if your browser supports local 50 | ajax calls (Firefox works. Chrome? Not so much). 51 | 52 | $ firefox index.html 53 | 54 | Now then, customize that template to your little hearts desire! 55 | 56 | To view you documentation remotely, firs publish you Shomen .json 57 | file, presumably to your website, but it can be anywhere on the 58 | internet that will accept loading via ajax. 59 | 60 | Now navigate over to the Rubyfaux site setting the `doc` property 61 | in the URL to the location of the file, e.g. 62 | 63 | http://rubyworks.github.com/hypervisor?doc=http://myorg.github.com/myapp/myapp-1.0.0.json 64 | 65 | And there you are. 66 | 67 | Note that if the documented project is large so too will be the Shomen `.json` file. 68 | In which case it take a moment for the browser to load the file. For large projects 69 | as such it is a good idea to divide documentation into a set of smaller files, rather 70 | than one big file. 71 | 72 | 73 | == Legalease 74 | 75 | Copyright (c) 2011 Thomas Sawyer 76 | 77 | Available according to the terms of the *BSD-2-Clause* license. 78 | 79 | External libraries used: 80 | 81 | * {jQuery}[http://jquery.org] 82 | * {jQote2}[http://github.com/aefxx/jQote2] 83 | * {Quicksearch}[http://github.com/riklomas/quicksearch] 84 | * {Highlight}[http://github.com/isagalaev/highlight.js] 85 | * {Showdown}[http://github.com/coreyti/showdown] 86 | * {Keymaster}[http://github.com/madrobby/keymaster] 87 | * {Mousewheel}[http://plugins.jquery.com/project/mousewheel] 88 | 89 | -------------------------------------------------------------------------------- /assets/javascripts/jquery.jqote2.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQote2 - client-side Javascript templating engine 3 | * Copyright (C) 2010, aefxx 4 | * http://aefxx.com/ 5 | * 6 | * Dual licensed under the WTFPL v2 or MIT (X11) licenses 7 | * WTFPL v2 Copyright (C) 2004, Sam Hocevar 8 | * 9 | * Date: Sat, Jun 29th, 2010 10 | * Version: 0.9.5 11 | */ 12 | (function($){var _=false,E1="UndefinedTemplateError",E2="TemplateCompilationError",E3="TemplateExecutionError",A="[object Array]",S="[object String]",F="[object Function]",n=1,c="%",q=/^[^<]*(<[\w\W]+>)[^>]*$/,ts=Object.prototype.toString;function r(e,x){throw $.extend(e,x),e;}function dns(f){var a=[];if(ts.call(f)!==A)return _;for(var i=0,l=f.length;i\s*|[\r\n\t]/g,"").split("<"+t).join(t+">\u001b").split(t+">");for(var m=0,k=a.length;m', 'g'), ""); 82 | output = $.trim(output.toLowerCase()); 83 | return output; 84 | }; 85 | 86 | this.results = function (bool) { 87 | if (typeof options.noResults === "string" && options.noResults !== "") { 88 | if (bool) { 89 | $(options.noResults).hide(); 90 | } else { 91 | $(options.noResults).show(); 92 | } 93 | } 94 | return this; 95 | }; 96 | 97 | this.loader = function (bool) { 98 | if (typeof options.loader === "string" && options.loader !== "") { 99 | (bool) ? $(options.loader).show() : $(options.loader).hide(); 100 | } 101 | return this; 102 | }; 103 | 104 | this.cache = function () { 105 | 106 | jq_results = $(target); 107 | 108 | if (typeof options.noResults === "string" && options.noResults !== "") { 109 | jq_results = jq_results.not(options.noResults); 110 | } 111 | 112 | var t = (typeof options.selector === "string") ? jq_results.find(options.selector) : $(target).not(options.noResults); 113 | cache = t.map(function () { 114 | return e.strip_html(this.innerHTML); 115 | }); 116 | 117 | rowcache = jq_results.map(function () { 118 | return this; 119 | }); 120 | 121 | return this.go(); 122 | }; 123 | 124 | this.trigger = function () { 125 | this.loader(true); 126 | options.onBefore(); 127 | 128 | window.clearTimeout(timeout); 129 | timeout = window.setTimeout(function () { 130 | e.go(); 131 | }, options.delay); 132 | 133 | return this; 134 | }; 135 | 136 | this.cache(); 137 | this.results(true); 138 | this.stripe(); 139 | this.loader(false); 140 | 141 | return this.each(function () { 142 | $(this).bind(options.bind, function () { 143 | val = $(this).val(); 144 | e.trigger(); 145 | }); 146 | }); 147 | 148 | }; 149 | 150 | }(jQuery, this, document)); 151 | -------------------------------------------------------------------------------- /assets/stylesheets/customize.css: -------------------------------------------------------------------------------- 1 | body{ background: #fff; color: #444; padding: 0 1em; } 2 | 3 | th { text-align: right; text-align: left; } 4 | td { padding: 0.5em; vertical-align: top; } 5 | 6 | .box { border-top: 1px solid #555; padding: 20px 40px; 7 | margin: 1em 0; box-shadow: 0 0 5px #888; -moz-box-shadow: 0 0 5px #888; 8 | } 9 | 10 | .box h3 { font-size: 0.9em; color: #ccc; } 11 | 12 | button, a { font-size: 0.9em; text-decoration: none; line-height: 1.6em; } 13 | 14 | button { border: none; background: transparent; color: #66aaff; cursor: pointer; } 15 | button.link { 16 | border: none; background: transparent; color: #66aaff; 17 | padding: 0.5em 0.5em; 18 | } 19 | button:hover { background: orange; color: white; } 20 | 21 | a { border: none; background: transparent; color: #66aaff; } 22 | a.link { 23 | border: none; background: transparent; color: #66aaff; 24 | padding: 0.5em 0.5em; 25 | } 26 | a:hover { background: orange; color: white; } 27 | 28 | button.letter { padding: 0 0 0 0; } 29 | 30 | /* H E A D E R */ 31 | 32 | #header { 33 | border-bottom: 1px solid #555; 34 | box-shadow: 0 0 5px #888; -moz-box-shadow: 0 0 5px #888; 35 | padding: 0.5em 0 1em 0; 36 | padding: 20px 40px; 37 | min-height: 60px; 38 | } 39 | 40 | #header h1 { 41 | margin: 0; padding: 0; 42 | } 43 | 44 | #header h2 { 45 | margin: 0; padding: 0; 46 | font-size: 1em; 47 | } 48 | 49 | #header-resources { 50 | float: right; 51 | width: auto; 52 | text-align: right; 53 | } 54 | 55 | #header-resources a, #header-resources button { 56 | font-size: 0.85em; 57 | padding: 0.5em; 58 | color: #66aaff; cursor: pointer; 59 | text-decoration: none; 60 | } 61 | 62 | #ribbon { 63 | margin: 1em; 64 | } 65 | 66 | /* root element for single scroll */ 67 | .scroll { 68 | position: relative; 69 | overflow: hidden; 70 | height: 1.4em; 71 | padding: 0.1em; 72 | margin: 0; 73 | background: #fff; 74 | color: orange; 75 | } 76 | 77 | .scroll:hover { 78 | background: #eee; 79 | } 80 | 81 | .scroll ul { margin: 0; padding: 0; } 82 | 83 | /* root element for the scroll menu items */ 84 | .scroll .items { 85 | nowrap: true; 86 | width: 100000px; /* overflow: hidden; */ 87 | position: absolute; 88 | clear:both; 89 | overflow: visible; 90 | } 91 | 92 | /* single scroll item */ 93 | .scroll .items li { 94 | float: left; 95 | padding: 0 0.3em 0 0; 96 | } 97 | 98 | /* possible settings for the active scroll */ 99 | .scroll.active { 100 | 101 | } 102 | 103 | .scroll ul { 104 | list-style: none; 105 | } 106 | 107 | 108 | /* INFOBOX */ 109 | 110 | #infobox { 111 | margin: 0; 112 | } 113 | 114 | #infobox pre { 115 | font-family: courier, monospace; 116 | font-size: 0.8em; 117 | padding: 1em 1.5em; 118 | } 119 | 120 | #infobox pre.script { 121 | padding: 1em 0; 122 | } 123 | 124 | #infobox .info-heading h1 { 125 | padding: 0; margin: 0; 126 | } 127 | 128 | #infobox .info-heading h2 { 129 | color: #444; font-size: 0.9em; 130 | padding: 0; margin: 0; 131 | } 132 | 133 | #infobox .info-heading h3 { 134 | color: #999; font-size: 0.7em; 135 | padding: 0; margin: 0.5em 0; 136 | } 137 | 138 | #infobox .info-heading .fade { color: #777; } 139 | 140 | #infobox .info-content { 141 | margin-top: 2em; 142 | } 143 | 144 | #infobox .class-breakdown { 145 | margin: 2em 2.5em 2em 0; 146 | vertical-align: top; 147 | background: #fff; 148 | } 149 | 150 | #infobox .class-breakdown table { 151 | border: 1px solid #ccc; 152 | border-collapse:collapse; 153 | } 154 | 155 | #infobox .class-breakdown table th { 156 | border: 1px solid #ccc; 157 | margin: 0; padding: 0.5em 1em; 158 | } 159 | 160 | #infobox .class-breakdown table td { 161 | border: 1px solid #ccc; 162 | margin: 0; padding: 0.5em 1em; 163 | vertical-align: top; 164 | } 165 | 166 | #infobox .class-breakdown ul { 167 | padding: 0 0 0 1em; 168 | margin: 0; 169 | } 170 | 171 | #infobox .class-breakdown li a { 172 | padding: 0; margin: 0; line-height: 1em; 173 | } 174 | 175 | /* FOOTER */ 176 | 177 | #footer { 178 | font-size: 0.7em; 179 | margin: -5px 5px 1em 5px; 180 | } 181 | 182 | 183 | .right-floating-horizontal-menu { 184 | float: right; 185 | width: auto; 186 | } 187 | 188 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | API 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 47 | 48 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 69 | 70 |
    71 | 72 | 73 | 74 | 83 | 84 | 85 | 92 | 93 | 94 | 101 | 102 | 103 | 110 | 111 |
    Search 75 |
    76 | 77 |   78 | 79 | 80 | 81 |
    82 |
    FILES 86 |
    87 |
      88 | 89 |
    90 |
    91 |
    CLASSES 95 |
    96 |
      97 | 98 |
    99 |
    100 |
    METHODS 104 |
    105 |
      106 | 107 |
    108 |
    109 |
    112 |
    113 | 114 |
    115 | 116 | 117 |
    118 |
    119 | 120 | 121 |
    122 |

    doc.json

    123 |
    124 |
    125 | 126 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /assets/javascripts/shortcut.js: -------------------------------------------------------------------------------- 1 | /** 2 | * http://www.openjs.com/scripts/events/keyboard_shortcuts/ 3 | * Version : 2.01.B 4 | * By Binny V A 5 | * License : BSD 6 | */ 7 | shortcut = { 8 | 'all_shortcuts':{},//All the shortcuts are stored in this array 9 | 'add': function(shortcut_combination,callback,opt) { 10 | //Provide a set of default options 11 | var default_options = { 12 | 'type':'keydown', 13 | 'propagate':false, 14 | 'disable_in_input':false, 15 | 'target':document, 16 | 'keycode':false 17 | } 18 | if(!opt) opt = default_options; 19 | else { 20 | for(var dfo in default_options) { 21 | if(typeof opt[dfo] == 'undefined') opt[dfo] = default_options[dfo]; 22 | } 23 | } 24 | 25 | var ele = opt.target; 26 | if(typeof opt.target == 'string') ele = document.getElementById(opt.target); 27 | var ths = this; 28 | shortcut_combination = shortcut_combination.toLowerCase(); 29 | 30 | //The function to be called at keypress 31 | var func = function(e) { 32 | e = e || window.event; 33 | 34 | if(opt['disable_in_input']) { //Don't enable shortcut keys in Input, Textarea fields 35 | var element; 36 | if(e.target) element=e.target; 37 | else if(e.srcElement) element=e.srcElement; 38 | if(element.nodeType==3) element=element.parentNode; 39 | 40 | if(element.tagName == 'INPUT' || element.tagName == 'TEXTAREA') return; 41 | } 42 | 43 | //Find Which key is pressed 44 | if (e.keyCode) code = e.keyCode; 45 | else if (e.which) code = e.which; 46 | var character = String.fromCharCode(code).toLowerCase(); 47 | 48 | if(code == 188) character=","; //If the user presses , when the type is onkeydown 49 | if(code == 190) character="."; //If the user presses , when the type is onkeydown 50 | 51 | var keys = shortcut_combination.split("+"); 52 | //Key Pressed - counts the number of valid keypresses - if it is same as the number of keys, the shortcut function is invoked 53 | var kp = 0; 54 | 55 | //Work around for stupid Shift key bug created by using lowercase - as a result the shift+num combination was broken 56 | var shift_nums = { 57 | "`":"~", 58 | "1":"!", 59 | "2":"@", 60 | "3":"#", 61 | "4":"$", 62 | "5":"%", 63 | "6":"^", 64 | "7":"&", 65 | "8":"*", 66 | "9":"(", 67 | "0":")", 68 | "-":"_", 69 | "=":"+", 70 | ";":":", 71 | "'":"\"", 72 | ",":"<", 73 | ".":">", 74 | "/":"?", 75 | "\\":"|" 76 | } 77 | //Special Keys - and their codes 78 | var special_keys = { 79 | 'esc':27, 80 | 'escape':27, 81 | 'tab':9, 82 | 'space':32, 83 | 'return':13, 84 | 'enter':13, 85 | 'backspace':8, 86 | 87 | 'scrolllock':145, 88 | 'scroll_lock':145, 89 | 'scroll':145, 90 | 'capslock':20, 91 | 'caps_lock':20, 92 | 'caps':20, 93 | 'numlock':144, 94 | 'num_lock':144, 95 | 'num':144, 96 | 97 | 'pause':19, 98 | 'break':19, 99 | 100 | 'insert':45, 101 | 'home':36, 102 | 'delete':46, 103 | 'end':35, 104 | 105 | 'pageup':33, 106 | 'page_up':33, 107 | 'pu':33, 108 | 109 | 'pagedown':34, 110 | 'page_down':34, 111 | 'pd':34, 112 | 113 | 'left':37, 114 | 'up':38, 115 | 'right':39, 116 | 'down':40, 117 | 118 | 'f1':112, 119 | 'f2':113, 120 | 'f3':114, 121 | 'f4':115, 122 | 'f5':116, 123 | 'f6':117, 124 | 'f7':118, 125 | 'f8':119, 126 | 'f9':120, 127 | 'f10':121, 128 | 'f11':122, 129 | 'f12':123 130 | } 131 | 132 | var modifiers = { 133 | shift: { wanted:false, pressed:false}, 134 | ctrl : { wanted:false, pressed:false}, 135 | alt : { wanted:false, pressed:false}, 136 | meta : { wanted:false, pressed:false} //Meta is Mac specific 137 | }; 138 | 139 | if(e.ctrlKey) modifiers.ctrl.pressed = true; 140 | if(e.shiftKey) modifiers.shift.pressed = true; 141 | if(e.altKey) modifiers.alt.pressed = true; 142 | if(e.metaKey) modifiers.meta.pressed = true; 143 | 144 | for(var i=0; k=keys[i],i 1) { //If it is a special key 161 | if(special_keys[k] == code) kp++; 162 | 163 | } else if(opt['keycode']) { 164 | if(opt['keycode'] == code) kp++; 165 | 166 | } else { //The special keys did not match 167 | if(character == k) kp++; 168 | else { 169 | if(shift_nums[character] && e.shiftKey) { //Stupid Shift key bug created by using lowercase 170 | character = shift_nums[character]; 171 | if(character == k) kp++; 172 | } 173 | } 174 | } 175 | } 176 | 177 | if(kp == keys.length && 178 | modifiers.ctrl.pressed == modifiers.ctrl.wanted && 179 | modifiers.shift.pressed == modifiers.shift.wanted && 180 | modifiers.alt.pressed == modifiers.alt.wanted && 181 | modifiers.meta.pressed == modifiers.meta.wanted) { 182 | callback(e); 183 | 184 | if(!opt['propagate']) { //Stop the event 185 | //e.cancelBubble is supported by IE - this will kill the bubbling process. 186 | e.cancelBubble = true; 187 | e.returnValue = false; 188 | 189 | //e.stopPropagation works in Firefox. 190 | if (e.stopPropagation) { 191 | e.stopPropagation(); 192 | e.preventDefault(); 193 | } 194 | return false; 195 | } 196 | } 197 | } 198 | this.all_shortcuts[shortcut_combination] = { 199 | 'callback':func, 200 | 'target':ele, 201 | 'event': opt['type'] 202 | }; 203 | //Attach the function with the event 204 | if(ele.addEventListener) ele.addEventListener(opt['type'], func, false); 205 | else if(ele.attachEvent) ele.attachEvent('on'+opt['type'], func); 206 | else ele['on'+opt['type']] = func; 207 | }, 208 | 209 | //Remove the shortcut - just specify the shortcut and I will remove the binding 210 | 'remove':function(shortcut_combination) { 211 | shortcut_combination = shortcut_combination.toLowerCase(); 212 | var binding = this.all_shortcuts[shortcut_combination]; 213 | delete(this.all_shortcuts[shortcut_combination]) 214 | if(!binding) return; 215 | var type = binding['event']; 216 | var ele = binding['target']; 217 | var callback = binding['callback']; 218 | 219 | if(ele.detachEvent) ele.detachEvent('on'+type, callback); 220 | else if(ele.removeEventListener) ele.removeEventListener(type, callback, false); 221 | else ele['on'+type] = false; 222 | } 223 | } -------------------------------------------------------------------------------- /assets/javascripts/handlebars.runtime.js: -------------------------------------------------------------------------------- 1 | // lib/handlebars/base.js 2 | var Handlebars = {}; 3 | 4 | Handlebars.VERSION = "1.0.beta.6"; 5 | 6 | Handlebars.helpers = {}; 7 | Handlebars.partials = {}; 8 | 9 | Handlebars.registerHelper = function(name, fn, inverse) { 10 | if(inverse) { fn.not = inverse; } 11 | this.helpers[name] = fn; 12 | }; 13 | 14 | Handlebars.registerPartial = function(name, str) { 15 | this.partials[name] = str; 16 | }; 17 | 18 | Handlebars.registerHelper('helperMissing', function(arg) { 19 | if(arguments.length === 2) { 20 | return undefined; 21 | } else { 22 | throw new Error("Could not find property '" + arg + "'"); 23 | } 24 | }); 25 | 26 | var toString = Object.prototype.toString, functionType = "[object Function]"; 27 | 28 | Handlebars.registerHelper('blockHelperMissing', function(context, options) { 29 | var inverse = options.inverse || function() {}, fn = options.fn; 30 | 31 | 32 | var ret = ""; 33 | var type = toString.call(context); 34 | 35 | if(type === functionType) { context = context.call(this); } 36 | 37 | if(context === true) { 38 | return fn(this); 39 | } else if(context === false || context == null) { 40 | return inverse(this); 41 | } else if(type === "[object Array]") { 42 | if(context.length > 0) { 43 | for(var i=0, j=context.length; i 0) { 60 | for(var i=0, j=context.length; i": ">", 120 | '"': """, 121 | "'": "'", 122 | "`": "`" 123 | }; 124 | 125 | var badChars = /&(?!\w+;)|[<>"'`]/g; 126 | var possible = /[&<>"'`]/; 127 | 128 | var escapeChar = function(chr) { 129 | return escape[chr] || "&"; 130 | }; 131 | 132 | Handlebars.Utils = { 133 | escapeExpression: function(string) { 134 | // don't escape SafeStrings, since they're already safe 135 | if (string instanceof Handlebars.SafeString) { 136 | return string.toString(); 137 | } else if (string == null || string === false) { 138 | return ""; 139 | } 140 | 141 | if(!possible.test(string)) { return string; } 142 | return string.replace(badChars, escapeChar); 143 | }, 144 | 145 | isEmpty: function(value) { 146 | if (typeof value === "undefined") { 147 | return true; 148 | } else if (value === null) { 149 | return true; 150 | } else if (value === false) { 151 | return true; 152 | } else if(Object.prototype.toString.call(value) === "[object Array]" && value.length === 0) { 153 | return true; 154 | } else { 155 | return false; 156 | } 157 | } 158 | }; 159 | })();; 160 | // lib/handlebars/runtime.js 161 | Handlebars.VM = { 162 | template: function(templateSpec) { 163 | // Just add water 164 | var container = { 165 | escapeExpression: Handlebars.Utils.escapeExpression, 166 | invokePartial: Handlebars.VM.invokePartial, 167 | programs: [], 168 | program: function(i, fn, data) { 169 | var programWrapper = this.programs[i]; 170 | if(data) { 171 | return Handlebars.VM.program(fn, data); 172 | } else if(programWrapper) { 173 | return programWrapper; 174 | } else { 175 | programWrapper = this.programs[i] = Handlebars.VM.program(fn); 176 | return programWrapper; 177 | } 178 | }, 179 | programWithDepth: Handlebars.VM.programWithDepth, 180 | noop: Handlebars.VM.noop 181 | }; 182 | 183 | return function(context, options) { 184 | options = options || {}; 185 | return templateSpec.call(container, Handlebars, context, options.helpers, options.partials, options.data); 186 | }; 187 | }, 188 | 189 | programWithDepth: function(fn, data, $depth) { 190 | var args = Array.prototype.slice.call(arguments, 2); 191 | 192 | return function(context, options) { 193 | options = options || {}; 194 | 195 | return fn.apply(this, [context, options.data || data].concat(args)); 196 | }; 197 | }, 198 | program: function(fn, data) { 199 | return function(context, options) { 200 | options = options || {}; 201 | 202 | return fn(context, options.data || data); 203 | }; 204 | }, 205 | noop: function() { return ""; }, 206 | invokePartial: function(partial, name, context, helpers, partials, data) { 207 | options = { helpers: helpers, partials: partials, data: data }; 208 | 209 | if(partial === undefined) { 210 | throw new Handlebars.Exception("The partial " + name + " could not be found"); 211 | } else if(partial instanceof Function) { 212 | return partial(context, options); 213 | } else if (!Handlebars.compile) { 214 | throw new Handlebars.Exception("The partial " + name + " could not be compiled when running in runtime-only mode"); 215 | } else { 216 | partials[name] = Handlebars.compile(partial); 217 | return partials[name](context, options); 218 | } 219 | } 220 | }; 221 | 222 | Handlebars.template = Handlebars.VM.template; 223 | ; 224 | -------------------------------------------------------------------------------- /assets/javascripts/jquery.history.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery history plugin 3 | * 4 | * The MIT License 5 | * 6 | * Copyright (c) 2006-2009 Taku Sano (Mikage Sawatari) 7 | * Copyright (c) 2010 Takayuki Miwa 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining a copy 10 | * of this software and associated documentation files (the "Software"), to deal 11 | * in the Software without restriction, including without limitation the rights 12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | * copies of the Software, and to permit persons to whom the Software is 14 | * furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be included in 17 | * all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | */ 27 | 28 | (function($) { 29 | var locationWrapper = { 30 | put: function(hash, win) { 31 | (win || window).location.hash = this.encoder(hash); 32 | }, 33 | get: function(win) { 34 | var hash = ((win || window).location.hash).replace(/^#/, ''); 35 | try { 36 | return $.browser.mozilla ? hash : decodeURIComponent(hash); 37 | } 38 | catch (error) { 39 | return hash; 40 | } 41 | }, 42 | encoder: encodeURIComponent 43 | }; 44 | 45 | var iframeWrapper = { 46 | id: "__jQuery_history", 47 | init: function() { 48 | var html = '