	// extend Apple Core's slider class
	var TutorialsSlider = Class.create();
	Object.extend(Object.extend(TutorialsSlider.prototype, AC.Slider.prototype), {
		orientation:'vertical',
		scrollBy:parseInt(3),
		renderPerPage:parseInt(5),

		// get's called in initialize upon construction
		populate: function() {
			var items = document.getElementsByClassName('slideritem');
			// actually populate
			for (var i=0, item; item=items[i]; i++) {
				var sliderItem = new AC.SliderItem(item);
				sliderItem.render = function() {
					return this.html.cloneNode(true);
				}
				this.items.push(sliderItem);
			}

			// render the slider
			this.render(this.renderPerPage);
			this.resetPages();
		},

		renderItems: function() {
			var list = [];
			var lastPageStart = this.items.length-this.items.length%this.itemsPerPage;
			if (lastPageStart==this.items.length) lastPageStart = this.items.length-this.itemsPerPage;
			var overflowAmount = this.itemsPerPage-this.items.length%this.itemsPerPage;
			if (overflowAmount==this.itemsPerPage) overflowAmount = 0;

			// create all the pages
			for (var i=0; i<this.items.length; i++) {
				var listItem = this.items[i].render().cloneNode(true);
				list.push(listItem);
			}

			return list;
		},

		createArrows: function() {
			if (this.items.length>this.itemsPerPage*this.scrollBy) {
				// previous arrow
				this.prevArrow = Builder.node('a', { 'class':'ACSliderPreviousArrow' }, '&lt;');
				Event.observe(this.prevArrow, 'click', function(evt) {
					Event.stop(evt);
					if (this.currentPage!=1) this.getPrevious();
				}.bind(this));
				this.container.appendChild(this.prevArrow);

				// next arrow
				this.nextArrow = Builder.node('a', { 'class':'ACSliderNextArrow' }, '&gt;');
				Event.observe(this.nextArrow, 'click', function(evt) {
					Event.stop(evt);
					if (this.currentPage!=this.totalPages-this.scrollBy+1) this.getNext();
				}.bind(this));
				this.container.appendChild(this.nextArrow);
			}
		},

		createDots: function() {
			this.pageNav = Builder.node('div', { 'class':'ACSliderPageNav' });
			this.updatePageNav();
			this.container.appendChild(this.pageNav);
		},

		updatePageNav: function() {
			var bounds = this.visibleItems(this.currentPage);
			var lower = 0;
			var upper = 0;
			var total = 0;

			for (var i=1; i<this.items.length; i++) {
				if (!Element.hasClassName(this.items[i].html, 'category')) {
					if (i<=bounds.lower) lower++;
					if (i<=bounds.upper) upper++;
					total++;
				}
			}

			var string = (this.pageNavString) ? this.pageNavString+' Tutorials' : 'Tutorials';
			this.pageNav.innerHTML = lower+1+'-'+upper+' of '+total+' '+string;
		},

		positionWithinMask: function(mask) {
			this.maskInnerDimension = Math.floor(Element.getInnerDimensions(mask).height/this.scrollBy);
			this.list.style.top = 0;
		},

		resetPages: function() {
			if (this.currentPage == 1) {
				Element.addClassName(this.prevArrow, 'inactive');
				Element.removeClassName(this.nextArrow, 'inactive');
			} else if (this.currentPage == this.totalPages-this.scrollBy+1) {
				Element.addClassName(this.nextArrow, 'inactive');
				Element.removeClassName(this.prevArrow, 'inactive');
			} else {
				Element.removeClassName(this.prevArrow, 'inactive');
				Element.removeClassName(this.nextArrow, 'inactive');
			}

			this.updatePageNav();
		},

		visibleItems: function(page) {
			var itemsPerPage = this.itemsPerPage*this.scrollBy;

			var lowerBound = (page*this.itemsPerPage)-this.itemsPerPage;
			var upperBound = lowerBound+itemsPerPage-1;

			return { lower:lowerBound, upper:upperBound }
		},

		scrollToItem: function(index) {
			var page = null;

			for (var i=1; i<=this.totalPages-this.scrollBy+1; i++) {
				// figure out the upper and lower bounds on this page
				var bounds = this.visibleItems();

				// check if it's visible on the current page so we don't scroll if we don't have to
				if (i==this.currentPage && index>=bounds.lower && index<=bounds.upper) page = i;

				// if we don't have a page number, and we're between the bounds, set the page number
				if (!page && index>=bounds.lower && index<=bounds.upper) page = i;
			}

			if (page!=this.currentPage) {
				this.scrolltoPageNumber(page);
			}
		}

	});

