288 lines
8.2 KiB
JavaScript
288 lines
8.2 KiB
JavaScript
|
dojo.provide("demos.skew.src");
|
||
|
|
||
|
dojo.require("demos.skew.src.Image");
|
||
|
|
||
|
dojo.require("dojo.NodeList-fx");
|
||
|
dojo.require("dojo.fx.easing");
|
||
|
dojo.require("dojox.widget.Dialog");
|
||
|
dojo.require("dojox.layout.RadioGroup");
|
||
|
dojo.require("dojox.analytics.Urchin");
|
||
|
|
||
|
(function($){
|
||
|
|
||
|
var _stuffMoving = false,
|
||
|
_started = false,
|
||
|
_stalltime = 650, // ms
|
||
|
_doneAnim = null,
|
||
|
_needed = null,
|
||
|
_loaded = [],
|
||
|
_connects = [],
|
||
|
profileWidget = null,
|
||
|
stack = null,
|
||
|
timer = null,
|
||
|
_profiletimer = null
|
||
|
;
|
||
|
|
||
|
var _doneAnim = function(){
|
||
|
|
||
|
$.fadeOut({
|
||
|
// fade out the overlay
|
||
|
node: "overlay",
|
||
|
duration: 300,
|
||
|
onEnd: function(){
|
||
|
// then make our image surface 240px, and fade it in
|
||
|
$.animateProperty({
|
||
|
node:"imageContainer",
|
||
|
properties: {
|
||
|
height: 240,
|
||
|
opacity:1
|
||
|
},
|
||
|
// with teh sexy
|
||
|
easing: $.fx.easing.backOut,
|
||
|
duration:420,
|
||
|
// wait for the fadeout above to finish
|
||
|
delay:600,
|
||
|
onEnd: function(){
|
||
|
// hide the actual overlay so you can click underneath it
|
||
|
$.style("overlay","display","none");
|
||
|
_started = true;
|
||
|
// take all the elements with "startsHidden" class, and
|
||
|
// set them up, fade them in, and remove hidden class
|
||
|
$.query(".startsHidden")
|
||
|
.style("opacity", "0")
|
||
|
.removeClass("startsHidden")
|
||
|
.fadeIn().play(500);
|
||
|
}
|
||
|
}).play();
|
||
|
}
|
||
|
}).play();
|
||
|
|
||
|
};
|
||
|
|
||
|
// onShow result, it no timer was running (see later)
|
||
|
var updateProfile = function(datawidget){
|
||
|
//if(!_started){ return; }
|
||
|
_stuffMoving = true;
|
||
|
// conveniently, later, we stored a reference to our avatar (RadioGroupSlide child)
|
||
|
// in the Image widget.
|
||
|
stack.selectChild(datawidget._avatar);
|
||
|
profileWidget.setData(datawidget._userInfo);
|
||
|
}
|
||
|
|
||
|
var _oneBroke = function(n,e){
|
||
|
_gotOne(n,e);
|
||
|
}
|
||
|
|
||
|
// the handler for our image onloader.
|
||
|
// FIXME: if we get a 404, we'll never finish ...
|
||
|
var _gotOne = function(n,e){
|
||
|
_loaded.push(n);
|
||
|
if(_loaded.length >= $._neededImages){
|
||
|
$.forEach(_connects, $.disconnect);
|
||
|
_doneAnim();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// the onLoad function
|
||
|
var init = function(){
|
||
|
|
||
|
// tracking demo:
|
||
|
var u = new dojox.analytics.Urchin({
|
||
|
acct: "UA-3572741-1",
|
||
|
GAonLoad: function(){
|
||
|
this.trackPageView("/demos/skew");
|
||
|
}
|
||
|
});
|
||
|
|
||
|
$.style("whoNode","opacity", 0);
|
||
|
|
||
|
// see, the page "degrades" ;) . This contributor listing page is only a link to
|
||
|
// http://dojo.jot.com/ContrbutorListing
|
||
|
$.query("a[href^=http://dojo.jot]").forEach(function(n){
|
||
|
n.parentNode.innerHTML = n.innerHTML;
|
||
|
});
|
||
|
|
||
|
// create a "help" dialog out of the node in the page.
|
||
|
var dialog = new dojox.widget.Dialog({
|
||
|
dimensions:[640,420]
|
||
|
},"dialog");
|
||
|
dialog.startup();
|
||
|
// setup a way to show it
|
||
|
$.connect($.byId("helper"), "onclick", dialog, "show");
|
||
|
|
||
|
// set it all off: grab some data from a remote file, and create
|
||
|
// the interface
|
||
|
$.xhrGet({
|
||
|
url:"../resources/users.json",
|
||
|
handleAs:"json",
|
||
|
load:function(data){
|
||
|
|
||
|
var labelNode = $.byId("whoNode");
|
||
|
var _lastNode = null;
|
||
|
|
||
|
profileWidget = new profile.Data({},"profileData");
|
||
|
|
||
|
// create the region where the avatars will live.
|
||
|
stack = new dojox.layout.RadioGroupSlide({
|
||
|
style:"width:180px; height:200px",
|
||
|
// FIXME: when did StackContainer start setting relative explicitly?
|
||
|
_setupChild: function(/*Widget*/ page){
|
||
|
$.style(page.domNode,{
|
||
|
display:"none",
|
||
|
position:"absolute",
|
||
|
overflow:"hidden"
|
||
|
})
|
||
|
return page; // dijit._Widget
|
||
|
}
|
||
|
},"stack");
|
||
|
|
||
|
// iterate over each of the returned committers, setting up the canvas
|
||
|
$.forEach(data.committers,function(user, i){
|
||
|
|
||
|
// create an Image in the container, and store the user profile data
|
||
|
// in it's instance.
|
||
|
var im = new image.Skewed({
|
||
|
// use a default square.png if no imgUrl found.
|
||
|
imgUrl: user.imgUrl || "images/square.png",
|
||
|
value: user.name
|
||
|
});
|
||
|
$.mixin(im,{ _userInfo: user });
|
||
|
|
||
|
// create a reflection-less scale thumbnail (color) in a div
|
||
|
var node = $.doc.createElement('div');
|
||
|
stack.containerNode.appendChild(node);
|
||
|
node.innerHTML = "<img src='imageReflect.php?spread=0.01&thumbsize=165&src=" + im.imgUrl + "' />";
|
||
|
|
||
|
// and make it a child of our RadioGroupSlide
|
||
|
var avatar = new dijit.layout.ContentPane({
|
||
|
id: im.id + "avatar",
|
||
|
slideFrom:"top"
|
||
|
}, node);
|
||
|
|
||
|
// mix a reference to the child of the stackContianer in the image widget
|
||
|
$.mixin(im, { _avatar: avatar });
|
||
|
|
||
|
// store a ref to our "center" image
|
||
|
if(i === 0){ _lastNode = im; }
|
||
|
|
||
|
// either add this image to the beginning or append to the end. alternate.
|
||
|
if(i % 2 == 0){
|
||
|
$.byId("imageContainer").appendChild(im.domNode);
|
||
|
}else{
|
||
|
$.place(im.domNode, "imageContainer", "first");
|
||
|
}
|
||
|
|
||
|
});
|
||
|
// this will setup all the children we _just_ added
|
||
|
stack.startup();
|
||
|
|
||
|
// turn the container holding all the image widgets into the interface
|
||
|
var ic = new image.Container({
|
||
|
// for performance (it's a big list/lot of images)
|
||
|
offOpacity:1,
|
||
|
onShow: function(widget){
|
||
|
// onShow fires _every_ time an image is "centered" visually (no skew)
|
||
|
// so for UX, we'll defer the "updateProfile()" call until some delay,
|
||
|
if(timer){ clearTimeout(timer); }
|
||
|
timer = setTimeout($.partial(updateProfile, widget), _stalltime);
|
||
|
// but still update one label from our widget data
|
||
|
labelNode.innerHTML = widget.value + "";
|
||
|
$.anim("profileArea",{ opacity:0 }, 175);
|
||
|
},
|
||
|
// should be lower, but i want to stage opacity on the edges rather
|
||
|
// than display:none, so for now this looks better.
|
||
|
visibleItems: 42,
|
||
|
// tweak as needed
|
||
|
spacing:25,
|
||
|
angle:10
|
||
|
},"imageContainer");
|
||
|
|
||
|
// find every image in this container, and connect an onload connect to it
|
||
|
// when each image fires it's onload, the _gotOne function above is alerted
|
||
|
var _needed = $.query("img", "imageContainer");
|
||
|
$._neededImages = Number(_needed.length);
|
||
|
_needed.forEach(function(n,i){
|
||
|
_connects.push($.connect(n, "onload", $.partial(_gotOne, n)));
|
||
|
_connects.push($.connect(n, "onerror", $.partial(_oneBroke, n)));
|
||
|
// if you don't touch the .src attribute _after_ connecting to onload, it
|
||
|
// won't fire in weird conditions.
|
||
|
if($.isIE){ n.src = n.src; }
|
||
|
});
|
||
|
|
||
|
ic.startup();
|
||
|
_lastNode.center(); // center the first node (from above creating image widgets)
|
||
|
|
||
|
// resize the image container when the window does, it's fluid
|
||
|
$.connect(window, "onresize", ic, "resize");
|
||
|
|
||
|
// make it small, so we can wipe it in
|
||
|
$.style("imageContainer",{ height:"1px", opacity:0 });
|
||
|
|
||
|
}
|
||
|
})
|
||
|
};
|
||
|
|
||
|
$.declare("profile.Stalker", dijit._Widget, {
|
||
|
|
||
|
});
|
||
|
|
||
|
$.declare("profile.Data", dijit._Widget, {
|
||
|
// summary: A simple widget we probably don't even need.
|
||
|
constructor: function(){
|
||
|
var $$ = $.byId;
|
||
|
this.nodeReferences = {
|
||
|
"location" : $$("proLocation"),
|
||
|
"website" : $$("proWebsite"),
|
||
|
"employer" : $$("proEmployer"),
|
||
|
"title" : $$("proRole")
|
||
|
}
|
||
|
},
|
||
|
|
||
|
setData: function(data){
|
||
|
var node = this.nodeReferences;
|
||
|
|
||
|
for(var i in node){
|
||
|
if(i in data){
|
||
|
$.style(node[i],"display","");
|
||
|
var txt = (
|
||
|
i == "website" ?
|
||
|
"<a href='" + data[i] + "'>" + data[i] + "</a><br>" :
|
||
|
data[i]
|
||
|
);
|
||
|
node[i].innerHTML = txt;
|
||
|
}else{
|
||
|
$.style(node[i],"display","none");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// this is really a list of potential aliases, so start clean:
|
||
|
var nick = "";
|
||
|
if("handle" in data){
|
||
|
// add the "handle" attribute
|
||
|
nick += '"' + data["handle"] + '"';
|
||
|
}
|
||
|
if("irc" in data && data["irc"] !== data["handle"]){
|
||
|
// add the "irc" attribute, if it is different from the "handle" attribute
|
||
|
nick += ' "' + data["irc"] + '"';
|
||
|
}
|
||
|
$.byId("proAliases").innerHTML = nick;
|
||
|
|
||
|
// fade and swipe in the content.
|
||
|
// FIXME: weirdness w/ IE7 and no respecting -42 marginLegf
|
||
|
$.anim("profileArea",{
|
||
|
opacity:{ start:0, end: 0.99 },
|
||
|
paddingLeft:{ start:72, end:0 }
|
||
|
}, 520, $.fx.easing.bounceOut);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
var newp = function(){
|
||
|
// IE6 branch of this demo
|
||
|
window.location.href = "http://" + (confirm("Hi IE6 user! Is it 2008?") ? "webkit.org" : "mozilla.org") + "/";
|
||
|
}
|
||
|
|
||
|
// setup our branch launch: ;)
|
||
|
$.addOnLoad(($.isIE < 7 ? newp : init));
|
||
|
|
||
|
})(dojo);
|