/*
=============================
Undergroundhouse.net
JavaScript for DJ Mixes
=============================

Jason Sims (jason@symmetriq.net)

Created: 2005-02-22
Modified: 2006-08-07


2006-08-07 Update
-----------------

The original version of this file was called 'ratings.js'. We now use RPC for the 'listen' links for mixes as well, so the file has been renamed accordingly. The following changes have been made:

- The code for creating the iFrameDoc (the document object in the hidden IFRAME) has been extracted to its own function, which can now be called by both setRating and listenToMix. The function returns the document object, or 'false' if it fails.

- The mouseover preload and functions for the rating stars have been removed. These have been replaced by a simple CSS method that uses a single "sprite" file for all the on/off states of the 5 rating stars, and no longer requires JavaScript.

- handleResponse has been renamed to setRatingResponse, to allow the listenToMix routine to have its own response handler.


Notes:

- We've now got the MixURL coming back to the getMixResponse function, which then tries to load it into the IFRAME. Firefox doesn't allow this, gives this message in the JS Console:

"Attempt to load a javascript: URL from one host
in a window displaying content from another host
was blocked by the security manager."

...however, it then retrieves the .ram file (instead of "displaying" it in the invisible IFRAME), and this has exactly the effect we want.

...but now OmniWeb is crashing. Previously it was loading the RealPlayer plugin into the invisible IFRAME, and we don't want that either. But now it's just outright bombing.


- Get rid of all the .ram files; we can now serve these up dynamically. The .ram file will just contain a link to the listen.php script, with the mix ID. The great part is, everytime the mix is played in RealPlayer, the play count will update.




- The listenToMix RPC could fetch the real listen count when incrementing it, and return that, which would make it show the correct count when someone listens to a mix, but other people have also listened to it since that person first loaded the page. Probably not worth the trouble though.

- Let's fix that problem with rating a mix that appears twice on the same page. It does work, but we're not updating the DOM objects correctly; the average rating blanks out. (This only occurs on the mix homepage, and only when a mix is shown twice on the same page.)

*/


//------------------------------------------------------------
// RPC functions
//------------------------------------------------------------
// based in part on code from the following article:
// http://developer.apple.com/internet/webcontent/iframe.html
//------------------------------------------------------------

/*
---------------------
Important note
---------------------

Instead of passing vars via the query string (as recommended in the above article), we're sticking them in a cookie. The RPC server page (which fortunately still has access to the Cookie class defined below) reads the cookie.

---------------------
Tested and working in
---------------------

Mac:
- OmniWeb 5.1
- Safari 1.2.4
- Firefox 1.0.1
- Internet Explorer 5.2.3

Windows:
- not yet tested

---------------------
Why?
---------------------

We're doing it this way to work around a strange bug in OmniWeb 5.1 that causes it to reload the RPC server page with the most recently used URL (and its query string) as soon as the IFRAME is created after the user reloads the main page that calls this script. It's not supposed to load anything into the IFRAME until we set its location object.

As a result, it was hitting the RPC server page with the previous query string, rather than the new one which reflects the rating the user clicked on this time. It was only doing this the first time after the user manually reloaded the main page. Subsequent ratings (without reloading the page first) were working fine. If the main page is loaded into a new tab, it does not exhibit the problem the first time. It only occurs when the user reloads the main page; perhaps the DOM tree in OW is not really being cleared properly on reload.
*/

// the IFrame object
var iFrameObj;

// response vars
var errorMessage;
var debugMessage;

// debug switch (don't comment this out, set it to false, or scripts will halt)
var debug = false;


function setRating(mixID, rating, userID) {

	if (!document.createElement) { return false };

	// stick the values in a cookie instead of in the query string, to fix OmniWeb thing

	var ratingCookie = new Cookie(document, 'ughRating', null, '/');
	ratingCookie.mixID = mixID;
	ratingCookie.rating = rating;
	ratingCookie.userID = userID;
	//if (debug) ratingCookie.debug = '1';
	ratingCookie.store();

	// pass vars by query string (disabled due to OmniWeb IFRAME bug)
	//var URL = UGH.SiteURL + '/include/rpc_rating.php?MixID=' + mixID + '&Rating=' + rating + '&UserID=' + userID;

	//alert("Going to access RPC script with this URL:\n" + UGH.SiteURL + '/include/rpc_rating.php');

	var iFrameDoc = getFrameDoc();

	iFrameDoc.location.replace(UGH.SiteURL + '/include/rpc_rating_2.php');
	return true;
}


