384 lines
11 KiB
HTML
Executable file
384 lines
11 KiB
HTML
Executable file
<!DOCTYPE html>
|
||
|
||
<html>
|
||
<head>
|
||
<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
|
||
<title>Antville’s Formica Bookmarklet</title>
|
||
<style>
|
||
body {
|
||
font-family: sans-serif;
|
||
}
|
||
form {
|
||
margin-bottom: 1em;
|
||
}
|
||
input#title, textarea#text {
|
||
width: 400px;
|
||
padding: 2px;
|
||
border: 1px solid #ccc;
|
||
font-size: 1.2em;
|
||
}
|
||
input#title {
|
||
height: 26px;
|
||
margin: 0 0 4px 0;
|
||
font-weight: bold;
|
||
}
|
||
textarea#text {
|
||
height: 160px;
|
||
}
|
||
button {
|
||
margin: 0;
|
||
font-size: 18px;
|
||
}
|
||
img {
|
||
background: url('http://t2.gstatic.com/images?q=tbn:ANd9GcRayuCjH7MGcnJmYfBEHmIVNl9UFJuhCsawGzGgjI66sgwmgMweIQ&t=1');
|
||
}
|
||
img.harvest {
|
||
margin: 3px;
|
||
background-color: #ccc;
|
||
border: 1px solid #ccc;
|
||
opacity: 0.33;
|
||
}
|
||
img.selected {
|
||
border-color: black;
|
||
opacity: 1.0;
|
||
}
|
||
@-webkit-keyframes rotate {
|
||
from {
|
||
-webkit-transform: rotate(0deg);
|
||
}
|
||
to {
|
||
-webkit-transform: rotate(360deg);
|
||
}
|
||
}
|
||
img.loading {
|
||
background: none;
|
||
margin-top: 50%;
|
||
-webkit-animation-name: rotate;
|
||
-webkit-animation-duration: 0.5s;
|
||
-webkit-animation-iteration-count: infinite;
|
||
-webkit-transition-timing-function: linear;
|
||
}
|
||
.left {
|
||
float: left;
|
||
min-height: 400px;
|
||
}
|
||
.info {
|
||
text-align: center;
|
||
}
|
||
.image {
|
||
width: 200px;
|
||
min-height: 201px;
|
||
margin: 0 4px 4px 0;
|
||
border-bottom: 1px solid #ccc;
|
||
overflow: visible hidden;
|
||
text-align: center;
|
||
}
|
||
.controls {
|
||
display: inline-block;
|
||
float: left;
|
||
margin-right: 4px;
|
||
}
|
||
.controls a {
|
||
display: inline-block;
|
||
padding: 4px;
|
||
border: 1px solid #ccc;
|
||
color: #ccc;
|
||
text-decoration: none;
|
||
font-size: 18px;
|
||
line-height: 16px;
|
||
}
|
||
.controls a[href='#next'] {
|
||
transform: scale(-1, 1);
|
||
-moz-transform: scale(-1, 1);
|
||
-webkit-transform: scale(-1, 1);
|
||
filter: progid:DXImageTransform.Microsoft.BasicImage(mirror=1)
|
||
}
|
||
.info {
|
||
line-height: 28px;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<div class='left'>
|
||
<div class='image'>
|
||
<img src='http://antville.org/static/www/ant.png' class='loading'>
|
||
</div>
|
||
<div class='info'></div>
|
||
</div>
|
||
|
||
<form>
|
||
<div>
|
||
<input id='title' type='text' placeholder='Title'>
|
||
</div>
|
||
<div>
|
||
<textarea id='text' placeholder='Description'></textarea>
|
||
</div>
|
||
<div>
|
||
<div class='controls'>
|
||
<a href='#previous'>⬅</a>
|
||
<a href='#next'>⬅</a>
|
||
</div>
|
||
<button name='button' type='button'>Publish</button>
|
||
<input type='checkbox' id='image' checked>
|
||
<label for='image'>Include image</label>
|
||
</div>
|
||
</form>
|
||
|
||
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js"></script>
|
||
|
||
<script type='text/javascript'>
|
||
$(function() {
|
||
var proxyUri = '//p3k-001.appspot.com/roxy';
|
||
//proxyUri = 'http://localhost:8081/roxy';
|
||
var args, siteUri, sourceUri, images, currentIndex;
|
||
|
||
(function(search) {
|
||
search = String(search).substr(1);
|
||
if (search.length > 0) {
|
||
args = {};
|
||
var parts = search.split('&');
|
||
$.each(parts, function(index, item) {
|
||
parts = item.split('=');
|
||
args[parts[0]] = decodeURIComponent(parts[1]);
|
||
});
|
||
}
|
||
}(location.search));
|
||
|
||
$('.controls a').click(function(event) {
|
||
event.preventDefault();
|
||
var image = getNextImage($(this).attr('href') === '#next' ? 1 : -1);
|
||
displayImage(image);
|
||
});
|
||
|
||
$('#image').click(function(event) {
|
||
toggleImage();
|
||
});
|
||
|
||
$('form button').click(function(event) {
|
||
event.preventDefault();
|
||
$(this).attr('disabled', true);
|
||
var imageUri = $('.left').css('display') === 'none' ? null : images[currentIndex].src;
|
||
post(sourceUri, imageUri);
|
||
});
|
||
|
||
function main() {
|
||
if (!args.s || !args.l) {
|
||
return;
|
||
}
|
||
siteUri = decodeURIComponent(args.s);
|
||
sourceUri = decodeURIComponent(args.l);
|
||
if (siteUri && sourceUri) {
|
||
var text = $.trim(decodeURIComponent(args.c));
|
||
text && (text = '<a href="' + sourceUri + '">' + $.trim(text) + '</a>');
|
||
args.r && (text += ' Via ' + decodeURIComponent(args.r) + '.');
|
||
$('#text').val(text);
|
||
images = [];
|
||
currentIndex = 0;
|
||
if (sourceUri.match(new RegExp('(?:bmp|gif|jpg|jpeg|png)$', 'i'))) {
|
||
addImage(sourceUri);
|
||
return;
|
||
}
|
||
$.getJSON(proxyUri + '?callback=?&url=' + sourceUri, function(data) {
|
||
if (!data.content) {
|
||
return;
|
||
}
|
||
var baseHref = getBaseHref(data.content);
|
||
var match, re = /(?:\(|=|"|')([^\s\(\)'">]+\.(?:gif|jpg|jpeg|png))/gi;
|
||
while (match = re.exec(data.content)) {
|
||
addImage(match[1], baseHref);
|
||
}
|
||
if (images.length < 1 && !addImage.counter) {
|
||
toggleImage();
|
||
$('#image').attr({disabled: true, checked: false});
|
||
}
|
||
});
|
||
}
|
||
}
|
||
|
||
function getBaseHref(data) {
|
||
// jQuery does not return the correct value for $('base').attr('href').
|
||
// Thus, we directly crunch the base href value from the raw data.
|
||
var re = new RegExp('<base href=(?:[\'"])?([^>\'"]+)');
|
||
var match = data.match(re);
|
||
if (match && match.length > 1) {
|
||
return match[1];
|
||
}
|
||
var index = sourceUri.lastIndexOf('/');
|
||
if (index !== sourceUri.length - 1) {
|
||
return sourceUri.substring(0, index + 1);
|
||
}
|
||
return sourceUri;
|
||
}
|
||
|
||
function addImage(url, baseUri) {
|
||
if (!url || images[url]) {
|
||
return;
|
||
}
|
||
images[url] = true;
|
||
addImage.counter || (addImage.counter = 0);
|
||
if (url.charAt(0) === '/') {
|
||
if (url.charAt(1) !== '/') {
|
||
// url starts with one single slash: prepend root of sourceUri.
|
||
var index = sourceUri.indexOf('/', sourceUri.indexOf('://') + 3);
|
||
baseUri = index > -1 ? sourceUri.substring(0, index) : sourceUri;
|
||
url = baseUri + url;
|
||
}
|
||
} else if (url.indexOf('://') < 0) {
|
||
// url does neither start with a slash, nor contain
|
||
// a protocol: prepend sourceUri up to the final slash.
|
||
baseUri || (baseUri = sourceUri.substring(0, sourceUri.lastIndexOf('/') + 1));
|
||
url = baseUri + url;
|
||
}
|
||
var image = new Image;
|
||
image.src = url;
|
||
addImage.counter += 1;
|
||
image.onload = function() {
|
||
if (this.width > 100 || this.height > 100) {
|
||
images.push(this);
|
||
displayImage(images[0]);
|
||
}
|
||
addImage.counter -= 1;
|
||
}
|
||
return;
|
||
|
||
var item = $('<img>');
|
||
item.attr({src: url}).addClass('harvest').click(function() {
|
||
var self = this;
|
||
$('img').each(function() {
|
||
$(this)[this === self ? 'addClass' : 'removeClass']('selected');
|
||
});
|
||
});
|
||
$('body').append(item);
|
||
}
|
||
|
||
function appendImage(url) {
|
||
if (!url || images[url]) {
|
||
return;
|
||
}
|
||
images[url] = true;
|
||
var baseUri = '';
|
||
if (url.charAt(0) === '/') {
|
||
if (url.charAt(1) !== '/') {
|
||
// url starts with one single slash: prepend root of sourceUri.
|
||
var index = sourceUri.indexOf('/', sourceUri.indexOf('://') + 3);
|
||
baseUri = index > -1 ? sourceUri.substring(0, index) : sourceUri;
|
||
url = baseUri + url;
|
||
}
|
||
} else if (url.indexOf('://') < 0) {
|
||
// url does neither start with a slash, nor contain
|
||
// a protocol: prepend sourceUri up to the final slash.
|
||
baseUri = sourceUri.substring(0, sourceUri.lastIndexOf('/') + 1);
|
||
url = baseUri + url;
|
||
}
|
||
var item = $('<img>');
|
||
item.attr({src: url}).addClass('harvest').click(function() {
|
||
var self = this;
|
||
$('img').each(function() {
|
||
$(this)[this === self ? 'addClass' : 'removeClass']('selected');
|
||
});
|
||
});
|
||
$('body').append(item);
|
||
}
|
||
|
||
function displayImage(image) {
|
||
var MAX_WIDTH = 200;
|
||
var MAX_HEIGHT = 600;
|
||
var width = image.width;
|
||
var height = image.height;
|
||
var factorH = 1, factorV = 1;
|
||
if (width > MAX_WIDTH) {
|
||
factorH = MAX_WIDTH / width;
|
||
}
|
||
if (height > MAX_HEIGHT) {
|
||
factorV = MAX_HEIGHT / height;
|
||
}
|
||
if (factorH !== 1 || factorV !== 1) {
|
||
image.width = Math.ceil(width * (factorH < factorV ? factorH : factorV));
|
||
image.height = Math.ceil(height * (factorH < factorV ? factorH : factorV));
|
||
}
|
||
$('.image').html(image);
|
||
$('.info').html((currentIndex + 1) + ' of ' + images.length);
|
||
return;
|
||
}
|
||
|
||
function getNextImage(direction) {
|
||
var index = currentIndex || 0;
|
||
index += direction || 1;
|
||
if (index >= images.length) {
|
||
index = 0;
|
||
} else if (index < 0) {
|
||
index = images.length - 1;
|
||
}
|
||
var image = images[index];
|
||
currentIndex = index;
|
||
return image;
|
||
}
|
||
|
||
function post(url, imageUrl) {
|
||
var postStory = function(imageName) {
|
||
var imageMacro = (imageName ? "\n\n<\x25 image '" +
|
||
imageName + "' | link '" + url + "' \x25>" : '');
|
||
$.getJSON(siteUri + '/stories/create?callback=?', {
|
||
save: 1,
|
||
title: $('#title').val(),
|
||
text: $('#text').val() + imageMacro
|
||
}, function(data, status, xhr) {
|
||
if (!data) {
|
||
//console.error(this, arguments);
|
||
return alert('Error: ' + status);
|
||
}
|
||
if (window.opener) {
|
||
window.close();
|
||
} else {
|
||
location.href = siteUri + '/stories/' + data;
|
||
}
|
||
});
|
||
}
|
||
if (imageUrl) {
|
||
var name = 'image-' + Date.now();
|
||
$.getJSON(siteUri + '/images/create?callback=?', {
|
||
save: 1,
|
||
file_origin: imageUrl,
|
||
name: name,
|
||
description: 'Source: ' + url.replace(new RegExp('^.+:///?([^/]+).*$'), '$1'),
|
||
maxWidth: args.w || '',
|
||
maxHeight: args.h || ''
|
||
}, function(data, status, xhr) {
|
||
if (!data) {
|
||
//console.error(this, arguments);
|
||
return alert('Error: ' + status);
|
||
}
|
||
postStory(name);
|
||
});
|
||
} else {
|
||
postStory();
|
||
}
|
||
return;
|
||
}
|
||
|
||
function toggleImage() {
|
||
var width;
|
||
var left = $('.left');
|
||
if (left.css('display') === 'none') {
|
||
left.show();
|
||
$('.controls').show();
|
||
width = $('input#title').data('width');
|
||
$('input#title').css({width: width});
|
||
$('textarea#text').css({width: width});
|
||
} else {
|
||
left.hide();
|
||
$('.controls').hide();
|
||
width = 604;
|
||
$('input#title').data('width', $('input#title').width())
|
||
.css({width: width});
|
||
$('textarea#text').css({width: width});
|
||
}
|
||
}
|
||
|
||
main();
|
||
});
|
||
</script>
|
||
|
||
</body>
|
||
</html>
|