JavaScript
Article
By Sam Deering

jQuery Floating Bookmark Globe – Awesome Fun!

By Sam Deering

jquery-bookmark-fun

Fun floating bookmark globe using some pretty clever JS/CSS coding which I won’t go into trying to explain (but if you want to see it i’ve included it below!). It’s based of the katamari ball game where is moves around and picks up stuff! The bookmark floats around the page when you hold down right click on your mouse.

Try it yourself

  1. Visit your website
  2. Copy the code below into your address bar
  3. Click it and enjoy :)

var _0x6e06=["x68x74x74x70x3Ax2Fx2Fx63x6Fx64x65x2Ex6Ax71x75x65x72x79x2Ex63x6Fx6Dx2Fx6Ax71x75x65x72x79x2Dx6Cx61x74x65x73x74x2Ex6Ax73","x68x74x74x70x3Ax2Fx2Fx6Bx61x74x68x61x63x6Bx2Ex63x6Fx6Dx2Fx6Ax73x2Fx6Bx68x2Ex6Ax73","x67x65x74x53x63x72x69x70x74","x72x65x61x64x79"];jQuery(document)[_0x6e06[3]](function (){jQuery[_0x6e06[2]](_0x6e06[0],function (){jQuery[_0x6e06[2]](_0x6e06[1]);} );} );

Or run in Firebug:

jQuery(document).ready( function()
{
	jQuery.getScript('http://code.jquery.com/jquery-latest.js', function() {
		jQuery.getScript('http://kathack.com/js/kh.js');
	});
});

--ADVERTISEMENT--

or if you you just want to see things blow up…

jQuery(document).ready( function()
{
	jQuery.getScript('http://code.jquery.com/jquery-latest.js', function() {
		jQuery.getScript('http://erkie.github.com/asteroids.min.js');
	});
});

The JavaScript Code

/*
Copyright Alex Leone, David Nufer, David Truong, 2011-03-11. kathack.com

javascript:var i,s,ss=[‘http://kathack.com/js/kh.js’,’http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js’];for(i=0;i!=ss.length;i++){s=document.createElement(‘script’);s.src=ss[i];document.body.appendChild(s);}void(0);

*/
var BORDER_STYLE = “1px solid #bbb”,
CSS_TRANSFORM = null,
CSS_TRANSFORM_ORIGIN = null,
POSSIBLE_TRANSFORM_PREFIXES = [‘-webkit-‘, ‘-moz-‘, ‘-o-‘, ‘-ms-‘, ”],
khFirst = false;

/* When running twice on one page, update pick-uppable nodes instead of
* creating more.
*/
if (!window.khNodes) {
khFirst = true;
window.khNodes = new StickyNodes();
}

function getCssTransform() {
var i, d = document.createElement(‘div’), pre;
for (i = 0; i 0) {
textEls.push(el);
return;
}
if (!el.childNodes || el.khIgnore) {
return;
}
shouldAdd = shouldAddChildren(el);
for (i = 0, len = el.childNodes.length; i 0 && ws[0].length === 0) {
ws.shift();
}
for (i = 0; i 0) {
n = document.createElement(‘span’);
n.innerHTML = words[i];
p.insertBefore(n, textEl);
addDomNode(n);
}
if (i 0) {
n = document.createTextNode(ws[i]);
p.insertBefore(n, textEl);
}
}
p.removeChild(textEl);
}

buildTextEls(el, shouldAddChildren(el));
textEls.map(wordsToSpans);
};

