CINXE.COM

March | 2009 | code.flickr.com

<!DOCTYPE html> <!--[if IE 6]> <html id="ie6" lang="en-US"> <![endif]--> <!--[if IE 7]> <html id="ie7" lang="en-US"> <![endif]--> <!--[if IE 8]> <html id="ie8" lang="en-US"> <![endif]--> <!--[if !(IE 6) & !(IE 7) & !(IE 8)]><!--> <html lang="en-US"> <!--<![endif]--> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width" /> <title> March | 2009 | code.flickr.com </title> <link rel="profile" href="https://gmpg.org/xfn/11" /> <link rel="stylesheet" type="text/css" media="all" href="https://code.flickr.net/wp-content/themes/flickr-code/style.css?ver=20190507" /> <link rel="pingback" href="https://code.flickr.net/xmlrpc.php"> <!--[if lt IE 9]> <script src="https://code.flickr.net/wp-content/themes/twentyeleven/js/html5.js?ver=3.7.0" type="text/javascript"></script> <![endif]--> <meta name='robots' content='max-image-preview:large' /> <style>img:is([sizes="auto" i], [sizes^="auto," i]) { contain-intrinsic-size: 3000px 1500px }</style> <link rel='dns-prefetch' href='//stats.wp.com' /> <link rel="alternate" type="application/rss+xml" title="code.flickr.com &raquo; Feed" href="https://code.flickr.net/feed/" /> <link rel="alternate" type="application/rss+xml" title="code.flickr.com &raquo; Comments Feed" href="https://code.flickr.net/comments/feed/" /> <script type="text/javascript"> /* <![CDATA[ */ window._wpemojiSettings = {"baseUrl":"https:\/\/s.w.org\/images\/core\/emoji\/15.0.3\/72x72\/","ext":".png","svgUrl":"https:\/\/s.w.org\/images\/core\/emoji\/15.0.3\/svg\/","svgExt":".svg","source":{"concatemoji":"https:\/\/code.flickr.net\/wp-includes\/js\/wp-emoji-release.min.js?ver=6.7.2"}}; /*! This file is auto-generated */ !function(i,n){var o,s,e;function c(e){try{var t={supportTests:e,timestamp:(new Date).valueOf()};sessionStorage.setItem(o,JSON.stringify(t))}catch(e){}}function p(e,t,n){e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(t,0,0);var t=new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data),r=(e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(n,0,0),new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data));return t.every(function(e,t){return e===r[t]})}function u(e,t,n){switch(t){case"flag":return n(e,"\ud83c\udff3\ufe0f\u200d\u26a7\ufe0f","\ud83c\udff3\ufe0f\u200b\u26a7\ufe0f")?!1:!n(e,"\ud83c\uddfa\ud83c\uddf3","\ud83c\uddfa\u200b\ud83c\uddf3")&&!n(e,"\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc65\udb40\udc6e\udb40\udc67\udb40\udc7f","\ud83c\udff4\u200b\udb40\udc67\u200b\udb40\udc62\u200b\udb40\udc65\u200b\udb40\udc6e\u200b\udb40\udc67\u200b\udb40\udc7f");case"emoji":return!n(e,"\ud83d\udc26\u200d\u2b1b","\ud83d\udc26\u200b\u2b1b")}return!1}function f(e,t,n){var r="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?new OffscreenCanvas(300,150):i.createElement("canvas"),a=r.getContext("2d",{willReadFrequently:!0}),o=(a.textBaseline="top",a.font="600 32px Arial",{});return e.forEach(function(e){o[e]=t(a,e,n)}),o}function t(e){var t=i.createElement("script");t.src=e,t.defer=!0,i.head.appendChild(t)}"undefined"!=typeof Promise&&(o="wpEmojiSettingsSupports",s=["flag","emoji"],n.supports={everything:!0,everythingExceptFlag:!0},e=new Promise(function(e){i.addEventListener("DOMContentLoaded",e,{once:!0})}),new Promise(function(t){var n=function(){try{var e=JSON.parse(sessionStorage.getItem(o));if("object"==typeof e&&"number"==typeof e.timestamp&&(new Date).valueOf()<e.timestamp+604800&&"object"==typeof e.supportTests)return e.supportTests}catch(e){}return null}();if(!n){if("undefined"!=typeof Worker&&"undefined"!=typeof OffscreenCanvas&&"undefined"!=typeof URL&&URL.createObjectURL&&"undefined"!=typeof Blob)try{var e="postMessage("+f.toString()+"("+[JSON.stringify(s),u.toString(),p.toString()].join(",")+"));",r=new Blob([e],{type:"text/javascript"}),a=new Worker(URL.createObjectURL(r),{name:"wpTestEmojiSupports"});return void(a.onmessage=function(e){c(n=e.data),a.terminate(),t(n)})}catch(e){}c(n=f(s,u,p))}t(n)}).then(function(e){for(var t in e)n.supports[t]=e[t],n.supports.everything=n.supports.everything&&n.supports[t],"flag"!==t&&(n.supports.everythingExceptFlag=n.supports.everythingExceptFlag&&n.supports[t]);n.supports.everythingExceptFlag=n.supports.everythingExceptFlag&&!n.supports.flag,n.DOMReady=!1,n.readyCallback=function(){n.DOMReady=!0}}).then(function(){return e}).then(function(){var e;n.supports.everything||(n.readyCallback(),(e=n.source||{}).concatemoji?t(e.concatemoji):e.wpemoji&&e.twemoji&&(t(e.twemoji),t(e.wpemoji)))}))}((window,document),window._wpemojiSettings); /* ]]> */ </script> <style id='wp-emoji-styles-inline-css'> img.wp-smiley, img.emoji { display: inline !important; border: none !important; box-shadow: none !important; height: 1em !important; width: 1em !important; margin: 0 0.07em !important; vertical-align: -0.1em !important; background: none !important; padding: 0 !important; } </style> <link rel='stylesheet' id='all-css-2' href='https://code.flickr.net/wp-includes/css/dist/block-library/style.min.css?m=1739294329g' type='text/css' media='all' /> <style id='wp-block-library-theme-inline-css'> .wp-block-audio :where(figcaption){color:#555;font-size:13px;text-align:center}.is-dark-theme .wp-block-audio :where(figcaption){color:#ffffffa6}.wp-block-audio{margin:0 0 1em}.wp-block-code{border:1px solid #ccc;border-radius:4px;font-family:Menlo,Consolas,monaco,monospace;padding:.8em 1em}.wp-block-embed :where(figcaption){color:#555;font-size:13px;text-align:center}.is-dark-theme .wp-block-embed :where(figcaption){color:#ffffffa6}.wp-block-embed{margin:0 0 1em}.blocks-gallery-caption{color:#555;font-size:13px;text-align:center}.is-dark-theme .blocks-gallery-caption{color:#ffffffa6}:root :where(.wp-block-image figcaption){color:#555;font-size:13px;text-align:center}.is-dark-theme :root :where(.wp-block-image figcaption){color:#ffffffa6}.wp-block-image{margin:0 0 1em}.wp-block-pullquote{border-bottom:4px solid;border-top:4px solid;color:currentColor;margin-bottom:1.75em}.wp-block-pullquote cite,.wp-block-pullquote footer,.wp-block-pullquote__citation{color:currentColor;font-size:.8125em;font-style:normal;text-transform:uppercase}.wp-block-quote{border-left:.25em solid;margin:0 0 1.75em;padding-left:1em}.wp-block-quote cite,.wp-block-quote footer{color:currentColor;font-size:.8125em;font-style:normal;position:relative}.wp-block-quote:where(.has-text-align-right){border-left:none;border-right:.25em solid;padding-left:0;padding-right:1em}.wp-block-quote:where(.has-text-align-center){border:none;padding-left:0}.wp-block-quote.is-large,.wp-block-quote.is-style-large,.wp-block-quote:where(.is-style-plain){border:none}.wp-block-search .wp-block-search__label{font-weight:700}.wp-block-search__button{border:1px solid #ccc;padding:.375em .625em}:where(.wp-block-group.has-background){padding:1.25em 2.375em}.wp-block-separator.has-css-opacity{opacity:.4}.wp-block-separator{border:none;border-bottom:2px solid;margin-left:auto;margin-right:auto}.wp-block-separator.has-alpha-channel-opacity{opacity:1}.wp-block-separator:not(.is-style-wide):not(.is-style-dots){width:100px}.wp-block-separator.has-background:not(.is-style-dots){border-bottom:none;height:1px}.wp-block-separator.has-background:not(.is-style-wide):not(.is-style-dots){height:2px}.wp-block-table{margin:0 0 1em}.wp-block-table td,.wp-block-table th{word-break:normal}.wp-block-table :where(figcaption){color:#555;font-size:13px;text-align:center}.is-dark-theme .wp-block-table :where(figcaption){color:#ffffffa6}.wp-block-video :where(figcaption){color:#555;font-size:13px;text-align:center}.is-dark-theme .wp-block-video :where(figcaption){color:#ffffffa6}.wp-block-video{margin:0 0 1em}:root :where(.wp-block-template-part.has-background){margin-bottom:0;margin-top:0;padding:1.25em 2.375em} </style> <link rel='stylesheet' id='all-css-6' href='https://code.flickr.net/_static/??-eJzTLy/QzcxLzilNSS3WzyrWz01NyUxMzUnNTc0rQeEU5CRWphbp5qSmJyZX6uVm5uklFxfr6OPTDpRD5sM02efaGpobWxpZmhgbGwAAROEu5A==' type='text/css' media='all' /> <style id='jetpack-sharing-buttons-style-inline-css'> .jetpack-sharing-buttons__services-list{display:flex;flex-direction:row;flex-wrap:wrap;gap:0;list-style-type:none;margin:5px;padding:0}.jetpack-sharing-buttons__services-list.has-small-icon-size{font-size:12px}.jetpack-sharing-buttons__services-list.has-normal-icon-size{font-size:16px}.jetpack-sharing-buttons__services-list.has-large-icon-size{font-size:24px}.jetpack-sharing-buttons__services-list.has-huge-icon-size{font-size:36px}@media print{.jetpack-sharing-buttons__services-list{display:none!important}}.editor-styles-wrapper .wp-block-jetpack-sharing-buttons{gap:0;padding-inline-start:0}ul.jetpack-sharing-buttons__services-list.has-background{padding:1.25em 2.375em} </style> <style id='classic-theme-styles-inline-css'> /*! This file is auto-generated */ .wp-block-button__link{color:#fff;background-color:#32373c;border-radius:9999px;box-shadow:none;text-decoration:none;padding:calc(.667em + 2px) calc(1.333em + 2px);font-size:1.125em}.wp-block-file__button{background:#32373c;color:#fff;text-decoration:none} </style> <style id='global-styles-inline-css'> :root{--wp--preset--aspect-ratio--square: 1;--wp--preset--aspect-ratio--4-3: 4/3;--wp--preset--aspect-ratio--3-4: 3/4;--wp--preset--aspect-ratio--3-2: 3/2;--wp--preset--aspect-ratio--2-3: 2/3;--wp--preset--aspect-ratio--16-9: 16/9;--wp--preset--aspect-ratio--9-16: 9/16;--wp--preset--color--black: #000;--wp--preset--color--cyan-bluish-gray: #abb8c3;--wp--preset--color--white: #fff;--wp--preset--color--pale-pink: #f78da7;--wp--preset--color--vivid-red: #cf2e2e;--wp--preset--color--luminous-vivid-orange: #ff6900;--wp--preset--color--luminous-vivid-amber: #fcb900;--wp--preset--color--light-green-cyan: #7bdcb5;--wp--preset--color--vivid-green-cyan: #00d084;--wp--preset--color--pale-cyan-blue: #8ed1fc;--wp--preset--color--vivid-cyan-blue: #0693e3;--wp--preset--color--vivid-purple: #9b51e0;--wp--preset--color--blue: #1982d1;--wp--preset--color--dark-gray: #373737;--wp--preset--color--medium-gray: #666;--wp--preset--color--light-gray: #e2e2e2;--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple: linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%);--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan: linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%);--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange: linear-gradient(135deg,rgba(252,185,0,1) 0%,rgba(255,105,0,1) 100%);--wp--preset--gradient--luminous-vivid-orange-to-vivid-red: linear-gradient(135deg,rgba(255,105,0,1) 0%,rgb(207,46,46) 100%);--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray: linear-gradient(135deg,rgb(238,238,238) 0%,rgb(169,184,195) 100%);--wp--preset--gradient--cool-to-warm-spectrum: linear-gradient(135deg,rgb(74,234,220) 0%,rgb(151,120,209) 20%,rgb(207,42,186) 40%,rgb(238,44,130) 60%,rgb(251,105,98) 80%,rgb(254,248,76) 100%);--wp--preset--gradient--blush-light-purple: linear-gradient(135deg,rgb(255,206,236) 0%,rgb(152,150,240) 100%);--wp--preset--gradient--blush-bordeaux: linear-gradient(135deg,rgb(254,205,165) 0%,rgb(254,45,45) 50%,rgb(107,0,62) 100%);--wp--preset--gradient--luminous-dusk: linear-gradient(135deg,rgb(255,203,112) 0%,rgb(199,81,192) 50%,rgb(65,88,208) 100%);--wp--preset--gradient--pale-ocean: linear-gradient(135deg,rgb(255,245,203) 0%,rgb(182,227,212) 50%,rgb(51,167,181) 100%);--wp--preset--gradient--electric-grass: linear-gradient(135deg,rgb(202,248,128) 0%,rgb(113,206,126) 100%);--wp--preset--gradient--midnight: linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%);--wp--preset--font-size--small: 13px;--wp--preset--font-size--medium: 20px;--wp--preset--font-size--large: 36px;--wp--preset--font-size--x-large: 42px;--wp--preset--spacing--20: 0.44rem;--wp--preset--spacing--30: 0.67rem;--wp--preset--spacing--40: 1rem;--wp--preset--spacing--50: 1.5rem;--wp--preset--spacing--60: 2.25rem;--wp--preset--spacing--70: 3.38rem;--wp--preset--spacing--80: 5.06rem;--wp--preset--shadow--natural: 6px 6px 9px rgba(0, 0, 0, 0.2);--wp--preset--shadow--deep: 12px 12px 50px rgba(0, 0, 0, 0.4);--wp--preset--shadow--sharp: 6px 6px 0px rgba(0, 0, 0, 0.2);--wp--preset--shadow--outlined: 6px 6px 0px -3px rgba(255, 255, 255, 1), 6px 6px rgba(0, 0, 0, 1);--wp--preset--shadow--crisp: 6px 6px 0px rgba(0, 0, 0, 1);}:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}:where(.wp-block-columns.is-layout-flex){gap: 2em;}:where(.wp-block-columns.is-layout-grid){gap: 2em;}:where(.wp-block-post-template.is-layout-flex){gap: 1.25em;}:where(.wp-block-post-template.is-layout-grid){gap: 1.25em;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-color{color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-color{color: var(--wp--preset--color--white) !important;}.has-pale-pink-color{color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-color{color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-color{color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-color{color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-color{color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-color{color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-color{color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-color{color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-color{color: var(--wp--preset--color--vivid-purple) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-background-color{background-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-pale-pink-background-color{background-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-background-color{background-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-background-color{background-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-background-color{background-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-background-color{background-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-background-color{background-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-background-color{background-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-background-color{background-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-background-color{background-color: var(--wp--preset--color--vivid-purple) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-border-color{border-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-pale-pink-border-color{border-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-border-color{border-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-border-color{border-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-border-color{border-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-border-color{border-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-border-color{border-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-border-color{border-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-border-color{border-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-border-color{border-color: var(--wp--preset--color--vivid-purple) !important;}.has-vivid-cyan-blue-to-vivid-purple-gradient-background{background: var(--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple) !important;}.has-light-green-cyan-to-vivid-green-cyan-gradient-background{background: var(--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan) !important;}.has-luminous-vivid-amber-to-luminous-vivid-orange-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange) !important;}.has-luminous-vivid-orange-to-vivid-red-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-orange-to-vivid-red) !important;}.has-very-light-gray-to-cyan-bluish-gray-gradient-background{background: var(--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray) !important;}.has-cool-to-warm-spectrum-gradient-background{background: var(--wp--preset--gradient--cool-to-warm-spectrum) !important;}.has-blush-light-purple-gradient-background{background: var(--wp--preset--gradient--blush-light-purple) !important;}.has-blush-bordeaux-gradient-background{background: var(--wp--preset--gradient--blush-bordeaux) !important;}.has-luminous-dusk-gradient-background{background: var(--wp--preset--gradient--luminous-dusk) !important;}.has-pale-ocean-gradient-background{background: var(--wp--preset--gradient--pale-ocean) !important;}.has-electric-grass-gradient-background{background: var(--wp--preset--gradient--electric-grass) !important;}.has-midnight-gradient-background{background: var(--wp--preset--gradient--midnight) !important;}.has-small-font-size{font-size: var(--wp--preset--font-size--small) !important;}.has-medium-font-size{font-size: var(--wp--preset--font-size--medium) !important;}.has-large-font-size{font-size: var(--wp--preset--font-size--large) !important;}.has-x-large-font-size{font-size: var(--wp--preset--font-size--x-large) !important;} :where(.wp-block-post-template.is-layout-flex){gap: 1.25em;}:where(.wp-block-post-template.is-layout-grid){gap: 1.25em;} :where(.wp-block-columns.is-layout-flex){gap: 2em;}:where(.wp-block-columns.is-layout-grid){gap: 2em;} :root :where(.wp-block-pullquote){font-size: 1.5em;line-height: 1.6;} </style> <link rel='stylesheet' id='all-css-12' href='https://code.flickr.net/_static/??-eJzTLy/QTc7PK0nNK9EvyUjNTS3WLykHcipTc1LLUvP0i0sqc1L1kouLdfQxVablZCZnFwFFU1LxK0QxMiknPzm7GKTUPtfW0NzYxNDA3NzQAABaZTMQ' type='text/css' media='all' /> <link rel="https://api.w.org/" href="https://code.flickr.net/wp-json/" /><link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://code.flickr.net/xmlrpc.php?rsd" /> <meta name="generator" content="WordPress 6.7.2" /> <style>img#wpstats{display:none}</style> <style type="text/css" id="twentyeleven-header-css"> #site-title, #site-description { position: absolute; clip: rect(1px 1px 1px 1px); /* IE6, IE7 */ clip: rect(1px, 1px, 1px, 1px); } </style> <style type="text/css" id="wp-custom-css"> body { background: #fff; } body,input,textarea { font-family: Arial, sans-serif; color: #404040; } #page { margin: 1em auto; max-width: 1000px; } a:link { text-decoration: none; color: #0063dc; } a:visited { text-decoration: none; color: #0063dc; } a:hover { text-decoration: none; background: #0063dc; color: #fff; } a:active { text-decoration: none; background-color: #0259c4; color: #fff; } #branding { border: none; } #branding .only-search #s,#branding .only-search #s:focus { width: 280px; background-color: transparent; border-color: #ddd; } #branding #searchform { right: 0; } nav#access { background: none; box-shadow: none; -webkit-box-shadow: none; -moz-box-shadow: none; margin: 0; } nav#access a { font-weight: bold; margin: 11px 28px 0 0; padding: 0; line-height: 21px; } nav#access a:link,nav#access a:visited { text-decoration: none; color: #888; } nav#access a:hover,nav#access li:hover > a,nav#access a:focus,nav#access a:active { text-decoration: none; color: #0063dc; background: none; } #branding .only-search + nav#access div { padding-right: 300px; } nav#access div,nav#access ul { margin: 0; } @media screen and (max-width: 768px) { #branding .only-search + nav#access div { padding-right: 0; } #branding #searchform { display: none; position: static; text-align: center; } #branding .with-image #searchform { max-width: 100%; } #branding .only-search #s,#branding .only-search #s:focus { width: 85%; float: none; } nav#access { margin: 0 0 0 5%; } } @media screen and (max-width: 480px) { nav#access { display: none; } } #content { margin: 0 20% 0 0; width: 80%; } #content .comments-link { display: none; } @media screen and (max-width: 800px) { #main { padding-top: 0; overflow: hidden; } #branding { padding-bottom: 0; } #main #content { margin: 0; } .entry-title,.entry-header .entry-meta { padding-right: 0; } } .singular #content,.left-sidebar.singular #content { margin: 0 10%; width: 80%; } .singular .entry-header,.singular .entry-content,.singular footer.entry-meta,.singular #comments-title { width: 100%; } .hentry,.no-results { border-bottom: 1px dotted #dadada; } .singular .hentry { padding-top: 1em; } .entry-title { padding-bottom: 0; } .entry-title,.entry-title a { font-size: 28px; color: #000; } .entry-title a:hover,.entry-title a:focus,.entry-title a:active { color: #0063dc; background-color: transparent; } @media screen and (max-width: 650px) { .singular .entry-title { padding-top: 0; line-height: 42px; } } .singular .entry-content { margin-top: 0; } #jp-post-flair { margin-top: 3em; } footer.entry-meta .cat-links,footer.entry-meta .sep,footer.entry-meta .tag-links { display: none; } .singular .entry-meta .edit-link a { position: static; } .singular footer.entry-meta { margin-top: 2em; } #comments { display: none; } #site-generator { background: transparent; border-top: none; padding: 0 .5em; } img#wpstats { position: absolute !important; clip: rect(1px 1px 1px 1px); } #secondary { margin-right: 0; width: 16%; text-align: right; } #secondary #s { display: none; } #secondary aside ul { list-style: none; } #secondary .widget-title { color: #999; font-size: 12px; letter-spacing: auto; text-transform: none; } .widget a { font-weight: normal; } .widget a:hover,.widget a:focus,.widget a:active { text-decoration: none; } #everything-after-this-line-is-a-post-level-style---yay-for-wordpress-stripping-comments-from-css { color: #000; } .entry-content p { margin-bottom: 1.3em; } .entry-content p.note { padding: 11px; background-color: #fffdeb; border-bottom: 1px solid #fff9c2; } .entry-content p.warning { padding: 11px; background-color: #fdf8f8; border-bottom: 1px solid #f7dedd; } .entry-content .aside { margin-bottom: 1.3em; padding: 11px; background-color: #f8fdf8; border-bottom: 1px solid #def6df; } .entry-content .aside p:last-child { margin-bottom: 0; } .entry-content h2,.entry-content h3,.entry-content h4 { font-weight: bold; color: #000; text-transform: none; } .entry-content h2 { font-size: 22px; } .entry-content h3 { font-size: 16px; letter-spacing: 0; line-height: 1.3em; margin-bottom: 1em; } .entry-content h4 { font-size: 13px; line-height: 1.4em; margin-bottom: 0; } .entry-content p.flickr-photo,.entry-content p.flickr-photo a,.entry-content p.figure { color: #999; font-size: 14px; } .entry-content p.flickr-photo a:hover,.entry-content p.flickr-photo a:active { color: #0063dc; background-color: transparent; } .entry-content p.flickr-photo .caption { display: block; padding-left: 22px; background: url('http://farm4.staticflickr.com/3329/favicons/72157601614001242_7730.png') no-repeat 0 3px; } .entry-content img { max-width: 100%; height: auto; } .undersized-image-container { text-align: center; } .entry-content code { color: #000; font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace; font-size: 14px; background-color: #F6FcFF; border-bottom: 1px solid #ebf5ff; } .entry-content ul { list-style: disc; } .entry-content ol ol { list-style: lower-alpha; } .entry-content table caption { font-size: 13px; font-weight: bold; color: #000; } .entry-content table tr.odd td,.entry-content table tr.odd th { background-color: #f8f8f8; } .entry-content table td,.entry-content table th { padding: 3px 10px; line-height: 1.4em; } .entry-content table tr th { color: #000; font-weight: bold; text-transform: none; font-size: 13px; letter-spacing: 0; border-top: 1px solid #ddd; } .entry-content table tr td { font-size: 14px; } .entry-content table.data tr td,.entry-content table.data thead tr th { text-align: right; } .entry-content table.tight td,.entry-content table.tight th { padding: 3px 6px; } .entry-content table.tight th { font-size: 12px; } .entry-content table.tight td { font-size: 13px; } @media screen and (max-width: 650px) { .entry-content table td,.entry-content table th { padding: 3px 5px; } .entry-content table tr th { font-size: 12px; } .entry-content table tr td { font-size: 13px; } .entry-content table.tight td,.entry-content table.tight th { padding: 3px 4px; } .entry-content table.tight th { font-size: 11px; } .entry-content table.tight td { font-size: 12px; } } .entry-content blockquote { font-family: inherit; font-style: normal; font-weight: normal; margin: 0 2em 1.3em; padding: 1em; background: #F9F9F9; border-bottom: 1px solid #ececec; } .entry-content blockquote p.source { margin-bottom: 0; } .entry-content .hiring-banner { position: relative; background: #ffebf5; padding: 11px 11px 11px 88px; border-bottom: 1px solid #ffc5e2; margin: 2em 0; } .entry-content .hiring-banner p { margin-bottom: 0; } .entry-content .hiring-banner .group-photo { position: absolute; left: -57px; top: -5px; width: 120px; padding: 6px; background: #fff; -webkit-box-shadow: 1px 1px 8px rgba(50,50,50,0.8); -moz-box-shadow: 1px 1px 8px rgba(50,50,50,0.8); box-shadow: 1px 1px 8px rgba(50,50,50,0.8); -webkit-transform: rotate(-11deg); -moz-transform: rotate(-11deg); -o-transform: rotate(-11deg); -ms-transform: rotate(-11deg); } .entry-content .hiring-banner .group-photo img { display: block; margin: 0; max-width: 100%; } @media screen and (max-width: 800px) { .entry-content .hiring-banner { padding-left: 11px; } .entry-content .hiring-banner .group-photo { display: none; } } #everything-after-this-line-is-for-the-syntaxhighlighter---all-rules-require-important { color: #000; } #main .syntaxhighlighter .lines { border-bottom: 1px solid #ebf5ff !important; } #main .syntaxhighlighter,#main .syntaxhighlighter div,#main .syntaxhighlighter code,#main .syntaxhighlighter table,#main .syntaxhighlighter table td,#main .syntaxhighlighter table tr,#main .syntaxhighlighter table tbody { font-size: 14px !important; } #main .syntaxhighlighter .line.alt1,#main .syntaxhighlighter .line.alt2 { background-color: #fafdff !important; } #main .syntaxhighlighter .line.highlighted { background-color: #fffbd6 !important; } #main .syntaxhighlighter .plain,#main .syntaxhighlighter .plain a { color: #000 !important; } #main .syntaxhighlighter .comments,#main .syntaxhighlighter .comments a { color: #999 !important; } #main .syntaxhighlighter .string,#main .syntaxhighlighter .string a { color: #ff52a9 !important; } #main .syntaxhighlighter .keyword { color: #0034fe !important; font-weight: normal !important; } #main .syntaxhighlighter .preprocessor { color: #417ba9 !important; } #main .syntaxhighlighter .variable { color: #b130c0 !important; } #main .syntaxhighlighter .value { color: #6b77f7 !important; } #main .syntaxhighlighter .functions { color: #002ad5 !important; } #main .syntaxhighlighter .constants { color: #d11e08 !important; } #main .syntaxhighlighter .script { background-color: yellow !important; } #main .syntaxhighlighter .color1,#main .syntaxhighlighter .color1 a { color: #808080 !important; } #main .syntaxhighlighter .color2,#main .syntaxhighlighter .color2 a { color: #ff1493 !important; } #main .syntaxhighlighter .color3,#main .syntaxhighlighter .color3 a { color: red !important; } a[data-flickr-embed] img { width: 800px; } </style> </head> <body class="archive date custom-background wp-embed-responsive jps-theme-flickr-code two-column right-sidebar"> <div class="skip-link"><a class="assistive-text" href="#content">Skip to primary content</a></div><div class="skip-link"><a class="assistive-text" href="#secondary">Skip to secondary content</a></div><div id="page" class="hfeed"> <header id="branding"> <hgroup> <h1 id="site-title"><span><a href="https://code.flickr.net/" rel="home">code.flickr.com</a></span></h1> <h2 id="site-description"></h2> </hgroup> <a href="https://code.flickr.net/"> <img src="https://wp.flickr.net/wp-content/uploads/sites/3/2012/09/code-flickr-com-drawn-header-grey-large.png" width="1000" height="157" alt="code.flickr.com" /> </a> <div class="only-search with-image"> <form method="get" id="searchform" action="https://code.flickr.net/"> <label for="s" class="assistive-text">Search</label> <input type="text" class="field" name="s" id="s" placeholder="Search" /> <input type="submit" class="submit" name="submit" id="searchsubmit" value="Search" /> </form> </div> <nav id="access"> <h3 class="assistive-text">Main menu</h3> <div class="menu-menu-container"><ul id="menu-menu" class="menu"><li id="menu-item-2084" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2084"><a href="http://www.flickr.com/">Flickr</a></li> <li id="menu-item-2085" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2085"><a href="http://blog.flickr.net/">Flickr Blog</a></li> <li id="menu-item-2250" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2250"><a href="http://twitter.com/flickr">@flickr</a></li> <li id="menu-item-2086" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2086"><a href="http://twitter.com/flickrapi">@flickrapi</a></li> <li id="menu-item-2087" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2087"><a href="https://www.flickr.com/services/developer/">Developer Guidelines</a></li> <li id="menu-item-2088" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2088"><a href="http://www.flickr.com/services/api/">API</a></li> <li id="menu-item-2089" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-2089"><a href="http://www.flickr.com/jobs/">Jobs</a></li> </ul></div> </nav><!-- #access --> </header><!-- #branding --> <div id="main"> <section id="primary"> <div id="content" role="main"> <header class="page-header"> <h1 class="page-title"> Monthly Archives: <span>March 2009</span> </h1> </header> <article id="post-777" class="post-777 post type-post status-publish format-standard hentry category-uncategorized tag-add-new-tag tag-api tag-astrometry tag-contest tag-flickr tag-google tag-machine-tags tag-science tag-space tag-tagging tag-yahoo tag-yql"> <header class="entry-header"> <h1 class="entry-title"><a href="https://code.flickr.net/2009/03/20/tags-in-space/" rel="bookmark">Tags in Space</a></h1> <div class="entry-meta"> <span class="sep">Posted on </span><a href="https://code.flickr.net/2009/03/20/tags-in-space/" title="8:49 pm" rel="bookmark"><time class="entry-date" datetime="2009-03-20T20:49:08-07:00">March 20, 2009</time></a><span class="by-author"> <span class="sep"> by </span> <span class="author vcard"><a class="url fn n" href="https://code.flickr.net/author/flickrphotography/" title="View all posts by Kay Kremerskothen" rel="author">Kay Kremerskothen</a></span></span> </div><!-- .entry-meta --> </header><!-- .entry-header --> <div class="entry-content"> <p>A lot of you enjoyed our post (<a href="http://code.flickr.com/blog/2009/02/18/found-in-space/">&#8220;Found in Space&#8221;</a>) on the amazing <a href="http://astrometry.net/">astrometry.net</a> project, and there have been some interesting followups.</p> <p>A mysterious figure known only as &#8220;jim&#8221; paired up <a href="http://eatyourgreens.org.uk/testapps/yql/overlay2.html">astronomy photos from Flickr with Google Sky</a>. (You&#8217;re going to need the Google Earth plug-in for your browser &#8212; just follow the instructions on that page if you don&#8217;t have it.) In his <a href="http://eatyourgreens.org.uk/archives/2009/03/mapping-the-sky-with-yql-and-astrometrynet.html#more-300">technical writeup</a>, &#8220;jim&#8221; explains how he used the <a href="http://developer.yahoo.com/yql/">Yahoo Query Language</a> (YQL) to fetch the data. YQL is similar to the existing <a href="http://www.flickr.com/services/api/">Flickr APIs</a>, but it&#8217;s a query language like SQL rather than a set of REST-ish APIs. And both of those are really just ways to get data out of Flickr&#8217;s <a href="http://code.flickr.com/blog/2008/12/15/machine-tag-hierarchies/">machine tag</a> system, specifically the <a href="http://www.flickr.com/photos/tags/astro:*"><code>astro:*</code></a> namespace. It&#8217;s turtles all the way down.</p> <p>Who else is using astrotags? The British Royal Observatory in Greenwich is sponsoring a contest to determine the <a href="http://www.nmm.ac.uk/visit/exhibitions/astronomy-photographer-of-the-year/">Astronomy Photographer of the Year</a> and the whole thing is based on a <a href="http://www.nmm.ac.uk/visit/exhibitions/astronomy-photographer-of-the-year/flickr-group/">Flickr group</a> and extensive use of Flickr&#8217;s APIs. The integration is so seamless &#8212; galleries of photos and discussions are surfaced on their site as well as ours &#8212; you might as well consider Flickr to be their &#8220;backend&#8221; server. But they&#8217;ve also added much, such as great documentation about <a href="http://www.nmm.ac.uk/visit/exhibitions/astronomy-photographer-of-the-year/astrotags/">how to astrotag your photos</a> as well as <a href="http://www.nmm.ac.uk/visit/exhibitions/astronomy-photographer-of-the-year/astro-robot/">a concise explanation</a> about how Astrometry.net identifies your photo, even among millions of known stars. (The sci-fi website <a href="http://io9.com">io9</a> interviewed <a href="http://io9.com/5169232/the-robot-who-helps-astronomers-identify-stars">Fiona Romeo</a> of the Royal Observatory about the contest; check it out.) </p> <p>It&#8217;s dizzying how many services have been combined here &#8212; Astrometry.net grew out of research at the University of Toronto, web mashups use Google Sky for visualization in context, Yahoo infrastructure delivers and transforms data, the Royal Observatory at Greenwich provides leadership and expertise, and then little old Flickr acts as a data repository and social hub. And let&#8217;s not forget you, the Flickr community, and your inexhaustible creativity &#8212; which is the reason why all this can even come together. </p> <p>All this was done with pretty light coordination and few people at Flickr were even aware what was going on until recently. I have no idea what the future is for APIs and a web of services loosely joined, but I hope we get to see more and more of this sort of thing.</p> </div><!-- .entry-content --> <footer class="entry-meta"> <span class="cat-links"> <span class="entry-utility-prep entry-utility-prep-cat-links">Posted in</span> <a href="https://code.flickr.net/category/uncategorized/" rel="category tag">Uncategorized</a> </span> <span class="sep"> | </span> <span class="tag-links"> <span class="entry-utility-prep entry-utility-prep-tag-links">Tagged</span> <a href="https://code.flickr.net/tag/add-new-tag/" rel="tag">Add new tag</a>, <a href="https://code.flickr.net/tag/api/" rel="tag">api</a>, <a href="https://code.flickr.net/tag/astrometry/" rel="tag">astrometry</a>, <a href="https://code.flickr.net/tag/contest/" rel="tag">contest</a>, <a href="https://code.flickr.net/tag/flickr/" rel="tag">flickr</a>, <a href="https://code.flickr.net/tag/google/" rel="tag">google</a>, <a href="https://code.flickr.net/tag/machine-tags/" rel="tag">machine tags</a>, <a href="https://code.flickr.net/tag/science/" rel="tag">science</a>, <a href="https://code.flickr.net/tag/space/" rel="tag">space</a>, <a href="https://code.flickr.net/tag/tagging/" rel="tag">tagging</a>, <a href="https://code.flickr.net/tag/yahoo/" rel="tag">yahoo</a>, <a href="https://code.flickr.net/tag/yql/" rel="tag">yql</a> </span> </footer><!-- .entry-meta --> </article><!-- #post-777 --> <article id="post-703" class="post-703 post type-post status-publish format-standard hentry category-uncategorized tag-frontend tag-javascript tag-optimization tag-yui"> <header class="entry-header"> <h1 class="entry-title"><a href="https://code.flickr.net/2009/03/18/building-fast-client-side-searches/" rel="bookmark">Building Fast Client-side Searches</a></h1> <div class="entry-meta"> <span class="sep">Posted on </span><a href="https://code.flickr.net/2009/03/18/building-fast-client-side-searches/" title="3:59 pm" rel="bookmark"><time class="entry-date" datetime="2009-03-18T15:59:42-07:00">March 18, 2009</time></a><span class="by-author"> <span class="sep"> by </span> <span class="author vcard"><a class="url fn n" href="https://code.flickr.net/author/rharmes/" title="View all posts by Ross Harmes" rel="author">Ross Harmes</a></span></span> </div><!-- .entry-meta --> </header><!-- .entry-header --> <div class="entry-content"> <p>Yesterday we released <a href="http://blog.flickr.net/en/2009/03/17/find-people-faster/">a new people selector widget</a> (which we’ve been calling Bo Selecta internally). This widget downloads a list of all of your contacts, in JavaScript, in under 200ms (this is true even for members with 10,000+ contacts). In order to get this level of performance, we had to completely rethink how we send data from the server to the client.</p> <h2 style="margin-bottom: 12px;">Server Side: Cache Everything</h2> <p>To make this data available quickly from the server, we maintain and update a per-member cache in our database, where we store each member&#8217;s contact list in a text blob — this way it’s a single quick DB query to retrieve it. We can format this blob in any way we want: XML, JSON, etc. Whenever a member updates their information, we update the cache for all of their contacts. Since a single member who changes their contact information can require updating the contacts cache for hundreds or even thousands of other members, we rely upon prioritized tasks in <a href="http://code.flickr.com/blog/2008/09/26/flickr-engineers-do-it-offline/">our offline queue system</a>.</p> <h2 style="margin-bottom: 12px;">Testing the Performance of Different Data Formats</h2> <p>Despite the fact that our backend system can deliver the contact list data very quickly, we still don’t want to unnecessarily fetch it for each page load. This means that we need to defer loading until it&#8217;s needed, and that we have to be able to request, download, and parse the contact list in the amount of time it takes a member to go from hovering over a text field to typing a name.</p> <p>With this goal in mind, we started testing various data formats, and recording the average amount of time it took to download and parse each one. We started with Ajax and XML; this proved to be the slowest by far, so much so that the larger test cases wouldn&#8217;t even run to completion (the tags used to create the XML structure also added a lot of weight to the filesize). It appeared that using XML was out of the question. </p> <h2 style="margin-bottom: 12px;">BoSelectaJsonGoodFunTimes: eval() is Slow</h2> <p><a href="http://www.flickr.com/photos/dchousegrooves/2539003507/" title="DJ Bo Selecta on the decks by dchousegrooves, on Flickr"><img fetchpriority="high" decoding="async" src="http://farm4.static.flickr.com/3020/2539003507_02728b3e80.jpg" width="500" height="375" alt="DJ Bo Selecta on the decks" /></a></p> <p>Next we tried using Ajax to fetch the list in the JSON format (and having eval() parse it). This was a major improvement, both in terms of filesize across the wire and parse time.</p> <p>While all of our tests ran to completion (even the 10,000 contacts case), parse time per contact was not the same for each case; it geometrically increased as we increased the number of contacts, up to the point where the 10,000 contact case took over 80 seconds to parse — 400 times slower than our goal of 200ms. It seemed that JavaScript had a problem manipulating and eval()ing very large strings, so this approach wasn’t going to work either.</p> <table class="data-table"> <tbody> <tr class="header"> <th>Contacts</th> <th>File Size (KB)</th> <th>Parse Time (ms)</th> <th>File Size per Contact (KB)</th> <th>Parse Time per Contact (ms)</th> </tr> <tr> <td class="s4">10,617</td> <td class="s5">1536</td> <td class="s5">81312</td> <td class="s6">0.14</td> <td class="s7">7.66</td> </tr> <tr class="odd"> <td class="s8">4,878</td> <td class="s9">681</td> <td class="s9">18842</td> <td class="s10">0.14</td> <td class="s11">3.86</td> </tr> <tr> <td class="s8">2,979</td> <td class="s9">393</td> <td class="s9">6987</td> <td class="s10">0.13</td> <td class="s11">2.35</td> </tr> <tr class="odd"> <td class="s8">1,914</td> <td class="s9">263</td> <td class="s9">3381</td> <td class="s10">0.14</td> <td class="s11">1.77</td> </tr> <tr> <td class="s8">1,363</td> <td class="s9">177</td> <td class="s9">1837</td> <td class="s10">0.13</td> <td class="s11">1.35</td> </tr> <tr class="odd"> <td class="s8">798</td> <td class="s9">109</td> <td class="s9">852</td> <td class="s10">0.14</td> <td class="s11">1.07</td> </tr> <tr> <td class="s8">644</td> <td class="s9">86</td> <td class="s9">611</td> <td class="s10">0.13</td> <td class="s11">0.95</td> </tr> <tr class="odd"> <td class="s8">325</td> <td class="s9">44</td> <td class="s9">252</td> <td class="s10">0.14</td> <td class="s11">0.78</td> </tr> <tr> <td class="s8">260</td> <td class="s9">36</td> <td class="s9">205</td> <td class="s10">0.14</td> <td class="s11">0.79</td> </tr> <tr class="odd"> <td class="s8">165</td> <td class="s9">24</td> <td class="s9">111</td> <td class="s10">0.15</td> <td class="s11">0.67</td> </tr> </tbody> </table> <h2 style="margin-bottom: 12px;">JSON and Dynamic Script Tags: Fast but Insecure</h2> <p>Working with the theory that large string manipulation was the problem with the last approach, we switched from using Ajax to instead fetching the data using a dynamically generated script tag. This means that the contact data was never treated as string, and was instead executed as soon as it was downloaded, just like any other JavaScript file. The difference in performance was shocking: 89ms to parse 10,000 contacts (a reduction of 3 orders of magnitude), while the smallest case of 172 contacts only took 6ms. The parse time per contact actually <i>decreased</i> the larger the list became. This approach looked perfect, except for one thing: in order for this JSON to be executed, we had to wrap it in a callback method. Since it’s executable code, any website in the world could use the same approach to download a Flickr member&#8217;s contact list. This was a deal breaker.</p> <table class="data-table"> <tbody> <tr class="header"> <th>Contacts</th> <th>File Size (KB)</th> <th>Parse Time (ms)</th> <th>File Size per Contact (KB)</th> <th>Parse Time per Contact (ms)</th> </tr> <tr> <td class="s4">10,709</td> <td class="s5">1105</td> <td class="s5">89</td> <td class="s6">0.10</td> <td class="s7">0.01</td> </tr> <tr class="odd"> <td class="s8">4,877</td> <td class="s9">508</td> <td class="s9">41</td> <td class="s10">0.10</td> <td class="s11">0.01</td> </tr> <tr> <td class="s8">2,979</td> <td class="s9">308</td> <td class="s9">26</td> <td class="s10">0.10</td> <td class="s11">0.01</td> </tr> <tr class="odd"> <td class="s8">1,915</td> <td class="s9">197</td> <td class="s9">19</td> <td class="s10">0.10</td> <td class="s11">0.01</td> </tr> <tr> <td class="s8">1,363</td> <td class="s9">140</td> <td class="s9">15</td> <td class="s10">0.10</td> <td class="s11">0.01</td> </tr> <tr class="odd"> <td class="s8">800</td> <td class="s9">83</td> <td class="s9">11</td> <td class="s10">0.10</td> <td class="s11">0.01</td> </tr> <tr> <td class="s8">644</td> <td class="s9">67</td> <td class="s9">9</td> <td class="s10">0.10</td> <td class="s11">0.01</td> </tr> <tr class="odd"> <td class="s8">325</td> <td class="s9">35</td> <td class="s9">8</td> <td class="s10">0.11</td> <td class="s11">0.02</td> </tr> <tr> <td class="s8">260</td> <td class="s9">27</td> <td class="s9">7</td> <td class="s10">0.10</td> <td class="s11">0.03</td> </tr> <tr class="odd"> <td class="s8">172</td> <td class="s9">18</td> <td class="s9">6</td> <td class="s10">0.10</td> <td class="s11">0.03</td> </tr> </tbody> </table> <h2 style="margin-bottom: 12px;">Going Custom</h2> <p><a href="http://www.flickr.com/photos/brianauer/2722866656/" title="Custom Ride by Brian Auer, on Flickr"><img decoding="async" src="http://farm4.static.flickr.com/3108/2722866656_5d5a9163e4.jpg" width="500" height="333" alt="Custom Ride" /></a></p> <p>Having set the performance bar pretty high with the last approach, we dove into custom data formats. The challenge would be to create a format that we could parse ourselves, using JavaScript’s String and RegExp methods, that would also match the speed of JSON executed natively. This would allow us to use Ajax again, but keep the data restricted to our domain. </p> <p>Since we had already discovered that some methods of string manipulation didn’t perform well on large strings, we restricted ourselves to a method that we knew to be fast: split(). We used control characters to delimit each contact, and a different control character to delimit the fields within each contact. This allowed us to parse the string into contact objects with one split, then loop through that array and split again on each string. </p> <pre style="margin-bottom: 14px;"> that.contacts = o.responseText.split("\c"); for (var n = 0, len = that.contacts.length, contactSplit; n < len; n++) { contactSplit = that.contacts[n].split("\a"); that.contacts[n] = {}; that.contacts[n].n = contactSplit[0]; that.contacts[n].e = contactSplit[1]; that.contacts[n].u = contactSplit[2]; that.contacts[n].r = contactSplit[3]; that.contacts[n].s = contactSplit[4]; that.contacts[n].f = contactSplit[5]; that.contacts[n].a = contactSplit[6]; that.contacts[n].d = contactSplit[7]; that.contacts[n].y = contactSplit[8]; } </pre> <p> Though this technique sounds like it would be slow, it actually performed on par with native JSON parsing (it was a little faster for cases containing less than 1000 contacts, and a little slower for those over 1000). It also had the smallest filesize: 80% the size of the JSON data for the same number of contacts. This is the format that we ended up using.</p> <table class="data-table"> <tbody> <tr class="header"> <th>Contacts</th> <th>File Size (KB)</th> <th>Parse Time (ms)</th> <th>File Size per Contact (KB)</th> <th>Parse Time per Contact (ms)</th> </tr> <tr> <td class="s4">10,741</td> <td class="s5">818</td> <td class="s5">173</td> <td class="s6">0.08</td> <td class="s7">0.02</td> </tr> <tr class="odd"> <td class="s8">4,877</td> <td class="s9">375</td> <td class="s9">50</td> <td class="s10">0.08</td> <td class="s11">0.01</td> </tr> <tr> <td class="s8">2,979</td> <td class="s9">208</td> <td class="s9">34</td> <td class="s10">0.07</td> <td class="s11">0.01</td> </tr> <tr class="odd"> <td class="s8">1,916</td> <td class="s9">144</td> <td class="s9">21</td> <td class="s10">0.08</td> <td class="s11">0.01</td> </tr> <tr> <td class="s8">1,363</td> <td class="s9">93</td> <td class="s9">16</td> <td class="s10">0.07</td> <td class="s11">0.01</td> </tr> <tr class="odd"> <td class="s8">800</td> <td class="s9">58</td> <td class="s9">10</td> <td class="s10">0.07</td> <td class="s11">0.01</td> </tr> <tr> <td class="s8">644</td> <td class="s9">46</td> <td class="s9">8</td> <td class="s10">0.07</td> <td class="s11">0.01</td> </tr> <tr class="odd"> <td class="s8">325</td> <td class="s9">24</td> <td class="s9">4</td> <td class="s10">0.07</td> <td class="s11">0.01</td> </tr> <tr> <td class="s8">260</td> <td class="s9">14</td> <td class="s9">3</td> <td class="s10">0.05</td> <td class="s11">0.01</td> </tr> <tr class="odd"> <td class="s8">160</td> <td class="s9">13</td> <td class="s9">3</td> <td class="s10">0.08</td> <td class="s11">0.02</td> </tr> </tbody> </table> <h2 style="margin-bottom: 12px;">Searching</h2> <p><a href="http://www.flickr.com/photos/dafuriousd/2870299882/" title="Ben to the Rescue by dafuriousd, on Flickr"><img decoding="async" src="http://farm4.static.flickr.com/3037/2870299882_54f39775bd.jpg" width="500" height="332" alt="Ben to the Rescue" /></a></p> <p>Now that we have a giant array of contacts in JavaScript, we needed a way to search through them and select one. For this, we used YUI’s excellent <a href="http://developer.yahoo.com/yui/autocomplete/">AutoComplete widget</a>. To get the data into the widget, we created a DataSource object that would execute a function to get results. This function simply looped through our contact array and matched the given query against four different properties of each contact, using a regular expression (RegExp objects turned out to be extremely well-suited for this, with the average search time for the 10,000 contacts case coming in under 38ms). After the results were collected, the AutoComplete widget took care of everything else, including caching the results.</p> <p>There was one optimization we made to our AutoComplete configuration that was particularly effective. Regardless of how much we optimized our search method, we could never get results to return in less than 200ms (even for trivially small numbers of contacts). After a lot of profiling and hair pulling, we found the queryDelay setting. This is set to 200ms by default, and artificially delays every search in order to reduce UI flicker for quick typists. After setting that to 0, we found our search times improved dramatically. </p> <h2 style="margin-bottom: 12px;">The End Result</h2> <div style="margin: 0 auto; text-align: center;"> <object type="application/x-shockwave-flash" width="400" height="229" data="http://www.flickr.com/apps/video/stewart.swf?v=68975" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"><param name="flashvars" value="intl_lang=en-us&amp;photo_secret=7d60e13b0d&amp;photo_id=3328806159"></param><param name="movie" value="http://www.flickr.com/apps/video/stewart.swf?v=68975"></param><param name="bgcolor" value="#000000"></param><param name="allowFullScreen" value="true"></param></object> </div> <p>Head over to your <a href="http://www.flickr.com/people/me/contacts/">Contact List</a> page and give it a whirl. We are also using the Bo Selecta with <a href="http://www.flickr.com/mail/write/">FlickrMail</a> and the Share This widget on each photo page. </p> </div><!-- .entry-content --> <footer class="entry-meta"> <span class="cat-links"> <span class="entry-utility-prep entry-utility-prep-cat-links">Posted in</span> <a href="https://code.flickr.net/category/uncategorized/" rel="category tag">Uncategorized</a> </span> <span class="sep"> | </span> <span class="tag-links"> <span class="entry-utility-prep entry-utility-prep-tag-links">Tagged</span> <a href="https://code.flickr.net/tag/frontend/" rel="tag">frontend</a>, <a href="https://code.flickr.net/tag/javascript/" rel="tag">javascript</a>, <a href="https://code.flickr.net/tag/optimization/" rel="tag">optimization</a>, <a href="https://code.flickr.net/tag/yui/" rel="tag">yui</a> </span> </footer><!-- .entry-meta --> </article><!-- #post-703 --> <article id="post-752" class="post-752 post type-post status-publish format-standard hentry category-change-log category-kittens tag-kittentuesday"> <header class="entry-header"> <h1 class="entry-title"><a href="https://code.flickr.net/2009/03/17/changelog-high-definition-kitten-tuesday-new-hd-search-option/" rel="bookmark">[changelog] High Definition Kitten Tuesday (New HD Search option)</a></h1> <div class="entry-meta"> <span class="sep">Posted on </span><a href="https://code.flickr.net/2009/03/17/changelog-high-definition-kitten-tuesday-new-hd-search-option/" title="4:59 pm" rel="bookmark"><time class="entry-date" datetime="2009-03-17T16:59:19-07:00">March 17, 2009</time></a><span class="by-author"> <span class="sep"> by </span> <span class="author vcard"><a class="url fn n" href="https://code.flickr.net/author/flickrphotography/" title="View all posts by Kay Kremerskothen" rel="author">Kay Kremerskothen</a></span></span> </div><!-- .entry-meta --> </header><!-- .entry-header --> <div class="entry-content"> <p>The other day <a href="http://www.flickr.com/photos/mylesdgrant/">Myles</a> added the option to search for <i>just</i> High Definition video to the <a href="http://www.flickr.com/search/advanced/">Advanced Search</a> page. Clearly just so I can use it to find <a href="http://www.flickr.com/search/?ct=6&#038;mt=videos&#038;hd=1&#038;w=all&#038;q=kitten&#038;m=tags">HD Kitten Videos</a> &#8230;</p> <p><object type="application/x-shockwave-flash" width="500" height="375" data="http://www.flickr.com/apps/video/stewart.swf?v=68975" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"><param name="flashvars" value="intl_lang=en-us&amp;photo_secret=447c7e99b7&amp;photo_id=3071945704&amp;hd_default=false"></param><param name="movie" value="http://www.flickr.com/apps/video/stewart.swf?v=68975"></param><param name="bgcolor" value="#000000"></param><param name="allowFullScreen" value="true"></param></object></p> <p>Thoughtfully I&#8217;ve highlighted the option here &#8230;</p> <p><img loading="lazy" decoding="async" src="http://farm4.static.flickr.com/3569/3363361090_3616293e1b.jpg" alt="Flickr: Advanced Search" border="0" width="500" height="248" /></p> <p>Video by <a href="http://www.flickr.com/photos/kathrynriechert/">kathrynriechert</a>.</p> </div><!-- .entry-content --> <footer class="entry-meta"> <span class="cat-links"> <span class="entry-utility-prep entry-utility-prep-cat-links">Posted in</span> <a href="https://code.flickr.net/category/change-log/" rel="category tag">changelog</a>, <a href="https://code.flickr.net/category/kittens/" rel="category tag">kittens</a> </span> <span class="sep"> | </span> <span class="tag-links"> <span class="entry-utility-prep entry-utility-prep-tag-links">Tagged</span> <a href="https://code.flickr.net/tag/kittentuesday/" rel="tag">kittentuesday</a> </span> </footer><!-- .entry-meta --> </article><!-- #post-752 --> <article id="post-737" class="post-737 post type-post status-publish format-standard hentry category-change-log"> <header class="entry-header"> <h1 class="entry-title"><a href="https://code.flickr.net/2009/03/16/changelog-revision-of-the-places-page-also-neighborhoods/" rel="bookmark">[changelog] Revision of the Places page, also Neighborhoods</a></h1> <div class="entry-meta"> <span class="sep">Posted on </span><a href="https://code.flickr.net/2009/03/16/changelog-revision-of-the-places-page-also-neighborhoods/" title="9:01 pm" rel="bookmark"><time class="entry-date" datetime="2009-03-16T21:01:51-07:00">March 16, 2009</time></a><span class="by-author"> <span class="sep"> by </span> <span class="author vcard"><a class="url fn n" href="https://code.flickr.net/author/flickrphotography/" title="View all posts by Kay Kremerskothen" rel="author">Kay Kremerskothen</a></span></span> </div><!-- .entry-meta --> </header><!-- .entry-header --> <div class="entry-content"> <p>A slightly overdue (and longer than it was supposed to be) post, considering this happened a while ago, but I thought I&#8217;d mention a few subtle updates to the Places page.</p> <p>Even before that though we&#8217;ve added neighborhood links to the Photo pages, before we just listed the neighborhood &#8230;</p> <p><a href="http://www.flickr.com/photos/35468159852@N01/3360817374" title="View 'Neighborhood Link' on Flickr.com"></p> <div style="text-align:center;"><img loading="lazy" decoding="async" src="http://farm4.static.flickr.com/3640/3360817374_18f58083d6.jpg" alt="Neighborhood Link" border="0" width="500" height="205" /></div> <p></a></p> <p>&#8230; now its a link through to the Places page itself, which look rather like this &#8230;</p> <p><a href="http://www.flickr.com/photos/35468159852@N01/3359892917" title="View 'Neighborhoods (South Bank)' on Flickr.com"></p> <div style="text-align:center;"><img loading="lazy" decoding="async" src="http://farm4.static.flickr.com/3443/3359892917_93f0b8dc76.jpg" alt="Neighborhoods (South Bank)" border="0" width="452" height="500" /></div> <p></a></p> <p>Meaning that from a photo that&#8217;s been geotagged you&#8217;ll be able to get more of a feel for the local area. Obviously this work better in large <a href="http://www.flickr.com/places/United+States/California/San+Francisco">Cities</a> where the <a href="http://www.flickr.com/places/United%20States/California/San%20Francisco/Alamo%20Square/">neighborhoods</a> themselves can be as big as <a href="http://www.flickr.com/places/United+Kingdom/England/Sandown">towns</a>, while in the towns you&#8217;re more likely to find the one or two photographers who count each neighborhood as their stomping ground.</p> <p>I guess that&#8217;s the <i>big</i> addition, but we also tweaked a few other things at the same time, here&#8217;s a before and after shot, you&#8217;ll probably need to click through to the <a href="http://www.flickr.com/photos/revdancatt/3360791992/sizes/l/">larger size</a> if you want to see the details.</p> <p><a href="http://www.flickr.com/photos/35468159852@N01/3360791992" title="View 'Old and Updated Places Pages' on Flickr.com"></p> <div style="text-align:center;"><img loading="lazy" decoding="async" src="http://farm4.static.flickr.com/3632/3360791992_6854e248f6.jpg" alt="Old and Updated Places Pages" border="0" width="500" height="228" /></div> <p></a></p> <p>On the left side of each Places page we&#8217;ve moved different elements around, pushing the search further up, the date/time down and scrapping the weather altogether now that we&#8217;ve established that it rains in London.</p> <p>The functional changes over on the right involved moving the title, attribution, Next &amp; Previous buttons off the photo. When we launched Places we didn&#8217;t have Videos, and now we do and the old position clashed with the video controls. </p> <p>The other benefit of the Next/Prev moving to above the photo is that they dont jump around as the photos resized. We also added key controls, now you can just press the forward and back cursor buttons on the keyboard to keep going through photos, power user tip!</p> <p>The &#8220;paging&#8221; buttons no longer hover over the top of the thumbnails, as they were &#8230;</p> <ol> <li>Annoying.</li> <li>Not always obvious.</li> </ol> <p>&nbsp;</p> <p>On a more technical level, now only geotagged photos appear on the Places page, and where possible the location shown on the map (sometimes with Neighborhoods, due to the nature of the beast, they can be just off the edge of the map). </p> <p>Big obvious arrow demonstrating the feature :) &#8230;</p> <p><a href="http://www.flickr.com/photos/35468159852@N01/3359810127" title="View 'Geotagged' on Flickr.com"></p> <div style="text-align:center;"><img loading="lazy" decoding="async" src="http://farm4.static.flickr.com/3617/3359810127_c82ed04f21.jpg" alt="Geotagged" border="0" width="500" height="328" /></div> <p></a></p> <p>When we first launched the Places page we wanted to make sure that each location had plenty of photos, so we used a combination of geotagging and tags/description to automate the selection of them. Which lead to interesting results such as the city of <a href="http://www.flickr.com/places/United+Kingdom/England/Reading">Reading in England</a> featuring a lot of photos about books (tagged reading, natch). Now that we have over <a href="http://code.flickr.com/blog/2009/02/04/100000000-geotagged-photos-plus/">100 Million</a> geotagged photos we&#8217;ve switched to &#8220;just&#8221; them.</p> <p>We also factor in the Season a photo was taken in to select the interesting ones, to give us a bit more change in the first photos you see and too keep them relatively, well, seasonal. We&#8217;ll probably tweak this again soon to get them to rotate even more often, but still working through that one.</p> <h3><strong>City Colours and Endless Photos</strong></h3> <p>As mentioned above we moved the time down and, partly for whimsy, partly because they&#8217;re really useful, used the <a href="http://www.dopplr.com">Dopplr</a> colour to display it and link their pages. Here&#8217;s our <a href="http://www.flickr.com/places/United+States/California/Los+Angeles">Los Angeles page</a> and Dopplr&#8217;s <a href="http://www.dopplr.com/place/us/ca/los-angeles">Los Angeles page</a>, Dopplr decided to <a href="http://blog.dopplr.com/2008/11/27/new-city-pages/">use Flickr to select photos for each City</a> they know about, so we thought we borrow their colour in return :)</p> <p>You can read more about how Dopplr (and therefor us) calculate the colour for a place over on their blog: <a href="http://blog.dopplr.com/2007/10/23/in-rainbows/">In rainbows</a> and <a href="http://blog.dopplr.com/2008/07/25/darker-city-colours/">Darker city colours</a>.</p> <p><a href="http://www.flickr.com/photos/35468159852@N01/3360636566" title="View 'Dopplr And Single Row' on Flickr.com"></p> <div style="text-align:center;"><img loading="lazy" decoding="async" src="http://farm4.static.flickr.com/3633/3360636566_9d04f2d528.jpg" alt="Dopplr And Single Row" border="0" width="500" height="291" /></div> <p></a></p> <p>Finally, because I&#8217;ve gone on enough already, the old design used to have two rows of thumbnails under the main photo and a total of 72 photos, meaning there were 6 &#8220;pages&#8221; of thumbnails. When you got to the last page, that was kinda it, you couldn&#8217;t go any further.</p> <p>Instead there&#8217;s now just one row, <i>but</i> I bolted on the API, so it keeps trying to load more and more photos as you get close to the end of the current lot. Instead of just 72 photos for Los Angeles there&#8217;s now the full (currently) nearly half million 444,594 photos.</p> <p>Which reminds me, we should probably add a Slideshow that that page :)</p> <p>And that&#8217;s the revised Places page.</p> <p>[Edit: Oh and I know we&#8217;ve just launched <a href="http://blog.flickr.net/en/2009/03/16/stats-for-today-and-more-yesterdays/">Stats</a> (again), but it&#8217;s nice to give the dev a couple of days to recover before forcing them to write a changelog about it ;) ] </p> </div><!-- .entry-content --> <footer class="entry-meta"> <span class="cat-links"> <span class="entry-utility-prep entry-utility-prep-cat-links">Posted in</span> <a href="https://code.flickr.net/category/change-log/" rel="category tag">changelog</a> </span> </footer><!-- .entry-meta --> </article><!-- #post-737 --> <article id="post-732" class="post-732 post type-post status-publish format-standard hentry category-uncategorized"> <header class="entry-header"> <h1 class="entry-title"><a href="https://code.flickr.net/2009/03/04/moar-panda-is-a-firehose-of-snowflakes-a-noreaster/" rel="bookmark">Moar Panda: Is a Firehose of Snowflakes a Nor’easter?</a></h1> <div class="entry-meta"> <span class="sep">Posted on </span><a href="https://code.flickr.net/2009/03/04/moar-panda-is-a-firehose-of-snowflakes-a-noreaster/" title="7:17 pm" rel="bookmark"><time class="entry-date" datetime="2009-03-04T19:17:40-08:00">March 4, 2009</time></a><span class="by-author"> <span class="sep"> by </span> <span class="author vcard"><a class="url fn n" href="https://code.flickr.net/author/flickrphotography/" title="View all posts by Kay Kremerskothen" rel="author">Kay Kremerskothen</a></span></span> </div><!-- .entry-meta --> </header><!-- .entry-header --> <div class="entry-content"> <p><a href="http://www.flickr.com/photos/kellan/">Kellan</a> in his blog post over here: <a href="http://laughingmeme.org/2009/03/04/is-a-firehose-of-snowflakes-a-noreaster/">Is a Firehose of Snowflakes a Nor’easter?</a> correctly points that that I <i>may</i> have been slightly cagey about the awesomeness of what we actually <a href="http://code.flickr.com/blog/2009/03/03/panda-tuesday-the-history-of-the-panda-new-apis-explore-and-you/">put out yesterday</a>, by saying &#8230;</p> <blockquote><p><i>&#8220;But because the documentation is quirky, I think people missed the significance. These are Flickr real time data APIs.&#8221;</i></p></blockquote> <p>My excuse is that&#8217;s my natural instinct to sneak new features past the lawyers, by dressing them up in a non-serious fashion :)</p> <p>But in reality, this is just an excuse to post the following photo &#8230;</p> <p><a href="http://www.flickr.com/photos/32794040@N03/3293815044/" title="Magic Panda Bus by Las Tonterias, on Flickr"><img loading="lazy" decoding="async" src="http://farm4.static.flickr.com/3336/3293815044_ae2a35f376_o.jpg" width="480" height="320" alt="Magic Panda Bus" /></a></p> <p>&#8230; see there I go again. Offsetting the important with light humor, <a href="http://laughingmeme.org/2009/03/04/is-a-firehose-of-snowflakes-a-noreaster/">go read Kellan&#8217;s post now</a> for he is smart and knows what he&#8217;s talking about.</p> <p>Now stop trying to get on explore &amp; <a href="http://www.flickr.com/services/api/flickr.panda.getPhotos.htm">enjoy yourself</a></p> <p>Photo by <a href="http://www.flickr.com/photos/32794040@N03/">Las Tonterias</a> points out </p> </div><!-- .entry-content --> <footer class="entry-meta"> <span class="cat-links"> <span class="entry-utility-prep entry-utility-prep-cat-links">Posted in</span> <a href="https://code.flickr.net/category/uncategorized/" rel="category tag">Uncategorized</a> </span> </footer><!-- .entry-meta --> </article><!-- #post-732 --> <article id="post-682" class="post-682 post type-post status-publish format-standard hentry category-uncategorized"> <header class="entry-header"> <h1 class="entry-title"><a href="https://code.flickr.net/2009/03/03/panda-tuesday-the-history-of-the-panda-new-apis-explore-and-you/" rel="bookmark">Panda Tuesday; The History of the Panda, New APIs, Explore and You</a></h1> <div class="entry-meta"> <span class="sep">Posted on </span><a href="https://code.flickr.net/2009/03/03/panda-tuesday-the-history-of-the-panda-new-apis-explore-and-you/" title="8:40 pm" rel="bookmark"><time class="entry-date" datetime="2009-03-03T20:40:41-08:00">March 3, 2009</time></a><span class="by-author"> <span class="sep"> by </span> <span class="author vcard"><a class="url fn n" href="https://code.flickr.net/author/flickrphotography/" title="View all posts by Kay Kremerskothen" rel="author">Kay Kremerskothen</a></span></span> </div><!-- .entry-meta --> </header><!-- .entry-header --> <div class="entry-content"> <h2>The New APIs</h2> <p>I&#8217;ll cut straight to the chase on this one, we&#8217;ve just launched two new API methods;</p> <p><a href="http://www.flickr.com/services/api/flickr.panda.getPhotos.html">flickr.panda.getPhotos</a><br /> <a href="http://www.flickr.com/services/api/flickr.panda.getList.html">flickr.panda.getList</a></p> <p>The first call (<a href="http://www.flickr.com/services/api/flickr.panda.getPhotos.html">flickr.panda.getPhotos</a>) returns you a list of photos that the mystical <a href="http://www.flickr.com/explore/panda">Flickr Pandas</a> are currently interested in, in the following format &#8230;</p> <pre> &lt;photos interval="60000" lastupdate="1235765058272" total="120" panda="ling ling"&gt; &lt;photo title="Shorebirds at Pillar Point" id="3313428913" secret="2cd3cb44cb" server="3609" farm="4" owner="72442527@N00" ownername="Pat Ulrich"/&gt; &lt;photo title="Battle of the sky" id="3313713993" secret="3f7f51500f" server="3382" farm="4" owner="10459691@N05" ownername="Sven Ericsson"/&gt; &lt;!-- and so on --&gt; &lt;/photos&gt; </pre> <p>When calling this API method please ensure that your code uses the <b>lastupdate</b> and <b>interval</b> attributes to determine when to request new photos. <b>lastupdate</b> is a Unix timestamp indicating when the list of photos was generated and <b>interval</b> is the number of seconds to wait before polling the Flickr API again.</p> <p>The second call (<a href="http://www.flickr.com/services/api/flickr.panda.getList.html">flickr.panda.getList</a>) tells you <i>which</i> of the Mystical Flickr Pandas are around to request photos from.</p> <p><b>Ling Ling</b> and <b>Hsing Hsing</b> both return photos they are currently interested in, both have slightly different tastes in photos depending on their mood. The (currently) third Panda <b>Wang Wang</b> returns photos that have recently been geotagged, not quite realtime but close.</p> <p><b>Important!</b> No-one fully understands the whims and fancies of the Pandas at any moment in time, these APIs give you a <i>direct</i> dump of what they are looking at (filtered for safe and public photos only) at this <i>very</i> moment. We cannot promise that this will <i>not</i> include ladies (or men) in bikinis, or possibly even ladies not in bikinis. You should keep this in mind while planning for your target audience, I&#8217;ll touch on this a little bit more in the <b>Implementation Hints</b> section.</p> <p><a href="http://www.flickr.com/photos/ohadby/492775448/" title="You Wanted the Best, You Got the Best by ohad*, on Flickr"><img loading="lazy" decoding="async" src="http://farm1.static.flickr.com/198/492775448_d8676e06ee.jpg" width="500" height="404" alt="You Wanted the Best, You Got the Best" /></a></p> <h2>Philosophy</h2> <p>We&#8217;re always toying around with different ways to find and surface &#8220;<i>interesting</i>&#8221; photos. One method that people are generally familiar with is the <a href="http://www.flickr.com/explore/interesting/7days/">Explore</a> page, of which there&#8217;s always a lot of discussion. A good starting place for more Explore information is <a href="http://www.flickr.com/groups/606639@N25/discuss/72157603825867227">here</a> with more general discussion in the <a href="http://www.flickr.com/groups/606639@N25/">Secrets Of Explore</a> group.</p> <p>But behind Explore is an amount of <a href="http://appft1.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&#038;Sect2=HITOFF&#038;d=PG01&#038;p=1&#038;u=%2Fnetahtml%2FPTO%2Fsrchnum.html&#038;r=1&#038;f=G&#038;l=50&#038;s1=%2220060242139%22.PGNR.&#038;OS=DN/20060242139&#038;RS=DN/20060242139">&#8220;Secret Sauce&#8221;</a> a lot of which focuses on <i>activity around a media object</i>. The Explore page is generally a daily experience, although things often pop in and out during the day.</p> <p>What we are doing with the Pandas is exposing a more real time experience, letting them each focus on various aspects of that activity, the first two <b>Ling Ling</b> and <b>Hsing Hsing</b> are fairly introspective and have different views of Flickr, but both focus on what they&#8217;ve noticed going on <i>recently</i>. The third <b>Wang Wang</b> is more a panda of the world and concentrates solely on geotagging. If you wanted to show photos being geotagged <i>nearly</i> as they happen, <b>Wang Wang</b> is the way to go.</p> <p>From a numbers point of view, Explore shows 500 photos from the last 7 days &#8230; a Panda can get through around 150,000 photos per day.</p> <p>A couple of caveats; Just because a Panda notices a photo, doesn&#8217;t mean that photo will make it into Explore, or even be destined to be considered by the Magic Donkey for Explore. Conversely, because a photo has made it into Explore doesn&#8217;t necessarily mean that a Panda will have noticed it. Also, because of the complexity and amount of stuff going on, no-one really knows exactly what <b>Ling Ling</b> and <b>Hsing Hsing</b> will find interesting, but that won&#8217;t stop us from tweaking the underlining code now and then.</p> <p>Also, you may have noticed that this is one of the less <i>serious</i> APIs, it&#8217;s both experimental and there to hopefully encourage fun and play. Please respect the Pandas and don&#8217;t abuse them, help us protect this endangered species and keep them alive.</p> <h2>Implementation Hints</h2> <p>So, why are we doing all this messing around with &#8220;Pandas&#8221;?</p> <p>Well, mainly because we want to give developers another stream of photos with which to play with. For example you could build your own Flickr Zeitgeist Badge or slideshow or tool to just show stuff that&#8217;s going on over at Flickr.</p> <p>We built this &#8230;</p> <p><a href="http://www.flickr.com/photos/psd/2913831391/" title="Flickr Panda! by psd, on Flickr"><img loading="lazy" decoding="async" src="http://farm4.static.flickr.com/3070/2913831391_7abfb85d94.jpg" width="500" height="341" alt="Flickr Panda!" /></a></p> <p>&#8230; (many people wished we hadn&#8217;t) &#8230; the <a href="http://www.flickr.com/explore/panda">Rainbow Vomiting Panda of Awesomeness</a> as an experiment (which used <b>Ling Ling</b> fwiw). Since then we&#8217;ve been tweaking the backend, and now finally released the API so you can all have a go.</p> <p>It&#8217;s a stream of, on average, more interesting photos then you&#8217;d generally get from polling Everyone&#8217;s photos. The quality is pretty good, the best thing to do is watch <a href="http://www.flickr.com/explore/panda">The Panda</a> for a while and figure out if <b>a</b>) you want to build something with a live stream of photos <b>b</b>) you can build something more better than a vomiting panda (which lets face it, it pretty hard to top!).</p> <p><b>This is what I learnt while building it, it may help you too &#8230;</b></p> <p>When you get a <i>packet</i> of photos back from a panda, its around 60 seconds worth of stuff that the Panda found interesting. The <i>packet</i> is sorted by what the Panda found <i>most</i> interesting in that timeframe to <i>least</i>. Because people can often find ladies in bikinis interesting (for some reason) there can sometimes be some activity around ladies in bikinis that the Pandas may pick-up on.</p> <p>However, Pandas tend not to find ladies in bikinis <i>that</i> interesting (which may have something to do with why they&#8217;re in such peril) and when those photos appear they tend to happen in lower half of the <i>packet</i> of photos.</p> <p><b>So</b> in the case of the Vomiting Panda above, I just threw away the second half of each packet, rather than go through all of the photos before asking for the next packet. I found this to be a good thing to do anyway, even though there&#8217;s always a lot of amazing stuff going on on Flickr the tail end of some packet wasn&#8217;t always quite as amazing as I wanted. You may want to do things differently, but that&#8217;s just what I found while working with the APIs.</p> <h2>Send us stuff</h2> <p>Anyway, on that note, at some point I&#8217;ll try to do a round up of stuff people have built on these APIs. If you want to post what you build to the <a href="http://flickr.com/groups/flickrhacks/">Flickr Hacks</a> group and/or <a href="http://www.flickr.com/messages_write.gne?to=35468159852@N01">FlickrMail</a> me I&#8217;ll start to build up a list and take it from there.</p> <p>Photos by <a href="http://flickr.com/photos/ohadby/">ohad*</a> and <a href="http://www.flickr.com/photos/psd/">psd</a>.</p> </div><!-- .entry-content --> <footer class="entry-meta"> <span class="cat-links"> <span class="entry-utility-prep entry-utility-prep-cat-links">Posted in</span> <a href="https://code.flickr.net/category/uncategorized/" rel="category tag">Uncategorized</a> </span> </footer><!-- .entry-meta --> </article><!-- #post-682 --> <article id="post-659" class="post-659 post type-post status-publish format-standard hentry category-uncategorized tag-api tag-hd tag-long-photos tag-mobile tag-video"> <header class="entry-header"> <h1 class="entry-title"><a href="https://code.flickr.net/2009/03/02/videos-in-the-flickr-api-part-deux/" rel="bookmark">Videos in the Flickr API: Part Deux</a></h1> <div class="entry-meta"> <span class="sep">Posted on </span><a href="https://code.flickr.net/2009/03/02/videos-in-the-flickr-api-part-deux/" title="10:52 pm" rel="bookmark"><time class="entry-date" datetime="2009-03-02T22:52:21-08:00">March 2, 2009</time></a><span class="by-author"> <span class="sep"> by </span> <span class="author vcard"><a class="url fn n" href="https://code.flickr.net/author/flickrphotography/" title="View all posts by Kay Kremerskothen" rel="author">Kay Kremerskothen</a></span></span> </div><!-- .entry-meta --> </header><!-- .entry-header --> <div class="entry-content"> <p><object width="500" height="281" height="281" width="500" data="http://www.flickr.com/apps/video/stewart.swf?v=67090" type="application/x-shockwave-flash"><param name="flashvars" value="intl_lang=en-us&amp;photo_secret=a901c4406d&amp;photo_id=2414600425&amp;hd=true&amp;show_info_box=true" /><param name="bgcolor" value="#000000" /><param name="allowFullScreen" value="true" /><param name="src" value="http://www.flickr.com/apps/video/stewart.swf?v=67090" /><param name="allowfullscreen" value="true" /></object></p> <p>We hope it&#8217;s obvious that long photos are taken <a href="http://flickr.com/photos/heather/2404080160/">extremely seriously</a> here at <a href="http://flickr.com/photos/tags/flickrhq/">FlickrHQ</a>. To that end, it&#8217;s important that videos be first class citizens in our api. And with <a href="http://blog.flickr.net/2009/03/02/video-for-all-hd/">today&#8217;s launch of video for free users and the HD output</a>, we have some <a href="http://flickr.com/services/api/">important new api changes</a> to share with you. So if you&#8217;re an uploader developer, a mobile application developer, or you make those things that are changing the way that people consume their tv and other media (nudge-nudge <a href="http://www.boxee.tv/">Boxee</a>), take a look at these new additions to the api and make our long photos feel right at home in your apps.</p> <p>With the addition of our HD output, all videos are now transcoded into 2 or 3 MP4s. Since these are in a widely-supported format, we thought it would be interesting to make them available to third-party developers. <a href="http://flickr.com/services/api/flickr.photos.getSizes.html">flickr.photos.getSizes</a> will give you semi-permanent urls to the 700k site output, the mobile-optimized output, the 2mbps HD output (if available), and the original video (if the call is authenticated by the video owner and the owner is a pro member). For example:</p> <pre>&lt;rsp stat=&quot;ok&quot;&gt; &lt;sizes canblog=&quot;1&quot; canprint=&quot;1&quot; candownload=&quot;1&quot;&gt; &lt;size label=&quot;Square&quot; width=&quot;75&quot; height=&quot;75&quot; source=&quot;http://farm4.static.flickr.com/3436/3232057393_815b1c5d26_s.jpg&quot; url=&quot;http://www.flickr.com/photos/mylesdgrant/3232057393/sizes/sq/&quot; media=&quot;photo&quot;/&gt; &lt;size label=&quot;Thumbnail&quot; width=&quot;100&quot; height=&quot;56&quot; source=&quot;http://farm4.static.flickr.com/3436/3232057393_815b1c5d26_t.jpg&quot; url=&quot;http://www.flickr.com/photos/mylesdgrant/3232057393/sizes/t/&quot; media=&quot;photo&quot;/&gt; &lt;size label=&quot;Small&quot; width=&quot;240&quot; height=&quot;135&quot; source=&quot;http://farm4.static.flickr.com/3436/3232057393_815b1c5d26_m.jpg&quot; url=&quot;http://www.flickr.com/photos/mylesdgrant/3232057393/sizes/s/&quot; media=&quot;photo&quot;/&gt; &lt;size label=&quot;Medium&quot; width=&quot;500&quot; height=&quot;281&quot; source=&quot;http://farm4.static.flickr.com/3436/3232057393_815b1c5d26.jpg&quot; url=&quot;http://www.flickr.com/photos/mylesdgrant/3232057393/sizes/m/&quot; media=&quot;photo&quot;/&gt; &lt;size label=&quot;Original&quot; width=&quot;1280&quot; height=&quot;720&quot; source=&quot;http://farm4.static.flickr.com/3436/3232057393_204af3bcff_o.jpg&quot; url=&quot;http://www.flickr.com/photos/mylesdgrant/3232057393/sizes/o/&quot; media=&quot;photo&quot;/&gt; &lt;size label=&quot;Video Player&quot; width=&quot;640&quot; height=&quot;360&quot; source=&quot;http://www.flickr.com/apps/video/stewart.swf?v=1233362721&amp;photo_id=3232057393&amp;photo_secret=815b1c5d26&quot; url=&quot;http://www.flickr.com/photos/mylesdgrant/3232057393/&quot; media=&quot;video&quot;/&gt; &lt;size label=&quot;Site MP4&quot; width=&quot;640&quot; height=&quot;360&quot; source=&quot;http://www.flickr.com/photos/mylesdgrant/3232057393/play/site/815b1c5d26/&quot; url=&quot;http://www.flickr.com/photos/mylesdgrant/3232057393/&quot; media=&quot;video&quot;/&gt; &lt;size label=&quot;Mobile MP4&quot; width=&quot;480&quot; height=&quot;360&quot; source=&quot;http://www.flickr.com/photos/mylesdgrant/3232057393/play/mobile/815b1c5d26/&quot; url=&quot;http://www.flickr.com/photos/mylesdgrant/3232057393/&quot; media=&quot;video&quot;/&gt; &lt;size label=&quot;HD MP4&quot; width=&quot;1280&quot; height=&quot;720&quot; source=&quot;http://www.flickr.com/photos/mylesdgrant/3232057393/play/hd/815b1c5d26/&quot; url=&quot;http://www.flickr.com/photos/mylesdgrant/3232057393/&quot; media=&quot;video&quot;/&gt; &lt;size label=&quot;Video Original&quot; width=&quot;1280&quot; height=&quot;720&quot; source=&quot;http://www.flickr.com/photos/mylesdgrant/3232057393/play/orig/123fakest/&quot; url=&quot;http://www.flickr.com/photos/mylesdgrant/3232057393/&quot; media=&quot;video&quot;/&gt; &lt;/sizes&gt; &lt;/rsp&gt;</pre> <p>Use this if you&#8217;re lazy. If you&#8217;re <em>not</em> lazy and want to be one of the cool kids, you can construct the urls to these outputs yourself, assuming you have the nsid or custom url of the owner, the video id, and the secret (or original secret). Requesting the HD output for a video that doesn&#8217;t have it (because it&#8217;s less than 720 pixels high, or the owner is a free member), will deliver a 404. An example url:</p> <pre>http://www.flickr.com/photos/{user-id|custom-url}/{photo-id}/play/{site|mobile|hd|orig}/{secret|originalsecret}/</pre> <p>If you&#8217;re developing uploading tools for free users, <a href="http://flickr.com/services/api/flickr.people.getUploadStatus.html">flickr.people.getUploadStatus</a> has new attributes to determine whether a user is allowed to upload any more videos or not. If the user is a free user, the output of this method will now look something like this:</p> <pre>&lt;rsp stat=&quot;ok&quot;&gt; &lt;user id=&quot;88251462@N00&quot; ispro=&quot;0&quot;&gt; &lt;username&gt;Dev Myles&lt;/username&gt; &lt;bandwidth max=&quot;107373568&quot; used=&quot;0&quot; maxbytes=&quot;104857600&quot; usedbytes=&quot;0&quot; remainingbytes=&quot;104857600&quot; maxkb=&quot;104857&quot; usedkb=&quot;0&quot; remainingkb=&quot;104857&quot; unlimited=&quot;0&quot;/&gt; &lt;filesize max=&quot;10485760&quot; maxbytes=&quot;10485760&quot; maxkb=&quot;10240&quot; maxmb=&quot;10&quot;/&gt; &lt;sets created=&quot;7&quot; remaining=&quot;lots&quot;/&gt; &lt;videosize maxbytes=&quot;157286400&quot; maxkb=&quot;153600&quot; maxmb=&quot;150&quot;/&gt; &lt;videos uploaded=&quot;0&quot; remaining=&quot;2&quot;/&gt; &lt;/user&gt; &lt;/rsp&gt;</pre> <p>Note the new &lt;videos&gt; element in the response, which will let you know how many more videos this user can upload this month.</p> <p>And as always, if you feel like we&#8217;re missing something, <a href="http://tech.groups.yahoo.com/group/yws-flickr/">please let us know</a>.</p> </div><!-- .entry-content --> <footer class="entry-meta"> <span class="cat-links"> <span class="entry-utility-prep entry-utility-prep-cat-links">Posted in</span> <a href="https://code.flickr.net/category/uncategorized/" rel="category tag">Uncategorized</a> </span> <span class="sep"> | </span> <span class="tag-links"> <span class="entry-utility-prep entry-utility-prep-tag-links">Tagged</span> <a href="https://code.flickr.net/tag/api/" rel="tag">api</a>, <a href="https://code.flickr.net/tag/hd/" rel="tag">hd</a>, <a href="https://code.flickr.net/tag/long-photos/" rel="tag">long photos</a>, <a href="https://code.flickr.net/tag/mobile/" rel="tag">mobile</a>, <a href="https://code.flickr.net/tag/video/" rel="tag">video</a> </span> </footer><!-- .entry-meta --> </article><!-- #post-659 --> </div><!-- #content --> </section><!-- #primary --> <div id="secondary" class="widget-area" role="complementary"> <aside id="jetpack-search-filters-3" class="widget jetpack-filters widget_search"> <div id="jetpack-search-filters-3-wrapper" class="jetpack-instant-search-wrapper"> <div class="jetpack-search-form"> <form method="get" id="searchform" action="https://code.flickr.net/"> <label for="s" class="assistive-text">Search</label> <input type="text" class="field" name="s" id="s" placeholder="Search" /> <input type="submit" class="submit" name="submit" id="searchsubmit" value="Search" /> <input type="hidden" name="orderby" value="" /><input type="hidden" name="order" value="" /></form> </div> <h4 class="jetpack-search-filters-widget__sub-heading"> Categories </h4> <ul class="jetpack-search-filters-widget__filter-list"> <li> <a href="#" class="jetpack-search-filter__link" data-filter-type="taxonomy" data-taxonomy="category" data-val="uncategorized"> Uncategorized&nbsp;(136) </a> </li> <li> <a href="#" class="jetpack-search-filter__link" data-filter-type="taxonomy" data-taxonomy="category" data-val="geo"> geo&nbsp;(12) </a> </li> <li> <a href="#" class="jetpack-search-filter__link" data-filter-type="taxonomy" data-taxonomy="category" data-val="kittens"> kittens&nbsp;(10) </a> </li> <li> <a href="#" class="jetpack-search-filter__link" data-filter-type="taxonomy" data-taxonomy="category" data-val="change-log"> changelog&nbsp;(7) </a> </li> <li> <a href="#" class="jetpack-search-filter__link" data-filter-type="taxonomy" data-taxonomy="category" data-val="uploadr"> uploadr&nbsp;(6) </a> </li> </ul> <h4 class="jetpack-search-filters-widget__sub-heading"> Tags </h4> <ul class="jetpack-search-filters-widget__filter-list"> <li> <a href="#" class="jetpack-search-filter__link" data-filter-type="taxonomy" data-taxonomy="post_tag" data-val="api"> api&nbsp;(24) </a> </li> <li> <a href="#" class="jetpack-search-filter__link" data-filter-type="taxonomy" data-taxonomy="post_tag" data-val="geo"> geo&nbsp;(13) </a> </li> <li> <a href="#" class="jetpack-search-filter__link" data-filter-type="taxonomy" data-taxonomy="post_tag" data-val="machine-tags"> machine tags&nbsp;(10) </a> </li> <li> <a href="#" class="jetpack-search-filter__link" data-filter-type="taxonomy" data-taxonomy="post_tag" data-val="javascript"> javascript&nbsp;(9) </a> </li> <li> <a href="#" class="jetpack-search-filter__link" data-filter-type="taxonomy" data-taxonomy="post_tag" data-val="kittentuesday"> kittentuesday&nbsp;(8) </a> </li> </ul> <h4 class="jetpack-search-filters-widget__sub-heading"> Year </h4> <ul class="jetpack-search-filters-widget__filter-list"> <li> <a href="#" class="jetpack-search-filter__link" data-filter-type="year_post_date" data-val="2022-01-01 00:00:00" > 2022&nbsp;(2) </a> </li> <li> <a href="#" class="jetpack-search-filter__link" data-filter-type="year_post_date" data-val="2021-01-01 00:00:00" > 2021&nbsp;(1) </a> </li> <li> <a href="#" class="jetpack-search-filter__link" data-filter-type="year_post_date" data-val="2018-01-01 00:00:00" > 2018&nbsp;(1) </a> </li> <li> <a href="#" class="jetpack-search-filter__link" data-filter-type="year_post_date" data-val="2017-01-01 00:00:00" > 2017&nbsp;(2) </a> </li> <li> <a href="#" class="jetpack-search-filter__link" data-filter-type="year_post_date" data-val="2016-01-01 00:00:00" > 2016&nbsp;(5) </a> </li> </ul> </div></aside> <aside id="recent-posts-2" class="widget widget_recent_entries"> <h3 class="widget-title">Recent Posts</h3> <ul> <li> <a href="https://code.flickr.net/2022/02/14/safer-internet-day-and-open-source-codes-of-conduct/">Safer Internet Day and Open Source Codes of Conduct</a> </li> <li> <a href="https://code.flickr.net/2022/01/04/a-pluggable-solution-for-api-observability-on-our-php-system/">A Pluggable Solution for API Observability on our PHP System</a> </li> <li> <a href="https://code.flickr.net/2021/11/22/flickr-engineering-team-vision-guiding-principles/">Flickr Engineering Team Vision &#038; Guiding Principles</a> </li> <li> <a href="https://code.flickr.net/2018/04/20/together/">Together</a> </li> <li> <a href="https://code.flickr.net/2017/03/07/introducing-similarity-search-at-flickr/">Introducing Similarity Search at Flickr</a> </li> </ul> </aside><aside id="archives-2" class="widget widget_archive"><h3 class="widget-title">Archives</h3> <ul> <li><a href='https://code.flickr.net/2022/02/'>February 2022</a></li> <li><a href='https://code.flickr.net/2022/01/'>January 2022</a></li> <li><a href='https://code.flickr.net/2021/11/'>November 2021</a></li> <li><a href='https://code.flickr.net/2018/04/'>April 2018</a></li> <li><a href='https://code.flickr.net/2017/03/'>March 2017</a></li> <li><a href='https://code.flickr.net/2017/01/'>January 2017</a></li> <li><a href='https://code.flickr.net/2016/09/'>September 2016</a></li> <li><a href='https://code.flickr.net/2016/05/'>May 2016</a></li> <li><a href='https://code.flickr.net/2016/04/'>April 2016</a></li> <li><a href='https://code.flickr.net/2016/03/'>March 2016</a></li> <li><a href='https://code.flickr.net/2015/12/'>December 2015</a></li> <li><a href='https://code.flickr.net/2015/11/'>November 2015</a></li> <li><a href='https://code.flickr.net/2015/09/'>September 2015</a></li> <li><a href='https://code.flickr.net/2015/07/'>July 2015</a></li> <li><a href='https://code.flickr.net/2015/06/'>June 2015</a></li> <li><a href='https://code.flickr.net/2015/03/'>March 2015</a></li> <li><a href='https://code.flickr.net/2014/10/'>October 2014</a></li> <li><a href='https://code.flickr.net/2014/08/'>August 2014</a></li> <li><a href='https://code.flickr.net/2014/07/'>July 2014</a></li> <li><a href='https://code.flickr.net/2014/05/'>May 2014</a></li> <li><a href='https://code.flickr.net/2014/04/'>April 2014</a></li> <li><a href='https://code.flickr.net/2014/02/'>February 2014</a></li> <li><a href='https://code.flickr.net/2013/09/'>September 2013</a></li> <li><a href='https://code.flickr.net/2013/06/'>June 2013</a></li> <li><a href='https://code.flickr.net/2013/03/'>March 2013</a></li> <li><a href='https://code.flickr.net/2012/12/'>December 2012</a></li> <li><a href='https://code.flickr.net/2012/10/'>October 2012</a></li> <li><a href='https://code.flickr.net/2012/07/'>July 2012</a></li> <li><a href='https://code.flickr.net/2012/06/'>June 2012</a></li> <li><a href='https://code.flickr.net/2012/05/'>May 2012</a></li> <li><a href='https://code.flickr.net/2012/04/'>April 2012</a></li> <li><a href='https://code.flickr.net/2012/02/'>February 2012</a></li> <li><a href='https://code.flickr.net/2012/01/'>January 2012</a></li> <li><a href='https://code.flickr.net/2011/12/'>December 2011</a></li> <li><a href='https://code.flickr.net/2011/10/'>October 2011</a></li> <li><a href='https://code.flickr.net/2011/09/'>September 2011</a></li> <li><a href='https://code.flickr.net/2011/08/'>August 2011</a></li> <li><a href='https://code.flickr.net/2011/07/'>July 2011</a></li> <li><a href='https://code.flickr.net/2011/06/'>June 2011</a></li> <li><a href='https://code.flickr.net/2011/03/'>March 2011</a></li> <li><a href='https://code.flickr.net/2011/02/'>February 2011</a></li> <li><a href='https://code.flickr.net/2011/01/'>January 2011</a></li> <li><a href='https://code.flickr.net/2010/11/'>November 2010</a></li> <li><a href='https://code.flickr.net/2010/10/'>October 2010</a></li> <li><a href='https://code.flickr.net/2010/09/'>September 2010</a></li> <li><a href='https://code.flickr.net/2010/08/'>August 2010</a></li> <li><a href='https://code.flickr.net/2010/07/'>July 2010</a></li> <li><a href='https://code.flickr.net/2010/05/'>May 2010</a></li> <li><a href='https://code.flickr.net/2010/04/'>April 2010</a></li> <li><a href='https://code.flickr.net/2010/03/'>March 2010</a></li> <li><a href='https://code.flickr.net/2010/02/'>February 2010</a></li> <li><a href='https://code.flickr.net/2010/01/'>January 2010</a></li> <li><a href='https://code.flickr.net/2009/12/'>December 2009</a></li> <li><a href='https://code.flickr.net/2009/11/'>November 2009</a></li> <li><a href='https://code.flickr.net/2009/10/'>October 2009</a></li> <li><a href='https://code.flickr.net/2009/09/'>September 2009</a></li> <li><a href='https://code.flickr.net/2009/07/'>July 2009</a></li> <li><a href='https://code.flickr.net/2009/06/'>June 2009</a></li> <li><a href='https://code.flickr.net/2009/05/'>May 2009</a></li> <li><a href='https://code.flickr.net/2009/04/'>April 2009</a></li> <li><a href='https://code.flickr.net/2009/03/' aria-current="page">March 2009</a></li> <li><a href='https://code.flickr.net/2009/02/'>February 2009</a></li> <li><a href='https://code.flickr.net/2009/01/'>January 2009</a></li> <li><a href='https://code.flickr.net/2008/12/'>December 2008</a></li> <li><a href='https://code.flickr.net/2008/11/'>November 2008</a></li> <li><a href='https://code.flickr.net/2008/10/'>October 2008</a></li> <li><a href='https://code.flickr.net/2008/09/'>September 2008</a></li> <li><a href='https://code.flickr.net/2008/08/'>August 2008</a></li> <li><a href='https://code.flickr.net/2008/07/'>July 2008</a></li> <li><a href='https://code.flickr.net/2008/06/'>June 2008</a></li> <li><a href='https://code.flickr.net/2008/05/'>May 2008</a></li> <li><a href='https://code.flickr.net/2008/04/'>April 2008</a></li> </ul> </aside><aside id="categories-2" class="widget widget_categories"><h3 class="widget-title">Categories</h3> <ul> <li class="cat-item cat-item-11749740"><a href="https://code.flickr.net/category/api-2/">API</a> </li> <li class="cat-item cat-item-564792"><a href="https://code.flickr.net/category/change-log/">changelog</a> </li> <li class="cat-item cat-item-5784"><a href="https://code.flickr.net/category/event/">event</a> </li> <li class="cat-item cat-item-29160"><a href="https://code.flickr.net/category/geo/">geo</a> </li> <li class="cat-item cat-item-139037766"><a href="https://code.flickr.net/category/hadoop/">hadoop</a> </li> <li class="cat-item cat-item-32"><a href="https://code.flickr.net/category/infrastructure/">infrastructure</a> </li> <li class="cat-item cat-item-139037765"><a href="https://code.flickr.net/category/kittens/">kittens</a> </li> <li class="cat-item cat-item-20156"><a href="https://code.flickr.net/category/labs/">labs</a> </li> <li class="cat-item cat-item-171"><a href="https://code.flickr.net/category/meta/">meta</a> </li> <li class="cat-item cat-item-7092"><a href="https://code.flickr.net/category/metrics/">metrics</a> </li> <li class="cat-item cat-item-139037764"><a href="https://code.flickr.net/category/open-source/">open source</a> </li> <li class="cat-item cat-item-1930"><a href="https://code.flickr.net/category/performance/">performance</a> </li> <li class="cat-item cat-item-304"><a href="https://code.flickr.net/category/photos/">photos</a> </li> <li class="cat-item cat-item-2373"><a href="https://code.flickr.net/category/search/">search</a> </li> <li class="cat-item cat-item-1"><a href="https://code.flickr.net/category/uncategorized/">Uncategorized</a> </li> <li class="cat-item cat-item-249276"><a href="https://code.flickr.net/category/uploadr/">uploadr</a> </li> <li class="cat-item cat-item-412"><a href="https://code.flickr.net/category/video/">video</a> </li> <li class="cat-item cat-item-830560"><a href="https://code.flickr.net/category/xulrunner/">xulrunner</a> </li> </ul> </aside><aside id="meta-2" class="widget widget_meta"><h3 class="widget-title">Meta</h3> <ul> <li><a href="https://code.flickr.net/wp-login.php">Log in</a></li> <li><a href="https://code.flickr.net/feed/">Entries feed</a></li> <li><a href="https://code.flickr.net/comments/feed/">Comments feed</a></li> <li><a href="https://wordpress.org/">WordPress.org</a></li> </ul> </aside> </div><!-- #secondary .widget-area --> </div><!-- #main --> <footer id="colophon" role="contentinfo"> <div id="site-generator"> &copy; 2025 Flickr, Inc. All rights reserved. | Powered by <a href="https://wpvip.com/?utm_source=vip_powered_wpcom&#038;utm_medium=web&#038;utm_campaign=VIP%20Footer%20Credit&#038;utm_term=code.flickr.net" rel="generator nofollow" class="powered-by-wpcom">WordPress VIP</a> </div> </footer><!-- #colophon --> </div><!-- #page --> <div class="jetpack-instant-search__widget-area" style="display: none"> <div id="jetpack-search-filters-2" class="widget jetpack-filters widget_search"> <div id="jetpack-search-filters-2-wrapper" class="jetpack-instant-search-wrapper"> </div></div> </div> <script type="text/javascript" src="https://code.flickr.net/wp-includes/js/dist/hooks.min.js?m=1739294330g" ></script><script type="text/javascript" src="https://code.flickr.net/wp-includes/js/dist/i18n.min.js?ver=5e580eb46a90c2b997e6" id="wp-i18n-js"></script> <script type="text/javascript" id="wp-i18n-js-after"> /* <![CDATA[ */ wp.i18n.setLocaleData( { 'text direction\u0004ltr': [ 'ltr' ] } ); /* ]]> */ </script> <script type="text/javascript" src="https://code.flickr.net/wp-content/mu-plugins/jetpack-14.2/jetpack_vendor/automattic/jetpack-assets/build/i18n-loader.js?minify=true&amp;ver=becd7d9884bc1b331e45" id="wp-jp-i18n-loader-js"></script> <script type="text/javascript" id="wp-jp-i18n-loader-js-after"> /* <![CDATA[ */ wp.jpI18nLoader.state = {"baseUrl":"https://code.flickr.net/wp-content/languages/","locale":"en_US","domainMap":{"jetpack-admin-ui":"plugins/jetpack","jetpack-assets":"plugins/jetpack","jetpack-backup-pkg":"plugins/jetpack","jetpack-blaze":"plugins/jetpack","jetpack-boost-core":"plugins/jetpack","jetpack-boost-speed-score":"plugins/jetpack","jetpack-classic-theme-helper":"plugins/jetpack","jetpack-compat":"plugins/jetpack","jetpack-config":"plugins/jetpack","jetpack-connection":"plugins/jetpack","jetpack-explat":"plugins/jetpack","jetpack-forms":"plugins/jetpack","jetpack-image-cdn":"plugins/jetpack","jetpack-import":"plugins/jetpack","jetpack-ip":"plugins/jetpack","jetpack-jitm":"plugins/jetpack","jetpack-licensing":"plugins/jetpack","jetpack-masterbar":"plugins/jetpack","jetpack-my-jetpack":"plugins/jetpack","jetpack-password-checker":"plugins/jetpack","jetpack-plugins-installer":"plugins/jetpack","jetpack-post-list":"plugins/jetpack","jetpack-protect-models":"plugins/jetpack","jetpack-protect-status":"plugins/jetpack","jetpack-publicize-pkg":"plugins/jetpack","jetpack-search-pkg":"plugins/jetpack","jetpack-stats":"plugins/jetpack","jetpack-stats-admin":"plugins/jetpack","jetpack-sync":"plugins/jetpack","jetpack-videopress-pkg":"plugins/jetpack","jetpack-waf":"plugins/jetpack","jetpack-wordads":"plugins/jetpack","woocommerce-analytics":"plugins/jetpack"},"domainPaths":{"jetpack-admin-ui":"jetpack_vendor/automattic/jetpack-admin-ui/","jetpack-assets":"jetpack_vendor/automattic/jetpack-assets/","jetpack-backup-pkg":"jetpack_vendor/automattic/jetpack-backup/","jetpack-blaze":"jetpack_vendor/automattic/jetpack-blaze/","jetpack-boost-core":"jetpack_vendor/automattic/jetpack-boost-core/","jetpack-boost-speed-score":"jetpack_vendor/automattic/jetpack-boost-speed-score/","jetpack-classic-theme-helper":"jetpack_vendor/automattic/jetpack-classic-theme-helper/","jetpack-compat":"jetpack_vendor/automattic/jetpack-compat/","jetpack-config":"jetpack_vendor/automattic/jetpack-config/","jetpack-connection":"jetpack_vendor/automattic/jetpack-connection/","jetpack-explat":"jetpack_vendor/automattic/jetpack-explat/","jetpack-forms":"jetpack_vendor/automattic/jetpack-forms/","jetpack-image-cdn":"jetpack_vendor/automattic/jetpack-image-cdn/","jetpack-import":"jetpack_vendor/automattic/jetpack-import/","jetpack-ip":"jetpack_vendor/automattic/jetpack-ip/","jetpack-jitm":"jetpack_vendor/automattic/jetpack-jitm/","jetpack-licensing":"jetpack_vendor/automattic/jetpack-licensing/","jetpack-masterbar":"jetpack_vendor/automattic/jetpack-masterbar/","jetpack-my-jetpack":"jetpack_vendor/automattic/jetpack-my-jetpack/","jetpack-password-checker":"jetpack_vendor/automattic/jetpack-password-checker/","jetpack-plugins-installer":"jetpack_vendor/automattic/jetpack-plugins-installer/","jetpack-post-list":"jetpack_vendor/automattic/jetpack-post-list/","jetpack-protect-models":"jetpack_vendor/automattic/jetpack-protect-models/","jetpack-protect-status":"jetpack_vendor/automattic/jetpack-protect-status/","jetpack-publicize-pkg":"jetpack_vendor/automattic/jetpack-publicize/","jetpack-search-pkg":"jetpack_vendor/automattic/jetpack-search/","jetpack-stats":"jetpack_vendor/automattic/jetpack-stats/","jetpack-stats-admin":"jetpack_vendor/automattic/jetpack-stats-admin/","jetpack-sync":"jetpack_vendor/automattic/jetpack-sync/","jetpack-videopress-pkg":"jetpack_vendor/automattic/jetpack-videopress/","jetpack-waf":"jetpack_vendor/automattic/jetpack-waf/","jetpack-wordads":"jetpack_vendor/automattic/jetpack-wordads/","woocommerce-analytics":"jetpack_vendor/automattic/woocommerce-analytics/"}}; /* ]]> */ </script> <script type="text/javascript" src="https://code.flickr.net/_static/??/wp-includes/js/dist/vendor/wp-polyfill.min.js,/wp-includes/js/dist/url.min.js?m=1739294330j" ></script><script type="text/javascript" id="jetpack-instant-search-js-before"> /* <![CDATA[ */ var JetpackInstantSearchOptions=JSON.parse(decodeURIComponent("%7B%22overlayOptions%22%3A%7B%22colorTheme%22%3A%22light%22%2C%22enableInfScroll%22%3Atrue%2C%22enableFilteringOpensOverlay%22%3Atrue%2C%22enablePostDate%22%3Atrue%2C%22enableSort%22%3Atrue%2C%22highlightColor%22%3A%22%23FFC%22%2C%22overlayTrigger%22%3A%22submit%22%2C%22resultFormat%22%3A%22expanded%22%2C%22showPoweredBy%22%3Atrue%2C%22defaultSort%22%3A%22relevance%22%2C%22excludedPostTypes%22%3A%5B%5D%7D%2C%22homeUrl%22%3A%22https%3A%5C%2F%5C%2Fcode.flickr.net%22%2C%22locale%22%3A%22en-US%22%2C%22postsPerPage%22%3A10%2C%22siteId%22%3A185426273%2C%22postTypes%22%3A%7B%22post%22%3A%7B%22singular_name%22%3A%22Post%22%2C%22name%22%3A%22Posts%22%7D%2C%22page%22%3A%7B%22singular_name%22%3A%22Page%22%2C%22name%22%3A%22Pages%22%7D%2C%22attachment%22%3A%7B%22singular_name%22%3A%22Media%22%2C%22name%22%3A%22Media%22%7D%7D%2C%22webpackPublicPath%22%3A%22https%3A%5C%2F%5C%2Fcode.flickr.net%5C%2Fwp-content%5C%2Fmu-plugins%5C%2Fjetpack-14.2%5C%2Fjetpack_vendor%5C%2Fautomattic%5C%2Fjetpack-search%5C%2Fbuild%5C%2Finstant-search%5C%2F%22%2C%22isPhotonEnabled%22%3Afalse%2C%22isFreePlan%22%3Afalse%2C%22apiRoot%22%3A%22https%3A%5C%2F%5C%2Fcode.flickr.net%5C%2Fwp-json%5C%2F%22%2C%22apiNonce%22%3A%226427edfc35%22%2C%22isPrivateSite%22%3Afalse%2C%22isWpcom%22%3Afalse%2C%22hasOverlayWidgets%22%3Atrue%2C%22widgets%22%3A%5B%7B%22filters%22%3A%5B%7B%22name%22%3A%22Bylines%22%2C%22type%22%3A%22taxonomy%22%2C%22taxonomy%22%3A%22byline%22%2C%22count%22%3A5%2C%22widget_id%22%3A%22jetpack-search-filters-2%22%2C%22filter_id%22%3A%22taxonomy_0%22%7D%2C%7B%22name%22%3A%22Categories%22%2C%22type%22%3A%22taxonomy%22%2C%22taxonomy%22%3A%22category%22%2C%22count%22%3A5%2C%22widget_id%22%3A%22jetpack-search-filters-2%22%2C%22filter_id%22%3A%22taxonomy_1%22%7D%2C%7B%22name%22%3A%22Tags%22%2C%22type%22%3A%22taxonomy%22%2C%22taxonomy%22%3A%22post_tag%22%2C%22count%22%3A5%2C%22widget_id%22%3A%22jetpack-search-filters-2%22%2C%22filter_id%22%3A%22taxonomy_2%22%7D%2C%7B%22name%22%3A%22Year%22%2C%22type%22%3A%22date_histogram%22%2C%22count%22%3A5%2C%22field%22%3A%22post_date%22%2C%22interval%22%3A%22year%22%2C%22widget_id%22%3A%22jetpack-search-filters-2%22%2C%22filter_id%22%3A%22date_histogram_3%22%7D%5D%2C%22widget_id%22%3A%22jetpack-search-filters-2%22%7D%5D%2C%22widgetsOutsideOverlay%22%3A%5B%7B%22filters%22%3A%5B%7B%22name%22%3A%22Bylines%22%2C%22type%22%3A%22taxonomy%22%2C%22taxonomy%22%3A%22byline%22%2C%22count%22%3A5%2C%22widget_id%22%3A%22jetpack-search-filters-3%22%2C%22filter_id%22%3A%22taxonomy_4%22%7D%2C%7B%22name%22%3A%22Categories%22%2C%22type%22%3A%22taxonomy%22%2C%22taxonomy%22%3A%22category%22%2C%22count%22%3A5%2C%22widget_id%22%3A%22jetpack-search-filters-3%22%2C%22filter_id%22%3A%22taxonomy_5%22%7D%2C%7B%22name%22%3A%22Tags%22%2C%22type%22%3A%22taxonomy%22%2C%22taxonomy%22%3A%22post_tag%22%2C%22count%22%3A5%2C%22widget_id%22%3A%22jetpack-search-filters-3%22%2C%22filter_id%22%3A%22taxonomy_6%22%7D%2C%7B%22name%22%3A%22Year%22%2C%22type%22%3A%22date_histogram%22%2C%22count%22%3A5%2C%22field%22%3A%22post_date%22%2C%22interval%22%3A%22year%22%2C%22widget_id%22%3A%22jetpack-search-filters-3%22%2C%22filter_id%22%3A%22date_histogram_7%22%7D%5D%2C%22widget_id%22%3A%22jetpack-search-filters-3%22%7D%5D%2C%22hasNonSearchWidgets%22%3Afalse%2C%22preventTrackingCookiesReset%22%3Afalse%7D")); /* ]]> */ </script> <script type="text/javascript" src="https://code.flickr.net/wp-content/mu-plugins/jetpack-14.2/jetpack_vendor/automattic/jetpack-search/build/instant-search/jp-search.js?minify=false&amp;ver=da5ecd9f722e7fcb409e" id="jetpack-instant-search-js"></script> <script type="text/javascript" src="//stats.wp.com/w.js?ver=202508" id="jp-tracks-js"></script> <script type="text/javascript" src="https://stats.wp.com/e-202508.js" id="jetpack-stats-js" data-wp-strategy="defer"></script> <script type="text/javascript" id="jetpack-stats-js-after"> /* <![CDATA[ */ _stq = window._stq || []; _stq.push([ "view", JSON.parse("{\"v\":\"ext\",\"blog\":\"185426273\",\"post\":\"0\",\"tz\":\"-8\",\"srv\":\"code.flickr.net\",\"hp\":\"vip\",\"j\":\"1:14.2.1\"}") ]); _stq.push([ "clickTrackerInit", "185426273", "0" ]); /* ]]> */ </script> <script async src="https://embedr.flickr.com/assets/client-code.js" charset="utf-8"></script> </body> </html>

Pages: 1 2 3 4 5 6 7 8 9 10