TutorialSwap = Class.create();
TutorialSwap.prototype = {	
	initialize: function(tips, qtPanel) {
		this.tips = tips;
		
		// cookie tracking
		this.seenTips = [];
		this.checkCookies();
		
		this.previousTip = false;
		this.docTitle = document.title;
		
		this.qtPanel = qtPanel;
		
		new Insertion.After(this.qtPanel, '<div id="quicktimecontroller"></div>');
		this.qtTitlePanel = $('quicktimetitle');
		this.qtControlPanel = $('quicktimecontroller');
		
		this.tips.each(function(tip, i) {
			this.setEvent(tip, i);
		}.bind(this));
		
		if(location.href.indexOf('#') > 0) {
			this.handleClick(null, this.tips[location.href.substr(location.href.indexOf('#')+1, location.href.length)-1]);
		}
	},
	
	setEvent: function(tip, i) {
		Event.observe(tip, 'click', function(evt, tip) {
			this.handleClick(evt, tip, i);
		}.bindAsEventListener(this, tip));
	},
	
	handleClick: function(evt, tip, i) {
		if(evt) Event.stop(evt);
		
		this.trackClick(tip.innerHTML);
		
		// sets/updates cookie when clicked
		this.setCookie(tip, i);

		// set active classes
		tip.hasClassName('active') ? $break : tip.addClassName('active');
		this.previousTip ? this.previousTip.hasClassName('active') ? this.previousTip.removeClassName('active') : $break : $break;
		this.previousTip = tip;
		
		// set checked
		tip.hasClassName('visited') ? $break : tip.addClassName('visited');
		
		if($('intro')) $('intro').remove();
		this.swapMovie(tip);
	},
	
	swapMovie: function(tip) {
		if(this.qtController) {
			this.qtController.Stop();
			this.qtController.detachFromMovie();
			this.qtController = false;
			this.qtTitlePanel.innerHTML = '';
			this.qtPanel.innerHTML = '';
			this.qtControlPanel.innerHTML = '';
		} 

		var movie = AC.Quicktime.packageMovie('tipMovie', tip.href, {
			width: 640,
			height: 400,
			controller: false,
			showlogo: false,
			cache: true
		});
		
		this.qtTitlePanel.update(tip.up('li').previous('.category').innerHTML+' / <span>'+tip.innerHTML+'</span>');
		this.qtPanel.appendChild(movie);
		this.qtController = new AC.QuicktimeController();
		this.qtController.render(this.qtControlPanel);				
		this.qtController.attachToMovie(movie);
		this.qtController.monitorMovie(movie);
		var movie = null;
	},
	
	setCookie: function(tip, i) {
		var date = new Date();
		// set cookie to expire in 1 week
		date.setDate(date.getDate()+7);
		// comma delimited to sort later
		var str = this.seenTips.join(',');
		document.cookie = 'seenTip='+str+','+i+'; expires='+date.toGMTString()+'; path=/; domain=apple.com';
		// remember we added it		
		this.seenTips.push(i);

	},
	
	checkCookies: function() {
		document.cookie.split(';').each(function(cookie) {
			if(cookie.match(/seenTip/)) {
				var seen = cookie.substring(cookie.indexOf('=')+1, cookie.length).split(',');
				// push each tip into an array
				seen.each(function(s) {
					if(s) {
						this.seenTips.push(s);
						this.tips[s].addClassName('visited');						
					}
				}.bind(this));
			}
		}.bind(this));
	},
	
	trackClick: function(title) {
		document.title = this.docTitle +' - '+ title;
	}
	
};