/* includes el. */
this.addTagNames = function (el, tagNames) {
var tname = el.tagName && el.tagName.toLowerCase(),
i, j, els, len;
if (el.khIgnore) {
return;
}
if (tagNames.indexOf(tname) !== -1) {
addDomNode(el);
}
if (!el.getElementsByTagName) {
return;
}
for (i = 0; i boolean true if the object should be removed.
*/
this.removeIntersecting = function (x, y, r, cb) {
var xi, yi, arr, i, r2 = r * r, go,
startXI = Math.floor((x – r) / GRIDX),
startYI = Math.floor((y – r) / GRIDY),
endXI = Math.floor((x + r) / GRIDX) + 1,
endYI = Math.floor((y + r) / GRIDY) + 1;
for (xi = startXI; xi getVol()) {
return false;
}
attachGridObj(go);
return true;
}

this.updatePhysics = function () {
var oldX = x, oldY = y, dx, dy,
bounce = false,
accelTh;
if (accel) {
accelTh = Math.atan2(accelTargetY – y, accelTargetX – x);
vx += Math.cos(accelTh) * 0.5;
vy += Math.sin(accelTh) * 0.5;
} else {
vx *= 0.95;
vy *= 0.95;
}
x += vx;
y += vy;
/* bounce ball on edges of document. */
if (x – radius docW) {
bounce = true;
x = docW – radius – 1;
vx = -vx;
}
if (y – radius docH) {
bounce = true;
y = docH – radius – 1;
vy = -vy;
}
if (vx !== 0 || vy !== 0) {
th = Math.atan2(vy, vx);
dx = x – oldX;
dy = y – oldY;
/* arclen = th * r, so th = arclen / r. */
phi -= Math.sqrt(dx * dx + dy * dy) / radius;
}
stickyNodes.removeIntersecting(x, y, radius, removeIntCb);
this.draw();
if (bounce && sounds) {
sounds.play_bounce();
}
};

function drawBall() {
var sx1, sy1, sx2, sy2, dx, dy, i, pct1, pct2, z1, z2;
/* move/resize canvas element. */
canvas_el.style.left = (x – radius) + ‘px’;
canvas_el.style.top = (y – radius) + ‘px’;
if (radius != lastR) {
canvas_el.width = 2 * radius + 1;
canvas_el.height = 2 * radius + 1;
lastR = radius;
}
/* draw white circle. */
canvas_ctx.clearRect(0, 0, 2 * radius, 2 * radius);
canvas_ctx.fillStyle = “#fff”;
canvas_ctx.beginPath();
canvas_ctx.arc(radius, radius, radius – 1, 0, Math.PI * 2, true);
canvas_ctx.fill();
/* draw outer border. */
canvas_ctx.strokeStyle = color;
canvas_ctx.beginPath();
canvas_ctx.arc(radius, radius, radius – 1, 0, Math.PI * 2, true);
canvas_ctx.stroke();
/* draw stripes. */
canvas_ctx.fillStyle = color;
sx1 = radius + radius * Math.cos(th + Math.PI / 16);
sy1 = radius + radius * Math.sin(th + Math.PI / 16);
sx2 = radius + radius * Math.cos(th – Math.PI / 16);
sy2 = radius + radius * Math.sin(th – Math.PI / 16);
dx = (radius + radius * Math.cos(th + Math.PI * 15 / 16)) – sx1;
dy = (radius + radius * Math.sin(th + Math.PI * 15 / 16)) – sy1;
for (i = 0; i 0 && z2 > 0) {
canvas_ctx.beginPath();
canvas_ctx.moveTo(sx1 + pct1 * dx, sy1 + pct1 * dy);
canvas_ctx.lineTo(sx1 + pct2 * dx, sy1 + pct2 * dy);
canvas_ctx.lineTo(sx2 + pct2 * dx, sy2 + pct2 * dy);
canvas_ctx.lineTo(sx2 + pct1 * dx, sy2 + pct1 * dy);
canvas_ctx.fill();
}
}
}

/**
* @return true if the attached object is roughly visible.
*/
function drawAttached(att) {
var oth = th + att.offTh,
ophi = phi + att.offPhi,
ox = att.r * Math.cos(oth),
oy = att.r * Math.sin(oth),
dx = (att.r * Math.cos((th – att.offTh) + Math.PI)) – ox,
dy = (att.r * Math.sin((th – att.offTh) + Math.PI)) – oy,
pct = (-Math.cos(ophi) + 1) / 2,
cx = ox + pct * dx,
cy = oy + pct * dy,
oz = att.r * Math.sin(ophi);
if (oz 0)? 501 : 499;
att.el.style.setProperty(
CSS_TRANSFORM,
‘translate(‘ + x + ‘px,’ + y + ‘px) ‘ +
‘rotate(‘ + th + ‘rad) ‘ +
‘scaleX(‘ + Math.cos(ophi) + ‘) ‘ +
att.attT, null);
return true;
}

function onAttachedRemoved(att) {
attachedDiv.removeChild(att.el);
delete att.el;
}

this.draw = function () {
var i, att, numAttachedVisible = 0;
drawBall();
for (i = attached.length; –i >= 0;) {
att = attached[i];
if (att.removeR MAX_ATTACHED_VISIBLE) {
/* remove older items and stop. */
attached.splice(0, i).map(onAttachedRemoved);
break;
}
}
}
};
}

function preventDefault(event) {
event.preventDefault();
event.returnValue = false;
return false;
}