function setRatingResponse(mixID, rating, result) {

	if (errorMessage) alert(errorMessage);
	if (debugMessage) alert(debugMessage);

	if (result) {
		// succeeded; update page accordingly

		// User Rating

		var stars = 5;
		var ratingHTML = '';

		// full stars
		for (var i = 0; i < rating; i++) {
			ratingHTML += '<img src="' + UGH.SkinImages + '/rating_star_on.gif" alt="" class="rating_star" />';
			stars--;
		}

		// make the rest of the stars empty (if any)
		while (stars > 0) {
			ratingHTML += '<img src="' + UGH.SkinImages + '/rating_star_off.gif" alt="" class="rating_star" />';
			stars--;
		}


		// Average Rating

		// calculate new average
		var NewAverageRating = (AverageRating[mixID] * RatingCount[mixID] + rating) / (++RatingCount[mixID]);
		// round it to one decimal place
		NewAverageRating = Math.round(NewAverageRating * 10)/10;
		// get the integer and decimal values separately
		var ARString = NewAverageRating.toString();
		var ARBits = ARString.split('.');

		var stars = 5;
		var voteword = (AverageRating[mixID] > 1 ? 'votes' : 'vote');

		var avgRatingHTML = '';

		// full stars
		for (i = 0; i < ARBits[0]; i++) {
			avgRatingHTML += '<img src="' + UGH.SkinImages + '/rating_star_full.gif" class="rating_star" />';
			stars--;
		}

		// decimals?
		if (ARBits[1]) {
			if (ARBits[1] >= 5) {
				avgRatingHTML += '<img src="' + UGH.SkinImages + '/rating_star_half.gif" class="rating_star" />';
			} else {
				avgRatingHTML += '<img src="' + UGH.SkinImages + '/rating_star_empty.gif" class="rating_star" />';
			}
			stars--;
		} else {
			ARString += '.0';
		}

		// make the rest of the stars empty (if any)
		while (stars > 0) {
			avgRatingHTML += '<img src="' + UGH.SkinImages + '/rating_star_empty.gif" class="rating_star" />';
			stars--;
		}

		// Now update the page
		document.getElementById('m' + mixID).innerHTML = ratingHTML;
		document.getElementById('ar' + mixID).innerHTML = avgRatingHTML;
		document.getElementById('ar' + mixID).title = ARString + ' (' + RatingCount[mixID] + ' ' + voteword + ')';

	}
}


function getMix(mixID) {

	// local debug (this one is safe to comment out, cause it's declared in global scope)
	var debug = true;

	if (!document.createElement) { return false };

	var mixCookie = new Cookie(document, 'ughMix', null, '/');
	mixCookie.mixID = mixID;
	if (debug) mixCookie.debug = '1';
	mixCookie.store();

	var iFrameDoc = getFrameDoc();

	if (debug) alert('About to call: ' + UGH.SiteURL + '/include/rpc_listen.php');

	iFrameDoc.location.replace(UGH.SiteURL + '/include/rpc_listen.php');
	return true;

}

function getMixResponse(mixURL, result) {

	if (errorMessage) alert(errorMessage);
	if (debugMessage) alert(debugMessage);

	alert('Hello! This is the response handler.\n\nGot this URL: ' + mixURL + '\n\nI will try to send you there now...');

	var iFrameDoc = getFrameDoc();

	iFrameDoc.location.replace(mixURL);

	if (result) {
		// we successfully updated the listen count
	}

}



