<include rel="inline" src="assets/xml/xmlrpc.xml" />
<script><![CDATA[
var currentElem = null; // The currently selected image.
var clickPt; // Where the image was clicked.
var clickDist; // Cache the distance from the click to the tack.
var clickScale; // Cache the scale at the time of the click.
var clickRotation; // Cache the rotation at the time of the click.
var clickAng; // Cache the angle of the click relative to the tack.
var tackPt; // The position of the tack.
var zIndex = 1; // Each click applies a higher z-index to the image.
var userNameIDs = { }; // A cache of user IDs.
var index = 1; // An index for images.
var tmpID; // Temp userID variable.
]]></script>
<style><![CDATA[
text:link:hover, text:visited:hover
{
underline: false;
color: #ff5523;
}
text
{
font-family: Swift LT Std;
flash-text-anti-alias-type: advanced;
leading: 3px;
}
document
{
background-color: #cccccc;
}
.gradient
{
margin: auto;
width: 1200px;
height: 1000px;
blend-mode: layer;
/*
background is a gradient; colors, alphas, and ratios matrix
need to have the same column amount; there are 6 colors here.
*/
bg-gradient-type: radial; // radial or linear
bg-gradient-colors: [ 0xffffff, 0xf8f8f8, 0xe5e5e5, 0xdfdfdf, 0xd2d2d2, 0xcccccc ]; // white fading into light gray
bg-gradient-alphas: [ 1, 1, 1, 1, 1, 1 ]; // every color has 100% opacity
bg-gradient-ratios: [ 0, 80, 150, 170, 220, 255 ]; // 0-255 range, every color has a portion of the gradient
bg-gradient-matrix: [ 1200, 1000, 0, 0, 0 ]; // width (1200), height (1000), angle (0)
bg-gradient-spread: pad; // pad = no repeat
bg-gradient-interpolation: rgb;
bg-gradient-focal-point-ratio: 0; // 0 = center
}
form
{
@onSubmit
{
if ( gE ( "flikr" ).value == "Enter flickr ID" )
{
gE ( "error" ).text = "Please enter a valid user ID";
parent.childrenManager.jumpTo ( 'error' );
return false;
}
}
@onAction
{
/*
This interaction is called just before the form
submission. We clear the error message, grab the user id
from the form and format the RPC call to Flickr. The
Frontal form element which actually handle the
submission.
*/
parent.childrenManager.jumpTo ( 'processing' );
var userID = gE ( "user_id" ).value;
if ( ! userNameIDs.hasOwnProperty ( userID ) )
{
var isUserID = new RegExp ( "^[0-9]+@[A-Z][0-9]+$", "i" );
if ( ! isUserID.test ( userID ) )
{
// Try to look this up as a user name.
userNameIDs [ userID ] = null;
userIDLookup = new xmlRPC ( );
userIDLookup.addParameter ( { api_key: "fa0ccb3c5f57dc174a484baa4d0f4ba8", username: userID } );
userIDLookup.setMethodName ( 'flickr.people.findByUsername' );
userIDLookup.setServer ( 'http://api.flickr.com/services/xmlrpc/' );
userIDLookup.send ( function ( event, userIDLookup, userID )
{
/*
This it the callback for the XML RPC. If
it looks like we got an ID for the user
name then set it in our user name cache.
*/
if ( event.type == flash.events.Event.COMPLETE && ! userIDLookup.isFault )
{
var response = new XML ( userIDLookup.response );
userNameIDs [ userID ] = response.attribute ( "nsid" ).toString ( );
}
/*
Now resubmit the form. This time it will
get a hit in the user cache and either
use the found user ID or just try what
the user typed in.
*/
gE ( "getPhotosForm" ).submit ( );
}, userID );
return false;
}
}
else if ( userNameIDs [ userID ] != null )
{
userID = userNameIDs [ userID ];
}
if (userID != tmpID)
index = 1;
tmpID = userID;
dynamic.rpc = new xmlRPC ( );
dynamic.rpc.addParameter ( { api_key: "fa0ccb3c5f57dc174a484baa4d0f4ba8", user_id: userID, per_page: 10, page: index } );
request.data = dynamic.rpc.marshalRequest ( 'flickr.people.getPublicPhotos' );
}
@onError
{
/*
A networking or security error occurred. Show the
message.
*/
gE ( "error" ).text = event.text;
parent.childrenManager.jumpTo ( 'error' );
}
@onSuccess
{
/*
We got a response from Flickr. Let's parse the response
which will unmarshal the XML RPC result and store it in
the RPC object's response property.
*/
dynamic.rpc.parseResponse ( event.target.data );
if ( dynamic.rpc.isFault )
{
// Flickr returned an error like, e.g., "user not
// found." Display it.
//
gE ( "error" ).text = dynamic.rpc.response.faultString;
parent.childrenManager.jumpTo ( 'error' );
}
else
{
/*
The Flickr response is an XML document. Use Flash's
E4X classes to loop over all the photo elements and
create and img element for each one. The img elements
are added to the "images" div. Limit 10 images per hit.
*/
var response = new XML ( dynamic.rpc.response );
if ( response.photo.length() > 0 )
{
for ( var i = 0; i < response.photo.length(); i++ )
{
document.write ( '<img class="img" src="http://farm' + response.photo [ i ].attribute ( "farm" ) + '.static.flickr.com/' + response.photo [ i ].attribute ( "server" ) + '/' + response.photo [ i ].attribute ( "id" ) + '_' + response.photo [ i ].attribute ( "secret" ) + '.jpg" />', gE ( 'images' ) );
}
index += 1;
gE ( "tack" ).sS ( "display", "block" );
gE ( "help" ).sS ( "display", "block" );
parent.childrenManager.jumpTo ( 'form' );
}
else
{
gE ( "error" ).text = "User has no images";
parent.childrenManager.jumpTo ( 'error' );
}
}
}
}
.img
{
// Style our photos.
//
shadow-blur: 4;
shadow-strength: 0.5;
shadow-distance: 2;
allow-smoothing: true;
double-click-enabled: true; // Double-clicks must be enabled.
+onMatch
{
/*
Use the onMatch action as a convenient place to apply
some random styles to the images. This action is called
whenever an element matches this ruleset's selector. That
is, it's called whenever an img element is added to the
document.
*/
sS ( "left", Math.round ( gE ( "stage" ).width * Math.random ( ) * 0.65 ) ); // image spread value from the center
sS ( "top", Math.round ( gE ( "stage" ).height * Math.random ( ) * 0.65 ) ); // middle. Value is set to 65%.
sS ( "rotation", Math.round ( Math.random ( ) * 90 - 45 ) );
sS ( "scale", Math.random ( ) * .4 + 0.2 );
}
@onMouseDown
{
// We're clicked. Store the click point.
//
currentElem = this;
sS ( "z-index", zIndex++ );
resetDepths ( );
clickPt = new flash.geom.Point ( event.stageX, event.stageY );
var tack = gE ( "tack" ).movie;
var p = tack.localToGlobal ( new flash.geom.Point ( 2.5, 2.5 ) );
if ( movie.hitTestPoint ( p.x, p.y, true ) )
{
/*
The tack is on our photo. Calculate and store some
useful information. Also set our movie's registration
point at the tack's position so that an scale or
rotation operations center around it. Finally, enable
the onMouseMoveRaw interaction on the images div. (We
don't leave this enabled for performance.)
*/
tackPt = p;
clickScale = gS ( "scale" );
clickRotation = gS ( "rotation" );
clickDist = flash.geom.Point.distance ( tackPt, clickPt );
clickAng = Math.atan2 ( clickPt.y - tackPt.y, clickPt.x - tackPt.x ) + Math.PI;
p = movie.globalToLocal ( p );
sS ( "movie-registration-x", p.x );
sS ( "movie-registration-y", p.y );
gE ( "images" ).applyInteraction ( flash.events.MouseEvent.MOUSE_MOVE, gE ( "images" ).movie );
}
else
{
/*
We're dragging the photo. We set the tack point to
null to indicate this. See the notes about the tack
below to understand why we disable rendering.
*/
tackPt = null;
sS ( "disable-rendering", true );
movie.startDrag ( );
}
}
@onDoubleClick
{
// Destroy the photo on double click.
//
destroy ( );
}
@onMouseUpAnywhere
{
if ( this == currentElem )
{
/*
See the notes about the tack below to understand why
we disable rendering and call synchStyles.
*/
currentElem = null;
movie.stopDrag ( );
sS ( "disable-rendering", false );
synchStyles ( );
}
}
}
#images
{
/*
Giving the images div a background color causes its movieclip to
have content and so telling Flash to send it mouse move events.
We could set the background-alpha to 0 if we want it invisible.
*/
background-color: white;
background-alpha: 0;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
/*
We use onMouseMoveRaw so that events still are passed through to
the individual images.
*/
@onMouseMoveRaw
{
/*
We handle the mouse move event on the images div so that
if the mouse rolls out of the image, it still is receives
events. That is, if the onMouseMove interaction were on
the image then it would stop firing if the mouse were
quickly jerked off the image.
*/
if ( currentElem == null )
{
/*
Remove the interaction when its not needed. This is
a good practice to help peformance.
*/
removeInteraction ( flash.events.MouseEvent.MOUSE_MOVE, movie );
}
else if ( tackPt != null )
{
// Calculate the new scale and rotation.
//
var movie = currentElem.movie;
var mousePt = movie.localToGlobal ( new flash.geom.Point ( movie.mouseX, movie.mouseY ) );
var scale = clickScale * ( flash.geom.Point.distance ( tackPt, mousePt ) / clickDist );
currentElem.sS ( "scale", scale );
var ang = Math.atan2 ( mousePt.y - tackPt.y, mousePt.x - tackPt.x ) + Math.PI;
currentElem.sS ( "rotation", clickRotation + 360 * ( ang - clickAng ) / ( 2 * Math.PI ) );
gE ( "images" ).needsRender = true;
}
}
}
#tack
{
shadow-blur: 4;
shadow-strength: 0.25;
shadow-distance: 2.5;
@onMouseDown
{
/*
Start dragging the tack. We set the style
disable-render during this phase so any render events
during the drag are ignored for it. Otherwise, the
tack would be rendered back at its starting point.
*/
sS ( "disable-rendering", true );
movie.startDrag ( );
gE("texter").sS("display", "none");
}
@onMouseUpAnywhere
{
/*
If we used onMouseUp then we'd only get the mouse up
event if it occurred over the tack so we use
onMouseUpAnywhere. We also re-enable rendering and then
call synchStyles which will set the element's styles
based on the movie clip's current properties. Otherwise
the next render would be based on the styles related to
the position when the drag started.
*/
movie.stopDrag ( );
sS ( "disable-rendering", false );
synchStyles ();
// Display the help text if the dot is back inside the container
//
if ( movie.hitTestObject ( gE ( "holder" ).movie ) ) gE ( "texter" ).sS ( "display", "normal" );
}
}
#submitButton
{
// position, structure
float: left;
margin-left: 15px;
width: 60px;
height: 20px;
padding-top: 4px;
// colors, gray glow
background-color: #ffffff;
is-link: true;
glow-blur: 14;
glow-color: #444444;
glow-strength: .25;
@onClick
{
gE ( "getPhotosForm" ).submit();
}
@onRollOver
{
gE ( 'submitButton' ).sA('src','assets/images/flikr_sub_h.png');
}
@onRollOut
{
gE ( 'submitButton' ).sA('src','assets/images/flikr_sub_n.png');
}
}
#submitButton:active
{
glow-strength: 0;
}
.status
{
padding-left: 30px;
padding-top: 30px;
}
.stage
{
width: 100%;
height: 100%;
top: 0px;
left: 0px;
}
]]></style>
<div class="gradient" />
<div id="stage" class="stage">
<div id="images" />
<!--
div containing the searchform and status messages
-->
<div style="layout: stack; top: 0px; left: 0px;">
<manager id="mgr" style="hide-unselected: true;" />
<form name="form" id="getPhotosForm" action="http://api.flickr.com/services/xmlrpc/" method="post" class="status">
<input id="flikr" tabIndex="1" type="text" name="user_id" style="margin-top: 1px; float: left;">Enter flickr ID</input>
<img id="submitButton" tabIndex="2" src="assets/images/flikr_sub_n.png" />
<input type="submit" style="display: none;" />
</form>
<div name="processing" id="processing" class="status">processing...
<text class="frMarker" mgrId="mgr" elemNdx="1">cancel</text>
</div>
<div name="error" class="status">
<text id="error"/>
<text class="frMarker" mgrId="mgr" elemNdx="1">new search</text>
</div>
</div>
<div id="help" style="display: none; left: 31px; top: 94px;">
<img id="holder" src="assets/images/flikr_holder.png" />
<text id="texter" style="left: -3px; top: 41px; width: 175px; text-align: justify;"><![CDATA[Move the dot over an image, then click and drag the image to scale and rotate; double-click to delete.<br/>]]></text>
</div>
<img id="tack" style="left: 39px; top: 102px; display: none;" src="assets/images/flikr_dot.png" />
<!--
frontal credit
-->
<text style="font-size: 12px; left: 30px; top: 95%; padding-bottom: 5px;" class="frLink" href="http://frontalcode.com" target="_blank"><![CDATA[Created w/ Frontal]]></text>
</div>