function Game(gameDiv, stickyNodes, ballOpts) {
var stickyNodes, player1, physicsInterval, resizeInterval, listeners = [];
player1 = new PlayerBall(gameDiv, stickyNodes, ballOpts, false);
player1.init();
player1.setXY(300, 300);
window.scrollTo(0, 200);

function on_resize() {
player1.setDocSize(jQuery(document).width() – 5,
jQuery(document).height() – 5);
}
on_resize();

/* touch events – always on? */
document.addEventListener(‘touchstart’, function (event) {
if (event.touches.length === 1) {
player1.setAccel(true);
return preventDefault(event);
}
}, true);
document.addEventListener(‘touchmove’, function (event) {
player1.setAccelTarget(event.touches[0].pageX,
event.touches[0].pageY);
}, true);
document.addEventListener(‘touchend’, function (event) {
if (event.touches.length === 0) {
player1.setAccel(false);
return preventDefault(event);
}
}, true);

if (ballOpts.MOUSEB !== -5) {
/* mouse buttons */
document.addEventListener(‘mousemove’, function (event) {
player1.setAccelTarget(event.pageX, event.pageY);
}, true);
document.addEventListener(‘mousedown’, function (event) {
if (event.button === ballOpts.MOUSEB) {
player1.setAccel(true);
return preventDefault(event);
}
}, true);
document.addEventListener(‘mouseup’, function (event) {
if (event.button === ballOpts.MOUSEB) {
player1.setAccel(false);
return preventDefault(event);
}
}, true);

if (ballOpts.MOUSEB === 0) {
/* block click events. */
document.addEventListener(‘click’, function (event) {
if (event.button === 0) {
return preventDefault(event);
}
}, true);
} else if (ballOpts.MOUSEB === 2) {
/* block right-click context menu. */
document.addEventListener(‘contextmenu’, preventDefault, true);
}
}

physicsInterval = setInterval(function () {
player1.updatePhysics();
}, 25);
resizeInterval = setInterval(on_resize, 1000);
}

function whenAllLoaded(gameDiv, popup, stickyNodes) {
stickyNodes.finalize(jQuery(document).width(), jQuery(document).height());
jQuery(‘#loadingp’).empty();
jQuery(‘‘).click(function () {
var game, bgmusic, ballOpts;
if (jQuery(‘#bgmusicc’).attr(‘checked’)) {
if (!(bgmusic = document.getElementById(‘khbgmusic’))) {
bgmusic = document.createElement(‘audio’);
bgmusic.id = ‘khbgmusic’;
bgmusic.loop = ‘loop’;
bgmusic.src = ‘http://kathack.com/js/katamari.mp3’;
gameDiv.appendChild(bgmusic);
}
bgmusic.play();
}
ballOpts = {
color: jQuery(‘#khcolor’).val(),
VOL_MULT: parseFloat(jQuery(‘#vol_mult’).val()),
MAX_ATTACHED_VISIBLE: parseInt(jQuery(‘#maxAtt’).val(), 10),
CHECK_VOLS: (jQuery(‘#checkv’).attr(‘checked’))? true : false,
MOUSEB: parseInt(jQuery(‘#mouseb’).val(), 10)
};
gameDiv.removeChild(popup);
game = new Game(gameDiv, stickyNodes, ballOpts);
}).appendTo(‘#loadingp’);
}

function buildPopup(gameDiv) {
var d = document.createElement(‘div’), b;
d.style.cssText = ‘
position: fixed;
left: 50%;
top: 50%;
width: 400px;
margin-left:-200px;
margin-top:-150px;
border:1px solid black;
background-color:white;
color:black;
padding:20px;
font-size:13px;
text-align:left;
z-index:501;’;
d.innerHTML = ‘


Katamari!

Controls: Hold down to control the ball!




Loading!

‘;
gameDiv.appendChild(d);
d.getElementsByTagName(‘button’)[0].addEventListener(‘click’, function () {
gameDiv.removeChild(d);
}, true);
return d;
}

function main() {
var gameDiv, checkInterval, stickyNodes, popup;

gameDiv = document.createElement(‘div’);
gameDiv.khIgnore = true;
document.body.appendChild(gameDiv);
popup = buildPopup(gameDiv);

/* setTimeout so that the popup displays before we freeze. */
setTimeout(function () {
var i, len, el;
window.khNodes.addWords(document.body);
for (i = 0, len = document.body.childNodes.length; i http://kathack.com/

Recommended
Sponsors
The most important and interesting stories in tech. Straight to your inbox, daily. Get Versioning.
Login or Create Account to Comment
Login Create Account