function getFrameDoc() {

	if (!iFrameObj && document.createElement) {

		if (debug) alert("We're going to create an iframe (don't have one yet)");

		// create the IFrame and assign a reference to the object to our global variable
		// iFrameObj. this will only happen the first time setRating() is called
		try {
			var tempObj = document.createElement('iframe');

			if (debug) alert("we just created the tempObj element; it hasn't been added to the DOM yet");

			tempObj.setAttribute('id','RSIFrame');
			tempObj.style.border = '0px';
			tempObj.style.width = '0px';
			tempObj.style.height = '0px';

			iFrameObj = document.body.appendChild(tempObj);

			if (debug) alert("we just added the tempObj to the DOM");

			if (document.frames) {
				// this is for IE5 Mac, because it will only allow access to the document 
				// object of the IFrame if we access it through the document.frames array
				iFrameObj = document.frames['RSIFrame'];
			}
		} catch(exception) {
			// This is for IE5 PC, which does not allow dynamic creation and manipulation
			// of an iframe object. Instead, we'll fake it up by creating our own objects.
			iFrameHTML = '\<iframe id="RSIFrame" style="';
			iFrameHTML += 'border:0px;';
			iFrameHTML += 'width:0px;';
			iFrameHTML += 'height:0px;';
			iFrameHTML += '"></iframe>';
			document.body.innerHTML += iFrameHTML;
			iFrameObj = new Object();
			iFrameObj.document = new Object();
			iFrameObj.document.location = new Object();
			iFrameObj.document.location.iframe = document.getElementById('RSIFrame');
			iFrameObj.document.location.replace = function(location) {
				this.iframe.src = location;
			}
		}

	}

	// we have to give NS6 a fraction of a second to recognize the new IFrame
	if (navigator.userAgent.indexOf('Gecko') != -1 && !iFrameObj.contentDocument) {
		setTimeout('doNothing()',10);
		return false;
	}

	if (iFrameObj.contentDocument) {
		if (debug) alert("We have iFrameObj.contentDocument");
		// For Firefox/Mozilla, Safari, OmniWeb
		return iFrameObj.contentDocument; 
	} else if (iFrameObj.contentWindow) {
		if (debug) alert("We have iFrameObj.contentWindow");
		// For IE 5.5 and IE 6
		return iFrameObj.contentWindow.document;
	} else if (iFrameObj.document) {
		if (debug) alert("We have iFrameObj.document");
		// For IE 5
		return iFrameObj.document;
	} else {
		if (debug) alert("we don't have an iframe object!");
		return false;
	}

}


function doNothing() {
	return;
}


//----------------------------------------------------------------------
// Cookie class
//----------------------------------------------------------------------
// taken from JavaScript: The Definitive Guide (4th Edition) (O'Reilly)
// David Flanagan
//----------------------------------------------------------------------

function Cookie(document, name, hours, path, domain, secure) {
    this.$document = document;
    this.$name = name;
    if (hours)
        this.$expiration = new Date((new Date()).getTime() + hours*3600000);
    else this.$expiration = null;
    if (path) this.$path = path; else this.$path = null;
    if (domain) this.$domain = domain; else this.$domain = null;
    if (secure) this.$secure = true; else this.$secure = false;
}

Cookie.prototype.store = function () {

    var cookieval = "";
    for(var prop in this) {
        if ((prop.charAt(0) == '$') || ((typeof this[prop]) == 'function')) 
            continue;
        if (cookieval != "") cookieval += '&';
        cookieval += prop + ':' + escape(this[prop]);
    }

    var cookie = this.$name + '=' + cookieval;
    if (this.$expiration)
        cookie += '; expires=' + this.$expiration.toGMTString();
    if (this.$path) cookie += '; path=' + this.$path;
    if (this.$domain) cookie += '; domain=' + this.$domain;
    if (this.$secure) cookie += '; secure';

    this.$document.cookie = cookie;
}

Cookie.prototype.load = function() { 

    var allcookies = this.$document.cookie;
    if (allcookies == "") return false;

    var start = allcookies.indexOf(this.$name + '=');
    if (start == -1) return false;
    start += this.$name.length + 1;
    var end = allcookies.indexOf(';', start);
    if (end == -1) end = allcookies.length;
    var cookieval = allcookies.substring(start, end);

    var a = cookieval.split('&');
    for(var i=0; i < a.length; i++)
        a[i] = a[i].split(':');

    for(var i = 0; i < a.length; i++) {
        this[a[i][0]] = unescape(a[i][1]);
    }

    return true;
}

Cookie.prototype.remove = function() {
    var cookie;
    cookie = this.$name + '=';
    if (this.$path) cookie += '; path=' + this.$path;
    if (this.$domain) cookie += '; domain=' + this.$domain;
    cookie += '; expires=Fri, 02-Jan-1970 00:00:00 GMT';

    this.$document.cookie = cookie;
}