Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
branch: master
Fetching contributors…

Cannot retrieve contributors at this time

466 lines (374 sloc) 18.168 kb
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<script type="text/javascript" charset="utf-8" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript">
var apikey = "32ecf7b4565d138bd5ca10e10ab7fae5"; // yes, this is probably bad, but you don't get the secret at least
var urlroot = "https://api.flickr.com/services/rest/"
var initial = {};
// TODO - shouldn't be globals, should pass state around in closures
var selected_namespace;
var selected_predicate;
var selected_tag;
var browserwidth = ($(window).width()-16)+"px";
var columnwidth = parseInt(($(window).width()-116)/3)+"px";
var pulserleft_main = parseInt(($(window).width()-48)/2)+"px";
var pulserleft_column = parseInt(($(window).width()-48-32)/2)+"px";
var debug = false;
function hide_uncommon() {
$("li.uncommon").slideUp();
}
function show_uncommon() {
$("li.uncommon").slideDown();
}
var l0json = function(data){
// TODO consider metaprogramming for json handers
for (var index = 0; index < data.namespaces.namespace.length; index++) {
var ns = data.namespaces.namespace[index]
$("ul#top div:first").append("<li class='level0' id='"+ns._content+"'>"+ns._content+" <span class='count'> "+ns.usage+"<"+"/span><span class='children'>"+ns.predicates+"<"+"/span><"+"/li>");
if (ns.usage < 10) {
$("li.level0:last").addClass("uncommon");
}
}
$("li.level0").click(l0click);
$("li.uncommon").hide();
// do we need to recurse?
if (!debug && data.namespaces.page < data.namespaces.pages) {
var page = data.namespaces.page+1;
$("div#load p#msg").text("loading namespaces (page "+page+")");
$.getJSON(urlroot+"?method=flickr.machinetags.getNamespaces&page="+page+"&api_key="+apikey+"&format=json&jsoncallback=?",
l0json);
} else {
$("ul#top div").show();
$("ul#top div#load").hide();
if (initial['namespace'] && $('li.level0:contains('+initial['namespace']+")").length) {
offset = $('li.level0:contains('+initial['namespace']+'):first').offset().top;
offset = offset-($('ul#top').offset().top);
$('ul#top div').attr({scrollTop:offset});
$('li.level0:contains('+initial['namespace']+'):first').click();
// reset initial hash
delete initial['namespace'];
}
}
};
var l0click = function(){
// TODO sort out commonalities here and in l1click
selected_namespace = $(this).attr("id");
set_hash(selected_namespace);
// Figure out if we've already asked for this predicate
var load = false;
if (!$(this).children("ul").length) {
load = true;
// Add and initialise the list element and the div
// container that's used to allow scrolling
$(this).append("<ul class='browser'><div><"+"/div><"+"/ul>");
$(this).find("ul").css({
left:columnwidth,
width:columnwidth,
height:"100%"
});
$(this).find("ul div").css({
width:columnwidth,
height:"100%",
overflowX:"hidden",
overflowY:"scroll"
});
}
// show this item as selected, and others as not
$(this).siblings().css({backgroundColor:"#fff"});
$(this).css({backgroundColor:"rgb(27,115,213)"});
// hide other children, show this one
$(this).siblings().find("ul").hide();
$(this).children("ul").show();
if (load) {
// show a spinner
$(this).find("ul div").html("<img src='http://l.yimg.com/g/images/pulser2.gif' style='position:relative; top:100px; left:"+pulserleft_column+";'>");
// actually call Flickr's API
$.getJSON(urlroot+"?method=flickr.machinetags.getPredicates&namespace="+selected_namespace+"&api_key="+apikey+"&format=json&jsoncallback=?",
l1json
);
}
return false;
};
var l1json = function(data){
$("li#"+selected_namespace+" ul div img").remove();
for (var index=0; index < data.predicates.predicate.length; index++) {
var predicate = data.predicates.predicate[index]
$("li#"+selected_namespace+" ul div").append("<li id='"+predicate._content+"' class='level1'>"+predicate._content+" <span class='count'>"+predicate.usage+"<"+"/span><"+"/li>");
}
if (data.predicates.page < data.predicates.pages) {
var more = data.predicates.total - data.predicates.perpage
$("li#"+selected_namespace+" ul div").append("<li>... ("+more+" not shown)<"+"/li>");
}
$("li.level1").click(l1click)
if (initial['predicate'] && $('li.level1:contains('+initial['predicate']+")").length) {
offset = $('li.level1:contains('+initial['predicate']+'):first').offset().top;
offset = offset-($('ul#top').offset().top);
$('li#'+selected_namespace+"ul div").attr({scrollTop:offset});
$('li.level1:contains('+initial['predicate']+'):first').click();
// reset initial hash
delete initial['predicate'];
}
};
var l1click = function(){
selected_predicate = $(this).attr("id");
set_hash(selected_namespace+":"+selected_predicate);
// ns = $(this).parent().parent().parent().attr("id");
var load = false;
if (!$(this).children("ul").length) {
load = true;
$(this).append("<ul id='"+selected_namespace+"_"+selected_predicate+"' class='browser'><div><"+"/div><"+"/ul>");
$(this).find("ul#"+selected_namespace+"_"+selected_predicate).css({
left:columnwidth,
width:columnwidth,
height:"100%"
});
$(this).find("ul#"+selected_namespace+"_"+selected_predicate+" div").css({
width: "250",
height:"100%",
overflowX:"hidden",
overflowY:"scroll"
});
};
$(this).siblings().css({backgroundColor:"#fff"});
$(this).css({backgroundColor:"rgb(27,115,213)"});
$(this).siblings().find("ul").hide();
$(this).children("ul").show();
if (load) {
$(this).find("ul#"+selected_namespace+"_"+selected_predicate+" div").html("<img src='http://l.yimg.com/g/images/pulser2.gif' style='position:relative; top:100px; left:"+pulserleft_column+";'>");
$.getJSON(urlroot+"?method=flickr.machinetags.getValues&namespace="+selected_namespace+"&predicate="+selected_predicate+"&api_key="+apikey+"&format=json&jsoncallback=?",
l2json
);
}
return false; // suppress level 0 click event
};
var l2json = function(data){
$("ul#"+selected_namespace+"_"+selected_predicate+" div img").remove();
for (var index = 0; index < data.values.value.length; index++) {
var value = data.values.value[index]
$("ul#"+selected_namespace+"_"+selected_predicate+" div").append("<li id='"+selected_namespace+"-"+selected_predicate+"-"+value._content.replace(/ /g, "-")+"' class='level2'>"+value._content+' <span class="count">'+value.usage+"<"+"/span><"+"/li>");
}
if (data.values.page < data.values.pages) {
var more = data.values.total-data.values.perpage
$("ul#"+selected_namespace+"_"+selected_predicate+" div").append("<li>... ("+more+" values not shown)<"+"/li>");
}
$("li.level2").click(l2click);
if (initial['value'] && $('li.level2:contains('+initial['value']+")").length) {
offset = $('li.level2:contains('+initial['value']+'):first').offset().top;
offset = offset-($('ul#top').offset().top);
$('ul#'+selected_namespace+"_"+selected_predicate+" div").attr({scrollTop:offset});
$('li.level2:contains('+initial['value']+'):first').click();
// reset initial hash
delete initial['value'];
}
};
var l2click = function(data) {
selected_tag = $(this).attr("id");
var flickr_tag = selected_tag.replace("-", ":");
flickr_tag = flickr_tag.replace("-", "=");
set_hash(flickr_tag);
flickr_tag = flickr_tag.replace(/-/g, " ");
var load = false;
if (!$(this).children("ul").length) {
load = true;
$(this).append("<ul id='"+selected_tag+"' class='browser'><div><"+"/div><"+"/ul>");
$(this).find("ul#"+selected_tag).css({
left:columnwidth,
width:"100px",
height:"100%"
});
$(this).find("ul#"+selected_tag+" div").css({
width: "100px",
height:"100%",
overflowX:"hidden",
overflowY:"scroll"
});
};
$(this).siblings().css({backgroundColor:"#fff"});
$(this).css({backgroundColor:"rgb(27,115,213)"});
$(this).siblings().find("ul").hide();
$(this).children("ul").show();
if (load) {
$(this).find("ul#"+selected_tag+" div").html("<img src='http://l.yimg.com/g/images/pulser2.gif' style='position:relative; top:100px; left:39px;'>");
$.getJSON(urlroot+"?method=flickr.photos.search&tags="+flickr_tag+"&per_page=20&extras=owner_name&api_key="+apikey+"&format=json&jsoncallback=?",
l3json
);
}
return false;
};
var l3json = function(data) {
$("li#"+selected_tag+" ul div img").remove();
var flickr_tag = selected_tag.replace("-", ":");
flickr_tag = flickr_tag.replace("-", "=");
flickr_tag = flickr_tag.replace(/-/g, " ");
$("li#"+selected_tag+" div").append("<li id='p_all'><a href='https://flickr.com/photos/tags/"+flickr_tag+"'>All photos &rarr;<"+"/a>");
for (var index = 0; index < data.photos.photo.length; index++) {
var p = data.photos.photo[index];
html = '<li id="p_'+p.id+'"><a href="https://flickr.com/photos/'+p.owner+'/'+p.id+'/"><img src="https://farm'+p.farm+'.static.flickr.com/'+p.server+'/'+p.id+'_'+p.secret+'_s.jpg" width="75" height="75" alt="'+p.title+'" border="0"><'+'/a>';
$("li#"+selected_tag+" div").append(html);
}
$("li#"+selected_tag+" ul div li").click( function() { window.location = $(this).find('a').attr('href'); } );
};
if (!window.console) {
window.console = {
'log':function() {}
}
}
function set_hash(text) {
window.location.hash = "tag="+text;
}
$(document).ready( function() {
// size and position browser elements
$("ul.browser").height($(window).height()-$('div#blurb').height()-48);
$("ul#top").css({
width: browserwidth
});
// $("div#load img").css({
// left: pulserleft_main
// });
$("ul#top div:first").css({
height:"100%",
width:columnwidth,
overflowX:"hidden",
overflowY:"scroll"
});
$("ul#top div").hide();
$("ul#top div#load").show();
$("div#load p#msg").text("loading namespaces (page 1)");
$.getJSON(urlroot+"?method=flickr.machinetags.getNamespaces&api_key="+apikey+"&format=json&jsoncallback=?",
l0json);
var tag = window.location.hash.substr(6) || window.location.search.substr(1);;
if (tag) {
// TODO split with regex?
var items1 = tag.split(":");
initial["namespace"] = items1[0];
if (items1[1]) {
var items2 = items1[1].split("=");
initial["predicate"] = items2[0];
if (items2[1]) {
initial["value"] = items2[1].replace(/-/g, " ");
}
}
}
$("a#hide-overlay").click(function() {$("div#overlay").hide();})
});
</script>
<style type="text/css">
/* set styles directly rather than using jQuery.css() calls,
* or indeed an extra file, so that it's easier to edit/deploy.
*/
body {
background:#fff;
color:#000;
font:13/16px Arial, Helvetica, sans-serif;
}
h1 {
font: 16px;
font-weight: normal;
line-height:10px;
}
ul.browser {
display:block;
position:absolute;
top:-1px;
left:250px;
padding:0;
margin:0;
width:250px;
height:600px;
border:1px solid rgb(178,178,178);
background:#fff;
}
ul#top {
width:850px;
}
ul#top.browser {
left:0px;
}
li {
list-style: none;
padding: 2px;
}
li span.count {
font-size: 80%;
line-height:160%;
color:#ccc;
}
li span.children {
font-size: 80%;
line-height:160%;
color:#ccc;
display:none;
}
li a {
text-decoration:none;
color:#000;
}
div#overlay {
padding: 0px 10px;
margin: 0px;
position: absolute;
opacity:0.8;
-moz-opacity:0.8;
filter: alpha(opacity=85);
z-index: 1;
bottom: 52px;
right: 46px;
width: 30%;
color: #999;
background-color: black;
}
div#overlay a {
color: white;
}
div ul {
padding-left:0px;
margin-left:0px;
}
</style>
<title>husk.org. a flickr machine tag browser.</title>
</head>
<body>
<div id="blurb">
<h1>a <a href="http://www.flickr.com/">flickr</a> machine tag browser</h1>
</div>
<div style="position:relative;">
<ul id="top" class="browser">
<div></div>
<div id='load' style="text-align:center;">
<img src='http://l.yimg.com/g/images/pulser2.gif' style='position:relative; top:100px;'><br>
<p id='msg' style="position:relative; top:150px;">initialising</p>
</div>
</ul>
</div>
<div id="overlay">
<p>Browse Flickr machine tag namespaces, predicates and values. For more, see <a href="http://www.flickr.com/groups/api/discuss/72157594497877875/">this post about machine tags</a> and <a href="http://tech.groups.yahoo.com/group/yws-flickr/message/4545">this post about new API methods</a> (which enabled this hack to be built).</p>
<p>A Flickr hack by <a href="http://husk.org/">Paul Mison</a>. Browser view code inspired by <a href="http://code.google.com/p/jquery-column-navigation/">jQuery Column Navigator</a>. Not associated with Flickr (but I use their pulser because I'm lazy, sorry). <a href="http://github.com/blech/flimter/tree/master">At Github.</a></p>
<p>TODO:</p>
<ul>
<li>make ... work in predicates+values</li>
<li>sort by count (total or child)</li>
<li>offer all namespaces browser</li>
</ul>
<p>Show <a href="#" onclick="javascript:$('span.children').show(); $('span.count').hide(); return false;">children</a>
| <a href="#" onclick="javascript:$('span.count').show(); $('span.children').hide(); return false;">count</a>.<br>
<a href="#" onclick="javascript:hide_uncommon(); return false;">Hide</a>
| <a href="#" onclick="javascript:show_uncommon(); return false;">show</a>
uncommon namespaces.
</p>
<p align="right"><a href="#" id="hide-overlay">Hide this overlay</a></p>
</div>
<!-- I thought I'd like to know if anyone was watching -->
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
try {
var pageTracker = _gat._getTracker("UA-5271055-2");
pageTracker._trackPageview();
} catch(err) {}</script>
</body>
</html>
Jump to Line
Something went wrong with that request. Please try again.