Instantly share code, notes, and snippets.
Last active
June 26, 2016 14:09
-
Star
1
(1)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save falsefalse/dc7bb726add8b19a741c to your computer and use it in GitHub Desktop.
FriendFeed bookmarklet that ain't broken in Chrome (and other sane webkits)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
javascript:void((function(){var%20e=document.createElement('script');e.setAttribute('type','text/javascript');e.setAttribute('src','https://cdn.rawgit.com/falsefalse/dc7bb726add8b19a741c/raw/bcb52121789465edc635ca9f244c21a997b00d04/share.js');document.body.appendChild(e)})()) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function() { | |
var kMinImageSize = 30; | |
var kOutlineColor = "#1030cc"; | |
var kOutlineSize = 3; | |
var kShadowSize = 7; | |
var gAvailableImages = []; | |
function bookmarklet() { | |
if (byId("ff__container")) { | |
return; | |
} | |
var selection; | |
if (window.getSelection) { | |
selection = '' + window.getSelection(); | |
} else if (document.selection) { | |
selection = document.selection.createRange().text; | |
} | |
// Highlight all the images on the page | |
var numImages = 0; | |
var imageElements = window.ff__reshare ? [] : document.getElementsByTagName("img"); | |
for (var i = 0; i < imageElements.length; i++) { | |
var image = imageElements[i]; | |
if (image.width < kMinImageSize || image.height < kMinImageSize) { | |
continue; | |
} | |
numImages++; | |
var listener = addEventListener(image, "mouseover", curry(onImageMouseOver, image)); | |
gAvailableImages.push({ | |
element: image, | |
cursor: image.style.cursor, | |
listener: listener | |
}); | |
} | |
// Create the share dialog in the corner of the window | |
var container = div(); | |
container.id = "ff__container"; | |
container.style.position = "absolute"; | |
container.style.top = scrollPos().y + "px"; | |
container.style.right = "0"; | |
container.style.width = "auto"; | |
container.style.zIndex = 100000; | |
var shadow = div(container); | |
shadow.id = "ff__shadow"; | |
shadow.style.backgroundColor = "black"; | |
shadow.style.position = "absolute"; | |
shadow.style.zIndex = 0; | |
shadow.style.top = "0"; | |
shadow.style.right = "0"; | |
setOpacity(shadow, 0.3); | |
var foreground = div(container); | |
foreground.id = "ff__foreground"; | |
foreground.style.backgroundColor = "white"; | |
foreground.style.zIndex = 2; | |
foreground.style.width = "450px"; | |
foreground.style.height = "310px"; | |
foreground.innerHTML = '<iframe frameborder="0" id="ff__iframe" style="width:100%;height:100%;border:0px;padding:0px;margin:0px"></iframe>'; | |
document.body.appendChild(container); | |
var msg = { | |
title: document.title, | |
url: location.href, | |
parenturl: location.href | |
}; | |
if (window.ff__reshare) { | |
msg = { | |
reshare: "1" | |
}; | |
window.handleShareMessage = handleMessage; | |
} | |
msg.selection = selection || ''; | |
var links = document.getElementsByTagName('link'); | |
for (var i = 0; i < links.length; i++) { | |
if (links[i].rel == 'image_src') { | |
msg.image = links[i].href; | |
} else if (links[i].rel == 'video_src') { | |
msg.video = links[i].href; | |
} | |
} | |
var metas = document.getElementsByTagName('meta'); | |
for (var i = 0; i < metas.length; i++) { | |
if (metas[i].name == 'video_thumb') { | |
msg.image = metas[i].content; | |
} | |
} | |
if (location.host == 'www.theonion.com' && typeof (player) != "undefined" && typeof (player.playlist) != "undefined") { | |
msg.video = player.playlist; | |
} | |
if (msg.image && msg.image.indexOf("http://www.comedycentral.com/sitewide/droplets/img_rez.jhtml") != -1) { | |
msg.image = "http://www.comedycentral.com" + msg.image.slice(msg.image.indexOf('/', msg.image.indexOf('?')), msg.image.indexOf('&')); | |
} | |
// remove flickr overlays that obscure clicking the image | |
if (location.host == 'www.flickr.com') { | |
[].slice.call(document.querySelectorAll('.facade-of-protection-neue, a.navigate-target')) | |
.forEach(function(node) { node.parentNode.removeChild(node) }); | |
} | |
sendFrameMessage(msg); | |
// Make a container for our "click to include" images | |
var popupContainer = div(); | |
popupContainer.id = "ff__popup"; | |
popupContainer.style.position = "absolute"; | |
popupContainer.style.display = "none"; | |
popupContainer.style.left = "0px"; | |
popupContainer.style.top = "0px"; | |
popupContainer.style.zIndex = 99999; | |
popupContainer.style.fontSize = "8pt"; | |
popupContainer.style.fontFamily = "Arial"; | |
popupContainer.style.fontStyle = "normal"; | |
popupContainer.style.fontWeight = "normal"; | |
popupContainer.style.background = "transparent"; | |
document.body.appendChild(popupContainer); | |
// Size the shadow as the DIV changes | |
var lastShadowWidth = 0; | |
var lastShadowHeight = 0; | |
function resizeShadow() { | |
var shadow = byId("ff__shadow"); | |
var foreground = byId("ff__foreground"); | |
if (!shadow || !foreground) { | |
clearInterval(interval); | |
return; | |
} | |
if (lastShadowWidth != foreground.offsetWidth || | |
lastShadowHeight != foreground.offsetHeight) { | |
lastShadowWidth = foreground.offsetWidth; | |
lastShadowHeight = foreground.offsetHeight; | |
shadow.style.width = (lastShadowWidth + kShadowSize) + "px"; | |
shadow.style.height = (lastShadowHeight + kShadowSize) + "px"; | |
} | |
} | |
var interval = window.setInterval(function () { | |
checkForFrameMessage(); | |
resizeShadow(); | |
}, 50); | |
resizeShadow(); | |
window.onscroll = function () { | |
container.style.top = scrollPos().y + "px"; | |
}; | |
} | |
function onImageMouseOver(image, e) { | |
var popupContainer = byId("ff__popup"); | |
popupContainer.style.display = "none"; | |
clearNode(popupContainer); | |
var clickTarget = div(popupContainer); | |
clickTarget.style.position = "absolute"; | |
var offset = getOffset(image); | |
clickTarget.style.left = (offset.left - kOutlineSize + 1) + "px"; | |
clickTarget.style.top = (offset.top - kOutlineSize + 1) + "px"; | |
clickTarget.style.width = image.width + "px"; | |
clickTarget.style.height = image.height + "px"; | |
clickTarget.style.border = kOutlineSize + "px solid " + kOutlineColor; | |
clickTarget.style.cursor = "pointer"; | |
clickTarget.innerHTML = '<div style="margin:0;padding:0;width:100%;height:100%;position:relative;z-index:1;background-color:white;filter:alpha(opacity=1);opacity: 0.01"></div><div style="margin:0;position:absolute;top:0;left:0;background-color:white;padding:3px;color:#1030cc;border: 1px solid #1030cc;border-width: 0px 1px 1px 0px;z-index:2">' + 'Share image on FriendFeed' + '</div>'; | |
addEventListener(clickTarget, "click", curry(onImageClick, image)); | |
addEventListener(clickTarget, "mouseout", onHoverMouseOut); | |
popupContainer.style.display = ""; | |
cancelEvent(e); | |
} | |
function onHoverMouseOut(e) { | |
var popupContainer = byId("ff__popup"); | |
if (!popupContainer) return; | |
for (var n = e.toElement || e.relatedTarget; n; n = n.parentNode) | |
if (n == popupContainer) return; // moused over child | |
clearNode(popupContainer); | |
popupContainer.style.display = "none"; | |
cancelEvent(e); | |
} | |
function onImageClick(image, e) { | |
cancelEvent(e); | |
// work around flickr photos with notes | |
if (image.src == "http://l.yimg.com/g/images/spaceball.gif") | |
image = image.previousSibling; | |
sendFrameMessage({ | |
image: image.src, | |
w: image.width, | |
h: image.height | |
}); | |
} | |
function addEventListener(instance, eventName, listener) { | |
var listenerFn = listener; | |
if (instance.addEventListener) { | |
instance.addEventListener(eventName, listenerFn, false); | |
} else if (instance.attachEvent) { | |
listenerFn = function () { | |
listener(window.event); | |
} | |
instance.attachEvent("on" + eventName, listenerFn); | |
} else { | |
throw new Error("Event registration not supported"); | |
} | |
return { | |
instance: instance, | |
name: eventName, | |
listener: listenerFn | |
}; | |
} | |
function removeEventListener(event) { | |
var instance = event.instance; | |
if (instance.removeEventListener) { | |
instance.removeEventListener(event.name, event.listener, false); | |
} else if (instance.detachEvent) { | |
instance.detachEvent("on" + event.name, event.listener); | |
} | |
} | |
function cancelEvent(e) { | |
if (!e) e = window.event; | |
if (e.preventDefault) { | |
e.preventDefault(); | |
} else { | |
e.returnValue = false; | |
} | |
} | |
function scrollPos() { | |
if (self.pageYOffset !== undefined) { | |
return { | |
x: self.pageXOffset, | |
y: self.pageYOffset | |
}; | |
} | |
var d = document.documentElement; | |
return { | |
x: d.scrollLeft, | |
y: d.scrollTop | |
}; | |
} | |
function setScrollPos(pos) { | |
var e = document.documentElement, | |
b = document.body; | |
e.scrollLeft = b.scrollLeft = pos.x; | |
e.scrollTop = b.scrollTop = pos.y; | |
} | |
function getOffset(obj) { | |
var curleft = 0; | |
var curtop = 0; | |
if (obj.offsetParent) { | |
curleft = obj.offsetLeft; | |
curtop = obj.offsetTop; | |
while (obj = obj.offsetParent) { | |
curleft += obj.offsetLeft; | |
curtop += obj.offsetTop; | |
} | |
} | |
return { | |
left: curleft, | |
top: curtop | |
}; | |
} | |
function clearNode(node) { | |
while (node.firstChild) { | |
node.removeChild(node.firstChild); | |
} | |
} | |
function removeNode(node) { | |
if (node && node.parentNode) { | |
node.parentNode.removeChild(node); | |
} | |
} | |
function div(opt_parent) { | |
var e = document.createElement("div"); | |
e.style.padding = "0"; | |
e.style.margin = "0"; | |
e.style.border = "0"; | |
e.style.position = "relative"; | |
if (opt_parent) { | |
opt_parent.appendChild(e); | |
} | |
return e; | |
} | |
function curry(method) { | |
var curried = []; | |
for (var i = 1; i < arguments.length; i++) { | |
curried.push(arguments[i]); | |
} | |
return function () { | |
var args = []; | |
for (var i = 0; i < curried.length; i++) { | |
args.push(curried[i]); | |
} | |
for (var i = 0; i < arguments.length; i++) { | |
args.push(arguments[i]); | |
} | |
return method.apply(null, args); | |
} | |
} | |
function byId(id) { | |
return document.getElementById(id); | |
} | |
function setOpacity(element, opacity) { | |
if (navigator.userAgent.indexOf("MSIE") != -1) { | |
var normalized = Math.round(opacity * 100); | |
element.style.filter = "alpha(opacity=" + normalized + ")"; | |
} else { | |
element.style.opacity = opacity; | |
} | |
} | |
function sendFrameMessage(m) { | |
var p = ""; | |
for (var i in m) { | |
if (!m.hasOwnProperty(i)) | |
continue; | |
p += (p.length ? '&' : ''); | |
p += encodeURIComponent(i) + '=' + encodeURIComponent(m[i]); | |
} | |
var iframe; | |
iframe = byId("ff__iframe"); | |
if (!iframe) { | |
iframe = frames["ff__iframe"]; | |
} | |
// out of luck | |
if (!iframe) return; | |
if (iframe.contentWindow) { | |
iframe = iframe.contentWindow; | |
} | |
var url = window.ff__reshare ? "" : 'https://friendfeed.com'; | |
url += '/share/bookmarklet/frame#' + p; | |
try { | |
iframe.location.replace(url); | |
} catch (e) { | |
iframe.location = url; // safari | |
} | |
} | |
var gCurScroll = scrollPos(); | |
function checkForFrameMessage() { | |
var prefix = "FFSHARE-"; | |
var hash = location.href.split('#')[1]; // location.hash is decoded | |
if (!hash || hash.substring(0, prefix.length) != prefix) { | |
gCurScroll = scrollPos(); // save pos | |
return; | |
} | |
location.replace(location.href.split("#")[0] + "#"); | |
handleMessage(hash) | |
var pos = gCurScroll; | |
setScrollPos(pos); | |
setTimeout(function () { | |
setScrollPos(pos); | |
}, 10); | |
} | |
function handleMessage(msg) { | |
msg = msg.split('-'); | |
for (var i = 0; i < msg.length; i++) | |
msg[i] = decodeURIComponent(msg[i]); | |
switch (msg[1]) { | |
case 'close': | |
close(msg.slice(2)); | |
break; | |
case 'frameh': | |
byId("ff__foreground").style.height = msg[2] + "px"; | |
break; | |
} | |
} | |
function close(args) { | |
if (window["ff_reshare"]) { | |
delete window["ff__reshare"]; | |
} | |
window.onscroll = null; // TODO! | |
for (var i = 0; i < gAvailableImages.length; i++) | |
removeEventListener(gAvailableImages[i].listener); | |
removeNode(byId("ff__popup")); | |
function removeContainer() { | |
removeNode(byId("ff__container")); | |
return false; | |
} | |
if (!args || !args.length) { | |
removeContainer(); | |
return; | |
} | |
var message = args[0].replace('<a ', '<a style="font-weight:bold;color:#1030cc" '); | |
var foreground = byId("ff__foreground"); | |
clearNode(foreground); | |
foreground.style.color = "black"; | |
foreground.style.padding = "4px 10px 4px 4px"; | |
foreground.style.font = "10pt Arial, sans-serif" | |
foreground.style.fontStyle = "normal"; | |
foreground.style.fontWeight = "normal"; | |
foreground.style.width = ""; | |
foreground.style.height = ""; | |
foreground.innerHTML = '<img style="width:16px;height:16px;margin-bottom:-3px;margin-right:1px" src="http://friendfeed.com/static/images/icons/internal.png?v=e471e9afdf04ae568dcbddb5584fc6c0"> ' + message + ' <a href="#" id="ff__close" style="margin-left:1em;color:#1030cc">' + 'close' + '</a>'; | |
byId("ff__close").onclick = removeContainer; | |
setTimeout(removeContainer, 3500); | |
} | |
if (document.getElementsByTagName('head').length == 0 || | |
frames.length > document.getElementsByTagName('iframe').length) { | |
window.location.href = 'http://friendfeed.com/?link=' + escape(window.location.href); | |
} else { | |
bookmarklet(); | |
} | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment