/*
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
Author: Sam Tsvilik
Version: 4.0 Beta
Last Modified: 08/29/2009
*/
(function($) {
//Converts XML DOM to JSON
//Helper functions
var util = {
isIE: function(){ return (+"\0"===0); },
isStr: function(o) { return typeof(o) === "string"; },
isFn: function(o) { return typeof(o) === "function"; },
isDef: function(o) {return (typeof(o) !== "undefined"); },
isArr: function(o) { return o instanceof Array; },
isInt: function(o) { return o instanceof Number && !isNaN(o); },
isNum: function(s) {
var out = false;
if(util.isStr(s)) {
var pattern = /^((-)?([0-9]*)((\.{0,1})([0-9]+))?$)/;
out = pattern.test(s);
}
return out;
},
isXNode: function(o) { return (typeof(o) === "object" && this.isDef(o.nodeName)); },
isNodeSet: function(o) { return o instanceof INodeSet; },
//Alters attribute and collection names to comply with JS
trim: function(str) {
var out = str;
if(this.isStr(str)) {
out = str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
}
return out;
},
formatName: function(name) {
var tName = this.trim(String(name));
return tName;
}
};
var XMLSerializer = {
//Creates an XMLDomDocument instance
newDocument: function(rootTagName, namespaceURL) {
if (!rootTagName) rootTagName = "";
if (!namespaceURL) namespaceURL = "";
if (document.implementation && document.implementation.createDocument) {
// This is the W3C standard way to do it
return document.implementation.createDocument(namespaceURL, rootTagName, null);
} else { // This is the IE way to do it
// Create an empty document as an ActiveX object
// If there is no root element, this is all we have to do
var doc = new ActiveXObject("MSXML2.DOMDocument");
// If there is a root tag, initialize the document
if (rootTagName) {
// Look for a namespace prefix
var prefix = "";
var tagname = rootTagName;
var p = rootTagName.indexOf(':');
if (p !== -1) {
prefix = rootTagName.substring(0, p);
tagname = rootTagName.substring(p+1);
}
// If we have a namespace, we must have a namespace prefix
// If we don't have a namespace, we discard any prefix
if (namespaceURL) {
if (!prefix) prefix = "a0"; // What Firefox uses
} else prefix = "";
// Create the root element (with optional namespace) as a
// string of text
var text = "<" + (prefix?(prefix+":"):"") + tagname +
(namespaceURL
?(" xmlns:" + prefix + '="' + namespaceURL +'"')
:"") +
"/>";
// And parse that text into the empty document
doc.loadXML(text);
}
return doc;
}
},
//Recursively converts JSON object to an XML node
objToNode: function(curNode, obj) {
var subElement, val, newNode;
if(util.isDef(curNode) && util.isDef(obj)) {
for(subElement in obj) {
if(obj.hasOwnProperty && obj.hasOwnProperty(subElement)) {
val = obj[subElement];
if(subElement.indexOf("@") !== -1) {
curNode.setAttribute(subElement.replace('@',''), val);
} else if(subElement === "$comments") {
if(!!val.length) {
var c = 0, clen = val.length-1, cc;
do {
cc = val[c];
curNode.appendChild(this.createComment(cc));
} while(c++ < clen);
}
} else if(util.isNodeSet(val)) {
var n = 0, nlen = val.length-1, nn;
do {
nn = val[n];
if(!!nn.ns) {
if(util.isDef(this.createElementNS)) {
newNode = curNode.appendChild(this.createElementNS(nn.ns, subElement));
} else {
newNode = curNode.appendChild(this.createNode(1, subElement, nn.ns));
}
} else {
newNode = curNode.appendChild(this.createElement(subElement));
}
if(!!nn.Text) { newNode.appendChild(util.isDef(nn.hasCDATA)?this.createCDATASection(nn.Text):this.createTextNode(nn.Text)); }
XMLSerializer.objToNode.call(this, newNode, nn);
} while(n++ < nlen);
}
}
}
}
}
};
//Base child element
var IChild = function(parent) {
this.parent = parent || null;
};
//Root Node Class
var IRoot = function(name) {
this.nodeName = name || "";
this.ns = "";
};
//Node Class
var INode = function() {
var parent = null, name = null, value = null;
switch(arguments.length) {
case 1: name = arguments[0]; break;
case 2: parent = arguments[0]; name = arguments[1]; break;
case 3: parent = arguments[0]; name = arguments[1]; value = arguments[2]; break;
default: name = "noname";
}
IRoot.apply(this, [name]);
IChild.apply(this, [parent]);
this.Text = value || "";
};
//Node Object - can have children
var INodeSet = function() {
this.length = 0;
this.push = function(elem){ Array.prototype.push.call( this, elem ); };
this.sort = function() { Array.prototype.sort.apply( this, arguments ); };
};
INodeSet.prototype = {
getNodesByAttribute: function(attr, obj){
var out = [];
if(!!this.length && util.isStr(attr) && util.isDef(obj)) {
var n = this.length, node, aval;
while(n--) {
node = this[n]; aval = node[attr];
if(util.isDef(aval) && aval === obj) { out.unshift(node); }
}
}
return (!out.length)?null:out;
},
getNodesByValue: function(obj){
var out = [];
if(!!this.length && util.isDef(obj)) {
var n = this.length, node;
while(n--) {
node = this[n];
if(node.Text === obj) { out.unshift(node); }
}
}
return (!out.length)?null:out;
},
contains: function(attr, obj){
var out = false;
if(!!this.length && util.isStr(attr) && util.isDef(obj)) {
var n = this.length, node, aval;
while(n--) {
node = this[n]; aval = node[attr];
if(util.isDef(aval) && aval === obj) { out = true; break; }
}
}
return out;
},
indexOf: function(){
var out = -1, attr, obj;
if(!!this.length) {
var n = this.length, node, val;
switch(arguments.length) {
case 1: obj = arguments[0];
while(n--) {
node = this[n]; val = node.val();
if(util.isDef(val) && val === obj) { out = n; break; }
}
break;
case 2: attr = arguments[0]; obj = arguments[1];
while(n--) {
node = this[n]; val = node[attr];
if(util.isDef(val) && val === obj) { out = n; break; }
}
break;
}
}
return out;
},
sortByAttribute: function(attr, dir){
if(!!this.length && util.isStr(attr)) {
this.sort(function(a,b) {
var _a = (a.attr(attr)),
_b = (b.attr(attr));
_a = util.isNum(_a)?parseFloat(_a):_a;
_b = util.isNum(_b)?parseFloat(_b):_b;
var _out = (_a<_b)?-1:(_b<_a)?1:0;
_out = (util.isDef(dir) && dir.toLowerCase() === "desc")?(0-_out):_out;
return _out;
});
}
},
sortByValue: function(dir){
if(!!this.length) {
this.sort(function(a,b) {
var _a = (a.Text),
_b = (b.Text);
_a = util.isNum(_a)?parseFloat(_a):_a;
_b = util.isNum(_b)?parseFloat(_b):_b;
var _out = (_a<_b)?-1:(_b<_a)?1:0;
_out = (util.isDef(dir) && dir.toLowerCase() === "desc")?(0-_out):_out;
return _out;
});
}
},
sortByChildNode: function(nodeName, dir){
if(!!this.length && util.isStr(nodeName)) {
this.sort(function(a,b) {
var _a = a[nodeName],
_b = b[nodeName];
_a = (util.isDef(_a) && !!_a.length)?_a[0].Text:null;
_b = (util.isDef(_b) && !!_b.length)?_b[0].Text:null;
//---------------------------------------------------//
_a = util.isNum(_a)?parseFloat(_a):_a;
_b = util.isNum(_b)?parseFloat(_b):_b;
var _out = (_a<_b)?-1:(_b<_a)?1:0;
_out = (util.isDef(dir) && dir.toLowerCase() === "desc")?(0-_out):_out;
return _out;
});
}
},
first: function() {
var out = null;
if(!!this.length) { out = this[0]; }
return out;
},
last: function() {
var out = null;
if(!!this.length) { out = this[this.length-1]; }
return out;
}
};
//Engine Factory
var XMLObjectifierEngine = (function() {
var _public = {
makeNodeSet: function() {
var node = new INodeSet();
return node;
},
makeNode: function(parent, obj) {
var name = obj.localName||obj.baseName;
name = util.formatName(name);
var node = new INode(parent, name);
node.ns = obj.prefix || "";
this.setAttributes(node, obj);
return node;
},
setAttributes: function(obj, xnode) {
if(util.isDef(xnode) && !!xnode.attributes.length) {
var a = xnode.attributes.length-1, attName = null, objParent = null;
do { //Order is irrelevant (speed-up)
attName = "@"+xnode.attributes[a].name;
obj.attr(attName, xnode.attributes[a].value);
} while(a--);
}
},
run: function(parent, xobj) {
var curChild, newNode;
if(util.isDef(parent) && util.isDef(xobj)) {
if(xobj.hasChildNodes()) {
var nodesLen = xobj.childNodes.length-1, n = 0;
do {
curChild = xobj.childNodes[n];
switch(curChild.nodeType) {
case 1: //Node
//Create a single node
newNode = _public.makeNode(parent, curChild);
if(util.isFn(this.decorator)) {
var _dout = this.decorator.call(newNode);
//Skip node if decorator returns false
if(_dout === false) { continue; }
}
if(!!newNode) {
//Add child node to parent
parent.appendChild(newNode);
//Recursive call if node contains children
if(curChild.hasChildNodes()){ _public.run.apply(this, [newNode, curChild]); }
}
break;
case 3: //Text Value
parent.val(util.trim(curChild.nodeValue));
break;
case 4: //CDATA
parent.hasCDATA = true;
parent.val(util.isDef(curChild.text)?util.trim(curChild.text):util.trim(curChild.nodeValue));
break;
case 8: //Comments
if(!util.isDef(this.noComments) || !this.noComments) {
if(!util.isDef(parent.$comments)) { parent.$comments = []; }
parent.$comments.push(util.trim(curChild.nodeValue));
}
break;
}
} while(n++ < nodesLen);
}
}
},
init: function(xobj, opt) {
opt = opt || {noComments: true};
if(util.isStr(xobj)){
xobj = this.textToXML(xobj);
} else if(util.isXNode(xobj)){ xobj = xobj;
} else { xobj = null; }
//If invalid xml object - abort
if(!xobj){ return null; }
//Determine a document root node
var xroot = (xobj.nodeType === 9)?xobj.documentElement:(xobj.nodeType === 11)?xobj.firstChild:xobj;
//Root Node
var root = new IRoot(xroot.nodeName);
if(util.isFn(opt.decorator)) {
opt.decorator.call(root);
}
//If init argument is just a text or CDATA return value
if(xobj.nodeType === 3 || xobj.nodeType === 4) {
return xobj.nodeValue;
}
//Begins a recursive process to build out a JSON structure
this.run.apply(opt, [root, xroot]);
this.setAttributes(root, xroot);
return root;
},
textToXML: function(strXML) {
var xmlDoc = null;
try {
xmlDoc = (util.isIE())?new ActiveXObject("MSXML2.DOMDocument"):new DOMParser();
xmlDoc.async = false;
} catch(e) {throw new Error("XML Parser could not be instantiated");}
var out = null, isParsed = true;
if(util.isIE()) {
isParsed = xmlDoc.loadXML(strXML);
out = (isParsed)?xmlDoc:false;
} else {
out = xmlDoc.parseFromString(strXML, "text/xml");
isParsed = (out.documentElement.tagName !== "parsererror");
}
if(!isParsed){throw new Error("Error parsing XML string");}
return out;
}
};
return _public;
})();
IRoot.prototype = {
typeOf: "xmlObjectifier",
attr: function() {
var out, attr, val;
if(!!arguments.length) {
switch(arguments.length) {
case 1: attr = util.formatName(arguments[0]);
val = this["@"+attr]||this[attr];
if(util.isDef(val) && !util.isArr(val)) { out = val; } break;
case 2: attr = util.formatName(arguments[0]);
val = arguments[1];
if(util.isStr(attr)) { this[(/^@/.test(attr))?attr:"@"+attr] = val; out = this;} break;
}
}
return out;
},
find: function(sel) {
var out = null, tokens, token, tokenOnly;
if(util.isStr(sel)) {
var curMatch, subNode;
var condMatch = /\[(\d+|@\w+(=\w+)?)\]/, conditionStr, parts, partA, partB;
var rx = /(?=\.)?([A-Za-z\-]+(\[(\d+|@\w+(=\w+)?)\])?)/g;
var attrMatch = /^@\w+/, attr;
//If selector is an attribute, then just find attribute and return it
if(sel.match(attrMatch)) {
attr = sel.match(attrMatch)[0];
return this.attr(attr);
}
tokens = sel.match(rx);
if(!!tokens.length) {
var t = 0, tLen = tokens.length-1;
do {
token = tokens[t];
tokenOnly = token.match(/[A-Za-z\-]+/)[0];
curMatch = !!curMatch?(util.isArr(curMatch)?curMatch[0]:curMatch)[tokenOnly]:this[tokenOnly];
if(!curMatch) { break; }
conditionStr = !!token.match(condMatch) && token.match(condMatch)[0].replace("[","").replace("]","");
if(conditionStr && !!conditionStr.length) {
if(conditionStr.indexOf("=")!==-1) {
parts = conditionStr.split("=");
partA = util.trim(parts[0]); partB = util.trim(parts[1]);
if(partA.indexOf("@")!==-1) {
attr = partA;
curMatch = curMatch.getNodesByAttribute(attr, partB);
} else {
subNode = util.trim(curMatch[partA]);
if(subNode) {
curMatch = subNode.getNodesByValue(partB);
}
}
} else if(util.isNum(conditionStr)){
curMatch = curMatch[parseInt(conditionStr, 10)];
}
}
} while(t++ < tLen);
out = curMatch;
}
}
return out;
},
addComment: function(comment) {
if(util.isStr(comment)) {
if(!util.isDef(this.$comments)) { this.$comments = []; }
this.$comments.push(comment);
}
return this;
},
val: function(v) {
var out = this;
if(util.isDef(v)) {
this.Text = v;
} else { out = this.Text; }
return out;
},
toXML: function() {
var root = XMLSerializer.newDocument(this.nodeName, this.ns);
XMLSerializer.objToNode.call(root, root.documentElement, this);
return root;
},
toString: function() {
var root = this.toXML();
var out = "";
if(util.isDef(root.xml)) {
out = root.xml;
} else if(util.isDef(XMLSerializer)){
var serializer = new window.XMLSerializer();
out = serializer.serializeToString(root);
}
return out;
},
appendChild: function(nodeClassInst) {
if(util.isDef(nodeClassInst) && nodeClassInst instanceof INode) {
nodeClassInst.parent = this;
if(!util.isDef(this[nodeClassInst.nodeName])) { this[nodeClassInst.nodeName] = XMLObjectifierEngine.makeNodeSet(); }
this[nodeClassInst.nodeName].push(nodeClassInst);
}
}
};
INode.prototype = {
attr: IRoot.prototype.attr,
val: IRoot.prototype.val,
find: IRoot.prototype.find,
addComment: IRoot.prototype.addComment,
appendChild: IRoot.prototype.appendChild
};
//All Public members
var _publicMapping = {
xmlToJSON: function(xdoc, opt) {
return XMLObjectifierEngine.init(xdoc, opt);
},
//Converts Text to XML DOM
textToXML: XMLObjectifierEngine.textToXML,
//Classes exposed for prototype extensibility
xmlObjectifier: {
RootClass: IRoot, //Root node only
NodeClass: INode, //Node element
NodeSetClass: INodeSet //NodeSet class
}
};
if(util.isDef($)) {
$.extend ( _publicMapping );
} else {
window.XMLObjectifier = _publicMapping;
}
})((typeof(jQuery) !== "undefined") && jQuery || undefined);
function setupHalloweenScrolbar(callback){
//scrollpane parts
var scrollPane = $('#halloween-coverflow');
var scrollContent = $('#halloween-scroll-content');
var scrollBarDom = $('#halloween-scroll-bar');
var itemsWidth = scrollContent.innerWidth() - scrollPane.outerWidth();
//build slider
//http://jquery-ui.googlecode.com/svn/trunk/demos/slider/side-scroll.html
var scrollbar = scrollBarDom.slider({
//value:1,
//min: 1,
//max: itemsWidth,
//animate: 'fast',
slide:function(e, ui){
//mylogger.log(ui.value);
if( scrollContent.width() > scrollPane.width() ){ scrollContent.css('margin-left', Math.round( ui.value / 100 * ( scrollPane.width() - scrollContent.width() )) + 'px'); }
else { scrollContent.css('margin-left', 0); }
}
//change:function(e, ui){
// scrollContent.animate({marginLeft:Math.round( ui.value / 100 * ( scrollPane.width() - scrollContent.width() ))}, 1000);
//}
// stop: function (event, ui) {
// scrollContent.animate({'margin-left' : ui.value * -1}, 500);
// },
// slide: function (event, ui) {
//mylogger.log(ui.value);
// scrollContent.css('margin-left', ui.value * -1);
// }
});
//append icon to handle
var handleHelper = scrollbar.find('.ui-slider-handle')
.mousedown(function(){
scrollbar.width( handleHelper.width() );
})
.mouseup(function(){
scrollbar.width( '100%' );
})
.append('')
.wrap('
').parent();
//$('.sortbar').click(function(){
//alert('fpp');
// scrollBarDom.slider('value' ,scrollBarDom.slider('value')+10 );
//});
//change overflow to hidden now that slider handles the scrolling
scrollPane.css('overflow','hidden');
//size scrollbar and handle proportionally to scroll distance
function sizeScrollbar(){
var remainder = scrollContent.width() - scrollPane.width();
var proportion = remainder / scrollContent.width();
var handleSize = scrollPane.width() - (proportion * scrollPane.width());
scrollbar.find('.ui-slider-handle').css({
width: handleSize,
'margin-left': -handleSize/2
});
handleHelper.width('').width( scrollbar.width() - handleSize);
}
//reset slider value based on scroll content position
function resetValue(){
var remainder = scrollPane.width() - scrollContent.width();
var leftVal = scrollContent.css('margin-left') == 'auto' ? 0 : parseInt(scrollContent.css('margin-left'));
var percentage = Math.round(leftVal / remainder * 100);
scrollbar.slider("value", percentage);
}
//if the slider is 100% and window gets larger, reveal content
function reflowContent(){
var showing = scrollContent.width() + parseInt( scrollContent.css('margin-left') );
var gap = scrollPane.width() - showing;
if(gap > 0){
scrollContent.css('margin-left', parseInt( scrollContent.css('margin-left') ) + gap);
}
}
//change handle position on window resize
$(window)
.resize(function(){
resetValue();
sizeScrollbar();
reflowContent();
});
//init scrollbar size
setTimeout(sizeScrollbar,10);//safari wants a timeout
return true;
}
function loadHalloweenAlbums(scrollContentRef, callback){
//Let's fetch data.xml using jQuery ajax request
$.ajax({
type: "GET",
url: "http://jamtopia.com/images/uploads/obituary.xml",
//url: "http://jamtopia.com/javascript/proxy.php",
dataType: "text", //Make sure that you specify the type of file you expecting (XML)
complete: function(data) {
var rawSource = data.responseText;
rawSource = rawSource.replace(/&/g, "&");
xmlSource = $.textToXML(rawSource);
var json = $.xmlToJSON(xmlSource); //Please notice that we use responseXML here which is DOMDocument object
// LOOP THROUGH COVERS AND CORRRECT BAND NAMES (ALBUM TITLES)
for(var item = 0; item < json.covers[0].cover.length; item++) {
var coverTitle = json.covers[0].cover[item].title[0].Text;
//mylogger.log(coverTitle);
switch(coverTitle)
{
case 'AC DC':
json.covers[0].cover[item].title[0].Text = "AC / DC";
break;
case 'VU':
json.covers[0].cover[item].title[0].Text = "Velvet Underground";
break;
case 'the Roots':
json.covers[0].cover[item].title[0].Text = "The Roots";
break;
case 'Bowie':
json.covers[0].cover[item].title[0].Text = "David Bowie";
break;
case 'MMW':
json.covers[0].cover[item].title[0].Text = "Medeski, Martin & Wood";
break;
case 'Guns N Roses':
json.covers[0].cover[item].title[0].Text = "Guns N' Roses";
break;
case 'Huey Lewis and the News':
json.covers[0].cover[item].title[0].Text = "Huey Lewis & the News";
break;
case 'Tom Petty \/ Heartbreakers':
json.covers[0].cover[item].title[0].Text = "Tom Petty & the Heartbreakers";
break;
case 'Pork':
json.covers[0].cover[item].title[0].Text = "Pork Tornado";
break;
case 'Clapton':
json.covers[0].cover[item].title[0].Text = "Eric Clapton";
break;
case 'Hall and Oates':
json.covers[0].cover[item].title[0].Text = "Hall & Oates";
break;
case 'Femmes':
json.covers[0].cover[item].title[0].Text = "Violent Femmes";
break;
case 'Firehose':
json.covers[0].cover[item].title[0].Text = "fIREHOSE";
break;
} // end switch
}
//Now I want to sort all item nodes by their value
json.covers[0].cover.sortByChildNode("title"); //Default order is ASC
var coverArtist = "";
var coverPath = "";
var coverTitle = "";
var coverImg = "";
var coverImgOrig = "";
var coverImgOrigTag = "";
var coverStateofbeing= "";
var coverVideoLink = "";
var out = "";
for(var item = 0; item < json.covers[0].cover.length; item++) {
coverStateofbeing = json.covers[0].cover[item].stateofbeing[0].Text;
if (coverStateofbeing != 'dead'){
//out += json.covers[0].cover[item].title[0].Text;
coverArtist = json.covers[0].cover[item].title[0].Text;
coverArtist= coverArtist.replace("\/", "& the");
//mylogger.log(coverArtist);
coverPath = json.covers[0].cover[item].img[0].Text;
coverTitle = coverPath.replace("albums\/", "");
coverTitle = coverTitle.replace(".jpg", "");
coverImg = 'http://jamtopia.com/images/halloween2009/' + coverPath;
coverOrigImgPath = 'http://assets.phish.com.s3.amazonaws.com/halloween2009/' + coverPath;
coverOrigImgTag = '
';
//mylogger.log(coverImgOrig);
//if (json.covers[0].cover[item].link[0].Text)
//{
// coverVideoLink = json.covers[0].cover[item].link[0].Text;
//}
//
//mylogger.log(coverVideoLink);
out += '';
out += '

';
//if (coverStateofbeing == 'dead'){
out += '
' + coverArtist + '';
//}
out += '
';
}
var $thisCoverDomElement = $("#th-" + coverTitle);
//out += '
';
}
//out += '';
scrollContentRef.html(out);
createAlbumQtips();
if (callback){
callback()
}
}
});
return true;
}
// SET UP THE TOOLTIPS
$.fn.qtip.styles.albumstyle = { // Last part is the name of the style
width: 270,
height: 250,
background: '#ffffff',
color: '#555555',
padding: 0,
textAlign: 'left',
border: {
width: 10,
radius: 5,
color: '#e1e1e1'
},
tip: 'rightMiddle',
name: 'dark' // Inherit the rest of the attributes from the preset dark style
}
function createAlbumQtips(){
$("div.scroll-content-item img[id]").each(function(){
// mylogger.log($(this).attr('rel'));
$(this).qtip({
content: {
text: '
',
prerender: false
},
show: {
delay: 100,
when:{
event: 'mouseover'
},
effect:{
type: 'fade',
length: 100
}
},
hide: {
delay: 100,
when:{
event: 'mouseout'
},
effect:{
type: 'fade',
length: 50
}
},
style: 'albumstyle',
position: {
corner: {
target: 'topMiddle',
tooltip: 'bottomMiddle'
},
adjust: {
screen: true
}
}
});
});
}