Skip to content

Instantly share code, notes, and snippets.

@oren
Forked from morganrallen/_README.md
Last active Aug 29, 2015
Embed
What would you like to do?

JankyBrowser

The only cross-platform browser that fits in a Gist!

One line install. Works on Linux, MacOSX and Windows.

Local Install

$> npm install http://gist.github.com/morganrallen/f07f59802884bcdcad4a/download
$> node node_modules/jankybrowser

Global Install

$> npm install -g http://gist.github.com/morganrallen/f07f59802884bcdcad4a/download
$> jankybrowser

JankyBrowser is based on Thrust

<html>
<head>
<style>
html, body,
header {
clear: both;
margin: 0;
padding: 0;
width: 100%;
}
header {
border-bottom: 1px solid gray;
}
header input {
margin: 8px;
}
#nav {
float: left;
}
#nav .forward,
#nav .backward {
font-weight: bold;
float: left;
padding: 8px;
padding-top: 10px;
}
#tabs-wrapper, #tabs {
margin: 0;
padding: 0;
}
#tabs-wrapper {
height: 40px;
overflow: hidden;
}
.tabs {
height: 100%;
list-style: none;
margin: 0;
padding: 0;
overflow: hidden;
width: 100%;
}
.tabs li {
float: left;
line-height: 0.5em;
padding: 15px;
}
.tabs li.active {
background-color: gray;
}
li.tab {
border: 1px solid black;
}
.tab .tab-close {
cursor: pointer;
float: right;
font-size: 0.5em;
left: 5px;
padding-left: 3px;
position: relative;
top: -8px;
}
#new {
border: solid 1px gray;
cursor: pointer;
float: right;
position: absolute;
right: 10px;
text-align: center;
top: 10px;
width: 20px;
-webkit-user-select: none;
z-index: 1000;
}
#page-content {
height: 100%;
width: 100%;
}
#page-content .page {
height: 100%;
transition: left 0.7s ease-in-out;
position: absolute;
left: -100%;
width: 100%;
}
#page-content .page.active {
left: 0;
}
</style>
<script src="/browser.js"></script>
</head>
<body>
<header>
<div id="nav">
<div class="backward">&lt;</div>
<div class="forward">&gt;</div>
<input id="location" />
</div>
<div id="tabs-wrapper">
<ul class="tabs"></ul>
<div id="new">+</div>
</div>
</header>
<div id="page-content"></div>
</body>
</html>
"use strict";
function urlToTtile(url) {
var a = document.createElement("a");
a.href = url;
var hostname = a.hostname;
hostname = hostname.split(".").slice(-2).join(".");
return hostname;
}
var loc;
var tabs;
var newTab;
var pageContent;
var navForward;
var navBackward;
var activePage;
var activeTab;
var activeWV;
function activate(page, tab) {
if(activePage && activePage !== page) {
activePage.classList.remove("active");
}
if(activeTab && activeTab !== tab) {
activeTab.classList.remove("active");
}
activePage = page;
activeTab = tab;
activeWV = page.firstElementChild;
activePage.classList.add("active");
activeTab.classList.add("active");
loc.value = activeWV.src;
}
window.onload = function() {
var $ = document.querySelector.bind(document);
loc = $("header input");
tabs = $("ul.tabs");
newTab = $("#new");
pageContent = $("#page-content");
navForward = $("#nav .forward");
navBackward = $("#nav .backward");
function openNewTab(url) {
var page = document.createElement("div");
page.className = "page";
var webview = document.createElement("webview");
page.appendChild(webview);
pageContent.appendChild(page);
if(url) {
webview.src = url;
}
var tab = document.createElement("li");
tab.className = "tab";
var label = document.createTextNode(urlToTtile(url));
tab.appendChild(label);
var close = document.createElement("div");
close.className = "tab-close";
close.textContent = "X";
tab.appendChild(close);
tabs.appendChild(tab);
function handleTabClick() {
console.log("clicking tab");
activate(page, tab);
}
function handleCloseClick(evt) {
console.log("closing tab");
tab.removeEventListener(handleTabClick);
webview.removeEventListener(handleTabClick);
close.removeEventListener(handleCloseClick);
tab.parentNode.removeChild(tab);
webview.parentNode.removeChild(webview);
evt.stopPropagation();
}
tab.addEventListener("click", handleTabClick, false);
close.addEventListener("click", handleCloseClick, true);
webview.addEventListener("title-set", function(evt) {
label.textContent = evt.title;
}, false);
activate(page, tab);
}
loc.addEventListener("keypress", function(evt) {
if(evt.keyCode === 13) {
console.log("changing location " + loc.value);
activeWV.src = loc.value;
}
}, false);
newTab.addEventListener("click", function() {
openNewTab("http://www.google.com");
}, false);
navBackward.addEventListener("click", function() {
activeWV.back();
});
navForward.addEventListener("click", function() {
activeWV.forward();
});
openNewTab("http://www.google.com");
};
"use strict";
var argv = require('minimist')(process.argv.slice(2));
var async = require('async');
var api = null;
var window = null;
var url = __dirname + "/test.html";
var fs = require("fs");
var http = require("http");
var port = 21024;
async.series([
function(cb) {
var server = http.createServer(function(req, res) {
if(req.url === "/") {
req.url = "/browser.html";
}
req.url = __dirname + req.url;
console.log("attempting to load %s", req.url);
fs.createReadStream(req.url).pipe(res);
});
server.listen(port, '127.0.0.1', function() {
console.log("listening on %s", port);
cb(null);
});
},
function(cb_) {
require('node-thrust')(function(err, a) {
api = a;
return cb_(err);
}, argv.thrust_path || null);
},
function(cb_) {
var root = "http://127.0.0.1:" + port;
if(argv.ext) root += ("/" + argv.ext);
window = api.window({
root_url: root,
size: {
width: 1024,
height: 768
}
});
window.on("closed", function() {
process.exit(0);
});
return cb_();
},
function(cb_) {
window.show(cb_);
}
], function(err) {
if(err) {
console.log('FAILED');
console.error(err);
}
console.log('OK');
});
#!/usr/bin/env node
require("./");
{
"name": "jankybrowser",
"version": "1.2.0",
"description": "",
"bin": {
"jankybrowser": "jankybrowser"
},
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"async": "^0.9.0",
"minimist": "^1.1.0",
"node-thrust": "^0.7.5"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment