/* 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 = '' + coverArtist + ' ' + coverTitle + ''; //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 += '' + coverArtist + ' ' + coverTitle + ''; //if (coverStateofbeing == 'dead'){ out += '' + coverArtist + ''; //} out += '
'; } var $thisCoverDomElement = $("#th-" + coverTitle); //out += '
  • ' + coverArtist + '
  • '; } //out += '
    '; //out += '

    What\'s
    Your
    Prediction?

    '; //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: 'Album Cover', 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 } } }); }); }